[dv/chip] otp inject prim_otp_error

This PR injects prim_otp_fatal error in chip level test.
The prim_otp_error won't affect any open source registers. It only
triggers alert.
Todos from issue #15649

Signed-off-by: Cindy Chen <chencindy@opentitan.org>
diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_all_escalation_resets_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_all_escalation_resets_vseq.sv
index 387928b..2cf6c5a 100644
--- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_all_escalation_resets_vseq.sv
+++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_all_escalation_resets_vseq.sv
@@ -37,8 +37,8 @@
     '{"*lc_ctrl*state_regs*", TopEarlgreyAlertIdLcCtrlFatalStateError},
     '{"*lc_ctrl*prim_reg_we_check*", TopEarlgreyAlertIdLcCtrlFatalBusIntegError},
     '{"*otbn*prim_reg_we_check*", TopEarlgreyAlertIdOtbnFatal},
-    // TODO TopEarlgreyAlertIdOtpCtrlFatalMacroError,
-    // TODO TopEarlgreyAlertIdOtpCtrlFatalPrimOtpAlert.
+    // TopEarlgreyAlertIdOtpCtrlFatalMacroError: done in chip_sw_otp_ctrl_escalation_vseq
+    '{"*otp_ctrl.u_otp.*u_state_regs", TopEarlgreyAlertIdOtpCtrlFatalPrimOtpAlert},
     '{"*otp_ctrl*u_otp_ctrl_dai*", TopEarlgreyAlertIdOtpCtrlFatalCheckError},
     '{"*otp_ctrl*prim_reg_we_check*", TopEarlgreyAlertIdOtpCtrlFatalBusIntegError},
     '{"*pattgen*prim_reg_we_check*", TopEarlgreyAlertIdPattgenFatalFault},
diff --git a/sw/device/tests/sim_dv/all_escalation_resets_test.c b/sw/device/tests/sim_dv/all_escalation_resets_test.c
index 85a916b..ad04045 100644
--- a/sw/device/tests/sim_dv/all_escalation_resets_test.c
+++ b/sw/device/tests/sim_dv/all_escalation_resets_test.c
@@ -377,6 +377,18 @@
         expected_codes);
 }
 
+// OTP_prim_fault does not affect open source otp_ctrl's status register.
+static void otp_ctrl_prim_fault_checker(bool enable, const char *ip_inst,
+                                        const char *type) {
+  // Check the otp_ctrl integrity fatal error code.
+  dif_otp_ctrl_status_t status;
+  uint32_t expected_codes;
+  CHECK_DIF_OK(dif_otp_ctrl_get_status(&otp_ctrl, &status));
+  expected_codes = 1 << kDifOtpCtrlStatusCodeDaiIdle;
+  CHECK(status.codes == expected_codes, "For %s got codes 0x%x, expected 0x%x",
+        ip_inst, status.codes, expected_codes);
+}
+
 static void pwrmgr_fault_checker(bool enable, const char *ip_inst,
                                  const char *type) {
   // Check the pwrmgr integrity fatal error code.
@@ -848,8 +860,6 @@
       fault_checker = fc;
     } break;
       // TODO add mechanism to inject:
-      // kTopEarlgreyAlertIdOtpCtrlFatalPrimOtpAlert force at prim_otp interface
-      // u_otp output fatal_alert_o.
       // forcing otp_prog_err_o from lc_ctrl_fsm and
       // kTopEarlgreyAlertIdLcCtrlFatalStateError using sparse fsm.
       // alerts, and corresponding CSR bit to check.
@@ -858,6 +868,11 @@
                             sparse_fsm_check};
       fault_checker = fc;
     } break;
+    case kTopEarlgreyAlertIdOtpCtrlFatalPrimOtpAlert: {
+      fault_checker_t fc = {otp_ctrl_prim_fault_checker, otp_ctrl_inst_name,
+                            sparse_fsm_check};
+      fault_checker = fc;
+    } break;
     case kTopEarlgreyAlertIdOtpCtrlFatalCheckError: {
       fault_checker_t fc = {otp_ctrl_fault_checker, otp_ctrl_inst_name,
                             sparse_fsm_check};