Add support for wide registers (where accesswidth < regwidth)

This commit is contained in:
Alex Mykyta
2022-10-12 20:44:22 -07:00
parent 21a4e5a41c
commit e07e7d26b2
18 changed files with 687 additions and 206 deletions

View File

@@ -30,21 +30,47 @@ class AddressDecode:
assert s is not None
return s
def get_access_strobe(self, node: Union[RegNode, FieldNode]) -> str:
def get_access_strobe(self, node: Union[RegNode, FieldNode], reduce_substrobes: bool=True) -> str:
"""
Returns the Verilog string that represents the register/field's access strobe.
"""
if isinstance(node, FieldNode):
node = node.parent
field = node
path = get_indexed_path(self.top_node, node.parent)
regwidth = node.parent.get_property('regwidth')
accesswidth = node.parent.get_property('accesswidth')
if regwidth > accesswidth:
# Is wide register.
# Determine the substrobe(s) relevant to this field
sidx_hi = field.msb // accesswidth
sidx_lo = field.lsb // accesswidth
if sidx_hi == sidx_lo:
suffix = f"[{sidx_lo}]"
else:
suffix = f"[{sidx_hi}:{sidx_lo}]"
path += suffix
if sidx_hi != sidx_lo and reduce_substrobes:
return "|decoded_reg_strb." + path
else:
path = get_indexed_path(self.top_node, node)
path = get_indexed_path(self.top_node, node)
return "decoded_reg_strb." + path
class DecodeStructGenerator(RDLStructGenerator):
def enter_Reg(self, node: 'RegNode') -> None:
self.add_member(kwf(node.inst_name), array_dimensions=node.array_dimensions)
# if register is "wide", expand the strobe to be able to access the sub-words
n_subwords = node.get_property("regwidth") // node.get_property("accesswidth")
self.add_member(
kwf(node.inst_name),
width=n_subwords,
array_dimensions=node.array_dimensions,
)
# Stub out
def exit_Reg(self, node: 'RegNode') -> None:
@@ -79,16 +105,26 @@ class DecodeLogicGenerator(RDLForLoopGenerator):
self._array_stride_stack.extend(strides)
def _get_address_str(self, node:AddressableNode) -> str:
a = f"'h{(node.raw_absolute_address - self.addr_decode.top_node.raw_absolute_address):x}"
def _get_address_str(self, node:AddressableNode, subword_offset: int=0) -> str:
a = f"'h{(node.raw_absolute_address - self.addr_decode.top_node.raw_absolute_address + subword_offset):x}"
for i, stride in enumerate(self._array_stride_stack):
a += f" + i{i}*'h{stride:x}"
return a
def enter_Reg(self, node: RegNode) -> None:
s = f"{self.addr_decode.get_access_strobe(node)} = cpuif_req_masked & (cpuif_addr == {self._get_address_str(node)});"
self.add_content(s)
regwidth = node.get_property('regwidth')
accesswidth = node.get_property('accesswidth')
if regwidth == accesswidth:
s = f"{self.addr_decode.get_access_strobe(node)} = cpuif_req_masked & (cpuif_addr == {self._get_address_str(node)});"
self.add_content(s)
else:
n_subwords = regwidth // accesswidth
subword_stride = accesswidth // 8
for i in range(n_subwords):
s = f"{self.addr_decode.get_access_strobe(node)}[{i}] = cpuif_req_masked & (cpuif_addr == {self._get_address_str(node, subword_offset=(i*subword_stride))});"
self.add_content(s)
def exit_AddressableComponent(self, node: 'AddressableNode') -> None: