blob: dfeb8300c25643129ac9b5cb3e214dc56ef0b9c8 [file] [log] [blame]
Kristofer Jonsson641c0912020-08-31 11:34:14 +02001/*
2 * Copyright (c) 2020 Arm Limited. All rights reserved.
3 *
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_process.hpp>
20
Per Åstrandd9afc082020-10-06 13:25:08 +020021#include "cmsis_compiler.h"
22
Kristofer Jonsson641c0912020-08-31 11:34:14 +020023#include <cstddef>
24#include <cstdio>
Kristofer Jonsson25480142020-09-03 12:35:21 +020025#include <cstring>
Per Åstrand91a91732020-09-25 15:04:26 +020026#include <inttypes.h>
Kristofer Jonsson641c0912020-08-31 11:34:14 +020027
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +020028using namespace std;
29using namespace InferenceProcess;
30
Kristofer Jonsson641c0912020-08-31 11:34:14 +020031namespace MessageProcess {
32
Per Åstrandbbd9c8f2020-09-25 15:07:35 +020033QueueImpl::QueueImpl(ethosu_core_queue &_queue) : queue(_queue) {}
Kristofer Jonsson641c0912020-08-31 11:34:14 +020034
35bool QueueImpl::empty() const {
36 return queue.header.read == queue.header.write;
37}
38
39size_t QueueImpl::available() const {
40 size_t avail = queue.header.write - queue.header.read;
41
42 if (queue.header.read > queue.header.write) {
43 avail += queue.header.size;
44 }
45
46 return avail;
47}
48
49size_t QueueImpl::capacity() const {
50 return queue.header.size - available();
51}
52
53bool QueueImpl::read(uint8_t *dst, uint32_t length) {
54 const uint8_t *end = dst + length;
55 uint32_t rpos = queue.header.read;
56
Kristofer Jonsson2cbaaa92020-11-19 16:14:46 +010057 invalidateHeaderData();
58
Kristofer Jonsson641c0912020-08-31 11:34:14 +020059 if (length > available()) {
60 return false;
61 }
62
63 while (dst < end) {
64 *dst++ = queue.data[rpos];
65 rpos = (rpos + 1) % queue.header.size;
66 }
67
68 queue.header.read = rpos;
69
Kristofer Jonsson2cbaaa92020-11-19 16:14:46 +010070 cleanHeader();
Kristofer Jonsson641c0912020-08-31 11:34:14 +020071
72 return true;
73}
74
75bool QueueImpl::write(const Vec *vec, size_t length) {
76 size_t total = 0;
77
78 for (size_t i = 0; i < length; i++) {
79 total += vec[i].length;
80 }
81
Kristofer Jonsson2cbaaa92020-11-19 16:14:46 +010082 invalidateHeader();
83
Kristofer Jonsson641c0912020-08-31 11:34:14 +020084 if (total > capacity()) {
85 return false;
86 }
87
88 uint32_t wpos = queue.header.write;
89
90 for (size_t i = 0; i < length; i++) {
91 const uint8_t *src = reinterpret_cast<const uint8_t *>(vec[i].base);
92 const uint8_t *end = src + vec[i].length;
93
94 while (src < end) {
95 queue.data[wpos] = *src++;
96 wpos = (wpos + 1) % queue.header.size;
97 }
98 }
99
100 // Update the write position last
101 queue.header.write = wpos;
102
Kristofer Jonsson2cbaaa92020-11-19 16:14:46 +0100103 cleanHeaderData();
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200104
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200105 return true;
106}
107
108bool QueueImpl::write(const uint32_t type, const void *src, uint32_t length) {
109 ethosu_core_msg msg = {type, length};
110 Vec vec[2] = {{&msg, sizeof(msg)}, {src, length}};
111
112 return write(vec, 2);
113}
114
Per Åstranddc28b132020-09-28 13:02:18 +0200115bool QueueImpl::skip(uint32_t length) {
116 uint32_t rpos = queue.header.read;
117
Kristofer Jonsson2cbaaa92020-11-19 16:14:46 +0100118 invalidateHeader();
119
Per Åstranddc28b132020-09-28 13:02:18 +0200120 if (length > available()) {
121 return false;
122 }
123
124 queue.header.read = (rpos + length) % queue.header.size;
125
Kristofer Jonsson2cbaaa92020-11-19 16:14:46 +0100126 cleanHeader();
Per Åstranddc28b132020-09-28 13:02:18 +0200127
128 return true;
129}
130
Kristofer Jonsson2cbaaa92020-11-19 16:14:46 +0100131void QueueImpl::cleanHeader() const {
132#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
133 SCB_CleanDCache_by_Addr(reinterpret_cast<uint32_t *>(&queue.header), sizeof(queue.header));
134#endif
135}
136
137void QueueImpl::cleanHeaderData() const {
138#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
139 SCB_CleanDCache_by_Addr(reinterpret_cast<uint32_t *>(&queue.header), sizeof(queue.header));
140 SCB_CleanDCache_by_Addr(reinterpret_cast<uint32_t *>(queue.data), queue.header.size);
141#endif
142}
143
144void QueueImpl::invalidateHeader() const {
145#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
146 SCB_InvalidateDCache_by_Addr(reinterpret_cast<uint32_t *>(&queue.header), sizeof(queue.header));
147#endif
148}
149
150void QueueImpl::invalidateHeaderData() const {
151#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
152 SCB_InvalidateDCache_by_Addr(reinterpret_cast<uint32_t *>(&queue.header), sizeof(queue.header));
153 SCB_InvalidateDCache_by_Addr(reinterpret_cast<uint32_t *>(queue.data), queue.header.size);
154#endif
155}
156
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200157MessageProcess::MessageProcess(ethosu_core_queue &in,
158 ethosu_core_queue &out,
Jonny Svärd44398c82020-10-06 14:18:28 +0200159 Mailbox::Mailbox &mbox,
Per Åstrandbbd9c8f2020-09-25 15:07:35 +0200160 ::InferenceProcess::InferenceProcess &_inferenceProcess) :
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200161 queueIn(in),
Jonny Svärd44398c82020-10-06 14:18:28 +0200162 queueOut(out), mailbox(mbox), inferenceProcess(_inferenceProcess) {
163 mailbox.registerCallback(mailboxCallback, reinterpret_cast<void *>(this));
164}
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200165
166void MessageProcess::run() {
167 while (true) {
168 // Handle all messages in queue
169 while (handleMessage())
170 ;
171
172 // Wait for event
173 __WFE();
174 }
175}
176
177void MessageProcess::handleIrq() {
178 __SEV();
179}
180
181bool MessageProcess::handleMessage() {
182 ethosu_core_msg msg;
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200183
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200184 // Read msg header
185 if (!queueIn.read(msg)) {
186 return false;
187 }
188
Per Åstrand91a91732020-09-25 15:04:26 +0200189 printf("Message. type=%" PRIu32 ", length=%" PRIu32 "\n", msg.type, msg.length);
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200190
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200191 switch (msg.type) {
192 case ETHOSU_CORE_MSG_PING:
193 printf("Ping\n");
194 sendPong();
195 break;
196 case ETHOSU_CORE_MSG_INFERENCE_REQ: {
Per Åstranddc28b132020-09-28 13:02:18 +0200197 ethosu_core_inference_req req;
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200198
Per Åstranddc28b132020-09-28 13:02:18 +0200199 if (!queueIn.readOrSkip(req, msg.length)) {
200 printf("Failed to read payload.\n");
201 return false;
202 }
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200203
Kristofer Jonsson34e24962020-11-23 16:22:10 +0100204 printf("InferenceReq. user_arg=0x%" PRIx64 ", network={0x%" PRIx32 ", %" PRIu32 "}",
Per Åstrand91a91732020-09-25 15:04:26 +0200205 req.user_arg,
206 req.network.ptr,
207 req.network.size);
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200208
Per Åstrand91a91732020-09-25 15:04:26 +0200209 printf(", ifm_count=%" PRIu32 ", ifm=[", req.ifm_count);
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200210 for (uint32_t i = 0; i < req.ifm_count; ++i) {
211 if (i > 0) {
212 printf(", ");
213 }
214
Per Åstrand91a91732020-09-25 15:04:26 +0200215 printf("{0x%" PRIx32 ", %" PRIu32 "}", req.ifm[i].ptr, req.ifm[i].size);
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200216 }
217 printf("]");
218
Per Åstrand91a91732020-09-25 15:04:26 +0200219 printf(", ofm_count=%" PRIu32 ", ofm=[", req.ofm_count);
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200220 for (uint32_t i = 0; i < req.ofm_count; ++i) {
221 if (i > 0) {
222 printf(", ");
223 }
224
Per Åstrand91a91732020-09-25 15:04:26 +0200225 printf("{0x%" PRIx32 ", %" PRIu32 "}", req.ofm[i].ptr, req.ofm[i].size);
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200226 }
227 printf("]\n");
228
229 DataPtr networkModel(reinterpret_cast<void *>(req.network.ptr), req.network.size);
230
231 vector<DataPtr> ifm;
232 for (uint32_t i = 0; i < req.ifm_count; ++i) {
233 ifm.push_back(DataPtr(reinterpret_cast<void *>(req.ifm[i].ptr), req.ifm[i].size));
234 }
235
236 vector<DataPtr> ofm;
237 for (uint32_t i = 0; i < req.ofm_count; ++i) {
238 ofm.push_back(DataPtr(reinterpret_cast<void *>(req.ofm[i].ptr), req.ofm[i].size));
239 }
240
241 vector<DataPtr> expectedOutput;
242
Jonny Svärde9f57dc2020-12-10 11:12:44 +0100243 vector<uint8_t> pmuEventConfig(ETHOSU_CORE_PMU_MAX);
Bhavik Patelffe845d2020-11-16 12:13:56 +0100244 for (uint32_t i = 0; i < ETHOSU_CORE_PMU_MAX; i++) {
245 pmuEventConfig[i] = req.pmu_event_config[i];
246 }
247
248 InferenceJob job(
249 "job", networkModel, ifm, ofm, expectedOutput, -1, pmuEventConfig, req.pmu_cycle_counter_enable);
Kristofer Jonsson34e24962020-11-23 16:22:10 +0100250 job.invalidate();
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200251
252 bool failed = inferenceProcess.runJob(job);
Kristofer Jonsson34e24962020-11-23 16:22:10 +0100253 job.clean();
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200254
Bhavik Patelffe845d2020-11-16 12:13:56 +0100255 sendInferenceRsp(req.user_arg,
256 job.output,
257 failed,
258 job.pmuEventConfig,
259 job.pmuCycleCounterEnable,
260 job.pmuEventCount,
261 job.pmuCycleCounterCount);
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200262 break;
263 }
Per Åstranddc28b132020-09-28 13:02:18 +0200264 default: {
265 printf("Unexpected message type: %" PRIu32 ", skipping %" PRIu32 " bytes\n", msg.type, msg.length);
266
267 queueIn.skip(msg.length);
268 } break;
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200269 }
270
271 return true;
272}
273
274void MessageProcess::sendPong() {
275 if (!queueOut.write(ETHOSU_CORE_MSG_PONG)) {
276 printf("Failed to write pong.\n");
277 }
Jonny Svärd44398c82020-10-06 14:18:28 +0200278 mailbox.sendMessage();
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200279}
280
Bhavik Patelffe845d2020-11-16 12:13:56 +0100281void MessageProcess::sendInferenceRsp(uint64_t userArg,
282 vector<DataPtr> &ofm,
283 bool failed,
284 vector<uint8_t> &pmuEventConfig,
285 uint32_t pmuCycleCounterEnable,
286 vector<uint32_t> &pmuEventCount,
287 uint64_t pmuCycleCounterCount) {
288 ethosu_core_inference_rsp rsp = {
289 .pmu_event_count =
290 {
291 0,
292 },
293 };
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200294
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200295 rsp.user_arg = userArg;
296 rsp.ofm_count = ofm.size();
297 rsp.status = failed ? ETHOSU_CORE_STATUS_ERROR : ETHOSU_CORE_STATUS_OK;
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200298
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200299 for (size_t i = 0; i < ofm.size(); ++i) {
300 rsp.ofm_size[i] = ofm[i].size;
301 }
302
Bhavik Patelffe845d2020-11-16 12:13:56 +0100303 for (size_t i = 0; i < pmuEventConfig.size(); i++) {
304 rsp.pmu_event_config[i] = pmuEventConfig[i];
305 }
306 rsp.pmu_cycle_counter_enable = pmuCycleCounterEnable;
307 for (size_t i = 0; i < pmuEventCount.size(); i++) {
308 rsp.pmu_event_count[i] = pmuEventCount[i];
309 }
310 rsp.pmu_cycle_counter_count = pmuCycleCounterCount;
311
Per Åstrand91a91732020-09-25 15:04:26 +0200312 printf("Sending inference response. userArg=0x%" PRIx64 ", ofm_count=%" PRIu32 ", status=%" PRIu32 "\n",
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200313 rsp.user_arg,
314 rsp.ofm_count,
315 rsp.status);
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200316
317 if (!queueOut.write(ETHOSU_CORE_MSG_INFERENCE_RSP, rsp)) {
318 printf("Failed to write inference.\n");
319 }
Jonny Svärd44398c82020-10-06 14:18:28 +0200320 mailbox.sendMessage();
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200321}
Jonny Svärd44398c82020-10-06 14:18:28 +0200322
323void MessageProcess::mailboxCallback(void *userArg) {
324 MessageProcess *_this = reinterpret_cast<MessageProcess *>(userArg);
325 _this->handleIrq();
326}
327
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200328} // namespace MessageProcess