From 72882f7207323206532693aec943801231521f84 Mon Sep 17 00:00:00 2001 From: Zehao Liu <86838383+lewislzh@users.noreply.github.com> Date: Wed, 13 Nov 2024 18:19:13 +0800 Subject: [PATCH] feat(dbltrp): support full dbltrp extension in spike (#54) --- difftest/difftest-def.h | 3 ++- difftest/difftest.cc | 8 ++++++++ difftest/difftest.h | 1 + riscv/csr_init.cc | 2 +- riscv/csrs.cc | 19 ++++++++++++++++++- riscv/csrs.h | 3 +++ riscv/processor.cc | 27 ++++++++++++++++++++++++--- riscv/processor.h | 3 ++- 8 files changed, 59 insertions(+), 7 deletions(-) diff --git a/difftest/difftest-def.h b/difftest/difftest-def.h index 19c67a090..4ce1abe36 100644 --- a/difftest/difftest-def.h +++ b/difftest/difftest-def.h @@ -81,7 +81,8 @@ "_svinval_sscofpmf" \ "_svpbmt" \ "_zicbom_zicboz" \ - "_sstc" + "_sstc" \ + "_smrnmi_smdbltrp_ssdbltrp" \ #define CONFIG_MEMORY_SIZE (16 * 1024 * 1024 * 1024UL) #define CONFIG_FLASH_BASE 0x10000000UL diff --git a/difftest/difftest.cc b/difftest/difftest.cc index 9185eb983..939fe49d6 100644 --- a/difftest/difftest.cc +++ b/difftest/difftest.cc @@ -394,6 +394,10 @@ void DifftestRef::raise_intr(uint64_t no) { } } +bool DifftestRef::raise_critical_error() { + return state->critical_error; +} + void DifftestRef::update_mip(void *non_reg_interrupt_pending) { auto n = (DifftestNonRegInterruptPending *) non_reg_interrupt_pending; state->mip->backdoor_write_with_mask(MIP_MTIP, n->platform_irp_mtip ? MIP_MTIP : 0); @@ -568,6 +572,10 @@ void difftest_raise_intr(uint64_t NO) { ref->raise_intr(NO); } +bool difftest_raise_critical_error() { + return ref->raise_critical_error(); +} + void isa_reg_display() { ref->display(); } diff --git a/difftest/difftest.h b/difftest/difftest.h index 978c383af..22ec17493 100644 --- a/difftest/difftest.h +++ b/difftest/difftest.h @@ -142,6 +142,7 @@ class DifftestRef { void debug_memcpy_from_dut(reg_t dest, void* src, size_t n); int store_commit(uint64_t *addr, uint64_t *data, uint8_t *mask); void raise_intr(uint64_t no); + bool raise_critical_error(); void display(); void update_mip(void *non_reg_interrupt_pending); void update_dynamic_config(void* config) { diff --git a/riscv/csr_init.cc b/riscv/csr_init.cc index 9f35ed99d..3f100b1ed 100644 --- a/riscv/csr_init.cc +++ b/riscv/csr_init.cc @@ -341,7 +341,7 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) if (proc->extension_enabled_const(EXT_SMRNMI)) { add_csr(CSR_MNSCRATCH, std::make_shared(proc, CSR_MNSCRATCH, 0)); add_csr(CSR_MNEPC, mnepc = std::make_shared(proc, CSR_MNEPC)); - add_csr(CSR_MNCAUSE, std::make_shared(proc, CSR_MNCAUSE, (reg_t)1 << (xlen - 1))); + add_csr(CSR_MNCAUSE, mncause = std::make_shared(proc, CSR_MNCAUSE)); add_csr(CSR_MNSTATUS, mnstatus = std::make_shared(proc, CSR_MNSTATUS)); } diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 00a3efc93..802a73d3f 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -597,18 +597,31 @@ reg_t mstatus_csr_t::compute_mstatus_initial_value() const noexcept { | (proc->extension_enabled_const('U') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_UXL, xlen_to_uxl(proc->get_const_xlen())) : 0) | (proc->extension_enabled_const('S') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_SXL, xlen_to_uxl(proc->get_const_xlen())) : 0) | (proc->get_mmu()->is_target_big_endian() ? big_endian_bits : 0) +#if defined(DIFFTEST) && defined(CPU_XIANGSHAN) + | 0 +#else | (proc->extension_enabled(EXT_SMDBLTRP) ? MSTATUS_MDT : 0) +#endif | 0; // initial value for mstatus } // implement class mnstatus_csr_t mnstatus_csr_t::mnstatus_csr_t(processor_t* const proc, const reg_t addr): - basic_csr_t(proc, addr, 0) { +#if defined(DIFFTEST) && defined(CPU_XIANGSHAN) + basic_csr_t(proc, addr, MNSTATUS_NMIE) +#else + basic_csr_t(proc, addr, 0) +#endif + { } bool mnstatus_csr_t::unlogged_write(const reg_t val) noexcept { // NMIE can be set but not cleared +#if defined(DIFFTEST) && defined(CPU_XIANGSHAN) + const reg_t mask = MNSTATUS_NMIE +#else const reg_t mask = (~read() & MNSTATUS_NMIE) +#endif | (proc->extension_enabled('H') ? MNSTATUS_MNPV : 0) | MNSTATUS_MNPP; @@ -619,6 +632,10 @@ bool mnstatus_csr_t::unlogged_write(const reg_t val) noexcept { return basic_csr_t::unlogged_write(new_mnstatus); } +bool mnstatus_csr_t::bare_write(const reg_t val) noexcept { + return basic_csr_t::unlogged_write(val); +} + // implement class rv32_low_csr_t rv32_low_csr_t::rv32_low_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig): csr_t(proc, addr), diff --git a/riscv/csrs.h b/riscv/csrs.h index 2505562c4..0fe3a36fe 100644 --- a/riscv/csrs.h +++ b/riscv/csrs.h @@ -271,6 +271,7 @@ typedef std::shared_ptr mstatus_csr_t_p; class mnstatus_csr_t final: public basic_csr_t { public: mnstatus_csr_t(processor_t* const proc, const reg_t addr); + bool bare_write(const reg_t val) noexcept; protected: virtual bool unlogged_write(const reg_t val) noexcept override; }; @@ -551,6 +552,8 @@ class wide_counter_csr_t: public csr_t { typedef std::shared_ptr wide_counter_csr_t_p; +typedef std::shared_ptr mnstatus_csr_t_p; + class time_counter_csr_t: public csr_t { public: time_counter_csr_t(processor_t* const proc, const reg_t addr); diff --git a/riscv/processor.cc b/riscv/processor.cc index 545f0ac32..c3030ab90 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -532,17 +532,38 @@ void processor_t::take_trap(trap_t& t, reg_t epc) reg_t s = state.mstatus->read(); if ( extension_enabled(EXT_SMDBLTRP)) { - if (get_field(s, MSTATUS_MDT) || !nmie) { + bool m_double_trap = get_field(s, MSTATUS_MDT); + if (!nmie) { // Critical error - Double trap in M-mode or trap when nmie is 0 // RNMI is not modeled else double trap in M-mode would trap to // RNMI handler instead of leading to a critical error state.critical_error = 1; return; } - s = set_field(s, MSTATUS_MDT, 1); + if (m_double_trap) { + state.pc = trap_handler_address; + reg_t mnstatus_val = state.mnstatus->read(); + mnstatus_val = set_field(mnstatus_val, MNSTATUS_MNPP, state.prv); + mnstatus_val = set_field(mnstatus_val, MNSTATUS_MNPV, curr_virt); + mnstatus_val = set_field(mnstatus_val, MNSTATUS_NMIE, 0); + state.mnstatus->bare_write(mnstatus_val); +#ifdef CPU_ROCKET_CHIP + state.mnepc->write(encode_vaddr(epc)); +#else + state.mnepc->write(epc); +#endif + state.mncause->write(t.cause()); + set_privilege(PRV_M, false); + return; + } else { + s = set_field(s, MSTATUS_MDT, 1); + } } - +#if defined(DIFFTEST) && defined(CPU_XIANGSHAN) + state.pc = trap_handler_address; +#else state.pc = !nmie ? rnmi_trap_handler_address : trap_handler_address; +#endif #ifdef CPU_ROCKET_CHIP state.mepc->write(encode_vaddr(epc)); #else diff --git a/riscv/processor.h b/riscv/processor.h index 7adfe8f01..431555044 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -102,8 +102,9 @@ struct state_t csr_t_p mcounteren; csr_t_p mcountinhibit; csr_t_p mevent[N_HPMCOUNTERS]; - csr_t_p mnstatus; + mnstatus_csr_t_p mnstatus; csr_t_p mnepc; + csr_t_p mncause; csr_t_p scounteren; csr_t_p sepc; csr_t_p stval;