14 #include "sw/device/lib/runtime/irq.h"
16 #include "sw/device/lib/testing/rv_core_ibex_testutils.h"
17 #include "sw/device/lib/testing/test_framework/check.h"
20 #include "hw/top_darjeeling/sw/autogen/top_darjeeling.h"
23 OTTF_DEFINE_TEST_CONFIG();
27 kIrqVoid = UINT32_MAX,
30 static dif_rv_core_ibex_t rv_core_ibex;
31 static dif_sram_ctrl_t sram_ctrl_mbox;
32 static dif_rv_plic_t rv_plic;
34 static dif_mbx_t mbx[kDtMbxCount];
40 typedef enum mbx_txn_state {
42 kStateWaitingForRequest = 1,
43 kStateReceivedRequest = 2,
44 kStateGeneratingResponse = 3,
45 kStateWaitingForResponseDrained = 4,
50 dif_mbx_irq_state_snapshot_t irq_state;
52 mbx_txn_state_t txn_state;
53 dif_mbx_irq_t mbx_irq_serviced;
57 static volatile bool is_finished =
false;
60 static const dif_mbx_irq_t mbx_irq_ids[] = {
61 kDtMbxIrqMbxReady, kDtMbxIrqMbxAbort, kDtMbxIrqMbxError};
64 kSoftwareBarrierTimeoutUsec = 100,
67 static volatile const uint8_t kSoftwareBarrier = 0;
68 static volatile const uint8_t kNumTxns = 0;
74 static void increment_array_uint32(uint32_t *arr, uint32_t size) {
75 for (
size_t i = 0; i < size; ++i) {
85 kSramCtrlMbxSize = TOP_DARJEELING_SRAM_CTRL_MBOX_RAM_SIZE_BYTES,
91 kDtMbxCount * (kMbxSizeDWORDS * 2) <= kSramCtrlMbxSize /
sizeof(uint32_t),
92 "As specified, the mailbox memories cannot fit in the backing SRAM!");
96 static uint32_t data_dwords[kDtMbxCount][kMbxSizeDWORDS];
104 void configure_mbx_peripherals(
void) {
105 uint32_t mbx_size_bytes = kMbxSizeDWORDS *
sizeof(uint32_t);
107 for (dt_mbx_t mbx_idx = 0; mbx_idx < kDtMbxCount; mbx_idx++) {
108 uint32_t sram_start =
109 dt_sram_ctrl_reg_block(kDtSramCtrlMbox, kDtSramCtrlRegBlockRam);
110 uint32_t mbx_region_base = sram_start + (mbx_size_bytes * 2 * mbx_idx);
113 .imbx_base_addr = mbx_region_base,
115 mbx_region_base + mbx_size_bytes -
sizeof(uint32_t),
116 .ombx_base_addr = mbx_region_base + mbx_size_bytes,
118 mbx_region_base + (mbx_size_bytes * 2) -
sizeof(uint32_t),
131 mmio_region_write32(mbx[mbx_idx].base_addr, MBX_CONTROL_REG_OFFSET, 0);
138 static void init_global_state(
void) {
139 for (dt_mbx_t mbx_idx = 0; mbx_idx < kDtMbxCount; mbx_idx++) {
141 txn[mbx_idx].data_dwords = data_dwords[mbx_idx];
143 dif_mbx_irq_state_snapshot_t snapshot;
144 CHECK_DIF_OK(dif_mbx_irq_get_state(&mbx[mbx_idx], &snapshot));
146 "No interrupts should be pending yet! (mbx[%0d].snapshot = 0x%0x)",
149 handler_state[mbx_idx] =
151 .irq_state = snapshot,
152 .txn = &txn[mbx_idx],
153 .txn_state = kStateIdle,
154 .mbx_irq_serviced = kIrqVoid,
155 .plic_irq_serviced = kIrqVoid};
166 static void init_peripherals(
void) {
167 CHECK_DIF_OK(dif_rv_core_ibex_init_from_dt(kDtRvCoreIbex, &rv_core_ibex));
168 CHECK_DIF_OK(dif_rv_plic_init_from_dt(kDtRvPlic, &rv_plic));
169 CHECK_DIF_OK(dif_sram_ctrl_init_from_dt(kDtSramCtrlMbox, &sram_ctrl_mbox));
171 for (dt_mbx_t mbx_idx = 0; mbx_idx < kDtMbxCount; mbx_idx++) {
172 CHECK_DIF_OK(dif_mbx_init_from_dt(mbx_idx, &mbx[mbx_idx]));
183 static void init_interrupts(
void) {
184 irq_global_ctrl(
false);
185 irq_external_ctrl(
false);
193 for (dt_mbx_t mbx_idx = 0; mbx_idx < kDtMbxCount; mbx_idx++) {
194 for (
int i = 0; i <
ARRAYSIZE(mbx_irq_ids); i++) {
195 dt_plic_irq_id_t plic_id = dt_mbx_irq_to_plic_id(mbx_idx, mbx_irq_ids[i]);
201 CHECK_DIF_OK(dif_mbx_irq_set_enabled(&mbx[mbx_idx], mbx_irq_ids[i],
206 irq_external_ctrl(
true);
207 irq_global_ctrl(
true);
220 static status_t external_isr(
void) {
230 dt_instance_id_t inst_id = dt_plic_id_to_instance_id(plic_irq_id);
231 dt_device_type_t
device_type = dt_device_type(inst_id);
233 "got an irq from a plic_peripheral that is not a mailbox!");
235 dt_mbx_t mbx = dt_mbx_from_instance_id(inst_id);
236 dif_mbx_irq_t mbx_irq_id = dt_mbx_irq_from_plic_id(mbx, plic_irq_id);
238 mbxths = &handler_state[mbx];
239 mbxths->mbx_irq_serviced = mbx_irq_id;
240 mbxths->plic_irq_serviced = plic_irq_id;
243 switch (mbx_irq_id) {
244 case kDtMbxIrqMbxReady: {
251 CHECK_DIF_OK(dif_mbx_irq_set_enabled(
257 mbxths->txn->nr_dwords = kMbxSizeDWORDS;
260 mbxths->txn_state = kStateReceivedRequest;
264 case kDtMbxIrqMbxAbort: {
265 CHECK(
false,
"Saw kDtMbxIrqMbxAbort, should not occur in this test!");
268 case kDtMbxIrqMbxError: {
269 CHECK(
false,
"Saw kDtMbxIrqMbxError, should not occur in this test!");
273 CHECK(
false,
"Invalid mbx_irq_id: %d", mbx_irq_id);
287 dif_mbx_irq_get_type(mbxths->mbx, mbxths->mbx_irq_serviced, &type));
290 dif_mbx_irq_acknowledge(mbxths->mbx, mbxths->mbx_irq_serviced));
302 static volatile status_t isr_result;
304 void ottf_external_isr(
void) {
306 if (status_ok(isr_result)) {
330 mbxths->txn_state = kStateGeneratingResponse;
334 increment_array_uint32(mbxths->txn->data_dwords, mbxths->txn->nr_dwords);
337 mbxths->txn_state = kStateWaitingForResponseDrained;
348 mbxths->txn_state = kStateCleaningUp;
350 CHECK_DIF_OK(dif_mbx_irq_acknowledge(mbxths->mbx, kDtMbxIrqMbxReady));
354 CHECK_DIF_OK(dif_mbx_irq_set_enabled(mbxths->mbx, mbxths->mbx_irq_serviced,
357 mbxths->mbx_irq_serviced = kIrqVoid;
358 mbxths->plic_irq_serviced = kIrqVoid;
359 mbxths->txn_state = kStateIdle;
364 configure_mbx_peripherals();
372 IBEX_SPIN_FOR(kSoftwareBarrier == 1, kSoftwareBarrierTimeoutUsec);
373 size_t numTxns = kNumTxns;
374 LOG_INFO(
"sw will await %0d transactions before ending the test.", numTxns);
380 for (
size_t i = 0; i < numTxns; ++i) {
382 bool got_mbx_id =
false;
386 ATOMIC_WAIT_FOR_INTERRUPT(is_finished);
389 for (dt_mbx_t mbx = 0; mbx < kDtMbxCount; mbx++) {
390 if (handler_state[mbx].txn_state == kStateReceivedRequest) {
396 "After ISR set 'is_finished', multiple mbx's had received "
404 CHECK(got_mbx_id,
"Something went wrong. Aborting test.");
412 LOG_INFO(
"Test sw responding to pending request in mbx[%0d]", mbx_id);
413 responder_mbx_transaction(&handler_state[mbx_id]);