cocotb 1.7.2__cp36-cp36m-win_amd64.whl → 1.8.0rc1__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.
- cocotb/__init__.py +7 -18
- cocotb/_sim_versions.py +16 -1
- cocotb/_version.py +1 -1
- cocotb/clock.py +8 -3
- cocotb/decorators.py +40 -318
- cocotb/ipython_support.py +3 -1
- cocotb/libs/cocotb.dll +0 -0
- cocotb/libs/cocotb.exp +0 -0
- cocotb/libs/cocotb.lib +0 -0
- cocotb/libs/cocotbfli_modelsim.dll +0 -0
- cocotb/libs/cocotbfli_modelsim.exp +0 -0
- cocotb/libs/cocotbfli_modelsim.lib +0 -0
- cocotb/libs/cocotbutils.dll +0 -0
- cocotb/libs/cocotbutils.exp +0 -0
- cocotb/libs/cocotbutils.lib +0 -0
- cocotb/libs/cocotbvhpi_aldec.dll +0 -0
- cocotb/libs/cocotbvhpi_aldec.exp +0 -0
- cocotb/libs/cocotbvhpi_aldec.lib +0 -0
- cocotb/libs/cocotbvhpi_modelsim.dll +0 -0
- cocotb/libs/cocotbvhpi_modelsim.exp +0 -0
- cocotb/libs/cocotbvhpi_modelsim.lib +0 -0
- cocotb/libs/cocotbvpi_aldec.dll +0 -0
- cocotb/libs/cocotbvpi_aldec.exp +0 -0
- cocotb/libs/cocotbvpi_aldec.lib +0 -0
- cocotb/libs/cocotbvpi_ghdl.dll +0 -0
- cocotb/libs/cocotbvpi_ghdl.exp +0 -0
- cocotb/libs/cocotbvpi_ghdl.lib +0 -0
- cocotb/libs/cocotbvpi_icarus.exp +0 -0
- cocotb/libs/cocotbvpi_icarus.lib +0 -0
- cocotb/libs/cocotbvpi_icarus.vpl +0 -0
- cocotb/libs/cocotbvpi_modelsim.dll +0 -0
- cocotb/libs/cocotbvpi_modelsim.exp +0 -0
- cocotb/libs/cocotbvpi_modelsim.lib +0 -0
- cocotb/libs/embed.dll +0 -0
- cocotb/libs/embed.exp +0 -0
- cocotb/libs/embed.lib +0 -0
- cocotb/libs/gpi.dll +0 -0
- cocotb/libs/gpi.exp +0 -0
- cocotb/libs/gpi.lib +0 -0
- cocotb/libs/gpilog.dll +0 -0
- cocotb/libs/gpilog.exp +0 -0
- cocotb/libs/gpilog.lib +0 -0
- cocotb/libs/pygpilog.dll +0 -0
- cocotb/libs/pygpilog.exp +0 -0
- cocotb/libs/pygpilog.lib +0 -0
- cocotb/regression.py +32 -14
- cocotb/runner.py +538 -453
- cocotb/scheduler.py +35 -18
- cocotb/share/def/aldec.exp +0 -0
- cocotb/share/def/aldec.lib +0 -0
- cocotb/share/def/ghdl.exp +0 -0
- cocotb/share/def/ghdl.lib +0 -0
- cocotb/share/def/icarus.exp +0 -0
- cocotb/share/def/icarus.lib +0 -0
- cocotb/share/def/modelsim.def +2 -0
- cocotb/share/def/modelsim.exp +0 -0
- cocotb/share/def/modelsim.lib +0 -0
- cocotb/share/include/embed.h +1 -2
- cocotb/share/include/gpi.h +10 -15
- cocotb/share/include/vpi_user_ext.h +3 -0
- cocotb/share/lib/verilator/verilator.cpp +8 -4
- cocotb/share/makefiles/Makefile.inc +16 -4
- cocotb/share/makefiles/Makefile.sim +2 -2
- cocotb/share/makefiles/simulators/Makefile.icarus +19 -0
- cocotb/share/makefiles/simulators/Makefile.ius +12 -1
- cocotb/share/makefiles/simulators/Makefile.questa +2 -1
- cocotb/share/makefiles/simulators/Makefile.riviera +4 -0
- cocotb/share/makefiles/simulators/Makefile.vcs +4 -0
- cocotb/share/makefiles/simulators/Makefile.verilator +5 -1
- cocotb/share/makefiles/simulators/Makefile.xcelium +5 -1
- cocotb/simulator.cp36-win_amd64.exp +0 -0
- cocotb/simulator.cp36-win_amd64.lib +0 -0
- cocotb/simulator.cp36-win_amd64.pyd +0 -0
- cocotb/task.py +325 -0
- cocotb/triggers.py +23 -7
- cocotb/types/logic_array.py +34 -3
- {cocotb-1.7.2.dist-info → cocotb-1.8.0rc1.dist-info}/METADATA +24 -9
- cocotb-1.8.0rc1.dist-info/RECORD +120 -0
- cocotb-1.7.2.dist-info/RECORD +0 -119
- {cocotb-1.7.2.dist-info → cocotb-1.8.0rc1.dist-info}/LICENSE +0 -0
- {cocotb-1.7.2.dist-info → cocotb-1.8.0rc1.dist-info}/WHEEL +0 -0
- {cocotb-1.7.2.dist-info → cocotb-1.8.0rc1.dist-info}/entry_points.txt +0 -0
- {cocotb-1.7.2.dist-info → cocotb-1.8.0rc1.dist-info}/top_level.txt +0 -0
cocotb/__init__.py
CHANGED
|
@@ -45,12 +45,12 @@ from cocotb._deprecation import deprecated
|
|
|
45
45
|
from cocotb.log import default_config
|
|
46
46
|
from cocotb.regression import RegressionManager
|
|
47
47
|
from cocotb.scheduler import Scheduler
|
|
48
|
+
from cocotb.task import Task
|
|
48
49
|
|
|
49
50
|
from ._version import __version__
|
|
50
51
|
|
|
51
52
|
# Things we want in the cocotb namespace
|
|
52
53
|
from cocotb.decorators import ( # isort: skip # noqa: F401
|
|
53
|
-
Task,
|
|
54
54
|
coroutine,
|
|
55
55
|
external,
|
|
56
56
|
function,
|
|
@@ -322,26 +322,15 @@ def _initialise_testbench_(argv_):
|
|
|
322
322
|
regression_manager._execute()
|
|
323
323
|
|
|
324
324
|
|
|
325
|
-
def _sim_event(
|
|
325
|
+
def _sim_event(message):
|
|
326
326
|
"""Function that can be called externally to signal an event."""
|
|
327
|
-
# SIM_INFO = 0
|
|
328
|
-
SIM_TEST_FAIL = 1
|
|
329
|
-
SIM_FAIL = 2
|
|
330
327
|
from cocotb.result import SimFailure
|
|
331
328
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
elif level is SIM_FAIL:
|
|
338
|
-
# We simply return here as the simulator will exit
|
|
339
|
-
# so no cleanup is needed
|
|
340
|
-
msg = f"Failing test at simulator request before test run completion: {message}"
|
|
341
|
-
scheduler.log.error(msg)
|
|
342
|
-
scheduler._finish_scheduler(SimFailure(msg))
|
|
343
|
-
else:
|
|
344
|
-
scheduler.log.error("Unsupported sim event")
|
|
329
|
+
# We simply return here as the simulator will exit
|
|
330
|
+
# so no cleanup is needed
|
|
331
|
+
msg = f"Failing test at simulator request before test run completion: {message}"
|
|
332
|
+
scheduler.log.error(msg)
|
|
333
|
+
scheduler._finish_scheduler(SimFailure(msg))
|
|
345
334
|
|
|
346
335
|
|
|
347
336
|
@deprecated("This function is now private")
|
cocotb/_sim_versions.py
CHANGED
|
@@ -68,9 +68,24 @@ class QuestaVersion(LooseVersion):
|
|
|
68
68
|
True
|
|
69
69
|
>>> QuestaVersion("2020.1 2020.01") > QuestaVersion("10.7c 2018.08")
|
|
70
70
|
True
|
|
71
|
+
>>> QuestaVersion("2020.1 2020.01") == QuestaVersion("2020.1")
|
|
72
|
+
True
|
|
73
|
+
>>> QuestaVersion("2023.1_2 2023.03") > QuestaVersion("2023.1_1")
|
|
74
|
+
True
|
|
71
75
|
"""
|
|
72
76
|
|
|
73
|
-
|
|
77
|
+
def parse(self, vstring):
|
|
78
|
+
# A Questa version string, as returned by the simulator, consists of two
|
|
79
|
+
# space-separated parts. The first part is the actual version number,
|
|
80
|
+
# the second part seems to be the year and month of the initial release.
|
|
81
|
+
# We only need the first part, which is also used in public
|
|
82
|
+
# communication by Siemens.
|
|
83
|
+
try:
|
|
84
|
+
first_component = vstring.split(" ", 1)[0]
|
|
85
|
+
except IndexError:
|
|
86
|
+
first_component = vstring
|
|
87
|
+
|
|
88
|
+
super().parse(first_component)
|
|
74
89
|
|
|
75
90
|
|
|
76
91
|
class RivieraVersion(LooseVersion):
|
cocotb/_version.py
CHANGED
cocotb/clock.py
CHANGED
|
@@ -29,6 +29,9 @@
|
|
|
29
29
|
|
|
30
30
|
import itertools
|
|
31
31
|
import warnings
|
|
32
|
+
from decimal import Decimal
|
|
33
|
+
from numbers import Real
|
|
34
|
+
from typing import Union
|
|
32
35
|
|
|
33
36
|
from cocotb.log import SimLog
|
|
34
37
|
from cocotb.triggers import Timer
|
|
@@ -114,7 +117,9 @@ class Clock(BaseClock):
|
|
|
114
117
|
Using ``None`` as the *units* argument is deprecated, use ``'step'`` instead.
|
|
115
118
|
"""
|
|
116
119
|
|
|
117
|
-
def __init__(
|
|
120
|
+
def __init__(
|
|
121
|
+
self, signal, period: Union[float, Real, Decimal], units: str = "step"
|
|
122
|
+
):
|
|
118
123
|
BaseClock.__init__(self, signal)
|
|
119
124
|
if units is None:
|
|
120
125
|
warnings.warn(
|
|
@@ -124,8 +129,8 @@ class Clock(BaseClock):
|
|
|
124
129
|
)
|
|
125
130
|
units = "step" # don't propagate deprecated value
|
|
126
131
|
self.period = get_sim_steps(period, units)
|
|
127
|
-
self.half_period = get_sim_steps(period / 2
|
|
128
|
-
self.frequency = 1
|
|
132
|
+
self.half_period = get_sim_steps(period / 2, units)
|
|
133
|
+
self.frequency = 1 / get_time_from_sim_steps(self.period, units="us")
|
|
129
134
|
self.hdl = None
|
|
130
135
|
self.signal = signal
|
|
131
136
|
self.coro = None
|
cocotb/decorators.py
CHANGED
|
@@ -25,31 +25,17 @@
|
|
|
25
25
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
26
26
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
27
|
|
|
28
|
-
import collections.abc
|
|
29
28
|
import functools
|
|
30
|
-
import inspect
|
|
31
|
-
import os
|
|
32
29
|
import sys
|
|
33
30
|
import typing
|
|
34
31
|
import warnings
|
|
35
|
-
from asyncio import CancelledError, InvalidStateError
|
|
36
32
|
|
|
37
33
|
import cocotb
|
|
38
34
|
import cocotb.triggers
|
|
39
|
-
from cocotb import outcomes
|
|
40
35
|
from cocotb.log import SimLog
|
|
41
|
-
from cocotb.
|
|
42
|
-
from cocotb.
|
|
43
|
-
|
|
44
|
-
T = typing.TypeVar("T")
|
|
45
|
-
Self = typing.TypeVar("Self")
|
|
46
|
-
|
|
47
|
-
# Sadly the Python standard logging module is very slow so it's better not to
|
|
48
|
-
# make any calls by testing a boolean flag first
|
|
49
|
-
if "COCOTB_SCHEDULER_DEBUG" in os.environ:
|
|
50
|
-
_debug = True
|
|
51
|
-
else:
|
|
52
|
-
_debug = False
|
|
36
|
+
from cocotb.task import Task as _Task # noqa: F401
|
|
37
|
+
from cocotb.task import _RunningCoroutine, _RunningTest
|
|
38
|
+
from cocotb.utils import lazy_property
|
|
53
39
|
|
|
54
40
|
|
|
55
41
|
def public(f):
|
|
@@ -69,308 +55,12 @@ def public(f):
|
|
|
69
55
|
public(public) # Emulate decorating ourself
|
|
70
56
|
|
|
71
57
|
|
|
72
|
-
class Task(typing.Coroutine[typing.Any, typing.Any, T]):
|
|
73
|
-
"""Concurrently executing task.
|
|
74
|
-
|
|
75
|
-
This class is not intended for users to directly instantiate.
|
|
76
|
-
Use :func:`cocotb.create_task` to create a Task object,
|
|
77
|
-
or use :func:`cocotb.start_soon` or :func:`cocotb.start` to
|
|
78
|
-
create a Task and schedule it to run.
|
|
79
|
-
"""
|
|
80
|
-
|
|
81
|
-
_name: str = "Task" # class name of schedulable task
|
|
82
|
-
_id_count = 0 # used by the scheduler for debug
|
|
83
|
-
|
|
84
|
-
def __init__(self, inst):
|
|
85
|
-
|
|
86
|
-
if isinstance(inst, collections.abc.Coroutine):
|
|
87
|
-
self._natively_awaitable = True
|
|
88
|
-
elif inspect.isgenerator(inst):
|
|
89
|
-
self._natively_awaitable = False
|
|
90
|
-
elif inspect.iscoroutinefunction(inst):
|
|
91
|
-
raise TypeError(
|
|
92
|
-
"Coroutine function {} should be called prior to being "
|
|
93
|
-
"scheduled.".format(inst)
|
|
94
|
-
)
|
|
95
|
-
elif inspect.isasyncgen(inst):
|
|
96
|
-
raise TypeError(
|
|
97
|
-
"{} is an async generator, not a coroutine. "
|
|
98
|
-
"You likely used the yield keyword instead of await.".format(
|
|
99
|
-
inst.__qualname__
|
|
100
|
-
)
|
|
101
|
-
)
|
|
102
|
-
else:
|
|
103
|
-
raise TypeError(
|
|
104
|
-
f"{inst} isn't a valid coroutine! Did you forget to use the yield keyword?"
|
|
105
|
-
)
|
|
106
|
-
self._coro = inst
|
|
107
|
-
self._started = False
|
|
108
|
-
self._outcome: outcomes.Outcome = None
|
|
109
|
-
self._trigger: typing.Optional[cocotb.triggers.Trigger] = None
|
|
110
|
-
self._cancelled: typing.Optional[CancelledError] = None
|
|
111
|
-
|
|
112
|
-
self._task_id = self._id_count
|
|
113
|
-
type(self)._id_count += 1
|
|
114
|
-
self.__name__ = f"{type(self)._name} {self._task_id}"
|
|
115
|
-
self.__qualname__ = self.__name__
|
|
116
|
-
|
|
117
|
-
@lazy_property
|
|
118
|
-
def log(self) -> SimLog:
|
|
119
|
-
# Creating a logger is expensive, only do it if we actually plan to
|
|
120
|
-
# log anything
|
|
121
|
-
return SimLog(f"cocotb.{self.__qualname__}.{self._coro.__qualname__}")
|
|
122
|
-
|
|
123
|
-
@property
|
|
124
|
-
def retval(self) -> T:
|
|
125
|
-
"""Return the result of the Task.
|
|
126
|
-
|
|
127
|
-
If the Task ran to completion, the result is returned.
|
|
128
|
-
If the Task failed with an exception, the exception is re-raised.
|
|
129
|
-
If the Task is not yet complete, a :exc:`RuntimeError` is raised.
|
|
130
|
-
|
|
131
|
-
.. deprecated:: 1.7.0
|
|
132
|
-
"""
|
|
133
|
-
warnings.warn(
|
|
134
|
-
"Deprecated in favor of the result() method. "
|
|
135
|
-
"Replace `task.retval` with `task.result()`.",
|
|
136
|
-
DeprecationWarning,
|
|
137
|
-
stacklevel=2,
|
|
138
|
-
)
|
|
139
|
-
if self._outcome is None:
|
|
140
|
-
raise RuntimeError("coroutine is not complete")
|
|
141
|
-
return self._outcome.get()
|
|
142
|
-
|
|
143
|
-
@property
|
|
144
|
-
def _finished(self) -> bool:
|
|
145
|
-
"""``True`` if the Task is finished executing.
|
|
146
|
-
|
|
147
|
-
.. deprecated:: 1.7.0
|
|
148
|
-
"""
|
|
149
|
-
warnings.warn(
|
|
150
|
-
"Deprecated in favor of the done() method. "
|
|
151
|
-
"Replace `task._finished` with `task.done()`.",
|
|
152
|
-
DeprecationWarning,
|
|
153
|
-
stacklevel=2,
|
|
154
|
-
)
|
|
155
|
-
return self._outcome is not None
|
|
156
|
-
|
|
157
|
-
def __iter__(self: Self) -> Self:
|
|
158
|
-
# for use in "yield from" statements
|
|
159
|
-
return self
|
|
160
|
-
|
|
161
|
-
def __str__(self) -> str:
|
|
162
|
-
return f"<{self.__name__}>"
|
|
163
|
-
|
|
164
|
-
def _get_coro_stack(self) -> typing.Any:
|
|
165
|
-
"""Get the coroutine callstack of this Task."""
|
|
166
|
-
coro_stack = extract_coro_stack(self._coro)
|
|
167
|
-
|
|
168
|
-
# Remove Trigger.__await__() from the stack, as it's not really useful
|
|
169
|
-
if self._natively_awaitable and len(coro_stack):
|
|
170
|
-
if coro_stack[-1].name == "__await__":
|
|
171
|
-
coro_stack.pop()
|
|
172
|
-
|
|
173
|
-
return coro_stack
|
|
174
|
-
|
|
175
|
-
def __repr__(self) -> str:
|
|
176
|
-
coro_stack = self._get_coro_stack()
|
|
177
|
-
|
|
178
|
-
if cocotb.scheduler._current_task is self:
|
|
179
|
-
fmt = "<{name} running coro={coro}()>"
|
|
180
|
-
elif self.done():
|
|
181
|
-
fmt = "<{name} finished coro={coro}() outcome={outcome}>"
|
|
182
|
-
elif self._trigger is not None:
|
|
183
|
-
fmt = "<{name} pending coro={coro}() trigger={trigger}>"
|
|
184
|
-
elif not self._started:
|
|
185
|
-
fmt = "<{name} created coro={coro}()>"
|
|
186
|
-
else:
|
|
187
|
-
fmt = "<{name} adding coro={coro}()>"
|
|
188
|
-
|
|
189
|
-
try:
|
|
190
|
-
coro_name = coro_stack[-1].name
|
|
191
|
-
# coro_stack may be empty if:
|
|
192
|
-
# - exhausted generator
|
|
193
|
-
# - finished coroutine
|
|
194
|
-
except IndexError:
|
|
195
|
-
coro_name = self._coro.__name__
|
|
196
|
-
|
|
197
|
-
repr_string = fmt.format(
|
|
198
|
-
name=self.__name__,
|
|
199
|
-
coro=coro_name,
|
|
200
|
-
trigger=self._trigger,
|
|
201
|
-
outcome=self._outcome,
|
|
202
|
-
)
|
|
203
|
-
return repr_string
|
|
204
|
-
|
|
205
|
-
def _advance(self, outcome: outcomes.Outcome) -> typing.Any:
|
|
206
|
-
"""Advance to the next yield in this coroutine.
|
|
207
|
-
|
|
208
|
-
Args:
|
|
209
|
-
outcome: The :any:`outcomes.Outcome` object to resume with.
|
|
210
|
-
|
|
211
|
-
Returns:
|
|
212
|
-
The object yielded from the coroutine or None if coroutine finished
|
|
213
|
-
|
|
214
|
-
"""
|
|
215
|
-
try:
|
|
216
|
-
self._started = True
|
|
217
|
-
return outcome.send(self._coro)
|
|
218
|
-
except ReturnValue as e:
|
|
219
|
-
self._outcome = outcomes.Value(e.retval)
|
|
220
|
-
except StopIteration as e:
|
|
221
|
-
self._outcome = outcomes.Value(e.value)
|
|
222
|
-
except BaseException as e:
|
|
223
|
-
self._outcome = outcomes.Error(
|
|
224
|
-
remove_traceback_frames(e, ["_advance", "send"])
|
|
225
|
-
)
|
|
226
|
-
|
|
227
|
-
def send(self, value: typing.Any) -> typing.Any:
|
|
228
|
-
return self._coro.send(value)
|
|
229
|
-
|
|
230
|
-
def throw(self, exc: BaseException) -> typing.Any:
|
|
231
|
-
return self._coro.throw(exc)
|
|
232
|
-
|
|
233
|
-
def close(self) -> None:
|
|
234
|
-
return self._coro.close()
|
|
235
|
-
|
|
236
|
-
def kill(self) -> None:
|
|
237
|
-
"""Kill a coroutine."""
|
|
238
|
-
if self._outcome is not None:
|
|
239
|
-
# already finished, nothing to kill
|
|
240
|
-
return
|
|
241
|
-
|
|
242
|
-
if _debug:
|
|
243
|
-
self.log.debug("kill() called on coroutine")
|
|
244
|
-
# todo: probably better to throw an exception for anyone waiting on the coroutine
|
|
245
|
-
self._outcome = outcomes.Value(None)
|
|
246
|
-
cocotb.scheduler._unschedule(self)
|
|
247
|
-
|
|
248
|
-
def join(self) -> cocotb.triggers.Join:
|
|
249
|
-
"""Return a trigger that will fire when the wrapped coroutine exits."""
|
|
250
|
-
return cocotb.triggers.Join(self)
|
|
251
|
-
|
|
252
|
-
def has_started(self) -> bool:
|
|
253
|
-
"""Return ``True`` if the Task has started executing."""
|
|
254
|
-
return self._started
|
|
255
|
-
|
|
256
|
-
def cancel(self, msg: typing.Optional[str] = None) -> None:
|
|
257
|
-
"""Cancel a Task's further execution.
|
|
258
|
-
|
|
259
|
-
When a Task is cancelled, a :exc:`asyncio.CancelledError` is thrown into the Task.
|
|
260
|
-
"""
|
|
261
|
-
self._cancelled = CancelledError(msg)
|
|
262
|
-
warnings.warn(
|
|
263
|
-
"Calling this method will cause a CancelledError to be thrown in the "
|
|
264
|
-
"Task sometime in the future.",
|
|
265
|
-
FutureWarning,
|
|
266
|
-
stacklevel=2,
|
|
267
|
-
)
|
|
268
|
-
self.kill()
|
|
269
|
-
|
|
270
|
-
def cancelled(self) -> bool:
|
|
271
|
-
"""Return ``True`` if the Task was cancelled."""
|
|
272
|
-
return self._cancelled is not None
|
|
273
|
-
|
|
274
|
-
def done(self) -> bool:
|
|
275
|
-
"""Return ``True`` if the Task has finished executing."""
|
|
276
|
-
return self._outcome is not None or self.cancelled()
|
|
277
|
-
|
|
278
|
-
def result(self) -> T:
|
|
279
|
-
"""Return the result of the Task.
|
|
280
|
-
|
|
281
|
-
If the Task ran to completion, the result is returned.
|
|
282
|
-
If the Task failed with an exception, the exception is re-raised.
|
|
283
|
-
If the Task was cancelled, the CancelledError is re-raised.
|
|
284
|
-
If the coroutine is not yet complete, a :exc:`asyncio.InvalidStateError` is raised.
|
|
285
|
-
"""
|
|
286
|
-
if not self.done():
|
|
287
|
-
raise InvalidStateError("result is not yet available")
|
|
288
|
-
elif self.cancelled():
|
|
289
|
-
raise self._cancelled
|
|
290
|
-
else:
|
|
291
|
-
return self._outcome.get()
|
|
292
|
-
|
|
293
|
-
def exception(self) -> typing.Optional[BaseException]:
|
|
294
|
-
"""Return the exception of the Task.
|
|
295
|
-
|
|
296
|
-
If the Task ran to completion, ``None`` is returned.
|
|
297
|
-
If the Task failed with an exception, the exception is returned.
|
|
298
|
-
If the Task was cancelled, the CancelledError is re-raised.
|
|
299
|
-
If the coroutine is not yet complete, a :exc:`asyncio.InvalidStateError` is raised.
|
|
300
|
-
"""
|
|
301
|
-
if not self.done():
|
|
302
|
-
raise InvalidStateError("result is not yet available")
|
|
303
|
-
elif self.cancelled():
|
|
304
|
-
raise self._cancelled
|
|
305
|
-
elif isinstance(self._outcome, outcomes.Error):
|
|
306
|
-
return self._outcome.error
|
|
307
|
-
else:
|
|
308
|
-
return None
|
|
309
|
-
|
|
310
|
-
def __bool__(self) -> bool:
|
|
311
|
-
"""``True`` if Task is not done.
|
|
312
|
-
|
|
313
|
-
.. deprecated:: 1.7.0
|
|
314
|
-
"""
|
|
315
|
-
warnings.warn(
|
|
316
|
-
"Deprecated in favor of the done() method. "
|
|
317
|
-
"Replace with `not task.done()`.",
|
|
318
|
-
DeprecationWarning,
|
|
319
|
-
stacklevel=2,
|
|
320
|
-
)
|
|
321
|
-
return not self.done()
|
|
322
|
-
|
|
323
|
-
def __await__(self) -> typing.Generator[typing.Any, typing.Any, T]:
|
|
324
|
-
# It's tempting to use `return (yield from self._coro)` here,
|
|
325
|
-
# which bypasses the scheduler. Unfortunately, this means that
|
|
326
|
-
# we can't keep track of the result or state of the coroutine,
|
|
327
|
-
# things which we expose in our public API. If you want the
|
|
328
|
-
# efficiency of bypassing the scheduler, remove the `@coroutine`
|
|
329
|
-
# decorator from your `async` functions.
|
|
330
|
-
|
|
331
|
-
# Hand the coroutine back to the scheduler trampoline.
|
|
332
|
-
return (yield self)
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
RunningTask = Task
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
class RunningCoroutine(Task[T]):
|
|
339
|
-
"""
|
|
340
|
-
The result of calling a :any:`cocotb.coroutine` decorated coroutine.
|
|
341
|
-
|
|
342
|
-
All this class does is provide some extra attributes.
|
|
343
|
-
"""
|
|
344
|
-
|
|
345
|
-
def __init__(self, inst, parent):
|
|
346
|
-
super().__init__(inst)
|
|
347
|
-
self._parent = parent
|
|
348
|
-
self.__doc__ = parent._func.__doc__
|
|
349
|
-
self.module = parent._func.__module__
|
|
350
|
-
self.funcname = parent._func.__name__
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
class RunningTest(RunningCoroutine[T]):
|
|
354
|
-
"""
|
|
355
|
-
The result of calling a :class:`cocotb.test` decorated object.
|
|
356
|
-
|
|
357
|
-
All this class does is change ``__name__`` to show "Test" instead of "Task".
|
|
358
|
-
"""
|
|
359
|
-
|
|
360
|
-
_name: str = "Test"
|
|
361
|
-
|
|
362
|
-
def __init__(self, inst, parent):
|
|
363
|
-
super().__init__(inst, parent)
|
|
364
|
-
self.__name__ = f"{type(self)._name} {self.funcname}"
|
|
365
|
-
self.__qualname__ = self.__name__
|
|
366
|
-
|
|
367
|
-
|
|
368
58
|
class coroutine:
|
|
369
59
|
"""Decorator class that allows us to provide common coroutine mechanisms:
|
|
370
60
|
|
|
371
61
|
``log`` methods will log to ``cocotb.coroutine.name``.
|
|
372
62
|
|
|
373
|
-
:meth:`~cocotb.
|
|
63
|
+
:meth:`~cocotb.task.Task.join` method returns an event which will fire when the coroutine exits.
|
|
374
64
|
|
|
375
65
|
Used as ``@cocotb.coroutine``.
|
|
376
66
|
"""
|
|
@@ -384,7 +74,7 @@ class coroutine:
|
|
|
384
74
|
return SimLog(f"cocotb.coroutine.{self._func.__qualname__}.{id(self)}")
|
|
385
75
|
|
|
386
76
|
def __call__(self, *args, **kwargs):
|
|
387
|
-
return
|
|
77
|
+
return _RunningCoroutine(self._func(*args, **kwargs), self)
|
|
388
78
|
|
|
389
79
|
def __get__(self, obj, owner=None):
|
|
390
80
|
"""Permit the decorator to be used on class methods
|
|
@@ -503,7 +193,9 @@ class test(coroutine, metaclass=_decorator_helper):
|
|
|
503
193
|
Using ``None`` as the *timeout_unit* argument is deprecated, use ``'step'`` instead.
|
|
504
194
|
|
|
505
195
|
expect_fail (bool, optional):
|
|
506
|
-
|
|
196
|
+
If ``True`` and the test fails a functional check via an ``assert`` statement, :class:`pytest.raises`,
|
|
197
|
+
:class:`pytest.warns`, or :class:`pytest.deprecated_call` the test is considered to have passed.
|
|
198
|
+
If ``True`` and the test passes successfully, the test is considered to have failed.
|
|
507
199
|
|
|
508
200
|
expect_error (exception type or tuple of exception types, optional):
|
|
509
201
|
Mark the result as a pass only if one of the exception types is raised in the test.
|
|
@@ -589,7 +281,7 @@ class test(coroutine, metaclass=_decorator_helper):
|
|
|
589
281
|
stacklevel=2,
|
|
590
282
|
)
|
|
591
283
|
if expect_error is True:
|
|
592
|
-
expect_error = (
|
|
284
|
+
expect_error = (BaseException,)
|
|
593
285
|
elif expect_error is False:
|
|
594
286
|
expect_error = ()
|
|
595
287
|
self.expect_error = expect_error
|
|
@@ -600,5 +292,35 @@ class test(coroutine, metaclass=_decorator_helper):
|
|
|
600
292
|
|
|
601
293
|
def __call__(self, *args, **kwargs):
|
|
602
294
|
inst = self._func(*args, **kwargs)
|
|
603
|
-
coro =
|
|
295
|
+
coro = _RunningTest(inst, self)
|
|
604
296
|
return coro
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
if sys.version_info < (3, 7):
|
|
300
|
+
Task = _Task
|
|
301
|
+
RunningTask = _Task
|
|
302
|
+
RunningCoroutine = _RunningCoroutine
|
|
303
|
+
RunningTest = _RunningTest
|
|
304
|
+
else:
|
|
305
|
+
|
|
306
|
+
def __getattr__(attr: str) -> typing.Any:
|
|
307
|
+
if attr in ("Task", "RunningTask"):
|
|
308
|
+
warnings.warn(
|
|
309
|
+
f"The class {attr} has been renamed to cocotb.task.Task.",
|
|
310
|
+
DeprecationWarning,
|
|
311
|
+
stacklevel=2,
|
|
312
|
+
)
|
|
313
|
+
attr = "_Task"
|
|
314
|
+
elif attr in ("RunningCoroutine", "RunningTest"):
|
|
315
|
+
warnings.warn(
|
|
316
|
+
f"The class {attr} is now private. Update all uses to the parent class cocotb.task.Task.",
|
|
317
|
+
DeprecationWarning,
|
|
318
|
+
stacklevel=2,
|
|
319
|
+
)
|
|
320
|
+
attr = f"_{attr}"
|
|
321
|
+
try:
|
|
322
|
+
return globals()[attr]
|
|
323
|
+
except KeyError:
|
|
324
|
+
raise AttributeError(
|
|
325
|
+
f"module {__name__!r} has no attribute {attr!r}"
|
|
326
|
+
) from None
|
cocotb/ipython_support.py
CHANGED
|
@@ -61,7 +61,9 @@ async def embed(user_ns: dict = {}):
|
|
|
61
61
|
c = load_default_config()
|
|
62
62
|
c.TerminalInteractiveShell.loop_runner = lambda x: _runner(shell, x)
|
|
63
63
|
c.TerminalInteractiveShell.autoawait = True
|
|
64
|
-
|
|
64
|
+
# Python3 checks SQLite DB accesses to ensure process ID matches the one that opened the DB and is not propogated
|
|
65
|
+
# because we launch IPython in a different process, this will cause unnecessary warnings, so disable the PID check
|
|
66
|
+
c.HistoryAccessor.connection_options = {"check_same_thread": False}
|
|
65
67
|
# create a shell with access to the dut, and cocotb pre-imported
|
|
66
68
|
shell = IPython.terminal.embed.InteractiveShellEmbed(
|
|
67
69
|
user_ns=default_ns,
|
cocotb/libs/cocotb.dll
CHANGED
|
Binary file
|
cocotb/libs/cocotb.exp
CHANGED
|
Binary file
|
cocotb/libs/cocotb.lib
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
cocotb/libs/cocotbutils.dll
CHANGED
|
Binary file
|
cocotb/libs/cocotbutils.exp
CHANGED
|
Binary file
|
cocotb/libs/cocotbutils.lib
CHANGED
|
Binary file
|
cocotb/libs/cocotbvhpi_aldec.dll
CHANGED
|
Binary file
|
cocotb/libs/cocotbvhpi_aldec.exp
CHANGED
|
Binary file
|
cocotb/libs/cocotbvhpi_aldec.lib
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
cocotb/libs/cocotbvpi_aldec.dll
CHANGED
|
Binary file
|
cocotb/libs/cocotbvpi_aldec.exp
CHANGED
|
Binary file
|
cocotb/libs/cocotbvpi_aldec.lib
CHANGED
|
Binary file
|
cocotb/libs/cocotbvpi_ghdl.dll
CHANGED
|
Binary file
|
cocotb/libs/cocotbvpi_ghdl.exp
CHANGED
|
Binary file
|
cocotb/libs/cocotbvpi_ghdl.lib
CHANGED
|
Binary file
|
cocotb/libs/cocotbvpi_icarus.exp
CHANGED
|
Binary file
|
cocotb/libs/cocotbvpi_icarus.lib
CHANGED
|
Binary file
|
cocotb/libs/cocotbvpi_icarus.vpl
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
cocotb/libs/embed.dll
CHANGED
|
Binary file
|
cocotb/libs/embed.exp
CHANGED
|
Binary file
|
cocotb/libs/embed.lib
CHANGED
|
Binary file
|
cocotb/libs/gpi.dll
CHANGED
|
Binary file
|
cocotb/libs/gpi.exp
CHANGED
|
Binary file
|
cocotb/libs/gpi.lib
CHANGED
|
Binary file
|
cocotb/libs/gpilog.dll
CHANGED
|
Binary file
|
cocotb/libs/gpilog.exp
CHANGED
|
Binary file
|
cocotb/libs/gpilog.lib
CHANGED
|
Binary file
|
cocotb/libs/pygpilog.dll
CHANGED
|
Binary file
|
cocotb/libs/pygpilog.exp
CHANGED
|
Binary file
|
cocotb/libs/pygpilog.lib
CHANGED
|
Binary file
|