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