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")