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 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
Only supporting async signals if they are exclusively used in resets.
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
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
stickybit and other similar situations generally should use hw precedence.
Emit a warning as appropriate

View File

@@ -1,9 +1,11 @@
from typing import TYPE_CHECKING, Optional
from systemrdl.walker import RDLListener, RDLWalker, WalkerAction
from systemrdl.rdltypes import PropertyReference
from systemrdl.node import Node
if TYPE_CHECKING:
from systemrdl.node import Node, RegNode, FieldNode, SignalNode, AddressableNode
from systemrdl.node import RegNode, FieldNode, SignalNode, AddressableNode
from .exporter import RegblockExporter
class DesignValidator(RDLListener):
@@ -30,6 +32,25 @@ class DesignValidator(RDLListener):
)
# Do not inspect external components. None of my business
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
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",
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