mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
build/lattice/prjtrellis: simplify code, remove some workarounds
This commit is contained in:
parent
a73d9d96b1
commit
49dab3b448
2 changed files with 59 additions and 53 deletions
|
@ -16,7 +16,7 @@ class BaseSoC(Module):
|
||||||
led0_pads = platform.request("user_led", 0)
|
led0_pads = platform.request("user_led", 0)
|
||||||
led1_pads = platform.request("user_led", 1)
|
led1_pads = platform.request("user_led", 1)
|
||||||
|
|
||||||
# no constraint file for now with prjtrellis
|
# FIXME: no constraint file for now with prjtrellis
|
||||||
platform.lookup_request("clk100").attr.add(("LOC", "P3"))
|
platform.lookup_request("clk100").attr.add(("LOC", "P3"))
|
||||||
platform.lookup_request("clk100").attr.add(("IO_TYPE", "LVDS"))
|
platform.lookup_request("clk100").attr.add(("IO_TYPE", "LVDS"))
|
||||||
platform.lookup_request("user_dip_btn").attr.add(("LOC", "H2"))
|
platform.lookup_request("user_dip_btn").attr.add(("LOC", "H2"))
|
||||||
|
@ -26,7 +26,7 @@ class BaseSoC(Module):
|
||||||
platform.lookup_request("user_led", 1).attr.add(("LOC", "D17"))
|
platform.lookup_request("user_led", 1).attr.add(("LOC", "D17"))
|
||||||
platform.lookup_request("user_led", 1).attr.add(("IO_TYPE", "LVCMOS25"))
|
platform.lookup_request("user_led", 1).attr.add(("IO_TYPE", "LVCMOS25"))
|
||||||
|
|
||||||
# add TRELLIS_IO instance on all inputs/outputs
|
# FIXME: add TRELLIS_IO instance on all inputs/outputs
|
||||||
sys_clk_pads_i = Signal()
|
sys_clk_pads_i = Signal()
|
||||||
btn_pads_i = Signal()
|
btn_pads_i = Signal()
|
||||||
led0_pads_i = Signal()
|
led0_pads_i = Signal()
|
||||||
|
@ -53,7 +53,7 @@ class BaseSoC(Module):
|
||||||
def main():
|
def main():
|
||||||
platform = versaecp55g.Platform(toolchain="prjtrellis")
|
platform = versaecp55g.Platform(toolchain="prjtrellis")
|
||||||
soc = BaseSoC(platform)
|
soc = BaseSoC(platform)
|
||||||
platform.build(soc)
|
platform.build(soc, toolchain_path="/home/florent/dev/symbiflow/prjtrellis") # FIXME
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
# License: BSD
|
# License: BSD
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from migen.fhdl.structure import _Fragment
|
from migen.fhdl.structure import _Fragment
|
||||||
|
@ -12,19 +11,17 @@ from litex.build import tools
|
||||||
from litex.build.lattice import common
|
from litex.build.lattice import common
|
||||||
|
|
||||||
|
|
||||||
def _build_script(source, build_template, build_name, device, basecfg):
|
nextpnr_ecp5_architectures = {
|
||||||
build_script_contents = "# Autogenerated by LiteX\nset -e\n"
|
"lfe5u-25f": "25k",
|
||||||
for s in build_template:
|
"lfe5u-45f": "45k",
|
||||||
build_script_contents += s.format(build_name=build_name, device=device, basecfg=basecfg) + '\n'
|
"lfe5u-85f": "85k",
|
||||||
build_script_file = "build_" + build_name + ".sh"
|
"lfe5um-25f": "um-25k",
|
||||||
tools.write_to_file(build_script_file, build_script_contents)
|
"lfe5um-45f": "um-45k",
|
||||||
return build_script_file
|
"lfe5um-85f": "um-85k",
|
||||||
|
"lfe5um5g-25f": "um5g-25k",
|
||||||
|
"lfe5um5g-45f": "um5g-45k",
|
||||||
def _run_script(script):
|
"lfe5um5g-85f": "um5g-85k",
|
||||||
r = subprocess.call(["bash", script])
|
}
|
||||||
if r != 0:
|
|
||||||
raise OSError("Subprocess failed")
|
|
||||||
|
|
||||||
|
|
||||||
class LatticePrjTrellisToolchain:
|
class LatticePrjTrellisToolchain:
|
||||||
|
@ -43,25 +40,13 @@ class LatticePrjTrellisToolchain:
|
||||||
|
|
||||||
special_overrides = common.lattice_ecpx_special_overrides
|
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",
|
def build(self, platform, fragment, build_dir="build", build_name="top",
|
||||||
toolchain_path=None, run=True):
|
toolchain_path=None, run=True):
|
||||||
os.makedirs(build_dir, exist_ok=True)
|
os.makedirs(build_dir, exist_ok=True)
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
os.chdir(build_dir)
|
os.chdir(build_dir)
|
||||||
|
|
||||||
|
# generate verilog
|
||||||
if not isinstance(fragment, _Fragment):
|
if not isinstance(fragment, _Fragment):
|
||||||
fragment = fragment.get_fragment()
|
fragment = fragment.get_fragment()
|
||||||
platform.finalize(fragment)
|
platform.finalize(fragment)
|
||||||
|
@ -70,36 +55,57 @@ class LatticePrjTrellisToolchain:
|
||||||
named_sc, named_pc = platform.resolve_signals(v_output.ns)
|
named_sc, named_pc = platform.resolve_signals(v_output.ns)
|
||||||
v_file = build_name + ".v"
|
v_file = build_name + ".v"
|
||||||
v_output.write(v_file)
|
v_output.write(v_file)
|
||||||
|
platform.add_source(v_file)
|
||||||
|
|
||||||
yosys_template = self.nextpnr_yosys_template
|
# generate yosys script
|
||||||
ys_contents = "\n".join(_.format(build_name=build_name,
|
def yosys_import_sources(platform):
|
||||||
read_files=self.gen_read_files(platform, v_file))
|
includes = ""
|
||||||
for _ in yosys_template)
|
reads = []
|
||||||
|
for path in platform.verilog_include_paths:
|
||||||
|
includes += " -I" + path
|
||||||
|
for filename, language, library in platform.sources:
|
||||||
|
reads.append("read_{}{} {}".format(
|
||||||
|
language, includes, filename))
|
||||||
|
return "\n".join(reads)
|
||||||
|
|
||||||
ys_name = build_name + ".ys"
|
yosys_script_file = build_name + ".ys"
|
||||||
tools.write_to_file(ys_name, ys_contents)
|
yosys_script_contents = [
|
||||||
|
yosys_import_sources(platform),
|
||||||
|
"synth_ecp5 -nomux -json {build_name}.json -top {build_name}"
|
||||||
|
]
|
||||||
|
yosys_script_contents = "\n".join(yosys_script_contents)
|
||||||
|
yosys_script_contents = yosys_script_contents.format(build_name=build_name)
|
||||||
|
tools.write_to_file(yosys_script_file, yosys_script_contents)
|
||||||
|
|
||||||
build_template = self.nextpnr_build_template
|
# transform platform.device to nextpnr's architecture / basecfg
|
||||||
script = _build_script(False, build_template, build_name,
|
(family, size, package) = platform.device.split("-")
|
||||||
"um5g-45k", # FIXME
|
architecture = nextpnr_ecp5_architectures[(family + "-" + size).lower()]
|
||||||
"../../../../../../../symbiflow/prjtrellis/misc/basecfgs/empty_lfe5um5g-45f.config") # FIXME
|
basecfg = "empty_" + (family + "-" + size).lower() + ".config"
|
||||||
_run_script(script)
|
basecfg = os.path.join(toolchain_path, "misc", "basecfgs", basecfg)
|
||||||
|
|
||||||
|
# generate build script
|
||||||
|
build_script_file = "build_" + build_name + ".sh"
|
||||||
|
build_script_contents = [
|
||||||
|
"yosys -q -l {build_name}.rpt {build_name}.ys",
|
||||||
|
"nextpnr-ecp5 --json {build_name}.json --textcfg {build_name}.config --basecfg {basecfg} --{architecture}",
|
||||||
|
"ecppack {build_name}.config {build_name}.bit"
|
||||||
|
|
||||||
|
]
|
||||||
|
build_script_contents = "\n".join(build_script_contents)
|
||||||
|
build_script_contents = build_script_contents.format(
|
||||||
|
build_name=build_name,
|
||||||
|
architecture=architecture,
|
||||||
|
basecfg=basecfg)
|
||||||
|
tools.write_to_file(build_script_file, build_script_contents)
|
||||||
|
|
||||||
|
# run scripts
|
||||||
|
if run:
|
||||||
|
if subprocess.call(["bash", build_script_file]) != 0:
|
||||||
|
raise OSError("Subprocess failed")
|
||||||
|
|
||||||
os.chdir(cwd)
|
os.chdir(cwd)
|
||||||
|
|
||||||
return v_output.ns
|
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):
|
def add_period_constraint(self, platform, clk, period):
|
||||||
print("TODO: add_period_constraint")
|
print("TODO: add_period_constraint")
|
||||||
|
|
Loading…
Reference in a new issue