[dv/alert] Add fatal alert check if scb is disabled
This PR addes a fatal alert check (check if fatal alert continuously
triggered until reset in a nonblocking task).
This can be used in aes shadow reg tests and keymgr tests where the scb
is disabled.
Signed-off-by: Cindy Chen <chencindy@google.com>
diff --git a/hw/dv/sv/alert_esc_agent/alert_esc_agent_pkg.sv b/hw/dv/sv/alert_esc_agent/alert_esc_agent_pkg.sv
index 0d65ccc..811aa96 100644
--- a/hw/dv/sv/alert_esc_agent/alert_esc_agent_pkg.sv
+++ b/hw/dv/sv/alert_esc_agent/alert_esc_agent_pkg.sv
@@ -10,6 +10,10 @@
import prim_alert_pkg::*;
import prim_esc_pkg::*;
+ // 2 clock cycles between two alert handshakes, 1 clock cycle to go back to `Idle` state,
+ // 1 clock cycle for monitor to detect alert.
+ parameter uint ALERT_B2B_DELAY = 4;
+
typedef class alert_esc_seq_item;
typedef class alert_esc_agent_cfg;
diff --git a/hw/dv/sv/alert_esc_agent/alert_esc_if.sv b/hw/dv/sv/alert_esc_agent/alert_esc_if.sv
index fb5a0cd..dc550f3 100644
--- a/hw/dv/sv/alert_esc_agent/alert_esc_if.sv
+++ b/hw/dv/sv/alert_esc_agent/alert_esc_if.sv
@@ -79,6 +79,11 @@
input esc_rx;
endclocking
+ assign alert_tx = (if_mode == dv_utils_pkg::Host && is_alert) ? alert_tx_int : 'z;
+ assign alert_rx = (if_mode == dv_utils_pkg::Device && is_alert) ? alert_rx_int : 'z;
+ assign esc_tx = (if_mode == dv_utils_pkg::Host && !is_alert) ? esc_tx_int : 'z;
+ assign esc_rx = (if_mode == dv_utils_pkg::Device && !is_alert) ? esc_rx_int : 'z;
+
task automatic wait_ack_complete();
while (alert_tx_final.alert_p === 1'b1) @(monitor_cb);
while (alert_rx_final.ack_p === 1'b1) @(monitor_cb);
@@ -92,11 +97,6 @@
get_alert = (alert_tx_final.alert_p === 1'b1 && alert_tx_final.alert_n === 1'b0);
endfunction : get_alert
- assign alert_tx = (if_mode == dv_utils_pkg::Host && is_alert) ? alert_tx_int : 'z;
- assign alert_rx = (if_mode == dv_utils_pkg::Device && is_alert) ? alert_rx_int : 'z;
- assign esc_tx = (if_mode == dv_utils_pkg::Host && !is_alert) ? esc_tx_int : 'z;
- assign esc_rx = (if_mode == dv_utils_pkg::Device && !is_alert) ? esc_rx_int : 'z;
-
// this task wait for alert_ping request.
// alert_ping request is detected by level triggered "alert_rx.ping_p/n" signals pairs
// and no sig_int_err
diff --git a/hw/dv/sv/cip_lib/cip_base_scoreboard.sv b/hw/dv/sv/cip_lib/cip_base_scoreboard.sv
index 12f419e..f44de00 100644
--- a/hw/dv/sv/cip_lib/cip_base_scoreboard.sv
+++ b/hw/dv/sv/cip_lib/cip_base_scoreboard.sv
@@ -155,9 +155,8 @@
endtask
virtual task check_alert_triggered(string alert_name);
- // 2 clock cycles between two alert handshakes, 1 clock cycle to go back to `Idle` state,
- // 1 clock cycle for monitor to detect alert, 1 negedge edge to make sure no race condition.
- repeat(5 + alert_chk_max_delay[alert_name]) begin
+ // Add 1 extra negedge edge clock to make sure no race condition.
+ repeat(alert_esc_agent_pkg::ALERT_B2B_DELAY + 1 + alert_chk_max_delay[alert_name]) begin
cfg.clk_rst_vif.wait_n_clks(1);
if (under_alert_handshake[alert_name] || cfg.under_reset) return;
end
diff --git a/hw/dv/sv/cip_lib/cip_base_vseq.sv b/hw/dv/sv/cip_lib/cip_base_vseq.sv
index 3b2f710..d658e0b 100644
--- a/hw/dv/sv/cip_lib/cip_base_vseq.sv
+++ b/hw/dv/sv/cip_lib/cip_base_vseq.sv
@@ -645,6 +645,23 @@
gen_storage_err_val = gen_storage_err_val << shift_bits >> shift_bits;
endfunction
+ virtual task check_fatal_alert_nonblocking(string alert_name);
+ fork
+ `DV_SPINWAIT_EXIT(
+ forever begin
+ // 1 extra cycle to make sure no race condition
+ repeat(alert_esc_agent_pkg::ALERT_B2B_DELAY + 1) begin
+ cfg.clk_rst_vif.wait_n_clks(1);
+ if (cfg.m_alert_agent_cfg[alert_name].vif.get_alert() == 1) break;
+ end
+ `DV_CHECK_EQ(cfg.m_alert_agent_cfg[alert_name].vif.get_alert(), 1,
+ $sformatf("fatal error %0s does not trigger!", alert_name))
+ cfg.m_alert_agent_cfg[alert_name].vif.wait_ack_complete();
+ end,
+ wait(cfg.under_reset);)
+ join_none
+ endtask
+
virtual task run_shadow_reg_errors(int num_times);
csr_excl_item csr_excl = add_and_return_csr_excl("csr_excl");
dv_base_reg shadowed_csrs[$], test_csrs[$];
@@ -731,22 +748,28 @@
if (has_storage_error && do_lock_shadow_reg) begin
shadowed_csrs[index].lock_shadow_reg();
+ check_fatal_alert_nonblocking(alert_name);
+
+ // Wait two clock cycles then backdoor write back original value.
+ // This won't stop fatal alert from firing.
+ cfg.clk_rst_vif.wait_clks(2);
+ csr_poke(.csr(shadowed_csrs[index]), .value(origin_val), .kind(kind), .predict(1));
+ end else begin
+ `DV_CHECK_EQ(has_storage_error, 1,
+ "dv_base_reg did not predict shadow storage error");
+ `DV_SPINWAIT(while (!cfg.m_alert_agent_cfg[alert_name].vif.get_alert())
+ cfg.clk_rst_vif.wait_clks(1);,
+ $sformatf("%0s shadow_reg storage_err alert not detected",
+ shadowed_csrs[index].get_name()));
+
+ // backdoor write back original value to avoid alert keep firing
+ csr_poke(.csr(shadowed_csrs[index]), .value(origin_val), .kind(kind), .predict(1));
+ `DV_SPINWAIT(cfg.m_alert_agent_cfg[alert_name].vif.wait_ack_complete();,
+ $sformatf("timeout for alert:%0s", alert_name))
+
+ // wait at least two clock cycle between alert_handshakes
+ cfg.clk_rst_vif.wait_clks(2);
end
-
- `DV_CHECK_EQ(has_storage_error, 1,
- "dv_base_reg did not predict shadow storage error");
- `DV_SPINWAIT(while (!cfg.m_alert_agent_cfg[alert_name].vif.get_alert())
- cfg.clk_rst_vif.wait_clks(1);,
- $sformatf("%0s shadow_reg storage_err alert not detected",
- shadowed_csrs[index].get_name()));
-
- // backdoor write back original value to avoid alert keep firing
- csr_poke(.csr(shadowed_csrs[index]), .value(origin_val), .kind(kind), .predict(1));
- `DV_SPINWAIT(cfg.m_alert_agent_cfg[alert_name].vif.wait_ack_complete();,
- $sformatf("timeout for alert:%0s", alert_name))
-
- // wait at least two clock cycle between alert_handshakes
- cfg.clk_rst_vif.wait_clks(2);
end
end
end
diff --git a/hw/ip/keymgr/dv/env/seq_lib/keymgr_cmd_invalid_vseq.sv b/hw/ip/keymgr/dv/env/seq_lib/keymgr_cmd_invalid_vseq.sv
index 1d65871..dc9de94 100644
--- a/hw/ip/keymgr/dv/env/seq_lib/keymgr_cmd_invalid_vseq.sv
+++ b/hw/ip/keymgr/dv/env/seq_lib/keymgr_cmd_invalid_vseq.sv
@@ -23,7 +23,12 @@
keymgr_operations(.clr_output(0), .wait_done(0));
end
- repeat (100) @(cfg.m_alert_agent_cfg["fatal_fault_err"].vif.alert_tx.alert_p);
+ // could not accurately predict when first fatal alert happen, so wait for the first fatal
+ // alert to trigger
+ wait(cfg.m_alert_agent_cfg["fatal_fault_err"].vif.alert_tx_final.alert_p);
+ check_fatal_alert_nonblocking("fatal_fault_err");
+
+ cfg.clk_rst_vif.wait_clks($urandom_range(1, 500));
csr_rd_check(.ptr(ral.working_state), .compare_value(keymgr_pkg::StDisabled));
endtask : trigger_error