Merge pull request #535 from antmicro/arty-cv32e40p
Add support for the CV32E40P RISC-V CPU
This commit is contained in:
commit
4c4cd335de
|
@ -57,6 +57,7 @@ from litex.soc.cores.cpu.minerva import Minerva
|
|||
from litex.soc.cores.cpu.vexriscv import VexRiscv
|
||||
from litex.soc.cores.cpu.rocket import RocketRV64
|
||||
from litex.soc.cores.cpu.blackparrot import BlackParrotRV64
|
||||
from litex.soc.cores.cpu.cv32e40p import CV32E40P
|
||||
|
||||
CPUS = {
|
||||
# None
|
||||
|
@ -76,6 +77,7 @@ CPUS = {
|
|||
"picorv32" : PicoRV32,
|
||||
"minerva" : Minerva,
|
||||
"vexriscv" : VexRiscv,
|
||||
"cv32e40p" : CV32E40P,
|
||||
|
||||
# RISC-V 64-bit
|
||||
"rocket" : RocketRV64,
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
from litex.soc.cores.cpu.cv32e40p.core import CV32E40P
|
|
@ -0,0 +1,4 @@
|
|||
.section .text, "ax", @progbits
|
||||
.global boot_helper
|
||||
boot_helper:
|
||||
jr x13
|
|
@ -0,0 +1,417 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
from migen import *
|
||||
from migen.fhdl.specials import Tristate
|
||||
|
||||
from litex import get_data_mod
|
||||
from litex.soc.interconnect import wishbone, stream
|
||||
from litex.soc.interconnect.csr import *
|
||||
from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_RISCV32
|
||||
|
||||
|
||||
CPU_VARIANTS = ["standard", "full"]
|
||||
|
||||
GCC_FLAGS = {
|
||||
# /-------- Base ISA
|
||||
# |/------- Hardware Multiply + Divide
|
||||
# ||/----- Atomics
|
||||
# |||/---- Compressed ISA
|
||||
# ||||/--- Single-Precision Floating-Point
|
||||
# |||||/-- Double-Precision Floating-Point
|
||||
# imacfd
|
||||
"standard": "-march=rv32imc -mabi=ilp32 ",
|
||||
"full": "-march=rv32imfc -mabi=ilp32 ",
|
||||
}
|
||||
|
||||
obi_layout = [
|
||||
("req", 1),
|
||||
("gnt", 1),
|
||||
("addr", 32),
|
||||
("we", 1),
|
||||
("be", 4),
|
||||
("wdata", 32),
|
||||
("rvalid", 1),
|
||||
("rdata", 32),
|
||||
]
|
||||
|
||||
apb_layout = [
|
||||
("paddr", 32),
|
||||
("pwdata", 32),
|
||||
("pwrite", 1),
|
||||
("psel", 1),
|
||||
("penable", 1),
|
||||
("prdata", 32),
|
||||
("pready", 1),
|
||||
("pslverr", 1),
|
||||
]
|
||||
|
||||
trace_layout = [
|
||||
("ivalid", 1),
|
||||
("iexception", 1),
|
||||
("interrupt", 1),
|
||||
("cause", 5),
|
||||
("tval", 32),
|
||||
("priv", 3),
|
||||
("iaddr", 32),
|
||||
("instr", 32),
|
||||
("compressed", 1),
|
||||
]
|
||||
|
||||
def add_manifest_sources(platform, manifest):
|
||||
basedir = get_data_mod("cpu", "cv32e40p").data_location
|
||||
with open(os.path.join(basedir, manifest), 'r') as f:
|
||||
for l in f:
|
||||
res = re.search('\$\{DESIGN_RTL_DIR\}/(.+)', l)
|
||||
if res and not re.match('//', l):
|
||||
if re.match('\+incdir\+', l):
|
||||
platform.add_verilog_include_path(os.path.join(basedir, 'rtl', res.group(1)))
|
||||
else:
|
||||
platform.add_source(os.path.join(basedir, 'rtl', res.group(1)))
|
||||
|
||||
|
||||
class OBI2Wishbone(Module):
|
||||
def __init__(self, obi, wb):
|
||||
dat_r_d = Signal().like(wb.dat_r)
|
||||
addr_d = Signal().like(obi.addr)
|
||||
ack_d = Signal()
|
||||
|
||||
self.sync += [
|
||||
dat_r_d.eq(wb.dat_r),
|
||||
ack_d.eq(wb.ack),
|
||||
addr_d.eq(obi.addr),
|
||||
]
|
||||
|
||||
self.comb += [
|
||||
wb.adr.eq(obi.addr[2:32]),
|
||||
wb.stb.eq(obi.req & (~ack_d)),
|
||||
wb.dat_w.eq(obi.wdata),
|
||||
wb.cyc.eq(obi.req),
|
||||
wb.sel.eq(obi.be),
|
||||
wb.we.eq(obi.we),
|
||||
obi.gnt.eq(wb.ack & (addr_d == obi.addr)),
|
||||
obi.rvalid.eq(ack_d),
|
||||
obi.rdata.eq(dat_r_d),
|
||||
]
|
||||
|
||||
class Wishbone2OBI(Module):
|
||||
def __init__(self, wb, obi):
|
||||
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
||||
fsm.act("IDLE",
|
||||
If(wb.cyc & wb.stb,
|
||||
obi.req.eq(1),
|
||||
NextState("ACK"),
|
||||
)
|
||||
)
|
||||
fsm.act("ACK",
|
||||
wb.ack.eq(1),
|
||||
NextState("IDLE"),
|
||||
)
|
||||
|
||||
self.comb += [
|
||||
obi.we.eq(wb.we),
|
||||
obi.be.eq(wb.sel),
|
||||
obi.addr.eq(Cat(0, 0, wb.adr)),
|
||||
obi.wdata.eq(wb.dat_w),
|
||||
wb.dat_r.eq(obi.rdata),
|
||||
]
|
||||
|
||||
class Wishbone2APB(Module):
|
||||
def __init__(self, wb, apb):
|
||||
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
||||
fsm.act("IDLE",
|
||||
If(wb.cyc & wb.stb,
|
||||
NextState("ACK"),
|
||||
)
|
||||
)
|
||||
fsm.act("ACK",
|
||||
apb.penable.eq(1),
|
||||
wb.ack.eq(1),
|
||||
NextState("IDLE"),
|
||||
)
|
||||
|
||||
self.comb += [
|
||||
apb.paddr.eq(Cat(0, 0, wb.adr)),
|
||||
apb.pwrite.eq(wb.we),
|
||||
apb.psel.eq(1),
|
||||
apb.pwdata.eq(wb.dat_w),
|
||||
wb.dat_r.eq(apb.prdata),
|
||||
]
|
||||
|
||||
class TraceCollector(Module, AutoCSR):
|
||||
def __init__(self, trace_depth=16384):
|
||||
self.bus = bus = wishbone.Interface()
|
||||
self.sink = sink = stream.Endpoint([("data", 32)])
|
||||
|
||||
clear = Signal()
|
||||
enable = Signal()
|
||||
pointer = Signal(32)
|
||||
|
||||
self._enable = CSRStorage()
|
||||
self._clear = CSRStorage()
|
||||
self._pointer = CSRStatus(32)
|
||||
|
||||
mem = Memory(32, trace_depth)
|
||||
rd_port = mem.get_port()
|
||||
wr_port = mem.get_port(write_capable=True)
|
||||
|
||||
self.specials += rd_port, wr_port, mem
|
||||
|
||||
self.sync += [
|
||||
# wishbone
|
||||
bus.ack.eq(0),
|
||||
If(bus.cyc & bus.stb & ~bus.ack, bus.ack.eq(1)),
|
||||
# trace core
|
||||
If(clear, pointer.eq(0)).Else(
|
||||
If(sink.ready & sink.valid, pointer.eq(pointer+1)),
|
||||
),
|
||||
]
|
||||
|
||||
self.comb += [
|
||||
# wishbone
|
||||
rd_port.adr.eq(bus.adr),
|
||||
bus.dat_r.eq(rd_port.dat_r),
|
||||
# trace core
|
||||
wr_port.adr.eq(pointer),
|
||||
wr_port.dat_w.eq(sink.data),
|
||||
wr_port.we.eq(sink.ready & sink.valid),
|
||||
sink.ready.eq(enable & (pointer < trace_depth)),
|
||||
# csrs
|
||||
enable.eq(self._enable.storage),
|
||||
clear.eq(self._clear.storage),
|
||||
self._pointer.status.eq(pointer),
|
||||
]
|
||||
|
||||
class TraceDebugger(Module):
|
||||
def __init__(self):
|
||||
self.bus = wishbone.Interface()
|
||||
self.source = source = stream.Endpoint([("data", 32)])
|
||||
self.trace_if = trace_if = Record(trace_layout)
|
||||
|
||||
apb = Record(apb_layout)
|
||||
|
||||
self.submodules.bus_conv = Wishbone2APB(self.bus, apb)
|
||||
|
||||
self.trace_params = dict(
|
||||
i_clk_i=ClockSignal(),
|
||||
i_rst_ni=~ResetSignal(),
|
||||
i_test_mode_i=0,
|
||||
# cpu interface
|
||||
i_ivalid_i=trace_if.ivalid,
|
||||
i_iexception_i=trace_if.iexception,
|
||||
i_interrupt_i=trace_if.interrupt,
|
||||
i_cause_i=trace_if.cause,
|
||||
i_tval_i=trace_if.tval,
|
||||
i_priv_i=trace_if.priv,
|
||||
i_iaddr_i=trace_if.iaddr,
|
||||
i_instr_i=trace_if.instr,
|
||||
i_compressed_i=trace_if.compressed,
|
||||
# apb interface
|
||||
i_paddr_i=apb.paddr,
|
||||
i_pwdata_i=apb.pwdata,
|
||||
i_pwrite_i=apb.pwrite,
|
||||
i_psel_i=apb.psel,
|
||||
i_penable_i=apb.penable,
|
||||
o_prdata_o=apb.prdata,
|
||||
o_pready_o=apb.pready,
|
||||
o_pslverr_o=apb.pslverr,
|
||||
# data output
|
||||
o_packet_word_o=source.data,
|
||||
o_packet_word_valid_o=source.valid,
|
||||
i_grant_i=source.ready,
|
||||
)
|
||||
self.specials += Instance("trace_debugger", **self.trace_params)
|
||||
|
||||
@staticmethod
|
||||
def add_sources(platform):
|
||||
add_manifest_sources(platform, "cv32e40p_trace_manifest.flist")
|
||||
|
||||
class DebugModule(Module):
|
||||
jtag_layout = [
|
||||
("tck", 1),
|
||||
("tms", 1),
|
||||
("trst", 1),
|
||||
("tdi", 1),
|
||||
("tdo", 1),
|
||||
]
|
||||
def __init__(self, pads=None):
|
||||
self.dmbus = wishbone.Interface()
|
||||
self.sbbus = wishbone.Interface()
|
||||
dmbus = Record(obi_layout)
|
||||
sbbus = Record(obi_layout)
|
||||
|
||||
self.submodules.sbbus_conv = OBI2Wishbone(sbbus, self.sbbus)
|
||||
self.submodules.dmbus_conv = Wishbone2OBI(self.dmbus, dmbus)
|
||||
|
||||
self.debug_req = Signal()
|
||||
self.ndmreset = Signal()
|
||||
|
||||
tdo_i = Signal()
|
||||
tdo_o = Signal()
|
||||
tdo_oe = Signal()
|
||||
|
||||
if pads is None:
|
||||
pads = Record(self.jtag_layout)
|
||||
|
||||
self.pads = pads
|
||||
|
||||
self.specials += Tristate(pads.tdo, tdo_o, tdo_oe, tdo_i)
|
||||
|
||||
self.dm_params = dict(
|
||||
i_clk=ClockSignal(),
|
||||
i_rst_n=~ResetSignal(),
|
||||
o_ndmreset=self.ndmreset,
|
||||
o_debug_req=self.debug_req,
|
||||
# slave bus
|
||||
i_dm_req=dmbus.req,
|
||||
i_dm_we=dmbus.we,
|
||||
i_dm_addr=dmbus.addr,
|
||||
i_dm_be=dmbus.be,
|
||||
i_dm_wdata=dmbus.wdata,
|
||||
o_dm_rdata=dmbus.rdata,
|
||||
# master bus
|
||||
o_sb_req=sbbus.req,
|
||||
o_sb_addr=sbbus.addr,
|
||||
o_sb_we=sbbus.we,
|
||||
o_sb_wdata=sbbus.wdata,
|
||||
o_sb_be=sbbus.be,
|
||||
i_sb_gnt=sbbus.gnt,
|
||||
i_sb_rvalid=sbbus.rvalid,
|
||||
i_sb_rdata=sbbus.rdata,
|
||||
# jtag
|
||||
i_tck=pads.tck,
|
||||
i_tms=pads.tms,
|
||||
i_trst_n=pads.trst,
|
||||
i_tdi=pads.tdi,
|
||||
o_tdo=tdo_o,
|
||||
o_tdo_oe=tdo_oe,
|
||||
)
|
||||
|
||||
self.comb += [
|
||||
dmbus.gnt.eq(dmbus.req),
|
||||
dmbus.rvalid.eq(dmbus.gnt),
|
||||
]
|
||||
|
||||
self.specials += Instance("dm_wrap", **self.dm_params)
|
||||
|
||||
@staticmethod
|
||||
def add_sources(platform):
|
||||
add_manifest_sources(platform, "cv32e40p_dm_manifest.flist")
|
||||
|
||||
|
||||
class CV32E40P(CPU):
|
||||
name = "cv32e40p"
|
||||
human_name = "CV32E40P"
|
||||
data_width = 32
|
||||
endianness = "little"
|
||||
gcc_triple = CPU_GCC_TRIPLE_RISCV32
|
||||
linker_output_format = "elf32-littleriscv"
|
||||
nop = "nop"
|
||||
io_regions = {0x80000000: 0x80000000} # origin, length
|
||||
|
||||
has_fpu = ["full"]
|
||||
|
||||
@property
|
||||
def gcc_flags(self):
|
||||
flags = GCC_FLAGS[self.variant]
|
||||
flags += "-D__cv32e40p__ "
|
||||
|
||||
return flags
|
||||
|
||||
def __init__(self, platform, variant="standard"):
|
||||
assert variant in CPU_VARIANTS, "Unsupported variant %s" % variant
|
||||
self.platform = platform
|
||||
self.variant = variant
|
||||
self.reset = Signal()
|
||||
self.ibus = wishbone.Interface()
|
||||
self.dbus = wishbone.Interface()
|
||||
self.periph_buses = [self.ibus, self.dbus]
|
||||
self.memory_buses = []
|
||||
self.interrupt = Signal(15)
|
||||
|
||||
ibus = Record(obi_layout)
|
||||
dbus = Record(obi_layout)
|
||||
|
||||
self.submodules.ibus_conv = OBI2Wishbone(ibus, self.ibus)
|
||||
self.submodules.dbus_conv = OBI2Wishbone(dbus, self.dbus)
|
||||
|
||||
self.comb += [
|
||||
ibus.we.eq(0),
|
||||
ibus.be.eq(1111),
|
||||
]
|
||||
|
||||
self.cpu_params = dict(
|
||||
i_clk_i=ClockSignal(),
|
||||
i_rst_ni=~ResetSignal(),
|
||||
i_clock_en_i=1,
|
||||
i_test_en_i=0,
|
||||
i_fregfile_disable_i=0,
|
||||
i_core_id_i=0,
|
||||
i_cluster_id_i=0,
|
||||
# ibus
|
||||
o_instr_req_o=ibus.req,
|
||||
i_instr_gnt_i=ibus.gnt,
|
||||
i_instr_rvalid_i=ibus.rvalid,
|
||||
o_instr_addr_o=ibus.addr,
|
||||
i_instr_rdata_i=ibus.rdata,
|
||||
# dbus
|
||||
o_data_req_o=dbus.req,
|
||||
i_data_gnt_i=dbus.gnt,
|
||||
i_data_rvalid_i=dbus.rvalid,
|
||||
o_data_we_o=dbus.we,
|
||||
o_data_be_o=dbus.be,
|
||||
o_data_addr_o=dbus.addr,
|
||||
o_data_wdata_o=dbus.wdata,
|
||||
i_data_rdata_i=dbus.rdata,
|
||||
# apu
|
||||
i_apu_master_gnt_i=0,
|
||||
i_apu_master_valid_i=0,
|
||||
# irq
|
||||
i_irq_sec_i=0,
|
||||
i_irq_software_i=0,
|
||||
i_irq_external_i=0,
|
||||
i_irq_fast_i=self.interrupt,
|
||||
i_irq_nmi_i=0,
|
||||
i_irq_fastx_i=0,
|
||||
# debug
|
||||
i_debug_req_i=0,
|
||||
# cpu control
|
||||
i_fetch_enable_i=1,
|
||||
)
|
||||
|
||||
# add verilog sources
|
||||
add_manifest_sources(platform, 'cv32e40p_manifest.flist')
|
||||
|
||||
if variant in self.has_fpu:
|
||||
self.cpu_params.update(p_FPU=1)
|
||||
add_manifest_sources(platform, 'cv32e40p_fpu_manifest.flist')
|
||||
|
||||
def add_debug_module(self, dm):
|
||||
self.cpu_params.update(i_debug_req_i=dm.debug_req)
|
||||
self.cpu_params.update(i_rst_ni=~(ResetSignal() | dm.ndmreset))
|
||||
|
||||
def add_trace_core(self, trace):
|
||||
trace_if = trace.trace_if
|
||||
|
||||
self.cpu_params.update(
|
||||
o_ivalid_o=trace_if.ivalid,
|
||||
o_iexception_o=trace_if.iexception,
|
||||
o_interrupt_o=trace_if.interrupt,
|
||||
o_cause_o=trace_if.cause,
|
||||
o_tval_o=trace_if.tval,
|
||||
o_priv_o=trace_if.priv,
|
||||
o_iaddr_o=trace_if.iaddr,
|
||||
o_instr_o=trace_if.instr,
|
||||
o_compressed_o=trace_if.compressed,
|
||||
)
|
||||
|
||||
def set_reset_address(self, reset_address):
|
||||
assert not hasattr(self, "reset_address")
|
||||
self.reset_address = reset_address
|
||||
self.cpu_params.update(i_boot_addr_i=Signal(32, reset=reset_address))
|
||||
|
||||
def do_finalize(self):
|
||||
assert hasattr(self, "reset_address")
|
||||
self.specials += Instance("riscv_core", **self.cpu_params)
|
|
@ -0,0 +1,112 @@
|
|||
.global main
|
||||
.global isr
|
||||
.global _start
|
||||
|
||||
_start:
|
||||
j crt_init
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
.balign 256
|
||||
|
||||
vector_table:
|
||||
j trap_entry # 0 unused
|
||||
j trap_entry # 1 unused
|
||||
j trap_entry # 2 unused
|
||||
j trap_entry # 3 software
|
||||
j trap_entry # 4 unused
|
||||
j trap_entry # 5 unused
|
||||
j trap_entry # 6 unused
|
||||
j trap_entry # 7 timer
|
||||
j trap_entry # 8 unused
|
||||
j trap_entry # 9 unused
|
||||
j trap_entry # 10 unused
|
||||
j trap_entry # 11 external
|
||||
j trap_entry # 12 unused
|
||||
j trap_entry # 13 unused
|
||||
j trap_entry # 14 unused
|
||||
j trap_entry # 15 unused
|
||||
j trap_entry # 16 firq0
|
||||
j trap_entry # 17 firq1
|
||||
j trap_entry # 18 firq2
|
||||
j trap_entry # 19 firq3
|
||||
j trap_entry # 20 firq4
|
||||
j trap_entry # 21 firq5
|
||||
j trap_entry # 22 firq6
|
||||
j trap_entry # 23 firq7
|
||||
j trap_entry # 24 firq8
|
||||
j trap_entry # 25 firq9
|
||||
j trap_entry # 26 firq10
|
||||
j trap_entry # 27 firq11
|
||||
j trap_entry # 28 firq12
|
||||
j trap_entry # 29 firq13
|
||||
j trap_entry # 30 firq14
|
||||
j trap_entry # 31 unused
|
||||
|
||||
.global trap_entry
|
||||
trap_entry:
|
||||
sw x1, - 1*4(sp)
|
||||
sw x5, - 2*4(sp)
|
||||
sw x6, - 3*4(sp)
|
||||
sw x7, - 4*4(sp)
|
||||
sw x10, - 5*4(sp)
|
||||
sw x11, - 6*4(sp)
|
||||
sw x12, - 7*4(sp)
|
||||
sw x13, - 8*4(sp)
|
||||
sw x14, - 9*4(sp)
|
||||
sw x15, -10*4(sp)
|
||||
sw x16, -11*4(sp)
|
||||
sw x17, -12*4(sp)
|
||||
sw x28, -13*4(sp)
|
||||
sw x29, -14*4(sp)
|
||||
sw x30, -15*4(sp)
|
||||
sw x31, -16*4(sp)
|
||||
addi sp,sp,-16*4
|
||||
call isr
|
||||
lw x1 , 15*4(sp)
|
||||
lw x5, 14*4(sp)
|
||||
lw x6, 13*4(sp)
|
||||
lw x7, 12*4(sp)
|
||||
lw x10, 11*4(sp)
|
||||
lw x11, 10*4(sp)
|
||||
lw x12, 9*4(sp)
|
||||
lw x13, 8*4(sp)
|
||||
lw x14, 7*4(sp)
|
||||
lw x15, 6*4(sp)
|
||||
lw x16, 5*4(sp)
|
||||
lw x17, 4*4(sp)
|
||||
lw x28, 3*4(sp)
|
||||
lw x29, 2*4(sp)
|
||||
lw x30, 1*4(sp)
|
||||
lw x31, 0*4(sp)
|
||||
addi sp,sp,16*4
|
||||
mret
|
||||
.text
|
||||
|
||||
|
||||
crt_init:
|
||||
la sp, _fstack + 4
|
||||
la a0, vector_table
|
||||
csrw mtvec, a0
|
||||
|
||||
bss_init:
|
||||
la a0, _fbss
|
||||
la a1, _ebss
|
||||
bss_loop:
|
||||
beq a0,a1,bss_done
|
||||
sw zero,0(a0)
|
||||
add a0,a0,4
|
||||
j bss_loop
|
||||
bss_done:
|
||||
|
||||
li a0, 0x7FFF0880 //7FFF0880 enable timer + external interrupt + fast interrupt sources (until mstatus.MIE is set, they will never trigger an interrupt)
|
||||
csrw mie,a0
|
||||
|
||||
j main
|
||||
infinit_loop:
|
||||
j infinit_loop
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef CSR_DEFS__H
|
||||
#define CSR_DEFS__H
|
||||
|
||||
#define CSR_MSTATUS_MIE 0x8
|
||||
|
||||
#define CSR_IRQ_MASK 0xBC0
|
||||
#define CSR_IRQ_PENDING 0xFC0
|
||||
|
||||
#define CSR_DCACHE_INFO 0xCC0
|
||||
|
||||
#endif /* CSR_DEFS__H */
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef __IRQ_H
|
||||
#define __IRQ_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <system.h>
|
||||
#include <generated/csr.h>
|
||||
|
||||
static inline unsigned int irq_getie(void)
|
||||
{
|
||||
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; // FIXME
|
||||
}
|
||||
|
||||
static inline void irq_setmask(unsigned int mask)
|
||||
{
|
||||
// FIXME
|
||||
}
|
||||
|
||||
static inline unsigned int irq_pending(void)
|
||||
{
|
||||
return 0;// FIXME
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __IRQ_H */
|
|
@ -0,0 +1,52 @@
|
|||
#ifndef __SYSTEM_H
|
||||
#define __SYSTEM_H
|
||||
|
||||
#include <csr-defs.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
__attribute__((unused)) static void flush_cpu_icache(void)
|
||||
{
|
||||
// FIXME
|
||||
asm volatile("nop");
|
||||
}
|
||||
|
||||
__attribute__((unused)) static void flush_cpu_dcache(void)
|
||||
{
|
||||
// FIXME
|
||||
asm volatile("nop");
|
||||
}
|
||||
|
||||
void flush_l2_cache(void);
|
||||
|
||||
void busy_wait(unsigned int ms);
|
||||
|
||||
#define csrr(reg) ({ unsigned long __tmp; \
|
||||
asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
|
||||
__tmp; })
|
||||
|
||||
#define csrw(reg, val) ({ \
|
||||
if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
|
||||
asm volatile ("csrw " #reg ", %0" :: "i"(val)); \
|
||||
else \
|
||||
asm volatile ("csrw " #reg ", %0" :: "r"(val)); })
|
||||
|
||||
#define csrs(reg, bit) ({ \
|
||||
if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
|
||||
asm volatile ("csrrs x0, " #reg ", %0" :: "i"(bit)); \
|
||||
else \
|
||||
asm volatile ("csrrs x0, " #reg ", %0" :: "r"(bit)); })
|
||||
|
||||
#define csrc(reg, bit) ({ \
|
||||
if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
|
||||
asm volatile ("csrrc x0, " #reg ", %0" :: "i"(bit)); \
|
||||
else \
|
||||
asm volatile ("csrrc x0, " #reg ", %0" :: "r"(bit)); })
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SYSTEM_H */
|
|
@ -62,6 +62,41 @@ void isr(void)
|
|||
*((unsigned int *)PLIC_CLAIM) = claim;
|
||||
}
|
||||
}
|
||||
#elif defined(__cv32e40p__)
|
||||
|
||||
#define FIRQ_OFFSET 16
|
||||
#define IRQ_MASK 0x7FFFFFFF
|
||||
#define INVINST 2
|
||||
#define ECALL 11
|
||||
#define RISCV_TEST
|
||||
|
||||
void isr(void)
|
||||
{
|
||||
unsigned int cause = csrr(mcause) & IRQ_MASK;
|
||||
|
||||
if (csrr(mcause) & 0x80000000) {
|
||||
#ifndef UART_POLLING
|
||||
if (cause == (UART_INTERRUPT+FIRQ_OFFSET)){
|
||||
uart_isr();
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
#ifdef RISCV_TEST
|
||||
int gp;
|
||||
asm volatile ("mv %0, gp" : "=r"(gp));
|
||||
printf("E %d\n", cause);
|
||||
if (cause == INVINST) {
|
||||
printf("Inv Instr\n");
|
||||
for(;;);
|
||||
}
|
||||
if (cause == ECALL) {
|
||||
printf("Ecall (gp: %d)\n", gp);
|
||||
csrw(mepc, csrr(mepc)+4);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
void isr(void)
|
||||
{
|
||||
|
|
|
@ -50,6 +50,7 @@ repos = [
|
|||
("pythondata-cpu-minerva", ("https://github.com/litex-hub/", False, True, None)),
|
||||
("pythondata-cpu-microwatt", ("https://github.com/litex-hub/", False, True, 0xa7859fb)),
|
||||
("pythondata-cpu-blackparrot", ("https://github.com/litex-hub/", False, True, None)),
|
||||
("pythondata-cpu-cv32e40p", ("https://github.com/litex-hub/", False, True, None)),
|
||||
]
|
||||
|
||||
repos = OrderedDict(repos)
|
||||
|
|
Loading…
Reference in New Issue