PyRogue Device Tree
The application’s PyRogue device tree mirrors the AXI-Lite crossbar hierarchy
in RTL. Each pr.Device carries an offset relative to its parent. The
values below are sourced from
firmware/python/simple_zcu111_example/_Root.py,
firmware/python/simple_zcu111_example/_RFSoC.py, and
firmware/python/simple_zcu111_example/_Application.py.
Hierarchy
Root(pr.Root, see firmware/python/simple_zcu111_example/_Root.py)Rfdc(RFDC API interface, platform-provided)RFSoC(offset0x04_0000_0000, see firmware/python/simple_zcu111_example/_RFSoC.py)AxiSocCore(offset0x0000_0000, platform core)Hardware(offset0x8000_0000,xilinxZcu111.Hardware— LMK/LMX I2C clock control)Application(offset0xA000_0000, see firmware/python/simple_zcu111_example/_Application.py)AppRingBuffer(offset0x00_000000)DacSigGen(offset0x01_000000,SigGeninstance)DacSigGenLoader(host-side waveform loader)
adcProcessor[0..7],dacProcessor[0..7](host-sideRingBufferProcessorinstances; see reference/pyrogue_api.html)DataWriter(pr.utilities.fileio.StreamWriter)
The Application device declares its children with offset values that
match the RTL Application crossbar (see Application Register Map):
self.add(rfsoc_utility.AppRingBuffer(
offset = 0x00_000000,
numAdcCh = 8, # Must match NUM_ADC_CH_G config
numDacCh = 8, # Must match NUM_DAC_CH_G config
))
self.add(rfsoc_utility.SigGen(
name = 'DacSigGen',
offset = 0x01_000000,
numCh = 8, # Must match NUM_CH_G config
ramWidth = 10, # Must match RAM_ADDR_WIDTH_G config
smplPerCycle = 16, # Must match SAMPLE_PER_CYCLE_G config
))
The smplPerCycle = 16 parameter mirrors the RTL SAMPLE_PER_CYCLE_C
constant declared in AppPkg Constants.
Startup sequence
Root.start() (in
firmware/python/simple_zcu111_example/_Root.py) executes the
following ordered sequence after the base pr.Root.start() runs:
TCP connection setup (memory map + RFDC + ring-buffer streams).
Stream wiring (8 ADC + 8 DAC ring buffer paths chained to
DataWriterand to per-channel host-side processors via>>).User-logic reset (
RFSoC.AxiSocCore.UserRst()).LMK/LMX clock chip initialization (
RFSoC.Hardware.InitClock).DSP-clock-stable wait (
RFSoC.AxiSocCore.DspRstWait()).Application enable (
RFSoC.Application.enable.set(True)) — only after the DSP clock is stable.RFDC initialization and MTS sync (
Rfdc.Init()andRfdc.Mts.*).Default YAML configuration load (
LoadConfig).DacSigGen waveform load (CSV file or
LoadSingleTonesfallback).
The Application device is constructed with enabled=False and is
deliberately enabled only after step 5. Bypassing this order leaves the
application reading registers in an unknown clock state.
For platform-level PyRogue patterns — the AxiSocCore interface, the
Rfdc API, and the host-side RingBufferProcessor stream pipeline — see
reference/pyrogue_api.html.
Public package surface
The simple_zcu111_example package exposes its public classes via a
wildcard re-export pattern in
firmware/python/simple_zcu111_example/__init__.py:
from simple_zcu111_example._Application import *
from simple_zcu111_example._RFSoC import *
from simple_zcu111_example._Root import *
Private implementation files are underscore-prefixed (_Application.py,
_RFSoC.py, _Root.py); __init__.py is the public face.