Host Runtime (aie.utils.hostruntime)¶
Host-side helpers for selecting a device, allocating NPU-accessible tensors, running compiled designs, and sharing common CLI / argument plumbing across programming examples.
Import the public surface from aie.utils.hostruntime (or via the
aie.utils / iron re-exports where noted). The symbols below are rendered
from the Python package under python/utils/hostruntime/ using the same
mkdocstrings path layout as the other Python API pages (utils.*, not the
installed aie.utils.* import name).
Runtime abstractions¶
Abstract runtime types that concrete backends (for example XRT) implement.
HostRuntimeError ¶
Bases: Exception
Error raised when a NPU kernel encounters an error during runtime operations.
KernelHandle ¶
Bases: ABC
Abstract representation that represents a kernel already registered/loaded with a runtime.
KernelResult ¶
Bases: ABC
A wrapper around data produced as the result of running a kernel.
Initialize the KernelResult.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
npu_time
|
int
|
The execution time on the NPU in nanoseconds. |
required |
trace_config
|
TraceConfig | None
|
Configuration for tracing. Defaults to None. |
None
|
Source code in python/utils/hostruntime/hostruntime.py
npu_time
property
¶
Get the NPU execution time.
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
The execution time in nanoseconds. |
trace_config
property
¶
Get the trace configuration.
Returns:
| Type | Description |
|---|---|
TraceConfig | None
|
TraceConfig | None: The trace configuration if available, else None. |
has_trace ¶
Check if trace data is available.
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
True if trace configuration is present, False otherwise. |
is_success
abstractmethod
¶
Check if the kernel execution was successful.
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
True if successful, False otherwise. |
HostRuntime ¶
Bases: ABC
An abstract class for a generic host runtime.
check_device_consistency ¶
Check if the overridden device is loadable on the runtime device.
A 1- or N-column variant of a generation (e.g. NPU1Col1) is loadable on a wider device of the same generation (e.g. a 4-column NPU1), so we accept any override whose arch matches and whose column count is <= the runtime device's column count.
Source code in python/utils/hostruntime/hostruntime.py
cleanup ¶
Release any cached device/runtime resources held by this runtime.
Base implementation is a no-op: a plain runtime holds nothing to release. Caching runtimes override this to free hardware contexts, loaded executables, instruction buffers, etc. Safe to call even if the runtime never ran anything.
Source code in python/utils/hostruntime/hostruntime.py
evict_context ¶
Drop any cached device context associated with xclbin_path.
Recovery hook invoked after the driver rejects a submit against a stale
context (e.g. an XRT IOCTL EINVAL) so the next load rebuilds a fresh
context. Base implementation is a no-op for runtimes that keep no
evictable context cache.
Source code in python/utils/hostruntime/hostruntime.py
load
abstractmethod
¶
load(npu_kernel: NPUKernel, **kwargs) -> KernelHandle
Load an NPU kernel into the runtime.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
npu_kernel
|
NPUKernel
|
The NPU kernel to load. |
required |
**kwargs
|
Additional arguments for loading. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
KernelHandle |
KernelHandle
|
A handle to the loaded kernel. |
Source code in python/utils/hostruntime/hostruntime.py
run
abstractmethod
¶
run(
kernel_handle: KernelHandle,
args,
trace_config: TraceConfig | None = None,
fail_on_error: bool = True,
only_if_loaded=False,
**kwargs
) -> KernelResult
Run a loaded kernel.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kernel_handle
|
KernelHandle
|
The handle to the loaded kernel. |
required |
args
|
Arguments to pass to the kernel. |
required | |
trace_config
|
TraceConfig | None
|
Configuration for tracing. Defaults to None. |
None
|
fail_on_error
|
bool
|
Whether to raise an exception on kernel failure. Defaults to True. |
True
|
only_if_loaded
|
bool
|
If True, only run if already loaded. Defaults to False. |
False
|
**kwargs
|
Additional arguments. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
KernelResult |
KernelResult
|
The result of the kernel execution. |
Source code in python/utils/hostruntime/hostruntime.py
load_and_run ¶
load_and_run(
npu_kernel: NPUKernel, run_args: list, **kwargs
) -> tuple[KernelHandle, KernelResult]
Load and run an NPU kernel.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
npu_kernel
|
NPUKernel
|
The NPU kernel to load and run. |
required |
run_args
|
list
|
Arguments to pass to the kernel. |
required |
**kwargs
|
Additional arguments passed to load. |
{}
|
Returns:
| Type | Description |
|---|---|
tuple[KernelHandle, KernelResult]
|
tuple[KernelHandle, KernelResult]: A tuple containing the kernel handle and the execution result. |
Source code in python/utils/hostruntime/hostruntime.py
device
abstractmethod
¶
Get the device associated with this runtime.
Returns:
| Name | Type | Description |
|---|---|---|
Device |
Device
|
The device object. |
read_insts_binary
classmethod
¶
Read instructions from a binary file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
insts_path
|
Path
|
Path to the binary instruction file. |
required |
Returns:
| Type | Description |
|---|---|
|
np.ndarray: Array of uint32 instructions. |
Source code in python/utils/hostruntime/hostruntime.py
read_insts
classmethod
¶
Read instructions from the given file.
If the file extension is .bin, uses binary read. If the file extension is .txt, uses sequence (text) read.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
insts_path
|
Path
|
Path to the instruction file. |
required |
Returns:
| Type | Description |
|---|---|
|
np.ndarray: Array of instructions. |
Raises:
| Type | Description |
|---|---|
HostRuntimeError
|
If the file extension is not supported. |
Source code in python/utils/hostruntime/hostruntime.py
prepare_args_for_trace
classmethod
¶
Prepare arguments for tracing by appending necessary buffers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
args
|
list[NpuTensor]
|
List of input/output tensors. |
required |
trace_config
|
TraceConfig
|
Trace configuration. |
required |
Returns:
| Type | Description |
|---|---|
list[NpuTensor]
|
list[NpuTensor]: The updated list of tensors with trace buffers appended. |
Source code in python/utils/hostruntime/hostruntime.py
extract_trace_from_args
classmethod
¶
extract_trace_from_args(
args: list[NpuTensor], trace_config: TraceConfig
) -> tuple[ndarray, ndarray | None]
Extract trace and control buffers from the arguments.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
args
|
list[NpuTensor]
|
List of tensors used in execution. |
required |
trace_config
|
TraceConfig
|
Trace configuration. |
required |
Returns:
| Type | Description |
|---|---|
tuple[ndarray, ndarray | None]
|
tuple[np.ndarray, np.ndarray | None]: A tuple containing the trace buffer and optionally the control buffer. |
Source code in python/utils/hostruntime/hostruntime.py
process_trace
classmethod
¶
Process the trace buffer and control buffer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trace_buffer
|
ndarray
|
The trace data buffer. |
required |
ctrl_buffer
|
ndarray
|
The control packet buffer. |
required |
trace_config
|
TraceConfig
|
Trace configuration. |
required |
verbosity
|
int
|
Verbosity level. Defaults to 0. |
0
|
Source code in python/utils/hostruntime/hostruntime.py
verify_results
classmethod
¶
Verify the results of the kernel execution against reference data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
io_args
|
list[NpuTensor]
|
List of input/output tensors. |
required |
refs
|
dict | None
|
Dictionary mapping index to reference numpy array. Defaults to None (empty dict). |
None
|
verbosity
|
int
|
Verbosity level. Defaults to 0. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
int |
Number of errors found. |
Raises:
| Type | Description |
|---|---|
HostRuntimeError
|
If a reference index is out of bounds. |
Source code in python/utils/hostruntime/hostruntime.py
run_test ¶
Run a test for the given NPU kernel.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
npu_kernel
|
NPUKernel
|
The NPU kernel to test. |
required |
io_args
|
list[NpuTensor]
|
List of input/output tensors. |
required |
ref
|
dict
|
Reference data for verification. |
required |
verify
|
bool
|
Whether to verify results. Defaults to True. |
True
|
verbosity
|
int
|
Verbosity level. Defaults to 0. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
0 if successful, 1 otherwise. |
Source code in python/utils/hostruntime/hostruntime.py
Tensor and device utilities¶
Device selection, the NpuTensor tensor type, and numerical helpers used when
comparing host results. NpuTensor was previously called Tensor, which
remains available as an alias.
A tensor is a shape and a dtype over bytes it does not own. The bytes, and the
record of which agent currently holds each range of them, belong to the
Storage below.
Host runtime utilities: device selection, tensor allocation, and numerical helpers.
NpuTensor ¶
Bases: ABC
A host-mapped, device-resident buffer of fixed shape and dtype.
This is a buffer with a residency state machine, not a general array. Its
invariant is host/device coherence: the host and the device each hold a view
of the same storage, and the two are reconciled only at the points this class
defines. Everything else it offers (indexing, filling, the numpy and torch
bridges, :meth:subview) exists to keep that reconciliation correct while
still letting callers treat the buffer as data.
The invariant in full:
- Writes through the declared paths (:meth:
__setitem__, :meth:fill_, and the factories) are reconciled: the factories transfer as they construct, and the in-place writes record the region so the next :meth:tosends it. A write through the rawdataarray does neither, and is the one way to leave host and device disagreeing. - A method that spans regions in different states reconciles per region.
Asking a whole tensor where it lives collapses a mixed extent to one
answer, which is the right answer for :meth:
toand the wrong one to transfer by. - :meth:
tomoves residency and is a no-op when the buffer is already on the target device, so a caller that has written through a declared path never pays for a redundant transfer, and a caller that has bypassed one gets no transfer at all. - Reconciliation is not byte-granular. It acts on whole cache lines, which is
why :meth:
subviewrequires its regions to be granule-aligned.
Subclasses supply the storage and the two transfer primitives; the invariant itself lives here so every backend states it the same way.
Named for the role rather than the mechanism: XRTTensor and HRXTensor
name what implements the buffer, NpuTensor names what it is. Tensor
remains as an alias for existing callers.
Initialize the tensor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shape_or_data
|
tuple or array - like
|
|
required |
dtype
|
dtype
|
Data type of the tensor. Defaults to np.uint32. |
uint32
|
device
|
str
|
Device string identifier (e.g., 'npu', 'cpu'). Defaults to 'npu'. |
'npu'
|
Source code in python/utils/hostruntime/tensor_class.py
storage
property
¶
storage: Storage
The allocation this tensor is a view of.
A backend that still owns its bytes directly is wrapped on first use in a storage whose transport reconciles whole-extent, so every tensor has one whether or not its backend has adopted the split.
device
property
writable
¶
Which agent holds the authoritative copy of this tensor's bytes.
Read from the allocation, so two tensors over the same bytes can never
disagree. A tensor spanning regions in different states reports cpu
while any part of it still needs flushing, since that is the answer that
keeps a caller's reconcile from being skipped.
base
property
¶
The buffer that owns this one's storage, or None if it owns it itself.
Mirrors :attr:numpy.ndarray.base, including collapsing a chain of
views: the base of a view of a view is the buffer that actually owns the
storage, not the intermediate view. The intermediate is still referenced
internally, so the whole chain stays alive for as long as any view of it
does.
storage_offset
property
¶
Where this buffer starts within :attr:base's storage, in bytes.
Zero for a buffer that owns its storage. Accumulated through nesting, so
it is always measured from the owner rather than from the view this one
was carved out of. Compare :meth:torch.Tensor.storage_offset, which is
in elements; this is in bytes because a view may reinterpret the dtype.
data
abstractmethod
property
¶
Subclasses must implement a data property.
Returns:
| Type | Description |
|---|---|
ndarray
|
np.ndarray: The underlying data of the tensor. |
shape
abstractmethod
property
¶
Subclasses must implement a shape property.
Returns:
| Name | Type | Description |
|---|---|---|
tuple |
tuple[int, ...]
|
The shape of the tensor. |
to ¶
Move the tensor to a specified target device.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target_device
|
str
|
The target device. |
required |
Returns:
| Type | Description |
|---|---|
|
The tensor object on the target device. |
Source code in python/utils/hostruntime/tensor_class.py
mutate ¶
Borrow this buffer's bytes for a host write.
Reconciles on entry so partial updates see current contents, records the write on exit, and retires the borrowed array so a reference kept past the block fails loudly instead of writing bytes nobody will flush.
The flush itself is deferred: the region is marked host-written and the next transfer to the device sends every dirty range in one pass, so a caller filling many windows of one buffer pays for one flush, not one per window.
with tensor.mutate() as buf:
buf[:] = values
Source code in python/utils/hostruntime/tensor_class.py
overwrite ¶
Borrow for a write that replaces every byte of this tensor.
The same as :meth:mutate without the reconcile on entry, which nothing
can observe if all of it is about to be replaced. Filling a buffer this
way costs one transfer rather than two.
The caller is promising to write the whole region. Bytes left unwritten
keep whatever the host last had there and are sent to the device with
the rest, so use :meth:mutate for a partial update. This is the one
promise here that cannot be checked; it is still narrower than reaching
for data, which makes the same promise and does not record the write.
Source code in python/utils/hostruntime/tensor_class.py
subview ¶
Return a tensor viewing a sub-region of this tensor's underlying storage.
The returned tensor shares this tensor's buffer (no new allocation, no copy), holds a reference to this tensor so the storage outlives the view, and synchronizes its own slice. It is a plain tensor of the same backend class, not a distinct type.
The region must be aligned to :data:COHERENCE_GRANULE, because host and
device are reconciled a cache line at a time, not a byte at a time. Two
views sharing a line are not independent: synchronizing one acts on the
other's bytes in that line, so a view whose host copy is stale can be
written back over data the device just produced in its neighbor. The
check makes that unrepresentable instead of leaving it to callers to
remember. It is enforced for every backend, including the CPU-only one
that has no coherence concern of its own, so a layout validated against
the test backend stays valid on a device.
A view may end anywhere if it ends where this tensor ends: its last line
is shared with no sibling, so it is no worse than synchronizing the whole
buffer. This also keeps a whole-buffer view (offset=0) legal for a
tensor whose own size is not a multiple of the granule.
Note that alignment bounds the damage but does not make a sync exactly slice-scoped: some driver paths (an imported buffer, or one with no kernel mapping) maintain the whole buffer regardless of the requested range. Correctness must not depend on a sync being narrow, only on views not sharing a coherence granule.
Three ways this departs from numpy and torch, none of them accidental:
Out-of-range and negative arguments are rejected, where numpy slicing
clamps and wraps them. Clamping a region silently hands back a smaller
one than asked for, and a DMA region that is quietly the wrong size is
worse than an error. The method-with-arguments spelling is far enough
from [start:stop] that it should not invite the slicing intuition.
The alignment requirement has no analogue in either library, because neither reconciles anything between two agents.
offset is in bytes, where numpy counts offsets in elements of the
array's own dtype and torch reports storage_offset in elements.
Bytes because that is the unit the thing being carved is measured in: a
buffer has no dtype, the alignment rule below is in bytes, and
:attr:storage_offset reports bytes, so the argument going in and the
value reported back are the same number. shape stays in elements of
the view's dtype, since it describes the tensor rather than the region.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
offset
|
Start of the region, in bytes from the start of this tensor's own region. |
required | |
shape
|
Logical shape of the view. |
required | |
dtype
|
dtype
|
dtype to interpret the region as. Defaults to this tensor's dtype. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
NpuTensor |
A view sharing this tensor's storage. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the region falls outside this tensor's buffer, or is
not aligned to :data: |
Source code in python/utils/hostruntime/tensor_class.py
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 | |
numpy ¶
Return a NumPy view of the tensor data on host memory.
This method ensures that data is first synchronized from the device (e.g., NPU) to the host before returning the array.
Returns:
| Type | Description |
|---|---|
|
np.ndarray: The tensor's data as a NumPy array. |
Note: For NPU tensors, this method causes implicit data synchronization from device to host to ensure the returned array reflects the current device state.
Source code in python/utils/hostruntime/tensor_class.py
to_torch ¶
Return a torch tensor sharing the data in this tensor if possible.
Syncs from device first if the tensor is on the NPU.
Returns:
| Type | Description |
|---|---|
|
torch.Tensor: A torch tensor containing the data. |
Raises:
| Type | Description |
|---|---|
ImportError
|
If torch is not installed. |
Source code in python/utils/hostruntime/tensor_class.py
torch_view ¶
Return a torch tensor sharing this buffer's host memory without syncing from device.
Unlike to_torch(), this does NOT sync from the NPU first. Marks the buffer as CPU-resident so that a subsequent .to("npu") call (or the NPU operator's implicit sync) will push the written data to device. Use this on write paths where the caller is about to overwrite the buffer contents.
Returns:
| Type | Description |
|---|---|
|
torch.Tensor: A zero-copy torch tensor view of the host-side buffer. |
Raises:
| Type | Description |
|---|---|
ImportError
|
If torch is not installed. |
Source code in python/utils/hostruntime/tensor_class.py
from_torch
classmethod
¶
Return a tensor with a copy of the data in the torch_tensor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
torch_tensor
|
Tensor
|
The source torch tensor. |
required |
device
|
str
|
The target device. Defaults to None. |
None
|
**kwargs
|
Additional arguments for tensor creation. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
NpuTensor |
A new tensor containing the data from the torch tensor. |
Raises:
| Type | Description |
|---|---|
ImportError
|
If torch is not installed. |
Source code in python/utils/hostruntime/tensor_class.py
fill_ ¶
Fill the tensor with a scalar value (in-place operation).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
The scalar value to fill the tensor with. |
required |
Note: this replaces every byte, so it skips the reconcile a partial write would need, and records the write rather than flushing it. The next transfer to the device sends it.
Source code in python/utils/hostruntime/tensor_class.py
numel ¶
Calculate the number of elements in the tensor.
Returns:
| Name | Type | Description |
|---|---|---|
int |
The total number of elements in the tensor. |
ones
classmethod
¶
Return a tensor filled with ones, with shape defined by size.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*size
|
int...
|
Shape of the tensor, passed as separate ints or a single tuple/list. |
()
|
out
|
NpuTensor
|
Optional output tensor to write into. |
None
|
dtype
|
dtype
|
Desired dtype. Defaults to np.float32. |
None
|
device
|
str
|
Target device. Defaults to 'npu'. |
None
|
**kwargs
|
Additional keyword args. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
NpuTensor |
A one-filled tensor. |
Source code in python/utils/hostruntime/tensor_class.py
zeros
classmethod
¶
Return a tensor filled with zeros, with shape defined by size.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*size
|
int...
|
Shape of the tensor, passed as separate ints or a single tuple/list. |
()
|
out
|
NpuTensor
|
Optional output tensor to write into. |
None
|
dtype
|
dtype
|
Desired dtype. Defaults to np.float32. |
None
|
device
|
str
|
Target device. Defaults to 'npu'. |
None
|
**kwargs
|
Additional keyword args. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
NpuTensor |
A zero-filled tensor. |
Source code in python/utils/hostruntime/tensor_class.py
full
classmethod
¶
Return a tensor of shape size filled with fill_value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
size
|
int or tuple/list of int
|
Shape of the returned tensor. |
required |
fill_value
|
scalar
|
Value to fill the tensor with. |
required |
out
|
NpuTensor
|
Optional output tensor to write into. |
None
|
dtype
|
dtype
|
Desired dtype. Defaults to np.float32. |
None
|
device
|
str
|
Target device. Defaults to 'npu'. |
None
|
**kwargs
|
Additional keyword args. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
NpuTensor |
A tensor filled with |
Source code in python/utils/hostruntime/tensor_class.py
randint
classmethod
¶
Return a tensor filled with random integers uniformly sampled from [low, high).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
low
|
int
|
Lowest integer to be drawn (inclusive). |
required |
high
|
int
|
One above the highest integer to be drawn (exclusive). |
required |
size
|
tuple
|
Shape of the returned tensor. |
required |
out
|
NpuTensor
|
Optional tensor to write the result into. |
None
|
dtype
|
dtype
|
Data type. Defaults to np.int64. |
None
|
device
|
str
|
Target device. Defaults to 'npu'. |
None
|
generator
|
Generator
|
Source RNG for reproducibility. If None, uses np.random module-level state. |
None
|
**kwargs
|
Additional arguments passed to the constructor. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
NpuTensor |
A tensor with random integers. |
Source code in python/utils/hostruntime/tensor_class.py
rand
classmethod
¶
Return a tensor filled with random numbers from a uniform distribution on [0, 1).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*size
|
int...
|
Variable number of integers or a single tuple defining the shape. |
()
|
out
|
NpuTensor
|
Output tensor to write into. |
None
|
dtype
|
dtype
|
Desired data type. Defaults to np.float32. |
None
|
device
|
str
|
Target device. Defaults to 'npu'. |
None
|
generator
|
Generator
|
Source RNG for reproducibility. If None, uses np.random module-level state. |
None
|
**kwargs
|
Additional arguments passed to constructor. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
NpuTensor |
A tensor with random values in [0, 1). |
Source code in python/utils/hostruntime/tensor_class.py
arange
classmethod
¶
Return a tensor with values from the interval [start, end) with spacing step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
number
|
Start of interval. Defaults to 0. |
0
|
end
|
number
|
End of interval (exclusive). Required if only one argument is given. |
None
|
step
|
number
|
Gap between elements. Defaults to 1. |
1
|
shape
|
tuple
|
If given, reshape the 1-D sequence to this shape.
|
None
|
dtype
|
dtype
|
Desired output data type. Inferred if not provided. |
None
|
out
|
NpuTensor
|
Optional tensor to write output to (must match shape and dtype). |
None
|
device
|
str
|
Target device. Defaults to 'npu'. |
None
|
**kwargs
|
Additional keyword arguments forwarded to the underlying tensor constructor. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
NpuTensor |
A tensor containing the sequence (1-D by default, or |
Source code in python/utils/hostruntime/tensor_class.py
zeros_like
classmethod
¶
Create a new tensor with the same shape as other, filled with zeros.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
NpuTensor
|
The reference tensor to copy shape from. |
required |
dtype
|
dtype
|
Data type of the new tensor. Defaults to other's dtype. |
None
|
device
|
str
|
Target device. Defaults to other's device. |
None
|
**kwargs
|
Additional keyword arguments forwarded to the constructor. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
NpuTensor |
A new zero-filled tensor with the same shape. |
Source code in python/utils/hostruntime/tensor_class.py
set_current_device ¶
Set (or clear) the current device.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
device
|
Device | None
|
The device to set as current. Passing |
required |
Source code in python/utils/hostruntime/__init__.py
bfloat16_safe_allclose ¶
Check if two arrays are element-wise equal within a tolerance, handling bfloat16 safely.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dtype
|
The data type of the arrays. |
required | |
arr1
|
First input array. |
required | |
arr2
|
Second input array. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
True if the arrays are equal within tolerance, False otherwise. |
Source code in python/utils/hostruntime/__init__.py
The host tensor: a shaped, typed view over a coherence-managed allocation.
The allocation itself, its residency bookkeeping, and the torch bridge live in
:mod:buffer, :mod:coherence and :mod:torch_interop. Each is re-exported
here, so from .tensor_class import Storage and friends keep resolving.
NpuTensor ¶
Bases: ABC
A host-mapped, device-resident buffer of fixed shape and dtype.
This is a buffer with a residency state machine, not a general array. Its
invariant is host/device coherence: the host and the device each hold a view
of the same storage, and the two are reconciled only at the points this class
defines. Everything else it offers (indexing, filling, the numpy and torch
bridges, :meth:subview) exists to keep that reconciliation correct while
still letting callers treat the buffer as data.
The invariant in full:
- Writes through the declared paths (:meth:
__setitem__, :meth:fill_, and the factories) are reconciled: the factories transfer as they construct, and the in-place writes record the region so the next :meth:tosends it. A write through the rawdataarray does neither, and is the one way to leave host and device disagreeing. - A method that spans regions in different states reconciles per region.
Asking a whole tensor where it lives collapses a mixed extent to one
answer, which is the right answer for :meth:
toand the wrong one to transfer by. - :meth:
tomoves residency and is a no-op when the buffer is already on the target device, so a caller that has written through a declared path never pays for a redundant transfer, and a caller that has bypassed one gets no transfer at all. - Reconciliation is not byte-granular. It acts on whole cache lines, which is
why :meth:
subviewrequires its regions to be granule-aligned.
Subclasses supply the storage and the two transfer primitives; the invariant itself lives here so every backend states it the same way.
Named for the role rather than the mechanism: XRTTensor and HRXTensor
name what implements the buffer, NpuTensor names what it is. Tensor
remains as an alias for existing callers.
Initialize the tensor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shape_or_data
|
tuple or array - like
|
|
required |
dtype
|
dtype
|
Data type of the tensor. Defaults to np.uint32. |
uint32
|
device
|
str
|
Device string identifier (e.g., 'npu', 'cpu'). Defaults to 'npu'. |
'npu'
|
Source code in python/utils/hostruntime/tensor_class.py
storage
property
¶
storage: Storage
The allocation this tensor is a view of.
A backend that still owns its bytes directly is wrapped on first use in a storage whose transport reconciles whole-extent, so every tensor has one whether or not its backend has adopted the split.
device
property
writable
¶
Which agent holds the authoritative copy of this tensor's bytes.
Read from the allocation, so two tensors over the same bytes can never
disagree. A tensor spanning regions in different states reports cpu
while any part of it still needs flushing, since that is the answer that
keeps a caller's reconcile from being skipped.
base
property
¶
The buffer that owns this one's storage, or None if it owns it itself.
Mirrors :attr:numpy.ndarray.base, including collapsing a chain of
views: the base of a view of a view is the buffer that actually owns the
storage, not the intermediate view. The intermediate is still referenced
internally, so the whole chain stays alive for as long as any view of it
does.
storage_offset
property
¶
Where this buffer starts within :attr:base's storage, in bytes.
Zero for a buffer that owns its storage. Accumulated through nesting, so
it is always measured from the owner rather than from the view this one
was carved out of. Compare :meth:torch.Tensor.storage_offset, which is
in elements; this is in bytes because a view may reinterpret the dtype.
data
abstractmethod
property
¶
Subclasses must implement a data property.
Returns:
| Type | Description |
|---|---|
ndarray
|
np.ndarray: The underlying data of the tensor. |
shape
abstractmethod
property
¶
Subclasses must implement a shape property.
Returns:
| Name | Type | Description |
|---|---|---|
tuple |
tuple[int, ...]
|
The shape of the tensor. |
to ¶
Move the tensor to a specified target device.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target_device
|
str
|
The target device. |
required |
Returns:
| Type | Description |
|---|---|
|
The tensor object on the target device. |
Source code in python/utils/hostruntime/tensor_class.py
mutate ¶
Borrow this buffer's bytes for a host write.
Reconciles on entry so partial updates see current contents, records the write on exit, and retires the borrowed array so a reference kept past the block fails loudly instead of writing bytes nobody will flush.
The flush itself is deferred: the region is marked host-written and the next transfer to the device sends every dirty range in one pass, so a caller filling many windows of one buffer pays for one flush, not one per window.
with tensor.mutate() as buf:
buf[:] = values
Source code in python/utils/hostruntime/tensor_class.py
overwrite ¶
Borrow for a write that replaces every byte of this tensor.
The same as :meth:mutate without the reconcile on entry, which nothing
can observe if all of it is about to be replaced. Filling a buffer this
way costs one transfer rather than two.
The caller is promising to write the whole region. Bytes left unwritten
keep whatever the host last had there and are sent to the device with
the rest, so use :meth:mutate for a partial update. This is the one
promise here that cannot be checked; it is still narrower than reaching
for data, which makes the same promise and does not record the write.
Source code in python/utils/hostruntime/tensor_class.py
subview ¶
Return a tensor viewing a sub-region of this tensor's underlying storage.
The returned tensor shares this tensor's buffer (no new allocation, no copy), holds a reference to this tensor so the storage outlives the view, and synchronizes its own slice. It is a plain tensor of the same backend class, not a distinct type.
The region must be aligned to :data:COHERENCE_GRANULE, because host and
device are reconciled a cache line at a time, not a byte at a time. Two
views sharing a line are not independent: synchronizing one acts on the
other's bytes in that line, so a view whose host copy is stale can be
written back over data the device just produced in its neighbor. The
check makes that unrepresentable instead of leaving it to callers to
remember. It is enforced for every backend, including the CPU-only one
that has no coherence concern of its own, so a layout validated against
the test backend stays valid on a device.
A view may end anywhere if it ends where this tensor ends: its last line
is shared with no sibling, so it is no worse than synchronizing the whole
buffer. This also keeps a whole-buffer view (offset=0) legal for a
tensor whose own size is not a multiple of the granule.
Note that alignment bounds the damage but does not make a sync exactly slice-scoped: some driver paths (an imported buffer, or one with no kernel mapping) maintain the whole buffer regardless of the requested range. Correctness must not depend on a sync being narrow, only on views not sharing a coherence granule.
Three ways this departs from numpy and torch, none of them accidental:
Out-of-range and negative arguments are rejected, where numpy slicing
clamps and wraps them. Clamping a region silently hands back a smaller
one than asked for, and a DMA region that is quietly the wrong size is
worse than an error. The method-with-arguments spelling is far enough
from [start:stop] that it should not invite the slicing intuition.
The alignment requirement has no analogue in either library, because neither reconciles anything between two agents.
offset is in bytes, where numpy counts offsets in elements of the
array's own dtype and torch reports storage_offset in elements.
Bytes because that is the unit the thing being carved is measured in: a
buffer has no dtype, the alignment rule below is in bytes, and
:attr:storage_offset reports bytes, so the argument going in and the
value reported back are the same number. shape stays in elements of
the view's dtype, since it describes the tensor rather than the region.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
offset
|
Start of the region, in bytes from the start of this tensor's own region. |
required | |
shape
|
Logical shape of the view. |
required | |
dtype
|
dtype
|
dtype to interpret the region as. Defaults to this tensor's dtype. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
NpuTensor |
A view sharing this tensor's storage. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the region falls outside this tensor's buffer, or is
not aligned to :data: |
Source code in python/utils/hostruntime/tensor_class.py
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 | |
numpy ¶
Return a NumPy view of the tensor data on host memory.
This method ensures that data is first synchronized from the device (e.g., NPU) to the host before returning the array.
Returns:
| Type | Description |
|---|---|
|
np.ndarray: The tensor's data as a NumPy array. |
Note: For NPU tensors, this method causes implicit data synchronization from device to host to ensure the returned array reflects the current device state.
Source code in python/utils/hostruntime/tensor_class.py
to_torch ¶
Return a torch tensor sharing the data in this tensor if possible.
Syncs from device first if the tensor is on the NPU.
Returns:
| Type | Description |
|---|---|
|
torch.Tensor: A torch tensor containing the data. |
Raises:
| Type | Description |
|---|---|
ImportError
|
If torch is not installed. |
Source code in python/utils/hostruntime/tensor_class.py
torch_view ¶
Return a torch tensor sharing this buffer's host memory without syncing from device.
Unlike to_torch(), this does NOT sync from the NPU first. Marks the buffer as CPU-resident so that a subsequent .to("npu") call (or the NPU operator's implicit sync) will push the written data to device. Use this on write paths where the caller is about to overwrite the buffer contents.
Returns:
| Type | Description |
|---|---|
|
torch.Tensor: A zero-copy torch tensor view of the host-side buffer. |
Raises:
| Type | Description |
|---|---|
ImportError
|
If torch is not installed. |
Source code in python/utils/hostruntime/tensor_class.py
from_torch
classmethod
¶
Return a tensor with a copy of the data in the torch_tensor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
torch_tensor
|
Tensor
|
The source torch tensor. |
required |
device
|
str
|
The target device. Defaults to None. |
None
|
**kwargs
|
Additional arguments for tensor creation. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
NpuTensor |
A new tensor containing the data from the torch tensor. |
Raises:
| Type | Description |
|---|---|
ImportError
|
If torch is not installed. |
Source code in python/utils/hostruntime/tensor_class.py
fill_ ¶
Fill the tensor with a scalar value (in-place operation).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
The scalar value to fill the tensor with. |
required |
Note: this replaces every byte, so it skips the reconcile a partial write would need, and records the write rather than flushing it. The next transfer to the device sends it.
Source code in python/utils/hostruntime/tensor_class.py
numel ¶
Calculate the number of elements in the tensor.
Returns:
| Name | Type | Description |
|---|---|---|
int |
The total number of elements in the tensor. |
ones
classmethod
¶
Return a tensor filled with ones, with shape defined by size.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*size
|
int...
|
Shape of the tensor, passed as separate ints or a single tuple/list. |
()
|
out
|
NpuTensor
|
Optional output tensor to write into. |
None
|
dtype
|
dtype
|
Desired dtype. Defaults to np.float32. |
None
|
device
|
str
|
Target device. Defaults to 'npu'. |
None
|
**kwargs
|
Additional keyword args. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
NpuTensor |
A one-filled tensor. |
Source code in python/utils/hostruntime/tensor_class.py
zeros
classmethod
¶
Return a tensor filled with zeros, with shape defined by size.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*size
|
int...
|
Shape of the tensor, passed as separate ints or a single tuple/list. |
()
|
out
|
NpuTensor
|
Optional output tensor to write into. |
None
|
dtype
|
dtype
|
Desired dtype. Defaults to np.float32. |
None
|
device
|
str
|
Target device. Defaults to 'npu'. |
None
|
**kwargs
|
Additional keyword args. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
NpuTensor |
A zero-filled tensor. |
Source code in python/utils/hostruntime/tensor_class.py
full
classmethod
¶
Return a tensor of shape size filled with fill_value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
size
|
int or tuple/list of int
|
Shape of the returned tensor. |
required |
fill_value
|
scalar
|
Value to fill the tensor with. |
required |
out
|
NpuTensor
|
Optional output tensor to write into. |
None
|
dtype
|
dtype
|
Desired dtype. Defaults to np.float32. |
None
|
device
|
str
|
Target device. Defaults to 'npu'. |
None
|
**kwargs
|
Additional keyword args. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
NpuTensor |
A tensor filled with |
Source code in python/utils/hostruntime/tensor_class.py
randint
classmethod
¶
Return a tensor filled with random integers uniformly sampled from [low, high).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
low
|
int
|
Lowest integer to be drawn (inclusive). |
required |
high
|
int
|
One above the highest integer to be drawn (exclusive). |
required |
size
|
tuple
|
Shape of the returned tensor. |
required |
out
|
NpuTensor
|
Optional tensor to write the result into. |
None
|
dtype
|
dtype
|
Data type. Defaults to np.int64. |
None
|
device
|
str
|
Target device. Defaults to 'npu'. |
None
|
generator
|
Generator
|
Source RNG for reproducibility. If None, uses np.random module-level state. |
None
|
**kwargs
|
Additional arguments passed to the constructor. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
NpuTensor |
A tensor with random integers. |
Source code in python/utils/hostruntime/tensor_class.py
rand
classmethod
¶
Return a tensor filled with random numbers from a uniform distribution on [0, 1).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*size
|
int...
|
Variable number of integers or a single tuple defining the shape. |
()
|
out
|
NpuTensor
|
Output tensor to write into. |
None
|
dtype
|
dtype
|
Desired data type. Defaults to np.float32. |
None
|
device
|
str
|
Target device. Defaults to 'npu'. |
None
|
generator
|
Generator
|
Source RNG for reproducibility. If None, uses np.random module-level state. |
None
|
**kwargs
|
Additional arguments passed to constructor. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
NpuTensor |
A tensor with random values in [0, 1). |
Source code in python/utils/hostruntime/tensor_class.py
arange
classmethod
¶
Return a tensor with values from the interval [start, end) with spacing step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
number
|
Start of interval. Defaults to 0. |
0
|
end
|
number
|
End of interval (exclusive). Required if only one argument is given. |
None
|
step
|
number
|
Gap between elements. Defaults to 1. |
1
|
shape
|
tuple
|
If given, reshape the 1-D sequence to this shape.
|
None
|
dtype
|
dtype
|
Desired output data type. Inferred if not provided. |
None
|
out
|
NpuTensor
|
Optional tensor to write output to (must match shape and dtype). |
None
|
device
|
str
|
Target device. Defaults to 'npu'. |
None
|
**kwargs
|
Additional keyword arguments forwarded to the underlying tensor constructor. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
NpuTensor |
A tensor containing the sequence (1-D by default, or |
Source code in python/utils/hostruntime/tensor_class.py
zeros_like
classmethod
¶
Create a new tensor with the same shape as other, filled with zeros.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
NpuTensor
|
The reference tensor to copy shape from. |
required |
dtype
|
dtype
|
Data type of the new tensor. Defaults to other's dtype. |
None
|
device
|
str
|
Target device. Defaults to other's device. |
None
|
**kwargs
|
Additional keyword arguments forwarded to the constructor. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
NpuTensor |
A new zero-filled tensor with the same shape. |
Source code in python/utils/hostruntime/tensor_class.py
Allocations and coherence¶
Storage is one allocation plus the coherence of the memory in it: which byte
ranges the host has written and which the device has. Many tensors may name one
storage, which is why the state lives here rather than on any of them.
It is a single concrete class, not a hierarchy. What differs between backends is
only where the host's bytes come from and what reconciling a range does, so those
are supplied as a Transport. A transport that cannot honour a range says so in
its name rather than accepting the arguments and ignoring them.
This is the split torch draws between UntypedStorage and Tensor, and is where
NpuTensor.storage_offset comes from.
An allocation, and how a backend reaches and reconciles the bytes in it.
The allocation is one class. What differs between backends is not the allocation
but the two things layered under it: where the host's bytes come from, and what
reconciling a range actually does. Those are the :class:Transport.
Storage ¶
Storage(transport: Transport, nbytes, device, granule=None)
One allocation, and the coherence of the memory in it.
Storage owns bytes and the record of which agent holds each range of them.
It has no shape and no dtype: those are interpretations, and interpretations
are what :class:NpuTensor is for. Many tensors may name one storage, which
is why the coherence state lives here. Kept per tensor, two names for the
same bytes could disagree and nothing would reconcile them.
This is the split torch draws between UntypedStorage and Tensor, and
is where storage_offset comes from.
Not subclassed. A backend supplies a :class:Transport, so the reconcile
mechanism is data this class holds rather than an identity a subclass
carries. That is the same argument made one level up about coherence
belonging to the memory rather than to whichever tensor names it, and it is
what stops a backend quietly redefining what a range means.
Source code in python/utils/hostruntime/buffer.py
Transport ¶
Bases: ABC
How one allocation's bytes are reached, and reconciled between agents.
Everything that varies between backends lives here, and it is only ever these three things: where the host's bytes come from, what moving a range in either direction does, and whether a region has a handle a runtime can bind. A backend is a transport, not a kind of allocation.
Ranges are part of the contract rather than a hint. A transport that cannot
honour them says so in its name (see :class:WholeExtentTransport) instead
of taking the arguments and ignoring them, which is a promise the caller has
no way to check, and is the reason this is a strategy rather than a subclass
of the allocation.
host_bytes
abstractmethod
property
¶
The allocation as a flat uint8 array the host can address.
to_device
abstractmethod
¶
from_device
abstractmethod
¶
handle ¶
Return a handle a runtime can bind for this region, if the backend has one.
Returning None is a legitimate answer, not a stub: a design where the host writes at offsets into a whole allocation and the kernel addresses the layout itself never needs a per-region handle at all.
Source code in python/utils/hostruntime/buffer.py
HostOnlyTransport ¶
Bases: Transport
Bytes the host allocates and no other agent touches.
Reconciliation is a no-op because there is only one agent, which is the degenerate case of this contract rather than a different one.
Source code in python/utils/hostruntime/buffer.py
WholeExtentTransport ¶
Bases: Transport
For a backend whose transfer methods do not take a range.
Reconciles the whole allocation whatever range it is handed, which is what those backends did before storage was split out of the tensor. The name is the point: over-reconciling is safe, so the cost is wider cache maintenance than was asked for, and per-region coherence is still tracked above it, but a reader can see which it is without opening the method.
A backend that can reconcile by range wants its own transport instead. HRX
is the standing example, since hrx_buffer_flush_range already takes an
offset and a size and it is the tensor layer above that discards them.
Source code in python/utils/hostruntime/buffer.py
Shared CLI/argument helpers¶
Reusable argparse flag groups and the standard design CLI dispatcher used by
the programming examples.
Reusable argparse flag groups shared by the programming examples.
Almost every basic/ design repeats the same handful of CLI flags:
-d/--dev (device selector), --xclbin-path/--insts-path
(compile-only output paths), optionally --elf-path (xrt::elf
testbench) and --emit-mlir (aiecc / vck5000 path), and the
benchmark/trace pair -w/--warmup / -i/--iters / -t/--trace_size.
The helpers in this module mutate an existing argparse.ArgumentParser
(so each design can keep its own design-specific flags and prog).
add_compile_args ¶
add_compile_args(
parser: ArgumentParser,
*,
with_dev: bool = True,
dev_choices: tuple[str, ...] = DEFAULT_DEV_CHOICES,
default_dev: str | None = None,
short_dev: str | None = "-d",
with_elf: bool = False,
with_full_elf: bool = False,
with_pdi: bool = False,
with_emit_mlir: bool = False
) -> None
Add the standard compile-mode flags.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parser
|
ArgumentParser
|
Parser to mutate. |
required |
with_dev
|
bool
|
If True (default), add |
True
|
dev_choices
|
tuple[str, ...]
|
Allowed device-name strings (default
|
DEFAULT_DEV_CHOICES
|
default_dev
|
str | None
|
Fixed target used when |
None
|
short_dev
|
str | None
|
Short-option for |
'-d'
|
with_elf
|
bool
|
When True, also add |
False
|
with_full_elf
|
bool
|
When True, also add |
False
|
with_pdi
|
bool
|
When True, also add |
False
|
with_emit_mlir
|
bool
|
When True, also add |
False
|
Source code in python/utils/hostruntime/argparse.py
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | |
add_benchmark_args ¶
add_benchmark_args(
parser: ArgumentParser,
*,
default_warmup: int = 2,
default_iters: int = 5
) -> None
Add the standard benchmark flags: -w/--warmup and -i/--iters.
Source code in python/utils/hostruntime/argparse.py
add_trace_arg ¶
Add the standard --trace_size flag.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parser
|
ArgumentParser
|
Parser to mutate. |
required |
with_short
|
bool
|
When True (default), exposes |
True
|
default
|
int
|
Default trace size in bytes ( |
0
|
Source code in python/utils/hostruntime/argparse.py
add_runtime_args ¶
add_runtime_args(
parser: ArgumentParser,
*,
with_io_sizes: bool = False,
with_benchmark: bool = False
) -> None
Add the standard runtime / test-harness flags.
Pairs with :func:add_compile_args: add_compile_args covers the
write-side flags (--xclbin-path, --insts-path) used by JIT
designs, while this helper covers the read-side flags (--xclbin,
--instr) used by test.py-style host harnesses that load a
pre-compiled xclbin and run it on the NPU.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parser
|
ArgumentParser
|
Parser to mutate. |
required |
with_io_sizes
|
bool
|
When True, adds |
False
|
with_benchmark
|
bool
|
When True, also calls :func: |
False
|
Adds (always): --xclbin, --instr, -k/--kernel,
-v/--verbosity, --verify/--no-verify, --trace-file,
--ddr-id, --enable-ctrl-pkts; and via :func:add_trace_arg,
-t/--trace_size.
Source code in python/utils/hostruntime/argparse.py
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 | |
device_from_args ¶
Resolve a parsed-argparse namespace to a :class:aie.iron.device.Device.
Collapses the boilerplate variants the example suite used to repeat across ~30 sites::
from_name(args.dev, n_cols=None) # "use all cols"
from_name(args.dev, n_cols=1) # "single col"
into one helper with an explicit n_cols parameter.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
args
|
An |
required | |
dev_attr
|
str
|
Name of the device-string attribute on |
'dev'
|
n_cols
|
'int | None | str'
|
Column-count selector. |
'auto'
|
Returns:
| Type | Description |
|---|---|
|
Device | None: The selected device, or |
|
|
device selection to the runtime. |
Source code in python/utils/hostruntime/argparse.py
run_design_cli — standard 3-mode dispatcher for IRON design CLIs.
Almost every basic/ design's main() is the same skeleton:
def main():
opts = _make_argparser().parse_args()
# optional: _validate(opts)
if opts.emit_mlir:
print(design.specialize(**_compile_kwargs(opts)).as_mlir()); return
if opts.xclbin_path:
_compile_only(opts); return
_run_and_verify(opts)
…where _compile_only always does the same --insts-path check +
device binding + design.specialize(**kw).compile(
xclbin_path=opts.xclbin_path, inst_path=opts.insts_path
[, elf_path=opts.elf_path][, pdi_path=opts.pdi_path]).
This module wraps that skeleton so each design just declares the two
pieces it actually owns (compile kwargs, the verify body) and lets the
dispatcher do the branching + the boilerplate around it. An optional
emit_mlir= callback covers the rare design whose generator needs
real iron.tensor instances at MLIR-gen time.
run_design_cli ¶
run_design_cli(
design,
opts,
*,
compile_kwargs: (
Mapping[str, Any]
| Callable[[Any], Mapping[str, Any]]
),
run_and_verify: Callable[[Any], None] | None = None,
device: _DeviceArg | None = None,
emit_mlir: Callable[[Any], None] | None = None,
validate: Callable[[Any], None] | None = None
) -> None
Dispatch the standard 3-mode CLI for basic/ designs.
The standard branch tree (in order):
- Bind an explicit
--devtarget or concretedeviceargument, or detect the attached runtime device for run and local compile-only modes. - If
validateis given, callvalidate(opts). -
If
opts.emit_mliris True, then:- If an
emit_mlircallback was supplied, callemit_mlir(opts). - Otherwise print
design.specialize(**compile_kwargs).as_mlir()— the right answer for almost every design (no tensor args needed when shapes come fromCompileTime[T]params).
Then return.
- If an
-
If
opts.xclbin_pathoropts.full_elf_pathis set (compile-only):- For
full_elf_path: calldesign.specialize(**compile_kwargs) .compile(full_elf_path=opts.full_elf_path)— a single self-contained ELF, no xclbin/insts. - Otherwise refuse if
opts.insts_pathis unset (sys.exitwith the standard message), then calldesign.specialize(**compile_kwargs).compile( xclbin_path=opts.xclbin_path, inst_path=opts.insts_path, [elf_path=opts.elf_path]).
- For
-
Otherwise, call
run_and_verify(opts).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
design
|
The |
required | |
opts
|
Parsed |
required | |
compile_kwargs
|
Mapping[str, Any] | Callable[[Any], Mapping[str, Any]]
|
Either a dict OR a callable that takes |
required |
run_and_verify
|
Callable[[Any], None] | None
|
Callable invoked in the default (NPU
run + numpy verify) branch. Takes |
None
|
device
|
_DeviceArg | None
|
Optional iron |
None
|
emit_mlir
|
Callable[[Any], None] | None
|
Optional callable for the |
None
|
validate
|
Callable[[Any], None] | None
|
Optional callable invoked after target selection — e.g. for shape / arg consistency checks that should fire in all modes. |
None
|
Source code in python/utils/hostruntime/cli.py
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 | |
XRT runtime implementation¶
Concrete XRT-backed runtime, tensor, and scratchpad types. These modules import
pyxrt, so they are only importable in environments where XRT / PyXRT is
installed. MkDocs CI does not install XRT, so these symbols are summarized here
(same approach as the non-importable JIT helpers on the IRON page) with links to
source. On a machine with PyXRT available they can also be rendered with
mkdocstrings, for example:
| Symbol | Module | Summary |
|---|---|---|
XRTKernelHandle |
xrtruntime.hostruntime |
Handle for a loaded XRT kernel. |
XRTKernelResult |
xrtruntime.hostruntime |
Result wrapper for a PyXRT kernel run. |
XRTHostRuntime |
xrtruntime.hostruntime |
Singleton manager for AIE XRT resources. |
CachedXRTKernelHandle |
xrtruntime.hostruntime |
Cached handle for a loaded XRT kernel. |
CachedXRTRuntime |
xrtruntime.hostruntime |
Cached XRTHostRuntime that reuses contexts for the same xclbin. |
XRTTensor |
xrtruntime.tensor |
Tensor backed by NPU/CPU-accessible memory managed with PyXRT. |
XrtTransport |
xrtruntime.tensor |
Transport for an XRT allocation; reconciles a range through a derived sub-buffer. |
ParameterScratchpad |
xrtruntime.parameter_scratchpad |
Write named runtime parameters to the NPU scratchpad buffer. |