Merge "Add clkmgr tests to edacloud"
diff --git a/hw/top_matcha/dv/chip_sim_cfg.hjson b/hw/top_matcha/dv/chip_sim_cfg.hjson
index 0f25c26..8be09e9 100644
--- a/hw/top_matcha/dv/chip_sim_cfg.hjson
+++ b/hw/top_matcha/dv/chip_sim_cfg.hjson
@@ -1708,21 +1708,21 @@
     {
       name: chip_sw_clkmgr_external_clk_src_for_sw_fast
       uvm_test_seq: chip_sw_base_vseq
-      sw_images: ["//sw/device/tests:clkmgr_external_clk_src_for_sw_fast_test:1"]
+      sw_images: ["//sw/device/tests:clkmgr_external_clk_src_for_sw_fast_test:1:matcha"]
       en_run_modes: ["sw_test_mode_test_rom"]
       run_opts: ["+chip_clock_source=ChipClockSourceExternal96Mhz", "+calibrate_usb_clk=1"]
     }
     {
       name: chip_sw_clkmgr_external_clk_src_for_sw_slow
       uvm_test_seq: chip_sw_base_vseq
-      sw_images: ["//sw/device/tests:clkmgr_external_clk_src_for_sw_slow_test:1"]
+      sw_images: ["//sw/device/tests:clkmgr_external_clk_src_for_sw_slow_test:1:matcha"]
       en_run_modes: ["sw_test_mode_test_rom"]
       run_opts: ["+chip_clock_source=ChipClockSourceExternal48Mhz", "+calibrate_usb_clk=1"]
     }
     {
       name: chip_sw_clkmgr_reset_frequency
       uvm_test_seq: chip_sw_base_vseq
-      sw_images: ["sw/device/tests:clkmgr_reset_frequency_test:1"]
+      sw_images: ["sw/device/tests:clkmgr_reset_frequency_test:1:matcha"]
       en_run_modes: ["sw_test_mode_test_rom"]
       run_opts: ["+calibrate_usb_clk=1"]
     }
@@ -1735,7 +1735,7 @@
     {
       name: chip_sw_clkmgr_sleep_frequency
       uvm_test_seq: chip_sw_base_vseq
-      sw_images: ["sw/device/tests:clkmgr_sleep_frequency_test:1"]
+      sw_images: ["sw/device/tests:clkmgr_sleep_frequency_test:1:matcha"]
       en_run_modes: ["sw_test_mode_test_rom"]
       run_opts: ["+calibrate_usb_clk=1"]
     }
@@ -2069,7 +2069,11 @@
         "chip_sw_ast_clk_rst_inputs",
         "chip_sw_atomics_test",
         "chip_sw_cam_ctrl_test",
+        "chip_sw_clkmgr_external_clk_src_for_sw_fast",
+        "chip_sw_clkmgr_external_clk_src_for_sw_slow",
         "chip_sw_clkmgr_off_peri",
+        "chip_sw_clkmgr_reset_frequency",
+        "chip_sw_clkmgr_sleep_frequency",
         "chip_sw_clkmgr_smoketest",
         "chip_sw_crt_test",
         "chip_sw_csrng_smoketest",
@@ -2149,7 +2153,11 @@
         "chip_sw_ast_clk_rst_inputs",
         "chip_sw_atomics_test",
         "chip_sw_cam_ctrl_test",
+        "chip_sw_clkmgr_external_clk_src_for_sw_fast",
+        "chip_sw_clkmgr_external_clk_src_for_sw_slow",
         "chip_sw_clkmgr_off_peri",
+        "chip_sw_clkmgr_reset_frequency",
+        "chip_sw_clkmgr_sleep_frequency",
         "chip_sw_clkmgr_smoketest",
         "chip_sw_crt_test",
         "chip_sw_csrng_smoketest",
diff --git a/sw/device/lib/testing/clkmgr_testutils.c b/sw/device/lib/testing/clkmgr_testutils.c
index caf3b68..d72b01e 100644
--- a/sw/device/lib/testing/clkmgr_testutils.c
+++ b/sw/device/lib/testing/clkmgr_testutils.c
@@ -195,13 +195,21 @@
     } else if (external_clk) {
       if (low_speed) {
         if (clk == kDifClkmgrMeasureClockIo ||
-            clk == kDifClkmgrMeasureClockMain) {
+            clk == kDifClkmgrMeasureClockMain ||
+            clk == kDifClkmgrMeasureClockAudio ||
+            clk == kDifClkmgrMeasureClockSmc ||
+            clk == kDifClkmgrMeasureClockMl ||
+            clk == kDifClkmgrMeasureClockVideo) {
           count_info = &kNoJitterCountInfos[kDifClkmgrMeasureClockIoDiv2];
         } else {
           count_info = &kNoJitterCountInfos[clk];
         }
       } else {
-        if (clk == kDifClkmgrMeasureClockMain) {
+        if (clk == kDifClkmgrMeasureClockMain ||
+            clk == kDifClkmgrMeasureClockAudio ||
+            clk == kDifClkmgrMeasureClockSmc ||
+            clk == kDifClkmgrMeasureClockMl ||
+            clk == kDifClkmgrMeasureClockVideo) {
           count_info = &kNoJitterCountInfos[kDifClkmgrMeasureClockIo];
         } else {
           count_info = &kNoJitterCountInfos[clk];
diff --git a/sw/device/tests/BUILD b/sw/device/tests/BUILD
index 48a45e5..d24b5a5 100644
--- a/sw/device/tests/BUILD
+++ b/sw/device/tests/BUILD
@@ -917,6 +917,66 @@
     ],
 )
 
+cc_library(
+    name = "clkmgr_external_clk_src_for_sw_impl",
+    srcs = ["@lowrisc_opentitan//sw/device/tests:clkmgr_external_clk_src_for_sw_impl.c"],
+    hdrs = ["@lowrisc_opentitan//sw/device/tests:clkmgr_external_clk_src_for_sw_impl.h"],
+    target_compatible_with = [OPENTITAN_CPU],
+    deps = [
+        ":test_dv_lib_opentitan",
+        "//sw/device/lib/dif:clkmgr",
+        "//sw/device/lib/testing:clkmgr_testutils",
+        "@lowrisc_opentitan//sw/device/lib/dif:base",
+        "@lowrisc_opentitan//sw/device/lib/testing:aon_timer_testutils",
+    ],
+)
+
+matcha_dv_test(
+    name = "clkmgr_external_clk_src_for_sw_fast_test",
+    srcs = ["@lowrisc_opentitan//sw/device/tests:clkmgr_external_clk_src_for_sw_fast_test.c"],
+    deps = [
+        ":clkmgr_external_clk_src_for_sw_impl",
+    ],
+)
+
+matcha_dv_test(
+    name = "clkmgr_external_clk_src_for_sw_slow_test",
+    srcs = ["@lowrisc_opentitan//sw/device/tests:clkmgr_external_clk_src_for_sw_slow_test.c"],
+    deps = [
+        ":clkmgr_external_clk_src_for_sw_impl",
+    ],
+)
+
+matcha_dv_test(
+    name = "clkmgr_reset_frequency_test",
+    srcs = ["@lowrisc_opentitan//sw/device/tests:clkmgr_reset_frequency_test.c"],
+    deps = [
+        ":test_dv_lib_opentitan",
+        "//sw/device/lib/arch:device",
+        "//sw/device/lib/testing:clkmgr_testutils",
+        "@lowrisc_opentitan//sw/device/lib/dif:sensor_ctrl",
+        "@lowrisc_opentitan//sw/device/lib/testing:aon_timer_testutils",
+        "@lowrisc_opentitan//sw/device/lib/testing:rstmgr_testutils",
+        "@lowrisc_opentitan//sw/device/lib/testing:sensor_ctrl_testutils",
+    ],
+)
+
+matcha_dv_test(
+    name = "clkmgr_sleep_frequency_test",
+    srcs = ["clkmgr_sleep_frequency_test.c"],
+    deps = [
+        ":test_dv_lib",
+        "//sw/device/lib/dif:rv_plic_sec",
+        "//sw/device/lib/testing:clkmgr_testutils",
+        "//sw/device/lib/testing:isr_testutils",
+        "@lowrisc_opentitan//sw/device/lib/dif:sensor_ctrl",
+        "@lowrisc_opentitan//sw/device/lib/testing:aon_timer_testutils",
+        "@lowrisc_opentitan//sw/device/lib/testing:pwrmgr_testutils",
+        "@lowrisc_opentitan//sw/device/lib/testing:rv_plic_testutils",
+        "@lowrisc_opentitan//sw/device/lib/testing:sensor_ctrl_testutils",
+    ],
+)
+
 # Smoke tests
 matcha_dv_test(
     name = "aes_smoketest",
diff --git a/sw/device/tests/clkmgr_sleep_frequency_test.c b/sw/device/tests/clkmgr_sleep_frequency_test.c
new file mode 100644
index 0000000..90c7cf0
--- /dev/null
+++ b/sw/device/tests/clkmgr_sleep_frequency_test.c
@@ -0,0 +1,147 @@
+// 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/memory.h"
+#include "sw/device/lib/dif/dif_rv_plic.h"
+#include "sw/device/lib/dif/dif_sensor_ctrl.h"
+#include "sw/device/lib/runtime/irq.h"
+#include "sw/device/lib/runtime/log.h"
+#include "sw/device/lib/testing/aon_timer_testutils.h"
+#include "sw/device/lib/testing/autogen/isr_testutils.h"
+#include "sw/device/lib/testing/clkmgr_testutils.h"
+#include "sw/device/lib/testing/pwrmgr_testutils.h"
+#include "sw/device/lib/testing/rv_plic_testutils.h"
+#include "sw/device/lib/testing/sensor_ctrl_testutils.h"
+#include "sw/device/lib/testing/test_framework/check.h"
+#include "sw/device/lib/testing/test_framework/ottf_main.h"
+
+OTTF_DEFINE_TEST_CONFIG();
+
+/**
+ * This test measure clock counts with clkmgr frequency measurements, performing
+ * 100 measurements per round. Measurement errors (fast or slow clocks) are
+ * recorded as recoverable error in clkmgr.
+ *
+ * After 100 measurements, test kicks in regular sleep with IO and USB
+ * clocks turned off. Once the chip wakes up the measurements should be
+ * enabled, but no errors should be found even for stopped clocks.
+ *
+ * Notice the test overrides the hardware behavior so it comes out with
+ * calibrated USB clock, otherwise the USB clock frequency will be incorrect.
+ * USB calibration should be a separate test, and may be vendor-specific.
+ */
+enum {
+  kWaitForCSRPollingMicros = 1,
+  kMeasurementsPerRound = 100,
+};
+
+static dif_clkmgr_t clkmgr;
+static dif_pwrmgr_t pwrmgr;
+static dif_rv_plic_t rv_plic;
+
+static plic_isr_ctx_t plic_ctx = {.rv_plic = &rv_plic,
+                                  .hart_id = kTopMatchaPlicTargetIbex0};
+
+static pwrmgr_isr_ctx_t pwrmgr_isr_ctx = {
+    .pwrmgr = &pwrmgr,
+    .plic_pwrmgr_start_irq_id = kTopMatchaPlicIrqIdPwrmgrAonWakeup,
+    .expected_irq = kDifPwrmgrIrqWakeup,
+    .is_only_irq = true};
+
+static volatile bool isr_entered;
+
+/**
+ * External interrupt handler.
+ */
+void ottf_external_isr(void) {
+  dif_pwrmgr_irq_t irq_id;
+  top_matcha_plic_peripheral_t peripheral;
+
+  isr_entered = true;
+  isr_testutils_pwrmgr_isr(plic_ctx, pwrmgr_isr_ctx, &peripheral, &irq_id);
+
+  // Check that both the peripheral and the irq id are correct.
+  CHECK(peripheral == kTopMatchaPlicPeripheralPwrmgrAon,
+        "IRQ peripheral: %d is incorrect", peripheral);
+  CHECK(irq_id == kDifPwrmgrIrqWakeup, "IRQ ID: %d is incorrect", irq_id);
+}
+
+bool test_main(void) {
+  dif_sensor_ctrl_t sensor_ctrl;
+  dif_aon_timer_t aon_timer;
+
+  const uint32_t kMeasurementDelayMicros =
+      aon_timer_testutils_get_us_from_aon_cycles(kMeasurementsPerRound);
+
+  // Enable global and external IRQ at Ibex.
+  irq_global_ctrl(true);
+  irq_external_ctrl(true);
+
+  CHECK_DIF_OK(dif_clkmgr_init(
+      mmio_region_from_addr(TOP_MATCHA_CLKMGR_AON_BASE_ADDR), &clkmgr));
+  CHECK_DIF_OK(dif_sensor_ctrl_init(
+      mmio_region_from_addr(TOP_MATCHA_SENSOR_CTRL_BASE_ADDR), &sensor_ctrl));
+  CHECK_DIF_OK(dif_pwrmgr_init(
+      mmio_region_from_addr(TOP_MATCHA_PWRMGR_AON_BASE_ADDR), &pwrmgr));
+  CHECK_DIF_OK(dif_aon_timer_init(
+      mmio_region_from_addr(TOP_MATCHA_AON_TIMER_AON_BASE_ADDR), &aon_timer));
+  CHECK_DIF_OK(dif_rv_plic_init(
+      mmio_region_from_addr(TOP_MATCHA_RV_PLIC_BASE_ADDR), &rv_plic));
+
+  LOG_INFO("TEST: wait for ast init");
+  IBEX_SPIN_FOR(sensor_ctrl_ast_init_done(&sensor_ctrl), 1000);
+  LOG_INFO("TEST: done ast init");
+
+  CHECK(pwrmgr_testutils_is_wakeup_reason(&pwrmgr, 0));
+
+  clkmgr_testutils_enable_clock_counts_with_expected_thresholds(
+      &clkmgr, /*jitter_enabled=*/false, /*external_clk=*/false,
+      /*low_speed=*/false);
+  busy_spin_micros(kMeasurementDelayMicros);
+
+  // check results
+  CHECK(clkmgr_testutils_check_measurement_counts(&clkmgr));
+  clkmgr_testutils_disable_clock_counts(&clkmgr);
+
+  // Start new round of measurements.
+  clkmgr_testutils_enable_clock_counts_with_expected_thresholds(
+      &clkmgr, /*jitter_enabled=*/false, /*external_clk=*/false,
+      /*low_speed=*/false);
+
+  busy_spin_micros(kMeasurementDelayMicros);
+
+  // Set wakeup timer to 100 us to have enough down time, and also wait before
+  // entering sleep to have a chance to measure before sleeping. With normal
+  // sleep all measurements should remain enabled, and there should be no
+  // errors for clocks that were selectively turned off.
+  uint32_t wakeup_threshold = kDeviceType == kDeviceSimVerilator ? 1000 : 100;
+  aon_timer_testutils_wakeup_config(&aon_timer, wakeup_threshold);
+
+  // Enable all the AON interrupts used in this test.
+  rv_plic_testutils_irq_range_enable(&rv_plic, kTopMatchaPlicTargetIbex0,
+                                     kTopMatchaPlicIrqIdPwrmgrAonWakeup,
+                                     kTopMatchaPlicIrqIdPwrmgrAonWakeup);
+  CHECK_DIF_OK(dif_pwrmgr_irq_set_enabled(&pwrmgr, 0, kDifToggleEnabled));
+
+  // Put chip in normal sleep, and keep Core clock running. All io and usb
+  // clocks are stopped, but we expect the stoppage won't trigger errors.
+  pwrmgr_testutils_enable_low_power(
+      &pwrmgr, /*wakeups=*/kDifPwrmgrWakeupRequestSourceFive,
+      /*domain_config=*/kDifPwrmgrDomainOptionCoreClockInLowPower |
+          kDifPwrmgrDomainOptionUsbClockInActivePower |
+          kDifPwrmgrDomainOptionMainPowerInLowPower);
+
+  LOG_INFO("TEST: Issue WFI to enter sleep");
+  wait_for_interrupt();
+
+  CHECK(isr_entered);
+
+  // Interrupt happened. Check the measurement state.
+  CHECK(clkmgr_testutils_check_measurement_counts(&clkmgr));
+  CHECK(clkmgr_testutils_check_measurement_enables(&clkmgr, kDifToggleEnabled));
+
+  return true;
+}