Add packed struct overlay for external register bitfields. #84

This commit is contained in:
Alex Mykyta
2024-03-29 22:16:05 -07:00
parent 840b54c6e1
commit f25ba60bfc
3 changed files with 100 additions and 22 deletions

View File

@@ -20,8 +20,8 @@ class HWIFStructGenerator(RDLFlatStructGenerator):
self.hwif_report_stack = [hwif_name]
def push_struct(self, type_name: str, inst_name: str, array_dimensions: Optional[List[int]] = None) -> None: # type: ignore
super().push_struct(type_name, inst_name, array_dimensions)
def push_struct(self, type_name: str, inst_name: str, array_dimensions: Optional[List[int]] = None, packed: bool = False) -> None: # type: ignore
super().push_struct(type_name, inst_name, array_dimensions, packed)
if array_dimensions:
array_suffix = "".join([f"[0:{dim-1}]" for dim in array_dimensions])
@@ -52,14 +52,14 @@ class InputStructGenerator_Hier(HWIFStructGenerator):
def __init__(self, hwif: 'Hwif') -> None:
super().__init__(hwif, "hwif_in")
def get_typdef_name(self, node:'Node') -> str:
def get_typdef_name(self, node:'Node', suffix: str = "") -> str:
base = node.get_rel_path(
self.top_node.parent,
hier_separator="__",
array_suffix="x",
empty_array_suffix="x"
)
return f'{base}__in_t'
return f'{base}{suffix}__in_t'
def enter_Signal(self, node: 'SignalNode') -> None:
# only emit the signal if design scanner detected it is actually being used
@@ -95,15 +95,48 @@ class InputStructGenerator_Hier(HWIFStructGenerator):
super().enter_Reg(node)
if node.external:
width = min(self.hwif.ds.cpuif_data_width, node.get_property('regwidth'))
n_subwords = node.get_property("regwidth") // node.get_property("accesswidth")
if node.has_sw_readable:
self.add_member("rd_ack")
self.add_member("rd_data", width)
self.add_external_reg_rd_data(node, width, n_subwords)
if node.has_sw_writable:
self.add_member("wr_ack")
return WalkerAction.SkipDescendants
return WalkerAction.Continue
def add_external_reg_rd_data(self, node: 'RegNode', width: int, n_subwords: int) -> None:
if n_subwords == 1:
# External reg is 1 sub-word. Add a packed struct to represent it
type_name = self.get_typdef_name(node, "__fields")
self.push_struct(type_name, "rd_data", packed=True)
current_bit = 0
for field in node.fields():
if not field.is_sw_readable:
continue
if field.low > current_bit:
# Add padding
self.add_member(
f"_reserved_{field.low - 1}_{current_bit}",
field.low - current_bit
)
self.add_member(
kwf(field.inst_name),
field.width
)
current_bit = field.high + 1
# Add end padding if needed
if current_bit != width:
self.add_member(
f"_reserved_{width - 1}_{current_bit}",
width - current_bit
)
self.pop_struct()
else:
# Multiple sub-words. Cannot generate a struct
self.add_member("rd_data", width)
def enter_Field(self, node: 'FieldNode') -> None:
type_name = self.get_typdef_name(node)
self.push_struct(type_name, kwf(node.inst_name))
@@ -150,14 +183,14 @@ class OutputStructGenerator_Hier(HWIFStructGenerator):
def __init__(self, hwif: 'Hwif') -> None:
super().__init__(hwif, "hwif_out")
def get_typdef_name(self, node:'Node') -> str:
def get_typdef_name(self, node:'Node', suffix: str = "") -> str:
base = node.get_rel_path(
self.top_node.parent,
hier_separator="__",
array_suffix="x",
empty_array_suffix="x"
)
return f'{base}__out_t'
return f'{base}{suffix}__out_t'
def _add_external_block_members(self, node: 'AddressableNode') -> None:
self.add_member("req")
@@ -193,12 +226,44 @@ class OutputStructGenerator_Hier(HWIFStructGenerator):
self.add_member("req", n_subwords)
self.add_member("req_is_wr")
if node.has_sw_writable:
self.add_member("wr_data", width)
self.add_member("wr_biten", width)
self.add_external_reg_wr_data("wr_data", node, width, n_subwords)
self.add_external_reg_wr_data("wr_biten", node, width, n_subwords)
return WalkerAction.SkipDescendants
return WalkerAction.Continue
def add_external_reg_wr_data(self, name: str, node: 'RegNode', width: int, n_subwords: int) -> None:
if n_subwords == 1:
# External reg is 1 sub-word. Add a packed struct to represent it
type_name = self.get_typdef_name(node, "__fields")
self.push_struct(type_name, name, packed=True)
current_bit = 0
for field in node.fields():
if not field.is_sw_writable:
continue
if field.low > current_bit:
# Add padding
self.add_member(
f"_reserved_{field.low - 1}_{current_bit}",
field.low - current_bit
)
self.add_member(
kwf(field.inst_name),
field.width
)
current_bit = field.high + 1
# Add end padding if needed
if current_bit != width:
self.add_member(
f"_reserved_{width - 1}_{current_bit}",
width - current_bit
)
self.pop_struct()
else:
# Multiple sub-words. Cannot generate a struct
self.add_member(name, width)
def enter_Field(self, node: 'FieldNode') -> None:
type_name = self.get_typdef_name(node)
self.push_struct(type_name, kwf(node.inst_name))
@@ -229,7 +294,7 @@ class OutputStructGenerator_Hier(HWIFStructGenerator):
#-------------------------------------------------------------------------------
class InputStructGenerator_TypeScope(InputStructGenerator_Hier):
def get_typdef_name(self, node:'Node') -> str:
def get_typdef_name(self, node:'Node', suffix: str = "") -> str:
scope_path = node.get_global_type_name("__")
if scope_path is None:
# Unable to determine a reusable type name. Fall back to hierarchical path
@@ -242,10 +307,10 @@ class InputStructGenerator_TypeScope(InputStructGenerator_Hier):
else:
extra_suffix = ""
return f'{scope_path}{extra_suffix}__in_t'
return f'{scope_path}{extra_suffix}{suffix}__in_t'
class OutputStructGenerator_TypeScope(OutputStructGenerator_Hier):
def get_typdef_name(self, node:'Node') -> str:
def get_typdef_name(self, node:'Node', suffix: str = "") -> str:
scope_path = node.get_global_type_name("__")
if scope_path is None:
# Unable to determine a reusable type name. Fall back to hierarchical path
@@ -258,7 +323,7 @@ class OutputStructGenerator_TypeScope(OutputStructGenerator_Hier):
else:
extra_suffix = ""
return f'{scope_path}{extra_suffix}__out_t'
return f'{scope_path}{extra_suffix}{suffix}__out_t'
#-------------------------------------------------------------------------------
class EnumGenerator:

View File

@@ -41,18 +41,26 @@ class _AnonymousStruct(_StructBase):
class _TypedefStruct(_StructBase):
def __init__(self, type_name: str, inst_name: Optional[str] = None, array_dimensions: Optional[List[int]] = None):
def __init__(self, type_name: str, inst_name: Optional[str] = None, array_dimensions: Optional[List[int]] = None, packed: bool = False):
super().__init__()
self.type_name = type_name
self.inst_name = inst_name
self.array_dimensions = array_dimensions
self.packed = packed
def __str__(self) -> str:
return (
"typedef struct {\n"
+ super().__str__()
+ f"\n}} {self.type_name};"
)
if self.packed:
return (
"typedef struct packed {\n"
+ super().__str__()
+ f"\n}} {self.type_name};"
)
else:
return (
"typedef struct {\n"
+ super().__str__()
+ f"\n}} {self.type_name};"
)
@property
def instantiation(self) -> str:
@@ -167,8 +175,8 @@ class FlatStructGenerator(StructGenerator):
super().__init__()
self.typedefs = OrderedDict() # type: OrderedDict[str, _TypedefStruct]
def push_struct(self, type_name: str, inst_name: str, array_dimensions: Optional[List[int]] = None) -> None: # type: ignore # pylint: disable=arguments-renamed
s = _TypedefStruct(type_name, inst_name, array_dimensions)
def push_struct(self, type_name: str, inst_name: str, array_dimensions: Optional[List[int]] = None, packed = False) -> None: # type: ignore # pylint: disable=arguments-renamed
s = _TypedefStruct(type_name, inst_name, array_dimensions, packed)
self._struct_stack.append(s)
def pop_struct(self) -> None:

View File

@@ -2,13 +2,18 @@ addrmap top {
reg my_reg {
field {sw=rw; hw=r;} whatever[32] = 0;
};
reg my_reg_alt {
field {sw=r; hw=w;} whatever_a[3:2] = 0;
field {sw=w; hw=r;} whatever_b[4:4] = 0;
field {sw=rw; hw=r;} whatever_c[15:8] = 0;
};
reg my_wide_reg {
regwidth = 64;
accesswidth = 32;
field {sw=rw; hw=r;} whatever = 0;
};
external my_reg ext_reg @ 0x00;
external my_reg_alt ext_reg @ 0x00;
my_reg int_reg @ 0x04;
external my_wide_reg wide_ext_reg @ 0x10;
external my_reg ext_reg_array[32] @ 0x100 += 4;