diff --git a/amaranth/build/res.py b/amaranth/build/res.py index d800a6781..fe7d0f68c 100644 --- a/amaranth/build/res.py +++ b/amaranth/build/res.py @@ -1,8 +1,10 @@ +import warnings from collections import OrderedDict from ..hdl import * from ..hdl._ast import SignalDict from ..lib import wiring, io +from .._utils import _ignore_deprecated from .dsl import * @@ -247,7 +249,11 @@ def resolve(resource, dir, xdr, path, attrs): if dir == "-": return port else: - pin = wiring.flipped(io.Pin(len(phys), dir, xdr=xdr, path=path)) + warnings.warn(f"Using platform.request without `dir=\"-\"` is deprecated; " + f"use `amaranth.lib.io.*Buffer` components instead", + DeprecationWarning, stacklevel=2) + with _ignore_deprecated(): + pin = wiring.flipped(io.Pin(len(phys), dir, xdr=xdr, path=path)) buffer = PinBuffer(pin, port) self._pins.append((pin, port, buffer)) diff --git a/amaranth/lib/io.py b/amaranth/lib/io.py index 5541fc387..8a1dbe2d8 100644 --- a/amaranth/lib/io.py +++ b/amaranth/lib/io.py @@ -6,6 +6,7 @@ from ..hdl import * from ..lib import wiring, data from ..lib.wiring import In, Out +from .._utils import deprecated, _ignore_deprecated from .. import tracer @@ -889,6 +890,8 @@ class Signature(wiring.Signature): """A signature for :class:`Pin`. The parameters are as defined on the ``Pin`` class, and are accessible as attributes. """ + # TODO(amaranth-0.6): remove + @deprecated("`amaranth.lib.io.Pin` is deprecated, use `amaranth.lib.io.*Buffer` instead") def __init__(self, width, dir, *, xdr=0): if not isinstance(width, int) or width < 0: raise TypeError("Width must be a non-negative integer, not {!r}" @@ -942,17 +945,20 @@ def __repr__(self): def create(self, *, path=None, src_loc_at=0): return Pin(self.width, self.dir, xdr=self.xdr, path=path, src_loc_at=1 + src_loc_at) + # TODO(amaranth-0.6): remove + @deprecated("`amaranth.lib.io.Pin` is deprecated, use `amaranth.lib.io.*Buffer` instead") def __init__(self, width, dir, *, xdr=0, name=None, path=None, src_loc_at=0): if name is not None: if path is not None: raise ValueError("Cannot pass both name and path") path = (name,) if path is None: - name = tracer.get_var_name(depth=2 + src_loc_at, default="$pin") + name = tracer.get_var_name(depth=3 + src_loc_at, default="$pin") path = (name,) self.path = tuple(path) self.name = "__".join(path) - signature = Pin.Signature(width, dir, xdr=xdr) + with _ignore_deprecated(): + signature = Pin.Signature(width, dir, xdr=xdr) super().__init__(signature, path=path, src_loc_at=src_loc_at + 1) @property diff --git a/docs/changes.rst b/docs/changes.rst index e2e7ce065..070cfb5e9 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -41,7 +41,8 @@ Apply the following changes to code written against Amaranth 0.4 to migrate it t * Remove any usage of ``name=`` with assertions, possibly replacing them with custom messages * Ensure all elaboratables are subclasses of :class:`Elaboratable` * Ensure clock domains aren't used outside the module that defines them, or its submodules; move clock domain definitions upwards in the hierarchy as necessary -* Remove uses of ``amaranth.lib.coding.*`` by inlining or copying the implementation of the modules. +* Remove uses of ``amaranth.lib.coding.*`` by inlining or copying the implementation of the modules +* Update uses of ``platform.request`` to pass ``dir="-"`` and use :mod:`amaranth.lib.io` buffers Implemented RFCs @@ -74,6 +75,7 @@ Implemented RFCs * `RFC 50`_: ``Print`` statement and string formatting * `RFC 51`_: Add ``ShapeCastable.from_bits`` and ``amaranth.lib.data.Const`` * `RFC 53`_: Low-level I/O primitives +* `RFC 55`_: New ``lib.io`` components * `RFC 58`_: Core support for ``ValueCastable`` formatting * `RFC 59`_: Get rid of upwards propagation of clock domains * `RFC 62`_: The ``MemoryData`` class diff --git a/tests/test_build_res.py b/tests/test_build_res.py index 923e6ecb6..bda61b480 100644 --- a/tests/test_build_res.py +++ b/tests/test_build_res.py @@ -5,6 +5,7 @@ from amaranth.lib.io import * from amaranth.build.dsl import * from amaranth.build.res import * +from amaranth._utils import _ignore_deprecated from .utils import * @@ -56,7 +57,8 @@ def test_lookup(self): def test_request_basic(self): r = self.cm.lookup("user_led", 0) - user_led = self.cm.request("user_led", 0) + with _ignore_deprecated(): + user_led = self.cm.request("user_led", 0) self.assertIsInstance(flipped(user_led), Pin) self.assertEqual(user_led.o.name, "user_led_0__o") @@ -74,7 +76,8 @@ def test_request_basic(self): self.assertEqual(port.invert, (False,)) def test_request_with_dir(self): - i2c = self.cm.request("i2c", 0, dir={"sda": "o"}) + with _ignore_deprecated(): + i2c = self.cm.request("i2c", 0, dir={"sda": "o"}) self.assertIsInstance(flipped(i2c.sda), Pin) self.assertEqual(i2c.sda.dir, "o") ((_, _, scl_buffer), (_, _, sda_buffer)) = self.cm.iter_pins() @@ -82,7 +85,8 @@ def test_request_with_dir(self): sda_buffer._MustUse__silence = True def test_request_tristate(self): - i2c = self.cm.request("i2c", 0) + with _ignore_deprecated(): + i2c = self.cm.request("i2c", 0) self.assertEqual(i2c.sda.dir, "io") ((scl_pin, scl_port, scl_buffer), (sda_pin, sda_port, sda_buffer)) = self.cm.iter_pins() @@ -97,7 +101,8 @@ def test_request_tristate(self): self.assertEqual(sda_port.io.metadata[0].name, "N11") def test_request_diffpairs(self): - clk100 = self.cm.request("clk100", 0) + with _ignore_deprecated(): + clk100 = self.cm.request("clk100", 0) self.assertIsInstance(flipped(clk100), Pin) self.assertEqual(clk100.dir, "i") self.assertEqual(clk100.width, 1) @@ -120,8 +125,10 @@ def test_request_inverted(self): ] self.cm.add_resources(new_resources) - cs = self.cm.request("cs") - clk = self.cm.request("clk") + with _ignore_deprecated(): + cs = self.cm.request("cs") + clk = self.cm.request("clk") + ( (cs_pin, cs_port, cs_buffer), (clk_pin, clk_port, clk_buffer), @@ -154,7 +161,8 @@ def test_request_via_connector(self): Subsignal("copi", Pins("4", conn=("pmod", 0))), ) ]) - spi0 = self.cm.request("spi", 0) + with _ignore_deprecated(): + spi0 = self.cm.request("spi", 0) ( (cs_pin, cs_port, cs_buffer), (clk_pin, clk_port, clk_buffer), @@ -187,7 +195,8 @@ def test_request_via_nested_connector(self): Subsignal("copi", Pins("4", conn=("pmod_extension", 0))), ) ]) - spi0 = self.cm.request("spi", 0) + with _ignore_deprecated(): + spi0 = self.cm.request("spi", 0) ( (cs_pin, cs_port, cs_buffer), (clk_pin, clk_port, clk_buffer), @@ -208,8 +217,9 @@ def test_request_via_nested_connector(self): self.assertEqual(copi_port.io.metadata[0].name, "B3") def test_request_clock(self): - clk100 = self.cm.request("clk100", 0) - clk50 = self.cm.request("clk50", 0, dir="i") + with _ignore_deprecated(): + clk100 = self.cm.request("clk100", 0) + clk50 = self.cm.request("clk50", 0, dir="i") ( (clk100_pin, clk100_port, clk100_buffer), (clk50_pin, clk50_port, clk50_buffer), @@ -222,7 +232,8 @@ def test_request_clock(self): ]) def test_add_clock(self): - i2c = self.cm.request("i2c") + with _ignore_deprecated(): + i2c = self.cm.request("i2c") self.cm.add_clock_constraint(i2c.scl.o, 100e3) self.assertEqual(list(self.cm.iter_clock_constraints()), [ (i2c.scl.o, None, 100e3) @@ -267,24 +278,28 @@ def test_wrong_clock_frequency(self): self.cm.add_clock_constraint(Signal(), None) def test_wrong_request_duplicate(self): - self.cm.request("user_led", 0) + with _ignore_deprecated(): + self.cm.request("user_led", 0) (pin, port, buffer), = self.cm.iter_pins() buffer._MustUse__silence = True with self.assertRaisesRegex(ResourceError, r"^Resource user_led#0 has already been requested$"): - self.cm.request("user_led", 0) + with _ignore_deprecated(): + self.cm.request("user_led", 0) def test_wrong_request_duplicate_physical(self): self.cm.add_resources([ Resource("clk20", 0, Pins("H1", dir="i")), ]) - self.cm.request("clk100", 0) + with _ignore_deprecated(): + self.cm.request("clk100", 0) (pin, port, buffer), = self.cm.iter_pins() buffer._MustUse__silence = True with self.assertRaisesRegex(ResourceError, (r"^Resource component clk20_0 uses physical pin H1, but it is already " r"used by resource component clk100_0 that was requested earlier$")): - self.cm.request("clk20", 0) + with _ignore_deprecated(): + self.cm.request("clk20", 0) def test_wrong_request_with_dir(self): with self.assertRaisesRegex(TypeError, @@ -319,7 +334,8 @@ def test_wrong_request_with_xdr_dict(self): i2c = self.cm.request("i2c", 0, xdr=2) def test_wrong_clock_constraint_twice(self): - clk100 = self.cm.request("clk100") + with _ignore_deprecated(): + clk100 = self.cm.request("clk100") (pin, port, buffer), = self.cm.iter_pins() buffer._MustUse__silence = True with self.assertRaisesRegex(ValueError, diff --git a/tests/test_lib_io.py b/tests/test_lib_io.py index 26ed23fb3..9dc208ede 100644 --- a/tests/test_lib_io.py +++ b/tests/test_lib_io.py @@ -6,6 +6,7 @@ from amaranth.lib.io import * from amaranth.lib.wiring import * from amaranth.lib import wiring, data +from amaranth._utils import _ignore_deprecated from .utils import * @@ -701,49 +702,57 @@ def assertSignatureEqual(self, signature, expected): class PinSignatureCombTestCase(PinSignatureTestCase): def test_signature_i(self): - sig_1 = Pin.Signature(1, dir="i") + with _ignore_deprecated(): + sig_1 = Pin.Signature(1, dir="i") self.assertSignatureEqual(sig_1, { "i": In(1), }) - sig_2 = Pin.Signature(2, dir="i") + with _ignore_deprecated(): + sig_2 = Pin.Signature(2, dir="i") self.assertSignatureEqual(sig_2, { "i": In(2), }) def test_signature_o(self): - sig_1 = Pin.Signature(1, dir="o") + with _ignore_deprecated(): + sig_1 = Pin.Signature(1, dir="o") self.assertSignatureEqual(sig_1, { "o": Out(1), }) - sig_2 = Pin.Signature(2, dir="o") + with _ignore_deprecated(): + sig_2 = Pin.Signature(2, dir="o") self.assertSignatureEqual(sig_2, { "o": Out(2), }) def test_signature_oe(self): - sig_1 = Pin.Signature(1, dir="oe") + with _ignore_deprecated(): + sig_1 = Pin.Signature(1, dir="oe") self.assertSignatureEqual(sig_1, { "o": Out(1), "oe": Out(1), }) - sig_2 = Pin.Signature(2, dir="oe") + with _ignore_deprecated(): + sig_2 = Pin.Signature(2, dir="oe") self.assertSignatureEqual(sig_2, { "o": Out(2), "oe": Out(1), }) def test_signature_io(self): - sig_1 = Pin.Signature(1, dir="io") + with _ignore_deprecated(): + sig_1 = Pin.Signature(1, dir="io") self.assertSignatureEqual(sig_1, { "i": In(1), "o": Out(1), "oe": Out(1), }) - sig_2 = Pin.Signature(2, dir="io") + with _ignore_deprecated(): + sig_2 = Pin.Signature(2, dir="io") self.assertSignatureEqual(sig_2, { "i": In(2), "o": Out(2), @@ -753,40 +762,46 @@ def test_signature_io(self): class PinSignatureSDRTestCase(PinSignatureTestCase): def test_signature_i(self): - sig_1 = Pin.Signature(1, dir="i", xdr=1) + with _ignore_deprecated(): + sig_1 = Pin.Signature(1, dir="i", xdr=1) self.assertSignatureEqual(sig_1, { "i_clk": Out(1), "i": In(1), }) - sig_2 = Pin.Signature(2, dir="i", xdr=1) + with _ignore_deprecated(): + sig_2 = Pin.Signature(2, dir="i", xdr=1) self.assertSignatureEqual(sig_2, { "i_clk": Out(1), "i": In(2), }) def test_signature_o(self): - sig_1 = Pin.Signature(1, dir="o", xdr=1) + with _ignore_deprecated(): + sig_1 = Pin.Signature(1, dir="o", xdr=1) self.assertSignatureEqual(sig_1, { "o_clk": Out(1), "o": Out(1), }) - sig_2 = Pin.Signature(2, dir="o", xdr=1) + with _ignore_deprecated(): + sig_2 = Pin.Signature(2, dir="o", xdr=1) self.assertSignatureEqual(sig_2, { "o_clk": Out(1), "o": Out(2), }) def test_signature_oe(self): - sig_1 = Pin.Signature(1, dir="oe", xdr=1) + with _ignore_deprecated(): + sig_1 = Pin.Signature(1, dir="oe", xdr=1) self.assertSignatureEqual(sig_1, { "o_clk": Out(1), "o": Out(1), "oe": Out(1), }) - sig_2 = Pin.Signature(2, dir="oe", xdr=1) + with _ignore_deprecated(): + sig_2 = Pin.Signature(2, dir="oe", xdr=1) self.assertSignatureEqual(sig_2, { "o_clk": Out(1), "o": Out(2), @@ -794,7 +809,8 @@ def test_signature_oe(self): }) def test_signature_io(self): - sig_1 = Pin.Signature(1, dir="io", xdr=1) + with _ignore_deprecated(): + sig_1 = Pin.Signature(1, dir="io", xdr=1) self.assertSignatureEqual(sig_1, { "i_clk": Out(1), "i": In(1), @@ -803,7 +819,8 @@ def test_signature_io(self): "oe": Out(1), }) - sig_2 = Pin.Signature(2, dir="io", xdr=1) + with _ignore_deprecated(): + sig_2 = Pin.Signature(2, dir="io", xdr=1) self.assertSignatureEqual(sig_2, { "i_clk": Out(1), "i": In(2), @@ -815,14 +832,16 @@ def test_signature_io(self): class PinSignatureDDRTestCase(PinSignatureTestCase): def test_signature_i(self): - sig_1 = Pin.Signature(1, dir="i", xdr=2) + with _ignore_deprecated(): + sig_1 = Pin.Signature(1, dir="i", xdr=2) self.assertSignatureEqual(sig_1, { "i_clk": Out(1), "i0": In(1), "i1": In(1), }) - sig_2 = Pin.Signature(2, dir="i", xdr=2) + with _ignore_deprecated(): + sig_2 = Pin.Signature(2, dir="i", xdr=2) self.assertSignatureEqual(sig_2, { "i_clk": Out(1), "i0": In(2), @@ -830,14 +849,16 @@ def test_signature_i(self): }) def test_signature_o(self): - sig_1 = Pin.Signature(1, dir="o", xdr=2) + with _ignore_deprecated(): + sig_1 = Pin.Signature(1, dir="o", xdr=2) self.assertSignatureEqual(sig_1, { "o_clk": Out(1), "o0": Out(1), "o1": Out(1), }) - sig_2 = Pin.Signature(2, dir="o", xdr=2) + with _ignore_deprecated(): + sig_2 = Pin.Signature(2, dir="o", xdr=2) self.assertSignatureEqual(sig_2, { "o_clk": Out(1), "o0": Out(2), @@ -845,7 +866,8 @@ def test_signature_o(self): }) def test_signature_oe(self): - sig_1 = Pin.Signature(1, dir="oe", xdr=2) + with _ignore_deprecated(): + sig_1 = Pin.Signature(1, dir="oe", xdr=2) self.assertSignatureEqual(sig_1, { "o_clk": Out(1), "o0": Out(1), @@ -853,7 +875,8 @@ def test_signature_oe(self): "oe": Out(1), }) - sig_2 = Pin.Signature(2, dir="oe", xdr=2) + with _ignore_deprecated(): + sig_2 = Pin.Signature(2, dir="oe", xdr=2) self.assertSignatureEqual(sig_2, { "o_clk": Out(1), "o0": Out(2), @@ -862,7 +885,8 @@ def test_signature_oe(self): }) def test_signature_io(self): - sig_1 = Pin.Signature(1, dir="io", xdr=2) + with _ignore_deprecated(): + sig_1 = Pin.Signature(1, dir="io", xdr=2) self.assertSignatureEqual(sig_1, { "i_clk": Out(1), "i0": In(1), @@ -873,7 +897,8 @@ def test_signature_io(self): "oe": Out(1), }) - sig_2 = Pin.Signature(2, dir="io", xdr=2) + with _ignore_deprecated(): + sig_2 = Pin.Signature(2, dir="io", xdr=2) self.assertSignatureEqual(sig_2, { "i_clk": Out(1), "i0": In(2), @@ -887,17 +912,21 @@ def test_signature_io(self): class PinSignatureReprCase(FHDLTestCase): def test_repr(self): - sig_0 = Pin.Signature(1, dir="i") + with _ignore_deprecated(): + sig_0 = Pin.Signature(1, dir="i") self.assertRepr(sig_0, "Pin.Signature(1, dir='i')") - sig_0 = Pin.Signature(2, dir="o", xdr=1) + with _ignore_deprecated(): + sig_0 = Pin.Signature(2, dir="o", xdr=1) self.assertRepr(sig_0, "Pin.Signature(2, dir='o', xdr=1)") - sig_0 = Pin.Signature(3, dir="io", xdr=2) + with _ignore_deprecated(): + sig_0 = Pin.Signature(3, dir="io", xdr=2) self.assertRepr(sig_0, "Pin.Signature(3, dir='io', xdr=2)") class PinTestCase(FHDLTestCase): def test_attributes(self): - pin = Pin(2, dir="io", xdr=2) + with _ignore_deprecated(): + pin = Pin(2, dir="io", xdr=2) self.assertEqual(pin.width, 2) self.assertEqual(pin.dir, "io") self.assertEqual(pin.xdr, 2) @@ -907,11 +936,13 @@ def test_attributes(self): self.assertEqual(pin.name, "pin") self.assertEqual(pin.path, ("pin",)) self.assertEqual(pin.i0.name, "pin__i0") - pin = Pin(2, dir="io", xdr=2, name="testpin") + with _ignore_deprecated(): + pin = Pin(2, dir="io", xdr=2, name="testpin") self.assertEqual(pin.name, "testpin") self.assertEqual(pin.path, ("testpin",)) self.assertEqual(pin.i0.name, "testpin__i0") - pin = Pin(2, dir="io", xdr=2, path=["a", "b"]) + with _ignore_deprecated(): + pin = Pin(2, dir="io", xdr=2, path=["a", "b"]) self.assertEqual(pin.name, "a__b") self.assertEqual(pin.path, ("a", "b")) self.assertEqual(pin.i0.name, "a__b__i0")