How to find and check a device¶
This guide shows you how to get from “there is a card in the machine” to a
validated DauDevice handle, and how to read the failure when you do not get
one.
Discovery is strict on purpose. A DAU device is an XDMA endpoint whose register window reports the DAU magic word and decodes a capability advertisement. Anything else is skipped, or raises a named error when you asked for it by path.
Discover every device on the host¶
from dau_driver import discover_devices
devices = discover_devices()
for device in devices:
print(device.name, device.backend, device.capabilities.platform_id)
On Linux this scans /dev for xdma*_user character devices, pairing each with
its xdma*_h2c_0 and xdma*_c2h_0 channels. On macOS, when the Linux scan finds
nothing, it falls back to the DriverKit transport over IOKit.
Point it somewhere else if your devnodes are not under /dev:
devices = discover_devices("/some/other/dev")
An endpoint whose BAR reads all ones, or whose magic word is not DAU’s, is skipped rather than returned: broad discovery should not fail because one card in the box is running someone else’s bitstream.
Identify one device by path¶
When you know which node you want, skip the scan:
from dau_driver import identify_device
device = identify_device("/dev/xdma0_user")
This one raises: you named this device, so a bad answer is an error rather than an omission.
Exception |
Meaning |
|---|---|
|
The magic word read all ones. The endpoint or its AXI-lite BAR is not responding. |
|
The window responded, but with something other than the DAU magic word. |
|
A register read failed after the window was located: a short read, or the node could not be opened. |
A path that does not exist reads back as zero rather than the magic word, so it
surfaces as WrongBitstreamError, not as a missing-file error.
Pass h2c_path= and c2h_path= if the channels are not the conventional
siblings of the user node.
The register window is located during identification: the shell base is probed first, then the stream-job contract window. The magic probe retries a few times, because the first AXI-lite reads after a PCIe rescan can return stale data before the link settles, and a single-shot probe would misread a healthy shell as the wrong bitstream.
Check the register path before you trust it¶
A dead AXI-lite path returns 0xFFFFFFFF, which looks like a valid number. Check for it explicitly:
device.check_bar_health()
Raises UnhealthyBarError if MAGIC or STREAM_PROTOCOL_VERSION reads all
ones. Call it before a sequence you care about and again afterwards, because a
successful DMA that leaves the BAR dead is something to know about at once.
To check other offsets, pass them:
from dau_core.registers import RegisterOffset
device.check_bar_health(offsets=(RegisterOffset.MAGIC, RegisterOffset.STATUS))
Read what the device advertises¶
snapshot = device.read_register_block_snapshot()
print(snapshot.register_map_version, snapshot.platform_id, hex(snapshot.build_id))
print(device.read_status())
print(device.read_counters())
read_register_block_snapshot() reads the whole identity block in one pass:
versions, platform id, shell version, build id, status, DMA constraints, the
operator bitmap, and the counters. The composed-capability words (lane count,
host opcode bitmap, sort capacity) are only read on register map 0.2 and above,
because older shells do not decode those offsets.
device.capabilities.operators lists what the device executes.
device.capabilities.host_operators lists protocol-level opcodes the host
derives from hardware results, such as AVERAGE from SUM and COUNT. Those must
never be submitted to the device.
Read the concrete capability contract¶
The register bitmap is a coarse advertisement. A design’s shell-build manifest holds the exact composed contract, per-tile opcodes and input types, with no bitmap-times-types expansion:
from dau_driver.capability_decode import contract_from_manifest_metadata, operators_from_contract
contract = contract_from_manifest_metadata(manifest.metadata)
hardware_operators, host_operators = operators_from_contract(contract)
Returns None when the manifest carries no capability_contract key.
Diagnose a macOS DriverKit path¶
The macOS transport has more ways to fail than “no device”, so it ships a probe that reports the failing stage:
dau-xdma-macos-probe --verbose
macos-xdma status=no-service devices=0 message=No macOS XDMA DriverKit service found for com.dau-dev.xdma...
|
What to check |
|---|---|
|
Devices were identified; nothing to fix. |
|
No IOKit DriverKit service matched. Is the PCI endpoint visible, and is the |
|
The service matched but |
|
The user client opened, but no device passed identification. |
|
BAR scanning did not find the DAU magic word. |
|
BAR reads returned all ones; the endpoint or AXI-lite BAR is not responding. |
|
A register read failed outright. |
Add --service-name (repeatable) to probe a service name other than the
default.
Check whether the native extension is loaded¶
from dau_driver import native_info
print(native_info())
NativeInfo(backend='nanobind', abi_version=1, package_version='0.1.0', extension_available=True)
backend='python' with extension_available=False means the compiled extension
is not present. Everything still works: the extension only reports its own
backend and ABI version today, and every path runs in Python either way.
Next¶
Move data to and from a device: DMA and the stream codec.
Device and discovery reference: every field and signature.
The transport boundary: why discovery is strict.