Add interrupt testing, and update some debug test checks (#324)

This commit is contained in:
udinator 2019-09-16 16:58:28 -07:00 committed by GitHub
parent 369f56bad0
commit 80e231dd8b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 225 additions and 76 deletions

View file

@ -10,6 +10,9 @@ class ibex_mem_intf_slave_driver extends uvm_driver #(ibex_mem_intf_seq_item);
protected virtual ibex_mem_intf vif;
int unsigned min_grant_delay = 0;
int unsigned max_grant_delay = 10;
`uvm_component_utils(ibex_mem_intf_slave_driver)
`uvm_component_new
@ -55,15 +58,20 @@ class ibex_mem_intf_slave_driver extends uvm_driver #(ibex_mem_intf_seq_item);
join_none
endtask : get_and_drive
// TODO(udinator) - this direct send_grant logic is temporary until instruction fetch protocol
// issue is clarified (https://github.com/lowRISC/ibex/pull/293). After resolution, will re-add
// random delays insertion before driving grant to the ibex core.
virtual protected task send_grant();
int gnt_delay;
forever begin
while(vif.request !== 1'b1) begin
@(negedge vif.clock);
end
std::randomize(gnt_delay) with {
gnt_delay dist {
min_grant_delay :/ 1,
[min_grant_delay+1 : max_grant_delay-1] :/ 1,
max_grant_delay :/ 1
};
};
repeat(gnt_delay) @(negedge vif.clock);
if(~vif.reset) begin
vif.grant = 1'b1;
@(negedge vif.clock);

View file

@ -52,11 +52,6 @@ class irq_master_driver extends uvm_driver #(irq_seq_item);
vif.irq_external <= trans.irq_external;
vif.irq_fast <= trans.irq_fast;
vif.irq_nm <= trans.irq_nm;
// We hold the interrupt high for two cycles as Ibex is level sensitive,
// so this guarantees that Ibex will respond appropriately to the
// interrupt
repeat (2) @(posedge vif.clock);
drive_reset_value();
endtask : drive_seq_item
task drive_reset_value();

View file

@ -25,11 +25,23 @@ class irq_monitor extends uvm_monitor;
collect_irq();
endtask : run_phase
// We know that for Ibex, any given interrupt stimulus will be asserted until the core signals the
// testbench that it has finished handling, and this stimulus will not change until the testbench
// receives the signal, at which point it will drop.
// Given this, as well as how the interrupt handshakes are designed, sending an irq_seq_item every
// cycle is not useful at all.
// In order to not send unnecessary sequence items, but to also send enough information that the
// testbench can handle nested interrupt scenarios, the monitor will send out a sequence
// item every time the interrupt lines change.
virtual protected task collect_irq();
irq_seq_item irq;
bit[DATA_WIDTH-1:0] stored_irq_val = '0;
bit[DATA_WIDTH-1:0] current_irq = '0;
forever begin
if (|{vif.irq_software, vif.irq_timer, vif.irq_external,
vif.irq_fast, vif.irq_nm}) begin
current_irq = {vif.irq_nm, vif.irq_fast, 4'b0, vif.irq_external, 3'b0,
vif.irq_timer, 3'b0, vif.irq_software, 3'b0};
if (current_irq !== stored_irq_val) begin
stored_irq_val = current_irq;
irq = irq_seq_item::type_id::create("irq");
irq.irq_software = vif.irq_software;
irq.irq_timer = vif.irq_timer;

View file

@ -12,7 +12,7 @@ class irq_seq_item extends uvm_sequence_item;
rand int num_of_interrupt;
constraint num_of_interrupt_c {
num_of_interrupt inside {[1:19]};
num_of_interrupt inside {[0:DATA_WIDTH-1]};
$countones({irq_software, irq_timer, irq_external, irq_fast, irq_nm}) == num_of_interrupt;
}

View file

@ -11,5 +11,6 @@ interface core_ibex_dut_probe_if(input logic clk);
logic dret;
logic mret;
logic fetch_enable;
logic core_sleep;
logic debug_req;
endinterface

View file

@ -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_stress_seq || cfg.enable_irq_single_seq) begin
if (cfg.enable_irq_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_stress_seq || cfg.enable_irq_single_seq) begin
if (cfg.enable_irq_seq) begin
vseqr.irq_seqr = irq_agent.sequencer;
end
endfunction : connect_phase

View file

@ -4,8 +4,7 @@
class core_ibex_env_cfg extends uvm_object;
bit enable_irq_stress_seq;
bit enable_irq_single_seq;
bit enable_irq_seq;
bit enable_debug_stress_seq;
bit enable_debug_single_seq;
bit[31:0] max_interval;
@ -13,8 +12,7 @@ class core_ibex_env_cfg extends uvm_object;
bit[31:0] signature_addr;
`uvm_object_utils_begin(core_ibex_env_cfg)
`uvm_field_int(enable_irq_stress_seq, UVM_DEFAULT)
`uvm_field_int(enable_irq_single_seq, UVM_DEFAULT)
`uvm_field_int(enable_irq_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)
@ -24,8 +22,7 @@ class core_ibex_env_cfg extends uvm_object;
function new(string name = "");
super.new(name);
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_irq_seq=%0d", enable_irq_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));

View file

@ -37,6 +37,10 @@ riscv_instr_group_t supported_isa[$] = {RV32I, RV32M, RV32C};
// Interrupt mode support
mtvec_mode_t supported_interrupt_mode[$] = {VECTORED};
// The number of interrupt vectors to be generated, only used if VECTORED interrupt mode is
// supported
int max_interrupt_vector_num = 32;
// Debug mode support
bit support_debug_mode = 1;
@ -46,8 +50,6 @@ bit support_umode_trap = 0;
// Support sfence.vma instruction
bit support_sfence = 0;
int max_interrupt_vector_num = 32;
//-----------------------------------------------------------------------------
// Kernel section setting, used by supervisor mode programs
//-----------------------------------------------------------------------------

View file

@ -201,16 +201,6 @@
sim_opts: >
+require_signature_addr=1
- test: riscv_ebreak_test
description: >
Ebreak instructions will be inserted into the M mode code, ibex should handle them normally.
iterations: 5
gen_test: riscv_rand_instr_test
gen_opts: >
+no_ebreak=0
+instr_cnt=6000
rtl_test: core_ibex_base_test
- test: riscv_debug_ebreak_test
description: >
A directed ebreak sequence will be inserted into the debug rom, upon encountering it,
@ -259,14 +249,15 @@
- test: riscv_interrupt_test
description: >
Random instruction test with complete interrupt handling
iterations: 0
iterations: 10
gen_test: riscv_rand_instr_test
gen_opts: >
+require_signature_addr=1
+enable_interrupt=1
rtl_test: core_ibex_debug_intr_basic_test
sim_opts: >
+require_signature_addr=1
+enable_irq_stress_seq=1
+enable_irq_seq=1
compare_opts:
compare_final_value_only: 1

View file

@ -143,6 +143,7 @@ def rtl_sim(sim_cmd, test_list, output_dir, bin_dir, lsf_cmd, seed, opts):
rand_seed = get_seed(seed)
test_sim_cmd = re.sub("<seed>", str(rand_seed), sim_cmd)
if "sim_opts" in test:
test_sim_cmd += ' '
test_sim_cmd += test['sim_opts']
sim_dir = output_dir + ("/%s.%d" %(test['test'], i))
run_cmd(("mkdir -p %s" % sim_dir))

View file

@ -68,11 +68,12 @@ 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.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;
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;
assign dut_if.core_sleep = dut.u_ibex_core.core_sleep_o;
initial begin

View file

@ -10,7 +10,6 @@ class core_ibex_base_test extends uvm_test;
virtual core_ibex_dut_probe_if dut_vif;
mem_model_pkg::mem_model mem;
core_ibex_vseq vseq;
irq_seq irq_seq_h;
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 specifield number of cycles before starting stimulus
@ -19,6 +18,7 @@ class core_ibex_base_test extends uvm_test;
bit[ibex_mem_intf_agent_pkg::DATA_WIDTH-1:0] signature_data_q[$];
bit[ibex_mem_intf_agent_pkg::DATA_WIDTH-1:0] signature_data;
uvm_tlm_analysis_fifo #(ibex_mem_intf_seq_item) item_collected_port;
uvm_tlm_analysis_fifo #(irq_seq_item) irq_collected_port;
`uvm_component_utils(core_ibex_base_test)
@ -28,6 +28,7 @@ class core_ibex_base_test extends uvm_test;
ibex_report_server = new();
uvm_report_server::set_server(ibex_report_server);
item_collected_port = new("item_collected_port_test", this);
irq_collected_port = new("irq_collected_port_test", this);
endfunction
virtual function void build_phase(uvm_phase phase);
@ -52,6 +53,9 @@ class core_ibex_base_test extends uvm_test;
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
env.data_if_slave_agent.monitor.item_collected_port.connect(this.item_collected_port.analysis_export);
if (cfg.enable_irq_seq) begin
env.irq_agent.monitor.irq_port.connect(this.irq_collected_port.analysis_export);
end
endfunction
virtual task run_phase(uvm_phase phase);
@ -165,7 +169,7 @@ class core_ibex_base_test extends uvm_test;
// Gets the next CORE_STATUS signature write and compares it against the provided core_status
// type, throws uvm_error on mismatch
virtual task check_next_core_status(core_status_t core_status, error_msg="");
virtual task check_next_core_status(core_status_t core_status, string error_msg="");
wait_for_mem_txn(cfg.signature_addr, CORE_STATUS);
signature_data = signature_data_q.pop_front();
if (signature_data != core_status) begin

View file

@ -61,17 +61,38 @@ class core_base_seq #(type REQ = uvm_sequence_item) extends uvm_sequence#(REQ);
endclass
// Interrupt sequence
class irq_seq extends core_base_seq#(irq_seq_item);
// Interrupt sequences
class irq_raise_single_seq extends core_base_seq#(irq_seq_item);
`uvm_object_utils(irq_seq)
`uvm_object_utils(irq_raise_single_seq)
`uvm_object_new
virtual task send_req();
irq_seq_item irq;
irq = irq_seq_item::type_id::create($sformatf("irq[%0d]", iteration_cnt));
irq = irq_seq_item::type_id::create($sformatf("irq_raise_single[%0d]", iteration_cnt));
start_item(irq);
`DV_CHECK_RANDOMIZE_FATAL(irq)
// TODO(udinator) - constrain irq_timer to 0 for now due to timer interrupt causing spike
// simulator to trap to irq handler
`DV_CHECK_RANDOMIZE_WITH_FATAL(irq, irq_timer==0;)
finish_item(irq);
get_response(irq);
endtask
endclass
// Irq sequence to deassert all interrupt lines, since Ibex interrupts are level sensitive
class irq_drop_seq extends core_base_seq#(irq_seq_item);
`uvm_object_utils(irq_drop_seq)
`uvm_object_new
// TODO(udinator) - for nested interrupt tests, test scenarios where a random number of interrupts
// are dropped
virtual task send_req();
irq_seq_item irq;
irq = irq_seq_item::type_id::create($sformatf("irq_drop[%0d]", iteration_cnt));
start_item(irq);
`DV_CHECK_RANDOMIZE_WITH_FATAL(irq, num_of_interrupt == 0;)
finish_item(irq);
get_response(irq);
endtask

View file

@ -37,6 +37,10 @@ class core_ibex_debug_intr_basic_test extends core_ibex_base_test;
`uvm_component_utils(core_ibex_debug_intr_basic_test)
`uvm_component_new
bit [ibex_mem_intf_agent_pkg::DATA_WIDTH-1:0] core_init_mstatus;
bit [ibex_mem_intf_agent_pkg::DATA_WIDTH-1:0] core_init_mie;
bit [$clog2(irq_agent_pkg::DATA_WIDTH)-1:0] irq_id;
virtual task send_stimulus();
fork
begin
@ -44,7 +48,7 @@ class core_ibex_debug_intr_basic_test extends core_ibex_base_test;
end
begin
if (cfg.require_signature_addr) begin
wait_for_core_status(INITIALIZED);
wait_for_core_setup();
end else begin
// If no signature_addr functionality is desired, then the test will simply wait for an
// adequate number of cycles
@ -52,13 +56,15 @@ class core_ibex_debug_intr_basic_test extends core_ibex_base_test;
end
fork
begin
if (cfg.enable_irq_stress_seq) begin
vseq.start_irq_stress_seq();
if (cfg.enable_irq_seq) begin
forever begin
send_irq_stimulus();
end
end
end
begin
if (cfg.enable_debug_stress_seq) begin
vseq.start_debug_stress_seq();
send_debug_stimulus();
end
end
join_none
@ -66,10 +72,119 @@ class core_ibex_debug_intr_basic_test extends core_ibex_base_test;
join_none
endtask
virtual task wait_for_core_setup();
wait_for_csr_write(CSR_MSTATUS);
core_init_mstatus = signature_data;
wait_for_csr_write(CSR_MIE);
core_init_mie = signature_data;
check_next_core_status(INITIALIZED, "Core initialization handshake failure");
endtask
// TODO(udi) - much of this checking logic is based on the current design only implementing
// MACHINE_MODE, the checking will have to be modified once USER_MODE is implemented and merged,
// e.g. need to also check mideleg for correct privilege mode context switch
virtual task send_irq_stimulus();
irq_seq_item irq_txn;
bit [irq_agent_pkg::DATA_WIDTH-1:0] irq;
bit [ibex_mem_intf_agent_pkg::DATA_WIDTH-1:0] mstatus;
bit [ibex_mem_intf_agent_pkg::DATA_WIDTH-1:0] mcause;
bit [ibex_mem_intf_agent_pkg::DATA_WIDTH-1:0] mip;
bit [ibex_mem_intf_agent_pkg::DATA_WIDTH-1:0] mie;
// send the interrupt
vseq.start_irq_single_seq();
irq_collected_port.get(irq_txn);
irq = {irq_txn.irq_nm, irq_txn.irq_fast, 4'b0, irq_txn.irq_external, 3'b0,
irq_txn.irq_timer, 3'b0, irq_txn.irq_software, 3'b0};
// Get the bit position of the highest priority interrupt - ibex will only handle this one if
// there are multiple irqs asserted at once
irq_id = get_max_irq_id(irq);
// If the interrupt is maskable, and the corresponding bit in MIE is not set, skip the next
// checks, as it means the interrupt in question is not enabled by Ibex, and drop the interrupt
// lines to avoid locking up the simulation
if (!irq_txn.irq_nm && !core_init_mie[irq_id]) begin
vseq.start_irq_drop_seq();
irq_collected_port.get(irq_txn);
irq = {irq_txn.irq_nm, irq_txn.irq_fast, 4'b0, irq_txn.irq_external, 3'b0,
irq_txn.irq_timer, 3'b0, irq_txn.irq_software, 3'b0};
`DV_CHECK_EQ_FATAL(irq, 0, "Interrupt lines have not been dropped")
return;
end
check_next_core_status(HANDLING_IRQ, "Core did not jump to vectored interrupt handler");
// check mstatus
wait_for_csr_write(CSR_MSTATUS);
mstatus = signature_data;
`DV_CHECK_EQ_FATAL(mstatus[12:11], PRIV_LVL_M, "Incorrect privilege mode")
`DV_CHECK_EQ_FATAL(mstatus[7], 1'b1, "mstatus.mpie was not set to 1'b1 after entering handler")
`DV_CHECK_EQ_FATAL(mstatus[3], 1'b0, "mstatus.mie was not set to 1'b0 after entering handler")
// check mcause against the interrupt id
wait_for_csr_write(CSR_MCAUSE);
mcause = signature_data;
// check that mcause.interrupt is set
`DV_CHECK_EQ_FATAL(mcause[ibex_mem_intf_agent_pkg::DATA_WIDTH-1], 1'b1,
"mcause.interrupt is not set to 1'b1")
// check that mcause.exception_code matches the current interrupt's ID
`DV_CHECK_EQ_FATAL(mcause[ibex_mem_intf_agent_pkg::DATA_WIDTH-2:0], irq_id,
"mcause.exception_code is encoding the wrong interrupt type")
// Wait for MIE and MIP to be written regardless of what interrupt ibex is dealing with, to
// prevent the case where MIP/MIE stays at 0 due to a nonmaskable interrupt, which will falsely
// trigger the following call of check_next_core_status()
wait_for_csr_write(CSR_MIE);
mie = signature_data;
wait_for_csr_write(CSR_MIP);
mip = signature_data;
// only check mip, and mie if the interrupt is not irq_nm, as Ibex's implementation of MIP and
// MIE CSRs do not contain a bit for irq_nm
if (!irq_txn.irq_nm) begin
// check that the proper bit in MIE is high
`DV_CHECK_EQ_FATAL(mie[irq_id], 1'b1,
$sformatf("mie[%0d] is not set, but core responded to corresponding interrupt", irq_id))
// check that the proper bit in MIP is high
`DV_CHECK_EQ_FATAL(mip[irq_id], 1'b1,
$sformatf("mip[%0d] is not set, but core responded to corresponding interrupt", irq_id))
end
// As Ibex interrupts are level sensitive, core must write to memory mapped address to
// indicate that irq stimulus be dropped
check_next_core_status(FINISHED_IRQ, "Core did not signal end of interrupt properly");
// Will receive irq_seq_item indicating that lines have been dropped
vseq.start_irq_drop_seq();
irq_collected_port.get(irq_txn);
irq = {irq_txn.irq_nm, irq_txn.irq_fast, 4'b0, irq_txn.irq_external, 3'b0,
irq_txn.irq_timer, 3'b0, irq_txn.irq_software, 3'b0};
`DV_CHECK_EQ_FATAL(irq, 0, "Interrupt lines have not been dropped")
wait (dut_vif.mret === 1'b1);
endtask
function int get_max_irq_id(bit [irq_agent_pkg::DATA_WIDTH-1:0] irq);
int i;
for (i = irq_agent_pkg::DATA_WIDTH-1; i >= 0; i = i - 1) begin
if (irq[i] === 1'b1) begin
return i;
break;
end
end
endfunction
// Basic debug stimulus check for Ibex for debug stimulus stress tests: check that Ibex enters
// debug mode properly after stimulus is sent and then check that a dret is encountered signifying
// the end of debug mode.
virtual task send_debug_stimulus();
fork
begin
vseq.start_debug_stress_seq();
end
begin
forever begin
check_next_core_status(IN_DEBUG_MODE, "Core did not enter debug mode properly");
wait(dut_vif.dret === 1'b1);
end
end
join_none
endtask
endclass
// Base class for directed debug and irq test scenarios
class core_ibex_directed_test extends core_ibex_base_test;
class core_ibex_directed_test extends core_ibex_debug_intr_basic_test;
`uvm_component_utils(core_ibex_directed_test)
`uvm_component_new
@ -84,20 +199,22 @@ class core_ibex_directed_test extends core_ibex_base_test;
clk_vif.wait_clks(stimulus_delay);
fork
begin
if (cfg.enable_irq_stress_seq) begin
vseq.start_irq_stress_seq();
if (cfg.enable_irq_seq) begin
forever begin
send_irq_stimulus();
end
end
end
begin
if (cfg.enable_debug_stress_seq) begin
vseq.start_debug_stress_seq();
send_debug_stimulus();
end
end
join_none
end else begin
// Wait for core initialization before starting the stimulus check loop - first write
// to signature address is guaranteed to be core initialization info
check_next_core_status(INITIALIZED, "Core initialization handshake failure");
wait_for_core_setup();
// Should be extended by derived classes.
// DO NOT use this test class directly.
check_stimulus();

View file

@ -11,8 +11,8 @@ 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_stress_h;
irq_seq irq_seq_single_h;
irq_raise_single_seq irq_single_seq_h;
irq_drop_seq irq_drop_seq_h;
debug_seq debug_seq_stress_h;
debug_seq debug_seq_single_h;
core_ibex_env_cfg cfg;
@ -25,17 +25,18 @@ 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_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_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;
if (cfg.enable_irq_seq) begin
irq_single_seq_h = irq_raise_single_seq::type_id::create("irq_seq_single_h");
irq_single_seq_h.num_of_iterations = 1;
irq_single_seq_h.max_interval = 1;
irq_single_seq_h.max_delay = 500;
irq_single_seq_h.interval = 0;
irq_drop_seq_h = irq_drop_seq::type_id::create("irq_drop_seq_h");
irq_drop_seq_h.num_of_iterations = 1;
irq_drop_seq_h.max_interval = 1;
irq_drop_seq_h.max_delay = 1;
irq_drop_seq_h.interval = 0;
end
if (cfg.enable_debug_stress_seq) begin
debug_seq_stress_h = debug_seq::type_id::create("debug_seq_stress_h");
@ -58,11 +59,9 @@ class core_ibex_vseq extends uvm_sequence;
endtask
virtual task stop();
if (cfg.enable_irq_stress_seq) begin
irq_seq_stress_h.stop();
end
if (cfg.enable_irq_single_seq) begin
irq_seq_single_h.stop();
if (cfg.enable_irq_seq) begin
irq_single_seq_h.stop();
irq_drop_seq_h.stop();
end
if (cfg.enable_debug_stress_seq) begin
debug_seq_stress_h.stop();
@ -82,12 +81,12 @@ class core_ibex_vseq extends uvm_sequence;
debug_seq_single_h.start(null);
endtask
virtual task start_irq_stress_seq();
irq_seq_stress_h.start(p_sequencer.irq_seqr);
virtual task start_irq_single_seq();
irq_single_seq_h.start(p_sequencer.irq_seqr);
endtask
virtual task start_irq_single_seq();
irq_seq_single_h.start(p_sequencer.irq_seqr);
virtual task start_irq_drop_seq();
irq_drop_seq_h.start(p_sequencer.irq_seqr);
endtask
endclass