Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clarify documentation on the module usage in wiring.connect() #1509

Open
5aji opened this issue Sep 10, 2024 · 1 comment
Open

Clarify documentation on the module usage in wiring.connect() #1509

5aji opened this issue Sep 10, 2024 · 1 comment

Comments

@5aji
Copy link

5aji commented Sep 10, 2024

The first argument to connect() is the module that the connections should be added to, but the documentation doesn't state this clearly. It becomes clear once you understand it (the connections must be added to something, and the documentation shows it later) but it tripped me up since I was mentally primed to other constructs that operate on a Module directly (If, FSM, .next etc).

def connect(m, *args, **kwargs):
"""Connect interface objects to each other.
This function creates connections between ports of several interface objects. (Any number of
interface objects may be provided; in most cases it is two.)
The connections can be made only if all of the objects satisfy a number of requirements:
* Every interface object must have the same set of port members, and they must have the same
:meth:`dimensions <Member.dimensions>`.
* For each path, the port members of every interface object must have the same width and initial
value (for port members corresponding to signals) or constant value (for port members
corresponding to constants). Signedness may differ.
* For each path, at most one interface object must have the corresponding port member be
an output.
* For a given path, if any of the interface objects has an input port member corresponding
to a constant value, then the rest of the interface objects must have output port members
corresponding to the same constant value.
* When connecting multiple interface objects, at least one connection must be made.
For example, if :py:`obj1` is being connected to :py:`obj2` and :py:`obj3`, and :py:`obj1.a.b`
is an output, then :py:`obj2.a.b` and :py:`obj2.a.b` must exist and be inputs. If :py:`obj2.c`
is an input and its value is :py:`Const(1)`, then :py:`obj1.c` and :py:`obj3.c` must be outputs
whose value is also :py:`Const(1)`. If no ports besides :py:`obj1.a.b` and :py:`obj1.c` exist,
then no ports except for those two must exist on :py:`obj2` and :py:`obj3` either.
Once it is determined that the interface objects can be connected, this function performs
an equivalent of:
.. code::
m.d.comb += [
in1.eq(out1),
in2.eq(out1),
...
]
Where :py:`out1` is an output and :py:`in1`, :py:`in2`, ... are the inputs that have the same
path. (If no interface object has an output for a given path, **no connection at all** is made.)
The positions (within :py:`args`) or names (within :py:`kwargs`) of the arguments do not affect
the connections that are made. There is no difference in behavior between :py:`connect(m, a, b)`
and :py:`connect(m, b, a)` or :py:`connect(m, arbiter=a, decoder=b)`. The names of the keyword
arguments serve only a documentation purpose: they clarify the diagnostic messages when
a connection cannot be made.

@whitequark
Copy link
Member

whitequark commented Sep 10, 2024

The first argument to connect() is the module that the connections should be added to, but the documentation doesn't state this clearly.

I think it does in the guide section, but we should probably just expand the error message to guide to the correct usage, in this case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

2 participants