blob: 5640a1a15e6b135b54612795a22c8d057986706b [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
57 if (length > available()) {
58 return false;
59 }
60
61 while (dst < end) {
62 *dst++ = queue.data[rpos];
63 rpos = (rpos + 1) % queue.header.size;
64 }
65
66 queue.header.read = rpos;
67
68#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
69 SCB_CleanDCache();
70#endif
71
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
82 if (total > capacity()) {
83 return false;
84 }
85
86 uint32_t wpos = queue.header.write;
87
88 for (size_t i = 0; i < length; i++) {
89 const uint8_t *src = reinterpret_cast<const uint8_t *>(vec[i].base);
90 const uint8_t *end = src + vec[i].length;
91
92 while (src < end) {
93 queue.data[wpos] = *src++;
94 wpos = (wpos + 1) % queue.header.size;
95 }
96 }
97
98 // Update the write position last
99 queue.header.write = wpos;
100
101#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
102 SCB_CleanDCache();
103#endif
104
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
118 if (length > available()) {
119 return false;
120 }
121
122 queue.header.read = (rpos + length) % queue.header.size;
123
124#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
125 SCB_CleanDCache();
126#endif
127
128 return true;
129}
130
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200131MessageProcess::MessageProcess(ethosu_core_queue &in,
132 ethosu_core_queue &out,
Jonny Svärd44398c82020-10-06 14:18:28 +0200133 Mailbox::Mailbox &mbox,
Per Åstrandbbd9c8f2020-09-25 15:07:35 +0200134 ::InferenceProcess::InferenceProcess &_inferenceProcess) :
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200135 queueIn(in),
Jonny Svärd44398c82020-10-06 14:18:28 +0200136 queueOut(out), mailbox(mbox), inferenceProcess(_inferenceProcess) {
137 mailbox.registerCallback(mailboxCallback, reinterpret_cast<void *>(this));
138}
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200139
140void MessageProcess::run() {
141 while (true) {
142 // Handle all messages in queue
143 while (handleMessage())
144 ;
145
146 // Wait for event
147 __WFE();
148 }
149}
150
151void MessageProcess::handleIrq() {
152 __SEV();
153}
154
155bool MessageProcess::handleMessage() {
156 ethosu_core_msg msg;
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200157
158#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
159 SCB_InvalidateDCache();
160#endif
161
162 // Read msg header
163 if (!queueIn.read(msg)) {
164 return false;
165 }
166
Per Åstrand91a91732020-09-25 15:04:26 +0200167 printf("Message. type=%" PRIu32 ", length=%" PRIu32 "\n", msg.type, msg.length);
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200168
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200169 switch (msg.type) {
170 case ETHOSU_CORE_MSG_PING:
171 printf("Ping\n");
172 sendPong();
173 break;
174 case ETHOSU_CORE_MSG_INFERENCE_REQ: {
Per Åstranddc28b132020-09-28 13:02:18 +0200175 ethosu_core_inference_req req;
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200176
Per Åstranddc28b132020-09-28 13:02:18 +0200177 if (!queueIn.readOrSkip(req, msg.length)) {
178 printf("Failed to read payload.\n");
179 return false;
180 }
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200181
Per Åstrand91a91732020-09-25 15:04:26 +0200182 printf("InferenceReq. user_arg=0x%" PRIx64 ", network={0x%" PRIu32 ", %" PRIu32 "}",
183 req.user_arg,
184 req.network.ptr,
185 req.network.size);
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200186
Per Åstrand91a91732020-09-25 15:04:26 +0200187 printf(", ifm_count=%" PRIu32 ", ifm=[", req.ifm_count);
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200188 for (uint32_t i = 0; i < req.ifm_count; ++i) {
189 if (i > 0) {
190 printf(", ");
191 }
192
Per Åstrand91a91732020-09-25 15:04:26 +0200193 printf("{0x%" PRIx32 ", %" PRIu32 "}", req.ifm[i].ptr, req.ifm[i].size);
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200194 }
195 printf("]");
196
Per Åstrand91a91732020-09-25 15:04:26 +0200197 printf(", ofm_count=%" PRIu32 ", ofm=[", req.ofm_count);
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200198 for (uint32_t i = 0; i < req.ofm_count; ++i) {
199 if (i > 0) {
200 printf(", ");
201 }
202
Per Åstrand91a91732020-09-25 15:04:26 +0200203 printf("{0x%" PRIx32 ", %" PRIu32 "}", req.ofm[i].ptr, req.ofm[i].size);
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200204 }
205 printf("]\n");
206
207 DataPtr networkModel(reinterpret_cast<void *>(req.network.ptr), req.network.size);
208
209 vector<DataPtr> ifm;
210 for (uint32_t i = 0; i < req.ifm_count; ++i) {
211 ifm.push_back(DataPtr(reinterpret_cast<void *>(req.ifm[i].ptr), req.ifm[i].size));
212 }
213
214 vector<DataPtr> ofm;
215 for (uint32_t i = 0; i < req.ofm_count; ++i) {
216 ofm.push_back(DataPtr(reinterpret_cast<void *>(req.ofm[i].ptr), req.ofm[i].size));
217 }
218
219 vector<DataPtr> expectedOutput;
220
221 InferenceJob job("job", networkModel, ifm, ofm, expectedOutput, -1);
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200222
223 bool failed = inferenceProcess.runJob(job);
224
Per Åstranddc28b132020-09-28 13:02:18 +0200225 sendInferenceRsp(req.user_arg, job.output, failed);
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200226 break;
227 }
Per Åstranddc28b132020-09-28 13:02:18 +0200228 default: {
229 printf("Unexpected message type: %" PRIu32 ", skipping %" PRIu32 " bytes\n", msg.type, msg.length);
230
231 queueIn.skip(msg.length);
232 } break;
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200233 }
234
235 return true;
236}
237
238void MessageProcess::sendPong() {
239 if (!queueOut.write(ETHOSU_CORE_MSG_PONG)) {
240 printf("Failed to write pong.\n");
241 }
Jonny Svärd44398c82020-10-06 14:18:28 +0200242 mailbox.sendMessage();
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200243}
244
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200245void MessageProcess::sendInferenceRsp(uint64_t userArg, vector<DataPtr> &ofm, bool failed) {
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200246 ethosu_core_inference_rsp rsp;
247
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200248 rsp.user_arg = userArg;
249 rsp.ofm_count = ofm.size();
250 rsp.status = failed ? ETHOSU_CORE_STATUS_ERROR : ETHOSU_CORE_STATUS_OK;
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200251
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200252 for (size_t i = 0; i < ofm.size(); ++i) {
253 rsp.ofm_size[i] = ofm[i].size;
254 }
255
Per Åstrand91a91732020-09-25 15:04:26 +0200256 printf("Sending inference response. userArg=0x%" PRIx64 ", ofm_count=%" PRIu32 ", status=%" PRIu32 "\n",
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200257 rsp.user_arg,
258 rsp.ofm_count,
259 rsp.status);
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200260
261 if (!queueOut.write(ETHOSU_CORE_MSG_INFERENCE_RSP, rsp)) {
262 printf("Failed to write inference.\n");
263 }
Jonny Svärd44398c82020-10-06 14:18:28 +0200264 mailbox.sendMessage();
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200265}
Jonny Svärd44398c82020-10-06 14:18:28 +0200266
267void MessageProcess::mailboxCallback(void *userArg) {
268 MessageProcess *_this = reinterpret_cast<MessageProcess *>(userArg);
269 _this->handleIrq();
270}
271
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200272} // namespace MessageProcess