@@ -200,7 +200,10 @@ bool SpikeCosim::step(uint32_t write_reg, uint32_t write_reg_data,
200
200
201
201
if (processor->get_state ()->last_inst_pc == PC_INVALID) {
202
202
if (!(processor->get_state ()->mcause ->read () & 0x80000000 ) ||
203
- processor->get_state ()->debug_mode ) { // (Async-Traps are disabled in debug mode)
203
+ (processor->get_state ()->mcause ->read () &
204
+ 0xFFFFFFE0 ) || // Internal NMI is a sync trap
205
+ processor->get_state ()
206
+ ->debug_mode ) { // (Async-Traps are disabled in debug mode)
204
207
// Spike encountered a synchronous trap
205
208
pending_sync_exception = true ;
206
209
@@ -358,6 +361,12 @@ bool SpikeCosim::check_sync_trap(uint32_t write_reg,
358
361
return false ;
359
362
}
360
363
364
+ // If we see an internal NMI, that means we receive an extra memory intf item.
365
+ // Deleting that is necessary since next Load/Store would fail otherwise.
366
+ if (processor->get_state ()->mcause ->read () & 0xFFFFFFE0 ) {
367
+ pending_dside_accesses.erase (pending_dside_accesses.begin ());
368
+ }
369
+
361
370
// Errors may have been generated outside of step() (e.g. in
362
371
// check_mem_access()), return false if there are any.
363
372
if (errors.size () != 0 ) {
@@ -480,6 +489,20 @@ void SpikeCosim::set_nmi(bool nmi) {
480
489
}
481
490
}
482
491
492
+ void SpikeCosim::set_nmi_int (bool nmi_int) {
493
+ if (nmi_int && !nmi_mode && !processor->get_state ()->debug_mode ) {
494
+ processor->get_state ()->nmi_int = true ;
495
+ nmi_mode = true ;
496
+
497
+ // When NMI is set it is guaranteed NMI trap will be taken at the next step
498
+ // so save CSR state for recoverable NMI to mstack now.
499
+ mstack.mpp = get_field (processor->get_csr (CSR_MSTATUS), MSTATUS_MPP);
500
+ mstack.mpie = get_field (processor->get_csr (CSR_MSTATUS), MSTATUS_MPIE);
501
+ mstack.epc = processor->get_csr (CSR_MEPC);
502
+ mstack.cause = processor->get_csr (CSR_MCAUSE);
503
+ }
504
+ }
505
+
483
506
void SpikeCosim::set_debug_req (bool debug_req) {
484
507
processor->halt_request =
485
508
debug_req ? processor_t ::HR_REGULAR : processor_t ::HR_NONE;
0 commit comments