mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-02-03 15:12:52 +00:00
This comes in two parts: - A generator script which uses LiteX to generate litedram cores along with their init files for various boards (currently Arty and Nexys-video). This comes with configs for arty and nexys_video. - A fusesoc "generator" which uses pre-generated litedram cores The generation process is manual on purpose. This include pre-generated cores for the two above boards. This is done so that one doesn't have to install LiteX to build microwatt. In addition, the generator script or wrapper vhdl tend to break when LiteX changes significantly which happens. This is still rather standalone and hasn't been plumbed into the SoC or the FPGA toplevel files yet. At this point LiteDRAM self-initializes using a built-in VexRiscv "Minimum" core obtained from LiteX and included in this commit. There is some plumbing to generate and cores that are initialized by Microwatt directly but this isn't working yet and so isn't enabled yet. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
151 lines
5.2 KiB
Python
Executable File
151 lines
5.2 KiB
Python
Executable File
#!/usr/bin/python3
|
|
|
|
from fusesoc.capi2.generator import Generator
|
|
from litex.build.tools import write_to_file
|
|
from litex.build.tools import replace_in_file
|
|
from litex.build.generic_platform import *
|
|
from litex.build.xilinx import XilinxPlatform
|
|
from litex.build.lattice import LatticePlatform
|
|
from litex.soc.integration.builder import *
|
|
from litedram.gen import *
|
|
import subprocess
|
|
import os
|
|
import sys
|
|
import yaml
|
|
import shutil
|
|
|
|
def make_new_dir(base, added):
|
|
r = os.path.join(base, added)
|
|
if os.path.exists(r):
|
|
shutil.rmtree(r)
|
|
os.mkdir(r)
|
|
return r
|
|
|
|
gen_src_dir = os.path.dirname(os.path.realpath(__file__))
|
|
base_dir = os.path.join(gen_src_dir, os.pardir)
|
|
build_top_dir = make_new_dir(base_dir, "build")
|
|
gen_src_dir = os.path.join(base_dir, "gen-src")
|
|
gen_dir = make_new_dir(base_dir, "generated")
|
|
|
|
# Build the init code for microwatt-initialized DRAM
|
|
#
|
|
# XXX Not working yet
|
|
#
|
|
def build_init_code(build_dir):
|
|
|
|
# More path fudging
|
|
sw_dir = os.path.join(build_dir, "software");
|
|
sw_inc_dir = os.path.join(build_dir, "include")
|
|
gen_inc_dir = os.path.join(sw_inc_dir, "generated")
|
|
src_dir = os.path.join(gen_src_dir, "sdram_init")
|
|
lxbios_src_dir = os.path.join(soc_directory, "software", "bios")
|
|
lxbios_inc_dir = os.path.join(soc_directory, "software", "include")
|
|
print(" sw dir:", sw_dir)
|
|
print("gen_inc_dir:", gen_inc_dir)
|
|
print(" src dir:", src_dir)
|
|
print(" lx src dir:", lxbios_src_dir)
|
|
print(" lx inc dir:", lxbios_inc_dir)
|
|
|
|
# Generate mem.h
|
|
mem_h = "#define MAIN_RAM_BASE 0x40000000"
|
|
write_to_file(os.path.join(gen_inc_dir, "mem.h"), mem_h)
|
|
|
|
# Environment
|
|
env_vars = []
|
|
def _makefile_escape(s): # From LiteX
|
|
return s.replace("\\", "\\\\")
|
|
def add_var(k, v):
|
|
env_vars.append("{}={}\n".format(k, _makefile_escape(v)))
|
|
|
|
add_var("BUILD_DIR", sw_dir)
|
|
add_var("SRC_DIR", src_dir)
|
|
add_var("GENINC_DIR", gen_inc_dir)
|
|
add_var("LXSRC_DIR", lxbios_src_dir)
|
|
add_var("LXINC_DIR", lxbios_inc_dir)
|
|
write_to_file(os.path.join(gen_inc_dir, "variables.mak"), "".join(env_vars))
|
|
|
|
# Build init code
|
|
print(" Generating init software...")
|
|
makefile = os.path.join(src_dir, "Makefile")
|
|
r = subprocess.check_call(["make", "-C", build_dir, "-I", gen_inc_dir, "-f", makefile])
|
|
print("Make result:", r)
|
|
|
|
return os.path.join(sw_dir, "obj", "sdram_init.hex")
|
|
|
|
def generate_one(t):
|
|
|
|
print("Generating target:", t)
|
|
|
|
# Muck with directory path
|
|
build_dir = make_new_dir(build_top_dir, t)
|
|
t_dir = make_new_dir(gen_dir, t)
|
|
|
|
# Grab config file
|
|
cfile = os.path.join(gen_src_dir, t + ".yml")
|
|
core_config = yaml.load(open(cfile).read(), Loader=yaml.Loader)
|
|
|
|
### TODO: Make most stuff below a function in litedram gen.py and
|
|
### call it rather than duplicate it
|
|
###
|
|
|
|
# Convert YAML elements to Python/LiteX
|
|
for k, v in core_config.items():
|
|
replaces = {"False": False, "True": True, "None": None}
|
|
for r in replaces.keys():
|
|
if v == r:
|
|
core_config[k] = replaces[r]
|
|
if "clk_freq" in k:
|
|
core_config[k] = float(core_config[k])
|
|
if k == "sdram_module":
|
|
core_config[k] = getattr(litedram_modules, core_config[k])
|
|
if k == "sdram_phy":
|
|
core_config[k] = getattr(litedram_phys, core_config[k])
|
|
|
|
# Generate core
|
|
if core_config["sdram_phy"] in [litedram_phys.ECP5DDRPHY]:
|
|
platform = LatticePlatform("LFE5UM5G-45F-8BG381C", io=[], toolchain="trellis")
|
|
elif core_config["sdram_phy"] in [litedram_phys.A7DDRPHY, litedram_phys.K7DDRPHY, litedram_phys.V7DDRPHY]:
|
|
platform = XilinxPlatform("", io=[], toolchain="vivado")
|
|
else:
|
|
raise ValueError("Unsupported SDRAM PHY: {}".format(core_config["sdram_phy"]))
|
|
|
|
soc = LiteDRAMCore(platform, core_config, integrated_rom_size=0x6000)
|
|
|
|
# Build into build_dir
|
|
builder = Builder(soc, output_dir=build_dir, compile_gateware=False)
|
|
vns = builder.build(build_name="litedram_core", regular_comb=False)
|
|
|
|
# Grab generated gatewar dir
|
|
gw_dir = os.path.join(build_dir, "gateware")
|
|
|
|
# Generate init-cpu.txt if any and generate init code if none
|
|
cpu = core_config["cpu"]
|
|
if cpu is None:
|
|
print("Microwatt based inits not supported yet !")
|
|
src_wrap_file = os.path.join(gen_src_dir, "wrapper-mw-init.vhdl")
|
|
src_init_file = build_init_code(build_dir)
|
|
else:
|
|
write_to_file(os.path.join(t_dir, "init-cpu.txt"), cpu)
|
|
src_wrap_file = os.path.join(gen_src_dir, "wrapper-self-init.vhdl")
|
|
src_init_file = os.path.join(gw_dir, "mem.init")
|
|
|
|
# Copy generated files to target dir, amend them if necessary
|
|
core_file = os.path.join(gw_dir, "litedram_core.v")
|
|
dst_init_file = os.path.join(t_dir, "litedram_core.init")
|
|
dst_wrap_file = os.path.join(t_dir, "litedram-wrapper.vhdl")
|
|
replace_in_file(core_file, "mem.init", "litedram_core.init")
|
|
shutil.copy(core_file, t_dir)
|
|
shutil.copyfile(src_init_file, dst_init_file)
|
|
shutil.copyfile(src_wrap_file, dst_wrap_file)
|
|
|
|
def main():
|
|
|
|
targets = ['arty','nexys-video']
|
|
for t in targets:
|
|
generate_one(t)
|
|
|
|
# XXX TODO: Remove build dir unless told not to via cmdline option
|
|
|
|
if __name__ == "__main__":
|
|
main()
|