From e4b92a3793ed11a8ec7a6ce8956c5f2d68aee1e6 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Tue, 2 Apr 2024 18:05:36 +0800 Subject: [PATCH] AIA: Let sie[n] be writable when mideleg[n]=0 and mvien[n]=1 The AIA spec specifies the sie[n] behavior conditionally: (1) When mideleg[n]=0 and mvien[n]=0, sie[n] is read-only 0. (2) When mideleg[n]=0 and mvien[n]=1, sie[n] is writable. (3) When mideleg[n]=1, sie[n] is an alias of mie[n]. Points (1) and (3) describe the same behavior without AIA. This commit provides the behavior of point (2). --- riscv/csr_init.cc | 2 +- riscv/csrs.cc | 17 +++++++++++++++++ riscv/csrs.h | 10 ++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/riscv/csr_init.cc b/riscv/csr_init.cc index c4bad77d..414613c2 100644 --- a/riscv/csr_init.cc +++ b/riscv/csr_init.cc @@ -150,7 +150,7 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) add_hypervisor_csr(CSR_HIP, std::make_shared(proc, CSR_HIP, hip_hie_accr)); add_hypervisor_csr(CSR_HVIP, hvip = std::make_shared(proc, CSR_HVIP, 0)); - auto nonvirtual_sie = std::make_shared(proc, CSR_SIE, sip_sie_accr); + auto nonvirtual_sie = std::make_shared(proc, CSR_SIE, sip_sie_accr); auto vsie = std::make_shared(proc, CSR_VSIE, vsip_vsie_accr); add_hypervisor_csr(CSR_VSIE, vsie); add_supervisor_csr(CSR_SIE, std::make_shared(proc, nonvirtual_sie, vsie)); diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 6255c050..55acaae1 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -979,6 +979,23 @@ bool sip_csr_t::unlogged_write(const reg_t val) noexcept { return mip_proxy_csr_t::unlogged_write(val & ~mask); } +sie_csr_t::sie_csr_t(processor_t* const proc, const reg_t addr, generic_int_accessor_t_p accr): + mie_proxy_csr_t(proc, addr, accr), + val(0) { +} + +reg_t sie_csr_t::read() const noexcept { + const reg_t mask = ~state->mideleg->read() & state->mvien->read(); + return (mie_proxy_csr_t::read() & ~mask) | (val & mask); +} + +bool sie_csr_t::unlogged_write(const reg_t val) noexcept { + const reg_t mask = ~state->mideleg->read() & state->mvien->read(); + this->val = (this->val & ~mask) | (val & mask); + mie_proxy_csr_t::unlogged_write(val & ~mask); + return true; +} + // implement class masked_csr_t masked_csr_t::masked_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init): basic_csr_t(proc, addr, init), diff --git a/riscv/csrs.h b/riscv/csrs.h index 65360305..5cf7a233 100644 --- a/riscv/csrs.h +++ b/riscv/csrs.h @@ -470,6 +470,16 @@ class sip_csr_t: public mip_proxy_csr_t { virtual bool unlogged_write(const reg_t val) noexcept override; }; +class sie_csr_t: public mie_proxy_csr_t { + public: + sie_csr_t(processor_t* const proc, const reg_t addr, generic_int_accessor_t_p accr); + virtual reg_t read() const noexcept override; + protected: + virtual bool unlogged_write(const reg_t val) noexcept override; + private: + reg_t val; +}; + // For CSRs with certain bits hardwired class masked_csr_t: public basic_csr_t { public: