2525#include " model_pte.h"
2626#include " mv2_input.h"
2727
28+ // Runtime copy of the model blob so that the Ethos-U DMA can access command
29+ // stream and weights. On Corstone FVP the original model_pte[] lives in flash
30+ // which is not DMA-accessible. On boards where MRAM is DMA-accessible (e.g.
31+ // Alif Ensemble), this copy can be bypassed via board-specific linker config.
32+ alignas (16 ) static unsigned char model_pte_runtime[sizeof (model_pte)];
33+ static bool model_pte_runtime_initialized = false ;
34+
2835using executorch::aten::ScalarType;
2936using executorch::aten::Tensor;
3037using executorch::aten::TensorImpl;
@@ -43,11 +50,6 @@ using executorch::runtime::Span;
4350using executorch::runtime::Tag;
4451using executorch::runtime::TensorInfo;
4552
46- #if defined(CONFIG_ARM_ETHOS_U)
47- extern " C" executorch::runtime::Error
48- executorch_delegate_EthosUBackend_registered (void );
49- #endif
50-
5153#if !defined(ET_ARM_METHOD_ALLOCATOR_POOL_SIZE)
5254#define ET_ARM_METHOD_ALLOCATOR_POOL_SIZE (1572864 )
5355#endif
@@ -126,21 +128,27 @@ Result<BufferCleanup> prepare_input_tensors(
126128 num_elements *= sizes[k];
127129 }
128130
129- ET_LOG (Info, " Input tensor: scalar_type=%s, numel=%lu, nbytes=%lu" ,
130- executorch::runtime::toString (scalar_type),
131- static_cast <unsigned long >(num_elements),
132- static_cast <unsigned long >(tensor_meta->nbytes ()));
131+ ET_LOG (
132+ Info,
133+ " Input tensor: scalar_type=%s, numel=%lu, nbytes=%lu" ,
134+ executorch::runtime::toString (scalar_type),
135+ static_cast <unsigned long >(num_elements),
136+ static_cast <unsigned long >(tensor_meta->nbytes ()));
133137
134138 if (scalar_type == ScalarType::Float && input_size == num_elements) {
135- ET_LOG (Info, " Converting uint8 input (%lu elements) to float32" ,
136- static_cast <unsigned long >(input_size));
139+ ET_LOG (
140+ Info,
141+ " Converting uint8 input (%lu elements) to float32" ,
142+ static_cast <unsigned long >(input_size));
137143 float * float_data = static_cast <float *>(data_ptr);
138144 for (size_t j = 0 ; j < input_size; j++) {
139145 float_data[j] = (static_cast <float >(input_data[j]) - 128 .0f ) / 128 .0f ;
140146 }
141147 } else if (input_size == tensor_meta->nbytes ()) {
142- ET_LOG (Info, " Copying input data to tensor (%lu bytes)" ,
143- static_cast <unsigned long >(input_size));
148+ ET_LOG (
149+ Info,
150+ " Copying input data to tensor (%lu bytes)" ,
151+ static_cast <unsigned long >(input_size));
144152 std::memcpy (data_ptr, input_data, input_size);
145153 } else {
146154 ET_LOG (
@@ -185,9 +193,11 @@ void print_top_k(const std::vector<EValue>& outputs) {
185193 ScalarType scalar_type = output_tensor.scalar_type ();
186194 size_t num_classes = output_tensor.numel ();
187195
188- ET_LOG (Info, " Output tensor: scalar_type=%s, numel=%lu" ,
189- executorch::runtime::toString (scalar_type),
190- static_cast <unsigned long >(num_classes));
196+ ET_LOG (
197+ Info,
198+ " Output tensor: scalar_type=%s, numel=%lu" ,
199+ executorch::runtime::toString (scalar_type),
200+ static_cast <unsigned long >(num_classes));
191201
192202 int top_indices[MV2_TOP_K ] = {0 };
193203 float top_values[MV2_TOP_K ];
@@ -208,9 +218,15 @@ void print_top_k(const std::vector<EValue>& outputs) {
208218 case ScalarType::Char:
209219 val = static_cast <float >(output_tensor.const_data_ptr <int8_t >()[i]);
210220 break ;
211- default :
221+ case ScalarType::Byte :
212222 val = static_cast <float >(output_tensor.const_data_ptr <uint8_t >()[i]);
213223 break ;
224+ default :
225+ ET_LOG (
226+ Error,
227+ " Unsupported output scalar type: %s" ,
228+ executorch::runtime::toString (scalar_type));
229+ return ;
214230 }
215231
216232 for (int j = 0 ; j < MV2_TOP_K ; j++) {
@@ -228,8 +244,12 @@ void print_top_k(const std::vector<EValue>& outputs) {
228244
229245 ET_LOG (Info, " \n Top-%d predictions:" , MV2_TOP_K );
230246 for (int j = 0 ; j < MV2_TOP_K ; j++) {
231- ET_LOG (Info, " [%d] class %d: %.4f" ,
232- j + 1 , top_indices[j], static_cast <double >(top_values[j]));
247+ ET_LOG (
248+ Info,
249+ " [%d] class %d: %.4f" ,
250+ j + 1 ,
251+ top_indices[j],
252+ static_cast <double >(top_values[j]));
233253 }
234254}
235255
@@ -240,26 +260,27 @@ int main(void) {
240260 printk (" ExecuTorch MobileNetV2 Classification Demo\n " );
241261 printk (" ========================================\n\n " );
242262
243- #if defined(CONFIG_ARM_ETHOS_U)
244- if (executorch_delegate_EthosUBackend_registered () != Error::Ok) {
245- ET_LOG (Error, " Ethos-U backend registration failed" );
246- return 1 ;
247- }
248- ET_LOG (Info, " Ethos-U backend registered successfully" );
249- #endif
250-
251263 executorch::runtime::runtime_init ();
252264
253265 size_t pte_size = sizeof (model_pte);
254- ET_LOG (Info, " Model PTE at %p, Size: %lu bytes" ,
255- model_pte, static_cast <unsigned long >(pte_size));
256-
257- const void * program_data = model_pte;
266+ ET_LOG (
267+ Info,
268+ " Model PTE at %p, Size: %lu bytes" ,
269+ model_pte,
270+ static_cast <unsigned long >(pte_size));
271+
272+ if (!model_pte_runtime_initialized) {
273+ std::memcpy (model_pte_runtime, model_pte, sizeof (model_pte));
274+ model_pte_runtime_initialized = true ;
275+ }
276+ const void * program_data = model_pte_runtime;
258277 size_t program_data_len = pte_size;
259278
260279 auto loader = BufferDataLoader (program_data, program_data_len);
261- ET_LOG (Info, " Model data loaded. Size: %lu bytes." ,
262- static_cast <unsigned long >(program_data_len));
280+ ET_LOG (
281+ Info,
282+ " Model data loaded. Size: %lu bytes." ,
283+ static_cast <unsigned long >(program_data_len));
263284
264285 Result<Program> program = Program::load (&loader);
265286 if (!program.ok ()) {
@@ -271,8 +292,10 @@ int main(void) {
271292 return 1 ;
272293 }
273294
274- ET_LOG (Info, " Model loaded, has %lu methods" ,
275- static_cast <unsigned long >(program->num_methods ()));
295+ ET_LOG (
296+ Info,
297+ " Model loaded, has %lu methods" ,
298+ static_cast <unsigned long >(program->num_methods ()));
276299
277300 const char * method_name = nullptr ;
278301 {
@@ -292,8 +315,10 @@ int main(void) {
292315 return 1 ;
293316 }
294317
295- ET_LOG (Info, " Method allocator pool size: %lu bytes." ,
296- static_cast <unsigned long >(method_allocation_pool_size));
318+ ET_LOG (
319+ Info,
320+ " Method allocator pool size: %lu bytes." ,
321+ static_cast <unsigned long >(method_allocation_pool_size));
297322
298323 ArmMemoryAllocator method_allocator (
299324 method_allocation_pool_size, method_allocation_pool);
@@ -305,9 +330,11 @@ int main(void) {
305330 for (size_t id = 0 ; id < num_memory_planned_buffers; ++id) {
306331 size_t buffer_size =
307332 static_cast <size_t >(method_meta->memory_planned_buffer_size (id).get ());
308- ET_LOG (Info, " Setting up planned buffer %lu, size %lu." ,
309- static_cast <unsigned long >(id),
310- static_cast <unsigned long >(buffer_size));
333+ ET_LOG (
334+ Info,
335+ " Setting up planned buffer %lu, size %lu." ,
336+ static_cast <unsigned long >(id),
337+ static_cast <unsigned long >(buffer_size));
311338
312339 uint8_t * buffer =
313340 reinterpret_cast <uint8_t *>(method_allocator.allocate (buffer_size));
@@ -344,8 +371,10 @@ int main(void) {
344371 }
345372 ET_LOG (Info, " Method '%s' loaded successfully" , method_name);
346373
347- ET_LOG (Info, " Preparing input: static RGB image (%lu bytes)" ,
348- static_cast <unsigned long >(sizeof (mv2_input_data)));
374+ ET_LOG (
375+ Info,
376+ " Preparing input: static RGB image (%lu bytes)" ,
377+ static_cast <unsigned long >(sizeof (mv2_input_data)));
349378
350379 {
351380 static auto prepared_inputs = ::prepare_input_tensors (
@@ -386,11 +415,19 @@ int main(void) {
386415
387416 ET_LOG (Info, " \n ========================================" );
388417 ET_LOG (Info, " MobileNetV2 Demo Complete" );
389- ET_LOG (Info, " Model size: %lu bytes" , static_cast <unsigned long >(pte_size));
390- ET_LOG (Info, " Input: 224x224x3 RGB image (%lu bytes)" ,
391- static_cast <unsigned long >(sizeof (mv2_input_data)));
392- ET_LOG (Info, " Output: %d ImageNet classes (top-%d shown)" ,
393- MV2_NUM_OUTPUT_CLASSES , MV2_TOP_K );
418+ ET_LOG (
419+ Info,
420+ " Model size: %lu bytes" ,
421+ static_cast <unsigned long >(pte_size));
422+ ET_LOG (
423+ Info,
424+ " Input: 224x224x3 RGB image (%lu bytes)" ,
425+ static_cast <unsigned long >(sizeof (mv2_input_data)));
426+ ET_LOG (
427+ Info,
428+ " Output: %d ImageNet classes (top-%d shown)" ,
429+ MV2_NUM_OUTPUT_CLASSES ,
430+ MV2_TOP_K );
394431 ET_LOG (Info, " Inference time: %u ms" , inference_time);
395432 ET_LOG (Info, " ========================================\n " );
396433
0 commit comments