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