From 694857723ca436283c3ee98132c5aff98f5ced1f Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 29 May 2026 20:17:04 +0200 Subject: [PATCH 1/3] adds support for AIA registers in 32bit mode Adds the 32bit high part of mie, mip and mideleg --- src/iss/arch/riscv_hart_common.h | 27 +++++++++++++----- src/iss/arch/riscv_hart_m_p.h | 23 ++++++++++++--- src/iss/arch/riscv_hart_msu_vp.h | 49 +++++++++++++++++++++++--------- src/iss/arch/riscv_hart_mu_p.h | 36 ++++++++++++++++++----- 4 files changed, 104 insertions(+), 31 deletions(-) diff --git a/src/iss/arch/riscv_hart_common.h b/src/iss/arch/riscv_hart_common.h index fd05b28..e7077cb 100644 --- a/src/iss/arch/riscv_hart_common.h +++ b/src/iss/arch/riscv_hart_common.h @@ -60,7 +60,7 @@ namespace iss { namespace arch { -enum features_e { FEAT_NONE, FEAT_EXT_N = 1, FEAT_DEBUG = 2 }; +enum features_e { FEAT_NONE, FEAT_EXT_N = 1, FEAT_DEBUG = 2, FEAT_AIA = 4 }; enum extension_encoding { A = 1UL << 0, B = 1UL << 1, @@ -135,12 +135,14 @@ enum riscv_csr { sie = 0x104, stvec = 0x105, scounteren = 0x106, + sieh = 0x114, // Supervisor Trap Handling sscratch = 0x140, sepc = 0x141, scause = 0x142, stval = 0x143, sip = 0x144, + siph = 0x154, // Supervisor Protection and Translation satp = 0x180, /* machine-level CSR */ @@ -154,18 +156,24 @@ enum riscv_csr { misa = 0x301, medeleg = 0x302, mideleg = 0x303, + midelegh = 0x313, // AIA defined mie = 0x304, + mieh = 0x314, // AIA defined mtvec = 0x305, mcounteren = 0x306, mtvt = 0x307, // CLIC mstatush = 0x310, medelegh = 0x312, + // AIA defined + mvienh = 0x318, + mviph = 0x319, // Machine Trap Handling mscratch = 0x340, mepc = 0x341, mcause = 0x342, mtval = 0x343, mip = 0x344, + miph = 0x354, // AIA defined mxnti = 0x345, // CLIC mintstatus = 0xFB1, // MRW Current interrupt levels (CLIC) - addr subject to change mintthresh = 0x347, // MRW Interrupt-level threshold (CLIC) - addr subject to change @@ -648,12 +656,12 @@ template struct riscv_hart_common : public BAS this->csr_rd_cb[dcsr] = MK_CSR_RD_CB(read_debug); } - constexpr reg_t get_irq_mask(size_t mode) { - std::array m = {{ - (std::numeric_limits::max() & ~0xffffULL) | 0b000100010001U, // U mode - (std::numeric_limits::max() & ~0xffffULL) | 0b001100110011U, // S mode - (std::numeric_limits::max() & ~0xffffULL) | 0b011101110111U, // H mode - (std::numeric_limits::max() & ~0xffffULL) | 0b111111111111U // M mode + constexpr uint64_t get_irq_mask(size_t mode) { + std::array m = {{ + (std::numeric_limits::max() & ~0xffffULL) | 0b000100010001U, // U mode + (std::numeric_limits::max() & ~0xffffULL) | 0b001100110011U, // S mode + (std::numeric_limits::max() & ~0xffffULL) | 0b011101110111U, // H mode + (std::numeric_limits::max() & ~0xffffULL) | 0b111111111111U // M mode }}; return m[mode]; } @@ -1069,6 +1077,11 @@ template struct riscv_hart_common : public BAS reg_t mhartid_reg{0x0}; uint64_t mcycle_csr{0}; uint64_t minstret_csr{0}; + uint64_t mie_csr{0}; + uint64_t mip_csr{0}; + uint64_t mideleg_csr{0}; + uint64_t sie_csr{0}; + uint64_t sip_csr{0}; reg_t fault_data; int64_t cycle_offset{0}; diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index a6a5bbc..ddc3c8a 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -114,6 +114,12 @@ riscv_hart_m_p::riscv_hart_m_p() if(FEAT & FEAT_DEBUG) this->add_debug_csrs(); + if(FEAT & FEAT_AIA && traits::XLEN == 32) { + this->csr_rd_cb[miph] = MK_CSR_RD_CB(read_ip); + this->csr_wr_cb[miph] = MK_CSR_WR_CB(write_plain); + this->csr_rd_cb[mieh] = MK_CSR_RD_CB(read_ie); + this->csr_wr_cb[mieh] = MK_CSR_WR_CB(write_ie); + } this->rd_func = util::delegate::from(this); this->wr_func = util::delegate::from(this); this->memories.root(*this); @@ -304,22 +310,31 @@ template iss::status riscv_hart_m_p } template iss::status riscv_hart_m_p::read_ie(unsigned addr, reg_t& val) { + if(UNLIKELY(addr == mieh)) { + val = this->mie_csr >> 32; + return iss::Ok; + } auto mask = riscv_hart_common::get_irq_mask(3); - val = this->csr[mie] & mask; + val = this->mie_csr & mask; return iss::Ok; } template iss::status riscv_hart_m_p::write_ie(unsigned addr, reg_t val) { + uint64_t lval = addr == mieh ? val << 32 : val; // generate mask from allowed writable bits, the number of custom interrupts and the available ie bits auto mask = riscv_hart_common::get_irq_mask(3) & this->clint_custom_irq_mask & ~0x777ULL; - this->csr[mie] = (this->csr[mie] & ~mask) | (val & mask); + this->mie_csr = (this->mie_csr & ~mask) | (lval & mask); check_interrupt(); return iss::Ok; } template iss::status riscv_hart_m_p::read_ip(unsigned addr, reg_t& val) { + if(UNLIKELY(addr == miph)) { + val = this->mip_csr >> 32; + return iss::Ok; + } auto mask = riscv_hart_common::get_irq_mask(3); - val = this->csr[mip] & mask; + val = this->mip_csr & mask; return iss::Ok; } @@ -333,7 +348,7 @@ template void riscv_hart_m_p::check // handled in the following decreasing priority order: // external interrupts, software interrupts, timer interrupts, then finally // any synchronous traps. - auto ena_irq = this->csr[mip] & this->csr[mie]; + auto ena_irq = this->mip_csr & this->mie_csr; bool mstatus_mie = this->state.mstatus.MIE; auto m_enabled = this->reg.PRIV < PRIV_M || mstatus_mie; diff --git a/src/iss/arch/riscv_hart_msu_vp.h b/src/iss/arch/riscv_hart_msu_vp.h index ee0b799..e1001c0 100644 --- a/src/iss/arch/riscv_hart_msu_vp.h +++ b/src/iss/arch/riscv_hart_msu_vp.h @@ -185,6 +185,15 @@ riscv_hart_msu_vp::riscv_hart_msu_vp() if(FEAT & FEAT_DEBUG) this->add_debug_csrs(); + if(FEAT & FEAT_AIA && traits::XLEN == 32) { + this->csr_rd_cb[miph] = MK_CSR_RD_CB(read_ip); + this->csr_wr_cb[miph] = MK_CSR_WR_CB(write_plain); + this->csr_rd_cb[mieh] = MK_CSR_RD_CB(read_ie); + this->csr_wr_cb[mieh] = MK_CSR_WR_CB(write_ie); + this->csr_rd_cb[midelegh] = MK_CSR_RD_CB(read_plain); + this->csr_wr_cb[midelegh] = MK_CSR_WR_CB(write_ideleg); + } + this->rd_func = util::delegate::from(this); this->wr_func = util::delegate::from(this); this->set_next(mmu.get_mem_if()); @@ -407,11 +416,25 @@ template iss::status riscv_hart_msu_vp iss::status riscv_hart_msu_vp::read_ie(unsigned addr, reg_t& val) { - val = this->csr[mie]; - if(addr < mie) - val &= this->csr[mideleg]; - if(addr < sie) - val &= this->csr[sideleg]; + val = this->mie_csr; + if(addr == mie) { + val &= this->mie_csr; + return iss::Ok; + } + if(addr == sie) { + val &= this->sie_csr; + return iss::Ok; + } + if((FEAT & FEAT_AIA) && traits::XLEN == 32) { + if(addr == mieh) { + val &= this->mie_csr >> 32; + return iss::Ok; + } + if(addr == sieh) { + val &= this->sie_csr >> 32; + return iss::Ok; + } + } return iss::Ok; } @@ -423,17 +446,17 @@ template iss::status riscv_hart_msu_vpcsr[mie] = (this->csr[mie] & ~mask) | (val & mask); + this->mie_csr = (this->mie_csr & ~mask) | (val & mask); check_interrupt(); return iss::Ok; } template iss::status riscv_hart_msu_vp::read_ip(unsigned addr, reg_t& val) { - val = this->csr[mip]; - if(addr < mip) - val &= this->csr[mideleg]; - if(addr < sip) - val &= this->csr[sideleg]; + val = this->mip_csr; + if(addr == mideleg) + val &= this->mideleg_csr; + if(addr == sideleg) + val &= this->sideleg_csr; return iss::Ok; } @@ -476,8 +499,8 @@ template inline void riscv_hart_msu_vp void riscv_hart_msu_vp::check_interrupt() { auto status = this->state.mstatus; - auto ip = this->csr[mip]; - auto ie = this->csr[mie]; + auto ip = this->mip_csr; + auto ie = this->mie_csr; auto ideleg = this->csr[mideleg]; // Multiple simultaneous interrupts and traps at the same privilege level are // handled in the following decreasing priority order: diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 8f4818b..389a676 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -39,6 +39,7 @@ #include "iss/vm_if.h" #include "iss/vm_types.h" #include "riscv_hart_common.h" +#include "util/ities.h" #include "util/logging.h" #include #include @@ -149,6 +150,17 @@ riscv_hart_mu_p::riscv_hart_mu_p() if(FEAT & FEAT_DEBUG) this->add_debug_csrs(); + if(FEAT & FEAT_AIA && traits::XLEN == 32) { + this->csr_rd_cb[miph] = MK_CSR_RD_CB(read_ip); + this->csr_wr_cb[miph] = MK_CSR_WR_CB(write_plain); + this->csr_rd_cb[mieh] = MK_CSR_RD_CB(read_ie); + this->csr_wr_cb[mieh] = MK_CSR_WR_CB(write_ie); + if(FEAT & FEAT_EXT_N) { + this->csr_rd_cb[midelegh] = MK_CSR_RD_CB(read_plain); + this->csr_wr_cb[midelegh] = MK_CSR_WR_CB(write_ideleg); + } + } + this->rd_func = util::delegate::from(this); this->wr_func = util::delegate::from(this); this->memories.root(*this); @@ -340,12 +352,17 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::read_ie(unsigned addr, reg_t& val) { + if(UNLIKELY(addr == mieh)) { + val = this->mie_csr >> 32; + return iss::Ok; + } auto mask = riscv_hart_common::get_irq_mask((addr >> 8) & 0x3); - val = this->csr[mie] & mask; + val = this->mie_csr & mask; return iss::Ok; } template iss::status riscv_hart_mu_p::write_ie(unsigned addr, reg_t val) { + uint64_t lval = addr == mieh ? val << 32 : val; // generate mask from allowed writable bits, the number of custom interrupts and the available ie bits auto mask = riscv_hart_common::get_irq_mask((addr >> 8) & 0x3) & FEAT & FEAT_EXT_N; mask &= this->clint_custom_irq_mask; @@ -353,21 +370,26 @@ template iss::status riscv_hart_mu_pcsr[mie] = (this->csr[mie] & ~mask) | (val & mask); + this->mie_csr = (this->mie_csr & ~mask) | (lval & mask); check_interrupt(); return iss::Ok; } template iss::status riscv_hart_mu_p::read_ip(unsigned addr, reg_t& val) { + if(UNLIKELY(addr == miph)) { + val = this->mip_csr >> 32; + return iss::Ok; + } auto mask = riscv_hart_common::get_irq_mask((addr >> 8) & 0x3); - val = this->csr[mip] & mask; + val = this->mip_csr & mask; return iss::Ok; } template iss::status riscv_hart_mu_p::write_ideleg(unsigned addr, reg_t val) { - // only U and S mode interrupts can be delegated - auto mask = 0b0001'0001'0001; - this->csr[mideleg] = (this->csr[mideleg] & ~mask) | (val & mask); + uint64_t lval = addr == midelegh ? val << 32 : val; + // only U mode interrupts can be delegated + auto mask = 0xffff'0111ul; + this->mideleg_csr = (this->mideleg_csr & ~mask) | (lval & mask); return iss::Ok; } @@ -396,7 +418,7 @@ template void riscv_hart_mu_p::chec // handled in the following decreasing priority order: // external interrupts, software interrupts, timer interrupts, then finally // any synchronous traps. - auto ena_irq = this->csr[mip] & this->csr[mie]; + auto ena_irq = this->mip_csr & this->mie_csr; bool mstatus_mie = this->state.mstatus.MIE; auto m_enabled = this->reg.PRIV < PRIV_M || mstatus_mie; From f97bcd665843e94df4dabf2b600cc58491aa9764 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 29 May 2026 21:41:30 +0200 Subject: [PATCH 2/3] fixes compilation issues --- src/iss/arch/riscv_hart_common.h | 1 + src/iss/arch/riscv_hart_m_p.h | 8 +++++--- src/iss/arch/riscv_hart_mu_p.h | 12 ++++++++---- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/iss/arch/riscv_hart_common.h b/src/iss/arch/riscv_hart_common.h index e7077cb..1bf0905 100644 --- a/src/iss/arch/riscv_hart_common.h +++ b/src/iss/arch/riscv_hart_common.h @@ -1082,6 +1082,7 @@ template struct riscv_hart_common : public BAS uint64_t mideleg_csr{0}; uint64_t sie_csr{0}; uint64_t sip_csr{0}; + uint64_t sideleg_csr{0}; reg_t fault_data; int64_t cycle_offset{0}; diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index ddc3c8a..548f57a 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -310,7 +310,7 @@ template iss::status riscv_hart_m_p } template iss::status riscv_hart_m_p::read_ie(unsigned addr, reg_t& val) { - if(UNLIKELY(addr == mieh)) { + if(unlikely(addr == mieh)) { val = this->mie_csr >> 32; return iss::Ok; } @@ -320,7 +320,9 @@ template iss::status riscv_hart_m_p } template iss::status riscv_hart_m_p::write_ie(unsigned addr, reg_t val) { - uint64_t lval = addr == mieh ? val << 32 : val; + uint64_t lval = val; + if(addr == mieh) + lval <<= 32; // generate mask from allowed writable bits, the number of custom interrupts and the available ie bits auto mask = riscv_hart_common::get_irq_mask(3) & this->clint_custom_irq_mask & ~0x777ULL; this->mie_csr = (this->mie_csr & ~mask) | (lval & mask); @@ -329,7 +331,7 @@ template iss::status riscv_hart_m_p } template iss::status riscv_hart_m_p::read_ip(unsigned addr, reg_t& val) { - if(UNLIKELY(addr == miph)) { + if(unlikely(addr == miph)) { val = this->mip_csr >> 32; return iss::Ok; } diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 389a676..f9ceeae 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -352,7 +352,7 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::read_ie(unsigned addr, reg_t& val) { - if(UNLIKELY(addr == mieh)) { + if(unlikely(addr == mieh)) { val = this->mie_csr >> 32; return iss::Ok; } @@ -362,7 +362,9 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::write_ie(unsigned addr, reg_t val) { - uint64_t lval = addr == mieh ? val << 32 : val; + uint64_t lval = val; + if(addr == mieh) + lval <<= 32; // generate mask from allowed writable bits, the number of custom interrupts and the available ie bits auto mask = riscv_hart_common::get_irq_mask((addr >> 8) & 0x3) & FEAT & FEAT_EXT_N; mask &= this->clint_custom_irq_mask; @@ -376,7 +378,7 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::read_ip(unsigned addr, reg_t& val) { - if(UNLIKELY(addr == miph)) { + if(unlikely(addr == miph)) { val = this->mip_csr >> 32; return iss::Ok; } @@ -386,7 +388,9 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::write_ideleg(unsigned addr, reg_t val) { - uint64_t lval = addr == midelegh ? val << 32 : val; + uint64_t lval = val; + if(addr == midelegh) + lval <<= 32; // only U mode interrupts can be delegated auto mask = 0xffff'0111ul; this->mideleg_csr = (this->mideleg_csr & ~mask) | (lval & mask); From 4849b4a13251f523039ee7e0e4301beed47c3987 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 29 May 2026 21:47:42 +0200 Subject: [PATCH 3/3] updates dbt-rise-core commit for standalone build --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 59239d5..b4761dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,7 +44,7 @@ if(NOT TARGET dbt-rise-core) FetchContent_Declare( dbt_rise_core_git GIT_REPOSITORY "https://github.com/Minres/DBT-RISE-Core.git" - GIT_TAG 50635c29 + GIT_TAG 9b571ff9 GIT_SHALLOW OFF UPDATE_DISCONNECTED NOT ${UPDATE_EXTERNAL_PROJECT} # When enabled, this option causes the update step to be skipped. )