From 5267a4d2452a274509695fd4887ca3f37626eed5 Mon Sep 17 00:00:00 2001 From: Alex Mykyta Date: Thu, 20 Apr 2023 23:36:15 -0700 Subject: [PATCH] validate internal/external boundary crossings --- docs/dev_notes/Validation Needed | 8 ++--- src/peakrdl_regblock/validate_design.py | 46 ++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/docs/dev_notes/Validation Needed b/docs/dev_notes/Validation Needed index 463c57f..6377ec2 100644 --- a/docs/dev_notes/Validation Needed +++ b/docs/dev_notes/Validation Needed @@ -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 diff --git a/src/peakrdl_regblock/validate_design.py b/src/peakrdl_regblock/validate_design.py index c975405..6c6a0ce 100644 --- a/src/peakrdl_regblock/validate_design.py +++ b/src/peakrdl_regblock/validate_design.py @@ -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