build/microsemi/libero_soc: add timing constraints support
This commit is contained in:
parent
60faae490a
commit
4c966114f8
|
@ -102,7 +102,7 @@ def _build_tcl(platform, sources, build_dir, build_name):
|
||||||
if file.endswith(".init"):
|
if file.endswith(".init"):
|
||||||
tcl.append("file copy -- {} impl/synthesis".format(file))
|
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("import_files -io_pdc {{{}}}".format(build_name + ".pdc"))
|
||||||
tcl.append(" ".join(["organize_tool_files",
|
tcl.append(" ".join(["organize_tool_files",
|
||||||
"-tool {PLACEROUTE}",
|
"-tool {PLACEROUTE}",
|
||||||
|
@ -111,6 +111,15 @@ def _build_tcl(platform, sources, build_dir, build_name):
|
||||||
"-input_type {constraint}"
|
"-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
|
# build flow
|
||||||
tcl.append("run_tool -name {CONSTRAINT_MANAGEMENT}")
|
tcl.append("run_tool -name {CONSTRAINT_MANAGEMENT}")
|
||||||
tcl.append("run_tool -name {SYNTHESIZE}")
|
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))
|
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):
|
def _build_script(build_name, device, toolchain_path, ver=None):
|
||||||
if sys.platform in ("win32", "cygwin"):
|
if sys.platform in ("win32", "cygwin"):
|
||||||
script_ext = ".bat"
|
script_ext = ".bat"
|
||||||
|
@ -170,6 +197,10 @@ class MicrosemiLiberoSoCPolarfireToolchain:
|
||||||
|
|
||||||
special_overrides = common.microsemi_polarfire_special_overrides
|
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",
|
def build(self, platform, fragment, build_dir="build", build_name="top",
|
||||||
toolchain_path=None, run=False, **kwargs):
|
toolchain_path=None, run=False, **kwargs):
|
||||||
os.makedirs(build_dir, exist_ok=True)
|
os.makedirs(build_dir, exist_ok=True)
|
||||||
|
@ -190,9 +221,12 @@ class MicrosemiLiberoSoCPolarfireToolchain:
|
||||||
# generate design script (tcl)
|
# generate design script (tcl)
|
||||||
_build_tcl(platform, platform.sources, build_dir, build_name)
|
_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)
|
_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
|
# generate build script
|
||||||
script = _build_script(build_name, platform.device, toolchain_path)
|
script = _build_script(build_name, platform.device, toolchain_path)
|
||||||
|
|
||||||
|
@ -205,4 +239,10 @@ class MicrosemiLiberoSoCPolarfireToolchain:
|
||||||
return top_output.ns
|
return top_output.ns
|
||||||
|
|
||||||
def add_period_constraint(self, platform, clk, period):
|
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))
|
||||||
|
|
|
@ -13,7 +13,7 @@ class MicrosemiPlatform(GenericPlatform):
|
||||||
raise ValueError("Unknown toolchain")
|
raise ValueError("Unknown toolchain")
|
||||||
|
|
||||||
def get_verilog(self, *args, special_overrides=dict(), **kwargs):
|
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(self.toolchain.special_overrides)
|
||||||
so.update(special_overrides)
|
so.update(special_overrides)
|
||||||
return GenericPlatform.get_verilog(self, *args, special_overrides=so,
|
return GenericPlatform.get_verilog(self, *args, special_overrides=so,
|
||||||
|
@ -27,3 +27,10 @@ class MicrosemiPlatform(GenericPlatform):
|
||||||
if hasattr(clk, "p"):
|
if hasattr(clk, "p"):
|
||||||
clk = clk.p
|
clk = clk.p
|
||||||
self.toolchain.add_period_constraint(self, clk, period)
|
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)
|
||||||
|
|
Loading…
Reference in New Issue