Skip to content

Commit e54a86b

Browse files
committed
Implement RFC 55: New lib.io components.
1 parent 51e0262 commit e54a86b

File tree

5 files changed

+111
-50
lines changed

5 files changed

+111
-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

@@ -889,6 +890,8 @@ class Signature(wiring.Signature):
889890
"""A signature for :class:`Pin`. The parameters are as defined on the ``Pin`` class,
890891
and are accessible as attributes.
891892
"""
893+
# TODO(amaranth-0.6): remove
894+
@deprecated("`amaranth.lib.io.Pin` is deprecated, use `amaranth.lib.io.*Buffer` instead")
892895
def __init__(self, width, dir, *, xdr=0):
893896
if not isinstance(width, int) or width < 0:
894897
raise TypeError("Width must be a non-negative integer, not {!r}"
@@ -942,17 +945,20 @@ def __repr__(self):
942945
def create(self, *, path=None, src_loc_at=0):
943946
return Pin(self.width, self.dir, xdr=self.xdr, path=path, src_loc_at=1 + src_loc_at)
944947

948+
# TODO(amaranth-0.6): remove
949+
@deprecated("`amaranth.lib.io.Pin` is deprecated, use `amaranth.lib.io.*Buffer` instead")
945950
def __init__(self, width, dir, *, xdr=0, name=None, path=None, src_loc_at=0):
946951
if name is not None:
947952
if path is not None:
948953
raise ValueError("Cannot pass both name and path")
949954
path = (name,)
950955
if path is None:
951-
name = tracer.get_var_name(depth=2 + src_loc_at, default="$pin")
956+
name = tracer.get_var_name(depth=3 + src_loc_at, default="$pin")
952957
path = (name,)
953958
self.path = tuple(path)
954959
self.name = "__".join(path)
955-
signature = Pin.Signature(width, dir, xdr=xdr)
960+
with _ignore_deprecated():
961+
signature = Pin.Signature(width, dir, xdr=xdr)
956962
super().__init__(signature, path=path, src_loc_at=src_loc_at + 1)
957963

958964
@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
@@ -74,6 +75,7 @@ Implemented RFCs
7475
* `RFC 50`_: ``Print`` statement and string formatting
7576
* `RFC 51`_: Add ``ShapeCastable.from_bits`` and ``amaranth.lib.data.Const``
7677
* `RFC 53`_: Low-level I/O primitives
78+
* `RFC 55`_: New ``lib.io`` components
7779
* `RFC 58`_: Core support for ``ValueCastable`` formatting
7880
* `RFC 59`_: Get rid of upwards propagation of clock domains
7981
* `RFC 62`_: The ``MemoryData`` class

tests/test_build_res.py

Lines changed: 32 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,15 +76,17 @@ 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
((_, _, scl_buffer), (_, _, sda_buffer)) = self.cm.iter_pins()
8184
scl_buffer._MustUse__silence = True
8285
sda_buffer._MustUse__silence = True
8386

8487
def test_request_tristate(self):
85-
i2c = self.cm.request("i2c", 0)
88+
with _ignore_deprecated():
89+
i2c = self.cm.request("i2c", 0)
8690
self.assertEqual(i2c.sda.dir, "io")
8791

8892
((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):
97101
self.assertEqual(sda_port.io.metadata[0].name, "N11")
98102

99103
def test_request_diffpairs(self):
100-
clk100 = self.cm.request("clk100", 0)
104+
with _ignore_deprecated():
105+
clk100 = self.cm.request("clk100", 0)
101106
self.assertIsInstance(flipped(clk100), Pin)
102107
self.assertEqual(clk100.dir, "i")
103108
self.assertEqual(clk100.width, 1)
@@ -120,8 +125,10 @@ def test_request_inverted(self):
120125
]
121126
self.cm.add_resources(new_resources)
122127

123-
cs = self.cm.request("cs")
124-
clk = self.cm.request("clk")
128+
with _ignore_deprecated():
129+
cs = self.cm.request("cs")
130+
clk = self.cm.request("clk")
131+
125132
(
126133
(cs_pin, cs_port, cs_buffer),
127134
(clk_pin, clk_port, clk_buffer),
@@ -154,7 +161,8 @@ def test_request_via_connector(self):
154161
Subsignal("copi", Pins("4", conn=("pmod", 0))),
155162
)
156163
])
157-
spi0 = self.cm.request("spi", 0)
164+
with _ignore_deprecated():
165+
spi0 = self.cm.request("spi", 0)
158166
(
159167
(cs_pin, cs_port, cs_buffer),
160168
(clk_pin, clk_port, clk_buffer),
@@ -187,7 +195,8 @@ def test_request_via_nested_connector(self):
187195
Subsignal("copi", Pins("4", conn=("pmod_extension", 0))),
188196
)
189197
])
190-
spi0 = self.cm.request("spi", 0)
198+
with _ignore_deprecated():
199+
spi0 = self.cm.request("spi", 0)
191200
(
192201
(cs_pin, cs_port, cs_buffer),
193202
(clk_pin, clk_port, clk_buffer),
@@ -208,8 +217,9 @@ def test_request_via_nested_connector(self):
208217
self.assertEqual(copi_port.io.metadata[0].name, "B3")
209218

210219
def test_request_clock(self):
211-
clk100 = self.cm.request("clk100", 0)
212-
clk50 = self.cm.request("clk50", 0, dir="i")
220+
with _ignore_deprecated():
221+
clk100 = self.cm.request("clk100", 0)
222+
clk50 = self.cm.request("clk50", 0, dir="i")
213223
(
214224
(clk100_pin, clk100_port, clk100_buffer),
215225
(clk50_pin, clk50_port, clk50_buffer),
@@ -222,7 +232,8 @@ def test_request_clock(self):
222232
])
223233

224234
def test_add_clock(self):
225-
i2c = self.cm.request("i2c")
235+
with _ignore_deprecated():
236+
i2c = self.cm.request("i2c")
226237
self.cm.add_clock_constraint(i2c.scl.o, 100e3)
227238
self.assertEqual(list(self.cm.iter_clock_constraints()), [
228239
(i2c.scl.o, None, 100e3)
@@ -267,24 +278,28 @@ def test_wrong_clock_frequency(self):
267278
self.cm.add_clock_constraint(Signal(), None)
268279

269280
def test_wrong_request_duplicate(self):
270-
self.cm.request("user_led", 0)
281+
with _ignore_deprecated():
282+
self.cm.request("user_led", 0)
271283
(pin, port, buffer), = self.cm.iter_pins()
272284
buffer._MustUse__silence = True
273285
with self.assertRaisesRegex(ResourceError,
274286
r"^Resource user_led#0 has already been requested$"):
275-
self.cm.request("user_led", 0)
287+
with _ignore_deprecated():
288+
self.cm.request("user_led", 0)
276289

277290
def test_wrong_request_duplicate_physical(self):
278291
self.cm.add_resources([
279292
Resource("clk20", 0, Pins("H1", dir="i")),
280293
])
281-
self.cm.request("clk100", 0)
294+
with _ignore_deprecated():
295+
self.cm.request("clk100", 0)
282296
(pin, port, buffer), = self.cm.iter_pins()
283297
buffer._MustUse__silence = True
284298
with self.assertRaisesRegex(ResourceError,
285299
(r"^Resource component clk20_0 uses physical pin H1, but it is already "
286300
r"used by resource component clk100_0 that was requested earlier$")):
287-
self.cm.request("clk20", 0)
301+
with _ignore_deprecated():
302+
self.cm.request("clk20", 0)
288303

289304
def test_wrong_request_with_dir(self):
290305
with self.assertRaisesRegex(TypeError,
@@ -319,7 +334,8 @@ def test_wrong_request_with_xdr_dict(self):
319334
i2c = self.cm.request("i2c", 0, xdr=2)
320335

321336
def test_wrong_clock_constraint_twice(self):
322-
clk100 = self.cm.request("clk100")
337+
with _ignore_deprecated():
338+
clk100 = self.cm.request("clk100")
323339
(pin, port, buffer), = self.cm.iter_pins()
324340
buffer._MustUse__silence = True
325341
with self.assertRaisesRegex(ValueError,

0 commit comments

Comments
 (0)