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",
+    ],
+)