build/lattice: add initial prjtrellis support
This commit is contained in:
parent
397e3c7682
commit
a69197d2db
|
@ -1,5 +1,5 @@
|
||||||
from litex.build.generic_platform import GenericPlatform
|
from litex.build.generic_platform import GenericPlatform
|
||||||
from litex.build.lattice import common, diamond, icestorm
|
from litex.build.lattice import common, diamond, icestorm, prjtrellis
|
||||||
|
|
||||||
|
|
||||||
class LatticePlatform(GenericPlatform):
|
class LatticePlatform(GenericPlatform):
|
||||||
|
@ -9,6 +9,8 @@ class LatticePlatform(GenericPlatform):
|
||||||
GenericPlatform.__init__(self, *args, **kwargs)
|
GenericPlatform.__init__(self, *args, **kwargs)
|
||||||
if toolchain == "diamond":
|
if toolchain == "diamond":
|
||||||
self.toolchain = diamond.LatticeDiamondToolchain()
|
self.toolchain = diamond.LatticeDiamondToolchain()
|
||||||
|
elif toolchain == "prjtrellis":
|
||||||
|
self.toolchain = prjtrellis.LatticePrjTrellisToolchain()
|
||||||
elif toolchain == "icestorm":
|
elif toolchain == "icestorm":
|
||||||
self.bitstream_ext = ".bin"
|
self.bitstream_ext = ".bin"
|
||||||
self.toolchain = icestorm.LatticeIceStormToolchain()
|
self.toolchain = icestorm.LatticeIceStormToolchain()
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
# This file is Copyright (c) 2018 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||||
|
# License: BSD
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from migen.fhdl.structure import _Fragment
|
||||||
|
|
||||||
|
from litex.build.generic_platform import *
|
||||||
|
from litex.build import tools
|
||||||
|
from litex.build.lattice import common
|
||||||
|
|
||||||
|
|
||||||
|
def _build_script(source, build_template, build_name, device, basecfg):
|
||||||
|
build_script_contents = "# Autogenerated by LiteX\nset -e\n"
|
||||||
|
for s in build_template:
|
||||||
|
build_script_contents += s.format(build_name=build_name, device=device, basecfg=basecfg) + '\n'
|
||||||
|
build_script_file = "build_" + build_name + ".sh"
|
||||||
|
tools.write_to_file(build_script_file, build_script_contents)
|
||||||
|
return build_script_file
|
||||||
|
|
||||||
|
|
||||||
|
def _run_script(script):
|
||||||
|
r = subprocess.call(["bash", script])
|
||||||
|
if r != 0:
|
||||||
|
raise OSError("Subprocess failed")
|
||||||
|
|
||||||
|
|
||||||
|
class LatticePrjTrellisToolchain:
|
||||||
|
attr_translate = {
|
||||||
|
# FIXME: document
|
||||||
|
"keep": ("keep", "true"),
|
||||||
|
"no_retiming": None,
|
||||||
|
"async_reg": None,
|
||||||
|
"mr_ff": None,
|
||||||
|
"mr_false_path": None,
|
||||||
|
"ars_ff1": None,
|
||||||
|
"ars_ff2": None,
|
||||||
|
"ars_false_path": None,
|
||||||
|
"no_shreg_extract": None
|
||||||
|
}
|
||||||
|
|
||||||
|
special_overrides = common.lattice_ecpx_special_overrides
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.nextpnr_yosys_template = [
|
||||||
|
"{read_files}",
|
||||||
|
"attrmap -tocase keep -imap keep=\"true\" keep=1 -imap keep=\"false\" keep=0 -remove keep=0",
|
||||||
|
"synth_ecp5 -nomux -json {build_name}.json -top {build_name}",
|
||||||
|
]
|
||||||
|
|
||||||
|
self.nextpnr_build_template = [
|
||||||
|
"yosys -q -l {build_name}.rpt {build_name}.ys",
|
||||||
|
"nextpnr-ecp5 --json {build_name}.json --textcfg {build_name}.config --basecfg {basecfg} --{device}",
|
||||||
|
"ecppack {build_name}.config {build_name}.bit"
|
||||||
|
]
|
||||||
|
|
||||||
|
def build(self, platform, fragment, build_dir="build", build_name="top",
|
||||||
|
toolchain_path=None, run=True):
|
||||||
|
os.makedirs(build_dir, exist_ok=True)
|
||||||
|
cwd = os.getcwd()
|
||||||
|
os.chdir(build_dir)
|
||||||
|
|
||||||
|
if not isinstance(fragment, _Fragment):
|
||||||
|
fragment = fragment.get_fragment()
|
||||||
|
platform.finalize(fragment)
|
||||||
|
|
||||||
|
v_output = platform.get_verilog(fragment)
|
||||||
|
named_sc, named_pc = platform.resolve_signals(v_output.ns)
|
||||||
|
v_file = build_name + ".v"
|
||||||
|
v_output.write(v_file)
|
||||||
|
|
||||||
|
yosys_template = self.nextpnr_yosys_template
|
||||||
|
ys_contents = "\n".join(_.format(build_name=build_name,
|
||||||
|
read_files=self.gen_read_files(platform, v_file))
|
||||||
|
for _ in yosys_template)
|
||||||
|
|
||||||
|
ys_name = build_name + ".ys"
|
||||||
|
tools.write_to_file(ys_name, ys_contents)
|
||||||
|
|
||||||
|
build_template = self.nextpnr_build_template
|
||||||
|
script = _build_script(False, build_template, build_name,
|
||||||
|
"um5g-45k", # FIXME
|
||||||
|
"../../../../../../../symbiflow/prjtrellis/misc/basecfgs/empty_lfe5um5g-45f.config") # FIXME
|
||||||
|
_run_script(script)
|
||||||
|
|
||||||
|
os.chdir(cwd)
|
||||||
|
|
||||||
|
return v_output.ns
|
||||||
|
|
||||||
|
def gen_read_files(self, platform, main):
|
||||||
|
sources = platform.sources + [(main, "verilog", "work")]
|
||||||
|
incflags = ""
|
||||||
|
read_files = list()
|
||||||
|
for path in platform.verilog_include_paths:
|
||||||
|
incflags += " -I" + path
|
||||||
|
for filename, language, library in sources:
|
||||||
|
read_files.append("read_{}{} {}".format(language,
|
||||||
|
incflags,
|
||||||
|
filename))
|
||||||
|
return "\n".join(read_files)
|
||||||
|
|
||||||
|
def add_period_constraint(self, platform, clk, period):
|
||||||
|
print("TODO: add_period_constraint")
|
Loading…
Reference in New Issue