cocotb 1.9.2__cp38-cp38-win32.whl → 2.0.0b1__cp38-cp38-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 (155) hide show
  1. cocotb/{ANSI.py → _ANSI.py} +5 -25
  2. cocotb/__init__.py +76 -332
  3. cocotb/_base_triggers.py +513 -0
  4. cocotb/_bridge.py +187 -0
  5. cocotb/_decorators.py +515 -0
  6. cocotb/_deprecation.py +3 -3
  7. cocotb/_exceptions.py +7 -0
  8. cocotb/_extended_awaitables.py +419 -0
  9. cocotb/_gpi_triggers.py +382 -0
  10. cocotb/_init.py +295 -0
  11. cocotb/_outcomes.py +54 -0
  12. cocotb/_profiling.py +46 -0
  13. cocotb/_py_compat.py +100 -29
  14. cocotb/_scheduler.py +454 -0
  15. cocotb/_test.py +245 -0
  16. cocotb/_test_factory.py +309 -0
  17. cocotb/_test_functions.py +42 -0
  18. cocotb/_typing.py +7 -0
  19. cocotb/_utils.py +296 -0
  20. cocotb/_version.py +3 -7
  21. cocotb/_xunit_reporter.py +66 -0
  22. cocotb/clock.py +271 -108
  23. cocotb/handle.py +1342 -795
  24. cocotb/libs/cocotb.dll +0 -0
  25. cocotb/libs/cocotb.exp +0 -0
  26. cocotb/libs/cocotb.lib +0 -0
  27. cocotb/libs/cocotbfli_modelsim.dll +0 -0
  28. cocotb/libs/cocotbfli_modelsim.exp +0 -0
  29. cocotb/libs/cocotbfli_modelsim.lib +0 -0
  30. cocotb/libs/cocotbutils.dll +0 -0
  31. cocotb/libs/cocotbutils.exp +0 -0
  32. cocotb/libs/cocotbutils.lib +0 -0
  33. cocotb/libs/cocotbvhpi_aldec.dll +0 -0
  34. cocotb/libs/cocotbvhpi_aldec.exp +0 -0
  35. cocotb/libs/cocotbvhpi_aldec.lib +0 -0
  36. cocotb/libs/cocotbvhpi_modelsim.dll +0 -0
  37. cocotb/libs/cocotbvhpi_modelsim.exp +0 -0
  38. cocotb/libs/cocotbvhpi_modelsim.lib +0 -0
  39. cocotb/libs/cocotbvpi_aldec.dll +0 -0
  40. cocotb/libs/cocotbvpi_aldec.exp +0 -0
  41. cocotb/libs/cocotbvpi_aldec.lib +0 -0
  42. cocotb/libs/cocotbvpi_ghdl.dll +0 -0
  43. cocotb/libs/cocotbvpi_ghdl.exp +0 -0
  44. cocotb/libs/cocotbvpi_ghdl.lib +0 -0
  45. cocotb/libs/cocotbvpi_icarus.exp +0 -0
  46. cocotb/libs/cocotbvpi_icarus.lib +0 -0
  47. cocotb/libs/cocotbvpi_icarus.vpl +0 -0
  48. cocotb/libs/cocotbvpi_modelsim.dll +0 -0
  49. cocotb/libs/cocotbvpi_modelsim.exp +0 -0
  50. cocotb/libs/cocotbvpi_modelsim.lib +0 -0
  51. cocotb/libs/embed.dll +0 -0
  52. cocotb/libs/embed.exp +0 -0
  53. cocotb/libs/embed.lib +0 -0
  54. cocotb/libs/gpi.dll +0 -0
  55. cocotb/libs/gpi.exp +0 -0
  56. cocotb/libs/gpi.lib +0 -0
  57. cocotb/libs/gpilog.dll +0 -0
  58. cocotb/libs/gpilog.exp +0 -0
  59. cocotb/libs/gpilog.lib +0 -0
  60. cocotb/libs/pygpilog.dll +0 -0
  61. cocotb/libs/pygpilog.exp +0 -0
  62. cocotb/libs/pygpilog.lib +0 -0
  63. cocotb/{log.py → logging.py} +105 -110
  64. cocotb/queue.py +103 -57
  65. cocotb/regression.py +667 -712
  66. cocotb/result.py +17 -188
  67. cocotb/share/def/aldec.exp +0 -0
  68. cocotb/share/def/aldec.lib +0 -0
  69. cocotb/share/def/ghdl.exp +0 -0
  70. cocotb/share/def/ghdl.lib +0 -0
  71. cocotb/share/def/icarus.exp +0 -0
  72. cocotb/share/def/icarus.lib +0 -0
  73. cocotb/share/def/modelsim.def +1 -0
  74. cocotb/share/def/modelsim.exp +0 -0
  75. cocotb/share/def/modelsim.lib +0 -0
  76. cocotb/share/include/cocotb_utils.h +6 -29
  77. cocotb/share/include/embed.h +5 -28
  78. cocotb/share/include/gpi.h +137 -92
  79. cocotb/share/include/gpi_logging.h +221 -142
  80. cocotb/share/include/py_gpi_logging.h +7 -4
  81. cocotb/share/include/vpi_user_ext.h +4 -26
  82. cocotb/share/lib/verilator/verilator.cpp +59 -54
  83. cocotb/simulator.cp38-win32.exp +0 -0
  84. cocotb/simulator.cp38-win32.lib +0 -0
  85. cocotb/simulator.cp38-win32.pyd +0 -0
  86. cocotb/simulator.pyi +107 -0
  87. cocotb/task.py +434 -212
  88. cocotb/triggers.py +55 -1092
  89. cocotb/types/__init__.py +25 -47
  90. cocotb/types/_abstract_array.py +151 -0
  91. cocotb/types/_array.py +264 -0
  92. cocotb/types/_logic.py +296 -0
  93. cocotb/types/_logic_array.py +834 -0
  94. cocotb/types/{range.py → _range.py} +36 -44
  95. cocotb/types/_resolve.py +76 -0
  96. cocotb/utils.py +119 -587
  97. cocotb-2.0.0b1.dist-info/METADATA +46 -0
  98. cocotb-2.0.0b1.dist-info/RECORD +143 -0
  99. {cocotb-1.9.2.dist-info → cocotb-2.0.0b1.dist-info}/WHEEL +1 -1
  100. cocotb-2.0.0b1.dist-info/entry_points.txt +2 -0
  101. {cocotb-1.9.2.dist-info → cocotb-2.0.0b1.dist-info}/top_level.txt +1 -0
  102. cocotb_tools/__init__.py +0 -0
  103. cocotb_tools/_coverage.py +33 -0
  104. cocotb_tools/_vendor/__init__.py +3 -0
  105. cocotb_tools/check_results.py +65 -0
  106. cocotb_tools/combine_results.py +152 -0
  107. cocotb_tools/config.py +241 -0
  108. {cocotb → cocotb_tools}/ipython_support.py +29 -22
  109. cocotb_tools/makefiles/Makefile.deprecations +27 -0
  110. {cocotb/share → cocotb_tools}/makefiles/Makefile.inc +82 -54
  111. {cocotb/share → cocotb_tools}/makefiles/Makefile.sim +8 -33
  112. {cocotb/share → cocotb_tools}/makefiles/simulators/Makefile.activehdl +9 -16
  113. cocotb_tools/makefiles/simulators/Makefile.cvc +61 -0
  114. cocotb_tools/makefiles/simulators/Makefile.dsim +39 -0
  115. {cocotb/share → cocotb_tools}/makefiles/simulators/Makefile.ghdl +13 -42
  116. cocotb_tools/makefiles/simulators/Makefile.icarus +80 -0
  117. cocotb_tools/makefiles/simulators/Makefile.ius +93 -0
  118. cocotb_tools/makefiles/simulators/Makefile.modelsim +9 -0
  119. cocotb_tools/makefiles/simulators/Makefile.nvc +60 -0
  120. cocotb_tools/makefiles/simulators/Makefile.questa +29 -0
  121. cocotb/share/makefiles/simulators/Makefile.questa → cocotb_tools/makefiles/simulators/Makefile.questa-compat +26 -54
  122. cocotb_tools/makefiles/simulators/Makefile.questa-qisqrun +149 -0
  123. {cocotb/share → cocotb_tools}/makefiles/simulators/Makefile.riviera +17 -56
  124. cocotb_tools/makefiles/simulators/Makefile.vcs +65 -0
  125. {cocotb/share → cocotb_tools}/makefiles/simulators/Makefile.verilator +15 -22
  126. {cocotb/share → cocotb_tools}/makefiles/simulators/Makefile.xcelium +20 -52
  127. cocotb_tools/py.typed +0 -0
  128. {cocotb → cocotb_tools}/runner.py +794 -361
  129. cocotb/_sim_versions.py → cocotb_tools/sim_versions.py +16 -21
  130. pygpi/entry.py +34 -17
  131. pygpi/py.typed +0 -0
  132. cocotb/binary.py +0 -858
  133. cocotb/config.py +0 -289
  134. cocotb/decorators.py +0 -332
  135. cocotb/memdebug.py +0 -35
  136. cocotb/outcomes.py +0 -56
  137. cocotb/scheduler.py +0 -1099
  138. cocotb/share/makefiles/Makefile.deprecations +0 -12
  139. cocotb/share/makefiles/simulators/Makefile.cvc +0 -94
  140. cocotb/share/makefiles/simulators/Makefile.icarus +0 -111
  141. cocotb/share/makefiles/simulators/Makefile.ius +0 -125
  142. cocotb/share/makefiles/simulators/Makefile.modelsim +0 -32
  143. cocotb/share/makefiles/simulators/Makefile.nvc +0 -64
  144. cocotb/share/makefiles/simulators/Makefile.vcs +0 -98
  145. cocotb/types/array.py +0 -309
  146. cocotb/types/logic.py +0 -292
  147. cocotb/types/logic_array.py +0 -298
  148. cocotb/wavedrom.py +0 -199
  149. cocotb/xunit_reporter.py +0 -80
  150. cocotb-1.9.2.dist-info/METADATA +0 -168
  151. cocotb-1.9.2.dist-info/RECORD +0 -121
  152. cocotb-1.9.2.dist-info/entry_points.txt +0 -2
  153. /cocotb/{_vendor/__init__.py → py.typed} +0 -0
  154. {cocotb-1.9.2.dist-info → cocotb-2.0.0b1.dist-info}/LICENSE +0 -0
  155. {cocotb → cocotb_tools}/_vendor/distutils_version.py +0 -0
cocotb/utils.py CHANGED
@@ -1,49 +1,30 @@
1
+ # Copyright cocotb contributors
1
2
  # Copyright (c) 2013 Potential Ventures Ltd
2
3
  # Copyright (c) 2013 SolarFlare Communications Inc
3
- # All rights reserved.
4
- #
5
- # Redistribution and use in source and binary forms, with or without
6
- # modification, are permitted provided that the following conditions are met:
7
- # * Redistributions of source code must retain the above copyright
8
- # notice, this list of conditions and the following disclaimer.
9
- # * Redistributions in binary form must reproduce the above copyright
10
- # notice, this list of conditions and the following disclaimer in the
11
- # documentation and/or other materials provided with the distribution.
12
- # * Neither the name of Potential Ventures Ltd,
13
- # SolarFlare Communications Inc nor the
14
- # names of its contributors may be used to endorse or promote products
15
- # derived from this software without specific prior written permission.
16
- #
17
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18
- # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
- # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
- # DISCLAIMED. IN NO EVENT SHALL POTENTIAL VENTURES LTD BE LIABLE FOR ANY
21
- # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
- # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
- # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
- # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
- # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
- # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
-
28
- """Collection of handy functions."""
29
- import ctypes
30
- import functools
31
- import inspect
32
- import math
33
- import os
34
- import sys
35
- import traceback
4
+ # Licensed under the Revised BSD License, see LICENSE for details.
5
+ # SPDX-License-Identifier: BSD-3-Clause
6
+
7
+ """Utility functions for dealing with simulation time."""
8
+
36
9
  import warnings
37
- import weakref
38
10
  from decimal import Decimal
39
- from numbers import Real
40
- from typing import Union
11
+ from fractions import Fraction
12
+ from functools import lru_cache
13
+ from math import ceil, floor
14
+ from typing import Union, overload
41
15
 
42
- import cocotb.ANSI as ANSI
43
16
  from cocotb import simulator
17
+ from cocotb._py_compat import Literal, TypeAlias
18
+ from cocotb._typing import RoundMode, TimeUnit
44
19
 
20
+ __all__ = (
21
+ "get_sim_steps",
22
+ "get_sim_time",
23
+ "get_time_from_sim_steps",
24
+ )
45
25
 
46
- def _get_simulator_precision():
26
+
27
+ def _get_simulator_precision() -> int:
47
28
  # cache and replace this function
48
29
  precision = simulator.get_precision()
49
30
  global _get_simulator_precision
@@ -51,51 +32,58 @@ def _get_simulator_precision():
51
32
  return _get_simulator_precision()
52
33
 
53
34
 
54
- def get_python_integer_types():
55
- warnings.warn(
56
- "This is an internal cocotb function, use six.integer_types instead",
57
- DeprecationWarning,
58
- stacklevel=2,
59
- )
60
- return (int,)
61
-
62
-
63
35
  # Simulator helper functions
64
- def get_sim_time(units: str = "step") -> int:
65
- """Retrieves the simulation time from the simulator.
36
+ def get_sim_time(unit: TimeUnit = "step", *, units: None = None) -> float:
37
+ """Retrieve the simulation time from the simulator.
66
38
 
67
39
  Args:
68
- units: String specifying the units of the result
40
+ unit: String specifying the unit of the result
69
41
  (one of ``'step'``, ``'fs'``, ``'ps'``, ``'ns'``, ``'us'``, ``'ms'``, ``'sec'``).
70
42
  ``'step'`` will return the raw simulation time.
71
43
 
72
- .. deprecated:: 1.6.0
73
- Using ``None`` as the *units* argument is deprecated, use ``'step'`` instead.
44
+ .. versionchanged:: 2.0
45
+ Passing ``None`` as the *unit* argument was removed, use ``'step'`` instead.
74
46
 
75
- Returns:
76
- The simulation time in the specified units.
47
+ .. versionchanged:: 2.0
48
+ Renamed from ``units``.
77
49
 
78
- .. versionchanged:: 1.6.0
79
- Support ``'step'`` as the the *units* argument to mean "simulator time step".
80
- """
81
- timeh, timel = simulator.get_sim_time()
50
+ Raises:
51
+ ValueError: If *unit* is not a valid unit.
82
52
 
83
- result = timeh << 32 | timel
53
+ Returns:
54
+ The simulation time in the specified unit.
84
55
 
85
- if units not in (None, "step"):
86
- result = get_time_from_sim_steps(result, units)
87
- if units is None:
56
+ .. versionchanged:: 1.6
57
+ Support ``'step'`` as the the *unit* argument to mean "simulator time step".
58
+ """
59
+ if units is not None:
88
60
  warnings.warn(
89
- 'Using units=None is deprecated, use units="step" instead.',
61
+ "The 'units' argument has been renamed to 'unit'.",
90
62
  DeprecationWarning,
91
63
  stacklevel=2,
92
64
  )
65
+ unit = units
66
+ timeh, timel = simulator.get_sim_time()
67
+ steps = timeh << 32 | timel
68
+ return get_time_from_sim_steps(steps, unit) if unit != "step" else steps
69
+
70
+
71
+ @overload
72
+ def _ldexp10(frac: float, exp: int) -> float: ...
93
73
 
94
- return result
95
74
 
75
+ @overload
76
+ def _ldexp10(frac: Fraction, exp: int) -> Fraction: ...
96
77
 
97
- def _ldexp10(frac, exp):
98
- """Like math.ldexp, but base 10"""
78
+
79
+ @overload
80
+ def _ldexp10(frac: Decimal, exp: int) -> Decimal: ...
81
+
82
+
83
+ def _ldexp10(
84
+ frac: Union[float, Fraction, Decimal], exp: int
85
+ ) -> Union[float, Fraction, Decimal]:
86
+ """Like :func:`math.ldexp`, but base 10."""
99
87
  # using * or / separately prevents rounding errors if `frac` is a
100
88
  # high-precision type
101
89
  if exp > 0:
@@ -104,23 +92,49 @@ def _ldexp10(frac, exp):
104
92
  return frac / (10**-exp)
105
93
 
106
94
 
107
- def get_time_from_sim_steps(steps: int, units: str) -> int:
108
- """Calculates simulation time in the specified *units* from the *steps* based
95
+ def get_time_from_sim_steps(
96
+ steps: int,
97
+ unit: Union[TimeUnit, None] = None,
98
+ *,
99
+ units: None = None,
100
+ ) -> float:
101
+ """Calculate simulation time in the specified *unit* from the *steps* based
109
102
  on the simulator precision.
110
103
 
111
104
  Args:
112
105
  steps: Number of simulation steps.
113
- units: String specifying the units of the result
106
+ unit: String specifying the unit of the result
114
107
  (one of ``'fs'``, ``'ps'``, ``'ns'``, ``'us'``, ``'ms'``, ``'sec'``).
115
108
 
109
+ .. versionchanged:: 2.0
110
+ Renamed from ``units``.
111
+
112
+ Raises:
113
+ ValueError: If *unit* is not a valid unit.
114
+
116
115
  Returns:
117
- The simulation time in the specified units.
116
+ The simulation time in the specified unit.
118
117
  """
119
- return _ldexp10(steps, _get_simulator_precision() - _get_log_time_scale(units))
118
+ if units is not None:
119
+ warnings.warn(
120
+ "The 'units' argument has been renamed to 'unit'.",
121
+ DeprecationWarning,
122
+ stacklevel=2,
123
+ )
124
+ unit = units
125
+ if unit is None:
126
+ raise TypeError("Missing required argument 'unit'")
127
+ if unit == "step":
128
+ return steps
129
+ return _ldexp10(steps, _get_simulator_precision() - _get_log_time_scale(unit))
120
130
 
121
131
 
122
132
  def get_sim_steps(
123
- time: Union[Real, Decimal], units: str = "step", *, round_mode: str = "error"
133
+ time: Union[float, Fraction, Decimal],
134
+ unit: TimeUnit = "step",
135
+ *,
136
+ round_mode: RoundMode = "error",
137
+ units: None = None,
124
138
  ) -> int:
125
139
  """Calculates the number of simulation time steps for a given amount of *time*.
126
140
 
@@ -132,9 +146,13 @@ def get_sim_steps(
132
146
 
133
147
  Args:
134
148
  time: The value to convert to simulation time steps.
135
- units: String specifying the units of the result
149
+ unit: String specifying the unit of the result
136
150
  (one of ``'step'``, ``'fs'``, ``'ps'``, ``'ns'``, ``'us'``, ``'ms'``, ``'sec'``).
137
151
  ``'step'`` means *time* is already in simulation time steps.
152
+
153
+ .. versionchanged:: 2.0
154
+ Renamed from ``units``.
155
+
138
156
  round_mode: String specifying how to handle time values that sit between time steps
139
157
  (one of ``'error'``, ``'round'``, ``'ceil'``, ``'floor'``).
140
158
 
@@ -146,553 +164,67 @@ def get_sim_steps(
146
164
  time steps when *round_mode* is ``"error"``.
147
165
 
148
166
  .. versionchanged:: 1.5
149
- Support ``'step'`` as the *units* argument to mean "simulator time step".
167
+ Support ``'step'`` as the *unit* argument to mean "simulator time step".
150
168
 
151
169
  .. versionchanged:: 1.6
152
170
  Support rounding modes.
153
171
  """
154
- if units not in (None, "step"):
155
- result = _ldexp10(time, _get_log_time_scale(units) - _get_simulator_precision())
156
- else:
157
- result = time
158
- if units is None:
172
+ if units is not None:
159
173
  warnings.warn(
160
- 'Using units=None is deprecated, use units="step" instead.',
174
+ "The 'units' argument has been renamed to 'unit'.",
161
175
  DeprecationWarning,
162
176
  stacklevel=2,
163
177
  )
164
- units = "step" # don't propagate deprecated value
178
+ unit = units
179
+ result: Union[float, Fraction, Decimal]
180
+ if unit != "step":
181
+ result = _ldexp10(time, _get_log_time_scale(unit) - _get_simulator_precision())
182
+ else:
183
+ result = time
165
184
 
166
185
  if round_mode == "error":
167
- result_rounded = math.floor(result)
186
+ result_rounded = floor(result)
168
187
  if result_rounded != result:
169
188
  precision = _get_simulator_precision()
170
189
  raise ValueError(
171
- f"Unable to accurately represent {time}({units}) with the simulator precision of 1e{precision}"
190
+ f"Unable to accurately represent {time}({unit}) with the simulator precision of 1e{precision}"
172
191
  )
173
192
  elif round_mode == "ceil":
174
- result_rounded = math.ceil(result)
193
+ result_rounded = ceil(result)
175
194
  elif round_mode == "round":
176
195
  result_rounded = round(result)
177
196
  elif round_mode == "floor":
178
- result_rounded = math.floor(result)
197
+ result_rounded = floor(result)
179
198
  else:
180
199
  raise ValueError(f"Invalid round_mode specifier: {round_mode}")
181
200
 
182
201
  return result_rounded
183
202
 
184
203
 
185
- def _get_log_time_scale(units):
186
- """Retrieves the ``log10()`` of the scale factor for a given time unit.
187
-
188
- Args:
189
- units (str): String specifying the units
190
- (one of ``'fs'``, ``'ps'``, ``'ns'``, ``'us'``, ``'ms'``, ``'sec'``).
191
-
192
- Returns:
193
- The ``log10()`` of the scale factor for the time unit.
194
- """
195
- scale = {"fs": -15, "ps": -12, "ns": -9, "us": -6, "ms": -3, "sec": 0}
196
-
197
- units_lwr = units.lower()
198
- if units_lwr not in scale:
199
- raise ValueError(f"Invalid unit ({units}) provided")
200
- else:
201
- return scale[units_lwr]
202
-
203
-
204
- # Ctypes helper functions
204
+ TimeUnitWithoutSteps: TypeAlias = Literal["fs", "ps", "ns", "us", "ms", "sec"]
205
205
 
206
206
 
207
- def pack(ctypes_obj):
208
- """Convert a :mod:`ctypes` structure into a Python string.
207
+ @lru_cache(maxsize=None)
208
+ def _get_log_time_scale(unit: TimeUnitWithoutSteps) -> int:
209
+ """Retrieves the ``log10()`` of the scale factor for a given time unit.
209
210
 
210
211
  Args:
211
- ctypes_obj (ctypes.Structure): The :mod:`ctypes` structure to convert to a string.
212
-
213
- Returns:
214
- New Python string containing the bytes from memory holding *ctypes_obj*.
215
-
216
- .. deprecated:: 1.5
217
- This function is deprecated, use ``bytes(ctypes_obj)`` instead.
218
- """
219
- warnings.warn(
220
- "This function is deprecated and will be removed, use ``bytes(ctypes_obj)`` instead.",
221
- DeprecationWarning,
222
- stacklevel=2,
223
- )
224
- return ctypes.string_at(ctypes.addressof(ctypes_obj), ctypes.sizeof(ctypes_obj))
225
-
226
-
227
- def unpack(ctypes_obj, string, bytes=None):
228
- """Unpack a Python string into a :mod:`ctypes` structure.
229
-
230
- If the length of *string* is not the correct size for the memory
231
- footprint of the :mod:`ctypes` structure then the *bytes* keyword argument
232
- must be used.
212
+ unit: String specifying the unit
213
+ (one of ``'fs'``, ``'ps'``, ``'ns'``, ``'us'``, ``'ms'``, ``'sec'``).
233
214
 
234
- Args:
235
- ctypes_obj (ctypes.Structure): The :mod:`ctypes` structure to pack into.
236
- string (str): String to copy over the *ctypes_obj* memory space.
237
- bytes (int, optional): Number of bytes to copy.
238
- Defaults to ``None``, meaning the length of *string* is used.
215
+ .. versionchanged:: 2.0
216
+ Renamed from ``units``.
239
217
 
240
218
  Raises:
241
- :exc:`ValueError`: If length of *string* and size of *ctypes_obj*
242
- are not equal.
243
- :exc:`MemoryError`: If *bytes* is longer than size of *ctypes_obj*.
244
-
245
- .. deprecated:: 1.5
246
- Converting bytes to a ctypes object should be done with :meth:`~ctypes._CData.from_buffer_copy`.
247
- If you need to assign bytes into an *existing* ctypes object, use ``memoryview(ctypes_obj).cast('B')[:bytes] = string``,
248
- see :class:`memoryview` for details.
249
- """
250
- warnings.warn(
251
- "This function is being removed, use ``memoryview(ctypes_obj).cast('B')[:bytes] = string`` instead.",
252
- DeprecationWarning,
253
- stacklevel=2,
254
- )
255
- if bytes is None:
256
- if len(string) != ctypes.sizeof(ctypes_obj):
257
- raise ValueError(
258
- "Attempt to unpack a string of size %d into a \
259
- struct of size %d"
260
- % (len(string), ctypes.sizeof(ctypes_obj))
261
- )
262
- bytes = len(string)
263
-
264
- if bytes > ctypes.sizeof(ctypes_obj):
265
- raise MemoryError(
266
- "Attempt to unpack %d bytes over an object \
267
- of size %d"
268
- % (bytes, ctypes.sizeof(ctypes_obj))
269
- )
270
-
271
- ctypes.memmove(ctypes.addressof(ctypes_obj), string, bytes)
272
-
273
-
274
- # A note on the use of latin1 in the deprecations below:
275
- # Latin1 is the only encoding `e` that satisfies
276
- # `all(chr(x).encode(e) == bytes([x]) for x in range(255))`
277
- # Our use of `ord` and `chr` throughout other bits of code make this the most
278
- # compatible choice of encoding. Under this convention, old code can be upgraded
279
- # by changing "binary" strings from `"\x12\x34"` to `b"\x12\x34"`.
280
-
281
-
282
- def _sane(x: bytes) -> str:
283
- r = ""
284
- for j in x:
285
- if (j < 32) or (j >= 127):
286
- r += "."
287
- else:
288
- r += chr(j)
289
- return r
290
-
291
-
292
- def hexdump(x: bytes) -> str:
293
- """Hexdump a buffer.
294
-
295
- Args:
296
- x: Object that supports conversion to :class:`bytes`.
219
+ ValueError: If *unit* is not a valid unit.
297
220
 
298
221
  Returns:
299
- A string containing the hexdump.
300
-
301
- .. deprecated:: 1.4
302
- Passing a :class:`str` to this function is deprecated, as it
303
- is not an appropriate type for binary data. Doing so anyway
304
- will encode the string to ``latin1``.
305
-
306
- .. deprecated:: 1.6.0
307
- The function will be removed in the next major version.
308
- Use :func:`scapy.utils.hexdump` instead.
309
-
310
- Example:
311
- >>> print(hexdump(b'this somewhat long string'))
312
- 0000 74 68 69 73 20 73 6F 6D 65 77 68 61 74 20 6C 6F this somewhat lo
313
- 0010 6E 67 20 73 74 72 69 6E 67 ng string
314
- <BLANKLINE>
315
- """
316
- # adapted from scapy.utils.hexdump
317
- warnings.warn(
318
- "cocotb.utils.hexdump is deprecated. Use scapy.utils.hexdump instead.",
319
- DeprecationWarning,
320
- stacklevel=2,
321
- )
322
- rs = ""
323
- if isinstance(x, str):
324
- warnings.warn(
325
- "Passing a string to hexdump is deprecated, pass bytes instead",
326
- DeprecationWarning,
327
- stacklevel=2,
328
- )
329
- x = x.encode("latin1")
330
- x = b"%b" % x
331
- l = len(x)
332
- i = 0
333
- while i < l:
334
- rs += "%04x " % i
335
- for j in range(16):
336
- if i + j < l:
337
- rs += "%02X " % x[i + j]
338
- else:
339
- rs += " "
340
- if j % 16 == 7:
341
- rs += ""
342
- rs += " "
343
- rs += _sane(x[i : i + 16]) + "\n"
344
- i += 16
345
- return rs
346
-
347
-
348
- def hexdiffs(x: bytes, y: bytes) -> str:
349
- r"""Return a diff string showing differences between two binary strings.
350
-
351
- Args:
352
- x: Object that supports conversion to :class:`bytes`.
353
- y: Object that supports conversion to :class:`bytes`.
354
-
355
- .. deprecated:: 1.4
356
- Passing :class:`str`\ s to this function is deprecated, as it
357
- is not an appropriate type for binary data. Doing so anyway
358
- will encode the string to ``latin1``.
359
-
360
- .. deprecated:: 1.6.0
361
- The function will be removed in the next major version.
362
- Use :func:`scapy.utils.hexdiff` instead.
363
-
364
- Example:
365
- >>> print(hexdiffs(b'a', b'b'))
366
- 0000 61 a
367
- 0000 62 b
368
- <BLANKLINE>
369
- >>> print(hexdiffs(b'this short thing', b'this also short'))
370
- 0000 746869732073686F 7274207468696E67 this short thing
371
- 0000 7468697320616C73 6F 2073686F7274 this also short
372
- <BLANKLINE>
373
- """
374
- # adapted from scapy.utils.hexdiff
375
- warnings.warn(
376
- "cocotb.utils.hexdiffs is deprecated. Use scapy.utils.hexdiff instead.",
377
- DeprecationWarning,
378
- stacklevel=2,
379
- )
380
-
381
- def highlight(string: str, colour=ANSI.COLOR_HILITE_HEXDIFF_DEFAULT) -> str:
382
- """Highlight with ANSI colors if possible/requested and not running in GUI."""
383
-
384
- if want_color_output():
385
- return colour + string + ANSI.COLOR_DEFAULT
386
- else:
387
- return string
388
-
389
- x_is_str = isinstance(x, str)
390
- y_is_str = isinstance(y, str)
391
- if x_is_str or y_is_str:
392
- warnings.warn(
393
- "Passing strings to hexdiffs is deprecated, pass bytes instead",
394
- DeprecationWarning,
395
- stacklevel=2,
396
- )
397
- if x_is_str:
398
- x = x.encode("latin1")
399
- if y_is_str:
400
- y = y.encode("latin1")
401
-
402
- rs = ""
403
-
404
- x = (b"%b" % x)[::-1]
405
- y = (b"%b" % y)[::-1]
406
- SUBST = 1
407
- INSERT = 1
408
- d = {}
409
- d[-1, -1] = 0, (-1, -1)
410
- for j in range(len(y)):
411
- d[-1, j] = d[-1, j - 1][0] + INSERT, (-1, j - 1)
412
- for i in range(len(x)):
413
- d[i, -1] = d[i - 1, -1][0] + INSERT, (i - 1, -1)
414
-
415
- for j in range(len(y)):
416
- for i in range(len(x)):
417
- d[i, j] = min(
418
- (d[i - 1, j - 1][0] + SUBST * (x[i] != y[j]), (i - 1, j - 1)),
419
- (d[i - 1, j][0] + INSERT, (i - 1, j)),
420
- (d[i, j - 1][0] + INSERT, (i, j - 1)),
421
- )
422
-
423
- backtrackx = []
424
- backtracky = []
425
- i = len(x) - 1
426
- j = len(y) - 1
427
- while not (i == j == -1):
428
- i2, j2 = d[i, j][1]
429
- backtrackx.append(x[i2 + 1 : i + 1])
430
- backtracky.append(y[j2 + 1 : j + 1])
431
- i, j = i2, j2
432
-
433
- x = y = i = 0
434
- colorize = {0: lambda x: x, -1: lambda x: x, 1: lambda x: x} # noqa # noqa # noqa
435
-
436
- dox = 1
437
- doy = 0
438
- l = len(backtrackx)
439
- while i < l:
440
- linex = backtrackx[i : i + 16]
441
- liney = backtracky[i : i + 16]
442
- xx = sum(len(k) for k in linex)
443
- yy = sum(len(k) for k in liney)
444
- if dox and not xx:
445
- dox = 0
446
- doy = 1
447
- if dox and linex == liney:
448
- doy = 1
449
-
450
- if dox:
451
- xd = y
452
- j = 0
453
- while not linex[j]:
454
- j += 1
455
- xd -= 1
456
- if dox != doy:
457
- rs += highlight("%04x" % xd) + " "
458
- else:
459
- rs += highlight("%04x" % xd, colour=ANSI.COLOR_HILITE_HEXDIFF_1) + " "
460
- x += xx
461
- line = linex
462
- else:
463
- rs += " "
464
- if doy:
465
- yd = y
466
- j = 0
467
- while not liney[j]:
468
- j += 1
469
- yd -= 1
470
- if doy - dox != 0:
471
- rs += " " + highlight("%04x" % yd)
472
- else:
473
- rs += highlight("%04x" % yd, colour=ANSI.COLOR_HILITE_HEXDIFF_1)
474
- y += yy
475
- line = liney
476
- else:
477
- rs += " "
478
-
479
- rs += " "
480
-
481
- cl = ""
482
- for j in range(16):
483
- if i + j < l:
484
- if line[j]:
485
- (char_j,) = line[j]
486
- if linex[j] != liney[j]:
487
- rs += highlight(
488
- "%02X" % char_j, colour=ANSI.COLOR_HILITE_HEXDIFF_2
489
- )
490
- else:
491
- rs += "%02X" % char_j
492
- if linex[j] == liney[j]:
493
- cl += highlight(
494
- _sane(line[j]), colour=ANSI.COLOR_HILITE_HEXDIFF_3
495
- )
496
- else:
497
- cl += highlight(
498
- _sane(line[j]), colour=ANSI.COLOR_HILITE_HEXDIFF_4
499
- )
500
- else:
501
- rs += " "
502
- cl += " "
503
- else:
504
- rs += " "
505
- if j == 7:
506
- rs += " "
507
-
508
- rs += " " + cl + "\n"
509
-
510
- if doy or not yy:
511
- doy = 0
512
- dox = 1
513
- i += 16
514
- else:
515
- if yy:
516
- dox = 0
517
- doy = 1
518
- else:
519
- i += 16
520
- return rs
521
-
522
-
523
- class ParametrizedSingleton(type):
524
- """A metaclass that allows class construction to reuse an existing instance.
525
-
526
- We use this so that :class:`RisingEdge(sig) <cocotb.triggers.RisingEdge>` and :class:`Join(coroutine) <cocotb.triggers.Join>` always return
527
- the same instance, rather than creating new copies.
528
- """
529
-
530
- def __init__(cls, *args, **kwargs):
531
- # Attach a lookup table to this class.
532
- # Weak such that if the instance is no longer referenced, it can be
533
- # collected.
534
- cls.__instances = weakref.WeakValueDictionary()
535
-
536
- def __singleton_key__(cls, *args, **kwargs):
537
- """Convert the construction arguments into a normalized representation that
538
- uniquely identifies this singleton.
539
- """
540
- # Could default to something like this, but it would be slow
541
- # return tuple(inspect.Signature(cls).bind(*args, **kwargs).arguments.items())
542
- raise NotImplementedError
543
-
544
- def __call__(cls, *args, **kwargs):
545
- key = cls.__singleton_key__(*args, **kwargs)
546
- try:
547
- return cls.__instances[key]
548
- except KeyError:
549
- # construct the object as normal
550
- self = super().__call__(*args, **kwargs)
551
- cls.__instances[key] = self
552
- return self
553
-
554
- @property
555
- def __signature__(cls):
556
- return inspect.signature(cls.__singleton_key__)
557
-
558
-
559
- def reject_remaining_kwargs(name, kwargs):
560
- """
561
- Helper function to emulate Python 3 keyword-only arguments.
562
-
563
- Use as::
564
-
565
- def func(x1, **kwargs):
566
- a = kwargs.pop('a', 1)
567
- b = kwargs.pop('b', 2)
568
- reject_remaining_kwargs('func', kwargs)
569
- ...
570
-
571
- To emulate the Python 3 syntax::
572
-
573
- def func(x1, *, a=1, b=2):
574
- ...
575
-
576
- .. deprecated:: 1.4
577
- Since the minimum supported Python version is now 3.5, this function
578
- is not needed.
579
- """
580
- warnings.warn(
581
- "reject_remaining_kwargs is deprecated and will be removed, use "
582
- "Python 3 keyword-only arguments directly.",
583
- DeprecationWarning,
584
- stacklevel=2,
585
- )
586
- if kwargs:
587
- # match the error message to what Python 3 produces
588
- bad_arg = next(iter(kwargs))
589
- raise TypeError(f"{name}() got an unexpected keyword argument {bad_arg!r}")
590
-
591
-
592
- class lazy_property:
593
- """
594
- A property that is executed the first time, then cached forever.
595
-
596
- It does this by replacing itself on the instance, which works because
597
- unlike `@property` it does not define __set__.
598
-
599
- This should be used for expensive members of objects that are not always
600
- used.
601
- """
602
-
603
- def __init__(self, fget):
604
- self.fget = fget
605
-
606
- # copy the getter function's docstring and other attributes
607
- functools.update_wrapper(self, fget)
608
-
609
- def __get__(self, obj, cls):
610
- if obj is None:
611
- return self
612
-
613
- value = self.fget(obj)
614
- setattr(obj, self.fget.__qualname__, value)
615
- return value
616
-
617
-
618
- def want_color_output():
619
- """Return ``True`` if colored output is possible/requested and not running in GUI.
620
-
621
- Colored output can be explicitly requested by setting :envvar:`COCOTB_ANSI_OUTPUT` to ``1``.
622
- """
623
- want_color = sys.stdout.isatty() # default to color for TTYs
624
- if os.getenv("NO_COLOR") is not None:
625
- want_color = False
626
- if os.getenv("COCOTB_ANSI_OUTPUT", default="0") == "1":
627
- want_color = True
628
- if os.getenv("GUI", default="0") == "1":
629
- want_color = False
630
- return want_color
631
-
632
-
633
- def remove_traceback_frames(tb_or_exc, frame_names):
222
+ The ``log10()`` of the scale factor for the time unit.
634
223
  """
635
- Strip leading frames from a traceback
224
+ scale = {"fs": -15, "ps": -12, "ns": -9, "us": -6, "ms": -3, "sec": 0}
636
225
 
637
- Args:
638
- tb_or_exc (Union[traceback, BaseException, exc_info]):
639
- Object to strip frames from. If an exception is passed, creates
640
- a copy of the exception with a new shorter traceback. If a tuple
641
- from `sys.exc_info` is passed, returns the same tuple with the
642
- traceback shortened
643
- frame_names (List[str]):
644
- Names of the frames to strip, which must be present.
645
- """
646
- # self-invoking overloads
647
- if isinstance(tb_or_exc, BaseException):
648
- exc = tb_or_exc
649
- return exc.with_traceback(
650
- remove_traceback_frames(exc.__traceback__, frame_names)
651
- )
652
- elif isinstance(tb_or_exc, tuple):
653
- exc_type, exc_value, exc_tb = tb_or_exc
654
- exc_tb = remove_traceback_frames(exc_tb, frame_names)
655
- return exc_type, exc_value, exc_tb
656
- # base case
226
+ unit_lwr = unit.lower()
227
+ if unit_lwr not in scale:
228
+ raise ValueError(f"Invalid unit ({unit}) provided")
657
229
  else:
658
- tb = tb_or_exc
659
- for frame_name in frame_names:
660
- assert tb.tb_frame.f_code.co_name == frame_name
661
- tb = tb.tb_next
662
- return tb
663
-
664
-
665
- def walk_coro_stack(coro):
666
- """Walk down the coroutine stack, starting at *coro*.
667
-
668
- Supports coroutines and generators.
669
- """
670
- while coro is not None:
671
- try:
672
- f = getattr(coro, "cr_frame")
673
- coro = coro.cr_await
674
- except AttributeError:
675
- try:
676
- f = getattr(coro, "gi_frame")
677
- coro = coro.gi_yieldfrom
678
- except AttributeError:
679
- f = None
680
- coro = None
681
- if f is not None:
682
- yield (f, f.f_lineno)
683
-
684
-
685
- def extract_coro_stack(coro, limit=None):
686
- """Create a list of pre-processed entries from the coroutine stack.
687
-
688
- This is based on :func:`traceback.extract_tb`.
689
-
690
- If *limit* is omitted or ``None``, all entries are extracted.
691
- The list is a :class:`traceback.StackSummary` object, and
692
- each entry in the list is a :class:`traceback.FrameSummary` object
693
- containing attributes ``filename``, ``lineno``, ``name``, and ``line``
694
- representing the information that is usually printed for a stack
695
- trace. The line is a string with leading and trailing
696
- whitespace stripped; if the source is not available it is ``None``.
697
- """
698
- return traceback.StackSummary.extract(walk_coro_stack(coro), limit=limit)
230
+ return scale[unit_lwr]