Native DetessDequant boundary
Use simaai/kernels/ops/detessdequant.h for shared admission and
simaai/kernels/ev74/detessdequant.h for device encoding. Link
SimaKernels::detessdequant.
These host targets require no MetaWare, ConfigManager, JSON or GStreamer.
Contract
The DetessDequant contract applies to both
backends: MlaTiled INT8 input becomes contiguous or byte-strided FP32 or BF16 output with the
same explicit logical shape. Ranks one through six and empty tensors are
supported; rank-zero scalars are not. Empty execution submits no numerical job.
D/H/W/C axis mappings remain explicit; C is required and unmapped logical axes
are independent outer dimensions. Compact and padded-to-16 input channels are
supported. Contiguous output means logical row-major order, not necessarily
channels last. Explicit Strided output supports scalar-aligned, non-overlapping
positive strides on non-unit axes, including pitches, steps and physical axis
permutations. Singleton strides may be zero. FP16 output and UINT8/INT16/INT32
tensor inputs are outside this native contract. Legacy graph
entries do not expand it.
Compiler channel-block input
The shared contract also admits MlaCBlocked input with trailing H/W/C at
ranks 3–6; see the physical addressing equation.
The native codec carries an explicit blocked-layout flag. The device validates
the trailing axes and padded-channel contract before dispatch. Existing firmware
that does not understand this flag rejects the packet; deploy matching firmware
and host artifacts together.
The worker gathers valid 16-channel fragments directly into bounded local panels, then uses the existing ordered dequantization core. No DDR intermediate or A65 tensor scan is required. Dense output task ownership and DMA retirement rules remain unchanged. Pixel-major-only bulk readers are not used for blocked payloads.
Parameters
Supply Params{scale, zero_point}. scale is required, finite and strictly
positive, including positive FP32 subnormals. zero_point defaults to zero and
admits the full INT32 parameter domain. This does not add INT32 tensor support.
Parameters follow Dequant semantics but have a distinct nominal C++ type so
Runtime can distinguish the two requests. No caller-selected numerical route,
rounding mode, per-axis scale or hardware-specific parameter is needed.
Numerical behavior
For every logical signed INT8 value q, perform these ordered stages:
z = round_to_nearest_even_FP32(zero_point)
d = round_to_nearest_even_FP32(FP32(q) - z)
r = round_to_nearest_even_FP32(d * scale)
FP32 output = r
BF16 output = round_to_nearest_even_BF16(r)
The subtraction and multiplication are not contracted into FMA. Wide zero points must round to FP32 before subtraction; integer affine rewrites are not interchangeable for the entire admitted domain. Overflow may produce infinity; underflow may produce signed zero or subnormal output. These are valid results. Valid inputs and parameters do not produce NaN.
Normal-scale EV execution converts signed INT8 lanes to exact FP32 values, subtracts the rounded zero point and multiplies by scale. BF16 uses integer nearest-even narrowing of the resulting FP32 bits. It does not use FP16 arithmetic. For subnormal scales, preparation builds an exact 256-entry table using integer arithmetic. Each entry models the same separately rounded stages, including wide-zero-point rounding and signed underflow. This avoids dependence on device FP32 flush behavior without adding CPU work proportional to tensor size. The table is immutable, reused across submissions and copied to worker-local storage once per invocation. BF16 entries contain the final narrowed bits.
A65 checks the executing thread's FP environment before writes; EV selects its normal or exact-table implementation from the admitted scale. See the canonical A65 numerical contract for host FP-state requirements.
C++ call
Use the A65 call for explicit
specifications and checked execution with caller-supplied storage. Shared preparation is
ops::detessdequant::check_inference(request). A65 derives a numerical plan with
a65::detessdequant::prepare(metadata). Runtime accepts the same request and
selects hardware outside the mathematical parameters.
check_inference → EV representability check → encode_relocatable
→ retained DMA-BUF bindings and address relocation
→ asynchronous submission → confirmed retirement and coherency
bind() supports integrations with resolved device regions. CPU pointers are
not EV addresses. Runtime's synchronous convenience call submits the same job
and waits; no second runner or configuration adapter is introduced.
Place the includes and namespace aliases at file scope; the remaining statements
belong in a simaai::kernels::Status-returning caller function. It checks metadata and
encodes a relocatable descriptor, not EV74 computation. Runtime must map actual
buffers, bind addresses and retain inputs, outputs and any workspace until
confirmed device completion.
#include <array>
#include <simaai/kernels/ev74/detessdequant.h>
#include <simaai/kernels/ops/detessdequant.h>
namespace k = simaai::kernels;
namespace op = k::ops::detessdequant;
namespace ev = k::ev74::detessdequant;
k::MlaTiled tiled;
tiled.axes = {-1, -1, 0, 1}; // Shape [W,C], with an explicit channel axis.
tiled.tile_shape = {1, 1, 2, 3};
const std::array inputs{k::TensorSpec{{2, 3}, k::DType::Int8, tiled}};
const std::array outputs{k::TensorSpec{{2, 3}, k::DType::BFloat16}};
const op::Request request{inputs, outputs, op::Params{1.0F}};
auto checked = op::check_inference(request);
if (const auto *error = std::get_if<k::Error>(&checked)) return *error;
const auto &plan = std::get<op::Plan>(checked);
auto encoded = ev::encode_relocatable(plan);
if (const auto *error = std::get_if<k::Error>(&encoded)) return *error;
// Encoding leaves device addresses unbound; no device work has run.
return {};
See the host contract tests (EV74/detessdequant/tests/correctness.cpp) and
device fixture (EV74/detessdequant/tests/runtime_e2e.cpp) for binding and execution coverage.
Memory and lifecycle
Preparation derives physical tiled input storage and the full addressed output span, including holes. Input alignment is 16 bytes; output alignment is two bytes for BF16 or four for FP32. Required ranges must not overlap. Padding and alignment gaps in the input are ignored, even if nonzero; the output contains only logical elements.
Runtime owns allocations, mappings, coherency, scheduling and recovery. It retains buffers and prepared descriptor storage until confirmed retirement. A timeout does not authorize releasing storage still accessible by DMA. Successful execution needs no full untiled intermediate, CPU tensor prescan, per-frame table generation or per-tile A65 submission.
Native boundary
The version-1 descriptor has a 176-byte base, with input/output address slots at
offsets 24 and 32, scale bits at 168 and zero point at 172. Normal-scale packets
are 176 bytes; subnormal-scale BF16 and FP32 packets are 688 and 1,200 bytes.
Six-capacity dimensions, mapping, tile shape and padding describe the input.
Dense output strides are derived rather than redundantly supplied. Non-dense
output sets STRIDED and appends six little-endian 64-bit byte strides after the
176-byte header. Its normal-scale packet is 224 bytes. The exact table follows
the stride trailer, so subnormal BF16 and FP32 packets are 736 and 1,248 bytes.
Explicit row-major strides, ignoring singleton strides, use the dense packet
formats and numerical workers described above. Both target compilers assert
control-layout offsets, sizes and alignment. EV-visible ranges must fit the
checked 32-bit address aperture.
Platform firmware must explicitly register
simaai_kernels_ev74_detessdequant_v1 and
Runtime must verify its capability before numerical submission. Installing a
host library does not install firmware or establish device qualification.
Strided output ownership
For byte-strided output, the addressed scalar offset is
offset = sum(coordinate[axis] * strides_bytes[axis])
span = scalar_bytes + sum((shape[axis] - 1) * strides_bytes[axis])
Admission sorts non-unit axes by stride and proves each new axis starts beyond
the complete previously addressed extent; it checks alignment, signed-64-bit
representability, overflow and capacity. The device repeats those checks before
dispatch and rejects nonzero unused stride slots. Bindings must cover the full
span, not just elements * scalar_bytes. Output holes remain untouched.
A private strided worker reuses the bounded tiled gather and unchanged numerical conversion, then coalesces the largest contiguous logical suffix into output spans. Whole aligned 16-byte interiors use DMA; exact scalar-boundary bytes do not round into holes. Each write retires before another span or exact boundary can share its physical write granule. Arbitrary strided output uses one owner: logical non-overlap alone does not prove independent DMA granules. Input-slot prefetch still overlaps conversion; no full untiled DDR intermediate or A65 per-element processing is introduced. Dense workers retain their existing parallel ownership and slot pipeline.
The host/native suites include pitched, stepped, permuted and singleton views, panel transitions, both output dtypes, compiler-block input, guarded holes and immediate/deferred DMA. Old firmware rejects the new flag/length; deploy the matching package, transport capability table and firmware together. Compilation and host expression models are not real-device qualification.
Implementation notes
Workers own disjoint dense output intervals, not input tiles. Different channel tiles may contribute neighboring elements to the same dense pixel. Ownership boundaries derive from the actual output bus address: interior writes are aligned whole-16-byte DMA ranges; unique global head/tail tasks use exact scalar-width stores. Neither guards nor neighboring views are written to round up a DMA transfer.
Each panel contains at most 4,096 elements. Two 4 KiB INT8 input slots alternate with two output slots and bounded 4 KiB raw-fragment scratch. There are no BF16 low/high input planes: a physical INT8 pixel contains one byte per stored channel. Source tile storage is aligned to 16 bytes and boundary tiles use their actual extents. Bulk reads use DMA; tiny fragments do not silently become a scalar DDR implementation.
The bounded geometry has sixteen full/boundary tile classes. Contiguous channel runs, split-channel pixel gathers, padded channels and permuted-axis rectangles reuse regular DMA spans. Unrepresentable DMA pitches split into exact row transfers rather than being narrowed. Local gathering follows logical output order, then conversion writes that panel directly. Coordinate state is reused across regular runs instead of interpreted anew for every scalar.
Rank-one channel tensors use one direct input DMA per panel when the tensor fits one tile or each full channel tile contains a multiple of sixteen elements. In that geometry, logical input bytes form a contiguous physical prefix, even with channel padding; final padding is not read as data. Other tile sizes retain the general reader. Conversion, output ownership and rounding are unchanged.
Six internal implementations cover the four output-dtype × normal/exact-table combinations and two metadata-selected execution families:
- Normal-scale BF16 rank-one channel tensors use a compact direct-input worker when there is one channel tile or full tiles contain a multiple of sixteen elements. It uses the same arithmetic and exact head/tail output ownership, without the general tiled-reader scratch or control flow.
- Normal-scale FP32 channel bands admit canonical channel-last axes, three or four C tiles of 16 or 32, unit D tiles, complete spatial tiles, W tiles divisible by sixteen, and 16-byte-aligned output. Each bounded band gathers its channel tiles into one dense output interval. Admission preserves the general reader’s available worker parallelism; unsupported geometry uses that reader.
Neither family changes the INT8-to-FP32 arithmetic order, BF16 narrowing, zero-point handling, or exact-table fallback. The native entry selects once. The next input panel is prefetched; input completion precedes consumption and output completion precedes slot reuse. All output transfers drain before numerical completion. Explicit local arrays are not the complete VCCM cost: target qualification must inspect generated stack frames, spills and nested calls as well.
Tests and qualification
ev74_detessdequant_contract checks codec, malformed descriptors, mock dispatch
and independent numerical/layout references. Optional Clang tests execute the
actual OpenCL expressions with immediate and deferred DMA models. Those models
check bounds and software wait ordering, not EV ISA or hardware concurrency.
Standalone Dequant regression tests cover the shared exact-subnormal helper.
Runtime's detessdequant_executor_contract covers shared admission, A65
execution and asynchronous owner lifetime. detessdequant_cvu_e2e runs real
correctness and latency by default, including process CPU time. Qualification
requires both output types, all INT8 values, wide zero points, subnormal scales,
rank/axis/tile tails, dirty padding, giant physical tiles, exact output guards
and one through four workers. Source compilation is not a device pass.
Measure the complete composed firmware, including neighboring operations. Existing Quant median failures remain independent blockers; adding this entry must not reset their baselines. Percentile tails remain diagnostic under the median qualification policy.
Channel-inner physical output traversal
The device entry validates the packet and buffer spans, then may reorder private traversal for a channel-contiguous physical output. Mapped source axes, outer strides and logical associations are permuted together. Bounded source runs may follow W, H or D using their exact tile pitch and current extent. INT8 conversion/table semantics and output holes are unchanged. Strided publication retains one owner. Channel-outer and CBlocked cases remain on their established routes until a cheaper bounded read/write strategy is proved.
H/C and D/C traversal can trade additional exact input-row commands for fewer scalar output writes. Host models report input/output DMA calls, payload bytes and output bytes left to typed stores; input-command count alone is not a latency criterion. Paired device qualification must decide the net benefit.
detessdequant_cvu_e2e --shared-family-only measures H/C and D/C output families
with both output dtypes, channel tails, C-first logical order, holes and phases.
The default fixture includes the same cases and checks every output scalar,
untouched hole and guard using its independent INT8/tiled oracle.