Add support for wide registers (where accesswidth < regwidth)
This commit is contained in:
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user