cocotb 2.0.0b1__cp313-cp313-win_amd64.whl → 2.0.0rc2__cp313-cp313-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/_ANSI.py +47 -54
- cocotb/__init__.py +12 -2
- cocotb/_base_triggers.py +11 -9
- cocotb/_bridge.py +8 -9
- cocotb/_extended_awaitables.py +1 -1
- cocotb/_gpi_triggers.py +4 -1
- cocotb/_init.py +17 -11
- cocotb/_py_compat.py +24 -10
- cocotb/_scheduler.py +25 -31
- cocotb/_test.py +6 -3
- cocotb/_test_factory.py +4 -1
- cocotb/_utils.py +1 -23
- cocotb/_version.py +1 -1
- cocotb/clock.py +98 -16
- cocotb/debug.py +24 -0
- cocotb/handle.py +62 -32
- 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/logging.py +243 -117
- cocotb/regression.py +43 -35
- 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.exp +0 -0
- cocotb/share/def/modelsim.lib +0 -0
- cocotb/share/include/cocotb_utils.h +3 -3
- cocotb/share/include/embed.h +2 -2
- cocotb/share/include/gpi.h +258 -109
- cocotb/share/include/py_gpi_logging.h +3 -3
- cocotb/share/lib/verilator/verilator.cpp +23 -15
- cocotb/simtime.py +230 -0
- cocotb/simulator.cp313-win_amd64.exp +0 -0
- cocotb/simulator.cp313-win_amd64.lib +0 -0
- cocotb/simulator.cp313-win_amd64.pyd +0 -0
- cocotb/task.py +54 -11
- cocotb/types/__init__.py +4 -1
- cocotb/types/_array.py +33 -2
- cocotb/types/_indexing.py +17 -0
- cocotb/types/_logic.py +96 -59
- cocotb/types/_logic_array.py +56 -22
- cocotb/types/_range.py +12 -5
- cocotb/utils.py +9 -129
- {cocotb-2.0.0b1.dist-info → cocotb-2.0.0rc2.dist-info}/METADATA +1 -1
- cocotb-2.0.0rc2.dist-info/RECORD +146 -0
- {cocotb-2.0.0b1.dist-info → cocotb-2.0.0rc2.dist-info}/licenses/LICENSE +1 -0
- cocotb_tools/config.py +5 -5
- cocotb_tools/makefiles/Makefile.inc +3 -9
- cocotb_tools/makefiles/Makefile.sim +9 -1
- cocotb_tools/makefiles/simulators/Makefile.vcs +1 -1
- cocotb_tools/runner.py +94 -59
- pygpi/entry.py +5 -6
- cocotb-2.0.0b1.dist-info/RECORD +0 -143
- {cocotb-2.0.0b1.dist-info → cocotb-2.0.0rc2.dist-info}/WHEEL +0 -0
- {cocotb-2.0.0b1.dist-info → cocotb-2.0.0rc2.dist-info}/entry_points.txt +0 -0
- {cocotb-2.0.0b1.dist-info → cocotb-2.0.0rc2.dist-info}/top_level.txt +0 -0
cocotb/_test_factory.py
CHANGED
|
@@ -7,8 +7,8 @@ import inspect
|
|
|
7
7
|
import logging
|
|
8
8
|
import warnings
|
|
9
9
|
from itertools import product
|
|
10
|
-
from types import FrameType, FunctionType
|
|
11
10
|
from typing import (
|
|
11
|
+
TYPE_CHECKING,
|
|
12
12
|
Callable,
|
|
13
13
|
Coroutine,
|
|
14
14
|
Dict,
|
|
@@ -25,6 +25,9 @@ from cocotb._base_triggers import Trigger
|
|
|
25
25
|
from cocotb._decorators import Test
|
|
26
26
|
from cocotb._typing import TimeUnit
|
|
27
27
|
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
from types import FrameType, FunctionType
|
|
30
|
+
|
|
28
31
|
|
|
29
32
|
class TestFactory:
|
|
30
33
|
"""Factory to automatically generate tests.
|
cocotb/_utils.py
CHANGED
|
@@ -6,12 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
"""Utilities for implementors."""
|
|
8
8
|
|
|
9
|
-
import os
|
|
10
|
-
import sys
|
|
11
9
|
import traceback
|
|
12
10
|
import types
|
|
13
11
|
from enum import Enum, IntEnum
|
|
14
|
-
from functools import
|
|
12
|
+
from functools import update_wrapper, wraps
|
|
15
13
|
from types import TracebackType
|
|
16
14
|
from typing import (
|
|
17
15
|
TYPE_CHECKING,
|
|
@@ -27,26 +25,6 @@ from typing import (
|
|
|
27
25
|
overload,
|
|
28
26
|
)
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
@lru_cache(maxsize=None)
|
|
32
|
-
def want_color_output() -> bool:
|
|
33
|
-
"""Return ``True`` if colored output is possible/requested and not running in GUI.
|
|
34
|
-
|
|
35
|
-
Colored output can be explicitly requested in a cocotb-specific way
|
|
36
|
-
by setting :envvar:`COCOTB_ANSI_OUTPUT` to ``1``.
|
|
37
|
-
|
|
38
|
-
Returns: Whether color output is wanted and supported.
|
|
39
|
-
"""
|
|
40
|
-
want_color = sys.stdout.isatty() # default to color for TTYs
|
|
41
|
-
if os.getenv("NO_COLOR") is not None:
|
|
42
|
-
want_color = False
|
|
43
|
-
if os.getenv("COCOTB_ANSI_OUTPUT", default="0") == "1":
|
|
44
|
-
want_color = True
|
|
45
|
-
if os.getenv("GUI", default="0") == "1":
|
|
46
|
-
want_color = False
|
|
47
|
-
return want_color
|
|
48
|
-
|
|
49
|
-
|
|
50
28
|
ExceptionTuple = Tuple[
|
|
51
29
|
Type[BaseException], BaseException, TracebackType
|
|
52
30
|
] # TypeAlias in Python 3.10
|
cocotb/_version.py
CHANGED
cocotb/clock.py
CHANGED
|
@@ -31,9 +31,9 @@ from cocotb.handle import (
|
|
|
31
31
|
from cocotb.simulator import clock_create
|
|
32
32
|
from cocotb.task import Task
|
|
33
33
|
from cocotb.triggers import (
|
|
34
|
-
ClockCycles,
|
|
35
34
|
Event,
|
|
36
35
|
FallingEdge,
|
|
36
|
+
NullTrigger,
|
|
37
37
|
RisingEdge,
|
|
38
38
|
Timer,
|
|
39
39
|
ValueChange,
|
|
@@ -58,10 +58,10 @@ class Clock:
|
|
|
58
58
|
|
|
59
59
|
Args:
|
|
60
60
|
signal: The clock pin/signal to be driven.
|
|
61
|
-
period:
|
|
61
|
+
period:
|
|
62
|
+
The clock period.
|
|
63
|
+
Must be a multiple of the time precision of the simulator.
|
|
62
64
|
|
|
63
|
-
.. note::
|
|
64
|
-
Must convert to an even number of timesteps.
|
|
65
65
|
unit:
|
|
66
66
|
One of ``'step'``, ``'fs'``, ``'ps'``, ``'ns'``, ``'us'``, ``'ms'``, ``'sec'``.
|
|
67
67
|
When *unit* is ``'step'``,
|
|
@@ -84,6 +84,13 @@ class Clock:
|
|
|
84
84
|
|
|
85
85
|
.. versionadded:: 2.0
|
|
86
86
|
|
|
87
|
+
period_high:
|
|
88
|
+
The period of time when the clock is driven to ``1``.
|
|
89
|
+
Defaults to half of the *period*.
|
|
90
|
+
Must be a multiple of the time precision of the simulator and less than *period*.
|
|
91
|
+
|
|
92
|
+
.. versionadded:: 2.0
|
|
93
|
+
|
|
87
94
|
When *impl* is ``'auto'``, if :envvar:`COCOTB_TRUST_INERTIAL_WRITES` is defined,
|
|
88
95
|
the :class:`~cocotb.simulator.GpiClock` implementation will be used.
|
|
89
96
|
Otherwise, the Python coroutine implementation will be used.
|
|
@@ -158,9 +165,10 @@ class Clock:
|
|
|
158
165
|
*,
|
|
159
166
|
units: None = None,
|
|
160
167
|
set_action: Union[Type[Immediate], Type[Deposit], Type[Force], None] = None,
|
|
168
|
+
period_high: Union[float, Fraction, Decimal, None] = None,
|
|
161
169
|
) -> None:
|
|
162
170
|
self._signal = signal
|
|
163
|
-
|
|
171
|
+
|
|
164
172
|
if units is not None:
|
|
165
173
|
warnings.warn(
|
|
166
174
|
"The 'units' argument has been renamed to 'unit'.",
|
|
@@ -169,11 +177,18 @@ class Clock:
|
|
|
169
177
|
)
|
|
170
178
|
unit = units
|
|
171
179
|
self._unit: TimeUnit = unit
|
|
180
|
+
|
|
181
|
+
self._period = period
|
|
182
|
+
try:
|
|
183
|
+
self._period_steps = get_sim_steps(self._period, self._unit)
|
|
184
|
+
except ValueError as e:
|
|
185
|
+
raise ValueError(f"Bad `period`: {e}") from None
|
|
186
|
+
|
|
172
187
|
if set_action is None:
|
|
173
188
|
set_action = type(self).default_set_action
|
|
174
189
|
if set_action not in (Immediate, Deposit, Force):
|
|
175
190
|
raise TypeError(
|
|
176
|
-
"Invalid value for
|
|
191
|
+
"Invalid value for `set_action`. `set_action` must be one of Immediate, Deposit, or Force"
|
|
177
192
|
)
|
|
178
193
|
self._set_action = set_action
|
|
179
194
|
|
|
@@ -187,6 +202,23 @@ class Clock:
|
|
|
187
202
|
f"Invalid clock impl {impl!r}, must be one of: {valid_impls_str}"
|
|
188
203
|
)
|
|
189
204
|
|
|
205
|
+
self._period_high: Union[float, Fraction, Decimal]
|
|
206
|
+
if period_high is not None:
|
|
207
|
+
if period_high >= self._period:
|
|
208
|
+
raise ValueError("`period_high` must be strictly less than `period`.")
|
|
209
|
+
self._period_high = period_high
|
|
210
|
+
try:
|
|
211
|
+
self._period_high_steps = get_sim_steps(self._period_high, self._unit)
|
|
212
|
+
except ValueError as e:
|
|
213
|
+
raise ValueError(f"Bad `period_high`: {e}") from None
|
|
214
|
+
else:
|
|
215
|
+
if self._period_steps % 2 != 0:
|
|
216
|
+
raise ValueError(
|
|
217
|
+
"Bad `period`: Must be divisible by 2 if `period_high` is not given."
|
|
218
|
+
)
|
|
219
|
+
self._period_high = period / 2
|
|
220
|
+
self._period_high_steps = self._period_steps // 2
|
|
221
|
+
|
|
190
222
|
self._task: Union[Task[None], None] = None
|
|
191
223
|
|
|
192
224
|
@property
|
|
@@ -196,9 +228,22 @@ class Clock:
|
|
|
196
228
|
|
|
197
229
|
@property
|
|
198
230
|
def period(self) -> Union[float, Fraction, Decimal]:
|
|
199
|
-
"""The clock period
|
|
231
|
+
"""The clock period.
|
|
232
|
+
|
|
233
|
+
The unit is :attr:`unit`.
|
|
234
|
+
"""
|
|
200
235
|
return self._period
|
|
201
236
|
|
|
237
|
+
@property
|
|
238
|
+
def period_high(self) -> Union[float, Fraction, Decimal]:
|
|
239
|
+
"""The period of time when the clock is driven to ``1``.
|
|
240
|
+
|
|
241
|
+
The unit is :attr:`unit`.
|
|
242
|
+
|
|
243
|
+
.. versionadded:: 2.0
|
|
244
|
+
"""
|
|
245
|
+
return self._period_high
|
|
246
|
+
|
|
202
247
|
@property
|
|
203
248
|
def unit(self) -> TimeUnit:
|
|
204
249
|
"""The unit of the clock period.
|
|
@@ -256,9 +301,6 @@ class Clock:
|
|
|
256
301
|
if self._task is not None:
|
|
257
302
|
raise RuntimeError("Starting clock that has already been started.")
|
|
258
303
|
|
|
259
|
-
period = get_sim_steps(self._period, self._unit)
|
|
260
|
-
t_high = period // 2
|
|
261
|
-
|
|
262
304
|
if self._impl == "gpi":
|
|
263
305
|
clkobj = clock_create(self._signal._handle)
|
|
264
306
|
set_action = {
|
|
@@ -266,7 +308,12 @@ class Clock:
|
|
|
266
308
|
Immediate: _GPISetAction.NO_DELAY,
|
|
267
309
|
Force: _GPISetAction.FORCE,
|
|
268
310
|
}[self._set_action]
|
|
269
|
-
clkobj.start(
|
|
311
|
+
clkobj.start(
|
|
312
|
+
self._period_steps,
|
|
313
|
+
self._period_high_steps,
|
|
314
|
+
start_high,
|
|
315
|
+
set_action.value,
|
|
316
|
+
)
|
|
270
317
|
|
|
271
318
|
async def drive() -> None:
|
|
272
319
|
# The clock is meant to toggle forever, so awaiting this should
|
|
@@ -280,8 +327,8 @@ class Clock:
|
|
|
280
327
|
else:
|
|
281
328
|
|
|
282
329
|
async def drive() -> None:
|
|
283
|
-
timer_high = Timer(
|
|
284
|
-
timer_low = Timer(
|
|
330
|
+
timer_high = Timer(self._period_high_steps)
|
|
331
|
+
timer_low = Timer(self._period_steps - self._period_high_steps)
|
|
285
332
|
if start_high:
|
|
286
333
|
self._signal.set(self._set_action(1))
|
|
287
334
|
await timer_high
|
|
@@ -316,9 +363,44 @@ class Clock:
|
|
|
316
363
|
Type[RisingEdge], Type[FallingEdge], Type[ValueChange]
|
|
317
364
|
] = RisingEdge,
|
|
318
365
|
) -> None:
|
|
319
|
-
"""Wait for a number of clock cycles.
|
|
320
|
-
|
|
321
|
-
|
|
366
|
+
"""Wait for a number of clock cycles.
|
|
367
|
+
|
|
368
|
+
Args:
|
|
369
|
+
num_cycles: The number of clock cycles to wait.
|
|
370
|
+
edge_type:
|
|
371
|
+
The edge of the clock to wait on.
|
|
372
|
+
Must be one of :class:`.RisingEdge`, :class:`.FallingEdge`, or :class:`.ValueChange`.
|
|
373
|
+
|
|
374
|
+
Raises:
|
|
375
|
+
ValueError: if *num_cycles* is negative.
|
|
376
|
+
"""
|
|
377
|
+
if num_cycles == 0:
|
|
378
|
+
await NullTrigger()
|
|
379
|
+
return
|
|
380
|
+
elif num_cycles < 0:
|
|
381
|
+
raise ValueError("`num_cycles` cannot be negative")
|
|
382
|
+
|
|
383
|
+
# Synchronize first.
|
|
384
|
+
await edge_type(self._signal)
|
|
385
|
+
num_cycles -= 1
|
|
386
|
+
|
|
387
|
+
# Use Timer as an optimization if we are waiting long enough.
|
|
388
|
+
if num_cycles >= 2:
|
|
389
|
+
# NOTE: num_cycles must end 1 higher than expected because all edge_types occur
|
|
390
|
+
# strictly after beginning of time steps, so the last edge_type will jump within
|
|
391
|
+
# the same time step.
|
|
392
|
+
if edge_type is ValueChange:
|
|
393
|
+
# Make cycles_skipped the nearest even number so division by 2 doesn't cause issues.
|
|
394
|
+
cycles_skipped = (num_cycles // 2) * 2
|
|
395
|
+
await Timer(self._period_steps * cycles_skipped / 2, "step")
|
|
396
|
+
num_cycles = num_cycles - cycles_skipped + 1
|
|
397
|
+
else:
|
|
398
|
+
await Timer(self._period_steps * num_cycles, "step")
|
|
399
|
+
num_cycles = 1
|
|
400
|
+
|
|
401
|
+
# Run N edge_type trigger.
|
|
402
|
+
for _ in range(num_cycles):
|
|
403
|
+
await edge_type(self._signal)
|
|
322
404
|
|
|
323
405
|
def __repr__(self) -> str:
|
|
324
406
|
return self._repr
|
cocotb/debug.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Copyright cocotb contributors
|
|
2
|
+
# Licensed under the Revised BSD License, see LICENSE for details.
|
|
3
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
debug: bool = bool(os.getenv("COCOTB_SCHEDULER_DEBUG"))
|
|
8
|
+
"""Global flag to enable additional debugging functionality.
|
|
9
|
+
|
|
10
|
+
Defaults to ``True`` if the :envvar:`COCOTB_SCHEDULER_DEBUG` environment variable is set,
|
|
11
|
+
but can be programmatically set by the user afterwards.
|
|
12
|
+
|
|
13
|
+
The ``"cocotb"`` logger should have its logging level set to :data:`logging.DEBUG`
|
|
14
|
+
to see additional debugging information in the test log.
|
|
15
|
+
This can be accomplished by setting the :envvar:`COCOTB_LOG_LEVEL` environment variable
|
|
16
|
+
to ``DEBUG``,
|
|
17
|
+
or using the following code.
|
|
18
|
+
|
|
19
|
+
.. code-block:: python
|
|
20
|
+
|
|
21
|
+
import logging
|
|
22
|
+
logging.getLogger("cocotb").setLevel(logging.DEBUG)
|
|
23
|
+
|
|
24
|
+
"""
|
cocotb/handle.py
CHANGED
|
@@ -45,6 +45,7 @@ from cocotb._py_compat import cached_property, insertion_ordered_dict
|
|
|
45
45
|
from cocotb._utils import DocIntEnum
|
|
46
46
|
from cocotb.task import Task
|
|
47
47
|
from cocotb.types import Array, Logic, LogicArray, Range
|
|
48
|
+
from cocotb.types._indexing import do_indexing_changed_warning, indexing_changed
|
|
48
49
|
|
|
49
50
|
__all__ = (
|
|
50
51
|
"ArrayObject",
|
|
@@ -214,6 +215,9 @@ class _RangeableObjectMixin(SimHandleBase):
|
|
|
214
215
|
#: Type of keys (name or index) in HierarchyObjectBase.
|
|
215
216
|
KeyType = TypeVar("KeyType")
|
|
216
217
|
|
|
218
|
+
#: Subtype of :class:`SimHandleBase` returned when iterating or indexing a :class:`HierarchyArrayObject`.
|
|
219
|
+
HierarchyChildObjectT = TypeVar("HierarchyChildObjectT", bound=SimHandleBase)
|
|
220
|
+
|
|
217
221
|
|
|
218
222
|
class GPIDiscovery(DocIntEnum):
|
|
219
223
|
"""Simulator object discovery strategy."""
|
|
@@ -417,7 +421,7 @@ class HierarchyObject(_HierarchyObjectBase[str]):
|
|
|
417
421
|
|
|
418
422
|
- the name cannot start with a number
|
|
419
423
|
- the name cannot start with a ``_`` character
|
|
420
|
-
- the name can only contain ASCII letters, numbers, and the ``_`` character
|
|
424
|
+
- the name can only contain ASCII letters, numbers, and the ``_`` character.
|
|
421
425
|
|
|
422
426
|
Any possible name of an object is supported with the index syntax,
|
|
423
427
|
but it can be more verbose.
|
|
@@ -460,7 +464,16 @@ class HierarchyObject(_HierarchyObjectBase[str]):
|
|
|
460
464
|
if name.startswith("_"):
|
|
461
465
|
return object.__setattr__(self, name, value)
|
|
462
466
|
|
|
463
|
-
|
|
467
|
+
try:
|
|
468
|
+
getattr(self, name)
|
|
469
|
+
except AttributeError:
|
|
470
|
+
raise AttributeError(
|
|
471
|
+
f"Cannot set attribute {name!r} on simulation object {self._path}. No such object exists."
|
|
472
|
+
) from None
|
|
473
|
+
else:
|
|
474
|
+
raise AttributeError(
|
|
475
|
+
f"Cannot set attribute {name!r} on simulation object {self._path}. Did you forget to add `.value`?"
|
|
476
|
+
)
|
|
464
477
|
|
|
465
478
|
def __getattr__(self, name: str) -> SimHandleBase:
|
|
466
479
|
if name.startswith("_"):
|
|
@@ -524,7 +537,9 @@ class HierarchyObject(_HierarchyObjectBase[str]):
|
|
|
524
537
|
return self._handle.get_handle_by_name(key, discovery_method)
|
|
525
538
|
|
|
526
539
|
|
|
527
|
-
class HierarchyArrayObject(
|
|
540
|
+
class HierarchyArrayObject(
|
|
541
|
+
_HierarchyObjectBase[int], _RangeableObjectMixin, Generic[HierarchyChildObjectT]
|
|
542
|
+
):
|
|
528
543
|
"""A simulation object that is an array of hierarchical simulation objects.
|
|
529
544
|
|
|
530
545
|
Inherits from :class:`SimHandleBase`.
|
|
@@ -597,35 +612,36 @@ class HierarchyArrayObject(_HierarchyObjectBase[int], _RangeableObjectMixin):
|
|
|
597
612
|
)
|
|
598
613
|
return self._handle.get_handle_by_index(key)
|
|
599
614
|
|
|
600
|
-
def __getitem__(self, key: int) ->
|
|
615
|
+
def __getitem__(self, key: int) -> HierarchyChildObjectT:
|
|
601
616
|
if isinstance(key, slice):
|
|
602
617
|
raise TypeError("Slice indexing is not supported")
|
|
603
618
|
|
|
604
619
|
handle = self._get(key)
|
|
605
620
|
if handle is None:
|
|
606
621
|
raise IndexError(f"{self._path} contains no child object at index {key}")
|
|
607
|
-
return handle
|
|
622
|
+
return cast("HierarchyChildObjectT", handle)
|
|
608
623
|
|
|
609
624
|
# ideally `__len__` could be implemented in terms of `range`, but `range` doesn't work universally.
|
|
610
625
|
|
|
611
|
-
def __iter__(self) -> Iterator[
|
|
626
|
+
def __iter__(self) -> Iterator[HierarchyChildObjectT]:
|
|
612
627
|
# must use `sorted(self._keys())` instead of the range because `range` doesn't work universally.
|
|
613
628
|
for i in sorted(self._keys()):
|
|
614
629
|
yield self[i]
|
|
615
630
|
|
|
616
631
|
|
|
617
|
-
class _GPISetAction(enum.
|
|
632
|
+
class _GPISetAction(enum.Enum):
|
|
618
633
|
DEPOSIT = 0
|
|
619
634
|
FORCE = 1
|
|
620
635
|
RELEASE = 2
|
|
621
636
|
NO_DELAY = 3
|
|
637
|
+
OLD_IMMEDIATE = 0
|
|
622
638
|
|
|
623
639
|
|
|
624
640
|
_ValueT = TypeVar("_ValueT")
|
|
625
641
|
|
|
626
642
|
|
|
627
643
|
class Deposit(Generic[_ValueT]):
|
|
628
|
-
r""":term:`Inertially
|
|
644
|
+
r""":term:`Inertially deposit <inertial deposit>` the given value on a simulator object.
|
|
629
645
|
|
|
630
646
|
If another :term:`deposit` comes after this deposit, the newer deposit overwrites the old value.
|
|
631
647
|
If an HDL process is :term:`driving` the signal/net/register where a deposit from cocotb is made,
|
|
@@ -655,12 +671,12 @@ class Force(Generic[_ValueT]):
|
|
|
655
671
|
while ``variable`` writes are set immediately, regardless of using this class.
|
|
656
672
|
|
|
657
673
|
.. note::
|
|
658
|
-
Verilog
|
|
674
|
+
Verilog :class:`!Force`\ s are always immediate.
|
|
659
675
|
This also means that if there are multiple cocotb Tasks or multiple ``always`` blocks writing to the same object,
|
|
660
676
|
the resulting value is non-deterministic.
|
|
661
677
|
|
|
662
678
|
.. note::
|
|
663
|
-
Issuing a Force and Release in the same evaluation cycle in VHDL will result in the Force "winning".
|
|
679
|
+
Issuing a :class:`!Force` and :class:`Release` in the same evaluation cycle in VHDL will result in the :class:`!Force` "winning".
|
|
664
680
|
"""
|
|
665
681
|
|
|
666
682
|
def __init__(self, value: _ValueT) -> None:
|
|
@@ -680,17 +696,17 @@ class Freeze:
|
|
|
680
696
|
while ``variable`` writes are set immediately, regardless of using this class.
|
|
681
697
|
|
|
682
698
|
.. note::
|
|
683
|
-
Verilog
|
|
699
|
+
Verilog :class:`Force`\ s are always immediate.
|
|
684
700
|
This also means that if there are multiple cocotb Tasks or multiple ``always`` blocks writing to the same object,
|
|
685
701
|
the resulting value is non-deterministic.
|
|
686
702
|
|
|
687
703
|
.. note::
|
|
688
|
-
Issuing a Force and Release in the same evaluation cycle in VHDL will result in the Force "winning".
|
|
704
|
+
Issuing a :class:`!Force` and :class:`Release` in the same evaluation cycle in VHDL will result in the :class:`!Force` "winning".
|
|
689
705
|
"""
|
|
690
706
|
|
|
691
707
|
|
|
692
708
|
class Release:
|
|
693
|
-
""":term:`Release <release>` a :term:`forced <force>` simulation object.
|
|
709
|
+
r""":term:`Release <release>` a :term:`forced <force>` simulation object.
|
|
694
710
|
|
|
695
711
|
Does not change the current value of the simulation object.
|
|
696
712
|
See :class:`Deposit` for information on behavior after this write completes.
|
|
@@ -701,18 +717,18 @@ class Release:
|
|
|
701
717
|
while ``variable`` writes are set immediately, regardless of using this class.
|
|
702
718
|
|
|
703
719
|
.. note::
|
|
704
|
-
Verilog
|
|
720
|
+
Verilog :class:`!Release`\ s are always immediate.
|
|
705
721
|
This also means that if there are multiple cocotb Tasks or multiple ``always`` blocks writing to the same object,
|
|
706
722
|
the resulting value is non-deterministic.
|
|
707
723
|
|
|
708
724
|
.. note::
|
|
709
|
-
Issuing a Force and Release in the same evaluation cycle in VHDL will result in the Force "winning".
|
|
725
|
+
Issuing a :class:`Force` and :class:`!Release` in the same evaluation cycle in VHDL will result in the :class:`!Force` "winning".
|
|
710
726
|
|
|
711
727
|
.. note::
|
|
712
|
-
Releasing a ``reg`` or
|
|
728
|
+
Releasing a ``reg`` or ``logic`` in Verilog will leave the current value.
|
|
713
729
|
Releasing a ``wire`` in Verilog will cause the value to be recomputed from the wire's drivers current values.
|
|
714
730
|
Releasing a ``signal`` in VHDL will cause the value to be recomputed from the signal's drivers current value.
|
|
715
|
-
Unconnected ``in`` ports and unconnected internal signals have no drivers and their value after Release will be ``U`` in VHDL and ``X`` in Verilog.
|
|
731
|
+
Unconnected ``in`` ports and unconnected internal signals have no drivers and their value after :class:`!Release` will be ``U`` in VHDL and ``X`` in Verilog.
|
|
716
732
|
"""
|
|
717
733
|
|
|
718
734
|
|
|
@@ -738,6 +754,11 @@ class Immediate(Generic[_ValueT]):
|
|
|
738
754
|
self.value = value
|
|
739
755
|
|
|
740
756
|
|
|
757
|
+
class _OldImmediate(Generic[_ValueT]):
|
|
758
|
+
def __init__(self, value: _ValueT) -> None:
|
|
759
|
+
self.value = value
|
|
760
|
+
|
|
761
|
+
|
|
741
762
|
_trust_inertial = bool(int(os.environ.get("COCOTB_TRUST_INERTIAL_WRITES", "0")))
|
|
742
763
|
|
|
743
764
|
# A dictionary of pending (write_func, args), keyed by handle.
|
|
@@ -801,7 +822,7 @@ else:
|
|
|
801
822
|
if isinstance(current_gpi_trigger(), ReadWrite):
|
|
802
823
|
# If we are already in the ReadWrite phase, apply writes immediately as an optimization.
|
|
803
824
|
write_func(action.value, value)
|
|
804
|
-
elif action
|
|
825
|
+
elif action is _GPISetAction.DEPOSIT:
|
|
805
826
|
# Queue write for the beginning of the next ReadWrite phase because we can't trust the simulator. =(
|
|
806
827
|
if handle in _write_calls:
|
|
807
828
|
del _write_calls[handle]
|
|
@@ -876,7 +897,6 @@ class ValueObjectBase(SimHandleBase, Generic[ValueGetT, ValueSetT]):
|
|
|
876
897
|
|
|
877
898
|
Args:
|
|
878
899
|
value: The value to set the simulation object to. This may include type conversion.
|
|
879
|
-
action: How to set the value. See :class:`Action` for more details.
|
|
880
900
|
|
|
881
901
|
Raises:
|
|
882
902
|
TypeError: If the *value* is of a type that cannot be converted to a simulation value,
|
|
@@ -899,6 +919,8 @@ class ValueObjectBase(SimHandleBase, Generic[ValueGetT, ValueSetT]):
|
|
|
899
919
|
self._set_value(cast("ValueSetT", self.get()), _GPISetAction.RELEASE)
|
|
900
920
|
elif isinstance(value, Immediate):
|
|
901
921
|
self._set_value(value.value, _GPISetAction.NO_DELAY)
|
|
922
|
+
elif isinstance(value, _OldImmediate):
|
|
923
|
+
self._set_value(value.value, _GPISetAction.OLD_IMMEDIATE)
|
|
902
924
|
else:
|
|
903
925
|
self._set_value(value, _GPISetAction.DEPOSIT)
|
|
904
926
|
|
|
@@ -924,12 +946,13 @@ class ValueObjectBase(SimHandleBase, Generic[ValueGetT, ValueSetT]):
|
|
|
924
946
|
Passing :class:`Deposit`\ s and unwrapped values is equivalent to passing an :class:`Immediate` to :meth:`set`.
|
|
925
947
|
|
|
926
948
|
.. deprecated:: 2.0
|
|
927
|
-
|
|
949
|
+
Use ``handle.set(Immediate(...))`` or ``handle.value = Immediate(...)`` instead.
|
|
950
|
+
This could result in a change in behavior because prior to version 2.0 this function did not set values immediately.
|
|
928
951
|
"""
|
|
929
952
|
if isinstance(value, Deposit):
|
|
930
|
-
value =
|
|
953
|
+
value = _OldImmediate(value.value) # type: ignore
|
|
931
954
|
elif not isinstance(value, (Force, Freeze, Release, Immediate)):
|
|
932
|
-
value =
|
|
955
|
+
value = _OldImmediate(value) # type: ignore
|
|
933
956
|
self.set(value)
|
|
934
957
|
|
|
935
958
|
@cached_property
|
|
@@ -1013,7 +1036,12 @@ class ArrayObject(
|
|
|
1013
1036
|
| ``arr[7:4]`` | ``arr(7 downto 4)`` | ``Array([arr[7].value, arr[6].value, arr[5].value, arr[4].value], range=Range(7, 'downto', 4))`` |
|
|
1014
1037
|
+--------------+---------------------+--------------------------------------------------------------------------------------------------+
|
|
1015
1038
|
"""
|
|
1016
|
-
|
|
1039
|
+
r = self.range
|
|
1040
|
+
return Array._from_handle(
|
|
1041
|
+
value=[self[i].value for i in r],
|
|
1042
|
+
range=r,
|
|
1043
|
+
warn_indexing=indexing_changed(r) if do_indexing_changed_warning else False,
|
|
1044
|
+
)
|
|
1017
1045
|
|
|
1018
1046
|
def set(
|
|
1019
1047
|
self,
|
|
@@ -1043,9 +1071,9 @@ class ArrayObject(
|
|
|
1043
1071
|
Raises:
|
|
1044
1072
|
TypeError: If *value* is of a type that can't be assigned to the simulation object.
|
|
1045
1073
|
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1074
|
+
.. warning::
|
|
1075
|
+
Exceptions from array element :meth:`.ValueObjectBase.set` calls will be propagated up,
|
|
1076
|
+
so the actual set of exceptions possible is greater than this list.
|
|
1049
1077
|
"""
|
|
1050
1078
|
super().set(value)
|
|
1051
1079
|
|
|
@@ -1187,9 +1215,6 @@ class LogicObject(_NonIndexableValueObjectBase[Logic, Union[Logic, int, str]]):
|
|
|
1187
1215
|
raise TypeError("Can't get FallingEdge on immutable signal")
|
|
1188
1216
|
return FallingEdge._make(self)
|
|
1189
1217
|
|
|
1190
|
-
@deprecated(
|
|
1191
|
-
'`len(logic_scalar_handle)` has been deprecated. A scalar handle\'s "length" is always 1.'
|
|
1192
|
-
)
|
|
1193
1218
|
def __len__(self) -> int:
|
|
1194
1219
|
return 1
|
|
1195
1220
|
|
|
@@ -1295,7 +1320,12 @@ class LogicArrayObject(
|
|
|
1295
1320
|
def get(self) -> LogicArray:
|
|
1296
1321
|
"""Return the current value of the simulation object as a :class:`.LogicArray`."""
|
|
1297
1322
|
binstr = self._handle.get_signal_val_binstr()
|
|
1298
|
-
return LogicArray._from_handle(
|
|
1323
|
+
return LogicArray._from_handle(
|
|
1324
|
+
value=binstr,
|
|
1325
|
+
warn_indexing=indexing_changed(self.range)
|
|
1326
|
+
if do_indexing_changed_warning
|
|
1327
|
+
else False,
|
|
1328
|
+
)
|
|
1299
1329
|
|
|
1300
1330
|
def set(
|
|
1301
1331
|
self,
|
|
@@ -1657,7 +1687,7 @@ class StringObject(
|
|
|
1657
1687
|
|
|
1658
1688
|
_ConcreteHandleTypes = Union[
|
|
1659
1689
|
HierarchyObject,
|
|
1660
|
-
HierarchyArrayObject,
|
|
1690
|
+
HierarchyArrayObject[SimHandleBase],
|
|
1661
1691
|
LogicObject,
|
|
1662
1692
|
LogicArrayObject,
|
|
1663
1693
|
ArrayObject[Any, ValueObjectBase[Any, Any]],
|
|
@@ -1684,7 +1714,7 @@ _type2cls: Dict[int, Type[_ConcreteHandleTypes]] = {
|
|
|
1684
1714
|
simulator.INTEGER: IntegerObject,
|
|
1685
1715
|
simulator.ENUM: EnumObject,
|
|
1686
1716
|
simulator.STRING: StringObject,
|
|
1687
|
-
simulator.GENARRAY: HierarchyArrayObject,
|
|
1717
|
+
simulator.GENARRAY: HierarchyArrayObject[SimHandleBase],
|
|
1688
1718
|
simulator.PACKAGE: HierarchyObject,
|
|
1689
1719
|
}
|
|
1690
1720
|
|
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
|