diff --git a/pyproject.toml b/pyproject.toml index bc8e139..3281182 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "peakrdl-busdecoder" -version = "0.6.7" +version = "0.6.8" requires-python = ">=3.10" dependencies = [ "jinja2~=3.1", diff --git a/src/peakrdl_busdecoder/design_scanner.py b/src/peakrdl_busdecoder/design_scanner.py index 871b4b7..7625d4d 100644 --- a/src/peakrdl_busdecoder/design_scanner.py +++ b/src/peakrdl_busdecoder/design_scanner.py @@ -44,3 +44,14 @@ class DesignScanner(RDLListener): self.ds.has_external_addressable = True if not isinstance(node, RegNode): self.ds.has_external_block = True + + def enter_Reg(self, node: RegNode) -> None: + if node.external and node != self.top_node: + return + + accesswidth = node.get_property("accesswidth") + if accesswidth is None: + return + + if accesswidth > self.ds.cpuif_data_width: + self.ds.cpuif_data_width = accesswidth diff --git a/tests/cocotb_lib/__init__.py b/tests/cocotb_lib/__init__.py index 91bea50..2ca262d 100644 --- a/tests/cocotb_lib/__init__.py +++ b/tests/cocotb_lib/__init__.py @@ -5,6 +5,8 @@ RDL_CASES: list[tuple[str, str]] = [ ("multiple_reg.rdl", "multi_reg"), ("deep_hierarchy.rdl", "deep_hierarchy"), ("wide_status.rdl", "wide_status"), + ("wide_access_64.rdl", "wide_access_64"), + ("wide_access_128.rdl", "wide_access_128"), ("variable_layout.rdl", "variable_layout"), ("asymmetric_bus.rdl", "asymmetric_bus"), ] diff --git a/tests/cocotb_lib/rdl/asymmetric_bus.rdl b/tests/cocotb_lib/rdl/asymmetric_bus.rdl index 8a730f4..18ae6e7 100644 --- a/tests/cocotb_lib/rdl/asymmetric_bus.rdl +++ b/tests/cocotb_lib/rdl/asymmetric_bus.rdl @@ -73,6 +73,7 @@ addrmap asymmetric_bus { reg { regwidth = 64; + accesswidth = 32; field { sw = rw; hw = rw; @@ -88,11 +89,18 @@ addrmap asymmetric_bus { reg { regwidth = 128; + accesswidth = 32; field { sw = rw; hw = rw; reset = 0x0; - } extended_id[63:0]; + } extended_id_low[31:0]; + + field { + sw = rw; + hw = rw; + reset = 0x0; + } extended_id_high[63:32]; field { sw = rw; diff --git a/tests/cocotb_lib/rdl/variable_layout.rdl b/tests/cocotb_lib/rdl/variable_layout.rdl index 2cac1e8..f95f099 100644 --- a/tests/cocotb_lib/rdl/variable_layout.rdl +++ b/tests/cocotb_lib/rdl/variable_layout.rdl @@ -69,6 +69,7 @@ regfile slice_rf { reg { regwidth = 64; + accesswidth = 32; field { sw = r; hw = w; diff --git a/tests/cocotb_lib/rdl/wide_access_128.rdl b/tests/cocotb_lib/rdl/wide_access_128.rdl new file mode 100644 index 0000000..1e40282 --- /dev/null +++ b/tests/cocotb_lib/rdl/wide_access_128.rdl @@ -0,0 +1,75 @@ +reg payload128_reg_t { + regwidth = 128; + accesswidth = 128; + desc = "128-bit payload register."; + + field { + sw = rw; + hw = rw; + reset = 0x0; + } word0[31:0]; + + field { + sw = rw; + hw = rw; + reset = 0x0; + } word1[63:32]; + + field { + sw = rw; + hw = rw; + reset = 0x0; + } word2[95:64]; + + field { + sw = rw; + hw = rw; + reset = 0x0; + } word3[127:96]; +}; + +regfile block128_rf { + payload128_reg_t payload @ 0x0; + + reg { + regwidth = 128; + accesswidth = 128; + field { + sw = r; + hw = w; + reset = 0x0; + } status0[31:0]; + + field { + sw = r; + hw = w; + reset = 0x0; + } status1[63:32]; + + field { + sw = r; + hw = w; + reset = 0x0; + } status2[95:64]; + + field { + sw = r; + hw = w; + reset = 0x0; + } status3[127:96]; + } status @ 0x10; +}; + +addrmap wide_access_128 { + block128_rf blocks[2] @ 0x0 += 0x40; + + reg { + regwidth = 64; + accesswidth = 64; + field { + sw = rw; + hw = rw; + reset = 0x0; + } id[63:0]; + } id @ 0x100; +}; diff --git a/tests/cocotb_lib/rdl/wide_access_64.rdl b/tests/cocotb_lib/rdl/wide_access_64.rdl new file mode 100644 index 0000000..2d6e0f4 --- /dev/null +++ b/tests/cocotb_lib/rdl/wide_access_64.rdl @@ -0,0 +1,56 @@ +reg status64_reg_t { + regwidth = 64; + accesswidth = 64; + desc = "64-bit status register."; + + field { + sw = r; + hw = w; + reset = 0x0; + } status_lo[31:0]; + + field { + sw = r; + hw = w; + reset = 0x0; + } status_hi[63:32]; +}; + +regfile channel64_rf { + status64_reg_t status @ 0x0; + + reg { + regwidth = 64; + accesswidth = 64; + field { + sw = rw; + hw = rw; + reset = 0x1; + } enable[0:0]; + + field { + sw = rw; + hw = rw; + reset = 0x0; + } mode[2:1]; + + field { + sw = rw; + hw = rw; + reset = 0x0; + } threshold[63:3]; + } control @ 0x8; +}; + +addrmap wide_access_64 { + channel64_rf channels[4] @ 0x0 += 0x20; + + reg { + regwidth = 32; + field { + sw = rw; + hw = rw; + reset = 0x0; + } flags[31:0]; + } flags @ 0x100; +}; diff --git a/tests/cocotb_lib/rdl/wide_status.rdl b/tests/cocotb_lib/rdl/wide_status.rdl index 4b34c2a..516e08a 100644 --- a/tests/cocotb_lib/rdl/wide_status.rdl +++ b/tests/cocotb_lib/rdl/wide_status.rdl @@ -1,5 +1,6 @@ reg status_reg_t { regwidth = 64; + accesswidth = 32; desc = "Status register capturing wide flags and sticky bits."; field { @@ -7,7 +8,14 @@ reg status_reg_t { hw = w; onread = rclr; reset = 0x0; - } flags[62:0]; + } flags_low[31:0]; + + field { + sw = r; + hw = w; + onread = rclr; + reset = 0x0; + } flags_high[62:32]; field { sw = rw; @@ -18,6 +26,7 @@ reg status_reg_t { reg metrics_reg_t { regwidth = 64; + accesswidth = 32; desc = "Metrics register pairing counters with thresholds."; field { @@ -40,11 +49,30 @@ addrmap wide_status { reg { regwidth = 128; + accesswidth = 32; field { sw = rw; hw = rw; reset = 0x0; - } configuration[127:0]; + } configuration_0[31:0]; + + field { + sw = rw; + hw = rw; + reset = 0x0; + } configuration_1[63:32]; + + field { + sw = rw; + hw = rw; + reset = 0x0; + } configuration_2[95:64]; + + field { + sw = rw; + hw = rw; + reset = 0x0; + } configuration_3[127:96]; } configuration @ 0x800; reg { diff --git a/tests/generator/test_design_state.py b/tests/generator/test_design_state.py index 9c13134..1f180f2 100644 --- a/tests/generator/test_design_state.py +++ b/tests/generator/test_design_state.py @@ -122,3 +122,43 @@ class TestDesignState: # Should infer 32-bit data width from field assert ds.cpuif_data_width == 32 + + def test_design_state_accesswidth_64(self, compile_rdl: Callable[..., AddrmapNode]) -> None: + """Test DesignState with explicit 64-bit access width.""" + rdl_source = """ + addrmap test { + reg { + regwidth = 64; + accesswidth = 64; + field { + sw=rw; + hw=r; + } data[63:0]; + } my_reg @ 0x0; + }; + """ + top = compile_rdl(rdl_source, top="test") + + ds = DesignState(top, {}) + + assert ds.cpuif_data_width == 64 + + def test_design_state_accesswidth_128(self, compile_rdl: Callable[..., AddrmapNode]) -> None: + """Test DesignState with explicit 128-bit access width.""" + rdl_source = """ + addrmap test { + reg { + regwidth = 128; + accesswidth = 128; + field { + sw=rw; + hw=r; + } data[127:0]; + } my_reg @ 0x0; + }; + """ + top = compile_rdl(rdl_source, top="test") + + ds = DesignState(top, {}) + + assert ds.cpuif_data_width == 128 diff --git a/uv.lock b/uv.lock index 9e14dc8..8fe2a71 100644 --- a/uv.lock +++ b/uv.lock @@ -526,7 +526,7 @@ wheels = [ [[package]] name = "peakrdl-busdecoder" -version = "0.6.7" +version = "0.6.8" source = { editable = "." } dependencies = [ { name = "jinja2" },