From 49897ee018b489007c928a4aeb4bab3aecdd2440 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 14 May 2024 10:02:56 +0200 Subject: [PATCH 1/6] software/libbase/isr.c: Cleanup plic_init/isr and move PLIC_EXT_IRQ_BASE to cores/cpu/../irq.h since specific to each CPU. --- litex/soc/cores/cpu/openc906/irq.h | 2 ++ litex/soc/cores/cpu/rocket/irq.h | 2 ++ litex/soc/software/libbase/isr.c | 21 ++++++++++++--------- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/litex/soc/cores/cpu/openc906/irq.h b/litex/soc/cores/cpu/openc906/irq.h index 9d9e4af17..8f4580b13 100644 --- a/litex/soc/cores/cpu/openc906/irq.h +++ b/litex/soc/cores/cpu/openc906/irq.h @@ -18,6 +18,8 @@ extern "C" { #define PLIC_THRSHLD 0x90200000L // Per-pin priority must be >= this to trigger #define PLIC_CLAIM 0x90200004L // Claim & completion register address +#define PLIC_EXT_IRQ_BASE 16 + static inline unsigned int irq_getie(void) { return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0; diff --git a/litex/soc/cores/cpu/rocket/irq.h b/litex/soc/cores/cpu/rocket/irq.h index 9548b01fd..83f854c86 100644 --- a/litex/soc/cores/cpu/rocket/irq.h +++ b/litex/soc/cores/cpu/rocket/irq.h @@ -18,6 +18,8 @@ extern "C" { #define PLIC_THRSHLD 0x0c200000L // Per-pin priority must be >= this to trigger #define PLIC_CLAIM 0x0c200004L // Claim & completion register address +#define PLIC_EXT_IRQ_BASE 1 + static inline unsigned int irq_getie(void) { return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0; diff --git a/litex/soc/software/libbase/isr.c b/litex/soc/software/libbase/isr.c index 98679f831..eb2fe7ae5 100644 --- a/litex/soc/software/libbase/isr.c +++ b/litex/soc/software/libbase/isr.c @@ -30,35 +30,37 @@ void isr(void) } } #elif defined(__rocket__) || defined(__openc906__) -#if defined(__openc906__) -#define PLIC_EXT_IRQ_BASE 16 -#else -#define PLIC_EXT_IRQ_BASE 1 -#endif + +// PLIC initialization. void plic_init(void); void plic_init(void) { int i; - // priorities for first 8 external interrupts + // Set priorities for the first 8 external interrupts to 1. for (i = 0; i < 8; i++) *((unsigned int *)PLIC_BASE + PLIC_EXT_IRQ_BASE + i) = 1; - // enable first 8 external interrupts + + // Enable the first 8 external interrupts *((unsigned int *)PLIC_ENABLED) = 0xff << PLIC_EXT_IRQ_BASE; - // set priority threshold to 0 (any priority > 0 triggers interrupt) + + // Set priority threshold to 0 (any priority > 0 triggers an interrupt). *((unsigned int *)PLIC_THRSHLD) = 0; } +// Interrupt Service Routine. void isr(void) { unsigned int claim; + // Claim and handle pending interrupts. while ((claim = *((unsigned int *)PLIC_CLAIM))) { switch (claim - PLIC_EXT_IRQ_BASE) { case UART_INTERRUPT: - uart_isr(); + uart_isr(); // Handle UART interrupt. break; default: + // Unhandled interrupt source, print diagnostic information. printf("## PLIC: Unhandled claim: %d\n", claim); printf("# plic_enabled: %08x\n", irq_getmask()); printf("# plic_pending: %08x\n", irq_pending()); @@ -70,6 +72,7 @@ void isr(void) printf("###########################\n\n"); break; } + // Acknowledge the interrupt. *((unsigned int *)PLIC_CLAIM) = claim; } } From 3506a5e82d3305c53051fe8895ea88f75b0e4508 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 14 May 2024 10:04:13 +0200 Subject: [PATCH 2/6] cores/cpu/vexriscv_smp: Prepare IRQ support based on Rocket IRQ support (not yet working). --- litex/soc/cores/cpu/vexriscv_smp/core.py | 4 ++-- litex/soc/cores/cpu/vexriscv_smp/crt0.S | 5 +++++ litex/soc/cores/cpu/vexriscv_smp/irq.h | 22 ++++++++++++++++------ 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/litex/soc/cores/cpu/vexriscv_smp/core.py b/litex/soc/cores/cpu/vexriscv_smp/core.py index 08320049a..2fe30c20c 100755 --- a/litex/soc/cores/cpu/vexriscv_smp/core.py +++ b/litex/soc/cores/cpu/vexriscv_smp/core.py @@ -168,8 +168,8 @@ class VexRiscvSMP(CPU): @property def gcc_flags(self): flags = f" -march={VexRiscvSMP.get_arch()} -mabi={VexRiscvSMP.get_abi()}" - flags += f" -D__vexriscv__" - flags += f" -DUART_POLLING" + flags += f" -D__vexriscv_smp__" + #flags += f" -DUART_POLLING" return flags # Reserved Interrupts. diff --git a/litex/soc/cores/cpu/vexriscv_smp/crt0.S b/litex/soc/cores/cpu/vexriscv_smp/crt0.S index ec18b8ecd..595891a6e 100644 --- a/litex/soc/cores/cpu/vexriscv_smp/crt0.S +++ b/litex/soc/cores/cpu/vexriscv_smp/crt0.S @@ -102,6 +102,11 @@ bss_loop: j bss_loop bss_done: + call plic_init // initialize external interrupt controller + li t0, 0x800 // external interrupt sources only (using LiteX timer); + // NOTE: must still enable mstatus.MIE! + csrw mie,t0 + call main infinit_loop: j infinit_loop diff --git a/litex/soc/cores/cpu/vexriscv_smp/irq.h b/litex/soc/cores/cpu/vexriscv_smp/irq.h index 558adc4f1..4dceaf8b8 100644 --- a/litex/soc/cores/cpu/vexriscv_smp/irq.h +++ b/litex/soc/cores/cpu/vexriscv_smp/irq.h @@ -9,30 +9,40 @@ extern "C" { #include #include +// VexRiscv-SMP uses a Platform-Level Interrupt Controller (PLIC) which +// is programmed and queried via a set of MMIO registerss + +#define PLIC_BASE 0xf0c00000L // Base address and per-pin priority array +#define PLIC_PENDING 0xf0c01000L // Bit field matching currently pending pins +#define PLIC_ENABLED 0xf0c02000L // Bit field corresponding to the current mask +#define PLIC_THRSHLD 0xf0e00000L // Per-pin priority must be >= this to trigger +#define PLIC_CLAIM 0xf0e00004L // Claim & completion register address + +#define PLIC_EXT_IRQ_BASE 1 // CHECKME/FIXME. + static inline unsigned int irq_getie(void) { - return 0; + return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0; } static inline void irq_setie(unsigned int ie) { - + if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE); } static inline unsigned int irq_getmask(void) { - - return 0; + return *((unsigned int *)PLIC_ENABLED) >> 1; } static inline void irq_setmask(unsigned int mask) { - + *((unsigned int *)PLIC_ENABLED) = mask << 1; } static inline unsigned int irq_pending(void) { - return 0; + return *((unsigned int *)PLIC_PENDING) >> 1; } #ifdef __cplusplus From 786c929f0815a3368a0ab7bd55a7947fb76b834b Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Tue, 14 May 2024 14:24:37 +0200 Subject: [PATCH 3/6] cores/cpu/vexriscv_smp: fix PLIC_EXT_IRQ_BASE --- litex/soc/cores/cpu/vexriscv_smp/irq.h | 8 ++++---- litex/soc/software/libbase/isr.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/litex/soc/cores/cpu/vexriscv_smp/irq.h b/litex/soc/cores/cpu/vexriscv_smp/irq.h index 4dceaf8b8..c50d44679 100644 --- a/litex/soc/cores/cpu/vexriscv_smp/irq.h +++ b/litex/soc/cores/cpu/vexriscv_smp/irq.h @@ -18,7 +18,7 @@ extern "C" { #define PLIC_THRSHLD 0xf0e00000L // Per-pin priority must be >= this to trigger #define PLIC_CLAIM 0xf0e00004L // Claim & completion register address -#define PLIC_EXT_IRQ_BASE 1 // CHECKME/FIXME. +#define PLIC_EXT_IRQ_BASE 0 // CHECKME/FIXME. static inline unsigned int irq_getie(void) { @@ -32,17 +32,17 @@ static inline void irq_setie(unsigned int ie) static inline unsigned int irq_getmask(void) { - return *((unsigned int *)PLIC_ENABLED) >> 1; + return *((unsigned int *)PLIC_ENABLED) >> PLIC_EXT_IRQ_BASE; } static inline void irq_setmask(unsigned int mask) { - *((unsigned int *)PLIC_ENABLED) = mask << 1; + *((unsigned int *)PLIC_ENABLED) = mask << PLIC_EXT_IRQ_BASE; } static inline unsigned int irq_pending(void) { - return *((unsigned int *)PLIC_PENDING) >> 1; + return *((unsigned int *)PLIC_PENDING) >> PLIC_EXT_IRQ_BASE; } #ifdef __cplusplus diff --git a/litex/soc/software/libbase/isr.c b/litex/soc/software/libbase/isr.c index eb2fe7ae5..359ac1cc1 100644 --- a/litex/soc/software/libbase/isr.c +++ b/litex/soc/software/libbase/isr.c @@ -29,7 +29,7 @@ void isr(void) onetime++; } } -#elif defined(__rocket__) || defined(__openc906__) +#elif defined(__rocket__) || defined(__openc906__) || defined(__vexriscv_smp__) // PLIC initialization. void plic_init(void); From c79e1ef95f0e0c7514deffac1d6e722d278ff18e Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 14 May 2024 14:43:57 +0200 Subject: [PATCH 4/6] cores/cpu/vexriscv_smp: Remove FIXME/CHECKME now that working and remove UART_POLLING flag. --- litex/soc/cores/cpu/vexriscv_smp/core.py | 1 - litex/soc/cores/cpu/vexriscv_smp/irq.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/litex/soc/cores/cpu/vexriscv_smp/core.py b/litex/soc/cores/cpu/vexriscv_smp/core.py index 2fe30c20c..3835ac253 100755 --- a/litex/soc/cores/cpu/vexriscv_smp/core.py +++ b/litex/soc/cores/cpu/vexriscv_smp/core.py @@ -169,7 +169,6 @@ class VexRiscvSMP(CPU): def gcc_flags(self): flags = f" -march={VexRiscvSMP.get_arch()} -mabi={VexRiscvSMP.get_abi()}" flags += f" -D__vexriscv_smp__" - #flags += f" -DUART_POLLING" return flags # Reserved Interrupts. diff --git a/litex/soc/cores/cpu/vexriscv_smp/irq.h b/litex/soc/cores/cpu/vexriscv_smp/irq.h index c50d44679..4c8461447 100644 --- a/litex/soc/cores/cpu/vexriscv_smp/irq.h +++ b/litex/soc/cores/cpu/vexriscv_smp/irq.h @@ -18,7 +18,7 @@ extern "C" { #define PLIC_THRSHLD 0xf0e00000L // Per-pin priority must be >= this to trigger #define PLIC_CLAIM 0xf0e00004L // Claim & completion register address -#define PLIC_EXT_IRQ_BASE 0 // CHECKME/FIXME. +#define PLIC_EXT_IRQ_BASE 0 static inline unsigned int irq_getie(void) { From e03b097e8e298d9fade0f65634a8ba3717a0b2fb Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 14 May 2024 14:47:01 +0200 Subject: [PATCH 5/6] software/libbase/isr.c: Simplify using __riscv_plic__ define. --- litex/soc/cores/cpu/openc906/core.py | 1 + litex/soc/cores/cpu/rocket/core.py | 1 + litex/soc/cores/cpu/vexriscv_smp/core.py | 1 + litex/soc/software/libbase/isr.c | 2 +- 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/litex/soc/cores/cpu/openc906/core.py b/litex/soc/cores/cpu/openc906/core.py index 06d32e998..b8144b81b 100644 --- a/litex/soc/cores/cpu/openc906/core.py +++ b/litex/soc/cores/cpu/openc906/core.py @@ -89,6 +89,7 @@ class OpenC906(CPU): flags = "-mno-save-restore " flags += "-march=rv64gc -mabi=lp64d " flags += "-D__openc906__ " + flags += "-D__riscv_plic__ " flags += "-mcmodel=medany" return flags diff --git a/litex/soc/cores/cpu/rocket/core.py b/litex/soc/cores/cpu/rocket/core.py index 16d9ffdcd..31e6e30b9 100644 --- a/litex/soc/cores/cpu/rocket/core.py +++ b/litex/soc/cores/cpu/rocket/core.py @@ -113,6 +113,7 @@ class Rocket(CPU): flags = "-mno-save-restore " flags += f"-march={self.get_arch(self.variant)} -mabi=lp64 " flags += "-D__rocket__ " + flags += "-D__riscv_plic__ " flags += "-mcmodel=medany" return flags diff --git a/litex/soc/cores/cpu/vexriscv_smp/core.py b/litex/soc/cores/cpu/vexriscv_smp/core.py index 3835ac253..f45bce1ab 100755 --- a/litex/soc/cores/cpu/vexriscv_smp/core.py +++ b/litex/soc/cores/cpu/vexriscv_smp/core.py @@ -169,6 +169,7 @@ class VexRiscvSMP(CPU): def gcc_flags(self): flags = f" -march={VexRiscvSMP.get_arch()} -mabi={VexRiscvSMP.get_abi()}" flags += f" -D__vexriscv_smp__" + flags += f" -D__riscv_plic__" return flags # Reserved Interrupts. diff --git a/litex/soc/software/libbase/isr.c b/litex/soc/software/libbase/isr.c index 359ac1cc1..71adac143 100644 --- a/litex/soc/software/libbase/isr.c +++ b/litex/soc/software/libbase/isr.c @@ -29,7 +29,7 @@ void isr(void) onetime++; } } -#elif defined(__rocket__) || defined(__openc906__) || defined(__vexriscv_smp__) +#elif defined(__riscv_plic__) // PLIC initialization. void plic_init(void); From d4c1a1081763204f271e4a4755522f6b27a327dd Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Tue, 14 May 2024 14:57:29 +0200 Subject: [PATCH 6/6] cores/cpu/naxriscv: Add baremetal IRQ support --- litex/soc/cores/cpu/naxriscv/core.py | 2 +- litex/soc/cores/cpu/naxriscv/crt0.S | 6 ++++-- litex/soc/cores/cpu/naxriscv/irq.h | 22 ++++++++++++++++------ 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/litex/soc/cores/cpu/naxriscv/core.py b/litex/soc/cores/cpu/naxriscv/core.py index a686534c9..7d8da8fb9 100755 --- a/litex/soc/cores/cpu/naxriscv/core.py +++ b/litex/soc/cores/cpu/naxriscv/core.py @@ -93,7 +93,7 @@ class NaxRiscv(CPU): def gcc_flags(self): flags = f" -march={NaxRiscv.get_arch()} -mabi={NaxRiscv.get_abi()}" flags += f" -D__NaxRiscv__" - flags += f" -DUART_POLLING" + flags += f" -D__riscv_plic__" return flags # Reserved Interrupts. diff --git a/litex/soc/cores/cpu/naxriscv/crt0.S b/litex/soc/cores/cpu/naxriscv/crt0.S index b27df7f47..4c4c69765 100644 --- a/litex/soc/cores/cpu/naxriscv/crt0.S +++ b/litex/soc/cores/cpu/naxriscv/crt0.S @@ -113,8 +113,10 @@ bss_loop: j bss_loop bss_done: - li a0, 0x880 //880 enable timer + external interrupt sources (until mstatus.MIE is set, they will never trigger an interrupt) - csrw mie,a0 + call plic_init // initialize external interrupt controller + li t0, 0x800 // external interrupt sources only (using LiteX timer); + // NOTE: must still enable mstatus.MIE! + csrw mie,t0 call main infinit_loop: diff --git a/litex/soc/cores/cpu/naxriscv/irq.h b/litex/soc/cores/cpu/naxriscv/irq.h index 558adc4f1..a8325ec46 100644 --- a/litex/soc/cores/cpu/naxriscv/irq.h +++ b/litex/soc/cores/cpu/naxriscv/irq.h @@ -9,30 +9,40 @@ extern "C" { #include #include +// NaxRiscv uses a Platform-Level Interrupt Controller (PLIC) which +// is programmed and queried via a set of MMIO registerss + +#define PLIC_BASE 0xf0c00000L // Base address and per-pin priority array +#define PLIC_PENDING 0xf0c01000L // Bit field matching currently pending pins +#define PLIC_ENABLED 0xf0c02000L // Bit field corresponding to the current mask +#define PLIC_THRSHLD 0xf0e00000L // Per-pin priority must be >= this to trigger +#define PLIC_CLAIM 0xf0e00004L // Claim & completion register address + +#define PLIC_EXT_IRQ_BASE 0 + static inline unsigned int irq_getie(void) { - return 0; + return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0; } static inline void irq_setie(unsigned int ie) { - + if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE); } static inline unsigned int irq_getmask(void) { - - return 0; + return *((unsigned int *)PLIC_ENABLED) >> PLIC_EXT_IRQ_BASE; } static inline void irq_setmask(unsigned int mask) { - + *((unsigned int *)PLIC_ENABLED) = mask << PLIC_EXT_IRQ_BASE; } static inline unsigned int irq_pending(void) { - return 0; + return *((unsigned int *)PLIC_PENDING) >> PLIC_EXT_IRQ_BASE; } #ifdef __cplusplus