-
Notifications
You must be signed in to change notification settings - Fork 598
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cpu: Add initial NEORV32 support (From out of tree prototyping in lit…
…ex_neorv32_test repo). - Only configured for rv32i for now (need to create variants). - I/DBus interfaces probably not optimal (latency). - Converted from VHDL to Verilog through GHDL-Yosys-Synth (should also support direct VHDL use with toolchains supporting it). - Interrupt not yet implemented. - Running in simulation with litex_sim --cpu-type=neorv32. - Running on Arty with: python3 -m litex_boards.targets.digilent_arty --cpu-type=neorv32 --build --load: __ _ __ _ __ / / (_) /____ | |/_/ / /__/ / __/ -_)> < /____/_/\__/\__/_/|_| Build your hardware, easily! (c) Copyright 2012-2022 Enjoy-Digital (c) Copyright 2007-2015 M-Labs BIOS built on Feb 14 2022 16:10:24 BIOS CRC passed (83edf3c3) Migen git sha1: ac70301 LiteX git sha1: 0d21830 --=============== SoC ==================-- CPU: NEORV32 @ 100MHz BUS: WISHBONE 32-bit @ 4GiB CSR: 32-bit data ROM: 128KiB SRAM: 8KiB L2: 8KiB SDRAM: 524288KiB 16-bit @ 800MT/s (CL-7 CWL-5) --========== Initialization ============-- Initializing SDRAM @0x40000000... Switching SDRAM to software control. Read leveling: m0, b00: |00000000000000000000000000000000| delays: - m0, b01: |11000000000000000000000000000000| delays: 01+-01 m0, b02: |00011111111111111000000000000000| delays: 10+-07 m0, b03: |00000000000000000000111111111111| delays: 26+-06 m0, b04: |00000000000000000000000000000000| delays: - m0, b05: |00000000000000000000000000000000| delays: - m0, b06: |00000000000000000000000000000000| delays: - m0, b07: |00000000000000000000000000000000| delays: - best: m0, b02 delays: 10+-07 m1, b00: |00000000000000000000000000000000| delays: - m1, b01: |10000000000000000000000000000000| delays: 00+-00 m1, b02: |00111111111111111000000000000000| delays: 09+-07 m1, b03: |00000000000000000001111111111111| delays: 25+-06 m1, b04: |00000000000000000000000000000000| delays: - m1, b05: |00000000000000000000000000000000| delays: - m1, b06: |00000000000000000000000000000000| delays: - m1, b07: |00000000000000000000000000000000| delays: - best: m1, b02 delays: 09+-07 Switching SDRAM to hardware control. Memtest at 0x40000000 (2.0MiB)... Write: 0x40000000-0x40200000 2.0MiB Read: 0x40000000-0x40200000 2.0MiB Memtest OK Memspeed at 0x40000000 (Sequential, 2.0MiB)... Write speed: 9.3MiB/s Read speed: 13.2MiB/s --============== Boot ==================-- Booting from serial... Press Q or ESC to abort boot completely. sL5DdSMmkekro Timeout No boot medium found --============= Console ================-- litex>
- Loading branch information
1 parent
d37ef60
commit 38a047b
Showing
7 changed files
with
448 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.neorv32.core import NEORV32 |
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,194 @@ | ||
# | ||
# This file is part of LiteX. | ||
# | ||
# Copyright (c) 2022 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"] | ||
|
||
# GCC Flags ---------------------------------------------------------------------------------------- | ||
|
||
GCC_FLAGS = { | ||
# /-------- Base ISA | ||
# |/------- Hardware Multiply + Divide | ||
# ||/----- Atomics | ||
# |||/---- Compressed ISA | ||
# ||||/--- Single-Precision Floating-Point | ||
# |||||/-- Double-Precision Floating-Point | ||
# imacfd | ||
"standard": "-march=rv32i -mabi=ilp32", | ||
} | ||
|
||
# NEORV32 ------------------------------------------------------------------------------------------ | ||
|
||
class NEORV32(CPU): | ||
family = "riscv" | ||
name = "neorv32" | ||
human_name = "NEORV32" | ||
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 = GCC_FLAGS[self.variant] | ||
flags += " -D__neorv32__ " | ||
return flags | ||
|
||
def __init__(self, platform, variant="standard"): | ||
self.platform = platform | ||
self.variant = variant | ||
self.reset = Signal() | ||
self.ibus = ibus = wishbone.Interface() | ||
self.dbus = dbus = wishbone.Interface() | ||
self.periph_buses = [ibus, dbus] # Peripheral buses (Connected to main SoC's bus). | ||
self.memory_buses = [] # Memory buses (Connected directly to LiteDRAM). | ||
|
||
# # # | ||
|
||
class Open(Signal) : pass | ||
|
||
# IBus Adaptations. FIXME: Works but not optimal (latency). | ||
ibus_we = Signal() | ||
ibus_re = Signal() | ||
self.sync += [ | ||
# Clear Cyc/Stb on Ack. | ||
If(ibus.ack, | ||
ibus.cyc.eq(0), | ||
ibus.stb.eq(0), | ||
), | ||
# Set Cyc/Stb on We/Re. | ||
If(ibus_we | ibus_re, | ||
ibus.cyc.eq(1), | ||
ibus.stb.eq(1), | ||
ibus.we.eq(ibus_we) | ||
) | ||
] | ||
|
||
# DBus Adaptations. FIXME: Works but not optimal (latency). | ||
dbus_we = Signal() | ||
dbus_re = Signal() | ||
self.sync += [ | ||
# Clear Cyc/Stb on Ack. | ||
If(dbus.ack, | ||
dbus.cyc.eq(0), | ||
dbus.stb.eq(0), | ||
), | ||
# Set Cyc/Stb on We/Re. | ||
If(dbus_we | dbus_re, | ||
dbus.cyc.eq(1), | ||
dbus.stb.eq(1), | ||
dbus.we.eq(dbus_we) | ||
) | ||
] | ||
|
||
# CPU Instance. | ||
self.specials += Instance("neorv32_cpu_wrapper", | ||
# Global Control. | ||
i_clk_i = ClockSignal("sys"), | ||
i_rstn_i = ~(ResetSignal() | self.reset), | ||
o_sleep_o = Open(), | ||
o_debug_o = Open(), | ||
i_db_halt_req_i = 0, | ||
|
||
# Instruction Bus. | ||
o_i_bus_addr_o = Cat(Signal(2), ibus.adr), | ||
i_i_bus_rdata_i = ibus.dat_r, | ||
o_i_bus_wdata_o = ibus.dat_w, | ||
o_i_bus_ben_o = ibus.sel, | ||
o_i_bus_we_o = ibus_we, | ||
o_i_bus_re_o = ibus_re, | ||
o_i_bus_lock_o = Open(), # FIXME. | ||
i_i_bus_ack_i = ibus.ack, | ||
i_i_bus_err_i = ibus.err, | ||
o_i_bus_fence_o = Open(), # FIXME. | ||
o_i_bus_priv_o = Open(), # FIXME. | ||
|
||
# Data Bus. | ||
o_d_bus_addr_o = Cat(Signal(2), dbus.adr), | ||
i_d_bus_rdata_i = dbus.dat_r, | ||
o_d_bus_wdata_o = dbus.dat_w, | ||
o_d_bus_ben_o = dbus.sel, | ||
o_d_bus_we_o = dbus_we, | ||
o_d_bus_re_o = dbus_re, | ||
o_d_bus_lock_o = Open(), # FIXME. | ||
i_d_bus_ack_i = dbus.ack, | ||
i_d_bus_err_i = dbus.err, | ||
o_d_bus_fence_o = Open(), # FIXME. | ||
o_d_bus_priv_o = Open(), # FIXME. | ||
|
||
# System Time. | ||
i_time_i = 0, # FIXME. | ||
|
||
# Interrupts. | ||
i_msw_irq_i = 0, # FIXME. | ||
i_mext_irq_i = 0, # FIXME. | ||
i_mtime_irq_i = 0, # FIXME. | ||
i_firq_i = 0 # FIXME. | ||
) | ||
|
||
# Add Verilog sources | ||
self.add_sources(platform) | ||
|
||
def set_reset_address(self, reset_address): | ||
self.reset_address = reset_address | ||
assert reset_address == 0x00000000 | ||
|
||
@staticmethod | ||
def add_sources(platform): | ||
cdir = os.path.abspath(os.path.dirname(__file__)) | ||
# List VHDL sources. | ||
sources = [ | ||
"neorv32_package.vhd", # Main CPU & Processor package file. | ||
"neorv32_fifo.vhd", # FIFO. | ||
"neorv32_cpu.vhd", # CPU top entity. | ||
"neorv32_cpu_alu.vhd", # Arithmetic/logic unit. | ||
"neorv32_cpu_cp_bitmanip.vhd", # Bit-manipulation co-processor. | ||
"neorv32_cpu_cp_cfu.vhd", # Custom instructions co-processor. | ||
"neorv32_cpu_cp_fpu.vhd", # Single-precision FPU co-processor. | ||
"neorv32_cpu_cp_muldiv.vhd", # Integer multiplier/divider co-processor. | ||
"neorv32_cpu_cp_shifter.vhd", # Base ISA shifter unit. | ||
"neorv32_cpu_bus.vhd", # Instruction and data bus interface unit. | ||
"neorv32_cpu_control.vhd", # CPU control and CSR system. | ||
"neorv32_cpu_decompressor.vhd", # Compressed instructions decoder. | ||
"neorv32_cpu_regfile.vhd", # Data register file. | ||
"neorv32_cpu_wrapper.vhd", # CPU top entity + default generics. | ||
] | ||
|
||
# Download VHDL sources (if not already present). | ||
for source in sources: | ||
if not os.path.exists(os.path.join(cdir, source)): | ||
os.system(f"wget https://raw.githubusercontent.com/stnolting/neorv32/main/rtl/core/{source} -P {cdir}") | ||
|
||
# Convert VHDL to Verilog through GHDL/Yosys. | ||
from litex.build import tools | ||
import subprocess | ||
cdir = os.path.dirname(__file__) | ||
ys = [] | ||
ys.append("ghdl --ieee=synopsys -fexplicit -frelaxed-rules --std=08 --work=neorv32 \\") | ||
for source in sources: | ||
ys.append(os.path.join(cdir, source) + " \\") | ||
ys.append("-e neorv32_cpu_wrapper") | ||
ys.append("chformal -assert -remove") | ||
ys.append("write_verilog {}".format(os.path.join(cdir, "neorv32.v"))) | ||
tools.write_to_file(os.path.join(cdir, "neorv32.ys"), "\n".join(ys)) | ||
if subprocess.call(["yosys", "-q", "-m", "ghdl", os.path.join(cdir, "neorv32.ys")]): | ||
raise OSError("Unable to convert NEORV32 CPU to verilog, please check your GHDL-Yosys-plugin install.") | ||
platform.add_source(os.path.join(cdir, "neorv32.v")) | ||
|
||
def do_finalize(self): | ||
assert hasattr(self, "reset_address") |
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 */ |
Oops, something went wrong.