[DV] Add reset test (#392)

This commit is contained in:
udinator 2019-10-10 13:01:32 -07:00 committed by GitHub
parent 2ca1a6da21
commit ae82d61401
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 187 additions and 45 deletions

View file

@ -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

View file

@ -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

View file

@ -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();

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;