fill in more hwif utility functions for dereferencer
This commit is contained in:
139
peakrdl/regblock/struct_generator.py
Normal file
139
peakrdl/regblock/struct_generator.py
Normal file
@@ -0,0 +1,139 @@
|
||||
from typing import TYPE_CHECKING, Optional, List
|
||||
import textwrap
|
||||
|
||||
from systemrdl.walker import RDLListener, RDLWalker
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Union
|
||||
|
||||
from systemrdl.node import AddrmapNode, RegfileNode, RegNode, FieldNode, Node
|
||||
|
||||
|
||||
class _StructBase:
|
||||
def __init__(self):
|
||||
self.children = [] # type: Union[str, _StructBase]
|
||||
|
||||
def __str__(self) -> str:
|
||||
s = '\n'.join((str(x) for x in self.children))
|
||||
return textwrap.indent(s, " ")
|
||||
|
||||
|
||||
class _AnonymousStruct(_StructBase):
|
||||
def __init__(self, inst_name: str, array_dimensions: Optional[List[int]] = None):
|
||||
super().__init__()
|
||||
self.inst_name = inst_name
|
||||
self.array_dimensions = array_dimensions
|
||||
|
||||
def __str__(self) -> str:
|
||||
if self.array_dimensions:
|
||||
suffix = "[" + "][".join((str(n) for n in self.array_dimensions)) + "]"
|
||||
else:
|
||||
suffix = ""
|
||||
|
||||
return (
|
||||
"struct {\n"
|
||||
+ super().__str__()
|
||||
+ f"\n}} {self.inst_name}{suffix};"
|
||||
)
|
||||
|
||||
|
||||
class _TypedefStruct(_StructBase):
|
||||
def __init__(self, type_name: str):
|
||||
super().__init__()
|
||||
self.type_name = type_name
|
||||
|
||||
def __str__(self) -> str:
|
||||
return (
|
||||
"typedef struct {\n"
|
||||
+ super().__str__()
|
||||
+ f"\n}} {self.type_name};"
|
||||
)
|
||||
|
||||
|
||||
class StructGenerator:
|
||||
|
||||
def __init__(self):
|
||||
self._struct_stack = []
|
||||
|
||||
@property
|
||||
def current_struct(self) -> _StructBase:
|
||||
return self._struct_stack[-1]
|
||||
|
||||
|
||||
def push_struct(self, inst_name: str, array_dimensions: Optional[List[int]] = None) -> None:
|
||||
s = _AnonymousStruct(inst_name, array_dimensions)
|
||||
self._struct_stack.append(s)
|
||||
|
||||
|
||||
def add_member(self, name: str, width: int = 1, array_dimensions: Optional[List[int]] = None) -> None:
|
||||
if array_dimensions:
|
||||
suffix = "[" + "][".join((str(n) for n in array_dimensions)) + "]"
|
||||
else:
|
||||
suffix = ""
|
||||
|
||||
if width == 1:
|
||||
m = f"logic {name}{suffix};"
|
||||
else:
|
||||
m = f"logic [{width-1}:0] {name}{suffix};"
|
||||
self.current_struct.children.append(m)
|
||||
|
||||
|
||||
def pop_struct(self) -> None:
|
||||
s = self._struct_stack.pop()
|
||||
|
||||
if s.children:
|
||||
# struct is not empty. Attach it to the parent
|
||||
self.current_struct.children.append(s)
|
||||
|
||||
|
||||
def start(self, type_name: str):
|
||||
assert not self._struct_stack
|
||||
s = _TypedefStruct(type_name)
|
||||
self._struct_stack.append(s)
|
||||
|
||||
def finish(self) -> Optional[str]:
|
||||
s = self._struct_stack.pop()
|
||||
assert not self._struct_stack
|
||||
|
||||
if not s.children:
|
||||
return None
|
||||
return str(s)
|
||||
|
||||
|
||||
class RDLStructGenerator(StructGenerator, RDLListener):
|
||||
"""
|
||||
Struct generator that naively translates an RDL node tree into a single
|
||||
struct typedef containing nested anonymous structs
|
||||
|
||||
This can be extended to add more intelligent behavior
|
||||
"""
|
||||
|
||||
def get_struct(self, node: 'Node', type_name: str) -> Optional[str]:
|
||||
self.start(type_name)
|
||||
|
||||
walker = RDLWalker()
|
||||
walker.walk(node, self, skip_top=True)
|
||||
|
||||
return self.finish()
|
||||
|
||||
|
||||
def enter_Addrmap(self, node: 'AddrmapNode') -> None:
|
||||
self.push_struct(node.inst_name, node.array_dimensions)
|
||||
|
||||
def exit_Addrmap(self, node: 'AddrmapNode') -> None:
|
||||
self.pop_struct()
|
||||
|
||||
def enter_Regfile(self, node: 'RegfileNode') -> None:
|
||||
self.push_struct(node.inst_name, node.array_dimensions)
|
||||
|
||||
def exit_Regfile(self, node: 'RegfileNode') -> None:
|
||||
self.pop_struct()
|
||||
|
||||
def enter_Reg(self, node: 'RegNode') -> None:
|
||||
self.push_struct(node.inst_name, node.array_dimensions)
|
||||
|
||||
def exit_Reg(self, node: 'RegNode') -> None:
|
||||
self.pop_struct()
|
||||
|
||||
def enter_Field(self, node: 'FieldNode') -> None:
|
||||
self.add_member(node.inst_name, node.width)
|
||||
Reference in New Issue
Block a user