blob: 200d92b34abba8d13b652ca04bfbf08617ba7cd9 [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
Per Åstrand91a91732020-09-25 15:04:26 +0200204 printf("InferenceReq. user_arg=0x%" PRIx64 ", network={0x%" PRIu32 ", %" PRIu32 "}",
205 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
243 InferenceJob job("job", networkModel, ifm, ofm, expectedOutput, -1);
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200244
245 bool failed = inferenceProcess.runJob(job);
246
Per Åstranddc28b132020-09-28 13:02:18 +0200247 sendInferenceRsp(req.user_arg, job.output, failed);
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200248 break;
249 }
Per Åstranddc28b132020-09-28 13:02:18 +0200250 default: {
251 printf("Unexpected message type: %" PRIu32 ", skipping %" PRIu32 " bytes\n", msg.type, msg.length);
252
253 queueIn.skip(msg.length);
254 } break;
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200255 }
256
257 return true;
258}
259
260void MessageProcess::sendPong() {
261 if (!queueOut.write(ETHOSU_CORE_MSG_PONG)) {
262 printf("Failed to write pong.\n");
263 }
Jonny Svärd44398c82020-10-06 14:18:28 +0200264 mailbox.sendMessage();
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200265}
266
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200267void MessageProcess::sendInferenceRsp(uint64_t userArg, vector<DataPtr> &ofm, bool failed) {
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200268 ethosu_core_inference_rsp rsp;
269
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200270 rsp.user_arg = userArg;
271 rsp.ofm_count = ofm.size();
272 rsp.status = failed ? ETHOSU_CORE_STATUS_ERROR : ETHOSU_CORE_STATUS_OK;
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200273
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200274 for (size_t i = 0; i < ofm.size(); ++i) {
275 rsp.ofm_size[i] = ofm[i].size;
276 }
277
Per Åstrand91a91732020-09-25 15:04:26 +0200278 printf("Sending inference response. userArg=0x%" PRIx64 ", ofm_count=%" PRIu32 ", status=%" PRIu32 "\n",
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200279 rsp.user_arg,
280 rsp.ofm_count,
281 rsp.status);
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200282
283 if (!queueOut.write(ETHOSU_CORE_MSG_INFERENCE_RSP, rsp)) {
284 printf("Failed to write inference.\n");
285 }
Jonny Svärd44398c82020-10-06 14:18:28 +0200286 mailbox.sendMessage();
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200287}
Jonny Svärd44398c82020-10-06 14:18:28 +0200288
289void MessageProcess::mailboxCallback(void *userArg) {
290 MessageProcess *_this = reinterpret_cast<MessageProcess *>(userArg);
291 _this->handleIrq();
292}
293
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200294} // namespace MessageProcess