Merge branch 'master' into cva5

This commit is contained in:
enjoy-digital
2022-05-25 15:18:17 +02:00
committed by GitHub
51 changed files with 726 additions and 375 deletions

View File

@@ -25,16 +25,16 @@ altera_reserved_jtag_pads = [
class AlteraAsyncResetSynchronizerImpl(Module):
def __init__(self, cd, async_reset):
rst_meta = Signal()
rst_meta = Signal(name_override=f'ars_cd_{cd.name}_rst_meta')
self.specials += [
Instance("DFF",
Instance("DFF", name=f'ars_cd_{cd.name}_ff0',
i_d = 0,
i_clk = cd.clk,
i_clrn = 1,
i_prn = ~async_reset,
o_q = rst_meta
),
Instance("DFF",
Instance("DFF", name=f'ars_cd_{cd.name}_ff1',
i_d = rst_meta,
i_clk = cd.clk,
i_clrn = 1,

View File

@@ -156,6 +156,7 @@ def _build_script(build_name, create_rbf):
script_contents = "# Autogenerated by LiteX / git: " + tools.get_litex_git_revision()
script_file = "build_" + build_name + ".sh"
script_contents += """
set -e -u -x -o pipefail
quartus_map --read_settings_files=on --write_settings_files=off {build_name} -c {build_name}
quartus_fit --read_settings_files=off --write_settings_files=off {build_name} -c {build_name}
quartus_asm --read_settings_files=off --write_settings_files=off {build_name} -c {build_name}

View File

@@ -230,7 +230,18 @@ class ConstraintManager:
except ConstraintError:
break
if not len(r):
raise ValueError
raise ValueError(f"Could not request some pin(s) named '{name}'")
return Cat(r)
def request_remaining(self, name):
r = []
while True:
try:
r.append(self.request(name))
except ConstraintError:
break
if not len(r):
raise ValueError(f"Could not request any pins named '{name}'")
return Cat(r)
def lookup_request(self, name, number=None, loose=False):
@@ -321,6 +332,9 @@ class GenericPlatform:
def request_all(self, *args, **kwargs):
return self.constraint_manager.request_all(*args, **kwargs)
def request_remaining(self, *args, **kwargs):
return self.constraint_manager.request_remaining(*args, **kwargs)
def lookup_request(self, *args, **kwargs):
return self.constraint_manager.lookup_request(*args, **kwargs)

View File

@@ -1 +0,0 @@
from litex.build.openfpga.platform import OpenFPGAPlatform

View File

@@ -1,44 +0,0 @@
#!/usr/bin/env python3
#
# 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.build.generic_platform import Pins
from litex.build.openfpga import OpenFPGAPlatform
# export LITEX_ENV_OPENFPGA=/home/florent/dev/openfpga/OpenFPGA
# export LITEX_ENV_OPENFPGA_SOFA=/home/florent/dev/openfpga/SOFA
# Minimal Platform ---------------------------------------------------------------------------------
_io = [
("clk", 0, Pins(1)),
("led", 0, Pins(1))
]
class Platform(OpenFPGAPlatform):
def __init__(self):
OpenFPGAPlatform.__init__(self, "FPGA1212_QLSOFA_HD", _io)
# Minimal Design -----------------------------------------------------------------------------------
platform = Platform()
clk = platform.request("clk")
led = platform.request("led")
module = Module()
module.clock_domains.cd_sys = ClockDomain("sys")
module.comb += module.cd_sys.clk.eq(clk)
counter = Signal(26)
module.comb += led.eq(counter[25])
module.sync += counter.eq(counter + 1)
# Build --------------------------------------------------------------------------------------------
platform.build(module, run=True)

View File

@@ -1,9 +0,0 @@
#
# This file is part of LiteX.
#
# Copyright (c) 2022 Florent Kermarrec <florent@enjoy-digital.fr>
# SPDX-License-Identifier: BSD-2-Clause
# OpenFPGA Special Overrides ---------------------------------------------------------------------
openfpga_special_overrides = {}

View File

@@ -1,152 +0,0 @@
#
# This file is part of LiteX.
#
# Copyright (c) 2022 Florent Kermarrec <florent@enjoy-digital.fr>
# SPDX-License-Identifier: BSD-2-Clause
import os
import sys
import subprocess
from shutil import which
from migen.fhdl.structure import _Fragment
from litex.build.generic_platform import *
from litex.build import tools
from litex.build.openfpga import common
# Check Setup --------------------------------------------------------------------------------------
def _check_setup():
if os.getenv("LITEX_ENV_OPENFPGA", False) == False:
msg = "Unable to find OpenFPGA toolchain, please:\n"
msg += "- Set LITEX_ENV_OPENFPGA environment variant to OpenFPGA's settings path.\n"
raise OSError(msg)
if os.getenv("LITEX_ENV_OPENFPGA_SOFA", False) == False:
msg = "Unable to find OpenFPGA's SOFA project, please:\n"
msg += "- Set LITEX_ENV_OPENFPGA_SOFA environment variant to OpenFPGA's SOFA settings path.\n"
raise OSError(msg)
# Task Config -------------------------------------------------------------------------------------
def _build_task_conf(platform, sources, build_dir, build_name):
# Get Environnment variables.
openfpga_path = os.getenv("LITEX_ENV_OPENFPGA")
openfpga_sofa_path = os.getenv("LITEX_ENV_OPENFPGA_SOFA")
# Get PnR/Task directories from OPENFPGA/SOFA paths.
pnr_path = os.path.join(openfpga_sofa_path, platform.device + "_PNR")
task_path = os.path.join(pnr_path, platform.device + "_task")
# Get Config file.
task_conf = os.path.join(task_path, "config", "task_simulation.conf")
# Helpers.
def replace_openfpga_task_section(filename, section, contents):
lines = []
# Read file and replace section with contents.
copy = True
for line in open(filename, "r"):
if not copy and line.startswith("["):
copy = True
if line.startswith(section):
copy = False
lines.append(section + "\n")
for l in contents:
lines.append(l + "\n")
lines.append("\n")
if copy:
lines.append(line)
# Save file to .orig.
os.system(f"mv {filename} {filename}.orig")
# Write file with replaced section.
with open(filename, "w") as f:
f.write("".join(lines))
# Add sources.
bench_sources = []
for filename, language, library in sources:
if language is None:
continue
if language not in ["verilog"]:
raise ValueError("OpenFPGA flow only supports verilog")
bench_sources.append(filename)
replace_openfpga_task_section(task_conf, "[BENCHMARKS]", [f"bench0={' '.join(bench_sources)}"])
# Set Top-Level.
replace_openfpga_task_section(task_conf, "[SYNTHESIS_PARAM]", [f"bench0_top={build_name}"])
def _run_task(device):
# Get Environnment variables.
openfpga_path = os.getenv("LITEX_ENV_OPENFPGA")
openfpga_sofa_path = os.getenv("LITEX_ENV_OPENFPGA_SOFA")
# Get PnR/Task directories from OPENFPGA/SOFA paths.
pnr_path = os.path.join(openfpga_sofa_path, device + "_PNR")
task_path = os.path.join(pnr_path, device + "_task")
# Set OPENFPGA_PATH.
os.environ["OPENFPGA_PATH"] = os.getenv("LITEX_ENV_OPENFPGA")
# Run OpenFPGA flow.
build_cmd = ["make", "-C", pnr_path, "clean", "runOpenFPGA"]
if subprocess.call(build_cmd) != 0:
raise OSError("Error occured during OpenFPGA's flow execution.")
# Copy artifacts.
os.system("rm -rf run001")
os.system(f"cp -r {task_path}/run001 run001")
# Display log. FIXME: Do it during build?
os.system("cat run001/vpr_arch/top/MIN_ROUTE_CHAN_WIDTH/openfpgashell.log")
# OpenFPGAToolchain --------------------------------------------------------------------------------
class OpenFPGAToolchain:
attr_translate = {}
special_overrides = common.openfpga_special_overrides
def __init__(self):
self.clocks = dict()
self.false_paths = set()
def build(self, platform, fragment,
build_dir = "build",
build_name = "top",
run = False,
**kwargs):
# Create Build Directory.
os.makedirs(build_dir, exist_ok=True)
cwd = os.getcwd()
os.chdir(build_dir)
# Finalize Design.
if not isinstance(fragment, _Fragment):
fragment = fragment.get_fragment()
platform.finalize(fragment)
# Generate Verilog.
v_output = platform.get_verilog(fragment, name=build_name, **kwargs)
named_sc, named_pc = platform.resolve_signals(v_output.ns)
top_file = build_name + ".v"
v_output.write(top_file)
platform.add_source(top_file)
# Check Setup.
_check_setup()
# Generate Task Config.
_build_task_conf(platform, platform.sources, build_dir, build_name)
# Run Task.
if run:
_run_task(platform.device)
os.chdir(cwd)
return v_output.ns

View File

@@ -1,28 +0,0 @@
#
# This file is part of LiteX.
#
# Copyright (c) 2022 Florent Kermarrec <florent@enjoy-digital.fr>
# SPDX-License-Identifier: BSD-2-Clause
import os
from litex.build.generic_platform import GenericPlatform
from litex.build.openfpga import common, openfpga
# OpenFPGAPlatform -------------------------------------------------------------------------------
class OpenFPGAPlatform(GenericPlatform):
def __init__(self, device, *args, **kwargs):
GenericPlatform.__init__(self, device, *args, **kwargs)
self.toolchain = openfpga.OpenFPGAToolchain()
def get_verilog(self, *args, special_overrides=dict(), **kwargs):
so = dict(common.openfpga_special_overrides)
so.update(special_overrides)
return GenericPlatform.get_verilog(self, *args,
special_overrides = so,
attr_translate = self.toolchain.attr_translate,
**kwargs)
def build(self, *args, **kwargs):
return self.toolchain.build(self, *args, **kwargs)

View File

@@ -26,18 +26,21 @@ def _build_sdc(clocks, vns, build_name):
# Script -------------------------------------------------------------------------------------------
def _build_tcl(name, device, files, build_name):
def _build_tcl(name, device, files, build_name, include_paths):
tcl = []
# Create Design.
tcl.append(f"create_design {build_name}")
# Set Device.
# TODO (Use Macro for now).
tcl.append("set_macro P1=10 P2=20")
# FIXME: Directly pass Devices instead of Macro when possible.
macro = {"test": "P1=10 P2=20"}[device]
tcl.append(f"set_macro {macro}")
# Add Include Path.
# TODO.
tcl.append("add_include_path ./")
for include_path in include_paths:
tcl.append(f"add_include_path {include_path}")
# Add Sources.
for f, typ, lib in files:
@@ -107,10 +110,11 @@ class OSFPGAToolchain:
# Generate build script (.tcl)
script = _build_tcl(
name = platform.devicename,
device = platform.device,
files = platform.sources,
build_name = build_name,
name = platform.devicename,
device = platform.device,
files = platform.sources,
build_name = build_name,
include_paths = platform.verilog_include_paths,
)
# Run

View File

@@ -22,7 +22,7 @@ _io = [
class Platform(OSFPGAPlatform):
def __init__(self):
OSFPGAPlatform.__init__(self, device=None, toolchain="raptor", io=_io) # FIXME: Add device support.
OSFPGAPlatform.__init__(self, device="test", toolchain="raptor", io=_io)
# Minimal Design -----------------------------------------------------------------------------------

64
litex/build/osfpga/test_soc.py Executable file
View File

@@ -0,0 +1,64 @@
#!/usr/bin/env python3
#
# This file is part of LiteX.
#
# Copyright (c) 2022 Florent Kermarrec <florent@enjoy-digital.fr>
# SPDX-License-Identifier: BSD-2-Clause
from migen import *
from litex.build.io import CRG
from litex.build.generic_platform import Pins, Subsignal
from litex.build.osfpga import OSFPGAPlatform
from litex.soc.integration.soc_core import *
from litex.soc.integration.builder import *
# Platform ---------------------------------------------------------------------------------
_io = [
# Clk.
("clk", 0, Pins(1)),
# Serial.
("serial", 0,
Subsignal("tx", Pins(1)),
Subsignal("rx", Pins(1)),
),
]
class Platform(OSFPGAPlatform):
def __init__(self, toolchain="foedag"):
OSFPGAPlatform.__init__(self, device="test", toolchain=toolchain, io=_io)
# BaseSoC ------------------------------------------------------------------------------------------
class BaseSoC(SoCCore):
def __init__(self, platform, sys_clk_freq=int(10e6), **kwargs):
# CRG --------------------------------------------------------------------------------------
self.submodules.crg = CRG(platform.request("clk"))
# SoCCore ----------------------------------------------------------------------------------
SoCCore.__init__(self, platform, sys_clk_freq, ident="LiteX Test SoC on OS-FPGA", **kwargs)
# Build --------------------------------------------------------------------------------------------
def main():
from litex.soc.integration.soc import LiteXSoCArgumentParser
parser = LiteXSoCArgumentParser(description="LiteX Test SoC on OS-FPGA")
target_group = parser.add_argument_group(title="Target options")
target_group.add_argument("--build", action="store_true", help="Build design.")
target_group.add_argument("--toolchain", default="foedag", help="FPGA toolchain.")
builder_args(parser)
soc_core_args(parser)
args = parser.parse_args()
platform = Platform(toolchain=args.toolchain)
soc = BaseSoC(platform,**soc_core_argdict(args))
builder = Builder(soc, **builder_argdict(args))
if args.build:
builder.build()
if __name__ == "__main__":
main()

View File

@@ -70,8 +70,8 @@ class IntelClocking(Module, AutoCSR):
break
if valid:
break
if not valid:
all_valid = False
if not valid:
all_valid = False
else:
all_valid = False
if all_valid:

View File

@@ -42,13 +42,13 @@ class CPUNone(CPU):
data_width = 32
endianness = "little"
reset_address = 0x00000000
io_regions = {0x00000000: 0x100000000} # origin, length
io_regions = {0x0000_0000: 0x1_0000_0000} # origin, length
periph_buses = []
memory_buses = []
mem_map = {
"csr" : 0x00000000,
"ethmac" : 0x00020000, # FIXME: Remove.
"spiflash" : 0x10000000, # FIXME: Remove.
"csr" : 0x0000_0000,
"ethmac" : 0x0002_0000, # FIXME: Remove.
"spiflash" : 0x1000_0000, # FIXME: Remove.
}
CPU_GCC_TRIPLE_RISCV64 = (

View File

@@ -65,17 +65,17 @@ class BlackParrot(CPU):
gcc_triple = CPU_GCC_TRIPLE_RISCV64
linker_output_format = "elf64-littleriscv"
nop = "nop"
io_regions = {0x50000000: 0x10000000} # Origin, Length.
io_regions = {0x5000_0000: 0x1000_0000} # Origin, Length.
# Memory Mapping.
@property
def mem_map(self):
# Keep the lower 128MBs for SoC IOs auto-allocation.
return {
"csr" : 0x58000000,
"rom" : 0x70000000,
"sram" : 0x71000000,
"main_ram" : 0x80000000,
"csr" : 0x5800_0000,
"rom" : 0x7000_0000,
"sram" : 0x7100_0000,
"main_ram" : 0x8000_0000,
}
# GCC Flags.
@@ -142,7 +142,7 @@ class BlackParrot(CPU):
def set_reset_address(self, reset_address):
self.reset_address = reset_address
assert reset_address == 0x70000000, "cpu_reset_addr hardcoded to 7x00000000!"
assert reset_address == 0x7000_0000, "cpu_reset_addr hardcoded to 7x00000000!"
@staticmethod
def add_sources(platform, variant="standard"):

View File

@@ -252,7 +252,7 @@ class CV32E41P(CPU):
gcc_triple = CPU_GCC_TRIPLE_RISCV32
linker_output_format = "elf32-littleriscv"
nop = "nop"
io_regions = {0x80000000: 0x80000000} # Origin, Length.
io_regions = {0x8000_0000: 0x8000_0000} # Origin, Length.
# GCC Flags.
@property

View File

@@ -0,0 +1 @@
from litex.soc.cores.cpu.cva6.core import CVA6

View File

@@ -0,0 +1,18 @@
.section .text, "ax", @progbits
.global boot_helper
.global smp_ap_args
.global smp_ap_target
.global smp_ap_ready
boot_helper:
// boot core saves args and jump target for ap cores:
sd a0, smp_ap_args, t1
sd a1, smp_ap_args+8, t1
sd a2, smp_ap_args+16, t1
sd a3, smp_ap_target, t1
fence w, w
// notify application cores to proceed with boot:
li t0, 1
sd t0, smp_ap_ready, t1
// boot core now also ready to boot:
jr a3

View File

@@ -0,0 +1,186 @@
#
# This file is part of LiteX.
#
# Copyright (c) 2021 Hensoldt Cyber GmbH <www.hensoldt-cyber.com>
# Copyright (c) 2022 Florent Kermarrec <florent@enjoy-digital.fr>
# SPDX-License-Identifier: BSD-2-Clause
import os
import re
from migen import *
from litex import get_data_mod
from litex.soc.interconnect import axi
from litex.soc.interconnect import wishbone
from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_RISCV64
class Open(Signal): pass
# Variants -----------------------------------------------------------------------------------------
CPU_VARIANTS = ["standard", "full"]
# GCC Flags ----------------------------------------------------------------------------------------
GCC_FLAGS = {
# /-------- Base ISA
# |/------- Hardware Multiply + Divide
# ||/----- Atomics
# |||/---- Compressed ISA
# ||||/--- Single-Precision Floating-Point
# |||||/-- Double-Precision Floating-Point
# imacfd
"standard": "-march=rv64imac -mabi=lp64 ",
"full": "-march=rv64gc -mabi=lp64 ",
}
# Helpers ------------------------------------------------------------------------------------------
def add_manifest_sources(platform, manifest):
basedir = get_data_mod("cpu", "cva6").data_location
with open(os.path.join(basedir, manifest), 'r') as f:
for l in f:
res = re.search('\$\{CVA6_REPO_DIR\}/(.+)', l)
if res and not re.match('//', l):
if re.match('\+incdir\+', l):
platform.add_verilog_include_path(os.path.join(basedir, res.group(1)))
else:
platform.add_source(os.path.join(basedir, res.group(1)))
# CVA6 ---------------------------------------------------------------------------------------------
class CVA6(CPU):
family = "riscv"
name = "cva6"
human_name = "CVA6"
variants = CPU_VARIANTS
data_width = 64
endianness = "little"
gcc_triple = CPU_GCC_TRIPLE_RISCV64
linker_output_format = "elf64-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__cva6__ "
flags += f" -DUART_POLLING"
return flags
# Memory Mapping.
@property
def mem_map(self):
return {
"rom" : 0x1000_0000,
"sram" : 0x2000_0000,
"csr" : 0x8000_0000,
}
def __init__(self, platform, variant="standard"):
self.platform = platform
self.variant = variant
self.reset = Signal()
self.interrupt = Signal(32)
self.axi_lite_if = axi.AXILiteInterface(data_width=64, address_width=32)
self.periph_buses = [self.axi_lite_if] # Peripheral buses (Connected to main SoC's bus).
self.memory_buses = [] # Memory buses (Connected directly to LiteDRAM).
# # #
# AXI <-> AXILite conversion.
axi_if = axi.AXIInterface(data_width=64, address_width=32, id_width=4)
self.submodules += axi.AXI2AXILite(axi_if, self.axi_lite_if)
# CPU Instance.
self.cpu_params = dict(
# Clk / Rst.
i_clk_i = ClockSignal("sys"),
i_rst_n = ~ResetSignal("sys") | self.reset,
# AXI interface.
o_AWVALID_o = axi_if.aw.valid,
i_AWREADY_i = axi_if.aw.ready,
o_AWID_o = axi_if.aw.id,
o_AWADDR_o = axi_if.aw.addr,
o_AWLEN_o = axi_if.aw.len,
o_AWSIZE_o = axi_if.aw.size,
o_AWBURST_o = axi_if.aw.burst,
o_AWLOCK_o = axi_if.aw.lock,
o_AWCACHE_o = axi_if.aw.cache,
o_AWPROT_o = axi_if.aw.prot,
o_AWQOS_o = axi_if.aw.qos,
o_AWREGION_o = Open(),
o_AWUSER_o = Open(),
o_WVALID_o = axi_if.w.valid,
i_WREADY_i = axi_if.w.ready,
o_WDATA_o = axi_if.w.data,
o_WSTRB_o = axi_if.w.strb,
o_WLAST_o = axi_if.w.last,
o_WUSER_o = Open(),
i_BVALID_i = axi_if.b.valid,
o_BREADY_o = axi_if.b.ready,
i_BID_i = axi_if.b.id,
i_BRESP_i = axi_if.b.resp,
i_BUSER_i = 0,
o_ARVALID_o = axi_if.ar.valid,
i_ARREADY_i = axi_if.ar.ready,
o_ARID_o = axi_if.ar.id,
o_ARADDR_o = axi_if.ar.addr,
o_ARLEN_o = axi_if.ar.len,
o_ARSIZE_o = axi_if.ar.size,
o_ARBURST_o = axi_if.ar.burst,
o_ARLOCK_o = axi_if.ar.lock,
o_ARCACHE_o = axi_if.ar.cache,
o_ARPROT_o = axi_if.ar.prot,
o_ARQOS_o = axi_if.ar.qos,
o_ARUSER_o = Open(),
o_ARREGION_o = Open(),
i_RVALID_i = axi_if.r.valid,
o_RREADY_o = axi_if.r.ready,
i_RID_i = axi_if.r.id,
i_RDATA_i = axi_if.r.data,
i_RRESP_i = axi_if.r.resp,
i_RLAST_i = axi_if.r.last,
i_RUSER_i = 0,
)
# Add Verilog sources.
# TODO: use Flist.cv64a6_imafdc_sv39 and Flist.cv32a6_imac_sv0 instead
add_manifest_sources(platform, "Flist.cv64a6_imafdc_sv39")
add_manifest_sources(platform, "Flist.cva6_wrapper")
def add_jtag(pads):
from migen.fhdl.specials import Tristate
self.jtag_tck = Signal()
self.jtag_tms = Signal()
self.jtag_trst = Signal()
self.jtag_tdi = Signal()
self.jtag_tdo = Signal()
tdo_o = Signal()
tdo_oe = Signal()
self.specials += Tristate(self.jtag_tdo, tdo_o, tdo_oe)
self.cpu_params.update(
i_trst_n = self.jtag_trst,
i_tck = self.jtag_tck,
i_tms = self.jtag_tms,
i_tdi = self.jtag_tdi,
o_tdo = tdo_o,
o_tdo_oe = tdo_oe,
)
def set_reset_address(self, reset_address):
self.reset_address = reset_address
assert reset_address == 0x1000_0000, "cpu_reset_addr hardcoded in during elaboration!"
def do_finalize(self):
assert hasattr(self, "reset_address")
self.specials += Instance("cva6_wrapper", **self.cpu_params)

View File

@@ -0,0 +1,125 @@
.global main
.global isr
.global _start
.global smp_ap_args
.global smp_ap_target
.global smp_ap_ready
_start:
j crt_init
nop
nop
nop
nop
nop
nop
nop
trap_entry:
sd x1, - 1*8(sp)
sd x5, - 2*8(sp)
sd x6, - 3*8(sp)
sd x7, - 4*8(sp)
sd x10, - 5*8(sp)
sd x11, - 6*8(sp)
sd x12, - 7*8(sp)
sd x13, - 8*8(sp)
sd x14, - 9*8(sp)
sd x15, -10*8(sp)
sd x16, -11*8(sp)
sd x17, -12*8(sp)
sd x28, -13*8(sp)
sd x29, -14*8(sp)
sd x30, -15*8(sp)
sd x31, -16*8(sp)
addi sp,sp,-16*8
call isr
ld x1 , 15*8(sp)
ld x5, 14*8(sp)
ld x6, 13*8(sp)
ld x7, 12*8(sp)
ld x10, 11*8(sp)
ld x11, 10*8(sp)
ld x12, 9*8(sp)
ld x13, 8*8(sp)
ld x14, 7*8(sp)
ld x15, 6*8(sp)
ld x16, 5*8(sp)
ld x17, 4*8(sp)
ld x28, 3*8(sp)
ld x29, 2*8(sp)
ld x30, 1*8(sp)
ld x31, 0*8(sp)
addi sp,sp,16*8
mret
.text
crt_init:
la sp, _fstack
sd zero, smp_ap_ready, t0
la t0, trap_entry
csrw mtvec, t0
smp_select_bp:
csrr a0, mhartid
beqz a0, data_init // hart 0 is bp, everyone else is ap
smp_ap_loop:
ld t0, smp_ap_ready
beqz t0, smp_ap_loop
smp_ap_boot:
fence r, r
fence.i // i$ flush
ld a0, smp_ap_args // hart ID (but next-stage loads its own)
ld a1, smp_ap_args+8 // DTB pointer (if provded by litex bios)
ld a2, smp_ap_args+16
ld a3, smp_ap_target
jr a3
smp_ap_done:
data_init:
la t0, _fdata
la t1, _edata
la t2, _fdata_rom
data_loop:
beq t0,t1,data_done
ld t3,0(t2)
sd t3,0(t0)
add t0,t0,8
add t2,t2,8
j data_loop
data_done:
bss_init:
la t0, _fbss
la t1, _ebss
bss_loop:
beq t0,t1,bss_done
sd zero,0(t0)
add t0,t0,8
j bss_loop
bss_done:
// call plic_init // initialize external interrupt controller
li t0, 0x800 // external interrupt sources only (using LiteX timer);
// NOTE: must still enable mstatus.MIE!
csrw mie,t0
call main
inf_loop:
j inf_loop
.bss
.align 8
smp_ap_args:
.dword 0
.dword 0
.dword 0
.align 8
smp_ap_target:
.dword 0
.align 8
smp_ap_ready:
.dword 0

View File

@@ -0,0 +1,8 @@
#ifndef CSR_DEFS__H
#define CSR_DEFS__H
#define CSR_MSTATUS_MIE 0x8
#define CSR_DCACHE_INFO 0xCC0
#endif /* CSR_DEFS__H */

Some files were not shown because too many files have changed in this diff Show More