build.res: simplify clock constraints.

Before this commit, it was possible to set and get clock constraints
placed on Pin objects. This was not a very good implementation, since
it relied on matching the identity of the provided Pin object to
a previously requested one. The only reason it worked like that is
deficiencies in nextpnr.

Since then, nextpnr has been fixed to allow setting constraints on
arbitrary nets. Correspondingly, backends that are using Synplify
were changed to use [get_nets] instead of [get_ports] in SDC files.
However, in some situations, Synplify does not allow specifying
ports in [get_nets]. (In fact, nextpnr had a similar problem, but
it has also been fixed.)

The simplest way to address this is to refer to the interior net
(after the input buffer), which always works. The only downside
of this is that requesting a clock as a raw pin using
    platform.request("clk", dir="-")
and directly applying a constraint to it could fail in some cases.
This is not a significant issue.
This commit is contained in:
whitequark 2019-09-21 14:12:29 +00:00
parent 07a82ed70e
commit 8050cfaa98
2 changed files with 10 additions and 47 deletions

View file

@ -147,7 +147,7 @@ class ResourceManager:
self._ports.append((resource, pin, port, attrs))
if pin is not None and resource.clock is not None:
self.add_clock_constraint(pin, resource.clock.frequency)
self.add_clock_constraint(pin.i, resource.clock.frequency)
return pin if pin is not None else port
@ -212,32 +212,12 @@ class ResourceManager:
for bit, pin_name in enumerate(pin_names):
yield "{}[{}]".format(port_name, bit), pin_name, attrs
def _map_clock_to_port(self, clock):
if not isinstance(clock, (Signal, Pin)):
raise TypeError("Object {!r} is not a Signal or Pin".format(clock))
if isinstance(clock, Pin):
for res, pin, port, attrs in self._ports:
if clock is pin:
if isinstance(res.ios[0], Pins):
clock = port.io
elif isinstance(res.ios[0], DiffPairs):
clock = port.p
else:
assert False
break
else:
raise ValueError("The Pin object {!r}, which is not a previously requested "
"resource, cannot be used to desigate a clock"
.format(clock))
return clock
def add_clock_constraint(self, clock, frequency):
if not isinstance(clock, Signal):
raise TypeError("Object {!r} is not a Signal".format(clock))
if not isinstance(frequency, (int, float)):
raise TypeError("Frequency must be a number, not {!r}".format(frequency))
clock = self._map_clock_to_port(clock)
if clock in self._clocks:
raise ValueError("Cannot add clock constraint on {!r}, which is already constrained "
"to {} Hz"
@ -245,9 +225,5 @@ class ResourceManager:
else:
self._clocks[clock] = float(frequency)
def get_clock_constraint(self, clock):
clock = self._map_clock_to_port(clock)
return self._clocks[clock]
def iter_clock_constraints(self):
return iter(self._clocks.items())