soc/cores/cpu/rocket: Support for 64-bit RocketChip (experimental)
authorGabriel L. Somlo <gsomlo@gmail.com>
Thu, 9 May 2019 12:47:06 +0000 (08:47 -0400)
committerGabriel L. Somlo <gsomlo@gmail.com>
Thu, 23 May 2019 19:59:51 +0000 (15:59 -0400)
Simulate a Rocket-based 64-bit LiteX SoC with the following command:

  litex/tools/litex_sim.py [--with-sdram] --cpu-type=rocket

NOTE: Synthesizes to FPGA and passes timing at 50MHz on nexys4ddr
(with vivado) and ecp5versa (with yosys/trellis/nextpnr), but at
this time does not yet properly initialize physical on-board DRAM.
On ecp5versa, using '--with-ethernet', up to 97% of the available
TRELLIS_SLICE capacity is utilized.

Signed-off-by: Gabriel Somlo <gsomlo@gmail.com>
15 files changed:
litex/boards/targets/nexys4ddr.py
litex/boards/targets/versa_ecp5.py
litex/build/sim/core/Makefile
litex/soc/cores/cpu/__init__.py
litex/soc/cores/cpu/rocket/__init__.py [new file with mode: 0644]
litex/soc/cores/cpu/rocket/core.py [new file with mode: 0644]
litex/soc/integration/soc_core.py
litex/soc/software/bios/boot-helper-rocket.S [new file with mode: 0644]
litex/soc/software/bios/isr.c
litex/soc/software/bios/main.c
litex/soc/software/bios/sdram.c
litex/soc/software/include/base/irq.h
litex/soc/software/include/base/system.h
litex/soc/software/libbase/crt0-rocket.S [new file with mode: 0644]
litex/soc/software/libbase/system.c

index 2cb638f092f64abe9a9c5122eca707c394231eee..77fcb5a69eea19847704c8267b1761298e676e12 100755 (executable)
@@ -47,7 +47,7 @@ class _CRG(Module):
 # BaseSoC ------------------------------------------------------------------------------------------
 
 class BaseSoC(SoCSDRAM):
-    def __init__(self, sys_clk_freq=int(100e6), **kwargs):
+    def __init__(self, sys_clk_freq=int(50e6), **kwargs):
         platform = nexys4ddr.Platform()
         SoCSDRAM.__init__(self, platform, clk_freq=sys_clk_freq,
                          integrated_rom_size=0x8000,
index c72037778dcbdc0097dda315ea60fbbdbcc99589..035a32a5277dafa6476d5a30ae631336893a292a 100755 (executable)
@@ -73,7 +73,7 @@ class _CRG(Module):
 # BaseSoC ------------------------------------------------------------------------------------------
 
 class BaseSoC(SoCSDRAM):
-    def __init__(self, sys_clk_freq=int(75e6), toolchain="diamond", **kwargs):
+    def __init__(self, sys_clk_freq=int(50e6), toolchain="diamond", **kwargs):
         platform = versa_ecp5.Platform(toolchain=toolchain)
         SoCSDRAM.__init__(self, platform, clk_freq=sys_clk_freq,
                           integrated_rom_size=0x8000,
index 9adb97630820e0198e5d0f9fc30658c355f4e56e..3737af82306abffc36fbcafa5b4f5072e8a7cb99 100644 (file)
@@ -27,6 +27,7 @@ $(OBJS_SIM): %.o: $(SRC_DIR)/%.c
 .PHONY: sim
 sim: mkdir $(OBJS_SIM)
        verilator -Wno-fatal -O3 $(CC_SRCS) --top-module dut --exe \
+               -DPRINTF_COND=0 \
                $(SRCS_SIM_CPP) $(OBJS_SIM) \
                --top-module dut \
                $(if $(THREADS), --threads $(THREADS),) \
index 5eccde2dc7c3bc0b9307c8424d4ce20a2200086a..5b4877c347aac816c5a4638ccf5db803d6d2a518 100644 (file)
@@ -3,3 +3,4 @@ from litex.soc.cores.cpu.mor1kx import MOR1KX
 from litex.soc.cores.cpu.picorv32 import PicoRV32
 from litex.soc.cores.cpu.vexriscv import VexRiscv
 from litex.soc.cores.cpu.minerva import Minerva
+from litex.soc.cores.cpu.rocket import RocketRV64
diff --git a/litex/soc/cores/cpu/rocket/__init__.py b/litex/soc/cores/cpu/rocket/__init__.py
new file mode 100644 (file)
index 0000000..b9a9061
--- /dev/null
@@ -0,0 +1 @@
+from litex.soc.cores.cpu.rocket.core import RocketRV64
diff --git a/litex/soc/cores/cpu/rocket/core.py b/litex/soc/cores/cpu/rocket/core.py
new file mode 100644 (file)
index 0000000..56eecf8
--- /dev/null
@@ -0,0 +1,242 @@
+# litex/soc/cores/cpu/rocket/core.py
+# Rocket Chip core support for the LiteX SoC.
+#
+# Author: Gabriel L. Somlo <somlo@cmu.edu>
+# Copyright (c) 2019, Carnegie Mellon University
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#
+#     * Redistributions in binary form must reproduce the above
+#       copyright notice, this list of conditions and the following
+#       disclaimer in the documentation and/or other materials provided
+#       with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import os
+
+from migen import *
+
+from litex.soc.interconnect import axi
+from litex.soc.interconnect import wishbone
+
+CPU_VARIANTS = ["standard"]
+
+GCC_FLAGS = {
+    "standard": "-march=rv64imac -mabi=lp64 ",
+}
+
+class RocketRV64(Module):
+    @property
+    def name(self):
+        return "rocket"
+
+    @property
+    def endianness(self):
+        return "little"
+
+    @property
+    def gcc_triple(self):
+        return ("riscv64-unknown-elf")
+
+    @property
+    def gcc_flags(self):
+        flags =  "-mno-save-restore "
+        flags += GCC_FLAGS[self.variant]
+        flags += "-D__rocket__ "
+        return flags
+
+    @property
+    def linker_output_format(self):
+        return "elf64-littleriscv"
+
+    @property
+    def reserved_interrupts(self):
+        return {}
+
+    def __init__(self, platform, cpu_reset_addr, variant="standard"):
+        assert variant in CPU_VARIANTS, "Unsupported variant %s" % variant
+        assert cpu_reset_addr == 0x10000000, "cpu_reset_addr hardcoded in Chisel elaboration!"
+
+        self.platform = platform
+        self.variant = variant
+        self.reset = Signal()
+
+        self.interrupt = Signal(4)
+
+        self.mem_axi = mem_axi = axi.AXIInterface(
+            data_width=64, address_width=32, id_width=4)
+        self.mmio_axi = mmio_axi = axi.AXIInterface(
+            data_width=64, address_width=32, id_width=4)
+
+        self.mem_wb = mem_wb = wishbone.Interface(data_width=64, adr_width=29)
+        self.mmio_wb = mmio_wb = wishbone.Interface(data_width=64, adr_width=29)
+
+        self.ibus = ibus = wishbone.Interface()
+        self.dbus = dbus = wishbone.Interface()
+
+
+        # # #
+
+        self.specials += Instance("ExampleRocketSystem",
+            # clock, reset
+            i_clock=ClockSignal(),
+            i_reset=ResetSignal() | self.reset,
+
+            # debug (ignored)
+            #o_debug_clockeddmi_dmi_req_ready=,
+            i_debug_clockeddmi_dmi_req_valid=0,
+            i_debug_clockeddmi_dmi_req_bits_addr=0,
+            i_debug_clockeddmi_dmi_req_bits_data=0,
+            i_debug_clockeddmi_dmi_req_bits_op=0,
+            i_debug_clockeddmi_dmi_resp_ready=0,
+            #o_debug_clockeddmi_dmi_resp_valid=,
+            #o_debug_clockeddmi_dmi_resp_bits_data=,
+            #o_debug_clockeddmi_dmi_resp_bits_resp=,
+            i_debug_clockeddmi_dmiClock=0,
+            i_debug_clockeddmi_dmiReset=0,
+            #o_debug_ndreset=,
+            #o_debug_dmactive=,
+
+
+            # irq
+            i_interrupts=self.interrupt,
+
+            # axi memory (L1-cached)
+            i_mem_axi4_0_aw_ready=mem_axi.aw.ready,
+            o_mem_axi4_0_aw_valid=mem_axi.aw.valid,
+            o_mem_axi4_0_aw_bits_id=mem_axi.aw.id,
+            o_mem_axi4_0_aw_bits_addr=mem_axi.aw.addr,
+            o_mem_axi4_0_aw_bits_len=mem_axi.aw.len,
+            o_mem_axi4_0_aw_bits_size=mem_axi.aw.size,
+            o_mem_axi4_0_aw_bits_burst=mem_axi.aw.burst,
+            o_mem_axi4_0_aw_bits_lock=mem_axi.aw.lock,
+            o_mem_axi4_0_aw_bits_cache=mem_axi.aw.cache,
+            o_mem_axi4_0_aw_bits_prot=mem_axi.aw.prot,
+            o_mem_axi4_0_aw_bits_qos=mem_axi.aw.qos,
+
+            i_mem_axi4_0_w_ready=mem_axi.w.ready,
+            o_mem_axi4_0_w_valid=mem_axi.w.valid,
+            o_mem_axi4_0_w_bits_data=mem_axi.w.data,
+            o_mem_axi4_0_w_bits_strb=mem_axi.w.strb,
+            o_mem_axi4_0_w_bits_last=mem_axi.w.last,
+
+            o_mem_axi4_0_b_ready=mem_axi.b.ready,
+            i_mem_axi4_0_b_valid=mem_axi.b.valid,
+            i_mem_axi4_0_b_bits_id=mem_axi.b.id,
+            i_mem_axi4_0_b_bits_resp=mem_axi.b.resp,
+
+            i_mem_axi4_0_ar_ready=mem_axi.ar.ready,
+            o_mem_axi4_0_ar_valid=mem_axi.ar.valid,
+            o_mem_axi4_0_ar_bits_id=mem_axi.ar.id,
+            o_mem_axi4_0_ar_bits_addr=mem_axi.ar.addr,
+            o_mem_axi4_0_ar_bits_len=mem_axi.ar.len,
+            o_mem_axi4_0_ar_bits_size=mem_axi.ar.size,
+            o_mem_axi4_0_ar_bits_burst=mem_axi.ar.burst,
+            o_mem_axi4_0_ar_bits_lock=mem_axi.ar.lock,
+            o_mem_axi4_0_ar_bits_cache=mem_axi.ar.cache,
+            o_mem_axi4_0_ar_bits_prot=mem_axi.ar.prot,
+            o_mem_axi4_0_ar_bits_qos=mem_axi.ar.qos,
+
+            o_mem_axi4_0_r_ready=mem_axi.r.ready,
+            i_mem_axi4_0_r_valid=mem_axi.r.valid,
+            i_mem_axi4_0_r_bits_id=mem_axi.r.id,
+            i_mem_axi4_0_r_bits_data=mem_axi.r.data,
+            i_mem_axi4_0_r_bits_resp=mem_axi.r.resp,
+            i_mem_axi4_0_r_bits_last=mem_axi.r.last,
+
+            # axi mmio (not cached)
+            i_mmio_axi4_0_aw_ready=mmio_axi.aw.ready,
+            o_mmio_axi4_0_aw_valid=mmio_axi.aw.valid,
+            o_mmio_axi4_0_aw_bits_id=mmio_axi.aw.id,
+            o_mmio_axi4_0_aw_bits_addr=mmio_axi.aw.addr,
+            o_mmio_axi4_0_aw_bits_len=mmio_axi.aw.len,
+            o_mmio_axi4_0_aw_bits_size=mmio_axi.aw.size,
+            o_mmio_axi4_0_aw_bits_burst=mmio_axi.aw.burst,
+            o_mmio_axi4_0_aw_bits_lock=mmio_axi.aw.lock,
+            o_mmio_axi4_0_aw_bits_cache=mmio_axi.aw.cache,
+            o_mmio_axi4_0_aw_bits_prot=mmio_axi.aw.prot,
+            o_mmio_axi4_0_aw_bits_qos=mmio_axi.aw.qos,
+
+            i_mmio_axi4_0_w_ready=mmio_axi.w.ready,
+            o_mmio_axi4_0_w_valid=mmio_axi.w.valid,
+            o_mmio_axi4_0_w_bits_data=mmio_axi.w.data,
+            o_mmio_axi4_0_w_bits_strb=mmio_axi.w.strb,
+            o_mmio_axi4_0_w_bits_last=mmio_axi.w.last,
+
+            o_mmio_axi4_0_b_ready=mmio_axi.b.ready,
+            i_mmio_axi4_0_b_valid=mmio_axi.b.valid,
+            i_mmio_axi4_0_b_bits_id=mmio_axi.b.id,
+            i_mmio_axi4_0_b_bits_resp=mmio_axi.b.resp,
+
+            i_mmio_axi4_0_ar_ready=mmio_axi.ar.ready,
+            o_mmio_axi4_0_ar_valid=mmio_axi.ar.valid,
+            o_mmio_axi4_0_ar_bits_id=mmio_axi.ar.id,
+            o_mmio_axi4_0_ar_bits_addr=mmio_axi.ar.addr,
+            o_mmio_axi4_0_ar_bits_len=mmio_axi.ar.len,
+            o_mmio_axi4_0_ar_bits_size=mmio_axi.ar.size,
+            o_mmio_axi4_0_ar_bits_burst=mmio_axi.ar.burst,
+            o_mmio_axi4_0_ar_bits_lock=mmio_axi.ar.lock,
+            o_mmio_axi4_0_ar_bits_cache=mmio_axi.ar.cache,
+            o_mmio_axi4_0_ar_bits_prot=mmio_axi.ar.prot,
+            o_mmio_axi4_0_ar_bits_qos=mmio_axi.ar.qos,
+
+            o_mmio_axi4_0_r_ready=mmio_axi.r.ready,
+            i_mmio_axi4_0_r_valid=mmio_axi.r.valid,
+            i_mmio_axi4_0_r_bits_id=mmio_axi.r.id,
+            i_mmio_axi4_0_r_bits_data=mmio_axi.r.data,
+            i_mmio_axi4_0_r_bits_resp=mmio_axi.r.resp,
+            i_mmio_axi4_0_r_bits_last=mmio_axi.r.last,
+        )
+
+        # adapt axi interfaces to wishbone
+        mem_a2w = ResetInserter()(
+            axi.AXI2Wishbone(mem_axi, mem_wb, base_address=0))
+        mmio_a2w = ResetInserter()(
+            axi.AXI2Wishbone(mmio_axi, mmio_wb, base_address=0))
+        # NOTE: AXI2Wishbone FSMs must be reset with the CPU!
+        self.comb += [
+            mem_a2w.reset.eq(ResetSignal() | self.reset),
+            mmio_a2w.reset.eq(ResetSignal() | self.reset),
+        ]
+
+        # down-convert wishbone from 64 to 32 bit data width
+        mem_dc = wishbone.Converter(mem_wb, ibus)
+        mmio_dc = wishbone.Converter(mmio_wb, dbus)
+
+        self.submodules += mem_a2w, mem_dc, mmio_a2w, mmio_dc
+
+        # add verilog sources
+        self.add_sources(platform)
+
+    @staticmethod
+    def add_sources(platform):
+        vdir = os.path.join(
+            os.path.abspath(os.path.dirname(__file__)), "verilog")
+        platform.add_sources(
+            os.path.join(vdir, "generated-src"),
+            "freechips.rocketchip.system.LitexConfig.v",
+            "freechips.rocketchip.system.LitexConfig.behav_srams.v",
+        )
+        platform.add_sources(
+            os.path.join(vdir, "vsrc"),
+            "plusarg_reader.v",
+            "AsyncResetReg.v",
+            "EICG_wrapper.v",
+        )
index 981027c415ef5b2b42160f250c70fd889e65fc26..236b822a9a22e3457f40f71742bff5c06cc6863d 100644 (file)
@@ -167,8 +167,9 @@ class SoCCore(Module):
     csr_map = {}
     interrupt_map = {}
     mem_map = {
-        "rom":      0x00000000,  # (default shadow @0x80000000)
-        "sram":     0x10000000,  # (default shadow @0x90000000)
+        # RocketChip reserves the first 256MBytes for internal use
+        "rom":      0x10000000,  # (default shadow @0x90000000)
+        "sram":     0x20000000,  # (default shadow @0xa0000000)
         "main_ram": 0x40000000,  # (default shadow @0xc0000000)
         "csr":      0x60000000,  # (default shadow @0xe0000000)
     }
@@ -267,6 +268,8 @@ class SoCCore(Module):
                 self.add_cpu(vexriscv.VexRiscv(platform, self.cpu_reset_address, self.cpu_variant))
             elif cpu_type == "minerva":
                 self.add_cpu(minerva.Minerva(platform, self.cpu_reset_address, self.cpu_variant))
+            elif cpu_type == "rocket":
+                self.add_cpu(rocket.RocketRV64(platform, self.cpu_reset_address, self.cpu_variant))
             else:
                 raise ValueError("Unsupported CPU type: {}".format(cpu_type))
             self.add_csr("cpu", allow_user_defined=True)
diff --git a/litex/soc/software/bios/boot-helper-rocket.S b/litex/soc/software/bios/boot-helper-rocket.S
new file mode 100644 (file)
index 0000000..6dd74aa
--- /dev/null
@@ -0,0 +1,4 @@
+.section    .text, "ax", @progbits
+.global     boot_helper
+boot_helper:
+       jr x13
index c49d31d8dbd8b6bcb88774d504f619eaee04fb0c..87b67ba038ee78e68d79876c91f5dae01b285cab 100644 (file)
@@ -1,14 +1,57 @@
 #include <generated/csr.h>
 #include <irq.h>
 #include <uart.h>
+#include <stdio.h>
+
+#ifdef __rocket__
+void plic_init(void);
+void plic_init(void)
+{
+       int i;
+
+       // priorities for interrupt pins 1..4
+       for (i = 1; i <= 4; i++)
+               csr_writel(1, PLIC_BASE + 4*i);
+       // enable interrupt pins 1..4
+       csr_writel(0xf << 1, PLIC_ENABLED);
+       // set priority threshold to 0 (any priority > 0 triggers interrupt)
+       csr_writel(0, PLIC_THRSHLD);
+}
 
+void isr(void);
+void isr(void)
+{
+       unsigned int claim;
+
+       while ((claim = csr_readl(PLIC_CLAIM))) {
+               switch (claim - 1) {
+               case UART_INTERRUPT:
+                       uart_isr();
+                       break;
+               default:
+                       printf("## PLIC: Unhandled claim: %d\n", claim);
+                       printf("# plic_enabled:    %08x\n", irq_getmask());
+                       printf("# plic_pending:    %08x\n", irq_pending());
+                       printf("# mepc:    %016lx\n", csrr(mepc));
+                       printf("# mcause:  %016lx\n", csrr(mcause));
+                       printf("# mtval:   %016lx\n", csrr(mtval));
+                       printf("# mie:     %016lx\n", csrr(mie));
+                       printf("# mip:     %016lx\n", csrr(mip));
+                       printf("###########################\n\n");
+                       break;
+               }
+               csr_writel(claim, PLIC_CLAIM);
+       }
+}
+#else
 void isr(void);
 void isr(void)
 {
        unsigned int irqs;
-       
+
        irqs = irq_pending() & irq_getmask();
-       
+
        if(irqs & (1 << UART_INTERRUPT))
                uart_isr();
 }
+#endif
index bfebfe8c679b1f937d6c981ae44f18c611e33c3a..de943d9086414bdacf5bec04be2706db7cb041ab 100644 (file)
@@ -416,6 +416,8 @@ int main(int i, char **c)
        printf("VexRiscv");
 #elif __minerva__
        printf("Minerva");
+#elif __rocket__
+       printf("RocketRV64[imac]");
 #else
        printf("Unknown");
 #endif
index ebd53130e186192dbaa6c5346d690914339acbab..948f2cbf31acc7f84db841f97173844acd9abf20 100644 (file)
@@ -30,6 +30,8 @@ __attribute__((unused)) static void cdelay(int i)
                __asm__ volatile("nop");
 #elif defined (__minerva__)
                __asm__ volatile("nop");
+#elif defined (__rocket__)
+               __asm__ volatile("nop");
 #else
 #error Unsupported architecture
 #endif
index 19f00b1c55b34afb1e053ff8f6b7d0a334265094..4bf6786c4569af6209a338a5a3558fd7eda5f423 100644 (file)
@@ -6,6 +6,7 @@ extern "C" {
 #endif
 
 #include <system.h>
+#include <generated/csr.h>
 
 #ifdef __picorv32__
 // PicoRV32 has a very limited interrupt support, implemented via custom
@@ -28,6 +29,17 @@ extern void _irq_disable(void);
 extern void _irq_setmask(unsigned int);
 #endif
 
+#ifdef __rocket__
+// The RocketChip uses a Platform-Level Interrupt Controller (PLIC) which
+// is programmed and queried via a set of MMIO registers.
+
+#define PLIC_BASE    0x0c000000L // Base address and per-pin priority array
+#define PLIC_PENDING 0x0c001000L // Bit field matching currently pending pins
+#define PLIC_ENABLED 0x0c002000L // Bit field corresponding to the current mask
+#define PLIC_THRSHLD 0x0c200000L // Per-pin priority must be >= this to trigger
+#define PLIC_CLAIM   0x0c200004L // Claim & completion register address
+#endif /* __rocket__ */
+
 static inline unsigned int irq_getie(void)
 {
 #if defined (__lm32__)
@@ -42,6 +54,8 @@ static inline unsigned int irq_getie(void)
        return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0;
 #elif defined (__minerva__)
        return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0;
+#elif defined (__rocket__)
+       return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0;
 #else
 #error Unsupported architecture
 #endif
@@ -65,6 +79,8 @@ static inline void irq_setie(unsigned int ie)
        if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE);
 #elif defined (__minerva__)
        if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE);
+#elif defined (__rocket__)
+       if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE);
 #else
 #error Unsupported architecture
 #endif
@@ -90,6 +106,8 @@ static inline unsigned int irq_getmask(void)
        unsigned int mask;
        asm volatile ("csrr %0, %1" : "=r"(mask) : "i"(CSR_IRQ_MASK));
        return mask;
+#elif defined (__rocket__)
+       return csr_readl(PLIC_ENABLED) >> 1;
 #else
 #error Unsupported architecture
 #endif
@@ -109,6 +127,8 @@ static inline void irq_setmask(unsigned int mask)
        asm volatile ("csrw %0, %1" :: "i"(CSR_IRQ_MASK), "r"(mask));
 #elif defined (__minerva__)
        asm volatile ("csrw %0, %1" :: "i"(CSR_IRQ_MASK), "r"(mask));
+#elif defined (__rocket__)
+       csr_writel(mask << 1, PLIC_ENABLED);
 #else
 #error Unsupported architecture
 #endif
@@ -132,6 +152,8 @@ static inline unsigned int irq_pending(void)
        unsigned int pending;
        asm volatile ("csrr %0, %1" : "=r"(pending) : "i"(CSR_IRQ_PENDING));
        return pending;
+#elif defined (__rocket__)
+       return csr_readl(PLIC_PENDING) >> 1;
 #else
 #error Unsupported architecture
 #endif
index 2d108d2c1a5ddcba882fdf2a746f4ff6343741d8..9b41a737ecd484febc7142e1658e5d48c5f0a977 100644 (file)
@@ -27,7 +27,7 @@ static inline void mtspr(unsigned long add, unsigned long val)
 #endif
 
 
-#if defined(__vexriscv__) || defined(__minerva__)
+#if defined(__vexriscv__) || defined(__minerva__) || defined(__rocket__)
 #include <csr-defs.h>
 #define csrr(reg) ({ unsigned long __tmp; \
   asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
diff --git a/litex/soc/software/libbase/crt0-rocket.S b/litex/soc/software/libbase/crt0-rocket.S
new file mode 100644 (file)
index 0000000..69b9d57
--- /dev/null
@@ -0,0 +1,77 @@
+.global main
+.global isr
+.global _start
+
+_start:
+  j crt_init
+  nop
+  nop
+  nop
+  nop
+  nop
+  nop
+  nop
+
+trap_entry:
+  sd x1,  - 1*8(sp)
+  sd x5,  - 2*8(sp)
+  sd x6,  - 3*8(sp)
+  sd x7,  - 4*8(sp)
+  sd x10, - 5*8(sp)
+  sd x11, - 6*8(sp)
+  sd x12, - 7*8(sp)
+  sd x13, - 8*8(sp)
+  sd x14, - 9*8(sp)
+  sd x15, -10*8(sp)
+  sd x16, -11*8(sp)
+  sd x17, -12*8(sp)
+  sd x28, -13*8(sp)
+  sd x29, -14*8(sp)
+  sd x30, -15*8(sp)
+  sd x31, -16*8(sp)
+  addi sp,sp,-16*8
+  call isr
+  ld x1 , 15*8(sp)
+  ld x5,  14*8(sp)
+  ld x6,  13*8(sp)
+  ld x7,  12*8(sp)
+  ld x10, 11*8(sp)
+  ld x11, 10*8(sp)
+  ld x12,  9*8(sp)
+  ld x13,  8*8(sp)
+  ld x14,  7*8(sp)
+  ld x15,  6*8(sp)
+  ld x16,  5*8(sp)
+  ld x17,  4*8(sp)
+  ld x28,  3*8(sp)
+  ld x29,  2*8(sp)
+  ld x30,  1*8(sp)
+  ld x31,  0*8(sp)
+  addi sp,sp,16*8
+  mret
+  .text
+
+
+crt_init:
+  la sp, _fstack + 8
+  la a0, trap_entry
+  csrw mtvec, a0
+
+bss_init:
+  la a0, _fbss
+  la a1, _ebss
+bss_loop:
+  beq a0,a1,bss_done
+  sd zero,0(a0)
+  add a0,a0,8
+  j bss_loop
+bss_done:
+
+  call plic_init // initialize external interrupt controller
+  li a0, 0x800   // external interrupt sources only (using LiteX timer);
+                 // NOTE: must still enable mstatus.MIE!
+  csrw mie,a0
+
+  call main
+inf_loop:
+  j inf_loop
index 3fa1fc29e166c2d9f0c6bec4672bde6bdcdd2b29..8f437bc71f45c10bdfccd08fd3d0d8048db2fe83 100644 (file)
@@ -53,6 +53,9 @@ void flush_cpu_icache(void)
 #elif defined (__minerva__)
        /* no instruction cache */
        asm volatile("nop");
+#elif defined (__rocket__)
+       /* FIXME: do something useful here! */
+       asm volatile("nop");
 #else
 #error Unsupported architecture
 #endif
@@ -95,6 +98,9 @@ void flush_cpu_dcache(void)
 #elif defined (__minerva__)
        /* no data cache */
        asm volatile("nop");
+#elif defined (__rocket__)
+       /* FIXME: do something useful here! */
+       asm volatile("nop");
 #else
 #error Unsupported architecture
 #endif