mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-20 03:47:15 -04:00
[cosim] Cosim integration of internal NMI
This commit is mainly an extension to cosim environment to drive the newly introduced state variable `nmi_int` in Spike. This commit - Extends RVFI interface by a single bit (ext_nmi_int) - Configures cosim to set nmi_int inside Spike Signed-off-by: Canberk Topal <ctopal@lowrisc.org>
This commit is contained in:
parent
12ae6b2478
commit
715292ce55
16 changed files with 68 additions and 2 deletions
|
@ -95,6 +95,12 @@ 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. Difference is that this one is a response from Ibex rather
|
||||
// than an input.
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -211,7 +211,8 @@ 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()
|
||||
->debug_mode) { // (Async-Traps are disabled in debug mode)
|
||||
// Spike encountered a synchronous trap
|
||||
pending_sync_exception = true;
|
||||
|
||||
|
@ -376,6 +377,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) {
|
||||
|
@ -529,6 +536,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;
|
||||
|
|
|
@ -109,6 +109,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;
|
||||
|
|
|
@ -121,6 +121,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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
|
2
dv/uvm/core_ibex/env/core_ibex_rvfi_if.sv
vendored
2
dv/uvm/core_ibex/env/core_ibex_rvfi_if.sv
vendored
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -139,6 +139,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],
|
||||
|
@ -1235,9 +1236,11 @@ 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;
|
||||
logic captured_nmi_int;
|
||||
logic captured_debug_req;
|
||||
logic captured_valid;
|
||||
|
||||
|
@ -1245,6 +1248,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+1];
|
||||
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];
|
||||
|
@ -1293,6 +1297,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];
|
||||
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];
|
||||
|
@ -1380,6 +1385,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.controller_i.irq_nm_int & ~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
|
||||
|
@ -1387,13 +1393,16 @@ module ibex_core import ibex_pkg::*; #(
|
|||
captured_valid <= 1'b0;
|
||||
captured_mip <= '0;
|
||||
captured_nmi <= 1'b0;
|
||||
captured_nmi_int <= 1'b0;
|
||||
captured_debug_req <= 1'b0;
|
||||
end else begin
|
||||
// Capture when ID stage has emptied out and something occurs that will cause a trap and we
|
||||
// haven't yet captured
|
||||
if (~instr_valid_id & (new_debug_req | new_irq | new_nmi) & ~captured_valid) begin
|
||||
if (~instr_valid_id & (new_debug_req | new_irq | new_nmi | new_nmi_int) &
|
||||
~captured_valid) begin
|
||||
captured_valid <= 1'b1;
|
||||
captured_nmi <= irq_nm_i;
|
||||
captured_nmi_int <= id_stage_i.controller_i.irq_nm_int;
|
||||
captured_mip <= cs_registers_i.mip;
|
||||
captured_debug_req <= debug_req_i;
|
||||
end
|
||||
|
@ -1415,12 +1424,16 @@ module ibex_core import ibex_pkg::*; #(
|
|||
if (!rst_ni) begin
|
||||
rvfi_ext_stage_mip[0] <= '0;
|
||||
rvfi_ext_stage_nmi[0] <= '0;
|
||||
rvfi_ext_stage_nmi_int[0] <= '0;
|
||||
rvfi_ext_stage_debug_req[0] <= '0;
|
||||
end else if (if_stage_i.instr_valid_id_d & if_stage_i.instr_new_id_d) begin
|
||||
rvfi_ext_stage_mip[0] <= instr_valid_id | ~captured_valid ? cs_registers_i.mip :
|
||||
captured_mip;
|
||||
rvfi_ext_stage_nmi[0] <= instr_valid_id | ~captured_valid ? irq_nm_i :
|
||||
captured_nmi;
|
||||
rvfi_ext_stage_nmi_int[0] <=
|
||||
instr_valid_id | ~captured_valid ? id_stage_i.controller_i.irq_nm_int :
|
||||
captured_nmi_int;
|
||||
rvfi_ext_stage_debug_req[0] <= instr_valid_id | ~captured_valid ? debug_req_i :
|
||||
captured_debug_req;
|
||||
end
|
||||
|
@ -1454,6 +1467,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+1] <= '0;
|
||||
rvfi_ext_stage_debug_req[i+1] <= '0;
|
||||
rvfi_ext_stage_mcycle[i] <= '0;
|
||||
rvfi_ext_stage_mhpmcounters[i] <= '{10{'0}};
|
||||
|
@ -1489,6 +1503,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+1] <= rvfi_ext_stage_nmi_int[i];
|
||||
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;
|
||||
|
@ -1531,6 +1546,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+1] <= rvfi_ext_stage_nmi_int[i];
|
||||
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];
|
||||
|
|
|
@ -429,6 +429,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 (),
|
||||
|
|
|
@ -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],
|
||||
|
@ -387,6 +388,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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue