1
0
mirror of https://github.com/antonblanchard/microwatt.git synced 2026-02-03 15:12:52 +00:00
Files
antonblanchard.microwatt/litedram/gen-src/generate.py
Benjamin Herrenschmidt 982cf166dd litedram: Add basic support for LiteX LiteDRAM
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>
2020-05-08 11:41:06 +10:00

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()