1- // KeywordSpotting — DS-CNN keyword spotting with ExecuTorch
1+ /*
2+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3+ * All rights reserved.
4+ *
5+ * This source code is licensed under the BSD-style license found in the
6+ * LICENSE file in the root directory of this source tree.
7+ */
8+
9+ // KeywordSpotting — DS-CNN inference with ExecuTorch + CMSIS-NN
210//
3- // Runs a quantized DS-CNN model (MLPerf Tiny KWS benchmark) on hardcoded
4- // MFCC test inputs and prints the detected keyword . The model classifies
5- // 12 keywords: silence, unknown, yes, no, up, down, left, right, on, off ,
6- // stop, go.
11+ // Runs a quantized DS-CNN model (MLPerf Tiny KWS benchmark) using the
12+ // Cortex-M backend with CMSIS-NN accelerated int8 ops . The model
13+ // classifies 12 keywords: silence, unknown, yes, no, up, down, left,
14+ // right, on, off, stop, go.
715//
8- // The model uses CMSIS-NN accelerated int8 ops on Cortex-M boards.
16+ // This example demonstrates:
17+ // - Loading a .pte model with cortex_m::* ops (CMSIS-NN backend)
18+ // - Setting up memory allocators for constrained devices
19+ // - Running inference and reading output tensors
920//
10- // Prerequisites :
11- // - model.h : DS-CNN .pte exported with CortexMQuantizer, as a C array
12- // - test_inputs.h : MFCC features from real audio, as float arrays
21+ // Required files (not included, generate with export_model.py) :
22+ // - model.h : DS-CNN .pte exported with CortexMQuantizer
23+ // - test_inputs.h : MFCC features from real audio samples
1324
1425#include < ExecuTorchArduino.h>
1526#include " model.h"
16- #include " test_inputs.h"
1727
28+ using executorch::aten::ScalarType;
1829using executorch::extension::BufferDataLoader;
1930using executorch::runtime::Error;
2031using executorch::runtime::EValue;
@@ -40,9 +51,9 @@ void setup() {
4051 delay (2000 );
4152
4253 Serial.println (" === ExecuTorch Keyword Spotting ===" );
43- Serial.print (" Model size : " );
54+ Serial.print (" Model: " );
4455 Serial.print (model_pte_size);
45- Serial.println (" bytes" );
56+ Serial.println (" bytes (DS-CNN int8, CMSIS-NN) " );
4657
4758 executorch::runtime::runtime_init ();
4859 Serial.println (" Runtime initialized." );
@@ -60,16 +71,23 @@ void loop() {
6071 const char * method_name = nullptr ;
6172 {
6273 auto r = program->get_method_name (0 );
63- if (!r.ok ()) { Serial.println (" ERROR: no methods" ); delay (5000 ); return ; }
74+ if (!r.ok ()) {
75+ Serial.println (" ERROR: no methods" );
76+ delay (5000 );
77+ return ;
78+ }
6479 method_name = *r;
6580 }
6681
6782 auto meta = program->method_meta (method_name);
68- if (!meta.ok ()) { Serial.println (" ERROR: method_meta" ); delay (5000 ); return ; }
83+ if (!meta.ok ()) {
84+ Serial.println (" ERROR: method_meta failed" );
85+ delay (5000 );
86+ return ;
87+ }
6988
7089 MemoryAllocator method_allocator (sizeof (method_pool), method_pool);
7190
72- // Allocate planned buffers
7391 size_t n_planned = meta->num_memory_planned_buffers ();
7492 Span<uint8_t >* spans = static_cast <Span<uint8_t >*>(
7593 method_allocator.allocate (n_planned * sizeof (Span<uint8_t >)));
@@ -85,33 +103,34 @@ void loop() {
85103
86104 auto method = program->load_method (method_name, &mm);
87105 if (!method.ok ()) {
88- Serial.print (" ERROR: load_method failed : 0x" );
106+ Serial.print (" ERROR: load_method: 0x" );
89107 Serial.println ((int )method.error (), HEX );
90108 delay (5000 );
91109 return ;
92110 }
93111
94- // Run inference
95112 Error status = method->execute ();
96113 if (status != Error::Ok) {
97- Serial.print (" ERROR: execute failed : 0x" );
114+ Serial.print (" ERROR: execute: 0x" );
98115 Serial.println ((int )status, HEX );
99116 delay (5000 );
100117 return ;
101118 }
102119
103- // Read output
104120 EValue output;
105121 method->get_outputs (&output, 1 );
106122 if (output.isTensor ()) {
107123 auto tensor = output.toTensor ();
108124 int best = 0 ;
109125 float best_val = -1e9f;
110126 for (int i = 0 ; i < kNumClasses && i < tensor.numel (); i++) {
111- float val = (tensor.scalar_type () == executorch::aten:: ScalarType::Float)
127+ float val = (tensor.scalar_type () == ScalarType::Float)
112128 ? tensor.const_data_ptr <float >()[i]
113129 : static_cast <float >(tensor.const_data_ptr <int8_t >()[i]);
114- if (val > best_val) { best_val = val; best = i; }
130+ if (val > best_val) {
131+ best_val = val;
132+ best = i;
133+ }
115134 }
116135 Serial.print (" Detected: " );
117136 Serial.println (kLabels [best]);
0 commit comments