Skip to content

Commit 7a07a66

Browse files
committed
[cosim] Cosim integration of internal NMI
Signed-off-by: Canberk Topal <[email protected]>
1 parent 554de79 commit 7a07a66

16 files changed

+64
-3
lines changed

dv/cosim/cosim.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,13 @@ class Cosim {
9595
// When an NMI is due to be taken that will occur at the next call of `step`.
9696
virtual void set_nmi(bool nmi) = 0;
9797

98+
// Set the state of the internal NMI (non-maskable interrupt) line.
99+
// Behaviour wise this is almost as same as external NMI case explained at
100+
// set_nmi method. Main difference to consider is that this interrupt is
101+
// synchronous because it comes from the integrity checking logic inside the
102+
// core.
103+
virtual void set_nmi_int(bool nmi_int) = 0;
104+
98105
// Set the debug request.
99106
//
100107
// When set to true the core will enter debug mode at the next step

dv/cosim/cosim_dpi.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ void riscv_cosim_set_nmi(Cosim *cosim, svBit nmi) {
2828
cosim->set_nmi(nmi);
2929
}
3030

31+
void riscv_cosim_set_nmi_int(Cosim *cosim, svBit nmi_int) {
32+
assert(cosim);
33+
34+
cosim->set_nmi_int(nmi_int);
35+
}
3136
void riscv_cosim_set_debug_req(Cosim *cosim, svBit debug_req) {
3237
assert(cosim);
3338

dv/cosim/cosim_dpi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ int riscv_cosim_step(Cosim *cosim, const svBitVecVal *write_reg,
1717
svBit sync_trap);
1818
void riscv_cosim_set_mip(Cosim *cosim, const svBitVecVal *mip);
1919
void riscv_cosim_set_nmi(Cosim *cosim, svBit nmi);
20+
void riscv_cosim_set_nmi_int(Cosim *cosim, svBit nmi_int);
2021
void riscv_cosim_set_debug_req(Cosim *cosim, svBit debug_req);
2122
void riscv_cosim_set_mcycle(Cosim *cosim, svBitVecVal *mcycle);
2223
void riscv_cosim_set_csr(Cosim *cosim, const int csr_id,

dv/cosim/cosim_dpi.svh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import "DPI-C" function int riscv_cosim_step(chandle cosim_handle, bit [4:0] wri
1414
bit [31:0] write_reg_data, bit [31:0] pc, bit sync_trap);
1515
import "DPI-C" function void riscv_cosim_set_mip(chandle cosim_handle, bit [31:0] mip);
1616
import "DPI-C" function void riscv_cosim_set_nmi(chandle cosim_handle, bit nmi);
17+
import "DPI-C" function void riscv_cosim_set_nmi_int(chandle cosim_handle, bit nmi_int);
1718
import "DPI-C" function void riscv_cosim_set_debug_req(chandle cosim_handle, bit debug_req);
1819
import "DPI-C" function void riscv_cosim_set_mcycle(chandle cosim_handle, bit [63:0] mcycle);
1920
import "DPI-C" function void riscv_cosim_set_csr(chandle cosim_handle, int csr_id,

dv/cosim/spike_cosim.cc

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,10 @@ bool SpikeCosim::step(uint32_t write_reg, uint32_t write_reg_data,
200200

201201
if (processor->get_state()->last_inst_pc == PC_INVALID) {
202202
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)
204207
// Spike encountered a synchronous trap
205208
pending_sync_exception = true;
206209

@@ -358,6 +361,12 @@ bool SpikeCosim::check_sync_trap(uint32_t write_reg,
358361
return false;
359362
}
360363

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+
361370
// Errors may have been generated outside of step() (e.g. in
362371
// check_mem_access()), return false if there are any.
363372
if (errors.size() != 0) {
@@ -480,6 +489,20 @@ void SpikeCosim::set_nmi(bool nmi) {
480489
}
481490
}
482491

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+
483506
void SpikeCosim::set_debug_req(bool debug_req) {
484507
processor->halt_request =
485508
debug_req ? processor_t::HR_REGULAR : processor_t::HR_NONE;

dv/cosim/spike_cosim.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ class SpikeCosim : public simif_t, public Cosim {
102102
uint32_t initial_spike_pc);
103103
void set_mip(uint32_t mip) override;
104104
void set_nmi(bool nmi) override;
105+
void set_nmi_int(bool nmi_int) override;
105106
void set_debug_req(bool debug_req) override;
106107
void set_mcycle(uint64_t mcycle) override;
107108
void set_csr(const int csr_num, const uint32_t new_val) override;

dv/uvm/core_ibex/common/ibex_cosim_agent/ibex_cosim_scoreboard.sv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ class ibex_cosim_scoreboard extends uvm_scoreboard;
122122
end
123123

124124
riscv_cosim_set_nmi(cosim_handle, rvfi_instr.nmi);
125+
riscv_cosim_set_nmi_int(cosim_handle, rvfi_instr.nmi_int);
125126
riscv_cosim_set_mip(cosim_handle, rvfi_instr.mip);
126127
riscv_cosim_set_debug_req(cosim_handle, rvfi_instr.debug_req);
127128
riscv_cosim_set_mcycle(cosim_handle, rvfi_instr.mcycle);

dv/uvm/core_ibex/common/ibex_cosim_agent/ibex_rvfi_monitor.sv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class ibex_rvfi_monitor extends uvm_monitor;
3838
trans_collected.order = vif.monitor_cb.order;
3939
trans_collected.mip = vif.monitor_cb.ext_mip;
4040
trans_collected.nmi = vif.monitor_cb.ext_nmi;
41+
trans_collected.nmi_int = vif.monitor_cb.ext_nmi_int;
4142
trans_collected.debug_req = vif.monitor_cb.ext_debug_req;
4243
trans_collected.mcycle = vif.monitor_cb.ext_mcycle;
4344
trans_collected.ic_scr_key_valid = vif.monitor_cb.ext_ic_scr_key_valid;

dv/uvm/core_ibex/common/ibex_cosim_agent/ibex_rvfi_seq_item.sv

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class ibex_rvfi_seq_item extends uvm_sequence_item;
1010
bit [63:0] order;
1111
bit [31:0] mip;
1212
bit nmi;
13+
bit nmi_int;
1314
bit debug_req;
1415
bit [63:0] mcycle;
1516

@@ -25,6 +26,7 @@ class ibex_rvfi_seq_item extends uvm_sequence_item;
2526
`uvm_field_int (order, UVM_DEFAULT)
2627
`uvm_field_int (mip, UVM_DEFAULT)
2728
`uvm_field_int (nmi, UVM_DEFAULT)
29+
`uvm_field_int (nmi_int, UVM_DEFAULT)
2830
`uvm_field_int (debug_req, UVM_DEFAULT)
2931
`uvm_field_int (mcycle, UVM_DEFAULT)
3032
`uvm_field_sarray_int (mhpmcounters, UVM_DEFAULT)

dv/uvm/core_ibex/env/core_ibex_rvfi_if.sv

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ interface core_ibex_rvfi_if(input logic clk);
2828
logic [31:0] mem_wdata;
2929
logic [31:0] ext_mip;
3030
logic ext_nmi;
31+
logic ext_nmi_int;
3132
logic [31:0] ext_debug_req;
3233
logic [63:0] ext_mcycle;
3334

@@ -61,6 +62,7 @@ interface core_ibex_rvfi_if(input logic clk);
6162
input mem_wdata;
6263
input ext_mip;
6364
input ext_nmi;
65+
input ext_nmi_int;
6466
input ext_debug_req;
6567
input ext_mcycle;
6668
input ext_mhpmcounters;

0 commit comments

Comments
 (0)