fragment = Fragment.get(fragment, self)
- pin_fragments = []
- for pin, port in self._se_pins:
+ def add_pin_fragment(pin, pin_fragment):
+ pin_fragment = Fragment.get(pin_fragment, self)
+ if not isinstance(pin_fragment, Instance):
+ pin_fragment.flatten = True
+ fragment.add_subfragment(pin_fragment, name="pin_{}".format(pin.name))
+
+ for pin, port, extras in self.iter_single_ended_pins():
if pin.dir == "i":
- pin_fragments.append((pin.name, self.get_input(pin, port)))
+ add_pin_fragment(pin, self.get_input(pin, port, extras))
if pin.dir == "o":
- pin_fragments.append((pin.name, self.get_output(pin, port)))
+ add_pin_fragment(pin, self.get_output(pin, port, extras))
if pin.dir == "io":
- pin_fragments.append((pin.name, self.get_tristate(pin, port)))
- for pin, p_port, n_port in self._dp_pins:
+ add_pin_fragment(pin, self.get_input(pin, port, extras))
+
+ for pin, p_port, n_port, extras in self.iter_differential_pins():
if pin.dir == "i":
- pin_fragments.append((pin.name, self.get_diff_input(pin, p_port, n_port)))
+ add_pin_fragment(pin, self.get_diff_input(pin, p_port, n_port))
if pin.dir == "o":
- pin_fragments.append((pin.name, self.get_diff_output(pin, p_port, n_port)))
+ add_pin_fragment(pin, self.get_diff_output(pin, p_port, n_port))
if pin.dir == "io":
- pin_fragments.append((pin.name, self.get_diff_tristate(pin, p_port, n_port)))
-
- for pin_name, pin_fragment in pin_fragments:
- pin_fragment = Fragment.get(pin_fragment, self)
- if not isinstance(pin_fragment, Instance):
- pin_fragment.flatten = True
- fragment.add_subfragment(pin_fragment, name="pin_{}".format(pin_name))
+ add_pin_fragment(pin, self.get_diff_tristate(pin, p_port, n_port))
return self.toolchain_prepare(fragment, name, **kwargs)
raise NotImplementedError("Platform {} does not support programming"
.format(self.__class__.__name__))
- def _check_feature(self, feature, pin, xdrs):
- if not xdrs:
+ def _check_feature(self, feature, pin, extras, valid_xdrs, valid_extras):
+ if not valid_xdrs:
raise NotImplementedError("Platform {} does not support {}"
.format(self.__class__.__name__, feature))
- elif pin.xdr not in xdrs:
+ elif pin.xdr not in valid_xdrs:
raise NotImplementedError("Platform {} does not support {} for XDR {}"
.format(self.__class__.__name__, feature, pin.xdr))
- def get_input(self, pin, port):
- self._check_feature("single-ended input", pin, xdrs=(1,))
+ if not valid_extras and extras:
+ raise NotImplementedError("Platform {} does not support extras for {}"
+ .format(self.__class__.__name__, feature))
+
+ def get_input(self, pin, port, extras):
+ self._check_feature("single-ended input", pin, extras,
+ valid_xdrs=(1,), valid_extras=None)
m = Module()
m.d.comb += pin.i.eq(port)
return m
- def get_output(self, pin, port):
- self._check_feature("single-ended output", pin, xdrs=(1,))
+ def get_output(self, pin, port, extras):
+ self._check_feature("single-ended output", pin, extras,
+ valid_xdrs=(1,), valid_extras=None)
m = Module()
m.d.comb += port.eq(pin.o)
return m
- def get_tristate(self, pin, port):
- self._check_feature("single-ended tristate", pin, xdrs=(1,))
+ def get_tristate(self, pin, port, extras):
+ self._check_feature("single-ended tristate", pin, extras,
+ valid_xdrs=(1,), valid_extras=None)
m = Module()
m.submodules += Instance("$tribuf",
m.d.comb += pin.i.eq(port)
return m
- def get_diff_input(self, pin, p_port, n_port):
- self._check_feature("differential input", pin, xdrs=())
+ def get_diff_input(self, pin, p_port, n_port, extras):
+ self._check_feature("differential input", pin, extras,
+ valid_xdrs=(), valid_extras=None)
- def get_diff_output(self, pin, p_port, n_port):
- self._check_feature("differential output", pin, xdrs=())
+ def get_diff_output(self, pin, p_port, n_port, extras):
+ self._check_feature("differential output", pin, extras,
+ valid_xdrs=(), valid_extras=None)
- def get_diff_tristate(self, pin, p_port, n_port):
- self._check_feature("differential tristate", pin, xdrs=())
+ def get_diff_tristate(self, pin, p_port, n_port, extras):
+ self._check_feature("differential tristate", pin, extras,
+ valid_xdrs=(), valid_extras=None)
class TemplatedPlatform(Platform):
self.resources = OrderedDict()
self.requested = OrderedDict()
self.clocks = OrderedDict()
-
self._ports = []
- self._se_pins = []
- self._dp_pins = []
self.add_resources(resources)
for name_number, frequency in clocks:
elif isinstance(subsignal.io[0], (Pins, DiffPairs)):
phys = subsignal.io[0]
pin = Pin(len(phys), dir, xdr, name=name)
-
if isinstance(phys, Pins):
port = Signal(pin.width, name="{}_io".format(pin.name))
- self._se_pins.append((pin, port))
- self._ports.append((port, phys.names, subsignal.extras))
-
if isinstance(phys, DiffPairs):
- p_port = Signal(pin.width, name="{}_p".format(pin.name))
- n_port = Signal(pin.width, name="{}_n".format(pin.name))
- self._dp_pins.append((pin, p_port, n_port))
- self._ports.append((p_port, phys.p.names, subsignal.extras))
- self._ports.append((n_port, phys.n.names, subsignal.extras))
-
+ port = (Signal(pin.width, name="{}_p".format(pin.name)),
+ Signal(pin.width, name="{}_n".format(pin.name)))
+ self._ports.append((subsignal, pin, port))
return pin
else:
assert False # :nocov:
self.requested[resource.name, resource.number] = value
return value
+ def iter_single_ended_pins(self):
+ for resource, pin, port in self._ports:
+ if isinstance(resource.io[0], Pins):
+ yield pin, port, resource.extras
+
+ def iter_differential_pins(self):
+ for resource, pin, port in self._ports:
+ if isinstance(resource.io[0], DiffPairs):
+ p_port, n_port = port
+ yield pin, p_port, n_port, resource.extras
+
def iter_ports(self):
- for port, pins, extras in self._ports:
- yield port
+ for resource, pin, port in self._ports:
+ if isinstance(resource.io[0], Pins):
+ yield port
+ elif isinstance(resource.io[0], DiffPairs):
+ p_port, n_port = port
+ yield p_port
+ yield n_port
+ else:
+ assert False
- def iter_port_constraints(self):
- for port, pins, extras in self._ports:
- yield (port.name, pins, extras)
+ def iter_port_constraints(self, diff_pins="pn"):
+ for resource, pin, port in self._ports:
+ if isinstance(resource.io[0], Pins):
+ yield port.name, resource.io[0].names, resource.extras
+ elif isinstance(resource.io[0], DiffPairs):
+ p_port, n_port = port
+ # On some FPGAs like iCE40, only one pin out of two in a differential pair may be
+ # constrained. The other has to be completely disconnected.
+ if "p" in diff_pins:
+ yield p_port.name, resource.io[0].p.names, resource.extras
+ if "n" in diff_pins:
+ yield n_port.name, resource.io[0].n.names, resource.extras
+ else:
+ assert False
def iter_clock_constraints(self):
for name, number in self.clocks.keys() & self.requested.keys():
self.assertEqual(ports[1].name, "i2c_0__sda_io")
self.assertEqual(ports[1].nbits, 1)
- self.assertEqual(self.cm._se_pins, [
- (i2c.scl, scl),
- (i2c.sda, sda),
+ self.assertEqual(list(self.cm.iter_single_ended_pins()), [
+ (i2c.scl, scl, {}),
+ (i2c.sda, sda, {}),
])
self.assertEqual(list(self.cm.iter_port_constraints()), [
("i2c_0__scl_io", ["N10"], {}),
self.assertEqual(n.name, "clk100_0_n")
self.assertEqual(n.nbits, clk100.width)
- self.assertEqual(self.cm._dp_pins, [
- (clk100, p, n),
+ self.assertEqual(list(self.cm.iter_differential_pins()), [
+ (clk100, p, n, {}),
])
self.assertEqual(list(self.cm.iter_port_constraints()), [
("clk100_0_p", ["H1"], {}),
- ("clk100_0_n", ["H2"], {})
+ ("clk100_0_n", ["H2"], {}),
+ ])
+ self.assertEqual(list(self.cm.iter_port_constraints(diff_pins="p")), [
+ ("clk100_0_p", ["H1"], {}),
+ ])
+ self.assertEqual(list(self.cm.iter_port_constraints(diff_pins="n")), [
+ ("clk100_0_n", ["H2"], {}),
])
def test_add_clock(self):