mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 04:47:25 -04:00
[DV] Add reset test (#392)
This commit is contained in:
parent
2ca1a6da21
commit
ae82d61401
12 changed files with 187 additions and 45 deletions
|
@ -29,12 +29,25 @@ class ibex_mem_intf_monitor extends uvm_monitor;
|
|||
|
||||
virtual task run_phase(uvm_phase phase);
|
||||
wait(vif.reset === 1'b0);
|
||||
fork
|
||||
collect_address_phase();
|
||||
collect_data_phase();
|
||||
join
|
||||
forever begin
|
||||
fork : check_mem_intf
|
||||
collect_address_phase();
|
||||
collect_data_phase();
|
||||
wait(vif.reset === 1'b1);
|
||||
join_any
|
||||
// Will only reach this point when mid-test reset is asserted
|
||||
disable check_mem_intf;
|
||||
handle_reset();
|
||||
end
|
||||
endtask : run_phase
|
||||
|
||||
virtual protected task handle_reset();
|
||||
ibex_mem_intf_seq_item mailbox_result;
|
||||
// Clear the mailbox of any content
|
||||
while (collect_data_queue.try_get(mailbox_result));
|
||||
wait(vif.reset === 1'b0);
|
||||
endtask
|
||||
|
||||
virtual protected task collect_address_phase();
|
||||
ibex_mem_intf_seq_item trans_collected;
|
||||
forever begin
|
||||
|
|
|
@ -32,4 +32,8 @@ class ibex_mem_intf_slave_agent extends uvm_agent;
|
|||
end
|
||||
endfunction : connect_phase
|
||||
|
||||
function void reset();
|
||||
sequencer.reset();
|
||||
endfunction
|
||||
|
||||
endclass : ibex_mem_intf_slave_agent
|
||||
|
|
|
@ -27,12 +27,34 @@ class ibex_mem_intf_slave_driver extends uvm_driver #(ibex_mem_intf_seq_item);
|
|||
|
||||
virtual task run_phase(uvm_phase phase);
|
||||
reset_signals();
|
||||
fork
|
||||
send_grant();
|
||||
join_none
|
||||
get_and_drive();
|
||||
wait(vif.reset === 1'b0);
|
||||
forever begin
|
||||
fork : drive_stimulus
|
||||
send_grant();
|
||||
get_and_drive();
|
||||
wait(vif.reset === 1'b1);
|
||||
join_any
|
||||
// Will only be reached after mid-test reset
|
||||
disable drive_stimulus;
|
||||
handle_reset();
|
||||
end
|
||||
endtask : run_phase
|
||||
|
||||
virtual protected task handle_reset();
|
||||
ibex_mem_intf_seq_item req;
|
||||
// Clear mailbox
|
||||
while (rdata_queue.try_get(req));
|
||||
// Clear seq_item_port
|
||||
do begin
|
||||
seq_item_port.try_next_item(req);
|
||||
if (req != null) begin
|
||||
seq_item_port.item_done();
|
||||
end
|
||||
end while (req != null);
|
||||
reset_signals();
|
||||
wait(vif.reset === 1'b0);
|
||||
endtask
|
||||
|
||||
virtual protected task reset_signals();
|
||||
vif.rvalid <= 1'b0;
|
||||
vif.grant <= 1'b0;
|
||||
|
@ -41,20 +63,24 @@ class ibex_mem_intf_slave_driver extends uvm_driver #(ibex_mem_intf_seq_item);
|
|||
endtask : reset_signals
|
||||
|
||||
virtual protected task get_and_drive();
|
||||
@(negedge vif.reset);
|
||||
wait(vif.reset === 1'b0);
|
||||
fork
|
||||
forever begin
|
||||
ibex_mem_intf_seq_item req, req_c;
|
||||
@(posedge vif.clock);
|
||||
seq_item_port.get_next_item(req);
|
||||
$cast(req_c, req.clone());
|
||||
if(~vif.reset) begin
|
||||
rdata_queue.put(req_c);
|
||||
begin
|
||||
forever begin
|
||||
ibex_mem_intf_seq_item req, req_c;
|
||||
@(posedge vif.clock);
|
||||
seq_item_port.get_next_item(req);
|
||||
$cast(req_c, req.clone());
|
||||
if(~vif.reset) begin
|
||||
rdata_queue.put(req_c);
|
||||
end
|
||||
seq_item_port.item_done();
|
||||
end
|
||||
seq_item_port.item_done();
|
||||
end
|
||||
send_read_data();
|
||||
join_none
|
||||
begin
|
||||
send_read_data();
|
||||
end
|
||||
join
|
||||
endtask : get_and_drive
|
||||
|
||||
virtual protected task send_grant();
|
||||
|
|
|
@ -18,4 +18,9 @@ class ibex_mem_intf_slave_sequencer extends uvm_sequencer #(ibex_mem_intf_seq_it
|
|||
addr_ph_port = new("addr_ph_port_sequencer", this);
|
||||
endfunction : new
|
||||
|
||||
// On reset, empty the tlm fifo
|
||||
function void reset();
|
||||
addr_ph_port.flush();
|
||||
endfunction
|
||||
|
||||
endclass : ibex_mem_intf_slave_sequencer
|
||||
|
|
|
@ -18,14 +18,32 @@ class irq_master_driver extends uvm_driver #(irq_seq_item);
|
|||
endfunction: build_phase
|
||||
|
||||
virtual task run_phase(uvm_phase phase);
|
||||
fork
|
||||
get_and_drive();
|
||||
reset_signals();
|
||||
join
|
||||
reset_signals();
|
||||
forever begin
|
||||
fork : drive_irq
|
||||
get_and_drive();
|
||||
wait(vif.reset === 1'b1);
|
||||
join_any
|
||||
// Will only reach here on mid-test reset
|
||||
disable drive_irq;
|
||||
handle_reset();
|
||||
end
|
||||
endtask : run_phase
|
||||
|
||||
virtual protected task handle_reset();
|
||||
irq_seq_item req;
|
||||
// Clear seq_item_port
|
||||
do begin
|
||||
seq_item_port.try_next_item(req);
|
||||
if (req != null) begin
|
||||
seq_item_port.item_done();
|
||||
end
|
||||
end while (req != null);
|
||||
reset_signals();
|
||||
endtask
|
||||
|
||||
virtual protected task get_and_drive();
|
||||
@(negedge vif.reset);
|
||||
wait(vif.reset === 1'b0);
|
||||
forever begin
|
||||
seq_item_port.try_next_item(req);
|
||||
if (req != null) begin
|
||||
|
|
|
@ -22,7 +22,15 @@ class irq_monitor extends uvm_monitor;
|
|||
endfunction: build_phase
|
||||
|
||||
virtual task run_phase(uvm_phase phase);
|
||||
collect_irq();
|
||||
forever begin
|
||||
wait(vif.reset === 1'b0);
|
||||
fork : monitor_irq
|
||||
collect_irq();
|
||||
wait(vif.reset === 1'b1);
|
||||
join_any
|
||||
// Will only reach here on mid-test reset
|
||||
disable monitor_irq;
|
||||
end
|
||||
endtask : run_phase
|
||||
|
||||
// We know that for Ibex, any given interrupt stimulus will be asserted until the core signals the
|
||||
|
|
|
@ -8,7 +8,11 @@
|
|||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
interface clk_if(input logic clk);
|
||||
interface clk_if(inout clk,
|
||||
inout rst_n);
|
||||
|
||||
logic clk_o;
|
||||
logic rst_no;
|
||||
|
||||
clocking cb @(posedge clk);
|
||||
endclocking
|
||||
|
@ -26,4 +30,28 @@ interface clk_if(input logic clk);
|
|||
repeat (num_clks) @cbn;
|
||||
endtask
|
||||
|
||||
// generate mid-test reset
|
||||
task reset();
|
||||
rst_no = 1'b0;
|
||||
wait_clks(100);
|
||||
rst_no = 1'b1;
|
||||
endtask
|
||||
|
||||
// generate clock
|
||||
initial begin
|
||||
clk_o = 1'b0;
|
||||
forever begin
|
||||
#10 clk_o = ~clk_o;
|
||||
end
|
||||
end
|
||||
|
||||
// generate initial reset
|
||||
initial begin
|
||||
reset();
|
||||
end
|
||||
|
||||
// Interface assignments
|
||||
assign clk = clk_o;
|
||||
assign rst_n = rst_no;
|
||||
|
||||
endinterface
|
||||
|
|
6
dv/uvm/env/core_ibex_dut_probe_if.sv
vendored
6
dv/uvm/env/core_ibex_dut_probe_if.sv
vendored
|
@ -4,6 +4,7 @@
|
|||
|
||||
// Interface to probe DUT internal signal
|
||||
interface core_ibex_dut_probe_if(input logic clk);
|
||||
logic reset;
|
||||
logic illegal_instr;
|
||||
logic ecall;
|
||||
logic wfi;
|
||||
|
@ -13,4 +14,9 @@ interface core_ibex_dut_probe_if(input logic clk);
|
|||
logic fetch_enable;
|
||||
logic core_sleep;
|
||||
logic debug_req;
|
||||
|
||||
initial begin
|
||||
debug_req = 1'b0;
|
||||
end
|
||||
|
||||
endinterface
|
||||
|
|
5
dv/uvm/env/core_ibex_env.sv
vendored
5
dv/uvm/env/core_ibex_env.sv
vendored
|
@ -37,4 +37,9 @@ class core_ibex_env extends uvm_env;
|
|||
vseqr.irq_seqr = irq_agent.sequencer;
|
||||
endfunction : connect_phase
|
||||
|
||||
function void reset();
|
||||
data_if_slave_agent.reset();
|
||||
instr_if_slave_agent.reset();
|
||||
endfunction
|
||||
|
||||
endclass
|
||||
|
|
|
@ -340,3 +340,16 @@
|
|||
compare_opts:
|
||||
compare_final_value_only: 1
|
||||
verbose: 1
|
||||
|
||||
- test: riscv_reset_test
|
||||
description: >
|
||||
Randomly reset the core once in the middle of program execution
|
||||
iterations: 10
|
||||
gen_test: riscv_rand_instr_test
|
||||
gen_opts: >
|
||||
+instr_cnt=10000
|
||||
+num_of_sub_program=5
|
||||
rtl_test: core_ibex_reset_test
|
||||
compare_opts:
|
||||
compare_final_value_only: 1
|
||||
verbose: 1
|
||||
|
|
|
@ -7,11 +7,11 @@ module core_ibex_tb_top;
|
|||
import uvm_pkg::*;
|
||||
import core_ibex_test_pkg::*;
|
||||
|
||||
logic clk;
|
||||
logic rst_n;
|
||||
wire clk;
|
||||
wire rst_n;
|
||||
logic fetch_enable;
|
||||
|
||||
clk_if ibex_clk_if(.clk(clk));
|
||||
clk_if ibex_clk_if(.clk(clk), .rst_n(rst_n));
|
||||
irq_if irq_vif();
|
||||
ibex_mem_intf data_mem_vif();
|
||||
ibex_mem_intf instr_mem_vif();
|
||||
|
@ -94,6 +94,7 @@ module core_ibex_tb_top;
|
|||
assign dut_if.dret = dut.u_ibex_core.id_stage_i.dret_insn_dec;
|
||||
assign dut_if.mret = dut.u_ibex_core.id_stage_i.mret_insn_dec;
|
||||
assign dut_if.core_sleep = dut.u_ibex_core.core_sleep_o;
|
||||
assign dut_if.reset = ~rst_n;
|
||||
|
||||
|
||||
initial begin
|
||||
|
@ -106,20 +107,4 @@ module core_ibex_tb_top;
|
|||
run_test();
|
||||
end
|
||||
|
||||
// Generate clk
|
||||
initial begin
|
||||
clk = 1'b0;
|
||||
forever begin
|
||||
#10 clk = ~clk;
|
||||
end
|
||||
end
|
||||
|
||||
// Generate reset
|
||||
initial begin
|
||||
rst_n = 1'b0;
|
||||
repeat(100) @(posedge clk);
|
||||
rst_n = 1'b1;
|
||||
dut_if.debug_req = 1'b0;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -31,6 +31,37 @@ class core_ibex_csr_test extends core_ibex_base_test;
|
|||
|
||||
endclass
|
||||
|
||||
// Reset test
|
||||
class core_ibex_reset_test extends core_ibex_base_test;
|
||||
|
||||
`uvm_component_utils(core_ibex_reset_test)
|
||||
`uvm_component_new
|
||||
|
||||
virtual task send_stimulus();
|
||||
vseq.start(env.vseqr);
|
||||
// Mid-test reset is possible in a wide range of times
|
||||
clk_vif.wait_clks($urandom_range(20000, 200000));
|
||||
fork
|
||||
begin
|
||||
dut_vif.fetch_enable = 1'b0;
|
||||
clk_vif.reset();
|
||||
end
|
||||
begin
|
||||
clk_vif.wait_clks(1);
|
||||
// Flush FIFOs
|
||||
item_collected_port.flush();
|
||||
irq_collected_port.flush();
|
||||
// Reset testbench state
|
||||
env.reset();
|
||||
load_binary_to_mem();
|
||||
end
|
||||
join
|
||||
// Assert fetch_enable to have the core start executing from boot address
|
||||
dut_vif.fetch_enable = 1'b1;
|
||||
endtask
|
||||
|
||||
endclass
|
||||
|
||||
// Performance counter test class
|
||||
class core_ibex_perf_test extends core_ibex_base_test;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue