From d0c338cb4216466928a6d054614db1ee5e133cac Mon Sep 17 00:00:00 2001 From: Zhaoyang You <45031352+sinceforYy@users.noreply.github.com> Date: Sat, 14 Sep 2024 10:02:15 +0800 Subject: [PATCH] fix(csr): add support non register interrupt pending (#465) This PR adds support for non-register interrupts pending to copy the interrupt to NEMU. The interrupts come from Count overflow and Platform-Level Interrupt Controller such as PLIC, CLINT, IMSIC. Thus, we could diff xip csr registers. --- README.md | 1 + src/main/scala/Bundles.scala | 11 +++++++++++ src/main/scala/Difftest.scala | 5 +++++ src/test/csrc/difftest/difftest.cpp | 27 ++++++++++++++++++++++----- src/test/csrc/difftest/difftest.h | 4 +++- src/test/csrc/difftest/refproxy.h | 20 +++++++++++++++++++- src/test/scala/DifftestTop.scala | 1 + 7 files changed, 62 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 6bbf4bce..132ae64c 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,7 @@ coherence via RefillTest. | `DiffL2TLBEvent` | L2 TLB operations | No | | `DiffRefillEvent` | Cache refill operations | No | | `DiffLrScEvent` | Executed LR/SC instructions | No | +| `DiffNonRegInterruptPengingEvent` | Non-register interrupts pending | No | The DiffTest framework comes with a simulation framework with some top-level IOs. They will be automatically created when calling `DifftestModule.finish(cpu: String)`. diff --git a/src/main/scala/Bundles.scala b/src/main/scala/Bundles.scala index 58901629..def4bda2 100644 --- a/src/main/scala/Bundles.scala +++ b/src/main/scala/Bundles.scala @@ -301,6 +301,17 @@ class RunaheadRedirectEvent extends DifftestBaseBundle with HasValid { val checkpoint_id = UInt(64.W) } +class NonRegInterruptPendingEvent extends DifftestBaseBundle with HasValid { + val platformIRPMeip = Bool() + val platformIRPMtip = Bool() + val platformIRPMsip = Bool() + val platformIRPSeip = Bool() + val platformIRPStip = Bool() + val platformIRPVseip = Bool() + val platformIRPVstip = Bool() + val localCounterOverflowInterruptReq = Bool() +} + class TraceInfo extends DifftestBaseBundle with HasValid { val in_replay = Bool() val trace_head = UInt(16.W) diff --git a/src/main/scala/Difftest.scala b/src/main/scala/Difftest.scala index ebae8eca..fef576e5 100644 --- a/src/main/scala/Difftest.scala +++ b/src/main/scala/Difftest.scala @@ -405,6 +405,11 @@ class DiffRunaheadRedirectEvent extends RunaheadRedirectEvent with DifftestBundl override val desiredCppName: String = "runahead_redirect" } +class DiffNonRegInterruptPendingEvent extends NonRegInterruptPendingEvent with DifftestBundle { + override val desiredCppName: String = "non_reg_interrupt_pending" + +} + class DiffTraceInfo(config: GatewayConfig) extends TraceInfo with DifftestBundle { override val desiredCppName: String = "trace_info" diff --git a/src/test/csrc/difftest/difftest.cpp b/src/test/csrc/difftest/difftest.cpp index 2dbdda42..b7a3d250 100644 --- a/src/test/csrc/difftest/difftest.cpp +++ b/src/test/csrc/difftest/difftest.cpp @@ -316,6 +316,10 @@ int Difftest::step() { } #endif +#ifdef CONFIG_DIFFTEST_NONREGINTERRUPTPENDINGEVENT + do_non_reg_interrupt_pending(); +#endif + num_commit = 0; // reset num_commit this cycle to 0 if (dut->event.valid) { // interrupt has a higher priority than exception @@ -363,11 +367,6 @@ int Difftest::step() { state->record_group(dut->commit[0].pc, num_commit); } - // FIXME: the following code is dirty - if (dut->csr.mip != proxy->csr.mip) { // Ignore difftest for MIP - proxy->csr.mip = dut->csr.mip; - } - if (apply_delayed_writeback()) { return 1; } @@ -1230,6 +1229,24 @@ void Difftest::raise_trap(int trapCode) { dut->trap.code = trapCode; } +#ifdef CONFIG_DIFFTEST_NONREGINTERRUPTPENDINGEVENT +void Difftest::do_non_reg_interrupt_pending() { + if (dut->non_reg_interrupt_pending.valid) { + struct NonRegInterruptPending ip; + ip.platformIRPMtip = dut->non_reg_interrupt_pending.platformIRPMtip; + ip.platformIRPMeip = dut->non_reg_interrupt_pending.platformIRPMeip; + ip.platformIRPMsip = dut->non_reg_interrupt_pending.platformIRPMsip; + ip.platformIRPSeip = dut->non_reg_interrupt_pending.platformIRPSeip; + ip.platformIRPStip = dut->non_reg_interrupt_pending.platformIRPStip; + ip.platformIRPVseip = dut->non_reg_interrupt_pending.platformIRPVseip; + ip.platformIRPVstip = dut->non_reg_interrupt_pending.platformIRPVstip; + ip.localCounterOverflowInterruptReq = dut->non_reg_interrupt_pending.localCounterOverflowInterruptReq; + + proxy->non_reg_interrupt_pending(ip); + } +} +#endif + void Difftest::display() { printf("\n============== In the last commit group ==============\n"); printf("the first commit instr pc of DUT is 0x%016lx\nthe first commit instr pc of REF is 0x%016lx\n", diff --git a/src/test/csrc/difftest/difftest.h b/src/test/csrc/difftest/difftest.h index adf6c65a..1069bc50 100644 --- a/src/test/csrc/difftest/difftest.h +++ b/src/test/csrc/difftest/difftest.h @@ -409,7 +409,9 @@ protected: int apply_delayed_writeback(); void raise_trap(int trapCode); - +#ifdef CONFIG_DIFFTEST_NONREGINTERRUPTPENDINGEVENT + void do_non_reg_interrupt_pending(); +#endif #ifdef CONFIG_DIFFTEST_REPLAY struct { bool in_replay = false; diff --git a/src/test/csrc/difftest/refproxy.h b/src/test/csrc/difftest/refproxy.h index 44da0546..c7e0e178 100644 --- a/src/test/csrc/difftest/refproxy.h +++ b/src/test/csrc/difftest/refproxy.h @@ -145,7 +145,8 @@ public: f(ref_guided_exec, difftest_guided_exec, void, void*) \ f(raise_nmi_intr, difftest_raise_nmi_intr, void, bool) \ f(ref_virtual_interrupt_is_hvictl_inject, difftest_virtual_interrupt_is_hvictl_inject, void, bool) \ - f(disambiguation_state, difftest_disambiguation_state, int, ) + f(disambiguation_state, difftest_disambiguation_state, int, ) \ + f(ref_non_reg_interrupt_pending, difftest_non_reg_interrupt_pending, void, void*) #define RefFunc(func, ret, ...) ret func(__VA_ARGS__) #define DeclRefFunc(this_func, dummy, ret, ...) RefFunc((*this_func), ret, __VA_ARGS__); @@ -243,6 +244,12 @@ public: } } + inline void non_reg_interrupt_pending(struct NonRegInterruptPending &ip) { + if (ref_non_reg_interrupt_pending) { + ref_non_reg_interrupt_pending(&ip); + } + } + inline void guided_exec(struct ExecutionGuide &guide) { return ref_guided_exec ? ref_guided_exec(&guide) : ref_exec(1); } @@ -342,6 +349,17 @@ struct ExecutionGuide { uint64_t jump_target; }; +struct NonRegInterruptPending { + bool platformIRPMtip; + bool platformIRPMeip; + bool platformIRPMsip; + bool platformIRPSeip; + bool platformIRPStip; + bool platformIRPVseip; + bool platformIRPVstip; + bool localCounterOverflowInterruptReq; +}; + extern const char *difftest_ref_so; extern uint8_t *ref_golden_mem; diff --git a/src/test/scala/DifftestTop.scala b/src/test/scala/DifftestTop.scala index 01487302..0e8a48d2 100644 --- a/src/test/scala/DifftestTop.scala +++ b/src/test/scala/DifftestTop.scala @@ -55,6 +55,7 @@ class DifftestTop extends Module { val difftest_runahead_event = DifftestModule(new DiffRunaheadEvent, dontCare = true) val difftest_runahead_commit_event = DifftestModule(new DiffRunaheadCommitEvent, dontCare = true) val difftest_runahead_redirect_event = DifftestModule(new DiffRunaheadRedirectEvent, dontCare = true) + val difftest_non_reg_interrupt_pending_event = DifftestModule(new DiffNonRegInterruptPendingEvent, dontCare = true) DifftestModule.finish("demo") }