[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()))