mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 21:07:34 -04:00
[dv] Improve interrupt signalling to cosim
Previously any changes in interrupt state or debug requests were strictly associated with retired instructions. This causes cosim mismatches where a lower priority interrupt occurs in time before a higher priority interrupt or debug request but between instruction fetches/retirements so both the low and high priority interrupts are signalled with the instruction retirement. This introduces a way for the RVFI to signal an interrupt has occurred that isn't associated with an instruction retirement to allow the cosim to see the seperation in time between different interrupts and debug requests and hence model behaviour correctly.
This commit is contained in:
parent
e587f20d44
commit
1120e8ddbf
12 changed files with 148 additions and 15 deletions
|
@ -133,7 +133,15 @@ The DV environment is responsible for determining when to call ``set_mip``, ``se
|
|||
|
||||
The state of the incoming interrupts and debug request is sampled when an instruction moves from IF to ID/EX.
|
||||
The sampled state is tracked with the rest of the RVFI pipeline and used to call ``set_mip``, ``set_debug_req`` and ``set_nmi`` when the instruction is output by the RVFI.
|
||||
See the comments in :file:`rtl/ibex_core.sv`, around the ``new_debug_req``, ``new_nmi`` and ``new_irq`` signals for further details.
|
||||
|
||||
A complication occurs when more than one interrupt or debug requests occur between individual instruction fetches.
|
||||
One interrupt or debug request may take priority over another when they all occur together but when they occur in time is important as well.
|
||||
If interrupt and debug request notification is associated exclusively with retired instructions the co-simulation system cannot correctly prioritise multiple interrupts and debug requests.
|
||||
To deal with this the RVFI can also signal an interrupt event not associated with an instruction by setting ``rvfi_ext_irq_valid`` without setting ``rvfi_valid``.
|
||||
When this is set the interrupt related RVFI signals are valid and provide the interrupt state.
|
||||
The RVFI is used in this way, as opposed to a separate notification interface, so the interrupt notifications are ordered relative to the retired instructions.
|
||||
|
||||
See the comments in :file:`rtl/ibex_core.sv`, around the ``new_debug_req``, ``new_nmi``, ``new_irq`` and ``rvfi_irq_valid`` signals for further details.
|
||||
|
||||
Memory Access Checking and Bus Errors
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -571,11 +571,50 @@ void SpikeCosim::initial_proc_setup(uint32_t start_pc, uint32_t start_mtvec,
|
|||
}
|
||||
|
||||
void SpikeCosim::set_mip(uint32_t mip) {
|
||||
uint32_t new_mip = mip;
|
||||
uint32_t old_mip = processor->get_state()->mip->read();
|
||||
|
||||
processor->get_state()->mip->write_with_mask(0xffffffff, mip);
|
||||
|
||||
if (processor->get_state()->debug_mode ||
|
||||
(processor->halt_request == processor_t::HR_REGULAR) ||
|
||||
(!get_field(processor->get_csr(CSR_MSTATUS), MSTATUS_MIE) &&
|
||||
processor->get_state()->prv == PRV_M)) {
|
||||
// Return now if new MIP won't trigger an interrupt handler either because
|
||||
// we're in or heading to debug mode or interrupts are disabled.
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t old_enabled_irq = old_mip & processor->get_state()->mie->read();
|
||||
uint32_t new_enabled_irq = new_mip & processor->get_state()->mie->read();
|
||||
|
||||
// Check to see if new MIP will trigger an interrupt (which occurs when new
|
||||
// MIP produces an enabled interrupt for the first time).
|
||||
if ((old_enabled_irq == 0) && (new_enabled_irq != 0)) {
|
||||
// Early interrupt handle if the interrupt is triggered.
|
||||
early_interrupt_handle();
|
||||
}
|
||||
}
|
||||
|
||||
void SpikeCosim::early_interrupt_handle() {
|
||||
// Execute a spike step on the assumption an interrupt will occur so no new
|
||||
// instruction is executed just the state altered to reflect the interrupt.
|
||||
uint32_t initial_spike_pc = (processor->get_state()->pc & 0xffffffff);
|
||||
processor->step(1);
|
||||
|
||||
if (processor->get_state()->last_inst_pc != PC_INVALID) {
|
||||
std::stringstream err_str;
|
||||
err_str << "Attempted step for interrupt, expecting no instruction would "
|
||||
<< "be executed but saw one. PC before: " << std::hex
|
||||
<< initial_spike_pc
|
||||
<< " PC after: " << (processor->get_state()->pc & 0xffffffff);
|
||||
errors.emplace_back(err_str.str());
|
||||
}
|
||||
}
|
||||
|
||||
void SpikeCosim::set_nmi(bool nmi) {
|
||||
if (nmi && !nmi_mode && !processor->get_state()->debug_mode) {
|
||||
if (nmi && !nmi_mode && !processor->get_state()->debug_mode &&
|
||||
processor->halt_request != processor_t::HR_REGULAR) {
|
||||
processor->get_state()->nmi = true;
|
||||
nmi_mode = true;
|
||||
|
||||
|
@ -585,11 +624,14 @@ void SpikeCosim::set_nmi(bool nmi) {
|
|||
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);
|
||||
|
||||
early_interrupt_handle();
|
||||
}
|
||||
}
|
||||
|
||||
void SpikeCosim::set_nmi_int(bool nmi_int) {
|
||||
if (nmi_int && !nmi_mode && !processor->get_state()->debug_mode) {
|
||||
if (nmi_int && !nmi_mode && !processor->get_state()->debug_mode &&
|
||||
processor->halt_request != processor_t::HR_REGULAR) {
|
||||
processor->get_state()->nmi_int = true;
|
||||
nmi_mode = true;
|
||||
|
||||
|
@ -599,6 +641,8 @@ void SpikeCosim::set_nmi_int(bool nmi_int) {
|
|||
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);
|
||||
|
||||
early_interrupt_handle();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -83,6 +83,8 @@ class SpikeCosim : public simif_t, public Cosim {
|
|||
void initial_proc_setup(uint32_t start_pc, uint32_t start_mtvec,
|
||||
uint32_t mhpm_counter_num);
|
||||
|
||||
void early_interrupt_handle();
|
||||
|
||||
unsigned int insn_cnt;
|
||||
|
||||
public:
|
||||
|
|
|
@ -116,6 +116,16 @@ class ibex_cosim_scoreboard extends uvm_scoreboard;
|
|||
forever begin
|
||||
rvfi_port.get(rvfi_instr);
|
||||
|
||||
if (rvfi_instr.irq_only) begin
|
||||
// RVFI item is only notifying about new interrupts, not a retired instruction, so provide
|
||||
// cosim with interrupt information and loop back to await the next item.
|
||||
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);
|
||||
|
||||
continue;
|
||||
end
|
||||
|
||||
if (iside_error_queue.size() > 0) begin
|
||||
// Remove entries from iside_error_queue where the instruction never reaches the RVFI
|
||||
// interface because it was flushed.
|
||||
|
@ -131,10 +141,12 @@ class ibex_cosim_scoreboard extends uvm_scoreboard;
|
|||
end
|
||||
end
|
||||
|
||||
// Note these must be called in this order to ensure debug vs nmi vs normal interrupt are
|
||||
// handled with the correct priority when they occur together.
|
||||
riscv_cosim_set_debug_req(cosim_handle, rvfi_instr.debug_req);
|
||||
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);
|
||||
|
||||
// Set performance counters through a pseudo-backdoor write
|
||||
|
|
|
@ -27,10 +27,11 @@ class ibex_rvfi_monitor extends uvm_monitor;
|
|||
|
||||
forever begin
|
||||
// Wait for a retired instruction
|
||||
while(!vif.monitor_cb.valid) vif.wait_clks(1);
|
||||
while(!(vif.monitor_cb.valid || vif.monitor_cb.ext_irq_valid)) vif.wait_clks(1);
|
||||
|
||||
// Read instruction details from RVFI interface
|
||||
trans_collected = ibex_rvfi_seq_item::type_id::create("trans_collected");
|
||||
trans_collected.irq_only = !vif.monitor_cb.valid && vif.monitor_cb.ext_irq_valid;
|
||||
trans_collected.trap = vif.monitor_cb.trap;
|
||||
trans_collected.pc = vif.monitor_cb.pc_rdata;
|
||||
trans_collected.rd_addr = vif.monitor_cb.rd_addr;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
class ibex_rvfi_seq_item extends uvm_sequence_item;
|
||||
bit irq_only;
|
||||
bit trap;
|
||||
bit [31:0] pc;
|
||||
bit [4:0] rd_addr;
|
||||
|
|
2
dv/uvm/core_ibex/env/core_ibex_rvfi_if.sv
vendored
2
dv/uvm/core_ibex/env/core_ibex_rvfi_if.sv
vendored
|
@ -32,6 +32,7 @@ interface core_ibex_rvfi_if(input logic clk);
|
|||
logic [31:0] ext_debug_req;
|
||||
logic [31:0] ext_rf_wr_suppress;
|
||||
logic [63:0] ext_mcycle;
|
||||
logic ext_irq_valid;
|
||||
|
||||
logic [31:0] ext_mhpmcounters [10];
|
||||
logic [31:0] ext_mhpmcountersh [10];
|
||||
|
@ -70,6 +71,7 @@ interface core_ibex_rvfi_if(input logic clk);
|
|||
input ext_mhpmcounters;
|
||||
input ext_mhpmcountersh;
|
||||
input ext_ic_scr_key_valid;
|
||||
input ext_irq_valid;
|
||||
endclocking
|
||||
|
||||
task automatic wait_clks(input int num);
|
||||
|
|
|
@ -205,6 +205,7 @@ module core_ibex_tb_top;
|
|||
assign rvfi_if.ext_mhpmcounters = dut.rvfi_ext_mhpmcounters;
|
||||
assign rvfi_if.ext_mhpmcountersh = dut.rvfi_ext_mhpmcountersh;
|
||||
assign rvfi_if.ext_ic_scr_key_valid = dut.rvfi_ext_ic_scr_key_valid;
|
||||
assign rvfi_if.ext_irq_valid = dut.rvfi_ext_irq_valid;
|
||||
// Irq interface connections
|
||||
assign irq_vif.reset = ~rst_n;
|
||||
// Dut_if interface connections
|
||||
|
|
|
@ -147,6 +147,7 @@ module ibex_core import ibex_pkg::*; #(
|
|||
output logic [31:0] rvfi_ext_mhpmcounters [10],
|
||||
output logic [31:0] rvfi_ext_mhpmcountersh [10],
|
||||
output logic rvfi_ext_ic_scr_key_valid,
|
||||
output logic rvfi_ext_irq_valid,
|
||||
`endif
|
||||
|
||||
// CPU Control Signals
|
||||
|
@ -1232,6 +1233,7 @@ module ibex_core import ibex_pkg::*; #(
|
|||
logic [31:0] rvfi_mem_addr_q;
|
||||
logic rvfi_trap_id;
|
||||
logic rvfi_trap_wb;
|
||||
logic rvfi_irq_valid;
|
||||
logic [63:0] rvfi_stage_order_d;
|
||||
logic rvfi_id_done;
|
||||
logic rvfi_wb_done;
|
||||
|
@ -1257,6 +1259,7 @@ module ibex_core import ibex_pkg::*; #(
|
|||
logic [31:0] rvfi_ext_stage_mhpmcounters [RVFI_STAGES][10];
|
||||
logic [31:0] rvfi_ext_stage_mhpmcountersh [RVFI_STAGES][10];
|
||||
logic rvfi_ext_stage_ic_scr_key_valid [RVFI_STAGES];
|
||||
logic rvfi_ext_stage_irq_valid [RVFI_STAGES+1];
|
||||
|
||||
|
||||
logic rvfi_stage_valid_d [RVFI_STAGES];
|
||||
|
@ -1307,6 +1310,7 @@ module ibex_core import ibex_pkg::*; #(
|
|||
assign rvfi_ext_mhpmcounters = rvfi_ext_stage_mhpmcounters [RVFI_STAGES-1];
|
||||
assign rvfi_ext_mhpmcountersh = rvfi_ext_stage_mhpmcountersh [RVFI_STAGES-1];
|
||||
assign rvfi_ext_ic_scr_key_valid = rvfi_ext_stage_ic_scr_key_valid [RVFI_STAGES-1];
|
||||
assign rvfi_ext_irq_valid = rvfi_ext_stage_irq_valid [RVFI_STAGES];
|
||||
|
||||
// When an instruction takes a trap the `rvfi_trap` signal will be set. Instructions that take
|
||||
// traps flush the pipeline so ordinarily wouldn't be seen to be retire. The RVFI tracking
|
||||
|
@ -1394,7 +1398,8 @@ module ibex_core import ibex_pkg::*; #(
|
|||
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;
|
||||
assign new_irq = irq_pending_o & (csr_mstatus_mie || (priv_mode_id == PRIV_LVL_U)) & ~nmi_mode &
|
||||
~debug_mode;
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
|
@ -1403,6 +1408,7 @@ module ibex_core import ibex_pkg::*; #(
|
|||
captured_nmi <= 1'b0;
|
||||
captured_nmi_int <= 1'b0;
|
||||
captured_debug_req <= 1'b0;
|
||||
rvfi_irq_valid <= 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
|
||||
|
@ -1421,6 +1427,18 @@ module ibex_core import ibex_pkg::*; #(
|
|||
captured_debug_req <= debug_req_i;
|
||||
end
|
||||
|
||||
// When the pipeline has emptied in preparation for handling a new interrupt send
|
||||
// a notification up the RVFI pipeline. This is used by the cosim to deal with cases where an
|
||||
// interrupt occurs before another interrupt or debug request but both occur before the first
|
||||
// instruction of the handler is executed and retired (where the cosim will see all the
|
||||
// interrupts and debug requests at once with no way to determine which occurred first).
|
||||
if (~instr_valid_id & ~new_debug_req & (new_irq | new_nmi | new_nmi_int) & ready_wb &
|
||||
~captured_valid) begin
|
||||
rvfi_irq_valid <= 1'b1;
|
||||
end else begin
|
||||
rvfi_irq_valid <= 1'b0;
|
||||
end
|
||||
|
||||
// Capture cleared out as soon as a new instruction appears in ID
|
||||
if (if_stage_i.instr_valid_id_d) begin
|
||||
captured_valid <= 1'b0;
|
||||
|
@ -1440,7 +1458,7 @@ module ibex_core import ibex_pkg::*; #(
|
|||
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
|
||||
end else if ((if_stage_i.instr_valid_id_d & if_stage_i.instr_new_id_d) | rvfi_irq_valid) 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 :
|
||||
|
@ -1453,6 +1471,29 @@ module ibex_core import ibex_pkg::*; #(
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
// rvfi_irq_valid signals an interrupt event to the cosim. These should only occur when the RVFI
|
||||
// pipe is empty so just send it straigh through.
|
||||
for (genvar i = 0; i < RVFI_STAGES + 1; i = i + 1) begin : g_rvfi_irq_valid
|
||||
if (i == 0) begin : g_rvfi_irq_valid_first_stage
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
rvfi_ext_stage_irq_valid[i] <= 1'b0;
|
||||
end else begin
|
||||
rvfi_ext_stage_irq_valid[i] <= rvfi_irq_valid;
|
||||
end
|
||||
end
|
||||
end else begin : g_rvfi_irq_valid_other_stages
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
rvfi_ext_stage_irq_valid[i] <= 1'b0;
|
||||
end else begin
|
||||
rvfi_ext_stage_irq_valid[i] <= rvfi_ext_stage_irq_valid[i-1];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for (genvar i = 0; i < RVFI_STAGES; i = i + 1) begin : g_rvfi_stages
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
|
@ -1515,10 +1556,6 @@ module ibex_core import ibex_pkg::*; #(
|
|||
rvfi_stage_mem_rdata[i] <= rvfi_mem_rdata_d;
|
||||
rvfi_stage_mem_wdata[i] <= rvfi_mem_wdata_d;
|
||||
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_debug_mode[i] <= debug_mode;
|
||||
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;
|
||||
|
@ -1529,6 +1566,17 @@ module ibex_core import ibex_pkg::*; #(
|
|||
rvfi_ext_stage_mhpmcountersh[i][k] <= cs_registers_i.mhpmcounter[k+3][63:32];
|
||||
end
|
||||
end
|
||||
|
||||
// Some of the rvfi_ext_* signals are used to provide an interrupt notification (signalled
|
||||
// via rvfi_ext_irq_valid) when there isn't a valid retired instruction as well as
|
||||
// providing information along with a retired instruction. Move these up the rvfi pipeline
|
||||
// for both cases.
|
||||
if (rvfi_id_done | rvfi_ext_stage_irq_valid[i]) begin
|
||||
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];
|
||||
end
|
||||
end else begin
|
||||
if (rvfi_wb_done) begin
|
||||
rvfi_stage_halt[i] <= rvfi_stage_halt[i-1];
|
||||
|
@ -1559,16 +1607,23 @@ module ibex_core import ibex_pkg::*; #(
|
|||
rvfi_stage_rd_wdata[i] <= rvfi_rd_wdata_d;
|
||||
rvfi_stage_mem_rdata[i] <= rvfi_mem_rdata_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_debug_mode[i] <= rvfi_ext_stage_debug_mode[i-1];
|
||||
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];
|
||||
rvfi_ext_stage_mhpmcounters[i] <= rvfi_ext_stage_mhpmcounters[i-1];
|
||||
rvfi_ext_stage_mhpmcountersh[i] <= rvfi_ext_stage_mhpmcountersh[i-1];
|
||||
end
|
||||
|
||||
// Some of the rvfi_ext_* signals are used to provide an interrupt notification (signalled
|
||||
// via rvfi_ext_irq_valid) when there isn't a valid retired instruction as well as
|
||||
// providing information along with a retired instruction. Move these up the rvfi pipeline
|
||||
// for both cases.
|
||||
if (rvfi_wb_done | rvfi_ext_stage_irq_valid[i]) begin
|
||||
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];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -437,6 +437,7 @@ module ibex_lockstep import ibex_pkg::*; #(
|
|||
.rvfi_ext_mhpmcounters (),
|
||||
.rvfi_ext_mhpmcountersh (),
|
||||
.rvfi_ext_ic_scr_key_valid (),
|
||||
.rvfi_ext_irq_valid (),
|
||||
`endif
|
||||
|
||||
.fetch_enable_i (shadow_inputs_q[0].fetch_enable),
|
||||
|
|
|
@ -126,6 +126,7 @@ module ibex_top import ibex_pkg::*; #(
|
|||
output logic [31:0] rvfi_ext_mhpmcounters [10],
|
||||
output logic [31:0] rvfi_ext_mhpmcountersh [10],
|
||||
output logic rvfi_ext_ic_scr_key_valid,
|
||||
output logic rvfi_ext_irq_valid,
|
||||
`endif
|
||||
|
||||
// CPU Control Signals
|
||||
|
@ -398,6 +399,7 @@ module ibex_top import ibex_pkg::*; #(
|
|||
.rvfi_ext_mhpmcounters,
|
||||
.rvfi_ext_mhpmcountersh,
|
||||
.rvfi_ext_ic_scr_key_valid,
|
||||
.rvfi_ext_irq_valid,
|
||||
`endif
|
||||
|
||||
.fetch_enable_i (fetch_enable_buf),
|
||||
|
|
|
@ -130,6 +130,7 @@ module ibex_top_tracing import ibex_pkg::*; #(
|
|||
logic [31:0] rvfi_ext_mhpmcounters [10];
|
||||
logic [31:0] rvfi_ext_mhpmcountersh [10];
|
||||
logic rvfi_ext_ic_scr_key_valid;
|
||||
logic rvfi_ext_irq_valid;
|
||||
|
||||
logic [31:0] unused_perf_regs [10];
|
||||
logic [31:0] unused_perf_regsh [10];
|
||||
|
@ -143,6 +144,7 @@ module ibex_top_tracing import ibex_pkg::*; #(
|
|||
logic unused_rvfi_ext_rf_wr_suppress;
|
||||
logic [63:0] unused_rvfi_ext_mcycle;
|
||||
logic unused_rvfi_ext_ic_scr_key_valid;
|
||||
logic unused_rvfi_ext_irq_valid;
|
||||
|
||||
// Tracer doesn't use these signals, though other modules may probe down into tracer to observe
|
||||
// them.
|
||||
|
@ -156,6 +158,7 @@ module ibex_top_tracing import ibex_pkg::*; #(
|
|||
assign unused_perf_regs = rvfi_ext_mhpmcounters;
|
||||
assign unused_perf_regsh = rvfi_ext_mhpmcountersh;
|
||||
assign unused_rvfi_ext_ic_scr_key_valid = rvfi_ext_ic_scr_key_valid;
|
||||
assign unused_rvfi_ext_irq_valid = rvfi_ext_irq_valid;
|
||||
|
||||
ibex_top #(
|
||||
.PMPEnable ( PMPEnable ),
|
||||
|
@ -259,6 +262,7 @@ module ibex_top_tracing import ibex_pkg::*; #(
|
|||
.rvfi_ext_mhpmcounters,
|
||||
.rvfi_ext_mhpmcountersh,
|
||||
.rvfi_ext_ic_scr_key_valid,
|
||||
.rvfi_ext_irq_valid,
|
||||
|
||||
.fetch_enable_i,
|
||||
.alert_minor_o,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue