Skip to content

Commit 1e3b1fb

Browse files
committed
[cosim] Cosim integration of internal NMI
Signed-off-by: Canberk Topal <ctopal@lowrisc.org>
1 parent 554de79 commit 1e3b1fb

File tree

15 files changed

+63
-3
lines changed

15 files changed

+63
-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;

dv/uvm/core_ibex/tb/core_ibex_tb_top.sv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ module core_ibex_tb_top;
192192
assign rvfi_if.mem_wdata = dut.rvfi_mem_wdata;
193193
assign rvfi_if.ext_mip = dut.rvfi_ext_mip;
194194
assign rvfi_if.ext_nmi = dut.rvfi_ext_nmi;
195+
assign rvfi_if.ext_nmi_int = dut.rvfi_ext_nmi_int;
195196
assign rvfi_if.ext_debug_req = dut.rvfi_ext_debug_req;
196197
assign rvfi_if.ext_mcycle = dut.rvfi_ext_mcycle;
197198
assign rvfi_if.ext_mhpmcounters = dut.rvfi_ext_mhpmcounters;

dv/verilator/simple_system_cosim/ibex_simple_system_cosim_checker.sv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ module ibex_simple_system_cosim_checker #(
4343
always @(posedge clk_i) begin
4444
if (u_top.rvfi_valid) begin
4545
riscv_cosim_set_nmi(cosim_handle, u_top.rvfi_ext_nmi);
46+
riscv_cosim_set_nmi_int(cosim_handle, u_top.rvfi_ext_nmi_int);
4647
riscv_cosim_set_mip(cosim_handle, u_top.rvfi_ext_mip);
4748
riscv_cosim_set_debug_req(cosim_handle, u_top.rvfi_ext_debug_req);
4849
riscv_cosim_set_mcycle(cosim_handle, u_top.rvfi_ext_mcycle);

rtl/ibex_core.sv

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ module ibex_core import ibex_pkg::*; #(
138138
output logic [31:0] rvfi_mem_wdata,
139139
output logic [31:0] rvfi_ext_mip,
140140
output logic rvfi_ext_nmi,
141+
output logic rvfi_ext_nmi_int,
141142
output logic rvfi_ext_debug_req,
142143
output logic [63:0] rvfi_ext_mcycle,
143144
output logic [31:0] rvfi_ext_mhpmcounters [10],
@@ -1172,6 +1173,7 @@ module ibex_core import ibex_pkg::*; #(
11721173

11731174
logic new_debug_req;
11741175
logic new_nmi;
1176+
logic new_nmi_int;
11751177
logic new_irq;
11761178
ibex_pkg::irqs_t captured_mip;
11771179
logic captured_nmi;
@@ -1184,6 +1186,7 @@ module ibex_core import ibex_pkg::*; #(
11841186
// debug_req and MIP captured at IF -> ID transition so one extra stage
11851187
ibex_pkg::irqs_t rvfi_ext_stage_mip [RVFI_STAGES+1];
11861188
logic rvfi_ext_stage_nmi [RVFI_STAGES+1];
1189+
logic rvfi_ext_stage_nmi_int [RVFI_STAGES];
11871190
logic rvfi_ext_stage_debug_req [RVFI_STAGES+1];
11881191
logic [63:0] rvfi_ext_stage_mcycle [RVFI_STAGES];
11891192
logic [31:0] rvfi_ext_stage_mhpmcounters [RVFI_STAGES][10];
@@ -1232,6 +1235,7 @@ module ibex_core import ibex_pkg::*; #(
12321235
end
12331236

12341237
assign rvfi_ext_nmi = rvfi_ext_stage_nmi [RVFI_STAGES];
1238+
assign rvfi_ext_nmi_int = rvfi_ext_stage_nmi_int [RVFI_STAGES-1];
12351239
assign rvfi_ext_debug_req = rvfi_ext_stage_debug_req [RVFI_STAGES];
12361240
assign rvfi_ext_mcycle = rvfi_ext_stage_mcycle [RVFI_STAGES-1];
12371241
assign rvfi_ext_mhpmcounters = rvfi_ext_stage_mhpmcounters [RVFI_STAGES-1];
@@ -1261,7 +1265,7 @@ module ibex_core import ibex_pkg::*; #(
12611265
(rvfi_stage_valid[0] & ~rvfi_wb_done);
12621266
// Second stage is output stage so simple valid cycle after instruction leaves WB (and so has
12631267
// retired)
1264-
assign rvfi_stage_valid_d[1] = rvfi_wb_done;
1268+
assign rvfi_stage_valid_d[1] = rvfi_wb_done && !rvfi_ext_nmi_int;
12651269

12661270
// Signal new instruction in WB cycle after instruction leaves ID/EX (to enter WB)
12671271
logic rvfi_instr_new_wb_q;
@@ -1279,7 +1283,7 @@ module ibex_core import ibex_pkg::*; #(
12791283
end
12801284

12811285
assign rvfi_trap_id = id_stage_i.controller_i.id_exception_o;
1282-
assign rvfi_trap_wb = id_stage_i.controller_i.exc_req_lsu;
1286+
assign rvfi_trap_wb = id_stage_i.controller_i.exc_req_lsu | new_nmi_int;
12831287
// WB is instantly done in the tracking pipeline when a trap is progress through the pipeline
12841288
assign rvfi_wb_done = instr_done_wb | (rvfi_stage_valid[0] & rvfi_stage_trap[0]);
12851289
end else begin : gen_rvfi_no_wb_stage
@@ -1319,6 +1323,7 @@ module ibex_core import ibex_pkg::*; #(
13191323
// appropriately.
13201324
assign new_debug_req = (debug_req_i & ~debug_mode);
13211325
assign new_nmi = irq_nm_i & ~nmi_mode & ~debug_mode;
1326+
assign new_nmi_int = lsu_load_intg_err & ~nmi_mode & ~debug_mode;
13221327
assign new_irq = irq_pending_o & csr_mstatus_mie & ~nmi_mode & ~debug_mode;
13231328

13241329
always_ff @(posedge clk_i or negedge rst_ni) begin
@@ -1403,6 +1408,7 @@ module ibex_core import ibex_pkg::*; #(
14031408
rvfi_stage_mem_addr[i] <= '0;
14041409
rvfi_ext_stage_mip[i+1] <= '0;
14051410
rvfi_ext_stage_nmi[i+1] <= '0;
1411+
rvfi_ext_stage_nmi_int[i] <= '0;
14061412
rvfi_ext_stage_debug_req[i+1] <= '0;
14071413
rvfi_ext_stage_mcycle[i] <= '0;
14081414
rvfi_ext_stage_mhpmcounters[i] <= '{10{'0}};
@@ -1438,6 +1444,7 @@ module ibex_core import ibex_pkg::*; #(
14381444
rvfi_stage_mem_addr[i] <= rvfi_mem_addr_d;
14391445
rvfi_ext_stage_mip[i+1] <= rvfi_ext_stage_mip[i];
14401446
rvfi_ext_stage_nmi[i+1] <= rvfi_ext_stage_nmi[i];
1447+
rvfi_ext_stage_nmi_int[i] <= '0;
14411448
rvfi_ext_stage_debug_req[i+1] <= rvfi_ext_stage_debug_req[i];
14421449
rvfi_ext_stage_mcycle[i] <= cs_registers_i.mcycle_counter_i.counter_val_o;
14431450
rvfi_ext_stage_ic_scr_key_valid[i] <= cs_registers_i.cpuctrlsts_ic_scr_key_valid_q;
@@ -1480,6 +1487,7 @@ module ibex_core import ibex_pkg::*; #(
14801487

14811488
rvfi_ext_stage_mip[i+1] <= rvfi_ext_stage_mip[i];
14821489
rvfi_ext_stage_nmi[i+1] <= rvfi_ext_stage_nmi[i];
1490+
rvfi_ext_stage_nmi_int[i] <= new_nmi_int;
14831491
rvfi_ext_stage_debug_req[i+1] <= rvfi_ext_stage_debug_req[i];
14841492
rvfi_ext_stage_mcycle[i] <= rvfi_ext_stage_mcycle[i-1];
14851493
rvfi_ext_stage_ic_scr_key_valid[i] <= rvfi_ext_stage_ic_scr_key_valid[i-1];

rtl/ibex_top.sv

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ module ibex_top import ibex_pkg::*; #(
118118
output logic [31:0] rvfi_mem_wdata,
119119
output logic [31:0] rvfi_ext_mip,
120120
output logic rvfi_ext_nmi,
121+
output logic rvfi_ext_nmi_int,
121122
output logic rvfi_ext_debug_req,
122123
output logic [63:0] rvfi_ext_mcycle,
123124
output logic [31:0] rvfi_ext_mhpmcounters [10],
@@ -366,6 +367,7 @@ module ibex_top import ibex_pkg::*; #(
366367
.rvfi_mem_wdata,
367368
.rvfi_ext_mip,
368369
.rvfi_ext_nmi,
370+
.rvfi_ext_nmi_int,
369371
.rvfi_ext_debug_req,
370372
.rvfi_ext_mcycle,
371373
.rvfi_ext_mhpmcounters,

rtl/ibex_top_tracing.sv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ module ibex_top_tracing import ibex_pkg::*; #(
121121
logic [31:0] rvfi_mem_wdata;
122122
logic [31:0] rvfi_ext_mip;
123123
logic rvfi_ext_nmi;
124+
logic rvfi_ext_nmi_int;
124125
logic rvfi_ext_debug_req;
125126
logic [63:0] rvfi_ext_mcycle;
126127

@@ -134,6 +135,7 @@ module ibex_top_tracing import ibex_pkg::*; #(
134135

135136
logic [31:0] unused_rvfi_ext_mip;
136137
logic unused_rvfi_ext_nmi;
138+
logic unused_rvfi_ext_nmi_int;
137139
logic unused_rvfi_ext_debug_req;
138140
logic [63:0] unused_rvfi_ext_mcycle;
139141
logic unused_rvfi_ext_ic_scr_key_valid;
@@ -142,6 +144,7 @@ module ibex_top_tracing import ibex_pkg::*; #(
142144
// them.
143145
assign unused_rvfi_ext_mip = rvfi_ext_mip;
144146
assign unused_rvfi_ext_nmi = rvfi_ext_nmi;
147+
assign unused_rvfi_ext_nmi_int = rvfi_ext_nmi_int;
145148
assign unused_rvfi_ext_debug_req = rvfi_ext_debug_req;
146149
assign unused_rvfi_ext_mcycle = rvfi_ext_mcycle;
147150
assign unused_perf_regs = rvfi_ext_mhpmcounters;
@@ -242,6 +245,7 @@ module ibex_top_tracing import ibex_pkg::*; #(
242245
.rvfi_mem_wdata,
243246
.rvfi_ext_mip,
244247
.rvfi_ext_nmi,
248+
.rvfi_ext_nmi_int,
245249
.rvfi_ext_debug_req,
246250
.rvfi_ext_mcycle,
247251
.rvfi_ext_mhpmcounters,

0 commit comments

Comments
 (0)