Skip to content

Commit

Permalink
[cosim] Cosim integration of internal NMI
Browse files Browse the repository at this point in the history
Signed-off-by: Canberk Topal <ctopal@lowrisc.org>
  • Loading branch information
ctopal committed Oct 17, 2022
1 parent 7222d4a commit 66f3e2d
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 @@ -1216,6 +1218,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 @@ -1264,6 +1267,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 @@ -1293,7 +1297,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 @@ -1311,7 +1315,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 @@ -1351,6 +1355,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 @@ -1435,6 +1440,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 @@ -1470,6 +1476,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 @@ -1512,6 +1519,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 66f3e2d

Please sign in to comment.