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>
This commit is contained in:
Copilot
2025-10-23 23:46:51 -07:00
committed by GitHub
parent 0b98165ccc
commit 4dc61d24ca
17 changed files with 2028 additions and 7 deletions

View File

@@ -0,0 +1,80 @@
"""Common utilities for cocotb testbenches."""
import os
import tempfile
from pathlib import Path
from tempfile import NamedTemporaryFile
from typing import Any
from systemrdl import RDLCompiler
from peakrdl_busdecoder.exporter import BusDecoderExporter
def compile_rdl_and_export(
rdl_source: str, top_name: str, output_dir: str, cpuif_cls: Any, **kwargs: Any
) -> tuple[Path, Path]:
"""
Compile RDL source and export to SystemVerilog.
Args:
rdl_source: SystemRDL source code as a string
top_name: Name of the top-level addrmap
output_dir: Directory to write generated files
cpuif_cls: CPU interface class to use
**kwargs: Additional arguments to pass to exporter
Returns:
Tuple of (module_path, package_path) for generated files
"""
# Compile RDL source
compiler = RDLCompiler()
# Write source to temporary file
with NamedTemporaryFile("w", suffix=".rdl", dir=output_dir, delete=False) as tmp_file:
tmp_file.write(rdl_source)
tmp_file.flush()
tmp_path = tmp_file.name
try:
compiler.compile_file(tmp_path)
top = compiler.elaborate(top_name)
# Export to SystemVerilog
exporter = BusDecoderExporter()
exporter.export(top, output_dir, cpuif_cls=cpuif_cls, **kwargs)
finally:
# Clean up temporary RDL file
if os.path.exists(tmp_path):
os.unlink(tmp_path)
# Return paths to generated files
module_name = kwargs.get("module_name", top_name)
package_name = kwargs.get("package_name", f"{top_name}_pkg")
module_path = Path(output_dir) / f"{module_name}.sv"
package_path = Path(output_dir) / f"{package_name}.sv"
return module_path, package_path
def get_verilog_sources(module_path: Path, package_path: Path, intf_files: list[Path]) -> list[str]:
"""
Get list of Verilog source files needed for simulation.
Args:
module_path: Path to the generated module file
package_path: Path to the generated package file
intf_files: List of paths to interface definition files
Returns:
List of source file paths as strings
"""
sources = []
# Add interface files first
sources.extend([str(f) for f in intf_files])
# Add package file
sources.append(str(package_path))
# Add module file
sources.append(str(module_path))
return sources