PyRogue API Reference
This page is a hand-written manual reference for all entries in the python/axipcie/
package — nine device classes and the module-level connection helpers. It covers what
each class exposes to the PyRogue register tree and how to instantiate it.
Surf-provided base classes (pr.Device, pr.Root, surf.axi.AxiVersion) are
referenced by name only; their APIs are documented in the pyrogue and surf projects
respectively. This reference is written by hand, not auto-generated — per the project
decision recorded in PROJECT.md (section “Key Decisions”:
Manual RTL/PyRogue reference (no autodoc)).
See Architecture for the BAR0 register-map overview that these classes map to.
AxiPcieCore
AxiPcieCore (subclasses pr.Device; defined in python/axipcie/_AxiPcieCore.py) maps to shared/rtl/AxiPcieReg.vhd. It
is the top-level PyRogue device tree for the PCIe BAR0 register space, instantiating
PcieAxiVersion, AXI-Stream monitors, optional PROM/SysMon/I2C/transceiver devices,
and optionally AxiGpuAsyncCore. It does not declare pr.RemoteVariable instances
directly; instead it assembles a tree of sub-devices at fixed offsets.
class AxiPcieCore(pr.Device):
def __init__(self,
description = 'Base components of the PCIe firmware core',
useBpi = False,
useGpu = False,
useSpi = False,
transceiverClass = [None],
numDmaLanes = 1,
boardType = None,
extended = False,
sim = False,
**kwargs):
Sub-device |
BAR0 Offset |
Condition |
Description |
|---|---|---|---|
|
|
Always |
Build-info and board-type identification registers |
|
|
Always |
DMA inbound (host to FPGA) stream monitor; |
|
|
Always |
DMA outbound (FPGA to host) stream monitor; |
|
|
|
PCIe PHY link-status registers |
|
|
|
GPU-Direct async data-path registers |
|
|
|
BPI PROM (Micron MT28 or Cypress S29GL) |
|
|
|
SPI PROM channel 0 |
|
|
|
SPI PROM channel 1 |
|
|
|
I2C bridge proxy (prevents BAR0 stall on slow I2C transactions) |
|
|
board-specific |
UltraScale/UltraScale+ SysMon (temperature, VCC rails) |
Per-slot transceiver (QSFP/SFP) |
varies |
|
|
Notes. At _start() time, AxiPcieCore reads PCIE_HW_TYPE_G from
PcieAxiVersion and raises ValueError if it does not match boardType.
Pass boardType=None to skip this check. Pass sim=True to bypass all hardware
devices (PCIe PHY, PROM, I2C, SysMon, transceiver) for software co-simulation.
The transceiverClass argument accepts a per-slot list; valid string entries are
'QSFP', 'SFP', and 'QSFP-DD'.
AxiPcieRoot
AxiPcieRoot (subclasses pr.Root; defined in python/axipcie/_AxiPcieRoot.py) is a convenience wrapper that opens the PCIe
BAR0 memory map via rogue.hardware.axi.AxiMemMap and instantiates AxiPcieCore
at the top of the device tree. It is intended for simple use-cases; production projects
typically build a custom pr.Root subclass.
class AxiPcieRoot(pr.Root):
def __init__(self, dev, **kwargs):
Sub-device |
Description |
|---|---|
|
Full BAR0 register tree; constructed with |
Notes. dev is the Linux device-node path (e.g., '/dev/datadev_0'). All
**kwargs are forwarded to pr.Root.__init__. For simulation or multi-device
scenarios, use createAxiPcieMemMap and createAxiPcieDmaStreams (see
Module Helpers) and construct pr.Root directly.
AxiPcieDma
The _AxiPcieDma module (python/axipcie/_AxiPcieDma.py) provides two module-level helper functions rather than a
device class. AxiPcieDma names a VHDL entity (the DMA engine in
shared/rtl/AxiPcieDma.vhd); there is no PyRogue AxiPcieDma class. DMA stream
monitoring is performed by surf.axi.AxiStreamMonAxiL instances added by
AxiPcieCore (DmaIbAxisMon at 0x60000, DmaObAxisMon at 0x68000).
The module-level helpers createAxiPcieMemMap and createAxiPcieDmaStreams are
exported from python/axipcie/__init__.py via wildcard import and are the primary
user-facing entry points for opening connections to hardware or simulation. See
Module Helpers for full signatures and driverPath mode documentation.
AxiPipCore
AxiPipCore (subclasses pr.Device; defined in python/axipcie/_AxiPipCore.py) maps the register interface of the PCIe
Intercommunication Protocol (PIP) core. It monitors and controls cross-FPGA write
transactions from a peer FPGA over a shared PCIe root complex.
class AxiPipCore(pr.Device):
def __init__(self,
numLane = 1,
description = 'Container for the PIP core registers',
**kwargs):
Name |
Offset |
Mode |
Description |
|---|---|---|---|
|
|
RW |
Base address of peer FPGA BAR0 for lane |
|
|
RO |
EOFE (end-of-frame error) depacketiser count for lane |
|
|
RO |
Total received frames |
|
|
RO |
Dropped received frames |
|
|
RO |
Total transmitted frames |
|
|
RO |
Dropped transmitted frames |
|
|
RO |
AXI write error count on the transmit path |
|
|
RO |
Number of AXI-Stream lanes built into firmware |
|
|
RW |
Per-lane transmit enable bitmask |
|
|
RW |
AXI write-cache attribute (4 bits, drives |
|
|
WO |
Pulse to clear all status counters |
Notes. The corresponding VHDL entity is AxiPciePipCore (note the Pcie
infix), located at protocol/pip/rtl/AxiPciePipCore.vhd. The PyRogue class drops
the Pcie infix: AxiPipCore != AxiPciePipCore. Both names refer to the same
hardware block; when tracing register definitions in the RTL, search for
AxiPciePipCore.
PcieAxiVersion
PcieAxiVersion (subclasses surf.axi.AxiVersion; defined in python/axipcie/_PcieAxiVersion.py) extends the standard surf
version block with PCIe-specific build-info fields. It is instantiated by
AxiPcieCore at BAR0 offset 0x20000.
class PcieAxiVersion(axi.AxiVersion):
def __init__(self,
name = 'AxiVersion',
description = 'AXI-Lite Version Module',
numUserConstants = 0,
**kwargs):
The table below covers the PCIe-specific registers appended at base offset 0x400.
Inherited surf.axi.AxiVersion registers (firmware version, build timestamp, git
hash, DNA, uptime counter, UserRst command) are not listed here. See
Register Map Reference for the full bit-field table.
Name |
Offset |
Mode |
Description |
|---|---|---|---|
|
|
RO |
Number of DMA lanes compiled into firmware (1 to 8) |
|
|
RO |
Driver type identifier constant |
|
|
RO |
FPGA family enum: 0=ULTRASCALE, 1=7SERIES |
|
|
RO |
DMA clock frequency in Hz (250 000 000 for all production boards) |
|
|
RO |
Boot PROM type enum: BPI / SPIx8 / SPIx4 / UNDEFINED |
|
|
RO |
DMA AXI-Stream data width in bytes (e.g., 32 for 256-bit bus) |
|
|
RO |
Application reset status; Boolean, polled every 1 s |
|
|
RO |
AXI address width in bits (64 on all production boards) |
|
|
RO |
AXI data bus width in bytes (32 for 256-bit bus) |
|
|
RO |
Application clock frequency in Hz; polled every 1 s |
|
|
RO |
Board-type enum matching |
|
|
RO |
GPU-Direct async core present in firmware; Boolean |
Notes. PCIE_HW_TYPE_G is cross-checked by AxiPcieCore._start() against the
boardType constructor argument. Additional packing sub-fields
(DMA_AXIS_CONFIG_G_TDEST_BITS_C, _TUSER_BITS_C, _TID_BITS_C,
_TKEEP_MODE_C, _TUSER_MODE_C, _TSTRB_EN_C) are packed into 0x418 and
AXI_PCIE_CONFIG_C_ID_BITS_C / _LEN_BITS_C into 0x41C; see the source file
for full bit-field layout.
CmsProxy
The _CmsProxy module (python/axipcie/_CmsProxy.py) defines the Xilinx CMS (Card Management Subsystem) interface
for XilinxAlveoU55c and XilinxVariumC1100 boards. The primary user-facing class
is CmsSubsystem (subclasses pr.Device). The module also exports
CmsLowSpeedIo and Status, which are accessed as sub-devices of
CmsSubsystem.
class CmsSubsystem(pr.Device):
def __init__(self,
pollPeriod = 0.0,
moduleType = None,
numCages = 1,
**kwargs):
Name |
Offset |
Mode |
Description |
|---|---|---|---|
|
|
RW |
MicroBlaze reset register; active-low, default 0x0 (reset active) |
Notes. CmsSubsystem instantiates a Status sub-device at offset 0x28000
exposing board telemetry (voltages, currents, temperatures, fan speed) and a Mailbox
sub-device that implements the CMS mailbox protocol (AMD PG348). A _ProxySlave
wraps the mailbox to relay I2C-over-CMS transactions for QSFP management. Pass
moduleType='QSFP' and numCages=2 to enable QSFP presence, interrupt, and
low-power GPIO (CmsLowSpeedIo). AxiPcieCore adds a CmsSubsystem instance
named CmsBridge when boardType is 'XilinxAlveoU55c' or
'XilinxVariumC1100'.
AxiGpuAsyncCore
AxiGpuAsyncCore (subclasses pr.Device; defined in python/axipcie/_AxiGpuAsyncCore.py) maps the GPU-Direct async data-path
registers. It controls write/read buffer counts and enables, and exposes frame counters
and DMA latency measurements for the GPU-direct bypass pipeline.
class AxiGpuAsyncCore(pr.Device):
def __init__(self,
showBuffers = False,
showErrorCnt = False,
description = 'Container for the GPUAsync core registers',
**kwargs):
Name |
Offset |
Mode |
Description |
|---|---|---|---|
|
|
RO |
Maximum DMA buffer count compiled into firmware |
|
|
RO |
AXI data bus width in bytes |
|
|
RO |
Number of active write buffers; kernel-managed |
|
|
RO |
Write path enable; Boolean, kernel-managed |
|
|
RO |
Number of active read buffers; kernel-managed |
|
|
RO |
Read path enable; Boolean, kernel-managed |
|
|
RO |
Received frame count; polled every 1 s |
|
|
RO |
Transmitted frame count; polled every 1 s |
|
|
RO |
Write AXI error count; visible when |
|
|
RO |
Read AXI error count; visible when |
|
|
WO |
Clear all status counters plus IB/OB stream monitors |
|
|
RW |
Stream routing: 0=CPU_path (debug), 1=GPU_path (normal operation) |
|
|
RO |
Minimum write free-list depth since last |
|
|
RO |
Maximum read queue depth since last |
|
|
RO |
Configured maximum write buffer size in bytes; kernel-managed |
|
|
RO |
End-to-end latency: DMA write start to DMA read complete (axiClk cycles) |
|
|
RO |
GPU processing latency: DMA write done to buffer returned (axiClk cycles) |
Notes. The corresponding VHDL entity is AxiPcieGpuAsyncCore (note the Pcie
infix), at protocol/gpuAsync/rtl/AxiPcieGpuAsyncCore.vhd. The PyRogue class drops
the Pcie infix: AxiGpuAsyncCore != AxiPcieGpuAsyncCore. Variables marked
“kernel-managed” (WriteCount, WriteEnable, ReadCount, ReadEnable,
RemoteWriteMaxSize) are written by the aes-stream-drivers kernel module, not
userspace. Per-buffer RemoteWriteAddress, RemoteReadAddress, and
RemoteReadSize sub-fields (AxiGpuAsyncBuffer sub-devices) are visible only when
showBuffers=True. Each latency metric (TotLatency, GpuLatency,
WrDmaLatency, RdDmaLatency) also has *Max and *Min variants at
base+0x4 and base+0x8; see the source for the full variable list.
BittWareXupVv8QsfpGpio
BittWareXupVv8QsfpGpio (subclasses pr.Device; defined in python/axipcie/_BittWareXupVv8QsfpGpio.py) maps the PCA9555 I/O expander
that drives QSFP presence, interrupt, low-power, and reset signals on BittWare XUP-VV8
boards (VU9P and VU13P variants). Each RemoteVariable encodes four QSFP slots using a
multi-offset packed representation.
class BittWareXupVv8QsfpGpio(pr.Device):
def __init__(self, **kwargs):
Name |
Offsets (slots 0-3) |
Mode |
Description |
|---|---|---|---|
|
|
RO |
Module presence per slot (0=present, 1=absent) |
|
|
RO |
Interrupt active per slot (0=asserted, 1=clear) |
|
|
RW |
Low-power mode per slot (1=low-power, 0=normal) |
|
|
RW |
Reset per slot (0=reset asserted, 1=de-asserted) |
Notes. Four additional pairs of hidden variables (POL_* polarity inversion
registers at 0x10/0x14 and CFG_* direction configuration registers at
0x18/0x1C) are present but hidden in the PyRogue GUI. Each variable encodes one
bit per QSFP slot using pyrogue’s multi-value offset/bitOffset list feature for
packing non-contiguous bits into a single logical variable.
TerminateQsfp
TerminateQsfp (subclasses pr.Device; defined in python/axipcie/_TerminateQsfp.py) reads the reference clock frequencies
delivered to QSFP cage transceivers. It is used on boards that share reference clocks
between the PCIe PHY and the QSFP cages.
class TerminateQsfp(pr.Device):
def __init__(self, numRefClk=4, **kwargs):
Name |
Offset |
Mode |
Description |
|---|---|---|---|
|
|
RO |
Reference clock frequency in Hz for clock |
Notes. TerminateQsfp uses addRemoteVariables with number=numRefClk and
stride=4 to create an array of numRefClk frequency-readback variables. The
default is four reference clocks. Instances appear in boards that derive QSFP reference
clocks from the system 156.25 MHz oscillator.
Module Helpers
The python/axipcie/__init__.py package re-exports all nine device classes via
wildcard imports (from axipcie._AxiPcieCore import *, etc.). Two module-level
helper functions defined in _AxiPcieDma are the primary user-facing entry points
for opening hardware or simulation connections:
createAxiPcieMemMap
def createAxiPcieMemMap(driverPath, host='localhost', port=8000):
Opens BAR0 memory-map access to AxiPcieCore. When driverPath != 'sim', opens a
rogue.hardware.axi.AxiMemMap to the Linux device node at driverPath (e.g.,
'/dev/datadev_0'). When driverPath == 'sim', returns a
rogue.interfaces.memory.TcpClient(host, port) that connects to a simulation server.
The returned object is passed as memBase to AxiPcieCore.
createAxiPcieDmaStreams
def createAxiPcieDmaStreams(driverPath, streamMap,
host='localhost', basePort=8000):
Opens DMA stream channels. streamMap is a {lane: [dest, ...]} dict specifying
which (lane, destination) pairs to open. When driverPath != 'sim', opens
rogue.hardware.axi.AxiStreamDma for each (lane, dest) pair, encoding the channel
number as (0x100 * lane) | dest. When driverPath == 'sim', opens
rogue.interfaces.stream.TcpClient connections with port computed as
(basePort + 2) + (512 * lane) + 2 * dest. Returns a nested dict
{lane: {dest: stream_object}}.
These two functions are the primary integration point between the PyRogue device tree
and the rogue hardware/simulation I/O layer.