Yocto Build: PYNQ v3.1.2 + XRT 2024.1

Hi PYNQ community,

I’m working on building a custom Yocto (Scarthgap) image for an Ultra96-ZynqMP board using PYNQ v3.1.2 and could use some help figuring out a persistent NameError.

Goal & Setup:

  • Build a Yocto image featuring PYNQ v3.1.2.

  • Initially used meta-xilinx rel-v2025.1 (XRT 2.19.0), but encountered issues.

  • Now targeting meta-xilinx corresponding to XRT 2024.1 (specifically 202410.2.17.319).

  • Using custom recipes for python3-pynq (pointing to SRCREV = "3c77124..." - the official v3.1.2 tag), python3-pynqutils, and python3-pynqmetadata.

  • Target Python version in Yocto is 3.12.

The Problem:

When running simple PYNQ scripts on the target (like initializing an Overlay), I consistently get the following error:

[...]
File "/usr/lib/python3.12/site-packages/pynq/pl_server/xrt_device.py", line 251, in _get_handle
  self.handle = pyxrt.device(self._index)
NameError: name 'pyxrt' is not defined

root:[~/notebooks]: python3 pynq_test.py
/usr/lib/python3.12/site-packages/pydantic/_internal/_config.py:334: UserWarning: Valid config keys have changed in V2:

  • ‘underscore_attrs_are_private’ has been removed
    warnings.warn(message, UserWarning)
    /usr/lib/python3.12/site-packages/pydantic/_internal/_config.py:334: UserWarning: Valid config keys have changed in V2:
  • ‘underscore_attrs_are_private’ has been removed
    warnings.warn(message, UserWarning)
    ====[ PYNQ Test Script ]====
    Traceback (most recent call last):
    File “/home/root/notebooks/pynq_test.py”, line 94, in
    test_pynq()
    File “/home/root/notebooks/pynq_test.py”, line 49, in test_pynq
    overlay = Overlay(“/run/media/BOOTFS-mmcblk0p1/ultra96.itb”)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File “/usr/lib/python3.12/site-packages/pynq/overlay.py”, line 318, in init
    super().init(bitfile_name, dtbo, partial=False, device=device)
    File “/usr/lib/python3.12/site-packages/pynq/bitstream.py”, line 88, in init
    device = Device.active_device
    ^^^^^^^^^^^^^^^^^^^^
    File “/usr/lib/python3.12/site-packages/pynq/pl_server/device.py”, line 70, in active_device
    if len(cls.devices) == 0:
    ^^^^^^^^^^^
    File “/usr/lib/python3.12/site-packages/pynq/pl_server/device.py”, line 54, in devices
    cls._devices.extend(DeviceMeta._subclasses[key].probe())
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File “/usr/lib/python3.12/site-packages/pynq/pl_server/embedded_device.py”, line 546, in probe
    return [EmbeddedDevice()]
    ^^^^^^^^^^^^^^^^
    File “/usr/lib/python3.12/site-packages/pynq/pl_server/embedded_device.py”, line 569, in init
    super().init(index, tag.format(index))
    File “/usr/lib/python3.12/site-packages/pynq/pl_server/xrt_device.py”, line 241, in init
    self._get_handle()
    File “/usr/lib/python3.12/site-packages/pynq/pl_server/xrt_device.py”, line 251, in _get_handle
    self.handle = pyxrt.device(self._index)
    ^^^^^
    NameError: name ‘pyxrt’ is not defined
    root:[~/notebooks]:

This clearly indicates that the PYNQ v3.1.2 code is trying to use the pyxrt module.

Investigation & Current Yocto Approach:

  1. API Mismatch Found: We initially discovered that XRT 2025.1 removed the pyxrt API, hence the error.

  2. Official Image Analysis: We examined the official PYNQ v3.1 image for ZCU104. It uses PYNQ v3.1 with XRT v2.17.0 (2024.1) and includes a pyxrt.so file located at /usr/lib/python3.10/pyxrt.so. It also contains helper Python files (xrt_binding.py, etc.) in /usr/python/. The Overlay import works on that image.

  3. PYNQ Build Script (qemu.sh) Discovery: We found a script (sdbuild/packages/xrtlib/qemu.sh) in the PYNQ v3.1.2 source repo. This script manually checks out XRT tag 202410.2.17.319, patches its src/CMake/embedded_system.cmake to force the Python bindings build (add_subdirectory(python)), compiles XRT, and then manually copies the resulting (misnamed) .so file to /usr/lib/pythonX.Y/pyxrt.so.

  4. Yocto xrt_%.bbappend Implementation: Based on the script and official image, we created an xrt_%.bbappend file in our Yocto layer to mimic this process:

    • Forces PREFERRED_VERSION_xrt = "202410.%".

    • Adds python3-native and python3-pybind11-native to DEPENDS.

    • Adds EXTRA_OECMAKE = " -DXRT_BUILD_PYTHON_BINDINGS=ON".

    • Applies the patch to embedded_system.cmake via SRC_URI.

    • Defines a new package python3-xrt via PACKAGES:append.

    • Uses do_install:append to:

      • Find the compiled .so (e.g., pyxrt.cpython-312-x86_64-linux-gnu.so) in the CMake install dir (${D}${prefix}/python).

      • Move and rename it to the correct location (${D}${libdir}/python3.12/pyxrt.so).

      • Keep the other .py files (xrt_binding.py, etc.) installed by CMake in /usr/python/.

    • Defines FILES:python3-xrt to include /usr/lib/python3.12/pyxrt.so and /usr/python/*.py (and parent dirs).

    • Adds LICENSE and INSANE_SKIP:already-stripped.

    • Adds RDEPENDS:${PN}:append:zynqmp = "... python3-xrt" to the python3-pynq recipe.

Current Status:

  • The Yocto image build completes successfully without packaging errors.

  • On the target, find / -name "*pyxrt.so" correctly shows /usr/lib/python3.12/site-packages/pyxrt.so (Correction: Should be /usr/lib/python3.12/pyxrt.so based on qemu.sh).

  • The helper files like /usr/python/xrt_binding.py are also present.

  • xbutil examine (or xrt-smi examine) works correctly, showing XRT 2.17.0.

  • However, running the Python test script still results in the NameError: name 'pyxrt' is not defined.

Question:

Despite having pyxrt.so seemingly in the correct location (/usr/lib/python3.12/, matching the official image’s pattern, though not site-packages as previously attempted) and the necessary helper .py files present, why would the import pyxrt (or subsequent use) still fail with a NameError?

  • Is there an environment variable (PYTHONPATH?) needed, even if the .so is in /usr/lib/python3.12/? (Tried export PYTHONPATH=/usr/python:$PYTHONPATH previously, didn’t help).

  • Is there an initialization step missing?

  • Could the interaction between /usr/lib/python3.12/pyxrt.so and the files in /usr/python/ be broken in the Yocto build compared to the qemu.sh manual build?

Any insights into how PYNQ v3.1(.2) loads and uses pyxrt when built with XRT 2024.1 would be greatly appreciated!

NB: Some more (usefull?) information about the target system:

root:[~/notebooks]: uname -a
Linux ultra96-zynqmp 6.6.10-xilinx-gf07db70c33a8 #1 SMP Sat Apr 27 05:22:24 UTC 2024 aarch64 GNU/Linux

root:[~/notebooks]:
root:[~/notebooks]: python3 --version
Python 3.12.11

root:[~/notebooks]: xbutil examine
[ 2558.725317] zocl-drm axi:zyxclmm_drm: zocl_destroy_client: client exits pid(1042)
[ 2558.734195] zocl-drm axi:zyxclmm_drm: zocl_create_client: created KDS client for pid(1042), ret: 0
[ 2558.743193] zocl-drm axi:zyxclmm_drm: zocl_destroy_client: client exits pid(1042)
System Configuration
OS Name : Linux
Release [ 2558.753363] zocl-drm axi:zyxclmm_drm: zocl_destroy_client: client exits pid(1042)
: 6.6.10-xilinx-gf07db70c33a8
Version : #1 SMP Sat Apr 27 05:22:24 UTC 2024
Machine : aarch64
CPU Cores : 4
Memory : 1922 MB
Distribution : Demo Distribution 5.0.10
GLIBC : 2.39
Model : demo - Ultra96v2 Board [28/10/25] By Ns.
BIOS vendor : unknown
BIOS version : unknown

XRT
Version : 2.17.0
Branch : 2024.1
Hash : 2c7ff250504589bd1f934010e37bdcef86afaa54
Hash Date : 2024-06-11 19:58:21
ZOCL : 2.17.0, 2c7ff250504589bd1f934010e37bdcef86afaa54
Firmware Version : N/A

Devices present

BDF : Shell Logic UUID Device ID Device Ready*

[0000:00:00.0] : edge 0x0 user(inst=0) Yes

  • Devices that are not ready will have reduced functionality when using XRT tools
    root:[~/notebooks]:
    root:[~/notebooks]: find / -name “xrt
    /etc/profile.d/xrt.sh
    /home/root/notebooks/pynq_test_xrt.ipynb
    /sys/devices/platform/axi/axi:zyxclmm_drm/kds_xrt_version
    /usr/lib/libxrt_core.so
    /usr/lib/libxrt_core.so.2
    /usr/lib/libxrt_core.so.2.17.0
    /usr/lib/libxrt_coreutil.so
    /usr/lib/libxrt_coreutil.so.2
    /usr/lib/libxrt_coreutil.so.2.17.0
    /usr/lib/libxrt_hwemu.so
    /usr/lib/libxrt_hwemu.so.2
    /usr/lib/libxrt_hwemu.so.2.17.0
    /usr/lib/libxrt++.so
    /usr/lib/libxrt++.so.2
    /usr/lib/libxrt++.so.2.17.0
    /usr/lib/libxrt_swemu.so
    /usr/lib/libxrt_swemu.so.2
    /usr/lib/libxrt_swemu.so.2.17.0
    /usr/lib/python3.12/site-packages/pynq/metadata/pycache/xrt_metadata_extension.cpython-312.pyc
    /usr/lib/python3.12/site-packages/pynq/metadata/xrt_metadata_extension.py
    /usr/lib/python3.12/site-packages/pynq/pl_server/pycache/xrt_device.cpython-312.pyc
    /usr/lib/python3.12/site-packages/pynq/pl_server/xrt_device.py
    /usr/lib/python3.12/site-packages/pynqmetadata/views/runtime/pycache/xrt_metadata_extension.cpython-312.pyc
    /usr/lib/python3.12/site-packages/pynqmetadata/views/runtime/xrt_metadata_extension.py
    /usr/lib/python3.12/site-packages/pyxrt.so
    /usr/lib/xrt
    /usr/python/xrt_binding.py
    /usr/python/pyxrt.so
    /usr/share/jupyter/kernels/python3-xrt
    /usr/share/xrt_subcommands.json
    root:[~/notebooks]:

Cheers,

Ns.

Hi @Nicolas_Salmin

In Python, a NameError means that an object or variable is called before it is defined. In this case, pyxrt is being used before it’s being imported.

It is very likely happening here:

As we have to determine between Classic PYNQ and PYNQ.remote installations now, we do this by checking for a specific device tree chosen node we insert during the PYNQ build process. This node is located in proc/device-tree/chosen/pynq_board. If it is available, then we know we’re on a board (Classic PYNQ), and if it’s not there then we assume we’re on a host computer (PYNQ.remote). We do this using the following logic:

What is likely happening is PYNQ is checking if you’re on a board (using the ON_TARGET check), and because it can’t see the pynq_board chosen node, it doesn’t import pyxrt.

If this is the issue, you can either edit the PYNQ source code to remove this check, or add the pynq_board chosen node to the device tree during your Yocto build.

For PYNQ builds, this DT chosen node is inserted during the Petalinux build process, which is done using this file.

There is also an XRT environment variable that needs to be set. We source this file when starting the PYNQ virtual environment.

Hopefully this solves your issue.

2 Likes

@joshgoldsmith Thanks for the really fast support !

Just FYI, after device-tree and init script modifications I was able to run :

  • meta-xilinx: (HEAD, tag: amd-edf-rel-v25.05, xilinx/rel-v2025.1, m/scarthgap-next)
  • Pynq 3.1.2
  • ZOCL/XRT 202410.2.17.319
  • pynqutils: 0.1.2
  • pynqmetadata: 0.1.9

There is no plan to have a meta-pynq ? This a great option to build Pynq with any custom board :slight_smile:

Thanks again for the support and for the wonderful PYNQ work!

Hi @Nicolas_Salmin

If you are able, it would be great if you could share your steps to build a pure Yocto PYNQ image with the community, as I imagine it would be of great interest to a lot of people (including myself).

Hi @joshgoldsmith,

Done

We can talk about in the future if you need help to create (and maintain :stuck_out_tongue: ) a meta-pynq layer.

Feel free to ask anything if something is not clear, maybe wrong, I will be happy to reply.

Why doesn’t an official meta-pynq layer exist?

For FPGA folks (at lest in my company) , PYNQ is an absolute game-changer. It’s the life-saver that lets us test complex hardware and accelerators directly from Python, without having to write and maintain complex bare-metal C/C++ applications just to send some data.

Now that AMD/Xilinx is pushing everyone from the (soon-to-be-deprecated) PetaLinux BSPs to a pure Yocto workflow, a meta-pynq layer seems like the most logical, most-needed piece of the puzzle. It would be the definitive bridge to make Yocto the default, easy-to-use platform for the entire PYNQ community.

Is there a technical reason one doesn’t exist? Is it on a secret roadmap somewhere? :wink: Or is this a gap the community needs to fill? We’d love to hear your thoughts!

Thanks for everything you do with PYNQ.

2 Likes

Hi @Nicolas_Salmin

Thank you for making that post, and I’m very happy to hear PYNQ has been so useful to you and your colleagues!

WRT your question, the PYNQ image build system goes a bit beyond the standard Petalinux/Yocto flow. It uses an Ubuntu-based root filesystem that we extend by building and installing additional packages. This helps us keep things consistent across boards.

With that said, your approach looks interesting, and is something worth discussing. We always encourage community discussion and contributions, so feel free to make a separate post about it, or reach out to me directly.

You might also want to look at PYNQ.remote, which allows host-based PYNQ development, where the PYNQ boards run a minimal Petalinux image (which could potentially be ported to Yocto as well).

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.