[dv] Update countermeasure verification
1. update prim_count_if to force on the actual storage
2. add cfg.sec_cm_alert_name for sec alert
3. split sec_cm_bind to multiple bind files as we can only bind the
prim_*_if when the design uses the prim
4. update keymgr for above changes
Signed-off-by: Weicai Yang <weicai@google.com>
diff --git a/hw/dv/sv/cip_lib/cip_base_env_cfg.sv b/hw/dv/sv/cip_lib/cip_base_env_cfg.sv
index 469d24f..0c87be8 100644
--- a/hw/dv/sv/cip_lib/cip_base_env_cfg.sv
+++ b/hw/dv/sv/cip_lib/cip_base_env_cfg.sv
@@ -13,6 +13,7 @@
// Override this alert name at `initialize` if it's not as below
string tl_intg_alert_name = "fatal_fault";
+ string sec_cm_alert_name = "fatal_fault";
// If there is a bit in an "alert cause" register that will be set by a corrupt bus access, this
// should be the name of that field (with syntax "reg.field"). Used by cip_base_scoreboard to
diff --git a/hw/dv/sv/cip_lib/seq_lib/cip_base_vseq__sec_cm_fi.svh b/hw/dv/sv/cip_lib/seq_lib/cip_base_vseq__sec_cm_fi.svh
index 663758a..f18c02c 100644
--- a/hw/dv/sv/cip_lib/seq_lib/cip_base_vseq__sec_cm_fi.svh
+++ b/hw/dv/sv/cip_lib/seq_lib/cip_base_vseq__sec_cm_fi.svh
@@ -25,12 +25,9 @@
// - Verify any operations that follow fail (as applicable).
// refer to ip/keymgr/dv/env/seq_lib/keymgr_common_vseq.sv as an example
virtual task check_sec_cm_fi_resp(sec_cm_base_if_proxy if_proxy);
- // TODO, it's better to unify these to one alert
- string sec_cm_alert_name = cfg.tl_intg_alert_name;
-
- `DV_CHECK_FATAL(sec_cm_alert_name inside {cfg.list_of_alerts},
+ `DV_CHECK_FATAL(cfg.sec_cm_alert_name inside {cfg.list_of_alerts},
$sformatf("sec_cm_alert_name (%s) is not inside %p",
- sec_cm_alert_name, cfg.list_of_alerts))
+ cfg.sec_cm_alert_name, cfg.list_of_alerts))
`uvm_info(`gfn, $sformatf("expected fatal alert is triggered for %s", if_proxy.sec_cm_type.name),
UVM_LOW)
@@ -38,7 +35,7 @@
// This is a fatal alert and design keeps sending it until reset is issued.
// Check alerts are triggered for a few times
repeat (5) begin
- wait_alert_trigger(sec_cm_alert_name, .wait_complete(1));
+ wait_alert_trigger(cfg.sec_cm_alert_name, .wait_complete(1));
end
endtask : check_sec_cm_fi_resp
diff --git a/hw/dv/sv/sec_cm/prim_count_if.sv b/hw/dv/sv/sec_cm/prim_count_if.sv
index e540ed4..97c145e 100644
--- a/hw/dv/sv/sec_cm/prim_count_if.sv
+++ b/hw/dv/sv/sec_cm/prim_count_if.sv
@@ -18,7 +18,8 @@
prim_count_pkg::prim_count_style_e cnt_style = CntStyle;
string path = dv_utils_pkg::get_parent_hier($sformatf("%m"));
- string signal_forced;
+ string signal_forced = $sformatf("%s.gen_cnts[0].u_cnt_flop.gen_generic.u_impl_generic.q_o",
+ path);
class prim_count_if_proxy extends sec_cm_pkg::sec_cm_base_if_proxy;
`uvm_object_new
@@ -46,13 +47,7 @@
endclass
prim_count_if_proxy if_proxy;
-
initial begin
- case (cnt_style)
- prim_count_pkg::CrossCnt: signal_forced = $sformatf("%s.up_cnt_q", path);
- prim_count_pkg::DupCnt: signal_forced = $sformatf("%s.up_cnt_q[0]", path);
- default: `uvm_fatal(msg_id, $sformatf("unsupported style %s", cnt_style.name()))
- endcase
`DV_CHECK_FATAL(uvm_hdl_check_path(signal_forced), , msg_id)
// Store the proxy object for TB to use
diff --git a/hw/dv/sv/sec_cm/sec_cm.core b/hw/dv/sv/sec_cm/sec_cm.core
index 299f023..52c86b6 100644
--- a/hw/dv/sv/sec_cm/sec_cm.core
+++ b/hw/dv/sv/sec_cm/sec_cm.core
@@ -17,7 +17,6 @@
- sec_cm_base_if_proxy.sv: {is_include_file: true}
- prim_count_if.sv
- prim_sparse_fsm_flop_if.sv
- - sec_cm_bind.sv
file_type: systemVerilogSource
targets:
diff --git a/hw/dv/sv/sec_cm/sec_cm_prim_count_bind.core b/hw/dv/sv/sec_cm/sec_cm_prim_count_bind.core
new file mode 100644
index 0000000..cceece0
--- /dev/null
+++ b/hw/dv/sv/sec_cm/sec_cm_prim_count_bind.core
@@ -0,0 +1,19 @@
+CAPI=2:
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+name: "lowrisc:dv:sec_cm_prim_count_bind"
+description: "Common bind file for testing prim_count countermeasures"
+
+filesets:
+ files_dv:
+ depend:
+ - lowrisc:prim:count
+ files:
+ - sec_cm_prim_count_bind.sv
+ file_type: systemVerilogSource
+
+targets:
+ default:
+ filesets:
+ - files_dv
diff --git a/hw/dv/sv/sec_cm/sec_cm_bind.sv b/hw/dv/sv/sec_cm/sec_cm_prim_count_bind.sv
similarity index 65%
copy from hw/dv/sv/sec_cm/sec_cm_bind.sv
copy to hw/dv/sv/sec_cm/sec_cm_prim_count_bind.sv
index b0d8820..8454cbd 100644
--- a/hw/dv/sv/sec_cm/sec_cm_bind.sv
+++ b/hw/dv/sv/sec_cm/sec_cm_prim_count_bind.sv
@@ -2,9 +2,6 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
-module sec_cm_bind();
+module sec_cm_prim_count_bind();
bind prim_count prim_count_if #(.CntStyle(CntStyle), .Width(Width)) u_prim_count_if (.*);
-
- bind prim_sparse_fsm_flop prim_sparse_fsm_flop_if #(
- .Width(Width)) u_prim_sparse_fsm_flop_if (.*);
endmodule
diff --git a/hw/dv/sv/sec_cm/sec_cm_prim_sparse_fsm_flop_bind.core b/hw/dv/sv/sec_cm/sec_cm_prim_sparse_fsm_flop_bind.core
new file mode 100644
index 0000000..02a5f8a
--- /dev/null
+++ b/hw/dv/sv/sec_cm/sec_cm_prim_sparse_fsm_flop_bind.core
@@ -0,0 +1,19 @@
+CAPI=2:
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+name: "lowrisc:dv:sec_cm_prim_sparse_fsm_flop_bind"
+description: "Common bind file for testing sparse_fsm countermeasures"
+
+filesets:
+ files_dv:
+ depend:
+ - lowrisc:prim:sparse_fsm
+ files:
+ - sec_cm_prim_sparse_fsm_flop_bind.sv
+ file_type: systemVerilogSource
+
+targets:
+ default:
+ filesets:
+ - files_dv
diff --git a/hw/dv/sv/sec_cm/sec_cm_bind.sv b/hw/dv/sv/sec_cm/sec_cm_prim_sparse_fsm_flop_bind.sv
similarity index 70%
rename from hw/dv/sv/sec_cm/sec_cm_bind.sv
rename to hw/dv/sv/sec_cm/sec_cm_prim_sparse_fsm_flop_bind.sv
index b0d8820..7bc15ae 100644
--- a/hw/dv/sv/sec_cm/sec_cm_bind.sv
+++ b/hw/dv/sv/sec_cm/sec_cm_prim_sparse_fsm_flop_bind.sv
@@ -2,9 +2,7 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
-module sec_cm_bind();
- bind prim_count prim_count_if #(.CntStyle(CntStyle), .Width(Width)) u_prim_count_if (.*);
-
+module sec_cm_prim_sparse_fsm_flop_bind();
bind prim_sparse_fsm_flop prim_sparse_fsm_flop_if #(
.Width(Width)) u_prim_sparse_fsm_flop_if (.*);
endmodule
diff --git a/hw/ip/keymgr/dv/env/keymgr_env_cfg.sv b/hw/ip/keymgr/dv/env/keymgr_env_cfg.sv
index 2c42fa7..1089672 100644
--- a/hw/ip/keymgr/dv/env/keymgr_env_cfg.sv
+++ b/hw/ip/keymgr/dv/env/keymgr_env_cfg.sv
@@ -17,6 +17,7 @@
virtual function void initialize(bit [31:0] csr_base_addr = '1);
list_of_alerts = keymgr_env_pkg::LIST_OF_ALERTS;
tl_intg_alert_name = "fatal_fault_err";
+ sec_cm_alert_name = tl_intg_alert_name;
num_edn = 1;
has_shadowed_regs = 1;
super.initialize(csr_base_addr);
diff --git a/hw/ip/keymgr/dv/keymgr_sim.core b/hw/ip/keymgr/dv/keymgr_sim.core
index 3bd7d8f..2e405b4 100644
--- a/hw/ip/keymgr/dv/keymgr_sim.core
+++ b/hw/ip/keymgr/dv/keymgr_sim.core
@@ -8,6 +8,8 @@
files_rtl:
depend:
- lowrisc:ip:keymgr
+ - lowrisc:dv:sec_cm_prim_count_bind
+ - lowrisc:dv:sec_cm_prim_sparse_fsm_flop_bind
files_dv:
depend:
diff --git a/hw/ip/keymgr/dv/keymgr_sim_cfg.hjson b/hw/ip/keymgr/dv/keymgr_sim_cfg.hjson
index c5b9c6a..abc3972 100644
--- a/hw/ip/keymgr/dv/keymgr_sim_cfg.hjson
+++ b/hw/ip/keymgr/dv/keymgr_sim_cfg.hjson
@@ -38,7 +38,7 @@
]
// Add additional tops for simulation.
- sim_tops: ["keymgr_bind", "sec_cm_bind"]
+ sim_tops: ["keymgr_bind", "sec_cm_prim_count_bind", "sec_cm_prim_sparse_fsm_flop_bind"]
// Default iterations for all tests - each test entry can override this.
reseed: 50
diff --git a/hw/ip/prim/rtl/prim_count.sv b/hw/ip/prim/rtl/prim_count.sv
index bf7e5f4..09b8c1d 100644
--- a/hw/ip/prim/rtl/prim_count.sv
+++ b/hw/ip/prim/rtl/prim_count.sv
@@ -180,24 +180,28 @@
// Clear and set should not be seen at the same time
`ASSUME(SimulClrSet_A, clr_i || set_i |-> clr_i != set_i)
- `ASSERT(OutClr_A, clr_i |=> OutSelDnCnt ? &cnt_o : cnt_o == 0)
+ // when the counter is forced by TB, it can be any value, but we should see err_o is set.
+ `ASSERT(OutClr_A, clr_i |=> (OutSelDnCnt ? &cnt_o : cnt_o == 0) || err_o)
// When `en_i` is set without `clr_i` and `set_i`, and counter does not reach max/min value,
- // we expect `cnt_o` to increment or decrement base on `step_i`.
+ // we expect `cnt_o` to increment or decrement base on `step_i`, or error occurs
`ASSERT(OutStep_A,
!(clr_i ||set_i) throughout en_i ##[1:$] en_i && max_val > cnt_o && cnt_o > 0 |->
- (CntStyle == DupCnt || !OutSelDnCnt) ? cnt_o - past_cnt_o == past_step_i :
- past_cnt_o - cnt_o == past_step_i)
+ ((CntStyle == DupCnt || !OutSelDnCnt) ? cnt_o - past_cnt_o == past_step_i :
+ past_cnt_o - cnt_o == past_step_i) || err_o)
// When `set_i` is set, at next clock cycle:
// 1). For duplicate counter, sets the `cnt_o` to `set_cnt_i`.
// 2). For cross up counter, sets the `max_value` to `set_cnt_i`.
// 3). For cross down counter, sets the `cnt_o` and `max_value` to `set_cnt_i`.
+ // 4). error occurs due to a fault injection
`ASSERT(OutSet_A, ##1 set_i |=>
- (CntStyle == DupCnt || OutSelDnCnt) ? cnt_o == $past(set_cnt_i) : cnt_o == 0)
+ ((CntStyle == DupCnt || OutSelDnCnt) ? cnt_o == $past(set_cnt_i) : cnt_o == 0) || err_o)
- // If the up counter reaches its max value, the value won't increment or change.
- `ASSERT(MaxUpCntStable_A, up_cnt_q[0] == max_val && !clr_i && !set_i |=> $stable(up_cnt_q[0]))
+ // If the up counter reaches its max value, the value won't increment or change, unless there is
+ // a fault injection
+ `ASSERT(MaxUpCntStable_A, up_cnt_q[0] == max_val && !clr_i && !set_i |=>
+ $stable(up_cnt_q[0]) || err_o)
// This logic that will be assign to one, when user adds macro
// ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT to check the error with alert, in case that prim_count