Memory placement
Convert one model twice, once with the planner’s own choices and once with placement rules, and diff the two residency reports. The second conversion stages the weights and hands arena ownership to the application. It also illustrates a persistent-state placement rule; this model has no persistent tensors, so that rule moves no state.
| Field | Value |
|---|---|
| Model | kws_ref, MLPerf Tiny keyword spotting, int8 |
| Target | apollo510_evb |
| Shows | Per-role placement rules, staged constants, caller-supplied arenas, and residency-report comparisons |
| CI | Conversion and host compilation are declared in the examples CI job, with both residency reports held to the committed copies |
The model is audio/mlperf-tiny/kws_ref/model.tflite from helia-model-zoo:
int8, 53,936 bytes, SHA-256 aeea4368…bd0ae, fetched by run.sh and checked
against the fixed SHA-256 recorded in the checked-in run script. Model licensing is not established by these hashes; see Model provenance.
Prerequisites
Section titled “Prerequisites”Use a repository checkout with Bash and the environment from Running examples: uv sync --frozen --group ci, then activate .venv. Fetched models require network access, curl and sha256sum or shasum. Run the commands below from this example directory. Conversion runs on the host; it does not execute the emitted firmware.
Run it
Section titled “Run it”./run.shTwo conversions of the same model: config-baseline.yaml
and config-tuned.yaml. The model and target stay fixed.
The memory block changes placement and ownership; separate module.name values
keep both outputs for comparison.
The rules
Section titled “The rules”memory: dump_residency_json: true allocate_arenas: false tensors: - attributes: { memory: DTCM } - type: persistent attributes: { memory: SRAM } - type: constant attributes: memory: MRAM constant_destination_memory: DTCMRules are matched by tensor role and merged by specificity, so the first line
is the default for everything and the two below it override it for their role.
The role names are constant, persistent and scratch, spelled as the
report spells them.
memory on a constant is where the bytes are stored;
constant_destination_memory is where the kernels read them. Naming both, and
naming two different memories, is what makes a constant staged rather than
cold: the image keeps one read-only blob in MRAM and the module hydrates a
writable copy into DTCM before the first run.
allocate_arenas: false makes the module declare its arenas and allocate
none. The application binds each one, including the cold constant arena, and
the header carries a size macro, an alignment macro and a region enumerator
per arena.
This model has no persistent tensors, so the persistent rule matches nothing
here. It demonstrates the rule syntax; whether a real model
benefits from moving state needs measurement. It establishes no state-access
latency result for this stateless model.
What to look at
Section titled “What to look at”The committed reports in expected/ are conversion baselines for this source revision. Compare your generated reports with those files. The constant arena changes as follows:
"constant": [ {"kind": "cold", "memory": "dtcm", "source_memory": "dtcm", "tensor_count": 39, "used": 28992}]"constant": [ {"kind": "staged", "memory": "dtcm", "source_memory": "mram", "tensor_count": 39, "used": 28992}]kind went from cold to staged, and source_memory from dtcm to mram.
The tuned module also emits aot_arena_const_dtcm__source.bin, a sidecar of
the packed source bytes. The generated default hydration helper copies its
embedded source blob into the bound writable DTCM destination during
aot_model_init(). Do not bind the read-only source as that destination.
Tensor IDs, sizes and offsets in these two captured reports stay the same, but
constant source_memory and the plan identity change. Compare fields instead
of assuming the complete tensor list is identical.
The reports are committed, and CI regenerates and diffs them. A planner or codegen change that moves a tensor shows up as a failing diff here rather than as a surprise in someone’s build. Regenerate them with:
./run.shcp out/kws_ref_baseline/aot_residency.json expected/kws_ref_baseline-residency.jsoncp out/kws_ref_tuned/aot_residency.json expected/kws_ref_tuned-residency.json- Memory for the planner, the hydration contract and the residency schema.
- Static schedule for the other lever this model has.