cocotb 2.0.0b1__cp39-cp39-win32.whl → 2.0.0rc2__cp39-cp39-win32.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 (95) hide show
  1. cocotb/_ANSI.py +47 -54
  2. cocotb/__init__.py +12 -2
  3. cocotb/_base_triggers.py +11 -9
  4. cocotb/_bridge.py +8 -9
  5. cocotb/_extended_awaitables.py +1 -1
  6. cocotb/_gpi_triggers.py +4 -1
  7. cocotb/_init.py +17 -11
  8. cocotb/_py_compat.py +24 -10
  9. cocotb/_scheduler.py +25 -31
  10. cocotb/_test.py +6 -3
  11. cocotb/_test_factory.py +4 -1
  12. cocotb/_utils.py +1 -23
  13. cocotb/_version.py +1 -1
  14. cocotb/clock.py +98 -16
  15. cocotb/debug.py +24 -0
  16. cocotb/handle.py +62 -32
  17. cocotb/libs/cocotb.dll +0 -0
  18. cocotb/libs/cocotb.exp +0 -0
  19. cocotb/libs/cocotb.lib +0 -0
  20. cocotb/libs/cocotbfli_modelsim.dll +0 -0
  21. cocotb/libs/cocotbfli_modelsim.exp +0 -0
  22. cocotb/libs/cocotbfli_modelsim.lib +0 -0
  23. cocotb/libs/cocotbutils.dll +0 -0
  24. cocotb/libs/cocotbutils.exp +0 -0
  25. cocotb/libs/cocotbutils.lib +0 -0
  26. cocotb/libs/cocotbvhpi_aldec.dll +0 -0
  27. cocotb/libs/cocotbvhpi_aldec.exp +0 -0
  28. cocotb/libs/cocotbvhpi_aldec.lib +0 -0
  29. cocotb/libs/cocotbvhpi_modelsim.dll +0 -0
  30. cocotb/libs/cocotbvhpi_modelsim.exp +0 -0
  31. cocotb/libs/cocotbvhpi_modelsim.lib +0 -0
  32. cocotb/libs/cocotbvpi_aldec.dll +0 -0
  33. cocotb/libs/cocotbvpi_aldec.exp +0 -0
  34. cocotb/libs/cocotbvpi_aldec.lib +0 -0
  35. cocotb/libs/cocotbvpi_ghdl.dll +0 -0
  36. cocotb/libs/cocotbvpi_ghdl.exp +0 -0
  37. cocotb/libs/cocotbvpi_ghdl.lib +0 -0
  38. cocotb/libs/cocotbvpi_icarus.exp +0 -0
  39. cocotb/libs/cocotbvpi_icarus.lib +0 -0
  40. cocotb/libs/cocotbvpi_icarus.vpl +0 -0
  41. cocotb/libs/cocotbvpi_modelsim.dll +0 -0
  42. cocotb/libs/cocotbvpi_modelsim.exp +0 -0
  43. cocotb/libs/cocotbvpi_modelsim.lib +0 -0
  44. cocotb/libs/embed.dll +0 -0
  45. cocotb/libs/embed.exp +0 -0
  46. cocotb/libs/embed.lib +0 -0
  47. cocotb/libs/gpi.dll +0 -0
  48. cocotb/libs/gpi.exp +0 -0
  49. cocotb/libs/gpi.lib +0 -0
  50. cocotb/libs/gpilog.dll +0 -0
  51. cocotb/libs/gpilog.exp +0 -0
  52. cocotb/libs/gpilog.lib +0 -0
  53. cocotb/libs/pygpilog.dll +0 -0
  54. cocotb/libs/pygpilog.exp +0 -0
  55. cocotb/libs/pygpilog.lib +0 -0
  56. cocotb/logging.py +243 -117
  57. cocotb/regression.py +43 -35
  58. cocotb/share/def/aldec.exp +0 -0
  59. cocotb/share/def/aldec.lib +0 -0
  60. cocotb/share/def/ghdl.exp +0 -0
  61. cocotb/share/def/ghdl.lib +0 -0
  62. cocotb/share/def/icarus.exp +0 -0
  63. cocotb/share/def/icarus.lib +0 -0
  64. cocotb/share/def/modelsim.exp +0 -0
  65. cocotb/share/def/modelsim.lib +0 -0
  66. cocotb/share/include/cocotb_utils.h +3 -3
  67. cocotb/share/include/embed.h +2 -2
  68. cocotb/share/include/gpi.h +258 -109
  69. cocotb/share/include/py_gpi_logging.h +3 -3
  70. cocotb/share/lib/verilator/verilator.cpp +23 -15
  71. cocotb/simtime.py +230 -0
  72. cocotb/simulator.cp39-win32.exp +0 -0
  73. cocotb/simulator.cp39-win32.lib +0 -0
  74. cocotb/simulator.cp39-win32.pyd +0 -0
  75. cocotb/task.py +54 -11
  76. cocotb/types/__init__.py +4 -1
  77. cocotb/types/_array.py +33 -2
  78. cocotb/types/_indexing.py +17 -0
  79. cocotb/types/_logic.py +96 -59
  80. cocotb/types/_logic_array.py +56 -22
  81. cocotb/types/_range.py +12 -5
  82. cocotb/utils.py +9 -129
  83. {cocotb-2.0.0b1.dist-info → cocotb-2.0.0rc2.dist-info}/METADATA +1 -1
  84. cocotb-2.0.0rc2.dist-info/RECORD +146 -0
  85. {cocotb-2.0.0b1.dist-info → cocotb-2.0.0rc2.dist-info}/licenses/LICENSE +1 -0
  86. cocotb_tools/config.py +5 -5
  87. cocotb_tools/makefiles/Makefile.inc +3 -9
  88. cocotb_tools/makefiles/Makefile.sim +9 -1
  89. cocotb_tools/makefiles/simulators/Makefile.vcs +1 -1
  90. cocotb_tools/runner.py +94 -59
  91. pygpi/entry.py +5 -6
  92. cocotb-2.0.0b1.dist-info/RECORD +0 -143
  93. {cocotb-2.0.0b1.dist-info → cocotb-2.0.0rc2.dist-info}/WHEEL +0 -0
  94. {cocotb-2.0.0b1.dist-info → cocotb-2.0.0rc2.dist-info}/entry_points.txt +0 -0
  95. {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 lru_cache, update_wrapper, wraps
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
@@ -1,4 +1,4 @@
1
1
  # Package version
2
2
  # Generated by setup.py -- do not modify directly
3
3
 
4
- __version__ = "2.0.0b1"
4
+ __version__ = "2.0.0rc2"
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: The clock 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
- self._period = period
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 *set_action*. *set_action* must be one of Immediate, Deposit, or Force"
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 (unit-less)."""
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(period, t_high, start_high, set_action)
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(t_high)
284
- timer_low = Timer(period - t_high)
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
- # TODO Improve implementation to use a Timer to skip most of the cycles
321
- await ClockCycles(self._signal, num_cycles, edge_type)
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
- raise AttributeError(f"{self._name} contains no object named {name}")
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(_HierarchyObjectBase[int], _RangeableObjectMixin):
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) -> SimHandleBase:
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[SimHandleBase]:
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.IntEnum):
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 deposits <inertial deposit>` the given value on a simulator object.
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 Forces are always immediate.
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 Forces are always immediate.
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 Releases are always immediate.
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 `logic` in Verilog will leave the current value.
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 == _GPISetAction.DEPOSIT:
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
- "Use `handle.set(Immediate(...))` or `handle.value = Immediate(...)` instead.
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 = Immediate(value.value)
953
+ value = _OldImmediate(value.value) # type: ignore
931
954
  elif not isinstance(value, (Force, Freeze, Release, Immediate)):
932
- value = Immediate(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
- return Array._from_handle([self[i].value for i in self.range], self.range)
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
- .. warning::
1047
- Exceptions from array element :meth:`.ValueObjectBase.set` calls will be propagated up,
1048
- so the actual set of exceptions possible is greater than this list.
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(binstr)
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
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
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