[dv] Allow full IRQ randomisation

`no_nmi` in irq_raise_seq and irq_raise_single_seq would always cause an
NMI to be raised if it was set. This alters it to have the same
behaviour as `no_fast`. Setting `no_nmi` prevents an NMI from being
produced by the sequences, leaving it clears allows an NMI to be
produced but doesn't force it. This allows tests which can deal with NMI
along with other IRQs to fully randomise IRQs.

A new `irq_raise_nmi_seq` is provided for tests that specifically want
an NMI.
This commit is contained in:
Greg Chadwick 2021-03-18 14:19:09 +00:00
parent 5711d4fc15
commit f0a4042d6a
4 changed files with 52 additions and 4 deletions

View file

@ -6,6 +6,7 @@ class core_ibex_env_cfg extends uvm_object;
bit enable_irq_single_seq;
bit enable_irq_multiple_seq;
bit enable_irq_nmi_seq;
bit enable_nested_irq;
bit enable_debug_seq;
bit[31:0] max_interval;
@ -16,6 +17,7 @@ class core_ibex_env_cfg extends uvm_object;
`uvm_object_utils_begin(core_ibex_env_cfg)
`uvm_field_int(enable_irq_single_seq, UVM_DEFAULT)
`uvm_field_int(enable_irq_multiple_seq, UVM_DEFAULT)
`uvm_field_int(enable_irq_nmi_seq, UVM_DEFAULT)
`uvm_field_int(enable_nested_irq, UVM_DEFAULT)
`uvm_field_int(enable_debug_seq, UVM_DEFAULT)
`uvm_field_int(max_interval, UVM_DEFAULT)
@ -27,6 +29,7 @@ class core_ibex_env_cfg extends uvm_object;
super.new(name);
void'($value$plusargs("enable_irq_single_seq=%0d", enable_irq_single_seq));
void'($value$plusargs("enable_irq_multiple_seq=%0d", enable_irq_multiple_seq));
void'($value$plusargs("enable_irq_nmi_seq=%0d", enable_irq_nmi_seq));
void'($value$plusargs("enable_nested_irq=%0d", enable_nested_irq));
void'($value$plusargs("enable_debug_seq=%0d", enable_debug_seq));
void'($value$plusargs("max_interval=%0d", max_interval));

View file

@ -99,7 +99,9 @@ class irq_raise_seq extends irq_base_seq;
virtual function void randomize_item(irq_seq_item irq);
`DV_CHECK_RANDOMIZE_WITH_FATAL(irq, num_of_interrupt > 1;
irq_nm == ~no_nmi;
if (no_nmi) {
irq_nm == 0;
}
if (no_fast) {
irq_fast == '0;
})
@ -117,7 +119,9 @@ class irq_raise_single_seq extends irq_base_seq;
virtual function void randomize_item(irq_seq_item irq);
`DV_CHECK_RANDOMIZE_WITH_FATAL(irq, num_of_interrupt == 1;
irq_nm == ~no_nmi;
if (no_nmi) {
irq_nm == 0;
}
if (no_fast) {
irq_fast == '0;
})
@ -125,6 +129,18 @@ class irq_raise_single_seq extends irq_base_seq;
endclass
class irq_raise_nmi_seq extends irq_base_seq;
`uvm_object_utils(irq_raise_nmi_seq)
`uvm_object_new
virtual function void randomize_item(irq_seq_item irq);
`DV_CHECK_RANDOMIZE_WITH_FATAL(irq, num_of_interrupt == 1;
irq_nm == 1;)
endfunction
endclass
// Irq sequence to deassert all interrupt lines, since Ibex interrupts are level sensitive
class irq_drop_seq extends irq_base_seq;

View file

@ -211,10 +211,20 @@ class core_ibex_debug_intr_basic_test extends core_ibex_base_test;
virtual task send_irq_stimulus_start(input bit no_nmi,
input bit no_fast,
output bit ret_val);
bit irq_valid;
// send the interrupt
if (cfg.enable_irq_single_seq) vseq.start_irq_raise_single_seq(no_nmi, no_fast);
else if (cfg.enable_irq_multiple_seq) vseq.start_irq_raise_seq(no_nmi, no_fast);
send_irq_stimulus_inner(ret_val);
endtask
virtual task send_nmi_stimulus_start(output bit ret_val);
vseq.start_nmi_raise_seq();
send_irq_stimulus_inner(ret_val);
endtask
virtual task send_irq_stimulus_inner(output bit ret_val);
bit irq_valid;
irq_collected_port.get(irq_txn);
// Get the bit position of the highest priority interrupt - ibex will only handle this one if
// there are multiple irqs asserted at once.
@ -289,6 +299,12 @@ class core_ibex_debug_intr_basic_test extends core_ibex_base_test;
if (ret_val) send_irq_stimulus_end();
endtask
virtual task send_nmi_stimulus();
bit ret_val;
send_nmi_stimulus_start(ret_val);
if (ret_val) send_irq_stimulus_end();
endtask
function int get_max_valid_irq_id(bit [irq_agent_pkg::DATA_WIDTH-1:0] irq);
int i;
// Ibex implementation of MIE does not mask NM interrupts, so need to check this separately

View file

@ -13,6 +13,7 @@ class core_ibex_vseq extends uvm_sequence;
mem_model_pkg::mem_model mem;
irq_raise_seq irq_raise_seq_h;
irq_raise_single_seq irq_raise_single_seq_h;
irq_raise_nmi_seq irq_raise_nmi_seq_h;
irq_drop_seq irq_drop_seq_h;
debug_seq debug_seq_stress_h;
debug_seq debug_seq_single_h;
@ -41,7 +42,14 @@ class core_ibex_vseq extends uvm_sequence;
irq_raise_seq_h.max_delay = 500;
irq_raise_seq_h.interval = 0;
end
if (cfg.enable_irq_single_seq || cfg.enable_irq_multiple_seq) begin
if (cfg.enable_irq_nmi_seq) begin
irq_raise_nmi_seq_h = irq_raise_nmi_seq::type_id::create("irq_raise_nmi_seq_h");
irq_raise_nmi_seq_h.num_of_iterations = 1;
irq_raise_nmi_seq_h.max_interval = 1;
irq_raise_nmi_seq_h.max_delay = 500;
irq_raise_nmi_seq_h.interval = 0;
end
if (cfg.enable_irq_single_seq || cfg.enable_irq_multiple_seq || cfg.enable_irq_nmi_seq) begin
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;
@ -105,8 +113,13 @@ class core_ibex_vseq extends uvm_sequence;
irq_raise_seq_h.start(p_sequencer.irq_seqr);
endtask
virtual task start_nmi_raise_seq();
irq_raise_nmi_seq_h.start(p_sequencer.irq_seqr);
endtask
virtual task start_irq_drop_seq();
irq_drop_seq_h.start(p_sequencer.irq_seqr);
endtask
endclass