build/microsemi/libero_soc: add timing constraints support

This commit is contained in:
Florent Kermarrec 2018-11-19 09:40:16 +01:00
parent 60faae490a
commit 4c966114f8
2 changed files with 52 additions and 5 deletions

View File

@ -102,7 +102,7 @@ def _build_tcl(platform, sources, build_dir, build_name):
if file.endswith(".init"):
tcl.append("file copy -- {} impl/synthesis".format(file))
# import constraints
# import io constraints
tcl.append("import_files -io_pdc {{{}}}".format(build_name + ".pdc"))
tcl.append(" ".join(["organize_tool_files",
"-tool {PLACEROUTE}",
@ -111,6 +111,15 @@ def _build_tcl(platform, sources, build_dir, build_name):
"-input_type {constraint}"
]))
# import timing constraints
tcl.append("import_files -convert_EDN_to_HDL 0 -sdc {{{}}}".format(build_name + ".sdc"))
tcl.append(" ".join(["organize_tool_files",
"-tool {VERIFYTIMING}",
"-file impl/constraint/{}.sdc".format(build_name),
"-module {}".format(build_name),
"-input_type {constraint}"
]))
# build flow
tcl.append("run_tool -name {CONSTRAINT_MANAGEMENT}")
tcl.append("run_tool -name {SYNTHESIZE}")
@ -129,6 +138,24 @@ def _build_tcl(platform, sources, build_dir, build_name):
tools.write_to_file(build_name + ".tcl", "\n".join(tcl))
def _build_sdc(vns, clocks, false_paths, build_name):
sdc = []
for clk, period in sorted(clocks.items(), key=lambda x: x[0].duid):
sdc.append(
"create_clock -name {clk} -period " + str(period) +
" [get_nets {clk}]".format(clk=vns.get_name(clk)))
for from_, to in sorted(false_paths,
key=lambda x: (x[0].duid, x[1].duid)):
sdc.append(
"set_clock_groups "
"-group [get_clocks -include_generated_clocks -of [get_nets {from_}]] "
"-group [get_clocks -include_generated_clocks -of [get_nets {to}]] "
"-asynchronous".format(from_=from_, to=to))
# generate sdc
tools.write_to_file(build_name + ".sdc", "\n".join(sdc))
def _build_script(build_name, device, toolchain_path, ver=None):
if sys.platform in ("win32", "cygwin"):
script_ext = ".bat"
@ -170,6 +197,10 @@ class MicrosemiLiberoSoCPolarfireToolchain:
special_overrides = common.microsemi_polarfire_special_overrides
def __init__(self):
self.clocks = dict()
self.false_paths = set()
def build(self, platform, fragment, build_dir="build", build_name="top",
toolchain_path=None, run=False, **kwargs):
os.makedirs(build_dir, exist_ok=True)
@ -190,9 +221,12 @@ class MicrosemiLiberoSoCPolarfireToolchain:
# generate design script (tcl)
_build_tcl(platform, platform.sources, build_dir, build_name)
# generate design constraints (pdc)
# generate design io constraints (pdc)
_build_pdc(named_sc, named_pc, build_name)
# generate design timing constraints (sdc)
_build_sdc(top_output.ns, self.clocks, self.false_paths, build_name)
# generate build script
script = _build_script(build_name, platform.device, toolchain_path)
@ -205,4 +239,10 @@ class MicrosemiLiberoSoCPolarfireToolchain:
return top_output.ns
def add_period_constraint(self, platform, clk, period):
print("TODO: add_period_constraint")
if clk in self.clocks:
raise ValueError("A period constraint already exists")
self.clocks[clk] = period
def add_false_path_constraint(self, platform, from_, to):
if (to, from_) not in self.false_paths:
self.false_paths.add((from_, to))

View File

@ -13,7 +13,7 @@ class MicrosemiPlatform(GenericPlatform):
raise ValueError("Unknown toolchain")
def get_verilog(self, *args, special_overrides=dict(), **kwargs):
so = dict() # No common overrides between ECP and ice40.
so = dict()
so.update(self.toolchain.special_overrides)
so.update(special_overrides)
return GenericPlatform.get_verilog(self, *args, special_overrides=so,
@ -27,3 +27,10 @@ class MicrosemiPlatform(GenericPlatform):
if hasattr(clk, "p"):
clk = clk.p
self.toolchain.add_period_constraint(self, clk, period)
def add_false_path_constraint(self, from_, to):
if hasattr(from_, "p"):
from_ = from_.p
if hasattr(to, "p"):
to = to.p
self.toolchain.add_false_path_constraint(self, from_, to)