[dv/chip] add otp_macro_err check in all_escalation test
This PR adds a DV sequence to trigger otp_macro_err by injecting ECC
errors and read back the partition via DAI interface.
Signed-off-by: Cindy Chen <chencindy@opentitan.org>
diff --git a/hw/top_earlgrey/data/chip_testplan.hjson b/hw/top_earlgrey/data/chip_testplan.hjson
index 9b0c645..5c3001a 100644
--- a/hw/top_earlgrey/data/chip_testplan.hjson
+++ b/hw/top_earlgrey/data/chip_testplan.hjson
@@ -2853,6 +2853,20 @@
stage: V3
tests: ["chip_sw_otp_ctrl_vendor_test_csr_access"]
}
+ {
+ name: chip_sw_otp_ctrl_escalation
+ desc: '''Verify escalation from otp_ctrl macro fatal error.
+
+ - Inject ECC fatal error into OTP macro's HW cfg partition, and read back this macro
+ via DAI interface.
+ - Because this fatal error will immediately turn off CPU, so the DV sequence will probe
+ the alert interface to make sure alert and escalation is triggered.
+
+ X'ref with chip_sw_all_escalation_resets.
+ '''
+ stage: V3
+ tests: ["chip_sw_otp_ctrl_escalation"]
+ }
// FLASH (pre-verified IP) integration tests:
{
diff --git a/hw/top_earlgrey/dv/chip_sim_cfg.hjson b/hw/top_earlgrey/dv/chip_sim_cfg.hjson
index c4259d4..9243dd5 100644
--- a/hw/top_earlgrey/dv/chip_sim_cfg.hjson
+++ b/hw/top_earlgrey/dv/chip_sim_cfg.hjson
@@ -745,6 +745,14 @@
en_run_modes: ["sw_test_mode_test_rom"]
}
{
+ name: chip_sw_otp_ctrl_escalation
+ uvm_test_seq: chip_sw_otp_ctrl_escalation_vseq
+ sw_images: ["//sw/device/tests/sim_dv:all_escalation_resets_test:1"]
+ en_run_modes: ["sw_test_mode_test_rom"]
+ run_opts: ["+bypass_alert_ready_to_end_check=1"]
+ reseed: 1
+ }
+ {
// Set higher reseed value to reach all kmac_data to lc_ctrl toggle coverage.
name: chip_sw_lc_ctrl_transition
uvm_test_seq: chip_sw_lc_ctrl_transition_vseq
diff --git a/hw/top_earlgrey/dv/env/chip_env.core b/hw/top_earlgrey/dv/env/chip_env.core
index 69e4012..1d4dc89 100644
--- a/hw/top_earlgrey/dv/env/chip_env.core
+++ b/hw/top_earlgrey/dv/env/chip_env.core
@@ -96,6 +96,7 @@
- seq_lib/chip_sw_lc_walkthrough_testunlocks_vseq.sv: {is_include_file: true}
- seq_lib/chip_sw_lc_ctrl_program_error_vseq.sv: {is_include_file: true}
- seq_lib/chip_sw_otp_ctrl_vendor_test_csr_access_vseq.sv: {is_include_file: true}
+ - seq_lib/chip_sw_otp_ctrl_escalation_vseq.sv: {is_include_file: true}
- seq_lib/chip_sw_spi_device_tx_rx_vseq.sv: {is_include_file: true}
- seq_lib/chip_sw_spi_host_tx_rx_vseq.sv: {is_include_file: true}
- seq_lib/chip_sw_spi_passthrough_collision_vseq.sv: {is_include_file: true}
diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_otp_ctrl_escalation_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_otp_ctrl_escalation_vseq.sv
new file mode 100644
index 0000000..81319f6
--- /dev/null
+++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_otp_ctrl_escalation_vseq.sv
@@ -0,0 +1,48 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// This virtual sequence triggers OTP macro and check fatal errors by backdoor injecting ECC errors
+// and read back the injected error via DAI interface.
+// Because these fatal alert in OTP immediately will send the error information to LC_CTRL and turn
+// off CPU, this sequence will check alerts via backdoor probing.
+
+class chip_sw_otp_ctrl_escalation_vseq extends chip_sw_base_vseq;
+ `uvm_object_utils(chip_sw_otp_ctrl_escalation_vseq)
+
+ `uvm_object_new
+
+ virtual task body();
+ bit [TL_AW-1:0] hw_cfg_addr = otp_ctrl_reg_pkg::HwCfgOffset;
+ bit [TL_DW-1:0] val;
+ bit [7:0] sw_alert_num[];
+
+ super.body();
+
+ // Disable scoreboard tl error checks since we will trigger faults which cannot be predicted.
+ cfg.en_scb_tl_err_chk = 0;
+
+ // Let SW know the expected alert.
+ sw_alert_num = {TopEarlgreyAlertIdOtpCtrlFatalMacroError};
+ sw_symbol_backdoor_overwrite("kExpectedAlertNumber", sw_alert_num);
+
+ `DV_WAIT(cfg.sw_logger_vif.printed_log == "Ready for fault injection",
+ "Timeout waiting for fault injection request.")
+
+ val = cfg.mem_bkdr_util_h[Otp].read32(hw_cfg_addr);
+
+ // Inject 2 bits error in this hw_cfg_addr to trigger a ECC non-correctable error.
+ cfg.mem_bkdr_util_h[Otp].inject_errors(hw_cfg_addr, 2);
+
+
+ `DV_WAIT(cfg.sw_logger_vif.printed_log == "OTP_CTRL error inject done",
+ "Timeout waiting for OTP_CTRL error injection done.")
+
+ // TODO: backdoor check if alerts are firing.
+
+ // Backdoor write back the original value so the chip can reboot successfully.
+ cfg.mem_bkdr_util_h[Otp].write32(hw_cfg_addr, val);
+
+ endtask
+
+endclass
diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_vseq_list.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_vseq_list.sv
index 07ff42f..d551457 100644
--- a/hw/top_earlgrey/dv/env/seq_lib/chip_vseq_list.sv
+++ b/hw/top_earlgrey/dv/env/seq_lib/chip_vseq_list.sv
@@ -42,6 +42,7 @@
`include "chip_sw_lc_walkthrough_vseq.sv"
`include "chip_sw_lc_walkthrough_testunlocks_vseq.sv"
`include "chip_sw_otp_ctrl_vendor_test_csr_access_vseq.sv"
+`include "chip_sw_otp_ctrl_escalation_vseq.sv"
`include "chip_sw_spi_device_tx_rx_vseq.sv"
`include "chip_sw_spi_host_tx_rx_vseq.sv"
`include "chip_sw_spi_passthrough_vseq.sv"
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 7e0f86f..85a916b 100644
--- a/sw/device/tests/sim_dv/all_escalation_resets_test.c
+++ b/sw/device/tests/sim_dv/all_escalation_resets_test.c
@@ -848,13 +848,16 @@
fault_checker = fc;
} break;
// TODO add mechanism to inject:
- // kTopEarlgreyAlertIdOtpCtrlFatalMacroError uncorrectable ecc from macro
- // In any partition otp_ctrl_part_unbuf error_q = MacroEccUncorrError
// 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.
+ case kTopEarlgreyAlertIdOtpCtrlFatalMacroError: {
+ fault_checker_t fc = {otp_ctrl_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};
@@ -991,6 +994,14 @@
// DO NOT CHANGE THIS: it is used to notify the SV side.
LOG_INFO("Ready for fault injection");
+ // OTP ecc macro error test requires otp to read backdoor injected error
+ // macro.
+ if (kExpectedAlertNumber == kTopEarlgreyAlertIdOtpCtrlFatalMacroError) {
+ CHECK_DIF_OK(
+ dif_otp_ctrl_dai_read_start(&otp_ctrl, kDifOtpCtrlPartitionHwCfg, 0));
+ LOG_INFO("OTP_CTRL error inject done");
+ }
+
// FlashCtrlFatalErr test requires host read request.
if (kExpectedAlertNumber == kTopEarlgreyAlertIdFlashCtrlFatalErr) {
enum {
@@ -1116,10 +1127,12 @@
// ISRs should not run if flash_ctrl or sram_ctrl_main get a fault because
// flash or sram accesses are blocked in those cases. For lc_ctrl fatal
- // state the lc_ctrl blocks the CPU.
+ // state, otp_fatal alerts tha will trigger LC to escalate, the lc_ctrl
+ // blocks the CPU.
if (kExpectedAlertNumber == kTopEarlgreyAlertIdFlashCtrlFatalStdErr ||
kExpectedAlertNumber == kTopEarlgreyAlertIdSramCtrlMainFatalError ||
kExpectedAlertNumber == kTopEarlgreyAlertIdLcCtrlFatalStateError ||
+ kExpectedAlertNumber == kTopEarlgreyAlertIdOtpCtrlFatalMacroError ||
kExpectedAlertNumber == kTopEarlgreyAlertIdOtpCtrlFatalCheckError) {
CHECK(interrupt_count == 0,
"Expected regular ISR should not run for flash_ctrl, lc_ctrl fatal "