refactor to use base listener for busdecoder

This commit is contained in:
Arnav Sacheti
2025-10-19 21:35:17 -07:00
parent be116def83
commit bafebf8595
10 changed files with 136 additions and 65 deletions

View File

@@ -2,10 +2,11 @@ from collections import deque
from enum import Enum
from systemrdl.node import AddressableNode
from systemrdl.walker import RDLListener, RDLSimpleWalker, WalkerAction
from systemrdl.walker import WalkerAction
from .body import Body, ForLoopBody, IfBody
from .design_state import DesignState
from .listener import BusDecoderListener
from .sv_int import SVInt
from .utils import get_indexed_path
@@ -23,30 +24,17 @@ class DecodeLogicFlavor(Enum):
return f"cpuif_{self.value}_sel"
class AddressDecode:
def __init__(self, flavor: DecodeLogicFlavor, ds: DesignState) -> None:
self._flavor = flavor
self._ds = ds
def walk(self) -> str:
walker = RDLSimpleWalker()
dlg = DecodeLogicGenerator(self._flavor, self._ds)
walker.walk(self._ds.top_node, dlg, skip_top=True)
return str(dlg)
class DecodeLogicGenerator(RDLListener):
class DecodeLogicGenerator(BusDecoderListener):
def __init__(
self,
flavor: DecodeLogicFlavor,
ds: DesignState,
flavor: DecodeLogicFlavor,
) -> None:
self._ds = ds
super().__init__(ds)
self._flavor = flavor
self._decode_stack: deque[Body] = deque() # Tracks decoder body
self._cond_stack: deque[str] = deque() # Tracks conditions nested for loops
self._array_stride_stack: deque[int] = deque() # Tracks nested array strids
# Initial Stack Conditions
self._decode_stack.append(IfBody())
@@ -55,15 +43,19 @@ class DecodeLogicGenerator(RDLListener):
# Generate address bounds
addr_width = self._ds.addr_width
l_bound = SVInt(
node.raw_address_offset,
node.raw_absolute_address,
addr_width,
)
u_bound = l_bound + SVInt(node.total_size, addr_width)
array_stack = list(self._array_stride_stack)
if node.array_dimensions:
array_stack = array_stack[: -len(node.array_dimensions)]
# Handle arrayed components
l_bound_comp = [str(l_bound)]
u_bound_comp = [str(u_bound)]
for i, stride in enumerate(self._array_stride_stack):
for i, stride in enumerate(array_stack):
l_bound_comp.append(f"({addr_width}'(i{i})*{SVInt(stride, addr_width)})")
u_bound_comp.append(f"({addr_width}'(i{i})*{SVInt(stride, addr_width)})")
@@ -82,30 +74,20 @@ class DecodeLogicGenerator(RDLListener):
return []
def enter_AddressableComponent(self, node: AddressableNode) -> WalkerAction | None:
action = super().enter_AddressableComponent(node)
conditions: list[str] = []
conditions.extend(self.cpuif_addr_predicate(node))
conditions.extend(self.cpuif_prot_predicate(node))
condition = " && ".join(f"({c})" for c in conditions)
if node.array_dimensions:
assert node.array_stride is not None, "Array stride should be defined for arrayed components"
# Collect strides for each array dimension
current_stride = node.array_stride
strides: list[int] = []
for dim in reversed(node.array_dimensions):
strides.append(current_stride)
current_stride *= dim
strides.reverse()
self._array_stride_stack.extend(strides)
# Generate condition string and manage stack
if isinstance(self._decode_stack[-1], IfBody) and node.array_dimensions:
# arrayed component with new if-body
self._cond_stack.append(condition)
for i, dim in enumerate(
node.array_dimensions,
start=len(self._array_stride_stack) - len(node.array_dimensions),
):
fb = ForLoopBody(
"int",
@@ -120,10 +102,7 @@ class DecodeLogicGenerator(RDLListener):
with self._decode_stack[-1].cm(condition) as b:
b += f"{self._flavor.cpuif_select}.{get_indexed_path(self._ds.top_node, node)} = 1'b1;"
# if node.external:
# return WalkerAction.SkipDescendants
return WalkerAction.Continue
return action
def exit_AddressableComponent(self, node: AddressableNode) -> None:
if not node.array_dimensions:
@@ -148,7 +127,7 @@ class DecodeLogicGenerator(RDLListener):
else:
self._decode_stack[-1] += b
self._array_stride_stack.pop()
super().exit_AddressableComponent(node)
def __str__(self) -> str:
body = self._decode_stack[-1]