Ethos-U with heliaAOT
heliaAOT understands the Ethos-U command streams generated by Arm Vela. When you feed a Vela-converted LiteRT/TFLite model into heliaAOT, every Ethos-U-supported subgraph is collapsed into a single ETHOS_U operator whose first input is the command stream. The generated C module emits a thin wrapper around ethosu_invoke_v3, automatically wiring up the command stream plus all required base addresses for inputs, outputs, and Vela-added auxiliary buffers.
The Ethos-U driver is a hard dependency
A module containing ETHOS_U operators will not compile without the
Ethos-U core driver on the include path. If <ethosu_driver.h> is not
found, the generated translation unit stops with an #error.
This is deliberate. A missing header used to compile a stub that returned success without touching the NPU, so an integrator could ship a "passing" build whose accelerator never ran. Failing the compile makes the missing dependency impossible to ignore.
A non-functional stub is still available for host-side codegen tests and for bring-up on a machine without the driver tree, but it must be requested explicitly:
The stub returns success without executing the NPU. Never use it in a build that is expected to run the model.
Run a LiteRT model through Vela and heliaAOT
- Compile with Vela. Install Vela (
python -m pip install ethos-u-vela) and run it on the original.tflite:
vela ./models/my_model.tflite \
--accelerator-config ethos-u85-256 \
--memory-mode Shared_Sram \
--output-dir build/vela_out \
--output-format tflite
Adjust the accelerator/system configs to match your target — the example above matches the Ethos-U85-256 in the Atomiq110. Vela produces a new .tflite where each Ethos-U region is encoded as a single custom op plus a command stream tensor.
- Convert with heliaAOT. Point heliaAOT at the Vela output to generate the C module:
helia-aot convert \
--model.path build/vela_out/my_model_vela.tflite \
--module.path ./out/ethos_u_module \
--platform.name atomiq110 \
--test.enabled
No extra flags are needed for Ethos-U; the converter detects the ETHOS_U custom op, lifts the command stream into a const tensor, and keeps any non-Ethos-U operators as standard CPU/Helium kernels.
Pick --platform.name to match the silicon you are targeting. atomiq110 is the Atomiq110, which pairs a Cortex-M55 host with an Arm Ethos-U85-256 NPU, and is the only registered platform that declares SocCapability.NPU today. Targeting a platform without an NPU is rejected at conversion time — see Platform gating below.
- Integrate the driver. Link the Ethos-U core driver (or the FVP-provided driver) into your application. The generated CMake module advertises and wires this dependency for you — see the emitted
CMakeLists.txt. Without it the build fails by design; see the driver-contract note above.
Memory placement
Ethos-U requires its buffers on 16-byte boundaries. heliaAOT stamps a 16-byte alignment hint on the command stream, every Vela-added auxiliary tensor, and the operator's inputs and outputs, so the memory planner places all NPU-visible buffers correctly without any configuration on your part.
Vela emits its own OfflineMemoryAllocation alongside the command stream. heliaAOT honors those offsets rather than re-planning the region, so the addresses the command stream was compiled against remain valid.
Platform gating
Converting a Vela model against a platform without an NPU is rejected at
conversion time. Platforms declare an accelerator via SocCapability.NPU
(atomiq110 does); targeting any other platform fails with an actionable
error instead of surfacing later in the integrator's build.
Opting out
Some setups legitimately run Ethos-U kernels on a host platform that declares
no SoC NPU — most notably the Corstone-300 FVP, where the accelerator is
provided by the simulator rather than by the modelled silicon. For those
cases, set the require_platform_npu attribute to "false" on the ETHOS_U
operator in your config:
This disables the gate only; nothing else about codegen changes. Use it for simulation and experimentation, not to ship a build against silicon that has no NPU.
The config file is the only route: --operators is a nested-model flag, so it
rejects inline values on the command line (a bare --operators only clears a
list supplied by YAML). Put the ruleset above in your config and pass it with
--path config.yaml.
Status and limitations
Known gaps
- Ethos-U85 has no automated coverage. End-to-end tests exercise
Ethos-U55 on the Corstone-300 FVP (with the gate opted out, as above).
The U85 path that
atomiq110targets is not covered by CI. Tracked in #78.
Platform gating: converting a Vela model against a platform without an NPU is
rejected at conversion time. Platforms declare an accelerator via
SocCapability.NPU (atomiq110 does); targeting any other platform fails with an
actionable error instead of surfacing later in the integrator's build.