Merge pull request #1755 from enjoy-digital/allows_clk_name_override
build/xx/toolchains: allows override clock naming
This commit is contained in:
commit
124e0d22c9
|
@ -44,8 +44,8 @@ class AlteraPlatform(GenericPlatform):
|
|||
def build(self, *args, **kwargs):
|
||||
return self.toolchain.build(self, *args, **kwargs)
|
||||
|
||||
def add_period_constraint(self, clk, period, keep=False):
|
||||
self.toolchain.add_period_constraint(self, clk, period, keep=False)
|
||||
def add_period_constraint(self, clk, period, keep=False, name=None):
|
||||
self.toolchain.add_period_constraint(self, clk, period, keep=keep, name=name)
|
||||
|
||||
def add_false_path_constraint(self, from_, to):
|
||||
if hasattr(from_, "p"):
|
||||
|
|
|
@ -89,17 +89,20 @@ class AlteraQuartusToolchain(GenericToolchain):
|
|||
sdc = []
|
||||
|
||||
# Clock constraints
|
||||
for clk, period in sorted(self.clocks.items(), key=lambda x: x[0].duid):
|
||||
for clk, [period, name] in sorted(self.clocks.items(), key=lambda x: x[0].duid):
|
||||
is_port = False
|
||||
for sig, pins, others, resname in self.named_sc:
|
||||
if sig == vns.get_name(clk):
|
||||
is_port = True
|
||||
clk_sig = self._vns.get_name(clk)
|
||||
if name is None:
|
||||
name = clk_sig
|
||||
if is_port:
|
||||
tpl = "create_clock -name {clk} -period {period} [get_ports {{{clk}}}]"
|
||||
sdc.append(tpl.format(clk=vns.get_name(clk), period=str(period)))
|
||||
tpl = "create_clock -name {name} -period {period} [get_ports {{{clk}}}]"
|
||||
sdc.append(tpl.format(name=name, clk=clk_sig, period=str(period)))
|
||||
else:
|
||||
tpl = "create_clock -name {clk} -period {period} [get_nets {{{clk}}}]"
|
||||
sdc.append(tpl.format(clk=vns.get_name(clk), period=str(period)))
|
||||
tpl = "create_clock -name {name} -period {period} [get_nets {{{clk}}}]"
|
||||
sdc.append(tpl.format(name=name, clk=clk_sig, period=str(period)))
|
||||
|
||||
# Enable automatical constraint generation for PLLs
|
||||
sdc.append("derive_pll_clocks -use_net_name")
|
||||
|
|
|
@ -62,8 +62,11 @@ class TangDinastyToolchain(GenericToolchain):
|
|||
|
||||
def build_timing_constraints(self, vns):
|
||||
sdc = []
|
||||
for clk, period in sorted(self.clocks.items(), key=lambda x: x[0].duid):
|
||||
sdc.append(f"create_clock -name {vns.get_name(clk)} -period {str(period)} [get_ports {{{vns.get_name(clk)}}}]")
|
||||
for clk, [period, name] in sorted(self.clocks.items(), key=lambda x: x[0].duid):
|
||||
clk_sig = self._vns.get_name(clk)
|
||||
if name is None:
|
||||
name = clk_sig
|
||||
sdc.append(f"create_clock -name {name} -period {str(period)} [get_ports {{{clk_sig}}}]")
|
||||
tools.write_to_file("top.sdc", "\n".join(sdc))
|
||||
return ("top.sdc", "SDC")
|
||||
|
||||
|
|
|
@ -63,17 +63,22 @@ class EfinityToolchain(GenericToolchain):
|
|||
sdc = []
|
||||
|
||||
# Clock constraints
|
||||
for clk, period in sorted(self.clocks.items(), key=lambda x: x[0].duid):
|
||||
for clk, [period, name] in sorted(self.clocks.items(), key=lambda x: x[0].duid):
|
||||
is_port = False
|
||||
for sig, pins, others, resname in self.named_sc:
|
||||
if sig == self._vns.get_name(clk):
|
||||
is_port = True
|
||||
|
||||
clk_sig = self._vns.get_name(clk)
|
||||
if name is None:
|
||||
name = clk_sig
|
||||
|
||||
if is_port:
|
||||
tpl = "create_clock -name {clk} -period {period} [get_ports {{{clk}}}]"
|
||||
sdc.append(tpl.format(clk=self._vns.get_name(clk), period=str(period)))
|
||||
tpl = "create_clock -name {name} -period {period} [get_ports {{{clk}}}]"
|
||||
sdc.append(tpl.format(name=name, clk=clk_sig, period=str(period)))
|
||||
else:
|
||||
tpl = "create_clock -name {clk} -period {period} [get_nets {{{clk}}}]"
|
||||
sdc.append(tpl.format(clk=self._vns.get_name(clk), period=str(period)))
|
||||
tpl = "create_clock -name {name} -period {period} [get_nets {{{clk}}}]"
|
||||
sdc.append(tpl.format(name=name, clk=clk_sig, period=str(period)))
|
||||
|
||||
# False path constraints
|
||||
for from_, to in sorted(self.false_paths, key=lambda x: (x[0].duid, x[1].duid)):
|
||||
|
|
|
@ -366,8 +366,8 @@ class GenericPlatform:
|
|||
def lookup_request(self, *args, **kwargs):
|
||||
return self.constraint_manager.lookup_request(*args, **kwargs)
|
||||
|
||||
def add_period_constraint(self, clk, period, keep=True):
|
||||
self.toolchain.add_period_constraint(self, clk, period, keep=keep)
|
||||
def add_period_constraint(self, clk, period, keep=True, name=None):
|
||||
self.toolchain.add_period_constraint(self, clk, period, keep=keep, name=name)
|
||||
|
||||
def add_false_path_constraint(self, from_, to):
|
||||
raise NotImplementedError
|
||||
|
|
|
@ -162,7 +162,7 @@ class GenericToolchain:
|
|||
|
||||
return v_output.ns
|
||||
|
||||
def add_period_constraint(self, platform, clk, period, keep=True):
|
||||
def add_period_constraint(self, platform, clk, period, keep=True, name=None):
|
||||
if clk is None:
|
||||
return
|
||||
if hasattr(clk, "p"):
|
||||
|
@ -171,10 +171,10 @@ class GenericToolchain:
|
|||
clk.attr.add("keep")
|
||||
period = math.floor(period*1e3)/1e3 # Round to lowest picosecond.
|
||||
if clk in self.clocks:
|
||||
if period != self.clocks[clk]:
|
||||
if period != self.clocks[clk][0]:
|
||||
raise ValueError("Clock already constrained to {:.2f}ns, new constraint to {:.2f}ns"
|
||||
.format(self.clocks[clk], period))
|
||||
self.clocks[clk] = period
|
||||
self.clocks[clk] = [period, name]
|
||||
|
||||
def add_false_path_constraint(self, platform, from_, to, keep=True):
|
||||
if keep:
|
||||
|
|
|
@ -89,8 +89,11 @@ class GowinToolchain(GenericToolchain):
|
|||
|
||||
def build_timing_constraints(self, vns):
|
||||
sdc = []
|
||||
for clk, period in sorted(self.clocks.items(), key=lambda x: x[0].duid):
|
||||
sdc.append(f"create_clock -name {vns.get_name(clk)} -period {str(period)} [get_ports {{{vns.get_name(clk)}}}]")
|
||||
for clk, [period, name] in sorted(self.clocks.items(), key=lambda x: x[0].duid):
|
||||
clk_sig = self._vns.get_name(clk)
|
||||
if name is None:
|
||||
name = clk_sig
|
||||
sdc.append(f"create_clock -name {name} -period {str(period)} [get_ports {{{clk_sig}}}]")
|
||||
tools.write_to_file(f"{self._build_name}.sdc", "\n".join(sdc))
|
||||
return (f"{self._build_name}.sdc", "SDC")
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ class LatticeDiamondToolchain(GenericToolchain):
|
|||
lpf.append("\n".join(self.named_pc))
|
||||
|
||||
# Note: .lpf is only used post-synthesis, Synplify constraints clocks by default to 200MHz.
|
||||
for clk, period in self.clocks.items():
|
||||
for clk, [period, _] in self.clocks.items():
|
||||
clk_name = self._vns.get_name(clk)
|
||||
lpf.append("FREQUENCY {} \"{}\" {} MHz;".format(
|
||||
"PORT" if clk_name in [name for name, _, _, _ in self.named_sc] else "NET",
|
||||
|
|
|
@ -67,7 +67,7 @@ class LatticeIceStormToolchain(YosysNextPNRToolchain):
|
|||
|
||||
def build_timing_constraints(self, vns):
|
||||
r = ""
|
||||
for clk, period in self.clocks.items():
|
||||
for clk, [period, _] in self.clocks.items():
|
||||
r += """ctx.addClock("{}", {})\n""".format(vns.get_name(clk), 1e3/period)
|
||||
tools.write_to_file(self._build_name + "_pre_pack.py", r)
|
||||
return (self._build_name + "_pre_pack.py", "PY")
|
||||
|
|
|
@ -56,13 +56,15 @@ def _build_pdc(named_sc, named_pc, clocks, vns, build_name):
|
|||
pdc.append("\n".join(named_pc))
|
||||
|
||||
# Note: .pdc is only used post-synthesis, Synplify constraints clocks by default to 200MHz.
|
||||
for clk, period in clocks.items():
|
||||
clk_name = vns.get_name(clk)
|
||||
for clk, [period, clk_name] in clocks.items():
|
||||
clk_sig = vns.get_name(clk)
|
||||
if clk_name is None:
|
||||
clk_name = clk_sig
|
||||
pdc.append("create_clock -period {} -name {} [{} {}];".format(
|
||||
str(period),
|
||||
clk_name,
|
||||
"get_ports" if clk_name in [name for name, _, _, _ in named_sc] else "get_nets",
|
||||
clk_name
|
||||
"get_ports" if clk_sig in [name for name, _, _, _ in named_sc] else "get_nets",
|
||||
clk_sig
|
||||
))
|
||||
|
||||
tools.write_to_file(build_name + ".pdc", "\n".join(pdc))
|
||||
|
|
|
@ -145,7 +145,7 @@ class LatticeTrellisToolchain(YosysNextPNRToolchain):
|
|||
"lfe5um5g-85f": "um5g-85k",
|
||||
}
|
||||
|
||||
def add_period_constraint(self, platform, clk, period):
|
||||
def add_period_constraint(self, platform, clk, period, name=None):
|
||||
if clk is None:
|
||||
return
|
||||
if hasattr(clk, "p"):
|
||||
|
|
|
@ -187,10 +187,13 @@ class MicrosemiLiberoSoCPolarfireToolchain(GenericToolchain):
|
|||
def build_timing_constraints(self, vns):
|
||||
sdc = []
|
||||
|
||||
for clk, period in sorted(self.clocks.items(), key=lambda x: x[0].duid):
|
||||
for clk, [period, name] in sorted(self.clocks.items(), key=lambda x: x[0].duid):
|
||||
clk_sig = self._vns.get_name(clk)
|
||||
if name is None:
|
||||
name = clk_sig
|
||||
sdc.append(
|
||||
"create_clock -name {clk} -period " + str(period) +
|
||||
" [get_nets {clk}]".format(clk=vns.get_name(clk)))
|
||||
"create_clock -name {name} -period " + str(period) +
|
||||
" [get_nets {clk}]".format(name=name, clk=clk_sig))
|
||||
for from_, to in sorted(self.false_paths,
|
||||
key=lambda x: (x[0].duid, x[1].duid)):
|
||||
sdc.append(
|
||||
|
|
|
@ -35,8 +35,11 @@ class OSFPGAToolchain(GenericToolchain):
|
|||
|
||||
def build_timing_constraints(self, vns):
|
||||
sdc = []
|
||||
for clk, period in sorted(self.clocks.items(), key=lambda x: x[0].duid):
|
||||
sdc.append(f"create_clock -name {vns.get_name(clk)} -period {str(period)} [get_ports {{{vns.get_name(clk)}}}]")
|
||||
for clk, [period, name] in sorted(self.clocks.items(), key=lambda x: x[0].duid):
|
||||
clk_sig = self._vns.get_name(clk)
|
||||
if name is None:
|
||||
name = clk_sig
|
||||
sdc.append(f"create_clock -name {name} -period {str(period)} [get_ports {{{clk_sig}}}]")
|
||||
with open(f"{self._build_name}.sdc", "w") as f:
|
||||
f.write("\n".join(sdc))
|
||||
return (self._build_name + ".sdc", "SDC")
|
||||
|
|
|
@ -69,7 +69,7 @@ class F4PGAToolchain(GenericToolchain):
|
|||
|
||||
def build_timing_constraints(self, vns):
|
||||
self.platform.add_platform_command(_xdc_separator("Clock constraints"))
|
||||
for clk, period in sorted(self.clocks.items(), key=lambda x: x[0].duid):
|
||||
for clk, [period, name] in sorted(self.clocks.items(), key=lambda x: x[0].duid):
|
||||
self.platform.add_platform_command(
|
||||
"create_clock -period " + str(period) +
|
||||
" {clk}", clk=clk)
|
||||
|
|
|
@ -205,7 +205,7 @@ bitgen {bitgen_opt} {build_name}.ncd {build_name}.bit{fail_stmt}
|
|||
# constraints and other constraints otherwise it will be unable to trace
|
||||
# them through clock objects like DCM and PLL objects.
|
||||
|
||||
def add_period_constraint(self, platform, clk, period, keep=True):
|
||||
def add_period_constraint(self, platform, clk, period, keep=True, name=None):
|
||||
if clk is None:
|
||||
return
|
||||
if hasattr(clk, "p"):
|
||||
|
|
|
@ -169,10 +169,13 @@ class XilinxVivadoToolchain(GenericToolchain):
|
|||
False : "nets",
|
||||
True : "ports",
|
||||
}[hasattr(clk, "port")]
|
||||
for clk, period in sorted(self.clocks.items(), key=lambda x: x[0].duid):
|
||||
for clk, [period, name] in sorted(self.clocks.items(), key=lambda x: x[0].duid):
|
||||
clk_sig = self._vns.get_name(clk)
|
||||
if name is None:
|
||||
name = clk_sig
|
||||
self.platform.add_platform_command(
|
||||
"create_clock -name {clk} -period " + str(period) +
|
||||
" [get_" + get_clk_type(clk) + " {clk}]", clk=clk)
|
||||
"create_clock -name {name} -period " + str(period) +
|
||||
" [get_" + get_clk_type(clk) + " {clk}]", name=name, clk=clk)
|
||||
for _from, _to in sorted(self.false_paths, key=lambda x: (x[0].duid, x[1].duid)):
|
||||
self.platform.add_platform_command(
|
||||
"set_clock_groups "
|
||||
|
|
Loading…
Reference in New Issue