Skip to content

Commit

Permalink
[sival,clkmgr] Add test for chip_sw_clkmgr_jitter_cycle_measurements …
Browse files Browse the repository at this point in the history
…testpoint

Fixes lowRISC#20230

Signed-off-by: Guillermo Maturana <[email protected]>
  • Loading branch information
matutem committed Nov 7, 2023
1 parent 7551807 commit a30023b
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 19 deletions.
9 changes: 4 additions & 5 deletions hw/top_earlgrey/data/ip/chip_clkmgr_testplan.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,9 @@
{
name: chip_sw_clkmgr_jitter_cycle_measurements
desc: '''Verify jitter via clock cycle measurements after calibration.
The clock count thresholds should need to be set wider than when jitter is disabled.
The clock count thresholds for main clk need to be set wider than when jitter is disabled.
SiVal: This is only useful on real silicon.
Can be done after clock calibration.
This test can use chip_sw_ast_clk_outputs with an option to turn jitter on.
Should be done after clock calibration.
'''
stage: V3
si_stage: SV3
Expand All @@ -252,8 +251,8 @@
"CLKMGR.MEAS_CTRL.MAIN",
"CLKMGR.MEAS_CTRL.USB",
]
tests: []
bazel: []
tests: ["chip_sw_clkmgr_jitter_frequency"]
bazel: ["//sw/device/tests:clkmgr_jitter_frequency_test_fpga_cw310_test_rom"]
}
{
name: chip_sw_clkmgr_extended_range
Expand Down
6 changes: 6 additions & 0 deletions hw/top_earlgrey/dv/chip_sim_cfg.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -1728,6 +1728,12 @@
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+calibrate_usb_clk=1"]
}
{
name: chip_sw_clkmgr_jitter_frequency
uvm_test_seq: chip_sw_base_vseq
sw_images: ["//sw/device/tests:clkmgr_jitter_frequency_test:1:new_rules"]
en_run_modes: ["sw_test_mode_test_rom"]
}
{
name: chip_sw_clkmgr_jitter
uvm_test_seq: chip_sw_base_vseq
Expand Down
32 changes: 18 additions & 14 deletions sw/device/lib/testing/clkmgr_testutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,14 @@ static expected_count_info_t kNoJitterCountInfos[kDifClkmgrMeasureClockUsb + 1];
static expected_count_info_t kJitterCountInfos[kDifClkmgrMeasureClockUsb + 1];

// The expected variability as a percentage. The AST guarantees 3% for all
// clocks, including the AON, so this sets the effective variability to 5%.
// clocks, including the AON, so the effective variability is set to 5%.
static uint32_t kVariabilityPercentage = 5;

// The expected variability when jitter is enabled as a percentage. The AST
// guarantees 10% for jittery clocks and 3% for the AON clock, so the
// effective variability is set to 12%.
static uint32_t kJitterVariabilityPercentage = 12;

// Compute the variability for a given number of cycles, adding an extra cycle
// for synchronizers.
static inline uint32_t get_count_variability(uint32_t cycles,
Expand Down Expand Up @@ -104,23 +109,22 @@ void initialize_expected_counts(void) {
.variability = get_count_variability(
kDeviceUsbCount, kVariabilityPercentage)};

// If jitter is enabled the low threshold should be up to 20% lower, so
// the variability is set to 0.1 * max_count, and count as max - 0.1 * max.
// When jitter is enabled only the main clk is affected: the low threshold
// should be up to 20% lower, so the expected count is set to 0.9 max, and
// the variability is set per kJitterVariabilityPercentage.
kJitterCountInfos[kDifClkmgrMeasureClockIo] =
(expected_count_info_t){.count = kDeviceIoCount - kDeviceIoCount / 10,
.variability = kDeviceIoCount / 10};
kJitterCountInfos[kDifClkmgrMeasureClockIoDiv2] = (expected_count_info_t){
.count = kDeviceIoDiv2Count - kDeviceIoDiv2Count / 10,
.variability = kDeviceIoDiv2Count / 10};
kJitterCountInfos[kDifClkmgrMeasureClockIoDiv4] = (expected_count_info_t){
.count = kDeviceIoDiv4Count - kDeviceIoDiv4Count / 10,
.variability = kDeviceIoDiv4Count};
kNoJitterCountInfos[kDifClkmgrMeasureClockIo];
kJitterCountInfos[kDifClkmgrMeasureClockIoDiv2] =
kNoJitterCountInfos[kDifClkmgrMeasureClockIoDiv2];
kJitterCountInfos[kDifClkmgrMeasureClockIoDiv4] =
kNoJitterCountInfos[kDifClkmgrMeasureClockIoDiv4];
kJitterCountInfos[kDifClkmgrMeasureClockMain] =
(expected_count_info_t){.count = kDeviceCpuCount - kDeviceCpuCount / 10,
.variability = kDeviceCpuCount / 10};
.variability = get_count_variability(
kDeviceCpuCount - kDeviceCpuCount / 10,
kJitterVariabilityPercentage)};
kJitterCountInfos[kDifClkmgrMeasureClockUsb] =
(expected_count_info_t){.count = kDeviceUsbCount - kDeviceUsbCount / 10,
.variability = kDeviceUsbCount / 10};
kNoJitterCountInfos[kDifClkmgrMeasureClockUsb];
}

const char *clkmgr_testutils_measurement_name(
Expand Down
20 changes: 20 additions & 0 deletions sw/device/tests/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,26 @@ opentitan_test(
],
)

opentitan_test(
name = "clkmgr_jitter_frequency_test",
srcs = ["clkmgr_jitter_frequency_test.c"],
exec_env = EARLGREY_TEST_ENVS,
deps = [
"//hw/top_earlgrey/sw/autogen:top_earlgrey",
"//sw/device/lib/base:memory",
"//sw/device/lib/dif:base",
"//sw/device/lib/dif:clkmgr",
"//sw/device/lib/dif:pwrmgr",
"//sw/device/lib/dif:sensor_ctrl",
"//sw/device/lib/testing:aon_timer_testutils",
"//sw/device/lib/testing:clkmgr_testutils",
"//sw/device/lib/testing:isr_testutils",
"//sw/device/lib/testing:pwrmgr_testutils",
"//sw/device/lib/testing:sensor_ctrl_testutils",
"//sw/device/lib/testing/test_framework:ottf_main",
],
)

opentitan_test(
name = "clkmgr_jitter_test",
srcs = ["clkmgr_jitter_test.c"],
Expand Down
108 changes: 108 additions & 0 deletions sw/device/tests/clkmgr_jitter_frequency_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#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/clkmgr_testutils.h"
#include "sw/device/lib/testing/pwrmgr_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"

#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
#include "sw/device/lib/testing/autogen/isr_testutils.h"

OTTF_DEFINE_TEST_CONFIG();

/**
* This test measure clock counts with clkmgr frequency measurements and with
* jitter enabled, performing 100 measurements per round. Measurement errors
* (fast or slow clocks) are recorded as recoverable error in clkmgr.
*
* This assumes clocks have been calibrated:
* - for silicon validation this means clocks are calibrated, which means SV1
* tasks are completed
* - for simulation it requires overriding the hardware behavior via plusargs
* so it runs with calibrated USB clock, or the USB clock frequency will be
* incorrect.
*/
enum {
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 = kTopEarlgreyPlicTargetIbex0};

static pwrmgr_isr_ctx_t pwrmgr_isr_ctx = {
.pwrmgr = &pwrmgr,
.plic_pwrmgr_start_irq_id = kTopEarlgreyPlicIrqIdPwrmgrAonWakeup,
.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_earlgrey_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 == kTopEarlgreyPlicPeripheralPwrmgrAon,
"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;

uint32_t delay_micros = 0;
CHECK_STATUS_OK(aon_timer_testutils_get_us_from_aon_cycles(
kMeasurementsPerRound, &delay_micros));

// 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_EARLGREY_CLKMGR_AON_BASE_ADDR), &clkmgr));
CHECK_DIF_OK(dif_sensor_ctrl_init(
mmio_region_from_addr(TOP_EARLGREY_SENSOR_CTRL_AON_BASE_ADDR),
&sensor_ctrl));
CHECK_DIF_OK(dif_pwrmgr_init(
mmio_region_from_addr(TOP_EARLGREY_PWRMGR_AON_BASE_ADDR), &pwrmgr));
CHECK_DIF_OK(dif_rv_plic_init(
mmio_region_from_addr(TOP_EARLGREY_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(UNWRAP(pwrmgr_testutils_is_wakeup_reason(&pwrmgr, 0)) == true);

CHECK_STATUS_OK(clkmgr_testutils_enable_clock_counts_with_expected_thresholds(
&clkmgr, /*jitter_enabled=*/true, /*external_clk=*/false,
/*low_speed=*/false));
busy_spin_micros(delay_micros);

// check results
CHECK_STATUS_OK(clkmgr_testutils_check_measurement_counts(&clkmgr));
CHECK_STATUS_OK(clkmgr_testutils_disable_clock_counts(&clkmgr));

CHECK(!isr_entered);

return true;
}

0 comments on commit a30023b

Please sign in to comment.