Skip to content

Commit dc38ea7

Browse files
committed
Add an RFC for PortLike.with_direction.
1 parent a838a3b commit dc38ea7

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

text/0079-port-with-direction.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
- Start Date: 2025-06-02
2+
- RFC PR: [amaranth-lang/rfcs#79](https://github.com/amaranth-lang/rfcs/pull/79)
3+
- Amaranth Issue: [amaranth-lang/amaranth#0000](https://github.com/amaranth-lang/amaranth/issues/0000)
4+
5+
# Add `PortLike.with_direction`
6+
7+
## Summary
8+
[summary]: #summary
9+
10+
Add a `with_direction` method to `lib.io.PortLike`, allowing for "downcasting" a bidirectional port to an input port or an output port.
11+
12+
## Motivation
13+
[motivation]: #motivation
14+
15+
[RFC 55](https://amaranth-lang.org/rfcs/0055-lib-io.html) has made way for a variety of generic and reusable I/O components. Many such components can be parametrized by the "signature" of I/O ports used, including their directionality. One such motivating example is Glasgow's `IOStreamer`.
16+
17+
It is often convenient to treat a bidirectional port as an input-only port, or an output-only port. `lib.io` already allows such usage by instantiating a `*Buffer` with a requested direction. However, for generic components, it's oftern convenient to determine requested buffer direction by introspecting the provided port — in such case, we need some means to explicitly "downcast" the port before providing it to the component.
18+
19+
## Guide-level explanation
20+
[guide-level-explanation]: #guide-level-explanation
21+
22+
Given a `PortLike` with a direction of `Direction.Bidir`, you can use the `with_direction` method to obtain an input-only or output-only version of it:
23+
24+
```
25+
port_io = platform.request("io0", dir="-")
26+
assert port_io.direction == Direction.Bidir
27+
port_i = port_io.with_direction("i")
28+
assert port_i.direction == Direction.Input
29+
```
30+
31+
## Reference-level explanation
32+
[reference-level-explanation]: #reference-level-explanation
33+
34+
A new method is added to `PortLike` and its implementations:
35+
36+
- `with_direction(self, direction: Direction) -> PortLike`: returns a new `PortLike` equivalent to this one, but with a limitted direction
37+
- if the `direction` provided is the same as the port's direction, the returned `PortLike` is fully equivalent to `self`
38+
- if the `direction` is `Direction.Input` or `Direction.Output` and `self.direction is Direction.Bidir`, the returned `PortLike` has the given direction
39+
- any other combination of `direction` and `self.direction` is an error
40+
41+
## Drawbacks
42+
[drawbacks]: #drawbacks
43+
44+
This adds a new required method to implement on a `PortLike`, and is thus a breaking change for users implementing their own `PortLike`s.
45+
46+
## Rationale and alternatives
47+
[rationale-and-alternatives]: #rationale-and-alternatives
48+
49+
The only obvious alternative to this RFC is providing the information to the generic component out-of-band. However, this is inconvenient, particularly when groups of ports are involved.
50+
51+
We can have the usual bikeshedding about the name.
52+
53+
## Prior art
54+
[prior-art]: #prior-art
55+
56+
Most languages allow using an `inout` as an `input` or `output`.
57+
58+
## Unresolved questions
59+
[unresolved-questions]: #unresolved-questions
60+
61+
None.
62+
63+
## Future possibilities
64+
[future-possibilities]: #future-possibilities
65+
66+
None.

0 commit comments

Comments
 (0)