xref: /aosp_15_r20/external/executorch/backends/cadence/executor_runner.cpp (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
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 /**
10  * @file
11  *
12  * This is a simple executor_runner that boots up the DSP, configures the serial
13  * port, sends a bunch of test messages to the M33 core and then loads the model
14  * defined in model_pte.h. It runs this model using the ops available in
15  * cadence/ops directory.
16  */
17 
18 #include <fsl_debug_console.h>
19 #include "fsl_device_registers.h"
20 #include "fsl_mu.h"
21 
22 #include "board_hifi4.h"
23 #include "model_pte.h"
24 #include "pin_mux.h"
25 
26 #include <memory>
27 // patternlint-disable executorch-cpp-nostdinc
28 #include <vector>
29 
30 #include <executorch/extension/data_loader/buffer_data_loader.h>
31 #include <executorch/extension/runner_util/inputs.h>
32 #include <executorch/runtime/executor/method.h>
33 #include <executorch/runtime/executor/program.h>
34 #include <executorch/runtime/platform/log.h>
35 #include <executorch/runtime/platform/profiler.h>
36 #include <executorch/runtime/platform/runtime.h>
37 
38 static uint8_t method_allocator_pool[18 * 1024U]; // 4 MB
39 
40 #include <xtensa/config/core.h>
41 
42 #define APP_MU MUB
43 /* Flag indicates Core Boot Up*/
44 #define BOOT_FLAG 0x01U
45 /* Channel transmit and receive register */
46 #define CHN_MU_REG_NUM 0U
47 /* How many message is used to test message sending */
48 #define MSG_LENGTH 32U
49 
50 using executorch::runtime::Error;
51 using executorch::runtime::Result;
52 
53 void LED_INIT();
54 void LED_TOGGLE();
55 
LED_INIT()56 void LED_INIT() {
57   CLOCK_EnableClock(kCLOCK_HsGpio0);
58   RESET_PeripheralReset(kHSGPIO0_RST_SHIFT_RSTn);
59   gpio_pin_config_t pin_config = {kGPIO_DigitalOutput, LOGIC_LED_OFF};
60   GPIO_PinInit(
61       BOARD_LED_RED_GPIO,
62       BOARD_LED_RED_GPIO_PORT,
63       BOARD_LED_RED_GPIO_PIN,
64       &pin_config);
65 }
66 
LED_TOGGLE()67 void LED_TOGGLE() {
68   LED_RED_TOGGLE();
69 }
70 
71 /*!
72  * @brief Function to create delay for Led blink.
73  */
delay(void)74 void delay(void) {
75   volatile uint32_t i = 0;
76   for (i = 0; i < 50000000; ++i) {
77     __NOP();
78   }
79 }
80 
et_pal_emit_log_message(et_timestamp_t timestamp,et_pal_log_level_t level,const char * filename,ET_UNUSED const char * function,size_t line,const char * message,ET_UNUSED size_t length)81 void et_pal_emit_log_message(
82     et_timestamp_t timestamp,
83     et_pal_log_level_t level,
84     const char* filename,
85     ET_UNUSED const char* function,
86     size_t line,
87     const char* message,
88     ET_UNUSED size_t length) {
89   PRINTF("\r%s\n", message);
90 }
91 
main(int argc,char ** argv)92 int main(int argc, char** argv) {
93   /* Init board hardware. */
94   BOARD_InitBootPins();
95 
96   /* Initialize LED */
97   LED_INIT();
98 
99   /* MUB init */
100   MU_Init(APP_MU);
101 
102   /* Send flag to Core 0 to indicate Core 1 has startup */
103   MU_SetFlags(APP_MU, BOOT_FLAG);
104 
105   BOARD_InitDebugConsole();
106   ET_LOG(Info, "Booted up in DSP.");
107 
108   executorch::runtime::runtime_init();
109 
110   auto loader =
111       executorch::extension::BufferDataLoader(model_pte, sizeof(model_pte));
112 
113   Result<executorch::runtime::Program> program =
114       executorch::runtime::Program::load(&loader);
115   if (!program.ok()) {
116     ET_LOG(
117         Error,
118         "ET: Program loading failed @ 0x%p: 0x%" PRIx32,
119         model_pte,
120         program.error());
121   }
122 
123   ET_LOG(
124       Info, "AET: Model buffer loaded, has %u methods", program->num_methods());
125 
126   const char* method_name = nullptr;
127   {
128     const auto method_name_result = program->get_method_name(0);
129     ET_CHECK_MSG(method_name_result.ok(), "Program has no methods");
130     method_name = *method_name_result;
131   }
132   ET_LOG(Info, "ET: Running method %s", method_name);
133 
134   Result<executorch::runtime::MethodMeta> method_meta =
135       program->method_meta(method_name);
136   if (!method_meta.ok()) {
137     ET_LOG(
138         Error,
139         "ET: Failed to get method_meta for %s: 0x%x",
140         method_name,
141         (unsigned int)method_meta.error());
142   }
143 
144   executorch::runtime::MemoryAllocator method_allocator{
145       executorch::runtime::MemoryAllocator(
146           sizeof(method_allocator_pool), method_allocator_pool)};
147 
148   std::vector<std::unique_ptr<uint8_t[]>> planned_buffers; // Owns the memory
149   std::vector<executorch::runtime::Span<uint8_t>>
150       planned_spans; // Passed to the allocator
151   size_t num_memory_planned_buffers = method_meta->num_memory_planned_buffers();
152 
153   for (size_t id = 0; id < num_memory_planned_buffers; ++id) {
154     size_t buffer_size =
155         static_cast<size_t>(method_meta->memory_planned_buffer_size(id).get());
156     ET_LOG(
157         Info, "ET: Setting up planned buffer %zu, size %zu.", id, buffer_size);
158 
159     planned_buffers.push_back(std::make_unique<uint8_t[]>(buffer_size));
160     planned_spans.push_back({planned_buffers.back().get(), buffer_size});
161   }
162 
163   executorch::runtime::HierarchicalAllocator planned_memory(
164       {planned_spans.data(), planned_spans.size()});
165 
166   executorch::runtime::MemoryManager memory_manager(
167       &method_allocator, &planned_memory);
168 
169   Result<executorch::runtime::Method> method =
170       program->load_method(method_name, &memory_manager);
171   if (!method.ok()) {
172     ET_LOG(
173         Error,
174         "Loading of method %s failed with status 0x%" PRIx32,
175         method_name,
176         method.error());
177   }
178 
179   ET_LOG(Info, "Method loaded.");
180   executorch::extension::prepare_input_tensors(*method);
181   ET_LOG(Info, "Starting the model execution...");
182 
183   Error status = method->execute();
184   ET_LOG(Info, "Executed model");
185   if (status != Error::Ok) {
186     ET_LOG(
187         Error,
188         "Execution of method %s failed with status 0x%" PRIx32,
189         method_name,
190         status);
191   } else {
192     ET_LOG(Info, "Model executed successfully.");
193   }
194 
195   std::vector<EValue> outputs(method->outputs_size());
196   status = method->get_outputs(outputs.data(), outputs.size());
197   for (int i = 0; i < outputs.size(); ++i) {
198     float* out_data_ptr = (float*)outputs[i].toTensor().const_data_ptr();
199     ET_LOG(Info, "First 20 elements of output %d", i);
200     for (size_t j = 0; j < 20; j++) {
201       ET_LOG(Info, "%f \n", out_data_ptr[j]);
202     }
203   }
204   delay();
205   LED_TOGGLE();
206 
207   return 0;
208 }
209