# First conversion

Compile a known model before adapting the process to your own. The result of
this step is a Zephyr module for Apollo510 EVB, with a generated numerical test
and a memory report. Everything here runs on the host.

## Get a model

Create a working directory and run the remaining host commands from it:

```sh
mkdir kws-first
cd kws-first
BASE=https://media.githubusercontent.com/media/AmbiqAI/helia-model-zoo/main/audio/mlperf-tiny/kws_ref
curl -fL -o kws_ref.tflite "$BASE/model.tflite"
curl -fL -o golden.npz "$BASE/golden.npz"
```

These are the MLPerf Tiny keyword-spotting model and golden fixture from
[helia-model-zoo](https://github.com/AmbiqAI/helia-model-zoo). They are stored
with Git LFS; a pointer file from an incomplete clone is not a model. Verify the
bytes against the hashes used by the repository's first-model example:

Verify the downloaded model and fixture

```sh
python - <<'PYTHON'
import hashlib
from pathlib import Path

expected = {
    "kws_ref.tflite": "aeea436800704fce17b17292e4412630ad856e9d777c044c64ef748a880bd0ae",
    "golden.npz": "434290baa67ce60cf6e7b0d3f5539acae92d3c0890d9f30636d16b3762402f13",
}
for name, wanted in expected.items():
    actual = hashlib.sha256(Path(name).read_bytes()).hexdigest()
    if actual != wanted:
        raise SystemExit(f"{name}: SHA-256 mismatch: {actual}")
    print(f"{name}: SHA-256 verified")
PYTHON
```

Stop on a mismatch and check the download and model revision. Do not replace the
expected hash just to accept different bytes.

This model has one int8 input shaped `[1, 49, 10, 1]` and one int8 output shaped
`[1, 12]`. The NPZ stores `input_0` and `output_0` for that pair. It is already
model input data, so no microphone capture or audio preprocessing is needed for
the generated test.

## Convert it

Save this complete configuration as `kws.yaml` in the same working directory:

```yaml title="kws.yaml"
model:
  path: kws_ref.tflite
  name: kws_ref
module:
  path: ./out
  name: kws_ref
  prefix: aot
  type: zephyr
platform:
  name: apollo510_evb
memory:
  dump_residency_json: true
test:
  enabled: true
  golden_data: golden.npz
  tolerance: 1.0
  num_iterations: 1
  skip_verification: false
```
```text
$ helia-aot convert --path kws.yaml
Analyze → Plan → Emit
Model: kws_ref | Module: zephyr | Target: apollo510_evb
Output: out/kws_ref/
```

This is a shortened illustration, not a captured conversion. The actual Results
summary includes the model's arena sizes and generated output path.

The explicit golden data supplies the stimulus and expected output; this path
does not need to invoke a host reference interpreter. The test allows an
absolute difference of one stored int8 output step. Keep that threshold fixed
while investigating a mismatch; it is not an instruction to accept whatever
difference appears.

CLI flags can override the file for a run, for example
`--platform.name apollo510_evb`. Use YAML for structured rule lists. See
[Configuration](https://ambiqai.github.io/helia-aot/reference/configuration/) for field names and flag
spellings.

The repository also has a runnable
[first-model example](https://github.com/AmbiqAI/helia-aot/tree/main/examples/first-model)
using the same hashed model/fixture pair. Its default output format is
neuralSPOT; the saved configuration above selects Zephyr for this walkthrough.

## What the console prints

Conversion progresses through **Analyze**, **Plan** and **Emit**. Read the Results
summary for `kws_ref`, `zephyr`, `apollo510_evb`, the arena sizes and the output
path. Exact counts and timing can vary with the compiler version. When an
option could make this model faster on this target, the Results also list it
under **Optimization hints**, with its measured gain, its accuracy cost and the
YAML that sets it. The choice made for every operator is in
`<prefix>_plan.json` next to the module, and the facts behind the hints are in
`<prefix>_report.json`; see
[Performance and accuracy options](https://ambiqai.github.io/helia-aot/guide/options/).

Check that these files now exist:

```text
out/kws_ref/README.md
out/kws_ref/includes-api/aot_model.h
out/kws_ref/includes-api/aot_test_case.h
out/kws_ref/src/aot_test_case.c
out/kws_ref/zephyr/module.yml
out/kws_ref/aot_residency.json
out/kws_ref/aot_plan.json
out/kws_ref/aot_report.json
```

A successful conversion means source was emitted. It has not compiled or run
the generated C. Save the compiler version, configuration and verified model
hashes with this output.

`--verbose 2` enables debug details, including planning. `--verbose 3` also
expands AIR tensor/options details. `--verbose 0` keeps the Results summary
without progress output.

## Exit codes

| Code | Meaning |
| --- | --- |
| 0 | The module was written. |
| 1 | A conversion failure; inspect the error and any remediation hint. |
| 2 | Invalid command/configuration arguments. |
| 130 | Interrupted conversion. |

Typed conversion failures include a message and may include a remediation hint. Some input failures, such
as a missing golden archive or an unknown transform, still raise ordinary
exceptions with tracebacks. Check the path or setting first, and retain an
unexplained traceback with the configuration and version for
[Support](https://ambiqai.github.io/helia-aot/reference/support/).

An existing module is not overwritten by default. For a second experiment, use
a fresh output path, such as `--module.path ./out-second`. `--force` deliberately
removes the previous module, including hand edits. Change configuration and
regenerate instead of patching generated C.
