[LC_CTRL/dv] Fixed up tests

- Updated FSM backdoor path
- Corrected KMAC I/F FSM backdoor read and write tasks.
- Selectively disabling assertions
- Fixed V2S testplan
- Added missing constraint token_digest_err_inj_c to lc_ctrl_errors_vseq.sv
- Added asserion disabling for sec_cm tests in lc_ctrl_common_vseq
- Moved to using prim_sparse_fsm_flop_if_proxy for backdoor error injection rather than tasks in lc_ctrl_if

Signed-off-by: Nigel Scales <nigel.scales@gmail.com>
diff --git a/hw/ip/lc_ctrl/data/lc_ctrl_sec_cm_testplan.hjson b/hw/ip/lc_ctrl/data/lc_ctrl_sec_cm_testplan.hjson
index 5e9f293..617af91 100644
--- a/hw/ip/lc_ctrl/data/lc_ctrl_sec_cm_testplan.hjson
+++ b/hw/ip/lc_ctrl/data/lc_ctrl_sec_cm_testplan.hjson
@@ -43,7 +43,7 @@
       mutex).
       '''
       milestone: V2S
-      tests: []
+      tests: ["lc_ctrl_regwen_during_op"]
     }
     {
       name: sec_cm_manuf_state_sparse
@@ -53,7 +53,7 @@
       Verify this countermeasure with a standardized test.
       '''
       milestone: V2S
-      tests: []
+      tests: ["lc_ctrl_sec_cm", "lc_ctrl_state_failure"]
     }
     {
       name: sec_cm_transition_ctr_sparse
diff --git a/hw/ip/lc_ctrl/dv/env/lc_ctrl_if.sv b/hw/ip/lc_ctrl/dv/env/lc_ctrl_if.sv
index ab7031e..cb1651d 100644
--- a/hw/ip/lc_ctrl/dv/env/lc_ctrl_if.sv
+++ b/hw/ip/lc_ctrl/dv/env/lc_ctrl_if.sv
@@ -4,26 +4,6 @@
 //
 // interface for input data from OTP
 
-`ifndef LC_CTRL_FSM_STATE_REGS_PATH
-`define LC_CTRL_FSM_STATE_REGS_PATH \
-    tb.dut.u_lc_ctrl_fsm.u_fsm_state_regs.u_state_flop.gen_generic.u_impl_generic.q_o
-`endif
-
-`ifndef LC_CTRL_KMAC_FSM_STATE_REGS_PATH
-`define LC_CTRL_KMAC_FSM_STATE_REGS_PATH \
-    tb.dut.u_lc_ctrl_kmac_if.u_state_regs.u_state_flop.gen_generic.u_impl_generic.q_o
-`endif
-
-`ifndef LC_CTRL_STATE_PATH
-`define LC_CTRL_STATE_PATH \
-    tb.dut.otp_lc_data_i.state
-`endif
-
-`ifndef LC_CTRL_COUNT_PATH
-`define LC_CTRL_COUNT_PATH \
-    tb.dut.otp_lc_data_i.count
-`endif
-
 `ifndef LC_CTRL_FSM_PATH
 `define LC_CTRL_FSM_PATH tb.dut.u_lc_ctrl_fsm
 `endif
@@ -139,8 +119,6 @@
       end
     join_none
 
-    release `LC_CTRL_FSM_STATE_REGS_PATH;
-
   endtask
 
   task automatic set_clk_byp_ack(lc_tx_t val);
@@ -157,96 +135,6 @@
     otp_vendor_test_status_i = 0;
   endfunction
 
-  //
-  // The functions below must be static because of the force statement
-  //
-
-  // Force lc_ctrl_fsm state registers
-  function static void lc_fsm_state_backdoor_write(input logic [FsmStateWidth-1:0] val = 'hdead,
-                                                   input int delay_clocks = 0,
-                                                   input int force_clocks = 5);
-    `dv_info($sformatf("Backdoor write to state registers"))
-    fork
-      begin : force_state_proc
-        repeat (delay_clocks) @(posedge clk);
-        ->lc_fsm_state_backdoor_write_ev;
-        force `LC_CTRL_FSM_STATE_REGS_PATH = val;
-        repeat (force_clocks) @(posedge clk);
-        release `LC_CTRL_FSM_STATE_REGS_PATH;
-      end : force_state_proc
-    join_none
-  endfunction
-
-  // Read lc_ctrl_fsm state registers
-  function automatic logic [FsmStateWidth-1:0] lc_fsm_state_backdoor_read();
-    ->lc_fsm_state_backdoor_read_ev;
-    return `LC_CTRL_FSM_STATE_REGS_PATH;
-  endfunction
-
-  // Force kmac i/f fsm state registers
-  function static void kmac_fsm_state_backdoor_write(
-      input logic [lc_ctrl_env_pkg::KMAC_FSM_WIDTH-1:0] val = 'hde, input int delay_clocks = 0,
-      input int force_clocks = 5);
-    `dv_info($sformatf("Backdoor write to kmac i/f state registers = %h", val))
-    fork
-      begin : force_state_proc
-        repeat (delay_clocks) @(posedge clk);
-        ->kmac_fsm_state_backdoor_write_ev;
-        force `LC_CTRL_FSM_STATE_REGS_PATH = val;
-        repeat (force_clocks) @(posedge clk);
-        release `LC_CTRL_FSM_STATE_REGS_PATH;
-      end : force_state_proc
-    join_none
-  endfunction
-
-  // Read  kmac i/f fsm state registers
-  function automatic logic [lc_ctrl_env_pkg::KMAC_FSM_WIDTH-1:0] kmac_fsm_state_backdoor_read();
-    ->kmac_fsm_state_backdoor_read_ev;
-    return `LC_CTRL_FSM_STATE_REGS_PATH;
-  endfunction
-
-  // Force OTP state input
-  function static void state_backdoor_write(input logic [LcStateWidth-1:0] val = 'hdead,
-                                            input int delay_clocks = 0, input int force_clocks = 5);
-    `dv_info($sformatf("Backdoor write to OTP state input = %h", val))
-    fork
-      begin : force_state_proc
-        repeat (delay_clocks) @(posedge clk);
-        ->state_backdoor_write_ev;
-        force `LC_CTRL_STATE_PATH = val;
-        repeat (force_clocks) @(posedge clk);
-        release `LC_CTRL_STATE_PATH;
-      end : force_state_proc
-    join_none
-  endfunction
-
-  // Read OTP state input
-  function automatic logic [LcStateWidth-1:0] state_backdoor_read();
-    ->state_backdoor_read_ev;
-    return `LC_CTRL_STATE_PATH;
-  endfunction
-
-  // Force OTP count input
-  function static void count_backdoor_write(input logic [LcCountWidth-1:0] val = 'hdead,
-                                            input int delay_clocks = 0, input int force_clocks = 5);
-    `dv_info($sformatf("Backdoor write to OTP count input = %h", val))
-    fork
-      begin : force_count_proc
-        repeat (delay_clocks) @(posedge clk);
-        ->count_backdoor_write_ev;
-        force `LC_CTRL_COUNT_PATH = val;
-        repeat (force_clocks) @(posedge clk);
-        release `LC_CTRL_COUNT_PATH;
-      end : force_count_proc
-    join_none
-  endfunction
-
-  // Read OTP count input
-  function automatic logic [LcCountWidth-1:0] count_backdoor_read();
-    ->count_backdoor_read_ev;
-    return `LC_CTRL_COUNT_PATH;
-  endfunction
-
   function automatic void set_test_sequence_typename(string name);
     test_sequence_typename = name;
   endfunction
@@ -293,6 +181,4 @@
 
 endinterface
 
-`undef LC_CTRL_FSM_STATE_REGS_PATH
-`undef LC_CTRL_COUNT_PATH
 `undef LC_CTRL_FSM_PATH
diff --git a/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_base_vseq.sv b/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_base_vseq.sv
index b726554..c65ada2 100644
--- a/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_base_vseq.sv
+++ b/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_base_vseq.sv
@@ -243,4 +243,14 @@
               ), UVM_MEDIUM)
   endfunction
 
+
+  // Find sec_cm_base_if_proxy for a given path
+  virtual function sec_cm_base_if_proxy find_sec_cm_base_if_proxy(string path);
+    sec_cm_base_if_proxy proxies[$];
+    // Search singleton queue of proxies in sec_cm_pkg
+    proxies = sec_cm_pkg::sec_cm_if_proxy_q.find_first() with (item.path == path);
+    if (proxies.size > 0) return proxies[0];
+    else `uvm_fatal(`gfn, $sformatf("find_sec_cm_base_if_proxy: no proxy with path %s", path))
+  endfunction
+
 endclass : lc_ctrl_base_vseq
diff --git a/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_common_vseq.sv b/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_common_vseq.sv
index 1353240..962f928 100644
--- a/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_common_vseq.sv
+++ b/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_common_vseq.sv
@@ -12,6 +12,21 @@
     run_common_vseq_wrapper(num_trans);
   endtask : body
 
+  virtual function void sec_cm_fi_ctrl_svas(sec_cm_base_if_proxy if_proxy, bit enable);
+    case (if_proxy.sec_cm_type)
+      SecCmPrimSparseFsmFlop: begin
+        `DV_ASSERT_CTRL_REQ("StateRegs_A", enable)
+        `DV_ASSERT_CTRL_REQ("CountRegs_A", enable)
+        `DV_ASSERT_CTRL_REQ("FsmStateRegs_A", enable)
+        `DV_ASSERT_CTRL_REQ("KmacFsmStateRegs_A", enable)
+      end
+      SecCmPrimCount: begin
+        // No need to disable any assertion
+      end
+      default: `uvm_fatal(`gfn, $sformatf("unexpected sec_cm_type %s", if_proxy.sec_cm_type.name))
+    endcase
+  endfunction : sec_cm_fi_ctrl_svas
+
   virtual task check_sec_cm_fi_resp(sec_cm_base_if_proxy if_proxy);
     // Expected state error bit of status register
     bit exp_state_error = 0;
diff --git a/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_errors_vseq.sv b/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_errors_vseq.sv
index ef0da31..464138b 100644
--- a/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_errors_vseq.sv
+++ b/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_errors_vseq.sv
@@ -126,6 +126,8 @@
 
   constraint tokem_mux_err_inj_c {err_inj.token_mux_ctrl_redun_err == 0;}
 
+  constraint token_digest_err_inj_c {err_inj.token_mux_digest_err == 0;}
+
   virtual task post_start();
     `uvm_info(`gfn, "post_start: Task called for lc_ctrl_errors_vseq", UVM_MEDIUM)
 
@@ -150,6 +152,10 @@
     `DV_ASSERT_CTRL_REQ("OtpProgReqHighUntilAck_A", 1)
     `DV_ASSERT_CTRL_REQ("OtpProgAckAssertedOnlyWhenReqAsserted_A", 1)
     `DV_ASSERT_CTRL_REQ("KmacIfSyncReqAckAckNeedsReq", 1)
+    `DV_ASSERT_CTRL_REQ("StateRegs_A", 1)
+    `DV_ASSERT_CTRL_REQ("FsmStateRegs_A", 1)
+    `DV_ASSERT_CTRL_REQ("CountRegs_A", 1)
+
 
     // Kill sub processes
     disable handle_alerts;
@@ -394,16 +400,27 @@
       `DV_ASSERT_CTRL_REQ("OtpProgReqHighUntilAck_A", 0)
       `DV_ASSERT_CTRL_REQ("OtpProgAckAssertedOnlyWhenReqAsserted_A", 0)
       `DV_ASSERT_CTRL_REQ("KmacIfSyncReqAckAckNeedsReq", 0)
-      assertions_disabled = 1;
-    end else if (assertions_disabled) begin
-      // Reenable assertions if they had been disabled
+    end else begin
       `DV_ASSERT_CTRL_REQ("OtpProgH_DataStableWhenBidirectionalAndReq_A", 1)
       `DV_ASSERT_CTRL_REQ("OtpProgReqHighUntilAck_A", 1)
       `DV_ASSERT_CTRL_REQ("OtpProgAckAssertedOnlyWhenReqAsserted_A", 1)
       `DV_ASSERT_CTRL_REQ("KmacIfSyncReqAckAckNeedsReq", 1)
-      assertions_disabled = 0;
     end
 
+    if (err_inj.state_err || err_inj.state_illegal_err || err_inj.state_backdoor_err) begin
+      `DV_ASSERT_CTRL_REQ("StateRegs_A", 0)
+    end else `DV_ASSERT_CTRL_REQ("StateRegs_A", 1)
+
+    if (err_inj.count_err || err_inj.count_illegal_err || err_inj.count_backdoor_err) begin
+      `DV_ASSERT_CTRL_REQ("CountRegs_A", 0)
+    end else `DV_ASSERT_CTRL_REQ("CountRegs_A", 1)
+
+    if (err_inj.lc_fsm_backdoor_err) `DV_ASSERT_CTRL_REQ("FsmStateRegs_A", 0)
+    else `DV_ASSERT_CTRL_REQ("FsmStateRegs_A", 1)
+
+    if (err_inj.kmac_fsm_backdoor_err) `DV_ASSERT_CTRL_REQ("KmacFsmStateRegs_A", 0)
+    else `DV_ASSERT_CTRL_REQ("KmacFsmStateRegs_A", 1)
+
   endtask
 
 
@@ -716,34 +733,37 @@
   // Flip bits in LC FSM registers
   protected virtual task lc_fsm_backdoor_err_inj();
     logic [FsmStateWidth-1:0] state;
-    state = cfg.lc_ctrl_vif.lc_fsm_state_backdoor_read();
-    state ^= lc_fsm_state_invert_bits;
-    cfg.lc_ctrl_vif.lc_fsm_state_backdoor_write(state, 0, lc_fsm_state_err_inj_period);
+    sec_cm_base_if_proxy if_proxy = find_sec_cm_base_if_proxy(
+        "tb.dut.u_lc_ctrl_fsm.u_fsm_state_regs"
+    );
+
+    if_proxy.inject_fault();
   endtask
 
   // Flip bits in KMAC FSM registers
   protected virtual task kmac_fsm_backdoor_err_inj();
     logic [KMAC_FSM_WIDTH-1:0] state;
-    state = cfg.lc_ctrl_vif.kmac_fsm_state_backdoor_read();
-    state ^= kmac_fsm_state_invert_bits;
-    cfg.lc_ctrl_vif.kmac_fsm_state_backdoor_write(state, 0, lc_fsm_state_err_inj_period);
-  endtask
+    sec_cm_base_if_proxy if_proxy = find_sec_cm_base_if_proxy(
+        "tb.dut.u_lc_ctrl_kmac_if.u_state_regs"
+    );
 
+    if_proxy.inject_fault();
+  endtask
 
   // Flip bits in OTP State input
   protected virtual task state_backdoor_err_inj();
     logic [LcStateWidth-1:0] state;
-    state = cfg.lc_ctrl_vif.count_backdoor_read();
-    state ^= state_invert_bits;
-    cfg.lc_ctrl_vif.count_backdoor_write(state, 0, state_err_inj_period);
+    sec_cm_base_if_proxy if_proxy = find_sec_cm_base_if_proxy("tb.dut.u_lc_ctrl_fsm.u_state_regs");
+
+    if_proxy.inject_fault();
   endtask
 
   // Flip bits OTP Count input
   protected virtual task count_backdoor_err_inj();
     logic [LcCountWidth-1:0] count;
-    count = cfg.lc_ctrl_vif.count_backdoor_read();
-    count ^= count_invert_bits;
-    cfg.lc_ctrl_vif.count_backdoor_write(count, 0, count_err_inj_period);
+    sec_cm_base_if_proxy if_proxy = find_sec_cm_base_if_proxy("tb.dut.u_lc_ctrl_fsm.u_cnt_regs");
+
+    if_proxy.inject_fault();
   endtask
 
   // Send an escalate alert
diff --git a/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_sec_token_digest_vseq.sv b/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_sec_token_digest_vseq.sv
index 3501a3d..4346d5c 100644
--- a/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_sec_token_digest_vseq.sv
+++ b/hw/ip/lc_ctrl/dv/env/seq_lib/lc_ctrl_sec_token_digest_vseq.sv
@@ -21,7 +21,7 @@
     err_inj.otp_partition_err == 0;
   }
 
-  constraint lc_token_digest_c {
+  constraint lc_token_digest_err_inj_c {
     $onehot(
         {
           // Either wrong token for transition
diff --git a/hw/ip/lc_ctrl/dv/tb.sv b/hw/ip/lc_ctrl/dv/tb.sv
index 0bfd8ac..4f020d3 100644
--- a/hw/ip/lc_ctrl/dv/tb.sv
+++ b/hw/ip/lc_ctrl/dv/tb.sv
@@ -249,5 +249,13 @@
   `DV_ASSERT_CTRL("FsmClkFlashRmaAckSync", dut.u_lc_ctrl_fsm.u_prim_lc_sync_flash_rma_ack)
   `DV_ASSERT_CTRL("FsmOtpTestTokensValidSync", dut.u_lc_ctrl_fsm.u_prim_lc_sync_test_token_valid)
   `DV_ASSERT_CTRL("FsmOtpRmaTokenValidSync", dut.u_lc_ctrl_fsm.u_prim_lc_sync_rma_token_valid)
-
+  `DV_ASSERT_CTRL("StateRegs_A", tb.dut.u_lc_ctrl_fsm.u_state_regs_A)
+  `DV_ASSERT_CTRL("StateRegs_A", tb.dut.FpvSecCmCtrlLcStateCheck_A)
+  `DV_ASSERT_CTRL("FsmStateRegs_A", tb.dut.u_lc_ctrl_fsm.u_fsm_state_regs_A)
+  `DV_ASSERT_CTRL("FsmStateRegs_A", tb.dut.FpvSecCmCtrlLcFsmCheck_A)
+  `DV_ASSERT_CTRL("CountRegs_A", tb.dut.u_lc_ctrl_fsm.u_cnt_regs_A)
+  `DV_ASSERT_CTRL("CountRegs_A", tb.dut.FpvSecCmCtrlLcCntCheck_A)
+  `DV_ASSERT_CTRL("KmacFsmStateRegs_A", tb.dut.u_lc_ctrl_kmac_if.u_state_regs_A)
+  `DV_ASSERT_CTRL("KmacFsmStateRegs_A", tb.dut.FpvSecCmCtrlKmacIfFsmCheck_A)
+  `DV_ASSERT_CTRL("EscStaysOnOnceAsserted_A", tb.dut.u_lc_ctrl_fsm.EscStaysOnOnceAsserted_A)
 endmodule