build.{dsl,res,plat}: add PinsN and DiffPairsN.
authorwhitequark <whitequark@whitequark.org>
Wed, 12 Jun 2019 14:42:39 +0000 (14:42 +0000)
committerwhitequark <whitequark@whitequark.org>
Wed, 12 Jun 2019 14:42:39 +0000 (14:42 +0000)
nmigen/build/dsl.py
nmigen/build/plat.py
nmigen/build/res.py
nmigen/test/test_build_dsl.py
nmigen/test/test_build_res.py
nmigen/vendor/lattice_ice40.py
nmigen/vendor/xilinx_7series.py
nmigen/vendor/xilinx_spartan6.py

index 8179323388e576e46a8e7126b55a36793118bffb..6f76d0552c56a11b4bf6ef7b5058e732ccf7304f 100644 (file)
@@ -1,7 +1,8 @@
 from collections import OrderedDict
 
 
-__all__ = ["Pins", "DiffPairs", "Attrs", "Clock", "Subsignal", "Resource", "Connector"]
+__all__ = ["Pins", "PinsN", "DiffPairs", "DiffPairsN",
+           "Attrs", "Clock", "Subsignal", "Resource", "Connector"]
 
 
 class Pins:
@@ -22,8 +23,9 @@ class Pins:
             raise TypeError("Direction must be one of \"i\", \"o\", \"oe\", or \"io\", not {!r}"
                             .format(dir))
 
-        self.names = names
-        self.dir   = dir
+        self.names  = names
+        self.dir    = dir
+        self.invert = False
 
     def __len__(self):
         return len(self.names)
@@ -43,7 +45,14 @@ class Pins:
         return mapped_names
 
     def __repr__(self):
-        return "(pins {} {})".format(self.dir, " ".join(self.names))
+        return "(pins{} {} {})".format("-n" if self.invert else "",
+            self.dir, " ".join(self.names))
+
+
+def PinsN(*args, **kwargs):
+    pins = Pins(*args, **kwargs)
+    pins.invert = True
+    return pins
 
 
 class DiffPairs:
@@ -56,7 +65,8 @@ class DiffPairs:
                             "and {!r} do not"
                             .format(self.p, self.n))
 
-        self.dir = dir
+        self.dir    = dir
+        self.invert = False
 
     def __len__(self):
         return len(self.p.names)
@@ -65,10 +75,16 @@ class DiffPairs:
         return zip(self.p.names, self.n.names)
 
     def __repr__(self):
-        return "(diffpairs {} (p {}) (n {}))".format(
+        return "(diffpairs{} {} (p {}) (n {}))".format("-n" if self.invert else "",
             self.dir, " ".join(self.p.names), " ".join(self.n.names))
 
 
+def DiffPairsN(*args, **kwargs):
+    diff_pairs = DiffPairs(*args, **kwargs)
+    diff_pairs.invert = True
+    return diff_pairs
+
+
 class Attrs(OrderedDict):
     def __init__(self, **attrs):
         for attr_key, attr_value in attrs.items():
index b33f2b9ff37fa9f753e8d897d2740e194d316f71..368065c859fa3e49aaa8fe43a3dce1fd16eb37ec 100644 (file)
@@ -66,25 +66,26 @@ class Platform(ResourceManager, metaclass=ABCMeta):
                 pin_fragment.flatten = True
             fragment.add_subfragment(pin_fragment, name="pin_{}".format(pin.name))
 
-        for pin, port, attrs in self.iter_single_ended_pins():
+        for pin, port, attrs, invert in self.iter_single_ended_pins():
             if pin.dir == "i":
-                add_pin_fragment(pin, self.get_input(pin, port, attrs))
+                add_pin_fragment(pin, self.get_input(pin, port, attrs, invert))
             if pin.dir == "o":
-                add_pin_fragment(pin, self.get_output(pin, port, attrs))
+                add_pin_fragment(pin, self.get_output(pin, port, attrs, invert))
             if pin.dir == "oe":
-                add_pin_fragment(pin, self.get_tristate(pin, port, attrs))
+                add_pin_fragment(pin, self.get_tristate(pin, port, attrs, invert))
             if pin.dir == "io":
-                add_pin_fragment(pin, self.get_input_output(pin, port, attrs))
+                add_pin_fragment(pin, self.get_input_output(pin, port, attrs, invert))
 
-        for pin, p_port, n_port, attrs in self.iter_differential_pins():
+        for pin, p_port, n_port, attrs, invert in self.iter_differential_pins():
             if pin.dir == "i":
-                add_pin_fragment(pin, self.get_diff_input(pin, p_port, n_port, attrs))
+                add_pin_fragment(pin, self.get_diff_input(pin, p_port, n_port, attrs, invert))
             if pin.dir == "o":
-                add_pin_fragment(pin, self.get_diff_output(pin, p_port, n_port, attrs))
+                add_pin_fragment(pin, self.get_diff_output(pin, p_port, n_port, attrs, invert))
             if pin.dir == "oe":
-                add_pin_fragment(pin, self.get_diff_tristate(pin, p_port, n_port, attrs))
+                add_pin_fragment(pin, self.get_diff_tristate(pin, p_port, n_port, attrs, invert))
             if pin.dir == "io":
-                add_pin_fragment(pin, self.get_diff_input_output(pin, p_port, n_port, attrs))
+                add_pin_fragment(pin,
+                    self.get_diff_input_output(pin, p_port, n_port, attrs, invert))
 
         return self.toolchain_prepare(fragment, name, **kwargs)
 
@@ -115,23 +116,30 @@ class Platform(ResourceManager, metaclass=ABCMeta):
             raise NotImplementedError("Platform {} does not support attributes for {}"
                                       .format(self.__class__.__name__, feature))
 
-    def get_input(self, pin, port, attrs):
+    @staticmethod
+    def _invert_if(invert, value):
+        if invert:
+            return ~value
+        else:
+            return value
+
+    def get_input(self, pin, port, attrs, invert):
         self._check_feature("single-ended input", pin, attrs,
                             valid_xdrs=(0,), valid_attrs=None)
 
         m = Module()
-        m.d.comb += pin.i.eq(port)
+        m.d.comb += pin.i.eq(self._invert_if(invert, port))
         return m
 
-    def get_output(self, pin, port, attrs):
+    def get_output(self, pin, port, attrs, invert):
         self._check_feature("single-ended output", pin, attrs,
                             valid_xdrs=(0,), valid_attrs=None)
 
         m = Module()
-        m.d.comb += port.eq(pin.o)
+        m.d.comb += port.eq(self._invert_if(invert, pin.o))
         return m
 
-    def get_tristate(self, pin, port, attrs):
+    def get_tristate(self, pin, port, attrs, invert):
         self._check_feature("single-ended tristate", pin, attrs,
                             valid_xdrs=(0,), valid_attrs=None)
 
@@ -139,12 +147,12 @@ class Platform(ResourceManager, metaclass=ABCMeta):
         m.submodules += Instance("$tribuf",
             p_WIDTH=pin.width,
             i_EN=pin.oe,
-            i_A=pin.o,
+            i_A=self._invert_if(invert, pin.o),
             o_Y=port,
         )
         return m
 
-    def get_input_output(self, pin, port, attrs):
+    def get_input_output(self, pin, port, attrs, invert):
         self._check_feature("single-ended input/output", pin, attrs,
                             valid_xdrs=(0,), valid_attrs=None)
 
@@ -152,25 +160,25 @@ class Platform(ResourceManager, metaclass=ABCMeta):
         m.submodules += Instance("$tribuf",
             p_WIDTH=pin.width,
             i_EN=pin.oe,
-            i_A=pin.o,
+            i_A=self._invert_if(invert, pin.o),
             o_Y=port,
         )
-        m.d.comb += pin.i.eq(port)
+        m.d.comb += pin.i.eq(self._invert_if(invert, port))
         return m
 
-    def get_diff_input(self, pin, p_port, n_port, attrs):
+    def get_diff_input(self, pin, p_port, n_port, attrs, invert):
         self._check_feature("differential input", pin, attrs,
                             valid_xdrs=(), valid_attrs=None)
 
-    def get_diff_output(self, pin, p_port, n_port, attrs):
+    def get_diff_output(self, pin, p_port, n_port, attrs, invert):
         self._check_feature("differential output", pin, attrs,
                             valid_xdrs=(), valid_attrs=None)
 
-    def get_diff_tristate(self, pin, p_port, n_port, attrs):
+    def get_diff_tristate(self, pin, p_port, n_port, attrs, invert):
         self._check_feature("differential tristate", pin, attrs,
                             valid_xdrs=(), valid_attrs=None)
 
-    def get_diff_input_output(self, pin, p_port, n_port, attrs):
+    def get_diff_input_output(self, pin, p_port, n_port, attrs, invert):
         self._check_feature("differential input/output", pin, attrs,
                             valid_xdrs=(), valid_attrs=None)
 
index 29926028b35309600383805c9cb9cfcbbc03e2c7..a17adf038a62507f9ff06ac75e3f5c023a27ed14 100644 (file)
@@ -145,14 +145,14 @@ class ResourceManager:
             if pin is None:
                 continue
             if isinstance(res.ios[0], Pins):
-                yield pin, port.io, attrs
+                yield pin, port.io, attrs, res.ios[0].invert
 
     def iter_differential_pins(self):
         for res, pin, port, attrs in self._ports:
             if pin is None:
                 continue
             if isinstance(res.ios[0], DiffPairs):
-                yield pin, port.p, port.n, attrs
+                yield pin, port.p, port.n, attrs, res.ios[0].invert
 
     def should_skip_port_component(self, port, attrs, component):
         return False
index 37c0398ae5386c5fa4463983b6c34bc56a2b70bd..158ef3549fe21466b3c66458418a3783fcc55688 100644 (file)
@@ -10,8 +10,14 @@ class PinsTestCase(FHDLTestCase):
         self.assertEqual(repr(p), "(pins io A0 A1 A2)")
         self.assertEqual(len(p.names), 3)
         self.assertEqual(p.dir, "io")
+        self.assertEqual(p.invert, False)
         self.assertEqual(list(p), ["A0", "A1", "A2"])
 
+    def test_invert(self):
+        p = PinsN("A0")
+        self.assertEqual(repr(p), "(pins-n io A0)")
+        self.assertEqual(p.invert, True)
+
     def test_conn(self):
         p = Pins("0 1 2", conn=("pmod", 0))
         self.assertEqual(list(p), ["pmod_0:0", "pmod_0:1", "pmod_0:2"])
@@ -63,6 +69,13 @@ class DiffPairsTestCase(FHDLTestCase):
         self.assertEqual(dp.dir, "io")
         self.assertEqual(list(dp), [("A0", "B0"), ("A1", "B1")])
 
+    def test_invert(self):
+        dp = DiffPairsN(p="A0", n="B0")
+        self.assertEqual(repr(dp), "(diffpairs-n io (p A0) (n B0))")
+        self.assertEqual(dp.p.names, ["A0"])
+        self.assertEqual(dp.n.names, ["B0"])
+        self.assertEqual(dp.invert, True)
+
     def test_conn(self):
         dp = DiffPairs(p="0 1 2", n="3 4 5", conn=("pmod", 0))
         self.assertEqual(list(dp), [
index a221cd4992bc6f25bec8e3c0691bd1e5dd88f10a..d6df1ca3ae372dbbe1a2fc92012209ab310a74b4 100644 (file)
@@ -84,8 +84,8 @@ class ResourceManagerTestCase(FHDLTestCase):
         self.assertEqual(ports[1].nbits, 1)
 
         self.assertEqual(list(self.cm.iter_single_ended_pins()), [
-            (i2c.scl, scl, {}),
-            (i2c.sda, sda, {}),
+            (i2c.scl, scl, {}, False),
+            (i2c.sda, sda, {}, False),
         ])
         self.assertEqual(list(self.cm.iter_port_constraints()), [
             ("i2c_0__scl__io", ["N10"], {}),
@@ -107,13 +107,30 @@ class ResourceManagerTestCase(FHDLTestCase):
         self.assertEqual(n.nbits, clk100.width)
 
         self.assertEqual(list(self.cm.iter_differential_pins()), [
-            (clk100, p, n, {}),
+            (clk100, p, n, {}, False),
         ])
         self.assertEqual(list(self.cm.iter_port_constraints()), [
             ("clk100_0__p", ["H1"], {}),
             ("clk100_0__n", ["H2"], {}),
         ])
 
+    def test_request_inverted(self):
+        new_resources = [
+            Resource("cs", 0, PinsN("X0")),
+            Resource("clk", 0, DiffPairsN("Y0", "Y1")),
+        ]
+        self.cm.add_resources(new_resources)
+
+        sig_cs = self.cm.request("cs")
+        sig_clk = self.cm.request("clk")
+        port_cs, port_clk_p, port_clk_n = self.cm.iter_ports()
+        self.assertEqual(list(self.cm.iter_single_ended_pins()), [
+            (sig_cs, port_cs, {}, True),
+        ])
+        self.assertEqual(list(self.cm.iter_differential_pins()), [
+            (sig_clk, port_clk_p, port_clk_n, {}, True),
+        ])
+
     def test_request_raw(self):
         clk50 = self.cm.request("clk50", 0, dir="-")
         self.assertIsInstance(clk50, Record)
index aa9f99e1c25a6671bc7a0f4d9706eb53fcaee94e..ae8d0ce8641931237c3f5dbcf8854650cc7734a1 100644 (file)
@@ -120,8 +120,8 @@ class LatticeICE40Platform(TemplatedPlatform):
             return True
         return False
 
-    def _get_io_buffer(self, m, pin, port, attrs, o_invert=None):
-        def _get_dff(clk, d, q):
+    def _get_io_buffer(self, m, pin, port, attrs, i_invert=None, o_invert=None):
+        def get_dff(clk, d, q):
             m.submodules += Instance("$dff",
                 p_CLK_POLARITY=0,
                 p_WIDTH=len(d),
@@ -129,7 +129,22 @@ class LatticeICE40Platform(TemplatedPlatform):
                 i_D=d,
                 o_Q=q)
 
-        def _get_inverter(a, invert):
+        def get_i_inverter(y, invert):
+            if invert is None:
+                return y
+            else:
+                a = Signal.like(y, name="{}_x{}".format(a.name, 1 if invert else 0))
+                for bit in range(len(y)):
+                    m.submodules += Instance("SB_LUT4",
+                        p_LUT_INIT=0b01 if invert else 0b10,
+                        i_I0=a[bit],
+                        i_I1=Const(0),
+                        i_I2=Const(0),
+                        i_I3=Const(0),
+                        o_O=y[bit])
+                return a
+
+        def get_o_inverter(a, invert):
             if invert is None:
                 return a
             else:
@@ -150,21 +165,27 @@ class LatticeICE40Platform(TemplatedPlatform):
         else:
             is_global_input = False
 
+        if "i" in pin.dir:
+            if pin.xdr < 2:
+                pin_i  = get_i_inverter(pin.i,  i_invert)
+            elif pin.xdr == 2:
+                pin_i0 = get_i_inverter(pin.i0, i_invert)
+                pin_i1 = get_i_inverter(pin.i1, i_invert)
         if "o" in pin.dir:
             if pin.xdr < 2:
-                pin_o  = _get_inverter(pin.o,  o_invert)
+                pin_o  = get_o_inverter(pin.o,  o_invert)
             elif pin.xdr == 2:
-                pin_o0 = _get_inverter(pin.o0, o_invert)
-                pin_o1 = _get_inverter(pin.o1, o_invert)
+                pin_o0 = get_o_inverter(pin.o0, o_invert)
+                pin_o1 = get_o_inverter(pin.o1, o_invert)
 
         if "i" in pin.dir and pin.xdr == 2:
-            i0_ff = Signal.like(pin.i0, name="{}_ff".format(pin.i0.name))
-            i1_ff = Signal.like(pin.i1, name="{}_ff".format(pin.i1.name))
-            _get_dff(pin.i_clk, i0_ff, pin.i0)
-            _get_dff(pin.i_clk, i1_ff, pin.i1)
+            i0_ff = Signal.like(pin_i0, name="{}_ff".format(pin_i0.name))
+            i1_ff = Signal.like(pin_i1, name="{}_ff".format(pin_i1.name))
+            get_dff(pin.i_clk, i0_ff, pin_i0)
+            get_dff(pin.i_clk, i1_ff, pin_i1)
         if "o" in pin.dir and pin.xdr == 2:
-            o1_ff = Signal.like(pin.o1, name="{}_ff".format(pin.o1.name))
-            _get_dff(pin.o_clk, pin_o1, o1_ff)
+            o1_ff = Signal.like(pin_o1, name="{}_ff".format(pin_o1.name))
+            get_dff(pin.o_clk, pin_o1, o1_ff)
 
         for bit in range(len(port)):
             io_args = [
@@ -201,9 +222,9 @@ class LatticeICE40Platform(TemplatedPlatform):
 
             if "i" in pin.dir:
                 if pin.xdr == 0 and is_global_input:
-                    io_args.append(("o", "GLOBAL_BUFFER_OUTPUT", pin.i[bit]))
+                    io_args.append(("o", "GLOBAL_BUFFER_OUTPUT", pin_i[bit]))
                 elif pin.xdr < 2:
-                    io_args.append(("o", "D_IN_0",  pin.i[bit]))
+                    io_args.append(("o", "D_IN_0",  pin_i[bit]))
                 elif pin.xdr == 2:
                     # Re-register both inputs before they enter fabric. This increases hold time
                     # to an entire cycle, and adds one cycle of latency.
@@ -226,43 +247,44 @@ class LatticeICE40Platform(TemplatedPlatform):
             else:
                 m.submodules += Instance("SB_IO", *io_args)
 
-    def get_input(self, pin, port, attrs):
+    def get_input(self, pin, port, attrs, invert):
         self._check_feature("single-ended input", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        self._get_io_buffer(m, pin, port, attrs)
+        self._get_io_buffer(m, pin, port, attrs, i_invert=True if invert else None)
         return m
 
-    def get_output(self, pin, port, attrs):
+    def get_output(self, pin, port, attrs, invert):
         self._check_feature("single-ended output", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        self._get_io_buffer(m, pin, port, attrs)
+        self._get_io_buffer(m, pin, port, attrs, o_invert=True if invert else None)
         return m
 
-    def get_tristate(self, pin, port, attrs):
+    def get_tristate(self, pin, port, attrs, invert):
         self._check_feature("single-ended tristate", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        self._get_io_buffer(m, pin, port, attrs)
+        self._get_io_buffer(m, pin, port, attrs, o_invert=True if invert else None)
         return m
 
-    def get_input_output(self, pin, port, attrs):
+    def get_input_output(self, pin, port, attrs, invert):
         self._check_feature("single-ended input/output", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        self._get_io_buffer(m, pin, port, attrs)
+        self._get_io_buffer(m, pin, port, attrs, i_invert=True if invert else None,
+                                                 o_invert=True if invert else None)
         return m
 
-    def get_diff_input(self, pin, p_port, n_port, attrs):
+    def get_diff_input(self, pin, p_port, n_port, attrs, invert):
         self._check_feature("differential input", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
         # See comment in should_skip_port_component above.
-        self._get_io_buffer(m, pin, p_port, attrs)
+        self._get_io_buffer(m, pin, p_port, attrs, i_invert=True if invert else None)
         return m
 
-    def get_diff_output(self, pin, p_port, n_port, attrs):
+    def get_diff_output(self, pin, p_port, n_port, attrs, invert):
         self._check_feature("differential output", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
@@ -270,8 +292,8 @@ class LatticeICE40Platform(TemplatedPlatform):
         # output pin. The inverter introduces a delay, so for a non-inverting output pin,
         # an identical delay is introduced by instantiating a LUT. This makes the waveform
         # perfectly symmetric in the xdr=0 case.
-        self._get_io_buffer(m, pin, p_port, attrs, o_invert=False)
-        self._get_io_buffer(m, pin, n_port, attrs, o_invert=True)
+        self._get_io_buffer(m, pin, p_port, attrs, o_invert=invert)
+        self._get_io_buffer(m, pin, n_port, attrs, o_invert=not invert)
         return m
 
     # Tristate and bidirectional buffers are not supported on iCE40 because it requires external
index 1ed8638e895b5e342ebc3fcd7efd9cb8bb40c935..92c4adde229bfe95100726d008c9a9b3e78d5f75 100644 (file)
@@ -129,7 +129,8 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
             )
             m.d.comb += q[bit].eq(_q)
 
-    def get_input(self, pin, port, attrs):
+    def get_input(self, pin, port, attrs, invert):
+        assert not invert
         self._check_feature("single-ended input", pin, attrs,
                             valid_xdrs=(0, 1), valid_attrs=True)
         m = Module()
@@ -139,7 +140,8 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
             m.d.comb += pin.i.eq(port)
         return m
 
-    def get_output(self, pin, port, attrs):
+    def get_output(self, pin, port, attrs, invert):
+        assert not invert
         self._check_feature("single-ended output", pin, attrs,
                             valid_xdrs=(0, 1), valid_attrs=True)
         m = Module()
@@ -149,7 +151,8 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
             m.d.comb += port.eq(pin.o)
         return m
 
-    def get_tristate(self, pin, port, attrs):
+    def get_tristate(self, pin, port, attrs, invert):
+        assert not invert
         self._check_feature("single-ended tristate", pin, attrs,
                             valid_xdrs=(0, 1), valid_attrs=True)
         m = Module()
@@ -166,7 +169,8 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
             )
         return m
 
-    def get_input_output(self, pin, port, attrs):
+    def get_input_output(self, pin, port, attrs, invert):
+        assert not invert
         self._check_feature("single-ended input/output", pin, attrs,
                             valid_xdrs=(0, 1), valid_attrs=True)
         m = Module()
@@ -186,7 +190,8 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
             )
         return m
 
-    def get_diff_input(self, pin, p_port, n_port, attrs):
+    def get_diff_input(self, pin, p_port, n_port, attrs, invert):
+        assert not invert
         self._check_feature("differential input", pin, attrs,
                             valid_xdrs=(0, 1), valid_attrs=True)
         m = Module()
@@ -201,7 +206,8 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
             )
         return m
 
-    def get_diff_output(self, pin, p_port, n_port, attrs):
+    def get_diff_output(self, pin, p_port, n_port, attrs, invert):
+        assert not invert
         self._check_feature("differential output", pin, attrs,
                             valid_xdrs=(0, 1), valid_attrs=True)
         m = Module()
@@ -216,7 +222,8 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
             )
         return m
 
-    def get_diff_tristate(self, pin, p_port, n_port, attrs):
+    def get_diff_tristate(self, pin, p_port, n_port, attrs, invert):
+        assert not invert
         self._check_feature("differential tristate", pin, attrs,
                             valid_xdrs=(0, 1), valid_attrs=True)
         m = Module()
@@ -234,7 +241,8 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
             )
         return m
 
-    def get_diff_input_output(self, pin, p_port, n_port, attrs):
+    def get_diff_input_output(self, pin, p_port, n_port, attrs, invert):
+        assert not invert
         self._check_feature("differential input/output", pin, attrs,
                             valid_xdrs=(0, 1), valid_attrs=True)
         m = Module()
index 946221702b7725736f8d008373ff5ff39baea42d..13876563db009530ef5053a274113a78608237be 100644 (file)
@@ -140,7 +140,8 @@ class XilinxSpartan6Platform(TemplatedPlatform):
             )
             m.d.comb += q[bit].eq(_q)
 
-    def get_input(self, pin, port, attrs):
+    def get_input(self, pin, port, attrs, invert):
+        assert not invert
         self._check_feature("single-ended input", pin, attrs,
                             valid_xdrs=(0, 1), valid_attrs=True)
         m = Module()
@@ -150,7 +151,8 @@ class XilinxSpartan6Platform(TemplatedPlatform):
             m.d.comb += pin.i.eq(port)
         return m
 
-    def get_output(self, pin, port, attrs):
+    def get_output(self, pin, port, attrs, invert):
+        assert not invert
         self._check_feature("single-ended output", pin, attrs,
                             valid_xdrs=(0, 1), valid_attrs=True)
         m = Module()
@@ -160,7 +162,8 @@ class XilinxSpartan6Platform(TemplatedPlatform):
             m.d.comb += port.eq(pin.o)
         return m
 
-    def get_tristate(self, pin, port, attrs):
+    def get_tristate(self, pin, port, attrs, invert):
+        assert not invert
         self._check_feature("single-ended tristate", pin, attrs,
                             valid_xdrs=(0, 1), valid_attrs=True)
         m = Module()
@@ -177,7 +180,8 @@ class XilinxSpartan6Platform(TemplatedPlatform):
             )
         return m
 
-    def get_input_output(self, pin, port, attrs):
+    def get_input_output(self, pin, port, attrs, invert):
+        assert not invert
         self._check_feature("single-ended input/output", pin, attrs,
                             valid_xdrs=(0, 1), valid_attrs=True)
         m = Module()
@@ -197,7 +201,8 @@ class XilinxSpartan6Platform(TemplatedPlatform):
             )
         return m
 
-    def get_diff_input(self, pin, p_port, n_port, attrs):
+    def get_diff_input(self, pin, p_port, n_port, attrs, invert):
+        assert not invert
         self._check_feature("differential input", pin, attrs,
                             valid_xdrs=(0, 1), valid_attrs=True)
         m = Module()
@@ -212,7 +217,8 @@ class XilinxSpartan6Platform(TemplatedPlatform):
             )
         return m
 
-    def get_diff_output(self, pin, p_port, n_port, attrs):
+    def get_diff_output(self, pin, p_port, n_port, attrs, invert):
+        assert not invert
         self._check_feature("differential output", pin, attrs,
                             valid_xdrs=(0, 1), valid_attrs=True)
         m = Module()
@@ -227,7 +233,8 @@ class XilinxSpartan6Platform(TemplatedPlatform):
             )
         return m
 
-    def get_diff_tristate(self, pin, p_port, n_port, attrs):
+    def get_diff_tristate(self, pin, p_port, n_port, attrs, invert):
+        assert not invert
         self._check_feature("differential tristate", pin, attrs,
                             valid_xdrs=(0, 1), valid_attrs=True)
         m = Module()
@@ -245,7 +252,8 @@ class XilinxSpartan6Platform(TemplatedPlatform):
             )
         return m
 
-    def get_diff_input_output(self, pin, p_port, n_port, attrs):
+    def get_diff_input_output(self, pin, p_port, n_port, attrs, invert):
+        assert not invert
         self._check_feature("differential input/output", pin, attrs,
                             valid_xdrs=(0, 1), valid_attrs=True)
         m = Module()