@@ -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