Merge "[ml_top/hw] Update Kelvin with mlu mask on branch"
diff --git a/hw/top_matcha/dv/chip_sim_cfg.hjson b/hw/top_matcha/dv/chip_sim_cfg.hjson
index 164c73a..5c178f4 100644
--- a/hw/top_matcha/dv/chip_sim_cfg.hjson
+++ b/hw/top_matcha/dv/chip_sim_cfg.hjson
@@ -409,98 +409,98 @@
tests: [
{
name: chip_sw_smc_isp_wrapper_tpg_64_64_test
- uvm_test_seq: chip_sw_base_vseq
+ uvm_test_seq: chip_sw_smc_base_vseq
sw_images: ["//sw/device/tests/smc:smc_isp_wrapper_tpg_64_64_test:6:matcha"]
en_run_modes: ["sw_test_mode_test_simple_sec"]
run_opts:["+sw_test_timeout_ns=40_000_000"]
}
{
name: chip_sw_smc_env_test
- uvm_test_seq: chip_sw_base_vseq
+ uvm_test_seq: chip_sw_smc_base_vseq
sw_images: ["//sw/device/tests/smc:smc_env_test:6:matcha"]
en_run_modes: ["sw_test_mode_test_simple_sec"]
run_opts:["+sw_test_timeout_ns=40_000_000"]
}
{
name: chip_sw_smc_isp_wrapper_irq_test
- uvm_test_seq: chip_sw_base_vseq
+ uvm_test_seq: chip_sw_smc_base_vseq
sw_images: ["//sw/device/tests/smc:smc_isp_wrapper_irq_test:6:matcha"]
en_run_modes: ["sw_test_mode_test_simple_sec"]
run_opts:["+sw_test_timeout_ns=40_000_000"]
}
{
name: chip_sw_smc_tlul_mailbox_test
- uvm_test_seq: chip_sw_base_vseq
+ uvm_test_seq: chip_sw_smc_base_vseq
sw_images: ["//sw/device/tests/smc:smc_tlul_mailbox_test:6:matcha"]
en_run_modes: ["sw_test_mode_test_simple_sec"]
run_opts:["+sw_test_timeout_ns=40_000_000"]
}
{
name: chip_sw_smc_cam_irq_test
- uvm_test_seq: chip_sw_base_vseq
+ uvm_test_seq: chip_sw_smc_base_vseq
sw_images: ["//sw/device/tests/smc:smc_cam_irq_test:6:matcha"]
en_run_modes: ["sw_test_mode_test_simple_sec"]
run_opts:["+sw_test_timeout_ns=40_000_000"]
}
{
name: chip_sw_smc_ml_sram_smoketest
- uvm_test_seq: chip_sw_base_vseq
+ uvm_test_seq: chip_sw_smc_base_vseq
sw_images: ["//sw/device/tests/smc:smc_ml_dmem_test:6:matcha"]
en_run_modes: ["sw_test_mode_test_simple_sec"]
run_opts:["+sw_test_timeout_ns=40_000_000"]
}
{
name: chip_sw_smc_kelvin_hello_test
- uvm_test_seq: chip_sw_base_vseq
+ uvm_test_seq: chip_sw_smc_base_vseq
sw_images: ["//sw/device/tests/smc:smc_kelvin_hello_test:6:matcha"]
en_run_modes: ["sw_test_mode_test_simple_sec"]
run_opts:["+sw_test_timeout_ns=40_000_000"]
}
{
name: chip_sw_smc_ml_top_irq_test
- uvm_test_seq: chip_sw_base_vseq
+ uvm_test_seq: chip_sw_smc_base_vseq
sw_images: ["//sw/device/tests/smc:smc_ml_top_irq_test:6:matcha"]
en_run_modes: ["sw_test_mode_test_simple_sec"]
run_opts:["+sw_test_timeout_ns=40_000_000"]
}
{
name: chip_sw_smc_supervisor_mode_test
- uvm_test_seq: chip_sw_base_vseq
+ uvm_test_seq: chip_sw_smc_base_vseq
sw_images: ["//sw/device/tests/smc:smc_supervisor_mode_test:6:matcha"]
en_run_modes: ["sw_test_mode_test_simple_sec"]
run_opts:["+sw_test_timeout_ns=40_000_000"]
}
{
name: chip_sw_smc_virtual_memory_test
- uvm_test_seq: chip_sw_base_vseq
+ uvm_test_seq: chip_sw_smc_base_vseq
sw_images: ["//sw/device/tests/smc:smc_virtual_memory_test:6:matcha"]
en_run_modes: ["sw_test_mode_test_simple_sec"]
run_opts:["+sw_test_timeout_ns=40_000_000"]
}
{
name: chip_sw_smc_interrupt_boundary_test
- uvm_test_seq: chip_sw_base_vseq
+ uvm_test_seq: chip_sw_smc_base_vseq
sw_images: ["//sw/device/tests/smc:smc_interrupt_boundary_test:6:matcha"]
en_run_modes: ["sw_test_mode_test_simple_sec"]
run_opts:["+sw_test_timeout_ns=40_000_000"]
}
{
name: chip_sw_smc_lsu_interrupt_boundary_test
- uvm_test_seq: chip_sw_base_vseq
+ uvm_test_seq: chip_sw_smc_base_vseq
sw_images: ["//sw/device/tests/smc:smc_lsu_interrupt_boundary_test:6:matcha"]
en_run_modes: ["sw_test_mode_test_simple_sec"]
run_opts:["+sw_test_timeout_ns=40_000_000"]
}
{
name: chip_sw_smc_page_boundary_test
- uvm_test_seq: chip_sw_base_vseq
+ uvm_test_seq: chip_sw_smc_base_vseq
sw_images: ["//sw/device/tests/smc:smc_page_boundary_test:6:matcha"]
en_run_modes: ["sw_test_mode_test_simple_sec"]
run_opts:["+sw_test_timeout_ns=40_000_000"]
}
{
name: chip_sw_smc_lsu_page_boundary_test
- uvm_test_seq: chip_sw_base_vseq
+ uvm_test_seq: chip_sw_smc_base_vseq
sw_images: ["//sw/device/tests/smc:smc_lsu_page_boundary_test:6:matcha"]
en_run_modes: ["sw_test_mode_test_simple_sec"]
run_opts:["+sw_test_timeout_ns=40_000_000"]
@@ -549,35 +549,35 @@
}
{
name: chip_sw_smc_i2s_rx_test
- uvm_test_seq: chip_sw_base_vseq
+ uvm_test_seq: chip_sw_smc_base_vseq
sw_images: ["//sw/device/tests/smc:smc_i2s_rx_test:6:matcha"]
en_run_modes: ["sw_test_mode_test_simple_sec"]
run_opts:["+sw_test_timeout_ns=40_000_000"]
}
{
name: chip_sw_smc_i2s_tx_test
- uvm_test_seq: chip_sw_base_vseq
+ uvm_test_seq: chip_sw_smc_base_vseq
sw_images: ["//sw/device/tests/smc:smc_i2s_tx_test:6:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts:["+sw_test_timeout_ns=40_000_000"]
}
{
name: chip_sw_smc_rv_timer_test
- uvm_test_seq: chip_sw_base_vseq
+ uvm_test_seq: chip_sw_smc_base_vseq
sw_images: ["//sw/device/tests/smc:smc_rv_timer_test:6:matcha"]
en_run_modes: ["sw_test_mode_test_simple_sec"]
run_opts:["+sw_test_timeout_ns=40_000_000"]
}
{
name: chip_sw_smc_kelvin_checksum_test
- uvm_test_seq: chip_sw_base_vseq
+ uvm_test_seq: chip_sw_smc_base_vseq
sw_images: ["//sw/device/tests/smc:smc_kelvin_checksum_test:6:matcha"]
en_run_modes: ["sw_test_mode_test_simple_sec"]
run_opts:["+sw_test_timeout_ns=40_000_000"]
}
{
name: chip_sw_smc_isp_wrapper_test
- uvm_test_seq: chip_sw_base_vseq
+ uvm_test_seq: chip_sw_smc_base_vseq
sw_images: ["//sw/device/tests/smc:smc_isp_wrapper_test:6:matcha"]
en_run_modes: ["sw_test_mode_test_simple_sec"]
run_opts:["+sw_test_timeout_ns=40_000_000"]
@@ -667,7 +667,7 @@
{
name: chip_sw_sleep_pin_retention
uvm_test_seq: chip_sw_sleep_pin_retention_vseq
- sw_images: ["//sw/device/tests/sim_dv:sleep_pin_retention_test:1"]
+ sw_images: ["//sw/device/tests/sim_dv:sleep_pin_retention_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
}
{
@@ -826,7 +826,7 @@
{
name: chip_sw_gpio
uvm_test_seq: chip_sw_gpio_vseq
- sw_images: ["//sw/device/tests/sim_dv:gpio_test:1"]
+ sw_images: ["//sw/device/tests/sim_dv:gpio_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
}
{
@@ -1092,7 +1092,7 @@
{
name: chip_sw_pwrmgr_random_sleep_all_reset_reqs
uvm_test_seq: chip_sw_random_sleep_all_reset_vseq
- sw_images: ["//sw/device/tests/sim_dv:pwrmgr_random_sleep_all_reset_reqs_test:1"]
+ sw_images: ["//sw/device/tests/sim_dv:pwrmgr_random_sleep_all_reset_reqs_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+sw_test_timeout_ns=50_000_000"]
run_timeout_mins: 120
@@ -1100,7 +1100,7 @@
{
name: chip_sw_pwrmgr_deep_sleep_all_reset_reqs
uvm_test_seq: chip_sw_deep_sleep_all_reset_vseq
- sw_images: ["//sw/device/tests/sim_dv:pwrmgr_deep_sleep_all_reset_reqs_test:1"]
+ sw_images: ["//sw/device/tests/sim_dv:pwrmgr_deep_sleep_all_reset_reqs_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+sw_test_timeout_ns=50_000_000"]
run_timeout_mins: 120
@@ -1108,28 +1108,28 @@
{
name: chip_sw_pwrmgr_normal_sleep_all_reset_reqs
uvm_test_seq: chip_sw_deep_sleep_all_reset_vseq
- sw_images: ["//sw/device/tests/sim_dv:pwrmgr_normal_sleep_all_reset_reqs_test:1"]
+ sw_images: ["//sw/device/tests/sim_dv:pwrmgr_normal_sleep_all_reset_reqs_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_timeout_mins: 120
}
{
name: chip_sw_pwrmgr_sleep_power_glitch_reset
uvm_test_seq: chip_sw_main_power_glitch_vseq
- sw_images: ["//sw/device/tests/sim_dv:pwrmgr_sleep_power_glitch_test:1"]
+ sw_images: ["//sw/device/tests/sim_dv:pwrmgr_sleep_power_glitch_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+bypass_alert_ready_to_end_check=1"]
}
{
name: chip_sw_pwrmgr_deep_sleep_power_glitch_reset
uvm_test_seq: chip_sw_deep_power_glitch_vseq
- sw_images: ["//sw/device/tests/sim_dv:pwrmgr_deep_sleep_power_glitch_test:1"]
+ sw_images: ["//sw/device/tests/sim_dv:pwrmgr_deep_sleep_power_glitch_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+bypass_alert_ready_to_end_check=1"]
}
{
name: chip_sw_pwrmgr_random_sleep_power_glitch_reset
uvm_test_seq: chip_sw_random_power_glitch_vseq
- sw_images: ["//sw/device/tests/sim_dv:pwrmgr_random_sleep_power_glitch_reset_test:1"]
+ sw_images: ["//sw/device/tests/sim_dv:pwrmgr_random_sleep_power_glitch_reset_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+bypass_alert_ready_to_end_check=1",
"+sw_test_timeout_ns=24_000_000"]
@@ -1629,7 +1629,7 @@
{
name: chip_sw_pwrmgr_b2b_sleep_reset_req
uvm_test_seq: chip_sw_repeat_reset_wkup_vseq
- sw_images: ["//sw/device/tests/sim_dv:pwrmgr_b2b_sleep_reset_test:1"]
+ sw_images: ["//sw/device/tests/sim_dv:pwrmgr_b2b_sleep_reset_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+sw_test_timeout_ns=35_000_000"]
run_timeout_mins: 120
@@ -2017,6 +2017,7 @@
"chip_sw_csrng_smoketest",
"chip_sw_dma_main_test",
"chip_sw_example_flash",
+ "chip_sw_gpio",
"chip_sw_i2c_host_tx_rx",
"chip_sw_mem_test",
"chip_sw_rom_ctrl_integrity_check",
@@ -2070,6 +2071,7 @@
"chip_sw_flash_ctrl_access",
"chip_sw_flash_ctrl_access_jitter_en",
"chip_sw_flash_ctrl_access_jitter_en_reduced_freq",
+ "chip_sw_gpio",
"chip_sw_hmac_enc",
"chip_sw_hmac_smoketest",
"chip_sw_i2c_host_tx_rx",
@@ -2081,6 +2083,8 @@
"chip_sw_otbn_smoketest",
"chip_sw_otp_ctrl_escalation",
"chip_sw_otp_ctrl_smoketest",
+ "chip_sw_pwrmgr_deep_sleep_power_glitch_reset",
+ "chip_sw_pwrmgr_sleep_power_glitch_reset",
"chip_sw_rom_ctrl_integrity_check",
"chip_sw_rstmgr_smoketest",
"chip_sw_rstmgr_sw_req",
@@ -2092,6 +2096,7 @@
"chip_sw_rv_timer_irq",
"chip_sw_sensor_ctrl_alert",
"chip_sw_sensor_ctrl_status",
+ "chip_sw_sleep_pin_retention",
"chip_sw_smc_cam_irq_test",
"chip_sw_smc_ctrl_test",
"chip_sw_smc_env_test",
@@ -2139,6 +2144,7 @@
"chip_sw_flash_ctrl_access",
"chip_sw_flash_ctrl_access_jitter_en",
"chip_sw_flash_ctrl_access_jitter_en_reduced_freq",
+ "chip_sw_gpio",
"chip_sw_hmac_enc",
"chip_sw_hmac_smoketest",
"chip_sw_i2c_host_tx_rx",
@@ -2150,6 +2156,13 @@
"chip_sw_otbn_smoketest",
"chip_sw_otp_ctrl_escalation",
"chip_sw_otp_ctrl_smoketest",
+ "chip_sw_pwrmgr_b2b_sleep_reset_req",
+ "chip_sw_pwrmgr_deep_sleep_all_reset_reqs",
+ "chip_sw_pwrmgr_deep_sleep_power_glitch_reset",
+ "chip_sw_pwrmgr_normal_sleep_all_reset_reqs",
+ "chip_sw_pwrmgr_random_sleep_all_reset_reqs",
+ "chip_sw_pwrmgr_random_sleep_power_glitch_reset",
+ "chip_sw_pwrmgr_sleep_power_glitch_reset",
"chip_sw_pwrmgr_sleep_sensor_ctrl_alert_wakeup",
"chip_sw_rom_ctrl_integrity_check",
"chip_sw_rstmgr_smoketest",
@@ -2162,6 +2175,7 @@
"chip_sw_rv_timer_irq",
"chip_sw_sensor_ctrl_alert",
"chip_sw_sensor_ctrl_status",
+ "chip_sw_sleep_pin_retention",
"chip_sw_smc_cam_irq_test",
"chip_sw_smc_ctrl_test",
"chip_sw_smc_env_test",
diff --git a/hw/top_matcha/dv/env/chip_env.core b/hw/top_matcha/dv/env/chip_env.core
index 28fb4bf..8b229e1 100644
--- a/hw/top_matcha/dv/env/chip_env.core
+++ b/hw/top_matcha/dv/env/chip_env.core
@@ -55,6 +55,7 @@
- seq_lib/chip_prim_tl_access_vseq.sv: {is_include_file: true}
- seq_lib/chip_tap_straps_vseq.sv: {is_include_file: true}
- seq_lib/chip_sw_base_vseq.sv: {is_include_file: true}
+ - seq_lib/chip_sw_smc_base_vseq.sv: {is_include_file: true}
- seq_lib/chip_sw_uart_smoke_vseq.sv: {is_include_file: true}
- seq_lib/chip_jtag_base_vseq.sv: {is_include_file: true}
- seq_lib/chip_sw_alert_handler_entropy_vseq.sv: {is_include_file: true}
diff --git a/hw/top_matcha/dv/env/chip_if.sv b/hw/top_matcha/dv/env/chip_if.sv
index 5b576bc..6663de3 100644
--- a/hw/top_matcha/dv/env/chip_if.sv
+++ b/hw/top_matcha/dv/env/chip_if.sv
@@ -404,9 +404,9 @@
// hw/top_matcha/rtl/chip_matcha_verilator.sv and
// sw/device/lib/testing/pinmux_testutils.c
pins_if #(.Width(NUM_GPIOS), .PullStrength("Weak")) gpios_if(
- .pins({mios[top_matcha_pkg::MioPadIor10], mios[top_matcha_pkg::MioPadIoc8],
+ .pins({mios[top_matcha_pkg::MioPadIor10], mios[top_matcha_pkg::MioPadIod1],
mios[top_matcha_pkg::MioPadIor7], mios[top_matcha_pkg::MioPadIor6],
- mios[top_matcha_pkg::MioPadIoc5], mios[top_matcha_pkg::MioPadIoc9],
+ mios[top_matcha_pkg::MioPadIod0], mios[top_matcha_pkg::MioPadIoc9],
mios[top_matcha_pkg::MioPadIoc7], mios[top_matcha_pkg::MioPadIoc2],
mios[top_matcha_pkg::MioPadIoc1], mios[top_matcha_pkg::MioPadIoc0],
mios[top_matcha_pkg::MioPadIoc6], mios[top_matcha_pkg::MioPadIob12],
diff --git a/hw/top_matcha/dv/env/seq_lib/chip_sw_base_vseq.sv b/hw/top_matcha/dv/env/seq_lib/chip_sw_base_vseq.sv
index ad8fdc2..f2a74c4 100644
--- a/hw/top_matcha/dv/env/seq_lib/chip_sw_base_vseq.sv
+++ b/hw/top_matcha/dv/env/seq_lib/chip_sw_base_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
@@ -58,7 +59,6 @@
`uvm_info(`gfn, "Starting cpu_init", UVM_MEDIUM)
// Initialize the sw logger interface.
- // SEC
foreach (cfg.sw_images[i]) begin
if (i inside {SwTypeRom, SwTypeDebug, SwTypeTestSlotA, SwTypeTestSlotB}) begin
cfg.sw_logger_vif.add_sw_log_db(cfg.sw_images[i]);
@@ -67,19 +67,9 @@
cfg.sw_logger_vif.sw_log_addr = SW_DV_LOG_ADDR;
cfg.sw_logger_vif.write_sw_logs_to_file = cfg.write_sw_logs_to_file;
cfg.sw_logger_vif.ready();
- // SMC
- foreach (cfg.sw_images[i]) begin
- if (i inside {SwTypeSmc}) begin
- cfg.sw_smc_logger_vif.add_sw_log_db(cfg.sw_images[i]);
- end
- end
- cfg.sw_smc_logger_vif.sw_log_addr = SW_DV_SMC_LOG_ADDR;
- cfg.sw_smc_logger_vif.write_sw_logs_to_file = cfg.write_sw_logs_to_file;
- cfg.sw_smc_logger_vif.ready();
// Initialize the sw test status.
- cfg.sw_test_status_vif.sw_test_status_addr = SW_DV_TEST_STATUS_ADDR;
- cfg.sw_smc_test_status_vif.sw_test_status_addr = SW_DV_SMC_TEST_STATUS_ADDR;
+ cfg.sw_test_status_vif.sw_test_status_addr = SW_DV_TEST_STATUS_ADDR;
`uvm_info(`gfn, "Initializing SRAMs", UVM_MEDIUM)
@@ -129,11 +119,6 @@
cfg.mem_bkdr_util_h[FlashBank1Data].load_mem_from_file(
{cfg.sw_images[SwTypeTestSlotB], ".64.scr.vmem"});
end
- // SMC RAM sw imsage load
- if (cfg.sw_images.exists(SwTypeSmc)) begin
- cfg.mem_bkdr_util_h[Smc_ram].load_mem_from_file(
- {cfg.sw_images[SwTypeSmc], ".32.vmem"});
- end
config_jitter();
@@ -247,7 +232,7 @@
fork
begin: isolation_thread
fork
- wait (cfg.sw_test_status_vif.sw_test_done || cfg.sw_smc_test_status_vif.sw_test_done);
+ wait (cfg.sw_test_status_vif.sw_test_done);
#(cfg.sw_test_timeout_ns * 1ns);
join_any
disable fork;
@@ -258,24 +243,15 @@
// Print pass / fail message to the log.
virtual function void log_sw_test_status();
- if(cfg.sw_test_status_vif.sw_test_done || cfg.sw_smc_test_status_vif.sw_test_done) begin
- if(cfg.sw_test_status_vif.sw_test_done) begin
- case (cfg.sw_test_status_vif.sw_test_status)
- SwTestStatusPassed: `uvm_info(`gfn, "[SEC] SW TEST PASSED!", UVM_LOW)
- SwTestStatusFailed: `uvm_error(`gfn, "[SEC] SW TEST FAILED!")
- endcase
- end
- if(cfg.sw_smc_test_status_vif.sw_test_done) begin
- case (cfg.sw_smc_test_status_vif.sw_test_status)
- SwTestStatusPassed: `uvm_info(`gfn, "[SMC] SW TEST PASSED!", UVM_LOW)
- SwTestStatusFailed: `uvm_error(`gfn, "[SMC] SW TEST FAILED!")
- endcase
- end
- end
- else begin
+ case (cfg.sw_test_status_vif.sw_test_status)
+ SwTestStatusPassed: `uvm_info(`gfn, "SW TEST PASSED!", UVM_LOW)
+ SwTestStatusFailed: `uvm_error(`gfn, "SW TEST FAILED!")
+ default: begin
+ // If the SW test has not reached the passed / failed state, then it timed out.
`uvm_error(`gfn, $sformatf("SW TEST TIMED OUT. STATE: %0s, TIMEOUT = %0d ns\n",
- cfg.sw_smc_test_status_vif.sw_test_status.name(), cfg.sw_test_timeout_ns))
- end
+ cfg.sw_test_status_vif.sw_test_status.name(), cfg.sw_test_timeout_ns))
+ end
+ endcase
endfunction
// Configure the provided spi_agent_cfg to use flash mode, and add the
diff --git a/hw/top_matcha/dv/env/seq_lib/chip_sw_gpio_vseq.sv b/hw/top_matcha/dv/env/seq_lib/chip_sw_gpio_vseq.sv
index c6266ca..e6a5ddc 100644
--- a/hw/top_matcha/dv/env/seq_lib/chip_sw_gpio_vseq.sv
+++ b/hw/top_matcha/dv/env/seq_lib/chip_sw_gpio_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
@@ -20,6 +21,7 @@
gpio_output_test();
// Run the GPIO input tests.
+ cfg.chip_vif.gpios_if.disconnect();
gpio_input_test();
endtask
diff --git a/hw/top_matcha/dv/env/seq_lib/chip_sw_smc_base_vseq.sv b/hw/top_matcha/dv/env/seq_lib/chip_sw_smc_base_vseq.sv
new file mode 100644
index 0000000..612c3f2
--- /dev/null
+++ b/hw/top_matcha/dv/env/seq_lib/chip_sw_smc_base_vseq.sv
@@ -0,0 +1,69 @@
+// 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_smc_base_vseq extends chip_sw_base_vseq;
+ `uvm_object_utils(chip_sw_smc_base_vseq)
+
+ `uvm_object_new
+
+ virtual task cpu_init();
+ super.cpu_init();
+
+ `uvm_info(`gfn, "Starting SMC cpu_init", UVM_MEDIUM)
+
+ foreach (cfg.sw_images[i]) begin
+ if (i inside {SwTypeSmc}) begin
+ cfg.sw_smc_logger_vif.add_sw_log_db(cfg.sw_images[i]);
+ end
+ end
+ cfg.sw_smc_logger_vif.sw_log_addr = SW_DV_SMC_LOG_ADDR;
+ cfg.sw_smc_logger_vif.write_sw_logs_to_file = cfg.write_sw_logs_to_file;
+ cfg.sw_smc_logger_vif.ready();
+
+ // Initialize the sw test status.
+ cfg.sw_smc_test_status_vif.sw_test_status_addr = SW_DV_SMC_TEST_STATUS_ADDR;
+
+ // SMC RAM sw image load
+ if (cfg.sw_images.exists(SwTypeSmc)) begin
+ cfg.mem_bkdr_util_h[Smc_ram].load_mem_from_file(
+ {cfg.sw_images[SwTypeSmc], ".32.vmem"});
+ end
+
+ `uvm_info(`gfn, "SMC cpu_init completed", UVM_MEDIUM)
+ endtask
+
+ virtual task body();
+ cfg.sw_smc_test_status_vif.set_num_iterations(num_trans);
+ // Initialize the CPU to kick off the sw test. TODO: Should be called in pre_start() instead.
+ cpu_init();
+ endtask
+
+ virtual task wait_for_sw_test_done();
+ `uvm_info(`gfn, "Waiting for the SW test to finish", UVM_MEDIUM)
+ fork
+ begin: isolation_thread
+ fork
+ wait (cfg.sw_smc_test_status_vif.sw_test_done);
+ #(cfg.sw_test_timeout_ns * 1ns);
+ join_any
+ disable fork;
+ log_sw_test_status();
+ end: isolation_thread
+ join
+ endtask
+
+ virtual function void log_sw_test_status();
+ case (cfg.sw_smc_test_status_vif.sw_test_status)
+ SwTestStatusPassed: `uvm_info(`gfn, "SW TEST PASSED!", UVM_LOW)
+ SwTestStatusFailed: `uvm_error(`gfn, "SW TEST FAILED!")
+ default: begin
+ // If the SW test has not reached the passed / failed state, then it timed out.
+ `uvm_error(`gfn, $sformatf("SW TEST TIMED OUT. STATE: %0s, TIMEOUT = %0d ns\n",
+ cfg.sw_smc_test_status_vif.sw_test_status.name(), cfg.sw_test_timeout_ns))
+ end
+ endcase
+ 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 ebe1a2b..3701ea8 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
@@ -11,6 +11,7 @@
`include "chip_jtag_mem_vseq.sv"
// This needs to be listed prior to all sequences that derive from it.
`include "chip_sw_base_vseq.sv"
+`include "chip_sw_smc_base_vseq.sv"
`include "chip_sw_uart_smoke_vseq.sv"
`include "chip_jtag_base_vseq.sv"
`include "chip_prim_tl_access_vseq.sv"
diff --git a/hw/top_matcha/ip/ast/ast.core b/hw/top_matcha/ip/ast/ast.core
index 9211b6c..ac3dadc 100644
--- a/hw/top_matcha/ip/ast/ast.core
+++ b/hw/top_matcha/ip/ast/ast.core
@@ -45,6 +45,8 @@
- rtl/sys_osc.sv
- rtl/usb_clk.sv
- rtl/usb_osc.sv
+ - rtl/audio_clk.sv
+ - rtl/audio_osc.sv
- rtl/gfr_clk_mux2.sv
- rtl/ast_clks_byp.sv
- rtl/rglts_pdm_3p3v.sv
diff --git a/hw/top_matcha/ip/ast/rtl/ast.sv b/hw/top_matcha/ip/ast/rtl/ast.sv
index 0c7c900..5f00c1c 100644
--- a/hw/top_matcha/ip/ast/rtl/ast.sv
+++ b/hw/top_matcha/ip/ast/rtl/ast.sv
@@ -98,18 +98,22 @@
output logic [UsbCalibWidth-1:0] usb_io_pu_cal_o, // USB IO Pull-up Calibration Setting
// smc source clock
+ input clk_src_smc_en_i, // SMC Source Clock Enable
output logic clk_src_smc_o, // SMC Source Clock
output logic clk_src_smc_val_o, // SMC Source Clock Valid
// ml source clock
+ input clk_src_ml_en_i, // ML Source Clock Enable
output logic clk_src_ml_o, // ML Source Clock
output logic clk_src_ml_val_o, // ML Source Clock Valid
// video source clock
+ input clk_src_video_en_i, // VideO Source Clock Enable
output logic clk_src_video_o, // Video Source Clock
output logic clk_src_video_val_o, // Video Source Clock Valid
// audio source clock
+ input clk_src_audio_en_i, // AUDIO Source Clock Enable
output logic clk_src_audio_o, // audio Source Clock
output logic clk_src_audio_val_o, // audio Source Clock Valid
@@ -518,6 +522,36 @@
///////////////////////////////////////
+// AUDIO Clock (Always ON)
+///////////////////////////////////////
+logic rst_audio_clk_n, clk_audio_pd_n;
+logic clk_src_audio_en, clk_osc_audio, clk_osc_audio_val;
+
+assign rst_audio_clk_n = vcmain_pok_por && vcc_pok;
+assign clk_audio_pd_n = scan_mode || !deep_sleep;
+
+`ifdef AST_BYPASS_CLK
+logic clk_audio_ext;
+assign clk_audio_ext = clk_osc_byp_i.audio;
+`endif
+
+assign clk_src_audio_en = clk_src_audio_en_i;
+
+audio_clk u_audio_clk (
+ .vcore_pok_h_i ( vcaon_pok_h ),
+ .clk_audio_pd_ni ( clk_audio_pd_n ),
+ .rst_audio_clk_ni ( rst_audio_clk_n ),
+ .clk_src_audio_en_i ( clk_src_audio_en ),
+ .scan_mode_i ( scan_mode ),
+ .audio_osc_cal_i ( sys_io_osc_cal ),
+`ifdef AST_BYPASS_CLK
+ .clk_audio_ext_i ( clk_audio_ext ),
+`endif
+ .clk_src_audio_o ( clk_osc_audio ),
+ .clk_src_audio_val_o ( clk_osc_audio_val )
+);
+
+///////////////////////////////////////
// AST Clocks Bypass
///////////////////////////////////////
logic clk_src_sys, clk_src_io, clk_src_usb, clk_src_aon;
@@ -536,6 +570,9 @@
.clk_osc_usb_val_i ( clk_osc_usb_val ),
.clk_osc_aon_i ( clk_osc_aon ),
.clk_osc_aon_val_i ( clk_osc_aon_val ),
+ .clk_src_audio_en_i ( clk_src_audio_en_i ),
+ .clk_osc_audio_i ( clk_osc_audio ),
+ .clk_osc_audio_val_i ( clk_osc_audio_val ),
.clk_ast_ext_i ( clk_ast_ext_i ),
.io_clk_byp_req_i ( io_clk_byp_req_i ),
.all_clk_byp_req_i ( all_clk_byp_req_i ),
@@ -550,7 +587,9 @@
.clk_src_usb_o ( clk_src_usb ),
.clk_src_usb_val_o ( clk_src_usb_val_o ),
.clk_src_aon_o ( clk_src_aon ),
- .clk_src_aon_val_o ( clk_src_aon_val_o )
+ .clk_src_aon_val_o ( clk_src_aon_val_o ),
+ .clk_src_audio_o ( clk_src_audio ),
+ .clk_src_audio_val_o ( clk_src_audio_val_o )
);
// System source clock buffer
@@ -590,47 +629,48 @@
);
-// TO-DO(pbf): Add PLL output for new clocks: smc, ml, video, audio
-// For now, just use the same clock as clk_osc_ss
-
-assign clk_src_smc_val_o = 1'b1;
-assign clk_src_ml_val_o = 1'b1;
-assign clk_src_video_val_o = 1'b1;
-assign clk_src_audio_val_o = 1'b1;
+// TO-DO(VSI): Add PLL output for new clocks: smc, ml, video
+// For DV test purpose as of now, smc/ml/video clock will just use the same clock as clk_src_syc.
// SMC source clock buffer
////////////////////////////////////////
prim_clock_buf #(
.NoFpgaBuf ( 1'b1 )
) u_clk_src_smc_buf (
- .clk_i ( clk_src_sys ), // TO-DO(pbf): use the sys_clk for now. Change to different clock late.
+ .clk_i ( clk_src_sys ), // TO-DO(VSI): use the sys_clk for now. Change to SMC clock late.
.clk_o ( clk_src_smc_o )
);
+assign clk_src_smc_val_o = clk_src_sys_val_o;
+
// ML source clock buffer
////////////////////////////////////////
prim_clock_buf #(
.NoFpgaBuf ( 1'b1 )
) u_clk_src_ml_buf (
- .clk_i ( clk_src_sys ), // TO-DO(pbf):use the sys_clk for now. Change to different clock late.
+ .clk_i ( clk_src_sys ), // TO-DO(VSI):use the sys_clk for now. Change to ML clock late.
.clk_o ( clk_src_ml_o )
);
+assign clk_src_ml_val_o = clk_src_sys_val_o;
+
// video source clock buffer
////////////////////////////////////////
prim_clock_buf #(
.NoFpgaBuf ( 1'b1 )
) u_clk_src_video_buf (
- .clk_i ( clk_src_sys ), // TO-DO(pbf):use the sys_clk for now. Change to different clock late.
+ .clk_i ( clk_src_sys ), // TO-DO(VSI):use the sys_clk for now. Change to video clock late.
.clk_o ( clk_src_video_o )
);
+assign clk_src_video_val_o = clk_src_sys_val_o;
+
// audio source clock buffer
////////////////////////////////////////
prim_clock_buf #(
.NoFpgaBuf ( 1'b1 )
) u_clk_src_audio_buf (
- .clk_i ( clk_src_usb ), // TO-DO(pbf): use 48Mhz usb clock as audio clock for FPGA for now.
+ .clk_i ( clk_src_audio ),
.clk_o ( clk_src_audio_o )
);
diff --git a/hw/top_matcha/ip/ast/rtl/ast_clks_byp.sv b/hw/top_matcha/ip/ast/rtl/ast_clks_byp.sv
index f7d6c0e..f21c774 100644
--- a/hw/top_matcha/ip/ast/rtl/ast_clks_byp.sv
+++ b/hw/top_matcha/ip/ast/rtl/ast_clks_byp.sv
@@ -26,6 +26,9 @@
input clk_osc_usb_val_i, // USB Oscillator Clock Valid
input clk_osc_aon_i, // AON Oscillator Clock
input clk_osc_aon_val_i, // AON Oscillator Clock Valid
+ input clk_src_audio_en_i, // IO Source Clock Enable
+ input clk_osc_audio_i, // AUDIO Oscillator Clock
+ input clk_osc_audio_val_i, // AUDIO Oscillator Clock Valid
input clk_ast_ext_i, // External Clock
input prim_mubi_pkg::mubi4_t io_clk_byp_req_i, // External IO clock mux for OTP bootstrap
input prim_mubi_pkg::mubi4_t all_clk_byp_req_i, // External all clock mux override
@@ -40,7 +43,9 @@
output logic clk_src_usb_o, // USB Source Clock
output logic clk_src_usb_val_o, // USB Source Clock Valid
output logic clk_src_aon_o, // AON Source Clock
- output logic clk_src_aon_val_o // AON Source Clock Valid
+ output logic clk_src_aon_val_o, // AON Source Clock Valid
+ output logic clk_src_audio_o, // AON Source Clock
+ output logic clk_src_audio_val_o // AON Source Clock Valid
);
logic scan_mode_i, scan_reset_ni;
@@ -267,7 +272,32 @@
.clk_o ( clk_ext_usb )
);
+// AUDIO External Clock Enable
+////////////////////////////////////////
+logic clk_ext_audio, clk_ext_audio_en, clk_ext_audio_val;
+logic clk_src_audio_en;
+prim_flop_2sync #(
+ .Width ( 1 ),
+ .ResetValue ( 1'b0 )
+) u_no_scan_clk_src_audio_en_sync (
+ .clk_i ( clk_ext ),
+ .rst_ni ( rst_aon_exda_n ),
+ .d_i ( clk_src_audio_en_i ),
+ .q_o ( clk_src_audio_en )
+);
+
+assign clk_ext_audio_en = deep_sleep_n && clk_src_audio_en;
+assign clk_ext_audio_val = clk_ext_audio_en;
+
+prim_clock_gating #(
+ .NoFpgaGate ( 1'b1)
+) u_clk_ext_audio_ckgt (
+ .clk_i ( clk_ext ),
+ .en_i ( clk_ext_audio_en ),
+ .test_en_i ( scan_mode_i ),
+ .clk_o ( clk_ext_audio )
+);
////////////////////////////////////////
// SW Bypass select logic
////////////////////////////////////////
@@ -305,16 +335,17 @@
);
// Decode logic
-logic ot_all_clk_byp, ot_sys_clk_byp, ot_io_clk_byp, ot_usb_clk_byp, ot_aon_clk_byp;
+logic ot_all_clk_byp, ot_sys_clk_byp, ot_io_clk_byp, ot_usb_clk_byp, ot_aon_clk_byp, ot_audio_clk_byp;
prim_mubi4_dec u_all_byp_sel ( .mubi_i ( ot_all_clk_byp_req ), .mubi_dec_o ( ot_all_clk_byp ) );
prim_mubi4_dec u_sys_byp_sel ( .mubi_i ( ot_all_clk_byp_req ), .mubi_dec_o ( ot_sys_clk_byp ) );
prim_mubi4_dec u_io_byp_sel ( .mubi_i ( ot_io_clk_byp_req ), .mubi_dec_o ( ot_io_clk_byp ) );
prim_mubi4_dec u_usb_byp_sel ( .mubi_i ( ot_all_clk_byp_req ), .mubi_dec_o ( ot_usb_clk_byp ) );
prim_mubi4_dec u_aon_byp_sel ( .mubi_i ( ot_all_clk_byp_req ), .mubi_dec_o ( ot_aon_clk_byp ) );
+prim_mubi4_dec u_audio_byp_sel ( .mubi_i ( ot_all_clk_byp_req ), .mubi_dec_o ( ot_audio_clk_byp ) );
// De-Glitch selects (decode "noise")
-logic sw_sys_clk_byp, sw_usb_clk_byp, sw_aon_clk_byp, sw_exfr_is_96m;
+logic sw_sys_clk_byp, sw_usb_clk_byp, sw_aon_clk_byp, sw_exfr_is_96m, sw_audio_clk_byp;
prim_flop #(
.Width ( 1 ),
@@ -376,6 +407,16 @@
.q_o ( sw_exfr_is_96m )
);
+prim_flop #(
+ .Width ( 1 ),
+ .ResetValue ( 1'b0 )
+) u_sw_audio_clk_byp_dgl (
+ .clk_i ( clk_aon ),
+ .rst_ni ( rst_aon_n ),
+ .d_i ( ot_audio_clk_byp ),
+ .q_o ( sw_audio_clk_byp )
+);
+
logic sys_clk_byp;
assign sys_clk_byp = sw_sys_clk_byp;
@@ -408,9 +449,13 @@
assign extfreq_is_96m = sw_exfr_is_96m;
+logic audio_clk_byp;
+
+assign audio_clk_byp = sw_audio_clk_byp;
+
// Block changes during scan mode
////////////////////////////////////////
-logic sys_clk_byp_sel, io_clk_byp_sel, usb_clk_byp_sel, aon_clk_byp_sel;
+logic sys_clk_byp_sel, io_clk_byp_sel, usb_clk_byp_sel, aon_clk_byp_sel, audio_clk_byp_sel;
always_latch begin
if ( !scan_mode_i ) begin
@@ -419,6 +464,7 @@
usb_clk_byp_sel = usb_clk_byp;
aon_clk_byp_sel = aon_clk_byp;
ext_freq_is_96m = extfreq_is_96m;
+ audio_clk_byp_sel = audio_clk_byp;
end
end
@@ -426,8 +472,8 @@
////////////////////////////////////////
// Clocks Bypass Muxes
////////////////////////////////////////
-logic sys_clk_osc_en, io_clk_osc_en, usb_clk_osc_en, aon_clk_osc_en;
-logic sys_clk_byp_en, io_clk_byp_en, usb_clk_byp_en, aon_clk_byp_en;
+logic sys_clk_osc_en, io_clk_osc_en, usb_clk_osc_en, aon_clk_osc_en, audio_clk_osc_en;
+logic sys_clk_byp_en, io_clk_byp_en, usb_clk_byp_en, aon_clk_byp_en, audio_clk_byp_en;
logic rst_clk_osc_n, rst_clk_ext_n;
assign rst_clk_osc_n = vcaon_pok;
@@ -455,6 +501,7 @@
logic rst_clk_osc_sys_n, rst_clk_ext_sys_n, rst_clk_osc_io_n, rst_clk_ext_io_n;
logic rst_clk_osc_usb_n, rst_clk_ext_usb_n, rst_clk_osc_aon_n, rst_clk_ext_aon_n;
+logic rst_clk_osc_audio_n, rst_clk_ext_audio_n;
prim_buf u_rst_clk_osc_sys (
.in_i ( rst_clk_osc_n ),
@@ -496,6 +543,16 @@
.out_o ( rst_clk_ext_aon_n )
);
+prim_buf u_rst_clk_osc_audio (
+ .in_i ( rst_clk_osc_n ),
+ .out_o ( rst_clk_osc_audio_n )
+);
+
+prim_buf u_rst_clk_ext_audio (
+ .in_i ( rst_clk_ext_n ),
+ .out_o ( rst_clk_ext_audio_n )
+);
+
// SYS Clock Bypass Mux
////////////////////////////////////////
gfr_clk_mux2 u_clk_src_sys_sel (
@@ -560,6 +617,22 @@
.clk_o ( clk_src_aon_o )
);
+// AUDIO Clock Bypass Mux
+////////////////////////////////////////
+gfr_clk_mux2 u_clk_src_audio_sel (
+ .clk_osc_i ( clk_osc_audio_i ),
+ .clk_osc_val_i ( clk_osc_audio_val_i ),
+ .rst_clk_osc_ni ( rst_clk_osc_audio_n ),
+ .clk_ext_i ( clk_ext_audio ),
+ .clk_ext_val_i ( clk_ext_audio_val ),
+ .rst_clk_ext_ni ( rst_clk_ext_audio_n ),
+ .ext_sel_i ( audio_clk_byp_sel ),
+ .clk_osc_en_o ( audio_clk_osc_en ),
+ .clk_ext_en_o ( audio_clk_byp_en ),
+ .clk_val_o ( clk_src_audio_val_o ),
+ .clk_o ( clk_src_audio_o )
+);
+
// rst_aon_n deasset to io clock
////////////////////////////////////////
logic rst_aon_n_ioda, rst_aon_ioda_n;
@@ -585,7 +658,7 @@
all_clks_byp_en_src <= 1'b0;
end else begin
all_clks_byp_en_src <= sw_all_clk_byp && sys_clk_byp_en && io_clk_byp_en &&
- usb_clk_byp_en && aon_clk_byp_en;
+ usb_clk_byp_en && aon_clk_byp_en && audio_clk_byp_en;
end
end
diff --git a/hw/top_matcha/ip/ast/rtl/audio_clk.sv b/hw/top_matcha/ip/ast/rtl/audio_clk.sv
new file mode 100644
index 0000000..4ad7d32
--- /dev/null
+++ b/hw/top_matcha/ip/ast/rtl/audio_clk.sv
@@ -0,0 +1,63 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//############################################################################
+// *Name: audio_clk
+// *Module Description: AUDIO Clock
+//############################################################################
+
+module audio_clk (
+ input vcore_pok_h_i, // VCORE POK @3.3V (for OSC)
+ input clk_audio_pd_ni, // IO Clock Power-down
+ input rst_audio_clk_ni, // IO Clock Logic reset
+ input clk_src_audio_en_i, // IO Source Clock Enable
+ input scan_mode_i, // Scan Mode
+ input audio_osc_cal_i, // IO Oscillator Calibrated
+`ifdef AST_BYPASS_CLK
+ input clk_audio_ext_i, // FPGA/VERILATOR Clock input
+`endif
+ output logic clk_src_audio_o, // IO Source Clock
+ output logic clk_src_audio_val_o // IO Source Clock Valid
+);
+
+logic clk, osc_en, audio_clk_en;
+
+assign osc_en = (clk_src_audio_en_i && clk_audio_pd_ni && rst_audio_clk_ni);
+assign audio_clk_en = scan_mode_i || osc_en;
+
+// Clock Oscilator
+///////////////////////////////////////
+audio_osc u_audio_osc (
+ .vcore_pok_h_i ( vcore_pok_h_i ),
+ .audio_en_i ( audio_clk_en ),
+ .audio_osc_cal_i ( audio_osc_cal_i ),
+`ifdef AST_BYPASS_CLK
+ .clk_audio_ext_i ( clk_audio_ext_i ),
+`endif
+ .audio_clk_o ( clk )
+); // of u_audio_osc
+
+// Clock & Valid
+///////////////////////////////////////
+prim_clock_buf #(
+ .NoFpgaBuf ( 1'b1 )
+) u_clk_audio_buf(
+ .clk_i ( clk ),
+ .clk_o ( clk_src_audio_o )
+);
+
+// 2-stage de-assertion
+logic rst_val_n;
+assign rst_val_n = audio_clk_en;
+
+prim_flop_2sync #(
+ .Width ( 1 ),
+ .ResetValue ( 1'b0 )
+) u_no_scan_val_sync (
+ .clk_i ( clk_src_audio_o ),
+ .rst_ni ( rst_val_n ),
+ .d_i ( 1'b1 ),
+ .q_o ( clk_src_audio_val_o )
+);
+
+endmodule : audio_clk
diff --git a/hw/top_matcha/ip/ast/rtl/audio_osc.sv b/hw/top_matcha/ip/ast/rtl/audio_osc.sv
new file mode 100644
index 0000000..c24f4e7
--- /dev/null
+++ b/hw/top_matcha/ip/ast/rtl/audio_osc.sv
@@ -0,0 +1,131 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//############################################################################
+// *Name: audio_osc
+// *Module Description: AUDIO Clock Oscilator
+//############################################################################
+
+module audio_osc (
+ input vcore_pok_h_i, // VCORE POK @3.3V
+ input audio_en_i, // IO Source Clock Enable
+ input audio_osc_cal_i, // IO Oscillator Calibrated
+`ifdef AST_BYPASS_CLK
+ input clk_audio_ext_i, // FPGA/VERILATOR Clock input
+`endif
+ output logic audio_clk_o // IO Clock Output
+);
+
+`ifndef AST_BYPASS_CLK
+`ifndef SYNTHESIS
+// Behavioral Model
+////////////////////////////////////////
+timeunit 1ns / 1ps;
+
+real CLK_PERIOD;
+
+reg init_start;
+initial init_start = 1'b0;
+
+initial begin
+ #1;
+ init_start = 1'b1;
+ #1;
+ $display("\n%m: IO Clock Power-up Frequency: %0d Hz", $rtoi(10**9/CLK_PERIOD));
+end
+
+// Enable 5us RC Delay on rise
+wire en_osc_re_buf, en_osc_re;
+buf #(ast_bhv_pkg::IO_EN_RDLY, 0) b0 (en_osc_re_buf, (vcore_pok_h_i && audio_en_i));
+assign en_osc_re = en_osc_re_buf && init_start;
+
+
+// Clock Oscillator
+////////////////////////////////////////
+real CalIoClkPeriod, UncIoClkPeriod, IoClkPeriod;
+
+initial CalIoClkPeriod = $itor( 1000000/48 ); // ~20833.333333ps (48MHz)
+initial UncIoClkPeriod = $itor( $urandom_range(55555, 25000) ); // 55555-25000ps (18-40MHz)
+
+assign IoClkPeriod = (audio_osc_cal_i && init_start) ? CalIoClkPeriod : UncIoClkPeriod;
+assign CLK_PERIOD = IoClkPeriod/1000;
+
+// Free running oscillator
+reg clk_osc;
+initial clk_osc = 1'b1;
+
+always begin
+ #(CLK_PERIOD/2) clk_osc = ~clk_osc;
+end
+
+logic en_osc;
+
+// HDL Clock Gate
+logic en_clk, clk;
+
+always_latch begin
+ if ( !clk_osc ) en_clk = en_osc;
+end
+
+assign clk = clk_osc && en_clk;
+`else // of SYNTHESIS
+// SYNTHESIS/LINTER
+///////////////////////////////////////
+logic en_osc_re;
+assign en_osc_re = vcore_pok_h_i && audio_en_i;
+
+logic clk, en_osc;
+assign clk = 1'b0;
+`endif // of SYNTHESIS
+`else // of AST_BYPASS_CLK
+// VERILATOR/FPGA
+///////////////////////////////////////
+logic en_osc_re;
+assign en_osc_re = vcore_pok_h_i && audio_en_i;
+
+// Clock Oscillator
+////////////////////////////////////////
+logic clk, en_osc;
+
+prim_clock_gating #(
+ .NoFpgaGate ( 1'b1 )
+) u_clk_ckgt (
+ .clk_i ( clk_audio_ext_i ),
+ .en_i ( en_osc ),
+ .test_en_i ( 1'b0 ),
+ .clk_o ( clk )
+);
+`endif
+
+logic en_osc_fe;
+
+// Syncronize en_osc to clk FE for glitch free disable
+always_ff @( negedge clk, negedge vcore_pok_h_i ) begin
+ if ( !vcore_pok_h_i ) begin
+ en_osc_fe <= 1'b0;
+ end else begin
+ en_osc_fe <= en_osc_re;
+ end
+end
+
+assign en_osc = en_osc_re || en_osc_fe; // EN -> 1 || EN -> 0
+
+// Clock Output Buffer
+////////////////////////////////////////
+prim_clock_buf #(
+ .NoFpgaBuf ( 1'b1 )
+) u_buf (
+ .clk_i ( clk ),
+ .clk_o ( audio_clk_o )
+);
+
+
+`ifdef SYNTHESIS
+/////////////////////////
+// Unused Signals
+/////////////////////////
+logic unused_sigs;
+assign unused_sigs = ^{ audio_osc_cal_i };
+`endif
+
+endmodule : audio_osc
diff --git a/hw/top_matcha/ip/smc/rtl/smc_core.sv b/hw/top_matcha/ip/smc/rtl/smc_core.sv
index 43e5242..7748ffc 100644
--- a/hw/top_matcha/ip/smc/rtl/smc_core.sv
+++ b/hw/top_matcha/ip/smc/rtl/smc_core.sv
@@ -949,7 +949,6 @@
.mmu_data_rdata_o ( mmu_data_rdata ),
.lsu_req_i ( lsu_req ),
- .lsu_req_done_i ( lsu_req_done ),
.lsu_req_in_dec_i ( lsu_req_in_dec ),
// General Control Signals
diff --git a/hw/top_matcha/ip/smc/rtl/smc_mmu.sv b/hw/top_matcha/ip/smc/rtl/smc_mmu.sv
index ca56ac8..69880b4 100644
--- a/hw/top_matcha/ip/smc/rtl/smc_mmu.sv
+++ b/hw/top_matcha/ip/smc/rtl/smc_mmu.sv
@@ -49,7 +49,6 @@
output logic [31:0] mmu_data_rdata_o,
input logic lsu_req_i,
- input logic lsu_req_done_i, // used to ensure we don't store to dmem twice after a ptw finishes
input logic lsu_req_in_dec_i,
// General Control Signals
@@ -248,7 +247,7 @@
assign paging_en_lsu = satp_i.mode & (priv_lvl_lsu_i != PRIV_LVL_M);
// Categorize atomic RMW ops and stores as writes for pte permissions
- assign is_write = (mmu_data_we_i != LOAD) ? 1'b1 : 1'b0;
+ assign is_write = mmu_data_we_i != LOAD;
// Check page access errors based on privilege mode and mstatus bits only
assign dmem_access_error =
@@ -367,7 +366,7 @@
data_addr_o = dtlb_superpage ? {dtlb_pte_content.ppn[19:10], mmu_data_addr_i[21:0]} :
{dtlb_pte_content.ppn[19:0], mmu_data_addr_i[11:0]};
data_req_o = mmu_data_req_i;
- data_we = is_write & (ptw_finish_lsu_dec_q | lsu_req_done_i);
+ data_we = is_write;
data_be_o = mmu_data_be_i;
data_wdata_o = mmu_data_wdata_i;
diff --git a/hw/top_matcha/rtl/autogen/chip_matcha_asic.sv b/hw/top_matcha/rtl/autogen/chip_matcha_asic.sv
index 2475bdd..9f4cb53 100644
--- a/hw/top_matcha/rtl/autogen/chip_matcha_asic.sv
+++ b/hw/top_matcha/rtl/autogen/chip_matcha_asic.sv
@@ -1036,15 +1036,19 @@
.clk_src_usb_o ( ast_base_clks.clk_usb ),
.clk_src_usb_val_o ( ast_base_pwr.usb_clk_val ),
// smc source clock
+ .clk_src_smc_en_i ( base_ast_pwr.smc_clk_en ),
.clk_src_smc_o ( ast_base_clks.clk_smc ),
.clk_src_smc_val_o ( ast_base_pwr.smc_clk_val),
// ml source clock
+ .clk_src_ml_en_i ( base_ast_pwr.ml_clk_en ),
.clk_src_ml_o ( ast_base_clks.clk_ml ),
.clk_src_ml_val_o ( ast_base_pwr.ml_clk_val),
// video source clock
+ .clk_src_video_en_i ( base_ast_pwr.video_clk_en ),
.clk_src_video_o ( ast_base_clks.clk_video ),
.clk_src_video_val_o ( ast_base_pwr.video_clk_val),
// audio source clock
+ .clk_src_audio_en_i ( base_ast_pwr.audio_clk_en ),
.clk_src_audio_o ( ast_base_clks.clk_audio ),
.clk_src_audio_val_o ( ast_base_pwr.audio_clk_val),
// adc
diff --git a/hw/top_matcha/rtl/autogen/chip_matcha_nexus.sv b/hw/top_matcha/rtl/autogen/chip_matcha_nexus.sv
index fad1369..f8fb1dd 100644
--- a/hw/top_matcha/rtl/autogen/chip_matcha_nexus.sv
+++ b/hw/top_matcha/rtl/autogen/chip_matcha_nexus.sv
@@ -824,15 +824,19 @@
.clk_src_usb_o ( ast_base_clks.clk_usb ),
.clk_src_usb_val_o ( ast_base_pwr.usb_clk_val ),
// smc source clock
+ .clk_src_smc_en_i ( base_ast_pwr.smc_clk_en ),
.clk_src_smc_o ( ast_base_clks.clk_smc ),
.clk_src_smc_val_o ( ast_base_pwr.smc_clk_val),
// ml source clock
+ .clk_src_ml_en_i ( base_ast_pwr.ml_clk_en ),
.clk_src_ml_o ( ast_base_clks.clk_ml ),
.clk_src_ml_val_o ( ast_base_pwr.ml_clk_val),
// video source clock
+ .clk_src_video_en_i ( base_ast_pwr.video_clk_en ),
.clk_src_video_o ( ast_base_clks.clk_video ),
.clk_src_video_val_o ( ast_base_pwr.video_clk_val),
// audio source clock
+ .clk_src_audio_en_i ( base_ast_pwr.audio_clk_en ),
.clk_src_audio_o ( ast_base_clks.clk_audio ),
.clk_src_audio_val_o ( ast_base_pwr.audio_clk_val),
// adc
diff --git a/hw/top_matcha/rtl/chip_matcha_verilator.sv b/hw/top_matcha/rtl/chip_matcha_verilator.sv
index d66f69b..8bee784 100644
--- a/hw/top_matcha/rtl/chip_matcha_verilator.sv
+++ b/hw/top_matcha/rtl/chip_matcha_verilator.sv
@@ -486,15 +486,19 @@
.clk_src_usb_o ( ast_base_clks.clk_usb ),
.clk_src_usb_val_o ( ast_base_pwr.usb_clk_val ),
// smc source clock
+ .clk_src_smc_en_i ( base_ast_pwr.smc_clk_en ),
.clk_src_smc_o ( ast_base_clks.clk_smc ),
.clk_src_smc_val_o ( ast_base_pwr.smc_clk_val),
// ml source clock
+ .clk_src_ml_en_i ( base_ast_pwr.ml_clk_en ),
.clk_src_ml_o ( ast_base_clks.clk_ml ),
.clk_src_ml_val_o ( ast_base_pwr.ml_clk_val),
// video source clock
+ .clk_src_video_en_i ( base_ast_pwr.video_clk_en ),
.clk_src_video_o ( ast_base_clks.clk_video ),
.clk_src_video_val_o ( ast_base_pwr.video_clk_val),
// audio source clock
+ .clk_src_audio_en_i ( base_ast_pwr.audio_clk_en ),
.clk_src_audio_o ( ast_base_clks.clk_audio ),
.clk_src_audio_val_o ( ast_base_pwr.audio_clk_val),
// adc
diff --git a/sw/device/lib/testing/pinmux_testutils.c b/sw/device/lib/testing/pinmux_testutils.c
index ea18a08..d71a23e 100644
--- a/sw/device/lib/testing/pinmux_testutils.c
+++ b/sw/device/lib/testing/pinmux_testutils.c
@@ -17,41 +17,41 @@
// hw/top_matcha/rtl/chip_matcha_verilator.sv and
// hw/top_matcha/dv/env/chip_if.sv
const dif_pinmux_index_t kPinmuxTestutilsGpioInselPins[kDifGpioNumPins] = {
- kTopMatchaPinmuxInselIoa0, kTopMatchaPinmuxInselIoa1,
- kTopMatchaPinmuxInselIoa2, kTopMatchaPinmuxInselIoa3,
- kTopMatchaPinmuxInselIoa4, kTopMatchaPinmuxInselIoa5,
- kTopMatchaPinmuxInselIoa6, kTopMatchaPinmuxInselIoa7,
- kTopMatchaPinmuxInselIoa8, kTopMatchaPinmuxInselIob0,
- kTopMatchaPinmuxInselIob1, kTopMatchaPinmuxInselIob2,
- kTopMatchaPinmuxInselIob3, kTopMatchaPinmuxInselIob4,
- kTopMatchaPinmuxInselIob5, kTopMatchaPinmuxInselIob6,
- kTopMatchaPinmuxInselIob7, kTopMatchaPinmuxInselIob8,
- kTopMatchaPinmuxInselIob10, kTopMatchaPinmuxInselIob11,
- kTopMatchaPinmuxInselIob12, kTopMatchaPinmuxInselIoc6,
- kTopMatchaPinmuxInselIoc0, kTopMatchaPinmuxInselIoc1,
- kTopMatchaPinmuxInselIoc2, kTopMatchaPinmuxInselIoc7,
- kTopMatchaPinmuxInselIoc9, kTopMatchaPinmuxInselIoc5,
- kTopMatchaPinmuxInselIor6, kTopMatchaPinmuxInselIor7,
- kTopMatchaPinmuxInselIoc8, kTopMatchaPinmuxInselIor10,
+ kTopMatchaPinmuxInselIoa0, kTopMatchaPinmuxInselIoa1,
+ kTopMatchaPinmuxInselIoa2, kTopMatchaPinmuxInselIoa3,
+ kTopMatchaPinmuxInselIoa4, kTopMatchaPinmuxInselIoa5,
+ kTopMatchaPinmuxInselIoa6, kTopMatchaPinmuxInselIoa7,
+ kTopMatchaPinmuxInselIoa8, kTopMatchaPinmuxInselIob0,
+ kTopMatchaPinmuxInselIob1, kTopMatchaPinmuxInselIob2,
+ kTopMatchaPinmuxInselIob3, kTopMatchaPinmuxInselIob4,
+ kTopMatchaPinmuxInselIob5, kTopMatchaPinmuxInselIob6,
+ kTopMatchaPinmuxInselIob7, kTopMatchaPinmuxInselIob8,
+ kTopMatchaPinmuxInselIob10, kTopMatchaPinmuxInselIob11,
+ kTopMatchaPinmuxInselIob12, kTopMatchaPinmuxInselIoc6,
+ kTopMatchaPinmuxInselIoc0, kTopMatchaPinmuxInselIoc1,
+ kTopMatchaPinmuxInselIoc2, kTopMatchaPinmuxInselIoc7,
+ kTopMatchaPinmuxInselIoc9, kTopMatchaPinmuxInselIod0,
+ kTopMatchaPinmuxInselIor6, kTopMatchaPinmuxInselIor7,
+ kTopMatchaPinmuxInselIod1, kTopMatchaPinmuxInselIor10,
};
const dif_pinmux_index_t kPinmuxTestutilsGpioMioOutPins[kDifGpioNumPins] = {
- kTopMatchaPinmuxMioOutIoa0, kTopMatchaPinmuxMioOutIoa1,
- kTopMatchaPinmuxMioOutIoa2, kTopMatchaPinmuxMioOutIoa3,
- kTopMatchaPinmuxMioOutIoa4, kTopMatchaPinmuxMioOutIoa5,
- kTopMatchaPinmuxMioOutIoa6, kTopMatchaPinmuxMioOutIoa7,
- kTopMatchaPinmuxMioOutIoa8, kTopMatchaPinmuxMioOutIob0,
- kTopMatchaPinmuxMioOutIob1, kTopMatchaPinmuxMioOutIob2,
- kTopMatchaPinmuxMioOutIob3, kTopMatchaPinmuxMioOutIob4,
- kTopMatchaPinmuxMioOutIob5, kTopMatchaPinmuxMioOutIob6,
- kTopMatchaPinmuxMioOutIob7, kTopMatchaPinmuxMioOutIob8,
- kTopMatchaPinmuxMioOutIob10, kTopMatchaPinmuxMioOutIob11,
- kTopMatchaPinmuxMioOutIob12, kTopMatchaPinmuxMioOutIoc6,
- kTopMatchaPinmuxMioOutIoc0, kTopMatchaPinmuxMioOutIoc1,
- kTopMatchaPinmuxMioOutIoc2, kTopMatchaPinmuxMioOutIoc7,
- kTopMatchaPinmuxMioOutIoc9, kTopMatchaPinmuxMioOutIoc5,
- kTopMatchaPinmuxMioOutIor6, kTopMatchaPinmuxMioOutIor7,
- kTopMatchaPinmuxMioOutIoc8, kTopMatchaPinmuxMioOutIor10,
+ kTopMatchaPinmuxMioOutIoa0, kTopMatchaPinmuxMioOutIoa1,
+ kTopMatchaPinmuxMioOutIoa2, kTopMatchaPinmuxMioOutIoa3,
+ kTopMatchaPinmuxMioOutIoa4, kTopMatchaPinmuxMioOutIoa5,
+ kTopMatchaPinmuxMioOutIoa6, kTopMatchaPinmuxMioOutIoa7,
+ kTopMatchaPinmuxMioOutIoa8, kTopMatchaPinmuxMioOutIob0,
+ kTopMatchaPinmuxMioOutIob1, kTopMatchaPinmuxMioOutIob2,
+ kTopMatchaPinmuxMioOutIob3, kTopMatchaPinmuxMioOutIob4,
+ kTopMatchaPinmuxMioOutIob5, kTopMatchaPinmuxMioOutIob6,
+ kTopMatchaPinmuxMioOutIob7, kTopMatchaPinmuxMioOutIob8,
+ kTopMatchaPinmuxMioOutIob10, kTopMatchaPinmuxMioOutIob11,
+ kTopMatchaPinmuxMioOutIob12, kTopMatchaPinmuxMioOutIoc6,
+ kTopMatchaPinmuxMioOutIoc0, kTopMatchaPinmuxMioOutIoc1,
+ kTopMatchaPinmuxMioOutIoc2, kTopMatchaPinmuxMioOutIoc7,
+ kTopMatchaPinmuxMioOutIoc9, kTopMatchaPinmuxMioOutIod0,
+ kTopMatchaPinmuxMioOutIor6, kTopMatchaPinmuxMioOutIor7,
+ kTopMatchaPinmuxMioOutIod1, kTopMatchaPinmuxMioOutIor10,
};
void pinmux_testutils_init(dif_pinmux_t *pinmux) {
@@ -104,3 +104,5 @@
CHECK_DIF_OK(dif_pinmux_output_select(pinmux, kTopMatchaPinmuxMioOutIoc11,
kTopMatchaPinmuxOutselSmcUartTx));
}
+
+uint32_t pinmux_testutils_get_testable_gpios_mask(void) { return 0xffffffff; }
diff --git a/sw/device/lib/testing/pinmux_testutils.h b/sw/device/lib/testing/pinmux_testutils.h
index 984b27f..657d6f0 100644
--- a/sw/device/lib/testing/pinmux_testutils.h
+++ b/sw/device/lib/testing/pinmux_testutils.h
@@ -25,4 +25,12 @@
extern const dif_pinmux_index_t kPinmuxTestutilsGpioInselPins[kDifGpioNumPins];
extern const dif_pinmux_index_t kPinmuxTestutilsGpioMioOutPins[kDifGpioNumPins];
+/**
+ * Returns the mask of testable GPIO pins.
+ *
+ * Returns a simulation-device-specific mask that enables testing of only a
+ * subset of GPIOs depending on the IO allocation limitations.
+ */
+uint32_t pinmux_testutils_get_testable_gpios_mask(void);
+
#endif // MATCHA_SW_DEVICE_LIB_TESTING_PINMUX_TESTUTILS_H_
diff --git a/sw/device/tests/sim_dv/BUILD b/sw/device/tests/sim_dv/BUILD
index 8740d12..66a73fd 100644
--- a/sw/device/tests/sim_dv/BUILD
+++ b/sw/device/tests/sim_dv/BUILD
@@ -8,32 +8,22 @@
matcha_dv_test(
name = "uart_tx_rx_test",
srcs = ["uart_tx_rx_test.c"],
- targets = ["dv"],
deps = [
- "//hw/top_matcha/ip/clkmgr/data/autogen:clkmgr_regs",
- "//hw/top_matcha/ip/pinmux/data/autogen:pinmux_regs",
- "//hw/top_matcha/sw/autogen:top_matcha",
"//sw/device/lib/dif:clkmgr",
+ "//sw/device/lib/dif:pinmux",
"//sw/device/lib/dif:rv_plic_sec",
"//sw/device/lib/testing:clkmgr_testutils",
- "//sw/device/lib/testing/test_framework:ottf_main",
+ "//sw/device/tests:test_dv_lib",
"@lowrisc_opentitan//hw/ip/lc_ctrl/data:lc_ctrl_regs",
- "@lowrisc_opentitan//sw/device/lib/base:mmio",
"@lowrisc_opentitan//sw/device/lib/dif:lc_ctrl",
"@lowrisc_opentitan//sw/device/lib/dif:uart",
- "@lowrisc_opentitan//sw/device/lib/runtime:hart",
- "@lowrisc_opentitan//sw/device/lib/runtime:irq",
- "@lowrisc_opentitan//sw/device/lib/runtime:log",
],
)
matcha_dv_test(
name = "rv_dm_ndm_reset_req",
srcs = ["rv_dm_ndm_reset_req.c"],
- targets = ["dv"],
deps = [
- "//hw/top_matcha/ip/pinmux/data/autogen:pinmux_regs",
- "//hw/top_matcha/sw/autogen:top_matcha",
"//sw/device/lib/dif:pinmux",
"//sw/device/lib/dif:rstmgr",
"//sw/device/tests:test_dv_lib",
@@ -54,26 +44,103 @@
matcha_dv_test(
name = "i2c_host_tx_rx_test",
srcs = ["i2c_host_tx_rx_test.c"],
- targets = ["dv"],
deps = [
- "//hw/top_matcha/ip/pinmux/data/autogen:pinmux_regs",
"//sw/device/lib/dif:pinmux",
"//sw/device/lib/dif:rstmgr",
+ "//sw/device/lib/testing:isr_testutils",
"//sw/device/tests:test_dv_lib",
"@lowrisc_opentitan//sw/device/lib/dif:i2c",
"@lowrisc_opentitan//sw/device/lib/testing:i2c_testutils",
- "//sw/device/lib/testing:isr_testutils",
"@lowrisc_opentitan//sw/device/lib/testing:rand_testutils",
],
)
+cc_library(
+ name = "pwrmgr_reset_test_lib",
+ deps = [
+ "//sw/device/lib/dif:alert_handler",
+ "//sw/device/lib/dif:pinmux",
+ "//sw/device/lib/dif:rstmgr",
+ "//sw/device/lib/dif:rv_plic_sec",
+ "//sw/device/lib/testing:pinmux_testutils",
+ "//sw/device/tests:test_dv_lib",
+ "@lowrisc_opentitan//sw/device/lib/base:abs_mmio",
+ "@lowrisc_opentitan//sw/device/lib/dif:aon_timer",
+ "@lowrisc_opentitan//sw/device/lib/dif:flash_ctrl",
+ "@lowrisc_opentitan//sw/device/lib/dif:pwrmgr",
+ "@lowrisc_opentitan//sw/device/lib/dif:rv_timer",
+ "@lowrisc_opentitan//sw/device/lib/dif:sysrst_ctrl",
+ "@lowrisc_opentitan//sw/device/lib/testing:alert_handler_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:aon_timer_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:flash_ctrl_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:pwrmgr_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:rstmgr_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:rv_plic_testutils",
+ ],
+)
+
+matcha_dv_test(
+ name = "pwrmgr_random_sleep_all_reset_reqs_test",
+ srcs = ["pwrmgr_random_sleep_all_reset_reqs_test.c"],
+ deps = [
+ ":pwrmgr_reset_test_lib",
+ ],
+)
+
+matcha_dv_test(
+ name = "pwrmgr_deep_sleep_all_reset_reqs_test",
+ srcs = ["pwrmgr_deep_sleep_all_reset_reqs_test.c"],
+ deps = [
+ ":pwrmgr_reset_test_lib",
+ ],
+)
+
+matcha_dv_test(
+ name = "pwrmgr_normal_sleep_all_reset_reqs_test",
+ srcs = ["pwrmgr_normal_sleep_all_reset_reqs_test.c"],
+ deps = [
+ ":pwrmgr_reset_test_lib",
+ ],
+)
+
+matcha_dv_test(
+ name = "pwrmgr_random_sleep_power_glitch_reset_test",
+ srcs = ["pwrmgr_random_sleep_power_glitch_reset_test.c"],
+ deps = [
+ ":pwrmgr_reset_test_lib",
+ ],
+)
+
+matcha_dv_test(
+ name = "pwrmgr_b2b_sleep_reset_test",
+ srcs = ["pwrmgr_b2b_sleep_reset_test.c"],
+ deps = [
+ ":pwrmgr_reset_test_lib",
+ ],
+)
+
+matcha_dv_test(
+ name = "sleep_pin_retention_test",
+ srcs = ["sleep_pin_retention_test.c"],
+ deps = [
+ "//sw/device/lib/dif:pinmux",
+ "//sw/device/lib/dif:rv_plic_sec",
+ "//sw/device/lib/testing:isr_testutils",
+ "//sw/device/tests:test_dv_lib",
+ "@lowrisc_opentitan//sw/device/lib/dif:gpio",
+ "@lowrisc_opentitan//sw/device/lib/dif:pwrmgr",
+ "@lowrisc_opentitan//sw/device/lib/testing:pwrmgr_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:rand_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:rv_plic_testutils",
+ ],
+)
+
################################################################################
# Place the Opentitan-sourced DV test below. #
# Opentitan DV binary build flow does not support centOS7, so we pull the #
# source code and build them here using `matcha_dv_test` rule. #
################################################################################
-
matcha_dv_test(
name = "spi_tx_rx_test",
srcs = ["@lowrisc_opentitan//sw/device/tests/sim_dv:spi_tx_rx_test.c"],
@@ -168,3 +235,39 @@
"@lowrisc_opentitan//sw/device/lib/testing:rv_plic_testutils",
],
)
+
+matcha_dv_test(
+ name = "pwrmgr_sleep_power_glitch_test",
+ srcs = ["@lowrisc_opentitan//sw/device/tests/sim_dv:pwrmgr_sleep_power_glitch_test.c"],
+ deps = [
+ "//sw/device/lib/dif:rstmgr",
+ "//sw/device/tests:test_dv_lib_opentitan",
+ "@lowrisc_opentitan//sw/device/lib/dif:pwrmgr",
+ "@lowrisc_opentitan//sw/device/lib/testing:pwrmgr_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:rstmgr_testutils",
+ ],
+)
+
+matcha_dv_test(
+ name = "pwrmgr_deep_sleep_power_glitch_test",
+ srcs = ["@lowrisc_opentitan//sw/device/tests/sim_dv:pwrmgr_deep_sleep_power_glitch_test.c"],
+ deps = [
+ "//sw/device/lib/dif:rstmgr",
+ "//sw/device/tests:test_dv_lib_opentitan",
+ "@lowrisc_opentitan//sw/device/lib/dif:pwrmgr",
+ "@lowrisc_opentitan//sw/device/lib/testing:pwrmgr_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:rstmgr_testutils",
+ ],
+)
+
+matcha_dv_test(
+ name = "gpio_test",
+ srcs = ["@lowrisc_opentitan//sw/device/tests/sim_dv:gpio_test.c"],
+ deps = [
+ "//sw/device/lib/dif:rv_plic_sec",
+ "//sw/device/lib/testing:pinmux_testutils",
+ "//sw/device/tests:test_dv_lib_opentitan",
+ "@lowrisc_opentitan//sw/device/lib/dif:gpio",
+ "@lowrisc_opentitan//sw/device/lib/testing:rv_plic_testutils",
+ ],
+)
diff --git a/sw/device/tests/sim_dv/pwrmgr_b2b_sleep_reset_test.c b/sw/device/tests/sim_dv/pwrmgr_b2b_sleep_reset_test.c
new file mode 100644
index 0000000..35b3be0
--- /dev/null
+++ b/sw/device/tests/sim_dv/pwrmgr_b2b_sleep_reset_test.c
@@ -0,0 +1,182 @@
+// 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 "aon_timer_regs.h"
+#include "hw/top_matcha/sw/autogen/top_matcha.h"
+#include "sw/device/lib/base/abs_mmio.h"
+#include "sw/device/lib/base/mmio.h"
+#include "sw/device/lib/dif/dif_aon_timer.h"
+#include "sw/device/lib/dif/dif_flash_ctrl.h"
+#include "sw/device/lib/dif/dif_pinmux.h"
+#include "sw/device/lib/dif/dif_pwrmgr.h"
+#include "sw/device/lib/dif/dif_rstmgr.h"
+#include "sw/device/lib/dif/dif_sysrst_ctrl.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/pwrmgr_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"
+/*
+ PWRMGR BACK TO BACK DEEP SLEEP, RESET / WAKEUP TEST
+
+ This test introduces reset or wakeup event close to (before or after)
+ entering low power state.
+
+ 'kNumRound' is set to 10 by sv sequence (chip_sw_repeat_reset_wkup_vseq.sv)
+
+ For the reset event, the sequence assert power on resest by driving POR_N
+ PAD. For the wake up event, the seqeunce assert power button in by driving
+ IOR13 PAD.
+
+ */
+OTTF_DEFINE_TEST_CONFIG();
+
+static volatile const uint8_t kNumRound;
+
+static dif_flash_ctrl_state_t flash_ctrl;
+static dif_sysrst_ctrl_t sysrst_ctrl;
+static dif_pinmux_t pinmux;
+
+/**
+ * sysrst_ctrl config for test #1
+ * . set sysrst_ctrl.KEY_INTR_CTL.pwrb_in_H2L to 1
+ * . use IOR13 as pwrb_in
+ */
+static void prgm_push_button_wakeup() {
+ dif_sysrst_ctrl_input_change_config_t config = {
+ .input_changes = kDifSysrstCtrlInputPowerButtonH2L,
+ .debounce_time_threshold = 1, // 5us
+ };
+ CHECK_DIF_OK(
+ dif_sysrst_ctrl_input_change_detect_configure(&sysrst_ctrl, config));
+ CHECK_DIF_OK(dif_pinmux_input_select(
+ &pinmux, kTopMatchaPinmuxPeripheralInSysrstCtrlAonPwrbIn,
+ kTopMatchaPinmuxInselIor13));
+}
+
+bool test_main(void) {
+ // Issue a wakeup signal in ~1.5 ms through the AON timer.
+ // This timer is needed when reset or wakeup fail to
+ // bring state machine back to active state.
+ // This can happen when wake up event comes before low power
+ // entry event.
+ uint32_t wakeup_threshold = kDeviceType == kDeviceSimVerilator ? 3000 : 300;
+
+ // Initialize pwrmgr
+ dif_pwrmgr_t pwrmgr;
+ CHECK_DIF_OK(dif_pwrmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_PWRMGR_AON_BASE_ADDR), &pwrmgr));
+
+ // Initialize rstmgr since this will check some registers.
+ dif_rstmgr_t rstmgr;
+ CHECK_DIF_OK(dif_rstmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_RSTMGR_AON_BASE_ADDR), &rstmgr));
+
+ // 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 sysrst_ctrl
+ CHECK_DIF_OK(dif_sysrst_ctrl_init(
+ mmio_region_from_addr(TOP_MATCHA_SYSRST_CTRL_AON_BASE_ADDR),
+ &sysrst_ctrl));
+
+ // Initialize pinmux
+ CHECK_DIF_OK(dif_pinmux_init(
+ mmio_region_from_addr(TOP_MATCHA_PINMUX_AON_BASE_ADDR), &pinmux));
+
+ // First check the flash stored value
+ uint32_t event_idx = flash_ctrl_testutils_counter_get(0);
+ // Enable flash access
+ flash_ctrl_testutils_default_region_access(&flash_ctrl,
+ /*rd_en*/ true,
+ /*prog_en*/ true,
+ /*erase_en*/ true,
+ /*scramble_en*/ false,
+ /*ecc_en*/ false,
+ /*he_en*/ false);
+
+ // Increment flash counter to know where we are
+ flash_ctrl_testutils_counter_increment(&flash_ctrl, 0);
+
+ // Read wakeup reason before check
+ dif_pwrmgr_wakeup_reason_t wakeup_reason;
+ CHECK_DIF_OK(dif_pwrmgr_wakeup_reason_get(&pwrmgr, &wakeup_reason));
+ LOG_INFO("wakeup type:%d wakeup reason: 0x%02X", wakeup_reason.types,
+ wakeup_reason.request_sources);
+
+ if (wakeup_reason.types == 0) {
+ // POR reset
+ CHECK(wakeup_reason.request_sources == 0);
+ } else if (wakeup_reason.types == kDifPwrmgrWakeupTypeRequest) {
+ // sysrst_ctrl or aon_timer
+ CHECK(wakeup_reason.request_sources == (kDifPwrmgrWakeupRequestSourceOne |
+ kDifPwrmgrWakeupRequestSourceFive));
+ } else {
+ LOG_ERROR("unexpected wakeup_type: 0x%x", wakeup_reason.types);
+ }
+
+ // Read reset info before check
+ dif_rstmgr_reset_info_bitfield_t rst_info;
+ rst_info = rstmgr_testutils_reason_get();
+ rstmgr_testutils_reason_clear();
+ LOG_INFO("reset info = 0x%02X", rst_info);
+
+ if (rst_info != kDifRstmgrResetInfoPor &&
+ rst_info != kDifRstmgrResetInfoLowPowerExit) {
+ LOG_ERROR("unexpected reset info: 0x%x", rst_info);
+ }
+
+ dif_aon_timer_t aon_timer;
+ CHECK_DIF_OK(dif_aon_timer_init(
+ mmio_region_from_addr(TOP_MATCHA_AON_TIMER_AON_BASE_ADDR), &aon_timer));
+
+ // Status clean up
+ if (event_idx > 0) {
+ // aon timer clean up
+ CHECK_DIF_OK(dif_aon_timer_wakeup_stop(&aon_timer));
+ // mmio_region_write32(
+ // mmio_region_from_addr(TOP_MATCHA_AON_TIMER_AON_BASE_ADDR),
+ // AON_TIMER_WKUP_CAUSE_REG_OFFSET, 0);
+ CHECK_DIF_OK(dif_aon_timer_clear_wakeup_cause(&aon_timer));
+ // sysrst ctrl status clean up
+ CHECK_DIF_OK(dif_sysrst_ctrl_ulp_wakeup_clear_status(&sysrst_ctrl));
+ }
+
+ if (event_idx < kNumRound) {
+ LOG_INFO("Test round %d", event_idx);
+ } else {
+ LOG_INFO("Test finish");
+ return true;
+ }
+
+ // pin mux / sysrst ctrl set up for push button wakeup
+ prgm_push_button_wakeup();
+
+ // Prepare rstmgr for a reset.
+ rstmgr_testutils_pre_reset(&rstmgr);
+
+ // This is mark for sv sequence to prepare to asserting parallel event.
+ LOG_INFO("ready for power down");
+ busy_spin_micros(10);
+ // timer setup in case wake up comes before entering low power mode
+ aon_timer_testutils_wakeup_config(&aon_timer, wakeup_threshold);
+
+ // Deep sleep.
+ pwrmgr_testutils_enable_low_power(
+ &pwrmgr,
+ (kDifPwrmgrWakeupRequestSourceOne | kDifPwrmgrWakeupRequestSourceTwo |
+ kDifPwrmgrWakeupRequestSourceThree | kDifPwrmgrWakeupRequestSourceFour |
+ kDifPwrmgrWakeupRequestSourceFive | kDifPwrmgrWakeupRequestSourceSix),
+ 0);
+
+ // Enter low power mode.
+ wait_for_interrupt();
+
+ return false;
+}
diff --git a/sw/device/tests/sim_dv/pwrmgr_deep_sleep_all_reset_reqs_test.c b/sw/device/tests/sim_dv/pwrmgr_deep_sleep_all_reset_reqs_test.c
new file mode 100644
index 0000000..b5f3191
--- /dev/null
+++ b/sw/device/tests/sim_dv/pwrmgr_deep_sleep_all_reset_reqs_test.c
@@ -0,0 +1,520 @@
+// 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 <assert.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "hw/top_matcha/sw/autogen/top_matcha.h"
+#include "sw/device/lib/base/abs_mmio.h"
+#include "sw/device/lib/base/math.h"
+#include "sw/device/lib/base/mmio.h"
+#include "sw/device/lib/dif/dif_alert_handler.h"
+#include "sw/device/lib/dif/dif_aon_timer.h"
+#include "sw/device/lib/dif/dif_flash_ctrl.h"
+#include "sw/device/lib/dif/dif_pinmux.h"
+#include "sw/device/lib/dif/dif_pwrmgr.h"
+#include "sw/device/lib/dif/dif_rstmgr.h"
+#include "sw/device/lib/dif/dif_rv_plic.h"
+#include "sw/device/lib/dif/dif_rv_timer.h"
+#include "sw/device/lib/dif/dif_sysrst_ctrl.h"
+#include "sw/device/lib/runtime/irq.h"
+#include "sw/device/lib/runtime/log.h"
+#include "sw/device/lib/testing/alert_handler_testutils.h"
+#include "sw/device/lib/testing/aon_timer_testutils.h"
+#include "sw/device/lib/testing/flash_ctrl_testutils.h"
+#include "sw/device/lib/testing/pwrmgr_testutils.h"
+#include "sw/device/lib/testing/rstmgr_testutils.h"
+#include "sw/device/lib/testing/rv_plic_testutils.h"
+#include "sw/device/lib/testing/test_framework/FreeRTOSConfig.h"
+#include "sw/device/lib/testing/test_framework/check.h"
+#include "sw/device/lib/testing/test_framework/ottf_main.h"
+
+// In dvsim, one run
+// with --waves can take
+// 1.874h | 38.068ms
+// without --waves,
+// 38.072m | 39.484ms
+
+OTTF_DEFINE_TEST_CONFIG();
+static volatile const uint8_t RST_IDX[7] = {0, 1, 2, 3, 4, 5, 6};
+static const uint32_t kPlicTarget = kTopMatchaPlicTargetIbex0;
+
+/**
+ * Objects to access the peripherals used in this test via dif API.
+ */
+static dif_flash_ctrl_state_t flash_ctrl;
+static dif_rv_plic_t plic;
+static dif_alert_handler_t alert_handler;
+static dif_aon_timer_t aon_timer;
+static dif_pwrmgr_t pwrmgr;
+static dif_sysrst_ctrl_t sysrst_ctrl_aon;
+static dif_rstmgr_t rstmgr;
+
+/**
+ * Program the alert handler to escalate on alerts upto phase 2 (i.e. reset) but
+ * the phase 1 (i.e. wipe secrets) should occur and last during the time the
+ * wdog is programed to bark.
+ *
+ * Notice these settings are suitable for sim_dv. For other platforms we scale
+ * the resulting cycles by a factor of 10.
+ */
+enum {
+ kWdogBarkMicros = 3 * 100, // 300 us
+ kWdogBiteMicros = 4 * 100, // 400 us
+ kEscalationPhase0Micros = 1 * 100, // 100 us
+ // The cpu value is slightly larger to avoid flakey results.
+ kEscalationPhase0MicrosCpu = kEscalationPhase0Micros + 20, // 120 us
+ kEscalationPhase1Micros = 5 * 100, // 500 us
+ kEscalationPhase2Micros = 50, // 50 us
+};
+
+static_assert(
+ kWdogBarkMicros < kWdogBiteMicros &&
+ kWdogBarkMicros > kEscalationPhase0Micros &&
+ kWdogBarkMicros < (kEscalationPhase0Micros + kEscalationPhase1Micros) &&
+ kWdogBiteMicros < (kEscalationPhase0Micros + kEscalationPhase1Micros),
+ "The wdog bark and bite shall happens during the escalation phase 1");
+
+/**
+ * External ISR.
+ *
+ * Handles all peripheral interrupts on Ibex. PLIC asserts an external interrupt
+ * line to the CPU, which results in a call to this OTTF ISR. This ISR
+ * overrides the default OTTF implementation.
+ */
+void ottf_external_isr(void) {
+ top_matcha_plic_peripheral_t peripheral;
+ dif_rv_plic_irq_id_t irq_id;
+ uint32_t irq = 0;
+ uint32_t alert = 0;
+
+ CHECK_DIF_OK(dif_rv_plic_irq_claim(&plic, kPlicTarget, &irq_id));
+
+ peripheral = (top_matcha_plic_peripheral_t)
+ top_matcha_plic_interrupt_for_peripheral[irq_id];
+
+ if (peripheral == kTopMatchaPlicPeripheralAonTimerAon) {
+ irq =
+ (dif_aon_timer_irq_t)(irq_id -
+ (dif_rv_plic_irq_id_t)
+ kTopMatchaPlicIrqIdAonTimerAonWkupTimerExpired);
+
+ // Stops escalation process.
+ CHECK_DIF_OK(dif_alert_handler_escalation_clear(&alert_handler,
+ kDifAlertHandlerClassA));
+ CHECK_DIF_OK(dif_aon_timer_irq_acknowledge(&aon_timer, irq));
+
+ CHECK(irq != kTopMatchaPlicIrqIdAonTimerAonWdogTimerBark,
+ "AON Timer Wdog should not bark");
+
+ } else if (peripheral == kTopMatchaPlicPeripheralAlertHandler) {
+ irq = (dif_rv_plic_irq_id_t)(irq_id -
+ (dif_rv_plic_irq_id_t)
+ kTopMatchaPlicIrqIdAlertHandlerClassa);
+
+ CHECK_DIF_OK(dif_alert_handler_alert_acknowledge(&alert_handler, alert));
+
+ dif_alert_handler_class_state_t state;
+ CHECK_DIF_OK(dif_alert_handler_get_class_state(
+ &alert_handler, kDifAlertHandlerClassA, &state));
+
+ CHECK(state == kDifAlertHandlerClassStatePhase0, "Wrong phase %d", state);
+
+ CHECK_DIF_OK(dif_alert_handler_irq_acknowledge(&alert_handler, irq));
+ }
+
+ // Complete the IRQ by writing the IRQ source to the Ibex specific CC
+ // register.
+ CHECK_DIF_OK(dif_rv_plic_irq_complete(&plic, kPlicTarget, irq_id));
+}
+
+/**
+ * Initialize the peripherals used in this test.
+ */
+void init_peripherals(void) {
+ // Initialize pwrmgr.
+ CHECK_DIF_OK(dif_pwrmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_PWRMGR_AON_BASE_ADDR), &pwrmgr));
+
+ // Initialize sysrst_ctrl.
+ CHECK_DIF_OK(dif_sysrst_ctrl_init(
+ mmio_region_from_addr(TOP_MATCHA_SYSRST_CTRL_AON_BASE_ADDR),
+ &sysrst_ctrl_aon));
+
+ // Initialize rstmgr to check the reset reason.
+ CHECK_DIF_OK(dif_rstmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_RSTMGR_AON_BASE_ADDR), &rstmgr));
+
+ // Initialize aon timer to use the wdog.
+ CHECK_DIF_OK(dif_aon_timer_init(
+ mmio_region_from_addr(TOP_MATCHA_AON_TIMER_AON_BASE_ADDR), &aon_timer));
+
+ // 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 plic.
+ CHECK_DIF_OK(dif_rv_plic_init(
+ mmio_region_from_addr(TOP_MATCHA_RV_PLIC_BASE_ADDR), &plic));
+
+ rv_plic_testutils_irq_range_enable(
+ &plic, kPlicTarget, kTopMatchaPlicIrqIdAonTimerAonWkupTimerExpired,
+ kTopMatchaPlicIrqIdAonTimerAonWdogTimerBark);
+
+ // Initialize alert handler.
+ CHECK_DIF_OK(dif_alert_handler_init(
+ mmio_region_from_addr(TOP_MATCHA_ALERT_HANDLER_BASE_ADDR),
+ &alert_handler));
+}
+
+/**
+ * Program the alert handler to escalate on alerts upto phase 2 (i.e. reset) but
+ * the phase 1 (i.e. wipe secrets) should occur and last during the time the
+ * wdog is programed to bark.
+ */
+static void alert_handler_config(void) {
+ dif_alert_handler_alert_t alerts[] = {kTopMatchaAlertIdPwrmgrAonFatalFault};
+ dif_alert_handler_class_t alert_classes[] = {kDifAlertHandlerClassA};
+
+ dif_alert_handler_escalation_phase_t esc_phases[] = {
+ {.phase = kDifAlertHandlerClassStatePhase0,
+ .signal = 0,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase0Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()},
+ {.phase = kDifAlertHandlerClassStatePhase1,
+ .signal = 1,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase1Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()},
+ {.phase = kDifAlertHandlerClassStatePhase2,
+ .signal = 3,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase2Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()}};
+
+ dif_alert_handler_class_config_t class_config[] = {{
+ .auto_lock_accumulation_counter = kDifToggleDisabled,
+ .accumulator_threshold = 0,
+ .irq_deadline_cycles = alert_handler_testutils_get_cycles_from_us(10) *
+ alert_handler_testutils_cycle_rescaling_factor(),
+ .escalation_phases = esc_phases,
+ .escalation_phases_len = ARRAYSIZE(esc_phases),
+ .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase3,
+ }};
+
+ dif_alert_handler_class_t classes[] = {kDifAlertHandlerClassA};
+ dif_alert_handler_config_t config = {
+ .alerts = alerts,
+ .alert_classes = alert_classes,
+ .alerts_len = ARRAYSIZE(alerts),
+ .classes = classes,
+ .class_configs = class_config,
+ .classes_len = ARRAYSIZE(class_config),
+ .ping_timeout = 0,
+ };
+
+ alert_handler_testutils_configure_all(&alert_handler, config,
+ kDifToggleEnabled);
+ // Enables alert handler irq.
+ CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
+ &alert_handler, kDifAlertHandlerIrqClassa, kDifToggleEnabled));
+}
+
+/**
+ * Execute the aon timer interrupt test.
+ */
+static void trigger_escalate(dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr) {
+ uint64_t bark_cycles =
+ udiv64_slow(kWdogBarkMicros * kClockFreqAonHz, 1000000, NULL) *
+ alert_handler_testutils_cycle_rescaling_factor();
+ uint64_t bite_cycles =
+ udiv64_slow(kWdogBiteMicros * kClockFreqAonHz, 1000000, NULL) *
+ alert_handler_testutils_cycle_rescaling_factor();
+
+ CHECK(bite_cycles < UINT32_MAX,
+ "The value %u can't fit into the 32 bits timer counter.", bite_cycles);
+
+ LOG_INFO(
+ "Wdog will bark after %u/%u us/cycles and bite after %u/%u us/cycles",
+ (uint32_t)kWdogBarkMicros, (uint32_t)bark_cycles,
+ (uint32_t)kWdogBiteMicros, (uint32_t)bite_cycles);
+
+ // Setup the wdog bark and bite timeouts.
+ aon_timer_testutils_watchdog_config(aon_timer, bark_cycles, bite_cycles,
+ false);
+
+ // Trigger the alert handler to escalate.
+ dif_pwrmgr_alert_t alert = kDifPwrmgrAlertFatalFault;
+ CHECK_DIF_OK(dif_pwrmgr_alert_force(pwrmgr, alert));
+}
+
+/**
+ * Configure the sysrst.
+ */
+static void config_sysrst(const dif_pwrmgr_t *pwrmgr,
+ const dif_sysrst_ctrl_t *sysrst_ctrl_aon) {
+ LOG_INFO("sysrst enabled");
+
+ // Set sysrst as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceOne,
+ kDifToggleEnabled));
+ LOG_INFO("Reset Request SourceOne is set");
+
+ // Configure sysrst key combo
+ // reset pulse : 50 us
+ // detect durration : 50 us
+
+ dif_sysrst_ctrl_key_combo_config_t sysrst_ctrl_key_combo_config = {
+ .keys = kDifSysrstCtrlKeyAll,
+ .detection_time_threshold = 10,
+ .actions = kDifSysrstCtrlKeyComboActionAll,
+ .embedded_controller_reset_duration = 10};
+
+ CHECK_DIF_OK(dif_sysrst_ctrl_key_combo_detect_configure(
+ sysrst_ctrl_aon, kDifSysrstCtrlKeyCombo0, sysrst_ctrl_key_combo_config));
+ // Configure sysrst input change
+ // debounce durration : 100 us
+ dif_sysrst_ctrl_input_change_config_t sysrst_ctrl_input_change_config = {
+ .input_changes = kDifSysrstCtrlInputAll, .debounce_time_threshold = 20};
+
+ // Configure pinmux
+ dif_pinmux_t pinmux;
+ CHECK_DIF_OK(dif_pinmux_init(
+ mmio_region_from_addr(TOP_MATCHA_PINMUX_AON_BASE_ADDR), &pinmux));
+
+ CHECK_DIF_OK(dif_sysrst_ctrl_input_change_detect_configure(
+ sysrst_ctrl_aon, sysrst_ctrl_input_change_config));
+
+ CHECK_DIF_OK(dif_pinmux_input_select(
+ &pinmux, kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey0In,
+ kTopMatchaPinmuxInselIor13));
+}
+
+static void low_power_sysrst(const dif_pwrmgr_t *pwrmgr) {
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceOne,
+ 0);
+ LOG_INFO("Low power set for sysrst");
+
+ // Enter in low power mode.
+ wait_for_interrupt();
+}
+
+static void timer_on(uint32_t usec) {
+ busy_spin_micros(usec);
+ // If we arrive here the test must fail.
+ CHECK(false, "Timeout waiting for reset!");
+}
+
+/**
+ * Configure the wdog.
+ */
+static void config_wdog(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us,
+ uint64_t bite_time_us) {
+ uint32_t bark_cycles =
+ aon_timer_testutils_get_aon_cycles_from_us(bark_time_us);
+ uint32_t bite_cycles =
+ aon_timer_testutils_get_aon_cycles_from_us(bite_time_us);
+
+ LOG_INFO("Wdog will bark after %u us and bite after %u us",
+ (uint32_t)bark_time_us, (uint32_t)bite_time_us);
+ // Setup the wdog bark and bite timeouts.
+ aon_timer_testutils_watchdog_config(aon_timer, bark_cycles, bite_cycles,
+ false);
+ // Set wdog as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceTwo,
+ kDifToggleEnabled));
+}
+
+/**
+ * Execute the aon timer wdog bite reset test.
+ */
+static void wdog_bite_test(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us) {
+ uint64_t bite_time_us = bark_time_us * 2;
+ config_wdog(aon_timer, pwrmgr, bark_time_us, bite_time_us);
+
+ // The `intr_state` takes 3 aon clock cycles to rise plus 2 extra cycles as a
+ // precaution.
+ uint32_t wait_us =
+ bark_time_us +
+ udiv64_slow(5 * 1000000 + kClockFreqAonHz - 1, kClockFreqAonHz, NULL);
+
+ // Wait bark time and check that the bark interrupt requested.
+ busy_spin_micros(wait_us);
+ bool is_pending = false;
+ CHECK_DIF_OK(dif_aon_timer_irq_is_pending(
+ aon_timer, kDifAonTimerIrqWdogTimerBark, &is_pending));
+ CHECK(is_pending, "Wdog bark irq did not rise after %u microseconds",
+ wait_us);
+
+ // Wait for the remaining time to the wdog bite.
+ busy_spin_micros(wait_us);
+ // If we arrive here the test must fail.
+ CHECK(false, "Timeout waiting for Wdog bite reset!");
+}
+
+/**
+ * Execute the aon timer wdog bite reset during sleep test.
+ */
+static void sleep_wdog_bite_test(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr,
+ uint64_t bark_time_us) {
+ uint64_t bite_time_us = bark_time_us * 2;
+ config_wdog(aon_timer, pwrmgr, bark_time_us, bite_time_us);
+}
+
+static void low_power_wdog(const dif_pwrmgr_t *pwrmgr) {
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceTwo,
+ 0);
+ LOG_INFO("Low power set for watch dog");
+ wait_for_interrupt();
+ // If we arrive here the test must fail.
+ CHECK(false, "Fail to enter in low power mode!");
+}
+
+static void low_power_por(const dif_pwrmgr_t *pwrmgr) {
+ // Set por as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceTwo,
+ kDifToggleEnabled));
+
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ pwrmgr_testutils_enable_low_power(
+ pwrmgr,
+ (kDifPwrmgrWakeupRequestSourceOne | kDifPwrmgrWakeupRequestSourceTwo |
+ kDifPwrmgrWakeupRequestSourceThree | kDifPwrmgrWakeupRequestSourceFour |
+ kDifPwrmgrWakeupRequestSourceFive | kDifPwrmgrWakeupRequestSourceSix),
+ 0);
+ LOG_INFO("ready for pad por");
+
+ // Enter in low power mode.
+ wait_for_interrupt();
+ // If we arrive here the test must fail.
+ CHECK(false, "Fail to enter in low power mode!");
+}
+
+bool test_main(void) {
+ // Enable global and external IRQ at Ibex.
+ irq_global_ctrl(true);
+ irq_external_ctrl(true);
+
+ init_peripherals();
+
+ // Enable all the AON interrupts used in this test.
+ rv_plic_testutils_irq_range_enable(&plic, kPlicTarget,
+ kTopMatchaPlicIrqIdAlertHandlerClassa,
+ kTopMatchaPlicIrqIdAlertHandlerClassd);
+
+ alert_handler_config();
+
+ // First check the flash stored value.
+ uint32_t event_idx = flash_ctrl_testutils_counter_get(0);
+
+ // Enable flash access
+ flash_ctrl_testutils_default_region_access(&flash_ctrl,
+ /*rd_en*/ true,
+ /*prog_en*/ true,
+ /*erase_en*/ true,
+ /*scramble_en*/ false,
+ /*ecc_en*/ false,
+ /*he_en*/ false);
+
+ // Increment flash counter to know where we are.
+ flash_ctrl_testutils_counter_increment(&flash_ctrl, 0);
+
+ LOG_INFO("Test round %d", event_idx);
+ LOG_INFO("RST_IDX[%d] = %d", event_idx, RST_IDX[event_idx]);
+
+ // Check if there was a HW reset caused by expected cases.
+ dif_rstmgr_reset_info_bitfield_t rst_info;
+ rst_info = rstmgr_testutils_reason_get();
+ rstmgr_testutils_reason_clear();
+
+ CHECK(rst_info == kDifRstmgrResetInfoPor ||
+ rst_info == kDifRstmgrResetInfoSysRstCtrl ||
+ rst_info == kDifRstmgrResetInfoWatchdog ||
+ rst_info == kDifRstmgrResetInfoEscalation ||
+ rst_info == kDifRstmgrResetInfoLowPowerExit ||
+ rst_info == (kDifRstmgrResetInfoSysRstCtrl |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info ==
+ (kDifRstmgrResetInfoPor | kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoWatchdog |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoEscalation |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == kDifRstmgrResetInfoSw,
+ "Wrong reset reason %02X", rst_info);
+
+ switch (RST_IDX[event_idx]) {
+ case 0:
+ LOG_INFO("Booting and setting deep sleep followed by sysrst");
+ config_sysrst(&pwrmgr, &sysrst_ctrl_aon);
+ low_power_sysrst(&pwrmgr);
+ break;
+ case 1:
+ LOG_INFO("Booting and setting deep sleep followed by hw por");
+ low_power_por(&pwrmgr);
+ break;
+ case 2:
+ LOG_INFO(
+ "Booting and setting deep sleep mode followed for low_power entry "
+ "reset");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ // actually the same test as deep sleep + watchdog
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ low_power_wdog(&pwrmgr);
+ break;
+ case 3:
+ LOG_INFO(
+ "Booting and setting deep sleep followed by watchdog reset "
+ "combined "
+ "with sw_req");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+
+ // Assert reeset req
+ CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
+ LOG_INFO("Device reset from sw");
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ low_power_wdog(&pwrmgr);
+ break;
+ case 4:
+ LOG_INFO("Booting and setting deep sleep followed by watchdog reset");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ low_power_wdog(&pwrmgr);
+ break;
+ case 5:
+ LOG_INFO("Booting and running normal sleep followed by escalation reset");
+ LOG_INFO("Let SV wait timer reset");
+ trigger_escalate(&aon_timer, &pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ break;
+ case 6:
+ LOG_INFO("Last Booting");
+ return true;
+ break;
+ default:
+ LOG_INFO("Booting for undefined case");
+ }
+
+ return false;
+}
diff --git a/sw/device/tests/sim_dv/pwrmgr_normal_sleep_all_reset_reqs_test.c b/sw/device/tests/sim_dv/pwrmgr_normal_sleep_all_reset_reqs_test.c
new file mode 100644
index 0000000..151b9c5
--- /dev/null
+++ b/sw/device/tests/sim_dv/pwrmgr_normal_sleep_all_reset_reqs_test.c
@@ -0,0 +1,532 @@
+// 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 <assert.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "hw/top_matcha/sw/autogen/top_matcha.h"
+#include "sw/device/lib/base/abs_mmio.h"
+#include "sw/device/lib/base/math.h"
+#include "sw/device/lib/base/mmio.h"
+#include "sw/device/lib/dif/dif_alert_handler.h"
+#include "sw/device/lib/dif/dif_aon_timer.h"
+#include "sw/device/lib/dif/dif_flash_ctrl.h"
+#include "sw/device/lib/dif/dif_pinmux.h"
+#include "sw/device/lib/dif/dif_pwrmgr.h"
+#include "sw/device/lib/dif/dif_rstmgr.h"
+#include "sw/device/lib/dif/dif_rv_plic.h"
+#include "sw/device/lib/dif/dif_rv_timer.h"
+#include "sw/device/lib/dif/dif_sysrst_ctrl.h"
+#include "sw/device/lib/runtime/irq.h"
+#include "sw/device/lib/runtime/log.h"
+#include "sw/device/lib/testing/alert_handler_testutils.h"
+#include "sw/device/lib/testing/aon_timer_testutils.h"
+#include "sw/device/lib/testing/flash_ctrl_testutils.h"
+#include "sw/device/lib/testing/pwrmgr_testutils.h"
+#include "sw/device/lib/testing/rstmgr_testutils.h"
+#include "sw/device/lib/testing/rv_plic_testutils.h"
+#include "sw/device/lib/testing/test_framework/FreeRTOSConfig.h"
+#include "sw/device/lib/testing/test_framework/check.h"
+#include "sw/device/lib/testing/test_framework/ottf_main.h"
+
+OTTF_DEFINE_TEST_CONFIG();
+static volatile const uint8_t RST_IDX[7] = {0, 1, 2, 3, 4, 5, 6};
+static const uint32_t kPlicTarget = kTopMatchaPlicTargetIbex0;
+
+/**
+ * Objects to access the peripherals used in this test via dif API.
+ */
+static dif_flash_ctrl_state_t flash_ctrl;
+static dif_rv_plic_t plic;
+static dif_alert_handler_t alert_handler;
+static dif_aon_timer_t aon_timer;
+static dif_pwrmgr_t pwrmgr;
+static dif_sysrst_ctrl_t sysrst_ctrl_aon;
+static dif_rstmgr_t rstmgr;
+
+/**
+ * Program the alert handler to escalate on alerts upto phase 2 (i.e. reset) but
+ * the phase 1 (i.e. wipe secrets) should occur and last during the time the
+ * wdog is programed to bark.
+ *
+ * Notice these settings are suitable for sim_dv. For other platforms we scale
+ * the resulting cycles by a factor of 10.
+ */
+enum {
+ kWdogBarkMicros = 3 * 100, // 300 us
+ kWdogBiteMicros = 4 * 100, // 400 us
+ kEscalationPhase0Micros = 1 * 100, // 100 us
+ // The cpu value is slightly larger to avoid flakey results.
+ kEscalationPhase0MicrosCpu = kEscalationPhase0Micros + 20, // 120 us
+ kEscalationPhase1Micros = 5 * 100, // 500 us
+ kEscalationPhase2Micros = 50, // 50 us
+};
+
+static_assert(
+ kWdogBarkMicros < kWdogBiteMicros &&
+ kWdogBarkMicros > kEscalationPhase0Micros &&
+ kWdogBarkMicros < (kEscalationPhase0Micros + kEscalationPhase1Micros) &&
+ kWdogBiteMicros < (kEscalationPhase0Micros + kEscalationPhase1Micros),
+ "The wdog bark and bite shall happens during the escalation phase 1");
+
+/**
+ * External ISR.
+ *
+ * Handles all peripheral interrupts on Ibex. PLIC asserts an external interrupt
+ * line to the CPU, which results in a call to this OTTF ISR. This ISR
+ * overrides the default OTTF implementation.
+ */
+void ottf_external_isr(void) {
+ top_matcha_plic_peripheral_t peripheral;
+ dif_rv_plic_irq_id_t irq_id;
+ uint32_t irq = 0;
+ uint32_t alert = 0;
+
+ CHECK_DIF_OK(dif_rv_plic_irq_claim(&plic, kPlicTarget, &irq_id));
+
+ peripheral = (top_matcha_plic_peripheral_t)
+ top_matcha_plic_interrupt_for_peripheral[irq_id];
+
+ if (peripheral == kTopMatchaPlicPeripheralAonTimerAon) {
+ irq =
+ (dif_aon_timer_irq_t)(irq_id -
+ (dif_rv_plic_irq_id_t)
+ kTopMatchaPlicIrqIdAonTimerAonWkupTimerExpired);
+
+ // Stops escalation process.
+ CHECK_DIF_OK(dif_alert_handler_escalation_clear(&alert_handler,
+ kDifAlertHandlerClassA));
+ CHECK_DIF_OK(dif_aon_timer_irq_acknowledge(&aon_timer, irq));
+
+ CHECK(irq != kTopMatchaPlicIrqIdAonTimerAonWdogTimerBark,
+ "AON Timer Wdog should not bark");
+
+ } else if (peripheral == kTopMatchaPlicPeripheralAlertHandler) {
+ irq = (dif_aon_timer_irq_t)(irq_id -
+ (dif_rv_plic_irq_id_t)
+ kTopMatchaPlicIrqIdAlertHandlerClassa);
+
+ CHECK_DIF_OK(dif_alert_handler_alert_acknowledge(&alert_handler, alert));
+
+ dif_alert_handler_class_state_t state;
+ CHECK_DIF_OK(dif_alert_handler_get_class_state(
+ &alert_handler, kDifAlertHandlerClassA, &state));
+
+ CHECK(state == kDifAlertHandlerClassStatePhase0, "Wrong phase %d", state);
+
+ CHECK_DIF_OK(dif_alert_handler_irq_acknowledge(&alert_handler, irq));
+ }
+
+ // Complete the IRQ by writing the IRQ source to the Ibex specific CC
+ // register.
+ CHECK_DIF_OK(dif_rv_plic_irq_complete(&plic, kPlicTarget, irq_id));
+}
+
+/**
+ * Initialize the peripherals used in this test.
+ */
+void init_peripherals(void) {
+ // Initialize pwrmgr.
+ CHECK_DIF_OK(dif_pwrmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_PWRMGR_AON_BASE_ADDR), &pwrmgr));
+
+ // Initialize sysrst_ctrl.
+ CHECK_DIF_OK(dif_sysrst_ctrl_init(
+ mmio_region_from_addr(TOP_MATCHA_SYSRST_CTRL_AON_BASE_ADDR),
+ &sysrst_ctrl_aon));
+
+ // Initialize rstmgr to check the reset reason.
+ CHECK_DIF_OK(dif_rstmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_RSTMGR_AON_BASE_ADDR), &rstmgr));
+
+ // Initialize aon timer to use the wdog.
+ CHECK_DIF_OK(dif_aon_timer_init(
+ mmio_region_from_addr(TOP_MATCHA_AON_TIMER_AON_BASE_ADDR), &aon_timer));
+
+ // 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 plic.
+ CHECK_DIF_OK(dif_rv_plic_init(
+ mmio_region_from_addr(TOP_MATCHA_RV_PLIC_BASE_ADDR), &plic));
+
+ rv_plic_testutils_irq_range_enable(
+ &plic, kPlicTarget, kTopMatchaPlicIrqIdAonTimerAonWkupTimerExpired,
+ kTopMatchaPlicIrqIdAonTimerAonWdogTimerBark);
+
+ // Initialize alert handler.
+ CHECK_DIF_OK(dif_alert_handler_init(
+ mmio_region_from_addr(TOP_MATCHA_ALERT_HANDLER_BASE_ADDR),
+ &alert_handler));
+}
+
+/**
+ * Program the alert handler to escalate on alerts upto phase 2 (i.e. reset) but
+ * the phase 1 (i.e. wipe secrets) should occur and last during the time the
+ * wdog is programed to bark.
+ */
+static void alert_handler_config(void) {
+ dif_alert_handler_alert_t alerts[] = {kTopMatchaAlertIdPwrmgrAonFatalFault};
+ dif_alert_handler_class_t alert_classes[] = {kDifAlertHandlerClassA};
+
+ dif_alert_handler_escalation_phase_t esc_phases[] = {
+ {.phase = kDifAlertHandlerClassStatePhase0,
+ .signal = 0,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase0Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()},
+ {.phase = kDifAlertHandlerClassStatePhase1,
+ .signal = 1,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase1Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()},
+ {.phase = kDifAlertHandlerClassStatePhase2,
+ .signal = 3,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase2Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()}};
+
+ dif_alert_handler_class_config_t class_config[] = {{
+ .auto_lock_accumulation_counter = kDifToggleDisabled,
+ .accumulator_threshold = 0,
+ .irq_deadline_cycles = alert_handler_testutils_get_cycles_from_us(10) *
+ alert_handler_testutils_cycle_rescaling_factor(),
+ .escalation_phases = esc_phases,
+ .escalation_phases_len = ARRAYSIZE(esc_phases),
+ .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase3,
+ }};
+
+ dif_alert_handler_class_t classes[] = {kDifAlertHandlerClassA};
+ dif_alert_handler_config_t config = {
+ .alerts = alerts,
+ .alert_classes = alert_classes,
+ .alerts_len = ARRAYSIZE(alerts),
+ .classes = classes,
+ .class_configs = class_config,
+ .classes_len = ARRAYSIZE(class_config),
+ .ping_timeout = 0,
+ };
+
+ alert_handler_testutils_configure_all(&alert_handler, config,
+ kDifToggleEnabled);
+ // Enables alert handler irq.
+ CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
+ &alert_handler, kDifAlertHandlerIrqClassa, kDifToggleEnabled));
+}
+
+/**
+ * Execute the aon timer interrupt test.
+ */
+static void config_escalate(dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr) {
+ uint64_t bark_cycles =
+ udiv64_slow(kWdogBarkMicros * kClockFreqAonHz, 1000000, NULL) *
+ alert_handler_testutils_cycle_rescaling_factor();
+ uint64_t bite_cycles =
+ udiv64_slow(kWdogBiteMicros * kClockFreqAonHz, 1000000, NULL) *
+ alert_handler_testutils_cycle_rescaling_factor();
+
+ CHECK(bite_cycles < UINT32_MAX,
+ "The value %u can't fit into the 32 bits timer counter.", bite_cycles);
+
+ LOG_INFO(
+ "Wdog will bark after %u/%u us/cycles and bite after %u/%u us/cycles",
+ (uint32_t)kWdogBarkMicros, (uint32_t)bark_cycles,
+ (uint32_t)kWdogBiteMicros, (uint32_t)bite_cycles);
+
+ // Setup the wdog bark and bite timeouts.
+ aon_timer_testutils_watchdog_config(aon_timer, bark_cycles, bite_cycles,
+ false);
+
+ // Trigger the alert handler to escalate.
+ dif_pwrmgr_alert_t alert = kDifPwrmgrAlertFatalFault;
+ CHECK_DIF_OK(dif_pwrmgr_alert_force(pwrmgr, alert));
+}
+
+/**
+ * Configure the sysrst.
+ */
+static void config_sysrst(const dif_pwrmgr_t *pwrmgr,
+ const dif_sysrst_ctrl_t *sysrst_ctrl_aon) {
+ LOG_INFO("sysrst enabled");
+
+ // Set sysrst as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceOne,
+ kDifToggleEnabled));
+ LOG_INFO("Reset Request SourceOne is set");
+
+ // Configure sysrst key combo
+ // reset pulse : 50 us
+ // detect durration : 50 us
+
+ dif_sysrst_ctrl_key_combo_config_t sysrst_ctrl_key_combo_config = {
+ .keys = kDifSysrstCtrlKeyAll,
+ .detection_time_threshold = 10,
+ .actions = kDifSysrstCtrlKeyComboActionAll,
+ .embedded_controller_reset_duration = 10};
+
+ CHECK_DIF_OK(dif_sysrst_ctrl_key_combo_detect_configure(
+ sysrst_ctrl_aon, kDifSysrstCtrlKeyCombo0, sysrst_ctrl_key_combo_config));
+ // Configure sysrst input change
+ // debounce durration : 100 us
+ dif_sysrst_ctrl_input_change_config_t sysrst_ctrl_input_change_config = {
+ .input_changes = kDifSysrstCtrlInputAll, .debounce_time_threshold = 20};
+
+ // Configure pinmux
+ dif_pinmux_t pinmux;
+ CHECK_DIF_OK(dif_pinmux_init(
+ mmio_region_from_addr(TOP_MATCHA_PINMUX_AON_BASE_ADDR), &pinmux));
+
+ CHECK_DIF_OK(dif_sysrst_ctrl_input_change_detect_configure(
+ sysrst_ctrl_aon, sysrst_ctrl_input_change_config));
+
+ CHECK_DIF_OK(dif_pinmux_input_select(
+ &pinmux, kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey0In,
+ kTopMatchaPinmuxInselIor13));
+}
+
+static void normal_sleep_sysrst(const dif_pwrmgr_t *pwrmgr) {
+ // Place device into low power and immediately wake.
+ dif_pwrmgr_domain_config_t config;
+ config = kDifPwrmgrDomainOptionUsbClockInLowPower |
+ kDifPwrmgrDomainOptionCoreClockInLowPower |
+ kDifPwrmgrDomainOptionIoClockInLowPower |
+ kDifPwrmgrDomainOptionMainPowerInLowPower;
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceOne,
+ config);
+ LOG_INFO("Normal sleep set for sysrst");
+
+ // Enter in low power mode.
+ wait_for_interrupt();
+}
+
+static void timer_on(uint32_t usec) {
+ busy_spin_micros(usec);
+ // If we arrive here the test must fail.
+ CHECK(false, "Timeout waiting for reset!");
+}
+
+/**
+ * Configure the wdog.
+ */
+static void config_wdog(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us,
+ uint64_t bite_time_us) {
+ uint32_t bark_cycles =
+ aon_timer_testutils_get_aon_cycles_from_us(bark_time_us);
+ uint32_t bite_cycles =
+ aon_timer_testutils_get_aon_cycles_from_us(bite_time_us);
+
+ LOG_INFO("Wdog will bark after %u us and bite after %u us",
+ (uint32_t)bark_time_us, (uint32_t)bite_time_us);
+ // Setup the wdog bark and bite timeouts.
+ aon_timer_testutils_watchdog_config(aon_timer, bark_cycles, bite_cycles,
+ false);
+ // Set wdog as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceTwo,
+ kDifToggleEnabled));
+}
+
+/**
+ * Execute the aon timer wdog bite reset test.
+ */
+static void wdog_bite_test(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us) {
+ uint64_t bite_time_us = bark_time_us * 2;
+ config_wdog(aon_timer, pwrmgr, bark_time_us, bite_time_us);
+
+ // The `intr_state` takes 3 aon clock cycles to rise plus 2 extra cycles as a
+ // precaution.
+ uint32_t wait_us =
+ bark_time_us +
+ udiv64_slow(5 * 1000000 + kClockFreqAonHz - 1, kClockFreqAonHz, NULL);
+
+ // Wait bark time and check that the bark interrupt requested.
+ busy_spin_micros(wait_us);
+ bool is_pending = false;
+ CHECK_DIF_OK(dif_aon_timer_irq_is_pending(
+ aon_timer, kDifAonTimerIrqWdogTimerBark, &is_pending));
+ CHECK(is_pending, "Wdog bark irq did not rise after %u microseconds",
+ wait_us);
+
+ // Wait for the remaining time to the wdog bite.
+ busy_spin_micros(wait_us);
+ // If we arrive here the test must fail.
+ CHECK(false, "Timeout waiting for Wdog bite reset!");
+}
+
+/**
+ * Execute the aon timer wdog bite reset during sleep test.
+ */
+static void sleep_wdog_bite_test(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr,
+ uint64_t bark_time_us) {
+ uint64_t bite_time_us = bark_time_us * 2;
+ config_wdog(aon_timer, pwrmgr, bark_time_us, bite_time_us);
+}
+
+static void normal_sleep_wdog(const dif_pwrmgr_t *pwrmgr) {
+ // Place device into low power and immediately wake.
+ dif_pwrmgr_domain_config_t config;
+ config = kDifPwrmgrDomainOptionUsbClockInLowPower |
+ kDifPwrmgrDomainOptionCoreClockInLowPower |
+ kDifPwrmgrDomainOptionIoClockInLowPower |
+ kDifPwrmgrDomainOptionMainPowerInLowPower;
+
+ // Enter in low power mode.
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceTwo,
+ config);
+ LOG_INFO("Normal sleep set for watchdog");
+ wait_for_interrupt();
+}
+
+static void normal_sleep_por(const dif_pwrmgr_t *pwrmgr) {
+ // Set por as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceTwo,
+ kDifToggleEnabled));
+
+ // Place device into low power and immediately wake.
+ dif_pwrmgr_domain_config_t config;
+ config = kDifPwrmgrDomainOptionUsbClockInLowPower |
+ kDifPwrmgrDomainOptionCoreClockInLowPower |
+ kDifPwrmgrDomainOptionIoClockInLowPower |
+ kDifPwrmgrDomainOptionMainPowerInLowPower;
+
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ pwrmgr_testutils_enable_low_power(
+ pwrmgr,
+ (kDifPwrmgrWakeupRequestSourceOne | kDifPwrmgrWakeupRequestSourceTwo |
+ kDifPwrmgrWakeupRequestSourceThree | kDifPwrmgrWakeupRequestSourceFour |
+ kDifPwrmgrWakeupRequestSourceFive | kDifPwrmgrWakeupRequestSourceSix),
+ config);
+ LOG_INFO("ready for pad por");
+ // Enter in low power mode.
+ wait_for_interrupt();
+}
+
+bool test_main(void) {
+ // Enable global and external IRQ at Ibex.
+ irq_global_ctrl(true);
+ irq_external_ctrl(true);
+
+ init_peripherals();
+
+ // Enable all the AON interrupts used in this test.
+ rv_plic_testutils_irq_range_enable(&plic, kPlicTarget,
+ kTopMatchaPlicIrqIdAlertHandlerClassa,
+ kTopMatchaPlicIrqIdAlertHandlerClassd);
+
+ alert_handler_config();
+
+ // First check the flash stored value
+ uint32_t event_idx = flash_ctrl_testutils_counter_get(0);
+
+ // Enable flash access
+ flash_ctrl_testutils_default_region_access(&flash_ctrl,
+ /*rd_en*/ true,
+ /*prog_en*/ true,
+ /*erase_en*/ true,
+ /*scramble_en*/ false,
+ /*ecc_en*/ false,
+ /*he_en*/ false);
+
+ // Increment flash counter to know where we are
+ flash_ctrl_testutils_counter_increment(&flash_ctrl, 0);
+
+ LOG_INFO("Test round %d", event_idx);
+ LOG_INFO("RST_IDX[%d] = %d", event_idx, RST_IDX[event_idx]);
+
+ // Check if there was a HW reset caused by expected cases
+ dif_rstmgr_reset_info_bitfield_t rst_info;
+ rst_info = rstmgr_testutils_reason_get();
+ rstmgr_testutils_reason_clear();
+
+ CHECK(rst_info == kDifRstmgrResetInfoPor ||
+ rst_info == kDifRstmgrResetInfoSysRstCtrl ||
+ rst_info == kDifRstmgrResetInfoWatchdog ||
+ rst_info == kDifRstmgrResetInfoEscalation ||
+ rst_info == kDifRstmgrResetInfoLowPowerExit ||
+ rst_info == (kDifRstmgrResetInfoSysRstCtrl |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info ==
+ (kDifRstmgrResetInfoPor | kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoWatchdog |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoEscalation |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == kDifRstmgrResetInfoSw,
+ "Wrong reset reason %02X", rst_info);
+
+ switch (RST_IDX[event_idx]) {
+ case 0:
+ LOG_INFO("Booting and setting normal sleep followed by sysrst");
+ config_sysrst(&pwrmgr, &sysrst_ctrl_aon);
+ normal_sleep_sysrst(&pwrmgr);
+ timer_on(kWdogBiteMicros);
+ break;
+ case 1:
+ LOG_INFO("Booting and setting normal sleep followed by hw por");
+ normal_sleep_por(&pwrmgr);
+ timer_on(kWdogBiteMicros);
+ break;
+ case 2:
+ LOG_INFO(
+ "Booting and setting normal sleep mode followed for low_power "
+ "entry reset");
+ LOG_INFO("Let SV wait timer reset");
+ // actually the same test as normal sleep + watchdog
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ normal_sleep_wdog(&pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ break;
+ case 3:
+ LOG_INFO(
+ "Booting and setting normal sleep followed by watchdog reset "
+ "combined "
+ "with sw_req");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+
+ // Assert reeset req
+ CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
+ LOG_INFO("Device reset from sw");
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ normal_sleep_wdog(&pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ break;
+ case 4:
+ LOG_INFO("Booting and setting normal sleep followed by watchdog reset");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ normal_sleep_wdog(&pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ break;
+ case 5:
+ LOG_INFO("Booting and running normal sleep followed by escalation reset");
+ LOG_INFO("Let SV wait timer reset");
+ config_escalate(&aon_timer, &pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ break;
+ case 6:
+ LOG_INFO("Last Booting");
+ return true;
+ break;
+ default:
+ LOG_INFO("Booting for undefined case");
+ }
+
+ return false;
+}
diff --git a/sw/device/tests/sim_dv/pwrmgr_random_sleep_all_reset_reqs_test.c b/sw/device/tests/sim_dv/pwrmgr_random_sleep_all_reset_reqs_test.c
new file mode 100644
index 0000000..440a84b
--- /dev/null
+++ b/sw/device/tests/sim_dv/pwrmgr_random_sleep_all_reset_reqs_test.c
@@ -0,0 +1,617 @@
+// 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 <assert.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "hw/top_matcha/sw/autogen/top_matcha.h"
+#include "sw/device/lib/base/abs_mmio.h"
+#include "sw/device/lib/base/math.h"
+#include "sw/device/lib/base/mmio.h"
+#include "sw/device/lib/dif/dif_alert_handler.h"
+#include "sw/device/lib/dif/dif_aon_timer.h"
+#include "sw/device/lib/dif/dif_flash_ctrl.h"
+#include "sw/device/lib/dif/dif_pinmux.h"
+#include "sw/device/lib/dif/dif_pwrmgr.h"
+#include "sw/device/lib/dif/dif_rstmgr.h"
+#include "sw/device/lib/dif/dif_rv_plic.h"
+#include "sw/device/lib/dif/dif_rv_timer.h"
+#include "sw/device/lib/dif/dif_sysrst_ctrl.h"
+#include "sw/device/lib/runtime/irq.h"
+#include "sw/device/lib/runtime/log.h"
+#include "sw/device/lib/testing/alert_handler_testutils.h"
+#include "sw/device/lib/testing/aon_timer_testutils.h"
+#include "sw/device/lib/testing/flash_ctrl_testutils.h"
+#include "sw/device/lib/testing/pwrmgr_testutils.h"
+#include "sw/device/lib/testing/rstmgr_testutils.h"
+#include "sw/device/lib/testing/rv_plic_testutils.h"
+#include "sw/device/lib/testing/test_framework/FreeRTOSConfig.h"
+#include "sw/device/lib/testing/test_framework/check.h"
+#include "sw/device/lib/testing/test_framework/ottf_main.h"
+
+OTTF_DEFINE_TEST_CONFIG();
+static volatile const uint8_t RST_IDX[12] = {0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11};
+static const uint32_t kPlicTarget = kTopMatchaPlicTargetIbex0;
+
+/**
+ * Objects to access the peripherals used in this test via dif API.
+ */
+static dif_flash_ctrl_state_t flash_ctrl;
+static dif_rv_plic_t plic;
+static dif_alert_handler_t alert_handler;
+static dif_aon_timer_t aon_timer;
+static dif_pwrmgr_t pwrmgr;
+static dif_sysrst_ctrl_t sysrst_ctrl_aon;
+static dif_rstmgr_t rstmgr;
+
+/**
+ * Program the alert handler to escalate on alerts upto phase 2 (i.e. reset) but
+ * the phase 1 (i.e. wipe secrets) should occur and last during the time the
+ * wdog is programed to bark.
+ */
+enum {
+ kWdogBarkMicros = 3 * 100, // 300 us
+ kWdogBiteMicros = 4 * 100, // 400 us
+ kEscalationPhase0Micros = 1 * 100, // 100 us
+ // The cpu value is slightly larger as the busy_spin_micros
+ // routine cycle count comes out slightly smaller due to the
+ // fact that it does not divide by exactly 1M
+ // see sw/device/lib/runtime/hart.c
+ kEscalationPhase0MicrosCpu = kEscalationPhase0Micros + 20, // 120 us
+ kEscalationPhase1Micros = 5 * 100, // 500 us
+ kEscalationPhase2Micros = 50, // 50 us
+};
+
+static_assert(
+ kWdogBarkMicros < kWdogBiteMicros &&
+ kWdogBarkMicros > kEscalationPhase0Micros &&
+ kWdogBarkMicros < (kEscalationPhase0Micros + kEscalationPhase1Micros) &&
+ kWdogBiteMicros < (kEscalationPhase0Micros + kEscalationPhase1Micros),
+ "The wdog bark and bite shall happens during the escalation phase 1");
+
+/**
+ * External ISR.
+ *
+ * Handles all peripheral interrupts on Ibex. PLIC asserts an external interrupt
+ * line to the CPU, which results in a call to this OTTF ISR. This ISR
+ * overrides the default OTTF implementation.
+ */
+void ottf_external_isr(void) {
+ top_matcha_plic_peripheral_t peripheral;
+ dif_rv_plic_irq_id_t irq_id;
+ uint32_t irq = 0;
+ uint32_t alert = 0;
+
+ CHECK_DIF_OK(dif_rv_plic_irq_claim(&plic, kPlicTarget, &irq_id));
+
+ peripheral = (top_matcha_plic_peripheral_t)
+ top_matcha_plic_interrupt_for_peripheral[irq_id];
+
+ if (peripheral == kTopMatchaPlicPeripheralAonTimerAon) {
+ irq =
+ (dif_aon_timer_irq_t)(irq_id -
+ (dif_rv_plic_irq_id_t)
+ kTopMatchaPlicIrqIdAonTimerAonWkupTimerExpired);
+
+ // Stops escalation process.
+ CHECK_DIF_OK(dif_alert_handler_escalation_clear(&alert_handler,
+ kDifAlertHandlerClassA));
+ CHECK_DIF_OK(dif_aon_timer_irq_acknowledge(&aon_timer, irq));
+
+ CHECK(irq != kTopMatchaPlicIrqIdAonTimerAonWdogTimerBark,
+ "AON Timer Wdog should not bark");
+
+ } else if (peripheral == kTopMatchaPlicPeripheralAlertHandler) {
+ irq = (dif_rv_plic_irq_id_t)(irq_id -
+ (dif_rv_plic_irq_id_t)
+ kTopMatchaPlicIrqIdAlertHandlerClassa);
+
+ CHECK_DIF_OK(dif_alert_handler_alert_acknowledge(&alert_handler, alert));
+
+ dif_alert_handler_class_state_t state;
+ CHECK_DIF_OK(dif_alert_handler_get_class_state(
+ &alert_handler, kDifAlertHandlerClassA, &state));
+
+ CHECK(state == kDifAlertHandlerClassStatePhase0, "Wrong phase %d", state);
+
+ CHECK_DIF_OK(dif_alert_handler_irq_acknowledge(&alert_handler, irq));
+ }
+
+ // Complete the IRQ by writing the IRQ source to the Ibex specific CC
+ // register.
+ CHECK_DIF_OK(dif_rv_plic_irq_complete(&plic, kPlicTarget, irq_id));
+}
+
+/**
+ * Initialize the peripherals used in this test.
+ */
+void init_peripherals(void) {
+ // Initialize pwrmgr.
+ CHECK_DIF_OK(dif_pwrmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_PWRMGR_AON_BASE_ADDR), &pwrmgr));
+
+ // Initialize sysrst_ctrl.
+ CHECK_DIF_OK(dif_sysrst_ctrl_init(
+ mmio_region_from_addr(TOP_MATCHA_SYSRST_CTRL_AON_BASE_ADDR),
+ &sysrst_ctrl_aon));
+
+ // Initialize rstmgr to check the reset reason.
+ CHECK_DIF_OK(dif_rstmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_RSTMGR_AON_BASE_ADDR), &rstmgr));
+
+ // Initialize aon timer to use the wdog.
+ CHECK_DIF_OK(dif_aon_timer_init(
+ mmio_region_from_addr(TOP_MATCHA_AON_TIMER_AON_BASE_ADDR), &aon_timer));
+
+ // 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 plic.
+ CHECK_DIF_OK(dif_rv_plic_init(
+ mmio_region_from_addr(TOP_MATCHA_RV_PLIC_BASE_ADDR), &plic));
+
+ rv_plic_testutils_irq_range_enable(
+ &plic, kPlicTarget, kTopMatchaPlicIrqIdAonTimerAonWkupTimerExpired,
+ kTopMatchaPlicIrqIdAonTimerAonWdogTimerBark);
+
+ // Initialize alert handler.
+ CHECK_DIF_OK(dif_alert_handler_init(
+ mmio_region_from_addr(TOP_MATCHA_ALERT_HANDLER_BASE_ADDR),
+ &alert_handler));
+}
+
+/**
+ * Program the alert handler to escalate on alerts upto phase 2 (i.e. reset) but
+ * the phase 1 (i.e. wipe secrets) should occur and last during the time the
+ * wdog is programed to bark.
+ */
+static void alert_handler_config(void) {
+ dif_alert_handler_alert_t alerts[] = {kTopMatchaAlertIdPwrmgrAonFatalFault};
+ dif_alert_handler_class_t alert_classes[] = {kDifAlertHandlerClassA};
+
+ dif_alert_handler_escalation_phase_t esc_phases[] = {
+ {.phase = kDifAlertHandlerClassStatePhase0,
+ .signal = 0,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase0Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()},
+ {.phase = kDifAlertHandlerClassStatePhase1,
+ .signal = 1,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase1Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()},
+ {.phase = kDifAlertHandlerClassStatePhase2,
+ .signal = 3,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase2Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()}};
+
+ dif_alert_handler_class_config_t class_config[] = {{
+ .auto_lock_accumulation_counter = kDifToggleDisabled,
+ .accumulator_threshold = 0,
+ .irq_deadline_cycles = alert_handler_testutils_get_cycles_from_us(10) *
+ alert_handler_testutils_cycle_rescaling_factor(),
+ .escalation_phases = esc_phases,
+ .escalation_phases_len = ARRAYSIZE(esc_phases),
+ .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase3,
+ }};
+
+ dif_alert_handler_class_t classes[] = {kDifAlertHandlerClassA};
+ dif_alert_handler_config_t config = {
+ .alerts = alerts,
+ .alert_classes = alert_classes,
+ .alerts_len = ARRAYSIZE(alerts),
+ .classes = classes,
+ .class_configs = class_config,
+ .classes_len = ARRAYSIZE(class_config),
+ .ping_timeout = 0,
+ };
+
+ alert_handler_testutils_configure_all(&alert_handler, config,
+ kDifToggleEnabled);
+ // Enables alert handler irq.
+ CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
+ &alert_handler, kDifAlertHandlerIrqClassa, kDifToggleEnabled));
+}
+
+/**
+ * Execute the aon timer interrupt test.
+ */
+static void config_escalate(dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr) {
+ uint64_t bark_cycles =
+ udiv64_slow(kWdogBarkMicros * kClockFreqAonHz, 1000000, NULL) *
+ alert_handler_testutils_cycle_rescaling_factor();
+ uint64_t bite_cycles =
+ udiv64_slow(kWdogBiteMicros * kClockFreqAonHz, 1000000, NULL) *
+ alert_handler_testutils_cycle_rescaling_factor();
+
+ CHECK(bite_cycles < UINT32_MAX,
+ "The value %u can't fit into the 32 bits timer counter.", bite_cycles);
+
+ LOG_INFO(
+ "Wdog will bark after %u/%u us/cycles and bite after %u/%u us/cycles",
+ (uint32_t)kWdogBarkMicros, (uint32_t)bark_cycles,
+ (uint32_t)kWdogBiteMicros, (uint32_t)bite_cycles);
+
+ // Setup the wdog bark and bite timeouts.
+ aon_timer_testutils_watchdog_config(aon_timer, bark_cycles, bite_cycles,
+ false);
+
+ // Trigger the alert handler to escalate.
+ dif_pwrmgr_alert_t alert = kDifPwrmgrAlertFatalFault;
+ CHECK_DIF_OK(dif_pwrmgr_alert_force(pwrmgr, alert));
+}
+
+/**
+ * Configure the sysrst.
+ */
+static void config_sysrst(const dif_pwrmgr_t *pwrmgr,
+ const dif_sysrst_ctrl_t *sysrst_ctrl_aon) {
+ LOG_INFO("sysrst enabled");
+
+ // Set sysrst as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceOne,
+ kDifToggleEnabled));
+ LOG_INFO("Reset Request SourceOne is set");
+
+ // Configure sysrst key combo
+ // reset pulse : 50 us
+ // detect durration : 50 us
+
+ dif_sysrst_ctrl_key_combo_config_t sysrst_ctrl_key_combo_config = {
+ .keys = kDifSysrstCtrlKeyAll,
+ .detection_time_threshold = 10,
+ .actions = kDifSysrstCtrlKeyComboActionAll,
+ .embedded_controller_reset_duration = 10};
+
+ CHECK_DIF_OK(dif_sysrst_ctrl_key_combo_detect_configure(
+ sysrst_ctrl_aon, kDifSysrstCtrlKeyCombo0, sysrst_ctrl_key_combo_config));
+ // Configure sysrst input change
+ // debounce durration : 100 us
+ dif_sysrst_ctrl_input_change_config_t sysrst_ctrl_input_change_config = {
+ .input_changes = kDifSysrstCtrlInputAll, .debounce_time_threshold = 20};
+
+ // Configure pinmux
+ dif_pinmux_t pinmux;
+ CHECK_DIF_OK(dif_pinmux_init(
+ mmio_region_from_addr(TOP_MATCHA_PINMUX_AON_BASE_ADDR), &pinmux));
+
+ CHECK_DIF_OK(dif_sysrst_ctrl_input_change_detect_configure(
+ sysrst_ctrl_aon, sysrst_ctrl_input_change_config));
+
+ CHECK_DIF_OK(dif_pinmux_input_select(
+ &pinmux, kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey0In,
+ kTopMatchaPinmuxInselIor13));
+}
+
+static void low_power_sysrst(const dif_pwrmgr_t *pwrmgr) {
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceOne,
+ 0);
+ // Enter in low power mode.
+ wait_for_interrupt();
+}
+
+static void normal_sleep_sysrst(const dif_pwrmgr_t *pwrmgr) {
+ // Place device into low power and immediately wake.
+ dif_pwrmgr_domain_config_t config;
+ config = kDifPwrmgrDomainOptionUsbClockInLowPower |
+ kDifPwrmgrDomainOptionCoreClockInLowPower |
+ kDifPwrmgrDomainOptionIoClockInLowPower |
+ kDifPwrmgrDomainOptionMainPowerInLowPower;
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceOne,
+ config);
+ // Enter in low power mode.
+ wait_for_interrupt();
+}
+
+static void timer_on(uint32_t usec) {
+ busy_spin_micros(usec);
+ // If we arrive here the test must fail.
+ CHECK(false, "Timeout waiting for reset!");
+}
+
+/**
+ * Configure the wdog.
+ */
+static void config_wdog(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us,
+ uint64_t bite_time_us) {
+ uint32_t bark_cycles =
+ aon_timer_testutils_get_aon_cycles_from_us(bark_time_us);
+ uint32_t bite_cycles =
+ aon_timer_testutils_get_aon_cycles_from_us(bite_time_us);
+
+ LOG_INFO("Wdog will bark after %u us and bite after %u us",
+ (uint32_t)bark_time_us, (uint32_t)bite_time_us);
+ // Setup the wdog bark and bite timeouts.
+
+ aon_timer_testutils_watchdog_config(aon_timer, bark_cycles, bite_cycles,
+ false);
+ // Set wdog as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceTwo,
+ kDifToggleEnabled));
+}
+
+/**
+ * Execute the aon timer wdog bite reset test.
+ */
+static void wdog_bite_test(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us) {
+ uint64_t bite_time_us = bark_time_us * 2;
+ config_wdog(aon_timer, pwrmgr, bark_time_us, bite_time_us);
+
+ // The `intr_state` takes 3 aon clock cycles to rise plus 2 extra cycles as a
+ // precaution.
+ uint32_t wait_us =
+ bark_time_us +
+ udiv64_slow(5 * 1000000 + kClockFreqAonHz - 1, kClockFreqAonHz, NULL);
+
+ // Wait bark time and check that the bark interrupt requested.
+ busy_spin_micros(wait_us);
+ bool is_pending = false;
+ CHECK_DIF_OK(dif_aon_timer_irq_is_pending(
+ aon_timer, kDifAonTimerIrqWdogTimerBark, &is_pending));
+ CHECK(is_pending, "Wdog bark irq did not rise after %u microseconds",
+ wait_us);
+
+ // Wait for the remaining time to the wdog bite.
+ busy_spin_micros(wait_us);
+ // If we arrive here the test must fail.
+ CHECK(false, "Timeout waiting for Wdog bite reset!");
+}
+
+/**
+ * Execute the aon timer wdog bite reset during sleep test.
+ */
+static void sleep_wdog_bite_test(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr,
+ uint64_t bark_time_us) {
+ uint64_t bite_time_us = bark_time_us * 2;
+ config_wdog(aon_timer, pwrmgr, bark_time_us, bite_time_us);
+}
+
+static void low_power_wdog(const dif_pwrmgr_t *pwrmgr) {
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ // Enter in low power mode.
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceTwo,
+ 0);
+ LOG_INFO("Low power set for watch dog");
+ wait_for_interrupt();
+ // If we arrive here the test must fail.
+ CHECK(false, "Fail to enter in low power mode!");
+}
+
+static void normal_sleep_wdog(const dif_pwrmgr_t *pwrmgr) {
+ // Place device into low power and immediately wake.
+ dif_pwrmgr_domain_config_t config;
+ config = kDifPwrmgrDomainOptionUsbClockInLowPower |
+ kDifPwrmgrDomainOptionCoreClockInLowPower |
+ kDifPwrmgrDomainOptionIoClockInLowPower |
+ kDifPwrmgrDomainOptionMainPowerInLowPower;
+
+ // Enter in low power mode.
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceTwo,
+ config);
+ LOG_INFO("Normal sleep set for watchdog");
+ wait_for_interrupt();
+}
+
+static void low_power_por(const dif_pwrmgr_t *pwrmgr) {
+ // Set por as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceTwo,
+ kDifToggleEnabled));
+
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ pwrmgr_testutils_enable_low_power(
+ pwrmgr,
+ (kDifPwrmgrWakeupRequestSourceOne | kDifPwrmgrWakeupRequestSourceTwo |
+ kDifPwrmgrWakeupRequestSourceThree | kDifPwrmgrWakeupRequestSourceFour |
+ kDifPwrmgrWakeupRequestSourceFive | kDifPwrmgrWakeupRequestSourceSix),
+ 0);
+ // Enter in low power mode.
+ wait_for_interrupt();
+ // If we arrive here the test must fail.
+ CHECK(false, "Fail to enter in low power mode!");
+}
+
+static void normal_sleep_por(const dif_pwrmgr_t *pwrmgr) {
+ // Set por as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceTwo,
+ kDifToggleEnabled));
+
+ // Place device into low power and immediately wake.
+ dif_pwrmgr_domain_config_t config;
+ config = kDifPwrmgrDomainOptionUsbClockInLowPower |
+ kDifPwrmgrDomainOptionCoreClockInLowPower |
+ kDifPwrmgrDomainOptionIoClockInLowPower |
+ kDifPwrmgrDomainOptionMainPowerInLowPower;
+
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ pwrmgr_testutils_enable_low_power(
+ pwrmgr,
+ (kDifPwrmgrWakeupRequestSourceOne | kDifPwrmgrWakeupRequestSourceTwo |
+ kDifPwrmgrWakeupRequestSourceThree | kDifPwrmgrWakeupRequestSourceFour |
+ kDifPwrmgrWakeupRequestSourceFive | kDifPwrmgrWakeupRequestSourceSix),
+ config);
+ // Enter in low power mode.
+ wait_for_interrupt();
+}
+
+bool test_main(void) {
+ // Enable global and external IRQ at Ibex.
+ irq_global_ctrl(true);
+ irq_external_ctrl(true);
+
+ init_peripherals();
+
+ // Enable all the AON interrupts used in this test.
+ rv_plic_testutils_irq_range_enable(&plic, kPlicTarget,
+ kTopMatchaPlicIrqIdAlertHandlerClassa,
+ kTopMatchaPlicIrqIdAlertHandlerClassd);
+
+ alert_handler_config();
+
+ // First check the flash stored value
+ uint32_t event_idx = flash_ctrl_testutils_counter_get(0);
+
+ // Enable flash access
+ flash_ctrl_testutils_default_region_access(&flash_ctrl,
+ /*rd_en*/ true,
+ /*prog_en*/ true,
+ /*erase_en*/ true,
+ /*scramble_en*/ false,
+ /*ecc_en*/ false,
+ /*he_en*/ false);
+
+ // Increment flash counter to know where we are
+ flash_ctrl_testutils_counter_increment(&flash_ctrl, 0);
+
+ LOG_INFO("Test round %d", event_idx);
+ LOG_INFO("RST_IDX[%d] = %d", event_idx, RST_IDX[event_idx]);
+
+ // Check if there was a HW reset caused by expected cases
+ dif_rstmgr_reset_info_bitfield_t rst_info;
+ rst_info = rstmgr_testutils_reason_get();
+ rstmgr_testutils_reason_clear();
+
+ CHECK(rst_info == kDifRstmgrResetInfoPor ||
+ rst_info == kDifRstmgrResetInfoSysRstCtrl ||
+ rst_info == kDifRstmgrResetInfoWatchdog ||
+ rst_info == kDifRstmgrResetInfoEscalation ||
+ rst_info == kDifRstmgrResetInfoLowPowerExit ||
+ rst_info == (kDifRstmgrResetInfoSysRstCtrl |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info ==
+ (kDifRstmgrResetInfoPor | kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoWatchdog |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoEscalation |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == kDifRstmgrResetInfoSw,
+ "Wrong reset reason %02X", rst_info);
+
+ LOG_INFO("New reset event");
+
+ switch (RST_IDX[event_idx] / 2) {
+ case 0:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO("Booting and setting normal sleep followed by sysrst");
+ config_sysrst(&pwrmgr, &sysrst_ctrl_aon);
+ normal_sleep_sysrst(&pwrmgr);
+ timer_on(kWdogBiteMicros);
+ } else {
+ LOG_INFO("Booting and setting deep sleep followed by sysrst");
+ config_sysrst(&pwrmgr, &sysrst_ctrl_aon);
+ low_power_sysrst(&pwrmgr);
+ }
+ break;
+ case 1:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO("Booting and setting normal sleep followed by hw por");
+ normal_sleep_por(&pwrmgr);
+ timer_on(kWdogBiteMicros);
+ } else {
+ LOG_INFO("Booting and setting deep sleep followed by hw por");
+ low_power_por(&pwrmgr);
+ }
+ break;
+ case 2:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO(
+ "Booting and setting normal sleep mode followed for low_power "
+ "entry reset");
+ LOG_INFO("Let SV wait timer reset");
+ // actually the same test as normal sleep + watchdog
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ normal_sleep_wdog(&pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ } else {
+ LOG_INFO(
+ "Booting and setting deep sleep mode followed for low_power entry "
+ "reset");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ // actually the same test as deep sleep + watchdog
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ low_power_wdog(&pwrmgr);
+ }
+ break;
+
+ case 3:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO(
+ "Booting and setting normal sleep followed by watchdog reset "
+ "combined "
+ "with sw_req");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+ CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
+ LOG_INFO("Device reset from sw");
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ normal_sleep_wdog(&pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ } else {
+ LOG_INFO(
+ "Booting and setting deep sleep followed by watchdog reset "
+ "combined "
+ "with sw_req");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+ CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
+ LOG_INFO("Device reset from sw");
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ low_power_wdog(&pwrmgr);
+ }
+ break;
+ case 4:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO("Booting and setting normal sleep followed by watchdog reset");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ normal_sleep_wdog(&pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ } else {
+ LOG_INFO("Booting and setting deep sleep followed by watchdog reset");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ low_power_wdog(&pwrmgr);
+ }
+ break;
+ case 5:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO("Last Booting");
+
+ return true;
+ } else {
+ LOG_INFO(
+ "Booting and running normal sleep followed by escalation reset");
+ config_escalate(&aon_timer, &pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ }
+ break;
+ default:
+ LOG_INFO("Booting for undefined case");
+ }
+ return false;
+}
diff --git a/sw/device/tests/sim_dv/pwrmgr_random_sleep_power_glitch_reset_test.c b/sw/device/tests/sim_dv/pwrmgr_random_sleep_power_glitch_reset_test.c
new file mode 100644
index 0000000..3f16463
--- /dev/null
+++ b/sw/device/tests/sim_dv/pwrmgr_random_sleep_power_glitch_reset_test.c
@@ -0,0 +1,577 @@
+// 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 <assert.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "hw/top_matcha/sw/autogen/top_matcha.h"
+#include "sw/device/lib/base/abs_mmio.h"
+#include "sw/device/lib/base/math.h"
+#include "sw/device/lib/base/mmio.h"
+#include "sw/device/lib/dif/dif_alert_handler.h"
+#include "sw/device/lib/dif/dif_aon_timer.h"
+#include "sw/device/lib/dif/dif_flash_ctrl.h"
+#include "sw/device/lib/dif/dif_pinmux.h"
+#include "sw/device/lib/dif/dif_pwrmgr.h"
+#include "sw/device/lib/dif/dif_rstmgr.h"
+#include "sw/device/lib/dif/dif_rv_plic.h"
+#include "sw/device/lib/dif/dif_rv_timer.h"
+#include "sw/device/lib/dif/dif_sysrst_ctrl.h"
+#include "sw/device/lib/runtime/irq.h"
+#include "sw/device/lib/runtime/log.h"
+#include "sw/device/lib/testing/alert_handler_testutils.h"
+#include "sw/device/lib/testing/aon_timer_testutils.h"
+#include "sw/device/lib/testing/flash_ctrl_testutils.h"
+#include "sw/device/lib/testing/pwrmgr_testutils.h"
+#include "sw/device/lib/testing/rstmgr_testutils.h"
+#include "sw/device/lib/testing/rv_plic_testutils.h"
+#include "sw/device/lib/testing/test_framework/FreeRTOSConfig.h"
+#include "sw/device/lib/testing/test_framework/check.h"
+#include "sw/device/lib/testing/test_framework/ottf_main.h"
+
+OTTF_DEFINE_TEST_CONFIG();
+static volatile const uint8_t RST_IDX[12] = {0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11};
+static const uint32_t kPlicTarget = kTopMatchaPlicTargetIbex0;
+
+/**
+ * Objects to access the peripherals used in this test via dif API.
+ */
+static dif_flash_ctrl_state_t flash_ctrl;
+static dif_rv_plic_t plic;
+static dif_alert_handler_t alert_handler;
+static dif_aon_timer_t aon_timer;
+static dif_pwrmgr_t pwrmgr;
+static dif_rstmgr_t rstmgr;
+
+/**
+ * Program the alert handler to escalate on alerts upto phase 2 (i.e. reset) but
+ * the phase 1 (i.e. wipe secrets) should occur and last during the time the
+ * wdog is programed to bark.
+ */
+enum {
+ kWdogBarkMicros = 3 * 100, // 300 us
+ kWdogBiteMicros = 4 * 100, // 400 us
+ kEscalationPhase0Micros = 1 * 100, // 100 us
+ // The cpu value is slightly larger as the busy_spin_micros
+ // routine cycle count comes out slightly smaller due to the
+ // fact that it does not divide by exactly 1M
+ // see sw/device/lib/runtime/hart.c
+ kEscalationPhase0MicrosCpu = kEscalationPhase0Micros + 20, // 120 us
+ kEscalationPhase1Micros = 5 * 100, // 500 us
+ kEscalationPhase2Micros = 50, // 50 us
+};
+
+static_assert(
+ kWdogBarkMicros < kWdogBiteMicros &&
+ kWdogBarkMicros > kEscalationPhase0Micros &&
+ kWdogBarkMicros < (kEscalationPhase0Micros + kEscalationPhase1Micros) &&
+ kWdogBiteMicros < (kEscalationPhase0Micros + kEscalationPhase1Micros),
+ "The wdog bark and bite shall happens during the escalation phase 1");
+
+/**
+ * External ISR.
+ *
+ * Handles all peripheral interrupts on Ibex. PLIC asserts an external interrupt
+ * line to the CPU, which results in a call to this OTTF ISR. This ISR
+ * overrides the default OTTF implementation.
+ */
+void ottf_external_isr(void) {
+ top_matcha_plic_peripheral_t peripheral;
+ dif_rv_plic_irq_id_t irq_id;
+ uint32_t irq = 0;
+ uint32_t alert = 0;
+
+ CHECK_DIF_OK(dif_rv_plic_irq_claim(&plic, kPlicTarget, &irq_id));
+
+ peripheral = (top_matcha_plic_peripheral_t)
+ top_matcha_plic_interrupt_for_peripheral[irq_id];
+
+ if (peripheral == kTopMatchaPlicPeripheralAonTimerAon) {
+ irq =
+ (dif_aon_timer_irq_t)(irq_id -
+ (dif_rv_plic_irq_id_t)
+ kTopMatchaPlicIrqIdAonTimerAonWkupTimerExpired);
+
+ // Stops escalation process.
+ CHECK_DIF_OK(dif_alert_handler_escalation_clear(&alert_handler,
+ kDifAlertHandlerClassA));
+ CHECK_DIF_OK(dif_aon_timer_irq_acknowledge(&aon_timer, irq));
+
+ CHECK(irq != kTopMatchaPlicIrqIdAonTimerAonWdogTimerBark,
+ "AON Timer Wdog should not bark");
+
+ } else if (peripheral == kTopMatchaPlicPeripheralAlertHandler) {
+ irq = (dif_rv_plic_irq_id_t)(irq_id -
+ (dif_rv_plic_irq_id_t)
+ kTopMatchaPlicIrqIdAlertHandlerClassa);
+
+ CHECK_DIF_OK(dif_alert_handler_alert_acknowledge(&alert_handler, alert));
+
+ dif_alert_handler_class_state_t state;
+ CHECK_DIF_OK(dif_alert_handler_get_class_state(
+ &alert_handler, kDifAlertHandlerClassA, &state));
+
+ CHECK(state == kDifAlertHandlerClassStatePhase0, "Wrong phase %d", state);
+
+ CHECK_DIF_OK(dif_alert_handler_irq_acknowledge(&alert_handler, irq));
+ }
+
+ // Complete the IRQ by writing the IRQ source to the Ibex specific CC
+ // register.
+ CHECK_DIF_OK(dif_rv_plic_irq_complete(&plic, kPlicTarget, irq_id));
+}
+
+/**
+ * Initialize the peripherals used in this test.
+ */
+void init_peripherals(void) {
+ // Initialize pwrmgr.
+ CHECK_DIF_OK(dif_pwrmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_PWRMGR_AON_BASE_ADDR), &pwrmgr));
+
+ // Initialize rstmgr to check the reset reason.
+ CHECK_DIF_OK(dif_rstmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_RSTMGR_AON_BASE_ADDR), &rstmgr));
+
+ // Initialize aon timer to use the wdog.
+ CHECK_DIF_OK(dif_aon_timer_init(
+ mmio_region_from_addr(TOP_MATCHA_AON_TIMER_AON_BASE_ADDR), &aon_timer));
+
+ // 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 plic.
+ CHECK_DIF_OK(dif_rv_plic_init(
+ mmio_region_from_addr(TOP_MATCHA_RV_PLIC_BASE_ADDR), &plic));
+
+ rv_plic_testutils_irq_range_enable(
+ &plic, kPlicTarget, kTopMatchaPlicIrqIdAonTimerAonWkupTimerExpired,
+ kTopMatchaPlicIrqIdAonTimerAonWdogTimerBark);
+
+ // Initialize alert handler.
+ CHECK_DIF_OK(dif_alert_handler_init(
+ mmio_region_from_addr(TOP_MATCHA_ALERT_HANDLER_BASE_ADDR),
+ &alert_handler));
+}
+
+/**
+ * Program the alert handler to escalate on alerts upto phase 2 (i.e. reset) but
+ * the phase 1 (i.e. wipe secrets) should occur and last during the time the
+ * wdog is programed to bark.
+ */
+static void alert_handler_config(void) {
+ dif_alert_handler_alert_t alerts[] = {kTopMatchaAlertIdPwrmgrAonFatalFault};
+ dif_alert_handler_class_t alert_classes[] = {kDifAlertHandlerClassA};
+
+ dif_alert_handler_escalation_phase_t esc_phases[] = {
+ {.phase = kDifAlertHandlerClassStatePhase0,
+ .signal = 0,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase0Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()},
+ {.phase = kDifAlertHandlerClassStatePhase1,
+ .signal = 1,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase1Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()},
+ {.phase = kDifAlertHandlerClassStatePhase2,
+ .signal = 3,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase2Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()}};
+
+ dif_alert_handler_class_config_t class_config[] = {{
+ .auto_lock_accumulation_counter = kDifToggleDisabled,
+ .accumulator_threshold = 0,
+ .irq_deadline_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase0Micros) *
+ alert_handler_testutils_cycle_rescaling_factor(),
+ .escalation_phases = esc_phases,
+ .escalation_phases_len = ARRAYSIZE(esc_phases),
+ .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase3,
+ }};
+
+ dif_alert_handler_class_t classes[] = {kDifAlertHandlerClassA};
+ dif_alert_handler_config_t config = {
+ .alerts = alerts,
+ .alert_classes = alert_classes,
+ .alerts_len = ARRAYSIZE(alerts),
+ .classes = classes,
+ .class_configs = class_config,
+ .classes_len = ARRAYSIZE(class_config),
+ .ping_timeout = 0,
+ };
+
+ alert_handler_testutils_configure_all(&alert_handler, config,
+ kDifToggleEnabled);
+ // Enables alert handler irq.
+ CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
+ &alert_handler, kDifAlertHandlerIrqClassa, kDifToggleEnabled));
+}
+
+/**
+ * Execute the aon timer interrupt test.
+ */
+static void config_escalate(dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr) {
+ uint64_t bark_cycles =
+ aon_timer_testutils_get_aon_cycles_from_us(kWdogBarkMicros) *
+ alert_handler_testutils_cycle_rescaling_factor();
+ uint64_t bite_cycles =
+ aon_timer_testutils_get_aon_cycles_from_us(kWdogBiteMicros) *
+ alert_handler_testutils_cycle_rescaling_factor();
+
+ LOG_INFO(
+ "Wdog will bark after %u/%u us/cycles and bite after %u/%u us/cycles",
+ (uint32_t)kWdogBarkMicros, (uint32_t)bark_cycles,
+ (uint32_t)kWdogBiteMicros, (uint32_t)bite_cycles);
+
+ // Setup the wdog bark and bite timeouts.
+ aon_timer_testutils_watchdog_config(aon_timer, bark_cycles, bite_cycles,
+ false);
+
+ // Trigger the alert handler to escalate.
+ dif_pwrmgr_alert_t alert = kDifPwrmgrAlertFatalFault;
+ CHECK_DIF_OK(dif_pwrmgr_alert_force(pwrmgr, alert));
+}
+
+static void low_power_glitch_reset(const dif_pwrmgr_t *pwrmgr) {
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceFive,
+ 0);
+ // Enter in low power mode.
+ wait_for_interrupt();
+}
+
+static void normal_sleep_glitch_reset(const dif_pwrmgr_t *pwrmgr) {
+ // Place device into normal (shallow) power
+ dif_pwrmgr_domain_config_t config;
+ config = kDifPwrmgrDomainOptionUsbClockInLowPower |
+ kDifPwrmgrDomainOptionCoreClockInLowPower |
+ kDifPwrmgrDomainOptionIoClockInLowPower |
+ kDifPwrmgrDomainOptionMainPowerInLowPower;
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceFive,
+ config);
+ // Enter in low power mode.
+ wait_for_interrupt();
+}
+
+static void timer_on(uint32_t usec) {
+ busy_spin_micros(usec);
+ // If we arrive here the test must fail.
+ CHECK(false, "Timeout waiting for reset!");
+}
+
+/**
+ * Configure the wdog.
+ */
+static void config_wdog(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us,
+ uint64_t bite_time_us) {
+ uint32_t bark_cycles =
+ aon_timer_testutils_get_aon_cycles_from_us(bark_time_us);
+ uint32_t bite_cycles =
+ aon_timer_testutils_get_aon_cycles_from_us(bite_time_us);
+
+ LOG_INFO("Wdog will bark after %u us and bite after %u us",
+ (uint32_t)bark_time_us, (uint32_t)bite_time_us);
+ // Setup the wdog bark and bite timeouts.
+
+ aon_timer_testutils_watchdog_config(aon_timer, bark_cycles, bite_cycles,
+ false);
+ // Set wdog as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceTwo,
+ kDifToggleEnabled));
+}
+
+/**
+ * Execute the aon timer wdog bite reset test.
+ */
+static void wdog_bite_test(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us) {
+ uint64_t bite_time_us = bark_time_us * 2;
+ config_wdog(aon_timer, pwrmgr, bark_time_us, bite_time_us);
+
+ // The `intr_state` takes 3 aon clock cycles to rise plus 2 extra cycles as a
+ // precaution.
+ uint32_t wait_us =
+ bark_time_us +
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase0Micros) *
+ alert_handler_testutils_cycle_rescaling_factor();
+
+ // Wait bark time and check that the bark interrupt requested.
+ busy_spin_micros(wait_us);
+ bool is_pending = false;
+ CHECK_DIF_OK(dif_aon_timer_irq_is_pending(
+ aon_timer, kDifAonTimerIrqWdogTimerBark, &is_pending));
+ CHECK(is_pending, "Wdog bark irq did not rise after %u microseconds",
+ wait_us);
+
+ // Wait for the remaining time to the wdog bite.
+ busy_spin_micros(wait_us);
+ // If we arrive here the test must fail.
+ CHECK(false, "Timeout waiting for Wdog bite reset!");
+}
+
+/**
+ * Execute the aon timer wdog bite reset during sleep test.
+ */
+static void sleep_wdog_bite_test(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr,
+ uint64_t bark_time_us) {
+ uint64_t bite_time_us = bark_time_us * 2;
+ config_wdog(aon_timer, pwrmgr, bark_time_us, bite_time_us);
+}
+
+static void low_power_wdog(const dif_pwrmgr_t *pwrmgr) {
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ // Enter in low power mode.
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceTwo,
+ 0);
+ LOG_INFO("Low power set for watch dog");
+ wait_for_interrupt();
+ // If we arrive here the test must fail.
+ CHECK(false, "Fail to enter in low power mode!");
+}
+
+static void normal_sleep_wdog(const dif_pwrmgr_t *pwrmgr) {
+ // Place device into low power and immediately wake.
+ dif_pwrmgr_domain_config_t config;
+ config = kDifPwrmgrDomainOptionUsbClockInLowPower |
+ kDifPwrmgrDomainOptionCoreClockInLowPower |
+ kDifPwrmgrDomainOptionIoClockInLowPower |
+ kDifPwrmgrDomainOptionMainPowerInLowPower;
+
+ // Enter in low power mode.
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceTwo,
+ config);
+ LOG_INFO("Normal sleep set for watchdog");
+ wait_for_interrupt();
+}
+
+static void low_power_por(const dif_pwrmgr_t *pwrmgr) {
+ // Set por as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceTwo,
+ kDifToggleEnabled));
+
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ pwrmgr_testutils_enable_low_power(
+ pwrmgr,
+ (kDifPwrmgrWakeupRequestSourceOne | kDifPwrmgrWakeupRequestSourceTwo |
+ kDifPwrmgrWakeupRequestSourceThree | kDifPwrmgrWakeupRequestSourceFour |
+ kDifPwrmgrWakeupRequestSourceFive | kDifPwrmgrWakeupRequestSourceSix),
+ 0);
+ // Enter in low power mode.
+ wait_for_interrupt();
+ // If we arrive here the test must fail.
+ CHECK(false, "Fail to enter in low power mode!");
+}
+
+static void normal_sleep_por(const dif_pwrmgr_t *pwrmgr) {
+ // Set por as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceTwo,
+ kDifToggleEnabled));
+
+ // Place device into low power and immediately wake.
+ dif_pwrmgr_domain_config_t config;
+ config = kDifPwrmgrDomainOptionUsbClockInLowPower |
+ kDifPwrmgrDomainOptionCoreClockInLowPower |
+ kDifPwrmgrDomainOptionIoClockInLowPower |
+ kDifPwrmgrDomainOptionMainPowerInLowPower;
+
+ // Program the pwrmgr to go to swallow sleep state (clocks on).
+ pwrmgr_testutils_enable_low_power(
+ pwrmgr,
+ (kDifPwrmgrWakeupRequestSourceOne | kDifPwrmgrWakeupRequestSourceTwo |
+ kDifPwrmgrWakeupRequestSourceThree | kDifPwrmgrWakeupRequestSourceFour |
+ kDifPwrmgrWakeupRequestSourceFive | kDifPwrmgrWakeupRequestSourceSix),
+ config);
+ // Enter in low power mode.
+ wait_for_interrupt();
+}
+
+bool test_main(void) {
+ // Enable global and external IRQ at Ibex.
+ irq_global_ctrl(true);
+ irq_external_ctrl(true);
+
+ init_peripherals();
+
+ // Enable all the AON interrupts used in this test.
+ rv_plic_testutils_irq_range_enable(&plic, kPlicTarget,
+ kTopMatchaPlicIrqIdAlertHandlerClassa,
+ kTopMatchaPlicIrqIdAlertHandlerClassd);
+
+ alert_handler_config();
+
+ // First check the flash stored value
+ uint32_t event_idx = flash_ctrl_testutils_counter_get(0);
+
+ // Enable flash access
+ flash_ctrl_testutils_default_region_access(&flash_ctrl,
+ /*rd_en*/ true,
+ /*prog_en*/ true,
+ /*erase_en*/ true,
+ /*scramble_en*/ false,
+ /*ecc_en*/ false,
+ /*he_en*/ false);
+
+ // Increment flash counter to know where we are
+ flash_ctrl_testutils_counter_increment(&flash_ctrl, 0);
+
+ LOG_INFO("Test round %d", event_idx);
+ LOG_INFO("RST_IDX[%d] = %d", event_idx, RST_IDX[event_idx]);
+
+ // Check if there was a HW reset caused by expected cases
+ dif_rstmgr_reset_info_bitfield_t rst_info;
+ rst_info = rstmgr_testutils_reason_get();
+ rstmgr_testutils_reason_clear();
+ LOG_INFO("reset info = %02X", rst_info);
+
+ CHECK(rst_info == kDifRstmgrResetInfoPor ||
+ rst_info == kDifRstmgrResetInfoSysRstCtrl ||
+ rst_info == kDifRstmgrResetInfoWatchdog ||
+ rst_info == kDifRstmgrResetInfoEscalation ||
+ rst_info == kDifRstmgrResetInfoLowPowerExit ||
+ rst_info == (kDifRstmgrResetInfoSysRstCtrl |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoPowerUnstable |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoPowerUnstable |
+ kDifRstmgrResetInfoWatchdog |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoPowerUnstable |
+ kDifRstmgrResetInfoWatchdog) ||
+ rst_info == kDifRstmgrResetInfoPowerUnstable ||
+ rst_info ==
+ (kDifRstmgrResetInfoPor | kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoWatchdog |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoEscalation |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == kDifRstmgrResetInfoSw,
+ "Wrong reset reason %02X", rst_info);
+
+ switch (RST_IDX[event_idx] / 2) {
+ case 0:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO("Booting and setting normal sleep followed by glitch reset");
+ LOG_INFO("Let SV wait timer reset");
+ normal_sleep_glitch_reset(&pwrmgr);
+ timer_on(kWdogBiteMicros);
+ } else {
+ LOG_INFO("Booting and setting deep sleep followed by glitch reset");
+ LOG_INFO("Let SV wait timer reset");
+ low_power_glitch_reset(&pwrmgr);
+ }
+ break;
+ case 1:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO("Booting and setting normal sleep followed by hw por");
+ LOG_INFO("Let SV wait timer reset");
+ normal_sleep_por(&pwrmgr);
+ timer_on(kWdogBiteMicros);
+ } else {
+ LOG_INFO("Booting and setting deep sleep followed by hw por");
+ LOG_INFO("Let SV wait timer reset");
+ low_power_por(&pwrmgr);
+ }
+ break;
+ case 2:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO(
+ "Booting and setting normal sleep mode followed for low_power "
+ "entry reset");
+ LOG_INFO("Let SV wait timer reset");
+ // actually the same test as normal sleep + watchdog
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ normal_sleep_wdog(&pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ } else {
+ LOG_INFO(
+ "Booting and setting deep sleep mode followed for low_power entry "
+ "reset");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ // actually the same test as deep sleep + watchdog
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ low_power_wdog(&pwrmgr);
+ }
+ break;
+
+ case 3:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO(
+ "Booting and setting normal sleep followed by watchdog reset "
+ "combined "
+ "with sw_req");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+ CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
+ LOG_INFO("Device reset from sw");
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ normal_sleep_wdog(&pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ } else {
+ LOG_INFO(
+ "Booting and setting deep sleep followed by watchdog reset "
+ "combined "
+ "with sw_req");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+ CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
+ LOG_INFO("Device reset from sw");
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ low_power_wdog(&pwrmgr);
+ }
+ break;
+ case 4:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO("Booting and setting normal sleep followed by watchdog reset");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ normal_sleep_wdog(&pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ } else {
+ LOG_INFO("Booting and setting deep sleep followed by watchdog reset");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ low_power_wdog(&pwrmgr);
+ }
+ break;
+ case 5:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO("Last Booting");
+
+ return true;
+ } else {
+ LOG_INFO(
+ "Booting and running normal sleep followed by escalation reset");
+ config_escalate(&aon_timer, &pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ }
+ break;
+ default:
+ LOG_INFO("Booting for undefined case");
+ }
+
+ return false;
+}
diff --git a/sw/device/tests/sim_dv/sleep_pin_retention_test.c b/sw/device/tests/sim_dv/sleep_pin_retention_test.c
new file mode 100644
index 0000000..750e90e
--- /dev/null
+++ b/sw/device/tests/sim_dv/sleep_pin_retention_test.c
@@ -0,0 +1,214 @@
+// 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 "sw/device/lib/base/mmio.h"
+#include "sw/device/lib/dif/dif_gpio.h"
+#include "sw/device/lib/dif/dif_pinmux.h"
+#include "sw/device/lib/dif/dif_pwrmgr.h"
+#include "sw/device/lib/dif/dif_rv_plic.h"
+#include "sw/device/lib/runtime/irq.h"
+#include "sw/device/lib/runtime/log.h"
+#include "sw/device/lib/testing/autogen/isr_testutils.h"
+#include "sw/device/lib/testing/pwrmgr_testutils.h"
+#include "sw/device/lib/testing/rand_testutils.h"
+#include "sw/device/lib/testing/rv_plic_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();
+
+// PLIC structures
+static const uint32_t kPlicTarget = kTopMatchaPlicTargetIbex0;
+static dif_gpio_t gpio;
+static dif_pwrmgr_t pwrmgr;
+static dif_pinmux_t pinmux;
+static dif_pwrmgr_domain_config_t pwrmgr_domain_cfg;
+static dif_rv_plic_t plic;
+
+static plic_isr_ctx_t plic_ctx = {.rv_plic = &plic, .hart_id = kPlicTarget};
+static pwrmgr_isr_ctx_t pwrmgr_isr_ctx = {
+ .pwrmgr = &pwrmgr,
+ .plic_pwrmgr_start_irq_id = kTopMatchaPlicIrqIdPwrmgrAonWakeup,
+ .expected_irq = kDifPwrmgrIrqWakeup,
+ .is_only_irq = true};
+
+// SV randomizes the round of entering/exiting sleep then set this volatile
+// variable via backdoor_overwrite.
+static volatile const uint8_t kRounds = 2;
+
+// SW testcode randomly chooses the value for 8 GPIO pins (pins are fixed) then
+// invert the value for retention. SW will sends the value to SV testbench via
+// LOG_INFO().
+static const uint8_t kGpioVal = 0x00;
+
+// To wakeup and maintain GPIO, for now test enters to normal sleep only.
+static const bool deepPowerdown = false;
+
+// Num of GPIO Pads to test
+enum { kNumGpioPads = 8 };
+
+/**
+ * External interrupt handler.
+ */
+void ottf_external_isr(void) {
+ dif_pwrmgr_irq_t irq_id;
+ top_matcha_plic_peripheral_t peripheral;
+
+ isr_testutils_pwrmgr_isr(plic_ctx, pwrmgr_isr_ctx, &peripheral, &irq_id);
+
+ // Check that both the peripheral and the irq id is correct
+ CHECK(peripheral == kTopMatchaPlicPeripheralPwrmgrAon,
+ "IRQ peripheral: %d is incorrect", peripheral);
+ CHECK(irq_id == kDifPwrmgrIrqWakeup, "IRQ ID: %d is incorrect", irq_id);
+
+ // Clear PINMUX WKUP_CAUSE reg
+ CHECK_DIF_OK(dif_pinmux_wakeup_cause_clear(&pinmux));
+}
+
+/**
+ * A round of GPIO[7:0] retention value test.
+ *
+ * The test sequence is:
+ *
+ * 1. Randomly choose GPIO[7:0] value using rand_testutils.
+ * 2. Drive GPIO with the chosen value.
+ * 3. Send the chosen values to SV via LOG_INFO.
+ * 4. Configure PINMUX Retention value opposit to the chosen value for
+ * GPIO[7:0].
+ * 5. Initiate sleep mode (assuming pinmux pin wake up has been configured.)
+ * 6. WFI()
+ * 7. At this point, chip has been waken up by DV. Send a log to DV that chip
+ * has waken up.
+ *
+ * DV env checks all PIN value. SW simply drives the GPIO and invert the value
+ * for retention.
+ */
+void gpio_test(dif_pwrmgr_t *pwrmgr, dif_pinmux_t *pinmux, dif_gpio_t *gpio,
+ int round) {
+ uint8_t gpio_val = 0;
+ dif_pinmux_pad_kind_t pad_kind;
+ dif_pinmux_sleep_mode_t pad_mode;
+
+ LOG_INFO("Current Test Round: %1d", round);
+
+ // 1. Randomly choose GPIO value
+ gpio_val = rand_testutils_gen32_range(0, 255);
+
+ // 2. Drive GPIO with the chosen value.
+ CHECK_DIF_OK(dif_gpio_write_masked(gpio, (dif_gpio_mask_t)0x000000FF,
+ (dif_gpio_state_t)gpio_val));
+
+ // 3. Send the chosen value to SV via LOG_INFO.
+ //
+ // The format is:
+ //
+ // Chosen GPIO value: %2x
+ LOG_INFO("Chosen GPIO value: %2x", gpio_val);
+
+ // 4. Configure PINMUX Retention value opposite to the chosen value.
+ pad_kind = kDifPinmuxPadKindMio;
+ for (int i = 0; i < kNumGpioPads; i++) {
+ // GPIO are assigned starting from MIO0
+ pad_mode = ((gpio_val >> i) & 0x1) ? kDifPinmuxSleepModeLow
+ : kDifPinmuxSleepModeHigh;
+ CHECK_DIF_OK(dif_pinmux_pad_sleep_enable(
+ pinmux, kTopMatchaPinmuxMioOutIoa0 + i, pad_kind, pad_mode));
+ }
+
+ // 5. Initiate sleep mode
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceThree,
+ pwrmgr_domain_cfg);
+ // 6. WFI()
+ LOG_INFO("Entering low power mode.");
+ wait_for_interrupt();
+
+ // 7. Turn-off retention.
+ for (int i = 0; i < kNumGpioPads; i++) {
+ CHECK_DIF_OK(dif_pinmux_pad_sleep_clear_state(
+ pinmux, kTopMatchaPinmuxMioOutIoa0 + i, pad_kind));
+ }
+}
+
+/**
+ * Configure GPIO
+ *
+ * gpio_init() configures first 8 MIO PADs to GPIO[7:0].
+ */
+void gpio_init(const dif_pinmux_t *pinmux, const dif_gpio_t *gpio) {
+ // Drive GPIO first
+ CHECK_DIF_OK(
+ dif_gpio_output_set_enabled_all(gpio, (dif_gpio_state_t)0x000000FFu));
+ CHECK_DIF_OK(dif_gpio_write_masked(gpio, (dif_gpio_mask_t)0x000000FF,
+ (dif_gpio_state_t)0x00000000));
+
+ // Configure PINMUX to GPIO
+ for (int i = 0; i < kNumGpioPads; i++) {
+ CHECK_DIF_OK(dif_pinmux_input_select(
+ pinmux, kTopMatchaPinmuxPeripheralInGpioGpio0 + i,
+ kTopMatchaPinmuxInselIoa0 + i));
+ CHECK_DIF_OK(dif_pinmux_output_select(pinmux,
+ kTopMatchaPinmuxMioOutIoa0 + i,
+ kTopMatchaPinmuxOutselGpioGpio0 + i));
+ }
+}
+
+bool test_main(void) {
+ bool result = true;
+
+ dif_pinmux_index_t detector;
+ dif_pinmux_wakeup_config_t wakeup_cfg;
+
+ // Default Deep Power Down
+
+ // Enable global and external IRQ at Ibex.
+ irq_global_ctrl(true);
+ irq_external_ctrl(true);
+
+ // Initialize power manager
+ CHECK_DIF_OK(dif_pwrmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_PWRMGR_AON_BASE_ADDR), &pwrmgr));
+ CHECK_DIF_OK(dif_rv_plic_init(
+ mmio_region_from_addr(TOP_MATCHA_RV_PLIC_BASE_ADDR), &plic));
+ CHECK_DIF_OK(dif_pinmux_init(
+ mmio_region_from_addr(TOP_MATCHA_PINMUX_AON_BASE_ADDR), &pinmux));
+ CHECK_DIF_OK(
+ dif_gpio_init(mmio_region_from_addr(TOP_MATCHA_GPIO_BASE_ADDR), &gpio));
+
+ // Enable all the AON interrupts used in this test.
+ rv_plic_testutils_irq_range_enable(&plic, kPlicTarget,
+ kTopMatchaPlicIrqIdPwrmgrAonWakeup,
+ kTopMatchaPlicIrqIdPwrmgrAonWakeup);
+ // Enable pwrmgr interrupt
+ CHECK_DIF_OK(dif_pwrmgr_irq_set_enabled(&pwrmgr, 0, kDifToggleEnabled));
+
+ // Wakeup configs
+ wakeup_cfg.mode = kDifPinmuxWakeupModePositiveEdge;
+ wakeup_cfg.signal_filter = false;
+ wakeup_cfg.pad_type = 0; // MIO
+ wakeup_cfg.pad_select = kTopMatchaPinmuxInselIoa8; // MIO08
+
+ // Configure Wakeup Detector 0
+ CHECK_DIF_OK(dif_pinmux_wakeup_detector_enable(&pinmux, 0, wakeup_cfg));
+
+ if (deepPowerdown == false) {
+ // Configure Normal Sleep
+ pwrmgr_domain_cfg = kDifPwrmgrDomainOptionMainPowerInLowPower |
+ kDifPwrmgrDomainOptionUsbClockInActivePower;
+ }
+
+ LOG_INFO("Num Rounds: %3d", kRounds);
+
+ // Select IOA0:IOA7 to GPIO
+ gpio_init(&pinmux, &gpio);
+
+ // Set wakeup condition. Always use GPIO[8] for Pinmux PIN Wakeup.
+
+ for (int i = kRounds - 1; i >= 0; i--) {
+ gpio_test(&pwrmgr, &pinmux, &gpio, i);
+ }
+
+ return result;
+}
diff --git a/util/topgen_matcha/templates/chiplevel.sv.tpl b/util/topgen_matcha/templates/chiplevel.sv.tpl
index 1c0daf1..87945c3 100644
--- a/util/topgen_matcha/templates/chiplevel.sv.tpl
+++ b/util/topgen_matcha/templates/chiplevel.sv.tpl
@@ -697,15 +697,19 @@
.clk_src_usb_o ( ast_base_clks.clk_usb ),
.clk_src_usb_val_o ( ast_base_pwr.usb_clk_val ),
// smc source clock
+ .clk_src_smc_en_i ( base_ast_pwr.smc_clk_en ),
.clk_src_smc_o ( ast_base_clks.clk_smc ),
.clk_src_smc_val_o ( ast_base_pwr.smc_clk_val),
// ml source clock
+ .clk_src_ml_en_i ( base_ast_pwr.ml_clk_en ),
.clk_src_ml_o ( ast_base_clks.clk_ml ),
.clk_src_ml_val_o ( ast_base_pwr.ml_clk_val),
// video source clock
+ .clk_src_video_en_i ( base_ast_pwr.video_clk_en ),
.clk_src_video_o ( ast_base_clks.clk_video ),
.clk_src_video_val_o ( ast_base_pwr.video_clk_val),
// audio source clock
+ .clk_src_audio_en_i ( base_ast_pwr.audio_clk_en ),
.clk_src_audio_o ( ast_base_clks.clk_audio ),
.clk_src_audio_val_o ( ast_base_pwr.audio_clk_val),
// adc