From 41564cc47b86b83e060daeaa1a22848659eb6534 Mon Sep 17 00:00:00 2001 From: Nuntipat Narkthong Date: Mon, 13 May 2024 16:03:23 -0400 Subject: [PATCH] Update CV32E40P to be based on the OpenHW Group's repo --- litex/soc/cores/cpu/cv32e40p/core.py | 185 ++++-------------------- litex/soc/cores/cpu/cv32e40p/crt0.S | 6 +- litex/soc/cores/cpu/cv32e40p/csr-defs.h | 9 +- litex/soc/cores/cpu/cv32e40p/irq.h | 10 +- litex/soc/cores/cpu/cv32e40p/system.h | 13 +- 5 files changed, 42 insertions(+), 181 deletions(-) diff --git a/litex/soc/cores/cpu/cv32e40p/core.py b/litex/soc/cores/cpu/cv32e40p/core.py index 79dfbeb1d..682635f40 100644 --- a/litex/soc/cores/cpu/cv32e40p/core.py +++ b/litex/soc/cores/cpu/cv32e40p/core.py @@ -19,7 +19,7 @@ from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_RISCV32 # Variants ----------------------------------------------------------------------------------------- -CPU_VARIANTS = ["standard", "full"] +CPU_VARIANTS = ["standard", "standard+fpu"] # GCC Flags ---------------------------------------------------------------------------------------- @@ -32,7 +32,7 @@ GCC_FLAGS = { # | ||||/-- Double-Precision Floating-Point # i macfd "standard": "-march=rv32i2p0_mc -mabi=ilp32 ", - "full": "-march=rv32i2p0_mfc -mabi=ilp32 ", + "standard+fpu": "-march=rv32i2p0_mfc -mabi=ilp32 ", } # OBI / APB / Trace Layouts ------------------------------------------------------------------------ @@ -59,18 +59,6 @@ apb_layout = [ ("pslverr", 1), ] -trace_layout = [ - ("ivalid", 1), - ("iexception", 1), - ("interrupt", 1), - ("cause", 5), - ("tval", 32), - ("priv", 3), - ("iaddr", 32), - ("instr", 32), - ("compressed", 1), -] - # Helpers ------------------------------------------------------------------------------------------ def add_manifest_sources(platform, manifest): @@ -182,102 +170,6 @@ class Wishbone2APB(LiteXModule): wb.dat_r.eq(apb.prdata), ] -# Trace Collector ---------------------------------------------------------------------------------- - -class TraceCollector(LiteXModule): - def __init__(self, trace_depth=16384): - self.bus = bus = wishbone.Interface(data_width=32, address_width=32, addressing="word") - 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), - ] - -# Trace Debugger ----------------------------------------------------------------------------------- - -class TraceDebugger(LiteXModule): - def __init__(self): - self.bus = wishbone.Interface(data_width=32, address_width=32, addressing="word") - self.source = source = stream.Endpoint([("data", 32)]) - self.trace_if = trace_if = Record(trace_layout) - - apb = Record(apb_layout) - - self.bus_conv = Wishbone2APB(self.bus, apb) - - self.trace_params = dict( - # Clk / Rst. - i_clk_i = ClockSignal("sys"), - i_rst_ni = ~ResetSignal("sys"), - 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") - # Debug Module ------------------------------------------------------------------------------------- class DebugModule(LiteXModule): @@ -350,10 +242,6 @@ class DebugModule(LiteXModule): self.specials += Instance("dm_wrap", **self.dm_params) - @staticmethod - def add_sources(platform): - add_manifest_sources(platform, "cv32e40p_dm_manifest.flist") - # CV32E40P ----------------------------------------------------------------------------------------- class CV32E40P(CPU): @@ -368,8 +256,7 @@ class CV32E40P(CPU): linker_output_format = "elf32-littleriscv" nop = "nop" io_regions = {0x80000000: 0x80000000} # Origin, Length. - - has_fpu = ["full"] + has_fpu = ["standard+fpu"] # GCC Flags. @property @@ -379,14 +266,15 @@ class CV32E40P(CPU): return flags def __init__(self, platform, variant="standard"): - self.platform = platform - self.variant = variant - self.reset = Signal() - self.ibus = wishbone.Interface(data_width=32, address_width=32, addressing="word") - self.dbus = wishbone.Interface(data_width=32, address_width=32, addressing="word") - self.periph_buses = [self.ibus, self.dbus] - self.memory_buses = [] - self.interrupt = Signal(15) + self.platform = platform + self.variant = variant + self.reset = Signal() + self.ibus = wishbone.Interface(data_width=32, address_width=32, addressing="word") + self.dbus = wishbone.Interface(data_width=32, address_width=32, addressing="word") + self.periph_buses = [self.ibus, self.dbus] + self.memory_buses = [] + self.interrupt = Signal(16) + self.interrupt_padding = Signal(16) ibus = Record(obi_layout) dbus = Record(obi_layout) @@ -406,11 +294,12 @@ class CV32E40P(CPU): i_rst_ni = ~ResetSignal("sys"), # Controls. - 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, + i_pulp_clock_en_i = 1, + i_scan_cg_en_i = 0, + i_mtvec_addr_i = 0, + i_dm_halt_addr_i = 0, + i_hart_id_i = 0, + i_dm_exception_addr_i = 0, # IBus. o_instr_req_o = ibus.req, @@ -429,56 +318,32 @@ class CV32E40P(CPU): 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, + i_irq_i = Cat(self.interrupt_padding, self.interrupt), # Debug. - i_debug_req_i = 0, + i_debug_req_i = 0, # CPU Control. - i_fetch_enable_i = 1, + i_fetch_enable_i = 1, ) # Add Verilog sources. - add_manifest_sources(platform, 'cv32e40p_manifest.flist') - - # Specific FPU variant parameters/files. if variant in self.has_fpu: + # Specific FPU variant parameters/files. self.cpu_params.update(p_FPU=1) add_manifest_sources(platform, 'cv32e40p_fpu_manifest.flist') + else: + add_manifest_sources(platform, 'cv32e40p_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("sys") | 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): 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) + self.specials += Instance("cv32e40p_core", **self.cpu_params) diff --git a/litex/soc/cores/cpu/cv32e40p/crt0.S b/litex/soc/cores/cpu/cv32e40p/crt0.S index 904cecde8..0773c4b5a 100644 --- a/litex/soc/cores/cpu/cv32e40p/crt0.S +++ b/litex/soc/cores/cpu/cv32e40p/crt0.S @@ -46,7 +46,7 @@ vector_table: j trap_entry # 28 firq12 j trap_entry # 29 firq13 j trap_entry # 30 firq14 - j trap_entry # 31 unused + j trap_entry # 31 firq15 .global trap_entry trap_entry: @@ -116,10 +116,8 @@ bss_loop: 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) + li a0, 0xFFFF0880 //FFFF0880 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 diff --git a/litex/soc/cores/cpu/cv32e40p/csr-defs.h b/litex/soc/cores/cpu/cv32e40p/csr-defs.h index d98e8dfb7..0f1907be7 100644 --- a/litex/soc/cores/cpu/cv32e40p/csr-defs.h +++ b/litex/soc/cores/cpu/cv32e40p/csr-defs.h @@ -1,11 +1,14 @@ #ifndef CSR_DEFS__H #define CSR_DEFS__H +/*Reference : https://docs.openhwgroup.org/projects/cv32e40p-user-manual/en/latest/control_status_registers.html */ + #define CSR_MSTATUS_MIE 0x8 -#define CSR_IRQ_MASK 0xBC0 -#define CSR_IRQ_PENDING 0xFC0 - +#define CSR_IRQ_MASK 0x304 +#define CSR_IRQ_PENDING 0x344 +#define FIRQ_OFFSET 16 #define CSR_DCACHE_INFO 0xCC0 + #endif /* CSR_DEFS__H */ diff --git a/litex/soc/cores/cpu/cv32e40p/irq.h b/litex/soc/cores/cpu/cv32e40p/irq.h index f1dd4c285..c11829bfc 100644 --- a/litex/soc/cores/cpu/cv32e40p/irq.h +++ b/litex/soc/cores/cpu/cv32e40p/irq.h @@ -20,17 +20,21 @@ static inline void irq_setie(unsigned int ie) static inline unsigned int irq_getmask(void) { - return 0; // FIXME + unsigned int mask; + asm volatile ("csrr %0, %1" : "=r"(mask) : "i"(CSR_IRQ_MASK)); + return (mask >> FIRQ_OFFSET); } static inline void irq_setmask(unsigned int mask) { - // FIXME + asm volatile ("csrw %0, %1" :: "i"(CSR_IRQ_MASK), "r"(mask << FIRQ_OFFSET)); } static inline unsigned int irq_pending(void) { - return 0;// FIXME + unsigned int pending; + asm volatile ("csrr %0, %1" : "=r"(pending) : "i"(CSR_IRQ_PENDING)); + return (pending >> FIRQ_OFFSET); } #ifdef __cplusplus diff --git a/litex/soc/cores/cpu/cv32e40p/system.h b/litex/soc/cores/cpu/cv32e40p/system.h index fa134fc38..4ac36faa7 100644 --- a/litex/soc/cores/cpu/cv32e40p/system.h +++ b/litex/soc/cores/cpu/cv32e40p/system.h @@ -7,17 +7,8 @@ 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"); -} +__attribute__((unused)) static void flush_cpu_icache(void){}; /* No instruction cache */ +__attribute__((unused)) static void flush_cpu_dcache(void){}; /* No instruction cache */ void flush_l2_cache(void);