blob: 4533455aeab93fb570c21107623eb79153a0b6b3 [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
21#include <cstddef>
22#include <cstdio>
Kristofer Jonsson25480142020-09-03 12:35:21 +020023#include <cstring>
Per Åstrand91a91732020-09-25 15:04:26 +020024#include <inttypes.h>
Kristofer Jonsson641c0912020-08-31 11:34:14 +020025
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +020026using namespace std;
27using namespace InferenceProcess;
28
Kristofer Jonsson641c0912020-08-31 11:34:14 +020029namespace MessageProcess {
30
Per Åstrandbbd9c8f2020-09-25 15:07:35 +020031QueueImpl::QueueImpl(ethosu_core_queue &_queue) : queue(_queue) {}
Kristofer Jonsson641c0912020-08-31 11:34:14 +020032
33bool QueueImpl::empty() const {
34 return queue.header.read == queue.header.write;
35}
36
37size_t QueueImpl::available() const {
38 size_t avail = queue.header.write - queue.header.read;
39
40 if (queue.header.read > queue.header.write) {
41 avail += queue.header.size;
42 }
43
44 return avail;
45}
46
47size_t QueueImpl::capacity() const {
48 return queue.header.size - available();
49}
50
51bool QueueImpl::read(uint8_t *dst, uint32_t length) {
52 const uint8_t *end = dst + length;
53 uint32_t rpos = queue.header.read;
54
55 if (length > available()) {
56 return false;
57 }
58
59 while (dst < end) {
60 *dst++ = queue.data[rpos];
61 rpos = (rpos + 1) % queue.header.size;
62 }
63
64 queue.header.read = rpos;
65
66#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
67 SCB_CleanDCache();
68#endif
69
70 return true;
71}
72
73bool QueueImpl::write(const Vec *vec, size_t length) {
74 size_t total = 0;
75
76 for (size_t i = 0; i < length; i++) {
77 total += vec[i].length;
78 }
79
80 if (total > capacity()) {
81 return false;
82 }
83
84 uint32_t wpos = queue.header.write;
85
86 for (size_t i = 0; i < length; i++) {
87 const uint8_t *src = reinterpret_cast<const uint8_t *>(vec[i].base);
88 const uint8_t *end = src + vec[i].length;
89
90 while (src < end) {
91 queue.data[wpos] = *src++;
92 wpos = (wpos + 1) % queue.header.size;
93 }
94 }
95
96 // Update the write position last
97 queue.header.write = wpos;
98
99#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
100 SCB_CleanDCache();
101#endif
102
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200103 return true;
104}
105
106bool QueueImpl::write(const uint32_t type, const void *src, uint32_t length) {
107 ethosu_core_msg msg = {type, length};
108 Vec vec[2] = {{&msg, sizeof(msg)}, {src, length}};
109
110 return write(vec, 2);
111}
112
Per Åstranddc28b132020-09-28 13:02:18 +0200113bool QueueImpl::skip(uint32_t length) {
114 uint32_t rpos = queue.header.read;
115
116 if (length > available()) {
117 return false;
118 }
119
120 queue.header.read = (rpos + length) % queue.header.size;
121
122#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
123 SCB_CleanDCache();
124#endif
125
126 return true;
127}
128
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200129MessageProcess::MessageProcess(ethosu_core_queue &in,
130 ethosu_core_queue &out,
Jonny Svärd44398c82020-10-06 14:18:28 +0200131 Mailbox::Mailbox &mbox,
Per Åstrandbbd9c8f2020-09-25 15:07:35 +0200132 ::InferenceProcess::InferenceProcess &_inferenceProcess) :
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200133 queueIn(in),
Jonny Svärd44398c82020-10-06 14:18:28 +0200134 queueOut(out), mailbox(mbox), inferenceProcess(_inferenceProcess) {
135 mailbox.registerCallback(mailboxCallback, reinterpret_cast<void *>(this));
136}
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200137
138void MessageProcess::run() {
139 while (true) {
140 // Handle all messages in queue
141 while (handleMessage())
142 ;
143
144 // Wait for event
145 __WFE();
146 }
147}
148
149void MessageProcess::handleIrq() {
150 __SEV();
151}
152
153bool MessageProcess::handleMessage() {
154 ethosu_core_msg msg;
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200155
156#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
157 SCB_InvalidateDCache();
158#endif
159
160 // Read msg header
161 if (!queueIn.read(msg)) {
162 return false;
163 }
164
Per Åstrand91a91732020-09-25 15:04:26 +0200165 printf("Message. type=%" PRIu32 ", length=%" PRIu32 "\n", msg.type, msg.length);
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200166
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200167 switch (msg.type) {
168 case ETHOSU_CORE_MSG_PING:
169 printf("Ping\n");
170 sendPong();
171 break;
172 case ETHOSU_CORE_MSG_INFERENCE_REQ: {
Per Åstranddc28b132020-09-28 13:02:18 +0200173 ethosu_core_inference_req req;
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200174
Per Åstranddc28b132020-09-28 13:02:18 +0200175 if (!queueIn.readOrSkip(req, msg.length)) {
176 printf("Failed to read payload.\n");
177 return false;
178 }
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200179
Per Åstrand91a91732020-09-25 15:04:26 +0200180 printf("InferenceReq. user_arg=0x%" PRIx64 ", network={0x%" PRIu32 ", %" PRIu32 "}",
181 req.user_arg,
182 req.network.ptr,
183 req.network.size);
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200184
Per Åstrand91a91732020-09-25 15:04:26 +0200185 printf(", ifm_count=%" PRIu32 ", ifm=[", req.ifm_count);
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200186 for (uint32_t i = 0; i < req.ifm_count; ++i) {
187 if (i > 0) {
188 printf(", ");
189 }
190
Per Åstrand91a91732020-09-25 15:04:26 +0200191 printf("{0x%" PRIx32 ", %" PRIu32 "}", req.ifm[i].ptr, req.ifm[i].size);
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200192 }
193 printf("]");
194
Per Åstrand91a91732020-09-25 15:04:26 +0200195 printf(", ofm_count=%" PRIu32 ", ofm=[", req.ofm_count);
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200196 for (uint32_t i = 0; i < req.ofm_count; ++i) {
197 if (i > 0) {
198 printf(", ");
199 }
200
Per Åstrand91a91732020-09-25 15:04:26 +0200201 printf("{0x%" PRIx32 ", %" PRIu32 "}", req.ofm[i].ptr, req.ofm[i].size);
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200202 }
203 printf("]\n");
204
205 DataPtr networkModel(reinterpret_cast<void *>(req.network.ptr), req.network.size);
206
207 vector<DataPtr> ifm;
208 for (uint32_t i = 0; i < req.ifm_count; ++i) {
209 ifm.push_back(DataPtr(reinterpret_cast<void *>(req.ifm[i].ptr), req.ifm[i].size));
210 }
211
212 vector<DataPtr> ofm;
213 for (uint32_t i = 0; i < req.ofm_count; ++i) {
214 ofm.push_back(DataPtr(reinterpret_cast<void *>(req.ofm[i].ptr), req.ofm[i].size));
215 }
216
217 vector<DataPtr> expectedOutput;
218
219 InferenceJob job("job", networkModel, ifm, ofm, expectedOutput, -1);
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200220
221 bool failed = inferenceProcess.runJob(job);
222
Per Åstranddc28b132020-09-28 13:02:18 +0200223 sendInferenceRsp(req.user_arg, job.output, failed);
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200224 break;
225 }
Per Åstranddc28b132020-09-28 13:02:18 +0200226 default: {
227 printf("Unexpected message type: %" PRIu32 ", skipping %" PRIu32 " bytes\n", msg.type, msg.length);
228
229 queueIn.skip(msg.length);
230 } break;
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200231 }
232
233 return true;
234}
235
236void MessageProcess::sendPong() {
237 if (!queueOut.write(ETHOSU_CORE_MSG_PONG)) {
238 printf("Failed to write pong.\n");
239 }
Jonny Svärd44398c82020-10-06 14:18:28 +0200240 mailbox.sendMessage();
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200241}
242
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200243void MessageProcess::sendInferenceRsp(uint64_t userArg, vector<DataPtr> &ofm, bool failed) {
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200244 ethosu_core_inference_rsp rsp;
245
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200246 rsp.user_arg = userArg;
247 rsp.ofm_count = ofm.size();
248 rsp.status = failed ? ETHOSU_CORE_STATUS_ERROR : ETHOSU_CORE_STATUS_OK;
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200249
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200250 for (size_t i = 0; i < ofm.size(); ++i) {
251 rsp.ofm_size[i] = ofm[i].size;
252 }
253
Per Åstrand91a91732020-09-25 15:04:26 +0200254 printf("Sending inference response. userArg=0x%" PRIx64 ", ofm_count=%" PRIu32 ", status=%" PRIu32 "\n",
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200255 rsp.user_arg,
256 rsp.ofm_count,
257 rsp.status);
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200258
259 if (!queueOut.write(ETHOSU_CORE_MSG_INFERENCE_RSP, rsp)) {
260 printf("Failed to write inference.\n");
261 }
Jonny Svärd44398c82020-10-06 14:18:28 +0200262 mailbox.sendMessage();
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200263}
Jonny Svärd44398c82020-10-06 14:18:28 +0200264
265void MessageProcess::mailboxCallback(void *userArg) {
266 MessageProcess *_this = reinterpret_cast<MessageProcess *>(userArg);
267 _this->handleIrq();
268}
269
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200270} // namespace MessageProcess