From 876018811b23ff1baffe3d201a1124869d1b948a Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Fri, 29 Mar 2024 13:48:11 +0800 Subject: [PATCH] AIA: refactor: Let mvip.SEIP be the software-writable bit of mip.SEIP The mip.SEIP is the logical-OR of a software-writable bit and signal from an external interrupt controller (e.g., APLIC or IMSIC). The AIA spec lets the software-writable bit be the mvip.SEIP. This commit follows the concept that the mvip.SEIP is a sub-component of mip.SEIP. Writing mip.SEIP actually updates the software-writable bit, i.e., mvip.SEIP. Reading mip.SEIP returns a value consisting of the software-writable bit, i.e., mvip.SEIP. The SEIP bit in mip::val becomes a placeholder for the external interrupt controller. Accessing mvip.SEIP reads from and writes to mvip.SEIP normally. Reference: https://github.com/riscv/riscv-aia/issues/64 --- riscv/csrs.cc | 18 ++++++++++++++---- riscv/csrs.h | 7 ++++++- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 8dd5071e..36dcca0c 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -783,8 +783,14 @@ mip_csr_t::mip_csr_t(processor_t* const proc, const reg_t addr): mip_or_mie_csr_t(proc, addr) { } +void mip_csr_t::write_with_mask(const reg_t mask, const reg_t val) noexcept { + if (mask & MIP_SEIP) + state->mvip->write_with_mask(MIP_SEIP, val); // mvip.SEIP is an alias of mip.SEIP when mvien.SEIP=0 + mip_or_mie_csr_t::write_with_mask(mask & ~MIP_SEIP, val); +} + reg_t mip_csr_t::read() const noexcept { - return val | state->hvip->basic_csr_t::read(); + return val | state->hvip->basic_csr_t::read() | (state->mvip->basic_csr_t::read() & MIP_SEIP); } void mip_csr_t::backdoor_write_with_mask(const reg_t mask, const reg_t val) noexcept { @@ -2004,19 +2010,23 @@ reg_t mvip_csr_t::read() const noexcept { const reg_t mip = state->mip->read(); const reg_t menvcfg = state->menvcfg->read(); return 0 - | (mip & MIP_SEIP) + | (val & MIP_SEIP) | ((menvcfg & MENVCFG_STCE) ? 0 : (mip & MIP_STIP)) | (((mvien & MIP_SSIP) ? val : mip) & MIP_SSIP) ; } bool mvip_csr_t::unlogged_write(const reg_t val) noexcept { - state->mip->write_with_mask(MIP_SEIP, val); if (!(state->menvcfg->read() & MENVCFG_STCE)) state->mip->write_with_mask(MIP_STIP, val); // mvip.STIP is an alias of mip.STIP when mip.STIP is writable if (!(state->mvien->read() & MIP_SSIP)) state->mip->write_with_mask(MIP_SSIP, val); // mvip.SSIP is an alias of mip.SSIP when mvien.SSIP=0 - const reg_t new_val = ((state->mvien->read() & MIP_SSIP) ? val : basic_csr_t::read()) & MIP_SSIP; + const reg_t new_val = (val & MIP_SEIP) | (((state->mvien->read() & MIP_SSIP) ? val : basic_csr_t::read()) & MIP_SSIP); return basic_csr_t::unlogged_write(new_val); } + +void mvip_csr_t::write_with_mask(const reg_t mask, const reg_t val) noexcept { + basic_csr_t::unlogged_write((basic_csr_t::read() & ~mask) | (val & mask)); + log_write(); +} diff --git a/riscv/csrs.h b/riscv/csrs.h index 5c583a47..b3e3af37 100644 --- a/riscv/csrs.h +++ b/riscv/csrs.h @@ -356,7 +356,7 @@ class mip_or_mie_csr_t: public csr_t { mip_or_mie_csr_t(processor_t* const proc, const reg_t addr); virtual reg_t read() const noexcept override; - void write_with_mask(const reg_t mask, const reg_t val) noexcept; + virtual void write_with_mask(const reg_t mask, const reg_t val) noexcept; protected: virtual bool unlogged_write(const reg_t val) noexcept override final; @@ -371,6 +371,8 @@ class mip_csr_t: public mip_or_mie_csr_t { mip_csr_t(processor_t* const proc, const reg_t addr); virtual reg_t read() const noexcept override final; + void write_with_mask(const reg_t mask, const reg_t val) noexcept override; + // Does not log. Used by external things (clint) that wiggle bits in mip. void backdoor_write_with_mask(const reg_t mask, const reg_t val) noexcept; private: @@ -921,6 +923,9 @@ class mvip_csr_t : public basic_csr_t { public: mvip_csr_t(processor_t* const proc, const reg_t addr, const reg_t init); reg_t read() const noexcept override; + + void write_with_mask(const reg_t mask, const reg_t val) noexcept; + protected: virtual bool unlogged_write(const reg_t val) noexcept override; };