[dv/otp_ctrl] Add coverpoint for scb checks
In otp_ctrl scb, there are cases where we might waive checks (due to
background checks, etc). I added some coverpoint to only collect
coverage after these checks are done.
Signed-off-by: Cindy Chen <chencindy@google.com>
diff --git a/hw/ip/otp_ctrl/dv/env/otp_ctrl_env_cov.sv b/hw/ip/otp_ctrl/dv/env/otp_ctrl_env_cov.sv
index c4ca7f8..a3cd714 100644
--- a/hw/ip/otp_ctrl/dv/env/otp_ctrl_env_cov.sv
+++ b/hw/ip/otp_ctrl/dv/env/otp_ctrl_env_cov.sv
@@ -15,11 +15,52 @@
// otp_ctrl_env_cfg: cfg
// covergroups
- // [add covergroups here]
+ // This covergroup collects different conditions when outputs (hwcfg_o, keymgr_key_o) are checked
+ // in scb:
+ // - If lc_esc_en is On
+ // - If each partition is locked (expect LC)
+ covergroup power_on_cg with function sample (bit lc_esc_en, bit[NumPart-2:0] parts_locked);
+ lc_esc: coverpoint lc_esc_en;
+ creator_sw_lock: coverpoint parts_locked[0];
+ owner_sw_lock: coverpoint parts_locked[1];
+ hw_cfg_lock: coverpoint parts_locked[2];
+ screct0_lock: coverpoint parts_locked[3];
+ screct1_lock: coverpoint parts_locked[4];
+ screct2_lock: coverpoint parts_locked[5];
+ endgroup
+
+ bit_toggle_cg_wrap lc_prog_cg;
+ bit_toggle_cg_wrap otbn_req_cg;
+
+ // This coverpoint is only collected if flash request passed scb check
+ covergroup flash_req_cg with function sample (int index, bit locked);
+ flash_index: coverpoint index {
+ bins flash_data_key = {FlashDataKey};
+ bins flash_addr_key = {FlashAddrKey};
+ illegal_bins il = default;
+ }
+ secret1_lock: coverpoint locked;
+ flash_req_lock_cross: cross flash_index, secret1_lock;
+ endgroup
+
+ // This coverpoint is only collected if sram request passed scb check
+ covergroup sram_req_cg with function sample (int index, bit locked);
+ sram_index: coverpoint index {
+ bins sram_key0 = {0};
+ bins sram_key1 = {1};
+ illegal_bins il = default;
+ }
+ secret1_lock: coverpoint locked;
+ sram_req_lock_cross: cross sram_index, secret1_lock;
+ endgroup
function new(string name, uvm_component parent);
super.new(name, parent);
- // [instantiate covergroups here]
+ power_on_cg = new();
+ flash_req_cg = new();
+ sram_req_cg = new();
+ lc_prog_cg = new("lc_prog_cg", "", 0);
+ otbn_req_cg = new("otbn_req_cg", "", 0);
endfunction : new
virtual function void build_phase(uvm_phase phase);
diff --git a/hw/ip/otp_ctrl/dv/env/otp_ctrl_scoreboard.sv b/hw/ip/otp_ctrl/dv/env/otp_ctrl_scoreboard.sv
index f0d2ea0..6a672ae 100644
--- a/hw/ip/otp_ctrl/dv/env/otp_ctrl_scoreboard.sv
+++ b/hw/ip/otp_ctrl/dv/env/otp_ctrl_scoreboard.sv
@@ -145,6 +145,12 @@
if (cfg.otp_ctrl_vif.lc_esc_on == 0) begin
`DV_CHECK_EQ(cfg.otp_ctrl_vif.keymgr_key_o, exp_keymgr_data)
end
+
+ if (cfg.en_cov) begin
+ bit [NumPart-2:0] parts_locked;
+ foreach (parts_locked[i]) parts_locked[i] = (get_otp_digest_val(i) != 0);
+ cov.power_on_cg.sample(cfg.otp_ctrl_vif.lc_esc_on, parts_locked);
+ end
end
end
end
@@ -196,6 +202,8 @@
// LC program request data is valid means no OTP macro error.
`DV_CHECK_EQ(rcv_item.d_data, exp_err_bit)
+
+ if (cfg.en_cov) cov.lc_prog_cg.sample(exp_err_bit);
end
endtask
@@ -269,6 +277,8 @@
exp_key = {exp_key_higher, exp_key_lower};
`DV_CHECK_EQ(key, exp_key, "otbn key mismatch")
+ if (cfg.en_cov) cov.otbn_req_cg.sample(part_locked);
+
// If during OTBN key request, the LFSR timer expired and trigger an EDN request to acquire
// two EDN keys, then ignore the OTBN output checking, because scb did not know which EDN
// keys are used for LFSR.
@@ -320,6 +330,8 @@
.final_const(RndCnstDigestConst[sel_flash]));
exp_key = {exp_key_higher, exp_key_lower};
`DV_CHECK_EQ(key, exp_key, $sformatf("flash %s key mismatch", sel_flash.name()))
+
+ if (cfg.en_cov) cov.flash_req_cg.sample(sel_flash, part_locked);
end
join_none;
end
@@ -369,6 +381,8 @@
.num_round(2));
exp_key = {exp_key_higher, exp_key_lower};
`DV_CHECK_EQ(key, exp_key, $sformatf("sram_%0d key mismatch", index))
+ if (cfg.en_cov) cov.sram_req_cg.sample(index, part_locked);
+
end else if ((edn_data_q.size() - NUM_SRAM_EDN_REQ) % 2 != 0) begin
`uvm_error(`gfn, $sformatf("Unexpected edn_data_q size (%0d) during SRAM request",
edn_data_q.size()))