vendor: eliminate unnecessary LUT instantiation.
authorwhitequark <whitequark@whitequark.org>
Thu, 22 Aug 2019 20:54:42 +0000 (20:54 +0000)
committerwhitequark <whitequark@whitequark.org>
Thu, 22 Aug 2019 21:29:20 +0000 (21:29 +0000)
Fixes #165.

nmigen/vendor/lattice_ecp5.py
nmigen/vendor/lattice_ice40.py
nmigen/vendor/xilinx_7series.py
nmigen/vendor/xilinx_spartan_3_6.py

index 0a31919fd7a5e2a8c4d664cd704252cc4ae13dfa..833cd7b26ca37312d334f4ca31426eb5ed450578 100644 (file)
@@ -148,7 +148,7 @@ class LatticeECP5Platform(TemplatedPlatform):
             return True
         return False
 
-    def _get_xdr_buffer(self, m, pin, i_invert=None, o_invert=None):
+    def _get_xdr_buffer(self, m, pin, *, i_invert=False, o_invert=False):
         def get_ireg(clk, d, q):
             for bit in range(len(q)):
                 m.submodules += Instance("IFS1P3DX",
@@ -187,50 +187,34 @@ class LatticeECP5Platform(TemplatedPlatform):
                     o_Q=q[bit]
                 )
 
-        def get_ixor(z, invert):
-            if invert is None:
-                return z
-            else:
-                a = Signal.like(z, name_suffix="_x{}".format(1 if invert else 0))
-                for bit in range(len(z)):
-                    m.submodules += Instance("LUT4",
-                        p_INIT=0x5555 if invert else 0xaaaa,
-                        i_A=a[bit],
-                        i_B=Const(0),
-                        i_C=Const(0),
-                        i_D=Const(0),
-                        o_Z=z[bit]
-                    )
+        def get_ineg(y, invert):
+            if invert:
+                a = Signal.like(y, name_suffix="_n")
+                m.d.comb += y.eq(~a)
                 return a
+            else:
+                return y
 
-        def get_oxor(a, invert):
-            if invert is None:
-                return a
+        def get_oneg(a, invert):
+            if invert:
+                y = Signal.like(a, name_suffix="_n")
+                m.d.comb += y.eq(~a)
+                return y
             else:
-                z = Signal.like(a, name_suffix="_x{}".format(1 if invert else 0))
-                for bit in range(len(a)):
-                    m.submodules += Instance("LUT4",
-                        p_INIT=0x5555 if invert else 0xaaaa,
-                        i_A=a[bit],
-                        i_B=Const(0),
-                        i_C=Const(0),
-                        i_D=Const(0),
-                        o_Z=z[bit]
-                    )
-                return z
+                return a
 
         if "i" in pin.dir:
             if pin.xdr < 2:
-                pin_i  = get_ixor(pin.i,  i_invert)
+                pin_i  = get_ineg(pin.i,  i_invert)
             elif pin.xdr == 2:
-                pin_i0 = get_ixor(pin.i0, i_invert)
-                pin_i1 = get_ixor(pin.i1, i_invert)
+                pin_i0 = get_ineg(pin.i0, i_invert)
+                pin_i1 = get_ineg(pin.i1, i_invert)
         if "o" in pin.dir:
             if pin.xdr < 2:
-                pin_o  = get_oxor(pin.o,  o_invert)
+                pin_o  = get_oneg(pin.o,  o_invert)
             elif pin.xdr == 2:
-                pin_o0 = get_oxor(pin.o0, o_invert)
-                pin_o1 = get_oxor(pin.o1, o_invert)
+                pin_o0 = get_oneg(pin.o0, o_invert)
+                pin_o1 = get_oneg(pin.o1, o_invert)
 
         i = o = t = None
         if "i" in pin.dir:
@@ -274,7 +258,7 @@ class LatticeECP5Platform(TemplatedPlatform):
         self._check_feature("single-ended input", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, i_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert)
         for bit in range(len(port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("IB",
                 i_I=port[bit],
@@ -286,7 +270,7 @@ class LatticeECP5Platform(TemplatedPlatform):
         self._check_feature("single-ended output", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, o_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
         for bit in range(len(port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("OB",
                 i_I=o[bit],
@@ -298,7 +282,7 @@ class LatticeECP5Platform(TemplatedPlatform):
         self._check_feature("single-ended tristate", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, o_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
         for bit in range(len(port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBZ",
                 i_T=t,
@@ -311,8 +295,7 @@ class LatticeECP5Platform(TemplatedPlatform):
         self._check_feature("single-ended input/output", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, i_invert=True if invert else None,
-                                               o_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert, o_invert=invert)
         for bit in range(len(port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("BB",
                 i_T=t,
@@ -326,7 +309,7 @@ class LatticeECP5Platform(TemplatedPlatform):
         self._check_feature("differential input", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, i_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert)
         for bit in range(len(p_port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("IB",
                 i_I=p_port[bit],
@@ -338,7 +321,7 @@ class LatticeECP5Platform(TemplatedPlatform):
         self._check_feature("differential output", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, o_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
         for bit in range(len(p_port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("OB",
                 i_I=o[bit],
@@ -350,7 +333,7 @@ class LatticeECP5Platform(TemplatedPlatform):
         self._check_feature("differential tristate", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, o_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
         for bit in range(len(p_port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBZ",
                 i_T=t,
@@ -363,8 +346,7 @@ class LatticeECP5Platform(TemplatedPlatform):
         self._check_feature("differential input/output", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, i_invert=True if invert else None,
-                                               o_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert, o_invert=invert)
         for bit in range(len(p_port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("BB",
                 i_T=t,
index 5c1880b1d40795f9a969a2b67e3644b9fa7f581d..21e9297517d60651497f7140f30a35ed4ab99781 100644 (file)
@@ -174,7 +174,8 @@ class LatticeICE40Platform(TemplatedPlatform):
             return True
         return False
 
-    def _get_io_buffer(self, m, pin, port, attrs, i_invert=None, o_invert=None):
+    def _get_io_buffer(self, m, pin, port, attrs, *, i_invert=False, o_invert=False,
+                       invert_lut=False):
         def get_dff(clk, d, q):
             m.submodules += Instance("$dff",
                 p_CLK_POLARITY=1,
@@ -183,35 +184,43 @@ class LatticeICE40Platform(TemplatedPlatform):
                 i_D=d,
                 o_Q=q)
 
-        def get_ixor(y, invert):
-            if invert is None:
-                return y
-            else:
+        def get_ineg(y, invert):
+            if invert_lut:
                 a = Signal.like(y, name_suffix="_x{}".format(1 if invert else 0))
                 for bit in range(len(y)):
                     m.submodules += Instance("SB_LUT4",
-                        p_LUT_INIT=0b01 if invert else 0b10,
+                        p_LUT_INIT=Const(0b01 if invert else 0b10, 16),
                         i_I0=a[bit],
                         i_I1=Const(0),
                         i_I2=Const(0),
                         i_I3=Const(0),
                         o_O=y[bit])
                 return a
-
-        def get_oxor(a, invert):
-            if invert is None:
+            elif invert:
+                a = Signal.like(y, name_suffix="_n")
+                m.d.comb += y.eq(~a)
                 return a
             else:
+                return y
+
+        def get_oneg(a, invert):
+            if invert_lut:
                 y = Signal.like(a, name_suffix="_x{}".format(1 if invert else 0))
                 for bit in range(len(a)):
                     m.submodules += Instance("SB_LUT4",
-                        p_LUT_INIT=0b01 if invert else 0b10,
+                        p_LUT_INIT=Const(0b01 if invert else 0b10, 16),
                         i_I0=a[bit],
                         i_I1=Const(0),
                         i_I2=Const(0),
                         i_I3=Const(0),
                         o_O=y[bit])
                 return y
+            elif invert:
+                y = Signal.like(a, name_suffix="_n")
+                m.d.comb += y.eq(~a)
+                return y
+            else:
+                return a
 
         if "GLOBAL" in attrs:
             is_global_input = bool(attrs["GLOBAL"])
@@ -222,16 +231,16 @@ class LatticeICE40Platform(TemplatedPlatform):
 
         if "i" in pin.dir:
             if pin.xdr < 2:
-                pin_i  = get_ixor(pin.i,  i_invert)
+                pin_i  = get_ineg(pin.i,  i_invert)
             elif pin.xdr == 2:
-                pin_i0 = get_ixor(pin.i0, i_invert)
-                pin_i1 = get_ixor(pin.i1, i_invert)
+                pin_i0 = get_ineg(pin.i0, i_invert)
+                pin_i1 = get_ineg(pin.i1, i_invert)
         if "o" in pin.dir:
             if pin.xdr < 2:
-                pin_o  = get_oxor(pin.o,  o_invert)
+                pin_o  = get_oneg(pin.o,  o_invert)
             elif pin.xdr == 2:
-                pin_o0 = get_oxor(pin.o0, o_invert)
-                pin_o1 = get_oxor(pin.o1, o_invert)
+                pin_o0 = get_oneg(pin.o0, o_invert)
+                pin_o1 = get_oneg(pin.o1, o_invert)
 
         if "i" in pin.dir and pin.xdr == 2:
             i0_ff = Signal.like(pin_i0, name_suffix="_ff")
@@ -310,29 +319,28 @@ class LatticeICE40Platform(TemplatedPlatform):
         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, i_invert=True if invert else None)
+        self._get_io_buffer(m, pin, port, attrs, i_invert=invert)
         return m
 
     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, o_invert=True if invert else None)
+        self._get_io_buffer(m, pin, port, attrs, o_invert=invert)
         return m
 
     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, o_invert=True if invert else None)
+        self._get_io_buffer(m, pin, port, attrs, o_invert=invert)
         return m
 
     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, i_invert=True if invert else None,
-                                                 o_invert=True if invert else None)
+        self._get_io_buffer(m, pin, port, attrs, i_invert=invert, o_invert=invert)
         return m
 
     def get_diff_input(self, pin, p_port, n_port, attrs, invert):
@@ -340,7 +348,7 @@ class LatticeICE40Platform(TemplatedPlatform):
                             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, i_invert=True if invert else None)
+        self._get_io_buffer(m, pin, p_port, attrs, i_invert=invert)
         return m
 
     def get_diff_output(self, pin, p_port, n_port, attrs, invert):
@@ -351,8 +359,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=invert)
-        self._get_io_buffer(m, pin, n_port, attrs, o_invert=not invert)
+        self._get_io_buffer(m, pin, p_port, attrs, o_invert=    invert, invert_lut=True)
+        self._get_io_buffer(m, pin, n_port, attrs, o_invert=not invert, invert_lut=True)
         return m
 
     # Tristate and bidirectional buffers are not supported on iCE40 because it requires external
index a7620ec5f8a306f799cf87c8a59dfac053d28548..be5901746b80cca9d6074b2f5d41c53a7a90af1d 100644 (file)
@@ -143,14 +143,14 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
                 m.d.comb += ResetSignal("sync").eq(rst_i)
             return m
 
-    def _get_xdr_buffer(self, m, pin, i_invert=None, o_invert=None):
+    def _get_xdr_buffer(self, m, pin, *, i_invert=False, o_invert=False):
         def get_dff(clk, d, q):
             # SDR I/O is performed by packing a flip-flop into the pad IOB.
             for bit in range(len(q)):
                 _q = Signal()
                 _q.attrs["IOB"] = "TRUE"
-                # XXX: Vivado 2019.1 seems to make this flip-flop ineligible for IOB packing
-                # unless we prevent it from being optimized.
+                # Vivado 2019.1 seems to make this flip-flop ineligible for IOB packing unless
+                # we prevent it from being optimized.
                 _q.attrs["DONT_TOUCH"] = "TRUE"
                 m.submodules += Instance("FDCE",
                     i_C=clk,
@@ -187,44 +187,34 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
                     o_Q=q[bit]
                 )
 
-        def get_ixor(y, invert):
-            if invert is None:
-                return y
-            else:
-                a = Signal.like(y, name_suffix="_x{}".format(1 if invert else 0))
-                for bit in range(len(y)):
-                    m.submodules += Instance("LUT1",
-                        p_INIT=0b01 if invert else 0b10,
-                        i_I0=a[bit],
-                        o_O=y[bit]
-                    )
-                return a
-
-        def get_oxor(a, invert):
-            if invert is None:
+        def get_ineg(y, invert):
+            if invert:
+                a = Signal.like(y, name_suffix="_n")
+                m.d.comb += y.eq(~a)
                 return a
             else:
-                y = Signal.like(a, name_suffix="_x{}".format(1 if invert else 0))
-                for bit in range(len(a)):
-                    m.submodules += Instance("LUT1",
-                        p_INIT=0b01 if invert else 0b10,
-                        i_I0=a[bit],
-                        o_O=y[bit]
-                    )
                 return y
 
+        def get_oneg(a, invert):
+            if invert:
+                y = Signal.like(a, name_suffix="_n")
+                m.d.comb += y.eq(~a)
+                return y
+            else:
+                return a
+
         if "i" in pin.dir:
             if pin.xdr < 2:
-                pin_i  = get_ixor(pin.i, i_invert)
+                pin_i  = get_ineg(pin.i,  i_invert)
             elif pin.xdr == 2:
-                pin_i0 = get_ixor(pin.i0, i_invert)
-                pin_i1 = get_ixor(pin.i1, i_invert)
+                pin_i0 = get_ineg(pin.i0, i_invert)
+                pin_i1 = get_ineg(pin.i1, i_invert)
         if "o" in pin.dir:
             if pin.xdr < 2:
-                pin_o  = get_oxor(pin.o, o_invert)
+                pin_o  = get_oneg(pin.o,  o_invert)
             elif pin.xdr == 2:
-                pin_o0 = get_oxor(pin.o0, o_invert)
-                pin_o1 = get_oxor(pin.o1, o_invert)
+                pin_o0 = get_oneg(pin.o0, o_invert)
+                pin_o1 = get_oneg(pin.o1, o_invert)
 
         i = o = t = None
         if "i" in pin.dir:
@@ -264,7 +254,7 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
         self._check_feature("single-ended input", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, i_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert)
         for bit in range(len(port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("IBUF",
                 i_I=port[bit],
@@ -276,7 +266,7 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
         self._check_feature("single-ended output", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, o_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
         for bit in range(len(port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBUF",
                 i_I=o[bit],
@@ -288,7 +278,7 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
         self._check_feature("single-ended tristate", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, o_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
         for bit in range(len(port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBUFT",
                 i_T=t,
@@ -301,8 +291,7 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
         self._check_feature("single-ended input/output", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, i_invert=True if invert else None,
-                                               o_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert, o_invert=invert)
         for bit in range(len(port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("IOBUF",
                 i_T=t,
@@ -316,7 +305,7 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
         self._check_feature("differential input", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, i_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert)
         for bit in range(len(p_port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("IBUFDS",
                 i_I=p_port[bit], i_IB=n_port[bit],
@@ -328,7 +317,7 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
         self._check_feature("differential output", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, o_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
         for bit in range(len(p_port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBUFDS",
                 i_I=o[bit],
@@ -340,7 +329,7 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
         self._check_feature("differential tristate", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, o_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
         for bit in range(len(p_port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBUFTDS",
                 i_T=t,
@@ -353,8 +342,7 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
         self._check_feature("differential input/output", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, i_invert=True if invert else None,
-                                               o_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert, o_invert=invert)
         for bit in range(len(p_port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("IOBUFDS",
                 i_T=t,
index bda51168c87682b45e5c5c67ec80e84b4e4c2a79..050a3e30bfc07d35063302c4b8add327e7d1c6a5 100644 (file)
@@ -193,7 +193,7 @@ class XilinxSpartan3Or6Platform(TemplatedPlatform):
                 m.d.comb += ResetSignal("sync").eq(rst_i)
             return m
 
-    def _get_xdr_buffer(self, m, pin, i_invert=None, o_invert=None):
+    def _get_xdr_buffer(self, m, pin, *, i_invert=False, o_invert=False):
         def get_dff(clk, d, q):
             # SDR I/O is performed by packing a flip-flop into the pad IOB.
             for bit in range(len(q)):
@@ -234,44 +234,34 @@ class XilinxSpartan3Or6Platform(TemplatedPlatform):
                     o_Q=q[bit]
                 )
 
-        def get_ixor(y, invert):
-            if invert is None:
-                return y
-            else:
-                a = Signal.like(y, name_suffix="_x{}".format(1 if invert else 0))
-                for bit in range(len(y)):
-                    m.submodules += Instance("LUT1",
-                        p_INIT=0b01 if invert else 0b10,
-                        i_I0=a[bit],
-                        o_O=y[bit]
-                    )
-                return a
-
-        def get_oxor(a, invert):
-            if invert is None:
+        def get_ineg(y, invert):
+            if invert:
+                a = Signal.like(y, name_suffix="_n")
+                m.d.comb += y.eq(~a)
                 return a
             else:
-                y = Signal.like(a, name_suffix="_x{}".format(1 if invert else 0))
-                for bit in range(len(a)):
-                    m.submodules += Instance("LUT1",
-                        p_INIT=0b01 if invert else 0b10,
-                        i_I0=a[bit],
-                        o_O=y[bit]
-                    )
                 return y
 
+        def get_oneg(a, invert):
+            if invert:
+                y = Signal.like(a, name_suffix="_n")
+                m.d.comb += y.eq(~a)
+                return y
+            else:
+                return a
+
         if "i" in pin.dir:
             if pin.xdr < 2:
-                pin_i  = get_ixor(pin.i, i_invert)
+                pin_i  = get_ineg(pin.i,  i_invert)
             elif pin.xdr == 2:
-                pin_i0 = get_ixor(pin.i0, i_invert)
-                pin_i1 = get_ixor(pin.i1, i_invert)
+                pin_i0 = get_ineg(pin.i0, i_invert)
+                pin_i1 = get_ineg(pin.i1, i_invert)
         if "o" in pin.dir:
             if pin.xdr < 2:
-                pin_o  = get_oxor(pin.o, o_invert)
+                pin_o  = get_oneg(pin.o,  o_invert)
             elif pin.xdr == 2:
-                pin_o0 = get_oxor(pin.o0, o_invert)
-                pin_o1 = get_oxor(pin.o1, o_invert)
+                pin_o0 = get_oneg(pin.o0, o_invert)
+                pin_o1 = get_oneg(pin.o1, o_invert)
 
         i = o = t = None
         if "i" in pin.dir:
@@ -315,7 +305,7 @@ class XilinxSpartan3Or6Platform(TemplatedPlatform):
         self._check_feature("single-ended input", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, i_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert)
         for bit in range(len(port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("IBUF",
                 i_I=port[bit],
@@ -327,7 +317,7 @@ class XilinxSpartan3Or6Platform(TemplatedPlatform):
         self._check_feature("single-ended output", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, o_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
         for bit in range(len(port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBUF",
                 i_I=o[bit],
@@ -339,7 +329,7 @@ class XilinxSpartan3Or6Platform(TemplatedPlatform):
         self._check_feature("single-ended tristate", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, o_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
         for bit in range(len(port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBUFT",
                 i_T=t,
@@ -352,8 +342,7 @@ class XilinxSpartan3Or6Platform(TemplatedPlatform):
         self._check_feature("single-ended input/output", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, i_invert=True if invert else None,
-                                               o_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert, o_invert=invert)
         for bit in range(len(port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("IOBUF",
                 i_T=t,
@@ -367,7 +356,7 @@ class XilinxSpartan3Or6Platform(TemplatedPlatform):
         self._check_feature("differential input", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, i_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert)
         for bit in range(len(p_port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("IBUFDS",
                 i_I=p_port[bit], i_IB=n_port[bit],
@@ -379,7 +368,7 @@ class XilinxSpartan3Or6Platform(TemplatedPlatform):
         self._check_feature("differential output", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, o_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
         for bit in range(len(p_port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBUFDS",
                 i_I=o[bit],
@@ -391,7 +380,7 @@ class XilinxSpartan3Or6Platform(TemplatedPlatform):
         self._check_feature("differential tristate", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, o_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, o_invert=invert)
         for bit in range(len(p_port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("OBUFTDS",
                 i_T=t,
@@ -404,8 +393,7 @@ class XilinxSpartan3Or6Platform(TemplatedPlatform):
         self._check_feature("differential input/output", pin, attrs,
                             valid_xdrs=(0, 1, 2), valid_attrs=True)
         m = Module()
-        i, o, t = self._get_xdr_buffer(m, pin, i_invert=True if invert else None,
-                                               o_invert=True if invert else None)
+        i, o, t = self._get_xdr_buffer(m, pin, i_invert=invert, o_invert=invert)
         for bit in range(len(p_port)):
             m.submodules["{}_{}".format(pin.name, bit)] = Instance("IOBUFDS",
                 i_T=t,