cocotb 1.9.2__cp36-cp36m-win_amd64.whl → 2.0.0b1__cp36-cp36m-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of cocotb might be problematic. Click here for more details.

Files changed (151) hide show
  1. cocotb/{ANSI.py → _ANSI.py} +5 -25
  2. cocotb/__init__.py +76 -332
  3. cocotb/_base_triggers.py +513 -0
  4. cocotb/_bridge.py +187 -0
  5. cocotb/_decorators.py +515 -0
  6. cocotb/_deprecation.py +3 -3
  7. cocotb/_exceptions.py +7 -0
  8. cocotb/_extended_awaitables.py +419 -0
  9. cocotb/_gpi_triggers.py +382 -0
  10. cocotb/_init.py +295 -0
  11. cocotb/_outcomes.py +54 -0
  12. cocotb/_profiling.py +46 -0
  13. cocotb/_py_compat.py +100 -29
  14. cocotb/_scheduler.py +454 -0
  15. cocotb/_test.py +245 -0
  16. cocotb/_test_factory.py +309 -0
  17. cocotb/_test_functions.py +42 -0
  18. cocotb/_typing.py +7 -0
  19. cocotb/_utils.py +296 -0
  20. cocotb/_version.py +3 -7
  21. cocotb/_xunit_reporter.py +66 -0
  22. cocotb/clock.py +271 -108
  23. cocotb/handle.py +1342 -795
  24. cocotb/libs/cocotb.dll +0 -0
  25. cocotb/libs/cocotb.exp +0 -0
  26. cocotb/libs/cocotb.lib +0 -0
  27. cocotb/libs/cocotbfli_modelsim.dll +0 -0
  28. cocotb/libs/cocotbfli_modelsim.exp +0 -0
  29. cocotb/libs/cocotbfli_modelsim.lib +0 -0
  30. cocotb/libs/cocotbutils.dll +0 -0
  31. cocotb/libs/cocotbutils.exp +0 -0
  32. cocotb/libs/cocotbutils.lib +0 -0
  33. cocotb/libs/cocotbvhpi_aldec.dll +0 -0
  34. cocotb/libs/cocotbvhpi_aldec.exp +0 -0
  35. cocotb/libs/cocotbvhpi_aldec.lib +0 -0
  36. cocotb/libs/cocotbvhpi_modelsim.dll +0 -0
  37. cocotb/libs/cocotbvhpi_modelsim.exp +0 -0
  38. cocotb/libs/cocotbvhpi_modelsim.lib +0 -0
  39. cocotb/libs/cocotbvpi_aldec.dll +0 -0
  40. cocotb/libs/cocotbvpi_aldec.exp +0 -0
  41. cocotb/libs/cocotbvpi_aldec.lib +0 -0
  42. cocotb/libs/cocotbvpi_ghdl.dll +0 -0
  43. cocotb/libs/cocotbvpi_ghdl.exp +0 -0
  44. cocotb/libs/cocotbvpi_ghdl.lib +0 -0
  45. cocotb/libs/cocotbvpi_icarus.exp +0 -0
  46. cocotb/libs/cocotbvpi_icarus.lib +0 -0
  47. cocotb/libs/cocotbvpi_icarus.vpl +0 -0
  48. cocotb/libs/cocotbvpi_modelsim.dll +0 -0
  49. cocotb/libs/cocotbvpi_modelsim.exp +0 -0
  50. cocotb/libs/cocotbvpi_modelsim.lib +0 -0
  51. cocotb/libs/embed.dll +0 -0
  52. cocotb/libs/embed.exp +0 -0
  53. cocotb/libs/embed.lib +0 -0
  54. cocotb/libs/gpi.dll +0 -0
  55. cocotb/libs/gpi.exp +0 -0
  56. cocotb/libs/gpi.lib +0 -0
  57. cocotb/libs/gpilog.dll +0 -0
  58. cocotb/libs/gpilog.exp +0 -0
  59. cocotb/libs/gpilog.lib +0 -0
  60. cocotb/libs/pygpilog.dll +0 -0
  61. cocotb/libs/pygpilog.exp +0 -0
  62. cocotb/libs/pygpilog.lib +0 -0
  63. cocotb/{log.py → logging.py} +105 -110
  64. cocotb/queue.py +103 -57
  65. cocotb/regression.py +667 -712
  66. cocotb/result.py +17 -188
  67. cocotb/share/def/aldec.exp +0 -0
  68. cocotb/share/def/aldec.lib +0 -0
  69. cocotb/share/def/ghdl.exp +0 -0
  70. cocotb/share/def/ghdl.lib +0 -0
  71. cocotb/share/def/icarus.exp +0 -0
  72. cocotb/share/def/icarus.lib +0 -0
  73. cocotb/share/def/modelsim.def +1 -0
  74. cocotb/share/def/modelsim.exp +0 -0
  75. cocotb/share/def/modelsim.lib +0 -0
  76. cocotb/share/include/cocotb_utils.h +6 -29
  77. cocotb/share/include/embed.h +5 -28
  78. cocotb/share/include/gpi.h +137 -92
  79. cocotb/share/include/gpi_logging.h +221 -142
  80. cocotb/share/include/py_gpi_logging.h +7 -4
  81. cocotb/share/include/vpi_user_ext.h +4 -26
  82. cocotb/share/lib/verilator/verilator.cpp +59 -54
  83. cocotb/simulator.cp36-win_amd64.exp +0 -0
  84. cocotb/simulator.cp36-win_amd64.lib +0 -0
  85. cocotb/simulator.cp36-win_amd64.pyd +0 -0
  86. cocotb/task.py +434 -212
  87. cocotb/triggers.py +55 -1092
  88. cocotb/types/__init__.py +25 -47
  89. cocotb/types/_abstract_array.py +151 -0
  90. cocotb/types/_array.py +264 -0
  91. cocotb/types/_logic.py +296 -0
  92. cocotb/types/_logic_array.py +834 -0
  93. cocotb/types/{range.py → _range.py} +36 -44
  94. cocotb/types/_resolve.py +76 -0
  95. cocotb/utils.py +119 -587
  96. cocotb-2.0.0b1.dist-info/METADATA +48 -0
  97. cocotb-2.0.0b1.dist-info/RECORD +139 -0
  98. cocotb-2.0.0b1.dist-info/entry_points.txt +3 -0
  99. {cocotb-1.9.2.dist-info → cocotb-2.0.0b1.dist-info}/top_level.txt +1 -0
  100. cocotb_tools/_coverage.py +33 -0
  101. cocotb_tools/_vendor/__init__.py +3 -0
  102. cocotb_tools/check_results.py +65 -0
  103. cocotb_tools/combine_results.py +152 -0
  104. cocotb_tools/config.py +241 -0
  105. {cocotb → cocotb_tools}/ipython_support.py +29 -22
  106. cocotb_tools/makefiles/Makefile.deprecations +27 -0
  107. {cocotb/share → cocotb_tools}/makefiles/Makefile.inc +82 -54
  108. {cocotb/share → cocotb_tools}/makefiles/Makefile.sim +8 -33
  109. {cocotb/share → cocotb_tools}/makefiles/simulators/Makefile.activehdl +9 -16
  110. cocotb_tools/makefiles/simulators/Makefile.cvc +61 -0
  111. cocotb_tools/makefiles/simulators/Makefile.dsim +39 -0
  112. {cocotb/share → cocotb_tools}/makefiles/simulators/Makefile.ghdl +13 -42
  113. cocotb_tools/makefiles/simulators/Makefile.icarus +80 -0
  114. cocotb_tools/makefiles/simulators/Makefile.ius +93 -0
  115. cocotb_tools/makefiles/simulators/Makefile.modelsim +9 -0
  116. cocotb_tools/makefiles/simulators/Makefile.nvc +60 -0
  117. cocotb_tools/makefiles/simulators/Makefile.questa +29 -0
  118. cocotb/share/makefiles/simulators/Makefile.questa → cocotb_tools/makefiles/simulators/Makefile.questa-compat +26 -54
  119. cocotb_tools/makefiles/simulators/Makefile.questa-qisqrun +149 -0
  120. {cocotb/share → cocotb_tools}/makefiles/simulators/Makefile.riviera +17 -56
  121. cocotb_tools/makefiles/simulators/Makefile.vcs +65 -0
  122. {cocotb/share → cocotb_tools}/makefiles/simulators/Makefile.verilator +15 -22
  123. {cocotb/share → cocotb_tools}/makefiles/simulators/Makefile.xcelium +20 -52
  124. {cocotb → cocotb_tools}/runner.py +794 -361
  125. cocotb/_sim_versions.py → cocotb_tools/sim_versions.py +16 -21
  126. pygpi/entry.py +34 -17
  127. cocotb/binary.py +0 -858
  128. cocotb/config.py +0 -289
  129. cocotb/decorators.py +0 -332
  130. cocotb/memdebug.py +0 -35
  131. cocotb/outcomes.py +0 -56
  132. cocotb/scheduler.py +0 -1099
  133. cocotb/share/makefiles/Makefile.deprecations +0 -12
  134. cocotb/share/makefiles/simulators/Makefile.cvc +0 -94
  135. cocotb/share/makefiles/simulators/Makefile.icarus +0 -111
  136. cocotb/share/makefiles/simulators/Makefile.ius +0 -125
  137. cocotb/share/makefiles/simulators/Makefile.modelsim +0 -32
  138. cocotb/share/makefiles/simulators/Makefile.nvc +0 -64
  139. cocotb/share/makefiles/simulators/Makefile.vcs +0 -98
  140. cocotb/types/array.py +0 -309
  141. cocotb/types/logic.py +0 -292
  142. cocotb/types/logic_array.py +0 -298
  143. cocotb/wavedrom.py +0 -199
  144. cocotb/xunit_reporter.py +0 -80
  145. cocotb-1.9.2.dist-info/METADATA +0 -170
  146. cocotb-1.9.2.dist-info/RECORD +0 -121
  147. cocotb-1.9.2.dist-info/entry_points.txt +0 -3
  148. {cocotb-1.9.2.dist-info → cocotb-2.0.0b1.dist-info}/LICENSE +0 -0
  149. {cocotb-1.9.2.dist-info → cocotb-2.0.0b1.dist-info}/WHEEL +0 -0
  150. {cocotb/_vendor → cocotb_tools}/__init__.py +0 -0
  151. {cocotb → cocotb_tools}/_vendor/distutils_version.py +0 -0
cocotb/types/array.py DELETED
@@ -1,309 +0,0 @@
1
- # Copyright cocotb contributors
2
- # Licensed under the Revised BSD License, see LICENSE for details.
3
- # SPDX-License-Identifier: BSD-3-Clause
4
- import typing
5
- from itertools import chain
6
-
7
- from cocotb.types.range import Range
8
-
9
- T = typing.TypeVar("T")
10
- S = typing.TypeVar("S")
11
- Self = typing.TypeVar("Self", bound="Array[typing.Any]")
12
-
13
-
14
- class Array(typing.Reversible[T], typing.Collection[T]):
15
- r"""
16
- Fixed-size, arbitrarily-indexed, homogeneous collection type.
17
-
18
- Arrays are similar to, but different from Python :class:`list`\ s.
19
- An array can store values of any type or values of multiple types at a time, just like a :class:`list`.
20
- Unlike :class:`list`\ s, an array's size cannot change.
21
-
22
- The indexes of an array can start or end at any integer value, they are not limited to 0-based indexing.
23
- Indexing schemes can be either ascending or descending in value.
24
- An array's indexes are described using a :class:`~cocotb.types.Range` object.
25
- Initial values are treated as iterables, which are copied into an internal buffer.
26
-
27
- .. code-block:: python3
28
-
29
- >>> Array("1234") # the 0-based range `(0, len(value)-1)` is inferred
30
- Array(['1', '2', '3', '4'], Range(0, 'to', 3))
31
-
32
- >>> Array([1, True, None, "example"], Range(-2, 1)) # initial value and range lengths must be equal
33
- Array([1, True, None, 'example'], Range(-2, 'to', 1))
34
-
35
- Arrays also support "null" ranges; "null" arrays have zero length and cannot be indexed.
36
-
37
- .. code-block:: python3
38
-
39
- >>> Array([], range=Range(1, "to", 0))
40
- Array([], Range(1, 'to', 0))
41
-
42
- Indexing and slicing is very similar to :class:`list`\ s, but it uses the indexing scheme specified.
43
- Slicing, just like the :class:`~cocotb.types.Range` object uses an inclusive right bound,
44
- which is commonly seen in HDLs.
45
- Like :class:`list`\ s, if a start or stop index is not specified, it is inferred as the start or end of the array.
46
- Slicing an array returns a new :class:`~cocotb.types.Array` object, whose bounds are the slice indexes.
47
-
48
- .. code-block:: python3
49
-
50
- >>> a = Array("1234abcd")
51
- >>> a[7]
52
- 'd'
53
- >>> a[2:5]
54
- Array(['3', '4', 'a', 'b'], Range(2, 'to', 5))
55
- >>> a[2:5] = reversed(a[2:5])
56
- >>> "".join(a)
57
- '12ba43cd'
58
-
59
- >>> b = Array("1234", Range(0, -3))
60
- >>> b[-2]
61
- '3'
62
- >>> b[-1:]
63
- Array(['2', '3', '4'], Range(-1, 'downto', -3))
64
- >>> b[:] = reversed(b)
65
- >>> b
66
- Array(['4', '3', '2', '1'], Range(0, 'downto', -3))
67
-
68
- .. warning::
69
- Arrays behave differently in certain situations than Python's builtin sequence types (:class:`list`, :class:`tuple`, etc.).
70
-
71
- - Arrays are not necessarily 0-based and slices use inclusive right bounds,
72
- so many functions that work on Python sequences by index (like :mod:`bisect`) may not work on arrays.
73
- - Slice indexes must be specified in the same direction as the array and do not support specifying a "step".
74
- - When setting a slice, the new value must be an iterable of the same size as the slice.
75
- - Negative indexes are *not* treated as an offset from the end of the array, but are treated literally.
76
-
77
- Arrays are equal to other arrays of the same length with the same values (structural equality).
78
- Bounds do not matter for equality.
79
-
80
- .. code-block:: python3
81
-
82
- >>> a = Array([1, 1, 2, 3, 5], Range(4, "downto", 0))
83
- >>> b = Array([1, 1, 2, 3, 5], Range(-2, "to", 2))
84
- >>> a == b
85
- True
86
-
87
- You can change the bounds of an array by setting the :attr:`range` to a new value.
88
- The new bounds must be the same length of the array.
89
-
90
- .. code-block:: python3
91
-
92
- >>> a = Array("1234")
93
- >>> a.range
94
- Range(0, 'to', 3)
95
- >>> a.range = Range(3, 'downto', 0)
96
- >>> a.range
97
- Range(3, 'downto', 0)
98
-
99
- Arrays support the methods and semantics defined by :class:`collections.abc.Sequence`.
100
-
101
- .. code-block:: python
102
-
103
- >>> a = Array("stuff", Range(2, "downto", -2))
104
- >>> len(a)
105
- 5
106
- >>> "t" in a
107
- True
108
- >>> a.index("u")
109
- 0
110
- >>> for c in a:
111
- ... print(c)
112
- s
113
- t
114
- u
115
- f
116
- f
117
-
118
- Args:
119
- value: Initial value for the array.
120
- range: Indexing scheme of the array.
121
-
122
- Raises:
123
- ValueError: When argument values cannot be used to construct an array.
124
- TypeError: When invalid argument types are used.
125
- """
126
-
127
- __slots__ = (
128
- "_value",
129
- "_range",
130
- )
131
-
132
- def __init__(self, value: typing.Iterable[T], range: typing.Optional[Range] = None):
133
- self._value = list(value)
134
- if range is None:
135
- self._range = Range(0, "to", len(self._value) - 1)
136
- else:
137
- self._range = range
138
- if len(self._value) != len(self._range):
139
- raise ValueError(
140
- "init value of length {!r} does not fit in {!r}".format(
141
- len(self._value), self._range
142
- )
143
- )
144
-
145
- @property
146
- def left(self) -> int:
147
- """Leftmost index of the array."""
148
- return self.range.left
149
-
150
- @property
151
- def direction(self) -> str:
152
- """``"to"`` if indexes are ascending, ``"downto"`` otherwise."""
153
- return self.range.direction
154
-
155
- @property
156
- def right(self) -> int:
157
- """Rightmost index of the array."""
158
- return self.range.right
159
-
160
- @property
161
- def range(self) -> Range:
162
- """:class:`Range` of the indexes of the array."""
163
- return self._range
164
-
165
- @range.setter
166
- def range(self, new_range: Range) -> None:
167
- """Sets a new indexing scheme on the array, must be the same size"""
168
- if not isinstance(new_range, Range):
169
- raise TypeError("range argument must be of type 'Range'")
170
- if len(new_range) != len(self):
171
- raise ValueError(
172
- f"{new_range!r} not the same length as old range ({self._range!r})."
173
- )
174
- self._range = new_range
175
-
176
- def __len__(self) -> int:
177
- return len(self.range)
178
-
179
- def __iter__(self) -> typing.Iterator[T]:
180
- return iter(self._value)
181
-
182
- def __reversed__(self) -> typing.Iterator[T]:
183
- return reversed(self._value)
184
-
185
- def __contains__(self, item: object) -> bool:
186
- return item in self._value
187
-
188
- def __eq__(self, other: object) -> bool:
189
- if isinstance(other, type(self)):
190
- return self._value == other._value
191
- return NotImplemented
192
-
193
- @typing.overload
194
- def __getitem__(self, item: int) -> T:
195
- ...
196
-
197
- @typing.overload
198
- def __getitem__(self, item: slice) -> "Array[T]":
199
- ...
200
-
201
- def __getitem__(
202
- self, item: typing.Union[int, slice]
203
- ) -> typing.Union[T, "Array[T]"]:
204
- if isinstance(item, int):
205
- idx = self._translate_index(item)
206
- return self._value[idx]
207
- elif isinstance(item, slice):
208
- start = item.start if item.start is not None else self.left
209
- stop = item.stop if item.stop is not None else self.right
210
- if item.step is not None:
211
- raise IndexError("do not specify step")
212
- start_i = self._translate_index(start)
213
- stop_i = self._translate_index(stop)
214
- if start_i > stop_i:
215
- raise IndexError(
216
- "slice [{}:{}] direction does not match array direction [{}:{}]".format(
217
- start, stop, self.left, self.right
218
- )
219
- )
220
- value = self._value[start_i : stop_i + 1]
221
- range = Range(start, self.direction, stop)
222
- return type(self)(value=value, range=range)
223
- raise TypeError(
224
- "indexes must be ints or slices, not {}".format(type(item).__name__)
225
- )
226
-
227
- @typing.overload
228
- def __setitem__(self, item: int, value: T) -> None:
229
- ...
230
-
231
- @typing.overload
232
- def __setitem__(self, item: slice, value: typing.Iterable[T]) -> None:
233
- ...
234
-
235
- def __setitem__(
236
- self, item: typing.Union[int, slice], value: typing.Union[T, typing.Iterable[T]]
237
- ) -> None:
238
- if isinstance(item, int):
239
- idx = self._translate_index(item)
240
- self._value[idx] = typing.cast(T, value)
241
- elif isinstance(item, slice):
242
- start = item.start if item.start is not None else self.left
243
- stop = item.stop if item.stop is not None else self.right
244
- if item.step is not None:
245
- raise IndexError("do not specify step")
246
- start_i = self._translate_index(start)
247
- stop_i = self._translate_index(stop)
248
- if start_i > stop_i:
249
- raise IndexError(
250
- "slice [{}:{}] direction does not match array direction [{}:{}]".format(
251
- start, stop, self.left, self.right
252
- )
253
- )
254
- value = list(typing.cast(typing.Iterable[T], value))
255
- if len(value) != (stop_i - start_i + 1):
256
- raise ValueError(
257
- "value of length {!r} will not fit in slice [{}:{}]".format(
258
- len(value), start, stop
259
- )
260
- )
261
- self._value[start_i : stop_i + 1] = value
262
- else:
263
- raise TypeError(
264
- "indexes must be ints or slices, not {}".format(type(item).__name__)
265
- )
266
-
267
- def __repr__(self) -> str:
268
- return "{}({!r}, {!r})".format(type(self).__name__, self._value, self._range)
269
-
270
- def __concat__(self: Self, other: Self) -> Self:
271
- if isinstance(other, type(self)):
272
- return type(self)(chain(self, other))
273
- return NotImplemented
274
-
275
- def __rconcat__(self: Self, other: Self) -> Self:
276
- if isinstance(other, type(self)):
277
- return type(self)(chain(other, self))
278
- return NotImplemented
279
-
280
- def index(
281
- self,
282
- value: T,
283
- start: typing.Optional[int] = None,
284
- stop: typing.Optional[int] = None,
285
- ) -> int:
286
- """
287
- Return index of first occurrence of *value*.
288
-
289
- Raises :exc:`IndexError` if the value is not found.
290
- Search only within *start* and *stop* if given.
291
- """
292
- if start is None:
293
- start = self.left
294
- if stop is None:
295
- stop = self.right
296
- for i in Range(start, self.direction, stop):
297
- if self[i] == value:
298
- return i
299
- raise IndexError(f"{value!r} not in array")
300
-
301
- def count(self, value: T) -> int:
302
- """Return number of occurrences of *value*."""
303
- return self._value.count(value)
304
-
305
- def _translate_index(self, item: int) -> int:
306
- try:
307
- return self._range.index(item)
308
- except ValueError:
309
- raise IndexError(f"index {item} out of range") from None
cocotb/types/logic.py DELETED
@@ -1,292 +0,0 @@
1
- # Copyright cocotb contributors
2
- # Licensed under the Revised BSD License, see LICENSE for details.
3
- # SPDX-License-Identifier: BSD-3-Clause
4
- import typing
5
- from functools import lru_cache
6
-
7
- LogicT = typing.TypeVar("LogicT", bound="Logic")
8
- LogicLiteralT = typing.Union[str, int, bool]
9
- LogicConstructibleT = typing.Union[LogicLiteralT, "Logic"]
10
-
11
-
12
- _0 = 0
13
- _1 = 1
14
- _X = 2
15
- _Z = 3
16
-
17
- _literal_repr: typing.Dict[LogicLiteralT, int] = {
18
- # 0 and weak 0
19
- False: _0,
20
- 0: _0,
21
- "0": _0,
22
- "L": _0,
23
- "l": _0,
24
- # 1 and weak 1
25
- True: _1,
26
- 1: _1,
27
- "1": _1,
28
- "H": _1,
29
- "h": _1,
30
- # unknown, unassigned, and weak unknown
31
- "X": _X,
32
- "x": _X,
33
- "U": _X,
34
- "u": _X,
35
- "W": _X,
36
- "w": _X,
37
- "-": _X,
38
- # high impedance
39
- "Z": _Z,
40
- "z": _Z,
41
- }
42
-
43
-
44
- class Logic:
45
- r"""
46
- Model of a 4-value (``0``, ``1``, ``X``, ``Z``) datatype commonly seen in HDLs.
47
-
48
- .. currentmodule:: cocotb.types
49
-
50
- This is modeled after (System)Verilog's 4-value ``logic`` type.
51
- VHDL's 9-value ``std_ulogic`` type maps to this type by treating weak values as full strength values
52
- and treating "uninitialized" (``U``) and "don't care" (``-``) as "unknown" (``X``).
53
-
54
- :class:`Logic` can be converted to and from :class:`int`, :class:`str`, :class:`bool`, and :class:`Bit`
55
- by using the appropriate constructor syntax.
56
- The list of values convertable to :class:`Logic` includes
57
- ``0``, ``1``, ``True``, ``False``, ``"0"``, ``"1"``, ``"X"``, ``"Z"``, ``Bit('0')``, and ``Bit('1')``.
58
- For a comprehensive list of values that can be converted into :class:`Logic` see :file:`tests/pytest/test_logic.py`.
59
-
60
- .. code-block:: python3
61
-
62
- >>> Logic("X")
63
- Logic('X')
64
- >>> Logic(True)
65
- Logic('1')
66
- >>> Logic(1)
67
- Logic('1')
68
- >>> Logic(Bit(0))
69
- Logic('0')
70
-
71
- >>> Logic() # default value
72
- Logic('X')
73
-
74
- >>> str(Logic("Z"))
75
- 'Z'
76
- >>> bool(Logic(0))
77
- False
78
- >>> int(Logic(1))
79
- 1
80
- >>> Bit(Logic("1"))
81
- Bit('1')
82
-
83
- .. note::
84
-
85
- The :class:`int` and :class:`bool` conversions will raise :exc:`ValueError` if the value is not ``0`` or ``1``.
86
-
87
- :class:`Logic` values are immutable and therefore hashable and can be placed in :class:`set`\ s and used as keys in :class:`dict`\ s.
88
-
89
- :class:`Logic` supports the common logic operations ``&``, ``|``, ``^``, and ``~``.
90
-
91
- .. code-block:: python3
92
-
93
- >>> def full_adder(a: Logic, b: Logic, carry: Logic) -> typing.Tuple[Logic, Logic]:
94
- ... res = a ^ b ^ carry
95
- ... carry_out = (a & b) | (b & carry) | (a & carry)
96
- ... return res, carry_out
97
-
98
- >>> full_adder(a=Logic('0'), b=Logic('1'), carry=Logic('1'))
99
- (Logic('0'), Logic('1'))
100
-
101
- Args:
102
- value: value to construct into a :class:`Logic`.
103
-
104
- Raises:
105
- ValueError: if the value cannot be constructed into a :class:`Logic`.
106
- """
107
- __slots__ = ("_repr",)
108
- _repr: int
109
-
110
- _default = _X
111
- _valid = {_X, _0, _1, _Z}
112
-
113
- @classmethod
114
- @lru_cache(maxsize=None)
115
- def _make(cls: typing.Type[LogicT], _repr: int) -> LogicT:
116
- """enforce singleton"""
117
- self = object.__new__(cls)
118
- self._repr = _repr
119
- return typing.cast(LogicT, self)
120
-
121
- def __new__(
122
- cls: typing.Type[LogicT],
123
- value: typing.Optional[LogicConstructibleT] = None,
124
- ) -> LogicT:
125
- if isinstance(value, Logic):
126
- # convert Logic
127
- _repr = value._repr
128
- elif value is None:
129
- _repr = cls._default
130
- else:
131
- # convert literal
132
- try:
133
- _repr = _literal_repr[value]
134
- except KeyError:
135
- raise ValueError(
136
- "{!r} is not convertible to a {}".format(value, cls.__qualname__)
137
- ) from None
138
- if _repr not in cls._valid:
139
- raise ValueError("{!r} is not a valid {}".format(value, cls.__qualname__))
140
- obj = cls._make(_repr)
141
- return obj
142
-
143
- if not typing.TYPE_CHECKING: # pragma: no cover
144
- # mypy currently does not support lru_cache on __new__
145
- __new__ = lru_cache(maxsize=None)(__new__)
146
-
147
- def __and__(self: LogicT, other: LogicT) -> LogicT:
148
- if not isinstance(other, type(self)):
149
- return NotImplemented
150
- return type(self)(
151
- (
152
- ("0", "0", "0", "0"),
153
- ("0", "1", "X", "X"),
154
- ("0", "X", "X", "X"),
155
- ("0", "X", "X", "X"),
156
- )[self._repr][other._repr]
157
- )
158
-
159
- def __rand__(self: LogicT, other: LogicT) -> LogicT:
160
- return self & other
161
-
162
- def __or__(self: LogicT, other: LogicT) -> LogicT:
163
- if not isinstance(other, type(self)):
164
- return NotImplemented
165
- return type(self)(
166
- (
167
- ("0", "1", "X", "X"),
168
- ("1", "1", "1", "1"),
169
- ("X", "1", "X", "X"),
170
- ("X", "1", "X", "X"),
171
- )[self._repr][other._repr]
172
- )
173
-
174
- def __ror__(self: LogicT, other: LogicT) -> LogicT:
175
- return self | other
176
-
177
- def __xor__(self: LogicT, other: LogicT) -> LogicT:
178
- if not isinstance(other, type(self)):
179
- return NotImplemented
180
- return type(self)(
181
- (
182
- ("0", "1", "X", "X"),
183
- ("1", "0", "X", "X"),
184
- ("X", "X", "X", "X"),
185
- ("X", "X", "X", "X"),
186
- )[self._repr][other._repr]
187
- )
188
-
189
- def __rxor__(self: LogicT, other: LogicT) -> LogicT:
190
- return self ^ other
191
-
192
- def __invert__(self: LogicT) -> LogicT:
193
- return type(self)(("1", "0", "X", "X")[self._repr])
194
-
195
- def __eq__(self, other: object) -> bool:
196
- if not isinstance(other, type(self)):
197
- return NotImplemented
198
- return self._repr == other._repr
199
-
200
- def __hash__(self) -> int:
201
- return self._repr
202
-
203
- def __repr__(self) -> str:
204
- return "{}({!r})".format(type(self).__qualname__, str(self))
205
-
206
- def __str__(self) -> str:
207
- return ("0", "1", "X", "Z")[self._repr]
208
-
209
- def __bool__(self) -> bool:
210
- if self._repr in {_0, _1}:
211
- return bool(self._repr)
212
- raise ValueError(f"Cannot convert {self!r} to bool")
213
-
214
- def __int__(self) -> int:
215
- if self._repr in {_0, _1}:
216
- return int(self._repr)
217
- raise ValueError(f"Cannot convert {self!r} to int")
218
-
219
-
220
- class Bit(Logic):
221
- r"""
222
- Model of a 2-value (``0``, ``1``) datatype commonly seen in HDLs.
223
-
224
- .. currentmodule:: cocotb.types
225
-
226
- This is modeled after (System)Verilog's 2-value ``bit`` type.
227
- VHDL's ``bit`` type maps to this type perfectly.
228
-
229
- :class:`Bit` is a proper subtype of :class:`Logic`, meaning a use of :class:`Logic` can be substituted with a :class:`Bit`.
230
- Some behavior may surprise you if you do not expect it.
231
-
232
- .. code-block:: python3
233
-
234
- >>> Bit(0) == Logic(0)
235
- True
236
- >>> Bit(0) in {Logic(0)}
237
- True
238
-
239
- :class:`Bit` can be converted to and from :class:`int`, :class:`str`, :class:`bool`, and :class:`Logic`
240
- by using the appropriate constructor syntax.
241
- The list of values convertable to :class:`Bit` includes
242
- ``0``, ``1``, ``True``, ``False``, ``"0"``, ``"1"``, ``Logic('0')``, and ``Logic('1')``.
243
- For a comprehensive list of values that can be converted into :class:`Bit` see :file:`tests/pytest/test_logic.py`.
244
-
245
- .. code-block:: python3
246
-
247
- >>> Bit("0")
248
- Bit('0')
249
- >>> Bit(True)
250
- Bit('1')
251
- >>> Bit(1)
252
- Bit('1')
253
- >>> Bit(Logic(0))
254
- Bit('0')
255
-
256
- >>> Bit() # default value
257
- Bit('0')
258
-
259
- >>> str(Bit("0"))
260
- '0'
261
- >>> bool(Bit(False))
262
- False
263
- >>> int(Bit(1))
264
- 1
265
- >>> Logic(Bit("1"))
266
- Logic('1')
267
-
268
- :class:`Bit` values are hashable and can be placed in :class:`set`\ s and used as keys in :class:`dict`\ s.
269
-
270
- :class:`Bit` supports the common logic operations ``&``, ``|``, ``^``, and ``~``.
271
-
272
- .. code-block:: py3
273
-
274
- >>> def mux(a: Bit, b: Bit, s: Bit) -> Bit:
275
- ... return (a & ~s) | (b & s)
276
-
277
- >>> a = Bit(0)
278
- >>> b = Bit(1)
279
- >>> sel = Bit(1) # choose second argument
280
- >>> mux(a, b, sel)
281
- Bit('1')
282
-
283
- Args:
284
- value: value to construct into a :class:`Bit`.
285
-
286
- Raises:
287
- ValueError: if the value cannot be constructed into a :class:`Bit`.
288
- """
289
- __slots__ = ()
290
-
291
- _default = _0
292
- _valid = {_0, _1}