cores/cpu: add initial lowRISC's Ibex support (without interrupts).
Working in simulation and on hardware: litex_sim --cpu-type=ibex, ./target.py --cpu-type=ibex.
This is currently doing a git clone of ibex and opentitan repositories but we'll
create a pythondata-cpu-ibex package in the future.
litex_sim --cpu-type=ibex:
__ _ __ _ __
/ / (_) /____ | |/_/
/ /__/ / __/ -_)> <
/____/_/\__/\__/_/|_|
Build your hardware, easily!
(c) Copyright 2012-2020 Enjoy-Digital
(c) Copyright 2007-2015 M-Labs
BIOS built on Feb 15 2021 11:57:50
BIOS CRC passed (e7517f7b)
Migen git sha1: 7014bdc
LiteX git sha1: ead12df2
--=============== SoC ==================--
CPU: Ibex @ 1MHz
BUS: WISHBONE 32-bit @ 4GiB
CSR: 32-bit data
ROM: 32KiB
SRAM: 8KiB
MAIN-RAM: 262144KiB
--============== Boot ==================--
Booting from serial...
Press Q or ESC to abort boot completely.
sL5DdSMmkekro
Timeout
No boot medium found
--============= Console ================--
This commit is contained in:
parent
ead12df21b
commit
510bda4c99
|
@ -77,6 +77,7 @@ from litex.soc.cores.cpu.picorv32 import PicoRV32
|
|||
from litex.soc.cores.cpu.minerva import Minerva
|
||||
from litex.soc.cores.cpu.vexriscv import VexRiscv
|
||||
from litex.soc.cores.cpu.vexriscv_smp import VexRiscvSMP
|
||||
from litex.soc.cores.cpu.ibex import Ibex
|
||||
from litex.soc.cores.cpu.cv32e40p import CV32E40P
|
||||
|
||||
# RISC-V (64-bit)
|
||||
|
@ -109,6 +110,7 @@ CPUS = {
|
|||
"minerva" : Minerva,
|
||||
"vexriscv" : VexRiscv,
|
||||
"vexriscv_smp": VexRiscvSMP,
|
||||
"ibex" : Ibex,
|
||||
"cv32e40p" : CV32E40P,
|
||||
|
||||
# RISC-V (64-bit)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
from litex.soc.cores.cpu.ibex.core import Ibex
|
|
@ -0,0 +1,4 @@
|
|||
.section .text, "ax", @progbits
|
||||
.global boot_helper
|
||||
boot_helper:
|
||||
jr x13
|
|
@ -0,0 +1,219 @@
|
|||
#
|
||||
# This file is part of LiteX.
|
||||
#
|
||||
# Copyright (c) 2021 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||
# Copyright (c) 2020 Antmicro <www.antmicro.com>
|
||||
# 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
|
||||
|
||||
|
||||
CPU_VARIANTS = ["standard"]
|
||||
|
||||
GCC_FLAGS = {
|
||||
# /-------- Base ISA
|
||||
# |/------- Hardware Multiply + Divide
|
||||
# ||/----- Atomics
|
||||
# |||/---- Compressed ISA
|
||||
# ||||/--- Single-Precision Floating-Point
|
||||
# |||||/-- Double-Precision Floating-Point
|
||||
# imacfd
|
||||
"standard": "-march=rv32imc -mabi=ilp32 ",
|
||||
}
|
||||
|
||||
obi_layout = [
|
||||
("req", 1),
|
||||
("gnt", 1),
|
||||
("addr", 32),
|
||||
("we", 1),
|
||||
("be", 4),
|
||||
("wdata", 32),
|
||||
("rvalid", 1),
|
||||
("rdata", 32),
|
||||
]
|
||||
|
||||
class OBI2Wishbone(Module):
|
||||
def __init__(self, obi, wb):
|
||||
addr = Signal.like(obi.addr)
|
||||
be = Signal.like(obi.be)
|
||||
we = Signal.like(obi.we)
|
||||
wdata = Signal.like(obi.wdata)
|
||||
|
||||
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
||||
fsm.act("IDLE",
|
||||
# On OBI request:
|
||||
If(obi.req,
|
||||
# Drive Wishbone bus from OBI bus.
|
||||
wb.adr.eq(obi.addr[2:32]),
|
||||
wb.stb.eq( 1),
|
||||
wb.dat_w.eq( obi.wdata),
|
||||
wb.cyc.eq( 1),
|
||||
wb.sel.eq( obi.be),
|
||||
wb.we.eq( obi.we),
|
||||
|
||||
# Store OBI bus values.
|
||||
NextValue(addr, obi.addr),
|
||||
NextValue(be, obi.be),
|
||||
NextValue(we, obi.we),
|
||||
NextValue(wdata, obi.wdata),
|
||||
|
||||
# Now we need to wait Wishbone Ack.
|
||||
NextState("ACK")
|
||||
),
|
||||
obi.gnt.eq(1), # Always ack OBI request in Idle.
|
||||
)
|
||||
fsm.act("ACK",
|
||||
# Drive Wishbone bus from stored OBI bus values.
|
||||
wb.adr.eq(addr[2:32]),
|
||||
wb.stb.eq( 1),
|
||||
wb.dat_w.eq( wdata),
|
||||
wb.cyc.eq( 1),
|
||||
wb.sel.eq( be),
|
||||
wb.we.eq( we),
|
||||
|
||||
# On Wishbone Ack:
|
||||
If(wb.ack,
|
||||
# Generate OBI response.
|
||||
obi.rvalid.eq(1),
|
||||
obi.rdata.eq(wb.dat_r),
|
||||
|
||||
# Return to Idle.
|
||||
NextState("IDLE")
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class Ibex(CPU):
|
||||
name = "ibex"
|
||||
human_name = "Ibex"
|
||||
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
|
||||
|
||||
@property
|
||||
def gcc_flags(self):
|
||||
flags = GCC_FLAGS[self.variant]
|
||||
flags += "-D__ibex__ "
|
||||
return flags
|
||||
|
||||
def __init__(self, platform, variant="standard"):
|
||||
self.platform = platform
|
||||
self.variant = variant
|
||||
self.reset = Signal()
|
||||
self.ibus = wishbone.Interface()
|
||||
self.dbus = wishbone.Interface()
|
||||
self.periph_buses = [self.ibus, self.dbus]
|
||||
self.memory_buses = []
|
||||
|
||||
ibus = Record(obi_layout)
|
||||
dbus = Record(obi_layout)
|
||||
|
||||
self.submodules.ibus_conv = OBI2Wishbone(ibus, self.ibus)
|
||||
self.submodules.dbus_conv = OBI2Wishbone(dbus, self.dbus)
|
||||
|
||||
self.comb += [
|
||||
ibus.we.eq(0),
|
||||
ibus.be.eq(1111),
|
||||
]
|
||||
|
||||
class Open(Signal): pass
|
||||
self.cpu_params = dict(
|
||||
# Configuration
|
||||
p_RegFile = 1, # RegFileFPGA
|
||||
i_test_en_i = 0,
|
||||
i_hart_id_i = 0,
|
||||
|
||||
# Clk/Rst
|
||||
i_clk_i = ClockSignal(),
|
||||
i_rst_ni = ~ResetSignal(),
|
||||
|
||||
# Instruction bus
|
||||
o_instr_req_o = ibus.req,
|
||||
i_instr_gnt_i = ibus.gnt,
|
||||
i_instr_rvalid_i = ibus.rvalid,
|
||||
o_instr_addr_o = ibus.addr,
|
||||
i_instr_rdata_i = ibus.rdata,
|
||||
i_instr_err_i = 0,
|
||||
|
||||
# Data bus
|
||||
o_data_req_o = dbus.req,
|
||||
i_data_gnt_i = dbus.gnt,
|
||||
i_data_rvalid_i = dbus.rvalid,
|
||||
o_data_we_o = dbus.we,
|
||||
o_data_be_o = dbus.be,
|
||||
o_data_addr_o = dbus.addr,
|
||||
o_data_wdata_o = dbus.wdata,
|
||||
i_data_rdata_i = dbus.rdata,
|
||||
i_data_err_i = 0,
|
||||
|
||||
# Interrupts
|
||||
i_irq_software_i = 0,
|
||||
i_irq_timer_i = 0,
|
||||
i_irq_external_i = 0,
|
||||
i_irq_fast_i = 0,
|
||||
i_irq_nm_i = 0,
|
||||
|
||||
# Debug
|
||||
i_debug_req_i = 0,
|
||||
|
||||
# Control/Status
|
||||
i_fetch_enable_i = 1,
|
||||
o_alert_minor_o = Open(),
|
||||
o_alert_major_o = Open(),
|
||||
o_core_sleep_o = Open()
|
||||
)
|
||||
|
||||
# Add verilog sources
|
||||
self.add_sources(platform)
|
||||
|
||||
@staticmethod
|
||||
def add_sources(platform):
|
||||
# FIXME: Create pythondata-cpu-ibex.
|
||||
os.system("git clone https://github.com/lowRISC/ibex")
|
||||
os.system("git clone https://github.com/lowRISC/opentitan")
|
||||
platform.add_sources(os.path.join("ibex", "rtl"),
|
||||
"ibex_pkg.sv",
|
||||
"ibex_alu.sv",
|
||||
"ibex_compressed_decoder.sv",
|
||||
"ibex_controller.sv",
|
||||
"ibex_counter.sv",
|
||||
"ibex_cs_registers.sv",
|
||||
"ibex_csr.sv",
|
||||
"ibex_decoder.sv",
|
||||
"ibex_ex_block.sv",
|
||||
"ibex_id_stage.sv",
|
||||
"ibex_if_stage.sv",
|
||||
"ibex_load_store_unit.sv",
|
||||
"ibex_multdiv_slow.sv",
|
||||
"ibex_multdiv_fast.sv",
|
||||
"ibex_prefetch_buffer.sv",
|
||||
"ibex_fetch_fifo.sv",
|
||||
"ibex_register_file_fpga.sv",
|
||||
"ibex_wb_stage.sv",
|
||||
"ibex_core.sv",
|
||||
)
|
||||
platform.add_source(os.path.join("ibex", "syn", "rtl", "prim_clock_gating.v"))
|
||||
platform.add_sources(os.path.join("opentitan", "hw", "ip", "prim", "rtl"),
|
||||
"prim_alert_pkg.sv",
|
||||
"prim_assert.sv"
|
||||
)
|
||||
platform.add_verilog_include_path(os.path.join("opentitan", "hw", "ip", "prim", "rtl"))
|
||||
platform.add_verilog_include_path(os.path.join("ibex", "dv", "fcov"))
|
||||
|
||||
def set_reset_address(self, reset_address):
|
||||
assert not hasattr(self, "reset_address")
|
||||
self.reset_address = reset_address
|
||||
self.cpu_params.update(i_boot_addr_i=Signal(32, reset=reset_address))
|
||||
|
||||
def do_finalize(self):
|
||||
assert hasattr(self, "reset_address")
|
||||
self.specials += Instance("ibex_core", **self.cpu_params)
|
|
@ -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
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef __IRQ_H
|
||||
#define __IRQ_H
|
||||
|
||||
#endif /* __IRQ_H */
|
|
@ -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 */
|
Loading…
Reference in New Issue