Merge pull request #1755 from enjoy-digital/allows_clk_name_override

build/xx/toolchains: allows override clock naming
This commit is contained in:
enjoy-digital 2023-08-31 15:57:39 +02:00 committed by GitHub
commit 124e0d22c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 63 additions and 38 deletions

View File

@ -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"):

View File

@ -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")

View File

@ -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")

View File

@ -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)):

View File

@ -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

View File

@ -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:

View File

@ -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")

View File

@ -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",

View File

@ -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")

View File

@ -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))

View File

@ -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"):

View File

@ -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(

View File

@ -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")

View File

@ -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)

View File

@ -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"):

View File

@ -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 "