-
Notifications
You must be signed in to change notification settings - Fork 566
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
soc/cores/cpu: Add initial uRV CPU support (not yet working).
- Loading branch information
1 parent
c82fddf
commit edb56e7
Showing
6 changed files
with
313 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from litex.soc.cores.cpu.urv.core import uRV |
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,210 @@ | ||
# | ||
# This file is part of LiteX. | ||
# | ||
# Copyright (c) 2024 Florent Kermarrec <[email protected]> | ||
# SPDX-License-Identifier: BSD-2-Clause | ||
|
||
import os | ||
|
||
from migen import * | ||
|
||
from litex.gen import * | ||
|
||
from litex.soc.interconnect import wishbone | ||
from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_RISCV32 | ||
|
||
# Variants ----------------------------------------------------------------------------------------- | ||
|
||
CPU_VARIANTS = { | ||
"standard": "urv", | ||
} | ||
|
||
# GCC Flags ---------------------------------------------------------------------------------------- | ||
|
||
GCC_FLAGS = { | ||
# /------------ Base ISA | ||
# | /------- Hardware Multiply + Divide | ||
# | |/----- Atomics | ||
# | ||/---- Compressed ISA | ||
# | |||/--- Single-Precision Floating-Point | ||
# | ||||/-- Double-Precision Floating-Point | ||
# i macfd | ||
"standard": "-march=rv32i2p0_m -mabi=ilp32", | ||
} | ||
|
||
# uRV ------------------------------------------------------------------------------------------ | ||
|
||
class uRV(CPU): | ||
category = "softcore" | ||
family = "riscv" | ||
name = "urv" | ||
human_name = "urv" | ||
variants = CPU_VARIANTS | ||
data_width = 32 | ||
endianness = "little" | ||
gcc_triple = CPU_GCC_TRIPLE_RISCV32 | ||
linker_output_format = "elf32-littleriscv" | ||
nop = "nop" | ||
io_regions = {0x8000_0000: 0x8000_0000} # Origin, Length. | ||
|
||
# GCC Flags. | ||
@property | ||
def gcc_flags(self): | ||
flags = GCC_FLAGS[self.variant] | ||
flags += " -D__urv__ " | ||
return flags | ||
|
||
def __init__(self, platform, variant="standard"): | ||
self.platform = platform | ||
self.variant = variant | ||
self.human_name = f"uRV-{variant.upper()}" | ||
self.reset = Signal() | ||
self.ibus = ibus = wishbone.Interface(data_width=32, address_width=32, addressing="byte") | ||
self.dbus = dbus = wishbone.Interface(data_width=32, address_width=32, addressing="byte") | ||
self.periph_buses = [ibus, dbus] # Peripheral buses (Connected to main SoC's bus). | ||
self.memory_buses = [] # Memory buses (Connected directly to LiteDRAM). | ||
|
||
# uRV Signals. | ||
# ------------ | ||
im_addr = Signal(32) | ||
im_rd = Signal(1) | ||
im_data = Signal(32) | ||
im_valid = Signal(1) | ||
|
||
dm_addr = Signal(32) | ||
dm_data_s = Signal(32) | ||
dm_data_l = Signal(32) | ||
dm_data_select = Signal(4) | ||
dm_store = Signal() | ||
dm_load = Signal() | ||
dm_load_done = Signal() | ||
dm_store_done = Signal() | ||
|
||
rst_count = Signal(8, reset=16) | ||
self.sync += If(rst_count != 0, rst_count.eq(rst_count - 1)) | ||
|
||
# uRV Instance. | ||
# ------------- | ||
self.cpu_params = dict( | ||
# Parameters. | ||
p_g_timer_frequency = 1000, | ||
p_g_clock_frequency = 100000000, | ||
p_g_with_hw_div = 1, | ||
p_g_with_hw_mulh = 1, | ||
p_g_with_hw_mul = 1, | ||
p_g_with_hw_debug = 0, | ||
p_g_with_ecc = 0, | ||
p_g_with_compressed_insns = 0, | ||
|
||
# Clk / Rst. | ||
i_clk_i = ClockSignal("sys"), | ||
i_rst_i = ~(ResetSignal("sys") | self.reset | (rst_count != 0)), | ||
|
||
# Instruction Mem Bus. | ||
o_im_addr_o = im_addr, | ||
o_im_rd_o = im_rd, | ||
i_im_data_i = im_data, | ||
i_im_valid_i = im_valid, | ||
|
||
# Data Mem Bus. | ||
o_dm_addr_o = dm_addr, | ||
o_dm_data_s_o = dm_data_s, | ||
i_dm_data_l_i = dm_data_l, | ||
o_dm_data_select_o = dm_data_select, | ||
|
||
o_dm_store_o = dm_store, | ||
o_dm_load_o = dm_load, | ||
i_dm_load_done_i = dm_load_done, | ||
i_dm_store_done_i = dm_store_done, | ||
) | ||
|
||
# uRV Instruction Bus. | ||
# -------------------- | ||
self.i_fsm = i_fsm = FSM(reset_state="IDLE") | ||
i_fsm.act("IDLE", | ||
If(im_rd, | ||
NextValue(im_valid, 0), | ||
NextState("READ") | ||
) | ||
) | ||
i_fsm.act("READ", | ||
ibus.stb.eq(1), | ||
ibus.cyc.eq(1), | ||
ibus.we.eq(0), | ||
ibus.adr.eq(im_addr), | ||
ibus.sel.eq(0b1111), | ||
If(ibus.ack, | ||
NextValue(im_valid, 1), | ||
NextValue(im_data, ibus.dat_r), | ||
NextState("IDLE") | ||
) | ||
) | ||
|
||
# uRV Data Bus. | ||
# ------------- | ||
self.d_fsm = d_fsm = FSM(reset_state="IDLE") | ||
d_fsm.act("IDLE", | ||
If(dm_store, | ||
NextState("WRITE") | ||
), | ||
If(dm_load, | ||
NextState("READ") | ||
) | ||
) | ||
d_fsm.act("WRITE", | ||
dbus.stb.eq(1), | ||
dbus.cyc.eq(1), | ||
dbus.we.eq(1), | ||
dbus.adr.eq(dm_addr), | ||
dbus.sel.eq(dm_data_select), | ||
dbus.dat_w.eq(dm_data_s), | ||
If(dbus.ack, | ||
NextState("IDLE") | ||
) | ||
) | ||
d_fsm.act("READ", | ||
dbus.stb.eq(1), | ||
dbus.cyc.eq(1), | ||
dbus.we.eq(0), | ||
dbus.adr.eq(dm_addr), | ||
dbus.sel.eq(dm_data_select), | ||
If(dbus.ack, | ||
dm_load_done.eq(1), | ||
dm_data_l.eq(dbus.dat_r), | ||
NextState("IDLE") | ||
) | ||
) | ||
|
||
# Add Verilog sources. | ||
# -------------------- | ||
self.add_sources(platform, variant) | ||
|
||
def set_reset_address(self, reset_address): | ||
assert reset_address == 0 | ||
self.reset_address = reset_address | ||
|
||
@staticmethod | ||
def add_sources(platform, variant): | ||
if not os.path.exists("urv-core"): | ||
os.system(f"git clone https://ohwr.org/project/urv-core/") | ||
vdir = "urv-core/rtl" | ||
platform.add_verilog_include_path("urv-core/rtl") | ||
platform.add_sources([ | ||
"urv-core/rtl/urv_cpu.v", | ||
"urv-core/rtl/urv_exec.v", | ||
"urv-core/rtl/urv_fetch.v", | ||
"urv-core/rtl/urv_decode.v", | ||
"urv-core/rtl/urv_regfile.v", | ||
"urv-core/rtl/urv_writeback.v", | ||
"urv-core/rtl/urv_shifter.v", | ||
"urv-core/rtl/urv_multiply.v", | ||
"urv-core/rtl/urv_divide.v", | ||
"urv-core/rtl/urv_csr.v", | ||
"urv-core/rtl/urv_timer.v", | ||
"urv-core/rtl/urv_exceptions.v", | ||
"urv-core/rtl/urv_iram.v", | ||
"urv-core/rtl/urv_ecc.v", | ||
]) | ||
|
||
def do_finalize(self): | ||
self.specials += Instance("urv_cpu", **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,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 */ |