Skip to content

Commit 655a190

Browse files
committed
Deploying to gh-pages from @ 5359d03 🚀
1 parent cb3d9d8 commit 655a190

File tree

228 files changed

+643
-300
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

228 files changed

+643
-300
lines changed

devel/_sources/basic_cocotb_test.rst.txt

Lines changed: 118 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,69 +2,152 @@
22
Getting Started with cocotb
33
===========================
44

5-
In this section, you will learn how to create a basic test for a flow/storage hardware component (such as a pipe, FIFO, etc.). To get started, first create a ``cocotb`` folder in the directory where the tested component is located, and put all the scripts implemented in this tutorial into it.
5+
This guide shows how to create a basic test for flow/storage hardware components (such as pipes, FIFOs, etc.) using the cocotb framework. Cocotb allows you to write testbenches in Python, which are then used to verify VHDL/Verilog designs.
66

7+
The examples in this guide use the MVB FIFOX component test located at ``comp/mvb_tools/storage/fifox/cocotb/cocotb_test.py`` as a reference.
78

8-
.. note:: For automatic generation of a test template use the ``generate_test_template`` script in ``ndk-fpga/build/scripts/cocotb``.
99

10+
Quick Start
11+
-----------
1012

11-
Creating a Test
12-
===============
13+
For beginners, the easiest way to get started is:
1314

14-
As an example, a simple test of an MVB FIFOX component will be used.
15-
It can be found at ``ndk-fpga/comp/mvb_tools/storage/fifox/cocotb/cocotb_test.py``.
15+
1. **Create a ``cocotb`` folder** in the directory of the component you want to test
16+
2. **Copy template files** from an existing test (e.g., ``comp/mvb_tools/storage/fifox/cocotb/``)
17+
3. **Modify the files** for your component:
18+
- Update the ``TOPLEVEL`` in the Makefile to match your component name
19+
- Adjust signal names and bus parameters in the testbench
20+
- Update the model function to compute expected outputs for your component
21+
4. **Run the test** using the Makefile
22+
23+
.. note:: For automatic generation of a test template, use the ``generate_test_template`` script in ``ndk-fpga/build/scripts/cocotb``. This creates a basic test structure that you can customize.
24+
25+
26+
Test Structure
27+
==============
28+
29+
A cocotb test consists of two main parts:
30+
31+
**1. Testbench Class** - Reusable setup code that encapsulates all test infrastructure:
32+
33+
- **Drivers** - Objects that write stimulus data to the DUT (Device Under Test) input interfaces
34+
- **Monitors** - Objects that read output data from the DUT and convert it to transactions
35+
- **Scoreboard** - Compares actual outputs (from monitors) against expected outputs
36+
- **Expected outputs** - List of transactions that the DUT should produce
37+
- **Optional objects** - Probes for throughput measurement, bit drivers for backpressure testing
38+
- **Reset sequence** - Hardware reset initialization
39+
40+
The testbench class is typically reusable across multiple tests and can be copied/adapted for similar components.
41+
42+
**2. Test Function** - The actual test with:
43+
44+
- ``@cocotb.test()`` decorator (required) - Marks the function as a cocotb test
45+
- ``async`` function definition (required) - Enables coroutine-based simulation
46+
- Test logic - Stimulus generation, DUT interaction, and verification
47+
48+
Example test file structure:
1649

1750
.. literalinclude:: ../../comp/mvb_tools/storage/fifox/cocotb/cocotb_test.py
1851
:language: python
1952
:linenos:
2053
:encoding: utf-8
2154

22-
This test can be used as a template for tests of basic `flow` and `storage` components, and can be easily adapted for most other verifications. It consists of two basic parts: the testbench class and the test itself:
2355

24-
- The testbench is the more reusable of the two and usually looks basically the same, so it can be copied and adapted. Its purpose is to initialize and encapsulate objects that drive the test. It sets up drivers, monitors, a scoreboard, expected outputs, and other optional objects, such as a bit driver for ready signals, adds probes, and so on. It also includes a simulated reset.
25-
- The second part is the test part. It can consist of one test (typical for simple components) or multiple tests (more common for larger designs, such as the whole firmware of a card). Every test must have the ``@cocotb.test()`` decorator and be ``async``.
56+
Test Flow
57+
---------
58+
59+
A typical test follows these steps:
60+
61+
1. **Start clock** - Initialize the clock generator using ``cocotb.start_soon(Clock(...).start())``. The clock drives the synchronous logic of the DUT.
62+
63+
2. **Initialize testbench** - Create the testbench object, which sets up all drivers, monitors, and the scoreboard.
64+
65+
3. **Reset** - Run the hardware reset sequence (typically 8-16 clock cycles with RESET high). This ensures the DUT starts in a known state.
66+
67+
4. **Configure stimulus** - Set up idle generators (to create realistic gaps in data) and backpressure drivers (to test DUT behavior when output is blocked).
68+
69+
5. **Generate and send data** - Create random transactions using helper functions like ``random_transactions`` or custom generators. Send them to the DUT via the driver's ``append()`` method.
70+
71+
6. **Model expected output** - For each sent transaction, compute what the DUT should output and add it to the ``expected_output`` list. This is typically done in a ``model()`` method.
72+
73+
7. **Wait for completion** - Use a waiting loop to ensure all transactions are processed before checking results. Without this, the scoreboard might evaluate prematurely.
74+
75+
8. **Check results** - Raise ``tb.scoreboard.result`` to display pass/fail. The scoreboard automatically compares each received transaction against the expected output.
76+
2677

27-
A test begins with the clock starting, testbench initialization, and a reset. After the reset, a bit driver is started to test the component's reaction to backpressure (dst_rdy). Random data is then generated, which can either be done using ``random_transactions`` or random data that is then inserted into transaction objects (this is the case in the test above). The generated transaction is then passed to the ``model`` method of the testbench, which inserts it into the ``expected_output`` list. The generated transaction is also inserted into the driver's send queue using the ``append`` method, from where it is then written onto the bus.
78+
Required Files
79+
==============
2880

29-
The data is then read from the bus by a monitor, which should pack it into a transaction of the same type as was modeled and pass it to the test's scoreboard via a callback. The scoreboard pops the transaction from the front of the expected output queue that the monitor is connected to and compares this transaction with the transaction it received from the monitor. If they are not the same, a test failure is raised.
81+
To run a cocotb test, you need these files in your ``cocotb/`` folder:
3082

31-
A waiting loop is implemented to ensure that the test doesn't report scoreboard results prematurely before all the transactions have been received. Otherwise, the scoreboard may receive a different number of transactions than it expected, which will lead to an error.
83+
**pyproject.toml** - Python dependencies
84+
This file declares the Python packages required for the test (cocotb, cocotbext-ndk, etc.). The build system uses it to create a virtual environment with all dependencies.
3285

33-
After all the packets are received, ``tb.scoreboard.result`` is raised, and the test results are shown.
86+
.. literalinclude:: ../../comp/mvb_tools/storage/fifox/cocotb/pyproject.toml
87+
:language: toml
88+
:linenos:
89+
:encoding: utf-8
90+
91+
**cocotb_test_sig.fdo** - Simulator waveform signals
92+
This script defines which signals will be visible in the simulator's waveform viewer. Use it to debug failing tests by inspecting signal timing.
93+
94+
.. literalinclude:: ../../comp/mvb_tools/storage/fifox/cocotb/cocotb_test_sig.fdo
95+
:language: bash
96+
:linenos:
97+
:encoding: utf-8
98+
99+
**Makefile** - Build and run configuration
100+
The Makefile specifies the simulator to use (Modelsim, Vivado, etc.), the top-level entity, and cocotb configuration. It handles building the simulation and running the test.
101+
102+
.. literalinclude:: ../../comp/mvb_tools/storage/fifox/cocotb/Makefile
103+
:language: bash
104+
:linenos:
105+
:encoding: utf-8
106+
107+
.. note:: Adjust component-specific values (TOPLEVEL, generics, parameters) and relative paths in all files to match your component.
34108

35109

36110
Running the Test
37111
================
38112

39-
To successfully build and run the simulation, it's necessary to implement a couple more files. Examples of these can again be found in the ``ndk-fpga/comp/mvb_tools/storage/fifox/cocotb/`` folder.
113+
1. **Create Python virtual environment:**
40114

41-
First, it is necessary to implement a ``pyproject.toml`` with all test dependencies listed:
115+
.. code-block:: bash
42116
43-
.. literalinclude:: ../../comp/mvb_tools/storage/fifox/cocotb/pyproject.toml
44-
:language: toml
45-
:linenos:
46-
:encoding: utf-8
117+
make cocotb-venv
47118
48-
Use a special ``cocotb_test_sig.fdo`` file to define the signals that will be displayed in the simulator's waveform.
119+
This creates a virtual environment (typically in ``venv-<hash>/``) with all dependencies from ``pyproject.toml``.
49120

50-
.. literalinclude:: ../../comp/mvb_tools/storage/fifox/cocotb/cocotb_test_sig.fdo
51-
:language: bash
52-
:linenos:
53-
:encoding: utf-8
121+
2. **Activate the environment:**
54122

55-
Finally, create a ``Makefile`` that will run the simulation:
123+
.. code-block:: bash
56124
57-
.. literalinclude:: ../../comp/mvb_tools/storage/fifox/cocotb/Makefile
58-
:language: bash
59-
:linenos:
60-
:encoding: utf-8
125+
source venv-xxx/bin/activate
126+
127+
Replace ``venv-xxx`` with the actual virtual environment folder name.
128+
129+
3. **Run the test:**
130+
131+
.. code-block:: bash
132+
133+
make
134+
135+
This builds the simulation (if needed) and runs the cocotb test. Results are printed to the terminal, and waveforms are saved for debugging.
136+
137+
To run the test in console-only mode (without launching the GUI waveform viewer), use:
138+
139+
.. code-block:: bash
140+
141+
make SIM_FLAGS=-c
142+
143+
This is useful for automated testing or when running tests on remote servers.
61144

62-
.. note:: Don't forget to adjust the values that are component-specific and the relative paths if needed.
145+
.. tip:: Use ``export COCOTB_LOG_LEVEL=DEBUG`` before running to enable debug logging for troubleshooting. See the :ref:`Debug Logging` section for more details.
63146

64-
You can run the simulation by creating a python virtual environment using make cocotb-venv, entering the created virtual environment, and running the ``Makefile``:
147+
.. tip:: If a test fails, examine the waveform file to understand the timing and identify the issue. The signals defined in ``cocotb_test_sig.fdo`` will be visible.
65148

66-
.. code-block:: bash
149+
See Also
150+
--------
67151

68-
make cocotb-venv
69-
source venv-xxx/bin/activate
70-
make
152+
- :doc:`cocotb_tips_and_tricks` - Tips for debug logging, random seed control, and optional signals
153+
- :doc:`cocotbext` - Overview of cocotbext-ndk extension with drivers, monitors, and utilities

devel/_sources/cocotb_tips_and_tricks.rst.txt

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,92 @@ Cocotb tips & tricks
55
This section consists of simple problems you may encounter when creating testbenches
66
using ``cocotb/cocotbext-ndk`` frameworks and the solutions to those problems.
77

8+
Random Seed
9+
===========
10+
11+
The ``RANDOM_SEED`` environment variable controls the seed for random number generation in cocotb tests.
12+
13+
By default, cocotb uses a different random seed for each simulation run, which means tests with random behavior (e.g., random packet generation, random delays, random backpressure) will produce different results each time.
14+
15+
To reproduce a specific test run (e.g., when debugging a failure), set the seed to a fixed value:
16+
17+
.. code-block:: bash
18+
19+
export RANDOM_SEED=12345
20+
make
21+
22+
Alternatively, add ``export RANDOM_SEED := 12345`` to your ``Makefile`` for permanent setting.
23+
24+
The seed value is logged at the start of each simulation run. When a test fails, note the seed value from the log and use it to reproduce the exact same conditions.
25+
26+
.. note:: Using a fixed seed makes tests deterministic, which is useful for debugging but may hide timing-related issues that only occur with certain random patterns.
27+
28+
Debug Logging
29+
=============
30+
31+
Components in ``cocotbext-ndk`` use ``self.log`` for debug messages. To enable debug logging, set the ``COCOTB_LOG_LEVEL`` environment variable before running the simulation:
32+
33+
.. code-block:: bash
34+
35+
export COCOTB_LOG_LEVEL=DEBUG
36+
make
37+
38+
Alternatively, add ``export COCOTB_LOG_LEVEL := DEBUG`` to your ``Makefile`` for permanent setting.
39+
40+
Available log levels are: ``CRITICAL``, ``ERROR``, ``WARNING``, ``INFO``, ``DEBUG``.
41+
42+
.. note:: Debug logging increases simulation time and log size. Use only during development.
43+
44+
Optional Signals on MFB/MVB/AXI4-Stream Interfaces
45+
==================================================
46+
47+
The ``_optional_signals`` mechanism is available on MVB, MFB, AXI4-Stream and other interfaces. It allows handling signals that are not part of the standard driver/monitor. To use it:
48+
49+
1. Create extended driver/monitor classes with ``_optional_signals`` list:
50+
51+
.. code-block:: python
52+
53+
class MVBDriverExt(MVBDriver):
54+
_optional_signals = ["l3_csum_orig", "l3_csum_en"]
55+
56+
class MVBMonitorExt(MVBMonitor):
57+
_optional_signals = ["l3_csum", "l3_csum_ok"]
58+
59+
2. Create custom transaction class with the optional fields:
60+
61+
.. code-block:: python
62+
63+
from dataclasses import dataclass
64+
65+
@dataclass
66+
class MetadataTr(MvbTransaction):
67+
l3_csum_orig: int = 0
68+
l3_csum_en: int = 0
69+
70+
3. Use the extended classes in your testbench:
71+
72+
.. code-block:: python
73+
74+
self.mvb_driver = MVBDriverExt(dut, "RX_MVB", dut.CLK)
75+
self.mvb_monitor = MVBMonitorExt(dut, "TX_MVB", dut.CLK, tr_type=MetadataTr)
76+
77+
4. Create and send transactions with optional signals:
78+
79+
.. code-block:: python
80+
81+
# Create transaction with optional signal values
82+
tr = MetadataTr(data=0x1234, l3_csum_orig=0x5678, l3_csum_en=1)
83+
self.mvb_driver.append(tr)
84+
85+
.. note:: The ``_optional_signals`` list tells the driver/monitor which additional signals to look for on the interface. Signals not present on the DUT will be silently ignored.
86+
87+
This feature is also available for:
88+
89+
- **MFB** - optional signals are replicated across regions.
90+
- **AXI4-Stream** - control signals like ``TLAST`` and ``TKEEP`` are automatically handled by the driver.
91+
92+
.. note:: Each interface has its own default ``_optional_signals`` list. Check the driver/monitor source code for details.
93+
894
Using probes
995
============
1096

@@ -76,3 +162,4 @@ Which then produces output like this:
76162
# 10000.00ns INFO cocotb.ThroughputProbe - OUT Immediate throughput at 10.0 us: 134.5104 Gb/s, Immediate efficiency: 32.8395%
77163
# 20000.00ns INFO cocotb.ThroughputProbe - OUT Immediate throughput at 20.0 us: 134.8456 Gb/s, Immediate efficiency: 32.9213%
78164
# 30000.00ns INFO cocotb.ThroughputProbe - OUT Immediate throughput at 30.0 us: 134.9 Gb/s, Immediate efficiency: 32.9346%
165+

devel/_sources/index.rst.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ it also provides converters:
9797
:maxdepth: 1
9898

9999
basic_cocotb_test
100-
cocotbext
101100
cocotb_tips_and_tricks
101+
cocotbext
102102

103103
.. toctree::
104104
:caption: GitLab CI/CD Tools

devel/app-minimal.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@
8686
<p class="caption" role="heading"><span class="caption-text">cocotb Verifications</span></p>
8787
<ul>
8888
<li class="toctree-l1"><a class="reference internal" href="basic_cocotb_test.html">Getting Started with cocotb</a></li>
89-
<li class="toctree-l1"><a class="reference internal" href="cocotbext.html">cocotbext-ndk</a></li>
9089
<li class="toctree-l1"><a class="reference internal" href="cocotb_tips_and_tricks.html">Cocotb tips &amp; tricks</a></li>
90+
<li class="toctree-l1"><a class="reference internal" href="cocotbext.html">cocotbext-ndk</a></li>
9191
</ul>
9292
<p class="caption" role="heading"><span class="caption-text">GitLab CI/CD Tools</span></p>
9393
<ul>

devel/async.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@
9393
<p class="caption" role="heading"><span class="caption-text">cocotb Verifications</span></p>
9494
<ul>
9595
<li class="toctree-l1"><a class="reference internal" href="basic_cocotb_test.html">Getting Started with cocotb</a></li>
96-
<li class="toctree-l1"><a class="reference internal" href="cocotbext.html">cocotbext-ndk</a></li>
9796
<li class="toctree-l1"><a class="reference internal" href="cocotb_tips_and_tricks.html">Cocotb tips &amp; tricks</a></li>
97+
<li class="toctree-l1"><a class="reference internal" href="cocotbext.html">cocotbext-ndk</a></li>
9898
</ul>
9999
<p class="caption" role="heading"><span class="caption-text">GitLab CI/CD Tools</span></p>
100100
<ul>

devel/axi.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@
8585
<p class="caption" role="heading"><span class="caption-text">cocotb Verifications</span></p>
8686
<ul>
8787
<li class="toctree-l1"><a class="reference internal" href="basic_cocotb_test.html">Getting Started with cocotb</a></li>
88-
<li class="toctree-l1"><a class="reference internal" href="cocotbext.html">cocotbext-ndk</a></li>
8988
<li class="toctree-l1"><a class="reference internal" href="cocotb_tips_and_tricks.html">Cocotb tips &amp; tricks</a></li>
89+
<li class="toctree-l1"><a class="reference internal" href="cocotbext.html">cocotbext-ndk</a></li>
9090
</ul>
9191
<p class="caption" role="heading"><span class="caption-text">GitLab CI/CD Tools</span></p>
9292
<ul>

devel/base.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@
9090
<p class="caption" role="heading"><span class="caption-text">cocotb Verifications</span></p>
9191
<ul>
9292
<li class="toctree-l1"><a class="reference internal" href="basic_cocotb_test.html">Getting Started with cocotb</a></li>
93-
<li class="toctree-l1"><a class="reference internal" href="cocotbext.html">cocotbext-ndk</a></li>
9493
<li class="toctree-l1"><a class="reference internal" href="cocotb_tips_and_tricks.html">Cocotb tips &amp; tricks</a></li>
94+
<li class="toctree-l1"><a class="reference internal" href="cocotbext.html">cocotbext-ndk</a></li>
9595
</ul>
9696
<p class="caption" role="heading"><span class="caption-text">GitLab CI/CD Tools</span></p>
9797
<ul>

0 commit comments

Comments
 (0)