Wave Neural-Model Backend Map
The Wave firmware contains several neural-looking APIs. They are not all the same accelerator path. This map separates dispatch that is proved by call edges from names that merely coexist in a binary.
System map
Section titled “System map” ┌────────────────────────────┐ │ v3 libmodel_infer.so │ │ AES / ANS APIs │ │ embedded CPU/MNN runtime │ └─────────────┬──────────────┘ │ CPU tensors ▼ Arm Cortex-A CPU
┌──────────────────────────────┐│ stock ASR / project probe ││ aml_module_* │└──────────────┬───────────────┘ │ ▼┌──────────────────────────────┐│ libnnsdk hardware dispatch │├──────────────────────────────┤│ 0 VIPUNIFY /dev/galcore ───┼──► libovxlib / OpenVX / GAL ─► NPU│ 1 VIPLITE /dev/vipcore ││ 2 ADLA /dev/adla0 ││ 3 delegate GPU/CPU TFLite │└──────────────────────────────┘The connected Wave’s live stock-CTC control follows the horizontal NPU path. The v3 AES/ANS API follows the upper CPU path.
libnnsdk dispatch
Section titled “libnnsdk dispatch”Exact provider:
sha256: 36b87d6ce89f4253b9120cb89b5cc1ce33a2cab84e4acb2ee010742b66cc44feaml_module_create calls aml_get_hardware_type, then indexes a family of
parallel function tables for create, input, run, output, and destroy.
| Index | Family | Detection | Static state | Live Wave state |
|---|---|---|---|---|
| 0 | VIPUNIFY | /dev/galcore |
Full create/input/run/output/destroy implementation. | Used by stock CTC. |
| 1 | VIPLITE | /dev/vipcore |
Full implementation present. | Device path not observed in PoC 0. |
| 2 | ADLA | /dev/adla0 |
Full implementation and dynamic libadla.so API present. |
Device path not observed. |
| 3 | Delegate | TFLite GPU/CPU fallback logic, /dev/mali0 |
Delegate exports present. | Not used by NBG stock CTC. |
If no NPU node exists, the selector permits only eligible TFLite models to fall back to GPU/CPU. It rejects non-TFLite models rather than pretending they ran on another backend.
The existence of ADLA symbols is not proof of an ADLA block in this unit. The device-node selection and live graph result establish VIPUNIFY instead.
VIPUNIFY
Section titled “VIPUNIFY”VIPUNIFY is the firmware’s wrapper over the VeriSilicon OpenVX stack.
Compiled graph: “off” branch
Section titled “Compiled graph: “off” branch”Selected by nbgType 0 or 1:
NBG file or memory -> NBG header/IO parser -> hardware target selection -> OpenVX context -> graph and IO tensors -> one NBG node, operation 0x44 -> setup -> verify -> run / outputThis is the live-proven route.
Reconstructed graph: “on” branch
Section titled “Reconstructed graph: “on” branch”Selected by nbgType 2 or 3:
private export-data file or memory -> sectioned export-data parser -> per-node parameter conversion -> norm/const/virtual tensor creation -> connection map -> individual OpenVX nodes -> setup -> verify -> run / outputThe parser recognizes section markers:
[export.data.info]:[node_info]:[norm_tensor]:[const_tensor]:[virtual_tensor]:[conn_info]:[param_info]:[graph_info]:The parser allocates records with these exact internal strides:
| Record family | Bytes per record |
|---|---|
| Node | 0x1f0 / 496 |
| Normal tensor | 0x34 / 52 |
| Constant tensor | 0x3c / 60 |
| Virtual tensor | 0x1c / 28 |
| Parameter | 0x11c / 284 |
| Graph connection | 0x10 / 16 |
Its switch covers many operation parameter types and then
vipunify_create_network_on_ovx constructs the graph through the same exact
stock OpenVX bridge.
This is the most interesting newly recovered custom-graph route. It is not yet approved for device execution:
- no complete example export was found in the extracted firmware;
- the entire grammar and all enum mappings are not yet encoded;
- setup may still require target-specific compiler assets;
- malformed input reaches parser paths that call
exit(0); - the provider uses global parse state.
A minimal identity/add export must be generated and validated entirely on the host before a bounded device PoC is proposed.
OpenVX bridge
Section titled “OpenVX bridge”libnnsdk dynamically resolves a table of wrapper calls such as:
- context create/release;
- graph create/release;
- graph input/output binding;
- tensor creation;
- node creation;
- setup and verification;
- run;
- output copy.
Provider wrappers such as aml_vipunify_create_context_ovxlib and
aml_vipunify_new_node_ovxlib are very small indirect calls through that
table. The actual graph engine is in libovxlib.so.
The exact libovxlib.so, libOpenVX.so, libGAL.so, libVSC.so, and
libArchModelSw.so are byte-identical across the four firmware roots in this
corpus. That stability is useful, but it does not supply a host compiler for
the Wave product.
Compiled NBG compatibility
Section titled “Compiled NBG compatibility”Known graph headers:
| Graph | NBG version | Product | Runtime result |
|---|---|---|---|
| Stock CTC | 0x00020000 |
0x1000000e |
Executes and retrieves output. |
| Host TIM-VX add | 0x0001001e |
0x10000020 |
Rejected before execution. |
vipunify_load_hw_config accepts the Wave product and rejects the foreign
target. Patching the field is not compilation and remains prohibited.
The local TIM-VX tree is now at commit 702715d…, newer than the checkout
used by early experiments. A later compiler PoC should retest this exact
commit against the external stock libovxlib, but PoC 1 does not assume that
new source alone contains the necessary VIP9000 target assets.
Firmware v3 audio API
Section titled “Firmware v3 audio API”Surface
Section titled “Surface”Business and v3 firmware contain libmodel_infer.so. v3 exports:
AES-labelled loaders:
model_infer_aes_load_vdcrn_16k_0_07m_*;model_infer_aes_load_vdcrn_16k_0_1m_*;model_infer_aes_load_vdcrn_32k_0_1m_*;- generic load, run, destroy, delay, and version APIs.
ANS-labelled loaders:
model_infer_ans_load_vdf2_16k_0_25m_*;model_infer_ans_load_vdf2_16k_0_35m_*;- several 32 kHz VDF2 variants;
- 32 kHz VAIBF variants;
- a 16 kHz multi-channel fusion variant;
- generic load, run, mask, SNR, strength, post-filter, delay, version, and destroy APIs.
The suffixes are firmware labels. PoC 1 does not reinterpret every numeric suffix as a measured parameter count.
Dependency proof
Section titled “Dependency proof”v3 libmodel_infer.so:
bytes: 2681888sha256: 78b9ddba32f608dd6771b3300fd4f7ce5f2808a1a52b05cdf618348db608bbe5needed: libc.so.6 libgcc_s.so.1 libm.so.6 libstdc++.so.6It has no dynamic dependency on:
libnnsdk;libovxlib;libOpenVX;libGAL;libVSC.
It imports no relevant Amlogic, VSI-NN, OpenVX, VIP, or GAL symbol.
Internal proof
Section titled “Internal proof”The AES internal loader:
- creates an interpreter from a buffer or file;
- creates a session;
- resolves a set of named input tensors;
- resolves named output tensors;
- allocates host tensor wrappers;
- installs an AES function table.
The ANS internal loader performs the same pattern, sometimes for three model parts, and optionally creates CPU worker threads.
The binary contains a full CPU backend and diagnostics such as tensor-copy, session-resize, and CPU operator failures. This is behavior, not just the word “CPU” in an unused string table.
Caller proof
Section titled “Caller proof”The v3 signal-processing DSO:
path: usr/lib/libspai_mic_sigp.sobytes: 30330096sha256: 8045da803d71ec3ea3e1c058340745ba2bd878eb28557300eba5cf65d8e5af1cloads several ANS models and one AES model, launches audio worker threads, and calls:
model_infer_aes_run(context, spectral_input, auxiliary_output, mask)model_infer_ans_run(context, spectral_input, output)model_infer_ans_get_mask(context, mask)model_infer_ans_get_snr_db(context)One recovered path copies a 513-float (0x804-byte) ANS mask and applies it
inside a larger classical DSP/beamforming pipeline. This is a useful design
reference for an NPU model: accelerate the neural mask estimator while
keeping STFT, beamforming, smoothing, and failover explicit.
Classification
Section titled “Classification”| Claim | Result |
|---|---|
| v3 exposes useful denoising-model APIs | Proved. |
| stock audio calls those APIs | Proved. |
| the library runs a CPU interpreter/backend | Proved statically. |
| those AES/ANS calls use the Wave NPU | Refuted for this DSO. |
| the embedded models can be converted to Wave NBG | Unknown. |
| the v3 pipeline is a useful quality/reference workload | Strong inference; dynamic reference PoC still needed. |
Noise-suppression implications
Section titled “Noise-suppression implications”The quickest credible NPU target is not “run the v3 API on the NPU.” It is:
- use the v3 ANS behavior to understand frame, feature, mask, delay, and post-filter contracts;
- choose or train an openly reproducible small mask estimator;
- establish a Wave-targeting graph route;
- prove its operations and recurrent state;
- compare against the existing CPU DeepFilterNet path and, if legally and operationally usable, the v3 reference.
Candidate architecture constraints now visible from stock code:
- streaming operation;
- bounded frames;
- explicit state/delay;
- spectral-mask output is practical;
- 16 kHz and 32 kHz variants are relevant;
- multi-channel fusion exists in stock CPU software;
- CPU DSP around the neural core remains substantial.
Custom-model route matrix
Section titled “Custom-model route matrix”| Route | Backend | Current evidence | Next PoC |
|---|---|---|---|
Stock Wave NBG through libnnsdk |
NPU | Live-proven. | Parse full stock corpus. |
Foreign host NBG through libnnsdk |
NPU intended | Product mismatch; safely rejected. | Retest a genuinely Wave-targeted compiler only. |
| Private export-data mode 3 | NPU/OpenVX intended | Parser and graph-builder binary-proven. | Reconstruct grammar; bounded identity graph. |
Direct stock libovxlib via current TIM-VX |
NPU intended | Context reachability known; current commit not yet retested end-to-end. | Minimal graph with exact stock runtime. |
v3 libmodel_infer AES/ANS |
CPU | Static backend proved. | Optional CPU reference/quality characterization. |
Raw /dev/galcore replay/fuzzing |
NPU | No safe contract. | Not part of this program. |
Production cautions
Section titled “Production cautions”- Serialize graph create/destroy until global-state behavior is tested.
- Do not mix export-data and NBG modes concurrently.
- Treat model input as trusted data; several parser errors call
exit. - Keep a CPU audio path alive and independently testable.
- Never make driver reset, service stop, or reboot an automatic recovery policy.
- Require exact library/model hashes for every device experiment.