From b80f166997a74fb08d7923415741533149a7c18e Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Sun, 26 Oct 2025 19:05:45 -0700 Subject: [PATCH] Export master interface address widths in package parameters (#16) * Initial plan * Add master address width parameters to exported package 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> --- src/peakrdl_busdecoder/exporter.py | 2 + src/peakrdl_busdecoder/package_tmpl.sv | 3 + tests/exporter/test_bus_decoder_exporter.py | 87 +++++++++++++++++++++ 3 files changed, 92 insertions(+) diff --git a/src/peakrdl_busdecoder/exporter.py b/src/peakrdl_busdecoder/exporter.py index ec9b80a..1a9467a 100644 --- a/src/peakrdl_busdecoder/exporter.py +++ b/src/peakrdl_busdecoder/exporter.py @@ -17,6 +17,7 @@ from .identifier_filter import kw_filter as kwf from .listener import BusDecoderListener from .struct_gen import StructGenerator from .sv_int import SVInt +from .utils import clog2 from .validate_design import DesignValidator @@ -60,6 +61,7 @@ class BusDecoderExporter: ) self.jj_env.filters["kwf"] = kwf # type: ignore self.jj_env.filters["walk"] = self.walk # type: ignore + self.jj_env.filters["clog2"] = clog2 # type: ignore def export(self, node: RootNode | AddrmapNode, output_dir: str, **kwargs: Unpack[ExporterKwargs]) -> None: """ diff --git a/src/peakrdl_busdecoder/package_tmpl.sv b/src/peakrdl_busdecoder/package_tmpl.sv index 611b836..4745b1d 100644 --- a/src/peakrdl_busdecoder/package_tmpl.sv +++ b/src/peakrdl_busdecoder/package_tmpl.sv @@ -14,5 +14,8 @@ package {{ds.package_name}}; localparam {{ds.module_name.upper()}}_DATA_WIDTH = {{ds.cpuif_data_width}}; localparam {{ds.module_name.upper()}}_MIN_ADDR_WIDTH = {{ds.addr_width}}; localparam {{ds.module_name.upper()}}_SIZE = {{SVInt(ds.top_node.size)}}; +{%- for child in cpuif.addressable_children %} + localparam {{ds.module_name.upper()}}_{{child.inst_name.upper()}}_ADDR_WIDTH = {{child.size|clog2}}; +{%- endfor %} endpackage {# (eof newline anchor) #} diff --git a/tests/exporter/test_bus_decoder_exporter.py b/tests/exporter/test_bus_decoder_exporter.py index 0b5ad6e..f5bdbaf 100644 --- a/tests/exporter/test_bus_decoder_exporter.py +++ b/tests/exporter/test_bus_decoder_exporter.py @@ -193,3 +193,90 @@ class TestBusDecoderExporter: assert "reg1" in module_content assert "reg2" in module_content assert "reg3" in module_content + + def test_master_address_widths_export( + self, compile_rdl: Callable[..., AddrmapNode], tmp_path: Path + ) -> None: + """Test exporting master address width parameters for child addrmaps.""" + rdl_source = """ + addrmap child1 { + reg { + field { + sw=rw; + hw=r; + } data[31:0]; + } reg1 @ 0x0; + reg { + field { + sw=rw; + hw=r; + } data[31:0]; + } reg2 @ 0x4; + }; + + addrmap child2 { + reg { + field { + sw=rw; + hw=r; + } data[15:0]; + } reg2 @ 0x0; + }; + + addrmap parent { + external child1 c1 @ 0x0000; + external child2 c2 @ 0x1000; + }; + """ + top = compile_rdl(rdl_source, top="parent") + + exporter = BusDecoderExporter() + output_dir = str(tmp_path) + exporter.export(top, output_dir, cpuif_cls=APB4Cpuif) + + package_file = tmp_path / "parent_pkg.sv" + assert package_file.exists() + + package_content = package_file.read_text() + assert "package parent_pkg" in package_content + # Check for master address width parameters + assert "localparam PARENT_C1_ADDR_WIDTH = 3" in package_content + assert "localparam PARENT_C2_ADDR_WIDTH = 2" in package_content + + def test_master_address_widths_with_arrays( + self, compile_rdl: Callable[..., AddrmapNode], tmp_path: Path + ) -> None: + """Test exporting master address width parameters for arrayed child addrmaps.""" + rdl_source = """ + addrmap child { + reg { + field { + sw=rw; + hw=r; + } data[31:0]; + } reg1 @ 0x0; + reg { + field { + sw=rw; + hw=r; + } data[31:0]; + } reg2 @ 0x4; + }; + + addrmap parent { + external child children[4] @ 0x0 += 0x100; + }; + """ + top = compile_rdl(rdl_source, top="parent") + + exporter = BusDecoderExporter() + output_dir = str(tmp_path) + exporter.export(top, output_dir, cpuif_cls=APB4Cpuif) + + package_file = tmp_path / "parent_pkg.sv" + assert package_file.exists() + + package_content = package_file.read_text() + assert "package parent_pkg" in package_content + # Check for master address width parameter - array should have a single parameter + assert "localparam PARENT_CHILDREN_ADDR_WIDTH = 3" in package_content