10 #include "sw/device/lib/runtime/irq.h"
12 #include "sw/device/lib/testing/csrng_testutils.h"
13 #include "sw/device/lib/testing/entropy_testutils.h"
15 #include "sw/device/lib/testing/rand_testutils.h"
16 #include "sw/device/lib/testing/rv_plic_testutils.h"
17 #include "sw/device/lib/testing/test_framework/check.h"
19 #include "sw/device/tests/otbn_randomness_impl.h"
22 #include "sw/device/lib/testing/autogen/isr_testutils.h"
24 static dif_csrng_t csrng;
25 static dif_edn_t edn0;
26 static dif_edn_t edn1;
27 static dif_otbn_t otbn;
28 static dif_rv_plic_t plic;
30 OTTF_DEFINE_TEST_CONFIG();
37 kTestParamFifoBufferSize = 12,
41 kTestParamNumIterationsSim = 1,
42 kTestParamNumIterationsOther = 20,
48 typedef enum irq_flag_id {
49 kTestIrqFlagIdCsrngEntropyReq,
50 kTestIrqFlagIdEdn1CmdDone,
51 kTestIrqFlagIdEdn0CmdDone,
59 static volatile bool irq_flags[kTestIrqFlagCount];
64 static void init_peripherals(
void) {
65 CHECK_DIF_OK(dif_csrng_init(
73 CHECK_DIF_OK(dif_rv_plic_init(
80 static void plic_interrupts_enable(
void) {
81 irq_external_ctrl(
false);
82 irq_global_ctrl(
false);
84 for (
size_t i = 0; i < kTestIrqFlagCount; ++i) {
91 for (
size_t i = 0; i <
ARRAYSIZE(irq_ids); ++i) {
101 CHECK_DIF_OK(dif_csrng_irq_set_enabled(&csrng, kDifCsrngIrqCsEntropyReq,
103 CHECK_DIF_OK(dif_edn_irq_set_enabled(&edn0, kDifEdnIrqEdnCmdReqDone,
105 CHECK_DIF_OK(dif_edn_irq_set_enabled(&edn1, kDifEdnIrqEdnCmdReqDone,
108 irq_global_ctrl(
true);
109 irq_external_ctrl(
true);
116 static void irq_block_wait(irq_flag_id_t isr_id) {
117 ATOMIC_WAIT_FOR_INTERRUPT(irq_flags[isr_id]);
119 case kTestIrqFlagIdCsrngEntropyReq:
120 CHECK_DIF_OK(dif_csrng_irq_set_enabled(&csrng, kDifCsrngIrqCsEntropyReq,
123 case kTestIrqFlagIdEdn0CmdDone:
124 CHECK_DIF_OK(dif_edn_irq_set_enabled(&edn0, kDifEdnIrqEdnCmdReqDone,
127 case kTestIrqFlagIdEdn1CmdDone:
128 CHECK_DIF_OK(dif_edn_irq_set_enabled(&edn0, kDifEdnIrqEdnCmdReqDone,
132 CHECK(
false,
"Invalid isr_id: %d", isr_id);
142 static void csrng_generate_output_check(
void) {
143 uint32_t output[kTestParamFifoBufferSize] = {0};
145 csrng_testutils_cmd_generate_run(&csrng, output,
ARRAYSIZE(output)));
147 uint32_t prev_data = 0;
148 for (
size_t i = 0; i <
ARRAYSIZE(output); ++i) {
149 CHECK(prev_data != output[i],
150 "Received duplicate data. Last index: %d, value: 0x%x", i, prev_data);
158 static void test_csrng_sw_entropy_req_interrupt(
160 CHECK_STATUS_OK(entropy_testutils_stop_all());
161 CHECK_STATUS_OK(entropy_testutils_entropy_src_init());
165 CHECK_STATUS_OK(csrng_testutils_cmd_ready_wait(&csrng));
166 plic_interrupts_enable();
169 irq_block_wait(kTestIrqFlagIdCsrngEntropyReq);
170 csrng_generate_output_check();
172 plic_interrupts_enable();
174 irq_block_wait(kTestIrqFlagIdCsrngEntropyReq);
175 csrng_generate_output_check();
177 CHECK_STATUS_OK(csrng_testutils_cmd_status_check(&csrng));
178 CHECK_STATUS_OK(csrng_testutils_recoverable_alerts_check(&csrng));
186 static void edn_ready_wait(
const dif_edn_t *edn) {
193 CHECK(!ack_err,
"Unexpected CSRNG ack error");
207 static void edn_configure(
const dif_edn_t *edn, irq_flag_id_t irq_flag_id,
212 plic_interrupts_enable();
215 irq_block_wait(kTestIrqFlagIdCsrngEntropyReq);
216 irq_block_wait(irq_flag_id);
219 plic_interrupts_enable();
221 irq_block_wait(kTestIrqFlagIdCsrngEntropyReq);
222 irq_block_wait(irq_flag_id);
235 CHECK_STATUS_OK(entropy_testutils_stop_all());
237 CHECK_STATUS_OK(entropy_testutils_entropy_src_init());
240 edn_configure(&edn0, kTestIrqFlagIdEdn0CmdDone, seed_material);
241 edn_configure(&edn1, kTestIrqFlagIdEdn1CmdDone, seed_material);
243 plic_interrupts_enable();
254 const size_t kEdnBlockSizeBits = 128;
255 const size_t kOtbnRequestSizeBits = 256;
256 const size_t kOtbnTestRequestCount =
260 size_t edn1_generated_blocks = 0;
265 edn_ready_wait(&edn0);
266 edn_ready_wait(&edn1);
267 CHECK_STATUS_OK(entropy_testutils_error_check(&csrng, &edn0, &edn1));
270 otbn_randomness_test_start(&otbn, 0);
276 if (irq_flags[kTestIrqFlagIdEdn0CmdDone]) {
277 irq_flags[kTestIrqFlagIdEdn0CmdDone] =
false;
280 if (irq_flags[kTestIrqFlagIdEdn1CmdDone]) {
281 edn1_generated_blocks++;
282 if (edn1_generated_blocks <
283 kOtbnTestRequestCount * kOtbnRequestSizeBits / kEdnBlockSizeBits) {
284 irq_flags[kTestIrqFlagIdEdn1CmdDone] =
false;
292 busy =
status != kDifOtbnStatusIdle &&
status != kDifOtbnStatusLocked;
295 CHECK(otbn_randomness_test_end(&otbn,
false));
300 irq_block_wait(kTestIrqFlagIdEdn1CmdDone);
301 irq_block_wait(kTestIrqFlagIdEdn0CmdDone);
304 plic_interrupts_enable();
306 irq_block_wait(kTestIrqFlagIdEdn0CmdDone);
308 plic_interrupts_enable();
310 irq_block_wait(kTestIrqFlagIdEdn1CmdDone);
312 CHECK_STATUS_OK(csrng_testutils_recoverable_alerts_check(&csrng));
313 CHECK_STATUS_OK(entropy_testutils_error_check(&csrng, &edn0, &edn1));
316 void ottf_external_isr(uint32_t *exc_info) {
330 dif_csrng_irq_t irq =
332 CHECK(irq == kDifCsrngIrqCsEntropyReq,
"Unexpected irq: 0x%x", irq);
333 CHECK_DIF_OK(dif_csrng_irq_acknowledge(&csrng, irq));
334 irq_flags[kTestIrqFlagIdCsrngEntropyReq] =
true;
338 CHECK(irq == kDifEdnIrqEdnCmdReqDone,
"Unexpected irq: 0x%x", irq);
339 CHECK_DIF_OK(dif_edn_irq_acknowledge(&edn0, irq));
340 irq_flags[kTestIrqFlagIdEdn0CmdDone] =
true;
344 CHECK(irq == kDifEdnIrqEdnCmdReqDone,
"Unexpected irq: 0x%x", irq);
345 CHECK_DIF_OK(dif_edn_irq_acknowledge(&edn1, irq));
346 irq_flags[kTestIrqFlagIdEdn1CmdDone] =
true;
368 for (
size_t i = 0; i < edn_seed.
len; ++i) {
369 edn_seed.
data[i] = rand_testutils_gen32();
372 uint32_t num_iterations = kTestParamNumIterationsSim;
374 num_iterations = kTestParamNumIterationsOther;
377 for (
size_t i = 0; i < num_iterations; ++i) {
378 test_csrng_sw_entropy_req_interrupt(&csrng_seed);
379 test_edn_cmd_done(&edn_seed);