.. _testing:
Testing
=======
PeakRDL-etana includes a comprehensive test suite built with `Cocotb `_,
validating register block functionality across multiple CPU interfaces and configurations.
Test Framework Overview
-----------------------
The test suite validates:
* Basic register operations (read, write, reset values)
* All SystemRDL field types and properties
* Hardware interface signal behavior
* CPU interface error responses (NEW in v0.23)
* External registers and memories
* Counter fields, interrupts, and side effects
* Multiple CPU interfaces and configurations
Test Modes
----------
Tests can run in three different modes:
Etana Mode (Default)
^^^^^^^^^^^^^^^^^^^^
Tests the PeakRDL-etana generated RTL using Icarus Verilog:
.. code-block:: bash
cd tests/test_simple
make clean etana sim COCOTB_REV=1.9.2
Regblock Reference Mode
^^^^^^^^^^^^^^^^^^^^^^^
Tests against PeakRDL-regblock reference implementation using Verilator:
.. code-block:: bash
make clean regblock sim COCOTB_REV=1.9.2 REGBLOCK=1
This validates that etana produces functionally equivalent RTL to the upstream project.
VHDL Mode
^^^^^^^^^
Tests VHDL generation (select tests only):
.. code-block:: bash
make clean regblock-vhdl sim COCOTB_REV=1.9.2 GHDL=1
Key Test Cases
--------------
test_simple
^^^^^^^^^^^
Basic register operations and field types.
**Validates:**
* Register read/write operations
* Reset value initialization
* Basic field properties (sw, hw access)
test_cpuif_err_rsp
^^^^^^^^^^^^^^^^^^
CPU interface error response validation (NEW).
**Validates:**
* Error responses for unmapped addresses (``--err-if-bad-addr``)
* Error responses for forbidden reads/writes (``--err-if-bad-rw``)
* Read-only register write protection
* Write-only register read protection
* External register/memory error handling
**Register Map:**
.. code-block::
0x00: r_rw - Read/Write register (internal)
0x04: r_r - Read-only register (internal)
0x08: r_w - Write-only register (internal)
0x0C: er_rw - External R/W register
0x10: er_r - External read-only register
0x14: er_w - External write-only register
0x18: - Generates error response
0x20: mem_rw - External R/W memory
0x28: mem_r - External read-only memory
0x30: mem_w - External write-only memory
**Supported CPU Interfaces:**
* APB4 (validates ``pslverr`` signal)
* AXI4-Lite (validates ``rresp``/``bresp`` signals)
* AHB (validates ``hresp`` signal)
* OBI (validates ``err`` signal)
* Wishbone (validates ``wb_err`` signal)
* Passthrough (validates ``rd_err``/``wr_err`` signals)
**Usage:**
.. code-block:: bash
cd tests/test_cpuif_err_rsp
make clean etana sim COCOTB_REV=1.9.2 CPUIF=apb4-flat
test_external
^^^^^^^^^^^^^
External register and memory validation.
**Validates:**
* External register protocol (req, ack, data)
* Read and write operations to external components
* External memory block access
* Hardware interface signal timing
test_counter_basics
^^^^^^^^^^^^^^^^^^^
Counter field type validation.
**Validates:**
* Increment and decrement counters
* Overflow/underflow behavior
* Counter reset and enable
test_field_types
^^^^^^^^^^^^^^^^
Comprehensive field type coverage.
**Validates:**
* All standard SystemRDL field types
* Field properties (onread, onwrite, etc.)
* Field access combinations
Running Tests
-------------
Run All Tests
^^^^^^^^^^^^^
Execute the complete test suite:
.. code-block:: bash
cd tests
./test_all.sh
This runs all tests with default settings (Icarus Verilog, Cocotb 1.9.2).
Run Specific Test
^^^^^^^^^^^^^^^^^
Navigate to a test directory and run:
.. code-block:: bash
cd tests/test_cpuif_err_rsp
make clean etana sim COCOTB_REV=1.9.2
CPU Interface Selection
^^^^^^^^^^^^^^^^^^^^^^^
Test with different CPU interfaces:
.. code-block:: bash
# APB4 (default)
make sim CPUIF=apb4-flat
# AXI4-Lite
make sim CPUIF=axi4-lite-flat
# AHB
make sim CPUIF=ahb-flat
# OBI
make sim CPUIF=obi-flat
# Wishbone
make sim CPUIF=wishbone-flat
# Passthrough
make sim CPUIF=passthrough
Generate Waveforms
^^^^^^^^^^^^^^^^^^
Enable waveform generation for debugging:
.. code-block:: bash
# Icarus (generates .fst file)
make sim WAVES=1
# View waveforms
gtkwave sim_build/*.fst
Test Infrastructure
-------------------
Base Testbench
^^^^^^^^^^^^^^
All tests use ``tb_base.py`` which provides:
* Auto-detection of CPU interface type
* Clock and reset management
* Unified interface abstraction
* Common utility functions
Bus Wrappers
^^^^^^^^^^^^
Located in ``tests/interfaces/``:
* ``apb_wrapper.py`` - APB4 bus functional model
* ``axi_wrapper.py`` - AXI4-Lite bus functional model
* ``ahb_wrapper.py`` - AHB bus functional model
* ``wishbone_wrapper.py`` - Wishbone B4 bus functional model
* ``passthrough.py`` - Passthrough protocol driver
All wrappers support the ``error_expected`` parameter for error response validation.
External Emulators
^^^^^^^^^^^^^^^^^^
Located in ``tests/test_cpuif_err_rsp/external_emulators.py``:
* ``SimpleExtRegEmulator`` - Read/write external register
* ``SimpleExtRegReadOnly`` - Read-only external register
* ``SimpleExtRegWriteOnly`` - Write-only external register
* ``SimpleExtMemEmulator`` - Read/write external memory
* ``SimpleExtMemReadOnly`` - Read-only external memory
* ``SimpleExtMemWriteOnly`` - Write-only external memory
**Features:**
* Auto-detection of field naming (regblock vs etana)
* Bit-enable mask support
* Single-cycle response latency
* Compatible with all CPU interfaces
Writing Tests
-------------
Basic Test Pattern
^^^^^^^^^^^^^^^^^^
.. code-block:: python
from cocotb import test
from tb_base import testbench
@test()
async def test_my_feature(dut):
"""Test description"""
tb = testbench(dut)
# Write to register
await tb.intf.write(0x00, 0x1234)
# Read back and verify
await tb.intf.read(0x00, 0x1234)
await tb.clk.end_test()
Error Response Testing
^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: python
@test()
async def test_errors(dut):
"""Test error responses"""
tb = testbench(dut)
# Expect error on unmapped address
await tb.intf.read(0xFF, 0, error_expected=True)
# Expect error on write to read-only register
await tb.intf.write(0x04, 0x5678, error_expected=True)
await tb.clk.end_test()
External Register Testing
^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: python
from cocotb import test, start_soon
from tb_base import testbench
from external_emulators import SimpleExtRegEmulator
@test()
async def test_external(dut):
"""Test external register"""
tb = testbench(dut)
# Create and start emulator
ext_reg = SimpleExtRegEmulator(dut, tb.clk.clk, "hwif_out_my_reg")
start_soon(ext_reg.run())
# Set value in emulator
ext_reg.value = 0xABCD
await tb.clk.wait_clkn(2)
# Read from CPU interface
await tb.intf.read(0x10, 0xABCD)
await tb.clk.end_test()
Test Directory Structure
------------------------
Each test follows this structure:
.. code-block::
tests/test_/
├── Makefile # Includes ../tests.mak
├── regblock.rdl # Register definition (copied from upstream)
├── test_dut.py # Cocotb test implementation
└── external_emulators.py # (Optional) External component emulators
Continuous Integration
----------------------
GitHub Actions workflows validate all tests across:
* **Python versions:** 3.8, 3.9, 3.10, 3.11, 3.12, 3.13
* **Simulators:** Icarus Verilog, Verilator
* **Cocotb version:** 1.9.2
* **Test modes:** Etana, Regblock reference
Workflows run on:
* Every push to branches
* Every pull request
* Weekly schedule (Sunday 1:00 AM)
Test workflows skip on tag pushes to avoid redundant runs during releases.
Troubleshooting
---------------
Common Issues
^^^^^^^^^^^^^
**ModuleNotFoundError: No module named 'cocotb'**
Activate the virtual environment:
.. code-block:: bash
source ../venv.2.0.0/bin/activate
**Signal Name Mismatch**
Regblock and etana have different field naming conventions:
* **Regblock:** Includes field suffix (e.g., ``hwif_out_reg_wr_data_f``)
* **Etana:** No field suffix (e.g., ``hwif_out_reg_wr_data``)
The external emulators auto-detect this difference.
**Cocotb 2.0.0 + AXI4-Lite Compatibility**
Use Cocotb 1.9.2 for AXI4-Lite testing:
.. code-block:: bash
make sim COCOTB_REV=1.9.2
Further Documentation
---------------------
For detailed test suite documentation, see ``tests/TEST_SUITE_README.md`` in the repository.
For test migration guidelines, see ``cursor_help/COCOTB_MIGRATION_GUIDE.md``.