[dv/alert_handler] Add a direct sequence to enhance ping mechanism
This PR is based on issue #14556 where it is hard to hit the timing
corner case in the current mask setting.
To be able to cover this case faster, in block level I create a direct
sequence test to simulate the chip level scenario but force the
`wait_cyc_mask_i` to a much smaller value.
This will increase the chance of finding the corner case like issue #14556.
Signed-off-by: Cindy Chen <chencindy@opentitan.org>
diff --git a/hw/ip_templates/alert_handler/data/alert_handler_testplan.hjson b/hw/ip_templates/alert_handler/data/alert_handler_testplan.hjson
index 735c7a6..bda03db 100644
--- a/hw/ip_templates/alert_handler/data/alert_handler_testplan.hjson
+++ b/hw/ip_templates/alert_handler/data/alert_handler_testplan.hjson
@@ -128,6 +128,21 @@
stage: V2
tests: ["alert_handler_stress_all"]
}
+ {
+ name: alert_handler_entropy_stress_test
+ desc: '''
+ Stress the alert_handler's entropy request and make sure there is no spurious alert.
+
+ Stimulus:
+ - Randomly force the `wait_cyc_mask_i` to a legal value to stress the ping requests.
+ - Wait for all alerts at least being pinged for a few times.
+ Checks:
+ - Check alert_cause and loc_alert_cause registers to make sure there is no spurious
+ alert being fired.
+ '''
+ stage: V2
+ tests: ["alert_handler_entropy_stress"]
+ }
]
covergroups: [
diff --git a/hw/ip_templates/alert_handler/dv/alert_handler_sim_cfg.hjson.tpl b/hw/ip_templates/alert_handler/dv/alert_handler_sim_cfg.hjson.tpl
index 800cb22..07a712e 100644
--- a/hw/ip_templates/alert_handler/dv/alert_handler_sim_cfg.hjson.tpl
+++ b/hw/ip_templates/alert_handler/dv/alert_handler_sim_cfg.hjson.tpl
@@ -106,6 +106,15 @@
}
{
+ name: alert_handler_entropy_stress
+ uvm_test_seq: alert_handler_entropy_stress_vseq
+ // This sequence forces signal `wait_cyc_mask_i` to a much smaller value.
+ // So all the timings are not accurate and we need to disable the scb.
+ run_opts: ["+en_scb=0"]
+ reseed: 20
+ }
+
+ {
name: alert_handler_stress_all
run_opts: ["+test_timeout_ns=15_000_000_000"]
}
diff --git a/hw/ip_templates/alert_handler/dv/env/alert_handler_env.core b/hw/ip_templates/alert_handler/dv/env/alert_handler_env.core
index d5c9d89..d6db6f8 100644
--- a/hw/ip_templates/alert_handler/dv/env/alert_handler_env.core
+++ b/hw/ip_templates/alert_handler/dv/env/alert_handler_env.core
@@ -31,6 +31,7 @@
- seq_lib/alert_handler_ping_timeout_vseq.sv: {is_include_file: true}
- seq_lib/alert_handler_lpg_vseq.sv: {is_include_file: true}
- seq_lib/alert_handler_lpg_stub_clk_vseq.sv: {is_include_file: true}
+ - seq_lib/alert_handler_entropy_stress_vseq.sv: {is_include_file: true}
- seq_lib/alert_handler_stress_all_vseq.sv: {is_include_file: true}
file_type: systemVerilogSource
diff --git a/hw/ip_templates/alert_handler/dv/env/alert_handler_if.sv b/hw/ip_templates/alert_handler/dv/env/alert_handler_if.sv
index f582ee6..1cb36b8 100644
--- a/hw/ip_templates/alert_handler/dv/env/alert_handler_if.sv
+++ b/hw/ip_templates/alert_handler/dv/env/alert_handler_if.sv
@@ -41,4 +41,12 @@
NLpg, index))
end
endfunction
+
+ task automatic set_wait_cyc_mask(logic [PING_CNT_DW-1:0] val);
+ static logic [PING_CNT_DW-1:0] val_static;
+ begin
+ val_static = val;
+ force tb.dut.u_ping_timer.wait_cyc_mask_i = val_static;
+ end
+ endtask
endinterface
diff --git a/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv
index 7536525..8c414e2 100644
--- a/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv
+++ b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv
@@ -65,8 +65,8 @@
.value(loc_alert_class[i]));
endtask
- virtual task alert_handler_rand_wr_class_ctrl(bit [NUM_ALERT_CLASSES-1:0] lock_bit);
- bit [NUM_ALERT_CLASSES-1:0] class_en = $urandom();
+ virtual task alert_handler_rand_wr_class_ctrl(bit [NUM_ALERT_CLASSES-1:0] lock_bit,
+ bit [NUM_ALERT_CLASSES-1:0] class_en = $urandom());
if (class_en[0]) `RAND_WRITE_CLASS_CTRL(a, lock_bit[0])
if (class_en[1]) `RAND_WRITE_CLASS_CTRL(b, lock_bit[1])
if (class_en[2]) `RAND_WRITE_CLASS_CTRL(c, lock_bit[2])
@@ -343,7 +343,7 @@
endtask
// This task will response to all alert_ping
- virtual task run_alert_ping_rsp_seq_nonblocking(bit [NUM_ALERTS-1:0] alert_int_err);
+ virtual task run_alert_ping_rsp_seq_nonblocking(bit [NUM_ALERTS-1:0] alert_int_err = 0);
foreach (cfg.alert_host_cfg[i]) begin
automatic int index = i;
fork
diff --git a/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_entropy_stress_vseq.sv b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_entropy_stress_vseq.sv
new file mode 100644
index 0000000..400aff3
--- /dev/null
+++ b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_entropy_stress_vseq.sv
@@ -0,0 +1,97 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// This sequence uses a fixed setting to enable all alerts and locks them to class A.
+// Then enable all local alerts and locks them to class B.
+// Randomly force the `wait_cyc_mask_i` from design to a valid small number to fasten the ping
+// request mechanism.
+// Finally this sequence wait until alerts are pinged certain times.
+class alert_handler_entropy_stress_vseq extends alert_handler_smoke_vseq;
+ `uvm_object_utils(alert_handler_entropy_stress_vseq)
+
+ `uvm_object_new
+
+ rand bit [7:0] forced_mask_val;
+ rand int num_pings;
+
+ constraint valid_mask_val_c {
+ forced_mask_val >= 'h7;
+ $onehot(32'(forced_mask_val) + 1) == 1;
+ };
+
+ constraint num_pings_c {
+ if (forced_mask_val > 'hf0) {
+ num_pings inside {[1 : 2]};
+ } else {
+ num_pings inside {[1 : 3]};
+ }
+ }
+
+ virtual task pre_start();
+ `DV_CHECK_RANDOMIZE_FATAL(this)
+ cfg.alert_handler_vif.set_wait_cyc_mask(forced_mask_val);
+
+ foreach (cfg.alert_host_cfg[i]) begin
+ cfg.alert_host_cfg[i].alert_delay_max = 0;
+ cfg.alert_host_cfg[i].ping_delay_max = 0;
+ end
+ super.pre_start();
+ endtask
+
+ task body();
+ bit [NUM_LOCAL_ALERTS-1:0][NUM_ALERT_CLASSES-1:0] loc_alert_class;
+
+ foreach (loc_alert_class[i]) loc_alert_class[i] = 1;
+
+ `uvm_info(`gfn, "Test started", UVM_LOW)
+
+ run_esc_rsp_seq_nonblocking();
+ run_alert_ping_rsp_seq_nonblocking();
+
+ alert_handler_init(.intr_en('1), // Enable all interrupts
+ .alert_en('1), // Enable all alerts
+ .alert_class(0), // Set all alerts to class A
+ .loc_alert_en('1), // Enable all local alerts
+ .loc_alert_class(loc_alert_class)); // Set all local alerts to class B
+
+ // Enable all classes and lock them.
+ alert_handler_rand_wr_class_ctrl('1, '1);
+
+ // Enable ping timer.
+ csr_wr(.ptr(ral.ping_timer_en_shadowed), .value(1));
+
+ // Lock alerts and configurations.
+ alert_handler_wr_regwen_regs(.regwen(0),
+ .alert_regwen(0),
+ .loc_alert_regwen(0),
+ .ping_timer_regwen(0),
+ .class_regwen(0));
+
+ // Wait for all alerts to be pinged at least once.
+ fork begin : isolation_fork
+ int num_alerts = NUM_ALERTS;
+ for (int i = 0; i < NUM_ALERTS; i++) begin
+ automatic int index = i;
+ fork begin
+ repeat (num_pings) cfg.alert_host_cfg[index].vif.wait_alert_ping();
+ num_alerts--;
+ `uvm_info(`gfn, $sformatf("alert %0d received %0d ping request.\n %0d alerts remaining.",
+ index, num_pings, num_alerts), UVM_LOW);
+ end join_none
+ end
+ wait fork;
+ end join
+
+ cfg.clk_rst_vif.wait_clks($urandom_range(50, 500));
+
+ // Check no error or local alerts triggered.
+ foreach (ral.alert_cause[i]) begin
+ csr_rd_check(.ptr(ral.alert_cause[i]), .compare_value(0));
+ end
+ foreach (ral.loc_alert_cause[i]) begin
+ csr_rd_check(.ptr(ral.loc_alert_cause[i]), .compare_value(0));
+ end
+ endtask
+
+endclass : alert_handler_entropy_stress_vseq
diff --git a/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_vseq_list.sv b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_vseq_list.sv
index 0735ff8..0d67972 100644
--- a/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_vseq_list.sv
+++ b/hw/ip_templates/alert_handler/dv/env/seq_lib/alert_handler_vseq_list.sv
@@ -14,4 +14,5 @@
`include "alert_handler_ping_timeout_vseq.sv"
`include "alert_handler_lpg_vseq.sv"
`include "alert_handler_lpg_stub_clk_vseq.sv"
+`include "alert_handler_entropy_stress_vseq.sv"
`include "alert_handler_stress_all_vseq.sv"
diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/data/alert_handler_testplan.hjson b/hw/top_earlgrey/ip_autogen/alert_handler/data/alert_handler_testplan.hjson
index 735c7a6..bda03db 100644
--- a/hw/top_earlgrey/ip_autogen/alert_handler/data/alert_handler_testplan.hjson
+++ b/hw/top_earlgrey/ip_autogen/alert_handler/data/alert_handler_testplan.hjson
@@ -128,6 +128,21 @@
stage: V2
tests: ["alert_handler_stress_all"]
}
+ {
+ name: alert_handler_entropy_stress_test
+ desc: '''
+ Stress the alert_handler's entropy request and make sure there is no spurious alert.
+
+ Stimulus:
+ - Randomly force the `wait_cyc_mask_i` to a legal value to stress the ping requests.
+ - Wait for all alerts at least being pinged for a few times.
+ Checks:
+ - Check alert_cause and loc_alert_cause registers to make sure there is no spurious
+ alert being fired.
+ '''
+ stage: V2
+ tests: ["alert_handler_entropy_stress"]
+ }
]
covergroups: [
diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/alert_handler_sim_cfg.hjson b/hw/top_earlgrey/ip_autogen/alert_handler/dv/alert_handler_sim_cfg.hjson
index a38a4f0..b64cf1d 100644
--- a/hw/top_earlgrey/ip_autogen/alert_handler/dv/alert_handler_sim_cfg.hjson
+++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/alert_handler_sim_cfg.hjson
@@ -106,6 +106,15 @@
}
{
+ name: alert_handler_entropy_stress
+ uvm_test_seq: alert_handler_entropy_stress_vseq
+ // This sequence forces signal `wait_cyc_mask_i` to a much smaller value.
+ // So all the timings are not accurate and we need to disable the scb.
+ run_opts: ["+en_scb=0"]
+ reseed: 20
+ }
+
+ {
name: alert_handler_stress_all
run_opts: ["+test_timeout_ns=15_000_000_000"]
}
diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_env.core b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_env.core
index d5c9d89..d6db6f8 100644
--- a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_env.core
+++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_env.core
@@ -31,6 +31,7 @@
- seq_lib/alert_handler_ping_timeout_vseq.sv: {is_include_file: true}
- seq_lib/alert_handler_lpg_vseq.sv: {is_include_file: true}
- seq_lib/alert_handler_lpg_stub_clk_vseq.sv: {is_include_file: true}
+ - seq_lib/alert_handler_entropy_stress_vseq.sv: {is_include_file: true}
- seq_lib/alert_handler_stress_all_vseq.sv: {is_include_file: true}
file_type: systemVerilogSource
diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_if.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_if.sv
index f582ee6..1cb36b8 100644
--- a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_if.sv
+++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/alert_handler_if.sv
@@ -41,4 +41,12 @@
NLpg, index))
end
endfunction
+
+ task automatic set_wait_cyc_mask(logic [PING_CNT_DW-1:0] val);
+ static logic [PING_CNT_DW-1:0] val_static;
+ begin
+ val_static = val;
+ force tb.dut.u_ping_timer.wait_cyc_mask_i = val_static;
+ end
+ endtask
endinterface
diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv
index 7536525..8c414e2 100644
--- a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv
+++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_base_vseq.sv
@@ -65,8 +65,8 @@
.value(loc_alert_class[i]));
endtask
- virtual task alert_handler_rand_wr_class_ctrl(bit [NUM_ALERT_CLASSES-1:0] lock_bit);
- bit [NUM_ALERT_CLASSES-1:0] class_en = $urandom();
+ virtual task alert_handler_rand_wr_class_ctrl(bit [NUM_ALERT_CLASSES-1:0] lock_bit,
+ bit [NUM_ALERT_CLASSES-1:0] class_en = $urandom());
if (class_en[0]) `RAND_WRITE_CLASS_CTRL(a, lock_bit[0])
if (class_en[1]) `RAND_WRITE_CLASS_CTRL(b, lock_bit[1])
if (class_en[2]) `RAND_WRITE_CLASS_CTRL(c, lock_bit[2])
@@ -343,7 +343,7 @@
endtask
// This task will response to all alert_ping
- virtual task run_alert_ping_rsp_seq_nonblocking(bit [NUM_ALERTS-1:0] alert_int_err);
+ virtual task run_alert_ping_rsp_seq_nonblocking(bit [NUM_ALERTS-1:0] alert_int_err = 0);
foreach (cfg.alert_host_cfg[i]) begin
automatic int index = i;
fork
diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_entropy_stress_vseq.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_entropy_stress_vseq.sv
new file mode 100644
index 0000000..400aff3
--- /dev/null
+++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_entropy_stress_vseq.sv
@@ -0,0 +1,97 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// This sequence uses a fixed setting to enable all alerts and locks them to class A.
+// Then enable all local alerts and locks them to class B.
+// Randomly force the `wait_cyc_mask_i` from design to a valid small number to fasten the ping
+// request mechanism.
+// Finally this sequence wait until alerts are pinged certain times.
+class alert_handler_entropy_stress_vseq extends alert_handler_smoke_vseq;
+ `uvm_object_utils(alert_handler_entropy_stress_vseq)
+
+ `uvm_object_new
+
+ rand bit [7:0] forced_mask_val;
+ rand int num_pings;
+
+ constraint valid_mask_val_c {
+ forced_mask_val >= 'h7;
+ $onehot(32'(forced_mask_val) + 1) == 1;
+ };
+
+ constraint num_pings_c {
+ if (forced_mask_val > 'hf0) {
+ num_pings inside {[1 : 2]};
+ } else {
+ num_pings inside {[1 : 3]};
+ }
+ }
+
+ virtual task pre_start();
+ `DV_CHECK_RANDOMIZE_FATAL(this)
+ cfg.alert_handler_vif.set_wait_cyc_mask(forced_mask_val);
+
+ foreach (cfg.alert_host_cfg[i]) begin
+ cfg.alert_host_cfg[i].alert_delay_max = 0;
+ cfg.alert_host_cfg[i].ping_delay_max = 0;
+ end
+ super.pre_start();
+ endtask
+
+ task body();
+ bit [NUM_LOCAL_ALERTS-1:0][NUM_ALERT_CLASSES-1:0] loc_alert_class;
+
+ foreach (loc_alert_class[i]) loc_alert_class[i] = 1;
+
+ `uvm_info(`gfn, "Test started", UVM_LOW)
+
+ run_esc_rsp_seq_nonblocking();
+ run_alert_ping_rsp_seq_nonblocking();
+
+ alert_handler_init(.intr_en('1), // Enable all interrupts
+ .alert_en('1), // Enable all alerts
+ .alert_class(0), // Set all alerts to class A
+ .loc_alert_en('1), // Enable all local alerts
+ .loc_alert_class(loc_alert_class)); // Set all local alerts to class B
+
+ // Enable all classes and lock them.
+ alert_handler_rand_wr_class_ctrl('1, '1);
+
+ // Enable ping timer.
+ csr_wr(.ptr(ral.ping_timer_en_shadowed), .value(1));
+
+ // Lock alerts and configurations.
+ alert_handler_wr_regwen_regs(.regwen(0),
+ .alert_regwen(0),
+ .loc_alert_regwen(0),
+ .ping_timer_regwen(0),
+ .class_regwen(0));
+
+ // Wait for all alerts to be pinged at least once.
+ fork begin : isolation_fork
+ int num_alerts = NUM_ALERTS;
+ for (int i = 0; i < NUM_ALERTS; i++) begin
+ automatic int index = i;
+ fork begin
+ repeat (num_pings) cfg.alert_host_cfg[index].vif.wait_alert_ping();
+ num_alerts--;
+ `uvm_info(`gfn, $sformatf("alert %0d received %0d ping request.\n %0d alerts remaining.",
+ index, num_pings, num_alerts), UVM_LOW);
+ end join_none
+ end
+ wait fork;
+ end join
+
+ cfg.clk_rst_vif.wait_clks($urandom_range(50, 500));
+
+ // Check no error or local alerts triggered.
+ foreach (ral.alert_cause[i]) begin
+ csr_rd_check(.ptr(ral.alert_cause[i]), .compare_value(0));
+ end
+ foreach (ral.loc_alert_cause[i]) begin
+ csr_rd_check(.ptr(ral.loc_alert_cause[i]), .compare_value(0));
+ end
+ endtask
+
+endclass : alert_handler_entropy_stress_vseq
diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_vseq_list.sv b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_vseq_list.sv
index 0735ff8..0d67972 100644
--- a/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_vseq_list.sv
+++ b/hw/top_earlgrey/ip_autogen/alert_handler/dv/env/seq_lib/alert_handler_vseq_list.sv
@@ -14,4 +14,5 @@
`include "alert_handler_ping_timeout_vseq.sv"
`include "alert_handler_lpg_vseq.sv"
`include "alert_handler_lpg_stub_clk_vseq.sv"
+`include "alert_handler_entropy_stress_vseq.sv"
`include "alert_handler_stress_all_vseq.sv"