Rework hwif to reuse typedefs more intelligently
This commit is contained in:
119
peakrdl/regblock/hwif/generators.py
Normal file
119
peakrdl/regblock/hwif/generators.py
Normal file
@@ -0,0 +1,119 @@
|
||||
from typing import TYPE_CHECKING
|
||||
from ..struct_generator import RDLFlatStructGenerator
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from systemrdl.node import Node, SignalNode, FieldNode
|
||||
|
||||
class InputStructGenerator_Hier(RDLFlatStructGenerator):
|
||||
def __init__(self, top_node: 'Node'):
|
||||
super().__init__()
|
||||
self.top_node = top_node
|
||||
|
||||
def get_typdef_name(self, node:'Node') -> str:
|
||||
base = node.get_rel_path(
|
||||
self.top_node.parent,
|
||||
hier_separator="__",
|
||||
array_suffix="x",
|
||||
empty_array_suffix="x"
|
||||
)
|
||||
return f'{base}__in_t'
|
||||
|
||||
def enter_Signal(self, node: 'SignalNode') -> None:
|
||||
self.add_member(node.inst_name, node.width)
|
||||
|
||||
def enter_Field(self, node: 'FieldNode') -> None:
|
||||
type_name = self.get_typdef_name(node)
|
||||
self.push_struct(type_name, node.inst_name)
|
||||
|
||||
# Provide input to field's value if it is writable by hw
|
||||
if node.is_hw_writable:
|
||||
self.add_member("value", node.width)
|
||||
|
||||
# Generate implied inputs
|
||||
for prop_name in ["we", "wel", "swwe", "swwel", "hwclr", "hwset"]:
|
||||
# if property is boolean and true, implies a corresponding input signal on the hwif
|
||||
if node.get_property(prop_name) is True:
|
||||
self.add_member(prop_name)
|
||||
|
||||
# Generate any implied counter inputs
|
||||
if node.is_up_counter:
|
||||
if not node.get_property('incr'):
|
||||
# User did not provide their own incr component reference.
|
||||
# Imply an input
|
||||
self.add_member('incr')
|
||||
|
||||
width = node.get_property('incrwidth')
|
||||
if width:
|
||||
# Implies a corresponding incrvalue input
|
||||
self.add_member('incrvalue', width)
|
||||
|
||||
if node.is_down_counter:
|
||||
if not node.get_property('decr'):
|
||||
# User did not provide their own decr component reference.
|
||||
# Imply an input
|
||||
self.add_member('decr')
|
||||
|
||||
width = node.get_property('decrwidth')
|
||||
if width:
|
||||
# Implies a corresponding decrvalue input
|
||||
self.add_member('decrvalue', width)
|
||||
|
||||
def exit_Field(self, node: 'FieldNode') -> None:
|
||||
self.pop_struct()
|
||||
|
||||
|
||||
class OutputStructGenerator_Hier(RDLFlatStructGenerator):
|
||||
def __init__(self, top_node: 'Node'):
|
||||
super().__init__()
|
||||
self.top_node = top_node
|
||||
|
||||
def get_typdef_name(self, node:'Node') -> str:
|
||||
base = node.get_rel_path(
|
||||
self.top_node.parent,
|
||||
hier_separator="__",
|
||||
array_suffix="x",
|
||||
empty_array_suffix="x"
|
||||
)
|
||||
return f'{base}__out_t'
|
||||
|
||||
def enter_Field(self, node: 'FieldNode') -> None:
|
||||
type_name = self.get_typdef_name(node)
|
||||
self.push_struct(type_name, node.inst_name)
|
||||
|
||||
# Expose field's value if it is readable by hw
|
||||
if node.is_hw_readable:
|
||||
self.add_member("value", node.width)
|
||||
|
||||
# Generate output bit signals enabled via property
|
||||
for prop_name in ["anded", "ored", "xored", "swmod", "swacc", "overflow", "underflow"]:
|
||||
if node.get_property(prop_name):
|
||||
self.add_member(prop_name)
|
||||
|
||||
if node.get_property('incrthreshold') is not False: # (explicitly not False. Not 0)
|
||||
self.add_member('incrthreshold')
|
||||
if node.get_property('decrthreshold') is not False: # (explicitly not False. Not 0)
|
||||
self.add_member('decrthreshold')
|
||||
|
||||
def exit_Field(self, node: 'FieldNode') -> None:
|
||||
self.pop_struct()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
class InputStructGenerator_TypeScope(InputStructGenerator_Hier):
|
||||
def get_typdef_name(self, node:'Node') -> str:
|
||||
scope_path = node.inst.get_scope_path("__")
|
||||
if scope_path is None:
|
||||
# Unable to determine a reusable type name. Fall back to hierarchical path
|
||||
# Add prefix to prevent collision when mixing namespace methods
|
||||
scope_path = "xtern__" + super().get_typdef_name(node)
|
||||
|
||||
return f'{scope_path}__{node.type_name}__in_t'
|
||||
|
||||
class OutputStructGenerator_TypeScope(OutputStructGenerator_Hier):
|
||||
def get_typdef_name(self, node:'Node') -> str:
|
||||
scope_path = node.inst.get_scope_path("__")
|
||||
if scope_path is None:
|
||||
# Unable to determine a reusable type name. Fall back to hierarchical path
|
||||
# Add prefix to prevent collision when mixing namespace methods
|
||||
scope_path = "xtern__" + super().get_typdef_name(node)
|
||||
|
||||
return f'{scope_path}__{node.type_name}__out_t'
|
||||
Reference in New Issue
Block a user