blob: 659d685599fc24beb45df87490fd5dfc25131b49 [file] [log] [blame]
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +01001/*
Mikael Olsson68709512024-02-12 13:30:31 +01002 * SPDX-FileCopyrightText: Copyright 2022-2024 Arm Limited and/or its affiliates <open-source-office@arm.com>
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +01003 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the License); you may
6 * not use _this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*****************************************************************************
19 * Includes
20 *****************************************************************************/
21
22#include "inference_runner.hpp"
23
24#include <cstdlib>
25
26#include <ethosu_log.h>
Mikael Olsson918cd902023-12-13 09:57:42 +010027#include <ethosu_profiler.hpp>
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +010028
29#if defined(ETHOSU)
30#include <ethosu_driver.h>
31#include <pmu_ethosu.h>
32#endif
33
34/*****************************************************************************
Mikael Olsson918cd902023-12-13 09:57:42 +010035 * JobContext
36 *****************************************************************************/
37
38struct JobContext {
39 JobContext(Message *msg) : rsp(msg), profiler_context({}) {}
40
41 Message *rsp;
42 struct ethosu_profiler_context profiler_context;
43};
44
45/*****************************************************************************
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +010046 * InferenceRunner
47 *****************************************************************************/
48
49InferenceRunner::InferenceRunner(uint8_t *tensorArena,
50 size_t arenaSize,
51 MessageHandler::InferenceQueue &_inferenceQueue,
52 MessageHandler::ResponseQueue &_responseQueue) :
53 inferenceQueue(_inferenceQueue),
Mikael Olssonc2185832024-04-05 16:58:49 +020054 responseQueue(_responseQueue), inference(tensorArena, arenaSize), taskHandle() {
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +010055 BaseType_t ret = xTaskCreate(inferenceTask, "inferenceTask", 8 * 1024, this, 4, &taskHandle);
56 if (ret != pdPASS) {
57 LOG_ERR("Failed to create inference task");
58 abort();
59 }
60}
61
62InferenceRunner::~InferenceRunner() {
63 vTaskDelete(taskHandle);
64}
65
66void InferenceRunner::inferenceTask(void *param) {
67 auto _this = static_cast<InferenceRunner *>(param);
68
69 LOG_DEBUG("Starting inference task");
70
71 while (true) {
72 Message *message;
73 auto ret = _this->inferenceQueue.receive(message);
74 if (ret) {
75 abort();
76 }
77
78 auto &rpmsg = message->rpmsg;
79
80 switch (rpmsg.header.type) {
Mikael Olsson68709512024-02-12 13:30:31 +010081 case EthosU::ETHOSU_RPMSG_INFERENCE_REQ: {
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +010082 _this->handleInferenceRequest(message->src, rpmsg.header.msg_id, rpmsg.inf_req);
83 break;
84 }
85 default: {
86 LOG_WARN("Unsupported message for inference runner. type=%lu", rpmsg.header.type);
87 }
88 }
89
90 delete message;
91 }
92}
93
94void InferenceRunner::handleInferenceRequest(const uint32_t src,
95 const uint64_t msgId,
Mikael Olsson68709512024-02-12 13:30:31 +010096 const EthosU::ethosu_rpmsg_inference_req &request) {
Mikael Olsson918cd902023-12-13 09:57:42 +010097 auto jobContext = new JobContext(
Mikael Olsson68709512024-02-12 13:30:31 +010098 new Message(src, EthosU::ETHOSU_RPMSG_INFERENCE_RSP, msgId, sizeof(EthosU::ethosu_rpmsg_inference_rsp)));
Mikael Olsson918cd902023-12-13 09:57:42 +010099 auto &response = jobContext->rsp->rpmsg.inf_rsp;
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100100
101 // Setup PMU configuration
102 response.pmu_cycle_counter_enable = request.pmu_cycle_counter_enable;
103
Mikael Olsson68709512024-02-12 13:30:31 +0100104 for (int i = 0; i < ETHOSU_RPMSG_PMU_MAX; i++) {
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100105 response.pmu_event_config[i] = request.pmu_event_config[i];
106 }
107
108 // Run inference
Mikael Olsson918cd902023-12-13 09:57:42 +0100109 auto job = makeInferenceJob(request, *jobContext);
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100110 auto failed = inference.runJob(job);
111
Mikael Olsson918cd902023-12-13 09:57:42 +0100112 ethosu_profiler_report(&jobContext->profiler_context);
113
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100114 // Send response rpmsg
115 response.ofm_count = job.output.size();
Mikael Olsson68709512024-02-12 13:30:31 +0100116 response.status = failed ? EthosU::ETHOSU_RPMSG_STATUS_ERROR : EthosU::ETHOSU_RPMSG_STATUS_OK;
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100117
118 for (size_t i = 0; i < job.output.size(); ++i) {
119 response.ofm_size[i] = job.output[i].size;
120 }
121
Mikael Olsson918cd902023-12-13 09:57:42 +0100122 responseQueue.send(jobContext->rsp);
123 delete jobContext;
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100124}
125
Mikael Olsson68709512024-02-12 13:30:31 +0100126InferenceProcess::InferenceJob InferenceRunner::makeInferenceJob(const EthosU::ethosu_rpmsg_inference_req &request,
Mikael Olsson918cd902023-12-13 09:57:42 +0100127 JobContext &jobContext) {
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100128 InferenceProcess::InferenceJob job;
129
130 job.networkModel =
131 InferenceProcess::DataPtr(reinterpret_cast<void *>(request.network.buffer.ptr), request.network.buffer.size);
132
133 for (uint32_t i = 0; i < request.ifm_count; ++i) {
134 job.input.push_back(
135 InferenceProcess::DataPtr(reinterpret_cast<void *>(request.ifm[i].ptr), request.ifm[i].size));
136 }
137
138 for (uint32_t i = 0; i < request.ofm_count; ++i) {
139 job.output.push_back(
140 InferenceProcess::DataPtr(reinterpret_cast<void *>(request.ofm[i].ptr), request.ofm[i].size));
141 }
142
Mikael Olsson918cd902023-12-13 09:57:42 +0100143 job.externalContext = &jobContext;
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100144
145 return job;
146}
147
148#if defined(ETHOSU)
149extern "C" {
150
151void ethosu_inference_begin(ethosu_driver *drv, void *userArg) {
152 LOG_DEBUG("");
153
Mikael Olsson918cd902023-12-13 09:57:42 +0100154 auto context = static_cast<JobContext *>(userArg);
155 auto &response = context->rsp->rpmsg.inf_rsp;
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100156
157 // Calculate maximum number of events
Mikael Olsson68709512024-02-12 13:30:31 +0100158 const int numEvents = std::min(static_cast<int>(ETHOSU_PMU_Get_NumEventCounters()), ETHOSU_RPMSG_PMU_MAX);
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100159
160 // Enable PMU
161 ETHOSU_PMU_Enable(drv);
162
163 // Configure and enable events
164 for (int i = 0; i < numEvents; i++) {
Mikael Olsson918cd902023-12-13 09:57:42 +0100165 ETHOSU_PMU_Set_EVTYPER(drv, i, static_cast<ethosu_pmu_event_type>(response.pmu_event_config[i]));
Ledion Dajab0aacb42023-02-17 09:37:58 +0100166 ETHOSU_PMU_CNTR_Enable(drv, 1u << i);
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100167 }
168
169 // Enable cycle counter
Mikael Olsson918cd902023-12-13 09:57:42 +0100170 if (response.pmu_cycle_counter_enable) {
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100171 ETHOSU_PMU_PMCCNTR_CFG_Set_Stop_Event(drv, ETHOSU_PMU_NPU_IDLE);
172 ETHOSU_PMU_PMCCNTR_CFG_Set_Start_Event(drv, ETHOSU_PMU_NPU_ACTIVE);
173
174 ETHOSU_PMU_CNTR_Enable(drv, ETHOSU_PMU_CCNT_Msk);
175 ETHOSU_PMU_CYCCNT_Reset(drv);
176 }
177
178 // Reset all counters
179 ETHOSU_PMU_EVCNTR_ALL_Reset(drv);
Mikael Olsson918cd902023-12-13 09:57:42 +0100180
181 ethosu_profiler_start(&context->profiler_context);
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100182}
183
184void ethosu_inference_end(ethosu_driver *drv, void *userArg) {
Mikael Olsson918cd902023-12-13 09:57:42 +0100185 LOG_DEBUG("");
186
187 auto context = static_cast<JobContext *>(userArg);
188 auto &response = context->rsp->rpmsg.inf_rsp;
189
190 ethosu_profiler_end(&context->profiler_context);
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100191
192 // Get cycle counter
Mikael Olsson918cd902023-12-13 09:57:42 +0100193 if (response.pmu_cycle_counter_enable) {
Mikael Olsson4c675f62023-12-15 17:25:53 +0100194 uint64_t cycleCount = ETHOSU_PMU_Get_CCNTR(drv);
195 response.pmu_cycle_counter_count += cycleCount;
Mikael Olsson918cd902023-12-13 09:57:42 +0100196 ethosu_profiler_add_to_pmu_cycles(&context->profiler_context, cycleCount);
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100197 }
198
199 // Calculate maximum number of events
Mikael Olsson68709512024-02-12 13:30:31 +0100200 const int numEvents = std::min(static_cast<int>(ETHOSU_PMU_Get_NumEventCounters()), ETHOSU_RPMSG_PMU_MAX);
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100201
202 // Get event counters
203 int i;
204 for (i = 0; i < numEvents; i++) {
Mikael Olsson4c675f62023-12-15 17:25:53 +0100205 uint32_t eventValue = ETHOSU_PMU_Get_EVCNTR(drv, i);
206 response.pmu_event_count[i] += eventValue;
Mikael Olsson918cd902023-12-13 09:57:42 +0100207 ethosu_profiler_add_to_pmu_event(&context->profiler_context, i, eventValue);
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100208 }
209
Mikael Olsson68709512024-02-12 13:30:31 +0100210 for (; i < ETHOSU_RPMSG_PMU_MAX; i++) {
Mikael Olsson918cd902023-12-13 09:57:42 +0100211 response.pmu_event_config[i] = 0;
212 response.pmu_event_count[i] = 0;
Kristofer Jonsson3f5510f2023-02-08 14:23:00 +0100213 }
214
215 // Disable PMU
216 ETHOSU_PMU_Disable(drv);
217}
218}
219
220#endif