cocotb 1.9.2__cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.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-x86_64-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 +6 -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
cocotb/task.py ADDED
@@ -0,0 +1,325 @@
1
+ # Copyright cocotb contributors
2
+ # Licensed under the Revised BSD License, see LICENSE for details.
3
+ # SPDX-License-Identifier: BSD-3-Clause
4
+ import collections.abc
5
+ import inspect
6
+ import os
7
+ import typing
8
+ import warnings
9
+ from asyncio import CancelledError, InvalidStateError
10
+
11
+ import cocotb
12
+ import cocotb.triggers
13
+ from cocotb import outcomes
14
+ from cocotb.log import SimLog
15
+ from cocotb.result import ReturnValue
16
+ from cocotb.utils import extract_coro_stack, lazy_property, remove_traceback_frames
17
+
18
+ T = typing.TypeVar("T")
19
+ Self = typing.TypeVar("Self")
20
+
21
+ # Sadly the Python standard logging module is very slow so it's better not to
22
+ # make any calls by testing a boolean flag first
23
+ _debug = "COCOTB_SCHEDULER_DEBUG" in os.environ
24
+
25
+
26
+ class Task(typing.Coroutine[typing.Any, typing.Any, T]):
27
+ """Concurrently executing task.
28
+
29
+ This class is not intended for users to directly instantiate.
30
+ Use :func:`cocotb.create_task` to create a Task object,
31
+ or use :func:`cocotb.start_soon` or :func:`cocotb.start` to
32
+ create a Task and schedule it to run.
33
+
34
+ .. versionchanged:: 1.8.0
35
+ Moved to the ``cocotb.task`` module.
36
+ """
37
+
38
+ _name: str = "Task" # class name of schedulable task
39
+ _id_count = 0 # used by the scheduler for debug
40
+
41
+ def __init__(self, inst):
42
+
43
+ if isinstance(inst, collections.abc.Coroutine):
44
+ self._natively_awaitable = True
45
+ elif inspect.isgenerator(inst):
46
+ self._natively_awaitable = False
47
+ elif inspect.iscoroutinefunction(inst):
48
+ raise TypeError(
49
+ "Coroutine function {} should be called prior to being "
50
+ "scheduled.".format(inst)
51
+ )
52
+ elif inspect.isasyncgen(inst):
53
+ raise TypeError(
54
+ "{} is an async generator, not a coroutine. "
55
+ "You likely used the yield keyword instead of await.".format(
56
+ inst.__qualname__
57
+ )
58
+ )
59
+ else:
60
+ raise TypeError(
61
+ f"{inst} isn't a valid coroutine! Did you forget to use the yield keyword?"
62
+ )
63
+ self._coro = inst
64
+ self._started = False
65
+ self._outcome: outcomes.Outcome = None
66
+ self._trigger: typing.Optional[cocotb.triggers.Trigger] = None
67
+ self._cancelled: typing.Optional[CancelledError] = None
68
+
69
+ self._task_id = self._id_count
70
+ type(self)._id_count += 1
71
+ self.__name__ = f"{type(self)._name} {self._task_id}"
72
+ self.__qualname__ = self.__name__
73
+
74
+ @lazy_property
75
+ def log(self) -> SimLog:
76
+ # Creating a logger is expensive, only do it if we actually plan to
77
+ # log anything
78
+ return SimLog(f"cocotb.{self.__qualname__}.{self._coro.__qualname__}")
79
+
80
+ @property
81
+ def retval(self) -> T:
82
+ """Return the result of the Task.
83
+
84
+ If the Task ran to completion, the result is returned.
85
+ If the Task failed with an exception, the exception is re-raised.
86
+ If the Task is not yet complete, a :exc:`RuntimeError` is raised.
87
+
88
+ .. deprecated:: 1.7.0
89
+ """
90
+ warnings.warn(
91
+ "Deprecated in favor of the result() method. "
92
+ "Replace `task.retval` with `task.result()`.",
93
+ DeprecationWarning,
94
+ stacklevel=2,
95
+ )
96
+ if self._outcome is None:
97
+ raise RuntimeError("coroutine is not complete")
98
+ return self._outcome.get()
99
+
100
+ @property
101
+ def _finished(self) -> bool:
102
+ """``True`` if the Task is finished executing.
103
+
104
+ .. deprecated:: 1.7.0
105
+ """
106
+ warnings.warn(
107
+ "Deprecated in favor of the done() method. "
108
+ "Replace `task._finished` with `task.done()`.",
109
+ DeprecationWarning,
110
+ stacklevel=2,
111
+ )
112
+ return self._outcome is not None
113
+
114
+ def __iter__(self: Self) -> Self:
115
+ # for use in "yield from" statements
116
+ return self
117
+
118
+ def __str__(self) -> str:
119
+ return f"<{self.__name__}>"
120
+
121
+ def _get_coro_stack(self) -> typing.Any:
122
+ """Get the coroutine callstack of this Task."""
123
+ coro_stack = extract_coro_stack(self._coro)
124
+
125
+ # Remove Trigger.__await__() from the stack, as it's not really useful
126
+ if self._natively_awaitable and len(coro_stack):
127
+ if coro_stack[-1].name == "__await__":
128
+ coro_stack.pop()
129
+
130
+ return coro_stack
131
+
132
+ def __repr__(self) -> str:
133
+ coro_stack = self._get_coro_stack()
134
+
135
+ if cocotb.scheduler._current_task is self:
136
+ fmt = "<{name} running coro={coro}()>"
137
+ elif self.done():
138
+ fmt = "<{name} finished coro={coro}() outcome={outcome}>"
139
+ elif self._trigger is not None:
140
+ fmt = "<{name} pending coro={coro}() trigger={trigger}>"
141
+ elif not self._started:
142
+ fmt = "<{name} created coro={coro}()>"
143
+ else:
144
+ fmt = "<{name} adding coro={coro}()>"
145
+
146
+ try:
147
+ coro_name = coro_stack[-1].name
148
+ # coro_stack may be empty if:
149
+ # - exhausted generator
150
+ # - finished coroutine
151
+ except IndexError:
152
+ coro_name = self._coro.__name__
153
+
154
+ repr_string = fmt.format(
155
+ name=self.__name__,
156
+ coro=coro_name,
157
+ trigger=self._trigger,
158
+ outcome=self._outcome,
159
+ )
160
+ return repr_string
161
+
162
+ def _advance(self, outcome: outcomes.Outcome) -> typing.Any:
163
+ """Advance to the next yield in this coroutine.
164
+
165
+ Args:
166
+ outcome: The :any:`outcomes.Outcome` object to resume with.
167
+
168
+ Returns:
169
+ The object yielded from the coroutine or None if coroutine finished
170
+
171
+ """
172
+ try:
173
+ self._started = True
174
+ return outcome.send(self._coro)
175
+ except ReturnValue as e:
176
+ self._outcome = outcomes.Value(e.retval)
177
+ except StopIteration as e:
178
+ self._outcome = outcomes.Value(e.value)
179
+ except BaseException as e:
180
+ self._outcome = outcomes.Error(
181
+ remove_traceback_frames(e, ["_advance", "send"])
182
+ )
183
+
184
+ def send(self, value: typing.Any) -> typing.Any:
185
+ return self._coro.send(value)
186
+
187
+ def throw(self, exc: BaseException) -> typing.Any:
188
+ return self._coro.throw(exc)
189
+
190
+ def close(self) -> None:
191
+ return self._coro.close()
192
+
193
+ def kill(self) -> None:
194
+ """Kill a coroutine."""
195
+ if self._outcome is not None:
196
+ # already finished, nothing to kill
197
+ return
198
+
199
+ if _debug:
200
+ self.log.debug("kill() called on coroutine")
201
+ # todo: probably better to throw an exception for anyone waiting on the coroutine
202
+ self._outcome = outcomes.Value(None)
203
+ cocotb.scheduler._unschedule(self)
204
+
205
+ def join(self) -> "cocotb.triggers.Join":
206
+ """Return a trigger that will fire when the wrapped coroutine exits."""
207
+ return cocotb.triggers.Join(self)
208
+
209
+ def has_started(self) -> bool:
210
+ """Return ``True`` if the Task has started executing."""
211
+ return self._started
212
+
213
+ def cancel(self, msg: typing.Optional[str] = None) -> None:
214
+ """Cancel a Task's further execution.
215
+
216
+ When a Task is cancelled, a :exc:`asyncio.CancelledError` is thrown into the Task.
217
+ """
218
+ self._cancelled = CancelledError(msg)
219
+ warnings.warn(
220
+ "Calling this method will cause a CancelledError to be thrown in the "
221
+ "Task sometime in the future.",
222
+ FutureWarning,
223
+ stacklevel=2,
224
+ )
225
+ self.kill()
226
+
227
+ def cancelled(self) -> bool:
228
+ """Return ``True`` if the Task was cancelled."""
229
+ return self._cancelled is not None
230
+
231
+ def done(self) -> bool:
232
+ """Return ``True`` if the Task has finished executing."""
233
+ return self._outcome is not None or self.cancelled()
234
+
235
+ def result(self) -> T:
236
+ """Return the result of the Task.
237
+
238
+ If the Task ran to completion, the result is returned.
239
+ If the Task failed with an exception, the exception is re-raised.
240
+ If the Task was cancelled, the CancelledError is re-raised.
241
+ If the coroutine is not yet complete, a :exc:`asyncio.InvalidStateError` is raised.
242
+ """
243
+ if not self.done():
244
+ raise InvalidStateError("result is not yet available")
245
+ elif self.cancelled():
246
+ raise self._cancelled
247
+ else:
248
+ return self._outcome.get()
249
+
250
+ def exception(self) -> typing.Optional[BaseException]:
251
+ """Return the exception of the Task.
252
+
253
+ If the Task ran to completion, ``None`` is returned.
254
+ If the Task failed with an exception, the exception is returned.
255
+ If the Task was cancelled, the CancelledError is re-raised.
256
+ If the coroutine is not yet complete, a :exc:`asyncio.InvalidStateError` is raised.
257
+ """
258
+ if not self.done():
259
+ raise InvalidStateError("result is not yet available")
260
+ elif self.cancelled():
261
+ raise self._cancelled
262
+ elif isinstance(self._outcome, outcomes.Error):
263
+ return self._outcome.error
264
+ else:
265
+ return None
266
+
267
+ def __bool__(self) -> bool:
268
+ """``True`` if Task is not done.
269
+
270
+ .. deprecated:: 1.7.0
271
+ """
272
+ warnings.warn(
273
+ "Deprecated in favor of the done() method. "
274
+ "Replace with `not task.done()`.",
275
+ DeprecationWarning,
276
+ stacklevel=2,
277
+ )
278
+ return not self.done()
279
+
280
+ def __await__(self) -> typing.Generator[typing.Any, typing.Any, T]:
281
+ # It's tempting to use `return (yield from self._coro)` here,
282
+ # which bypasses the scheduler. Unfortunately, this means that
283
+ # we can't keep track of the result or state of the coroutine,
284
+ # things which we expose in our public API. If you want the
285
+ # efficiency of bypassing the scheduler, remove the `@coroutine`
286
+ # decorator from your `async` functions.
287
+
288
+ # Hand the coroutine back to the scheduler trampoline.
289
+ return (yield self)
290
+
291
+
292
+ class _RunningCoroutine(Task[T]):
293
+ """
294
+ The result of calling a :any:`cocotb.coroutine` decorated coroutine.
295
+
296
+ All this class does is provide some extra attributes.
297
+
298
+ .. versionchanged:: 1.8.0
299
+ Moved to the ``cocotb.task`` module.
300
+ """
301
+
302
+ def __init__(self, inst, parent):
303
+ super().__init__(inst)
304
+ self._parent = parent
305
+ self.__doc__ = parent._func.__doc__
306
+ self.module = parent._func.__module__
307
+ self.funcname = parent._func.__name__
308
+
309
+
310
+ class _RunningTest(_RunningCoroutine[T]):
311
+ """
312
+ The result of calling a :class:`cocotb.test` decorated object.
313
+
314
+ All this class does is change ``__name__`` to show "Test" instead of "Task".
315
+
316
+ .. versionchanged:: 1.8.0
317
+ Moved to the ``cocotb.task`` module.
318
+ """
319
+
320
+ _name: str = "Test"
321
+
322
+ def __init__(self, inst, parent):
323
+ super().__init__(inst, parent)
324
+ self.__name__ = f"{type(self)._name} {self.funcname}"
325
+ self.__qualname__ = self.__name__