From 66229c8c05b0c61d9aa9a92c69d94c98c6df1c39 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Wed, 9 May 2018 14:31:05 +0200 Subject: [PATCH] add VexRiscv support (imported/adapted from misoc) --- litex/soc/cores/cpu/vexriscv/__init__.py | 1 + litex/soc/cores/cpu/vexriscv/core.py | 50 ++++++++++++ litex/soc/integration/cpu_interface.py | 11 ++- litex/soc/integration/soc_core.py | 4 +- litex/soc/software/bios/Makefile | 4 + .../soc/software/bios/boot-helper-vexriscv.S | 4 + litex/soc/software/bios/main.c | 2 + litex/soc/software/bios/sdram.c | 2 + litex/soc/software/include/base/csr-defs.h | 11 +++ litex/soc/software/include/base/irq.h | 14 ++++ litex/soc/software/include/base/system.h | 26 +++++++ litex/soc/software/libbase/crt0-vexriscv.S | 76 +++++++++++++++++++ litex/soc/software/libbase/system.c | 21 +++++ litex/soc/tools/mkmscimg.py | 11 ++- 14 files changed, 230 insertions(+), 7 deletions(-) create mode 100644 litex/soc/cores/cpu/vexriscv/__init__.py create mode 100644 litex/soc/cores/cpu/vexriscv/core.py create mode 100644 litex/soc/software/bios/boot-helper-vexriscv.S create mode 100644 litex/soc/software/include/base/csr-defs.h create mode 100644 litex/soc/software/libbase/crt0-vexriscv.S diff --git a/litex/soc/cores/cpu/vexriscv/__init__.py b/litex/soc/cores/cpu/vexriscv/__init__.py new file mode 100644 index 00000000..068cc2e5 --- /dev/null +++ b/litex/soc/cores/cpu/vexriscv/__init__.py @@ -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 index 00000000..68aea9dd --- /dev/null +++ b/litex/soc/cores/cpu/vexriscv/core.py @@ -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) diff --git a/litex/soc/integration/cpu_interface.py b/litex/soc/integration/cpu_interface.py index b3463bcc..8e755202 100644 --- a/litex/soc/integration/cpu_interface.py +++ b/litex/soc/integration/cpu_interface.py @@ -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" diff --git a/litex/soc/integration/soc_core.py b/litex/soc/integration/soc_core.py index 9644dc9e..4d2a026c 100644 --- a/litex/soc/integration/soc_core.py +++ b/litex/soc/integration/soc_core.py @@ -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) diff --git a/litex/soc/software/bios/Makefile b/litex/soc/software/bios/Makefile index 25217e11..6a33698b 100644 --- a/litex/soc/software/bios/Makefile +++ b/litex/soc/software/bios/Makefile @@ -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 index 00000000..0c6c3269 --- /dev/null +++ b/litex/soc/software/bios/boot-helper-vexriscv.S @@ -0,0 +1,4 @@ +.section .text, "ax", @progbits +.global boot_helper +boot_helper: + nop diff --git a/litex/soc/software/bios/main.c b/litex/soc/software/bios/main.c index 2dcd2d92..8d475c39 100644 --- a/litex/soc/software/bios/main.c +++ b/litex/soc/software/bios/main.c @@ -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 diff --git a/litex/soc/software/bios/sdram.c b/litex/soc/software/bios/sdram.c index 6f460383..b9fb015c 100644 --- a/litex/soc/software/bios/sdram.c +++ b/litex/soc/software/bios/sdram.c @@ -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 index 00000000..5f5ea847 --- /dev/null +++ b/litex/soc/software/include/base/csr-defs.h @@ -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 */ diff --git a/litex/soc/software/include/base/irq.h b/litex/soc/software/include/base/irq.h index 91f67019..83d1ace5 100644 --- a/litex/soc/software/include/base/irq.h +++ b/litex/soc/software/include/base/irq.h @@ -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 diff --git a/litex/soc/software/include/base/system.h b/litex/soc/software/include/base/system.h index 2a0d0c29..27f45403 100644 --- a/litex/soc/software/include/base/system.h +++ b/litex/soc/software/include/base/system.h @@ -26,6 +26,32 @@ static inline void mtspr(unsigned long add, unsigned long val) } #endif + +#if defined(__vexriscv__) +#include +#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 index 00000000..c27a3da7 --- /dev/null +++ b/litex/soc/software/libbase/crt0-vexriscv.S @@ -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 diff --git a/litex/soc/software/libbase/system.c b/litex/soc/software/libbase/system.c index 974e5283..8ad76066 100644 --- a/litex/soc/software/libbase/system.c +++ b/litex/soc/software/libbase/system.c @@ -4,6 +4,10 @@ #include #endif +#ifdef __vexriscv__ +#include +#endif + #include #include #include @@ -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 diff --git a/litex/soc/tools/mkmscimg.py b/litex/soc/tools/mkmscimg.py index 751e9e53..54f27e1d 100644 --- a/litex/soc/tools/mkmscimg.py +++ b/litex/soc/tools/mkmscimg.py @@ -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__": -- 2.30.2