mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 04:47:25 -04:00
Update interrupt mode, add debug mode WFI test (#268)
This commit is contained in:
parent
2b93475864
commit
68b170638a
11 changed files with 248 additions and 96 deletions
4
dv/uvm/env/core_ibex_dut_probe_if.sv
vendored
4
dv/uvm/env/core_ibex_dut_probe_if.sv
vendored
|
@ -6,6 +6,10 @@
|
|||
interface core_ibex_dut_probe_if(input logic clk);
|
||||
logic illegal_instr;
|
||||
logic ecall;
|
||||
logic wfi;
|
||||
logic ebreak;
|
||||
logic dret;
|
||||
logic mret;
|
||||
logic fetch_enable;
|
||||
logic debug_req;
|
||||
endinterface
|
||||
|
|
4
dv/uvm/env/core_ibex_env.sv
vendored
4
dv/uvm/env/core_ibex_env.sv
vendored
|
@ -25,7 +25,7 @@ class core_ibex_env extends uvm_env;
|
|||
create("data_if_slave_agent", this);
|
||||
instr_if_slave_agent = ibex_mem_intf_slave_agent::type_id::
|
||||
create("instr_if_slave_agent", this);
|
||||
if (cfg.enable_irq_seq) begin
|
||||
if (cfg.enable_irq_stress_seq || cfg.enable_irq_single_seq) begin
|
||||
irq_agent = irq_master_agent::type_id::create("irq_agent", this);
|
||||
end
|
||||
// Create virtual sequencer
|
||||
|
@ -36,7 +36,7 @@ class core_ibex_env extends uvm_env;
|
|||
super.connect_phase(phase);
|
||||
vseqr.data_if_seqr = data_if_slave_agent.sequencer;
|
||||
vseqr.instr_if_seqr = instr_if_slave_agent.sequencer;
|
||||
if (cfg.enable_irq_seq) begin
|
||||
if (cfg.enable_irq_stress_seq || cfg.enable_irq_single_seq) begin
|
||||
vseqr.irq_seqr = irq_agent.sequencer;
|
||||
end
|
||||
endfunction : connect_phase
|
||||
|
|
21
dv/uvm/env/core_ibex_env_cfg.sv
vendored
21
dv/uvm/env/core_ibex_env_cfg.sv
vendored
|
@ -4,22 +4,31 @@
|
|||
|
||||
class core_ibex_env_cfg extends uvm_object;
|
||||
|
||||
bit enable_irq_seq;
|
||||
bit enable_debug_seq;
|
||||
bit enable_irq_stress_seq;
|
||||
bit enable_irq_single_seq;
|
||||
bit enable_debug_stress_seq;
|
||||
bit enable_debug_single_seq;
|
||||
bit[31:0] max_interval;
|
||||
bit require_signature_addr;
|
||||
bit[31:0] signature_addr;
|
||||
|
||||
`uvm_object_utils_begin(core_ibex_env_cfg)
|
||||
`uvm_field_int(enable_irq_seq, UVM_DEFAULT)
|
||||
`uvm_field_int(enable_debug_seq, UVM_DEFAULT)
|
||||
`uvm_field_int(enable_irq_stress_seq, UVM_DEFAULT)
|
||||
`uvm_field_int(enable_irq_single_seq, UVM_DEFAULT)
|
||||
`uvm_field_int(enable_debug_single_seq, UVM_DEFAULT)
|
||||
`uvm_field_int(enable_debug_stress_seq, UVM_DEFAULT)
|
||||
`uvm_field_int(max_interval, UVM_DEFAULT)
|
||||
`uvm_field_int(require_signature_addr, UVM_DEFAULT)
|
||||
`uvm_field_int(signature_addr, UVM_DEFAULT)
|
||||
`uvm_object_utils_end
|
||||
|
||||
function new(string name = "");
|
||||
super.new(name);
|
||||
void'($value$plusargs("enable_irq_seq=%0d", enable_irq_seq));
|
||||
void'($value$plusargs("enable_debug_seq=%0d", enable_debug_seq));
|
||||
void'($value$plusargs("enable_irq_stress_seq=%0d", enable_irq_stress_seq));
|
||||
void'($value$plusargs("enable_irq_single_seq=%0d", enable_irq_single_seq));
|
||||
void'($value$plusargs("enable_debug_stress_seq=%0d", enable_debug_stress_seq));
|
||||
void'($value$plusargs("enable_debug_single_seq=%0d", enable_debug_single_seq));
|
||||
void'($value$plusargs("max_interval=%0d", max_interval));
|
||||
void'($value$plusargs("require_signature_addr=%0d", require_signature_addr));
|
||||
void'($value$plusargs("signature_addr=%0h", signature_addr));
|
||||
endfunction
|
||||
|
|
|
@ -47,7 +47,7 @@ def process_ibex_sim_log(ibex_log, csv):
|
|||
print("Processed instruction count : %d" % instr_cnt)
|
||||
|
||||
|
||||
def check_ibex_uvm_log(uvm_log, core_name, test_name, report):
|
||||
def check_ibex_uvm_log(uvm_log, core_name, test_name, report, write=True):
|
||||
"""Process Ibex UVM simulation log.
|
||||
|
||||
This function will be used when a test disables the normal post_compare step.
|
||||
|
@ -58,14 +58,11 @@ def check_ibex_uvm_log(uvm_log, core_name, test_name, report):
|
|||
core_name: the name of the core
|
||||
test_name: name of the test being checked
|
||||
report: the output report file
|
||||
write: enables writing to the log file
|
||||
|
||||
Returns:
|
||||
A boolean indicating whether the test passed or failed based on the signature
|
||||
"""
|
||||
if report:
|
||||
fd = open(report, "a+")
|
||||
else:
|
||||
fd = sys.stdout
|
||||
|
||||
fd.write("%s uvm log : %s\n" % (core_name, uvm_log))
|
||||
|
||||
pass_cnt = 0
|
||||
fail_cnt = 0
|
||||
with open(uvm_log, "r") as log:
|
||||
|
@ -76,12 +73,21 @@ def check_ibex_uvm_log(uvm_log, core_name, test_name, report):
|
|||
elif 'RISC-V UVM TEST FAILED' in line:
|
||||
fail_cnt += 1
|
||||
break
|
||||
if pass_cnt == 1:
|
||||
fd.write("%s : PASSED\n" % test_name)
|
||||
elif fail_cnt == 1:
|
||||
fd.write("%s : FAILED\n" % test_name)
|
||||
if report:
|
||||
fd.close()
|
||||
|
||||
if write:
|
||||
if report:
|
||||
fd = open(report, "a+")
|
||||
else:
|
||||
fd = sys.stdout
|
||||
fd.write("%s uvm log : %s\n" % (core_name, uvm_log))
|
||||
if pass_cnt == 1:
|
||||
fd.write("%s : PASSED\n" % test_name)
|
||||
elif fail_cnt == 1:
|
||||
fd.write("%s : FAILED\n" % test_name)
|
||||
if report:
|
||||
fd.close()
|
||||
|
||||
return pass_cnt == 1
|
||||
|
||||
|
||||
def main():
|
||||
|
|
|
@ -119,7 +119,8 @@
|
|||
rtl_test: core_ibex_debug_intr_test
|
||||
sim_opts: >
|
||||
+require_signature_addr=1
|
||||
+enable_debug_seq=1
|
||||
+max_interval=1000
|
||||
+enable_debug_stress_seq=1
|
||||
compare_opts:
|
||||
compare_final_value_only: 1
|
||||
verbose: 1
|
||||
|
@ -137,7 +138,8 @@
|
|||
rtl_test: core_ibex_debug_intr_test
|
||||
iterations: 5
|
||||
sim_opts: >
|
||||
+frequent_debug=1
|
||||
+max_interval=250
|
||||
+enable_debug_stress_seq=1
|
||||
+require_signature_addr=1
|
||||
compare_opts:
|
||||
compare_final_value_only: 1
|
||||
|
@ -161,7 +163,28 @@
|
|||
rtl_test: core_ibex_debug_intr_test
|
||||
sim_opts: >
|
||||
+require_signature_addr=1
|
||||
+enable_debug_seq=1
|
||||
+enable_debug_stress_seq=1
|
||||
compare_opts:
|
||||
compare_final_value_only: 1
|
||||
verbose: 1
|
||||
|
||||
- test: riscv_debug_wfi_test
|
||||
description: >
|
||||
Assert debug_req while core is in WFI sleep state, should jump to debug mode
|
||||
iterations: 5
|
||||
gen_test: riscv_rand_instr_test
|
||||
gen_opts: >
|
||||
+require_signature_addr=1
|
||||
+gen_debug_section=1
|
||||
+no_ebreak=1
|
||||
+instr_cnt=3000
|
||||
+no_csr_instr=1
|
||||
+no_fence=1
|
||||
+no_wfi=0
|
||||
rtl_test: core_ibex_debug_wfi_test
|
||||
sim_opts: >
|
||||
+require_signature_addr=1
|
||||
+enable_debug_single_seq=1
|
||||
compare_opts:
|
||||
compare_final_value_only: 1
|
||||
verbose: 1
|
||||
|
@ -176,7 +199,7 @@
|
|||
rtl_test: core_ibex_debug_intr_test
|
||||
sim_opts: >
|
||||
+require_signature_addr=1
|
||||
+enable_irq_seq=1
|
||||
+enable_irq_stress_seq=1
|
||||
compare_opts:
|
||||
compare_final_value_only: 1
|
||||
|
||||
|
|
|
@ -168,8 +168,8 @@ def compare(test_list, iss, output_dir, verbose):
|
|||
uvm_log = ("%s/rtl_sim/%s.%d/sim.log" % (output_dir, test['test'], i))
|
||||
rtl_log = ("%s/rtl_sim/%s.%d/trace_core_00_0.log" % (output_dir, test['test'], i))
|
||||
rtl_csv = ("%s/rtl_sim/%s.%d/trace_core_00_0.csv" % (output_dir, test['test'], i))
|
||||
test_name = "%s.%d" % (test['test'], i)
|
||||
if 'no_post_compare' in test and test['no_post_compare'] == 1:
|
||||
test_name = "%s.%d" % (test['test'], i)
|
||||
check_ibex_uvm_log(uvm_log, "ibex", test_name, report)
|
||||
else:
|
||||
process_ibex_sim_log(rtl_log, rtl_csv)
|
||||
|
@ -182,18 +182,22 @@ def compare(test_list, iss, output_dir, verbose):
|
|||
else:
|
||||
print("Unsupported ISS" % iss)
|
||||
sys.exit(1)
|
||||
if 'compare_opts' in test:
|
||||
compare_opts = test.get('compare_opts')
|
||||
in_order_mode = compare_opts.get('in_order_mode', 1)
|
||||
coalescing_limit = compare_opts.get('coalescing_limit', 0)
|
||||
verbose = compare_opts.get('verbose', 0)
|
||||
mismatch = compare_opts.get('mismatch_print_limit', 5)
|
||||
compare_final = compare_opts.get('compare_final_value_only', 0)
|
||||
compare_trace_csv(rtl_csv, iss_csv, "ibex", iss, report,
|
||||
in_order_mode, coalescing_limit, verbose,
|
||||
mismatch, compare_final)
|
||||
uvm_result = check_ibex_uvm_log(uvm_log, "ibex", test_name, report, False)
|
||||
if not uvm_result:
|
||||
check_ibex_uvm_log(uvm_log, "ibex", test_name, report)
|
||||
else:
|
||||
compare_trace_csv(rtl_csv, iss_csv, "ibex", iss, report)
|
||||
if 'compare_opts' in test:
|
||||
compare_opts = test.get('compare_opts')
|
||||
in_order_mode = compare_opts.get('in_order_mode', 1)
|
||||
coalescing_limit = compare_opts.get('coalescing_limit', 0)
|
||||
verbose = compare_opts.get('verbose', 0)
|
||||
mismatch = compare_opts.get('mismatch_print_limit', 5)
|
||||
compare_final = compare_opts.get('compare_final_value_only', 0)
|
||||
compare_trace_csv(rtl_csv, iss_csv, "ibex", iss, report,
|
||||
in_order_mode, coalescing_limit, verbose,
|
||||
mismatch, compare_final)
|
||||
else:
|
||||
compare_trace_csv(rtl_csv, iss_csv, "ibex", iss, report)
|
||||
passed_cnt = run_cmd("grep PASSED %s | wc -l" % report).strip()
|
||||
failed_cnt = run_cmd("grep FAILED %s | wc -l" % report).strip()
|
||||
summary = ("%s PASSED, %s FAILED" % (passed_cnt, failed_cnt))
|
||||
|
|
|
@ -69,7 +69,11 @@ module core_ibex_tb_top;
|
|||
force irq_vif.reset = ~rst_n;
|
||||
end
|
||||
|
||||
assign dut_if.ecall = dut.u_ibex_core.id_stage_i.ecall_insn_dec;
|
||||
assign dut_if.ecall = dut.u_ibex_core.id_stage_i.ecall_insn_dec;
|
||||
assign dut_if.wfi = dut.u_ibex_core.id_stage_i.wfi_insn_dec;
|
||||
assign dut_if.ebreak = dut.u_ibex_core.id_stage_i.ebrk_insn;
|
||||
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;
|
||||
|
||||
|
||||
initial begin
|
||||
|
|
|
@ -8,17 +8,16 @@ class core_ibex_base_test extends uvm_test;
|
|||
core_ibex_env_cfg cfg;
|
||||
virtual clk_if clk_vif;
|
||||
virtual core_ibex_dut_probe_if dut_vif;
|
||||
virtual ibex_mem_intf dmem_vif;
|
||||
mem_model_pkg::mem_model mem;
|
||||
core_ibex_vseq vseq;
|
||||
bit enable_irq_seq;
|
||||
bit enable_debug_seq;
|
||||
irq_seq irq_seq_h;
|
||||
int unsigned timeout_in_cycles = 2000000;
|
||||
int unsigned timeout_in_cycles = 3000000;
|
||||
// If no signature_addr handshake functionality is desired between the
|
||||
// testbench and the generated code, the test will wait for the specified
|
||||
// number of cycles before starting stimulus sequences (irq and debug)
|
||||
int unsigned stimulus_delay = 800;
|
||||
bit[ibex_mem_intf_agent_pkg::DATA_WIDTH] signature_data_q[$];
|
||||
bit[ibex_mem_intf_agent_pkg::DATA_WIDTH] signature_data;
|
||||
uvm_tlm_analysis_fifo #(ibex_mem_intf_seq_item) item_collected_port;
|
||||
|
||||
`uvm_component_utils(core_ibex_base_test)
|
||||
|
@ -40,9 +39,6 @@ class core_ibex_base_test extends uvm_test;
|
|||
if (!uvm_config_db#(virtual core_ibex_dut_probe_if)::get(null, "", "dut_if", dut_vif)) begin
|
||||
`uvm_fatal(get_full_name(), "Cannot get dut_if")
|
||||
end
|
||||
if (!uvm_config_db#(virtual ibex_mem_intf)::get(null, "*data_if_slave*", "vif", dmem_vif)) begin
|
||||
`uvm_fatal(get_full_name(), "Cannot get dmem_vif")
|
||||
end
|
||||
env = core_ibex_env::type_id::create("env", this);
|
||||
cfg = core_ibex_env_cfg::type_id::create("cfg", this);
|
||||
uvm_config_db#(core_ibex_env_cfg)::set(this, "*", "cfg", cfg);
|
||||
|
@ -64,7 +60,7 @@ class core_ibex_base_test extends uvm_test;
|
|||
clk_vif.wait_clks(100);
|
||||
load_binary_to_mem();
|
||||
dut_vif.fetch_enable = 1'b1;
|
||||
vseq.start(env.vseqr);
|
||||
send_stimulus();
|
||||
wait_for_test_done();
|
||||
phase.drop_objection(this);
|
||||
endtask
|
||||
|
@ -73,6 +69,10 @@ class core_ibex_base_test extends uvm_test;
|
|||
super.report_phase(phase);
|
||||
endfunction
|
||||
|
||||
virtual task send_stimulus();
|
||||
vseq.start(env.vseqr);
|
||||
endtask
|
||||
|
||||
function void load_binary_to_mem();
|
||||
string bin;
|
||||
bit [7:0] r8;
|
||||
|
@ -115,11 +115,10 @@ class core_ibex_base_test extends uvm_test;
|
|||
join_any
|
||||
endtask
|
||||
|
||||
|
||||
virtual task wait_for_mem_txn(input bit[ibex_mem_intf_agent_pkg::ADDR_WIDTH-1:0] ref_addr,
|
||||
input signature_type_t ref_type,
|
||||
output bit[ibex_mem_intf_agent_pkg::DATA_WIDTH-1:0] data[$]);
|
||||
input signature_type_t ref_type);
|
||||
ibex_mem_intf_seq_item mem_txn;
|
||||
bit[ibex_mem_intf_agent_pkg::DATA_WIDTH-1:0] signature_data;
|
||||
forever begin
|
||||
// The first write to this address is guaranteed to contain the
|
||||
// signature type in bits [7:0]
|
||||
|
@ -127,11 +126,14 @@ class core_ibex_base_test extends uvm_test;
|
|||
if (mem_txn.addr == ref_addr && mem_txn.data[7:0] === ref_type && mem_txn.read_write == WRITE) begin
|
||||
signature_data = mem_txn.data;
|
||||
case (ref_type)
|
||||
// The very first write to the signature address in every test is
|
||||
// guaranteed to be a write of CORE_STATUS, indicating the
|
||||
// INITIALIZED state
|
||||
CORE_STATUS: begin
|
||||
data.push_back(signature_data >> 8);
|
||||
signature_data_q.push_back(signature_data >> 8);
|
||||
end
|
||||
TEST_RESULT: begin
|
||||
data.push_back(signature_data >> 8);
|
||||
signature_data_q.push_back(signature_data >> 8);
|
||||
end
|
||||
// The next 32 writes to the address are guaranteed to be a dump of
|
||||
// all GPRs
|
||||
|
@ -140,17 +142,17 @@ class core_ibex_base_test extends uvm_test;
|
|||
do begin
|
||||
item_collected_port.get(mem_txn);
|
||||
end while(!(mem_txn.addr == ref_addr && mem_txn.read_write == WRITE));
|
||||
data.push_back(mem_txn.data);
|
||||
signature_data_q.push_back(mem_txn.data);
|
||||
end
|
||||
end
|
||||
// The next write to this address is guaranteed to be the data held
|
||||
// in the CSR
|
||||
WRITE_CSR: begin
|
||||
data.push_back(signature_data >> 8);
|
||||
signature_data_q.push_back(signature_data >> 8);
|
||||
do begin
|
||||
item_collected_port.get(mem_txn);
|
||||
end while (!(mem_txn.addr == ref_addr && mem_txn.read_write == WRITE));
|
||||
data.push_back(mem_txn.data);
|
||||
signature_data_q.push_back(mem_txn.data);
|
||||
end
|
||||
default: begin
|
||||
`uvm_fatal(`gfn, $sformatf("The data 0x%0h written to the signature address is formatted incorrectly.", signature_data))
|
||||
|
@ -161,4 +163,23 @@ class core_ibex_base_test extends uvm_test;
|
|||
end
|
||||
endtask
|
||||
|
||||
// API of various tasks wrapping wait_for_mem_txn, for various common
|
||||
// functionalities that might be needed for verification purposes.
|
||||
// Will be expanded as needed.
|
||||
|
||||
virtual task check_next_core_status(core_status_t core_status, error_msg="");
|
||||
wait_for_mem_txn(cfg.signature_addr, CORE_STATUS);
|
||||
signature_data = signature_data_q.pop_front();
|
||||
if (signature_data != core_status) begin
|
||||
`uvm_error(`gfn, error_msg)
|
||||
end
|
||||
endtask
|
||||
|
||||
virtual task wait_for_core_status(core_status_t core_status);
|
||||
do begin
|
||||
wait_for_mem_txn(cfg.signature_addr, CORE_STATUS);
|
||||
signature_data = signature_data_q.pop_front();
|
||||
end while (signature_data != core_status);
|
||||
endtask
|
||||
|
||||
endclass
|
||||
|
|
|
@ -9,7 +9,7 @@ class core_base_seq #(type REQ = uvm_sequence_item) extends uvm_sequence#(REQ);
|
|||
rand int unsigned delay;
|
||||
int unsigned num_of_iterations; // 0: infinite until stopped
|
||||
int unsigned iteration_cnt;
|
||||
int unsigned max_interval = 1000;
|
||||
int unsigned max_interval;
|
||||
int unsigned max_delay = 500;
|
||||
virtual clk_if clk_vif;
|
||||
bit stop_seq;
|
||||
|
@ -98,7 +98,7 @@ class debug_seq extends core_base_seq;
|
|||
virtual task send_req();
|
||||
`uvm_info(get_full_name(), "Sending debug request", UVM_HIGH)
|
||||
dut_vif.debug_req <= 1'b1;
|
||||
clk_vif.wait_clks($urandom_range(1, 20));
|
||||
clk_vif.wait_clks($urandom_range(10, 30));
|
||||
dut_vif.debug_req <= 1'b0;
|
||||
endtask
|
||||
|
||||
|
|
|
@ -9,12 +9,11 @@ class core_ibex_csr_test extends core_ibex_base_test;
|
|||
`uvm_component_new
|
||||
|
||||
virtual task wait_for_test_done();
|
||||
bit[ibex_mem_intf_agent_pkg::DATA_WIDTH-1:0] signature_data[$];
|
||||
bit result;
|
||||
fork
|
||||
begin
|
||||
wait_for_mem_txn(cfg.signature_addr, TEST_RESULT, signature_data);
|
||||
result = signature_data.pop_front();
|
||||
wait_for_mem_txn(cfg.signature_addr, TEST_RESULT);
|
||||
result = signature_data_q.pop_front();
|
||||
if (result == TEST_PASS) begin
|
||||
`uvm_info(`gfn, "CSR test completed successfully!", UVM_LOW)
|
||||
end else if (result == TEST_FAIL) begin
|
||||
|
@ -35,43 +34,91 @@ endclass
|
|||
// Debug test class
|
||||
class core_ibex_debug_intr_test extends core_ibex_base_test;
|
||||
|
||||
bit[ibex_mem_intf_agent_pkg::DATA_WIDTH-1:0] core_start_data[$];
|
||||
bit[ibex_mem_intf_agent_pkg::DATA_WIDTH-1:0] initialized_data;
|
||||
|
||||
`uvm_component_utils(core_ibex_debug_intr_test)
|
||||
`uvm_component_new
|
||||
|
||||
virtual task run_phase(uvm_phase phase);
|
||||
phase.raise_objection(this);
|
||||
dut_vif.fetch_enable = 1'b0;
|
||||
clk_vif.wait_clks(100);
|
||||
load_binary_to_mem();
|
||||
dut_vif.fetch_enable = 1'b1;
|
||||
virtual task send_stimulus();
|
||||
fork
|
||||
vseq.start(env.vseqr);
|
||||
begin
|
||||
vseq.start(env.vseqr);
|
||||
end
|
||||
begin
|
||||
if (cfg.require_signature_addr) begin
|
||||
do begin
|
||||
wait_for_mem_txn(cfg.signature_addr, CORE_STATUS, core_start_data);
|
||||
initialized_data = core_start_data.pop_front();
|
||||
end while(initialized_data != INITIALIZED);
|
||||
wait_for_core_status(INITIALIZED);
|
||||
end else begin
|
||||
// If no signature_addr functionality is desired, then the test will
|
||||
// simply wait for an adequate number of cycles
|
||||
clk_vif.wait_clks(stimulus_delay);
|
||||
end
|
||||
fork
|
||||
if (cfg.enable_irq_seq) begin
|
||||
vseq.start_irq_seq();
|
||||
begin
|
||||
if (cfg.enable_irq_stress_seq) begin
|
||||
vseq.start_irq_stress_seq();
|
||||
end
|
||||
end
|
||||
if (cfg.enable_debug_seq) begin
|
||||
vseq.start_debug_seq();
|
||||
begin
|
||||
if (cfg.enable_debug_stress_seq) begin
|
||||
vseq.start_debug_stress_seq();
|
||||
end
|
||||
end
|
||||
join_none
|
||||
end
|
||||
join_none
|
||||
wait_for_test_done();
|
||||
phase.drop_objection(this);
|
||||
endtask
|
||||
|
||||
endclass
|
||||
|
||||
// Debug WFI test class
|
||||
class core_ibex_debug_wfi_test extends core_ibex_base_test;
|
||||
|
||||
`uvm_component_utils(core_ibex_debug_wfi_test)
|
||||
`uvm_component_new
|
||||
|
||||
virtual task send_stimulus();
|
||||
fork
|
||||
begin
|
||||
vseq.start(env.vseqr);
|
||||
end
|
||||
begin
|
||||
if (!cfg.require_signature_addr) begin
|
||||
clk_vif.wait_clks(stimulus_delay);
|
||||
fork
|
||||
begin
|
||||
if (cfg.enable_irq_stress_seq) begin
|
||||
vseq.start_irq_stress_seq();
|
||||
end
|
||||
end
|
||||
begin
|
||||
if (cfg.enable_debug_stress_seq) begin
|
||||
vseq.start_debug_stress_seq();
|
||||
end
|
||||
end
|
||||
join_none
|
||||
end else begin
|
||||
// Wait for core initialization before starting the wfi stimulus
|
||||
// loop - first write to signature address is guaranteed to be core
|
||||
// initialization info
|
||||
check_next_core_status(INITIALIZED, "Core initialization handshake failure");
|
||||
// TODO(udi) - need to check that no other instruction fetches occur
|
||||
// after the WFI is detected, and before any stimulus is sent to the
|
||||
// core
|
||||
forever begin
|
||||
wait (dut_vif.wfi === 1'b1);
|
||||
clk_vif.wait_clks($urandom_range(100));
|
||||
vseq.start_debug_single_seq();
|
||||
// After assserting this signal, core should wake up and jump into
|
||||
// debug mode from WFI state - next handshake should
|
||||
// be a notification that the core is now in debug mode
|
||||
check_next_core_status(IN_DEBUG_MODE, "Core did not jump into debug mode from WFI state");
|
||||
// We don't want to trigger debug stimulus for any WFI
|
||||
// instructions encountered inside the debug rom - those should
|
||||
// act as NOP instructions - so we wait until hitting the end of
|
||||
// the debug rom
|
||||
wait (dut_vif.dret === 1'b1);
|
||||
end
|
||||
end
|
||||
end
|
||||
join_none
|
||||
endtask
|
||||
|
||||
endclass
|
||||
|
|
|
@ -11,8 +11,10 @@ class core_ibex_vseq extends uvm_sequence;
|
|||
ibex_mem_intf_slave_seq instr_intf_seq;
|
||||
ibex_mem_intf_slave_seq data_intf_seq;
|
||||
mem_model_pkg::mem_model mem;
|
||||
irq_seq irq_seq_h;
|
||||
debug_seq debug_seq_h;
|
||||
irq_seq irq_seq_stress_h;
|
||||
irq_seq irq_seq_single_h;
|
||||
debug_seq debug_seq_stress_h;
|
||||
debug_seq debug_seq_single_h;
|
||||
core_ibex_env_cfg cfg;
|
||||
bit[ibex_mem_intf_agent_pkg::DATA_WIDTH-1:0] data;
|
||||
|
||||
|
@ -23,16 +25,32 @@ class core_ibex_vseq extends uvm_sequence;
|
|||
virtual task body();
|
||||
instr_intf_seq = ibex_mem_intf_slave_seq::type_id::create("instr_intf_seq");
|
||||
data_intf_seq = ibex_mem_intf_slave_seq::type_id::create("data_intf_seq");
|
||||
if (cfg.enable_irq_seq) begin
|
||||
irq_seq_h = irq_seq::type_id::create("irq_seq_h");
|
||||
if (cfg.enable_irq_stress_seq) begin
|
||||
irq_seq_stress_h = irq_seq::type_id::create("irq_seq_stress_h");
|
||||
irq_seq_stress_h.max_interval = cfg.max_interval;
|
||||
end
|
||||
if (cfg.enable_debug_seq) begin
|
||||
debug_seq_h = debug_seq::type_id::create("debug_seq_h");
|
||||
if (cfg.enable_irq_single_seq) begin
|
||||
irq_seq_single_h = irq_seq::type_id::create("irq_seq_single_h");
|
||||
irq_seq_single_h.num_of_iterations = 1;
|
||||
irq_seq_single_h.max_interval = 1;
|
||||
irq_seq_single_h.max_delay = 1;
|
||||
irq_seq_single_h.interval.rand_mode(0);
|
||||
irq_seq_single_h.interval = 0;
|
||||
end
|
||||
if (cfg.enable_debug_stress_seq) begin
|
||||
debug_seq_stress_h = debug_seq::type_id::create("debug_seq_stress_h");
|
||||
debug_seq_stress_h.max_interval = cfg.max_interval;
|
||||
end
|
||||
if (cfg.enable_debug_single_seq) begin
|
||||
debug_seq_single_h = debug_seq::type_id::create("debug_seq_single_h");
|
||||
debug_seq_single_h.num_of_iterations = 1;
|
||||
debug_seq_single_h.max_interval = 1;
|
||||
debug_seq_single_h.max_delay = 1;
|
||||
debug_seq_single_h.interval.rand_mode(0);
|
||||
debug_seq_single_h.interval = 0;
|
||||
end
|
||||
instr_intf_seq.m_mem = mem;
|
||||
data_intf_seq.m_mem = mem;
|
||||
|
||||
|
||||
fork
|
||||
instr_intf_seq.start(p_sequencer.instr_if_seqr);
|
||||
data_intf_seq.start(p_sequencer.data_if_seqr);
|
||||
|
@ -40,20 +58,36 @@ class core_ibex_vseq extends uvm_sequence;
|
|||
endtask
|
||||
|
||||
virtual task stop();
|
||||
if (cfg.enable_irq_seq) begin
|
||||
irq_seq_h.stop();
|
||||
if (cfg.enable_irq_stress_seq) begin
|
||||
irq_seq_stress_h.stop();
|
||||
end
|
||||
if (cfg.enable_debug_seq) begin
|
||||
debug_seq_h.stop();
|
||||
if (cfg.enable_irq_single_seq) begin
|
||||
irq_seq_single_h.stop();
|
||||
end
|
||||
if (cfg.enable_debug_stress_seq) begin
|
||||
debug_seq_stress_h.stop();
|
||||
end
|
||||
if (cfg.enable_debug_single_seq) begin
|
||||
debug_seq_single_h.stop();
|
||||
end
|
||||
endtask
|
||||
|
||||
virtual task start_debug_seq();
|
||||
debug_seq_h.start(null);
|
||||
// Helper tasks to allow the test fine grained control to start sequences
|
||||
// through the vseq - necessary for testing directed stimulus scenarios
|
||||
virtual task start_debug_stress_seq();
|
||||
debug_seq_stress_h.start(null);
|
||||
endtask
|
||||
|
||||
virtual task start_irq_seq();
|
||||
irq_seq_h.start(p_sequencer.irq_seqr);
|
||||
virtual task start_debug_single_seq();
|
||||
debug_seq_single_h.start(null);
|
||||
endtask
|
||||
|
||||
virtual task start_irq_stress_seq();
|
||||
irq_seq_stress_h.start(p_sequencer.irq_seqr);
|
||||
endtask
|
||||
|
||||
virtual task start_irq_single_seq();
|
||||
irq_seq_single_h.start(p_sequencer.irq_seqr);
|
||||
endtask
|
||||
|
||||
endclass
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue