blob: 9c06d36afb44f68201aebe117030ea2da370d91c [file] [log] [blame]
// 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/base/mmio.h"
#include "sw/device/lib/dif/dif_edn.h"
#include "sw/device/lib/dif/dif_rv_core_ibex.h"
#include "sw/device/lib/runtime/ibex.h"
#include "sw/device/lib/runtime/log.h"
#include "sw/device/lib/testing/entropy_testutils.h"
#include "sw/device/lib/testing/rv_core_ibex_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 "rv_core_ibex_regs.h"
// Initialize OTTF.
OTTF_DEFINE_TEST_CONFIG();
// Declare two assembly function defined in `rv_core_ibex_rnd_test.S`.
extern volatile uint32_t rv_core_ibex_rnd_read_and_immediately_check_status();
extern volatile uint32_t
rv_core_ibex_check_rnd_read_possible_while_status_invalid();
#define RANDOM_DATA_READS 32
#define MAX_STATUS_CHECKS 1024
bool test_main(void) {
// Verify the functionality of the random number generation CSRs.
// Enable entropy complex, CSRNG and EDN so Ibex can get entropy.
// No code is necessary for this because EDN0 is automatically initialized
// by the ROM.
// Initialize Ibex.
dif_rv_core_ibex_t rv_core_ibex;
CHECK_DIF_OK(dif_rv_core_ibex_init(
mmio_region_from_addr(TOP_EARLGREY_RV_CORE_IBEX_CFG_BASE_ADDR),
&rv_core_ibex));
// Perform multiple reads from `RND_DATA` polling `RND_STATUS` in between to
// only read valid data. Check different random bits are provided each time
// and that the random data is never zero or all ones.
uint32_t rnd_data;
uint32_t previous_rnd_data = 0;
for (int i = 0; i < RANDOM_DATA_READS; i++) {
rnd_data =
rv_core_ibex_testutils_get_rnd_data(&rv_core_ibex, MAX_STATUS_CHECKS);
CHECK(rnd_data != previous_rnd_data);
previous_rnd_data = rnd_data;
}
// Ensure `RND_STATUS` indicate invalid data immediately after `RND_DATA`
// read.
CHECK(rv_core_ibex_rnd_read_and_immediately_check_status() == 0);
// Perform repeated reads from `RND_DATA` without `RND_STATUS` polling to
// check read when invalid doesn't block.
for (int i = 0; i < RANDOM_DATA_READS; i++) {
CHECK_DIF_OK(dif_rv_core_ibex_read_rnd_data(&rv_core_ibex, &rnd_data));
}
// Check to see that we can really do an RND while status is invalid before
// and after.
IBEX_SPIN_FOR(rv_core_ibex_testutils_is_rnd_data_valid(&rv_core_ibex),
MAX_STATUS_CHECKS);
uint32_t status_value =
rv_core_ibex_check_rnd_read_possible_while_status_invalid();
CHECK(status_value == 0);
return true;
}