Skip to content
develop

Quickstart

Take a supported ONNX model, compile it for a bounded SRAM budget, and generate the target integration code. This walkthrough uses the matched INT8 MobileNetV1 model from the benchmark repository and a 64 KiB fast-memory budget. Exact stage counts and tiling decisions are compiler results, so they may improve between releases. Independently captured measurements remain in Introducing TiGrIS.

  • Python 3.10+ with tigris-ml installed
  • A supported float32 or fully quantized INT8 ONNX model. A dimension the model leaves free, such as the batch dimension of a stock export, is bound to 1; --input-shape input:4x3x224x224 compiles for a different one
Terminal window
pip install tigris-ml

To reproduce this walkthrough, run python models/prepare.py from the root of tigris-bench, then copy models/output/mobilenet_v1_matched.onnx into your working directory. That model is reconstructed from the benchmark’s TFLite model so its weights and quantization match the hardware comparison. For supported operators and backend qualifications, see Operator and Backend Support.

Check whether the model fits within a 64 KB SRAM + 8 MB PSRAM budget (typical for an ESP32-S3):

Terminal window
tigris analyze mobilenet_v1_matched.onnx -m 64K -m 8M -f 16M
mobilenet_v1_matched.onnx int8, 31 operators
input input 1x3x128x128 float32, stored as int8 at scale 0.0392704, zero point -1
output l33_dq 1x10 float32, stored as int8 at scale 0.00390625, zero point -128
fits 64.00 KiB fast memory, 13 stages, 12 tiled
memory
unscheduled 384.00 KiB
largest tensor 256.00 KiB 1x64x64x64
this plan 64.00 KiB 0 B headroom
slow memory 192.00 KiB budget 8.00 MiB
slow traffic 767.38 KiB per inference: 208.01 KiB written, 559.38 KiB read
also fits at 32.00 KiB 25 stages, 24 tiled
also fits at 16.00 KiB 29 stages, 28 tiled
does not fit at 8.00 KiB
flash
plan 3.35 MiB weights 3.09 MiB, overhead 269.93 KiB
flash budget 16.00 MiB fits

Continue when the verdict line starts with fits. The flash section confirms the plan fits the 16 MiB flash budget. No hardware is required for analysis.

Generate a binary execution plan:

Terminal window
tigris compile mobilenet_v1_matched.onnx -m 64K -m 8M -f 16M --xip -o mobilenet.tgrs
Flag Meaning
-m 64K -m 8M Memory pools, fast to slow. First is SRAM budget, second is PSRAM. The compiler decides what goes where.
-f 16M Flash budget. Fails if the plan doesn’t fit.
--xip Execute-in-place. Weights are read from flash at runtime, not copied to SRAM.
-o mobilenet.tgrs Output path for the binary plan.

Multi-stage models keep the tensors that cross stage boundaries in the slow arena, normally PSRAM or another writable RAM region. Flash cannot serve, because it is read-only.

Step 3: Check the plan on your machine (optional)

Section titled “Step 3: Check the plan on your machine (optional)”

On a platform wheel of tigris-ml, the bundled reference runtime executes the plan without a board. inspect shows the interface the plan expects:

Terminal window
tigris inspect mobilenet.tgrs

The input is declared as float32 in stored NHWC order, 1x128x128x3, so one input is 49152 float32 values, 196608 bytes. A smoke run with an all-zero input:

Terminal window
head -c 196608 /dev/zero > input.bin
tigris run mobilenet.tgrs --input input.bin --output prediction.bin

This runs the portable reference kernels and confirms the plan loads and executes; it does not test ESP-NN numerics or device latency. See tigris run for real inputs and the Python API.

Use codegen to produce a backend-specific C harness:

Terminal window
tigris codegen mobilenet.tgrs --backend esp-nn -o mobilenet.c
Backend Target
reference Portable C99 (any platform)
esp-nn Espressif optimized kernels (ESP32 family)
cmsis-nn Arm optimized kernels (Cortex-M family)

Same plan, different kernels. codegen writes target-specific runtime glue; the .tgrs plan remains a separate deployment artifact loaded from a file, flash partition, or linker-provided flash symbols depending on the backend.

To start from a precompiled model instead, tigris zoo fetch downloads a plan with its runtime requirements; see tigris zoo. See Runtime Integration for manual loading details.

Run the plan once on the host runtime and see what it does:

Terminal window
tigris analyze mobilenet_v1_matched.onnx -m 64K -m 8M --trace

This prints, per stage, the tiles, the bytes read from and written to slow memory, and the highest fast memory use, as measured by the runtime. Add -v for every load, spill and kernel call.

The .tgrs plan contains the operator schedule, memory map, tiling parameters, and weights. On your target:

  1. Add the generated source to the firmware project.
  2. Store the plan at the location expected by the selected generated harness.
  3. Supply the generated integration with the required fast and slow arenas.
  4. Initialize the selected backend, fill every model input, and check the generated run function’s result before reading model outputs.

The generated source is the maintained starting point: compiler CI syntax-checks a fresh portable C99 harness against the matching runtime headers. Applications that need custom ownership, RTOS task-local workspaces, or their own entry point should use codegen --format core. The complete checked manual sequence, including plan-sized executor workspace and backend preparation, is in Runtime Integration.