Add double-buffer UDP definitions
This commit is contained in:
120
src/peakrdl_regblock/udps.py
Normal file
120
src/peakrdl_regblock/udps.py
Normal file
@@ -0,0 +1,120 @@
|
||||
from typing import Any
|
||||
|
||||
from systemrdl.udp import UDPDefinition
|
||||
from systemrdl.component import Reg
|
||||
from systemrdl.rdltypes.references import RefType, PropertyReference
|
||||
from systemrdl.node import Node, RegNode, VectorNode
|
||||
|
||||
|
||||
class xBufferTrigger(UDPDefinition):
|
||||
valid_components = {Reg}
|
||||
valid_type = RefType
|
||||
|
||||
def validate(self, node: Node, value: Any) -> None:
|
||||
# TODO: Reference shall not cross an internal/external boundary
|
||||
|
||||
if isinstance(value, VectorNode):
|
||||
# Trigger can reference a vector, but only if it is a single-bit
|
||||
if value.width != 1:
|
||||
self.msg.error(
|
||||
"%s '%s' references %s '%s' but it's width is not 1"
|
||||
% (
|
||||
type(node.inst).__name__.lower(), node.inst_name,
|
||||
type(value.inst).__name__.lower(), value.inst_name
|
||||
),
|
||||
self.get_src_ref(node)
|
||||
)
|
||||
elif isinstance(value, PropertyReference) and value.width is not None:
|
||||
# Trigger can reference a property, but only if it is a single-bit
|
||||
if value.width != 1:
|
||||
self.msg.error(
|
||||
"%s '%s' references property '%s->%s' but it's width is not 1"
|
||||
% (
|
||||
type(node.inst).__name__.lower(), node.inst_name,
|
||||
value.node.inst_name, value.name,
|
||||
),
|
||||
self.get_src_ref(node)
|
||||
)
|
||||
elif isinstance(value, RegNode):
|
||||
# Trigger can reference a register, which implies access of the
|
||||
# 'correct half' of the register is the trigger.
|
||||
# For buffered writes, it is the upper-half.
|
||||
# For buffered reads, it is the lower-half.
|
||||
pass
|
||||
else:
|
||||
# All other reference types are invalid
|
||||
self.msg.error(
|
||||
"Reference to a %s component is incompatible with the '%s' property."
|
||||
% (type(node.inst).__name__.lower(), self.name),
|
||||
self.get_src_ref(node)
|
||||
)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
class BufferWrites(UDPDefinition):
|
||||
name = "buffer_writes"
|
||||
valid_components = {Reg}
|
||||
valid_type = bool
|
||||
default_assignment = True
|
||||
|
||||
def validate(self, node: 'Node', value: Any) -> None:
|
||||
assert isinstance(node, RegNode)
|
||||
if value:
|
||||
if not node.has_sw_writable:
|
||||
self.msg.error(
|
||||
"'buffer_writes' is set to true, but this register does not contain any writable fields.",
|
||||
self.get_src_ref(node)
|
||||
)
|
||||
# TODO: Should I limit the use of other properties on double-buffered registers?
|
||||
|
||||
def get_unassigned_default(self, node: 'Node') -> Any:
|
||||
return False
|
||||
|
||||
|
||||
class WBufferTrigger(xBufferTrigger):
|
||||
name = "wbuffer_trigger"
|
||||
|
||||
def get_unassigned_default(self, node: 'Node') -> Any:
|
||||
# If buffering is enabled, trigger is the register itself
|
||||
if node.get_property('buffer_writes'):
|
||||
return node
|
||||
return None
|
||||
|
||||
|
||||
class BufferReads(UDPDefinition):
|
||||
name = "buffer_reads"
|
||||
valid_components = {Reg}
|
||||
valid_type = bool
|
||||
default_assignment = True
|
||||
|
||||
def validate(self, node: 'Node', value: Any) -> None:
|
||||
assert isinstance(node, RegNode)
|
||||
if value:
|
||||
if not node.has_sw_readable:
|
||||
self.msg.error(
|
||||
"'buffer_reads' is set to true, but this register does not contain any readable fields.",
|
||||
self.get_src_ref(node)
|
||||
)
|
||||
|
||||
# TODO: Should I limit the use of other properties on double-buffered registers?
|
||||
|
||||
def get_unassigned_default(self, node: 'Node') -> Any:
|
||||
return False
|
||||
|
||||
|
||||
class RBufferTrigger(xBufferTrigger):
|
||||
name = "rbuffer_trigger"
|
||||
|
||||
def get_unassigned_default(self, node: 'Node') -> Any:
|
||||
# If buffering is enabled, trigger is the register itself
|
||||
if node.get_property('buffer_reads'):
|
||||
return node
|
||||
return None
|
||||
|
||||
|
||||
|
||||
ALL_UDPS = [
|
||||
BufferWrites,
|
||||
WBufferTrigger,
|
||||
BufferReads,
|
||||
RBufferTrigger,
|
||||
]
|
||||
Reference in New Issue
Block a user