Add precedence test. fixup docs

This commit is contained in:
Alex Mykyta
2022-02-28 22:05:24 -08:00
parent 404e7e8365
commit 9295cbb7c0
14 changed files with 164 additions and 55 deletions

View File

@@ -1 +1 @@
__version__ = "0.1.0-a1"
__version__ = "0.1.0"

View File

@@ -1,11 +1,11 @@
from typing import TYPE_CHECKING, Set
from typing import TYPE_CHECKING, Set, List
from collections import OrderedDict
from systemrdl.walker import RDLListener, RDLWalker
from systemrdl.node import AddrmapNode, SignalNode
from systemrdl.node import SignalNode, AddressableNode
if TYPE_CHECKING:
from systemrdl.node import Node, RegNode, MemNode, FieldNode
from systemrdl.node import Node, RegNode, FieldNode
from .exporter import RegblockExporter
@@ -21,6 +21,9 @@ 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]
# Collections of signals that were actually referenced by the design
self.in_hier_signal_paths = set() # type: Set[str]
self.out_of_hier_signals = OrderedDict() # type: OrderedDict[str, SignalNode]
@@ -49,6 +52,14 @@ class DesignScanner(RDLListener):
# collect out-of-hier field_reset, if any
self._get_out_of_hier_field_reset()
# Ensure addrmap is not a bridge. This concept does not make sense for
# terminal components.
if self.exp.top_node.get_property('bridge'):
self.msg.error(
"Regblock generator does not support exporting bridge address maps",
self.exp.top_node.inst.property_src_ref.get('bridge', self.exp.top_node.inst.inst_src_ref)
)
RDLWalker().walk(self.exp.top_node, self)
if self.msg.had_error:
self.msg.fatal(
@@ -57,11 +68,51 @@ class DesignScanner(RDLListener):
raise ValueError
def enter_Reg(self, node: 'RegNode') -> None:
regwidth = node.get_property('regwidth')
self.max_regwidth_stack[-1] = max(self.max_regwidth_stack[-1], regwidth)
# The CPUIF's bus width is sized according to the largest register in the design
self.cpuif_data_width = max(self.cpuif_data_width, node.get_property('regwidth'))
# TODO: make this user-overridable once more flexible regwidth/accesswidths are supported
self.cpuif_data_width = max(self.cpuif_data_width, regwidth)
# TODO: remove this limitation eventually
if regwidth != 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)
)
# TODO: remove this limitation eventually
if regwidth != node.get_property('accesswidth'):
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)
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)
alignment = int(max_block_regwidth / 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}",
node.inst.inst_src_ref
)
if node.is_array and (node.array_stride % alignment) != 0:
self.msg.error(
f"Unaligned registers are not supported. Address stride of instance array '{node.inst_name}' must be a multiple of {alignment}",
node.inst.inst_src_ref
)
def enter_Component(self, node: 'Node') -> None:
if not isinstance(node, AddrmapNode) and node.external:
if node.external and (node != self.exp.top_node):
self.msg.error(
"Exporter does not support external components",
node.inst.inst_src_ref
@@ -93,9 +144,3 @@ class DesignScanner(RDLListener):
self.out_of_hier_signals[path] = value
else:
self.in_hier_signal_paths.add(path)
def enter_Mem(self, node: 'MemNode') -> None:
self.msg.error(
"Cannot export a register block that contains a memory",
node.inst.inst_src_ref
)