Cortex-M (CMSIS-NN) Backend
Architecture
Not a delegate backend — no partitioner. Custom ops and graph passes replace ATen quantized ops with CMSIS-NN equivalents at the graph level.
Pipeline
Uses standard PT2E quantization (prepare_pt2e / convert_pt2e), then CortexMPassManager rewrites quantized ops to cortex_m:: equivalents.
python1from executorch.backends.cortex_m.quantizer.quantizer import CortexMQuantizer 2from executorch.backends.cortex_m.passes.cortex_m_pass_manager import CortexMPassManager 3from torch.export import export 4from torchao.quantization.pt2e.quantize_pt2e import convert_pt2e, prepare_pt2e 5from executorch.exir import to_edge_transform_and_lower, EdgeCompileConfig 6 7quantizer = CortexMQuantizer() 8captured = export(model, example_inputs).module() 9prepared = prepare_pt2e(captured, quantizer) 10prepared(*example_inputs) # calibration 11quantized = convert_pt2e(prepared) 12 13exported = export(quantized, example_inputs) 14edge = to_edge_transform_and_lower( 15 exported, 16 compile_config=EdgeCompileConfig(_check_ir_validity=False), 17) 18edge._edge_programs["forward"] = CortexMPassManager( 19 edge.exported_program(), CortexMPassManager.pass_list 20).transform() 21et_program = edge.to_executorch()
In tests, CortexMTester wraps this pipeline:
python1from executorch.backends.cortex_m.test.tester import CortexMTester 2 3tester = CortexMTester(model, example_inputs) 4tester.quantize().export().to_edge().run_passes().to_executorch()
Key Files
| File | Purpose |
|---|---|
backends/cortex_m/quantizer/quantizer.py | CortexMQuantizer — quantizes model for CMSIS-NN |
backends/cortex_m/passes/cortex_m_pass_manager.py | CortexMPassManager — rewrites ATen ops → cortex_m:: ops |
backends/cortex_m/test/tester.py | CortexMTester — test harness with test_dialect() and test_implementation() |
backends/cortex_m/ops/operators.py | Python op definitions and reference implementations (cortex_m:: namespace) |
backends/cortex_m/ops/operators.yaml | C++ kernel registration schemas (used by build system) |
C++ kernels calling CMSIS-NN APIs live under backends/cortex_m/ops/.
Testing
Toolchain setup (required for test_implementation tests):
bash1./examples/arm/setup.sh --i-agree-to-the-contained-eula 2source ./examples/arm/arm-scratch/setup_path.sh
Run all tests:
bash1source ./examples/arm/arm-scratch/setup_path.sh 2pytest backends/cortex_m/test/
test_dialect_* tests verify graph correctness (pure Python, no toolchain needed).
test_implementation_* tests verify numerical accuracy on the Corstone-300 FVP (requires toolchain on PATH).
Baremetal build:
bash1backends/cortex_m/test/build_test_runner.sh
Adding a New Op
- Define the op schema, meta function, and reference implementation in
operators.py - Write the C++ kernel in
backends/cortex_m/ops/calling CMSIS-NN APIs - Register the
.outkernel inoperators.yaml - Add a pass to rewrite the ATen op →
cortex_m::op - Test with
CortexMTester.test_dialect()(graph correctness) andtest_implementation()(numerical accuracy on FVP)