Files
PeakRDL-BusDecoder/tests/cocotb/examples.py
Copilot 4dc61d24ca Add cocotb testbench for validating generated bus decoder RTL across APB3, APB4, and AXI4-Lite interfaces (#9)
* Initial plan

* Add cocotb test infrastructure and testbenches for APB3, APB4, and AXI4-Lite

Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>

* Add integration tests, examples, and documentation for cocotb testbenches

Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>

* Address code review feedback: use relative imports and update installation docs

Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>

* Add implementation summary document

Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>

* Merge cocotb dependencies into test group

Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>

* Add optional cocotb simulation workflow with Icarus Verilog

Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>
2025-10-23 23:46:51 -07:00

222 lines
6.3 KiB
Python

#!/usr/bin/env python3
"""
Example script showing how to generate and test bus decoders.
This script demonstrates:
1. Compiling RDL specifications
2. Generating SystemVerilog decoders for different CPU interfaces
3. Validating the generated code (syntax check only, no simulation)
To run actual cocotb simulations, you need:
- Icarus Verilog, Verilator, or other HDL simulator
- cocotb and cocotb-bus Python packages
"""
import sys
import tempfile
from pathlib import Path
from peakrdl_busdecoder.cpuif.apb3 import APB3Cpuif
from peakrdl_busdecoder.cpuif.apb4 import APB4Cpuif
from peakrdl_busdecoder.cpuif.axi4lite import AXI4LiteCpuif
from .common.utils import compile_rdl_and_export
def example_apb4_simple_register():
"""Generate APB4 decoder for a simple register."""
print("\n" + "=" * 70)
print("Example 1: APB4 Decoder with Simple Register")
print("=" * 70)
rdl_source = """
addrmap simple_test {
name = "Simple Register Test";
desc = "A simple register for testing";
reg {
name = "Test Register";
desc = "32-bit test register";
field {
sw=rw;
hw=r;
desc = "Data field";
} data[31:0];
} test_reg @ 0x0;
};
"""
with tempfile.TemporaryDirectory() as tmpdir:
print(f"\nGenerating SystemVerilog in: {tmpdir}")
module_path, package_path = compile_rdl_and_export(
rdl_source, "simple_test", tmpdir, APB4Cpuif
)
print(f"✓ Generated module: {module_path.name}")
print(f"✓ Generated package: {package_path.name}")
# Show snippet of generated code
with open(module_path) as f:
lines = f.readlines()[:20]
print("\n--- Generated Module (first 20 lines) ---")
for line in lines:
print(line, end="")
def example_apb3_multiple_registers():
"""Generate APB3 decoder for multiple registers."""
print("\n" + "=" * 70)
print("Example 2: APB3 Decoder with Multiple Registers")
print("=" * 70)
rdl_source = """
addrmap multi_reg {
name = "Multiple Register Block";
reg {
name = "Control Register";
field { sw=rw; hw=r; } data[31:0];
} ctrl @ 0x0;
reg {
name = "Status Register";
field { sw=r; hw=w; } status[15:0];
} status @ 0x4;
reg {
name = "Data Register";
field { sw=rw; hw=r; } data[31:0];
} data @ 0x8;
};
"""
with tempfile.TemporaryDirectory() as tmpdir:
print(f"\nGenerating SystemVerilog in: {tmpdir}")
module_path, package_path = compile_rdl_and_export(
rdl_source, "multi_reg", tmpdir, APB3Cpuif
)
print(f"✓ Generated module: {module_path.name}")
print(f"✓ Generated package: {package_path.name}")
# Count registers in generated code
with open(module_path) as f:
content = f.read()
print(f"\n✓ Found 'ctrl' in generated code: {'ctrl' in content}")
print(f"✓ Found 'status' in generated code: {'status' in content}")
print(f"✓ Found 'data' in generated code: {'data' in content}")
def example_axi4lite_nested_addrmap():
"""Generate AXI4-Lite decoder for nested address map."""
print("\n" + "=" * 70)
print("Example 3: AXI4-Lite Decoder with Nested Address Map")
print("=" * 70)
rdl_source = """
addrmap inner_block {
name = "Inner Block";
reg {
field { sw=rw; hw=r; } data[31:0];
} inner_reg @ 0x0;
};
addrmap outer_block {
name = "Outer Block";
inner_block inner @ 0x0;
reg {
field { sw=rw; hw=r; } outer_data[31:0];
} outer_reg @ 0x100;
};
"""
with tempfile.TemporaryDirectory() as tmpdir:
print(f"\nGenerating SystemVerilog in: {tmpdir}")
module_path, package_path = compile_rdl_and_export(
rdl_source, "outer_block", tmpdir, AXI4LiteCpuif
)
print(f"✓ Generated module: {module_path.name}")
print(f"✓ Generated package: {package_path.name}")
# Check for nested structure
with open(module_path) as f:
content = f.read()
print(f"\n✓ Found 'inner' in generated code: {'inner' in content}")
print(f"✓ Found 'outer_reg' in generated code: {'outer_reg' in content}")
def example_register_array():
"""Generate decoder with register arrays."""
print("\n" + "=" * 70)
print("Example 4: Decoder with Register Arrays")
print("=" * 70)
rdl_source = """
addrmap array_test {
name = "Register Array Test";
reg {
field { sw=rw; hw=r; } data[31:0];
} regs[8] @ 0x0 += 0x4;
};
"""
with tempfile.TemporaryDirectory() as tmpdir:
print(f"\nGenerating SystemVerilog in: {tmpdir}")
module_path, package_path = compile_rdl_and_export(
rdl_source, "array_test", tmpdir, APB4Cpuif
)
print(f"✓ Generated module: {module_path.name}")
print(f"✓ Generated package: {package_path.name}")
with open(module_path) as f:
content = f.read()
print(f"\n✓ Found 'regs' in generated code: {'regs' in content}")
def main():
"""Run all examples."""
print("\n")
print("*" * 70)
print("*" + " " * 68 + "*")
print("*" + " PeakRDL-BusDecoder: Code Generation Examples".center(68) + "*")
print("*" + " " * 68 + "*")
print("*" * 70)
try:
example_apb4_simple_register()
example_apb3_multiple_registers()
example_axi4lite_nested_addrmap()
example_register_array()
print("\n" + "=" * 70)
print("All examples completed successfully!")
print("=" * 70)
print(
"""
To run actual simulations with cocotb:
1. Install simulator: apt-get install iverilog (or verilator)
2. Install cocotb: pip install cocotb cocotb-bus
3. Run tests: pytest tests/cocotb/testbenches/
For more information, see: tests/cocotb/README.md
"""
)
except Exception as e:
print(f"\n✗ Error: {e}")
import traceback
traceback.print_exc()
return 1
return 0
if __name__ == "__main__":
sys.exit(main())