-
Notifications
You must be signed in to change notification settings - Fork 545
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cores/cpu: Add initial FemtoRV support.
FemtoRV is a minimalist RISC-V CPU with design process documented and available at https://github.com/BrunoLevy/learn-fpga. This CPU is a very nice way to discover/learn RISC-V and this LiteX support can be useful to learn how to integrate a custom CPU with LiteX. With this support, FemtoRV is now directly usable with LiteX Sim: $litex_sim --cpu-type=femtorv This should also enable its use on all boards (> 50) available in LiteX-Boards repository (but hasn't been tested yet), ex: $python3 -m litex_boards.targets.digilent_arty --cpu-type=femtorv --build
- Loading branch information
1 parent
d3560e5
commit b1d8fe6
Showing
8 changed files
with
290 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from litex.soc.cores.cpu.femtorv.core import FemtoRV |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
.section .text, "ax", @progbits | ||
.global boot_helper | ||
boot_helper: | ||
jr x13 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
# | ||
# This file is part of LiteX. | ||
# | ||
# Copyright (c) 2021 Florent Kermarrec <florent@enjoy-digital.fr> | ||
# SPDX-License-Identifier: BSD-2-Clause | ||
|
||
import os | ||
|
||
from migen import * | ||
|
||
from litex.soc.interconnect import wishbone | ||
from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_RISCV32 | ||
|
||
# Variants ----------------------------------------------------------------------------------------- | ||
|
||
CPU_VARIANTS = ["standard"] | ||
|
||
# FemtoRV ------------------------------------------------------------------------------------------ | ||
|
||
class FemtoRV(CPU): | ||
name = "femtorv" | ||
human_name = "FemtoRV" | ||
variants = CPU_VARIANTS | ||
data_width = 32 | ||
endianness = "little" | ||
gcc_triple = CPU_GCC_TRIPLE_RISCV32 | ||
linker_output_format = "elf32-littleriscv" | ||
nop = "nop" | ||
io_regions = {0x80000000: 0x80000000} # Origin, Length. | ||
|
||
# GCC Flags. | ||
@property | ||
def gcc_flags(self): | ||
flags = "-march=rv32i " | ||
flags += "-mabi=ilp32 " | ||
flags += "-D__femtorv__ " | ||
return flags | ||
|
||
def __init__(self, platform, variant="standard"): | ||
self.platform = platform | ||
self.variant = variant | ||
self.reset = Signal() | ||
self.idbus = idbus = wishbone.Interface() | ||
self.periph_buses = [idbus] # Peripheral buses (Connected to main SoC's bus). | ||
self.memory_buses = [] # Memory buses (Connected directly to LiteDRAM). | ||
|
||
# # # | ||
|
||
# FemtoRV Mem Bus. | ||
# ---------------- | ||
mbus = Record([ | ||
("addr", 32), | ||
("wdata", 32), | ||
("wmask", 4), | ||
("rdata", 32), | ||
("rstrb", 1), | ||
("rbusy", 1), | ||
("wbusy", 1), | ||
]) | ||
|
||
# FemtoRV Instance. | ||
# ----------------- | ||
self.cpu_params = dict( | ||
# Parameters. | ||
p_ADDR_WIDTH = 32, | ||
p_RESET_ADDR = Constant(0, 32), | ||
|
||
# Clk / Rst. | ||
i_clk = ClockSignal("sys"), | ||
i_reset = ~ResetSignal("sys"), # Active Low. | ||
|
||
# I/D Bus. | ||
o_mem_addr = mbus.addr, | ||
o_mem_wdata = mbus.wdata, | ||
o_mem_wmask = mbus.wmask, | ||
i_mem_rdata = mbus.rdata, | ||
o_mem_rstrb = mbus.rstrb, | ||
i_mem_rbusy = mbus.rbusy, | ||
i_mem_wbusy = mbus.wbusy, | ||
) | ||
|
||
# Adapt FemtoRV Mem Bus to Wishbone. | ||
# ---------------------------------- | ||
|
||
# Bytes to Words addressing conversion. | ||
self.comb += idbus.adr.eq(mbus.addr[2:]) | ||
|
||
# Wdata/WMask direct connection. | ||
self.comb += idbus.dat_w.eq(mbus.wdata) | ||
self.comb += idbus.sel.eq(mbus.wmask) | ||
|
||
# Control adaptation. | ||
latch = Signal() | ||
write = mbus.wmask != 0 | ||
read = mbus.rstrb | ||
|
||
self.submodules.fsm = fsm = FSM(reset_state="IDLE") | ||
fsm.act("IDLE", | ||
idbus.stb.eq(read | write), | ||
idbus.cyc.eq(read | write), | ||
idbus.we.eq(write), | ||
If(read, | ||
mbus.rbusy.eq(1), | ||
NextState("READ") | ||
).Elif(write, | ||
mbus.wbusy.eq(1), | ||
NextState("WRITE") | ||
) | ||
) | ||
fsm.act("READ", | ||
idbus.stb.eq(1), | ||
idbus.cyc.eq(1), | ||
mbus.rbusy.eq(1), | ||
If(idbus.ack, | ||
latch.eq(1), | ||
NextState("IDLE") | ||
) | ||
) | ||
fsm.act("WRITE", | ||
idbus.stb.eq(1), | ||
idbus.cyc.eq(1), | ||
idbus.we.eq(1), | ||
mbus.wbusy.eq(1), | ||
If(idbus.ack, | ||
NextState("IDLE") | ||
) | ||
) | ||
|
||
# Latch RData on Wishbone ack. | ||
self.sync += If(latch, mbus.rdata.eq(idbus.dat_r)) | ||
|
||
# Add Verilog sources. | ||
# -------------------- | ||
self.add_sources(platform) | ||
|
||
def set_reset_address(self, reset_address): | ||
assert not hasattr(self, "reset_address") | ||
self.reset_address = reset_address | ||
self.cpu_params.update(p_RESET_ADDR=Constant(reset_address, 32)) | ||
|
||
@staticmethod | ||
def add_sources(platform): | ||
if not os.path.exists("femtorv32_quark.v"): | ||
# Get FemtoRV32 source. | ||
os.system("wget https://github.com/raw/BrunoLevy/learn-fpga/master/FemtoRV/RTL/PROCESSOR/femtorv32_quark.v") | ||
# FIXME: Patch it to fix compilation issue with Verilator, report issue. | ||
os.system(f"patch -p0 < {os.path.dirname(os.path.realpath(__file__))}/femtorv32_quark.patch") | ||
platform.add_source("femtorv32_quark.v") | ||
|
||
def do_finalize(self): | ||
assert hasattr(self, "reset_address") | ||
self.specials += Instance("FemtoRV32", **self.cpu_params) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
#define MIE_MEIE 0x800 | ||
|
||
.global _start | ||
_start: | ||
j reset_vector | ||
|
||
reset_vector: | ||
la sp, _fstack | ||
la t0, trap_vector | ||
csrw mtvec, t0 | ||
|
||
// initialize .data | ||
la t0, _fdata | ||
la t1, _edata | ||
la t2, _fdata_rom | ||
1: beq t0, t1, 2f | ||
lw t3, 0(t2) | ||
sw t3, 0(t0) | ||
addi t0, t0, 4 | ||
addi t2, t2, 4 | ||
j 1b | ||
2: | ||
|
||
// initialize .bss | ||
la t0, _fbss | ||
la t1, _ebss | ||
1: beq t0, t1, 3f | ||
sw zero, 0(t0) | ||
addi t0, t0, 4 | ||
j 1b | ||
3: | ||
// enable external interrupts | ||
li t0, MIE_MEIE | ||
csrs mie, t0 | ||
|
||
call main | ||
1: j 1b | ||
|
||
trap_vector: | ||
addi sp, sp, -16*4 | ||
sw ra, 0*4(sp) | ||
sw t0, 1*4(sp) | ||
sw t1, 2*4(sp) | ||
sw t2, 3*4(sp) | ||
sw a0, 4*4(sp) | ||
sw a1, 5*4(sp) | ||
sw a2, 6*4(sp) | ||
sw a3, 7*4(sp) | ||
sw a4, 8*4(sp) | ||
sw a5, 9*4(sp) | ||
sw a6, 10*4(sp) | ||
sw a7, 11*4(sp) | ||
sw t3, 12*4(sp) | ||
sw t4, 13*4(sp) | ||
sw t5, 14*4(sp) | ||
sw t6, 15*4(sp) | ||
call isr | ||
lw ra, 0*4(sp) | ||
lw t0, 1*4(sp) | ||
lw t1, 2*4(sp) | ||
lw t2, 3*4(sp) | ||
lw a0, 4*4(sp) | ||
lw a1, 5*4(sp) | ||
lw a2, 6*4(sp) | ||
lw a3, 7*4(sp) | ||
lw a4, 8*4(sp) | ||
lw a5, 9*4(sp) | ||
lw a6, 10*4(sp) | ||
lw a7, 11*4(sp) | ||
lw t3, 12*4(sp) | ||
lw t4, 13*4(sp) | ||
lw t5, 14*4(sp) | ||
lw t6, 15*4(sp) | ||
addi sp, sp, 16*4 | ||
mret |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
diff --git a/femtorv32_quark_fix.v femtorv32_quark.v | ||
index 220b8d4..31f6c08 100644 | ||
--- a/femtorv32_quark_fix.v | ||
+++ femtorv32_quark.v | ||
@@ -44,8 +44,6 @@ module FemtoRV32( | ||
parameter RESET_ADDR = 32'h00000000; | ||
parameter ADDR_WIDTH = 24; | ||
|
||
- localparam ADDR_PAD = {(32-ADDR_WIDTH){1'b0}}; // 32-bits padding for addrs | ||
- | ||
/***************************************************************************/ | ||
// Instruction decoding. | ||
/***************************************************************************/ | ||
@@ -205,7 +203,7 @@ module FemtoRV32( | ||
wire [ADDR_WIDTH-1:0] loadstore_addr = rs1[ADDR_WIDTH-1:0] + | ||
(instr[5] ? Simm[ADDR_WIDTH-1:0] : Iimm[ADDR_WIDTH-1:0]); | ||
|
||
- assign mem_addr = {ADDR_PAD, | ||
+ assign mem_addr = { | ||
state[WAIT_INSTR_bit] | state[FETCH_INSTR_bit] ? | ||
PC : loadstore_addr | ||
}; | ||
@@ -220,8 +218,8 @@ module FemtoRV32( | ||
/* verilator lint_on WIDTH */ | ||
(isLUI ? Uimm : 32'b0) | // LUI | ||
(isALU ? aluOut : 32'b0) | // ALUreg, ALUimm | ||
- (isAUIPC ? {ADDR_PAD,PCplusImm} : 32'b0) | // AUIPC | ||
- (isJALR | isJAL ? {ADDR_PAD,PCplus4 } : 32'b0) | // JAL, JALR | ||
+ (isAUIPC ? {PCplusImm} : 32'b0) | // AUIPC | ||
+ (isJALR | isJAL ? {PCplus4 } : 32'b0) | // JAL, JALR | ||
(isLoad ? LOAD_data : 32'b0); // Load | ||
|
||
/***************************************************************************/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#ifndef __IRQ_H | ||
#define __IRQ_H | ||
|
||
#endif /* __IRQ_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#ifndef __SYSTEM_H | ||
#define __SYSTEM_H | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
__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); | ||
|
||
void busy_wait(unsigned int ms); | ||
void busy_wait_us(unsigned int us); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif /* __SYSTEM_H */ |