Merge "Add sram_ctrl tests to edacloud."
diff --git a/hw/top_matcha/dv/chip_sim_cfg.hjson b/hw/top_matcha/dv/chip_sim_cfg.hjson
index c5e8959..ed15271 100644
--- a/hw/top_matcha/dv/chip_sim_cfg.hjson
+++ b/hw/top_matcha/dv/chip_sim_cfg.hjson
@@ -1063,7 +1063,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
@@ -1071,7 +1071,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"]
}
{
@@ -2104,6 +2104,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",
@@ -2207,6 +2208,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/hw/top_matcha/ip/smc/rtl/smc_controller.sv b/hw/top_matcha/ip/smc/rtl/smc_controller.sv
index fc4f76d..275ec8c 100644
--- a/hw/top_matcha/ip/smc/rtl/smc_controller.sv
+++ b/hw/top_matcha/ip/smc/rtl/smc_controller.sv
@@ -762,11 +762,11 @@
exc_cause_o = ExcCauseIrqTimerS;
end
- if (ptw_spec_walk_i) begin
+ if (ptw_spec_walk_i | ptw_instr_walk_i) begin
ptw_pc_change_instr_d = 1'b1;
- ctrl_fsm_ns = PAGING_IF;
ptw_exc_cause_d = exc_cause_o;
ptw_exc_pc_mux_d = exc_pc_mux_o;
+ ptw_pc_mux_d = pc_mux_o;
end
end
diff --git a/hw/top_matcha/ip/smc/rtl/smc_core.sv b/hw/top_matcha/ip/smc/rtl/smc_core.sv
index 5559088..e65e55e 100644
--- a/hw/top_matcha/ip/smc/rtl/smc_core.sv
+++ b/hw/top_matcha/ip/smc/rtl/smc_core.sv
@@ -557,7 +557,8 @@
.ptw_instr_walk_i (mmu_ptw_instr_walk),
.ptw_spec_iwalk_i (mmu_ptw_spec_iwalk),
.ptw_if_flush_i (mmu_ptw_if_flush),
- .ptw_pc_change_instr_i(ptw_pc_change_instr)
+ .ptw_pc_change_instr_i(ptw_pc_change_instr),
+ .legal_page_boundary_i(mmu_legal_boundary)
);
// Core is waiting for the ISide when ID/EX stage is ready for a new instruction but none are
diff --git a/hw/top_matcha/ip/smc/rtl/smc_if_stage.sv b/hw/top_matcha/ip/smc/rtl/smc_if_stage.sv
index 4a09596..24f1efa 100644
--- a/hw/top_matcha/ip/smc/rtl/smc_if_stage.sv
+++ b/hw/top_matcha/ip/smc/rtl/smc_if_stage.sv
@@ -121,7 +121,8 @@
input logic ptw_instr_walk_i,
input logic ptw_spec_iwalk_i,
input logic ptw_if_flush_i,
- input logic ptw_pc_change_instr_i
+ input logic ptw_pc_change_instr_i,
+ input logic legal_page_boundary_i
);
logic instr_valid_id_d, instr_valid_id_q;
@@ -337,33 +338,34 @@
smc_prefetch_buffer #(
.ResetAll (ResetAll)
) prefetch_buffer_i (
- .clk_i ( clk_i ),
- .rst_ni ( rst_ni ),
+ .clk_i ( clk_i ),
+ .rst_ni ( rst_ni ),
- .req_i ( req_i ),
+ .req_i ( req_i ),
- .branch_i ( prefetch_branch ),
- .addr_i ( prefetch_addr ),
+ .branch_i ( prefetch_branch ),
+ .addr_i ( prefetch_addr ),
- .ready_i ( fetch_ready ),
- .valid_o ( fetch_valid_raw ),
- .rdata_o ( fetch_rdata ),
- .addr_o ( fetch_addr ),
- .err_o ( fetch_err ),
- .err_plus2_o ( fetch_err_plus2 ),
+ .ready_i ( fetch_ready ),
+ .valid_o ( fetch_valid_raw ),
+ .rdata_o ( fetch_rdata ),
+ .addr_o ( fetch_addr ),
+ .err_o ( fetch_err ),
+ .err_plus2_o ( fetch_err_plus2 ),
- .instr_req_o ( instr_req_o ),
- .instr_addr_o ( instr_addr_o ),
- .instr_gnt_i ( instr_gnt_i ),
- .instr_rvalid_i ( instr_rvalid_i ),
- .instr_rdata_i ( instr_rdata_i[31:0] ),
- .instr_err_i ( instr_err ),
+ .instr_req_o ( instr_req_o ),
+ .instr_addr_o ( instr_addr_o ),
+ .instr_gnt_i ( instr_gnt_i ),
+ .instr_rvalid_i ( instr_rvalid_i ),
+ .instr_rdata_i ( instr_rdata_i[31:0] ),
+ .instr_err_i ( instr_err ),
- .busy_o ( prefetch_busy ),
+ .busy_o ( prefetch_busy ),
- .ptw_instr_walk_i ( ptw_instr_walk_i ),
- .ptw_spec_iwalk_i ( ptw_spec_iwalk_i ),
- .ptw_if_flush_i ( ptw_if_flush_i )
+ .ptw_instr_walk_i ( ptw_instr_walk_i ),
+ .ptw_spec_iwalk_i ( ptw_spec_iwalk_i ),
+ .ptw_if_flush_i ( ptw_if_flush_i ),
+ .legal_page_boundary_i( legal_page_boundary_i )
);
// ICache tieoffs
logic unused_icen, unused_icinv, unused_scr_key_valid;
diff --git a/hw/top_matcha/ip/smc/rtl/smc_mmu.sv b/hw/top_matcha/ip/smc/rtl/smc_mmu.sv
index f02890c..30fc471 100644
--- a/hw/top_matcha/ip/smc/rtl/smc_mmu.sv
+++ b/hw/top_matcha/ip/smc/rtl/smc_mmu.sv
@@ -266,7 +266,7 @@
always_comb begin
legal_boundary_d = 1'b0;
if (paging_en) begin
- if ((~itlb_hit & lsu_outstanding_req & dtlb_ptw_active) | instr_ptw) begin
+ if ((~itlb_hit & lsu_outstanding_req) | instr_ptw) begin
legal_boundary_d = cross_page_boundary & ~pc_mod_instr_i;
end
end
@@ -317,7 +317,7 @@
instr_page_fault_o = imem_access_error;
// ITLB miss
- end else if (paging_en && ptw_active_o) begin
+ end else if (paging_en && (ptw_active_o | ~itlb_hit)) begin
// Stall IF while PTW occurs through DMEM. Allow fetches that cross
// page boundaries to complete.
diff --git a/hw/top_matcha/ip/smc/rtl/smc_prefetch_buffer.sv b/hw/top_matcha/ip/smc/rtl/smc_prefetch_buffer.sv
index d3f80f0..0c2a69d 100644
--- a/hw/top_matcha/ip/smc/rtl/smc_prefetch_buffer.sv
+++ b/hw/top_matcha/ip/smc/rtl/smc_prefetch_buffer.sv
@@ -41,7 +41,8 @@
// MMU
input logic ptw_instr_walk_i,
input logic ptw_spec_iwalk_i,
- input logic ptw_if_flush_i
+ input logic ptw_if_flush_i,
+ input logic legal_page_boundary_i
);
localparam int unsigned NUM_REQS = 2;
@@ -89,7 +90,8 @@
// The fifo is ready to accept a new request if it is not full - including space reserved for
// requests already outstanding.
// Overlay the fifo fill state with the outstanding requests to see if there is space.
- assign fifo_ready = ~&(fifo_busy | rdata_outstanding_rev) & ~ptw_spec_iwalk_i & ~ptw_instr_walk_i;
+ assign fifo_ready = ~&(fifo_busy | rdata_outstanding_rev) & ~ptw_spec_iwalk_i &
+ ~ptw_instr_walk_i & ~legal_page_boundary_i;
smc_fetch_fifo #(
.NUM_REQS (NUM_REQS),
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 d9f748d..d5823a8 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"])};