Skip to main content

CastTess

Experimental C++20 API, package version 0.1.0. Link SimaKernels::a65_casttess. The caller contract below describes supported behavior; implementation notes describe this release, not a stable dispatch or binary ABI promise.

Shared metadata header: simaai/kernels/ops/casttess.h (common/casttess/casttess.h). A65 execution header: simaai/kernels/a65/casttess.h (A65/casttess/backend.h). Typed request: ops::casttess::Request.

Contract​

Contiguous or admitted strided inputMLA-tiled outputConversion
FP32BF16Existing Cast bit-rounding rule, fused with packing
IEEE FP16BF16Round to nearest, ties to even; preserve signed zero and infinity; quiet NaNs while preserving sign and the high payload bits
BF16BF16Bit-preserving tessellation, including NaN payloads

FP16 and BF16 are different scalar types. FP16 is not an MLA output format here. The BF16 input case is a tessellation-only path sharing the same packing engine. There are no quantization parameters or hidden casts. Params is empty because the two tensor specifications fully describe the operation.

FP32 follows the integer expression (bits + 0x7fff + ((bits >> 16) & 1)) >> 16, including its unusual NaN behavior. Some FP32 NaN payloads therefore become infinity or wrap, matching Cast semantics. FP16 has the explicit NaN policy in the table. Neither input format is processed by floating-point arithmetic in the default implementation. Calls do not require or change the caller's FP mode.

Parameters​

Params is empty. Source/output dtype and the explicit output MlaTiled layout are authoritative.

Numerical behavior​

For FP32 input, use the exact Cast bit rule, including its NaN behavior. FP16 input uses nearest-even BF16 rounding with explicit NaN quieting; BF16 input is bit-preserving. Packing does not add a numerical conversion or change logical shape.

C++ call​

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/casttess.h>
#include <array>

namespace k = simaai::kernels;
namespace op = k::a65::casttess;
// Six logical dimensions; the final two are W=2 and C=3.
const k::Shape shape{1, 1, 1, 1, 2, 3};
k::MlaTiled layout;
layout.axes = {2, 3, 4, 5}; // D, H, W, C logical axis indices.
layout.tile_shape = {1, 1, 2, 3};
const std::array inputs{k::TensorSpec{shape, k::DType::Float32}};
const std::array outputs{k::TensorSpec{shape, k::DType::BFloat16, layout}};
// The same typed metadata admission serves A65 and EV74 preparation.
auto checked = k::ops::casttess::check_inference(
{inputs, outputs, {}});
if (const auto* error = std::get_if<k::Error>(&checked)) return *error;
const auto plan = op::prepare(std::get<k::ops::casttess::Plan>(checked));

return op::execute(plan, input_views, output_views);

See the correctness tests (A65/casttess/tests/correctness.cpp) for concrete storage, independent expected results and failure cases.

See calling kernels for the shared lifecycle.

Memory and lifecycle​

Input and output must have identical logical shapes and ranks, from one through six. Scalar tensors are rejected because this MLA mapping does not define a scalar format. Empty tensors are valid, require zero storage and permit null views. Negative dimensions are rejected, including in otherwise empty tensors.

MlaTiled is a physical layout, not a dtype. Its fields are:

  • axes: logical axis indices in D, H, W, C order. Every present axis must be unique and in range. C is mandatory; a spatial axis can be -1 to denote an absent unit dimension.
  • tile_shape: positive tile extents in D, H, W, C order. An absent axis requires extent one. Tile extents larger than the tensor dimension produce one boundary tile, not a padded logical dimension.
  • channels: Compact stores the actual channels in each tile; PadTo16 rounds each tile's actual channel count up to a multiple of 16.

Unmapped logical axes are outer dimensions, traversed in increasing logical axis order with the last outer axis varying fastest. Each outer slice contains a full tile sequence. Within a slice, tiles are ordered C → D → H → W, with W varying fastest. Within each tile, pixels are ordered D → H → W. Each pixel stores all low BF16 bytes followed by all high BF16 bytes. Channel padding is zero in both byte planes. Boundary tiles use their actual spatial extents.

Every tile's byte span is rounded up to 16 bytes, with zero-filled trailing padding. This first contract intentionally has no arbitrary alignment, alternate byte-plane encoding or C-block-format switch. Other formats require an explicit extension, not reinterpretation of this descriptor. A Runtime/Model Compiler adapter must establish that a model's physical metadata matches this contract; the new descriptor does not by itself qualify all compiler-produced layouts.

Input storage is either row-major Contiguous or explicit Strided storage. Strides are nonnegative byte offsets, scalar-aligned and positive on axes with extent greater than one. Zero strides are allowed only for singleton or empty axes. A sorted-span proof admits nonoverlapping views conservatively; negative strides, broadcasting, overlapping views and unproven interleaved views are rejected. Unused stride slots do not address data. Empty tensors still validate stride signs and alignment, without multiplying irrelevant large dimensions.

For a nonempty strided input, required capacity is scalar width plus the sum of (extent - 1) * stride_bytes over logical axes. Input gaps are not logical values and are never converted. For example, FP32 shape {2, 3} with byte strides {32, 8} needs 52 accessible bytes, not the 24-byte logical payload.

Input strides and output axis mapping are independent. They can describe channels-first, channels-last, transposed or pitched views without changing the output format. Contiguous-channel paths retain their vectorized packing; noncontiguous channels use scalar addressing. No intermediate dense tensor is created for strided input.

ops::casttess::check_inference() derives physical storage requirements, checks overflow and owns copies of both specs. The shared plan contains only metadata; a65::casttess::prepare() selects numerical and packing code from that plan. The existing a65::casttess::check_inference() combines those two steps. Its fixed-size plan precomputes input strides, outer iteration and at most 16 full/boundary tile classes. Preparation does not allocate storage or a job per tile. Input pointers require scalar alignment (4 bytes for FP32, 2 for FP16/BF16); output pointers require 16-byte alignment.

execute() validates arity, capacities, pointers, alignment, address-range overflow and overlap before writing. Disjoint views in one allocation are valid. Extra accessible capacity is permitted but is not read or overwritten. Every execution writes the complete required output, including padding; callers do not need to prezero reused buffers. Execution is synchronous and allocates no memory, uses no scratch tensor and creates no threads. The caller retains buffer owners and is responsible for host accessibility and cache/DMA synchronization.

Implementation notes​

A65 uses fused integer conversion and packing, with specialized C=1/2/3 row paths and eight-channel NEON blocks. Channel-subtile tails do not assume adjacent pixels are adjacent input scalars. FP16 normal values use a short integer path; subnormals and special values use the full bit-defined conversion. A private fused-widening candidate exists for qualification, not as a public parameter. There is no temporary dense BF16 tensor in either candidate.

For contiguous C=1 or C=3 image rows, BF16 and FP32 input can use a direct Pad16 writer when all channels fit one channel tile and adjacent pixels are packed contiguously. Preparation selects this path once. Each pixel writes its complete low-byte and high-byte planes, including zero ghost channels, from registers instead of clearing two variable-length padding spans. Input reads remain scalar-sized, including the last pixel. Conversion order and bit results are unchanged. FP16, split-channel tiles, compact output and other strides keep the existing packing paths.

For nonempty C-only layouts with one outer slice, unit actual spatial extents and contiguous input channels, preparation caches eligibility and execution walks the physical channel tiles directly, including single-tile layouts. Unit logical axes may be mapped spatial axes or unmapped outer axes. Preparation selects a one-pixel channel-only packing leaf for FP32, BF16 and FP16, eliminating image-width/interleave decisions from that path. The C=1/C=3 BF16/FP32 Pad16 direct writer above retains precedence. Conversion helpers, vector bounds and scalar tails remain unchanged. Each channel-only call receives width one and the physical tile's own channel count and byte-plane separation. This path retains one row conversion per tile, including the final partial tile; it does not join BF16 byte planes or numerical tails across tiles. Channel padding and trailing tile-alignment padding are still zero-filled. The channel walk skips trailing-padding initialization when the physical tile has no alignment tail, avoiding zero-length calls without skipping required channel padding. Other layouts use the general tile traversal.

See build and test for default correctness and latency tests.

Tests and qualification​

The default build includes a65_casttess_contract and a65_casttess_benchmark.

The independent correctness suite is in A65/casttess/tests/correctness.cpp (A65/casttess/tests/correctness.cpp). Guard-page coverage includes C=17 and C=32 tile widths, full and partial final tiles, both channel-padding modes, all three input dtypes and every channel-axis position at ranks one through six, with mapped and unmapped unit axes. The same correctness executable also covers dense-equivalent, pitched, physically permuted and channel-strided input, zero-stride singleton axes, conservative overlap rejection, span overflow, empty views and checked binding failures. Latency cases include three strided patterns for all input dtypes and both channel-padding modes; their oracle constructs physical output independently of production geometry. See build and test for commands and the distinction between host development checks, A65 measurements and baseline qualification.