Skip to content

Commit

Permalink
[cosim] Cosim integration of internal NMI
Browse files Browse the repository at this point in the history
This commit is mainly an extension to cosim environment to drive the newly
introduced state variable `nmi_int` in Spike.

Internal NMI's in Ibex are synchronous by nature. Because they only happen
when we see an integrity error from a memory response which happens in
WB (if nonexistent ID/EX) stage.

This commit
 - Extends RVFI interface by a single bit (ext_nmi_int)
 - Configures cosim to set nmi_int inside Spike
 - Changes internals of SpikeCosim object to reflect internal NMI behaviour
   in Ibex. Namely, being a synchronous and producing an extra dside access.

Signed-off-by: Canberk Topal <ctopal@lowrisc.org>
  • Loading branch information
ctopal committed Oct 17, 2022
1 parent bd68f07 commit 00dcce7
Show file tree
Hide file tree
Showing 16 changed files with 64 additions and 3 deletions.
7 changes: 7 additions & 0 deletions dv/cosim/cosim.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@ class Cosim {
// When an NMI is due to be taken that will occur at the next call of `step`.
virtual void set_nmi(bool nmi) = 0;

// Set the state of the internal NMI (non-maskable interrupt) line.
// Behaviour wise this is almost as same as external NMI case explained at
// set_nmi method. Main difference to consider is that this interrupt is
// synchronous because it comes from the integrity checking logic inside the
// core.
virtual void set_nmi_int(bool nmi_int) = 0;

// Set the debug request.
//
// When set to true the core will enter debug mode at the next step
Expand Down
5 changes: 5 additions & 0 deletions dv/cosim/cosim_dpi.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ void riscv_cosim_set_nmi(Cosim *cosim, svBit nmi) {
cosim->set_nmi(nmi);
}

void riscv_cosim_set_nmi_int(Cosim *cosim, svBit nmi_int) {
assert(cosim);

cosim->set_nmi_int(nmi_int);
}
void riscv_cosim_set_debug_req(Cosim *cosim, svBit debug_req) {
assert(cosim);

Expand Down
1 change: 1 addition & 0 deletions dv/cosim/cosim_dpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ int riscv_cosim_step(Cosim *cosim, const svBitVecVal *write_reg,
svBit sync_trap);
void riscv_cosim_set_mip(Cosim *cosim, const svBitVecVal *mip);
void riscv_cosim_set_nmi(Cosim *cosim, svBit nmi);
void riscv_cosim_set_nmi_int(Cosim *cosim, svBit nmi_int);
void riscv_cosim_set_debug_req(Cosim *cosim, svBit debug_req);
void riscv_cosim_set_mcycle(Cosim *cosim, svBitVecVal *mcycle);
void riscv_cosim_set_csr(Cosim *cosim, const int csr_id,
Expand Down
1 change: 1 addition & 0 deletions dv/cosim/cosim_dpi.svh
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import "DPI-C" function int riscv_cosim_step(chandle cosim_handle, bit [4:0] wri
bit [31:0] write_reg_data, bit [31:0] pc, bit sync_trap);
import "DPI-C" function void riscv_cosim_set_mip(chandle cosim_handle, bit [31:0] mip);
import "DPI-C" function void riscv_cosim_set_nmi(chandle cosim_handle, bit nmi);
import "DPI-C" function void riscv_cosim_set_nmi_int(chandle cosim_handle, bit nmi_int);
import "DPI-C" function void riscv_cosim_set_debug_req(chandle cosim_handle, bit debug_req);
import "DPI-C" function void riscv_cosim_set_mcycle(chandle cosim_handle, bit [63:0] mcycle);
import "DPI-C" function void riscv_cosim_set_csr(chandle cosim_handle, int csr_id,
Expand Down
25 changes: 24 additions & 1 deletion dv/cosim/spike_cosim.cc
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,10 @@ bool SpikeCosim::step(uint32_t write_reg, uint32_t write_reg_data,

if (processor->get_state()->last_inst_pc == PC_INVALID) {
if (!(processor->get_state()->mcause->read() & 0x80000000) ||
processor->get_state()->debug_mode) { // (Async-Traps are disabled in debug mode)
(processor->get_state()->mcause->read() ==
0xFFFFFFE0) || // Internal NMI is a sync trap
processor->get_state()
->debug_mode) { // (Async-Traps are disabled in debug mode)
// Spike encountered a synchronous trap
pending_sync_exception = true;

Expand Down Expand Up @@ -358,6 +361,12 @@ bool SpikeCosim::check_sync_trap(uint32_t write_reg,
return false;
}

// If we see an internal NMI, that means we receive an extra memory intf item.
// Deleting that is necessary since next Load/Store would fail otherwise.
if (processor->get_state()->mcause->read() == 0xFFFFFFE0) {
pending_dside_accesses.erase(pending_dside_accesses.begin());
}

// Errors may have been generated outside of step() (e.g. in
// check_mem_access()), return false if there are any.
if (errors.size() != 0) {
Expand Down Expand Up @@ -480,6 +489,20 @@ void SpikeCosim::set_nmi(bool nmi) {
}
}

void SpikeCosim::set_nmi_int(bool nmi_int) {
if (nmi_int && !nmi_mode && !processor->get_state()->debug_mode) {
processor->get_state()->nmi_int = true;
nmi_mode = true;

// When NMI is set it is guaranteed NMI trap will be taken at the next step
// so save CSR state for recoverable NMI to mstack now.
mstack.mpp = get_field(processor->get_csr(CSR_MSTATUS), MSTATUS_MPP);
mstack.mpie = get_field(processor->get_csr(CSR_MSTATUS), MSTATUS_MPIE);
mstack.epc = processor->get_csr(CSR_MEPC);
mstack.cause = processor->get_csr(CSR_MCAUSE);
}
}

void SpikeCosim::set_debug_req(bool debug_req) {
processor->halt_request =
debug_req ? processor_t::HR_REGULAR : processor_t::HR_NONE;
Expand Down
1 change: 1 addition & 0 deletions dv/cosim/spike_cosim.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ class SpikeCosim : public simif_t, public Cosim {
uint32_t initial_spike_pc);
void set_mip(uint32_t mip) override;
void set_nmi(bool nmi) override;
void set_nmi_int(bool nmi_int) override;
void set_debug_req(bool debug_req) override;
void set_mcycle(uint64_t mcycle) override;
void set_csr(const int csr_num, const uint32_t new_val) override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ class ibex_cosim_scoreboard extends uvm_scoreboard;
end

riscv_cosim_set_nmi(cosim_handle, rvfi_instr.nmi);
riscv_cosim_set_nmi_int(cosim_handle, rvfi_instr.nmi_int);
riscv_cosim_set_mip(cosim_handle, rvfi_instr.mip);
riscv_cosim_set_debug_req(cosim_handle, rvfi_instr.debug_req);
riscv_cosim_set_mcycle(cosim_handle, rvfi_instr.mcycle);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class ibex_rvfi_monitor extends uvm_monitor;
trans_collected.order = vif.monitor_cb.order;
trans_collected.mip = vif.monitor_cb.ext_mip;
trans_collected.nmi = vif.monitor_cb.ext_nmi;
trans_collected.nmi_int = vif.monitor_cb.ext_nmi_int;
trans_collected.debug_req = vif.monitor_cb.ext_debug_req;
trans_collected.mcycle = vif.monitor_cb.ext_mcycle;
trans_collected.ic_scr_key_valid = vif.monitor_cb.ext_ic_scr_key_valid;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class ibex_rvfi_seq_item extends uvm_sequence_item;
bit [63:0] order;
bit [31:0] mip;
bit nmi;
bit nmi_int;
bit debug_req;
bit [63:0] mcycle;

Expand All @@ -25,6 +26,7 @@ class ibex_rvfi_seq_item extends uvm_sequence_item;
`uvm_field_int (order, UVM_DEFAULT)
`uvm_field_int (mip, UVM_DEFAULT)
`uvm_field_int (nmi, UVM_DEFAULT)
`uvm_field_int (nmi_int, UVM_DEFAULT)
`uvm_field_int (debug_req, UVM_DEFAULT)
`uvm_field_int (mcycle, UVM_DEFAULT)
`uvm_field_sarray_int (mhpmcounters, UVM_DEFAULT)
Expand Down
2 changes: 2 additions & 0 deletions dv/uvm/core_ibex/env/core_ibex_rvfi_if.sv
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ interface core_ibex_rvfi_if(input logic clk);
logic [31:0] mem_wdata;
logic [31:0] ext_mip;
logic ext_nmi;
logic ext_nmi_int;
logic [31:0] ext_debug_req;
logic [63:0] ext_mcycle;

Expand Down Expand Up @@ -61,6 +62,7 @@ interface core_ibex_rvfi_if(input logic clk);
input mem_wdata;
input ext_mip;
input ext_nmi;
input ext_nmi_int;
input ext_debug_req;
input ext_mcycle;
input ext_mhpmcounters;
Expand Down
1 change: 1 addition & 0 deletions dv/uvm/core_ibex/tb/core_ibex_tb_top.sv
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ module core_ibex_tb_top;
assign rvfi_if.mem_wdata = dut.rvfi_mem_wdata;
assign rvfi_if.ext_mip = dut.rvfi_ext_mip;
assign rvfi_if.ext_nmi = dut.rvfi_ext_nmi;
assign rvfi_if.ext_nmi_int = dut.rvfi_ext_nmi_int;
assign rvfi_if.ext_debug_req = dut.rvfi_ext_debug_req;
assign rvfi_if.ext_mcycle = dut.rvfi_ext_mcycle;
assign rvfi_if.ext_mhpmcounters = dut.rvfi_ext_mhpmcounters;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ module ibex_simple_system_cosim_checker #(
always @(posedge clk_i) begin
if (u_top.rvfi_valid) begin
riscv_cosim_set_nmi(cosim_handle, u_top.rvfi_ext_nmi);
riscv_cosim_set_nmi_int(cosim_handle, u_top.rvfi_ext_nmi_int);
riscv_cosim_set_mip(cosim_handle, u_top.rvfi_ext_mip);
riscv_cosim_set_debug_req(cosim_handle, u_top.rvfi_ext_debug_req);
riscv_cosim_set_mcycle(cosim_handle, u_top.rvfi_ext_mcycle);
Expand Down
12 changes: 10 additions & 2 deletions rtl/ibex_core.sv
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ module ibex_core import ibex_pkg::*; #(
output logic [31:0] rvfi_mem_wdata,
output logic [31:0] rvfi_ext_mip,
output logic rvfi_ext_nmi,
output logic rvfi_ext_nmi_int,
output logic rvfi_ext_debug_req,
output logic [63:0] rvfi_ext_mcycle,
output logic [31:0] rvfi_ext_mhpmcounters [10],
Expand Down Expand Up @@ -1204,6 +1205,7 @@ module ibex_core import ibex_pkg::*; #(

logic new_debug_req;
logic new_nmi;
logic new_nmi_int;
logic new_irq;
ibex_pkg::irqs_t captured_mip;
logic captured_nmi;
Expand All @@ -1214,6 +1216,7 @@ module ibex_core import ibex_pkg::*; #(
// debug_req and MIP captured at IF -> ID transition so one extra stage
ibex_pkg::irqs_t rvfi_ext_stage_mip [RVFI_STAGES+1];
logic rvfi_ext_stage_nmi [RVFI_STAGES+1];
logic rvfi_ext_stage_nmi_int [RVFI_STAGES];
logic rvfi_ext_stage_debug_req [RVFI_STAGES+1];
logic [63:0] rvfi_ext_stage_mcycle [RVFI_STAGES];
logic [31:0] rvfi_ext_stage_mhpmcounters [RVFI_STAGES][10];
Expand Down Expand Up @@ -1262,6 +1265,7 @@ module ibex_core import ibex_pkg::*; #(
end

assign rvfi_ext_nmi = rvfi_ext_stage_nmi [RVFI_STAGES];
assign rvfi_ext_nmi_int = rvfi_ext_stage_nmi_int [RVFI_STAGES-1];
assign rvfi_ext_debug_req = rvfi_ext_stage_debug_req [RVFI_STAGES];
assign rvfi_ext_mcycle = rvfi_ext_stage_mcycle [RVFI_STAGES-1];
assign rvfi_ext_mhpmcounters = rvfi_ext_stage_mhpmcounters [RVFI_STAGES-1];
Expand Down Expand Up @@ -1291,7 +1295,7 @@ module ibex_core import ibex_pkg::*; #(
(rvfi_stage_valid[0] & ~rvfi_wb_done);
// Second stage is output stage so simple valid cycle after instruction leaves WB (and so has
// retired)
assign rvfi_stage_valid_d[1] = rvfi_wb_done;
assign rvfi_stage_valid_d[1] = rvfi_wb_done && !rvfi_ext_nmi_int;

// Signal new instruction in WB cycle after instruction leaves ID/EX (to enter WB)
logic rvfi_instr_new_wb_q;
Expand All @@ -1309,7 +1313,7 @@ module ibex_core import ibex_pkg::*; #(
end

assign rvfi_trap_id = id_stage_i.controller_i.id_exception_o;
assign rvfi_trap_wb = id_stage_i.controller_i.exc_req_lsu;
assign rvfi_trap_wb = id_stage_i.controller_i.exc_req_lsu | new_nmi_int;
// WB is instantly done in the tracking pipeline when a trap is progress through the pipeline
assign rvfi_wb_done = instr_done_wb | (rvfi_stage_valid[0] & rvfi_stage_trap[0]);
end else begin : gen_rvfi_no_wb_stage
Expand Down Expand Up @@ -1349,6 +1353,7 @@ module ibex_core import ibex_pkg::*; #(
// appropriately.
assign new_debug_req = (debug_req_i & ~debug_mode);
assign new_nmi = irq_nm_i & ~nmi_mode & ~debug_mode;
assign new_nmi_int = id_stage_i.mem_resp_intg_err & ~nmi_mode & ~debug_mode;
assign new_irq = irq_pending_o & csr_mstatus_mie & ~nmi_mode & ~debug_mode;

always_ff @(posedge clk_i or negedge rst_ni) begin
Expand Down Expand Up @@ -1423,6 +1428,7 @@ module ibex_core import ibex_pkg::*; #(
rvfi_stage_mem_addr[i] <= '0;
rvfi_ext_stage_mip[i+1] <= '0;
rvfi_ext_stage_nmi[i+1] <= '0;
rvfi_ext_stage_nmi_int[i] <= '0;
rvfi_ext_stage_debug_req[i+1] <= '0;
rvfi_ext_stage_mcycle[i] <= '0;
rvfi_ext_stage_mhpmcounters[i] <= '{10{'0}};
Expand Down Expand Up @@ -1458,6 +1464,7 @@ module ibex_core import ibex_pkg::*; #(
rvfi_stage_mem_addr[i] <= rvfi_mem_addr_d;
rvfi_ext_stage_mip[i+1] <= rvfi_ext_stage_mip[i];
rvfi_ext_stage_nmi[i+1] <= rvfi_ext_stage_nmi[i];
rvfi_ext_stage_nmi_int[i] <= '0;
rvfi_ext_stage_debug_req[i+1] <= rvfi_ext_stage_debug_req[i];
rvfi_ext_stage_mcycle[i] <= cs_registers_i.mcycle_counter_i.counter_val_o;
rvfi_ext_stage_ic_scr_key_valid[i] <= cs_registers_i.cpuctrlsts_ic_scr_key_valid_q;
Expand Down Expand Up @@ -1500,6 +1507,7 @@ module ibex_core import ibex_pkg::*; #(

rvfi_ext_stage_mip[i+1] <= rvfi_ext_stage_mip[i];
rvfi_ext_stage_nmi[i+1] <= rvfi_ext_stage_nmi[i];
rvfi_ext_stage_nmi_int[i] <= new_nmi_int;
rvfi_ext_stage_debug_req[i+1] <= rvfi_ext_stage_debug_req[i];
rvfi_ext_stage_mcycle[i] <= rvfi_ext_stage_mcycle[i-1];
rvfi_ext_stage_ic_scr_key_valid[i] <= rvfi_ext_stage_ic_scr_key_valid[i-1];
Expand Down
1 change: 1 addition & 0 deletions rtl/ibex_lockstep.sv
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ module ibex_lockstep import ibex_pkg::*; #(
.rvfi_mem_wdata (),
.rvfi_ext_mip (),
.rvfi_ext_nmi (),
.rvfi_ext_nmi_int (),
.rvfi_ext_debug_req (),
.rvfi_ext_mcycle (),
.rvfi_ext_mhpmcounters (),
Expand Down
2 changes: 2 additions & 0 deletions rtl/ibex_top.sv
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ module ibex_top import ibex_pkg::*; #(
output logic [31:0] rvfi_mem_wdata,
output logic [31:0] rvfi_ext_mip,
output logic rvfi_ext_nmi,
output logic rvfi_ext_nmi_int,
output logic rvfi_ext_debug_req,
output logic [63:0] rvfi_ext_mcycle,
output logic [31:0] rvfi_ext_mhpmcounters [10],
Expand Down Expand Up @@ -366,6 +367,7 @@ module ibex_top import ibex_pkg::*; #(
.rvfi_mem_wdata,
.rvfi_ext_mip,
.rvfi_ext_nmi,
.rvfi_ext_nmi_int,
.rvfi_ext_debug_req,
.rvfi_ext_mcycle,
.rvfi_ext_mhpmcounters,
Expand Down
4 changes: 4 additions & 0 deletions rtl/ibex_top_tracing.sv
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ module ibex_top_tracing import ibex_pkg::*; #(
logic [31:0] rvfi_mem_wdata;
logic [31:0] rvfi_ext_mip;
logic rvfi_ext_nmi;
logic rvfi_ext_nmi_int;
logic rvfi_ext_debug_req;
logic [63:0] rvfi_ext_mcycle;

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

logic [31:0] unused_rvfi_ext_mip;
logic unused_rvfi_ext_nmi;
logic unused_rvfi_ext_nmi_int;
logic unused_rvfi_ext_debug_req;
logic [63:0] unused_rvfi_ext_mcycle;
logic unused_rvfi_ext_ic_scr_key_valid;
Expand All @@ -142,6 +144,7 @@ module ibex_top_tracing import ibex_pkg::*; #(
// them.
assign unused_rvfi_ext_mip = rvfi_ext_mip;
assign unused_rvfi_ext_nmi = rvfi_ext_nmi;
assign unused_rvfi_ext_nmi_int = rvfi_ext_nmi_int;
assign unused_rvfi_ext_debug_req = rvfi_ext_debug_req;
assign unused_rvfi_ext_mcycle = rvfi_ext_mcycle;
assign unused_perf_regs = rvfi_ext_mhpmcounters;
Expand Down Expand Up @@ -242,6 +245,7 @@ module ibex_top_tracing import ibex_pkg::*; #(
.rvfi_mem_wdata,
.rvfi_ext_mip,
.rvfi_ext_nmi,
.rvfi_ext_nmi_int,
.rvfi_ext_debug_req,
.rvfi_ext_mcycle,
.rvfi_ext_mhpmcounters,
Expand Down

0 comments on commit 00dcce7

Please sign in to comment.