|
|
|
|
@@ -12,7 +12,7 @@ from peakrdl_busdecoder.cpuif.apb4 import APB4Cpuif
|
|
|
|
|
|
|
|
|
|
def test_external_nested_components_generate_correct_decoder(external_nested_rdl: AddrmapNode) -> None:
|
|
|
|
|
"""Test that external nested components generate correct decoder logic.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The decoder should:
|
|
|
|
|
- Generate select signals for multicast and port[16]
|
|
|
|
|
- NOT generate select signals for multicast.common[] or multicast.response
|
|
|
|
|
@@ -25,21 +25,21 @@ def test_external_nested_components_generate_correct_decoder(external_nested_rdl
|
|
|
|
|
tmpdir,
|
|
|
|
|
cpuif_cls=APB4Cpuif,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Read the generated module
|
|
|
|
|
module_file = Path(tmpdir) / "buffer_t.sv"
|
|
|
|
|
content = module_file.read_text()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Should have correct select signals
|
|
|
|
|
assert "cpuif_wr_sel.multicast = 1'b1;" in content
|
|
|
|
|
assert "cpuif_wr_sel.port[i0] = 1'b1;" in content
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Should NOT have invalid nested paths
|
|
|
|
|
assert "cpuif_wr_sel.multicast.common" not in content
|
|
|
|
|
assert "cpuif_wr_sel.multicast.response" not in content
|
|
|
|
|
assert "cpuif_rd_sel.multicast.common" not in content
|
|
|
|
|
assert "cpuif_rd_sel.multicast.response" not in content
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Verify struct is flat (no nested structs for external children)
|
|
|
|
|
assert "typedef struct" in content
|
|
|
|
|
assert "logic multicast;" in content
|
|
|
|
|
@@ -48,7 +48,7 @@ def test_external_nested_components_generate_correct_decoder(external_nested_rdl
|
|
|
|
|
|
|
|
|
|
def test_external_nested_components_generate_correct_interfaces(external_nested_rdl: AddrmapNode) -> None:
|
|
|
|
|
"""Test that external nested components generate correct interface ports.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The module should have:
|
|
|
|
|
- One master interface for multicast
|
|
|
|
|
- Array of 16 master interfaces for port[]
|
|
|
|
|
@@ -61,15 +61,15 @@ def test_external_nested_components_generate_correct_interfaces(external_nested_
|
|
|
|
|
tmpdir,
|
|
|
|
|
cpuif_cls=APB4Cpuif,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Read the generated module
|
|
|
|
|
module_file = Path(tmpdir) / "buffer_t.sv"
|
|
|
|
|
content = module_file.read_text()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Should have master interfaces for top-level external children
|
|
|
|
|
assert "m_apb_multicast" in content
|
|
|
|
|
assert "m_apb_port [16]" in content or "m_apb_port[16]" in content
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Should NOT have interfaces for nested external children
|
|
|
|
|
assert "m_apb_multicast_common" not in content
|
|
|
|
|
assert "m_apb_multicast_response" not in content
|
|
|
|
|
@@ -79,7 +79,7 @@ def test_external_nested_components_generate_correct_interfaces(external_nested_
|
|
|
|
|
|
|
|
|
|
def test_non_external_nested_components_are_descended(compile_rdl: Callable[..., AddrmapNode]) -> None:
|
|
|
|
|
"""Test that non-external nested components are still descended into.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This is a regression test to ensure we didn't break normal nested
|
|
|
|
|
component handling.
|
|
|
|
|
"""
|
|
|
|
|
@@ -98,16 +98,16 @@ def test_non_external_nested_components_are_descended(compile_rdl: Callable[...,
|
|
|
|
|
};
|
|
|
|
|
"""
|
|
|
|
|
top = compile_rdl(rdl_source, top="outer_block")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with TemporaryDirectory() as tmpdir:
|
|
|
|
|
exporter = BusDecoderExporter()
|
|
|
|
|
# Use depth=0 to descend all the way down to registers
|
|
|
|
|
exporter.export(top, tmpdir, cpuif_cls=APB4Cpuif, max_decode_depth=0)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Read the generated module
|
|
|
|
|
module_file = Path(tmpdir) / "outer_block.sv"
|
|
|
|
|
content = module_file.read_text()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Should descend into inner and reference inner_reg
|
|
|
|
|
assert "inner" in content
|
|
|
|
|
assert "inner_reg" in content
|
|
|
|
|
@@ -123,7 +123,7 @@ def test_max_decode_depth_parameter_exists(compile_rdl: Callable[..., AddrmapNod
|
|
|
|
|
};
|
|
|
|
|
"""
|
|
|
|
|
top = compile_rdl(rdl_source, top="simple")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with TemporaryDirectory() as tmpdir:
|
|
|
|
|
exporter = BusDecoderExporter()
|
|
|
|
|
# Should not raise an exception
|
|
|
|
|
@@ -133,7 +133,7 @@ def test_max_decode_depth_parameter_exists(compile_rdl: Callable[..., AddrmapNod
|
|
|
|
|
cpuif_cls=APB4Cpuif,
|
|
|
|
|
max_decode_depth=2,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Verify output was generated
|
|
|
|
|
module_file = Path(tmpdir) / "simple.sv"
|
|
|
|
|
assert module_file.exists()
|
|
|
|
|
@@ -141,7 +141,7 @@ def test_max_decode_depth_parameter_exists(compile_rdl: Callable[..., AddrmapNod
|
|
|
|
|
|
|
|
|
|
def test_unaligned_external_component_supported(compile_rdl: Callable[..., AddrmapNode]) -> None:
|
|
|
|
|
"""Test that external components can be at unaligned addresses.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This test verifies that external components don't need to be aligned
|
|
|
|
|
to a power-of-2 multiple of their size, as the busdecoder supports
|
|
|
|
|
unaligned access.
|
|
|
|
|
@@ -161,16 +161,16 @@ def test_unaligned_external_component_supported(compile_rdl: Callable[..., Addrm
|
|
|
|
|
};
|
|
|
|
|
"""
|
|
|
|
|
top = compile_rdl(rdl_source, top="buffer_t")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with TemporaryDirectory() as tmpdir:
|
|
|
|
|
exporter = BusDecoderExporter()
|
|
|
|
|
# Should not raise an alignment error
|
|
|
|
|
exporter.export(top, tmpdir, cpuif_cls=APB4Cpuif)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Verify output was generated
|
|
|
|
|
module_file = Path(tmpdir) / "buffer_t.sv"
|
|
|
|
|
assert module_file.exists()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
content = module_file.read_text()
|
|
|
|
|
# Verify the external component is in the generated code
|
|
|
|
|
assert "multicast" in content
|
|
|
|
|
@@ -178,7 +178,7 @@ def test_unaligned_external_component_supported(compile_rdl: Callable[..., Addrm
|
|
|
|
|
|
|
|
|
|
def test_unaligned_external_component_array_supported(compile_rdl: Callable[..., AddrmapNode]) -> None:
|
|
|
|
|
"""Test that external component arrays with non-power-of-2 strides are supported.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This test verifies that external component arrays can have arbitrary strides,
|
|
|
|
|
not just power-of-2 strides.
|
|
|
|
|
"""
|
|
|
|
|
@@ -197,16 +197,16 @@ def test_unaligned_external_component_array_supported(compile_rdl: Callable[...,
|
|
|
|
|
};
|
|
|
|
|
"""
|
|
|
|
|
top = compile_rdl(rdl_source, top="buffer_t")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with TemporaryDirectory() as tmpdir:
|
|
|
|
|
exporter = BusDecoderExporter()
|
|
|
|
|
# Should not raise an alignment error
|
|
|
|
|
exporter.export(top, tmpdir, cpuif_cls=APB4Cpuif)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Verify output was generated
|
|
|
|
|
module_file = Path(tmpdir) / "buffer_t.sv"
|
|
|
|
|
assert module_file.exists()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
content = module_file.read_text()
|
|
|
|
|
# Verify the external component array is in the generated code
|
|
|
|
|
assert "port" in content
|
|
|
|
|
@@ -214,7 +214,7 @@ def test_unaligned_external_component_array_supported(compile_rdl: Callable[...,
|
|
|
|
|
|
|
|
|
|
def test_unaligned_external_nested_in_addrmap(compile_rdl: Callable[..., AddrmapNode]) -> None:
|
|
|
|
|
"""Test that addrmaps containing external components can be at unaligned addresses.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This verifies that not just external components themselves, but also
|
|
|
|
|
non-external addrmaps/regfiles that contain external components can be
|
|
|
|
|
at unaligned addresses.
|
|
|
|
|
@@ -235,18 +235,16 @@ def test_unaligned_external_nested_in_addrmap(compile_rdl: Callable[..., Addrmap
|
|
|
|
|
};
|
|
|
|
|
"""
|
|
|
|
|
top = compile_rdl(rdl_source, top="outer_block")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with TemporaryDirectory() as tmpdir:
|
|
|
|
|
exporter = BusDecoderExporter()
|
|
|
|
|
# Should not raise an alignment error
|
|
|
|
|
exporter.export(top, tmpdir, cpuif_cls=APB4Cpuif)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Verify output was generated
|
|
|
|
|
module_file = Path(tmpdir) / "outer_block.sv"
|
|
|
|
|
assert module_file.exists()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
content = module_file.read_text()
|
|
|
|
|
# Verify the nested components are in the generated code
|
|
|
|
|
assert "inner" in content
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|