add VexRiscv support (imported/adapted from misoc)
authorDolu1990 <charles.papon.90@gmail.com>
Wed, 9 May 2018 12:31:05 +0000 (14:31 +0200)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Wed, 9 May 2018 13:03:37 +0000 (15:03 +0200)
14 files changed:
litex/soc/cores/cpu/vexriscv/__init__.py [new file with mode: 0644]
litex/soc/cores/cpu/vexriscv/core.py [new file with mode: 0644]
litex/soc/integration/cpu_interface.py
litex/soc/integration/soc_core.py
litex/soc/software/bios/Makefile
litex/soc/software/bios/boot-helper-vexriscv.S [new file with mode: 0644]
litex/soc/software/bios/main.c
litex/soc/software/bios/sdram.c
litex/soc/software/include/base/csr-defs.h [new file with mode: 0644]
litex/soc/software/include/base/irq.h
litex/soc/software/include/base/system.h
litex/soc/software/libbase/crt0-vexriscv.S [new file with mode: 0644]
litex/soc/software/libbase/system.c
litex/soc/tools/mkmscimg.py

diff --git a/litex/soc/cores/cpu/vexriscv/__init__.py b/litex/soc/cores/cpu/vexriscv/__init__.py
new file mode 100644 (file)
index 0000000..068cc2e
--- /dev/null
@@ -0,0 +1 @@
+from litex.soc.cores.cpu.vexriscv.core import VexRiscv
diff --git a/litex/soc/cores/cpu/vexriscv/core.py b/litex/soc/cores/cpu/vexriscv/core.py
new file mode 100644 (file)
index 0000000..68aea9d
--- /dev/null
@@ -0,0 +1,50 @@
+import os
+
+from migen import *
+
+from litex.soc.interconnect import wishbone
+
+
+class VexRiscv(Module):
+    def __init__(self, platform, cpu_reset_address):
+        self.ibus = i = wishbone.Interface()
+        self.dbus = d = wishbone.Interface()
+
+        self.interrupt = Signal(32)
+
+        self.specials += Instance("VexRiscv",
+                                  i_clk=ClockSignal(),
+                                  i_reset=ResetSignal(),
+
+                                  i_externalResetVector=cpu_reset_address,
+                                  i_externalInterruptArray=self.interrupt,
+                                  i_timerInterrupt=0,
+
+                                  o_iBusWishbone_ADR=i.adr,
+                                  o_iBusWishbone_DAT_MOSI=i.dat_w,
+                                  o_iBusWishbone_SEL=i.sel,
+                                  o_iBusWishbone_CYC=i.cyc,
+                                  o_iBusWishbone_STB=i.stb,
+                                  o_iBusWishbone_WE=i.we,
+                                  o_iBusWishbone_CTI=i.cti,
+                                  o_iBusWishbone_BTE=i.bte,
+                                  i_iBusWishbone_DAT_MISO=i.dat_r,
+                                  i_iBusWishbone_ACK=i.ack,
+                                  i_iBusWishbone_ERR=i.err,
+
+                                  o_dBusWishbone_ADR=d.adr,
+                                  o_dBusWishbone_DAT_MOSI=d.dat_w,
+                                  o_dBusWishbone_SEL=d.sel,
+                                  o_dBusWishbone_CYC=d.cyc,
+                                  o_dBusWishbone_STB=d.stb,
+                                  o_dBusWishbone_WE=d.we,
+                                  o_dBusWishbone_CTI=d.cti,
+                                  o_dBusWishbone_BTE=d.bte,
+                                  i_dBusWishbone_DAT_MISO=d.dat_r,
+                                  i_dBusWishbone_ACK=d.ack,
+                                  i_dBusWishbone_ERR=d.err)
+
+        # add Verilog sources
+        vdir = os.path.join(os.path.abspath(os.path.dirname(__file__)), "verilog")
+        platform.add_sources(os.path.join(vdir), "VexRiscv.v")
+        platform.add_verilog_include_path(vdir)
index b3463bcce265ee064675aaf74fa96a0166866bf0..8e755202c7f48aab2a9e339dcd855f32ed4b14d2 100644 (file)
@@ -7,7 +7,8 @@ from litex.soc.interconnect.csr import CSRStatus
 cpu_endianness = {
     "lm32": "big",
     "or1k": "big",
-    "picorv32": "little"
+    "picorv32": "little",
+    "vexriscv": "little"
 }
 
 def get_cpu_mak(cpu):
@@ -37,6 +38,11 @@ def get_cpu_mak(cpu):
         triple = "riscv32-unknown-elf"
         cpuflags = "-D__picorv32__ -mno-save-restore -march=rv32im -mabi=ilp32"
         clang = False
+    elif cpu == "vexriscv":
+        assert not clang, "vexrisv not supported with clang."
+        triple = "riscv32-unknown-elf"
+        cpuflags = "-D__vexriscv__ -march=rv32im  -mabi=ilp32"
+        clang = False
     else:
         raise ValueError("Unsupported CPU type: "+cpu)
 
@@ -54,7 +60,8 @@ def get_linker_output_format(cpu_type):
     linker_output_formats = {
         "lm32": "elf32-lm32",
         "or1k": "elf32-or1k",
-        "picorv32": "elf32-littleriscv"
+        "picorv32": "elf32-littleriscv",
+        "vexriscv": "elf32-littleriscv"
     }
     return "OUTPUT_FORMAT(\"" + linker_output_formats[cpu_type] + "\")\n"
 
index 9644dc9e6cc888da4e931a1a43f10102620d3b01..4d2a026cde58a7dc2ee0ea15ed17116084d42f23 100644 (file)
@@ -4,7 +4,7 @@ from operator import itemgetter
 from migen import *
 
 from litex.soc.cores import identifier, timer, uart
-from litex.soc.cores.cpu import lm32, mor1kx, picorv32
+from litex.soc.cores.cpu import lm32, mor1kx, picorv32, vexriscv
 from litex.soc.interconnect import wishbone, csr_bus, wishbone2csr
 
 
@@ -110,6 +110,8 @@ class SoCCore(Module):
                 self.add_cpu_or_bridge(mor1kx.MOR1KX(platform, self.cpu_reset_address, self.cpu_variant))
             elif cpu_type == "picorv32":
                 self.add_cpu_or_bridge(picorv32.PicoRV32(platform, self.cpu_reset_address, self.cpu_variant))
+            elif cpu_type == "vexriscv":
+                self.add_cpu_or_bridge(vexriscv.VexRiscv(platform, self.cpu_reset_address))
             else:
                 raise ValueError("Unsupported CPU type: {}".format(cpu_type))
             self.add_wb_master(self.cpu_or_bridge.ibus)
index 25217e11ebe1361edd35d49e353f5781be6841bc..6a33698bfa34b962b72b4dad9a6658f0c7fc1bbc 100644 (file)
@@ -13,7 +13,11 @@ all: bios.bin
 %.bin: %.elf
        $(OBJCOPY) -O binary $< $@
        chmod -x $@
+ifeq ($(CPUENDIANNESS),little)
+       $(PYTHON) -m litex.soc.tools.mkmscimg $@ --little
+else
        $(PYTHON) -m litex.soc.tools.mkmscimg $@
+endif
 
 bios.elf: $(BIOS_DIRECTORY)/linker.ld $(OBJECTS)
 
diff --git a/litex/soc/software/bios/boot-helper-vexriscv.S b/litex/soc/software/bios/boot-helper-vexriscv.S
new file mode 100644 (file)
index 0000000..0c6c326
--- /dev/null
@@ -0,0 +1,4 @@
+.section    .text, "ax", @progbits
+.global     boot_helper
+boot_helper:
+    nop
index 2dcd2d92467779f3fdf6677305570ce69813be44..8d475c396004b407f30a2375a39dd096bf17bd6a 100644 (file)
@@ -500,6 +500,8 @@ int main(int i, char **c)
        printf("\e[1mMOR1K\e[0m\n");
 #elif __picorv32__
        printf("\e[1mPicoRV32\e[0m\n");
+#elif __vexriscv__
+       printf("\e[1mVexRiscv\e[0m\n");
 #else
        printf("\e[1mUnknown\e[0m\n");
 #endif
index 6f460383b3c892003b67a2de7df509b99a4d9372..b9fb015c89ff749c053c55cdbbce62676af8143c 100644 (file)
@@ -20,6 +20,8 @@ static void cdelay(int i)
                __asm__ volatile("l.nop");
 #elif defined (__picorv32__)
                __asm__ volatile("nop");
+#elif defined (__vexriscv__)
+               __asm__ volatile("nop");
 #else
 #error Unsupported architecture
 #endif
diff --git a/litex/soc/software/include/base/csr-defs.h b/litex/soc/software/include/base/csr-defs.h
new file mode 100644 (file)
index 0000000..5f5ea84
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef CSR_DEFS__H
+#define CSR_DEFS__H
+
+#define CSR_MSTATUS_MIE 0x8
+
+#define CSR_IRQ_MASK 0x330
+#define CSR_IRQ_PENDING 0x360
+
+#define CSR_DCACHE_INFO 0xCC0
+
+#endif /* CSR_DEFS__H */
index 91f67019c346a6ef8c07c89e8828e1cf5085c95e..83d1ace5ce8fcbadea758c986ecd0decf033a9ed 100644 (file)
@@ -38,6 +38,8 @@ static inline unsigned int irq_getie(void)
        return !!(mfspr(SPR_SR) & SPR_SR_IEE);
 #elif defined (__picorv32__)
        return _irq_enabled != 0;
+#elif defined (__vexriscv__)
+       return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0;
 #else
 #error Unsupported architecture
 #endif
@@ -57,6 +59,8 @@ static inline void irq_setie(unsigned int ie)
         _irq_enable();
     else
         _irq_disable();
+#elif defined (__vexriscv__)
+       if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE);
 #else
 #error Unsupported architecture
 #endif
@@ -74,6 +78,10 @@ static inline unsigned int irq_getmask(void)
     // PicoRV32 interrupt mask bits are high-disabled. This is the inverse of how
     // LiteX sees things.
     return ~_irq_mask;
+#elif defined (__vexriscv__)
+       unsigned int mask;
+       asm volatile ("csrr %0, %1" : "=r"(mask) : "i"(CSR_IRQ_MASK));
+       return mask;
 #else
 #error Unsupported architecture
 #endif
@@ -89,6 +97,8 @@ static inline void irq_setmask(unsigned int mask)
     // PicoRV32 interrupt mask bits are high-disabled. This is the inverse of how
     // LiteX sees things.
     _irq_setmask(~mask);
+#elif defined (__vexriscv__)
+       asm volatile ("csrw %0, %1" :: "i"(CSR_IRQ_MASK), "r"(mask));
 #else
 #error Unsupported architecture
 #endif
@@ -104,6 +114,10 @@ static inline unsigned int irq_pending(void)
        return mfspr(SPR_PICSR);
 #elif defined (__picorv32__)
        return _irq_pending;
+#elif defined (__vexriscv__)
+       unsigned int pending;
+       asm volatile ("csrr %0, %1" : "=r"(pending) : "i"(CSR_IRQ_PENDING));
+       return pending;
 #else
 #error Unsupported architecture
 #endif
index 2a0d0c2955414a405c2f6d63dff305d77a140a44..27f454032ff449c98777c318b72d3cd94f1bc28c 100644 (file)
@@ -26,6 +26,32 @@ static inline void mtspr(unsigned long add, unsigned long val)
 }
 #endif
 
+
+#if defined(__vexriscv__)
+#include <csr-defs.h>
+#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)); })
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/litex/soc/software/libbase/crt0-vexriscv.S b/litex/soc/software/libbase/crt0-vexriscv.S
new file mode 100644 (file)
index 0000000..c27a3da
--- /dev/null
@@ -0,0 +1,76 @@
+.global main
+.global isr
+.global _start
+
+_start:
+  j crt_init
+  nop
+  nop
+  nop
+  nop
+  nop
+  nop
+  nop
+
+.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, trap_entry
+  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, 0x880  //880 enable timer + external interrupt sources (until mstatus.MIE is set, they will never trigger an interrupt)
+  csrw mie,a0
+
+  call main
+infinit_loop:
+  j infinit_loop
index 974e52832832add102c684a0afd874f6668dd858..8ad76066921c7ed1bb31445f67eb66337aacb3fc 100644 (file)
@@ -4,6 +4,10 @@
 #include <spr-defs.h>
 #endif
 
+#ifdef __vexriscv__
+#include <csr-defs.h>
+#endif
+
 #include <system.h>
 #include <generated/mem.h>
 #include <generated/csr.h>
@@ -37,6 +41,15 @@ void flush_cpu_icache(void)
 #elif defined (__picorv32__)
        /* no instruction cache */
        asm volatile("nop");
+#elif defined (__vexriscv__)
+       asm volatile(
+               ".word(0x400F)\n"
+               "nop\n"
+               "nop\n"
+               "nop\n"
+               "nop\n"
+               "nop\n"
+       );
 #else
 #error Unsupported architecture
 #endif
@@ -68,6 +81,14 @@ void flush_cpu_dcache(void)
 #elif defined (__picorv32__)
        /* no data cache */
        asm volatile("nop");
+#elif defined (__vexriscv__)
+       unsigned long cache_info;
+       asm volatile ("csrr %0, %1" : "=r"(cache_info) : "i"(CSR_DCACHE_INFO));
+       unsigned long cache_way_size = cache_info & 0xFFFFF;
+       unsigned long cache_line_size = (cache_info >> 20) & 0xFFF;
+       for(register unsigned long idx = 0;idx < cache_way_size;idx += cache_line_size){
+               asm volatile("mv x10, %0 \n .word(0b01110000000001010101000000001111)"::"r"(idx));
+       }
 #else
 #error Unsupported architecture
 #endif
index 751e9e5357df6c165c5fdd43e384c531be04363b..54f27e1dd42bb19511c803e6e8833d1df6932250 100644 (file)
@@ -4,14 +4,16 @@ import argparse
 import binascii
 
 
-def insert_crc(i_filename, fbi_mode=False, o_filename=None):
+def insert_crc(i_filename, fbi_mode=False, o_filename=None, little_endian=False):
+    endian = "little" if little_endian else "big"
+
     if o_filename is None:
         o_filename = i_filename
 
     with open(i_filename, "rb") as f:
         fdata = f.read()
-    fcrc = binascii.crc32(fdata).to_bytes(4, byteorder="big")
-    flength = len(fdata).to_bytes(4, byteorder="big")
+    fcrc = binascii.crc32(fdata).to_bytes(4, byteorder=endian)
+    flength = len(fdata).to_bytes(4, byteorder=endian)
 
     with open(o_filename, "wb") as f:
         if fbi_mode:
@@ -28,8 +30,9 @@ def main():
     parser.add_argument("input", help="input file")
     parser.add_argument("-o", "--output", default=None, help="output file (if not specified, use input file)")
     parser.add_argument("-f", "--fbi", default=False, action="store_true", help="build flash boot image (FBI) file")
+    parser.add_argument("-l", "--little", default=False, action="store_true", help="Use little endian to write the CRC32")
     args = parser.parse_args()
-    insert_crc(args.input, args.fbi, args.output)
+    insert_crc(args.input, args.fbi, args.output, args.little)
 
 
 if __name__ == "__main__":