Skip to content

Commit b27e7d3

Browse files
now we have both baremetal mode with no plic and linux mode with plic(it's more efficient ot not use plic in the baremetal case)
1 parent a6593be commit b27e7d3

File tree

3 files changed

+165
-117
lines changed

3 files changed

+165
-117
lines changed

litex/soc/cores/cpu/cva5/core.py

Lines changed: 78 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
# Variants -----------------------------------------------------------------------------------------
2222

23-
CPU_VARIANTS = ["minimal", "standard"]
23+
CPU_VARIANTS = ["minimal", "standard","standard+atomic","standard+atomic+float+double"]
2424

2525
# GCC Flags ----------------------------------------------------------------------------------------
2626

@@ -34,6 +34,8 @@
3434
# i macfd
3535
"minimal" : "-march=rv32i2p0 -mabi=ilp32 ",
3636
"standard" : "-march=rv32i2p0_m -mabi=ilp32 ",
37+
"standard+atomic" : "-march=rv32i2p0_ma -mabi=ilp32 ",
38+
"standard+atomic+float+double" : "-march=rv32i2p0_mafd -mabi=ilp32 ",
3739
}
3840

3941
# CVA5 ----------------------------------------------------------------------------------------------
@@ -62,7 +64,7 @@ def args_fill(parser):
6264
cpu_group = parser.add_argument_group(title="CPU options")
6365
cpu_group.add_argument("--cpu-count", default=1, help="Number of CPU(s) in the cluster.", type=int)
6466
cpu_group.add_argument("--clint-base", default="0xf0010000", help="CLINT base address.")
65-
cpu_group.add_argument("--plic-base", default="0xf8000000", help="PLIC base address.")
67+
cpu_group.add_argument("--plic-base", default="0xf800_0000", help="PLIC base address.")
6668
cpu_group.add_argument("--bus-type", default="wishbone", help="Bus type can be either wishbone or axi")
6769
cpu_group.add_argument("--variant", default="Linux", help="The CPU type for now it has the linux type")#TODO add other configs
6870

@@ -90,7 +92,10 @@ def mem_map(self):
9092
@property
9193
def gcc_flags(self):
9294
flags = GCC_FLAGS[self.variant]
93-
flags += "-D__riscv_plic__"
95+
if(CVA5.cpu_variant=="Linux"):
96+
flags += "-D__riscv_plic__"
97+
else:
98+
flags += "-D__cva5__"
9499
return flags
95100

96101
def __init__(self, platform, variant="standard"):
@@ -101,6 +106,7 @@ def __init__(self, platform, variant="standard"):
101106
self.interrupt = Signal(2)
102107
self.periph_buses = [] # Peripheral buses (Connected to main SoC's bus).
103108
self.memory_buses = [] # Memory buses (Connected directly to LiteDRAM).
109+
self.reset = Signal()
104110

105111
# CPU Instance.
106112
self.cpu_params = dict(
@@ -113,7 +119,7 @@ def __init__(self, platform, variant="standard"):
113119

114120
# Clk/Rst.
115121
i_clk = ClockSignal("sys"),
116-
i_rst = ResetSignal("sys"),
122+
i_rst = ResetSignal("sys") | self.reset,
117123
)
118124

119125
if(CVA5.bus_type == "wishbone"):
@@ -209,67 +215,74 @@ def add_soc_components(self, soc):
209215
meip = Signal(int(self.cpu_params["p_NUM_CORES"]))
210216
eip = Signal(2*int(self.cpu_params["p_NUM_CORES"]))
211217
es = Signal(2, reset=0)
212-
if(CVA5.bus_type == "wishbone"):
213-
self.plicbus = plicbus = wishbone.Interface(data_width=32, address_width=32, addressing="word")
214-
self.specials += Instance("plic_wrapper",
215-
p_NUM_SOURCES = 1,
216-
p_NUM_TARGETS = 2*int(self.cpu_params["p_NUM_CORES"]),
217-
p_PRIORITY_W = 8,
218-
p_REG_STAGE = 1,
219-
p_AXI = 0,
220-
i_clk = ClockSignal("sys"),
221-
i_rst = ResetSignal("sys"),
222-
i_irq_srcs = self.interrupt,
223-
i_edge_sensitive = es,
224-
o_eip = eip,
225-
i_wb_cyc = plicbus.cyc,
226-
i_wb_stb = plicbus.stb,
227-
i_wb_we = plicbus.we,
228-
i_wb_adr = plicbus.adr,
229-
i_wb_dat_i = plicbus.dat_w,
230-
o_wb_dat_o = plicbus.dat_r,
231-
o_wb_ack = plicbus.ack,
218+
219+
if(CVA5.cpu_variant == "Linux"):
220+
if(CVA5.bus_type == "wishbone"):
221+
self.plicbus = plicbus = wishbone.Interface(data_width=32, address_width=32, addressing="word")
222+
self.specials += Instance("plic_wrapper",
223+
p_NUM_SOURCES = 1,
224+
p_NUM_TARGETS = 2*int(self.cpu_params["p_NUM_CORES"]),
225+
p_PRIORITY_W = 8,
226+
p_REG_STAGE = 1,
227+
p_AXI = 0,
228+
i_clk = ClockSignal("sys"),
229+
i_rst = ResetSignal("sys"),
230+
i_irq_srcs = self.interrupt,
231+
i_edge_sensitive = es,
232+
o_eip = eip,
233+
i_wb_cyc = plicbus.cyc,
234+
i_wb_stb = plicbus.stb,
235+
i_wb_we = plicbus.we,
236+
i_wb_adr = plicbus.adr,
237+
i_wb_dat_i = plicbus.dat_w,
238+
o_wb_dat_o = plicbus.dat_r,
239+
o_wb_ack = plicbus.ack,
240+
)
241+
else:
242+
self.plicbus = plicbus = axi.AXIInterface(data_width=32, address_width=32, id_width=4)
243+
self.specials += Instance("plic_wrapper",
244+
p_NUM_SOURCES = 1,
245+
p_NUM_TARGETS = 2*int(self.cpu_params["p_NUM_CORES"]),
246+
p_PRIORITY_W = 8,
247+
p_REG_STAGE = 1,
248+
p_AXI = 1,
249+
i_clk = ClockSignal("sys"),
250+
i_rst = ResetSignal("sys"),
251+
i_irq_srcs = self.interrupt,
252+
i_edge_sensitive = es,
253+
o_eip = eip,
254+
i_s_axi_awvalid = plicbus.aw.valid,
255+
i_s_axi_awaddr = plicbus.aw.addr,
256+
i_s_axi_wvalid = plicbus.w.valid,
257+
i_s_axi_wdata = plicbus.w.data,
258+
i_s_axi_bready = plicbus.b.ready,
259+
i_s_axi_arvalid = plicbus.ar.valid,
260+
i_s_axi_araddr = plicbus.ar.addr,
261+
i_s_axi_rready = plicbus.r.ready,
262+
o_s_axi_awready = plicbus.aw.ready,
263+
o_s_axi_wready = plicbus.w.ready,
264+
o_s_axi_bvalid = plicbus.b.valid,
265+
o_s_axi_arready = plicbus.ar.ready,
266+
o_s_axi_rvalid = plicbus.r.valid,
267+
o_s_axi_rdata = plicbus.r.data
268+
)
269+
270+
self.comb += [
271+
meip.eq(Cat(*[eip[i*2] for i in range(int(self.cpu_params["p_NUM_CORES"]))])),
272+
seip.eq(Cat(*[eip[i*2 + 1] for i in range(int(self.cpu_params["p_NUM_CORES"]))]))
273+
]
274+
275+
self.cpu_params.update(
276+
i_seip = seip,
277+
i_meip = meip
232278
)
279+
soc.bus.add_slave("plic", self.plicbus, region=SoCRegion(origin=self.plic_base, size=0x40_0000, cached=False))
233280
else:
234-
self.plicbus = plicbus = axi.AXIInterface(data_width=32, address_width=32, id_width=4)
235-
self.specials += Instance("plic_wrapper",
236-
p_NUM_SOURCES = 1,
237-
p_NUM_TARGETS = 2*int(self.cpu_params["p_NUM_CORES"]),
238-
p_PRIORITY_W = 8,
239-
p_REG_STAGE = 1,
240-
p_AXI = 1,
241-
i_clk = ClockSignal("sys"),
242-
i_rst = ResetSignal("sys"),
243-
i_irq_srcs = self.interrupt,
244-
i_edge_sensitive = es,
245-
o_eip = eip,
246-
i_s_axi_awvalid = plicbus.aw.valid,
247-
i_s_axi_awaddr = plicbus.aw.addr,
248-
i_s_axi_wvalid = plicbus.w.valid,
249-
i_s_axi_wdata = plicbus.w.data,
250-
i_s_axi_bready = plicbus.b.ready,
251-
i_s_axi_arvalid = plicbus.ar.valid,
252-
i_s_axi_araddr = plicbus.ar.addr,
253-
i_s_axi_rready = plicbus.r.ready,
254-
o_s_axi_awready = plicbus.aw.ready,
255-
o_s_axi_wready = plicbus.w.ready,
256-
o_s_axi_bvalid = plicbus.b.valid,
257-
o_s_axi_arready = plicbus.ar.ready,
258-
o_s_axi_rvalid = plicbus.r.valid,
259-
o_s_axi_rdata = plicbus.r.data
281+
self.cpu_params.update(
282+
i_meip = self.interrupt[0]
260283
)
261284

262-
self.comb += [
263-
meip.eq(Cat(*[eip[i*2] for i in range(int(self.cpu_params["p_NUM_CORES"]))])),
264-
seip.eq(Cat(*[eip[i*2 + 1] for i in range(int(self.cpu_params["p_NUM_CORES"]))]))
265-
]
266-
267-
self.cpu_params.update(
268-
i_seip = seip,
269-
i_meip = meip
270-
)
271285

272-
soc.bus.add_slave("plic", self.plicbus, region=SoCRegion(origin=self.plic_base, size=0x40_0000, cached=False))
273286

274287
# CLINT
275288
if(CVA5.cpu_variant == "Linux"):
@@ -324,5 +337,9 @@ def add_soc_components(self, soc):
324337
i_msip = msip,
325338
i_mtip = mtip
326339
)
340+
soc.bus.add_slave("clint", clintbus, region=SoCRegion(origin=self.clint_base, size=0x1_0000, cached=False))
341+
else:
342+
self.cpu_params.update(
343+
i_mtip = self.interrupt[1]
344+
)
327345

328-
soc.bus.add_slave("clint", clintbus, region=SoCRegion(origin=self.clint_base, size=0x1_0000, cached=False))

litex/soc/cores/cpu/cva5/irq.h

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,30 +20,63 @@ extern "C" {
2020

2121
#define PLIC_EXT_IRQ_BASE 1
2222

23-
static inline unsigned int irq_getie(void)
24-
{
25-
return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0;
26-
}
23+
#ifndef __riscv_plic__
2724

28-
static inline void irq_setie(unsigned int ie)
29-
{
30-
if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE);
31-
}
25+
static inline unsigned int irq_getie(void)
26+
{
27+
return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0;
28+
}
3229

33-
static inline unsigned int irq_getmask(void)
34-
{
35-
return (csrr(mie) >> CSR_IRQ_EXTERNAL_OFFSET);
36-
}
30+
static inline void irq_setie(unsigned int ie)
31+
{
32+
if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE);
33+
}
3734

38-
static inline void irq_setmask(unsigned int mask)
39-
{
40-
if (mask) csrs(mie,CSR_IRQ_EXTERNAL_OFFSET); else csrc(mie,CSR_IRQ_EXTERNAL_OFFSET);
41-
}
35+
static inline unsigned int irq_getmask(void)
36+
{
37+
return (csrr(mie) >> CSR_IRQ_EXTERNAL_OFFSET);
38+
}
4239

43-
static inline unsigned int irq_pending(void)
44-
{
45-
return ((csrr(mie) | csrr(mip)) >> CSR_IRQ_EXTERNAL_OFFSET) & 0x1;
46-
}
40+
static inline void irq_setmask(unsigned int mask)
41+
{
42+
if (mask) csrs(mie,CSR_IRQ_EXTERNAL_OFFSET); else csrc(mie,CSR_IRQ_EXTERNAL_OFFSET);
43+
}
44+
45+
static inline unsigned int irq_pending(void)
46+
{
47+
return ((csrr(mie) | csrr(mip)) >> CSR_IRQ_EXTERNAL_OFFSET) & 0x1;
48+
}
49+
#else
50+
51+
static inline unsigned int irq_getie(void)
52+
{
53+
return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0;
54+
}
55+
56+
static inline void irq_setie(unsigned int ie)
57+
{
58+
if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE);
59+
}
60+
61+
static inline unsigned int irq_getmask(void)
62+
{
63+
// (csrr(mie) >> CSR_IRQ_EXTERNAL_OFFSET);
64+
return *((unsigned int *)PLIC_ENABLED) >> PLIC_EXT_IRQ_BASE;
65+
}
66+
67+
static inline void irq_setmask(unsigned int mask)
68+
{
69+
// if (mask) csrs(mie,CSR_IRQ_EXTERNAL_OFFSET); else csrc(mie,CSR_IRQ_EXTERNAL_OFFSET);
70+
*((unsigned int *)PLIC_ENABLED) = mask << PLIC_EXT_IRQ_BASE;
71+
}
72+
73+
static inline unsigned int irq_pending(void)
74+
{
75+
// ((csrr(mie) | csrr(mip)) >> CSR_IRQ_EXTERNAL_OFFSET) & 0x1;
76+
return *((unsigned int *)PLIC_PENDING) >> PLIC_EXT_IRQ_BASE;
77+
}
78+
79+
#endif
4780

4881
#ifdef __cplusplus
4982
}

litex/soc/software/libbase/isr.c

Lines changed: 34 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -199,58 +199,56 @@ void isr_dec(void)
199199
}
200200

201201
/***********************************/
202-
/* ISR Handling for CVA5 CPU. */
202+
/* ISR Handling for CVA5 CPU in Baremetal Mode. */
203203
/***********************************/
204204
#elif defined(__cva5__)
205205

206-
// PLIC initialization.
207206
void plic_init(void);
207+
208208
void plic_init(void)
209209
{
210-
int i;
210+
}
211+
struct irq_table
212+
{
213+
isr_t isr;
214+
} irq_table[CONFIG_CPU_INTERRUPTS];
211215

212-
// Set priorities for the first 8 external interrupts to 1.
213-
for (i = 0; i < 8; i++)
214-
*((unsigned int *)PLIC_BASE + PLIC_EXT_IRQ_BASE + i) = 1;
216+
int irq_attach(unsigned int irq, isr_t isr)
217+
{
218+
if (irq >= CONFIG_CPU_INTERRUPTS) {
219+
printf("Inv irq %d\n", irq);
220+
return -1;
221+
}
215222

216-
// Enable the first 8 external interrupts
217-
*((unsigned int *)PLIC_ENABLED) = 0xff << PLIC_EXT_IRQ_BASE;
223+
unsigned int ie = irq_getie();
224+
irq_setie(0);
225+
irq_table[irq].isr = isr;
226+
irq_setie(ie);
227+
return irq;
228+
}
218229

219-
// Set priority threshold to 0 (any priority > 0 triggers an interrupt).
220-
*((unsigned int *)PLIC_THRSHLD) = 0;
230+
int irq_detach(unsigned int irq)
231+
{
232+
return irq_attach(irq, NULL);
221233
}
222234

223-
// Interrupt Service Routine.
224235
void isr(void)
225236
{
226-
unsigned int claim = 1;
227-
228-
while (claim) {
229-
claim = *((unsigned int *)PLIC_CLAIM);
230-
if(claim - PLIC_EXT_IRQ_BASE == UART_INTERRUPT+1) {
231-
uart_isr(); // Handle UART interrupt.
232-
*((unsigned int *)PLIC_CLAIM) = claim;
233-
csrr(mip);
234-
break;
235-
}else if(claim) {
236-
printf("## PLIC: Unhandled claim: %d\n", claim);
237-
printf("# plic_enabled: %08x\n", irq_getmask());
238-
printf("# plic_pending: %08x\n", irq_pending());
239-
printf("# mepc: %016lx\n", csrr(mepc));
240-
printf("# mcause: %016lx\n", csrr(mcause));
241-
printf("# mtval: %016lx\n", csrr(mtval));
242-
printf("# mie: %016lx\n", csrr(mie));
243-
printf("# mip: %016lx\n", csrr(mip));
244-
printf("###########################\n\n");
245-
break;
237+
// irq_setie(1);
238+
unsigned int irqs = irq_pending() & irq_getmask();
239+
240+
while (irqs)
241+
{
242+
const unsigned int irq = __builtin_ctz(irqs);
243+
if ((irq < CONFIG_CPU_INTERRUPTS) && irq_table[irq].isr)
244+
irq_table[irq].isr();
245+
else {
246+
irq_setmask(irq_getmask() & ~(1<<irq));
247+
printf("\n*** disabled spurious irq %d ***\n", irq);
246248
}
247-
// Acknowledge the interrupt.
248-
*((unsigned int *)PLIC_CLAIM) = claim;
249-
csrr(mip);
250-
break;
249+
irqs &= irqs - 1; // clear this irq (the first bit set)
251250
}
252251
}
253-
254252
/*******************************************************/
255253
/* Generic ISR Handling for CPUs with Interrupt Table. */
256254
/*******************************************************/

0 commit comments

Comments
 (0)