* fix

* fix pyrefly

* remove tests

* Update tests/unit/test_exporter.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update src/peakrdl_busdecoder/listener.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update tests/unit/test_exporter.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix iter

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Arnav Sacheti
2025-10-26 14:40:03 -07:00
committed by GitHub
parent c9addd6ac2
commit 93276ff616
11 changed files with 715 additions and 676 deletions

View File

@@ -104,5 +104,5 @@ python-version = "3.10"
# Default behavior: check bodies of untyped defs & infer return types.
untyped-def-behavior = "check-and-infer-return-type"
project-includes = ["**/*"]
project-includes = ["src/**/*"]
project-excludes = ["**/__pycache__", "**/*venv/**/*"]

View File

@@ -1,5 +1,3 @@
from __future__ import annotations
from textwrap import indent
from types import EllipsisType
@@ -50,7 +48,7 @@ class IfBody(Body):
# --- Context manager for a branch ---
class _BranchCtx:
def __init__(self, outer: IfBody, condition: SupportsStr | None) -> None:
def __init__(self, outer: "IfBody", condition: SupportsStr | None) -> None:
self._outer = outer
# route through __getitem__ to reuse validation logic
self._body = outer[Ellipsis if condition is None else condition]
@@ -66,7 +64,7 @@ class IfBody(Body):
) -> bool:
return False
def cm(self, condition: SupportsStr | None) -> IfBody._BranchCtx:
def cm(self, condition: SupportsStr | None) -> "IfBody._BranchCtx":
"""Use with: with ifb.cm('cond') as b: ... ; use None for else."""
return IfBody._BranchCtx(self, condition)

View File

@@ -36,18 +36,17 @@ class FaninGenerator(BusDecoderListener):
)
self._stack.append(fb)
if action == WalkerAction.Continue:
ifb = IfBody()
with ifb.cm(
f"cpuif_rd_sel.{get_indexed_path(self._cpuif.exp.ds.top_node, node)} || cpuif_wr_sel.{get_indexed_path(self._cpuif.exp.ds.top_node, node)}"
) as b:
b += self._cpuif.fanin(node)
self._stack[-1] += ifb
ifb = IfBody()
with ifb.cm(
f"cpuif_rd_sel.{get_indexed_path(self._cpuif.exp.ds.top_node, node)} || cpuif_wr_sel.{get_indexed_path(self._cpuif.exp.ds.top_node, node)}"
) as b:
b += self._cpuif.fanin(node)
self._stack[-1] += ifb
ifb = IfBody()
with ifb.cm(f"cpuif_rd_sel.{get_indexed_path(self._cpuif.exp.ds.top_node, node)}") as b:
b += self._cpuif.readback(node)
self._stack[-1] += ifb
ifb = IfBody()
with ifb.cm(f"cpuif_rd_sel.{get_indexed_path(self._cpuif.exp.ds.top_node, node)}") as b:
b += self._cpuif.readback(node)
self._stack[-1] += ifb
return action

View File

@@ -32,8 +32,7 @@ class FanoutGenerator(BusDecoderListener):
)
self._stack.append(fb)
if action == WalkerAction.Continue:
self._stack[-1] += self._cpuif.fanout(node)
self._stack[-1] += self._cpuif.fanout(node)
return action

View File

@@ -17,42 +17,34 @@ class BusDecoderListener(RDLListener):
# Check if current depth exceeds max depth
if self._depth > self._ds.max_decode_depth:
return True
# Check if this node only contains external addressable children
if node != self._ds.top_node and not isinstance(node, RegNode):
if any(isinstance(c, AddressableNode) for c in node.children()) and \
all(c.external for c in node.children() if isinstance(c, AddressableNode)):
if any(isinstance(c, AddressableNode) for c in node.children()) and all(
c.external for c in node.children() if isinstance(c, AddressableNode)
):
return True
return False
def enter_AddressableComponent(self, node: AddressableNode) -> WalkerAction | None:
if node.array_dimensions:
assert node.array_stride is not None, "Array stride should be defined for arrayed components"
# Calculate stride for each dimension
# For multi-dimensional arrays like [2][3], array_stride gives the stride of the
# rightmost (fastest-changing) dimension. We need to calculate strides for all dimensions.
# Example: for [2][3] with 4-byte elements:
# - i1 (rightmost/fastest): stride = 4 (from array_stride)
# - i0 (leftmost/slowest): stride = 3 * 4 = 12
strides = []
current_stride = node.array_stride
strides.append(current_stride)
self._array_stride_stack.append(current_stride)
# Work backwards from rightmost to leftmost dimension (fastest to slowest changing)
# Each dimension's stride is the product of its size and the previous dimension's stride
for i in range(len(node.array_dimensions) - 1, 0, -1):
current_stride = current_stride * node.array_dimensions[i]
strides.insert(0, current_stride)
self._array_stride_stack.extend(strides)
for dim in node.array_dimensions[-1:0:-1]:
current_stride = current_stride * dim
self._array_stride_stack.appendleft(current_stride)
self._depth += 1
# Check if we should skip this node's descendants
if self.should_skip_node(node):
return WalkerAction.SkipDescendants
return WalkerAction.Continue
def exit_AddressableComponent(self, node: AddressableNode) -> None:

View File

@@ -1,6 +1,6 @@
"""Pytest fixtures for unit tests."""
from __future__ import annotations
from pathlib import Path
from tempfile import NamedTemporaryFile

View File

@@ -1,6 +1,6 @@
"""Tests for body classes used in code generation."""
from __future__ import annotations
import pytest

View File

@@ -1,6 +1,5 @@
"""Integration tests for the BusDecoderExporter."""
from __future__ import annotations
import os
from pathlib import Path
@@ -321,7 +320,6 @@ class TestAPB4Interface:
module_file = tmp_path / "test_block.sv"
module_content = module_file.read_text()
# For a [2][3] array where each register is 4 bytes:
# i0 (leftmost/slowest) should have stride = 3 * 4 = 12 (0xc)
# i1 (rightmost/fastest) should have stride = 4 (0x4)

View File

@@ -1,6 +1,6 @@
"""Tests for code generation classes."""
from __future__ import annotations
import pytest

View File

@@ -1,6 +1,6 @@
"""Tests for utility functions."""
from __future__ import annotations
import pytest
from systemrdl import RDLCompiler

1319
uv.lock generated

File diff suppressed because it is too large Load Diff