Skip to content

Commit

Permalink
[top/dv] add test chip_sw_uart_tx_rx_alt_clk_freq
Browse files Browse the repository at this point in the history
Extend from chip_sw_uart_rand_baudrate with following added settings.
- Configure LC to RMA state, so that it allows clkmgr to use external clock.
- Configure clkmgr to select external clock.
- Randomize `LOW_SPEED_SEL`, so that uart core clock frequency can be either
  ext_clk_freq / 4 or ext_clk_freq / 2.

Signed-off-by: Weicai Yang <[email protected]>
  • Loading branch information
weicaiyang authored and mcy committed Jan 26, 2022
1 parent d6e9161 commit 961710a
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 21 deletions.
13 changes: 7 additions & 6 deletions hw/top_earlgrey/data/chip_testplan.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,16 @@
}
{
name: chip_sw_uart_tx_rx_alt_clk_freq
desc: '''Verify the transmission of UART while randomizing the core clock frequency.
desc: '''Verify the transmission of UART via using external clock as uart core clock.

Run the chip_uart_tx_rx test with the core clock frequency randomized between known
bounds.

TODO: Find out what the range is for the core clock frequency randomization.
Extend from chip_sw_uart_rand_baudrate with following added settings.
- Configure LC to RMA state, so that it allows clkmgr to use external clock.
- Configure clkmgr to select external clock.
- Randomize `LOW_SPEED_SEL`, so that uart core clock frequency can be either
ext_clk_freq / 4 or ext_clk_freq / 2.
'''
milestone: V1
tests: []
tests: ["chip_sw_uart_tx_rx_alt_clk_freq", "chip_sw_uart_tx_rx_alt_clk_freq_low_speed"]
}

// GPIO (pre-verified IP) integration tests:
Expand Down
16 changes: 16 additions & 0 deletions hw/top_earlgrey/dv/chip_sim_cfg.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,22 @@
en_run_modes: ["sw_test_mode"]
reseed: 20
}
{
name: chip_sw_uart_tx_rx_alt_clk_freq
uvm_test_seq: chip_sw_uart_rand_baudrate_vseq
sw_images: ["sw/device/tests/uart_tx_rx_test:1"]
en_run_modes: ["sw_test_mode"]
run_opts: ["+use_otp_image=LcStRma", "+use_extclk=1"]
reseed: 10
}
{
name: chip_sw_uart_tx_rx_alt_clk_freq_low_speed
uvm_test_seq: chip_sw_uart_rand_baudrate_vseq
sw_images: ["sw/device/tests/uart_tx_rx_test:1"]
en_run_modes: ["sw_test_mode"]
run_opts: ["+use_otp_image=LcStRma", "+use_extclk=1", "extclk_low_speed_sel=1"]
reseed: 10
}
{
name: chip_sw_spi_device_tx_rx
uvm_test_seq: chip_sw_spi_tx_rx_vseq
Expand Down
67 changes: 52 additions & 15 deletions hw/top_earlgrey/dv/env/seq_lib/chip_sw_uart_rand_baudrate_vseq.sv
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

`define CALC_NCO(baud_rate, nco_width, clk_freq_mhz) \
(baud_rate == BaudRate1p5Mbps && clk_freq_mhz == 24) ? 16'hffff : \
(longint'(baud_rate) * (2**(nco_width+4))) / (clk_freq_mhz * 1000_000)
`define CALC_NCO(baud_rate, nco_width, clk_freq_khz) \
(baud_rate == BaudRate1p5Mbps && clk_freq_khz == 24_000) ? 16'hffff : \
(longint'(baud_rate) * (2**(nco_width+4))) / (clk_freq_khz * 1000)

class chip_sw_uart_rand_baudrate_vseq extends chip_sw_uart_tx_rx_vseq;
`uvm_object_utils(chip_sw_uart_rand_baudrate_vseq)
Expand All @@ -13,34 +13,71 @@ class chip_sw_uart_rand_baudrate_vseq extends chip_sw_uart_tx_rx_vseq;

localparam NCO_WIDTH = 16;

rand baud_rate_e baud_rate;
rand int uart_clk_freq_mhz = 24;
// Clkmgr external clock settings
bit use_extclk = 0;
bit extclk_low_speed_sel = 0;

// Use the fixed 24Mhz, override it in extended vseq
constraint uart_clk_freq_mhz_c {
uart_clk_freq_mhz == 24;
}
int uart_clk_freq_khz; // use khz to avoid fractional value

rand baud_rate_e baud_rate;

constraint baud_rate_c {
// constrain nco not over nco width
`CALC_NCO(baud_rate, NCO_WIDTH, uart_clk_freq_mhz) < (1 << NCO_WIDTH);
`CALC_NCO(baud_rate, NCO_WIDTH, uart_clk_freq_khz) < (1 << NCO_WIDTH);
}

function void pre_randomize();
super.pre_randomize();
void'($value$plusargs("use_extclk=%0d", use_extclk));
void'($value$plusargs("extclk_low_speed_sel=%0d", extclk_low_speed_sel));
if (use_extclk) begin
// Uart bus clock is in div4 domain
uart_clk_freq_khz = cfg.clk_freq_mhz * 1000 / 4;

if (extclk_low_speed_sel) uart_clk_freq_khz = uart_clk_freq_khz * 2;
end else begin
// internal uart bus clock is 24Mhz
uart_clk_freq_khz = 24_0000;
end
`uvm_info(`gfn,
$sformatf("External clock freq: %0dmhz, use_extclk: %0d, extclk_low_speed_sel: %0d",
cfg.clk_freq_mhz, use_extclk, extclk_low_speed_sel),
UVM_MEDIUM)
endfunction

virtual task dut_init(string reset_kind = "HARD");
super.dut_init(reset_kind);
cfg.uart_baud_rate = baud_rate;
endtask

virtual task cpu_init();
// sw_symbol_backdoor_overwrite takes an array as the input
bit [7:0] uart_freq[8] = {<< byte {cfg.uart_baud_rate}};
bit [7:0] uart_freq_arr[8] = {<< byte {cfg.uart_baud_rate}};

super.cpu_init();
$display("wcy0 %p", uart_freq);
sw_symbol_backdoor_overwrite("kUartBaudrate", uart_freq);
`uvm_info(`gfn, $sformatf("Configure uart core clk %0d Mhz, baud_rate: %s",
uart_clk_freq_mhz, baud_rate.name), UVM_LOW)
sw_symbol_backdoor_overwrite("kUartBaudrate", uart_freq_arr);
`uvm_info(`gfn, $sformatf("Backdoor_overwrite: configure uart core clk %0d khz, baud_rate: %s",
uart_clk_freq_khz, baud_rate.name), UVM_LOW)

if (use_extclk) begin
bit [7:0] use_extclk_arr[] = {use_extclk};
bit [7:0] low_speed_sel_arr[] = {extclk_low_speed_sel};
bit [7:0] uart_clk_freq_arr[8] = {<< byte {uart_clk_freq_khz * 1000}};

sw_symbol_backdoor_overwrite("kUseExtClk", use_extclk_arr);
`uvm_info(`gfn, $sformatf("Backdoor_overwrite: configure uart use_extclk: %0d", use_extclk),
UVM_LOW)

sw_symbol_backdoor_overwrite("kUseLowSpeedSel", low_speed_sel_arr);
`uvm_info(`gfn, $sformatf("Backdoor_overwrite: configure low_speed_sel: %0d",
extclk_low_speed_sel), UVM_LOW)

// SW relies on kClockFreqPeripheralHz to calcuate NCO and it's hard-coded to 24Mhz in SW.
// this value is changed when extclk is used
sw_symbol_backdoor_overwrite("kClockFreqPeripheralHz", uart_clk_freq_arr);
`uvm_info(`gfn, $sformatf("Backdoor_overwrite: configure uart use_extclk: %0d",
uart_clk_freq_khz), UVM_LOW)
end
endtask

endclass : chip_sw_uart_rand_baudrate_vseq
Expand Down
18 changes: 18 additions & 0 deletions sw/device/lib/dif/dif_clkmgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,21 @@ dif_result_t dif_clkmgr_hintable_clock_get_hint(

return kDifOk;
}

dif_result_t dif_clkmgr_external_clock_set_enabled(const dif_clkmgr_t *clkmgr,
bool is_low_speed) {
uint32_t extclk_ctrl_reg = 0;

if (clkmgr == NULL) {
return kDifBadArg;
}

extclk_ctrl_reg = bitfield_field32_write(
extclk_ctrl_reg, CLKMGR_EXTCLK_CTRL_SEL_FIELD, kMultiBitBool4True);
extclk_ctrl_reg = bitfield_field32_write(
extclk_ctrl_reg, CLKMGR_EXTCLK_CTRL_LOW_SPEED_SEL_FIELD,
is_low_speed ? kMultiBitBool4True : kMultiBitBool4False);
mmio_region_write32(clkmgr->base_addr, CLKMGR_EXTCLK_CTRL_REG_OFFSET,
extclk_ctrl_reg);
return kDifOk;
}
15 changes: 15 additions & 0 deletions sw/device/lib/dif/dif_clkmgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,21 @@ dif_result_t dif_clkmgr_hintable_clock_get_hint(
const dif_clkmgr_t *clkmgr, dif_clkmgr_hintable_clock_t clock,
dif_toggle_t *state);

/**
* Enable chip to use the external clock.
*
* @param clkmgr Clock Manager Handle.
* @param is_low_speed External clock is low speed or high speed.
* High speed - external clock is close to nominal speeds (e.g. external clock
* is 96MHz and nominal frequency is 96MHz-100MHz). Low speed - external clock
* is half of nominal speeds (e.g. external clock is 48MHz and nominal frequency
* is 96MHz-100MHz).
*
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_clkmgr_external_clock_set_enabled(const dif_clkmgr_t *clkmgr,
bool is_low_speed);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
Expand Down
4 changes: 4 additions & 0 deletions sw/device/tests/sim_dv/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,16 @@ uart_tx_rx_test_lib = declare_dependency(
link_with: static_library(
'uart_tx_rx_test_lib',
sources: [
hw_ip_lc_ctrl_reg_h,
hw_ip_clkmgr_reg_h,
# TODO, remove it once pinout configuration is provided
hw_top_earlgrey_pinmux_reg_h,
'uart_tx_rx_test.c'],
dependencies: [
sw_lib_dif_uart,
sw_lib_dif_rv_plic,
sw_lib_dif_lc_ctrl,
sw_lib_dif_clkmgr,
sw_lib_irq,
sw_lib_mmio,
sw_lib_runtime_log,
Expand Down
36 changes: 36 additions & 0 deletions sw/device/tests/sim_dv/uart_tx_rx_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "sw/device/lib/arch/device.h"
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_base.h"
#include "sw/device/lib/dif/dif_clkmgr.h"
#include "sw/device/lib/dif/dif_lc_ctrl.h"
#include "sw/device/lib/dif/dif_rv_plic.h"
#include "sw/device/lib/dif/dif_uart.h"
#include "sw/device/lib/irq.h"
Expand Down Expand Up @@ -65,6 +67,14 @@ typedef enum uart_direction {
*/
static volatile const uint8_t kUartIdx = 0x0;

/**
* Indicates if ext_clk is used and what speed.
*
* Similar to `kUartIdx`, this may be overridden in DV testbench
*/
static volatile const uint8_t kUseExtClk = 0x0;
static volatile const uint8_t kUseLowSpeedSel = 0x0;

// A set of bytes to be send out of TX.
static const uint8_t kUartTxData[UART_DATASET_SIZE] = {
0xe8, 0x50, 0xc6, 0xb4, 0xbe, 0x16, 0xed, 0x55, 0x16, 0x1d, 0xe6, 0x1c,
Expand Down Expand Up @@ -491,6 +501,28 @@ static bool execute_test(const dif_uart_t *uart) {
return true;
}

void config_external_clock(void) {
dif_lc_ctrl_t lc;
dif_clkmgr_t clkmgr;
mmio_region_t lc_ctrl_base_addr =
mmio_region_from_addr(TOP_EARLGREY_LC_CTRL_BASE_ADDR);
mmio_region_t clkmgr_base_addr =
mmio_region_from_addr(TOP_EARLGREY_CLKMGR_AON_BASE_ADDR);

CHECK_DIF_OK(dif_lc_ctrl_init(lc_ctrl_base_addr, &lc));
CHECK_DIF_OK(dif_clkmgr_init(clkmgr_base_addr, &clkmgr));

LOG_INFO("Read and check LC state.");
dif_lc_ctrl_state_t curr_state;
CHECK_DIF_OK(dif_lc_ctrl_get_state(&lc, &curr_state));
CHECK(curr_state == kDifLcCtrlStateRma,
"LC State isn't in kDifLcCtrlStateRma!");

// Enable external clock
LOG_INFO("Configure clkmgr to enable external clock");
CHECK_DIF_OK(dif_clkmgr_external_clock_set_enabled(&clkmgr, kUseLowSpeedSel));
}

const test_config_t kTestConfig;

bool test_main(void) {
Expand All @@ -512,6 +544,10 @@ bool test_main(void) {
kTopEarlgreyPinmuxInselIor11, kTopEarlgreyPinmuxPeripheralInUart3Rx,
kTopEarlgreyPinmuxMioOutIor12, kTopEarlgreyPinmuxOutselUart3Tx);

if (kUseExtClk) {
config_external_clock();
}

// Initialize the UART.
mmio_region_t chosen_uart_region = mmio_region_from_addr(uart_base_addr);
uart_init_with_irqs(chosen_uart_region, &uart);
Expand Down

0 comments on commit 961710a

Please sign in to comment.