#include "platform.h"

//#define NESTED_VPLIC_COMPLETE_INTERRUPT(irq)
//do {
//  *(volatile unsigned int *)(NDS_PLIC_BASE +PLIC_CLAIM_OFFSET +(0 << PLIC_CLAIM_SHIFT_PER_TARGET)) = irq;
//  __asm volatile("fence io, io");
//} while(0)


#define NESTED_VPLIC_COMPLETE_INTERRUPT(irq)            \
do {                                                    \
    *(volatile unsigned int *)(NDS_PLIC_BASE +PLIC_CLAIM_OFFSET +(0 << PLIC_CLAIM_SHIFT_PER_TARGET)) = irq; \
} while(0)


void default_irq_handler(void)
{
}

void wdog_irq_handler(void)         __attribute__((weak, alias("default_irq_handler")));
void pmu_irq_handler(void)          __attribute__((weak, alias("default_irq_handler")));
void lradc_irq_handler(void)        __attribute__((weak, alias("default_irq_handler")));
void adui_irq_handler(void)         __attribute__((weak, alias("default_irq_handler")));
void udsp_irq_handler(void)         __attribute__((weak, alias("default_irq_handler")));
void npu_tab_irq_handler(void)      __attribute__((weak, alias("default_irq_handler")));
void npu_res_irq_handler(void)      __attribute__((weak, alias("default_irq_handler")));
void timer0_irq_handler(void)       __attribute__((weak, alias("default_irq_handler")));
void timer1_irq_handler(void)       __attribute__((weak, alias("default_irq_handler")));
void timer2_irq_handler(void)       __attribute__((weak, alias("default_irq_handler")));
void timer3_irq_handler(void)       __attribute__((weak, alias("default_irq_handler")));
void capture0_irq_handler(void)     __attribute__((weak, alias("default_irq_handler")));
void capture1_irq_handler(void)     __attribute__((weak, alias("default_irq_handler")));
void capture2_irq_handler(void)     __attribute__((weak, alias("default_irq_handler")));
void capture3_irq_handler(void)     __attribute__((weak, alias("default_irq_handler")));
void irrx_irq_handler(void)         __attribute__((weak, alias("default_irq_handler")));
void irtx_irq_handler(void)         __attribute__((weak, alias("default_irq_handler")));
void spi0_irq_handler(void)         __attribute__((weak, alias("default_irq_handler")));
void spi1_irq_handler(void)         __attribute__((weak, alias("default_irq_handler")));
void sdc_irq_handler(void)          __attribute__((weak, alias("default_irq_handler")));
void adc_irq_handler(void)          __attribute__((weak, alias("default_irq_handler")));
void dac_irq_handler(void)          __attribute__((weak, alias("default_irq_handler")));
void src_irq_handler(void)          __attribute__((weak, alias("default_irq_handler")));
void dma_irq_handler(void)         __attribute__((weak, alias("default_irq_handler")));
void mmu_irq_handler(void)         __attribute__((weak, alias("default_irq_handler")));
void norc_irq_handler(void)         __attribute__((weak, alias("default_irq_handler")));
void uart0_irq_handler(void)        __attribute__((weak, alias("default_irq_handler")));
void uart1_irq_handler(void)        __attribute__((weak, alias("default_irq_handler")));
void uart2_irq_handler(void)        __attribute__((weak, alias("default_irq_handler")));
void i2c0_irq_handler(void)         __attribute__((weak, alias("default_irq_handler")));
void i2c1_irq_handler(void)         __attribute__((weak, alias("default_irq_handler")));
void asi0_irq_handler(void)         __attribute__((weak, alias("default_irq_handler")));
void asi1_irq_handler(void)         __attribute__((weak, alias("default_irq_handler")));
void usb_mac_irq_handler(void)      __attribute__((weak, alias("default_irq_handler")));
void usb_dma_irq_handler(void)      __attribute__((weak, alias("default_irq_handler")));
void gpio0_irq_handler(void)        __attribute__((weak, alias("default_irq_handler")));
void gpio1_irq_handler(void)        __attribute__((weak, alias("default_irq_handler")));
void pwm_irq_handler(void)          __attribute__((weak, alias("default_irq_handler")));
void camera_irq_handler(void)       __attribute__((weak, alias("default_irq_handler")));
void uart3_irq_handler(void)        __attribute__((weak, alias("default_irq_handler")));
void psram_irq_handler(void)        __attribute__((weak, alias("default_irq_handler")));
void mpu_irq_handler(void)          __attribute__((weak, alias("default_irq_handler")));

void __attribute__((interrupt)) wdog_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    wdog_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_WDOG);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) pmu_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    pmu_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_PMU);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) lradc_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    lradc_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_LRADC);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) adui_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    adui_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_ADUI);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) udsp_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    udsp_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_UDSP);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) npu_tab_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    npu_tab_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_NPU_TAB);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) npu_res_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    npu_res_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_NPU_RES);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) timer0_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    timer0_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_TIMER0);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) timer1_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    timer1_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_TIMER1);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) timer2_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    timer2_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_TIMER2);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) timer3_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    timer3_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_TIMER3);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) capture0_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    capture0_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_CAPTURE0);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) capture1_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    capture1_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_CAPTURE1);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) capture2_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    capture2_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_CAPTURE2);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) capture3_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    capture3_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_CAPTURE3);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) irrx_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    irrx_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_IRRX);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) irtx_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    irtx_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_IRTX);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) spi0_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    spi0_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_SPI0);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) spi1_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    spi1_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_SPI1);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) sdc_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    sdc_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_SDC);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) adc_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    adc_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_ADC);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) dac_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    dac_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_DAC);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) src_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    src_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_SRC);
    NESTED_IRQ_EXIT();
}

__ILM void __attribute__((interrupt)) dma_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    dma_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_DMA);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) mmu_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    mmu_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_MMU);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) norc_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    norc_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_NORC);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) uart0_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    uart0_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_UART0);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) uart1_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    uart1_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_UART1);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) uart2_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    uart2_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_UART2);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) i2c0_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    i2c0_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_I2C0);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) i2c1_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    i2c1_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_I2C1);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) asi0_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    asi0_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_ASI0);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) asi1_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    asi1_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_ASI1);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) usb_mac_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    usb_mac_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_USB_MAC);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) usb_dma_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    usb_dma_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_USB_DMA);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) gpio0_irq_entry(void)
{
	NESTED_IRQ_ENTER();
    gpio0_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_GPIO0);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) gpio1_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    gpio1_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_GPIO1);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) pwm_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    pwm_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_PWM);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) camera_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    camera_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_CAMERA);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) uart3_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    uart3_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_UART3);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) psram_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    psram_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_PSRAM);
    NESTED_IRQ_EXIT();
}

void __attribute__((interrupt)) mpu_irq_entry(void)
{
    NESTED_IRQ_ENTER();
    mpu_irq_handler();
    NESTED_VPLIC_COMPLETE_INTERRUPT(IRQ_SOURCE_MPU);
    NESTED_IRQ_EXIT();
}

