mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-24 13:57:19 -04:00
[ibex,dv] Switch to new sequence for memory errors
Signed-off-by: Canberk Topal <ctopal@lowrisc.org>
This commit is contained in:
parent
bd8bee8a72
commit
377e7da8e7
2 changed files with 23 additions and 89 deletions
|
@ -72,6 +72,7 @@ class core_base_new_seq #(type REQ = uvm_sequence_item) extends uvm_sequence #(R
|
|||
`DV_CHECK_FATAL(iteration_cnt != 0)
|
||||
`uvm_info(`gfn, $sformatf("Number of stimulus iterations = %0d", iteration_cnt), UVM_LOW)
|
||||
for (int i = 0; i <= iteration_cnt; i++) begin
|
||||
`uvm_info(`gfn, $sformatf("Running %0d/%0d", i, iteration_cnt), UVM_LOW)
|
||||
drive_stimulus();
|
||||
end
|
||||
end
|
||||
|
@ -198,7 +199,7 @@ class debug_new_seq extends core_base_new_seq#(irq_seq_item);
|
|||
|
||||
endclass
|
||||
|
||||
class memory_error_seq extends core_base_new_seq#(irq_seq_item);
|
||||
class memory_error_seq extends core_base_new_seq#(ibex_mem_intf_seq_item);
|
||||
core_ibex_vseq vseq;
|
||||
rand bit choose_side;
|
||||
bit start_seq = 0; // Use this bit to start any unique sequence once
|
||||
|
@ -210,7 +211,6 @@ class memory_error_seq extends core_base_new_seq#(irq_seq_item);
|
|||
|
||||
function new (string name = "");
|
||||
super.new(name);
|
||||
vseq = core_ibex_vseq::type_id::create("vseq");
|
||||
endfunction
|
||||
|
||||
virtual task send_req();
|
||||
|
@ -233,10 +233,6 @@ class memory_error_seq extends core_base_new_seq#(irq_seq_item);
|
|||
// DO nothing
|
||||
end
|
||||
endcase
|
||||
if(!start_seq) begin
|
||||
vseq.start(p_sequencer);
|
||||
start_seq = 1;
|
||||
end
|
||||
endtask
|
||||
|
||||
endclass: memory_error_seq
|
||||
|
|
|
@ -1630,93 +1630,31 @@ class core_ibex_mem_error_test extends core_ibex_directed_test;
|
|||
`uvm_component_utils(core_ibex_mem_error_test)
|
||||
`uvm_component_new
|
||||
|
||||
int err_delay;
|
||||
|
||||
// check memory error inputs and verify that core jumps to correct exception handler
|
||||
virtual task check_stimulus();
|
||||
forever begin
|
||||
while (!vseq.data_intf_seq.get_error_synch()) begin
|
||||
clk_vif.wait_clks(1);
|
||||
end
|
||||
vseq.data_intf_seq.inject_error();
|
||||
`uvm_info(`gfn, "Injected dmem error", UVM_LOW)
|
||||
// Dmem interface error could be either a load or store operation
|
||||
check_dmem_fault();
|
||||
// Random delay before injecting instruction fetch fault
|
||||
`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(err_delay, err_delay inside { [50:200] };)
|
||||
clk_vif.wait_clks(err_delay);
|
||||
inject_imem_error();
|
||||
check_imem_fault();
|
||||
// Random delay before injecting this series of errors again
|
||||
`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(err_delay, err_delay inside { [250:750] };)
|
||||
clk_vif.wait_clks(err_delay);
|
||||
end
|
||||
endtask
|
||||
memory_error_seq memory_error_seq_h;
|
||||
memory_error_seq_h = memory_error_seq::type_id::create("memory_error_seq_h", this);
|
||||
|
||||
virtual task inject_imem_error();
|
||||
while (!vseq.instr_intf_seq.get_error_synch()) begin
|
||||
clk_vif.wait_clks(1);
|
||||
end
|
||||
`uvm_info(`gfn, "Injecting imem fault", UVM_LOW)
|
||||
vseq.instr_intf_seq.inject_error();
|
||||
endtask
|
||||
|
||||
virtual task check_dmem_fault();
|
||||
bit[ibex_mem_intf_agent_pkg::DATA_WIDTH-1:0] mcause;
|
||||
core_status_t mem_status;
|
||||
ibex_pkg::exc_cause_t exc_type;
|
||||
// Don't impose a timeout period for dmem check, since dmem errors injected by the sequence are
|
||||
// not guaranteed to be reflected in RTL state until the next memory instruction is executed,
|
||||
// and the frequency of which is not controllable by the testbench
|
||||
check_next_core_status(HANDLING_EXCEPTION, "Core did not jump to exception handler");
|
||||
check_priv_mode(PRIV_LVL_M);
|
||||
// Next write of CORE_STATUS will be the load/store fault type
|
||||
wait_for_mem_txn(cfg.signature_addr, CORE_STATUS);
|
||||
mem_status = core_status_t'(signature_data_q.pop_front());
|
||||
if (mem_status == LOAD_FAULT_EXCEPTION) begin
|
||||
exc_type = ExcCauseLoadAccessFault;
|
||||
end else if (mem_status == STORE_FAULT_EXCEPTION) begin
|
||||
exc_type = ExcCauseStoreAccessFault;
|
||||
end
|
||||
check_mcause(1'b0, exc_type.lower_cause);
|
||||
wait (dut_vif.dut_cb.mret === 1'b1);
|
||||
`uvm_info(`gfn, "exiting mem fault checker", UVM_LOW)
|
||||
endtask
|
||||
|
||||
virtual task check_imem_fault();
|
||||
bit latched_imem_err = 1'b0;
|
||||
core_status_t mem_status;
|
||||
ibex_pkg::exc_cause_t exc_type;
|
||||
// Need to account for case where imem_error is asserted during an instruction fetch that gets
|
||||
// killed - due to jumps and control flow changes
|
||||
do begin
|
||||
fork
|
||||
begin
|
||||
fork : imem_fork
|
||||
begin
|
||||
check_next_core_status(HANDLING_EXCEPTION, "Core did not jump to exception handler");
|
||||
check_priv_mode(PRIV_LVL_M);
|
||||
latched_imem_err = 1'b1;
|
||||
`uvm_info(`gfn, $sformatf("latched_imem_err: 0x%0x", latched_imem_err), UVM_LOW)
|
||||
end
|
||||
begin
|
||||
clk_vif.wait_clks(5000);
|
||||
end
|
||||
join_any
|
||||
disable fork;
|
||||
`uvm_info(`gfn, "Running core_ibex_mem_error_test", UVM_LOW)
|
||||
memory_error_seq_h.vseq = vseq;
|
||||
memory_error_seq_h.iteration_modes = InfiniteRuns;
|
||||
memory_error_seq_h.stimulus_delay_cycles_min = 800; // Interval between injected errors
|
||||
memory_error_seq_h.stimulus_delay_cycles_max = 5000;
|
||||
fork
|
||||
begin
|
||||
forever begin
|
||||
memory_error_seq_h.start(env.vseqr);
|
||||
// Wait until we are out of IRQ handler to the inject errors
|
||||
wait_ret("mret", 20000);
|
||||
end
|
||||
join
|
||||
if (latched_imem_err === 1'b0) begin
|
||||
cur_run_phase.drop_objection(this);
|
||||
inject_imem_error();
|
||||
end
|
||||
end while (latched_imem_err === 1'b0);
|
||||
check_next_core_status(INSTR_FAULT_EXCEPTION,
|
||||
"Core did not register correct memory fault type", 5000);
|
||||
exc_type = ExcCauseInstrAccessFault;
|
||||
check_mcause(1'b0, exc_type.lower_cause);
|
||||
wait (dut_vif.dut_cb.mret === 1'b1);
|
||||
`uvm_info(`gfn, "exiting mem fault checker", UVM_LOW)
|
||||
begin
|
||||
forever begin
|
||||
wait_for_core_status(HANDLING_IRQ);
|
||||
// Do not allow error injection while we are handling IRQ
|
||||
memory_error_seq_h.stop();
|
||||
end
|
||||
end
|
||||
join_none
|
||||
endtask
|
||||
|
||||
endclass
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue