Skip to content

Commit 61ed6a1

Browse files
committed
Add documentation about WireVector equality checks (is and ==).
1 parent a1b0ac9 commit 61ed6a1

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed

pyrtl/wire.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,92 @@ class WireVector(object):
9292
this case with a reference to WireVector ``b``. In contrast ``a <<= b``
9393
does not overwrite ``a``, but simply wires the two together.
9494
95+
-------------------
96+
WireVector Equality
97+
-------------------
98+
99+
WireVector's :meth:`.__eq__` generates logic that dynamically reports if two wires
100+
carry the same values. WireVector's :meth:`.__eq__` returns a 1-bit WireVector, not
101+
a ``bool``, and attempting to convert a WireVector to a ``bool`` throws a
102+
``PyrtlError``. This behavior is incompatible with `Python's data model
103+
<https://docs.python.org/3/reference/expressions.html#value-comparisons>`_, which
104+
can cause problems.
105+
106+
For example, you *can not* statically check if two WireVectors are equal with
107+
``==``. Statically checking for WireVector equality can be useful while constructing
108+
or analyzing circuits::
109+
110+
>>> w1 = pyrtl.WireVector(name="w1", bitwidth=1)
111+
>>> w2 = pyrtl.WireVector(name="w2", bitwidth=2)
112+
>>> if w1 == w2:
113+
... print('same')
114+
...
115+
Traceback (most recent call last):
116+
...
117+
pyrtl.pyrtlexceptions.PyrtlError: cannot convert WireVector to compile-time
118+
boolean. This error often happens when you attempt to use WireVectors with "=="
119+
or something that calls "__eq__", such as when you test if a WireVector is "in"
120+
something
121+
122+
The error about converting WireVector to ``bool`` results from Python attempting to
123+
convert the 1-bit WireVector returned by :meth:`.__eq__` to ``True`` or ``False``
124+
while evaluating the ``if`` statement's condition.
125+
126+
Instead, you *can* statically check if two WireVectors refer to the same object with
127+
``is``::
128+
129+
>>> if w1 is not w2:
130+
... print('not the same')
131+
...
132+
not the same
133+
>>> temp = w1
134+
>>> temp is w1
135+
True
136+
>>> temp is w2
137+
False
138+
139+
Be careful when using Python features that depend on ``==`` with WireVectors. This
140+
often comes up when checking if a WireVector is in a list with ``in``, which does
141+
not work because ``in`` falls back on checking each item in the ``list`` for
142+
equality with ``==``::
143+
144+
>>> l = [w1]
145+
>>> w2 in l
146+
Traceback (most recent call last):
147+
...
148+
pyrtl.pyrtlexceptions.PyrtlError: cannot convert WireVector to compile-time
149+
boolean. This error often happens when you attempt to use WireVectors with "=="
150+
or something that calls "__eq__", such as when you test if a WireVector is "in"
151+
something
152+
153+
Most other ``list`` operations work, so you can store WireVectors in a ``list`` if
154+
you avoid using the ``in`` operator::
155+
156+
>>> len(l)
157+
1
158+
>>> l[0] is w1
159+
True
160+
>>> [(w.name, w.bitwidth) for w in l]
161+
[('w1', 1)]
162+
163+
WireVectors define a standard ``__hash__`` method, so if you need to check if a
164+
WireVector is in a container, use a ``set`` or ``dict``. This works because these
165+
containers use ``__hash__`` to skip unnecessary equality checks::
166+
167+
>>> s = {w1}
168+
>>> w1 in s
169+
True
170+
>>> w2 in s
171+
False
172+
173+
>>> d = {w1: 'hello'}
174+
>>> w1 in d
175+
True
176+
>>> w2 in d
177+
False
178+
>>> d[w1]
179+
'hello'
180+
95181
"""
96182

97183
# "code" is a static variable used when output as string.

0 commit comments

Comments
 (0)