Software APIs
rv_core_ibex_rnd_test.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
6 #include "sw/device/lib/dif/dif_rv_core_ibex.h"
9 #include "sw/device/lib/testing/entropy_testutils.h"
10 #include "sw/device/lib/testing/rv_core_ibex_testutils.h"
11 #include "sw/device/lib/testing/test_framework/check.h"
13 
14 #include "rv_core_ibex_regs.h"
15 
16 // Initialize OTTF.
17 OTTF_DEFINE_TEST_CONFIG();
18 
19 // Declare two assembly functions defined in `rv_core_ibex_rnd_test.S`.
20 extern uint32_t rv_core_ibex_rnd_read_and_immediately_check_status(
21  volatile void *);
22 extern uint32_t rv_core_ibex_check_rnd_read_possible_while_status_invalid(
23  volatile void *);
24 
25 enum {
26  kRandomDataReads = 32,
27  kRandomDataReadsSilicon = 500000,
28  kInvalidReadAttempts = 8,
29  // Timeout (in microseconds) when polling random data or the validity of
30  // random data. Can currently take up to 80 ms on the FPGA and up to 2.5 s
31  // in Verilator (in simulated time; empirically determined at the time
32  // of commit) due to the rather slow rate of emulated entropy. In DV, the
33  // emulated entropy rate gets constrained by overriding `rng_srate_value_max`
34  // so that the overall test does not exceed the default timeout of 60 minutes.
35  kTimeoutUsec = 2500000,
36 };
37 
38 bool test_main(void) {
39  // Verify the functionality of the random number generation CSRs.
40 
41  // Enable entropy complex, CSRNG and EDN so Ibex can get entropy.
42  // Configure entropy in auto_mode to avoid starving the system from entropy,
43  // given that boot mode entropy has a limited number of generated bits.
44  CHECK_STATUS_OK(entropy_testutils_auto_mode_init());
45 
46  // Initialize Ibex.
47  dif_rv_core_ibex_t rv_core_ibex;
48  dt_rv_core_ibex_t kRvCoreIbexDt = (dt_rv_core_ibex_t)0;
49  static_assert(kDtRvCoreIbexCount == 1,
50  "This test expects exactly one Ibex core");
51  CHECK_DIF_OK(dif_rv_core_ibex_init_from_dt(kRvCoreIbexDt, &rv_core_ibex));
52 
53  uint32_t data_reads_count = kRandomDataReads;
54  if (kDeviceType == kDeviceSilicon) {
55  data_reads_count = kRandomDataReadsSilicon;
56  }
57 
58  // Perform multiple reads from `RND_DATA` polling `RND_STATUS` in between to
59  // only read valid data. Check different random bits are provided each time
60  // and that the random data is never zero or all ones.
61  uint32_t rnd_data;
62  uint32_t previous_rnd_data = 0;
63  for (int i = 0; i < data_reads_count; i++) {
64  CHECK_STATUS_OK(rv_core_ibex_testutils_get_rnd_data(
65  &rv_core_ibex, kTimeoutUsec, &rnd_data));
66  CHECK(rnd_data != previous_rnd_data);
67  previous_rnd_data = rnd_data;
68  }
69 
70  // Ensure `RND_STATUS` indicate invalid data immediately after `RND_DATA`
71  // read. Make multiple attempts in a loop to avoid icache effects.
72  bool quick_reads_success = true;
73  for (int i = 0; i < kInvalidReadAttempts; ++i) {
74  quick_reads_success &= rv_core_ibex_rnd_read_and_immediately_check_status(
75  rv_core_ibex.base_addr.base);
76  }
77  CHECK(!quick_reads_success);
78 
79  // Perform repeated reads from `RND_DATA` without `RND_STATUS` polling to
80  // check read when invalid doesn't block.
81  for (int i = 0; i < data_reads_count; i++) {
82  CHECK_DIF_OK(dif_rv_core_ibex_read_rnd_data(&rv_core_ibex, &rnd_data));
83  }
84 
85  // Check to see that we can really do an RND while status is invalid before
86  // and after. Also make multiple attempts in a loop to avoid icache effects.
87  IBEX_SPIN_FOR(rv_core_ibex_testutils_is_rnd_data_valid(&rv_core_ibex),
88  kTimeoutUsec);
89  uint32_t status_value = UINT32_MAX;
90  for (int i = 0; i < kInvalidReadAttempts; ++i) {
91  status_value &= rv_core_ibex_check_rnd_read_possible_while_status_invalid(
92  rv_core_ibex.base_addr.base);
93  }
94  CHECK(status_value == 0);
95 
96  return true;
97 }