diff --git a/docs/cpuif/introduction.rst b/docs/cpuif/introduction.rst index 3d622de..459da54 100644 --- a/docs/cpuif/introduction.rst +++ b/docs/cpuif/introduction.rst @@ -7,6 +7,13 @@ When exporting a design, you can select from a variety of popular CPU interface protocols. These are described in more detail in the pages that follow. +Bus Width +^^^^^^^^^ +The CPU interface bus width is automatically determined from the contents of the +design being exported. The bus width is equal to the widest ``accesswidth`` +encountered in the deisgn. + + Addressing ^^^^^^^^^^ diff --git a/docs/limitations.rst b/docs/limitations.rst index 72ce7a7..5437ff8 100644 --- a/docs/limitations.rst +++ b/docs/limitations.rst @@ -18,10 +18,10 @@ Registers instantiated using the ``alias`` keyword are not supported yet. Unaligned Registers ------------------- -All address offsets & strides shall be a multiple of the regwidth used. Specifically: +All address offsets & strides shall be a multiple of the accesswidth used. Specifically: -* Each register's address and array stride shall be aligned to it's regwidth. -* Each regfile or addrmap shall use an offset and stride that is a multiple of the largest regwidth it encloses. +* Each register's address and array stride shall be aligned to it's accesswidth. +* Each regfile or addrmap shall use an offset and stride that is a multiple of the largest accesswidth it encloses. No partial writes @@ -38,6 +38,5 @@ and the resulting CPU bus width has some limitations: * All registers shall have ``regwidth`` == ``accesswidth`` * ``regwidth`` shall be the same across all registers within the block being exported. -* The CPU interface's bus width is statically determined by the ``regwidth`` used. I have plans to remove these restrictions and allow for more flexibility in the future. diff --git a/src/peakrdl_regblock/scan_design.py b/src/peakrdl_regblock/scan_design.py index 4a33ad0..e159fb8 100644 --- a/src/peakrdl_regblock/scan_design.py +++ b/src/peakrdl_regblock/scan_design.py @@ -1,7 +1,7 @@ -from typing import TYPE_CHECKING, Set, List +from typing import TYPE_CHECKING, Set, List, Optional from collections import OrderedDict -from systemrdl.walker import RDLListener, RDLWalker +from systemrdl.walker import RDLListener, RDLWalker, WalkerAction from systemrdl.node import SignalNode, AddressableNode if TYPE_CHECKING: @@ -21,8 +21,8 @@ class DesignScanner(RDLListener): self.cpuif_data_width = 0 self.msg = exp.top_node.env.msg - # Keep track of max regwidth encountered in a given block - self.max_regwidth_stack = [] # type: List[int] + # Keep track of max accesswidth encountered in a given block + self.max_accesswidth_stack = [] # type: List[int] # Collections of signals that were actually referenced by the design self.in_hier_signal_paths = set() # type: Set[str] @@ -68,37 +68,36 @@ class DesignScanner(RDLListener): raise ValueError def enter_Reg(self, node: 'RegNode') -> None: - regwidth = node.get_property('regwidth') + accesswidth = node.get_property('accesswidth') - self.max_regwidth_stack[-1] = max(self.max_regwidth_stack[-1], regwidth) + self.max_accesswidth_stack[-1] = max(self.max_accesswidth_stack[-1], accesswidth) - # The CPUIF's bus width is sized according to the largest register in the design - # TODO: make this user-overridable once more flexible regwidth/accesswidths are supported - self.cpuif_data_width = max(self.cpuif_data_width, regwidth) + # The CPUIF's bus width is sized according to the largest accesswidth in the design + self.cpuif_data_width = max(self.cpuif_data_width, accesswidth) # TODO: remove this limitation eventually - if regwidth != self.cpuif_data_width: + if accesswidth != self.cpuif_data_width: self.msg.error( - "register blocks with non-uniform regwidths are not supported yet", - node.inst.property_src_ref.get('regwidth', node.inst.inst_src_ref) + "register blocks with non-uniform accesswidth are not supported yet", + node.inst.property_src_ref.get('accesswidth', node.inst.inst_src_ref) ) # TODO: remove this limitation eventually - if regwidth != node.get_property('accesswidth'): + if accesswidth != node.get_property('regwidth'): self.msg.error( "Registers that have an accesswidth different from the register width are not supported yet", node.inst.property_src_ref.get('accesswidth', node.inst.inst_src_ref) ) def enter_AddressableComponent(self, node: AddressableNode) -> None: - self.max_regwidth_stack.append(0) + self.max_accesswidth_stack.append(0) def exit_AddressableComponent(self, node: AddressableNode) -> None: - max_block_regwidth = self.max_regwidth_stack.pop() - if self.max_regwidth_stack: - self.max_regwidth_stack[-1] = max(self.max_regwidth_stack[-1], max_block_regwidth) + max_block_accesswidth = self.max_accesswidth_stack.pop() + if self.max_accesswidth_stack: + self.max_accesswidth_stack[-1] = max(self.max_accesswidth_stack[-1], max_block_accesswidth) - alignment = int(max_block_regwidth / 8) + alignment = int(max_block_accesswidth / 8) if (node.raw_address_offset % alignment) != 0: self.msg.error( f"Unaligned registers are not supported. Address offset of instance '{node.inst_name}' must be a multiple of {alignment}", @@ -111,12 +110,14 @@ class DesignScanner(RDLListener): node.inst.inst_src_ref ) - def enter_Component(self, node: 'Node') -> None: + def enter_Component(self, node: 'Node') -> Optional[WalkerAction]: if node.external and (node != self.exp.top_node): self.msg.error( "Exporter does not support external components", node.inst.inst_src_ref ) + # Do not inspect external components. None of my business + return WalkerAction.SkipDescendants def enter_Signal(self, node: 'SignalNode') -> None: # If encountering a CPUIF reset that is nested within the register model,