Merge "[HW][TOP] Move some DIOs to MIOs."
diff --git a/hw/dv/tools/dvsim/sim.mk b/hw/dv/tools/dvsim/sim.mk
index cbac3af..d803100 100644
--- a/hw/dv/tools/dvsim/sim.mk
+++ b/hw/dv/tools/dvsim/sim.mk
@@ -91,7 +91,7 @@
else \
bazel_cquery="$${bazel_label}"; \
fi; \
- if [[ $$sw_image =~ "test_rom" || $${flags[@]} =~ "matcha" ]]; then \
+ if [[ $$sw_image =~ "test_rom" || $${flags[@]} =~ "matcha" || $${flags[@]} =~ "test_in_rom" ]]; then \
build_repo="matcha"; \
cd ${proj_root}; \
else \
diff --git a/hw/top_matcha/dv/chip_sim_cfg.hjson b/hw/top_matcha/dv/chip_sim_cfg.hjson
index 0bb3864..620b47e 100644
--- a/hw/top_matcha/dv/chip_sim_cfg.hjson
+++ b/hw/top_matcha/dv/chip_sim_cfg.hjson
@@ -947,7 +947,7 @@
{
name: chip_sw_otp_ctrl_escalation
uvm_test_seq: chip_sw_otp_ctrl_escalation_vseq
- sw_images: ["//sw/device/tests/sim_dv:all_escalation_resets_test:1"]
+ sw_images: ["//sw/device/tests/sim_dv:all_escalation_resets_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+bypass_alert_ready_to_end_check=1"]
reseed: 1
@@ -1261,7 +1261,7 @@
{
name: chip_sw_rv_core_ibex_rnd
uvm_test_seq: chip_sw_base_vseq
- sw_images: ["sw/device/tests:rv_core_ibex_rnd_test:1"]
+ sw_images: ["sw/device/tests:rv_core_ibex_rnd_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
// Timeout based on a 10min dvsim runtime.
run_opts: ["+sw_test_timeout_ns=10_000_000"]
@@ -1269,7 +1269,7 @@
{
name: chip_sw_rv_core_ibex_nmi_irq
uvm_test_seq: chip_sw_base_vseq
- sw_images: ["sw/device/tests:rv_core_ibex_nmi_irq_test:1"]
+ sw_images: ["sw/device/tests:rv_core_ibex_nmi_irq_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+sw_test_timeout_ns=10_000_000"]
}
@@ -1597,7 +1597,7 @@
{
name: chip_sw_sensor_ctrl_alert
uvm_test_seq: chip_sw_base_vseq
- sw_images: ["//sw/device/tests:sensor_ctrl_alert_test:1"]
+ sw_images: ["//sw/device/tests:sensor_ctrl_alert_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+sw_test_timeout_ns=40_000_000"]
reseed: 5
@@ -1605,14 +1605,14 @@
{
name: chip_sw_sensor_ctrl_status
uvm_test_seq: chip_sw_sensor_ctrl_status_intr_vseq
- sw_images: ["//sw/device/tests/sim_dv:sensor_ctrl_status_test:1"]
+ sw_images: ["//sw/device/tests/sim_dv:sensor_ctrl_status_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+sw_test_timeout_ns=40_000_000"]
}
{
name: chip_sw_pwrmgr_sleep_sensor_ctrl_alert_wakeup
uvm_test_seq: chip_sw_base_vseq
- sw_images: ["//sw/device/tests:sensor_ctrl_wakeup_test:1"]
+ sw_images: ["//sw/device/tests:sensor_ctrl_wakeup_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+sw_test_timeout_ns=8_000_000"]
}
@@ -1667,8 +1667,8 @@
}
{
name: chip_sw_clkmgr_off_peri
- uvm_test_seq: chip_sw_base_vseq
- sw_images: ["//sw/device/tests:clkmgr_off_peri_test:1"]
+ uvm_test_seq: chip_sw_clkmgr_off_peri_vseq
+ sw_images: ["//sw/device/tests:clkmgr_off_peri_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+sw_test_timeout_ns=30_000_000"]
}
@@ -1793,7 +1793,7 @@
{
name: chip_sw_rv_dm_ndm_reset_req_when_cpu_halted
uvm_test_seq: "chip_sw_rv_dm_ndm_reset_when_cpu_halted_vseq"
- sw_images: ["//sw/device/tests/sim_dv:rv_dm_ndm_reset_req_when_cpu_halted:1"]
+ sw_images: ["//sw/device/tests/sim_dv:rv_dm_ndm_reset_req_when_cpu_halted:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+use_jtag_dmi=1"]
}
@@ -2025,6 +2025,7 @@
"chip_sw_rstmgr_sw_rst",
"chip_sw_rv_plic_smoketest",
"chip_sw_rv_timer_irq",
+ "chip_sw_sensor_ctrl_status",
"chip_sw_smc_cam_irq_test",
"chip_sw_smc_ctrl_test",
"chip_sw_smc_env_test",
@@ -2059,6 +2060,7 @@
"chip_sw_aon_timer_smoketest",
"chip_sw_atomics_test",
"chip_sw_cam_ctrl_test",
+ "chip_sw_clkmgr_off_peri",
"chip_sw_clkmgr_smoketest",
"chip_sw_crt_test",
"chip_sw_csrng_smoketest",
@@ -2075,15 +2077,22 @@
"chip_sw_keymgr_key_derivation",
"chip_sw_kmac_idle",
"chip_sw_kmac_smoketest",
- "chip_sw_otbn_smoketest",
- "chip_sw_otp_ctrl_smoketest",
"chip_sw_lc_ctrl_otp_hw_cfg",
+ "chip_sw_otbn_smoketest",
+ "chip_sw_otp_ctrl_escalation",
+ "chip_sw_otp_ctrl_smoketest",
+ "chip_sw_pwrmgr_sleep_sensor_ctrl_alert_wakeup",
"chip_sw_rom_ctrl_integrity_check",
"chip_sw_rstmgr_smoketest",
"chip_sw_rstmgr_sw_req",
"chip_sw_rstmgr_sw_rst",
+ "chip_sw_rv_core_ibex_nmi_irq",
+ "chip_sw_rv_core_ibex_rnd",
+ "chip_sw_rv_dm_ndm_reset_req_when_cpu_halted",
"chip_sw_rv_plic_smoketest",
"chip_sw_rv_timer_irq",
+ "chip_sw_sensor_ctrl_alert",
+ "chip_sw_sensor_ctrl_status",
"chip_sw_smc_cam_irq_test",
"chip_sw_smc_ctrl_test",
"chip_sw_smc_env_test",
@@ -2108,6 +2117,9 @@
"chip_sw_sram_ctrl_smoketest",
"chip_sw_uart_smoketest",
"chip_sw_uart_tx_rx",
+ "chip_tap_straps_dev",
+ "chip_tap_straps_prod",
+ "chip_tap_straps_rma",
]
}
{
@@ -2122,6 +2134,7 @@
"chip_sw_aon_timer_smoketest",
"chip_sw_atomics_test",
"chip_sw_cam_ctrl_test",
+ "chip_sw_clkmgr_off_peri",
"chip_sw_clkmgr_smoketest",
"chip_sw_crt_test",
"chip_sw_csrng_smoketest",
@@ -2138,15 +2151,22 @@
"chip_sw_keymgr_key_derivation",
"chip_sw_kmac_idle",
"chip_sw_kmac_smoketest",
- "chip_sw_otbn_smoketest",
- "chip_sw_otp_ctrl_smoketest",
"chip_sw_lc_ctrl_otp_hw_cfg",
+ "chip_sw_otbn_smoketest",
+ "chip_sw_otp_ctrl_escalation",
+ "chip_sw_otp_ctrl_smoketest",
+ "chip_sw_pwrmgr_sleep_sensor_ctrl_alert_wakeup",
"chip_sw_rom_ctrl_integrity_check",
"chip_sw_rstmgr_smoketest",
"chip_sw_rstmgr_sw_req",
"chip_sw_rstmgr_sw_rst",
+ "chip_sw_rv_core_ibex_nmi_irq",
+ "chip_sw_rv_core_ibex_rnd",
+ "chip_sw_rv_dm_ndm_reset_req_when_cpu_halted",
"chip_sw_rv_plic_smoketest",
"chip_sw_rv_timer_irq",
+ "chip_sw_sensor_ctrl_alert",
+ "chip_sw_sensor_ctrl_status",
"chip_sw_smc_cam_irq_test",
"chip_sw_smc_ctrl_test",
"chip_sw_smc_env_test",
@@ -2171,6 +2191,9 @@
"chip_sw_sram_ctrl_smoketest",
"chip_sw_uart_smoketest",
"chip_sw_uart_tx_rx",
+ "chip_tap_straps_dev",
+ "chip_tap_straps_prod",
+ "chip_tap_straps_rma",
]
}
{
diff --git a/hw/top_matcha/dv/env/chip_env.core b/hw/top_matcha/dv/env/chip_env.core
index 778355e..28fb4bf 100644
--- a/hw/top_matcha/dv/env/chip_env.core
+++ b/hw/top_matcha/dv/env/chip_env.core
@@ -143,6 +143,7 @@
- seq_lib/chip_sw_power_sleep_load_vseq.sv: {is_include_file: true}
- seq_lib/chip_sw_power_virus_vseq.sv: {is_include_file: true}
- seq_lib/chip_sw_ast_clk_rst_inputs_vseq.sv: {is_include_file: true}
+ - seq_lib/chip_sw_clkmgr_off_peri_vseq.sv: {is_include_file: true}
- autogen/chip_env_pkg__params.sv: {is_include_file: true}
- alerts_if.sv
- ast_ext_clk_if.sv
diff --git a/hw/top_matcha/dv/env/seq_lib/chip_sw_clkmgr_off_peri_vseq.sv b/hw/top_matcha/dv/env/seq_lib/chip_sw_clkmgr_off_peri_vseq.sv
new file mode 100644
index 0000000..8b7fe9d
--- /dev/null
+++ b/hw/top_matcha/dv/env/seq_lib/chip_sw_clkmgr_off_peri_vseq.sv
@@ -0,0 +1,113 @@
+// 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
+
+class chip_sw_clkmgr_off_peri_vseq extends chip_sw_base_vseq;
+ `uvm_object_utils(chip_sw_clkmgr_off_peri_vseq)
+
+ `uvm_object_new
+
+ localparam uint SampTimeNS = 2; // Sample time
+ localparam uint NumOfSamples = 100000;
+ localparam string ClkIoDiv2Path = "tb.dut.top_matcha.u_clkmgr_aon.clocks_o.clk_io_div2_peri";
+ localparam string ClkIoDiv2SwEnPath = "tb.dut.top_matcha.u_clkmgr_aon.clk_io_div2_peri_sw_en";
+ localparam string ClkVideoPath = "tb.dut.top_matcha.u_clkmgr_aon.clocks_o.clk_video_peri";
+ localparam string ClkVideoSwEnPath = "tb.dut.top_matcha.u_clkmgr_aon.clk_video_peri_sw_en";
+ localparam string ClkAudioPath = "tb.dut.top_matcha.u_clkmgr_aon.clocks_o.clk_audio_peri";
+ localparam string ClkAudioSwEnPath = "tb.dut.top_matcha.u_clkmgr_aon.clk_audio_peri_sw_en";
+ localparam string ClkSmcPath = "tb.dut.top_matcha.u_clkmgr_aon.clocks_o.clk_smc_peri";
+ localparam string ClkSmcSwEnPath = "tb.dut.top_matcha.u_clkmgr_aon.clk_smc_peri_sw_en";
+
+
+ virtual task body();
+ super.body();
+
+ // Wait until we reach the SW test state.
+ `DV_WAIT(cfg.sw_test_status_vif.sw_test_status == SwTestStatusInTest)
+
+ // Run the clkmgr peri off tests.
+ clk_io_div2_peri_off_test();
+ clk_video_peri_off_test();
+ clk_audio_peri_off_test();
+ clk_smc_peri_off_test();
+
+ endtask
+
+ virtual task clk_io_div2_peri_off_test();
+ bit retval = 1;
+
+ `DV_WAIT(cfg.sw_logger_vif.printed_log == "Testing peripheral clock 1");
+ #100us;
+ `DV_CHECK(uvm_hdl_read(ClkIoDiv2SwEnPath, retval));
+ if (retval !== 1'b0)
+ `uvm_error(`gfn, $sformatf("Sw enable signal for clk_io_div2 has wrong value"));
+ `DV_CHECK(uvm_hdl_read(ClkIoDiv2Path, retval));
+ if (retval !== 1'b0)
+ `uvm_error(`gfn, $sformatf("clk_io_div2 has wrong value"));
+ for (int i=0; i<NumOfSamples; i++) begin
+ #(SampTimeNS * 1ns);
+ `DV_CHECK(uvm_hdl_read(ClkIoDiv2Path, retval));
+ if (retval !== 1'b0)
+ `uvm_error(`gfn, $sformatf("clk_io_div2 has wrong value"));
+ end
+ endtask
+
+ virtual task clk_video_peri_off_test();
+ bit retval = 1;
+
+ `DV_WAIT(cfg.sw_logger_vif.printed_log == "Testing peripheral clock 4");
+ #100us;
+ `DV_CHECK(uvm_hdl_read(ClkVideoSwEnPath, retval));
+ if (retval !== 1'b0)
+ `uvm_error(`gfn, $sformatf("Sw enable signal for clk_video has wrong value"));
+ `DV_CHECK(uvm_hdl_read(ClkVideoPath, retval));
+ if (retval !== 1'b0)
+ `uvm_error(`gfn, $sformatf("clk_video has wrong value"));
+ for (int i=0; i<NumOfSamples; i++) begin
+ #(SampTimeNS * 1ns);
+ `DV_CHECK(uvm_hdl_read(ClkVideoPath, retval));
+ if (retval !== 1'b0)
+ `uvm_error(`gfn, $sformatf("clk_video has wrong value"));
+ end
+ endtask
+
+ virtual task clk_audio_peri_off_test();
+ bit retval = 1;
+
+ `DV_WAIT(cfg.sw_logger_vif.printed_log == "Testing peripheral clock 6");
+ #100us;
+ `DV_CHECK(uvm_hdl_read(ClkAudioSwEnPath, retval));
+ if (retval !== 1'b0)
+ `uvm_error(`gfn, $sformatf("Sw enable signal for clk_audio has wrong value"));
+ `DV_CHECK(uvm_hdl_read(ClkAudioPath, retval));
+ if (retval !== 1'b0)
+ `uvm_error(`gfn, $sformatf("clk_audio has wrong value"));
+ for (int i=0; i<NumOfSamples; i++) begin
+ #(SampTimeNS * 1ns);
+ `DV_CHECK(uvm_hdl_read(ClkAudioPath, retval));
+ if (retval !== 1'b0)
+ `uvm_error(`gfn, $sformatf("clk_audio has wrong value"));
+ end
+ endtask
+
+ virtual task clk_smc_peri_off_test();
+ bit retval = 1;
+
+ `DV_WAIT(cfg.sw_logger_vif.printed_log == "Testing peripheral clock 7");
+ #100us;
+ `DV_CHECK(uvm_hdl_read(ClkSmcSwEnPath, retval));
+ if (retval !== 1'b0)
+ `uvm_error(`gfn, $sformatf("Sw enable signal for clk_smc has wrong value"));
+ `DV_CHECK(uvm_hdl_read(ClkSmcPath, retval));
+ if (retval !== 1'b0)
+ `uvm_error(`gfn, $sformatf("clk_smc has wrong value"));
+ for (int i=0; i<NumOfSamples; i++) begin
+ #(SampTimeNS * 1ns);
+ `DV_CHECK(uvm_hdl_read(ClkSmcPath, retval));
+ if (retval !== 1'b0)
+ `uvm_error(`gfn, $sformatf("clk_smc has wrong value"));
+ end
+ endtask
+
+endclass : chip_sw_clkmgr_off_peri_vseq
diff --git a/hw/top_matcha/dv/env/seq_lib/chip_sw_sensor_ctrl_status_intr_vseq.sv b/hw/top_matcha/dv/env/seq_lib/chip_sw_sensor_ctrl_status_intr_vseq.sv
index 7766a34..f8f6266 100644
--- a/hw/top_matcha/dv/env/seq_lib/chip_sw_sensor_ctrl_status_intr_vseq.sv
+++ b/hw/top_matcha/dv/env/seq_lib/chip_sw_sensor_ctrl_status_intr_vseq.sv
@@ -10,7 +10,7 @@
localparam int TOTAL_IO = 2;
localparam string VIOA_POK_PATH = "tb.dut.u_ast.u_vioa_pok.vio_pok_o";
localparam string VIOB_POK_PATH = "tb.dut.u_ast.u_viob_pok.vio_pok_o";
- localparam string SLEEPING_PATH = "tb.dut.top_matcha.u_rv_core_ibex.u_core_sleeping_buf.out_o";
+ localparam string SLEEPING_PATH = "tb.dut.top_matcha.u_rv_core_ibex_sec.u_core_sleeping_buf.out_o";
string io_paths[2] = '{VIOA_POK_PATH, VIOB_POK_PATH};
int iterations = 10;
diff --git a/hw/top_matcha/dv/env/seq_lib/chip_tap_straps_vseq.sv b/hw/top_matcha/dv/env/seq_lib/chip_tap_straps_vseq.sv
index 6994085..ffab4b7 100644
--- a/hw/top_matcha/dv/env/seq_lib/chip_tap_straps_vseq.sv
+++ b/hw/top_matcha/dv/env/seq_lib/chip_tap_straps_vseq.sv
@@ -1,3 +1,4 @@
+// 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
@@ -12,8 +13,6 @@
// Verify pimux.dft_strap_test_o is always 0 in the states other than TEST_UNLOCKED* and
// RMA, regardless of the value on DFT SW straps.
-// TODO: This test is broken. Drive functional JTAG traffic as opposed to pin connectivity.
-
class chip_tap_straps_vseq extends chip_sw_base_vseq;
string path_dft_strap_test_o = "tb.dut.top_matcha.dft_strap_test_o";
string path_dft_tap_req = "tb.dut.top_matcha.u_dft_tap_breakout.req_i";
@@ -51,7 +50,17 @@
virtual task dut_init(string reset_kind = "HARD");
bit lc_at_prod;
- randomize_dft_straps();
+ // Release DFT straps after they are sampled
+ fork
+ begin randomize_dft_straps(); end
+ begin
+
+ wait (cfg.sw_test_status_vif.sw_test_status == SwTestStatusInTest)
+ cfg.chip_vif.dft_straps_if.disconnect();
+ `uvm_info(`gfn, "DICONNECTED DFT STRAPS", UVM_NONE)
+ end
+ join_none
+
`DV_CHECK_STD_RANDOMIZE_FATAL(select_jtag)
cfg.chip_vif.tap_straps_if.drive(select_jtag);
cfg.chip_vif.set_tdo_pull(0);
@@ -208,8 +217,8 @@
`DV_CHECK_FATAL(uvm_hdl_force(path_tb_jtag_tdi, exp_jtag_req.tdi))
`DV_CHECK_FATAL(uvm_hdl_force(path_dft_tap_rsp, exp_jtag_rsp))
- // avoid race condition
- #1ps;
+ // Wait for jtag signals to be driven
+ cfg.clk_rst_vif.wait_clks(10);
// check jtag
`DV_CHECK_FATAL(uvm_hdl_read(path_dft_tap_req, act_jtag_req))
@@ -262,24 +271,30 @@
end
endtask
+ // Randomize DFT straps for rma and unlock between (0,2,3) for dev and prod (0,1,2,3).
+ // It is problematic to run the test with some DFT values, for some vendors.
+ bit [1:0] dft_straps_val;
+ bit partner;
virtual function void randomize_dft_straps();
- bit [1:0] val = $urandom;
-
- `uvm_info(`gfn, $sformatf("Drive dft straps to %0d", val), UVM_LOW)
- cfg.chip_vif.dft_straps_if.drive(val);
+ if ($value$plusargs("PARTNER_N=%b",partner))
+ begin
+ randomize(dft_straps_val) with {dft_straps_val inside {0,2,3};};
+ end else begin
+ randomize(dft_straps_val) with {dft_straps_val inside {0,1,2,3};};
+ end
+ `uvm_info(`gfn, $sformatf("LC state is = %0s, DFT straps = %2b\n",
+ cur_lc_state.name(),dft_straps_val), UVM_LOW)
+ cfg.chip_vif.dft_straps_if.drive(dft_straps_val);
endfunction
+ // Compare DFT strap to driven values, interface is disconnected and loses actual value.
virtual function void check_dft_straps();
- bit [1:0] exp_val, act_val;
-
- if (is_lc_in_unlocked_or_rma()) begin
- exp_val = cfg.chip_vif.dft_straps_if.sample();
- end else begin
- exp_val = 0;
+ bit [1:0] act_val;
+ if (!is_lc_in_unlocked_or_rma()) begin
+ dft_straps_val = 0;
end
`DV_CHECK_FATAL(uvm_hdl_read(path_dft_strap_test_o, act_val))
-
- `DV_CHECK_EQ(act_val, exp_val)
+ `DV_CHECK_EQ(act_val, dft_straps_val)
endfunction
virtual function bit is_lc_in_unlocked_or_rma();
@@ -287,4 +302,5 @@
LcStTestUnlocked0, LcStTestUnlocked1, LcStTestUnlocked2, LcStTestUnlocked3,
LcStTestUnlocked4, LcStTestUnlocked5, LcStTestUnlocked6, LcStTestUnlocked7};
endfunction
+
endclass
diff --git a/hw/top_matcha/dv/env/seq_lib/chip_vseq_list.sv b/hw/top_matcha/dv/env/seq_lib/chip_vseq_list.sv
index d551457..ebe1a2b 100644
--- a/hw/top_matcha/dv/env/seq_lib/chip_vseq_list.sv
+++ b/hw/top_matcha/dv/env/seq_lib/chip_vseq_list.sv
@@ -1,3 +1,4 @@
+// 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
@@ -99,3 +100,4 @@
`include "chip_sw_power_sleep_load_vseq.sv"
`include "chip_sw_ast_clk_rst_inputs_vseq.sv"
`include "chip_sw_power_virus_vseq.sv"
+`include "chip_sw_clkmgr_off_peri_vseq.sv"
diff --git a/rules/matcha.bzl b/rules/matcha.bzl
index 87b4594..c8886e6 100644
--- a/rules/matcha.bzl
+++ b/rules/matcha.bzl
@@ -568,6 +568,8 @@
linking_contexts = linking_contexts,
user_link_flags = ctx.attr.linkopts + [
"-Wl,-T,{}".format(ctx.file.linker_script.path),
+ # binutils >= 2.39 checks the loadable segments RWX setting by default.
+ "-Wl,--no-warn-rwx-segments",
],
additional_inputs = depset([ctx.file.linker_script] + ctx.files.linker_script_includes),
output_type = "executable",
diff --git a/sw/device/examples/hello_world/hello_world.c b/sw/device/examples/hello_world/hello_world.c
index 216178b..577e7c5 100644
--- a/sw/device/examples/hello_world/hello_world.c
+++ b/sw/device/examples/hello_world/hello_world.c
@@ -107,7 +107,11 @@
// Now have UART <-> Buttons/LEDs demo
// all LEDs off
CHECK_DIF_OK(dif_gpio_write_all(&gpio, 0x0000));
- LOG_INFO("Try out the switches on the board");
+ if (kDeviceType == kDeviceFpgaNexus) {
+ LOG_INFO("Try out the switches on the board");
+ } else if (kDeviceType == kDeviceSimVerilator) {
+ LOG_INFO("Try out the GPIO switches 28, 29, 31");
+ }
LOG_INFO("or type anything into the console window.");
LOG_INFO(
"The LEDs show the bits of the ASCII code of the last "
diff --git a/sw/device/examples/hello_world/run_verilator_hello_world.sh b/sw/device/examples/hello_world/run_verilator_hello_world.sh
index e85af45..e220a8a 100755
--- a/sw/device/examples/hello_world/run_verilator_hello_world.sh
+++ b/sw/device/examples/hello_world/run_verilator_hello_world.sh
@@ -17,7 +17,7 @@
# Run verilator interactive simulation on sw/device/examples/hello_world.
function print_usage {
- echo "Usage: run_verilator_hello_world.sh <verilator testbench> <rom binary> <flash binary> <otp binary>"
+ echo "Usage: run_verilator_hello_world.sh <verilator testbench> <rom binary> <flash binary> <otp binary> [gpio_test]"
}
if [[ $1 == "--help" ]]; then
@@ -25,7 +25,7 @@
exit 0
fi
-if [[ $# -ne 4 ]]; then
+if [[ $# -lt 4 ]]; then
print_usage
exit 1
fi
@@ -35,8 +35,16 @@
exit 1
fi
+# This cycle count is tuned so we don't need to wait too long for the test to
+# finish.
+TEST_CYCLES=700000
-TEST_CYCLES=650000
+GPIO_TEST=0
+
+if [[ $# -eq 5 ]] && [[ $5 == "gpio_test" ]]; then
+ GPIO_TEST=1
+ TEST_CYCLES=900000
+fi
VCHIP_TB=$1
ROM_BIN=$2
@@ -62,19 +70,37 @@
VERILATOR_PID=$!
-# Pipe GPIO output to a log file
-sleep 5
-cat gpio0-read | tee "${TEST_UNDECLARED_OUTPUTS_DIR}/gpio0_read.log" &
+if (( ${GPIO_TEST} == 0 )); then
+ # Pipe GPIO output to a log file
+ sleep 5
+ cat gpio0-read | tee "${TEST_UNDECLARED_OUTPUTS_DIR}/gpio0_read.log" &
-# Wait for 300s to reach the end of the hello_world initialization.
-sleep 300
-echo 'led gpio test' > "${TEST_UNDECLARED_OUTPUTS_DIR}/uart0_device"
+ # Wait for 300s to reach the end of the hello_world initialization.
+ # Note: The value is tuned for the CICD to run. For local failing tests,
+ # consider to reduce the wait or increase the TEST_CYCLES.
+ sleep 300
+ echo 'led gpio test' > "${TEST_UNDECLARED_OUTPUTS_DIR}/uart0_device"
-# Wait up to another 350s to complete the verilator simulation.
-timeout 350 tail --pid=${VERILATOR_PID} -f /dev/null
+ tail --pid=${VERILATOR_PID} -f /dev/null
-# Check results in GPIO and UART logs.
-cat "${TEST_UNDECLARED_OUTPUTS_DIR}/uart0.log" | grep -q "led gpio test" || exit 1
+ # Check results in GPIO and UART logs.
+ cat "${TEST_UNDECLARED_OUTPUTS_DIR}/uart0.log" | grep -q "led gpio test" || exit 1
-diff -q "${TEST_UNDECLARED_OUTPUTS_DIR}/gpio0_read.log" \
- "sw/device/examples/hello_world/hello_world_test_expected_gpio.txt" || exit 1
+ diff -q "${TEST_UNDECLARED_OUTPUTS_DIR}/gpio0_read.log" \
+ "sw/device/examples/hello_world/hello_world_test_expected_gpio.txt" || exit 1
+else
+ # Wait for 260s to reach the end of the hello_world initialization.
+ # Note: This value may need to tuned by the machine performance. Need to
+ # reduce the wait if the verilator simulation is fast (or increase the
+ # TEST_CYCLES variable).
+ sleep 260
+ echo 'h28 h29 h31' > gpio0-write
+
+ tail --pid=${VERILATOR_PID} -f /dev/null
+
+ # Check GPIO toggle result in the UART log
+ for switch in "9" "10" "11"; do
+ cat "${TEST_UNDECLARED_OUTPUTS_DIR}/uart0.log" | \
+ grep -q "GPIO switch #${switch} changed to 1" || exit 1
+ done
+fi
diff --git a/sw/device/tests/BUILD b/sw/device/tests/BUILD
index 7d398b3..0bee4f2 100644
--- a/sw/device/tests/BUILD
+++ b/sw/device/tests/BUILD
@@ -1,4 +1,4 @@
-# Copyright 2022 Google LLC.
+# 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
@@ -659,6 +659,22 @@
)
matcha_dv_test(
+ name = "example_test_from_rom",
+ srcs = ["example_test_from_rom.c"],
+ # This test is designed to run and complete entirely in the ROM boot stage.
+ # Setting the `test_in_rom` flag makes the `matcha_dv_test` rule aware
+ # of this, and instructs it to load the test image into ROM (rather than
+ # loading the default test ROM, or any other ROM that may be specified via
+ # DV params).
+ test_in_rom = True,
+ deps = [
+ ":test_lib_base",
+ "//sw/device/lib/testing/test_rom:linker_script",
+ "//sw/device/lib/testing/test_rom:test_rom_lib",
+ ],
+)
+
+matcha_dv_test(
name = "hmac_enc_test",
srcs = ["@lowrisc_opentitan//sw/device/tests:hmac_enc_test.c"],
deps = [
@@ -817,6 +833,92 @@
],
)
+matcha_dv_test(
+ name = "sensor_ctrl_alert_test",
+ srcs = ["sensor_ctrl_alerts.c"],
+ deps = [
+ ":test_dv_lib",
+ "//hw/top_matcha/ip/sensor_ctrl/data:sensor_ctrl_regs",
+ "//sw/device/lib/dif:alert_handler",
+ "//sw/device/lib/dif:rstmgr",
+ "//sw/device/lib/dif:rv_plic_sec",
+ "@lowrisc_opentitan//sw/device/lib/base:abs_mmio",
+ "@lowrisc_opentitan//sw/device/lib/dif:sensor_ctrl",
+ "@lowrisc_opentitan//sw/device/lib/testing:flash_ctrl_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:pwrmgr_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:rand_testutils",
+ ],
+)
+
+matcha_dv_test(
+ name = "sensor_ctrl_wakeup_test",
+ srcs = ["@lowrisc_opentitan//sw/device/tests:sensor_ctrl_wakeup.c"],
+ deps = [
+ ":test_dv_lib_opentitan",
+ "//hw/top_matcha/ip/sensor_ctrl/data:sensor_ctrl_regs",
+ "//sw/device/lib/dif:rv_plic_sec",
+ "@lowrisc_opentitan//sw/device/lib/arch:device",
+ "@lowrisc_opentitan//sw/device/lib/dif:pwrmgr",
+ "@lowrisc_opentitan//sw/device/lib/dif:sensor_ctrl",
+ "@lowrisc_opentitan//sw/device/lib/testing:isr_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:pwrmgr_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:rv_plic_testutils",
+ ],
+)
+
+matcha_dv_test(
+ name = "rv_core_ibex_rnd_test",
+ srcs = [
+ "@lowrisc_opentitan//sw/device/tests:rv_core_ibex_rnd_test.S",
+ "@lowrisc_opentitan//sw/device/tests:rv_core_ibex_rnd_test.c",
+ ],
+ deps = [
+ ":test_dv_lib_opentitan",
+ "@lowrisc_opentitan//sw/device/lib/dif:edn",
+ "@lowrisc_opentitan//sw/device/lib/dif:rv_core_ibex",
+ "@lowrisc_opentitan//sw/device/lib/testing:entropy_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:rv_core_ibex_testutils",
+ ],
+)
+
+matcha_dv_test(
+ name = "rv_core_ibex_nmi_irq_test",
+ srcs = ["@lowrisc_opentitan//sw/device/tests:rv_core_ibex_nmi_irq_test.c"],
+ deps = [
+ ":test_dv_lib_opentitan",
+ "//sw/device/lib/dif:alert_handler",
+ "@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",
+ ],
+)
+
+matcha_dv_test(
+ name = "clkmgr_off_peri_test",
+ srcs = ["clkmgr_off_peri_test.c"],
+ deps = [
+ ":test_dv_lib",
+ "//sw/device/lib/dif:clkmgr",
+ "//sw/device/lib/dif:dma",
+ "//sw/device/lib/dif:ml_top",
+ "//sw/device/lib/dif:rstmgr",
+ "@lowrisc_opentitan//sw/device/lib/base:abs_mmio",
+ "@lowrisc_opentitan//sw/device/lib/dif:aon_timer",
+ "@lowrisc_opentitan//sw/device/lib/dif:base",
+ "@lowrisc_opentitan//sw/device/lib/dif:flash_ctrl",
+ "@lowrisc_opentitan//sw/device/lib/dif:pwrmgr",
+ "@lowrisc_opentitan//sw/device/lib/dif:spi_host",
+ "@lowrisc_opentitan//sw/device/lib/dif:uart",
+ "@lowrisc_opentitan//sw/device/lib/dif:usbdev",
+ "@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",
+ ],
+)
+
# Smoke tests
matcha_dv_test(
name = "aes_smoketest",
diff --git a/sw/device/tests/clkmgr_off_peri_test.c b/sw/device/tests/clkmgr_off_peri_test.c
new file mode 100644
index 0000000..5aafbf0
--- /dev/null
+++ b/sw/device/tests/clkmgr_off_peri_test.c
@@ -0,0 +1,327 @@
+// 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 "dma_regs.h"
+#include "hw/top_matcha/sw/autogen/top_matcha.h"
+#include "ml_top_regs.h"
+#include "spi_host_regs.h"
+#include "sw/device/lib/base/abs_mmio.h"
+#include "sw/device/lib/base/memory.h"
+#include "sw/device/lib/dif/dif_aon_timer.h"
+#include "sw/device/lib/dif/dif_base.h"
+#include "sw/device/lib/dif/dif_clkmgr.h"
+#include "sw/device/lib/dif/dif_dma.h"
+#include "sw/device/lib/dif/dif_flash_ctrl.h"
+#include "sw/device/lib/dif/dif_ml_top.h"
+#include "sw/device/lib/dif/dif_pwrmgr.h"
+#include "sw/device/lib/dif/dif_rstmgr.h"
+#include "sw/device/lib/dif/dif_spi_host.h"
+#include "sw/device/lib/dif/dif_uart.h"
+#include "sw/device/lib/dif/dif_usbdev.h"
+#include "sw/device/lib/runtime/log.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/test_framework/check.h"
+#include "sw/device/lib/testing/test_framework/ottf_main.h"
+#include "uart_regs.h"
+#include "usbdev_regs.h"
+
+/**
+ * The peripherals used to test when the peri clocks are disabled are
+ * bit 0: clk_io_div4_peri: uart0
+ * bit 1: clk_io_div2_peri: spi_host1
+ * bit 2: clk_io_peri: spi_host0
+ * bit 3: clk_usb_peri: usbdev
+ * bit 4: clk_video:
+ * bit 5: clk_ml: ml_top
+ * bit 6: clk_audio:
+ * bit 7: clk_smc: dma_smc
+ */
+
+OTTF_DEFINE_TEST_CONFIG();
+
+typedef struct peri_context {
+ void (*csr_access)(); // The function causing a timeout.
+ uint32_t address; // The address causing a timeout.
+} peri_context_t;
+
+static dif_aon_timer_t aon_timer;
+static dif_flash_ctrl_state_t flash_ctrl;
+static dif_spi_host_t spi_host0;
+static dif_spi_host_t spi_host1;
+static dif_usbdev_t usbdev;
+static dif_uart_t uart0;
+static dif_ml_top_t ml_top;
+static dif_dma_t dma_smc;
+
+OT_SECTION(".non_volatile_scratch") uint64_t hung_data_addr[4];
+
+static void set_hung_address(dif_clkmgr_gateable_clock_t clock,
+ uint32_t value) {
+ uint32_t addr =
+ (uintptr_t)&hung_data_addr[clock] - TOP_MATCHA_FLASH_CTRL_MEM_BASE_ADDR;
+ uint32_t flash_word[2] = {value, 0};
+ CHECK(flash_ctrl_testutils_write(&flash_ctrl, addr, 0, flash_word,
+ kDifFlashCtrlPartitionTypeData, 2));
+ CHECK(hung_data_addr[clock] == value, "Unexpected mismatch on read back");
+ LOG_INFO("The expected hung address for clock %d is 0x%x at 0x%x", clock,
+ value, addr);
+}
+
+static void uart0_csr_access() {
+ dif_toggle_t state;
+ CHECK_DIF_OK(dif_uart_irq_set_enabled(&uart0, kDifUartIrqTxWatermark,
+ kDifToggleEnabled));
+ CHECK_DIF_OK(
+ dif_uart_irq_get_enabled(&uart0, kDifUartIrqTxWatermark, &state));
+ CHECK(state == kDifToggleEnabled);
+}
+
+static void spi_host0_csr_access() {
+ dif_toggle_t state;
+ CHECK_DIF_OK(dif_spi_host_irq_set_enabled(&spi_host0, kDifSpiHostIrqSpiEvent,
+ kDifToggleEnabled));
+ CHECK_DIF_OK(
+ dif_spi_host_irq_get_enabled(&spi_host0, kDifSpiHostIrqSpiEvent, &state));
+ CHECK(state == kDifToggleEnabled);
+}
+
+static void spi_host1_csr_access() {
+ dif_toggle_t state;
+ CHECK_DIF_OK(dif_spi_host_irq_set_enabled(&spi_host1, kDifSpiHostIrqSpiEvent,
+ kDifToggleEnabled));
+ CHECK_DIF_OK(
+ dif_spi_host_irq_get_enabled(&spi_host1, kDifSpiHostIrqSpiEvent, &state));
+ CHECK(state == kDifToggleEnabled);
+}
+
+static void usbdev_csr_access() {
+ CHECK_DIF_OK(dif_usbdev_irq_set_enabled(&usbdev, kDifUsbdevIrqPowered,
+ kDifToggleEnabled));
+ dif_toggle_t state;
+ CHECK_DIF_OK(
+ dif_usbdev_irq_get_enabled(&usbdev, kDifUsbdevIrqPowered, &state));
+ CHECK(state == kDifToggleEnabled);
+}
+
+static void ml_top_csr_access() {
+ CHECK_DIF_OK(dif_ml_top_irq_set_enabled(&ml_top, kDifMlTopIrqHostReq,
+ kDifToggleEnabled));
+ dif_toggle_t state;
+ CHECK_DIF_OK(
+ dif_ml_top_irq_get_enabled(&ml_top, kDifMlTopIrqHostReq, &state));
+ CHECK(state == kDifToggleEnabled);
+}
+
+static void dma_smc_csr_access() {
+ CHECK_DIF_OK(dif_dma_irq_set_enabled(&dma_smc, kDifDmaIrqWriterDone,
+ kDifToggleEnabled));
+ dif_toggle_t state;
+ CHECK_DIF_OK(dif_dma_irq_get_enabled(&dma_smc, kDifDmaIrqWriterDone, &state));
+ CHECK(state == kDifToggleEnabled);
+}
+
+peri_context_t peri_context[kTopMatchaGateableClocksLast + 1] = {
+ {uart0_csr_access,
+ TOP_MATCHA_UART0_BASE_ADDR + UART_INTR_ENABLE_REG_OFFSET},
+ {spi_host1_csr_access,
+ TOP_MATCHA_SPI_HOST1_BASE_ADDR + SPI_HOST_INTR_ENABLE_REG_OFFSET},
+ {spi_host0_csr_access,
+ TOP_MATCHA_SPI_HOST0_BASE_ADDR + SPI_HOST_INTR_ENABLE_REG_OFFSET},
+ {usbdev_csr_access,
+ TOP_MATCHA_USBDEV_BASE_ADDR + USBDEV_INTR_ENABLE_REG_OFFSET},
+ {},
+ {ml_top_csr_access,
+ TOP_MATCHA_ML_TOP_CORE_BASE_ADDR + ML_TOP_INTR_ENABLE_REG_OFFSET},
+ {},
+ {dma_smc_csr_access,
+ TOP_MATCHA_DMA_SMC_BASE_ADDR + DMA_INTR_ENABLE_REG_OFFSET}};
+
+/**
+ * Test that disabling a 'gateable' unit's clock causes the unit to become
+ * unresponsive to CSR accesses. Configure a watchdog reset, and if it triggers
+ * the test is successful.
+ */
+static void test_gateable_clocks_off(const dif_clkmgr_t *clkmgr,
+ const dif_pwrmgr_t *pwrmgr,
+ dif_clkmgr_gateable_clock_t clock) {
+ // Make sure the clock for the unit is on.
+ CHECK_DIF_OK(
+ dif_clkmgr_gateable_clock_set_enabled(clkmgr, clock, kDifToggleEnabled));
+ // Enable watchdog bite reset.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceTwo,
+ kDifToggleEnabled));
+ LOG_INFO("Testing peripheral clock %d", clock);
+
+ // Bite after enough time has elapsed past the hung csr access.
+ uint32_t bite_us = (kDeviceType == kDeviceSimDV) ? 400 : 800;
+ uint32_t bite_cycles = aon_timer_testutils_get_aon_cycles_from_us(bite_us);
+ LOG_INFO("Setting bite reset for %u us (%u cycles)", bite_us, bite_cycles);
+
+ // Make sure the CSR is accessible before turning the clock off.
+ (*peri_context[clock].csr_access)();
+ LOG_INFO("CSR access was okay before disabling the clock");
+
+ // Save the expected hung address to check against cpu_info's LAST_DATA_ADDR.
+ set_hung_address(clock, peri_context[clock].address);
+ // Set bite timer.
+ aon_timer_testutils_watchdog_config(&aon_timer, UINT32_MAX, bite_cycles,
+ false);
+ // Disable the peripheral's clock.
+ CHECK_DIF_OK(
+ dif_clkmgr_gateable_clock_set_enabled(clkmgr, clock, kDifToggleDisabled));
+ // Wait for the clock to really turn off.
+ busy_spin_micros(100);
+ // And issue the CSR access that will freeze and cause a reset.
+ (*peri_context[clock].csr_access)();
+}
+
+/**
+ * Turn off the clock for 400us, then turn on
+ * Check the result in chip_sw_clkmgr_off_peri_vseq
+ */
+static void test_gateable_clocks_off_without_reset(
+ const dif_clkmgr_t *clkmgr, dif_clkmgr_gateable_clock_t clock) {
+ // Make sure the clock for the unit is on.
+ CHECK_DIF_OK(
+ dif_clkmgr_gateable_clock_set_enabled(clkmgr, clock, kDifToggleEnabled));
+
+ LOG_INFO("Testing peripheral clock %d", clock);
+
+ // Disable the peripheral's clock.
+ CHECK_DIF_OK(
+ dif_clkmgr_gateable_clock_set_enabled(clkmgr, clock, kDifToggleDisabled));
+ // Wait for the clock to really turn off.
+ busy_spin_micros(400);
+ // Enalbe the clock
+ CHECK_DIF_OK(
+ dif_clkmgr_gateable_clock_set_enabled(clkmgr, clock, kDifToggleEnabled));
+}
+
+bool test_main(void) {
+ dif_clkmgr_t clkmgr;
+ dif_pwrmgr_t pwrmgr;
+ dif_rstmgr_t rstmgr;
+
+ CHECK_DIF_OK(dif_rstmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_RSTMGR_AON_BASE_ADDR), &rstmgr));
+
+ CHECK_DIF_OK(dif_clkmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_CLKMGR_AON_BASE_ADDR), &clkmgr));
+
+ CHECK_DIF_OK(dif_pwrmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_PWRMGR_AON_BASE_ADDR), &pwrmgr));
+
+ CHECK_DIF_OK(dif_flash_ctrl_init_state(
+ &flash_ctrl,
+ mmio_region_from_addr(TOP_MATCHA_FLASH_CTRL_CORE_BASE_ADDR)));
+
+ // Initialize aon timer.
+ CHECK_DIF_OK(dif_aon_timer_init(
+ mmio_region_from_addr(TOP_MATCHA_AON_TIMER_AON_BASE_ADDR), &aon_timer));
+
+ // Initialize peripherals.
+ CHECK_DIF_OK(
+ dif_uart_init(mmio_region_from_addr(TOP_MATCHA_UART0_BASE_ADDR), &uart0));
+ CHECK_DIF_OK(dif_spi_host_init(
+ mmio_region_from_addr(TOP_MATCHA_SPI_HOST0_BASE_ADDR), &spi_host0));
+ CHECK_DIF_OK(dif_spi_host_init(
+ mmio_region_from_addr(TOP_MATCHA_SPI_HOST1_BASE_ADDR), &spi_host1));
+ CHECK_DIF_OK(dif_usbdev_init(
+ mmio_region_from_addr(TOP_MATCHA_USBDEV_BASE_ADDR), &usbdev));
+ CHECK_DIF_OK(dif_ml_top_init(
+ mmio_region_from_addr(TOP_MATCHA_ML_TOP_CORE_BASE_ADDR), &ml_top));
+ CHECK_DIF_OK(dif_dma_init(mmio_region_from_addr(TOP_MATCHA_DMA_SMC_BASE_ADDR),
+ &dma_smc));
+
+ // Enable cpu dump capture.
+ CHECK_DIF_OK(dif_rstmgr_cpu_info_set_enabled(&rstmgr, kDifToggleEnabled));
+
+ // Enable raw 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);
+
+ if (rstmgr_testutils_is_reset_info(&rstmgr, kDifRstmgrResetInfoPor)) {
+ rstmgr_testutils_pre_reset(&rstmgr);
+
+ // Starting clock.
+ dif_clkmgr_gateable_clock_t clock = kTopMatchaGateableClocksIoDiv4Peri;
+ LOG_INFO("Next clock to test %d", flash_ctrl_testutils_counter_get(0));
+
+ test_gateable_clocks_off(&clkmgr, &pwrmgr, clock);
+
+ // This should never be reached.
+ LOG_ERROR("This is unreachable since a reset should have been triggered");
+ return false;
+ } else if (rstmgr_testutils_is_reset_info(&rstmgr,
+ kDifRstmgrResetInfoWatchdog)) {
+ dif_clkmgr_gateable_clock_t clock = flash_ctrl_testutils_counter_get(0);
+ LOG_INFO("Got an expected watchdog reset when reading for clock %d", clock);
+
+ size_t actual_size;
+ CHECK_DIF_OK(dif_rstmgr_cpu_info_get_size(&rstmgr, &actual_size));
+ // Verify the cpu crash dump.
+ dif_rstmgr_cpu_info_dump_segment_t cpu_dump[DIF_RSTMGR_CPU_INFO_MAX_SIZE];
+ size_t size_read;
+ CHECK_DIF_OK(dif_rstmgr_cpu_info_dump_read(
+ &rstmgr, cpu_dump, DIF_RSTMGR_CPU_INFO_MAX_SIZE, &size_read));
+ CHECK(size_read <= DIF_RSTMGR_CPU_INFO_MAX_SIZE);
+ CHECK(size_read == actual_size);
+ LOG_INFO("EXC_ADDR = 0x%x", cpu_dump[0]);
+ LOG_INFO("EXC_PC = 0x%x", cpu_dump[1]);
+ LOG_INFO("LAST_DATA ADDR = 0x%x", cpu_dump[2]);
+ LOG_INFO("NEXT_PC = 0x%x", cpu_dump[3]);
+ LOG_INFO("CURRENT_PC = 0x%x", cpu_dump[4]);
+ LOG_INFO("PREV_EXC_ADDR = 0x%x", cpu_dump[5]);
+ LOG_INFO("PREV_EXC_PC = 0x%x", cpu_dump[6]);
+ LOG_INFO("PREV_VALID = 0x%x", cpu_dump[7]);
+ uint32_t expected_hung_address = hung_data_addr[clock];
+ LOG_INFO("The expected hung address = 0x%x", expected_hung_address);
+ CHECK(cpu_dump[2] == expected_hung_address, "Unexpected hung address");
+ // Mark this clock as tested.
+ flash_ctrl_testutils_counter_increment(&flash_ctrl, 0);
+
+ if (clock < kTopMatchaGateableClocksLast) {
+ clock = flash_ctrl_testutils_counter_get(0);
+ LOG_INFO("Next clock to test %d", clock);
+
+ if (clock == kTopMatchaGateableClocksIoDiv2Peri ||
+ clock == kTopMatchaGateableClocksVideoPeri ||
+ clock == kTopMatchaGateableClocksAudioPeri) {
+ test_gateable_clocks_off_without_reset(&clkmgr, clock);
+
+ flash_ctrl_testutils_counter_increment(&flash_ctrl, 0);
+ clock = flash_ctrl_testutils_counter_get(0);
+
+ if (clock == kTopMatchaGateableClocksLast) {
+ test_gateable_clocks_off_without_reset(&clkmgr, clock);
+ return true;
+ }
+ }
+
+ rstmgr_testutils_pre_reset(&rstmgr);
+
+ test_gateable_clocks_off(&clkmgr, &pwrmgr, clock);
+
+ // This should never be reached.
+ LOG_ERROR("This is unreachable since a reset should have been triggered");
+ return false;
+ } else {
+ return true;
+ }
+ } else {
+ dif_rstmgr_reset_info_bitfield_t reset_info;
+ reset_info = rstmgr_testutils_reason_get();
+ LOG_ERROR("Unexpected reset_info 0x%x", reset_info);
+ }
+ return false;
+}
diff --git a/sw/device/tests/example_test_from_rom.c b/sw/device/tests/example_test_from_rom.c
new file mode 100644
index 0000000..eddb47d
--- /dev/null
+++ b/sw/device/tests/example_test_from_rom.c
@@ -0,0 +1,54 @@
+// 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 "hw/top_matcha/sw/autogen/top_matcha.h" // Generated.
+#include "sw/device/lib/arch/device.h"
+#include "sw/device/lib/base/mmio.h"
+#include "sw/device/lib/dif/dif_pinmux.h"
+#include "sw/device/lib/dif/dif_uart.h"
+#include "sw/device/lib/runtime/hart.h"
+#include "sw/device/lib/runtime/log.h"
+#include "sw/device/lib/runtime/print.h"
+#include "sw/device/lib/testing/pinmux_testutils.h"
+#include "sw/device/lib/testing/test_framework/check.h"
+#include "sw/device/lib/testing/test_framework/status.h"
+
+static dif_pinmux_t pinmux;
+static dif_uart_t uart0;
+
+bool rom_test_main(void) {
+ // We need to set the test status as "in test" to indicate to the test code
+ // has been reached, even though this test is also in the "boot ROM".
+ test_status_set(kTestStatusInTest);
+ CHECK_DIF_OK(dif_pinmux_init(
+ mmio_region_from_addr(TOP_MATCHA_PINMUX_AON_BASE_ADDR), &pinmux));
+ pinmux_testutils_init(&pinmux);
+
+ // We need to initialize the UART regardless if we LOG any messages, since
+ // Verilator and FPGA platforms use the UART to communicate the test results.
+ if (kDeviceType != kDeviceSimDV) {
+ CHECK_DIF_OK(dif_uart_init(
+ mmio_region_from_addr(TOP_MATCHA_UART0_BASE_ADDR), &uart0));
+ CHECK_DIF_OK(
+ dif_uart_configure(&uart0, (dif_uart_config_t){
+ .baudrate = kUartBaudrate,
+ .clk_freq_hz = kClockFreqPeripheralHz,
+ .parity_enable = kDifToggleDisabled,
+ .parity = kDifUartParityEven,
+ .tx_enable = kDifToggleEnabled,
+ .rx_enable = kDifToggleEnabled,
+ }));
+ base_uart_stdout(&uart0);
+ }
+
+ /**
+ * Place test code here.
+ */
+
+ /**
+ * Return true if the test succeeds. Return false if it should fail.
+ */
+ return true;
+}
diff --git a/sw/device/tests/sensor_ctrl_alerts.c b/sw/device/tests/sensor_ctrl_alerts.c
new file mode 100644
index 0000000..8b01da3
--- /dev/null
+++ b/sw/device/tests/sensor_ctrl_alerts.c
@@ -0,0 +1,212 @@
+// 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 "hw/top_matcha/sw/autogen/top_matcha.h"
+#include "sensor_ctrl_regs.h" // Generated.
+#include "sw/device/lib/base/abs_mmio.h"
+#include "sw/device/lib/base/mmio.h"
+#include "sw/device/lib/dif/dif_alert_handler.h"
+#include "sw/device/lib/dif/dif_flash_ctrl.h"
+#include "sw/device/lib/dif/dif_rstmgr.h"
+#include "sw/device/lib/dif/dif_rv_plic.h"
+#include "sw/device/lib/dif/dif_sensor_ctrl.h"
+#include "sw/device/lib/runtime/ibex.h"
+#include "sw/device/lib/runtime/irq.h"
+#include "sw/device/lib/runtime/log.h"
+#include "sw/device/lib/testing/flash_ctrl_testutils.h"
+#include "sw/device/lib/testing/pwrmgr_testutils.h"
+#include "sw/device/lib/testing/rand_testutils.h"
+#include "sw/device/lib/testing/test_framework/check.h"
+#include "sw/device/lib/testing/test_framework/ottf_main.h"
+
+OTTF_DEFINE_TEST_CONFIG();
+
+/**
+ * This test checks that incoming ast events can be
+ * configured as both recoverable and fatal.
+ * Further, this test checks that recoverable and fatal
+ * events are able to reach their proper alert_handler
+ * destination.
+ *
+ * Since fatal events do not stop firing once asserted,
+ * this test performs a self reset after every fatal
+ * event. In order to keep track of how far the test
+ * has advanced, a non-volatile counter in flash is
+ * used to track current progress.
+ */
+static dif_rstmgr_t rstmgr;
+static dif_flash_ctrl_state_t flash_ctrl;
+static dif_sensor_ctrl_t sensor_ctrl;
+static dif_alert_handler_t alert_handler;
+
+/**
+ * Clear event trigger and recoverable status.
+ */
+static void clear_event(uint32_t idx, dif_toggle_t fatal) {
+ CHECK_DIF_OK(dif_sensor_ctrl_set_ast_event_trigger(&sensor_ctrl, idx,
+ kDifToggleDisabled));
+
+ if (!dif_toggle_to_bool(fatal)) {
+ CHECK_DIF_OK(dif_sensor_ctrl_clear_recov_event(&sensor_ctrl, idx));
+ }
+}
+
+static uint32_t get_events(dif_toggle_t fatal) {
+ dif_sensor_ctrl_events_t events = 0;
+ if (dif_toggle_to_bool(fatal)) {
+ CHECK_DIF_OK(dif_sensor_ctrl_get_fatal_events(&sensor_ctrl, &events));
+ } else {
+ CHECK_DIF_OK(dif_sensor_ctrl_get_recov_events(&sensor_ctrl, &events));
+ }
+ return events;
+}
+
+/**
+ * Check alert cause registers are correctly set
+ */
+static void check_alert_state(dif_toggle_t fatal) {
+ bool fatal_cause = false;
+ bool recov_cause = false;
+
+ CHECK_DIF_OK(dif_alert_handler_alert_is_cause(
+ &alert_handler, kTopMatchaAlertIdSensorCtrlFatalAlert, &fatal_cause));
+
+ CHECK_DIF_OK(dif_alert_handler_alert_is_cause(
+ &alert_handler, kTopMatchaAlertIdSensorCtrlRecovAlert, &recov_cause));
+
+ if (dif_toggle_to_bool(fatal)) {
+ CHECK(fatal_cause & !recov_cause,
+ "Fatal alert not correctly observed in alert handler");
+ } else {
+ CHECK(recov_cause & !fatal_cause,
+ "Recov alert not correctly observed in alert handler");
+ }
+
+ CHECK_DIF_OK(dif_alert_handler_alert_acknowledge(
+ &alert_handler, kTopMatchaAlertIdSensorCtrlRecovAlert));
+ CHECK_DIF_OK(dif_alert_handler_alert_acknowledge(
+ &alert_handler, kTopMatchaAlertIdSensorCtrlFatalAlert));
+};
+
+/**
+ * First configure fatality of the desired event.
+ * Then trigger the event from sensor_ctrl to ast.
+ * Next poll for setting of correct events inside sensor_ctrl status.
+ * When a recoverable event is triggerd, make sure only recoverable
+ * status is seen, likewise for fatal events.
+ * Finally, check for correct capture of cause in alert handler.
+ */
+static void test_event(uint32_t idx, dif_toggle_t fatal) {
+ // Configure event fatality
+ CHECK_DIF_OK(dif_sensor_ctrl_set_alert_fatal(&sensor_ctrl, idx, fatal));
+
+ // Trigger event
+ CHECK_DIF_OK(dif_sensor_ctrl_set_ast_event_trigger(&sensor_ctrl, idx,
+ kDifToggleEnabled));
+
+ // wait for events to set
+ IBEX_SPIN_FOR(get_events(fatal) > 0, 1);
+
+ // Check for the event in ast sensor_ctrl
+ // if the event is not set, error
+ CHECK(((get_events(fatal) >> idx) & 0x1) == 1, "Event %d not observed in AST",
+ idx);
+
+ // check the opposite fatality setting, should not be set
+ CHECK(((get_events(!fatal) >> idx) & 0x1) == 0,
+ "Event %d observed in AST when it should not be", idx);
+
+ // clear event trigger
+ clear_event(idx, fatal);
+
+ // check whether alert handler captured the event
+ check_alert_state(fatal);
+};
+
+enum {
+ // Counter for event index.
+ kCounterEventIdx,
+ // Counter for number of events tested.
+ kCounterNumTests,
+ // Max number of events to test per run.
+ kNumTestsMax = SENSOR_CTRL_PARAM_NUM_ALERT_EVENTS >> 1,
+};
+
+static uint32_t get_next_event_to_test(void) {
+ uint32_t event_idx;
+ // Reseed so that we don't see the same sequence after each reset.
+ rand_testutils_reseed();
+ do {
+ event_idx = flash_ctrl_testutils_counter_get(kCounterEventIdx);
+ flash_ctrl_testutils_counter_increment(&flash_ctrl, kCounterEventIdx);
+ // Drop each event randomly to reduce run time.
+ } while (rand_testutils_gen32() <= UINT32_MAX >> 1 &&
+ event_idx < SENSOR_CTRL_PARAM_NUM_ALERT_EVENTS);
+ return event_idx;
+}
+
+bool test_main(void) {
+ // Initialize flash_ctrl
+ CHECK_DIF_OK(dif_flash_ctrl_init_state(
+ &flash_ctrl,
+ mmio_region_from_addr(TOP_MATCHA_FLASH_CTRL_CORE_BASE_ADDR)));
+
+ // Initialize sensor_ctrl
+ CHECK_DIF_OK(dif_sensor_ctrl_init(
+ mmio_region_from_addr(TOP_MATCHA_SENSOR_CTRL_BASE_ADDR), &sensor_ctrl));
+
+ // Initialize alert_handler
+ CHECK_DIF_OK(dif_alert_handler_init(
+ mmio_region_from_addr(TOP_MATCHA_ALERT_HANDLER_BASE_ADDR),
+ &alert_handler));
+
+ CHECK_DIF_OK(dif_rstmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_RSTMGR_AON_BASE_ADDR), &rstmgr));
+
+ // Enable both recoverable and fatal alerts
+ CHECK_DIF_OK(dif_alert_handler_configure_alert(
+ &alert_handler, kTopMatchaAlertIdSensorCtrlRecovAlert,
+ kDifAlertHandlerClassA, kDifToggleEnabled, kDifToggleEnabled));
+ CHECK_DIF_OK(dif_alert_handler_configure_alert(
+ &alert_handler, kTopMatchaAlertIdSensorCtrlFatalAlert,
+ kDifAlertHandlerClassA, kDifToggleEnabled, kDifToggleEnabled));
+
+ // 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);
+
+ // Make sure we do not try to test more than half of all available events
+ // in a single test. Testing too many would just make the run time too
+ // long.
+ uint32_t event_idx = get_next_event_to_test();
+ if (event_idx == SENSOR_CTRL_PARAM_NUM_ALERT_EVENTS ||
+ flash_ctrl_testutils_counter_get(kCounterNumTests) >= kNumTestsMax) {
+ LOG_INFO("Tested all events");
+ return true;
+ } else {
+ LOG_INFO("Testing event %d", event_idx);
+ }
+
+ // test recoverable event
+ test_event(event_idx, /*fatal*/ kDifToggleDisabled);
+
+ // test fatal event
+ test_event(event_idx, /*fatal*/ kDifToggleEnabled);
+
+ // increment flash counter to know where we are
+ flash_ctrl_testutils_counter_increment(&flash_ctrl, kCounterNumTests);
+
+ // Now request system to reset and test again
+ LOG_INFO("Rebooting system");
+ CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
+ wait_for_interrupt();
+
+ return false;
+}
diff --git a/sw/device/tests/sim_dv/BUILD b/sw/device/tests/sim_dv/BUILD
index 46f4ce3..8740d12 100644
--- a/sw/device/tests/sim_dv/BUILD
+++ b/sw/device/tests/sim_dv/BUILD
@@ -116,3 +116,55 @@
"@lowrisc_opentitan//sw/device/lib/testing:rstmgr_testutils",
],
)
+
+matcha_dv_test(
+ name = "rv_dm_ndm_reset_req_when_cpu_halted",
+ srcs = ["@lowrisc_opentitan//sw/device/tests/sim_dv:rv_dm_ndm_reset_req_when_cpu_halted.c"],
+ deps = [
+ "//sw/device/lib/dif:rstmgr",
+ "//sw/device/tests:test_dv_lib_opentitan",
+ "@lowrisc_opentitan//sw/device/lib/testing:rstmgr_testutils",
+ ],
+)
+
+matcha_dv_test(
+ name = "sensor_ctrl_status_test",
+ srcs = ["@lowrisc_opentitan//sw/device/tests/sim_dv:sensor_ctrl_status.c"],
+ deps = [
+ "//hw/top_matcha/ip/sensor_ctrl/data:sensor_ctrl_regs",
+ "//sw/device/lib/dif:rv_plic_sec",
+ "//sw/device/tests:test_dv_lib_opentitan",
+ "@lowrisc_opentitan//sw/device/lib/base:abs_mmio",
+ "@lowrisc_opentitan//sw/device/lib/dif:sensor_ctrl",
+ "@lowrisc_opentitan//sw/device/lib/testing:isr_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:rv_plic_testutils",
+ ],
+)
+
+matcha_dv_test(
+ name = "all_escalation_resets_test",
+ srcs = ["@lowrisc_opentitan//sw/device/tests/sim_dv:all_escalation_resets_test.c"],
+ deps = [
+ "//sw/device/lib/dif:alert_handler",
+ "//sw/device/lib/dif:clkmgr",
+ "//sw/device/lib/dif:rstmgr",
+ "//sw/device/lib/dif:rv_plic_sec",
+ "//sw/device/tests:test_dv_lib_opentitan",
+ "@lowrisc_opentitan//sw/device/lib/base:abs_mmio",
+ "@lowrisc_opentitan//sw/device/lib/dif:aes",
+ "@lowrisc_opentitan//sw/device/lib/dif:aon_timer",
+ "@lowrisc_opentitan//sw/device/lib/dif:flash_ctrl",
+ "@lowrisc_opentitan//sw/device/lib/dif:kmac",
+ "@lowrisc_opentitan//sw/device/lib/dif:lc_ctrl",
+ "@lowrisc_opentitan//sw/device/lib/dif:otp_ctrl",
+ "@lowrisc_opentitan//sw/device/lib/dif:pwrmgr",
+ "@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",
+ "@lowrisc_opentitan//sw/device/lib/testing:rv_plic_testutils",
+ ],
+)