Skip to content

Commit 96a548d

Browse files
committed
Implement RFC 55: New lib.io components.
1 parent 0be2dda commit 96a548d

File tree

5 files changed

+110
-50
lines changed

5 files changed

+110
-50
lines changed

amaranth/build/res.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
import warnings
12
from collections import OrderedDict
23

34
from ..hdl import *
45
from ..hdl._ast import SignalDict
56
from ..lib import wiring, io
7+
from .._utils import _ignore_deprecated
68

79
from .dsl import *
810

@@ -247,7 +249,11 @@ def resolve(resource, dir, xdr, path, attrs):
247249
if dir == "-":
248250
return port
249251
else:
250-
pin = wiring.flipped(io.Pin(len(phys), dir, xdr=xdr, path=path))
252+
warnings.warn(f"Using platform.request without `dir=\"-\"` is deprecated; "
253+
f"use `amaranth.lib.io.*Buffer` components instead",
254+
DeprecationWarning, stacklevel=2)
255+
with _ignore_deprecated():
256+
pin = wiring.flipped(io.Pin(len(phys), dir, xdr=xdr, path=path))
251257
buffer = PinBuffer(pin, port)
252258
self._pins.append((pin, port, buffer))
253259

amaranth/lib/io.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from ..hdl import *
77
from ..lib import wiring, data
88
from ..lib.wiring import In, Out
9+
from .._utils import deprecated, _ignore_deprecated
910
from .. import tracer
1011

1112

@@ -708,6 +709,8 @@ class Signature(wiring.Signature):
708709
"""A signature for :class:`Pin`. The parameters are as defined on the ``Pin`` class,
709710
and are accessible as attributes.
710711
"""
712+
# TODO(amaranth-0.6): remove
713+
@deprecated("`amaranth.lib.io.Pin` is deprecated, use `amaranth.lib.io.*Buffer` instead")
711714
def __init__(self, width, dir, *, xdr=0):
712715
if not isinstance(width, int) or width < 0:
713716
raise TypeError("Width must be a non-negative integer, not {!r}"
@@ -761,17 +764,20 @@ def __repr__(self):
761764
def create(self, *, path=None, src_loc_at=0):
762765
return Pin(self.width, self.dir, xdr=self.xdr, path=path, src_loc_at=1 + src_loc_at)
763766

767+
# TODO(amaranth-0.6): remove
768+
@deprecated("`amaranth.lib.io.Pin` is deprecated, use `amaranth.lib.io.*Buffer` instead")
764769
def __init__(self, width, dir, *, xdr=0, name=None, path=None, src_loc_at=0):
765770
if name is not None:
766771
if path is not None:
767772
raise ValueError("Cannot pass both name and path")
768773
path = (name,)
769774
if path is None:
770-
name = tracer.get_var_name(depth=2 + src_loc_at, default="$pin")
775+
name = tracer.get_var_name(depth=3 + src_loc_at, default="$pin")
771776
path = (name,)
772777
self.path = tuple(path)
773778
self.name = "__".join(path)
774-
signature = Pin.Signature(width, dir, xdr=xdr)
779+
with _ignore_deprecated():
780+
signature = Pin.Signature(width, dir, xdr=xdr)
775781
super().__init__(signature, path=path, src_loc_at=src_loc_at + 1)
776782

777783
@property

docs/changes.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ Apply the following changes to code written against Amaranth 0.4 to migrate it t
4141
* Remove any usage of ``name=`` with assertions, possibly replacing them with custom messages
4242
* Ensure all elaboratables are subclasses of :class:`Elaboratable`
4343
* 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
44-
* Remove uses of ``amaranth.lib.coding.*`` by inlining or copying the implementation of the modules.
44+
* Remove uses of ``amaranth.lib.coding.*`` by inlining or copying the implementation of the modules
45+
* Update uses of ``platform.request`` to pass ``dir="-"`` and use :mod:`amaranth.lib.io` buffers
4546

4647

4748
Implemented RFCs
@@ -71,6 +72,7 @@ Implemented RFCs
7172
* `RFC 50`_: ``Print`` statement and string formatting
7273
* `RFC 51`_: Add ``ShapeCastable.from_bits`` and ``amaranth.lib.data.Const``
7374
* `RFC 53`_: Low-level I/O primitives
75+
* `RFC 55`_: New ``lib.io`` components
7476
* `RFC 58`_: Core support for ``ValueCastable`` formatting
7577
* `RFC 59`_: Get rid of upwards propagation of clock domains
7678
* `RFC 62`_: The ``MemoryData`` class

tests/test_build_res.py

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from amaranth.lib.io import *
66
from amaranth.build.dsl import *
77
from amaranth.build.res import *
8+
from amaranth._utils import _ignore_deprecated
89

910
from .utils import *
1011

@@ -56,7 +57,8 @@ def test_lookup(self):
5657

5758
def test_request_basic(self):
5859
r = self.cm.lookup("user_led", 0)
59-
user_led = self.cm.request("user_led", 0)
60+
with _ignore_deprecated():
61+
user_led = self.cm.request("user_led", 0)
6062

6163
self.assertIsInstance(flipped(user_led), Pin)
6264
self.assertEqual(user_led.o.name, "user_led_0__o")
@@ -74,12 +76,14 @@ def test_request_basic(self):
7476
self.assertEqual(port.invert, (False,))
7577

7678
def test_request_with_dir(self):
77-
i2c = self.cm.request("i2c", 0, dir={"sda": "o"})
79+
with _ignore_deprecated():
80+
i2c = self.cm.request("i2c", 0, dir={"sda": "o"})
7881
self.assertIsInstance(flipped(i2c.sda), Pin)
7982
self.assertEqual(i2c.sda.dir, "o")
8083

8184
def test_request_tristate(self):
82-
i2c = self.cm.request("i2c", 0)
85+
with _ignore_deprecated():
86+
i2c = self.cm.request("i2c", 0)
8387
self.assertEqual(i2c.sda.dir, "io")
8488

8589
((scl_pin, scl_port, _), (sda_pin, sda_port, _)) = self.cm.iter_pins()
@@ -91,7 +95,8 @@ def test_request_tristate(self):
9195
self.assertEqual(sda_port.io.metadata[0].name, "N11")
9296

9397
def test_request_diffpairs(self):
94-
clk100 = self.cm.request("clk100", 0)
98+
with _ignore_deprecated():
99+
clk100 = self.cm.request("clk100", 0)
95100
self.assertIsInstance(flipped(clk100), Pin)
96101
self.assertEqual(clk100.dir, "i")
97102
self.assertEqual(clk100.width, 1)
@@ -112,8 +117,10 @@ def test_request_inverted(self):
112117
]
113118
self.cm.add_resources(new_resources)
114119

115-
cs = self.cm.request("cs")
116-
clk = self.cm.request("clk")
120+
with _ignore_deprecated():
121+
cs = self.cm.request("cs")
122+
clk = self.cm.request("clk")
123+
117124
(
118125
(cs_pin, cs_port, _),
119126
(clk_pin, clk_port, _),
@@ -144,7 +151,8 @@ def test_request_via_connector(self):
144151
Subsignal("mosi", Pins("4", conn=("pmod", 0))),
145152
)
146153
])
147-
spi0 = self.cm.request("spi", 0)
154+
with _ignore_deprecated():
155+
spi0 = self.cm.request("spi", 0)
148156
(
149157
(ss_pin, ss_port, _),
150158
(clk_pin, clk_port, _),
@@ -173,7 +181,8 @@ def test_request_via_nested_connector(self):
173181
Subsignal("mosi", Pins("4", conn=("pmod_extension", 0))),
174182
)
175183
])
176-
spi0 = self.cm.request("spi", 0)
184+
with _ignore_deprecated():
185+
spi0 = self.cm.request("spi", 0)
177186
(
178187
(ss_pin, ss_port, _),
179188
(clk_pin, clk_port, _),
@@ -190,8 +199,9 @@ def test_request_via_nested_connector(self):
190199
self.assertEqual(mosi_port.io.metadata[0].name, "B3")
191200

192201
def test_request_clock(self):
193-
clk100 = self.cm.request("clk100", 0)
194-
clk50 = self.cm.request("clk50", 0, dir="i")
202+
with _ignore_deprecated():
203+
clk100 = self.cm.request("clk100", 0)
204+
clk50 = self.cm.request("clk50", 0, dir="i")
195205
(
196206
(clk100_pin, clk100_port, _),
197207
(clk50_pin, clk50_port, _),
@@ -202,7 +212,8 @@ def test_request_clock(self):
202212
])
203213

204214
def test_add_clock(self):
205-
i2c = self.cm.request("i2c")
215+
with _ignore_deprecated():
216+
i2c = self.cm.request("i2c")
206217
self.cm.add_clock_constraint(i2c.scl.o, 100e3)
207218
self.assertEqual(list(self.cm.iter_clock_constraints()), [
208219
(i2c.scl.o, None, 100e3)
@@ -246,18 +257,21 @@ def test_wrong_clock_frequency(self):
246257
def test_wrong_request_duplicate(self):
247258
with self.assertRaisesRegex(ResourceError,
248259
r"^Resource user_led#0 has already been requested$"):
249-
self.cm.request("user_led", 0)
250-
self.cm.request("user_led", 0)
260+
with _ignore_deprecated():
261+
self.cm.request("user_led", 0)
262+
self.cm.request("user_led", 0)
251263

252264
def test_wrong_request_duplicate_physical(self):
253265
self.cm.add_resources([
254266
Resource("clk20", 0, Pins("H1", dir="i")),
255267
])
256-
self.cm.request("clk100", 0)
268+
with _ignore_deprecated():
269+
self.cm.request("clk100", 0)
257270
with self.assertRaisesRegex(ResourceError,
258271
(r"^Resource component clk20_0 uses physical pin H1, but it is already "
259272
r"used by resource component clk100_0 that was requested earlier$")):
260-
self.cm.request("clk20", 0)
273+
with _ignore_deprecated():
274+
self.cm.request("clk20", 0)
261275

262276
def test_wrong_request_with_dir(self):
263277
with self.assertRaisesRegex(TypeError,
@@ -292,7 +306,8 @@ def test_wrong_request_with_xdr_dict(self):
292306
i2c = self.cm.request("i2c", 0, xdr=2)
293307

294308
def test_wrong_clock_constraint_twice(self):
295-
clk100 = self.cm.request("clk100")
309+
with _ignore_deprecated():
310+
clk100 = self.cm.request("clk100")
296311
with self.assertRaisesRegex(ValueError,
297312
(r"^Cannot add clock constraint on \(sig clk100_0__i\), which is already "
298313
r"constrained to 100000000\.0 Hz$")):

0 commit comments

Comments
 (0)