validate internal/external boundary crossings
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user