[test] Implement rom_e2e_asm_watchdog bark tests
Test that the watchdog bark restarts the ROM when the bite threshold is
artificially inflated to UINT32_MAX.
This commit also modifies rom_start.S:
* it enables NMIs from the watchdog timer,
* it configures the bark and bite thresholds at 1 and 1.1 seconds,
respectively, and
* it adds a few labels so the GDB tests can make fewer assumptions about
the code.
Signed-off-by: Dan McArdle <dmcardle@google.com>
diff --git a/sw/device/silicon_creator/rom/e2e/BUILD b/sw/device/silicon_creator/rom/e2e/BUILD
index 70e6c03..a45668a 100644
--- a/sw/device/silicon_creator/rom/e2e/BUILD
+++ b/sw/device/silicon_creator/rom/e2e/BUILD
@@ -1499,6 +1499,7 @@
rom_kind = "Rom",
tags = [
"cw310",
+ "exclusive",
"vivado",
],
)
@@ -1550,6 +1551,7 @@
rom_kind = "Rom",
tags = [
"cw310",
+ "exclusive",
"vivado",
],
)
@@ -1568,6 +1570,92 @@
# Dict that also includes an invalid redaction value for test purposes.
REDACT = structs.to_dict(CONST.SHUTDOWN.REDACT)
+# Ensure that the watchdog restarts the ROM even when the bite threshold has
+# been artificially inflated.
+[
+ opentitan_gdb_fpga_cw310_test(
+ name = "rom_e2e_asm_watchdog_fpga_cw310_test_otp_" + otp_name,
+ timeout = "short",
+ gdb_script = """
+ target extended-remote :3333
+
+ echo :::: Send OpenOCD the 'reset halt' command.\\n
+ monitor reset halt
+
+ echo :::: Load ROM symbols into GDB.\\n
+ file rom.elf
+
+ echo :::: Run until we check whether ROM execution is enabled.\\n
+ break kRomStartBootMaybeHalt
+ continue
+
+ printf ":::: PC=%p. Expected PC=%p.\\n", $pc, kRomStartBootMaybeHalt
+ if $pc != kRomStartBootMaybeHalt
+ quit 42
+ end
+
+ echo :::: Pretend execution is enabled.\\n
+ set $pc = kRomStartBootExecEn
+
+ break kRomStartStoreT1ToBiteThold
+ continue
+ printf ":::: PC=%p. Expected PC=%p.\\n", $pc, kRomStartStoreT1ToBiteThold
+ if $pc != kRomStartStoreT1ToBiteThold
+ quit 43
+ end
+
+ # Set the bite threshold to UINT32_MAX. We want to exercise that the
+ # bark causes control to reach the interrupt handler.
+ set $t1 = 0xffffffff
+
+ echo :::: Run until right after configuring the watchdog timer.\\n
+ break kRomStartWatchdogEnabled
+ continue
+
+ printf ":::: PC=%p. Expected PC=%p.\\n", $pc, kRomStartWatchdogEnabled
+ if $pc != kRomStartWatchdogEnabled
+ quit 44
+ end
+
+ echo :::: Set breakpoint on NMI handler.\\n
+ delete breakpoints
+ break _asm_exception_handler
+
+ echo :::: Wait for interrupt.\\n
+ set $pc = kRomStartBootMaybeHalt
+ echo :::: Continue.\\n
+ continue
+
+ printf ":::: PC=%p. Expected PC=%p.\\n", $pc, _asm_exception_handler
+ if $pc != _asm_exception_handler
+ quit 45
+ end
+ """,
+ gdb_script_symlinks = {
+ "//sw/device/silicon_creator/rom:rom_fpga_cw310.elf": "rom.elf",
+ },
+ rom_bitstream = ":rom_otp_{}_exec_disabled".format(otp_name),
+ rom_kind = "Rom",
+ tags = [
+ "cw310",
+ "exclusive",
+ "vivado",
+ ],
+ )
+ for otp_name in OTP_CFGS_EXEC_DISABLED
+]
+
+test_suite(
+ name = "rom_e2e_asm_watchdog",
+ tags = [
+ "cw310",
+ "vivado",
+ ],
+ tests = ["rom_e2e_asm_watchdog_fpga_cw310_test_otp_" + otp_name for otp_name in OTP_CFGS_EXEC_DISABLED],
+)
+
+# Shutdown Redact Test
+
REDACT.update({"INVALID": 0x0})
[
diff --git a/sw/device/silicon_creator/rom/rom_start.S b/sw/device/silicon_creator/rom/rom_start.S
index 6965da8..a74ae49 100644
--- a/sw/device/silicon_creator/rom/rom_start.S
+++ b/sw/device/silicon_creator/rom/rom_start.S
@@ -17,10 +17,19 @@
#include "otp_ctrl_regs.h"
#include "pinmux_regs.h"
#include "pwrmgr_regs.h"
+#include "rv_core_ibex_regs.h"
#include "sensor_ctrl_regs.h"
#include "sram_ctrl_regs.h"
+// This macro defines convenience labels for tests that use a debugger.
+#define LABEL_FOR_TEST(kName_) .local kName_ ; kName_: ;
+
.equ UNIMP, 0xc0001073
+// We will configure the watchdog timers to reset the chip in the event that the
+// ROM stalls. The watchdog's bite and bark thresholds are set to 1 and 1.1
+// seconds, respectively, assuming a clock frequency of 200 kHz.
+.equ WDOG_BITE_THOLD, 0x30d400
+.equ WDOG_BARK_THOLD, WDOG_BITE_THOLD * 11 / 10
/**
* ROM interrupt vectors.
@@ -40,15 +49,15 @@
/**
* Initial RISC-V vectored exception/interrupt handlers.
*
- * After reset all interrupts are disabled. Only exceptions (interrupt 0) and
- * non-maskable interrupts (interrupt 31) are possible. For simplicity however
- * we just set all interrupt handlers to the same exception handler.
+ * After reset, all interrupts are disabled. Only exceptions (interrupt 0) and
+ * non-maskable interrupts (interrupt 31) are possible. For simplicity,
+ * however, we just set all interrupt handlers to the same exception handler.
*
- * Since the C runtime is not initialized immediately after reset the initial
+ * Since the C runtime is not initialized immediately after reset, the initial
* interrupt vector must only call functions written in assembly. Once the C
- * runtime is intialized the interrupt vector should be replaced.
+ * runtime is intialized, the interrupt vector should be replaced.
*
- * If the hardware is operating correctly the assembly interrupt handlers
+ * If the hardware is operating correctly, the assembly interrupt handlers
* should never be called.
*
* Note that the Ibex reset handler (entry point) immediately follows this
@@ -136,6 +145,7 @@
la gp, __global_pointer$
.option pop
+LABEL_FOR_TEST(kRomStartBootMaybeHalt)
// Check if we should halt here.
li a0, (TOP_EARLGREY_OTP_CTRL_CORE_BASE_ADDR + \
OTP_CTRL_SW_CFG_WINDOW_REG_OFFSET)
@@ -145,7 +155,13 @@
wfi
j .L_halt_loop
+LABEL_FOR_TEST(kRomStartBootExecEn)
.L_exec_en:
+ // Enable NMIs from the watchdog timer.
+ li t0, TOP_EARLGREY_RV_CORE_IBEX_CFG_BASE_ADDR
+ li t1, (1 << RV_CORE_IBEX_NMI_ENABLE_WDOG_EN_BIT)
+ sw t1, RV_CORE_IBEX_NMI_ENABLE_REG_OFFSET(t0)
+
// Configure the power manager to enable resets.
// Note: this enables all types of reset request for simplicity.
li t0, TOP_EARLGREY_PWRMGR_AON_BASE_ADDR
@@ -156,20 +172,19 @@
li t1, (1 << PWRMGR_CFG_CDC_SYNC_SYNC_BIT)
sw t1, PWRMGR_CFG_CDC_SYNC_REG_OFFSET(t0)
- // Setup the watchdog bite timer in order to reset the chip if the ROM stalls.
- // The value below corresponds to 1 s for a clock frequency of 200 kHz.
- // Since interrupts are disabled the watchdog bark will have no effect
- // therefore the bark threshold is just set to the highest possible value.
+ // Configure the watchdog's bark and bite thresholds.
li t0, TOP_EARLGREY_AON_TIMER_AON_BASE_ADDR
- li t1, 0x30d40
- sw t1, AON_TIMER_WDOG_BITE_THOLD_REG_OFFSET(t0)
- li t1, 0xffffffff
+ li t1, WDOG_BARK_THOLD
sw t1, AON_TIMER_WDOG_BARK_THOLD_REG_OFFSET(t0)
+ li t1, WDOG_BITE_THOLD
+LABEL_FOR_TEST(kRomStartStoreT1ToBiteThold)
+ sw t1, AON_TIMER_WDOG_BITE_THOLD_REG_OFFSET(t0)
// Enable the watchdog timer.
li t1, (1 << AON_TIMER_WDOG_CTRL_ENABLE_BIT)
sw t1, AON_TIMER_WDOG_CTRL_REG_OFFSET(t0)
+LABEL_FOR_TEST(kRomStartWatchdogEnabled)
// Clear all the machine-defined interrupts, `MEIE`, `MTIE`, and `MSIE` fields
// of `mie`.
li t0, 0xFFFF0888
diff --git a/sw/device/tests/BUILD b/sw/device/tests/BUILD
index 1e2adbf..fe8047b 100644
--- a/sw/device/tests/BUILD
+++ b/sw/device/tests/BUILD
@@ -272,6 +272,11 @@
opentitan_functest(
name = "aon_timer_irq_test",
srcs = ["aon_timer_irq_test.c"],
+ targets = [
+ "dv",
+ "verilator",
+ "cw310_test_rom",
+ ],
deps = [
"//hw/top_earlgrey/sw/autogen:top_earlgrey",
"//sw/device/lib/base:math",
@@ -291,6 +296,11 @@
opentitan_functest(
name = "aon_timer_smoketest",
srcs = ["aon_timer_smoketest.c"],
+ targets = [
+ "dv",
+ "verilator",
+ "cw310_test_rom",
+ ],
deps = [
"//sw/device/lib/base:mmio",
"//sw/device/lib/dif:aon_timer",
@@ -853,6 +863,11 @@
opentitan_functest(
name = "flash_ctrl_idle_low_power_test",
srcs = ["flash_ctrl_idle_low_power_test.c"],
+ targets = [
+ "dv",
+ "verilator",
+ "cw310_test_rom",
+ ],
verilator = verilator_params(
tags = [
"broken",