diff --git a/litex/build/altera/platform.py b/litex/build/altera/platform.py index 3bef3011f..a389a24f8 100644 --- a/litex/build/altera/platform.py +++ b/litex/build/altera/platform.py @@ -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"): diff --git a/litex/build/altera/quartus.py b/litex/build/altera/quartus.py index 61877283e..f85f3a4c0 100644 --- a/litex/build/altera/quartus.py +++ b/litex/build/altera/quartus.py @@ -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") diff --git a/litex/build/anlogic/anlogic.py b/litex/build/anlogic/anlogic.py index 838f0bf9c..11a3bf223 100644 --- a/litex/build/anlogic/anlogic.py +++ b/litex/build/anlogic/anlogic.py @@ -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") diff --git a/litex/build/efinix/efinity.py b/litex/build/efinix/efinity.py index 1508d6b3e..9e2592e01 100644 --- a/litex/build/efinix/efinity.py +++ b/litex/build/efinix/efinity.py @@ -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)): diff --git a/litex/build/generic_platform.py b/litex/build/generic_platform.py index 14dd17c5e..a9a24eeaa 100644 --- a/litex/build/generic_platform.py +++ b/litex/build/generic_platform.py @@ -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 diff --git a/litex/build/generic_toolchain.py b/litex/build/generic_toolchain.py index 46a01e459..488b92178 100644 --- a/litex/build/generic_toolchain.py +++ b/litex/build/generic_toolchain.py @@ -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: diff --git a/litex/build/gowin/gowin.py b/litex/build/gowin/gowin.py index dac35c25a..a0e693e14 100644 --- a/litex/build/gowin/gowin.py +++ b/litex/build/gowin/gowin.py @@ -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") diff --git a/litex/build/lattice/diamond.py b/litex/build/lattice/diamond.py index 494b01644..6ab994ebc 100644 --- a/litex/build/lattice/diamond.py +++ b/litex/build/lattice/diamond.py @@ -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", diff --git a/litex/build/lattice/icestorm.py b/litex/build/lattice/icestorm.py index 24f164c64..0664a063a 100644 --- a/litex/build/lattice/icestorm.py +++ b/litex/build/lattice/icestorm.py @@ -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") diff --git a/litex/build/lattice/radiant.py b/litex/build/lattice/radiant.py index a0ab290a7..433c2758f 100644 --- a/litex/build/lattice/radiant.py +++ b/litex/build/lattice/radiant.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)) diff --git a/litex/build/lattice/trellis.py b/litex/build/lattice/trellis.py index 367864237..2651f62af 100644 --- a/litex/build/lattice/trellis.py +++ b/litex/build/lattice/trellis.py @@ -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"): diff --git a/litex/build/microsemi/libero_soc.py b/litex/build/microsemi/libero_soc.py index b4ca3cde7..87c7949d2 100644 --- a/litex/build/microsemi/libero_soc.py +++ b/litex/build/microsemi/libero_soc.py @@ -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( diff --git a/litex/build/osfpga/osfpga.py b/litex/build/osfpga/osfpga.py index c7652e535..382e864fc 100644 --- a/litex/build/osfpga/osfpga.py +++ b/litex/build/osfpga/osfpga.py @@ -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") diff --git a/litex/build/xilinx/f4pga.py b/litex/build/xilinx/f4pga.py index 1ce6f9b4c..1d78235c3 100644 --- a/litex/build/xilinx/f4pga.py +++ b/litex/build/xilinx/f4pga.py @@ -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) diff --git a/litex/build/xilinx/ise.py b/litex/build/xilinx/ise.py index d62c9ca85..a2fbda9a4 100755 --- a/litex/build/xilinx/ise.py +++ b/litex/build/xilinx/ise.py @@ -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"): diff --git a/litex/build/xilinx/vivado.py b/litex/build/xilinx/vivado.py index 9b51b65ad..ef3bcf318 100644 --- a/litex/build/xilinx/vivado.py +++ b/litex/build/xilinx/vivado.py @@ -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 "