validate internal/external boundary crossings

This commit is contained in:
Alex Mykyta
2023-04-20 23:36:15 -07:00
parent 109a36632b
commit 5267a4d245
2 changed files with 49 additions and 5 deletions

View File

@@ -165,6 +165,10 @@ X Do not allow unaligned addresses
X each reg needs to be aligned to its width X each reg needs to be aligned to its width
X each regfile/addrmap/stride shall be aligned to the largest regwidth it encloses X each regfile/addrmap/stride shall be aligned to the largest regwidth it encloses
X Error if a property is a reference to something that is external, or enclosed
in an external component.
Limit this check to child nodes inside the export hierarchy
! async data signals ! async data signals
Only supporting async signals if they are exclusively used in resets. Only supporting async signals if they are exclusively used in resets.
Anything else declared as "async" shall emit a warning that it is ignored Anything else declared as "async" shall emit a warning that it is ignored
@@ -173,10 +177,6 @@ X Do not allow unaligned addresses
! Error if a property references a non-signal component, or property reference from ! Error if a property references a non-signal component, or property reference from
outside the export hierarchy outside the export hierarchy
! Error if a property is a reference to something that is external, or enclosed
in an external component.
Limit this check to child nodes inside the export hierarchy
! Add warning for sticky race condition ! Add warning for sticky race condition
stickybit and other similar situations generally should use hw precedence. stickybit and other similar situations generally should use hw precedence.
Emit a warning as appropriate Emit a warning as appropriate

View File

@@ -1,9 +1,11 @@
from typing import TYPE_CHECKING, Optional from typing import TYPE_CHECKING, Optional
from systemrdl.walker import RDLListener, RDLWalker, WalkerAction from systemrdl.walker import RDLListener, RDLWalker, WalkerAction
from systemrdl.rdltypes import PropertyReference
from systemrdl.node import Node
if TYPE_CHECKING: if TYPE_CHECKING:
from systemrdl.node import Node, RegNode, FieldNode, SignalNode, AddressableNode from systemrdl.node import RegNode, FieldNode, SignalNode, AddressableNode
from .exporter import RegblockExporter from .exporter import RegblockExporter
class DesignValidator(RDLListener): class DesignValidator(RDLListener):
@@ -30,6 +32,25 @@ class DesignValidator(RDLListener):
) )
# Do not inspect external components. None of my business # Do not inspect external components. None of my business
return WalkerAction.SkipDescendants return WalkerAction.SkipDescendants
# Check if any property references reach across the internal/external boundary
for prop_name in node.list_properties():
value = node.get_property(prop_name)
if isinstance(value, PropertyReference):
if not self._is_internal(value.node):
self.msg.error(
"Property is assigned a reference that points to a component not internal to the regblock being exported.",
value.src_ref
)
elif isinstance(value, Node):
if not self._is_internal(value):
src_ref = node.inst.property_src_ref.get(prop_name, node.inst.inst_src_ref)
self.msg.error(
"Property is assigned a reference that points to a component not internal to the regblock being exported.",
src_ref
)
return None return None
def enter_Signal(self, node: 'SignalNode') -> None: def enter_Signal(self, node: 'SignalNode') -> None:
@@ -106,3 +127,26 @@ class DesignValidator(RDLListener):
"For more details, see: https://peakrdl-regblock.readthedocs.io/en/latest/udps/read_buffering.html", "For more details, see: https://peakrdl-regblock.readthedocs.io/en/latest/udps/read_buffering.html",
node.inst.inst_src_ref node.inst.inst_src_ref
) )
def _is_internal(self, node: Node) -> bool:
"""
Recurse parents to see if at any point, the referenced component is
enclosed in an external component.
"""
current_node = node
while current_node is not None:
if current_node == self.exp.top_node:
# reached top node without finding any external components
# is internal!
return True
if current_node.external:
# not internal!
return False
current_node = current_node.parent
# A root signal was referenced, which dodged the top addrmap
# This is considerd internal for this exporter
return True