Add packed struct overlay for external register bitfields. #84
This commit is contained in:
@@ -20,8 +20,8 @@ class HWIFStructGenerator(RDLFlatStructGenerator):
|
|||||||
|
|
||||||
self.hwif_report_stack = [hwif_name]
|
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
|
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)
|
super().push_struct(type_name, inst_name, array_dimensions, packed)
|
||||||
|
|
||||||
if array_dimensions:
|
if array_dimensions:
|
||||||
array_suffix = "".join([f"[0:{dim-1}]" for dim in 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:
|
def __init__(self, hwif: 'Hwif') -> None:
|
||||||
super().__init__(hwif, "hwif_in")
|
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(
|
base = node.get_rel_path(
|
||||||
self.top_node.parent,
|
self.top_node.parent,
|
||||||
hier_separator="__",
|
hier_separator="__",
|
||||||
array_suffix="x",
|
array_suffix="x",
|
||||||
empty_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:
|
def enter_Signal(self, node: 'SignalNode') -> None:
|
||||||
# only emit the signal if design scanner detected it is actually being used
|
# 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)
|
super().enter_Reg(node)
|
||||||
if node.external:
|
if node.external:
|
||||||
width = min(self.hwif.ds.cpuif_data_width, node.get_property('regwidth'))
|
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:
|
if node.has_sw_readable:
|
||||||
self.add_member("rd_ack")
|
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:
|
if node.has_sw_writable:
|
||||||
self.add_member("wr_ack")
|
self.add_member("wr_ack")
|
||||||
return WalkerAction.SkipDescendants
|
return WalkerAction.SkipDescendants
|
||||||
|
|
||||||
return WalkerAction.Continue
|
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:
|
def enter_Field(self, node: 'FieldNode') -> None:
|
||||||
type_name = self.get_typdef_name(node)
|
type_name = self.get_typdef_name(node)
|
||||||
self.push_struct(type_name, kwf(node.inst_name))
|
self.push_struct(type_name, kwf(node.inst_name))
|
||||||
@@ -150,14 +183,14 @@ class OutputStructGenerator_Hier(HWIFStructGenerator):
|
|||||||
def __init__(self, hwif: 'Hwif') -> None:
|
def __init__(self, hwif: 'Hwif') -> None:
|
||||||
super().__init__(hwif, "hwif_out")
|
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(
|
base = node.get_rel_path(
|
||||||
self.top_node.parent,
|
self.top_node.parent,
|
||||||
hier_separator="__",
|
hier_separator="__",
|
||||||
array_suffix="x",
|
array_suffix="x",
|
||||||
empty_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:
|
def _add_external_block_members(self, node: 'AddressableNode') -> None:
|
||||||
self.add_member("req")
|
self.add_member("req")
|
||||||
@@ -193,12 +226,44 @@ class OutputStructGenerator_Hier(HWIFStructGenerator):
|
|||||||
self.add_member("req", n_subwords)
|
self.add_member("req", n_subwords)
|
||||||
self.add_member("req_is_wr")
|
self.add_member("req_is_wr")
|
||||||
if node.has_sw_writable:
|
if node.has_sw_writable:
|
||||||
self.add_member("wr_data", width)
|
self.add_external_reg_wr_data("wr_data", node, width, n_subwords)
|
||||||
self.add_member("wr_biten", width)
|
self.add_external_reg_wr_data("wr_biten", node, width, n_subwords)
|
||||||
return WalkerAction.SkipDescendants
|
return WalkerAction.SkipDescendants
|
||||||
|
|
||||||
return WalkerAction.Continue
|
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:
|
def enter_Field(self, node: 'FieldNode') -> None:
|
||||||
type_name = self.get_typdef_name(node)
|
type_name = self.get_typdef_name(node)
|
||||||
self.push_struct(type_name, kwf(node.inst_name))
|
self.push_struct(type_name, kwf(node.inst_name))
|
||||||
@@ -229,7 +294,7 @@ class OutputStructGenerator_Hier(HWIFStructGenerator):
|
|||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
class InputStructGenerator_TypeScope(InputStructGenerator_Hier):
|
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("__")
|
scope_path = node.get_global_type_name("__")
|
||||||
if scope_path is None:
|
if scope_path is None:
|
||||||
# Unable to determine a reusable type name. Fall back to hierarchical path
|
# Unable to determine a reusable type name. Fall back to hierarchical path
|
||||||
@@ -242,10 +307,10 @@ class InputStructGenerator_TypeScope(InputStructGenerator_Hier):
|
|||||||
else:
|
else:
|
||||||
extra_suffix = ""
|
extra_suffix = ""
|
||||||
|
|
||||||
return f'{scope_path}{extra_suffix}__in_t'
|
return f'{scope_path}{extra_suffix}{suffix}__in_t'
|
||||||
|
|
||||||
class OutputStructGenerator_TypeScope(OutputStructGenerator_Hier):
|
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("__")
|
scope_path = node.get_global_type_name("__")
|
||||||
if scope_path is None:
|
if scope_path is None:
|
||||||
# Unable to determine a reusable type name. Fall back to hierarchical path
|
# Unable to determine a reusable type name. Fall back to hierarchical path
|
||||||
@@ -258,7 +323,7 @@ class OutputStructGenerator_TypeScope(OutputStructGenerator_Hier):
|
|||||||
else:
|
else:
|
||||||
extra_suffix = ""
|
extra_suffix = ""
|
||||||
|
|
||||||
return f'{scope_path}{extra_suffix}__out_t'
|
return f'{scope_path}{extra_suffix}{suffix}__out_t'
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
class EnumGenerator:
|
class EnumGenerator:
|
||||||
|
|||||||
@@ -41,18 +41,26 @@ class _AnonymousStruct(_StructBase):
|
|||||||
|
|
||||||
|
|
||||||
class _TypedefStruct(_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__()
|
super().__init__()
|
||||||
self.type_name = type_name
|
self.type_name = type_name
|
||||||
self.inst_name = inst_name
|
self.inst_name = inst_name
|
||||||
self.array_dimensions = array_dimensions
|
self.array_dimensions = array_dimensions
|
||||||
|
self.packed = packed
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return (
|
if self.packed:
|
||||||
"typedef struct {\n"
|
return (
|
||||||
+ super().__str__()
|
"typedef struct packed {\n"
|
||||||
+ f"\n}} {self.type_name};"
|
+ super().__str__()
|
||||||
)
|
+ f"\n}} {self.type_name};"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return (
|
||||||
|
"typedef struct {\n"
|
||||||
|
+ super().__str__()
|
||||||
|
+ f"\n}} {self.type_name};"
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def instantiation(self) -> str:
|
def instantiation(self) -> str:
|
||||||
@@ -167,8 +175,8 @@ class FlatStructGenerator(StructGenerator):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self.typedefs = OrderedDict() # type: OrderedDict[str, _TypedefStruct]
|
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
|
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)
|
s = _TypedefStruct(type_name, inst_name, array_dimensions, packed)
|
||||||
self._struct_stack.append(s)
|
self._struct_stack.append(s)
|
||||||
|
|
||||||
def pop_struct(self) -> None:
|
def pop_struct(self) -> None:
|
||||||
|
|||||||
@@ -2,13 +2,18 @@ addrmap top {
|
|||||||
reg my_reg {
|
reg my_reg {
|
||||||
field {sw=rw; hw=r;} whatever[32] = 0;
|
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 {
|
reg my_wide_reg {
|
||||||
regwidth = 64;
|
regwidth = 64;
|
||||||
accesswidth = 32;
|
accesswidth = 32;
|
||||||
field {sw=rw; hw=r;} whatever = 0;
|
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;
|
my_reg int_reg @ 0x04;
|
||||||
external my_wide_reg wide_ext_reg @ 0x10;
|
external my_wide_reg wide_ext_reg @ 0x10;
|
||||||
external my_reg ext_reg_array[32] @ 0x100 += 4;
|
external my_reg ext_reg_array[32] @ 0x100 += 4;
|
||||||
|
|||||||
Reference in New Issue
Block a user