* Initial plan * Fix nonconstant index error by using unpacked structs and arrays Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com> * Add comprehensive tests for Questa compatibility with instance arrays Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com> * Add intermediate signals for interface array fanin to fix Questa compatibility Questa simulator rejects indexing interface arrays with non-constant variables in procedural blocks (always_comb). This fix creates intermediate unpacked array signals that are assigned from interface arrays using generate loops (with genvar), then references those intermediates in the fanin logic. Changes: - Added fanin_intermediate_gen.py to generate intermediate signals - Modified APB3/APB4/AXI4-Lite cpuif classes to use intermediates for interface arrays - Updated templates to include intermediate signal section - Intermediate signals use genvar indexing (legal) instead of variable indexing (illegal in Questa) Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com> * Fix type checking and formatting issues in fanin intermediate generator - Added proper null checks for node.array_dimensions to avoid type errors - Used getattr() to safely access is_interface and _interface attributes - Added early returns when interface is None to prevent errors - Fixed formatting issues in fanin_intermediate_gen.py - All type checks now pass (only pre-existing errors remain in other files) - All 67 tests still pass Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com> * Fix test collection when cocotb is not installed The cocotb test files (test_runner.py) have imports that fail at module level when cocotb is not installed, causing pytest collection to fail. This prevents running tests in environments without cocotb dependencies. Solution: Updated conftest.py to conditionally ignore cocotb tests when cocotb is not available, allowing tests to pass in both environments (with and without cocotb). - When cocotb is available: only ignore test_register_access.py files (existing behavior) - When cocotb is not available: ignore all files under cocotb/** directories This allows CI to run all 67 non-simulation tests successfully without requiring cocotb/verilator dependencies for basic testing. Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com> * add default for unpacked struct * cocotb is test dependancy * Refactor fanin intermediate signal logic to cpuif level Moved the interface-specific signal assignment logic from fanin_intermediate_gen.py to individual cpuif classes (APB3Cpuif, APB4Cpuif, AXI4LiteCpuif). This follows better architecture principles where each cpuif knows which signals it needs. Changes: - Added fanin_intermediate_assignments() method to BaseCpuif - Implemented fanin_intermediate_assignments() in APB3Cpuif, APB4Cpuif, and AXI4LiteCpuif - Updated FaninIntermediateGenerator to call the cpuif method instead of checking interface type - Removed interface type checking logic from fanin_intermediate_gen.py This makes the code more maintainable and follows the single responsibility principle - each cpuif class knows its own signal requirements. 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>
106 lines
3.1 KiB
Python
106 lines
3.1 KiB
Python
from collections.abc import Callable
|
|
|
|
from systemrdl.node import AddrmapNode
|
|
|
|
from peakrdl_busdecoder.design_state import DesignState
|
|
from peakrdl_busdecoder.struct_gen import StructGenerator
|
|
|
|
|
|
class TestStructGenerator:
|
|
"""Test the StructGenerator."""
|
|
|
|
def test_simple_struct_generation(self, compile_rdl: Callable[..., AddrmapNode]) -> None:
|
|
"""Test struct generation for simple register."""
|
|
rdl_source = """
|
|
addrmap test {
|
|
reg {
|
|
field {
|
|
sw=rw;
|
|
hw=r;
|
|
} data[31:0];
|
|
} my_reg @ 0x0;
|
|
};
|
|
"""
|
|
top = compile_rdl(rdl_source, top="test")
|
|
|
|
ds = DesignState(top, {})
|
|
gen = StructGenerator(ds)
|
|
|
|
# Should generate struct definition
|
|
assert gen is not None
|
|
result = str(gen)
|
|
|
|
# Should contain struct declaration
|
|
assert "struct" in result or "typedef" in result
|
|
|
|
def test_nested_struct_generation(self, compile_rdl: Callable[..., AddrmapNode]) -> None:
|
|
"""Test struct generation for nested addrmaps."""
|
|
rdl_source = """
|
|
addrmap inner {
|
|
reg {
|
|
field {
|
|
sw=rw;
|
|
hw=r;
|
|
} data[31:0];
|
|
} inner_reg @ 0x0;
|
|
};
|
|
|
|
addrmap outer {
|
|
inner my_inner @ 0x0;
|
|
};
|
|
"""
|
|
top = compile_rdl(rdl_source, top="outer")
|
|
|
|
ds = DesignState(top, {})
|
|
gen = StructGenerator(ds)
|
|
|
|
# Walk the tree to generate structs
|
|
from systemrdl.walker import RDLWalker
|
|
|
|
walker = RDLWalker()
|
|
walker.walk(top, gen, skip_top=True)
|
|
|
|
result = str(gen)
|
|
|
|
# Should contain struct declaration
|
|
assert "struct" in result or "typedef" in result
|
|
# The struct should reference the inner component
|
|
assert "my_inner" in result
|
|
|
|
def test_array_struct_generation(self, compile_rdl: Callable[..., AddrmapNode]) -> None:
|
|
"""Test struct generation for register arrays."""
|
|
rdl_source = """
|
|
addrmap test {
|
|
reg {
|
|
field {
|
|
sw=rw;
|
|
hw=r;
|
|
} data[31:0];
|
|
} my_regs[4] @ 0x0;
|
|
};
|
|
"""
|
|
top = compile_rdl(rdl_source, top="test")
|
|
|
|
ds = DesignState(top, {})
|
|
gen = StructGenerator(ds)
|
|
|
|
# Walk the tree to generate structs
|
|
from systemrdl.walker import RDLWalker
|
|
|
|
walker = RDLWalker()
|
|
walker.walk(top, gen, skip_top=True)
|
|
|
|
result = str(gen)
|
|
|
|
# Should contain array notation
|
|
assert "[" in result and "]" in result
|
|
# Should reference the register
|
|
assert "my_regs" in result
|
|
# Should use unpacked array syntax (name[size]), not packed bit-vector ([size:0]name)
|
|
assert "my_regs[4]" in result
|
|
# Should NOT use packed bit-vector syntax
|
|
assert "[3:0]my_regs" not in result
|
|
# Should be unpacked struct, not packed
|
|
assert "typedef struct {" in result
|
|
assert "typedef struct packed" not in result
|