|
| 1 | +==================== |
| 2 | +Cocotb tips & tricks |
| 3 | +==================== |
| 4 | + |
| 5 | +This section consists of simple problems you may encounter when creating testbenches |
| 6 | +using ``cocotb/cocotbext-ndk`` frameworks and the solutions to those problems. |
| 7 | + |
| 8 | +Using probes |
| 9 | +============ |
| 10 | + |
| 11 | +``cocotbext-ndk`` framework includes a base class for creating probes for various purposes. |
| 12 | +It can be found at ``ndk-fpga/python/cocotbext/cocotbext/ofm/base/probe.py``. The |
| 13 | +probes typically read attributes of their connected agents, usually a monitor or a driver, |
| 14 | +perform calculations with them, and display the results to the terminal either at a specific |
| 15 | +time, periodically, or on request. |
| 16 | + |
| 17 | +The base ``Probe`` class offers a couple of methods to make this possible. |
| 18 | + |
| 19 | +To log a specific time interval, use the ``add_log_interval`` method. If you want the time interval |
| 20 | +to go to infinity, set the ``stop_time`` argument to ``None``; however, don’t forget to also set a period, |
| 21 | +otherwise the probe will never log. |
| 22 | + |
| 23 | +Periodic logging can be achieved by setting a period using the ``set_log_period`` method. |
| 24 | + |
| 25 | +For cases where full control over when the probe starts and stops logging is needed, the ``start_log`` |
| 26 | +and ``stop_log`` methods are implemented. |
| 27 | + |
| 28 | +When it comes to specific implementations of probes, at the time of writing, there is only one, |
| 29 | +and that is ``ThroughputProbe`` for measuring throughput and efficiency. |
| 30 | +Check out ``ndk-fpga/python/cocotbext/cocotbext/ofm/utils/throughput_probe.py`` for the implementation. |
| 31 | + |
| 32 | +Class ``ThroughputProbe`` further adds the ``log_average_throughput`` and ``log_max_throughput`` methods |
| 33 | +to log the average throughput and efficiency and the maximal possible average throughput, |
| 34 | +respectively. It is recommended to call these methods at the end of the test when all the transactions |
| 35 | +have been processed. |
| 36 | + |
| 37 | +To perform its task, a probe typically needs to read attributes from the probed agent synchronously. |
| 38 | +However, the names of the attributes of the agent may differ from the names of the attributes of the probe, |
| 39 | +or they may not be present at all; in that case, they need to be either calculated or set to a fixed value. |
| 40 | + |
| 41 | +To resolve this, it is recommended to use interfaces derived from the ``ProbeInterface`` class. This class |
| 42 | +offers two approaches for passing a value to the probe – a translation dictionary ``interface_dict`` and |
| 43 | +properties. |
| 44 | + |
| 45 | +The translation dictionary ``interface_dict`` should contain all needed attributes as its keys. |
| 46 | +The values linked to the keys should be either the names of the equivalent attributes of the agent, |
| 47 | +or ``None`` to indicate that the value is returned by a property of the interface. |
| 48 | + |
| 49 | +If the value cannot be simply read from the agent object because some logic needs to be performed |
| 50 | +(e.g., the value must be calculated from multiple attributes, or the behavior depends on the type of the |
| 51 | +agent), a property with the same name as the key in ``interface_dict`` can be created, which overrides the |
| 52 | +dictionary entry. |
| 53 | + |
| 54 | +.. note:: The interface always looks for a property first. Only after it is not found does it try to get the value |
| 55 | + from the connected agent using ``interface_dict``. |
| 56 | + |
| 57 | +For a specific implementation of a probe interface, check out the different interfaces for |
| 58 | +``ThroughputProbe`` in ``ndk-fpga/python/cocotbext/cocotbext/ofm/utils/throughput_probe.py``. |
| 59 | + |
| 60 | +The setup of a probe can, for example, look like this: |
| 61 | + |
| 62 | +.. code-block:: python |
| 63 | +
|
| 64 | + self.out_throughput_probe = ThroughputProbe( |
| 65 | + ThroughputProbeMfbInterface(self.stream_out), |
| 66 | + throughput_units="bits", |
| 67 | + name="ThroughputProbe - OUT" |
| 68 | + ) |
| 69 | + self.out_throughput_probe.add_log_interval(0, None) |
| 70 | + self.out_throughput_probe.set_log_period(10) |
| 71 | +
|
| 72 | +Which then produces output like this: |
| 73 | + |
| 74 | +.. code-block:: |
| 75 | +
|
| 76 | + # 10000.00ns INFO cocotb.ThroughputProbe - OUT Immediate throughput at 10.0 us: 134.5104 Gb/s, Immediate efficiency: 32.8395% |
| 77 | + # 20000.00ns INFO cocotb.ThroughputProbe - OUT Immediate throughput at 20.0 us: 134.8456 Gb/s, Immediate efficiency: 32.9213% |
| 78 | + # 30000.00ns INFO cocotb.ThroughputProbe - OUT Immediate throughput at 30.0 us: 134.9 Gb/s, Immediate efficiency: 32.9346% |
0 commit comments