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.
This commit is contained in:
Zhaoyang You 2024-09-14 10:02:15 +08:00 committed by GitHub
parent a1b35f7fda
commit d0c338cb42
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 62 additions and 7 deletions

View File

@ -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)`.

View File

@ -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)

View File

@ -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"

View File

@ -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",

View File

@ -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;

View File

@ -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;

View File

@ -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")
}