blob: 66623f96677513b0a1cf74d8153f08c392922e33 [file] [log] [blame]
Yulia Garbovichf61ea352021-11-11 14:16:57 +02001/*
Kristofer Jonssonac535f02022-03-10 11:08:39 +01002 * Copyright (c) 2020-2022 Arm Limited.
Yulia Garbovichf61ea352021-11-11 14:16:57 +02003 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the License); you may
7 * not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#include "message_handler.hpp"
20
21#include "cmsis_compiler.h"
22
23#ifdef ETHOSU
24#include <ethosu_driver.h>
Kristofer Jonsson5410db12022-01-27 17:39:06 +010025#include <pmu_ethosu.h>
Yulia Garbovichf61ea352021-11-11 14:16:57 +020026#endif
27
28#include "FreeRTOS.h"
29#include "queue.h"
30#include "semphr.h"
31
32#include <cstring>
Kristofer Jonssonac535f02022-03-10 11:08:39 +010033#include <vector>
Yulia Garbovichf61ea352021-11-11 14:16:57 +020034
35using namespace EthosU;
36using namespace MessageQueue;
37
38namespace MessageHandler {
39
40/****************************************************************************
41 * IncomingMessageHandler
42 ****************************************************************************/
43
Davide Grohmann160001c2022-03-24 15:38:27 +010044IncomingMessageHandler::IncomingMessageHandler(
45 EthosU::ethosu_core_queue &_inputMessageQueue,
46 EthosU::ethosu_core_queue &_outputMessageQueue,
47 Mailbox::Mailbox &_mailbox,
48 std::shared_ptr<Queue<EthosU::ethosu_core_inference_req>> _inferenceInputQueue,
49 QueueHandle_t _inferenceOutputQueue,
Davide Grohmann144b2d22022-05-31 15:24:02 +020050 SemaphoreHandle_t _messageNotify,
51 std::shared_ptr<Networks> _networks) :
Davide Grohmann134c39e2022-04-25 12:21:12 +020052 inputMessageQueue(_inputMessageQueue),
53 outputMessageQueue(_outputMessageQueue), mailbox(_mailbox), inferenceInputQueue(_inferenceInputQueue),
Davide Grohmann144b2d22022-05-31 15:24:02 +020054 inferenceOutputQueue(_inferenceOutputQueue), messageNotify(_messageNotify), networks(_networks) {
Yulia Garbovichf61ea352021-11-11 14:16:57 +020055 mailbox.registerCallback(handleIrq, reinterpret_cast<void *>(this));
Davide Grohmann134c39e2022-04-25 12:21:12 +020056 readCapabilties(capabilities);
Yulia Garbovichf61ea352021-11-11 14:16:57 +020057}
58
59void IncomingMessageHandler::run() {
60 while (true) {
61 // Wait for event
Davide Grohmann134c39e2022-04-25 12:21:12 +020062 xSemaphoreTake(messageNotify, portMAX_DELAY);
Yulia Garbovichf61ea352021-11-11 14:16:57 +020063
Davide Grohmann134c39e2022-04-25 12:21:12 +020064 // Handle all inference outputs and all messages in queue
65 while (handleInferenceOutput() || handleMessage()) {}
Yulia Garbovichf61ea352021-11-11 14:16:57 +020066 }
67}
68
69void IncomingMessageHandler::handleIrq(void *userArg) {
Davide Grohmann134c39e2022-04-25 12:21:12 +020070 if (userArg == nullptr) {
71 return;
72 }
Yulia Garbovichf61ea352021-11-11 14:16:57 +020073 IncomingMessageHandler *_this = reinterpret_cast<IncomingMessageHandler *>(userArg);
Davide Grohmann160001c2022-03-24 15:38:27 +010074 xSemaphoreGiveFromISR(_this->messageNotify, nullptr);
Yulia Garbovichf61ea352021-11-11 14:16:57 +020075}
76
Davide Grohmann134c39e2022-04-25 12:21:12 +020077void IncomingMessageHandler::sendErrorAndResetQueue(ethosu_core_msg_err_type type, const char *message) {
78 ethosu_core_msg_err error;
79 error.type = type;
Yulia Garbovichf61ea352021-11-11 14:16:57 +020080
Davide Grohmann134c39e2022-04-25 12:21:12 +020081 for (size_t i = 0; i < sizeof(error.msg) && message[i]; i++) {
82 error.msg[i] = message[i];
83 }
84 printf("ERROR: Msg: \"%s\"\n", error.msg);
85
86 if (!outputMessageQueue.write(ETHOSU_CORE_MSG_ERR, error)) {
87 printf("ERROR: Msg: Failed to write error response. No mailbox message sent\n");
88 } else {
89 mailbox.sendMessage();
90 }
91 inputMessageQueue.reset();
92}
93
94bool IncomingMessageHandler::handleInferenceOutput() {
95 struct ethosu_core_inference_rsp rsp;
96 if (pdTRUE != xQueueReceive(inferenceOutputQueue, &rsp, 0)) {
97 return false;
Yulia Garbovichf61ea352021-11-11 14:16:57 +020098 }
99
Davide Grohmann134c39e2022-04-25 12:21:12 +0200100 sendInferenceRsp(rsp);
101 return true;
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200102}
103
104bool IncomingMessageHandler::handleMessage() {
105 struct ethosu_core_msg msg;
106
Davide Grohmann134c39e2022-04-25 12:21:12 +0200107 if (inputMessageQueue.available() == 0) {
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200108 return false;
109 }
110
111 // Read msg header
112 // Only process a complete message header, else send error message
113 // and reset queue
Davide Grohmann134c39e2022-04-25 12:21:12 +0200114 if (!inputMessageQueue.read(msg)) {
115 sendErrorAndResetQueue(ETHOSU_CORE_MSG_ERR_INVALID_SIZE, "Failed to read a complete header");
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200116 return false;
117 }
118
119 printf("Msg: header magic=%" PRIX32 ", type=%" PRIu32 ", length=%" PRIu32 "\n", msg.magic, msg.type, msg.length);
120
121 if (msg.magic != ETHOSU_CORE_MSG_MAGIC) {
122 printf("Msg: Invalid Magic\n");
Davide Grohmann134c39e2022-04-25 12:21:12 +0200123 sendErrorAndResetQueue(ETHOSU_CORE_MSG_ERR_INVALID_MAGIC, "Invalid magic");
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200124 return false;
125 }
126
127 switch (msg.type) {
128 case ETHOSU_CORE_MSG_PING: {
129 printf("Msg: Ping\n");
Davide Grohmann134c39e2022-04-25 12:21:12 +0200130 sendPong();
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200131 break;
132 }
133 case ETHOSU_CORE_MSG_ERR: {
134 ethosu_core_msg_err error;
Davide Grohmann134c39e2022-04-25 12:21:12 +0200135 if (!inputMessageQueue.read(error)) {
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200136 printf("ERROR: Msg: Failed to receive error message\n");
137 } else {
138 printf("Msg: Received an error response, type=%" PRIu32 ", msg=\"%s\"\n", error.type, error.msg);
139 }
140
Davide Grohmann134c39e2022-04-25 12:21:12 +0200141 inputMessageQueue.reset();
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200142 return false;
143 }
144 case ETHOSU_CORE_MSG_VERSION_REQ: {
145 printf("Msg: Version request\n");
Davide Grohmann134c39e2022-04-25 12:21:12 +0200146 sendVersionRsp();
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200147 break;
148 }
149 case ETHOSU_CORE_MSG_CAPABILITIES_REQ: {
Davide Grohmann134c39e2022-04-25 12:21:12 +0200150 ethosu_core_capabilities_req req;
151 if (!inputMessageQueue.read(req)) {
152 sendErrorAndResetQueue(ETHOSU_CORE_MSG_ERR_INVALID_PAYLOAD, "CapabilitiesReq. Failed to read payload");
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200153 break;
154 }
155
Davide Grohmann134c39e2022-04-25 12:21:12 +0200156 printf("Msg: Capabilities request.user_arg=0x%" PRIx64 "\n", req.user_arg);
157 sendCapabilitiesRsp(req.user_arg);
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200158 break;
159 }
160 case ETHOSU_CORE_MSG_INFERENCE_REQ: {
Davide Grohmann134c39e2022-04-25 12:21:12 +0200161 ethosu_core_inference_req req;
162 if (!inputMessageQueue.read(req)) {
163 sendErrorAndResetQueue(ETHOSU_CORE_MSG_ERR_INVALID_PAYLOAD, "InferenceReq. Failed to read payload");
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200164 break;
165 }
166
Davide Grohmann134c39e2022-04-25 12:21:12 +0200167 printf("Msg: InferenceReq. user_arg=0x%" PRIx64 ", network_type=%" PRIu32 ", ", req.user_arg, req.network.type);
Kristofer Jonsson585ce692022-03-08 13:28:05 +0100168
Davide Grohmann134c39e2022-04-25 12:21:12 +0200169 if (req.network.type == ETHOSU_CORE_NETWORK_BUFFER) {
170 printf("network.buffer={0x%" PRIx32 ", %" PRIu32 "},\n", req.network.buffer.ptr, req.network.buffer.size);
Kristofer Jonsson585ce692022-03-08 13:28:05 +0100171 } else {
Davide Grohmann134c39e2022-04-25 12:21:12 +0200172 printf("network.index=%" PRIu32 ",\n", req.network.index);
Kristofer Jonsson585ce692022-03-08 13:28:05 +0100173 }
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200174
Davide Grohmann134c39e2022-04-25 12:21:12 +0200175 printf("ifm_count=%" PRIu32 ", ifm=[", req.ifm_count);
176 for (uint32_t i = 0; i < req.ifm_count; ++i) {
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200177 if (i > 0) {
178 printf(", ");
179 }
180
Davide Grohmann134c39e2022-04-25 12:21:12 +0200181 printf("{0x%" PRIx32 ", %" PRIu32 "}", req.ifm[i].ptr, req.ifm[i].size);
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200182 }
183 printf("]");
184
Davide Grohmann134c39e2022-04-25 12:21:12 +0200185 printf(", ofm_count=%" PRIu32 ", ofm=[", req.ofm_count);
186 for (uint32_t i = 0; i < req.ofm_count; ++i) {
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200187 if (i > 0) {
188 printf(", ");
189 }
190
Davide Grohmann134c39e2022-04-25 12:21:12 +0200191 printf("{0x%" PRIx32 ", %" PRIu32 "}", req.ofm[i].ptr, req.ofm[i].size);
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200192 }
193 printf("]\n");
194
Davide Grohmann160001c2022-03-24 15:38:27 +0100195 if (!inferenceInputQueue->push(req)) {
Davide Grohmann134c39e2022-04-25 12:21:12 +0200196 printf("Msg: Inference queue full. Rejecting inference user_arg=0x%" PRIx64 "\n", req.user_arg);
197 sendFailedInferenceRsp(req.user_arg, ETHOSU_CORE_STATUS_REJECTED);
198 }
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200199 break;
200 }
Davide Grohmann00de9ee2022-03-23 14:59:56 +0100201 case ETHOSU_CORE_MSG_CANCEL_INFERENCE_REQ: {
202 ethosu_core_cancel_inference_req req;
203 if (!inputMessageQueue.read(req)) {
204 sendErrorAndResetQueue(ETHOSU_CORE_MSG_ERR_INVALID_PAYLOAD, "CancelInferenceReq. Failed to read payload");
205 break;
206 }
207 printf("Msg: CancelInferenceReq. user_arg=0x%" PRIx64 ", inference_handle=0x%" PRIx64 "\n",
208 req.user_arg,
209 req.inference_handle);
210
Davide Grohmann160001c2022-03-24 15:38:27 +0100211 bool found =
212 inferenceInputQueue->erase([req](auto &inf_req) { return inf_req.user_arg == req.inference_handle; });
213
214 // NOTE: send an inference response with status ABORTED if the inference has been droped from the queue
215 if (found) {
216 sendFailedInferenceRsp(req.inference_handle, ETHOSU_CORE_STATUS_ABORTED);
217 }
218
219 sendCancelInferenceRsp(req.user_arg, found ? ETHOSU_CORE_STATUS_OK : ETHOSU_CORE_STATUS_ERROR);
Davide Grohmann00de9ee2022-03-23 14:59:56 +0100220 break;
221 }
Kristofer Jonssonac535f02022-03-10 11:08:39 +0100222 case ETHOSU_CORE_MSG_NETWORK_INFO_REQ: {
223 ethosu_core_network_info_req req;
Davide Grohmann134c39e2022-04-25 12:21:12 +0200224 if (!inputMessageQueue.read(req)) {
225 sendErrorAndResetQueue(ETHOSU_CORE_MSG_ERR_INVALID_PAYLOAD, "NetworkInfoReq. Failed to read payload");
Kristofer Jonssonac535f02022-03-10 11:08:39 +0100226 break;
227 }
228
229 printf("Msg: NetworkInfoReq. user_arg=0x%" PRIx64 "\n", req.user_arg);
Davide Grohmann134c39e2022-04-25 12:21:12 +0200230 sendNetworkInfoRsp(req.user_arg, req.network);
Kristofer Jonssonac535f02022-03-10 11:08:39 +0100231 break;
232 }
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200233 default: {
234 char errMsg[128];
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200235 snprintf(&errMsg[0],
236 sizeof(errMsg),
237 "Msg: Unknown type: %" PRIu32 " with payload length %" PRIu32 " bytes\n",
238 msg.type,
239 msg.length);
240
Davide Grohmann134c39e2022-04-25 12:21:12 +0200241 sendErrorAndResetQueue(ETHOSU_CORE_MSG_ERR_UNSUPPORTED_TYPE, errMsg);
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200242 return false;
243 }
244 }
245
246 return true;
247}
248
Davide Grohmann134c39e2022-04-25 12:21:12 +0200249void IncomingMessageHandler::sendPong() {
250 if (!outputMessageQueue.write(ETHOSU_CORE_MSG_PONG)) {
251 printf("ERROR: Msg: Failed to write pong response. No mailbox message sent\n");
252 } else {
253 mailbox.sendMessage();
254 }
255}
256
257void IncomingMessageHandler::sendVersionRsp() {
258 ethosu_core_msg_version version = {
259 ETHOSU_CORE_MSG_VERSION_MAJOR,
260 ETHOSU_CORE_MSG_VERSION_MINOR,
261 ETHOSU_CORE_MSG_VERSION_PATCH,
262 0,
263 };
264
265 if (!outputMessageQueue.write(ETHOSU_CORE_MSG_VERSION_RSP, version)) {
266 printf("ERROR: Failed to write version response. No mailbox message sent\n");
267 } else {
268 mailbox.sendMessage();
269 }
270}
271
272void IncomingMessageHandler::sendCapabilitiesRsp(uint64_t userArg) {
273 capabilities.user_arg = userArg;
274
275 if (!outputMessageQueue.write(ETHOSU_CORE_MSG_CAPABILITIES_RSP, capabilities)) {
276 printf("ERROR: Failed to write capabilities response. No mailbox message sent\n");
277 } else {
278 mailbox.sendMessage();
279 }
280}
281
282void IncomingMessageHandler::sendNetworkInfoRsp(uint64_t userArg, ethosu_core_network_buffer &network) {
283 ethosu_core_network_info_rsp rsp;
284 rsp.user_arg = userArg;
285 rsp.ifm_count = 0;
286 rsp.ofm_count = 0;
287
288 void *buffer;
289 size_t size;
Per Ã…strand41999352022-05-18 09:09:01 +0200290
Davide Grohmann144b2d22022-05-31 15:24:02 +0200291 bool failed = networks->getNetwork(network, buffer, size);
Per Ã…strand41999352022-05-18 09:09:01 +0200292
293 if (!failed) {
294 failed = parser.parseModel(buffer,
Davide Grohmannf4379e92022-06-15 11:20:41 +0200295 size,
Per Ã…strand41999352022-05-18 09:09:01 +0200296 rsp.desc,
297 InferenceProcess::makeArray(rsp.ifm_size, rsp.ifm_count, ETHOSU_CORE_BUFFER_MAX),
298 InferenceProcess::makeArray(rsp.ofm_size, rsp.ofm_count, ETHOSU_CORE_BUFFER_MAX));
299 }
300 rsp.status = failed ? ETHOSU_CORE_STATUS_ERROR : ETHOSU_CORE_STATUS_OK;
Davide Grohmann134c39e2022-04-25 12:21:12 +0200301
302 if (!outputMessageQueue.write(ETHOSU_CORE_MSG_NETWORK_INFO_RSP, rsp)) {
303 printf("ERROR: Msg: Failed to write network info response. No mailbox message sent\n");
304 } else {
305 mailbox.sendMessage();
306 }
307}
308
309void IncomingMessageHandler::sendInferenceRsp(ethosu_core_inference_rsp &rsp) {
310 if (!outputMessageQueue.write(ETHOSU_CORE_MSG_INFERENCE_RSP, rsp)) {
311 printf("ERROR: Msg: Failed to write inference response. No mailbox message sent\n");
312 } else {
313 mailbox.sendMessage();
314 }
315}
316
317void IncomingMessageHandler::sendFailedInferenceRsp(uint64_t userArg, uint32_t status) {
318 ethosu_core_inference_rsp rsp;
319 rsp.user_arg = userArg;
320 rsp.status = status;
321 if (!outputMessageQueue.write(ETHOSU_CORE_MSG_INFERENCE_RSP, rsp)) {
322 printf("ERROR: Msg: Failed to write inference response. No mailbox message sent\n");
323 } else {
324 mailbox.sendMessage();
325 }
326}
Davide Grohmann00de9ee2022-03-23 14:59:56 +0100327void IncomingMessageHandler::sendCancelInferenceRsp(uint64_t userArg, uint32_t status) {
328 ethosu_core_cancel_inference_rsp cancellation;
329 cancellation.user_arg = userArg;
330 cancellation.status = status;
331 if (!outputMessageQueue.write(ETHOSU_CORE_MSG_CANCEL_INFERENCE_RSP, cancellation)) {
332 printf("ERROR: Msg: Failed to write cancel inference response. No mailbox message sent\n");
333 } else {
334 mailbox.sendMessage();
335 }
336}
Davide Grohmann134c39e2022-04-25 12:21:12 +0200337
338void IncomingMessageHandler::readCapabilties(ethosu_core_msg_capabilities_rsp &rsp) {
339 rsp = {};
340
341#ifdef ETHOSU
342 struct ethosu_driver_version version;
343 ethosu_get_driver_version(&version);
344
345 struct ethosu_hw_info info;
346 struct ethosu_driver *drv = ethosu_reserve_driver();
347 ethosu_get_hw_info(drv, &info);
348 ethosu_release_driver(drv);
349
350 rsp.user_arg = 0;
351 rsp.version_status = info.version.version_status;
352 rsp.version_minor = info.version.version_minor;
353 rsp.version_major = info.version.version_major;
354 rsp.product_major = info.version.product_major;
355 rsp.arch_patch_rev = info.version.arch_patch_rev;
356 rsp.arch_minor_rev = info.version.arch_minor_rev;
357 rsp.arch_major_rev = info.version.arch_major_rev;
358 rsp.driver_patch_rev = version.patch;
359 rsp.driver_minor_rev = version.minor;
360 rsp.driver_major_rev = version.major;
361 rsp.macs_per_cc = info.cfg.macs_per_cc;
362 rsp.cmd_stream_version = info.cfg.cmd_stream_version;
363 rsp.custom_dma = info.cfg.custom_dma;
364#endif
365}
366
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200367/****************************************************************************
368 * InferenceHandler
369 ****************************************************************************/
370
Davide Grohmann160001c2022-03-24 15:38:27 +0100371InferenceHandler::InferenceHandler(uint8_t *tensorArena,
372 size_t arenaSize,
373 std::shared_ptr<Queue<EthosU::ethosu_core_inference_req>> _inferenceInputQueue,
Davide Grohmann134c39e2022-04-25 12:21:12 +0200374 QueueHandle_t _inferenceOutputQueue,
Davide Grohmann144b2d22022-05-31 15:24:02 +0200375 SemaphoreHandle_t _messageNotify,
376 std::shared_ptr<Networks> _networks) :
Davide Grohmann134c39e2022-04-25 12:21:12 +0200377 inferenceInputQueue(_inferenceInputQueue),
Davide Grohmann144b2d22022-05-31 15:24:02 +0200378 inferenceOutputQueue(_inferenceOutputQueue), messageNotify(_messageNotify), inference(tensorArena, arenaSize),
379 networks(_networks) {}
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200380
381void InferenceHandler::run() {
Davide Grohmann134c39e2022-04-25 12:21:12 +0200382 ethosu_core_inference_req req;
383 ethosu_core_inference_rsp rsp;
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200384
Davide Grohmann134c39e2022-04-25 12:21:12 +0200385 while (true) {
Davide Grohmann160001c2022-03-24 15:38:27 +0100386 inferenceInputQueue->pop(req);
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200387
Davide Grohmann134c39e2022-04-25 12:21:12 +0200388 runInference(req, rsp);
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200389
Davide Grohmann134c39e2022-04-25 12:21:12 +0200390 xQueueSend(inferenceOutputQueue, &rsp, portMAX_DELAY);
391 xSemaphoreGive(messageNotify);
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200392 }
393}
394
395void InferenceHandler::runInference(ethosu_core_inference_req &req, ethosu_core_inference_rsp &rsp) {
Kristofer Jonsson5410db12022-01-27 17:39:06 +0100396 currentReq = &req;
397 currentRsp = &rsp;
398
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200399 /*
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200400 * Run inference
401 */
402
Kristofer Jonsson585ce692022-03-08 13:28:05 +0100403 InferenceProcess::InferenceJob job;
404 bool failed = getInferenceJob(req, job);
405
406 if (!failed) {
407 job.invalidate();
408 failed = inference.runJob(job);
409 job.clean();
410 }
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200411
Davide Grohmannadc908c2022-02-16 13:13:27 +0100412#if defined(ETHOSU)
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200413 /*
Kristofer Jonsson47f556a2022-02-02 12:11:22 +0100414 * Print PMU counters
415 */
416
Kristofer Jonsson585ce692022-03-08 13:28:05 +0100417 if (!failed) {
418 const int numEvents = std::min(static_cast<int>(ETHOSU_PMU_Get_NumEventCounters()), ETHOSU_CORE_PMU_MAX);
Kristofer Jonsson47f556a2022-02-02 12:11:22 +0100419
Kristofer Jonsson585ce692022-03-08 13:28:05 +0100420 for (int i = 0; i < numEvents; i++) {
421 printf("ethosu_pmu_cntr%d : %" PRIu32 "\n", i, rsp.pmu_event_count[i]);
422 }
Kristofer Jonsson47f556a2022-02-02 12:11:22 +0100423
Kristofer Jonsson585ce692022-03-08 13:28:05 +0100424 if (rsp.pmu_cycle_counter_enable) {
425 printf("ethosu_pmu_cycle_cntr : %" PRIu64 " cycles\n", rsp.pmu_cycle_counter_count);
426 }
Kristofer Jonsson47f556a2022-02-02 12:11:22 +0100427 }
Davide Grohmannadc908c2022-02-16 13:13:27 +0100428#endif
Kristofer Jonsson47f556a2022-02-02 12:11:22 +0100429
430 /*
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200431 * Send inference response
432 */
433
434 rsp.user_arg = req.user_arg;
435 rsp.ofm_count = job.output.size();
436 rsp.status = failed ? ETHOSU_CORE_STATUS_ERROR : ETHOSU_CORE_STATUS_OK;
437
438 for (size_t i = 0; i < job.output.size(); ++i) {
439 rsp.ofm_size[i] = job.output[i].size;
440 }
441
Kristofer Jonsson5410db12022-01-27 17:39:06 +0100442 currentReq = nullptr;
443 currentRsp = nullptr;
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200444}
445
Kristofer Jonsson585ce692022-03-08 13:28:05 +0100446bool InferenceHandler::getInferenceJob(const ethosu_core_inference_req &req, InferenceProcess::InferenceJob &job) {
Davide Grohmann144b2d22022-05-31 15:24:02 +0200447 bool failed = networks->getNetwork(req.network, job.networkModel.data, job.networkModel.size);
Kristofer Jonsson585ce692022-03-08 13:28:05 +0100448 if (failed) {
449 return true;
450 }
451
452 for (uint32_t i = 0; i < req.ifm_count; ++i) {
453 job.input.push_back(InferenceProcess::DataPtr(reinterpret_cast<void *>(req.ifm[i].ptr), req.ifm[i].size));
454 }
455
456 for (uint32_t i = 0; i < req.ofm_count; ++i) {
457 job.output.push_back(InferenceProcess::DataPtr(reinterpret_cast<void *>(req.ofm[i].ptr), req.ofm[i].size));
458 }
459
460 job.externalContext = this;
461
462 return false;
463}
464
Yulia Garbovichf61ea352021-11-11 14:16:57 +0200465} // namespace MessageHandler
Kristofer Jonsson5410db12022-01-27 17:39:06 +0100466
Davide Grohmannadc908c2022-02-16 13:13:27 +0100467#if defined(ETHOSU)
Kristofer Jonsson5410db12022-01-27 17:39:06 +0100468extern "C" void ethosu_inference_begin(struct ethosu_driver *drv, void *userArg) {
469 MessageHandler::InferenceHandler *self = static_cast<MessageHandler::InferenceHandler *>(userArg);
470
471 // Calculate maximum number of events
472 const int numEvents = std::min(static_cast<int>(ETHOSU_PMU_Get_NumEventCounters()), ETHOSU_CORE_PMU_MAX);
473
474 // Enable PMU
475 ETHOSU_PMU_Enable(drv);
476
477 // Configure and enable events
478 for (int i = 0; i < numEvents; i++) {
479 ETHOSU_PMU_Set_EVTYPER(drv, i, static_cast<ethosu_pmu_event_type>(self->currentReq->pmu_event_config[i]));
480 ETHOSU_PMU_CNTR_Enable(drv, 1 << i);
481 }
482
483 // Enable cycle counter
484 if (self->currentReq->pmu_cycle_counter_enable) {
Kristofer Jonssonb9d7ded2022-02-04 13:10:04 +0100485 ETHOSU_PMU_PMCCNTR_CFG_Set_Stop_Event(drv, ETHOSU_PMU_NPU_IDLE);
486 ETHOSU_PMU_PMCCNTR_CFG_Set_Start_Event(drv, ETHOSU_PMU_NPU_ACTIVE);
487
Kristofer Jonsson5410db12022-01-27 17:39:06 +0100488 ETHOSU_PMU_CNTR_Enable(drv, ETHOSU_PMU_CCNT_Msk);
489 ETHOSU_PMU_CYCCNT_Reset(drv);
490 }
491
492 // Reset all counters
493 ETHOSU_PMU_EVCNTR_ALL_Reset(drv);
494}
495
496extern "C" void ethosu_inference_end(struct ethosu_driver *drv, void *userArg) {
497 MessageHandler::InferenceHandler *self = static_cast<MessageHandler::InferenceHandler *>(userArg);
498
499 // Get cycle counter
500 self->currentRsp->pmu_cycle_counter_enable = self->currentReq->pmu_cycle_counter_enable;
501 if (self->currentReq->pmu_cycle_counter_enable) {
502 self->currentRsp->pmu_cycle_counter_count = ETHOSU_PMU_Get_CCNTR(drv);
503 }
504
505 // Calculate maximum number of events
506 const int numEvents = std::min(static_cast<int>(ETHOSU_PMU_Get_NumEventCounters()), ETHOSU_CORE_PMU_MAX);
507
508 // Get event counters
509 int i;
510 for (i = 0; i < numEvents; i++) {
511 self->currentRsp->pmu_event_config[i] = self->currentReq->pmu_event_config[i];
512 self->currentRsp->pmu_event_count[i] = ETHOSU_PMU_Get_EVCNTR(drv, i);
513 }
514
515 for (; i < ETHOSU_CORE_PMU_MAX; i++) {
516 self->currentRsp->pmu_event_config[i] = 0;
517 self->currentRsp->pmu_event_count[i] = 0;
518 }
519
520 // Disable PMU
521 ETHOSU_PMU_Disable(drv);
522}
Davide Grohmannadc908c2022-02-16 13:13:27 +0100523#endif