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'