From 3b0b86fc0d4b3ce8dc5b549f1885f20873ba59b2 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 12 Jun 2019 14:42:39 +0000 Subject: [PATCH] build.{dsl,res,plat}: add PinsN and DiffPairsN. --- nmigen/build/dsl.py | 28 +++++++++--- nmigen/build/plat.py | 54 +++++++++++++---------- nmigen/build/res.py | 4 +- nmigen/test/test_build_dsl.py | 13 ++++++ nmigen/test/test_build_res.py | 23 ++++++++-- nmigen/vendor/lattice_ice40.py | 76 ++++++++++++++++++++------------ nmigen/vendor/xilinx_7series.py | 24 ++++++---- nmigen/vendor/xilinx_spartan6.py | 24 ++++++---- 8 files changed, 169 insertions(+), 77 deletions(-) diff --git a/nmigen/build/dsl.py b/nmigen/build/dsl.py index 8179323..6f76d05 100644 --- a/nmigen/build/dsl.py +++ b/nmigen/build/dsl.py @@ -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(): diff --git a/nmigen/build/plat.py b/nmigen/build/plat.py index b33f2b9..368065c 100644 --- a/nmigen/build/plat.py +++ b/nmigen/build/plat.py @@ -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) diff --git a/nmigen/build/res.py b/nmigen/build/res.py index 2992602..a17adf0 100644 --- a/nmigen/build/res.py +++ b/nmigen/build/res.py @@ -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 diff --git a/nmigen/test/test_build_dsl.py b/nmigen/test/test_build_dsl.py index 37c0398..158ef35 100644 --- a/nmigen/test/test_build_dsl.py +++ b/nmigen/test/test_build_dsl.py @@ -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), [ diff --git a/nmigen/test/test_build_res.py b/nmigen/test/test_build_res.py index a221cd4..d6df1ca 100644 --- a/nmigen/test/test_build_res.py +++ b/nmigen/test/test_build_res.py @@ -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) diff --git a/nmigen/vendor/lattice_ice40.py b/nmigen/vendor/lattice_ice40.py index aa9f99e..ae8d0ce 100644 --- a/nmigen/vendor/lattice_ice40.py +++ b/nmigen/vendor/lattice_ice40.py @@ -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 diff --git a/nmigen/vendor/xilinx_7series.py b/nmigen/vendor/xilinx_7series.py index 1ed8638..92c4add 100644 --- a/nmigen/vendor/xilinx_7series.py +++ b/nmigen/vendor/xilinx_7series.py @@ -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() diff --git a/nmigen/vendor/xilinx_spartan6.py b/nmigen/vendor/xilinx_spartan6.py index 9462217..1387656 100644 --- a/nmigen/vendor/xilinx_spartan6.py +++ b/nmigen/vendor/xilinx_spartan6.py @@ -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() -- 2.30.2