Add chip_sw_sleep_pwm_pulses to edacloud - Add chip_sw_sleep_pwm_pulses - Temporarily remove chip_sw_sleep_pin_wake from edacloud_nightly Change-Id: I75717311114209018d0ac6496125003ca64191bd
diff --git a/hw/top_matcha/dv/chip_sim_cfg.hjson b/hw/top_matcha/dv/chip_sim_cfg.hjson index 1fbdabb..9486b91 100644 --- a/hw/top_matcha/dv/chip_sim_cfg.hjson +++ b/hw/top_matcha/dv/chip_sim_cfg.hjson
@@ -675,7 +675,7 @@ { name: chip_sw_sleep_pwm_pulses uvm_test_seq: chip_sw_pwm_pulses_vseq - sw_images: ["//sw/device/tests:sleep_pwm_pulses_test:1"] + sw_images: ["//sw/device/tests:sleep_pwm_pulses_test:1:matcha"] en_run_modes: ["sw_test_mode_test_rom"] } { @@ -2112,7 +2112,7 @@ "chip_sw_sensor_ctrl_status", "chip_sw_sleep_pin_mio_dio_val", "chip_sw_sleep_pin_retention", - "chip_sw_sleep_pin_wake", + "chip_sw_sleep_pwm_pulses", "chip_sw_smc_cam_irq_test", "chip_sw_smc_ctrl_test", "chip_sw_smc_env_test", @@ -2206,6 +2206,7 @@ "chip_sw_sleep_pin_mio_dio_val", "chip_sw_sleep_pin_retention", "chip_sw_sleep_pin_wake", + "chip_sw_sleep_pwm_pulses", "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_if.sv b/hw/top_matcha/dv/env/chip_if.sv index 6663de3..a5efa22 100644 --- a/hw/top_matcha/dv/env/chip_if.sv +++ b/hw/top_matcha/dv/env/chip_if.sv
@@ -569,7 +569,7 @@ // Functional (muxed) interface: PWM. localparam int AssignedPwmIos[NUM_PWM_CHANNELS] = { top_matcha_pkg::MioPadIob10, top_matcha_pkg::MioPadIob11, top_matcha_pkg::MioPadIob12, - top_matcha_pkg::MioPadIoc10, top_matcha_pkg::MioPadIoc11, top_matcha_pkg::MioPadIoc12 + top_matcha_pkg::MioPadIod2, top_matcha_pkg::MioPadIod3, top_matcha_pkg::MioPadIoc12 }; for (genvar i = 0; i < NUM_PWM_CHANNELS; i++) begin : gen_pwm_if_conn
diff --git a/sw/device/tests/BUILD b/sw/device/tests/BUILD index d24b5a5..5c0339f 100644 --- a/sw/device/tests/BUILD +++ b/sw/device/tests/BUILD
@@ -977,6 +977,22 @@ ], ) +matcha_dv_test( + name = "sleep_pwm_pulses_test", + srcs = ["sleep_pwm_pulses_test.c"], + deps = [ + ":test_dv_lib", + "//sw/device/lib/dif:pinmux", + "//sw/device/lib/dif:rstmgr", + "@lowrisc_opentitan//sw/device/lib/dif:aon_timer", + "@lowrisc_opentitan//sw/device/lib/dif:pwm", + "@lowrisc_opentitan//sw/device/lib/dif:pwrmgr", + "@lowrisc_opentitan//sw/device/lib/testing:aon_timer_testutils", + "@lowrisc_opentitan//sw/device/lib/testing:pwrmgr_testutils", + "@lowrisc_opentitan//sw/device/lib/testing:rstmgr_testutils", + ], +) + # Smoke tests matcha_dv_test( name = "aes_smoketest",
diff --git a/sw/device/tests/sleep_pwm_pulses_test.c b/sw/device/tests/sleep_pwm_pulses_test.c new file mode 100644 index 0000000..7e94c98 --- /dev/null +++ b/sw/device/tests/sleep_pwm_pulses_test.c
@@ -0,0 +1,209 @@ +// 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 "pwm_regs.h" +#include "sw/device/lib/base/mmio.h" +#include "sw/device/lib/dif/dif_aon_timer.h" +#include "sw/device/lib/dif/dif_pinmux.h" +#include "sw/device/lib/dif/dif_pwm.h" +#include "sw/device/lib/dif/dif_pwrmgr.h" +#include "sw/device/lib/dif/dif_rstmgr.h" +#include "sw/device/lib/runtime/log.h" +#include "sw/device/lib/testing/aon_timer_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" + +/** + * SLEEP PWM PULSES test + * + * This test configure 6 pwm channels with a fixed duty cycle + * then kicks power manager sleep mode to see pwm pluses are + * not affected by power down event. + * pwm out --> pinmux setup is chosen arbitrary as below + * pwmout[0] -> IOB10 + * pwmout[1] -> IOB11 + * pwmout[2] -> IOB12 + * pwmout[3] -> IOD2 + * pwmout[4] -> IOD3 + * pwmout[5] -> IOC12 + * + * Since purpose of this test is to check pwm -> pinmux + * connectivity and pulse integrity under sleep event, + * Fixed pwm configuration, mode and 0 phase delay are chosen. + */ + +OTTF_DEFINE_TEST_CONFIG(); + +static const dif_pinmux_index_t kPinmuxOutsel[PWM_PARAM_N_OUTPUTS] = { + kTopMatchaPinmuxOutselPwmAonPwm0, kTopMatchaPinmuxOutselPwmAonPwm1, + kTopMatchaPinmuxOutselPwmAonPwm2, kTopMatchaPinmuxOutselPwmAonPwm3, + kTopMatchaPinmuxOutselPwmAonPwm4, kTopMatchaPinmuxOutselPwmAonPwm5, +}; + +static const dif_pinmux_index_t kPinmuxMioOut[PWM_PARAM_N_OUTPUTS] = { + kTopMatchaPinmuxMioOutIob10, kTopMatchaPinmuxMioOutIob11, + kTopMatchaPinmuxMioOutIob12, kTopMatchaPinmuxMioOutIod2, + kTopMatchaPinmuxMioOutIod3, kTopMatchaPinmuxMioOutIoc12, +}; + +static const dif_pwm_channel_t kPwmChannel[PWM_PARAM_N_OUTPUTS] = { + kDifPwmChannel0, kDifPwmChannel1, kDifPwmChannel2, + kDifPwmChannel3, kDifPwmChannel4, kDifPwmChannel5, +}; + +// Duty cycle in the unit of beat +// These are random numbers betwen [1,beats_per_pulse_cycle) +// make 'static volatile' to overwrite from +// hw/top_matcha/dv/env/seq_lib/chip_sw_pwm_pulses_vseq.sv +// via backdoor +static volatile const uint16_t kPwmDutycycle[PWM_PARAM_N_OUTPUTS] = { + 6, 11, 27, 8, 17, 7, +}; + +static const dif_pwm_config_t config_ = { + // set beat period to 3 + .clock_divisor = 2, + + // upper 5bits of phase cntr only matter + // and total(on+off) beats per cycle will be 32 + .beats_per_pulse_cycle = 32, +}; + +// This is initial value of config variable +static const dif_pwm_channel_config_t default_ch_cfg_ = { + .duty_cycle_a = 0, + .duty_cycle_b = 0, + .phase_delay = 0, + .mode = kDifPwmModeFirmware, + .polarity = kDifPwmPolarityActiveHigh, + .blink_parameter_x = 0, + .blink_parameter_y = 0, +}; + +// Configure pwm channel register for all 6 channels. +// This also contain disable and enable each channel. +void config_pwm_channels(dif_pwm_t *pwm) { + dif_pwm_channel_config_t channel_config_ = default_ch_cfg_; + + for (int i = 0; i < PWM_PARAM_N_OUTPUTS; ++i) { + CHECK_DIF_OK( + dif_pwm_channel_set_enabled(pwm, kPwmChannel[i], kDifToggleDisabled)); + channel_config_.duty_cycle_a = kPwmDutycycle[i]; + CHECK_DIF_OK( + dif_pwm_configure_channel(pwm, kPwmChannel[i], channel_config_)); + CHECK_DIF_OK( + dif_pwm_channel_set_enabled(pwm, kPwmChannel[i], kDifToggleEnabled)); + } +} + +bool test_main(void) { + dif_pwrmgr_t pwrmgr; + dif_rstmgr_t rstmgr; + + // Issue a wakeup signal in ~150us through the AON timer. + // + // At 200kHz, threshold of 30 is equal to 150us. There is an additional + // ~4 cycle overhead for the CSR value to synchronize with the AON clock. + // We should expect the wake up to trigger in ~170us. This is sufficient + // time to allow pwrmgr config and the low power entry on WFI to complete. + // + // Adjust the threshold for Verilator since it runs on different clock + // frequencies. + uint32_t wakeup_threshold = 30; + if (kDeviceType == kDeviceSimVerilator) { + wakeup_threshold = 300; + } + + // Initialize 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. + CHECK_DIF_OK(dif_rstmgr_init( + mmio_region_from_addr(TOP_MATCHA_RSTMGR_AON_BASE_ADDR), &rstmgr)); + + 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)); + + // Assuming the chip hasn't slept yet, wakeup reason should be empty. + + // Notice we are clearing rstmgr's RESET_INFO, so after the aon wakeup there + // is only one bit set. + if (pwrmgr_testutils_is_wakeup_reason(&pwrmgr, 0)) { + dif_pwm_t pwm; + dif_pinmux_t pinmux; + // Initialize pwm + CHECK_DIF_OK(dif_pwm_init( + mmio_region_from_addr(TOP_MATCHA_PWM_AON_BASE_ADDR), &pwm)); + + // Update pwm.CFG + CHECK_DIF_OK(dif_pwm_configure(&pwm, config_)); + + // Update all 6 pwm channels + config_pwm_channels(&pwm); + + // enable phase count to make the change effective + CHECK_DIF_OK(dif_pwm_phase_cntr_set_enabled(&pwm, kDifToggleEnabled)); + + // Initialize pinmux - this assigns PwmAonPwm[0..5] to + // IOB10..12, IOD2, IOD3 and IOC12 + // LOG_INFO is used to indicate pwmout is available to + // SV pwm_monitor + CHECK_DIF_OK(dif_pinmux_init( + mmio_region_from_addr(TOP_MATCHA_PINMUX_AON_BASE_ADDR), &pinmux)); + + LOG_INFO("pinmux_init begin"); + for (int i = 0; i < PWM_PARAM_N_OUTPUTS; ++i) { + CHECK_DIF_OK(dif_pinmux_output_select(&pinmux, kPinmuxMioOut[i], + kPinmuxOutsel[i])); + } + LOG_INFO("pinmux_init end"); + + // Add 1ms to initial pulses go through before sleep event + busy_spin_micros(1 * 1000); + + LOG_INFO("POR reset"); + CHECK(rstmgr_testutils_reset_info_any(&rstmgr, kDifRstmgrResetInfoPor)); + + // Prepare rstmgr for a reset. + rstmgr_testutils_pre_reset(&rstmgr); + + aon_timer_testutils_wakeup_config(&aon_timer, wakeup_threshold); + // Deep sleep. + pwrmgr_testutils_enable_low_power(&pwrmgr, + kDifPwrmgrWakeupRequestSourceFive, 0); + + // Enter low power mode. + LOG_INFO("Issue WFI to enter sleep"); + wait_for_interrupt(); + + } else if (pwrmgr_testutils_is_wakeup_reason( + &pwrmgr, kDifPwrmgrWakeupRequestSourceFive)) { + LOG_INFO("Wakeup reset"); + + CHECK(rstmgr_testutils_is_reset_info(&rstmgr, + kDifRstmgrResetInfoLowPowerExit)); + LOG_INFO("Aon timer wakeup detected"); + rstmgr_testutils_post_reset(&rstmgr, kDifRstmgrResetInfoLowPowerExit, 0, 0, + 0, 0); + + // add another 2ms to give more time to pwm pulses sequences + busy_spin_micros(2 * 1000); + + return true; + } else { + dif_pwrmgr_wakeup_reason_t wakeup_reason; + CHECK_DIF_OK(dif_pwrmgr_wakeup_reason_get(&pwrmgr, &wakeup_reason)); + LOG_ERROR("Unexpected wakeup detected: type = %d, request_source = %d", + wakeup_reason.types, wakeup_reason.request_sources); + return false; + } + + return false; +}