blob: 4055abfd1668e608f0a00cc9e1d3cefd5c18f358 [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_TESTS_PLIC_ALL_IRQS_TEST_HELPER_H_
#define OPENTITAN_SW_DEVICE_TESTS_PLIC_ALL_IRQS_TEST_HELPER_H_
/**
* Helper macros used by the auto-generated test ./autogen/plic_all_irqs_test.c
*
* These are not meant to be used in any other tests.
*/
/**
* Handles an IRQ from a peripheral instance.
*/
#define PERIPHERAL_ISR(peripheral, handle, plic_start_irq) \
do { \
/* Correlate the interrupt fired at PLIC with the peripheral. */ \
dif_##peripheral##_irq_t irq = (dif_##peripheral##_irq_t)( \
plic_irq_id - (dif_rv_plic_irq_id_t)plic_start_irq); \
CHECK(irq == peripheral##_irq_expected, \
"Incorrect " #handle " IRQ received at PLIC: exp = %d, obs = %d", \
peripheral##_irq_expected, irq); \
peripheral##_irq_serviced = irq; \
\
/* Check if the same interrupt fired at the peripheral as well. */ \
/* TODO: read the whole status register to confirm none other pending. */ \
bool is_pending; \
CHECK_DIF_OK( \
dif_##peripheral##_irq_is_pending(&handle, irq, &is_pending)); \
CHECK(is_pending, "Interrupt %d fired at PLIC did not fire at " #handle, \
irq); \
\
/* Clear the interrupt at the peripheral. */ \
CHECK_DIF_OK(dif_##peripheral##_irq_acknowledge(&handle, irq)); \
} while (0)
/**
* Initializes the handle to a peripheral instance.
*/
#define PERIPHERAL_INIT(peripheral, handle, base_addr) \
do { \
mmio_region_t addr = mmio_region_from_addr(base_addr); \
CHECK_DIF_OK(dif_##peripheral##_init(addr, &handle)); \
} while (0)
/**
* Initializes the handle to a parameterized peripheral instance.
*/
#define PERIPHERAL_INIT_WITH_PARAMS(peripheral, params, handle, base_addr) \
do { \
mmio_region_t addr = mmio_region_from_addr(base_addr); \
CHECK_DIF_OK(dif_##peripheral##_init(addr, params, &handle)); \
} while (0)
/**
* Clears all previous interrupt invocations.
*/
#define PERIPHERAL_IRQS_CLEAR(handle) \
do { \
/* TODO(#8142): Replace with dif_<ip>_irq_acknowledge_all when available. \
*/ \
mmio_region_write32(handle.base_addr, 0, (uint32_t)ULONG_MAX); \
} while (0)
/**
* Enables all IRQs in the given peripheral instance.
*/
#define PERIPHERAL_IRQS_ENABLE(peripheral, handle) \
do { \
dif_##peripheral##_irq_state_snapshot_t all_irqs = \
(dif_##peripheral##_irq_state_snapshot_t)ULONG_MAX; \
CHECK_DIF_OK(dif_##peripheral##_irq_restore_all(&handle, &all_irqs)); \
} while (0)
/**
* Triggers all IRQs in a peripherals instance one-by-one.
/*/
#define PERIPHERAL_IRQS_TRIGGER(peripheral, handle, plic_peripheral, \
start_irq, end_irq) \
do { \
peripheral_expected = plic_peripheral; \
for (dif_##peripheral##_irq_t irq = start_irq; irq <= end_irq; ++irq) { \
peripheral##_irq_expected = irq; \
LOG_INFO("Triggering " #handle " IRQ %d.", irq); \
CHECK_DIF_OK(dif_##peripheral##_irq_force(&handle, irq)); \
/* NOTE: The interrupt triggered above is instantaneous - Ibex jumps \
* into the ISR even before a WFI can be called. Hence, we do nothing. \
*/ \
CHECK(peripheral##_irq_serviced == irq, \
"Incorrect " #peripheral " irq serviced: exp = %d, obs = %d", irq, \
peripheral##_irq_serviced); \
LOG_INFO("IRQ %d from " #handle " is serviced.", irq); \
} \
} while (0)
#endif // OPENTITAN_SW_DEVICE_TESTS_PLIC_ALL_IRQS_TEST_HELPER_H_