Integration

../_images/QEMU_Hierachy.png

Python Integration

AVL-QEMU is simple to integrate by:

  • Instancing the Agent avl_qemu._x86 module

  • Implementing async read and write callbacks

  • Declaring active memory ranges associated with the callbacks

# Copyright 2024 Apheleia
#
# Description:
# Apheleia attributes example


import avl
import avl_qemu
import cocotb
from cocotb.triggers import Timer


class example_env(avl.Env):

    def __init__(self, name : str, parent : avl.Component | None) -> None:
        """
        Initialize the example environment with a simple memory model and an x86 QEMU agent.

        :param name: The name of the environment.
        :type name: str
        :param parent: The parent component in the AVL hierarchy.
        :type parent: avl.Component
        :return: None
        """
        super().__init__(name, parent)

        # Simple memory model for testing
        self.mem = avl.Memory(width=64)
        self.mem.add_range(0x4000000, 0x4001000)

        # Qemu agent configuration
        self.qemu = avl_qemu.X86Agent("x86_agent", self)
        self.qemu.add_range("test_region", 0x4000000, 0x1000, self.read_cb, self.write_cb)


    async def read_cb(self, addr : int, size: int) -> int:
        """
        Callback function for read operations from QEMU. Reads data from the memory model.

        :param addr: The address being read.
        :type addr: int
        :param size: The size of the read operation in bytes.
        :type size: int
        :return: The data read from the memory.
        :rtype: int
        """
        await Timer(10, unit="ns")  # Simulate some latency
        return self.mem.read(addr, size)

    async def write_cb(self, addr : int, size: int, data: int) -> None:
        """

        Callback function for write operations from QEMU. Writes data to the memory model.

        :param addr: The address being written to.
        :type addr: int
        :param size: The size of the write operation in bytes.
        :type size: int
        :param data: The data being written.
        :type data: int
        :return: None
        """
        self.mem.write(addr, data, num_bytes=size)

@cocotb.test
async def test(dut):
    e = example_env("env", None)
    await e.start()

Developing C-Tests

C-Tests are written and developed exactly as you would for any embedded software. The provided example uses bare-metal, but using any of the OS libraries supported in QEMU is equally valid.

The example provides:

  • boot.s (simple boot script)

  • linker.ld (linker with defined memory range for AVL integration)

  • main.c (the test case)

  • Makefile