Writing cocotb extensions¶
This guide explains how to write cocotb extensions, with a focus on the conventions that should be followed.
Cocotb gives its users a framework to build Python testbenches for hardware designs. But sometimes the functionality provided by cocotb is too low-level. One common example are bus drivers and monitors: instead of creating a bus adapter from scratch for each new project, wouldn’t it be nice to share this component, and build on top it? In the verification world, such extensions are often called “verification IP” (VIP).
In cocotb, such functionality can be packaged and distributed as extensions. Technically, cocotb extensions are normal Python packages, and all standard Python packaging and distribution techniques can be used. Additionally, the cocotb community has agreed on a set of conventions to make extensions easier to use and to discover.
Cocotb extensions are normal Python modules which follow these naming conventions.
Assuming an extension named
EXTNAME (all lower-case),
the package is in the
the distribution (package) name is prefixed with
An SPI bus extension might be packaged as
cocotbext-spi, and its functionality would live in the
The module can then be installed with
pip3 install cocotbext-spi, and used with
Types of cocotb extensions¶
For some types of cocotb extensions we have developed conventions which go beyond naming. These conventions help to achieve a consistent behavior across extensions of the same type.
A cocotb extension which interacts with a bus or an interface (such as SPI or AXI) should build on top of a common set of classes to provide a uniform interface for its users. Typically, a bus extension provides three pieces of functionality: an abstraction of the bus itself, a bus driver, and a bus monitor.
A bus driver is the “active” part, it drives the signals that make up the bus to request reads or writes from the bus. A bus monitor is the “passive” part, it observes signal changes on the bus and assigns meaning to them. Monitors can also check the bus behavior against a standard to ensure no invalid states are being observed.
The signals which make up the bus should be grouped in a class inheriting from
Bus drivers should inherit from the
Bus monitors should inherit from the
To package a cocotb extension as Python package follow the Naming conventions, and the normal Python packaging rules.
Extensions namespaced packages, implemented using the native namespacing approach discussed in PEP 420.
The module file hierarchy should be as follows (replace
EXTNAME with the name of the extension, e.g.
# file structure of the cocotbext-EXTNAME repository ├── cocotbext/ │ │ # No __init__.py here. │ └── EXTNAME/ │ └── __init__.py ├── README.md └── setup.py
The Python source code should go into the
EXTNAME directory, next to the
All packaging metadata goes into
# Minimal setup.py. Extend as needed. from setuptools import setup, find_namespace_packages setup(name = 'cocotbext-EXTNAME', version = '0.1', packages = find_namespace_packages(include=['cocotbext.*']), install_requires = ['cocotb'], python_requires = '>=3.5', classifiers = [ "Programming Language :: Python :: 3", "Operating System :: OS Independent", "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)"])
With this file structure in place the cocotb extension can be installed through
pip in development mode
$ python3 -m pip install -e .
Once the extension has been uploaded to PyPi, it can be installed by name.
To use the functionality in the extension module, import it into your testbench.
# Examples for importing (parts of) the extension import cocotbext.EXTNAME from cocotbext import EXTNAME from cocotbext.EXTNAME import MyVerificationClass
The source code of cocotb extensions can be hosted anywhere.
If authors wish to do so, extensions can also be hosted on GitHub in the cocotb GitHub organization (e.g.
Please file a GitHub issue in the cocotb repository if you’d like to discuss that.