-# This file is Copyright (c) 2018 Florent Kermarrec <florent@enjoy-digital.fr>
+# This file is Copyright (c) 2018-2019 Florent Kermarrec <florent@enjoy-digital.fr>
# License: BSD
import os
from litex.build.microsemi import common
+# Helpers ------------------------------------------------------------------------------------------
+
def tcl_name(name):
return "{" + name + "}"
+# IO Constraints (.pdc) ----------------------------------------------------------------------------
def _format_io_constraint(c):
if isinstance(c, Pins):
r += "\n"
return r
-
def _build_io_pdc(named_sc, named_pc, build_name, additional_io_constraints):
pdc = ""
for sig, pins, others, resname in named_sc:
pdc += "\n".join(additional_io_constraints)
tools.write_to_file(build_name + "_io.pdc", pdc)
+# Placement Constraints (.pdc) ---------------------------------------------------------------------
def _build_fp_pdc(build_name, additional_fp_constraints):
pdc = "\n".join(additional_fp_constraints)
tools.write_to_file(build_name + "_fp.pdc", pdc)
+# Project (.tcl) -----------------------------------------------------------------------------------
def _build_tcl(platform, sources, build_dir, build_name):
tcl = []
- # create project
+ # Create project
tcl.append(" ".join([
"new_project",
"-location {./impl}",
"-adv_options {VOLTR:EXT} "
]))
- # add files
+ # Add sources
for filename, language, library in sources:
filename_tcl = "{" + filename + "}"
tcl.append("import_files -hdl_source " + filename_tcl)
- # set top
+ # Set top level
tcl.append("set_root -module {}".format(tcl_name(build_name)))
- # copy init files FIXME: support for include path on LiberoSoC?
+ # Copy init files FIXME: support for include path on LiberoSoC?
for file in os.listdir(build_dir):
if file.endswith(".init"):
tcl.append("file copy -- {} impl/synthesis".format(file))
- # import io constraints
+ # Import io constraints
tcl.append("import_files -io_pdc {}".format(tcl_name(build_name + "_io.pdc")))
- # import floorplanner constraints
+ # Import floorplanner constraints
tcl.append("import_files -fp_pdc {}".format(tcl_name(build_name + "_fp.pdc")))
- # import timing constraints
+ # Import timing constraints
tcl.append("import_files -convert_EDN_to_HDL 0 -sdc {}".format(tcl_name(build_name + ".sdc")))
- # associate constraints with tools
+ # Associate constraints with tools
tcl.append(" ".join(["organize_tool_files",
"-tool {SYNTHESIZE}",
"-file impl/constraint/{}.sdc".format(build_name),
"-input_type {constraint}"
]))
- # build flow
+ # Build flow
tcl.append("run_tool -name {CONSTRAINT_MANAGEMENT}")
tcl.append("run_tool -name {SYNTHESIZE}")
tcl.append("run_tool -name {PLACEROUTE}")
tcl.append("run_tool -name {GENERATEPROGRAMMINGDATA}")
tcl.append("run_tool -name {GENERATEPROGRAMMINGFILE}")
- # generate tcl
+ # Generate tcl
tools.write_to_file(build_name + ".tcl", "\n".join(tcl))
+# Timing Constraints (.sdc) ------------------------------------------------------------------------
def _build_timing_sdc(vns, clocks, false_paths, build_name, additional_timing_constraints):
sdc = []
sdc += additional_timing_constraints
tools.write_to_file(build_name + ".sdc", "\n".join(sdc))
+# Script -------------------------------------------------------------------------------------------
def _build_script(build_name, device, toolchain_path, ver=None):
if sys.platform in ("win32", "cygwin"):
script_ext = ".bat"
- build_script_contents = "@echo off\nrem Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n\n"
+ script_contents = "@echo off\nREM Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n\n"
copy_stmt = "copy"
fail_stmt = " || exit /b"
else:
script_ext = ".sh"
- build_script_contents = "# Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n"
+ script_contents = "# Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n"
copy_stmt = "cp"
fail_stmt = " || exit 1"
- build_script_file = "build_" + build_name + script_ext
- tools.write_to_file(build_script_file, build_script_contents,
+ script_file = "build_" + build_name + script_ext
+ tools.write_to_file(script_file, script_contents,
force_unix=False)
- return build_script_file
-
+ return script_file
def _run_script(script):
- if sys.platform in ("win32", "cygwin"):
+ if sys.platform in ["win32", "cygwin"]:
shell = ["cmd", "/c"]
else:
shell = ["bash"]
if subprocess.call(shell + [script]) != 0:
raise OSError("Subprocess failed")
+# MicrosemiLiberoSoCPolarfireToolchain -------------------------------------------------------------
class MicrosemiLiberoSoCPolarfireToolchain:
attr_translate = {
# FIXME: document
- "keep": None,
- "no_retiming": None,
- "async_reg": None,
- "mr_ff": None,
- "mr_false_path": None,
- "ars_ff1": None,
- "ars_ff2": None,
- "ars_false_path": None,
+ "keep": None,
+ "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.microsemi_polarfire_special_overrides
def __init__(self):
- self.clocks = dict()
+ self.clocks = dict()
self.false_paths = set()
- self.additional_io_constraints = []
- self.additional_fp_constraints = []
+ self.additional_io_constraints = []
+ self.additional_fp_constraints = []
self.additional_timing_constraints = []
- def build(self, platform, fragment, build_dir="build", build_name="top",
- toolchain_path=None, run=False, **kwargs):
- # create build directory
+ def build(self, platform, fragment,
+ build_dir = "build",
+ build_name = "top",
+ toolchain_path = None,
+ run = False,
+ **kwargs):
+
+ # Create build directory
os.makedirs(build_dir, exist_ok=True)
cwd = os.getcwd()
os.chdir(build_dir)
- # finalize design
+ # Finalize design
if not isinstance(fragment, _Fragment):
fragment = fragment.get_fragment()
platform.finalize(fragment)
- # generate top module
- top_output = platform.get_verilog(fragment, name=build_name, **kwargs)
- named_sc, named_pc = platform.resolve_signals(top_output.ns)
+ # 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"
- top_output.write(top_file)
+ v_output.write(top_file)
platform.add_source(top_file)
- # generate design script file (.tcl)
+ # Generate design script file (.tcl)
_build_tcl(platform, platform.sources, build_dir, build_name)
- # generate design io constraints file (.pdc)
+ # Generate design io constraints file (.pdc)
_build_io_pdc(named_sc, named_pc, build_name, self.additional_io_constraints)
- # generate design fp constraints file (.pdc)
+ # Generate design placement constraints file (.pdc)
_build_fp_pdc(build_name, self.additional_fp_constraints)
- # generate design timing constraints file (sdc)
- _build_timing_sdc(top_output.ns, self.clocks, self.false_paths, build_name,
+ # Generate design timing constraints file (.sdc)
+ _build_timing_sdc(v_output.ns, self.clocks, self.false_paths, build_name,
self.additional_timing_constraints)
- # generate build script
+ # Generate build script
script = _build_script(build_name, platform.device, toolchain_path)
- # run
+ # Run
if run:
- # delete previous impl
+ # Delete previous impl
if os.path.exists("impl"):
shutil.rmtree("impl")
_run_script(script)
os.chdir(cwd)
- return top_output.ns
+ return v_output.ns
def add_period_constraint(self, platform, clk, period):
if clk in self.clocks: