HRX Runtime (amdxdna)¶
The HRX backend is an opt-in host runtime for IRON that dispatches designs on
the AMD XDNA NPU through libhrx (the IREE-based runtime with an amdxdna
HAL), consuming the same aiecc artifacts (final.xclbin + insts.bin) as the
default XRT path. It requires no XRT userspace at
runtime, and — combined with the bundled XRT-free xclbinutil — lets the whole
build-and-run flow work on a machine with no XRT install at all.
HRX plugs into the same aie.utils.Tensor
and HostRuntime abstractions the
XRT backend uses, so example and design code is unchanged — the backend is chosen
by an environment/make variable, not by editing sources.
Enabling HRX¶
HRX is strictly opt-in. It is never auto-selected: an XRT-less host degrades to CPU-only tensors rather than silently switching to HRX.
A single NPU_RUNTIME variable drives both flows:
| Flow | Example |
|---|---|
| IRON / Python | NPU_RUNTIME=hrx python my_design.py |
C++ examples (make) |
NPU_RUNTIME=hrx make run |
The IRON/Python flow reads NPU_RUNTIME at import time (a runtime switch), while
the C++ example make flow reads the same variable to build the HRX host stack (a
build-time switch) — one selector, two mechanisms. The full list of NPU_RUNTIME
values and every HRX environment variable
(HRX_DIR, LIBHRX_DIR, HRX_LIBHRX, IRON_HRX_DEVICE, HRX_EXE_CACHE_SIZE,
IRON_HRX_TIMEOUT) is documented in
IRON Configuration.
Provisioning libhrx¶
Fetch, checksum-verify, and extract the pinned HRX release (coordinates in
utils/hrx-release.env) with the helper script, then source the environment it
prints:
source "$(utils/fetch-hrx-release.sh)"
# or, in one step: eval "$(utils/fetch-hrx-release.sh --print-env)"
Verify HRX is discoverable (path-only probe — no dlopen, no device init):
Architecture¶
The Python package
aie.utils.hostruntime.hrxruntime
is split into focused modules:
| Module | Role |
|---|---|
discovery |
Locate libhrx on disk (no dlopen); backs aie.utils.has_hrx. |
_bindings |
The C ABI layer: constants, ctypes struct mirrors, and bound hrx_* entry points. |
context |
HRXContext — the process-wide device + dispatch-stream singleton (buffers, executables, chained dispatch). |
tensor |
HRXTensor — a persistent host-mapped, device-visible buffer with explicit flush/invalidate coherence. |
hostruntime |
HRXHostRuntime (uncached) and CachedHRXRuntime (LRU executable cache) — the IRON HostRuntime implementations. |
Importing the package is side-effect-free; libhrx is bound lazily on first
HRXContext creation.
Multi-dispatch chains (run_chain)¶
HRXHostRuntime.run_chain([(handle, args), ...]) records several dispatches into
one HRX command buffer — in order, with an execution + memory barrier between
them — and submits the batch with a single synchronize (the amdxdna HAL lowers
it into one ERT_CMD_CHAIN). Because of the barrier, a later run observes an
earlier run's device writes, so producer→consumer chains work. This is the HRX
analogue of the XRT runlist; there is no equivalent in the XRT Python runtime.
Concurrency and multi-tenancy¶
HRXContext is a per-process singleton (thread-safe lazy creation). Separate
processes — including different users — are fully isolated: each builds its own
context and buffers, and the amdxdna driver isolates each process's hardware
context and device memory. The only shared resource is the finite, system-wide
pool of amdxdna hardware contexts, which can be exhausted under heavy
parallelism (a capacity limit, not a data-safety issue). Within one process the
dispatch stream is not built for concurrent dispatch, so callers must serialize
dispatch on a single context — the same expectation the XRT Python runtime has.
Further reading¶
- HRX runbook — the
self-contained, step-by-step guide for building and running the IRON (Python)
and C++ tests on HRX, including the bundled XRT-free
xclbinutil. - IRON Configuration — all runtime configuration variables.