cocotb 1.9.2__cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.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 (89) hide show
  1. cocotb/ANSI.py +92 -0
  2. cocotb/__init__.py +371 -0
  3. cocotb/_deprecation.py +36 -0
  4. cocotb/_py_compat.py +63 -0
  5. cocotb/_sim_versions.py +145 -0
  6. cocotb/_vendor/__init__.py +0 -0
  7. cocotb/_vendor/distutils_version.py +346 -0
  8. cocotb/_version.py +8 -0
  9. cocotb/binary.py +858 -0
  10. cocotb/clock.py +174 -0
  11. cocotb/config.py +289 -0
  12. cocotb/decorators.py +332 -0
  13. cocotb/handle.py +1175 -0
  14. cocotb/ipython_support.py +92 -0
  15. cocotb/libs/libcocotb.so +0 -0
  16. cocotb/libs/libcocotbfli_modelsim.so +0 -0
  17. cocotb/libs/libcocotbutils.so +0 -0
  18. cocotb/libs/libcocotbvhpi_aldec.so +0 -0
  19. cocotb/libs/libcocotbvhpi_ius.so +0 -0
  20. cocotb/libs/libcocotbvhpi_modelsim.so +0 -0
  21. cocotb/libs/libcocotbvhpi_nvc.so +0 -0
  22. cocotb/libs/libcocotbvpi_aldec.so +0 -0
  23. cocotb/libs/libcocotbvpi_ghdl.so +0 -0
  24. cocotb/libs/libcocotbvpi_icarus.vpl +0 -0
  25. cocotb/libs/libcocotbvpi_ius.so +0 -0
  26. cocotb/libs/libcocotbvpi_modelsim.so +0 -0
  27. cocotb/libs/libcocotbvpi_vcs.so +0 -0
  28. cocotb/libs/libcocotbvpi_verilator.so +0 -0
  29. cocotb/libs/libembed.so +0 -0
  30. cocotb/libs/libgpi.so +0 -0
  31. cocotb/libs/libgpilog.so +0 -0
  32. cocotb/libs/libpygpilog.so +0 -0
  33. cocotb/log.py +303 -0
  34. cocotb/memdebug.py +35 -0
  35. cocotb/outcomes.py +56 -0
  36. cocotb/queue.py +179 -0
  37. cocotb/regression.py +933 -0
  38. cocotb/result.py +209 -0
  39. cocotb/runner.py +1400 -0
  40. cocotb/scheduler.py +1099 -0
  41. cocotb/share/def/.gitignore +2 -0
  42. cocotb/share/def/README.md +4 -0
  43. cocotb/share/def/aldec.def +61 -0
  44. cocotb/share/def/ghdl.def +43 -0
  45. cocotb/share/def/icarus.def +43 -0
  46. cocotb/share/def/modelsim.def +137 -0
  47. cocotb/share/include/cocotb_utils.h +93 -0
  48. cocotb/share/include/embed.h +56 -0
  49. cocotb/share/include/exports.h +20 -0
  50. cocotb/share/include/gpi.h +265 -0
  51. cocotb/share/include/gpi_logging.h +212 -0
  52. cocotb/share/include/py_gpi_logging.h +30 -0
  53. cocotb/share/include/vhpi_user_ext.h +26 -0
  54. cocotb/share/include/vpi_user_ext.h +55 -0
  55. cocotb/share/lib/verilator/verilator.cpp +196 -0
  56. cocotb/share/makefiles/Makefile.deprecations +12 -0
  57. cocotb/share/makefiles/Makefile.inc +176 -0
  58. cocotb/share/makefiles/Makefile.sim +113 -0
  59. cocotb/share/makefiles/simulators/Makefile.activehdl +79 -0
  60. cocotb/share/makefiles/simulators/Makefile.cvc +94 -0
  61. cocotb/share/makefiles/simulators/Makefile.ghdl +113 -0
  62. cocotb/share/makefiles/simulators/Makefile.icarus +111 -0
  63. cocotb/share/makefiles/simulators/Makefile.ius +125 -0
  64. cocotb/share/makefiles/simulators/Makefile.modelsim +32 -0
  65. cocotb/share/makefiles/simulators/Makefile.nvc +64 -0
  66. cocotb/share/makefiles/simulators/Makefile.questa +171 -0
  67. cocotb/share/makefiles/simulators/Makefile.riviera +183 -0
  68. cocotb/share/makefiles/simulators/Makefile.vcs +98 -0
  69. cocotb/share/makefiles/simulators/Makefile.verilator +86 -0
  70. cocotb/share/makefiles/simulators/Makefile.xcelium +136 -0
  71. cocotb/simulator.cpython-313-i386-linux-gnu.so +0 -0
  72. cocotb/task.py +325 -0
  73. cocotb/triggers.py +1104 -0
  74. cocotb/types/__init__.py +50 -0
  75. cocotb/types/array.py +309 -0
  76. cocotb/types/logic.py +292 -0
  77. cocotb/types/logic_array.py +298 -0
  78. cocotb/types/range.py +198 -0
  79. cocotb/utils.py +698 -0
  80. cocotb/wavedrom.py +199 -0
  81. cocotb/xunit_reporter.py +80 -0
  82. cocotb-1.9.2.dist-info/LICENSE +28 -0
  83. cocotb-1.9.2.dist-info/METADATA +168 -0
  84. cocotb-1.9.2.dist-info/RECORD +89 -0
  85. cocotb-1.9.2.dist-info/WHEEL +8 -0
  86. cocotb-1.9.2.dist-info/entry_points.txt +2 -0
  87. cocotb-1.9.2.dist-info/top_level.txt +21 -0
  88. pygpi/__init__.py +0 -0
  89. pygpi/entry.py +26 -0
@@ -0,0 +1,298 @@
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
+
6
+ from cocotb.binary import BinaryRepresentation, BinaryValue
7
+ from cocotb.types.array import Array
8
+ from cocotb.types.logic import Logic, LogicConstructibleT
9
+ from cocotb.types.range import Range
10
+
11
+ LogicT = typing.TypeVar("LogicT", bound=Logic)
12
+ S = typing.TypeVar("S")
13
+ Self = typing.TypeVar("Self", bound="LogicArray")
14
+
15
+
16
+ class LogicArray(Array[Logic]):
17
+ r"""
18
+ Fixed-sized, arbitrarily-indexed, array of :class:`cocotb.types.Logic`.
19
+
20
+ .. currentmodule:: cocotb.types
21
+
22
+ :class:`LogicArray`\ s can be constructed from either iterables of values
23
+ constructible into :class:`Logic`: like :class:`bool`, :class:`str`, :class:`int`;
24
+ or from integers.
25
+ If constructed from a positive integer, an unsigned bit representation is used to
26
+ construct the :class:`LogicArray`.
27
+ If constructed from a negative integer, a two's complement bit representation is
28
+ used.
29
+ Like :class:`Array`, if no *range* argument is given, it is deduced from the length
30
+ of the iterable or bit string used to initialize the variable.
31
+ If a *range* argument is given, but no value,
32
+ the array is filled with the default value of Logic().
33
+
34
+ .. code-block:: python3
35
+
36
+ >>> LogicArray("01XZ")
37
+ LogicArray('01XZ', Range(3, 'downto', 0))
38
+
39
+ >>> LogicArray([0, True, "X"])
40
+ LogicArray('01X', Range(2, 'downto', 0))
41
+
42
+ >>> LogicArray(0xA) # picks smallest range that can fit the value
43
+ LogicArray('1010', Range(3, 'downto', 0))
44
+
45
+ >>> LogicArray(-4, Range(0, "to", 3)) # will sign-extend
46
+ LogicArray('1100', Range(0, 'to', 3))
47
+
48
+ >>> LogicArray(range=Range(0, "to", 3)) # default values
49
+ LogicArray('XXXX', Range(0, 'to', 3))
50
+
51
+ :class:`LogicArray`\ s support the same operations as :class:`Array`;
52
+ however, it enforces the condition that all elements must be a :class:`Logic`.
53
+
54
+ .. code-block:: python3
55
+
56
+ >>> la = LogicArray("1010")
57
+ >>> la[0] # is indexable
58
+ Logic('0')
59
+
60
+ >>> la[1:] # is slice-able
61
+ LogicArray('10', Range(1, 'downto', 0))
62
+
63
+ >>> Logic("0") in la # is a collection
64
+ True
65
+
66
+ >>> list(la) # is an iterable
67
+ [Logic('1'), Logic('0'), Logic('1'), Logic('0')]
68
+
69
+ When setting an element or slice, the *value* is first constructed into a
70
+ :class:`Logic`.
71
+
72
+ .. code-block:: python3
73
+
74
+ >>> la = LogicArray("1010")
75
+ >>> la[3] = "Z"
76
+ >>> la[3]
77
+ Logic('Z')
78
+
79
+ >>> la[2:] = ['X', True, 0]
80
+ >>> la
81
+ LogicArray('ZX10', Range(3, 'downto', 0))
82
+
83
+ :class:`LogicArray`\ s can be converted into :class:`str`\ s or :class:`int`\ s.
84
+
85
+ .. code-block:: python3
86
+
87
+ >>> la = LogicArray("1010")
88
+ >>> la.binstr
89
+ '1010'
90
+
91
+ >>> la.integer # uses unsigned representation
92
+ 10
93
+
94
+ >>> la.signed_integer # uses two's complement representation
95
+ -6
96
+
97
+ :class:`LogicArray`\ s also support element-wise logical operations: ``&``, ``|``,
98
+ ``^``, and ``~``.
99
+
100
+ .. code-block:: python3
101
+
102
+ >>> def big_mux(a: LogicArray, b: LogicArray, sel: Logic) -> LogicArray:
103
+ ... s = LogicArray([sel] * len(a))
104
+ ... return (a & ~s) | (b & s)
105
+
106
+ >>> la = LogicArray("0110")
107
+ >>> p = LogicArray("1110")
108
+ >>> sel = Logic('1') # choose second option
109
+ >>> big_mux(la, p, sel)
110
+ LogicArray('1110', Range(3, 'downto', 0))
111
+
112
+ Args:
113
+ value: Initial value for the array.
114
+ range: Indexing scheme of the array.
115
+
116
+ Raises:
117
+ ValueError: When argument values cannot be used to construct an array.
118
+ TypeError: When invalid argument types are used.
119
+ """
120
+
121
+ __slots__ = ()
122
+
123
+ @typing.overload
124
+ def __init__(
125
+ self,
126
+ value: typing.Union[int, typing.Iterable[LogicConstructibleT], BinaryValue],
127
+ range: typing.Optional[Range],
128
+ ):
129
+ ...
130
+
131
+ @typing.overload
132
+ def __init__(
133
+ self,
134
+ value: typing.Union[
135
+ int, typing.Iterable[LogicConstructibleT], BinaryValue, None
136
+ ],
137
+ range: Range,
138
+ ):
139
+ ...
140
+
141
+ def __init__(
142
+ self,
143
+ value: typing.Union[
144
+ int, typing.Iterable[LogicConstructibleT], BinaryValue, None
145
+ ] = None,
146
+ range: typing.Optional[Range] = None,
147
+ ) -> None:
148
+ if value is None and range is None:
149
+ raise ValueError(
150
+ "at least one of the value and range input parameters must be given"
151
+ )
152
+ if value is None:
153
+ self._value = [Logic() for _ in range]
154
+ elif isinstance(value, int):
155
+ if value < 0:
156
+ bitlen = int.bit_length(value + 1) + 1
157
+ else:
158
+ bitlen = max(1, int.bit_length(value))
159
+ if range is None:
160
+ self._value = [Logic(v) for v in _int_to_bitstr(value, bitlen)]
161
+ else:
162
+ if bitlen > len(range):
163
+ raise ValueError(f"{value} will not fit in {range}")
164
+ self._value = [Logic(v) for v in _int_to_bitstr(value, len(range))]
165
+ elif isinstance(value, typing.Iterable):
166
+ self._value = [Logic(v) for v in value]
167
+ elif isinstance(value, BinaryValue):
168
+ self._value = [Logic(v) for v in value.binstr]
169
+ else:
170
+ raise TypeError(
171
+ f"cannot construct {type(self).__qualname__} from value of type {type(value).__qualname__}"
172
+ )
173
+ if range is None:
174
+ self._range = Range(len(self._value) - 1, "downto", 0)
175
+ else:
176
+ self._range = range
177
+ if len(self._value) != len(self._range):
178
+ raise ValueError(
179
+ f"value of length {len(self._value)} will not fit in {self._range}"
180
+ )
181
+
182
+ @property
183
+ def binstr(self) -> str:
184
+ return "".join(str(bit) for bit in self)
185
+
186
+ @property
187
+ def is_resolvable(self) -> bool:
188
+ return all(bit in (Logic(0), Logic(1)) for bit in self)
189
+
190
+ @property
191
+ def integer(self) -> int:
192
+ value = 0
193
+ for bit in self:
194
+ value = value << 1 | int(bit)
195
+ return value
196
+
197
+ @property
198
+ def signed_integer(self) -> int:
199
+ value = self.integer
200
+ if value >= (1 << (len(self) - 1)):
201
+ value -= 1 << len(self)
202
+ return value
203
+
204
+ @typing.overload
205
+ def __setitem__(self, item: int, value: LogicConstructibleT) -> None:
206
+ ...
207
+
208
+ @typing.overload
209
+ def __setitem__(
210
+ self, item: slice, value: typing.Iterable[LogicConstructibleT]
211
+ ) -> None:
212
+ ...
213
+
214
+ def __setitem__(
215
+ self,
216
+ item: typing.Union[int, slice],
217
+ value: typing.Union[LogicConstructibleT, typing.Iterable[LogicConstructibleT]],
218
+ ) -> None:
219
+ if isinstance(item, int):
220
+ super().__setitem__(item, Logic(typing.cast(LogicConstructibleT, value)))
221
+ elif isinstance(item, slice):
222
+ super().__setitem__(
223
+ item,
224
+ (
225
+ Logic(v)
226
+ for v in typing.cast(typing.Iterable[LogicConstructibleT], value)
227
+ ),
228
+ )
229
+ else:
230
+ raise TypeError(
231
+ f"indexes must be ints or slices, not {type(item).__name__}"
232
+ )
233
+
234
+ def __repr__(self) -> str:
235
+ return "{}({!r}, {!r})".format(type(self).__qualname__, self.binstr, self.range)
236
+
237
+ def __and__(self: Self, other: Self) -> Self:
238
+ if isinstance(other, type(self)):
239
+ if len(self) != len(other):
240
+ raise ValueError(
241
+ f"cannot perform bitwise & "
242
+ f"between {type(self).__qualname__} of length {len(self)} "
243
+ f"and {type(other).__qualname__} of length {len(other)}"
244
+ )
245
+ return type(self)(a & b for a, b in zip(self, other)) # type: ignore
246
+ return NotImplemented
247
+
248
+ def __rand__(self: Self, other: Self) -> Self:
249
+ return self & other
250
+
251
+ def __or__(self: Self, other: Self) -> Self:
252
+ if isinstance(other, type(self)):
253
+ if len(self) != len(other):
254
+ raise ValueError(
255
+ f"cannot perform bitwise | "
256
+ f"between {type(self).__qualname__} of length {len(self)} "
257
+ f"and {type(other).__qualname__} of length {len(other)}"
258
+ )
259
+ return type(self)(a | b for a, b in zip(self, other)) # type: ignore
260
+ return NotImplemented
261
+
262
+ def __ror__(self: Self, other: Self) -> Self:
263
+ return self | other
264
+
265
+ def __xor__(self: Self, other: Self) -> Self:
266
+ if isinstance(other, type(self)):
267
+ if len(self) != len(other):
268
+ raise ValueError(
269
+ f"cannot perform bitwise ^ "
270
+ f"between {type(self).__qualname__} of length {len(self)} "
271
+ f"and {type(other).__qualname__} of length {len(other)}"
272
+ )
273
+ return type(self)(a ^ b for a, b in zip(self, other)) # type: ignore
274
+ return NotImplemented
275
+
276
+ def __rxor__(self: Self, other: Self) -> Self:
277
+ return self ^ other
278
+
279
+ def __invert__(self: Self) -> Self:
280
+ return type(self)(~v for v in self)
281
+
282
+ def to_BinaryValue(
283
+ self,
284
+ bigEndian: bool = True,
285
+ binaryRepresentation: BinaryRepresentation = BinaryRepresentation.UNSIGNED,
286
+ ) -> BinaryValue:
287
+ return BinaryValue(
288
+ value=self.binstr,
289
+ n_bits=len(self),
290
+ bigEndian=bigEndian,
291
+ binaryRepresentation=binaryRepresentation,
292
+ )
293
+
294
+
295
+ def _int_to_bitstr(value: int, n_bits: int) -> str:
296
+ if value < 0:
297
+ value += 1 << n_bits
298
+ return format(value, f"0{n_bits}b")
cocotb/types/range.py ADDED
@@ -0,0 +1,198 @@
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
+
6
+ T = typing.TypeVar("T")
7
+
8
+
9
+ class Range(typing.Sequence[int]):
10
+ r"""
11
+ Variant of :class:`range` with inclusive right bound.
12
+
13
+ In Python, :class:`range` and :class:`slice` have a non-inclusive right bound.
14
+ In both Verilog and VHDL, ranges and arrays have an inclusive right bound.
15
+ This type mimics Python's :class:`range` type, but implements HDL-like inclusive right bounds,
16
+ using the names :attr:`left` and :attr:`right` as replacements for ``start`` and ``stop`` to
17
+ match VHDL.
18
+ Range directionality can be specified using ``'to'`` or ``'downto'`` between the
19
+ left and right bounds.
20
+ Not specifying directionality will cause the directionality to be inferred.
21
+
22
+ .. code-block:: python3
23
+
24
+ >>> r = Range(-2, 3)
25
+ >>> r.left, r.right, len(r)
26
+ (-2, 3, 6)
27
+
28
+ >>> s = Range(8, 'downto', 1)
29
+ >>> s.left, s.right, len(s)
30
+ (8, 1, 8)
31
+
32
+ :meth:`from_range` and :meth:`to_range` can be used to convert from and to :class:`range`.
33
+
34
+ .. code-block:: python3
35
+
36
+ >>> r = Range(-2, 3)
37
+ >>> r.to_range()
38
+ range(-2, 4)
39
+
40
+ :class:`Range` supports "null" ranges as seen in VHDL.
41
+ "null" ranges occur when a left bound cannot reach a right bound with the given direction.
42
+ They have a length of 0, but the :attr:`left`, :attr:`right`, and :attr:`direction` values remain as given.
43
+
44
+ .. code-block:: python3
45
+
46
+ >>> r = Range(1, 'to', 0) # no way to count from 1 'to' 0
47
+ >>> r.left, r.direction, r.right
48
+ (1, 'to', 0)
49
+ >>> len(r)
50
+ 0
51
+
52
+ .. note::
53
+ This is only possible when specifying the direction.
54
+
55
+ Ranges also support all the features of :class:`range` including, but not limited to:
56
+
57
+ - ``value in range`` to see if a value is in the range,
58
+ - ``range.index(value)`` to see what position in the range the value is,
59
+
60
+ The typical use case of this type is in conjunction with :class:`~cocotb.types.Array`.
61
+
62
+ Args:
63
+ left: leftmost bound of range
64
+ direction: ``'to'`` if values are ascending, ``'downto'`` if descending
65
+ right: rightmost bound of range (inclusive)
66
+ """
67
+
68
+ __slots__ = ("_range",)
69
+
70
+ @typing.overload
71
+ def __init__(self, left: int, direction: int) -> None:
72
+ pass # pragma: no cover
73
+
74
+ @typing.overload
75
+ def __init__(self, left: int, direction: str, right: int) -> None:
76
+ pass # pragma: no cover
77
+
78
+ @typing.overload
79
+ def __init__(self, left: int, *, right: int) -> None:
80
+ pass # pragma: no cover
81
+
82
+ def __init__(
83
+ self,
84
+ left: int,
85
+ direction: typing.Union[int, str, None] = None,
86
+ right: typing.Union[int, None] = None,
87
+ ) -> None:
88
+ start = left
89
+ stop: int
90
+ step: int
91
+ if isinstance(direction, int) and right is None:
92
+ step = _guess_step(left, direction)
93
+ stop = direction + step
94
+ elif direction is None and isinstance(right, int):
95
+ step = _guess_step(left, right)
96
+ stop = right + step
97
+ elif isinstance(direction, str) and isinstance(right, int):
98
+ step = _direction_to_step(direction)
99
+ stop = right + step
100
+ else:
101
+ raise TypeError("invalid arguments")
102
+ self._range = range(start, stop, step)
103
+
104
+ @classmethod
105
+ def from_range(cls, range: range) -> "Range":
106
+ """Convert :class:`range` to :class:`Range`."""
107
+ return cls(
108
+ left=range.start,
109
+ direction=_step_to_direction(range.step),
110
+ right=(range.stop - range.step),
111
+ )
112
+
113
+ def to_range(self) -> range:
114
+ """Convert :class:`Range` to :class:`range`."""
115
+ return self._range
116
+
117
+ @property
118
+ def left(self) -> int:
119
+ """Leftmost value in a range."""
120
+ return self._range.start
121
+
122
+ @property
123
+ def direction(self) -> str:
124
+ """``'to'`` if values are meant to be ascending, ``'downto'`` otherwise."""
125
+ return _step_to_direction(self._range.step)
126
+
127
+ @property
128
+ def right(self) -> int:
129
+ """Rightmost value in a range."""
130
+ return self._range.stop - self._range.step
131
+
132
+ def __len__(self) -> int:
133
+ return len(self._range)
134
+
135
+ @typing.overload
136
+ def __getitem__(self, item: int) -> int:
137
+ pass # pragma: no cover
138
+
139
+ @typing.overload
140
+ def __getitem__(self, item: slice) -> "Range":
141
+ pass # pragma: no cover
142
+
143
+ def __getitem__(self, item: typing.Union[int, slice]) -> typing.Union[int, "Range"]:
144
+ if isinstance(item, int):
145
+ return self._range[item]
146
+ elif isinstance(item, slice):
147
+ return type(self).from_range(self._range[item])
148
+ raise TypeError(
149
+ "indices must be integers or slices, not {}".format(type(item).__name__)
150
+ )
151
+
152
+ def __contains__(self, item: object) -> bool:
153
+ return item in self._range
154
+
155
+ def __iter__(self) -> typing.Iterator[int]:
156
+ return iter(self._range)
157
+
158
+ def __reversed__(self) -> typing.Iterator[int]:
159
+ return reversed(self._range)
160
+
161
+ def __eq__(self, other: object) -> bool:
162
+ if isinstance(other, type(self)):
163
+ return self._range == other._range
164
+ return NotImplemented # must not be in a type narrowing context to be ignored properly
165
+
166
+ def __hash__(self) -> int:
167
+ return hash(self._range)
168
+
169
+ def count(self, item: int) -> int:
170
+ return self._range.count(item)
171
+
172
+ def __repr__(self) -> str:
173
+ return "{}({!r}, {!r}, {!r})".format(
174
+ type(self).__qualname__, self.left, self.direction, self.right
175
+ )
176
+
177
+
178
+ def _guess_step(left: int, right: int) -> int:
179
+ if left <= right:
180
+ return 1
181
+ return -1
182
+
183
+
184
+ def _direction_to_step(direction: str) -> int:
185
+ direction = direction.lower()
186
+ if direction == "to":
187
+ return 1
188
+ elif direction == "downto":
189
+ return -1
190
+ raise ValueError("direction must be 'to' or 'downto'")
191
+
192
+
193
+ def _step_to_direction(step: int) -> str:
194
+ if step == 1:
195
+ return "to"
196
+ elif step == -1:
197
+ return "downto"
198
+ raise ValueError("step must be 1 or -1")