Library Reference

Python Test Runner

Warning

Python runners and associated APIs are an experimental feature and subject to change.

Build HDL and run cocotb tests.

cocotb_tools.runner.shlex_join(split_command)[source]

Return a shell-escaped string from split_command This is here more for compatibility purposes

class cocotb_tools.runner.Simulator[source]
build(hdl_library='top', verilog_sources=[], vhdl_sources=[], includes=[], defines={}, parameters={}, build_args=[], hdl_toplevel=None, always=False, build_dir='sim_build', clean=False, verbose=False, timescale=None, waves=None, log_file=None)[source]

Build the HDL sources.

Parameters:
  • hdl_library (str) – The library name to compile into.

  • verilog_sources (Sequence[PathLike[str] | str]) – Verilog source files to build.

  • vhdl_sources (Sequence[PathLike[str] | str]) – VHDL source files to build.

  • includes (Sequence[PathLike[str] | str]) – Verilog include directories.

  • defines (Mapping[str, object]) – Defines to set.

  • parameters (Mapping[str, object]) – Verilog parameters or VHDL generics.

  • build_args (Sequence[str]) – Extra build arguments for the simulator.

  • hdl_toplevel (str | None) – The name of the HDL toplevel module.

  • always (bool) – Always run the build step.

  • build_dir (PathLike[str] | str) – Directory to run the build step in.

  • clean (bool) – Delete build_dir before building.

  • verbose (bool) – Enable verbose messages.

  • timescale (Tuple[str, str] | None) – Tuple containing time unit and time precision for simulation.

  • waves (bool | None) – Record signal traces.

  • log_file (PathLike[str] | str | None) – File to write the build log to.

Return type:

None

test(test_module, hdl_toplevel, hdl_toplevel_library='top', hdl_toplevel_lang=None, gpi_interfaces=None, testcase=None, seed=None, test_args=[], plusargs=[], extra_env={}, waves=None, gui=None, parameters=None, build_dir=None, test_dir=None, results_xml=None, pre_cmd=[], verbose=False, timescale=None, log_file=None)[source]

Run the tests.

Parameters:
  • test_module (str | Sequence[str]) – Name(s) of the Python module(s) containing the tests to run. Can be a comma-separated list.

  • hdl_toplevel (str) – Name of the HDL toplevel module.

  • hdl_toplevel_library (str) – The library name for HDL toplevel module.

  • hdl_toplevel_lang (str | None) – Language of the HDL toplevel module.

  • gpi_interfaces (List[str] | None) – List of GPI interfaces to use, with the first one being the entry point.

  • testcase (str | Sequence[str] | None) – Name(s) of a specific testcase(s) to run. If not set, run all testcases found in test_module. Can be a comma-separated list.

  • seed (str | int | None) – A specific random seed to use.

  • test_args (Sequence[str]) – A list of extra arguments for the simulator.

  • plusargs (Sequence[str]) – ‘plusargs’ to set for the simulator.

  • extra_env (Mapping[str, str]) – Extra environment variables to set.

  • waves (bool | None) – Record signal traces.

  • gui (bool | None) – Run with simulator GUI.

  • parameters (Mapping[str, object]) – Verilog parameters or VHDL generics.

  • build_dir (PathLike[str] | str | None) – Directory the build step has been run in.

  • test_dir (PathLike[str] | str | None) – Directory to run the tests in.

  • results_xml (str | None) – Name of xUnit XML file to store test results in. If an absolute path is provided it will be used as-is, {build_dir}/results.xml otherwise. This argument should not be set when run with pytest.

  • verbose (bool) – Enable verbose messages.

  • pre_cmd (List[str]) – Commands to run before simulation begins. Typically Tcl commands for simulators that support them.

  • timescale (Tuple[str, str] | None) – Tuple containing time unit and time precision for simulation.

  • log_file (PathLike[str] | str | None) – File to write the test log to.

Returns:

The absolute location of the results XML file which can be defined by the results_xml argument.

Return type:

Path

cocotb_tools.runner.get_results(results_xml_file)[source]

Return number of tests and fails in results_xml_file.

Returns:

Tuple of number of tests and number of fails.

Raises:

SystemExitresults_xml_file is non-existent.

Parameters:

results_xml_file (Path) –

Return type:

Tuple[int, int]

cocotb_tools.runner.check_results_file(results_xml_file)[source]

Raise exception if results_xml_file does not exist or contains failed tests.

Raises:

SystemExitresults_xml_file is non-existent or contains fails.

Parameters:

results_xml_file (Path) –

Return type:

None

cocotb_tools.runner.outdated(output, dependencies)[source]

Return True if any source files in dependencies are newer than the output directory.

Returns:

True if any source files are newer, False otherwise.

Parameters:
Return type:

bool

cocotb_tools.runner.get_abs_path(path)[source]

Return path in absolute form.

Parameters:

path (PathLike[str] | str) –

Return type:

Path

cocotb_tools.runner.get_abs_paths(paths)[source]

Return list of paths in absolute form.

Parameters:

paths (Sequence[PathLike[str] | str]) –

Return type:

List[Path]

class cocotb_tools.runner.Icarus[source]
class cocotb_tools.runner.Questa[source]
class cocotb_tools.runner.Ghdl[source]
class cocotb_tools.runner.Nvc[source]
class cocotb_tools.runner.Riviera[source]
class cocotb_tools.runner.Verilator[source]
class cocotb_tools.runner.Xcelium[source]
cocotb_tools.runner.get_runner(simulator_name)[source]

Return an instance of a runner for simulator_name.

Parameters:

simulator_name (str) – Name of simulator to get runner for.

Raises:

ValueError – If simulator_name is not one of the supported simulators or an alias of one.

Return type:

Simulator

Test Results

The exceptions in this module can be raised at any point by any code and will terminate the test.

Exceptions and functions for simulation result handling.

exception cocotb.result.TestComplete[source]

Exception showing that the test was completed. Sub-exceptions detail the exit status.

Changed in version 2.0: The stdout and stderr attributes were removed.

exception cocotb.result.ExternalException(exception)[source]

Exception thrown by cocotb.external functions.

exception cocotb.result.TestSuccess[source]

Exception showing that the test was completed successfully.

exception cocotb.result.SimFailure[source]

Exception showing that the simulator exited unsuccessfully.

exception cocotb.result.SimTimeoutError[source]

Exception for when a timeout, in terms of simulation time, occurs.

Writing and Generating tests

cocotb.test(_func: F | _Parameterized[F]) F[source]
cocotb.test(*, timeout_time: float | None = None, timeout_unit: str = 'step', expect_fail: bool = False, expect_error: Type[Exception] | Sequence[Type[Exception]] = (), skip: bool = False, stage: int = 0, name: str | None = None) Callable[[F | _Parameterized[F]], F]

Decorator to register a Callable which returns a Coroutine as a test.

The test decorator provides a test timeout, and allows us to mark tests as skipped or expecting errors or failures. Tests are evaluated in the order they are defined in a test module.

Usage:
@cocotb.test(timeout_time=10, timeout_unit="ms")
async def test_thing(dut): ...

Changed in version 2.0: Support using decorator on test function without supplying parameters first.

Assumes all default values for the test parameters.

@cocotb.test
async def test_thing(dut): ...

Changed in version 2.0: Decorated tests now return the decorated object.

Parameters:
  • timeout_time

    Simulation time duration before timeout occurs.

    New in version 1.3.

    Note

    Test timeout is intended for protection against deadlock. Users should use with_timeout if they require a more general-purpose timeout mechanism.

  • timeout_unit

    Units of timeout_time, accepts any units that Timer does.

    New in version 1.3.

    Changed in version 2.0: Passing None as the timeout_unit argument was removed, use 'step' instead.

  • expect_fail – If True and the test fails a functional check via an assert statement, pytest.raises, pytest.warns, or pytest.deprecated_call the test is considered to have passed. If True and the test passes successfully, the test is considered to have failed.

  • expect_error

    Mark the result as a pass only if one of the exception types is raised in the test. This is primarily for cocotb internal regression use for when a simulator error is expected.

    Users are encouraged to use the following idiom instead:

    @cocotb.test()
    async def my_test(dut):
        try:
            await thing_that_should_fail()
        except ExceptionIExpect:
            pass
        else:
            assert False, "Exception did not occur"
    

    Changed in version 1.3: Specific exception types can be expected

    Changed in version 2.0: Passing a bool value was removed. Pass a specific Exception or a tuple of Exceptions instead.

  • skip – Don’t execute this test as part of the regression. Test can still be run manually by setting TESTCASE.

  • stage – Order tests logically into stages, where multiple tests can share a stage. Defaults to 0.

  • name

    Override the default name of the test. The default test name is the __qualname__ of the decorated test function.

    New in version 2.0.

Returns:

The test function to which the decorator is applied.

cocotb.external(func)[source]

Decorator that turns a blocking function into a coroutine function.

When the returned async function is called, it creates a coroutine object that can be directly awaited or constructed into a Task. The coroutine will suspend the awaiting task until the wrapped function completes in its thread, and the result of the function will be returned from the coroutine. Currently, this creates a new execution thread for each function that is called.

Parameters:

func (Callable[[...], Result]) – The function to run externally.

Returns:

The coroutine function.

Return type:

Callable[[…], Coroutine[Any, Any, Result]]

Changed in version 2.0: No longer implemented as a unique type. The log attribute is no longer available.

cocotb.function(func)[source]

Decorator that turns a coroutine function into a blocking function.

This allows an async function that yields to the simulator and consumes simulation time to be called by a thread started with cocotb.external. When the returned blocking function is called, a new Task is constructed from the async function, passing through any arguments provided by the caller, and scheduled on the main thread. The external caller thread will block until the task finishes, and the result will be returned to the caller of the blocking function.

Parameters:

func (Callable[[...], Coroutine[Any, Any, Result]]) – The coroutine function to wrap/convert.

Returns:

The function to be called.

Raises:

RuntimeError – If the blocking function that is returned is subsequently called from a thread that was not started with cocotb.external.

Return type:

Callable[[…], Result]

Changed in version 2.0: No longer implemented as a unique type. The log attribute is no longer available.

cocotb.parameterize(*options_by_tuple, **options_by_name)[source]

Decorator to generate parameterized tests from a single test function.

Decorates a test function with named test parameters. The call to parameterize should include the name of each test parameter and the possible values each parameter can hold. This will generate a test for each of the Cartesian products of the parameters and their values.

@cocotb.test(
    skip=False,
)
@cocotb.parameterize(
    arg1=[0, 1],
    arg2=["a", "b"],
)
async def my_test(arg1: int, arg2: str) -> None: ...

The above is equivalent to the following.

@cocotb.test(skip=False)
async def my_test_0_a() -> None:
    arg1, arg2 = 0, "a"
    ...


@cocotb.test(skip=False)
async def my_test_0_b() -> None:
    arg1, arg2 = 0, "b"
    ...


@cocotb.test(skip=False)
async def my_test_1_a() -> None:
    arg1, arg2 = 1, "a"
    ...


@cocotb.test(skip=False)
async def my_test_1_b() -> None:
    arg1, arg2 = 1, "b"
    ...

Options can also be specified in much the same way that TestFactory.add_option can, either by supplying tuples of the parameter name to values, or a sequence of variable names and a sequence of values.

@cocotb.parameterize(
    ("arg1", [0, 1]),
    (("arg2", arg3"), [(1, 2), (3, 4)])
)
Parameters:
  • options_by_tuple (Tuple[str, Sequence[Any]] | Tuple[Sequence[str], Sequence[Sequence[Any]]]) – Tuple of parameter name to sequence of values for that parameter, or tuple of sequence of parameter names to sequence of sequences of values for that pack of parameters.

  • options_by_name (Sequence[Any]) – Mapping of parameter name to sequence of values for that parameter.

Return type:

Callable[[F], _Parameterized[F]]

New in version 2.0.

class cocotb.regression.TestFactory(test_function, *args, **kwargs)[source]

Factory to automatically generate tests.

Parameters:
  • test_function (F) – A Callable that returns the test Coroutine. Must take dut as the first argument.

  • *args (Any) – Remaining arguments are passed directly to the test function. Note that these arguments are not varied. An argument that varies with each test must be a keyword argument to the test function.

  • **kwargs (Any) – Remaining keyword arguments are passed directly to the test function. Note that these arguments are not varied. An argument that varies with each test must be a keyword argument to the test function.

Assuming we have a common test function that will run a test. This test function will take keyword arguments (for example generators for each of the input interfaces) and generate tests that call the supplied function.

This Factory allows us to generate sets of tests based on the different permutations of the possible arguments to the test function.

For example, if we have a module that takes backpressure, has two configurable features where enabling feature_b requires feature_a to be active, and need to test against data generation routines gen_a and gen_b:

>>> tf = TestFactory(test_function=run_test)
>>> tf.add_option(name="data_in", optionlist=[gen_a, gen_b])
>>> tf.add_option("backpressure", [None, random_backpressure])
>>> tf.add_option(
...     ("feature_a", "feature_b"), [(False, False), (True, False), (True, True)]
... )
>>> tf.generate_tests()

We would get the following tests:

  • gen_a with no backpressure and both features disabled

  • gen_a with no backpressure and only feature_a enabled

  • gen_a with no backpressure and both features enabled

  • gen_a with random_backpressure and both features disabled

  • gen_a with random_backpressure and only feature_a enabled

  • gen_a with random_backpressure and both features enabled

  • gen_b with no backpressure and both features disabled

  • gen_b with no backpressure and only feature_a enabled

  • gen_b with no backpressure and both features enabled

  • gen_b with random_backpressure and both features disabled

  • gen_b with random_backpressure and only feature_a enabled

  • gen_b with random_backpressure and both features enabled

The tests are appended to the calling module for auto-discovery.

Tests are simply named test_function_N. The docstring for the test (hence the test description) includes the name and description of each generator.

Changed in version 1.5: Groups of options are now supported

Changed in version 2.0: You can now pass cocotb.test() decorator arguments when generating tests.

Deprecated since version 2.0: Use cocotb.parameterize() instead.

add_option(name: str, optionlist: Sequence[Any]) None[source]
add_option(name: Sequence[str], optionlist: Sequence[Sequence[Any]]) None

Add a named option to the test.

Parameters:
  • name – An option name, or an iterable of several option names. Passed to test as keyword arguments.

  • optionlist – A list of possible options for this test knob. If N names were specified, this must be a list of N-tuples or lists, where each element specifies a value for its respective option.

Changed in version 1.5: Groups of options are now supported

generate_tests(*, prefix=None, postfix=None, name=None, timeout_time=None, timeout_unit='steps', expect_fail=False, expect_error=(), skip=False, stage=0)[source]

Generate an exhaustive set of tests using the cartesian product of the possible keyword arguments.

The generated tests are appended to the namespace of the calling module.

Parameters:
  • prefix (str | None) –

    Text string to append to start of test_function name when naming generated test cases. This allows reuse of a single test_function with multiple TestFactories without name clashes.

    Deprecated since version 2.0: Use the more flexible name field instead.

  • postfix (str | None) –

    Text string to append to end of test_function name when naming generated test cases. This allows reuse of a single test_function with multiple TestFactories without name clashes.

    Deprecated since version 2.0: Use the more flexible name field instead.

  • name (str | None) –

    Passed as name argument to cocotb.test().

    New in version 2.0.

  • timeout_time (float | None) –

    Passed as timeout_time argument to cocotb.test().

    New in version 2.0.

  • timeout_unit (str) –

    Passed as timeout_unit argument to cocotb.test().

    New in version 2.0.

  • expect_fail (bool) –

    Passed as expect_fail argument to cocotb.test().

    New in version 2.0.

  • expect_error (Type[Exception] | Sequence[Type[Exception]]) –

    Passed as expect_error argument to cocotb.test().

    New in version 2.0.

  • skip (bool) –

    Passed as skip argument to cocotb.test().

    New in version 2.0.

  • stage (int) –

    Passed as stage argument to cocotb.test().

    New in version 2.0.

Interacting with the Simulator

Task Management

cocotb.start_soon(coro)[source]

Schedule a coroutine to be run concurrently.

Note that this is not an async function, and the new task will not execute until the calling task yields control.

Parameters:

coro (Task | Coroutine) – A task or coroutine to be run.

Returns:

The Task that is scheduled to be run.

Return type:

Task

New in version 1.6.0.

async cocotb.start(coro)[source]

Schedule a coroutine to be run concurrently, then yield control to allow pending tasks to execute.

The calling task will resume execution before control is returned to the simulator.

When the calling task resumes, the newly scheduled task may have completed, raised an Exception, or be pending on a Trigger.

Parameters:

coro (Task | Coroutine) – A task or coroutine to be run.

Returns:

The Task that has been scheduled and allowed to execute.

Return type:

Task

New in version 1.6.0.

cocotb.create_task(coro)[source]

Construct a coroutine into a Task without scheduling the task.

The task can later be scheduled with cocotb.start() or cocotb.start_soon().

Parameters:

coro (Task | Coroutine) – An existing task or a coroutine to be wrapped.

Returns:

Either the provided Task or a new Task wrapping the coroutine.

Return type:

Task

New in version 1.6.0.

class cocotb.task.Task(inst)[source]

Concurrently executing task.

This class is not intended for users to directly instantiate. Use cocotb.create_task() to create a Task object, or use cocotb.start_soon() or cocotb.start() to create a Task and schedule it to run.

Changed in version 1.8.0: Moved to the cocotb.task module.

Changed in version 2.0: The retval, _finished, and __bool__ methods were removed. Use result(), done(), and done() methods instead, respectively.

cancel(msg=None)[source]

Cancel a Task’s further execution.

When a Task is cancelled, a asyncio.CancelledError is thrown into the Task.

Parameters:

msg (str | None) –

Return type:

None

cancelled()[source]

Return True if the Task was cancelled.

Return type:

bool

close()[source]

Raise GeneratorExit inside coroutine.

Return type:

None

done()[source]

Return True if the Task has finished executing.

Return type:

bool

exception()[source]

Return the exception of the Task.

If the Task ran to completion, None is returned. If the Task failed with an exception, the exception is returned. If the Task was cancelled, the CancelledError is re-raised. If the coroutine is not yet complete, a asyncio.InvalidStateError is raised.

Return type:

BaseException | None

has_started()[source]

Return True if the Task has started executing.

Return type:

bool

join()[source]

Return a trigger that will fire when the wrapped coroutine exits.

Return type:

Join

kill()[source]

Kill a coroutine.

Return type:

None

result()[source]

Return the result of the Task.

If the Task ran to completion, the result is returned. If the Task failed with an exception, the exception is re-raised. If the Task was cancelled, the CancelledError is re-raised. If the coroutine is not yet complete, a asyncio.InvalidStateError is raised.

Return type:

T

send(value)[source]

Send a value into the coroutine. Return next yielded value or raise StopIteration.

Parameters:

value (Any) –

Return type:

Any

throw(exc)[source]

Raise an exception in the coroutine. Return next yielded value or raise StopIteration.

Parameters:

exc (BaseException) –

Return type:

Any

HDL Datatypes

These are a set of datatypes that model the behavior of common HDL datatypes.

New in version 1.6.0.

class cocotb.types.Logic(value=None)[source]

Model of a 9-value (U, X, 0, 1, Z, W, L, H, -) datatype commonly seen in VHDL.

This is modeled after VHDL’s std_ulogic type. (System)Verilog’s 4-value logic type only utilizes X, 0, 1, and Z values.

Logic can be converted to and from int, str, and bool. The list of values convertable to Logic includes "U", "X", "0", "1", "Z", "W", "L", "H", "-", 0, 1, True, and False.

>>> Logic("X")
Logic('X')
>>> Logic(True)
Logic('1')
>>> Logic(1)
Logic('1')

>>> Logic()  # default value
Logic('X')

>>> str(Logic("Z"))
'Z'
>>> bool(Logic(0))
False
>>> int(Logic(1))
1

Note

The int and bool conversions will raise ValueError if the value is not 0 or 1.

Logic values are immutable and therefore hashable and can be placed in sets and used as keys in dicts.

Logic supports the common logic operations &, |, ^, and ~.

>>> def full_adder(a: Logic, b: Logic, carry: Logic) -> typing.Tuple[Logic, Logic]:
...     res = a ^ b ^ carry
...     carry_out = (a & b) | (b & carry) | (a & carry)
...     return res, carry_out

>>> full_adder(a=Logic('0'), b=Logic('1'), carry=Logic('1'))
(Logic('0'), Logic('1'))
Parameters:

value (str | int | bool | Logic | None) – value to construct into a Logic.

Raises:

ValueError – if the value cannot be constructed into a Logic.

Return type:

Logic

class cocotb.types.Range(left: int, direction: int)[source]
class cocotb.types.Range(left: int, direction: str, right: int)
class cocotb.types.Range(left: int, *, right: int)

Variant of range with inclusive right bound.

In Python, range and slice have a non-inclusive right bound. In both Verilog and VHDL, ranges and arrays have an inclusive right bound. This type mimics Python’s range type, but implements HDL-like inclusive right bounds, using the names left and right as replacements for start and stop to match VHDL. Range directionality can be specified using 'to' or 'downto' between the left and right bounds. Not specifying directionality will cause the directionality to be inferred.

>>> r = Range(-2, 3)
>>> r.left, r.right, len(r)
(-2, 3, 6)

>>> s = Range(8, 'downto', 1)
>>> s.left, s.right, len(s)
(8, 1, 8)

from_range() and to_range() can be used to convert from and to range.

>>> r = Range(-2, 3)
>>> r.to_range()
range(-2, 4)

Range supports “null” ranges as seen in VHDL. “null” ranges occur when a left bound cannot reach a right bound with the given direction. They have a length of 0, but the left, right, and direction values remain as given.

>>> r = Range(1, 'to', 0)  # no way to count from 1 'to' 0
>>> r.left, r.direction, r.right
(1, 'to', 0)
>>> len(r)
0

Note

This is only possible when specifying the direction.

Ranges also support all the features of range including, but not limited to:

  • value in range to see if a value is in the range,

  • range.index(value) to see what position in the range the value is,

The typical use case of this type is in conjunction with Array.

Parameters:
  • left (int) – leftmost bound of range

  • direction (int | str | None) – 'to' if values are ascending, 'downto' if descending

  • right (int | None) – rightmost bound of range (inclusive)

property direction: str

'to' if values are meant to be ascending, 'downto' otherwise.

classmethod from_range(range)[source]

Convert range to Range.

Parameters:

range (range) –

Return type:

Range

property left: int

Leftmost value in a range.

property right: int

Rightmost value in a range.

to_range()[source]

Convert Range to range.

Return type:

range

class cocotb.types.Array(value, range=None)[source]

Fixed-size, arbitrarily-indexed, homogeneous collection type.

Arrays are similar to, but different from Python lists. An array can store values of any type or values of multiple types at a time, just like a list. Unlike lists, an array’s size cannot change.

The indexes of an array can start or end at any integer value, they are not limited to 0-based indexing. Indexing schemes can be either ascending or descending in value. An array’s indexes are described using a Range object. Initial values are treated as iterables, which are copied into an internal buffer.

>>> Array("1234")  # the 0-based range `(0, len(value)-1)` is inferred
Array(['1', '2', '3', '4'], Range(0, 'to', 3))

>>> Array([1, True, None, "example"], Range(-2, 1))  # initial value and range lengths must be equal
Array([1, True, None, 'example'], Range(-2, 'to', 1))

Arrays also support “null” ranges; “null” arrays have zero length and cannot be indexed.

>>> Array([], range=Range(1, "to", 0))
Array([], Range(1, 'to', 0))

Indexing and slicing is very similar to lists, but it uses the indexing scheme specified. Slicing, just like the Range object uses an inclusive right bound, which is commonly seen in HDLs. Like lists, if a start or stop index is not specified, it is inferred as the start or end of the array. Slicing an array returns a new Array object, whose bounds are the slice indexes.

>>> a = Array("1234abcd")
>>> a[7]
'd'
>>> a[2:5]
Array(['3', '4', 'a', 'b'], Range(2, 'to', 5))
>>> a[2:5] = reversed(a[2:5])
>>> "".join(a)
'12ba43cd'

>>> b = Array("1234", Range(0, -3))
>>> b[-2]
'3'
>>> b[-1:]
Array(['2', '3', '4'], Range(-1, 'downto', -3))
>>> b[:] = reversed(b)
>>> b
Array(['4', '3', '2', '1'], Range(0, 'downto', -3))

Warning

Arrays behave differently in certain situations than Python’s builtin sequence types (list, tuple, etc.).

  • Arrays are not necessarily 0-based and slices use inclusive right bounds, so many functions that work on Python sequences by index (like bisect) may not work on arrays.

  • Slice indexes must be specified in the same direction as the array and do not support specifying a “step”.

  • When setting a slice, the new value must be an iterable of the same size as the slice.

  • Negative indexes are not treated as an offset from the end of the array, but are treated literally.

Arrays are equal to other arrays of the same length with the same values (structural equality). Bounds do not matter for equality.

>>> a = Array([1, 1, 2, 3, 5], Range(4, "downto", 0))
>>> b = Array([1, 1, 2, 3, 5], Range(-2, "to", 2))
>>> a == b
True

You can change the bounds of an array by setting the range to a new value. The new bounds must be the same length of the array.

>>> a = Array("1234")
>>> a.range
Range(0, 'to', 3)
>>> a.range = Range(3, 'downto', 0)
>>> a.range
Range(3, 'downto', 0)

Arrays support the methods and semantics defined by collections.abc.Sequence.

>>> a = Array("stuff", Range(2, "downto", -2))
>>> len(a)
5
>>> "t" in a
True
>>> a.index("u")
0
>>> for c in a:
...     print(c)
s
t
u
f
f
Parameters:
  • value (Iterable[T]) – Initial value for the array.

  • range (Range | None) – Indexing scheme of the array.

Raises:
  • ValueError – When argument values cannot be used to construct an array.

  • TypeError – When invalid argument types are used.

count(value)[source]

Return number of occurrences of value.

Parameters:

value (T) –

Return type:

int

property direction: str

"to" if indexes are ascending, "downto" otherwise.

index(value, start=None, stop=None)

Return index of first occurrence of value.

Raises IndexError if the value is not found. Search only within start and stop if given.

Parameters:
  • value (T) –

  • start (int | None) –

  • stop (int | None) –

Return type:

int

property left: int

Leftmost index of the array.

property range: Range

Range of the indexes of the array.

property right: int

Rightmost index of the array.

class cocotb.types.LogicArray(value: int | Iterable[str | int | bool | Logic], range: Range | None = None)[source]
class cocotb.types.LogicArray(value: int | Iterable[str | int | bool | Logic] | None = None, *, range: Range)

Fixed-sized, arbitrarily-indexed, array of cocotb.types.Logic.

LogicArrays can be constructed from either iterables of values constructible into Logic: like bool, str, int; or from integers. If constructed from a positive integer, an unsigned bit representation is used to construct the LogicArray. If constructed from a negative integer, a two’s complement bit representation is used. Like Array, if no range argument is given, it is deduced from the length of the iterable or bit string used to initialize the variable. If a range argument is given, but no value, the array is filled with the default value of Logic().

>>> LogicArray("01XZ")
LogicArray('01XZ', Range(3, 'downto', 0))

>>> LogicArray([0, True, "X"])
LogicArray('01X', Range(2, 'downto', 0))

>>> LogicArray(0xA)  # picks smallest range that can fit the value
LogicArray('1010', Range(3, 'downto', 0))

>>> LogicArray(-4, Range(0, "to", 3))  # will sign-extend
LogicArray('1100', Range(0, 'to', 3))

>>> LogicArray(range=Range(0, "to", 3))  # default values
LogicArray('XXXX', Range(0, 'to', 3))

LogicArrays support the same operations as Array; however, it enforces the condition that all elements must be a Logic.

>>> la = LogicArray("1010")
>>> la[0]                               # is indexable
Logic('0')

>>> la[1:]                              # is slice-able
LogicArray('10', Range(1, 'downto', 0))

>>> Logic("0") in la                    # is a collection
True

>>> list(la)                            # is an iterable
[Logic('1'), Logic('0'), Logic('1'), Logic('0')]

When setting an element or slice, the value is first constructed into a Logic.

>>> la = LogicArray("1010")
>>> la[3] = "Z"
>>> la[3]
Logic('Z')

>>> la[2:] = ['X', True, 0]
>>> la
LogicArray('ZX10', Range(3, 'downto', 0))

LogicArrays can be converted into strs or ints.

>>> la = LogicArray("1010")
>>> la.binstr
'1010'

>>> la.integer          # uses unsigned representation
10

>>> la.signed_integer   # uses two's complement representation
-6

LogicArrays also support element-wise logical operations: &, |, ^, and ~.

>>> def big_mux(a: LogicArray, b: LogicArray, sel: Logic) -> LogicArray:
...     s = LogicArray([sel] * len(a))
...     return (a & ~s) | (b & s)

>>> la = LogicArray("0110")
>>> p = LogicArray("1110")
>>> sel = Logic('1')        # choose second option
>>> big_mux(la, p, sel)
LogicArray('1110', Range(3, 'downto', 0))
Parameters:
Raises:
  • ValueError – When argument values cannot be used to construct an array.

  • TypeError – When invalid argument types are used.

count(value)[source]

Return number of occurrences of value.

Parameters:

value (Logic) –

Return type:

int

property direction: str

"to" if indexes are ascending, "downto" otherwise.

index(value, start=None, stop=None)

Return index of first occurrence of value.

Raises IndexError if the value is not found. Search only within start and stop if given.

Parameters:
  • value (T) –

  • start (int | None) –

  • stop (int | None) –

Return type:

int

property left: int

Leftmost index of the array.

property range: Range

Range of the indexes of the array.

property right: int

Rightmost index of the array.

Triggers

Simulator Triggers

Signals

class cocotb.triggers.Edge(signal)[source]

Fires on any value change of signal.

class cocotb.triggers.RisingEdge(signal)[source]

Fires on the rising edge of signal, on a transition from 0 to 1.

class cocotb.triggers.FallingEdge(signal)[source]

Fires on the falling edge of signal, on a transition from 1 to 0.

class cocotb.triggers.ClockCycles(signal, num_cycles, rising=True)[source]

Fires after num_cycles transitions of signal from 0 to 1.

Parameters:
  • signal – The signal to monitor.

  • num_cycles (int) – The number of cycles to count.

  • rising (bool, optional) – If True, the default, count rising edges. Otherwise, count falling edges.

Timing

class cocotb.triggers.Timer(time, units='step', *, round_mode=None)[source]

Fire after the specified simulation time period has elapsed.

Parameters:
  • time (Real | Decimal) –

    The time value.

    Changed in version 1.5.0: Previously this argument was misleadingly called time_ps.

  • units (str) –

    One of

    'step', 'fs', 'ps', 'ns', 'us', 'ms', 'sec'. When units is 'step', the timestep is determined by the simulator (see COCOTB_HDL_TIMEPRECISION).

    round_mode (str, optional):

    String specifying how to handle time values that sit between time steps (one of 'error', 'round', 'ceil', 'floor').

  • round_mode (str) –

Examples

>>> await Timer(100, units="ps")

The time can also be a float:

>>> await Timer(100e-9, units="sec")

which is particularly convenient when working with frequencies:

>>> freq = 10e6  # 10 MHz
>>> await Timer(1 / freq, units="sec")

Other builtin exact numeric types can be used too:

>>> from fractions import Fraction
>>> await Timer(Fraction(1, 10), units="ns")
>>> from decimal import Decimal
>>> await Timer(Decimal("100e-9"), units="sec")

These are most useful when using computed durations while avoiding floating point inaccuracies.

See also

get_sim_steps()

Raises:

ValueError – If a negative value is passed for Timer setup.

Parameters:

Changed in version 1.5: Raise an exception when Timer uses a negative value as it is undefined behavior. Warn for 0 as this will cause erratic behavior in some simulators as well.

Changed in version 1.5: Support 'step' as the units argument to mean “simulator time step”.

Changed in version 1.6: Support rounding modes.

Changed in version 2.0: Passing None as the units argument was removed, use 'step' instead.

Changed in version 2.0: The time_ps parameter was removed, use the time parameter instead.

class cocotb.triggers.ReadOnly[source]

Fires when the current simulation timestep moves to the read-only phase.

The read-only phase is entered when the current timestep no longer has any further delta steps. This will be a point where all the signal values are stable as there are no more RTL events scheduled for the timestep. The simulator will not allow scheduling of more events in this timestep. Useful for monitors which need to wait for all processes to execute (both RTL and cocotb) to ensure sampled signal values are final.

class cocotb.triggers.ReadWrite[source]

Fires when the read-write portion of the simulation cycles is reached.

class cocotb.triggers.NextTimeStep[source]

Fires when the next time step is started.

Python Triggers

class cocotb.triggers.Combine(*triggers)[source]

Fires when all of triggers have fired.

Like most triggers, this simply returns itself.

This is similar to Verilog’s join.

class cocotb.triggers.First(*triggers)[source]

Fires when the first trigger in triggers fires.

Returns the result of the trigger that fired.

This is similar to Verilog’s join_any.

Note

The event loop is single threaded, so while events may be simultaneous in simulation time, they can never be simultaneous in real time. For this reason, the value of t_ret is t1 in the following example is implementation-defined, and will vary by simulator:

t1 = Timer(10, units="ps")
t2 = Timer(10, units="ps")
t_ret = await First(t1, t2)

Note

In the old-style generator-based coroutines, t = yield [a, b] was another spelling of t = yield First(a, b). This spelling is no longer available when using await-based coroutines.

class cocotb.triggers.Join(coroutine)[source]

Fires when a task completes.

The result of blocking on the trigger can be used to get the coroutine result:

async def coro_inner():
    await Timer(1, units="ns")
    return "Hello world"


task = cocotb.start_soon(coro_inner())
result = await Join(task)
assert result == "Hello world"

If the coroutine threw an exception, the await will re-raise it.

property retval

The return value of the joined coroutine.

Note

Typically there is no need to use this attribute - the following code samples are equivalent:

task = cocotb.start_soon(mycoro())
j = Join(task)
await j
result = j.retval
task = cocotb.start_soon(mycoro())
result = await Join(task)

Synchronization

These are not Triggers themselves, but contain methods that can be used as triggers. These are used to synchronize coroutines with each other.

class cocotb.triggers.Event(name=None)[source]

Event to permit synchronization between two coroutines.

Awaiting wait() from one coroutine will block the coroutine until set() is called somewhere else.

set(data=None)[source]

Wake up all coroutines blocked on this event.

wait()[source]

Get a trigger which fires when another coroutine sets the event.

If the event has already been set, the trigger will fire immediately.

To reset the event (and enable the use of wait again), clear() should be called.

clear()[source]

Clear this event that has fired.

Subsequent calls to wait() will block until set() is called again.

is_set()[source]

Return true if event has been set

Return type:

bool

class cocotb.triggers.Lock(name=None)[source]

Lock primitive (not re-entrant).

This can be used as:

await lock.acquire()
try:
    # do some stuff
finally:
    lock.release()

Changed in version 1.4: The lock can be used as an asynchronous context manager in an async with statement:

async with lock:
    # do some stuff
locked

True if the lock is held.

acquire()[source]

Produce a trigger which fires when the lock is acquired.

release()[source]

Release the lock.

async cocotb.triggers.with_timeout(trigger, timeout_time, timeout_unit='step', round_mode=None)[source]

Waits on triggers or coroutines, throws an exception if it waits longer than the given time.

When a coroutine is passed, the callee coroutine is started, the caller blocks until the callee completes, and the callee’s result is returned to the caller. If timeout occurs, the callee is killed and SimTimeoutError is raised.

When an unstarted coroutineis passed, the callee coroutine is started, the caller blocks until the callee completes, and the callee’s result is returned to the caller. If timeout occurs, the callee continues to run and SimTimeoutError is raised.

When a task is passed, the caller blocks until the callee completes and the callee’s result is returned to the caller. If timeout occurs, the callee continues to run and SimTimeoutError is raised.

If a Trigger or Waitable is passed, the caller blocks until the trigger fires, and the trigger is returned to the caller. If timeout occurs, the trigger is cancelled and SimTimeoutError is raised.

Usage:

await with_timeout(coro, 100, "ns")
await with_timeout(First(coro, event.wait()), 100, "ns")
Parameters:
  • trigger (Trigger, Waitable, Task, or coroutine) – A single object that could be right of an await expression in cocotb.

  • timeout_time (numbers.Real or decimal.Decimal) – Simulation time duration before timeout occurs.

  • timeout_unit (str, optional) – Units of timeout_time, accepts any units that Timer does.

  • round_mode (str, optional) – String specifying how to handle time values that sit between time steps (one of 'error', 'round', 'ceil', 'floor').

Returns:

First trigger that completed if timeout did not occur.

Raises:

SimTimeoutError – If timeout occurs.

Return type:

T

New in version 1.3.

Changed in version 1.7.0: Support passing coroutines.

Changed in version 2.0: Passing None as the timeout_unit argument was removed, use 'step' instead.

Triggers (Internals)

The following are internal classes used within cocotb.

class cocotb.triggers.Trigger[source]

Base class to derive from.

class cocotb.triggers.GPITrigger[source]

Base Trigger class for GPI triggers.

Consumes simulation time.

class cocotb.triggers.Waitable[source]

Base class for trigger-like objects implemented using coroutines.

This converts a _wait abstract method into a suitable __await__.

async _wait()[source]

Should be implemented by the sub-class. Called by await self to convert the waitable object into a coroutine.

Testbench Structure

Clock

class cocotb.clock.Clock(signal, period, units='step')[source]

Simple 50:50 duty cycle clock driver.

Instances of this class should call its start() method and pass the coroutine object to one of the functions in Task Management.

This will create a clocking task that drives the signal at the desired period/frequency.

Example:

c = Clock(dut.clk, 10, "ns")
await cocotb.start(c.start())
Parameters:
  • signal – The clock pin/signal to be driven.

  • period (int) – The clock period. Must convert to an even number of timesteps.

  • units (str, optional) – One of 'step', 'fs', 'ps', 'ns', 'us', 'ms', 'sec'. When units is 'step', the timestep is determined by the simulator (see COCOTB_HDL_TIMEPRECISION).

If you need more features like a phase shift and an asymmetric duty cycle, it is simple to create your own clock generator (that you then start()):

async def custom_clock():
    # pre-construct triggers for performance
    high_time = Timer(high_delay, units="ns")
    low_time = Timer(low_delay, units="ns")
    await Timer(initial_delay, units="ns")
    while True:
        dut.clk.value = 1
        await high_time
        dut.clk.value = 0
        await low_time

If you also want to change the timing during simulation, use this slightly more inefficient example instead where the Timers inside the while loop are created with current delay values:

async def custom_clock():
    while True:
        dut.clk.value = 1
        await Timer(high_delay, units="ns")
        dut.clk.value = 0
        await Timer(low_delay, units="ns")


high_delay = low_delay = 100
await cocotb.start(custom_clock())
await Timer(1000, units="ns")
high_delay = low_delay = 10  # change the clock speed
await Timer(1000, units="ns")

Changed in version 1.5: Support 'step' as the units argument to mean “simulator time step”.

Changed in version 2.0: Passing None as the units argument was removed, use 'step' instead.

async start(cycles=None, start_high=True)[source]

Clocking coroutine. Start driving your clock by cocotb.start()ing a call to this.

Parameters:
  • cycles (int, optional) – Cycle the clock cycles number of times, or if None then cycle the clock forever. Note: 0 is not the same as None, as 0 will cycle no times.

  • start_high (bool, optional) –

    Whether to start the clock with a 1 for the first half of the period. Default is True.

    New in version 1.3.

Utilities

Collection of handy functions.

cocotb.utils.get_sim_time(units='step')[source]

Retrieves the simulation time from the simulator.

Parameters:

units (str) –

String specifying the units of the result (one of 'step', 'fs', 'ps', 'ns', 'us', 'ms', 'sec'). 'step' will return the raw simulation time.

Changed in version 2.0: Passing None as the units argument was removed, use 'step' instead.

Returns:

The simulation time in the specified units.

Return type:

int

Changed in version 1.6.0: Support 'step' as the the units argument to mean “simulator time step”.

cocotb.utils.get_time_from_sim_steps(steps, units)[source]

Calculates simulation time in the specified units from the steps based on the simulator precision.

Parameters:
  • steps (int) – Number of simulation steps.

  • units (str) – String specifying the units of the result (one of 'fs', 'ps', 'ns', 'us', 'ms', 'sec').

Returns:

The simulation time in the specified units.

Return type:

int

cocotb.utils.get_sim_steps(time, units='step', *, round_mode='error')[source]

Calculates the number of simulation time steps for a given amount of time.

When round_mode is "error", a ValueError is thrown if the value cannot be accurately represented in terms of simulator time steps. When round_mode is "round", "ceil", or "floor", the corresponding rounding function from the standard library will be used to round to a simulator time step.

Parameters:
  • time (Real | Decimal) – The value to convert to simulation time steps.

  • units (str) – String specifying the units of the result (one of 'step', 'fs', 'ps', 'ns', 'us', 'ms', 'sec'). 'step' means time is already in simulation time steps.

  • round_mode (str) – String specifying how to handle time values that sit between time steps (one of 'error', 'round', 'ceil', 'floor').

Returns:

The number of simulation time steps.

Raises:

ValueError – if the value cannot be represented accurately in terms of simulator time steps when round_mode is "error".

Return type:

int

Changed in version 1.5: Support 'step' as the units argument to mean “simulator time step”.

Changed in version 1.6: Support rounding modes.

class cocotb.utils.ParametrizedSingleton(*args, **kwargs)[source]

A metaclass that allows class construction to reuse an existing instance.

We use this so that RisingEdge(sig) and Join(coroutine) always return the same instance, rather than creating new copies.

cocotb.utils.want_color_output()[source]

Return True if colored output is possible/requested and not running in GUI.

Colored output can be explicitly requested by setting COCOTB_ANSI_OUTPUT to 1.

cocotb.utils.remove_traceback_frames(tb_or_exc, frame_names)[source]

Strip leading frames from a traceback

Parameters:
  • tb_or_exc (Union[traceback, BaseException, exc_info]) – Object to strip frames from. If an exception is passed, creates a copy of the exception with a new shorter traceback. If a tuple from sys.exc_info is passed, returns the same tuple with the traceback shortened

  • frame_names (List[str]) – Names of the frames to strip, which must be present.

cocotb.utils.walk_coro_stack(coro)[source]

Walk down the coroutine stack, starting at coro.

cocotb.utils.extract_coro_stack(coro, limit=None)[source]

Create a list of pre-processed entries from the coroutine stack.

This is based on traceback.extract_tb().

If limit is omitted or None, all entries are extracted. The list is a traceback.StackSummary object, and each entry in the list is a traceback.FrameSummary object containing attributes filename, lineno, name, and line representing the information that is usually printed for a stack trace. The line is a string with leading and trailing whitespace stripped; if the source is not available it is None.

enum cocotb.utils.DocEnum(value)[source]

Like enum.Enum, but allows documenting enum values.

Documentation for enum members can be optionally added by setting enum values to a tuple of the intended value and the docstring. This adds the provided docstring to the __doc__ field of the enum value.

class MyEnum(DocEnum):
    """Class documentation"""

    VALUE1 = 1, "Value documentation"
    VALUE2 = 2  # no documentation

Taken from this StackOverflow answer by Eric Wieser, as recommended by the enum_tools documentation.

Logging

cocotb.log: Logger

The default cocotb logger.

cocotb.logging.default_config()[source]

Apply the default cocotb log formatting to the root logger.

This hooks up the logger to write to stdout, using either SimColourLogFormatter or SimLogFormatter depending on whether colored output is requested. It also adds a SimTimeContextFilter filter so that created_sim_time is available to the formatter.

The logging level for cocotb logs is set based on the COCOTB_LOG_LEVEL environment variable, which defaults to INFO.

If desired, this logging configuration can be overwritten by calling logging.basicConfig(..., force=True) (in Python 3.8 onwards), or by manually resetting the root logger instance. An example of this can be found in the section on Rotating Log Files.

New in version 1.4.

class cocotb.logging.SimLogFormatter[source]

Bases: Formatter

Log formatter to provide consistent log message handling.

This will only add simulator timestamps if the handler object this formatter is attached to has a SimTimeContextFilter filter attached, which cocotb ensures by default.

Takes no arguments.

class cocotb.logging.SimColourLogFormatter[source]

Bases: SimLogFormatter

Log formatter to provide consistent log message handling.

Takes no arguments.

class cocotb.logging.SimTimeContextFilter[source]

Bases: Filter

A filter to inject simulator times into the log records.

This uses the approach described in the Python logging cookbook.

This adds the created_sim_time attribute.

New in version 1.4.

logging.LogRecord.created_sim_time

The result of get_sim_time() at the point the log was created (in simulator units). The formatter is responsible for converting this to something like nanoseconds via get_time_from_sim_steps().

This is added by cocotb.log.SimTimeContextFilter.

Simulation Object Handles

The class inheritance diagram for cocotb.handle
class cocotb.handle.SimHandleBase(handle, path)[source]

Bases: ABC

Base class for all simulation objects.

All simulation objects are hashable and equatable by identity.

a = dut.clk
b = dut.clk
assert a == b

Changed in version 2.0: get_definition_name() and get_definition_file() were removed in favor of _def_name() and _def_file(), respectively.

Parameters:
_path: str

The path to this handle, or its name if this is the root handle.

property _name: str

The name of an object.

property _type: str

The type of an object as a string.

property _log: Logger

The logging object.

property _def_name: str

The name of a GPI object’s definition.

This is the value of vpiDefName for VPI, vhpiNameP for VHPI, and mti_GetPrimaryName for FLI. Support for this depends on the specific object type and simulator used.

property _def_file: str

The name of the file that sources the object’s definition.

This is the value of vpiDefFile for VPI, vhpiFileNameP for VHPI, and mti_GetRegionSourceName for FLI. Support for this depends on the specific object type and simulator used.

class cocotb.handle.KeyType

Type of keys (name or index) in HierarchyObjectBase.

alias of TypeVar(‘KeyType’)

class cocotb.handle.HierarchyObjectBase(handle, path)[source]

Bases: SimHandleBase, Generic[KeyType]

Base class for hierarchical simulation objects.

Hierarchical objects don’t have values, they are just scopes/namespaces of other objects. This includes array-like hierarchical structures like “generate loops” and named hierarchical structures like “generate blocks” or “module”/”entity” instantiations.

This base class defines logic to discover, cache, and inspect child objects. It provides a dict-like interface for doing so.

_keys(), _values(), and _items() mimic their dict counterparts. You can also iterate over an object, which returns child objects, not keys like in dict; and can check the len().

See HierarchyObject and HierarchyArrayObject for examples.

Parameters:
_keys()[source]

Iterate over the keys (name or index) of the child objects.

Return type:

Iterable[KeyType]

_values()[source]

Iterate over the child objects.

Return type:

Iterable[SimHandleBase]

_items()[source]

Iterate over (key, object) tuples of child objects.

Return type:

Iterable[Tuple[KeyType, SimHandleBase]]

class cocotb.handle.HierarchyObject(handle, path)[source]

Bases: HierarchyObjectBase[str]

A simulation object that is a name-indexed collection of hierarchical simulation objects.

This class is used for named hierarchical structures, such as “generate blocks” or “module”/”entity” instantiations.

Children under this structure are found by using the name of the child with either the attribute syntax or index syntax. For example, if in your TOPLEVEL entity/module you have a signal/net named count, you could do either of the following.

dut.count  # attribute syntax
dut["count"]  # index syntax

Attribute syntax is usually shorter and easier to read, and is more common. However, it has limitations:

  • the name cannot start with a number

  • the name cannot start with a _ character

  • the name can only contain ASCII letters, numbers, and the _ character

Any possible name of an object is supported with the index syntax, but it can be more verbose.

Accessing a non-existent child with attribute syntax results in an AttributeError, and accessing a non-existent child with index syntax results in a KeyError.

Note

If you need to access signals/nets that start with _, or use escaped identifier (Verilog) or extended identifier (VHDL) characters, you have to use the index syntax. Accessing escaped/extended identifiers requires enclosing the name with leading and trailing double backslashes (\\).

dut["_underscore_signal"]
dut["\\%extended !ID\\"]

Iteration yields all child objects in no particular order. The len() function can be used to find the number of children.

# discover all children in 'some_module'
total = 0
for handle in dut.some_module:
    cocotb.log("Found %r", handle._path)
    total += 1

# make sure we found them all
assert len(dut.some_module) == total
Parameters:
_id(name, extended=True)[source]

Query the simulator for an object with the specified name.

If extended is True, run the query only for VHDL extended identifiers. For Verilog, only extended=False is supported.

Parameters:
  • name (str) – The child object by name.

  • extended (bool) – If True, treat the name as an extended identifier.

Returns:

The child object.

Raises:

AttributeError – If the child object is not found.

Return type:

SimHandleBase

Deprecated since version 2.0: Use handle[child_name] syntax instead. If extended identifiers are needed simply add a \ character before and after the name.

class cocotb.handle.HierarchyArrayObject(handle, path)[source]

Bases: HierarchyObjectBase[int]

A simulation object that is an array of hierarchical simulation objects.

This class is used for array-like hierarchical structures like “generate loops”.

Children of this object are found by supplying a numerical index using index syntax. For example, if you have a design with a generate loop gen_pipe_stages from the range 0 to 7:

block_0 = dut.gen_pipe_stages[0]
block_7 = dut.gen_pipe_stages[7]

Accessing a non-existent child results in an IndexError.

Iteration yields all child objects in order.

# set all 'reg's in each pipe stage to 0
for pipe_stage in dut.gen_pipe_stages:
    pipe_stage.reg.value = 0

Use the range() property if you want to iterate over the indexes. The len() function can be used to find the number of elements.

# set all 'reg's in each pipe stage to 0
for idx in dut.gen_pipe_stages.range:
    dut.gen_pipe_stages[idx].reg.value = 0

# make sure we have all the pipe stages
assert len(dut.gen_pipe_stage) == len(dut.gen_pipe_stages.range)
Parameters:
property range: Range

Return a Range over the indexes of the array/vector.

left()[source]

Return the leftmost index in the array/vector.

Return type:

int

direction()[source]

Return the direction ("to"/"downto") of indexes in the array/vector.

Return type:

str

right()[source]

Return the rightmost index in the array/vector.

Return type:

int

class cocotb.handle.ValueT

The type of the value a Deposit or Force action contains.

alias of TypeVar(‘ValueT’)

class cocotb.handle.ValuePropertyT

Type accepted and returned by the value property.

alias of TypeVar(‘ValuePropertyT’)

class cocotb.handle.ValueSetT

Type accepted by set() and setimmediatevalue().

alias of TypeVar(‘ValueSetT’)

class cocotb.handle.ValueObjectBase(handle, path)[source]

Bases: SimHandleBase, Generic[ValuePropertyT, ValueSetT]

Base class for all simulation objects that have a value.

Parameters:
abstract property value: ValuePropertyT

Get or set the value of the simulation object.

Getter:

Returns the current value of the simulation object.

Setter:

Assigns the value at end of the current simulator delta cycle. Takes whatever values that set() takes, including Deposit, Force, Freeze, and Release actions.

Note

Use setimmediatevalue() if you need to set the value of the simulation object immediately.

set(value)[source]

Assign the value to this simulation object at the end of the current delta cycle.

This is known in Verilog as a “non-blocking assignment” and in VHDL as a “signal assignment”.

See Deposit, Force, Freeze, and Release for additional actions that can be taken when setting a value. The default behavior is to Deposit the value. Use these actions like so:

dut.handle.set(1)  # default Deposit action
dut.handle.set(Deposit(2))
dut.handle.set(Force(3))
dut.handle.set(Freeze())
dut.handle.set(Release())
Parameters:

value (ValueSetT | Deposit[ValueSetT] | Force[ValueSetT] | Freeze | Release) –

Return type:

None

setimmediatevalue(value)[source]

Assign a value to this simulation object immediately.

This is known in Verilog as a “blocking” assignment and in VHDL as a variable assignment.

See Deposit, Force, Freeze, and Release for additional actions that can be taken when setting a value. The default behavior is to Deposit the value. See set() for an example on how to use these action types.

Parameters:

value (ValueSetT | Deposit[ValueSetT] | Force[ValueSetT] | Freeze | Release) –

Return type:

None

property is_const: bool

True if the simulator object is immutable, e.g. a Verilog parameter or VHDL constant or generic.

class cocotb.handle.ChildObjectT

Subtype of ValueObjectBase returned when iterating or indexing a IndexableValueObjectBase.

alias of TypeVar(‘ChildObjectT’, bound=ValueObjectBase[Any, Any])

class cocotb.handle.IndexableValueObjectBase(handle, path)[source]

Bases: ValueObjectBase[ValuePropertyT, ValueSetT], Generic[ValuePropertyT, ValueSetT, ChildObjectT]

Base class for all simulation object types that have a range and can be indexed.

These objects can be iterated over to yield child objects:

for child in dut.array_object:
    print(child._path)

A particular child can be retrieved using its index:

child = dut.array_object[0]

# reversed iteration over children
for child_idx in reversed(dut.array_object.range):
    dut.array_object[child_idx]

Note

While seemingly all objects that inherit from this class should be able to be indexed, this is not the case. For example, a single logic object cannot be indexed, while an array of logics may be able to be indexed. If this object cannot be indexed, trying to index will raise an IndexError and iteration will yield nothing.

Parameters:
class cocotb.handle.ElemValueT

Type of value of each element in an ArrayObject.

alias of TypeVar(‘ElemValueT’)

class cocotb.handle.ArrayObject(handle, path)[source]

Bases: IndexableValueObjectBase[List[ElemValueT], List[ElemValueT], ChildObjectT], Generic[ElemValueT, ChildObjectT]

A simulation object that is an array of value-having simulation objects.

This object is used whenever an array is seen that isn’t either a logic array or string. In Verilog, only unpacked vectors use this type. Packed vectors are typically mapped to LogicObject.

Parameters:
property value: List[ElemValueT]

The current value of the simulation object.

Getter:

Returns the current values of each element of the array object as a list of element values. The elements of the array appear in the list in left-to-right order.

Setter:

Assigns a list of values to each element of the array at the end of the current delta cycle. The element values are assigned in left-to-right order.

Given an HDL array arr, when getting the value:

Verilog

VHDL

arr.value is equivalent to

arr[4:7]

arr(4 to 7)

[arr[4].value, arr[5].value, arr[6].value, arr[7].value]

arr[7:4]

arr(7 downto 4)

[arr[7].value, arr[6].value, arr[5].value, arr[4].value]

When setting the signal as in arr.value = ..., the same index equivalence as noted in the table holds.

Warning

Assigning a value to a sub-handle:

  • Wrong: dut.some_array.value[0] = 1 (gets value as a list then updates index 0)

  • Correct: dut.some_array[0].value = 1

Raises:
  • TypeError – If assigning a type other than list.

  • ValueError – If assigning a list of different length than the simulation object.

class cocotb.handle.LogicObject(handle, path)[source]

Bases: IndexableValueObjectBase[LogicArray, Union[LogicArray, Logic, int], LogicObject], ValueObjectBase[LogicArray, Union[LogicArray, Logic, int]]

A logic or logic array simulation object.

Verilog types that map to this object:
  • logic

  • reg

  • bit

  • packed any-dimensional vectors of logic, reg, or bit

  • packed any-dimensional vectors of packed structures

VHDL types that map to this object:
  • std_logic and std_ulogic

  • std_logic_vector and std_ulogic_vector

  • unsigned

  • signed

  • ufixed

  • sfixed

  • float

Parameters:
property value: LogicArray

The value of the simulation object.

Getter:

Returns the current value of the simulation object as a LogicArray, even when the object is a single logic object and not an array.

Setter:

Assigns a value at the end of the current delta cycle. A LogicArray, str, or int can be used to set the value. When a str or int is given, it is as if it is first converted a LogicArray.

Raises:
  • TypeError – If assignment is given a type other than LogicArray, int, or str.

  • OverflowError – If int value is out of the range that can be represented by the target: -2**(len(handle) - 1) <= value <= 2**len(handle) - 1

Changed in version 2.0: Using ctypes.Structure objects to set values was removed. Convert the struct object to a LogicArray before assignment using LogicArray("".join(format(int(byte), "08b") for byte in bytes(struct_obj))) instead.

Changed in version 2.0: Using dict objects to set values was removed. Convert the dictionary to an integer before assignment using sum(v << (d['bits'] * i) for i, v in enumerate(d['values'])) instead.

class cocotb.handle.RealObject(handle, path)[source]

Bases: ValueObjectBase[float, float]

A real/float simulation object.

This type is used when a real object in VHDL or float object in Verilog is seen.

Parameters:
property value: float

The value of the simulation object.

Getter:

Returns the current value of the simulation object as a float.

Setter:

Assigns a float value at the end of the current delta cycle.

Raises:

TypeError – If assignment is given a type other than float.

class cocotb.handle.EnumObject(handle, path)[source]

Bases: ValueObjectBase[int, int]

An enumeration simulation object.

This type is used when an enumerated-type simulation object is seen that isn’t a “logic” or similar type.

Parameters:
property value: int

The value of the simulation object.

Getter:

Returns the current enumeration value of the simulation object as an int. The value is the integer mapping of the enumeration value.

Setter:

Assigns a new enumeration value at the end of the current delta cycle using an int. The int value is the integer mapping of the enumeration value.

Raises:
  • TypeError – If assignment is given a type other than int.

  • OverflowError – If the value used in assignment is out of range of a 32-bit signed integer.

class cocotb.handle.IntegerObject(handle, path)[source]

Bases: ValueObjectBase[int, int]

An integer simulation object.

Verilog types that map to this object:
  • byte

  • shortint

  • int

  • longint

This type should not be used for the 4-state integer types integer and time.

VHDL types that map to this object:
  • integer

  • natural

  • positive

Objects that use this type are assumed to be two’s complement 32-bit integers with 2-state (0 and 1) bits.

Parameters:
property value: int

The value of the simulation object.

Getter:

Returns the current value of the simulation object as a int.

Setter:

Assigns a int value at the end of the current delta cycle.

Raises:
  • TypeError – If assignment is given a type other than int.

  • OverflowError – If the value used in assignment is out of range of a 32-bit signed integer.

class cocotb.handle.StringObject(handle, path)[source]

Bases: IndexableValueObjectBase[bytes, bytes, IntegerObject], ValueObjectBase[bytes, bytes]

A string simulation object.

This type is used when a string (VHDL or Verilog) simulation object is seen.

Parameters:
property value: bytes

The value of the simulation object.

Getter:

Returns the current value of the simulation object as a bytes.

Setter:

Assigns a bytes value at the end of the current delta cycle. When the value’s length is less than the simulation object’s, the value is padded with NUL ('\') characters up to the appropriate length. When the value’s length is greater than the simulation object’s, the value is truncated without a NUL terminator to the appropriate length, without warning.

Strings in both Verilog and VHDL are byte arrays without any particular encoding. Encoding must be done to turn Python strings into byte arrays. Because there are many encodings, this step is left up to the user.

An example of how encoding and decoding could be accomplished using an ASCII string.

# lowercase a string
value = dut.string_handle.value.decode("ascii")
value = value.lower()
dut.string_handle.value = value.encode("ascii")
Raises:

TypeError – If assignment is given a type other than bytes.

Changed in version 1.4: Takes bytes instead of str. Users are now expected to choose an encoding when using these objects.

cocotb.handle.SimHandle(handle, path=None)[source]

Factory function to create the correct type of SimHandle object.

Parameters:
  • handle (gpi_sim_hdl) – The GPI handle to the simulator object.

  • path (str | None) – Path to this handle.

Returns:

An appropriate SimHandleBase object.

Raises:

NotImplementedError – If no matching object for GPI type could be found.

Return type:

SimHandleBase

Assignment Methods

class cocotb.handle.Deposit(value)[source]

Action used for placing a value into a given handle. This is the default action.

If another deposit comes after this deposit, the newer deposit overwrites the old value. If an HDL process is driving the signal/net/register where a deposit from cocotb is made, the deposited value will be overwritten at the end of the next delta cycle, essentially causing a single delta cycle “glitch” in the waveform.

Parameters:

value (ValueT) –

class cocotb.handle.Force(value)[source]

Action used to force a handle to a given value until a Release is applied.

Deposit writes from cocotb or drives from HDL processes do not cause the value to change until the handle is Released. Further Forces will overwrite the value and leave the value forced. Freezes will act as a no-op.

Parameters:

value (ValueT) –

class cocotb.handle.Freeze[source]

Action used to make a handle keep its current value until a Release is applied.

Deposit writes from cocotb or drives from HDL processes do not cause the value to change until the handle is Released. Forces will overwrite the value and leave the value forced. Further Freezes will act as a no-op.

class cocotb.handle.Release[source]

Action used to stop the effects of a previously applied Force/Freeze action.

Other Handle Methods

len(handle)

Return the “length” (the number of elements) of the underlying object.

For vectors this is the number of bits.

dir(handle)

Return a list of the sub-handles of handle, that is, the instances, signals, constants etc. of a certain hierarchy level in the DUT.

Miscellaneous

Asynchronous Queues

exception cocotb.queue.QueueFull[source]

Raised when the Queue.put_nowait() method is called on a full Queue.

exception cocotb.queue.QueueEmpty[source]

Raised when the Queue.get_nowait() method is called on a empty Queue.

class cocotb.queue.Queue(maxsize=0)[source]

A queue, useful for coordinating producer and consumer coroutines.

If maxsize is less than or equal to 0, the queue size is infinite. If it is an integer greater than 0, then put() will block when the queue reaches maxsize, until an item is removed by get().

Parameters:

maxsize (int) –

qsize()[source]

Number of items in the queue.

Return type:

int

property maxsize: int

Number of items allowed in the queue.

empty()[source]

Return True if the queue is empty, False otherwise.

Return type:

bool

full()[source]

Return True if there are maxsize() items in the queue.

Note

If the Queue was initialized with maxsize=0 (the default), then full() is never True.

Return type:

bool

async put(item)[source]

Put an item into the queue.

If the queue is full, wait until a free slot is available before adding the item.

Parameters:

item (T) –

Return type:

None

put_nowait(item)[source]

Put an item into the queue without blocking.

If no free slot is immediately available, raise asyncio.QueueFull.

Parameters:

item (T) –

Return type:

None

async get()[source]

Remove and return an item from the queue.

If the queue is empty, wait until an item is available.

Return type:

T

get_nowait()[source]

Remove and return an item from the queue.

Return an item if one is immediately available, else raise asyncio.QueueEmpty.

Return type:

T

class cocotb.queue.PriorityQueue(maxsize=0)[source]

A subclass of Queue; retrieves entries in priority order (smallest item first).

Entries are typically tuples of the form (priority number, data).

Parameters:

maxsize (int) –

class cocotb.queue.LifoQueue(maxsize=0)[source]

A subclass of Queue; retrieves most recently added entries first.

Parameters:

maxsize (int) –

Other Runtime Information

cocotb.argv: List[str]

The argument list as seen by the simulator.

cocotb.SIM_NAME: str

The product information of the running simulator.

cocotb.SIM_VERSION: str

The version of the running simulator.

cocotb.plusargs: Dict[str, bool | str]

A dictionary of “plusargs” handed to the simulation.

See PLUSARGS for details.

cocotb.packages: SimpleNamespace

A types.SimpleNamespace of package handles.

This will be populated with handles at test time if packages can be discovered via the GPI.

New in version 2.0.

cocotb.top: SimHandleBase

A handle to the TOPLEVEL entity/module.

This is equivalent to the DUT parameter given to cocotb tests, so it can be used wherever that variable can be used. It is particularly useful for extracting information about the DUT in module-level class and function definitions; and in parameters to TestFactorys.

cocotb.is_simulation: bool = False

True if cocotb was loaded in a simulation.

The combine_results script

Use python -m cocotb_tools.combine_results to call the script.

combine_results - CLI interface

Simple script to combine JUnit test results into a single XML file.

combine_results [-h] [-i INPUT_FILENAME] [-o OUTPUT_FILE]
                [--output-testsuites-name OUTPUT_TESTSUITES_NAME] [--verbose]
                [directories ...]
combine_results positional arguments
  • directories - Directories to search for input files. (default: ['.'])

combine_results options
  • -h, --help - show this help message and exit

  • -i INPUT_FILENAME, --input-filename INPUT_FILENAME - A regular expression to match input filenames. (default: results.xml)

  • -o OUTPUT_FILE, --output-file OUTPUT_FILE - Path of output XML file. (default: combined_results.xml)

  • --output-testsuites-name OUTPUT_TESTSUITES_NAME - Name of 'testsuites' element in output XML file. (default: results)

  • --verbose - Enables verbose output.

The cocotb-config script

Use cocotb-config or python -m cocotb_tools.config to call the script.

cocotb-config - CLI interface

cocotb-config [-h]
              [--share | --makefiles | --python-bin | --help-vars | --libpython | --lib-dir | --lib-name INTERFACE SIMULATOR | --lib-name-path INTERFACE SIMULATOR | --version]
cocotb-config options
  • -h, --help - show this help message and exit

  • --share - Print the path to cocotb’s share directory

  • --makefiles - Print the path to cocotb’s makefile directory

  • --python-bin - Print the path to the Python executable associated with the environment that cocotb is installed in.

  • --help-vars - Print help about supported Makefile variables

  • --libpython - Print the absolute path to the libpython associated with the current Python installation

  • --lib-dir - Print the absolute path to the interface libraries location

  • --lib-name INTERFACE - Print the name of interface library for given interface (VPI/VHPI/FLI) and simulator (default: None)

  • --lib-name-path INTERFACE - Print the absolute path of interface library for given interface (VPI/VHPI/FLI) and simulator (default: None)

  • --version - Print the version of cocotb

Implementation Details

Note

In general, nothing in this section should be interacted with directly - these components work mostly behind the scenes.

The Regression Manager

cocotb.regression_manager: RegressionManager

The global regression manager instance.

class cocotb.regression.Test(*, func, name=None, module=None, doc=None, timeout_time=None, timeout_unit='step', expect_fail=False, expect_error=(), skip=False, stage=0)[source]

A cocotb test in a regression.

Parameters:
  • func (Callable[[...], Coroutine[Any, Any, None]]) – The test function object.

  • name (str | None) – The name of the test function. Defaults to func.__qualname__ (the dotted path to the test function in the module).

  • module (str | None) – The name of the module containing the test function. Defaults to func.__module__ (the name of the module containing the test function).

  • doc (str | None) – The docstring for the test. Defaults to func.__doc__ (the docstring of the test function).

  • timeout_time (float | None) – Simulation time duration before the test is forced to fail with a SimTimeoutError.

  • timeout_unit (str) – Units of timeout_time, accepts any units that Timer does.

  • expect_fail (bool) – If True and the test fails a functional check via an assert statement, :pytest:class:`pytest.raises`, :pytest:class:`pytest.warns`, or :pytest:class:`pytest.deprecated_call`, the test is considered to have passed. If True and the test passes successfully, the test is considered to have failed.

  • expect_error (Type[Exception] | Sequence[Type[Exception]]) – Mark the result as a pass only if one of the given exception types is raised in the test.

  • skip (bool) – Don’t execute this test as part of the regression. The test can still be run manually by setting TESTCASE.

  • stage (int) – Order tests logically into stages. Tests from earlier stages are run before tests from later stages.

enum cocotb.regression.RegressionMode(value)[source]

The mode of the RegressionManager.

Valid values are as follows:

REGRESSION = <RegressionMode.REGRESSION: 1>

Tests are run if included. Skipped tests are skipped, expected failures and errors are respected.

TESTCASE = <RegressionMode.TESTCASE: 2>

Like REGRESSION, but skipped tests are not skipped if included.

class cocotb.regression.RegressionManager[source]

Object which manages tests.

This object uses the builder pattern to build up a regression. Tests are added using register_test() or discover_tests(). Inclusion filters for tests can be added using add_filters(). The “mode” of the regression can be controlled using set_mode(). These methods can be called in any order any number of times before start_regression() is called, and should not be called again after that.

Once all the tests, filters, and regression behavior configuration is done, the user starts the regression with start_regression(). This method must be called exactly once.

Until the regression is started, total_tests, count, passed, skipped, and failures hold placeholder values.

total_tests

Total number of tests that will be run or skipped.

count

The current test count.

passed

The current number of passed tests.

skipped

The current number of skipped tests.

failures

The current number of failed tests.

discover_tests(*modules)[source]

Discover tests in files automatically.

Should be called before start_regression() is called.

Parameters:

modules (str) – Each argument given is the name of a module where tests are found.

Raises:

RuntimeError – If no tests are found in any of the provided modules.

Return type:

None

add_filters(*filters)[source]

Add regular expressions to filter-in registered tests.

Only those tests which match at least one of the given filters are included; the rest are excluded.

Should be called before start_regression() is called.

Parameters:

filters (str) – Each argument given is a regex pattern for test names. A match includes the test.

Return type:

None

set_mode(mode)[source]

Set the regression mode.

See RegressionMode for more details on how each mode affects RegressionManager behavior. Should be called before start_regression() is called.

Parameters:

mode (RegressionMode) – The regression mode to set.

Return type:

None

register_test(test)[source]

Register a test with the RegressionManager.

Should be called before start_regression() is called.

Parameters:

test (Test) – The test object to register.

Return type:

None

classmethod setup_pytest_assertion_rewriting()[source]

Configure pytest to rewrite assertions for better failure messages.

Must be called before all modules containing tests are imported.

Return type:

None

start_regression()[source]

Start the regression.

Return type:

None

The cocotb.simulator module

This module is a Python wrapper to libgpi. It should not be considered public API, but is documented here for developers of cocotb.

cocotb.simulator.get_precision() int

Get the precision of the simulator in powers of 10.

For example, if -12 is returned, the simulator’s time precision is 10**-12 or 1 ps.

cocotb.simulator.get_root_handle(name: str) cocotb.simulator.gpi_sim_hdl

Get the root handle.

cocotb.simulator.get_sim_time() Tuple[int, int]

Get the current simulation time.

Time is represented as a tuple of 32 bit integers ([low32, high32]) comprising a single 64 bit integer.

cocotb.simulator.get_simulator_product() str

Get the simulator’s product string.

cocotb.simulator.get_simulator_version() str

Get the simulator’s product version string.

class cocotb.simulator.gpi_cb_hdl

GPI callback handle

deregister() None

De-register this callback.

class cocotb.simulator.gpi_iterator_hdl

GPI iterator handle.

class cocotb.simulator.gpi_sim_hdl

GPI object handle

Contains methods for getting and setting the value of a GPI object, and introspection.

get_const() bool

Return True if the object is a constant.

get_definition_file() str

Get the file that sources the object’s definition.

get_definition_name() str

Get the name of a GPI object’s definition.

get_handle_by_index(index: int) cocotb.simulator.gpi_sim_hdl

Get a handle to a child object by index.

get_handle_by_name(name: str) cocotb.simulator.gpi_sim_hdl

Get a handle to a child object by name.

get_name_string() str

Get the name of an object as a string.

get_num_elems() int

Get the number of elements contained in the handle.

get_range() Tuple[int, int]

Get the range of elements (tuple) contained in the handle, return None if not indexable.

get_signal_val_binstr() str

Get the value of a logic vector signal as a string of (0, 1, X, etc.), one element per character.

get_signal_val_long() int

Get the value of a signal as an integer.

get_signal_val_real() float

Get the value of a signal as a float.

get_signal_val_str() bytes

Get the value of a signal as a byte string.

get_type() int

Get the GPI type of an object as an enum.

get_type_string() str

Get the GPI type of an object as a string.

iterate(mode: int) cocotb.simulator.gpi_iterator_hdl

Get an iterator handle to loop over all members in an object.

set_signal_val_binstr(action: int, value: str) None

Set the value of a logic vector signal using a string of (0, 1, X, etc.), one element per character.

set_signal_val_int(action: int, value: int) None

Set the value of a signal using an int.

set_signal_val_real(action: int, value: float) None

Set the value of a signal using a float.

set_signal_val_str(action: int, value: bytes) None

Set the value of a signal using a user-encoded string.

cocotb.simulator.is_running() bool

Returns True if the caller is running within a simulator.

New in version 1.4.

cocotb.simulator.log_level(level: int) None

Set the log level for GPI.

cocotb.simulator.package_iterate() cocotb.simulator.gpi_iterator_hdl

Get an iterator handle to loop over all packages. .. versionadded:: 2.0

cocotb.simulator.register_nextstep_callback(func: Callable[..., None], *args: Any) cocotb.simulator.gpi_cb_hdl

Register a callback for the cbNextSimTime callback.

cocotb.simulator.register_readonly_callback(func: Callable[..., None], *args: Any) cocotb.simulator.gpi_cb_hdl

Register a callback for the read-only section.

cocotb.simulator.register_rwsynch_callback(func: Callable[..., None], *args: Any) cocotb.simulator.gpi_cb_hdl

Register a callback for the read-write section.

cocotb.simulator.register_timed_callback(time: int, func: Callable[..., None], *args: Any) cocotb.simulator.gpi_cb_hdl

Register a timed callback.

cocotb.simulator.register_value_change_callback(signal: cocotb.simulator.gpi_sim_hdl, func: Callable[..., None], edge: int, *args: Any) cocotb.simulator.gpi_cb_hdl

Register a signal change callback.

cocotb.simulator.stop_simulator() None

Instruct the attached simulator to stop. Users should not call this function.