Add rstmgr crash dump tests to edacloud

Change-Id: I1e285aae12f225e0d6ad669c0332aa53e8eedbcf
diff --git a/hw/top_matcha/dv/chip_sim_cfg.hjson b/hw/top_matcha/dv/chip_sim_cfg.hjson
index 3a3fe1f..4753526 100644
--- a/hw/top_matcha/dv/chip_sim_cfg.hjson
+++ b/hw/top_matcha/dv/chip_sim_cfg.hjson
@@ -1061,7 +1061,7 @@
     {
       name: chip_sw_rstmgr_alert_info
       uvm_test_seq: chip_sw_base_vseq
-      sw_images: ["//sw/device/tests:rstmgr_alert_info_test:1"]
+      sw_images: ["//sw/device/tests:rstmgr_alert_info_test:1:matcha"]
       en_run_modes: ["sw_test_mode_test_rom"]
       run_opts: ["+sw_test_timeout_ns=30_000_000", "+en_scb_tl_err_chk=0"]
       run_timeout_mins: 120
@@ -1069,7 +1069,7 @@
     {
       name: chip_sw_rstmgr_cpu_info
       uvm_test_seq: chip_sw_base_vseq
-      sw_images: ["//sw/device/tests:rstmgr_cpu_info_test:1"]
+      sw_images: ["//sw/device/tests:rstmgr_cpu_info_test:1:matcha"]
       en_run_modes: ["sw_test_mode_test_rom"]
     }
     {
@@ -2103,6 +2103,7 @@
         "chip_sw_pwrmgr_sleep_power_glitch_reset",
         "chip_sw_pwrmgr_sleep_sensor_ctrl_alert_wakeup",
         "chip_sw_rom_ctrl_integrity_check",
+        "chip_sw_rstmgr_cpu_info",
         "chip_sw_rstmgr_smoketest",
         "chip_sw_rstmgr_sw_req",
         "chip_sw_rstmgr_sw_rst",
@@ -2204,6 +2205,8 @@
         "chip_sw_pwrmgr_sleep_power_glitch_reset",
         "chip_sw_pwrmgr_sleep_sensor_ctrl_alert_wakeup",
         "chip_sw_rom_ctrl_integrity_check",
+        "chip_sw_rstmgr_alert_info",
+        "chip_sw_rstmgr_cpu_info",
         "chip_sw_rstmgr_smoketest",
         "chip_sw_rstmgr_sw_req",
         "chip_sw_rstmgr_sw_rst",
diff --git a/hw/top_matcha/dv/env/autogen/chip_env_pkg__params.sv b/hw/top_matcha/dv/env/autogen/chip_env_pkg__params.sv
index 4deb6b3..87cac99 100644
--- a/hw/top_matcha/dv/env/autogen/chip_env_pkg__params.sv
+++ b/hw/top_matcha/dv/env/autogen/chip_env_pkg__params.sv
@@ -1,9 +1,8 @@
-// Copyright 2023 Google LLC.
 // Copyright lowRISC contributors.
 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
 // SPDX-License-Identifier: Apache-2.0
 
-// Generated by topgen_matcha.py
+// Generated by topgen.py
 
 parameter string LIST_OF_ALERTS[] = {
   "uart0_fatal_fault",
@@ -72,8 +71,11 @@
   "rv_core_ibex_sec_fatal_hw_err",
   "rv_core_ibex_sec_recov_hw_err",
   "smc_uart_fatal_fault",
+  "rv_timer_smc_fatal_fault",
   "cam_i2c_fatal_fault",
+  "rv_plic_smc_fatal_fault",
   "spi_host2_fatal_fault",
+  "rv_timer_smc2_fatal_fault",
   "rv_core_ibex_smc_fatal_sw_err",
   "rv_core_ibex_smc_recov_sw_err",
   "rv_core_ibex_smc_fatal_hw_err",
diff --git a/sw/device/lib/testing/BUILD b/sw/device/lib/testing/BUILD
index 581a9ac..305c3c3 100644
--- a/sw/device/lib/testing/BUILD
+++ b/sw/device/lib/testing/BUILD
@@ -68,3 +68,16 @@
         "@lowrisc_opentitan//sw/device/lib/testing/test_framework:check",
     ],
 )
+
+cc_library(
+    name = "alert_handler_testutils",
+    srcs = ["@lowrisc_opentitan//sw/device/lib/testing:alert_handler_testutils.c"],
+    hdrs = ["@lowrisc_opentitan//sw/device/lib/testing:alert_handler_testutils.h"],
+    target_compatible_with = [OPENTITAN_CPU],
+    deps = [
+        "//sw/device/lib/dif:alert_handler",
+        "//sw/device/lib/dif:rstmgr",
+        "@lowrisc_opentitan//sw/device/lib/dif:base",
+        "@lowrisc_opentitan//sw/device/lib/testing/test_framework:check",
+    ],
+)
diff --git a/sw/device/tests/BUILD b/sw/device/tests/BUILD
index 5c0339f..8217ae7 100644
--- a/sw/device/tests/BUILD
+++ b/sw/device/tests/BUILD
@@ -751,6 +751,7 @@
         "//sw/device/lib/dif:pinmux",
         "//sw/device/lib/dif:rstmgr",
         "//sw/device/lib/dif:rv_plic_sec",
+        "//sw/device/lib/testing:alert_handler_testutils",
         "@lowrisc_opentitan//sw/device/lib/dif:adc_ctrl",
         "@lowrisc_opentitan//sw/device/lib/dif:aes",
         "@lowrisc_opentitan//sw/device/lib/dif:aon_timer",
@@ -779,7 +780,6 @@
         "@lowrisc_opentitan//sw/device/lib/dif:sysrst_ctrl",
         "@lowrisc_opentitan//sw/device/lib/dif:uart",
         "@lowrisc_opentitan//sw/device/lib/dif:usbdev",
-        "@lowrisc_opentitan//sw/device/lib/testing:alert_handler_testutils",
     ],
 )
 
@@ -790,10 +790,10 @@
         ":test_dv_lib_opentitan",
         "//hw/top_matcha:alert_handler_regs",
         "//sw/device/lib/dif:alert_handler",
+        "//sw/device/lib/testing:alert_handler_testutils",
         "@lowrisc_opentitan//sw/device/lib/base:math",
         "@lowrisc_opentitan//sw/device/lib/dif:rv_core_ibex",
         "@lowrisc_opentitan//sw/device/lib/dif:rv_plic",
-        "@lowrisc_opentitan//sw/device/lib/testing:alert_handler_testutils",
         "@lowrisc_opentitan//sw/device/lib/testing:isr_testutils",
         "@lowrisc_opentitan//sw/device/lib/testing:rv_plic_testutils",
     ],
@@ -885,9 +885,9 @@
     deps = [
         ":test_dv_lib_opentitan",
         "//sw/device/lib/dif:alert_handler",
+        "//sw/device/lib/testing:alert_handler_testutils",
         "@lowrisc_opentitan//sw/device/lib/dif:aon_timer",
         "@lowrisc_opentitan//sw/device/lib/dif:rv_core_ibex",
-        "@lowrisc_opentitan//sw/device/lib/testing:alert_handler_testutils",
         "@lowrisc_opentitan//sw/device/lib/testing:aon_timer_testutils",
         "@lowrisc_opentitan//sw/device/lib/testing:isr_testutils",
         "@lowrisc_opentitan//sw/device/lib/testing:pwrmgr_testutils",
@@ -993,6 +993,47 @@
     ],
 )
 
+matcha_dv_test(
+    name = "rstmgr_alert_info_test",
+    srcs = ["rstmgr_alert_info_test.c"],
+    deps = [
+        ":test_dv_lib",
+        "//sw/device/lib/dif:alert_handler",
+        "//sw/device/lib/dif:cam_ctrl",
+        "//sw/device/lib/dif:rstmgr",
+        "//sw/device/lib/dif:rv_plic_sec",
+        "//sw/device/lib/dif:rv_plic_smc",
+        "//sw/device/lib/testing:alert_handler_testutils",
+        "@lowrisc_opentitan//sw/device/lib/dif:aon_timer",
+        "@lowrisc_opentitan//sw/device/lib/dif:i2c",
+        "@lowrisc_opentitan//sw/device/lib/dif:otp_ctrl",
+        "@lowrisc_opentitan//sw/device/lib/dif:pwrmgr",
+        "@lowrisc_opentitan//sw/device/lib/dif:rv_core_ibex",
+        "@lowrisc_opentitan//sw/device/lib/dif:rv_timer",
+        "@lowrisc_opentitan//sw/device/lib/dif:spi_host",
+        "@lowrisc_opentitan//sw/device/lib/dif:uart",
+        "@lowrisc_opentitan//sw/device/lib/testing:aon_timer_testutils",
+        "@lowrisc_opentitan//sw/device/lib/testing:flash_ctrl_testutils",
+        "@lowrisc_opentitan//sw/device/lib/testing:rstmgr_testutils",
+        "@lowrisc_opentitan//sw/device/lib/testing:rv_plic_testutils",
+    ],
+)
+
+matcha_dv_test(
+    name = "rstmgr_cpu_info_test",
+    srcs = ["@lowrisc_opentitan//sw/device/tests:rstmgr_cpu_info_test.c"],
+    deps = [
+        ":test_dv_lib_opentitan",
+        "//sw/device/lib/dif:rstmgr",
+        "@lowrisc_opentitan//sw/device/lib/base:abs_mmio",
+        "@lowrisc_opentitan//sw/device/lib/base:macros",
+        "@lowrisc_opentitan//sw/device/lib/dif:pwrmgr",
+        "@lowrisc_opentitan//sw/device/lib/dif:rv_core_ibex",
+        "@lowrisc_opentitan//sw/device/lib/testing:aon_timer_testutils",
+        "@lowrisc_opentitan//sw/device/lib/testing:rstmgr_testutils",
+    ],
+)
+
 # Smoke tests
 matcha_dv_test(
     name = "aes_smoketest",
diff --git a/sw/device/tests/rstmgr_alert_info_test.c b/sw/device/tests/rstmgr_alert_info_test.c
new file mode 100644
index 0000000..c0eb428
--- /dev/null
+++ b/sw/device/tests/rstmgr_alert_info_test.c
@@ -0,0 +1,852 @@
+// Copyright 2023 Google LLC.
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#include "alert_handler_regs.h"  // Generated.
+#include "hw/top_matcha/sw/autogen/top_matcha.h"
+#include "sw/device/lib/base/math.h"
+#include "sw/device/lib/base/mmio.h"
+#include "sw/device/lib/dif/dif_alert_handler.h"
+#include "sw/device/lib/dif/dif_aon_timer.h"
+#include "sw/device/lib/dif/dif_cam_ctrl.h"
+#include "sw/device/lib/dif/dif_i2c.h"
+#include "sw/device/lib/dif/dif_otp_ctrl.h"
+#include "sw/device/lib/dif/dif_pwrmgr.h"
+#include "sw/device/lib/dif/dif_rstmgr.h"
+#include "sw/device/lib/dif/dif_rv_core_ibex.h"
+#include "sw/device/lib/dif/dif_rv_plic.h"
+#include "sw/device/lib/dif/dif_rv_timer.h"
+#include "sw/device/lib/dif/dif_spi_host.h"
+#include "sw/device/lib/dif/dif_uart.h"
+#include "sw/device/lib/runtime/irq.h"
+#include "sw/device/lib/runtime/log.h"
+#include "sw/device/lib/testing/alert_handler_testutils.h"
+#include "sw/device/lib/testing/aon_timer_testutils.h"
+#include "sw/device/lib/testing/flash_ctrl_testutils.h"
+#include "sw/device/lib/testing/rstmgr_testutils.h"
+#include "sw/device/lib/testing/rv_plic_testutils.h"
+#include "sw/device/lib/testing/test_framework/FreeRTOSConfig.h"
+#include "sw/device/lib/testing/test_framework/check.h"
+#include "sw/device/lib/testing/test_framework/ottf_main.h"
+/*
+  RSTMGR ALERT_INFO Test
+
+  This test runs some alert / dump scenario and check integrity of
+  ALERT_INFO coming from alert_hander to rstmgr.
+
+  From dif_rstmgr_reset_info_t, there are 8 different resets.
+  This test covers 3 of those (kDifRstmgrResetInfoSw,
+  kDifRstmgrResetInfoWatchdog, kDifRstmgrResetInfoEscalation).
+  kDifRstmgrResetInfoNdm will be added as a separate test after ndm request test
+  is available. Test goes for 3 rounds, and on each round it creates a different
+  reset scenario.
+
+  Round 1: Single Class profile
+  - Trigger alert from i2c0..2 by calling alert_force.
+  - This will trigger kDifAlertHandlerIrqClassa from alert_handler.
+  - Also alert_info start to transfer from alert_handler to rstmgr.
+  - Upon detecting interrupt, 'ottf_external_isr' request reset to rstmgr
+  - After reset, alert_info will be available at rstmgr.
+  - Read alert_info from rstmgr and compare with expected value.
+
+  Round 2: Multi Classes profile
+  - Trigger alert from uart0..3 and otp_ctrl.
+  - Setup the aon_timer wdog bark and bite timeouts.
+  - Let the timer expire to create watchdog bite.
+  - After reset, coalesced alert info from uarts and otp_ctrl
+    will be available from rstmgr.
+  - Read alert_info from rstmgr and compare with expected value.
+
+  Round 3: All Classes profile with alert escalation
+  - Trigger rv_core_ibex alert that leads to an interrupt.
+  - Trigger other alerts for all classes.
+  - rv_core_ibex alert will be escalated to phase2 then it will trigger
+    reset.
+  - Read alert_info from rstmgr and compare with expected value.
+
+  Round 4: Local alert
+  - Trigger local alert by setting ping timeout value to 1.
+  - Once alert triggers interrupt, call sw_device reset from interrupt
+    handler.
+  - After reset, read alert_info from rstmgr and compare with expected value.
+
+ */
+
+OTTF_DEFINE_TEST_CONFIG();
+
+enum {
+  kWdogBarkMicros = 200,          // us
+  kWdogBiteMicros = 200,          // us
+  kEscalationPhase0Micros = 300,  // us
+  kEscalationPhase1Micros = 200,  // us
+  kEscalationPhase2Micros = 100,  // us
+  kRoundOneDelay = 100,           // us
+  kRoundTwoDelay = 100,           // us
+  kRoundThreeDelay = 1000         // us
+};
+
+static const uint32_t kPlicTarget = kTopMatchaPlicTargetIbex0;
+static dif_flash_ctrl_state_t flash_ctrl;
+static dif_rstmgr_t rstmgr;
+static dif_alert_handler_t alert_handler;
+static dif_uart_t uart0, uart1, uart2, uart3;
+static dif_otp_ctrl_t otp_ctrl;
+static dif_spi_host_t spi_host;
+static dif_rv_plic_t plic;
+static dif_rv_core_ibex_t rv_core_ibex;
+static dif_aon_timer_t aon_timer;
+static dif_pwrmgr_t pwrmgr;
+static dif_i2c_t i2c0, i2c1, i2c2;
+
+// Components added in matcha
+static dif_uart_t smc_uart;
+static dif_rv_timer_t timer_smc, timer_smc2;
+static dif_cam_ctrl_t cam_ctrl;
+static dif_rv_plic_t plic_smc;
+static dif_spi_host_t spi_host2;
+static dif_rv_core_ibex_t rv_core_ibex_smc;
+
+typedef struct node {
+  const char *name;
+  dif_alert_handler_alert_t alert;
+  dif_alert_handler_class_t class;
+} node_t;
+
+typedef enum test_round {
+  kRound1 = 0,
+  kRound2 = 1,
+  kRound3 = 2,
+  kRound4 = 3,
+  kRoundTotal = 4
+} test_round_t;
+
+static volatile test_round_t global_test_round;
+static volatile uint32_t global_alert_called;
+static const dif_alert_handler_escalation_phase_t
+    kEscProfiles[][ALERT_HANDLER_PARAM_N_CLASSES] = {
+        [kDifAlertHandlerClassA] = {{.phase = kDifAlertHandlerClassStatePhase0,
+                                     .signal = 0,
+                                     .duration_cycles = 5000},
+                                    {.phase = kDifAlertHandlerClassStatePhase1,
+                                     .signal = 0,
+                                     .duration_cycles = 3000}},
+        [kDifAlertHandlerClassB] = {{.phase = kDifAlertHandlerClassStatePhase1,
+                                     .signal = 0,
+                                     .duration_cycles = 3000}},
+        [kDifAlertHandlerClassC] = {{.phase = kDifAlertHandlerClassStatePhase0,
+                                     .signal = 0,
+                                     .duration_cycles = 5000},
+                                    {.phase = kDifAlertHandlerClassStatePhase1,
+                                     .signal = 0,
+                                     .duration_cycles = 3000}},
+        [kDifAlertHandlerClassD] = {{.phase = kDifAlertHandlerClassStatePhase0,
+                                     .signal = 0,
+                                     .duration_cycles = 7200},
+                                    {.phase = kDifAlertHandlerClassStatePhase1,
+                                     .signal = 1,
+                                     .duration_cycles = 4800},
+                                    {.phase = kDifAlertHandlerClassStatePhase2,
+                                     .signal = 3,
+                                     .duration_cycles = 2400}}};
+
+static const dif_alert_handler_class_config_t
+    kConfigProfiles[ALERT_HANDLER_PARAM_N_CLASSES] = {
+        [kDifAlertHandlerClassA] =
+            {
+                .auto_lock_accumulation_counter = kDifToggleDisabled,
+                .accumulator_threshold = 0,
+                .irq_deadline_cycles = 240,
+                .escalation_phases = kEscProfiles[kDifAlertHandlerClassA],
+                .escalation_phases_len = 2,
+                .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase1,
+            },
+        [kDifAlertHandlerClassB] =
+            {
+                .auto_lock_accumulation_counter = kDifToggleDisabled,
+                .accumulator_threshold = 0,
+                .irq_deadline_cycles = 240,
+                .escalation_phases = kEscProfiles[kDifAlertHandlerClassB],
+                .escalation_phases_len = 1,
+                .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase1,
+            },
+        [kDifAlertHandlerClassC] =
+            {
+                .auto_lock_accumulation_counter = kDifToggleDisabled,
+                .accumulator_threshold = 0,
+                .irq_deadline_cycles = 240,
+                .escalation_phases = kEscProfiles[kDifAlertHandlerClassC],
+                .escalation_phases_len = 2,
+                .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase1,
+            },
+        [kDifAlertHandlerClassD] =
+            {
+                .auto_lock_accumulation_counter = kDifToggleDisabled,
+                .accumulator_threshold = 0,
+                .irq_deadline_cycles = 1000,
+                .escalation_phases = kEscProfiles[kDifAlertHandlerClassD],
+                .escalation_phases_len = 3,
+                .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase3,
+            },
+};
+
+typedef struct test_alert_info {
+  char *test_name;
+  alert_info_t alert_info;
+} test_alert_info_t;
+
+static test_alert_info_t kExpectedInfo[kRoundTotal] = {
+    [kRound1] =
+        {
+            .test_name = "Single class(ClassA)",
+            .alert_info =
+                {
+                    .class_accum_cnt = {3, 0, 0, 0},
+                    .class_esc_state = {kCstatePhase0, kCstateIdle, kCstateIdle,
+                                        kCstateIdle},
+                },
+        },
+    [kRound2] =
+        {
+            .test_name = "Multi classes(ClassB,C)",
+            .alert_info =
+                {
+                    .class_accum_cnt = {0, 1, 4, 0},
+                    .class_esc_state = {kCstateIdle, kCstatePhase1,
+                                        kCstatePhase0, kCstateIdle},
+                },
+        },
+    [kRound3] =
+        {
+            .test_name = "All classes",
+            .alert_info =
+                {
+                    .class_accum_cnt = {1, 1, 1, 1},
+                    .class_esc_state = {kCstatePhase0, kCstatePhase1,
+                                        kCstatePhase0, kCstatePhase0},
+                },
+        },
+    [kRound4] =
+        {
+            .test_name = "Local alert(ClassB)",
+            .alert_info =
+                {
+                    .loc_alert_cause =
+                        (0x1 << kDifAlertHandlerLocalAlertAlertPingFail),
+                    .class_accum_cnt = {0, 1, 0, 0},
+                    .class_esc_state = {kCstateIdle, kCstatePhase2, kCstateIdle,
+                                        kCstateIdle},
+                },
+        },
+};
+
+static node_t test_node[kTopMatchaAlertPeripheralLast];
+
+static void set_extra_alert(volatile uint32_t *set) {
+  CHECK_DIF_OK(dif_uart_alert_force(&uart0, kDifUartAlertFatalFault));
+  CHECK_DIF_OK(dif_i2c_alert_force(&i2c0, kDifI2cAlertFatalFault));
+  CHECK_DIF_OK(dif_spi_host_alert_force(&spi_host, kDifSpiHostAlertFatalFault));
+  *set = 1;
+}
+
+/**
+ * External ISR.
+ *
+ * Handles all peripheral interrupts on Ibex. PLIC asserts an external interrupt
+ * line to the CPU, which results in a call to this OTTF ISR. This ISR
+ * overrides the default OTTF implementation.
+ */
+void ottf_external_isr(void) {
+  top_matcha_plic_peripheral_t peripheral;
+  dif_rv_plic_irq_id_t irq_id;
+  uint32_t irq = 0;
+
+  CHECK_DIF_OK(dif_rv_plic_irq_claim(&plic, kPlicTarget, &irq_id));
+
+  peripheral = (top_matcha_plic_peripheral_t)
+      top_matcha_plic_interrupt_for_peripheral[irq_id];
+
+  if (peripheral == kTopMatchaPlicPeripheralAonTimerAon) {
+    irq =
+        (dif_aon_timer_irq_t)(irq_id -
+                              (dif_rv_plic_irq_id_t)
+                                  kTopMatchaPlicIrqIdAonTimerAonWkupTimerExpired);
+
+    CHECK_DIF_OK(dif_aon_timer_irq_acknowledge(&aon_timer, irq));
+  } else if (peripheral == kTopMatchaPlicPeripheralAlertHandler) {
+    irq =
+        (irq_id - (dif_rv_plic_irq_id_t)kTopMatchaPlicIrqIdAlertHandlerClassa);
+
+    switch (irq) {
+      case 0:  // class a
+        LOG_INFO("IRQ: class A");
+        CHECK_DIF_OK(dif_alert_handler_alert_acknowledge(
+            &alert_handler, kDifI2cAlertFatalFault));
+
+        // check classes
+        dif_alert_handler_class_state_t state;
+        CHECK_DIF_OK(dif_alert_handler_get_class_state(
+            &alert_handler, kDifAlertHandlerClassA, &state));
+
+        // sw reset for round 1
+        if (global_test_round == kRound1) {
+          CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
+        }
+        CHECK_DIF_OK(dif_alert_handler_irq_acknowledge(&alert_handler, irq));
+
+        break;
+      case 1:
+        LOG_INFO("IRQ: class B %d", global_test_round);
+        break;
+      case 2:
+        LOG_INFO("IRQ: class C");
+        break;
+      case 3:
+        if (global_alert_called == 0) {
+          set_extra_alert(&global_alert_called);
+          LOG_INFO("IRQ: class D");
+          LOG_INFO("IRQ: extra alert called");
+        }
+        break;
+      default:
+        LOG_FATAL("IRQ: unknown irq %d", irq);
+    }
+  }
+  // Complete the IRQ by writing the IRQ source to the Ibex specific CC
+  // register.
+
+  CHECK_DIF_OK(dif_rv_plic_irq_complete(&plic, kPlicTarget, irq_id));
+}
+
+static void print_alert_cause(alert_info_t info) {
+  for (uint32_t i = 0; i < ALERT_HANDLER_PARAM_N_ALERTS; ++i) {
+    LOG_INFO("alert_cause[%d]: 0x%x", i, info.alert_cause[i]);
+  }
+}
+
+/*
+ * Configure alert for i2c0..i2c2 s.t.
+ * .alert class = class A
+ * .escalation phase0,1
+ * .disable ping timer
+ */
+static void prgm_alert_handler_round1(void) {
+  dif_alert_handler_class_t alert_class = kDifAlertHandlerClassA;
+
+  for (int i = kTopMatchaAlertPeripheralI2c0;
+       i < kTopMatchaAlertPeripheralI2c2 + 1; ++i) {
+    CHECK_DIF_OK(dif_alert_handler_configure_alert(
+        &alert_handler, test_node[i].alert, test_node[i].class,
+        /*enabled=*/kDifToggleEnabled, /*locked=*/kDifToggleEnabled));
+  }
+
+  CHECK_DIF_OK(dif_alert_handler_configure_class(
+      &alert_handler, alert_class, kConfigProfiles[alert_class],
+      /*enabled=*/kDifToggleEnabled, /*locked=*/kDifToggleEnabled));
+  CHECK_DIF_OK(dif_alert_handler_configure_ping_timer(
+      &alert_handler, 0, /*enabled=*/kDifToggleEnabled,
+      /*locked=*/kDifToggleEnabled));
+}
+
+/*
+ * Configure alert for uart0..3
+ * .alert class = class C
+ * .escalation phase0,1
+ * Configure alert from aon timer
+ * .alert class = class B
+ * .escalation phases 1
+ *
+ * Set esc_phases.signal = 0 for all cases to avoid
+ * watchdog timer freeze.
+ */
+static void prgm_alert_handler_round2(void) {
+  dif_alert_handler_class_t alert_classes[] = {kDifAlertHandlerClassC,
+                                               kDifAlertHandlerClassB};
+  dif_alert_handler_class_config_t class_configs[] = {
+      kConfigProfiles[kDifAlertHandlerClassC],
+      kConfigProfiles[kDifAlertHandlerClassB]};
+
+  for (int i = kTopMatchaAlertPeripheralUart0;
+       i < kTopMatchaAlertPeripheralUart3 + 1; ++i) {
+    CHECK_DIF_OK(dif_alert_handler_configure_alert(
+        &alert_handler, test_node[i].alert, test_node[i].class,
+        /*enabled=*/kDifToggleEnabled, /*locked=*/kDifToggleEnabled));
+  }
+  CHECK_DIF_OK(dif_alert_handler_configure_alert(
+      &alert_handler, test_node[kTopMatchaAlertPeripheralOtpCtrl].alert,
+      test_node[kTopMatchaAlertPeripheralOtpCtrl].class,
+      /*enabled=*/kDifToggleEnabled,
+      /*locked=*/kDifToggleEnabled));
+
+  for (int i = 0; i < ARRAYSIZE(alert_classes); ++i) {
+    CHECK_DIF_OK(dif_alert_handler_configure_class(
+        &alert_handler, alert_classes[i], class_configs[i],
+        /*enabled=*/kDifToggleEnabled,
+        /*locked=*/kDifToggleEnabled));
+  }
+}
+
+/*
+ * Set I2c0 alert to class a
+ *     spi_host alert to class b
+ *     uart0 alert to class c and
+ *     the rest to class d
+ *
+ * For class d, enable 3 phases and escalation reset will be
+ * triggered at phase2
+ */
+
+static void prgm_alert_handler_round3(void) {
+  // Enable all incoming alerts. This will create ping timeout event
+  // for all possible alerts and will see the timeout more often.
+  dif_alert_handler_class_t alert_class;
+
+  for (int i = 0; i < ALERT_HANDLER_PARAM_N_ALERTS; ++i) {
+    if (i == kTopMatchaAlertIdSpiHost0FatalFault) {
+      alert_class = kDifAlertHandlerClassB;
+    } else if (i == kTopMatchaAlertIdUart0FatalFault) {
+      alert_class = kDifAlertHandlerClassC;
+    } else if (i == kTopMatchaAlertIdI2c0FatalFault) {
+      alert_class = kDifAlertHandlerClassA;
+    } else {
+      alert_class = kDifAlertHandlerClassD;
+    }
+    CHECK_DIF_OK(dif_alert_handler_configure_alert(
+        &alert_handler, i, alert_class, /*enabled=*/kDifToggleEnabled,
+        /*locked=*/kDifToggleEnabled));
+  }
+
+  dif_alert_handler_class_t alert_classes[] = {
+      kDifAlertHandlerClassA, kDifAlertHandlerClassB, kDifAlertHandlerClassC,
+      kDifAlertHandlerClassD};
+
+  dif_alert_handler_class_config_t class_d_config =
+      kConfigProfiles[kDifAlertHandlerClassD];
+
+  dif_alert_handler_escalation_phase_t class_d_esc[3];
+
+  if (kDeviceType == kDeviceFpgaNexus) {
+    uint32_t cpu_freq = kClockFreqCpuHz;
+    uint32_t peri_freq = kClockFreqPeripheralHz;
+    uint32_t cycles = kUartTxFifoCpuCycles * (cpu_freq / peri_freq);
+    class_d_esc[0] = kEscProfiles[kDifAlertHandlerClassD][0];
+    class_d_esc[1] = kEscProfiles[kDifAlertHandlerClassD][1];
+    class_d_esc[2] = kEscProfiles[kDifAlertHandlerClassD][2];
+    // we must allow sufficient time for the device to complete uart
+    class_d_esc[0].duration_cycles = cycles;
+    class_d_config.escalation_phases = class_d_esc;
+  }
+
+  LOG_INFO("Escalation set to %d cycles",
+           class_d_config.escalation_phases[0].duration_cycles);
+
+  dif_alert_handler_class_config_t class_configs[] = {
+      kConfigProfiles[kDifAlertHandlerClassA],
+      kConfigProfiles[kDifAlertHandlerClassB],
+      kConfigProfiles[kDifAlertHandlerClassC], class_d_config};
+
+  for (int i = 0; i < ARRAYSIZE(alert_classes); ++i) {
+    CHECK_DIF_OK(dif_alert_handler_configure_class(
+        &alert_handler, alert_classes[i], class_configs[i],
+        /*enabled=*/kDifToggleEnabled,
+        /*locked=*/kDifToggleEnabled));
+  }
+
+  CHECK_DIF_OK(dif_alert_handler_configure_ping_timer(
+      &alert_handler, 1000, /*enabled=*/kDifToggleEnabled,
+      /*locked=*/kDifToggleEnabled));
+
+  CHECK_DIF_OK(dif_rv_core_ibex_alert_force(&rv_core_ibex,
+                                            kDifRvCoreIbexAlertRecovSwErr));
+}
+
+/*
+ * Configure all global alert enable and mapped to class A
+ * Configure local alert enable and mapped to class B
+ * For class B, set signal to 3 to trigger escalation reset
+ * Change ping timeout value to 1 to cause alert ping timeout
+ */
+
+static void prgm_alert_handler_round4(void) {
+  dif_alert_handler_alert_t alerts[ALERT_HANDLER_PARAM_N_ALERTS];
+  dif_alert_handler_class_t alert_classes[ALERT_HANDLER_PARAM_N_ALERTS];
+
+  // Enable all alerts to enable ping associate with them.
+  for (int i = 0; i < ALERT_HANDLER_PARAM_N_ALERTS; ++i) {
+    CHECK_DIF_OK(dif_alert_handler_configure_alert(
+        &alert_handler, i, kDifAlertHandlerClassA, kDifToggleEnabled,
+        kDifToggleEnabled));
+  }
+
+  // Enable alert ping fail local alert and configure that to classb.
+  dif_alert_handler_local_alert_t loc_alert =
+      kDifAlertHandlerLocalAlertAlertPingFail;
+  dif_alert_handler_class_t loc_alert_class = kDifAlertHandlerClassB;
+
+  dif_alert_handler_escalation_phase_t esc_phases[] = {
+      {.phase = kDifAlertHandlerClassStatePhase2,
+       .signal = 3,
+       .duration_cycles = 2000}};
+
+  dif_alert_handler_class_config_t class_config = {
+      .auto_lock_accumulation_counter = kDifToggleDisabled,
+      .accumulator_threshold = 0,
+      .irq_deadline_cycles = 240,
+      .escalation_phases = esc_phases,
+      .escalation_phases_len = ARRAYSIZE(esc_phases),
+      .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase3,
+  };
+
+  CHECK_DIF_OK(dif_alert_handler_configure_local_alert(
+      &alert_handler, loc_alert, loc_alert_class, kDifToggleEnabled,
+      kDifToggleEnabled));
+
+  CHECK_DIF_OK(dif_alert_handler_configure_class(
+      &alert_handler, kDifAlertHandlerClassB, class_config, kDifToggleEnabled,
+      kDifToggleEnabled));
+
+  CHECK_DIF_OK(dif_alert_handler_configure_ping_timer(
+      &alert_handler, 1, kDifToggleEnabled, kDifToggleEnabled));
+
+  // Enables alert handler irq.
+  CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
+      &alert_handler, kDifAlertHandlerIrqClassb, kDifToggleEnabled));
+}
+
+static void peripheral_init(void) {
+  CHECK_DIF_OK(dif_spi_host_init(
+      mmio_region_from_addr(TOP_MATCHA_SPI_HOST0_BASE_ADDR), &spi_host));
+  CHECK_DIF_OK(
+      dif_i2c_init(mmio_region_from_addr(TOP_MATCHA_I2C0_BASE_ADDR), &i2c0));
+  CHECK_DIF_OK(
+      dif_i2c_init(mmio_region_from_addr(TOP_MATCHA_I2C1_BASE_ADDR), &i2c1));
+  CHECK_DIF_OK(
+      dif_i2c_init(mmio_region_from_addr(TOP_MATCHA_I2C2_BASE_ADDR), &i2c2));
+  CHECK_DIF_OK(
+      dif_uart_init(mmio_region_from_addr(TOP_MATCHA_UART0_BASE_ADDR), &uart0));
+  CHECK_DIF_OK(
+      dif_uart_init(mmio_region_from_addr(TOP_MATCHA_UART1_BASE_ADDR), &uart1));
+  CHECK_DIF_OK(
+      dif_uart_init(mmio_region_from_addr(TOP_MATCHA_UART2_BASE_ADDR), &uart2));
+  CHECK_DIF_OK(
+      dif_uart_init(mmio_region_from_addr(TOP_MATCHA_UART3_BASE_ADDR), &uart3));
+  CHECK_DIF_OK(dif_otp_ctrl_init(
+      mmio_region_from_addr(TOP_MATCHA_OTP_CTRL_CORE_BASE_ADDR), &otp_ctrl));
+  CHECK_DIF_OK(dif_aon_timer_init(
+      mmio_region_from_addr(TOP_MATCHA_AON_TIMER_AON_BASE_ADDR), &aon_timer));
+  CHECK_DIF_OK(dif_pwrmgr_init(
+      mmio_region_from_addr(TOP_MATCHA_PWRMGR_AON_BASE_ADDR), &pwrmgr));
+  CHECK_DIF_OK(dif_rv_core_ibex_init(
+      mmio_region_from_addr(TOP_MATCHA_RV_CORE_IBEX_SEC_CFG_BASE_ADDR),
+      &rv_core_ibex));
+
+  // Initilize components added in matcha
+  CHECK_DIF_OK(dif_uart_init(
+      mmio_region_from_addr(TOP_MATCHA_SMC_UART_BASE_ADDR), &smc_uart));
+  CHECK_DIF_OK(dif_rv_timer_init(
+      mmio_region_from_addr(TOP_MATCHA_RV_TIMER_SMC_BASE_ADDR), &timer_smc));
+  CHECK_DIF_OK(dif_cam_ctrl_init(
+      mmio_region_from_addr(TOP_MATCHA_CAM_CTRL_BASE_ADDR), &cam_ctrl));
+  CHECK_DIF_OK(dif_rv_plic_init(
+      mmio_region_from_addr(TOP_MATCHA_RV_PLIC_SMC_BASE_ADDR), &plic_smc));
+  CHECK_DIF_OK(dif_spi_host_init(
+      mmio_region_from_addr(TOP_MATCHA_SPI_HOST2_BASE_ADDR), &spi_host2));
+  CHECK_DIF_OK(dif_rv_timer_init(
+      mmio_region_from_addr(TOP_MATCHA_RV_TIMER_SMC2_BASE_ADDR), &timer_smc2));
+  CHECK_DIF_OK(dif_rv_core_ibex_init(
+      mmio_region_from_addr(TOP_MATCHA_RV_CORE_IBEX_SMC_CFG_BASE_ADDR),
+      &rv_core_ibex_smc));
+
+  // Set pwrmgr reset_en
+  CHECK_DIF_OK(dif_pwrmgr_set_request_sources(&pwrmgr, kDifPwrmgrReqTypeReset,
+                                              kDifPwrmgrResetRequestSourceTwo,
+                                              kDifToggleEnabled));
+}
+
+static void collect_alert_dump_and_compare(test_round_t round) {
+  dif_rstmgr_alert_info_dump_segment_t dump[DIF_RSTMGR_ALERT_INFO_MAX_SIZE];
+  size_t seg_size;
+  alert_info_t actual_info;
+
+  CHECK_DIF_OK(dif_rstmgr_alert_info_dump_read(
+      &rstmgr, dump, DIF_RSTMGR_ALERT_INFO_MAX_SIZE, &seg_size));
+
+  LOG_INFO("Testname: %s  DUMP SIZE %d", kExpectedInfo[round].test_name,
+           seg_size);
+  for (int i = 0; i < seg_size; i++) {
+    LOG_INFO("DUMP:%d: 0x%x", i, dump[i]);
+  }
+
+  actual_info = alert_info_dump_to_struct(dump, seg_size);
+
+  if (round == kRound4) {
+    // Check local alert only.
+    // While testing ping timeout for local alert,
+    // global alert ping timeout can be triggered
+    // dut to short timeout value.
+    // However, alert source of this ping timeout can be choosen randomly,
+    // as documented in issue #2321, so we only check local alert cause.
+    LOG_INFO("loc_alert_cause: exp: %08x   obs: %08x",
+             kExpectedInfo[round].alert_info.loc_alert_cause,
+             actual_info.loc_alert_cause);
+    CHECK(kExpectedInfo[round].alert_info.loc_alert_cause ==
+          actual_info.loc_alert_cause);
+  } else {
+    LOG_INFO("observed alert cause:");
+    print_alert_cause(actual_info);
+    LOG_INFO("expected alert cause:");
+    print_alert_cause(kExpectedInfo[round].alert_info);
+    for (int i = 0; i < ALERT_HANDLER_PARAM_N_ALERTS; ++i) {
+      CHECK(kExpectedInfo[round].alert_info.alert_cause[i] ==
+                actual_info.alert_cause[i],
+            "At alert cause %d Expected %d, got %d", i,
+            kExpectedInfo[round].alert_info.alert_cause[i],
+            actual_info.alert_cause[i]);
+    }
+  }
+
+  for (int i = 0; i < ALERT_HANDLER_PARAM_N_CLASSES; ++i) {
+    // We cannot do an "equal" check here since some of the alerts may
+    // be fatal and cause the accumulated count to continuously grow.
+    CHECK(kExpectedInfo[round].alert_info.class_accum_cnt[i] <=
+              actual_info.class_accum_cnt[i],
+          "alert_info.class_accum_cnt[%d] mismatch exp:0x%x  obs:0x%x", i,
+          kExpectedInfo[round].alert_info.class_accum_cnt[i],
+          actual_info.class_accum_cnt[i]);
+  }
+  for (int i = 0; i < ALERT_HANDLER_PARAM_N_CLASSES; ++i) {
+    // added '<' because expected state can be minimum phase but
+    // depends on simulation, sometimes it captures higher phase.
+    CHECK(kExpectedInfo[round].alert_info.class_esc_state[i] <=
+              actual_info.class_esc_state[i],
+          "alert_info.class_esc_state[%d] mismatch exp:0x%x  obs:0x%x", i,
+          kExpectedInfo[round].alert_info.class_esc_state[i],
+          actual_info.class_esc_state[i]);
+  }
+}
+
+static node_t test_node[kTopMatchaAlertPeripheralLast] = {
+    [kTopMatchaAlertPeripheralSpiHost0] =
+        {
+            .name = "SPIHOST0",
+            .alert = kTopMatchaAlertIdSpiHost0FatalFault,
+            .class = kDifAlertHandlerClassB,
+        },
+    [kTopMatchaAlertPeripheralOtpCtrl] =
+        {
+            .name = "OTPCTRL",
+            .alert = kTopMatchaAlertIdOtpCtrlFatalBusIntegError,
+            .class = kDifAlertHandlerClassB,
+        },
+    [kTopMatchaAlertPeripheralKmac] =
+        {
+            .name = "KMAC",
+            .alert = kTopMatchaAlertIdKmacFatalFaultErr,
+            .class = kDifAlertHandlerClassB,
+        },
+    [kTopMatchaAlertPeripheralUart0] =
+        {
+            .name = "UART0",
+            .alert = kTopMatchaAlertIdUart0FatalFault,
+            .class = kDifAlertHandlerClassC,
+        },
+    [kTopMatchaAlertPeripheralUart1] =
+        {
+            .name = "UART1",
+            .alert = kTopMatchaAlertIdUart1FatalFault,
+            .class = kDifAlertHandlerClassC,
+        },
+    [kTopMatchaAlertPeripheralUart2] =
+        {
+            .name = "UART2",
+            .alert = kTopMatchaAlertIdUart2FatalFault,
+            .class = kDifAlertHandlerClassC,
+        },
+    [kTopMatchaAlertPeripheralUart3] =
+        {
+            .name = "UART3",
+            .alert = kTopMatchaAlertIdUart3FatalFault,
+            .class = kDifAlertHandlerClassC,
+        },
+    [kTopMatchaAlertPeripheralI2c0] =
+        {
+            .name = "I2C0",
+            .alert = kTopMatchaAlertIdI2c0FatalFault,
+            .class = kDifAlertHandlerClassA,
+        },
+    [kTopMatchaAlertPeripheralI2c1] =
+        {
+            .name = "I2C1",
+            .alert = kTopMatchaAlertIdI2c1FatalFault,
+            .class = kDifAlertHandlerClassA,
+        },
+    [kTopMatchaAlertPeripheralI2c2] =
+        {
+            .name = "I2C2",
+            .alert = kTopMatchaAlertIdI2c2FatalFault,
+            .class = kDifAlertHandlerClassA,
+        },
+};
+
+static void init_expected_cause() {
+  kExpectedInfo[kRound1]
+      .alert_info.alert_cause[kTopMatchaAlertIdI2c0FatalFault] = 1;
+  kExpectedInfo[kRound1]
+      .alert_info.alert_cause[kTopMatchaAlertIdI2c1FatalFault] = 1;
+  kExpectedInfo[kRound1]
+      .alert_info.alert_cause[kTopMatchaAlertIdI2c2FatalFault] = 1;
+
+  kExpectedInfo[kRound2]
+      .alert_info.alert_cause[kTopMatchaAlertIdUart0FatalFault] = 1;
+  kExpectedInfo[kRound2]
+      .alert_info.alert_cause[kTopMatchaAlertIdUart1FatalFault] = 1;
+  kExpectedInfo[kRound2]
+      .alert_info.alert_cause[kTopMatchaAlertIdUart2FatalFault] = 1;
+  kExpectedInfo[kRound2]
+      .alert_info.alert_cause[kTopMatchaAlertIdUart3FatalFault] = 1;
+  kExpectedInfo[kRound2]
+      .alert_info.alert_cause[kTopMatchaAlertIdOtpCtrlFatalBusIntegError] = 1;
+
+  kExpectedInfo[kRound3]
+      .alert_info.alert_cause[kTopMatchaAlertIdRvCoreIbexSecRecovSwErr] = 1;
+  kExpectedInfo[kRound3]
+      .alert_info.alert_cause[kTopMatchaAlertIdUart0FatalFault] = 1;
+  kExpectedInfo[kRound3]
+      .alert_info.alert_cause[kTopMatchaAlertIdI2c0FatalFault] = 1;
+  kExpectedInfo[kRound3]
+      .alert_info.alert_cause[kTopMatchaAlertIdSpiHost0FatalFault] = 1;
+};
+
+bool test_main(void) {
+  // Enable global and external IRQ at Ibex.
+  irq_global_ctrl(true);
+  irq_external_ctrl(true);
+
+  // set expected values
+  init_expected_cause();
+
+  CHECK_DIF_OK(dif_rstmgr_init(
+      mmio_region_from_addr(TOP_MATCHA_RSTMGR_AON_BASE_ADDR), &rstmgr));
+  CHECK_DIF_OK(dif_alert_handler_init(
+      mmio_region_from_addr(TOP_MATCHA_ALERT_HANDLER_BASE_ADDR),
+      &alert_handler));
+  CHECK_DIF_OK(dif_rv_plic_init(
+      mmio_region_from_addr(TOP_MATCHA_RV_PLIC_BASE_ADDR), &plic));
+
+  CHECK_DIF_OK(dif_flash_ctrl_init_state(
+      &flash_ctrl,
+      mmio_region_from_addr(TOP_MATCHA_FLASH_CTRL_CORE_BASE_ADDR)));
+
+  peripheral_init();
+
+  // Enable all interrupts used in this test.
+  rv_plic_testutils_irq_range_enable(&plic, kPlicTarget,
+                                     kTopMatchaPlicIrqIdAlertHandlerClassa,
+                                     kTopMatchaPlicIrqIdAlertHandlerClassd);
+  rv_plic_testutils_irq_range_enable(
+      &plic, kPlicTarget, kTopMatchaPlicIrqIdAonTimerAonWkupTimerExpired,
+      kTopMatchaPlicIrqIdAonTimerAonWdogTimerBark);
+
+  // First check the flash stored value.
+  uint32_t event_idx = flash_ctrl_testutils_counter_get(0);
+
+  // Enable flash access
+  flash_ctrl_testutils_default_region_access(&flash_ctrl,
+                                             /*rd_en*/ true,
+                                             /*prog_en*/ true,
+                                             /*erase_en*/ true,
+                                             /*scramble_en*/ false,
+                                             /*ecc_en*/ false,
+                                             /*he_en*/ false);
+
+  // Increment flash counter to know where we are.
+  flash_ctrl_testutils_counter_increment(&flash_ctrl, 0);
+
+  LOG_INFO("Test round %d", event_idx);
+
+  // enable alert info
+  CHECK_DIF_OK(dif_rstmgr_alert_info_set_enabled(&rstmgr, kDifToggleEnabled));
+
+  // Check if there was a HW reset caused by the escalation.
+  dif_rstmgr_reset_info_bitfield_t rst_info;
+  rst_info = rstmgr_testutils_reason_get();
+  rstmgr_testutils_reason_clear();
+
+  LOG_INFO("reset info = 0x%02X", rst_info);
+  global_alert_called = 0;
+
+  // TODO(#13098): Change to equality after #13277 is merged.
+  if (rst_info & kDifRstmgrResetInfoPor) {
+    global_test_round = kRound1;
+    prgm_alert_handler_round1();
+
+    CHECK_DIF_OK(dif_i2c_alert_force(&i2c0, kDifI2cAlertFatalFault));
+    CHECK_DIF_OK(dif_i2c_alert_force(&i2c1, kDifI2cAlertFatalFault));
+    CHECK_DIF_OK(dif_i2c_alert_force(&i2c2, kDifI2cAlertFatalFault));
+    CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
+        &alert_handler, kDifAlertHandlerIrqClassa, kDifToggleEnabled));
+
+    // Give an enough delay until sw rest happens.
+    busy_spin_micros(kRoundOneDelay);
+    CHECK(false, "Should have reset before this line");
+  } else if (rst_info == kDifRstmgrResetInfoSw && event_idx == 1) {
+    collect_alert_dump_and_compare(kRound1);
+    global_test_round = kRound2;
+    prgm_alert_handler_round2();
+
+    // Setup the aon_timer the wdog bark and bite timeouts.
+    uint64_t bark_cycles =
+        udiv64_slow(kWdogBarkMicros * kClockFreqAonHz, 1000000, NULL);
+    uint64_t bite_cycles =
+        udiv64_slow(kWdogBiteMicros * kClockFreqAonHz, 1000000, NULL);
+    aon_timer_testutils_watchdog_config(&aon_timer, bark_cycles, bite_cycles,
+                                        false);
+
+    CHECK_DIF_OK(dif_uart_alert_force(&uart0, kDifUartAlertFatalFault));
+    CHECK_DIF_OK(dif_uart_alert_force(&uart1, kDifUartAlertFatalFault));
+    CHECK_DIF_OK(dif_uart_alert_force(&uart2, kDifUartAlertFatalFault));
+    CHECK_DIF_OK(dif_uart_alert_force(&uart3, kDifUartAlertFatalFault));
+    CHECK_DIF_OK(dif_otp_ctrl_alert_force(&otp_ctrl,
+                                          kDifOtpCtrlAlertFatalBusIntegError));
+    CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
+        &alert_handler, kDifAlertHandlerIrqClassb, kDifToggleEnabled));
+    CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
+        &alert_handler, kDifAlertHandlerIrqClassc, kDifToggleEnabled));
+
+    busy_spin_micros(kRoundTwoDelay);
+    CHECK(false, "Should have reset before this line");
+  } else if (rst_info == kDifRstmgrResetInfoWatchdog) {
+    collect_alert_dump_and_compare(kRound2);
+
+    global_test_round = kRound3;
+    prgm_alert_handler_round3();
+    CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
+        &alert_handler, kDifAlertHandlerIrqClassd, kDifToggleEnabled));
+
+    busy_spin_micros(kRoundThreeDelay);
+    CHECK(false, "Should have reset before this line");
+  } else if (rst_info == kDifRstmgrResetInfoEscalation && event_idx == 3) {
+    collect_alert_dump_and_compare(kRound3);
+    global_test_round = kRound4;
+    prgm_alert_handler_round4();
+    // Previously, this test assumed that escalation would always happen
+    // within a fixed amount of time.  However, that is not necessarily
+    // the case for ping timeouts.  The ping mechanism randomly selects a
+    // peripheral to check.  However, since the selection vector is larger
+    // than the number of peripherals we have, it does not always select a valid
+    // peripheral. When the alert handler does not select a valid peripheral,
+    // it simply moves on to the test the next ping. However the max wait time
+    // until the next ping is checked is in the mS range.
+    // Therefore, the test should not make that assumption and just wait in
+    // place.
+    wait_for_interrupt();
+  } else if (rst_info == kDifRstmgrResetInfoEscalation && event_idx == 4) {
+    collect_alert_dump_and_compare(kRound4);
+
+    return true;
+  } else {
+    LOG_FATAL("unexpected reset info %d", rst_info);
+  }
+
+  return false;
+}
diff --git a/sw/device/tests/sim_dv/BUILD b/sw/device/tests/sim_dv/BUILD
index c45c6f5..ed9042d 100644
--- a/sw/device/tests/sim_dv/BUILD
+++ b/sw/device/tests/sim_dv/BUILD
@@ -62,6 +62,7 @@
         "//sw/device/lib/dif:pinmux",
         "//sw/device/lib/dif:rstmgr",
         "//sw/device/lib/dif:rv_plic_sec",
+        "//sw/device/lib/testing:alert_handler_testutils",
         "//sw/device/lib/testing:pinmux_testutils",
         "//sw/device/tests:test_dv_lib",
         "@lowrisc_opentitan//sw/device/lib/base:abs_mmio",
@@ -70,7 +71,6 @@
         "@lowrisc_opentitan//sw/device/lib/dif:pwrmgr",
         "@lowrisc_opentitan//sw/device/lib/dif:rv_timer",
         "@lowrisc_opentitan//sw/device/lib/dif:sysrst_ctrl",
-        "@lowrisc_opentitan//sw/device/lib/testing:alert_handler_testutils",
         "@lowrisc_opentitan//sw/device/lib/testing:aon_timer_testutils",
         "@lowrisc_opentitan//sw/device/lib/testing:flash_ctrl_testutils",
         "@lowrisc_opentitan//sw/device/lib/testing:pwrmgr_testutils",
@@ -173,6 +173,7 @@
         "//sw/device/lib/dif:clkmgr",
         "//sw/device/lib/dif:rstmgr",
         "//sw/device/lib/dif:rv_plic_sec",
+        "//sw/device/lib/testing:alert_handler_testutils",
         "//sw/device/lib/testing:clkmgr_testutils",
         "//sw/device/lib/testing:isr_testutils",
         "//sw/device/tests:test_dv_lib",
@@ -180,7 +181,6 @@
         "@lowrisc_opentitan//sw/device/lib/dif:entropy_src",
         "@lowrisc_opentitan//sw/device/lib/dif:pwrmgr",
         "@lowrisc_opentitan//sw/device/lib/dif:sensor_ctrl",
-        "@lowrisc_opentitan//sw/device/lib/testing:alert_handler_testutils",
         "@lowrisc_opentitan//sw/device/lib/testing:aon_timer_testutils",
         "@lowrisc_opentitan//sw/device/lib/testing:pwrmgr_testutils",
         "@lowrisc_opentitan//sw/device/lib/testing:rstmgr_testutils",
@@ -355,10 +355,10 @@
         "//sw/device/lib/dif:alert_handler",
         "//sw/device/lib/dif:clkmgr",
         "//sw/device/lib/dif:rstmgr",
+        "//sw/device/lib/testing:alert_handler_testutils",
         "//sw/device/tests:test_dv_lib_opentitan",
         "@lowrisc_opentitan//sw/device/lib/dif:keymgr",
         "@lowrisc_opentitan//sw/device/lib/dif:rv_core_ibex",
-        "@lowrisc_opentitan//sw/device/lib/testing:alert_handler_testutils",
         "@lowrisc_opentitan//sw/device/lib/testing:keymgr_testutils",
         "@lowrisc_opentitan//sw/device/lib/testing:rstmgr_testutils",
     ],
@@ -396,6 +396,7 @@
         "//sw/device/lib/dif:clkmgr",
         "//sw/device/lib/dif:rstmgr",
         "//sw/device/lib/dif:rv_plic_sec",
+        "//sw/device/lib/testing:alert_handler_testutils",
         "//sw/device/tests:test_dv_lib_opentitan",
         "@lowrisc_opentitan//sw/device/lib/base:abs_mmio",
         "@lowrisc_opentitan//sw/device/lib/dif:aes",
@@ -408,7 +409,6 @@
         "@lowrisc_opentitan//sw/device/lib/dif:rom_ctrl",
         "@lowrisc_opentitan//sw/device/lib/dif:rv_core_ibex",
         "@lowrisc_opentitan//sw/device/lib/dif:sram_ctrl",
-        "@lowrisc_opentitan//sw/device/lib/testing:alert_handler_testutils",
         "@lowrisc_opentitan//sw/device/lib/testing:aon_timer_testutils",
         "@lowrisc_opentitan//sw/device/lib/testing:flash_ctrl_testutils",
         "@lowrisc_opentitan//sw/device/lib/testing:rstmgr_testutils",
diff --git a/util/topgen_matcha.py b/util/topgen_matcha.py
index 117f153..fc618ff 100755
--- a/util/topgen_matcha.py
+++ b/util/topgen_matcha.py
@@ -1443,7 +1443,7 @@
 
         # generate parameters for chip-level environment package
         tpl_fname = "chip_env_pkg__params.sv.tpl"
-        alert_handler_chip_data_path = TOPGEN_TEMPLATE_MATCHA_PATH / tpl_fname
+        alert_handler_chip_data_path = TOPGEN_TEMPLATE_PATH / tpl_fname
         template_contents = generate_top(completecfg, name_to_block,
                                          str(alert_handler_chip_data_path))
 
diff --git a/util/topgen_matcha/templates/chip_env_pkg__params.sv.tpl b/util/topgen_matcha/templates/chip_env_pkg__params.sv.tpl
deleted file mode 100644
index 3e1783d..0000000
--- a/util/topgen_matcha/templates/chip_env_pkg__params.sv.tpl
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2023 Google LLC.
-// Copyright lowRISC contributors.
-// Licensed under the Apache License, Version 2.0, see LICENSE for details.
-// SPDX-License-Identifier: Apache-2.0
-
-// Generated by topgen_matcha.py
-
-<%
-  import re
-%>\
-parameter string LIST_OF_ALERTS[] = {
-% for alert in top["alert"]:
-  % if not re.match(r".*smc\d?_fatal_fault", alert["name"]):
-    % if loop.last:
-  "${alert["name"]}"
-    % else:
-  "${alert["name"]}",
-    % endif
-  % endif
-% endfor
-};
-
-parameter uint NUM_ALERTS = ${len(top["alert"])};