DetessCast
Experimental C++20 API, package version 0.1.0. Link SimaKernels::a65_detesscast.
Shared requests and metadata admission are available through
simaai/kernels/ops/detesscast.h and SimaKernels::detesscast.
The caller contract below describes supported behavior; implementation notes describe
this release, not a stable dispatch or binary ABI promise.
Header: simaai/kernels/a65/detesscast.h (A65/detesscast/backend.h).
Typed request: ops::detesscast::Request.
Contract
simaai/kernels/a65/detesscast.h (A65/detesscast/backend.h)
provides checked, synchronous MLA-tiled BF16 → FP32 or BF16
execution. FP16 is deliberately unsupported on both ports. Quantized MLA output
belongs to DetessDequant, not this operation.
| Property | Supported contract |
|---|---|
| Ports | Exactly one input and one output; both specs are explicit. |
| Shapes | Equal logical shape and rank, 1–6 dimensions. Empty tensors are valid; scalars are rejected. No implicit folding or padding of logical axes. |
| Input | BFloat16, MlaTiled or MlaCBlocked, 16-byte-aligned host pointer. |
| Output | Float32 or BFloat16, Contiguous or admitted Strided, scalar-aligned pointer (4 or 2 bytes). Strides are nonnegative, scalar-aligned, positive for nonunit axes, and pass a sorted-span nonoverlap proof. |
| Mapping | Explicit D/H/W/C logical-axis mapping; C is required. Unmapped axes are independent outer dimensions. Compact or padded-to-16 channel storage. |
| Parameters | Empty Params; dtype and layout are authoritative. No scale, rounding selector, JSON or ConfigManager. |
| Buffer sizes | Preparation derives the physical tiled input span and full addressed output span, including stride holes. Each submitted view must provide at least that capacity. |
| Aliasing | Accessed input/output ranges must not overlap. Adjacent views and extra unused capacity are allowed. |
| Lifetime | Borrowed CPU views, valid and accessible until synchronous return. Runtime owns allocation, mapping and coherency. |
The input follows the explicit MlaTiled (include/simaai/kernels/tensor.h)
contract used by native CastTess: each pixel has a low-byte channel plane followed
by a high-byte channel plane. Padded channels participate in both planes. Tiles
use actual boundary extents and 16-byte-aligned spans. Channel tiles precede D/H/W
tiles; outer slices retain logical row-major order.
Padded channels and alignment gaps are ignored, not checked for zero, copied to output or rewritten. Logical channel counts—not stored padded counts—determine the output shape. The producer must use this exact physical contract; other layout names alone do not establish compatibility.
Compiler channel-block input
MlaCBlocked{{tile_h, tile_w, tile_c}} admits ranks 3–6 with trailing
H/W/C axes. Earlier axes are independent HWC volumes. Each channel slice is
padded independently to 16; output contains only logical elements, with caller-selected strides. This
representation is not interchangeable with pixel-major MlaTiled.
For a tile with P = actual_h * actual_w pixels, local channel c and
local pixel p, the low-byte offset is:
32 * ((c / 16) * P + p) + c % 16
high-byte offset = low-byte offset + 16
Integer division is used. The fused reader traverses channel blocks and converts
only valid lanes directly into the final output. It uses the same numerical
core as the pixel-major path; no full-size repacking tensor or extra numerical
pass is introduced. Existing MlaTiled routes retain their optimized dispatch.
Depth tiling or nontrailing H/W/C mappings are not implied by this layout.
Parameters
Params is empty; output dtype and layout select the supported conversion.
Numerical behavior
- BF16 → BF16: every 16-bit word is preserved.
- BF16 → FP32: each word becomes the upper 16 bits of a binary32 word; its lower 16 bits are zero. This is exact expansion, not FP32 arithmetic.
- Both paths preserve signed zero, infinities, subnormals, NaN sign/payload and signaling/quiet status. They do not perform floating-point operations or change FP control or exception flags. Later arithmetic on signaling NaNs can still raise exceptions.
- DetessCast does not recover precision lost when an earlier CastTess rounded FP32 to BF16.
C++ call
The call below checks the shared request, selects A65 execution with
prepare(metadata) and executes with caller-supplied storage. The A65 check_inference()
convenience function performs those first two steps together.
The native EV74 boundary accepts the same
request and numerical contract through Runtime.
Place the includes and namespace aliases at file scope; the remaining statements
belong in a simaai::kernels::Status-returning caller function. input_views and
output_views are caller-supplied arrays of ConstHostBuffer and HostBuffer
in port order, with accessible capacities and alignment from the checked plan.
Keep their storage alive until synchronous execution returns.
#include <simaai/kernels/a65/detesscast.h>
#include <array>
namespace k = simaai::kernels;
namespace dc = k::a65::detesscast;
namespace op = k::ops::detesscast;
k::MlaTiled layout;
layout.axes = {-1, -1, 0, 1}; // Logical shape is [W, C].
layout.tile_shape = {1, 1, 2, 3};
const std::array inputs{
k::TensorSpec{{2, 3}, k::DType::BFloat16, layout}};
const std::array outputs{
k::TensorSpec{{2, 3}, k::DType::Float32, k::Contiguous{}}};
auto prepared = op::check_inference(
{inputs, outputs, {}});
if (const auto *error = std::get_if<k::Error>(&prepared)) return *error;
const auto plan = dc::prepare(std::get<op::Plan>(prepared));
return dc::execute(plan, input_views, output_views);
For a pitched [2, 3] FP32 result, replace the output layout with
k::Strided{{16, 4}}. The required addressed span is 28 bytes, not 24;
the four-byte hole between rows stays untouched. This changes storage only,
not logical indexing or BF16 reconstruction.
See the correctness tests (A65/detesscast/tests/correctness.cpp) for concrete storage,
independent expected results and failure cases.
See calling kernels for the shared lifecycle.
Memory and lifecycle
check_inference() checks port count, dtype, logical shapes, output stride
alignment/nonoverlap, layout mapping, tile extents and storage overflow. It returns an owning,
fixed-size plan with at most 16 full/boundary tile classes, not a list of jobs
proportional to tensor size. Invalid requests cannot construct an executable plan.
Every execute() checks the actual view arity, capacities, null pointers,
alignment, address-range overflow and overlap before any output write.
Pointer accessibility and allocation lifetime remain the caller's responsibility.
The plan is immutable and reusable across invocations and concurrent calls using
separate output buffers. Empty tensors require zero storage and permit null views.
Implementation notes
On A65, contiguous channel runs use NEON byte-plane unpacking and integer shifts. Complete 16-channel blocks interleave low and high byte planes directly; shorter blocks and scalar tails retain their own bounded loads. Reconstruction preserves all BF16 bit patterns and never treats padding as logical channels. Compact C=1/2/3 rows have cross-pixel vector paths where the dense width stride permits them. Nonunit channel strides use direct scalar reconstruction; contiguous channel runs retain vector unpacking even when rows are pitched. Other axis mappings and tails have direct scalar paths. Stride holes are never initialized or overwritten. Output is written directly: no full-tensor staging, heap allocation, worker threads or caller workspace is needed.
Preparation caches a C-only traversal flag in the fixed-size plan. It is selected
for one or more channel tiles with contiguous output channels, one outer slice
and unit actual spatial extents. Unit logical axes can be mapped spatial axes or
unmapped outer axes. When two or more full channel tiles have no alignment gap
between their byte-plane pairs (storage_bytes == 2 * stored_channels), execution
passes them to one row conversion instead of calling it per tile. The dense row
stride is the logical channel count times the output scalar size. Internal
channel padding remains skipped; tiles separated by alignment gaps retain the
per-tile traversal. The final tile is always converted separately with its own
byte planes, logical extent and bounded tail. This reduces repeated dispatch and
setup without changing reconstruction or reading across a tile's byte planes.
Tests and qualification
The default build includes a65_detesscast_contract and a65_detesscast_benchmark.
See build and test for host and DevKit execution.
The independent correctness suite is in
A65/detesscast/tests/correctness.cpp (A65/detesscast/tests/correctness.cpp).
Guard-page tests cover C=8, C=17 and C=32 tile widths, both output dtypes and channel
padding modes, full and partial final tiles, and every channel-axis position at
ranks one through six with mapped or unmapped unit axes. Input padding is poisoned
and the input mapping is read-only during execution. A focused channel-batch
matrix also covers compact and padded widths from one to 64 channels, including
physical alignment gaps, empty tensors and batch-boundary tails.
Physical-family tests cover scalar stepping, row pitches, physical permutations,
outer dimensions and scalar-aligned base phases. Compiler CBlock16 tests cover
strided channels and channel-block tails. Exact-capacity rejection and protected
pages verify addressed-span bounds; poisoned output holes must remain untouched.
See build and test for commands and the distinction
between host development checks, A65 measurements and baseline qualification.