Add clkmgr tests to edacloud Change-Id: I8fcc5c37e4d4b704cc158e85091a3b87006dd869
diff --git a/hw/top_matcha/dv/chip_sim_cfg.hjson b/hw/top_matcha/dv/chip_sim_cfg.hjson index cc64188..2f574e4 100644 --- a/hw/top_matcha/dv/chip_sim_cfg.hjson +++ b/hw/top_matcha/dv/chip_sim_cfg.hjson
@@ -1706,21 +1706,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"] } @@ -1733,7 +1733,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"] } @@ -2063,7 +2063,11 @@ "chip_sw_aon_timer_smoketest", "chip_sw_ast_clk_rst_inputs", "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", @@ -2141,7 +2145,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; +}