// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

${autogen_banner}

#include "sw/device/lib/testing/autogen/isr_testutils.h"
#include "sw/device/lib/dif/dif_base.h"

#include "sw/device/lib/dif/dif_rv_plic.h"
% for ip in ips_with_difs:
  % if ip.irqs:
    #include "sw/device/lib/dif/dif_${ip.name_snake}.h"
  % endif
% endfor
#include "sw/device/lib/testing/test_framework/check.h"

#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" // Generated.

% for ip in ips_with_difs:
  % if ip.irqs:
    void isr_testutils_${ip.name_snake}_isr(
      plic_isr_ctx_t plic_ctx,
      ${ip.name_snake}_isr_ctx_t ${ip.name_snake}_ctx,
      top_earlgrey_plic_peripheral_t *peripheral_serviced,
      dif_${ip.name_snake}_irq_t *irq_serviced) {

      // Claim the IRQ at the PLIC.
      dif_rv_plic_irq_id_t plic_irq_id;
      CHECK_DIF_OK(dif_rv_plic_irq_claim(
        plic_ctx.rv_plic,
        plic_ctx.hart_id,
        &plic_irq_id));

      // Get the peripheral the IRQ belongs to.
      *peripheral_serviced = (top_earlgrey_plic_peripheral_t)
        top_earlgrey_plic_interrupt_for_peripheral[plic_irq_id];

      // Get the IRQ that was fired from the PLIC IRQ ID.
      dif_${ip.name_snake}_irq_t irq = (dif_${ip.name_snake}_irq_t)(plic_irq_id -
        ${ip.name_snake}_ctx.plic_${ip.name_snake}_start_irq_id);
      *irq_serviced = irq;

      // Check if it is supposed to be the only IRQ fired.
      if (${ip.name_snake}_ctx.is_only_irq) {
        dif_${ip.name_snake}_irq_state_snapshot_t snapshot;
        CHECK_DIF_OK(dif_${ip.name_snake}_irq_get_state(
          ${ip.name_snake}_ctx.${ip.name_snake},
        % if ip.name_snake == "rv_timer":
          plic_ctx.hart_id,
        % endif
          &snapshot));
        CHECK(snapshot == (dif_${ip.name_snake}_irq_state_snapshot_t)(1 << irq),
          "Only ${ip.name_snake} IRQ %d expected to fire. Actual IRQ state = %x",
          irq, snapshot);
      }

    % if ip.name_snake == "adc_ctrl":
      // TODO(lowRISC/opentitan:#11354): future releases of the ADC Controller HW should hide
      // the need to also clear the cause CSRs. At which point, this can be removed.
      CHECK_DIF_OK(dif_${ip.name_snake}_irq_clear_causes(
          ${ip.name_snake}_ctx.${ip.name_snake},
          kDifAdcCtrlIrqCauseAll));
    % endif

      // Acknowledge the IRQ at the peripheral if IRQ is of the event type.
      dif_irq_type_t type;
      CHECK_DIF_OK(dif_${ip.name_snake}_irq_get_type(
          ${ip.name_snake}_ctx.${ip.name_snake}, irq, &type));
      if (type == kDifIrqTypeEvent) {
        CHECK_DIF_OK(dif_${ip.name_snake}_irq_acknowledge(
            ${ip.name_snake}_ctx.${ip.name_snake},
            irq));
      }

      // Complete the IRQ at the PLIC.
      CHECK_DIF_OK(dif_rv_plic_irq_complete(
          plic_ctx.rv_plic,
          plic_ctx.hart_id,
          plic_irq_id));
    }

  % endif
% endfor
