mirror of
https://github.com/openhwgroup/cve2.git
synced 2025-04-22 13:07:46 -04:00
[ibex, dv] Added new base, interrupt, debug and mem error sequences
Added an independent base test with following capabilities: * chooses between single run, multiples runs or infinite runs (existing sequence does this via the `num_of_interations` variable). * interval between runs can be fixed or random, with 0 delay between runs possible. For random intervals there should be a way to bias them more towards 0 delay (e.g. specify 75% of delays should 0 with the rest randomly chosen). Added an interrupt sequence that inherits from the above base sequence. It has following capabilities: * chooses the number of interrupts to raise * specifies the interval between interrupt being raised and dropped * a mask to specify interrupts that shouldn't be raised. Added a debug sequence with the only functionality to specify the interval between the debug request being raised and dropped Added a sequence to corrupt instruction and data memory. Signed-off-by: Prajwala Puttappa <prajwalaputtappa@lowrisc.org>
This commit is contained in:
parent
c15f3b8888
commit
46c397501d
4 changed files with 250 additions and 2 deletions
227
dv/uvm/core_ibex/tests/core_ibex_new_seq_lib.sv
Normal file
227
dv/uvm/core_ibex/tests/core_ibex_new_seq_lib.sv
Normal file
|
@ -0,0 +1,227 @@
|
|||
typedef enum bit [1:0] {
|
||||
SingleRun, // Singl iteration
|
||||
InfiniteRuns, // Run forever until stop is specified
|
||||
MultipleRuns, // Multiple runs with configurable or randomizable iteration count
|
||||
InvalidRuns // Default state
|
||||
} run_type_e;
|
||||
|
||||
typedef enum bit [1:0] {
|
||||
IsideErr, // Inject error in instruction side memory.
|
||||
DsideErr, // Inject error in data side memory.
|
||||
PickErr // Pick which memory to inject error in.
|
||||
} error_type_e;
|
||||
|
||||
class core_base_new_seq #(type REQ = uvm_sequence_item) extends uvm_sequence #(REQ);
|
||||
// Default set to 50% for zero delay to be picked. Set to 100 if zero delay is required always.
|
||||
int unsigned zero_delay_pct = 50;
|
||||
rand bit zero_delays;
|
||||
rand int delay = 0;
|
||||
int unsigned iteration_cnt = 0;
|
||||
int unsigned max_delay = 500;
|
||||
virtual clk_rst_if clk_vif;
|
||||
bit stop_seq;
|
||||
bit seq_finished;
|
||||
rand run_type_e num_of_iterations = InvalidRuns;
|
||||
virtual core_ibex_dut_probe_if dut_vif;
|
||||
// Use this bit to start any unique sequence once
|
||||
bit start_seq = 0;
|
||||
|
||||
`uvm_object_param_utils(core_base_new_seq#(REQ))
|
||||
|
||||
function new (string name = "");
|
||||
super.new(name);
|
||||
if(!uvm_config_db#(virtual clk_rst_if)::get(null, "", "clk_if", clk_vif)) begin
|
||||
`uvm_fatal(get_full_name(), "Cannot get clk_if")
|
||||
end
|
||||
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
|
||||
endfunction
|
||||
|
||||
constraint zero_delays_c {
|
||||
zero_delays dist {1 :/ zero_delay_pct,
|
||||
0 :/ 100 - zero_delay_pct};
|
||||
}
|
||||
constraint reasonable_delay_c {
|
||||
delay inside {[0 : max_delay]};
|
||||
}
|
||||
|
||||
virtual task body();
|
||||
if(num_of_iterations == InvalidRuns) begin
|
||||
`DV_CHECK_MEMBER_RANDOMIZE_WITH_FATAL(num_of_iterations, num_of_iterations != InvalidRuns;)
|
||||
end
|
||||
`uvm_info(`gfn, $sformatf("Doing %s", num_of_iterations.name()), UVM_LOW)
|
||||
case (num_of_iterations)
|
||||
SingleRun: begin
|
||||
drive_stimulus(delay);
|
||||
end
|
||||
MultipleRuns: begin
|
||||
if(iteration_cnt == 0) begin
|
||||
`DV_CHECK_MEMBER_RANDOMIZE_WITH_FATAL(iteration_cnt,
|
||||
iteration_cnt > 0 && iteration_cnt <= 20; )
|
||||
end
|
||||
for (int i = 0; i <= iteration_cnt; i++) begin
|
||||
drive_stimulus(delay);
|
||||
end
|
||||
end
|
||||
InfiniteRuns: begin
|
||||
while (!stop_seq) begin
|
||||
drive_stimulus(delay);
|
||||
end
|
||||
seq_finished = 1'b1;
|
||||
end
|
||||
default: begin
|
||||
`uvm_fatal(`gfn, "Type of run not set")
|
||||
end
|
||||
endcase
|
||||
endtask: body
|
||||
|
||||
task drive_stimulus(int unsigned delay);
|
||||
if(delay == 0) begin
|
||||
`DV_CHECK_MEMBER_RANDOMIZE_FATAL(zero_delays)
|
||||
if(zero_delays) begin
|
||||
delay = 0;
|
||||
end else begin
|
||||
`DV_CHECK_MEMBER_RANDOMIZE_FATAL(delay)
|
||||
end
|
||||
end
|
||||
clk_vif.wait_clks(delay);
|
||||
`uvm_info(get_full_name(), "Starting sequence...", UVM_MEDIUM)
|
||||
send_req();
|
||||
`uvm_info(get_full_name(), "Exiting sequence", UVM_MEDIUM)
|
||||
endtask: drive_stimulus
|
||||
|
||||
virtual task send_req();
|
||||
`uvm_fatal(get_full_name(), "This task must be implemented in the extended class")
|
||||
endtask
|
||||
|
||||
virtual task stop();
|
||||
stop_seq = 1'b1;
|
||||
`uvm_info(get_full_name(), "Stopping sequence", UVM_MEDIUM)
|
||||
wait (seq_finished == 1'b1);
|
||||
endtask
|
||||
|
||||
endclass
|
||||
|
||||
class irq_new_seq extends core_base_new_seq #(irq_seq_item);
|
||||
|
||||
`uvm_object_utils(irq_new_seq)
|
||||
`uvm_object_new
|
||||
|
||||
bit no_nmi;
|
||||
bit no_fast;
|
||||
bit no_external;
|
||||
bit no_timer;
|
||||
bit no_software;
|
||||
int max_delay = 500;
|
||||
int min_delay = 50;
|
||||
|
||||
rand int interval = min_delay;
|
||||
|
||||
constraint reasonable_interval_c {
|
||||
interval inside {[min_delay : max_delay]};
|
||||
}
|
||||
|
||||
virtual task send_req();
|
||||
irq_seq_item irq;
|
||||
irq = irq_seq_item::type_id::create("irq");
|
||||
// Raise interrupts
|
||||
start_item(irq);
|
||||
`DV_CHECK_RANDOMIZE_WITH_FATAL(irq, num_of_interrupt > 1;
|
||||
if (no_nmi) {
|
||||
irq_nm == 0;
|
||||
}
|
||||
if (no_fast) {
|
||||
irq_fast == '0;
|
||||
}
|
||||
if (no_external) {
|
||||
irq_external == 0;
|
||||
}
|
||||
if (no_timer) {
|
||||
irq_timer == 0;
|
||||
}
|
||||
if (no_software) {
|
||||
irq_software == 0;
|
||||
})
|
||||
finish_item(irq);
|
||||
get_response(irq);
|
||||
`DV_CHECK_MEMBER_RANDOMIZE_FATAL(interval)
|
||||
clk_vif.wait_clks(interval);
|
||||
// Drop interrupts
|
||||
start_item(irq);
|
||||
`DV_CHECK_RANDOMIZE_WITH_FATAL(irq, num_of_interrupt == 0;)
|
||||
finish_item(irq);
|
||||
get_response(irq);
|
||||
endtask: send_req
|
||||
|
||||
endclass: irq_new_seq
|
||||
|
||||
// Simple debug sequence
|
||||
// debug_req is just a single bit sideband signal, use the interface to drive it directly
|
||||
class debug_new_seq extends core_base_new_seq#(irq_seq_item);
|
||||
|
||||
`uvm_object_utils(debug_new_seq)
|
||||
`uvm_object_new
|
||||
|
||||
int max_delay = 500;
|
||||
int min_delay = 75;
|
||||
rand int unsigned drop_delay = 0;
|
||||
|
||||
virtual task body();
|
||||
dut_vif.dut_cb.debug_req <= 1'b0;
|
||||
if(drop_delay == 0) begin
|
||||
`DV_CHECK_MEMBER_RANDOMIZE_WITH_FATAL(drop_delay,
|
||||
drop_delay inside {[min_delay : max_delay]};)
|
||||
end
|
||||
super.body();
|
||||
endtask
|
||||
|
||||
virtual task send_req();
|
||||
`uvm_info(get_full_name(), "Sending debug request", UVM_HIGH)
|
||||
dut_vif.dut_cb.debug_req <= 1'b1;
|
||||
clk_vif.wait_clks(drop_delay);
|
||||
dut_vif.dut_cb.debug_req <= 1'b0;
|
||||
endtask
|
||||
|
||||
endclass
|
||||
|
||||
class memory_error_seq extends core_base_new_seq#(irq_seq_item);
|
||||
core_ibex_vseq vseq;
|
||||
rand error_type_e err_type = PickErr;
|
||||
rand bit choose_side;
|
||||
|
||||
`uvm_object_utils(memory_error_seq)
|
||||
`uvm_declare_p_sequencer(core_ibex_vseqr)
|
||||
|
||||
function new (string name = "");
|
||||
super.new(name);
|
||||
vseq = core_ibex_vseq::type_id::create("vseq");
|
||||
endfunction
|
||||
|
||||
virtual task send_req();
|
||||
case (err_type)
|
||||
IsideErr: begin
|
||||
vseq.instr_intf_seq.inject_error();
|
||||
end
|
||||
DsideErr: begin
|
||||
vseq.data_intf_seq.inject_error();
|
||||
end
|
||||
PickErr: begin
|
||||
`DV_CHECK_STD_RANDOMIZE_FATAL(choose_side)
|
||||
if (choose_side) begin
|
||||
vseq.instr_intf_seq.inject_error();
|
||||
end else begin
|
||||
vseq.data_intf_seq.inject_error();
|
||||
end
|
||||
end
|
||||
default: begin
|
||||
// DO nothing
|
||||
end
|
||||
endcase
|
||||
if(!start_seq) begin
|
||||
vseq.start(p_sequencer);
|
||||
start_seq = 1;
|
||||
end
|
||||
endtask
|
||||
|
||||
endclass: memory_error_seq
|
|
@ -1399,3 +1399,18 @@ class core_ibex_invalid_csr_test extends core_ibex_directed_test;
|
|||
endtask
|
||||
|
||||
endclass
|
||||
|
||||
class core_mem_err_test extends core_ibex_directed_test;
|
||||
memory_error_seq memory_error_seq_h;
|
||||
|
||||
`uvm_component_utils(core_mem_err_test)
|
||||
`uvm_component_new
|
||||
|
||||
virtual task send_stimulus();
|
||||
memory_error_seq_h = memory_error_seq::type_id::create("memory_error_seq_h");
|
||||
memory_error_seq_h.vseq.cfg = cfg;
|
||||
memory_error_seq_h.vseq.mem = mem;
|
||||
memory_error_seq_h.start(env.vseqr);
|
||||
endtask: send_stimulus
|
||||
|
||||
endclass: core_mem_err_test
|
||||
|
|
|
@ -23,8 +23,11 @@ package core_ibex_test_pkg;
|
|||
bit [11:0] system_imm;
|
||||
} instr_t;
|
||||
|
||||
typedef class core_ibex_vseq;
|
||||
|
||||
`include "core_ibex_report_server.sv"
|
||||
`include "core_ibex_seq_lib.sv"
|
||||
`include "core_ibex_new_seq_lib.sv"
|
||||
`include "core_ibex_vseq.sv"
|
||||
`include "core_ibex_base_test.sv"
|
||||
`include "core_ibex_test_lib.sv"
|
||||
|
|
|
@ -22,12 +22,15 @@ class core_ibex_vseq extends uvm_sequence;
|
|||
|
||||
`uvm_object_utils(core_ibex_vseq)
|
||||
`uvm_declare_p_sequencer(core_ibex_vseqr)
|
||||
`uvm_object_new
|
||||
|
||||
virtual task body();
|
||||
function new (string name = "");
|
||||
super.new(name);
|
||||
instr_intf_seq = ibex_mem_intf_response_seq::type_id::create("instr_intf_seq");
|
||||
data_intf_seq = ibex_mem_intf_response_seq::type_id::create("data_intf_seq");
|
||||
data_intf_seq.is_dmem_seq = 1'b1;
|
||||
endfunction
|
||||
|
||||
virtual task body();
|
||||
if (cfg.enable_irq_single_seq) begin
|
||||
irq_raise_single_seq_h = irq_raise_single_seq::type_id::create("irq_single_seq_h");
|
||||
irq_raise_single_seq_h.num_of_iterations = 1;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue