How to Extend Peripheral Access Width in QEMU-based QBox CPU Model
This is a great work!!!
I am currently exploring the QEMU-based QBox project and looking for guidance on extending the peripheral access width for CPU-to-peripheral transactions. I want to ensure that the CPU model can support wider data transactions (e.g., 64-bit or more) while accessing peripherals. Here are the specific questions I have:
- Current Peripheral Access Width Determination How does the current QBox determine the access width when the CPU communicates with peripherals (e.g., UART, memory-mapped devices)? Which components or configurations influence this behavior? For example: qemu-components/common/src/libqemu-cxx/cpu.cc for CPU model behavior. MemoryRegionOps definitions for peripherals. Bus protocols (e.g., AXI or PCI configurations).
- Extending Access Width If I want to extend the access width (e.g., from 32-bit to 64-bit or 128-bit) in the QBox: What parts of the CPU model or peripheral implementation should I focus on? Should I update the MemoryRegionOps in files like qemu-components/common/src/libqemu-cxx/device.cc? How does the tlm_generic_payload or TLM extensions in SystemC interact with these configurations?
- Testing and Validation Are there existing tests in the tests/ directory that cover access width validation? If not, what would be the recommended way to test such modifications in QBox?
- General Recommendations Are there any best practices or existing design patterns in QBox for handling wider transactions (e.g., outstanding transactions or batched access)?
I would like to extend the QEMU CPU model and peripheral interactions to support wider data transactions and understand the appropriate design choices. Any pointers, suggestions, or examples would be highly appreciated!
Interesting question... The answer I think is in 3 parts:
1/ First, a QEMU memory region has a 'size' set, and QEMU will organise to split requests accordingly (you will see multiple transactions upto 8-bytes wide). In Qbox we hard-wire that to 8-bytes (see https://github.com/quic/qbox/blob/4c11306986746b5d8c31f63c6142a193903e10a4/qemu-components/common/include/ports/initiator.h#L636 and other places in that file).
On it's own, one could imagine changing this number, but .... the consequences may be unforeseen
2/ When QEMU makes an access the 'size' of the access is provided back to SystemC : https://github.com/quic/qbox/blob/4c11306986746b5d8c31f63c6142a193903e10a4/qemu-components/common/include/ports/initiator.h#L606 This is good news, HOWEVER....
3/ I suspect in several places in qbox, from the memory to the uarts, to everything in between, there are probably a myriad of places where assumptions about a transaction's data fitting into a uint64 are made. I haven't looked for those, I think you would have to take each one by one. I would personally suggest they were 'bugs' - the 'size' of the transaction should be respected.
You ask about AXI and PCI. AXI is treated as a normal TLM-2 generic bus. The PCI bus however is not dealt with by QBox. A GPEX device is exposed from QEMU, and you can then add PCI devices to that GPEX, but the bus-handling is within QEMU itself. Exposing a PCI bus in SystemC would also be an interesting task.
In terms of testing, please take a look at the simple memory tests - they may not cover all the cases you would like, please feel free to suggest patches!
Thanks for your quick replay. I will give it a try.