Skip to content

Commit eeb54c9

Browse files
committed
Address PR review feedback
- Remove deprecated executorch_delegate_EthosUBackend_registered() call; linking executorch_delegate_ethos_u auto-registers the backend - Add model_pte_runtime ISRAM copy for Corstone FVP DMA accessibility - Fix ET_LOG formatting to pass linter (one arg per line) - Add explicit ScalarType::Byte case and error for unsupported types in print_top_k instead of silent uint8 fallback - Add comment explaining ISRAM copy vs direct MRAM access tradeoff
1 parent 8c6093e commit eeb54c9

1 file changed

Lines changed: 84 additions & 47 deletions

File tree

zephyr/samples/mv2-ethosu/src/main.cpp

Lines changed: 84 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@
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+
2835
using executorch::aten::ScalarType;
2936
using executorch::aten::Tensor;
3037
using executorch::aten::TensorImpl;
@@ -43,11 +50,6 @@ using executorch::runtime::Span;
4350
using executorch::runtime::Tag;
4451
using 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, "\nTop-%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

Comments
 (0)