# Copyright 2026 Apheleia
#
# Description:
# Apheleia Verification Library Register Abstraction Component
from typing import Any
import systemrdl.node
from cocotb.handle import LogicObject
[docs]
class Field(systemrdl.node.FieldNode):
def __str__(self) -> str:
"""
Custom String Formatting
:return: The formatted string
:rtype: str
"""
reset = self.get_property("reset")
sw = self.get_property("sw").name.upper()
hw = self.get_property("hw").name.upper()
_str_ = ""
_str_ += f"\t\tField: {self.inst_name:<16}\n"
_str_ += f"\t\t\t{'Bits':<16}: [{self.high}:{self.low}]\n"
_str_ += f"\t\t\t{'Reset':<16}: {reset}\n"
_str_ += f"\t\t\t{'Value':<16}: {reset}\n"
_str_ += f"\t\t\t{'SW Access':<16}: {sw}\n"
_str_ += f"\t\t\t{'HW Access':<16}: {hw}\n"
if hasattr(self.inst, "cocotb_hdl_handle"):
_str_ += f"\t\t\t{'Current Value':<16}: {hex(self.peek())}\n"
return _str_
def _extract_(self, value : int) -> int:
"""
Extract the value of the field from a value
:param value: The value to extract from
:type value: int
:return: The extracted value
:rtype: int
"""
return (value & self.bitmask) >> self.low
def _replace_(self, original : int , value : int) -> int:
"""
Replace field in original value
:param original: Original value
:type original: int
:param value: Replace value
:type value: int
:return: The full value afer replacing
:rtype: int
"""
masked_value = value & ((1 << self.width)-1)
v = original & ~self.bitmask
v |= (masked_value << self.low)
return v
@property
def bitmask(self) -> int:
"""
Get the bitmask of the field
:return: The bitmask of the field
:rtype: int
"""
mask = (1 << self.width) - 1
return mask << self.low
[docs]
def assign_hdl(self, hdl : LogicObject) -> None:
"""
Assign a HDL handle to the field
:param hdl: The HDL handle to assign
:type hdl: LogicObject
:return: None
"""
self.inst.cocotb_hdl_handle = hdl
[docs]
def peek(self) -> int | None:
"""
Peek value of field directly from HDL handle
:return: The value of the field
:rtype: int
"""
if hasattr(self.inst, "cocotb_hdl_handle"):
return int(self.inst.cocotb_hdl_handle.value)
else:
return None
[docs]
def poke(self, value: Any) -> None:
"""
Peek value of field directly from HDL handle
:param value: The value to poke
:type value: Any
:return: None
"""
if hasattr(self.inst, "cocotb_hdl_handle"):
self.inst.cocotb_hdl_handle.value = int(value)
[docs]
async def read(self) -> int:
"""
Read the value of the register
:return: The value of the register
:rtype: int
"""
rdval = await self.parent.read()
return self._extract_(rdval)
[docs]
async def write(self, value : int) -> None:
"""
Read the value of the register
:param value: The value to write
:type value: int
:return: None
"""
rdval = await self.parent.read()
wrval = self._replace_(rdval, value)
await self.parent.write(wrval)
# Monkey Patch
systemrdl.node.FieldNode = Field
__all__ = ["Field"]