Register / Field Access
Once the register definitions have been import avl_ral._ral.RAL provides two functions to locate registers and fields.
These functions return a list of Register and / or field objects that match the given criteria. Full path names (including “.” separators) and / or wildcards (including “*”) are supported.
Front-Door Access
Front-door accesses are supported via callbacks supplied by the user.
These are assigned using the RAL.assign_callbacks function.
# Assign callbacks
self.ral.assign_callbacks(read=self.read, write=self.write)
async def read(self, addr : int) -> int:
await RisingEdge(self.hdl.clk)
self.hdl.valid.value = 1
self.hdl.addr.value = addr
self.hdl.r_not_w.value = 1
await RisingEdge(self.hdl.clk)
self.hdl.valid.value = 0
self.hdl.addr.value = 0
self.hdl.r_not_w.value = 0
await RisingEdge(self.hdl.clk)
return int(self.hdl.rdata.value)
async def write(self, addr : int, value : int) -> None:
await RisingEdge(self.hdl.clk)
self.hdl.valid.value = 1
self.hdl.addr.value = addr
self.hdl.wdata.value = value
self.hdl.r_not_w.value = 0
await RisingEdge(self.hdl.clk)
self.hdl.valid.value = 0
self.hdl.addr.value = 0
self.hdl.wdata.value = 0
self.hdl.r_not_w.value = 0
When performed on a register these callbacks are executed exactly as implemented.
When performed on a field accesses are performed on the parent register as read-modify-writes. This matches how software would implement a field specific update.
Implementing front-door access via AVL-AXI or AVL-APB callbacks is trivial.
Back-Door Access
Back-door access are supported by Field.peek and Field.poke functions. Before these are able to be used the user must assign a HDL handle to the field, Field.assign_hdl function.`
Registers also support Reg.peek and Reg.poke functions, calling each child fields functions for the give bit positions.
# Connect all field to HDL variables (assume HDL variables name match logical name)
fields = self.ral.find_by_name(name="*", types=FieldNode)
for f in fields:
f.assign_hdl(getattr(self.hdl, f.inst_name))
# Field Poke / Peek Test
for f in self.ral.find_by_name(name="*", types=FieldNode):
f.poke(0x1)
await RisingEdge(self.hdl.clk)
assert f.peek() == 0x1, f"{f.inst_name} poke / peek failed expected 0x1 got {f.peek()}"
self.info("Field Poke / Peek Test: PASS")
# Register Poke / Peek Test
for r in self.ral.find_by_name(name="*", types=RegNode):
r.poke(0x0)
await RisingEdge(self.hdl.clk)
assert r.peek() == 0x0, f"{r.inst_name} poke / peek failed expected 0x0 got {r.peek()}"
self.info("Register Poke / Peek Test: PASS")