blob: 85ec17c02c23acb05bab954d0279ed6211a1a57e [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#ifndef OPENTITAN_SW_DEVICE_LIB_TESTING_RAND_TESTUTILS_H_
#define OPENTITAN_SW_DEVICE_LIB_TESTING_RAND_TESTUTILS_H_
#include <stdint.h>
#include "sw/device/lib/testing/rv_core_ibex_testutils.h"
/**
* A random number generator testutil type.
*
* Provides ability to control and maintain a random number generator. A random
* number is produced via a mix of hardware-based (using on-device entropy
* from rv_core_ibex random registers) and software-based (an LFSR-based PRNG)
* approaches. The initial seed value for the PRNG is fetched from the
* hardware. Following that, the PRNG kicks in and supplies random values
* sought by the test. After a number of PRNG cycles, the LFSR can be freshly
* reseeded from the hardware. If this frequency is set to 0, then the PRNG is
* rendered disabled and random data is always fetched from the hardware.
*
* The software PRNG is faster because it consumes very few cycles compared to
* the hardware - it helps improve the simulation time.
*/
typedef struct rand_testutils_rng {
/**
* An rv_core_ibex DIF handle.
*/
dif_rv_core_ibex_t *rv_core_ibex;
/**
* The timeout in microseconds for fetching data from the hardware.
*/
uint32_t entropy_fetch_timeout_usec;
/**
* The PRNG LFSR.
*/
uint32_t lfsr;
/**
* The PRNG polynomial co-efficients.
*/
uint32_t polynomial_coefficients;
/**
* The PRNG LFSR reseed frequency.
*/
uint32_t reseed_frequency;
/**
* The LFSR operation counter. Resets on every reseed.
*/
uint32_t op_counter;
} rand_testutils_rng_t;
/**
* A global random number generator testutil handle.
*/
extern rand_testutils_rng_t rand_testutils_rng_ctx;
/**
* Initializes and returns a random number generator testutil handle.
*
* @param rv_core_ibex An rv_core_ibex DIF handle.
* @return The initialized timeout value.
*/
rand_testutils_rng_t rand_testutils_init(dif_rv_core_ibex_t *rv_core_ibex);
/**
* Reseeds the PRNG LFSR.
*
* The LFSR value is updated later, when the caller fetches the next random
* data.
*
* Uses the global random number generator testutil handle
* `rand_testutils_rng_ctx` which is initialized in ottf_main().
*/
inline void rand_testutils_reseed(void) {
rand_testutils_rng_ctx.op_counter = UINT32_MAX;
}
/**
* Returns a random unsigned integer.
*
* The random number is sourced either from the LFSR-based PRNG or from the
* hardware, depending on the lobal random number generator testutil context
* settings.
* @return A pseudo-random 32-bit value.
*/
uint32_t rand_testutils_gen32(void);
/**
* Returns a random unsigned integer within a given range.
*
* This function invokes `rand_testutils_gen32()` and restricts the returned
* value to be within the supplied range, inclusive of the range limits. Note
* that a uniform distribution of values within the given range is not
* guaranteed.
* @param min The lower limit of the range.
* @param max The upper limit of the range.
* @return The computed random value within the supplied range.
*/
uint32_t rand_testutils_gen32_range(uint32_t min, uint32_t max);
/** Shuffles an arbitrary array of elements.
*
* The shuffling occurs in-place. The reseeding of the LFSR is temporarily
* turned off to allow faster runtime performance.
* @param array Pointer to the array being shuffled.
* @param size The size of each element in the array.
* @param length The number of elements in the array.
*/
void rand_testutils_shuffle(void *array, size_t size, size_t length);
#endif // OPENTITAN_SW_DEVICE_LIB_TESTING_RAND_TESTUTILS_H_