blob: 9c0fc8456d7d0ca39e2792b1cfbe72ace0344f39 [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
Kristofer Jonsson68b4ad52020-12-10 15:11:27 +010033QueueImpl::QueueImpl(ethosu_core_queue &_queue) : queue(_queue) {
34 cleanHeaderData();
35}
Kristofer Jonsson641c0912020-08-31 11:34:14 +020036
37bool QueueImpl::empty() const {
38 return queue.header.read == queue.header.write;
39}
40
41size_t QueueImpl::available() const {
42 size_t avail = queue.header.write - queue.header.read;
43
44 if (queue.header.read > queue.header.write) {
45 avail += queue.header.size;
46 }
47
48 return avail;
49}
50
51size_t QueueImpl::capacity() const {
52 return queue.header.size - available();
53}
54
55bool QueueImpl::read(uint8_t *dst, uint32_t length) {
56 const uint8_t *end = dst + length;
57 uint32_t rpos = queue.header.read;
58
Kristofer Jonsson2cbaaa92020-11-19 16:14:46 +010059 invalidateHeaderData();
60
Kristofer Jonsson641c0912020-08-31 11:34:14 +020061 if (length > available()) {
62 return false;
63 }
64
65 while (dst < end) {
66 *dst++ = queue.data[rpos];
67 rpos = (rpos + 1) % queue.header.size;
68 }
69
70 queue.header.read = rpos;
71
Kristofer Jonsson2cbaaa92020-11-19 16:14:46 +010072 cleanHeader();
Kristofer Jonsson641c0912020-08-31 11:34:14 +020073
74 return true;
75}
76
77bool QueueImpl::write(const Vec *vec, size_t length) {
78 size_t total = 0;
79
80 for (size_t i = 0; i < length; i++) {
81 total += vec[i].length;
82 }
83
Kristofer Jonsson2cbaaa92020-11-19 16:14:46 +010084 invalidateHeader();
85
Kristofer Jonsson641c0912020-08-31 11:34:14 +020086 if (total > capacity()) {
87 return false;
88 }
89
90 uint32_t wpos = queue.header.write;
91
92 for (size_t i = 0; i < length; i++) {
93 const uint8_t *src = reinterpret_cast<const uint8_t *>(vec[i].base);
94 const uint8_t *end = src + vec[i].length;
95
96 while (src < end) {
97 queue.data[wpos] = *src++;
98 wpos = (wpos + 1) % queue.header.size;
99 }
100 }
101
102 // Update the write position last
103 queue.header.write = wpos;
104
Kristofer Jonsson2cbaaa92020-11-19 16:14:46 +0100105 cleanHeaderData();
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200106
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200107 return true;
108}
109
110bool QueueImpl::write(const uint32_t type, const void *src, uint32_t length) {
111 ethosu_core_msg msg = {type, length};
112 Vec vec[2] = {{&msg, sizeof(msg)}, {src, length}};
113
114 return write(vec, 2);
115}
116
Per Åstranddc28b132020-09-28 13:02:18 +0200117bool QueueImpl::skip(uint32_t length) {
118 uint32_t rpos = queue.header.read;
119
Kristofer Jonsson2cbaaa92020-11-19 16:14:46 +0100120 invalidateHeader();
121
Per Åstranddc28b132020-09-28 13:02:18 +0200122 if (length > available()) {
123 return false;
124 }
125
126 queue.header.read = (rpos + length) % queue.header.size;
127
Kristofer Jonsson2cbaaa92020-11-19 16:14:46 +0100128 cleanHeader();
Per Åstranddc28b132020-09-28 13:02:18 +0200129
130 return true;
131}
132
Kristofer Jonsson2cbaaa92020-11-19 16:14:46 +0100133void QueueImpl::cleanHeader() const {
134#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
135 SCB_CleanDCache_by_Addr(reinterpret_cast<uint32_t *>(&queue.header), sizeof(queue.header));
136#endif
137}
138
139void QueueImpl::cleanHeaderData() const {
140#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
141 SCB_CleanDCache_by_Addr(reinterpret_cast<uint32_t *>(&queue.header), sizeof(queue.header));
142 SCB_CleanDCache_by_Addr(reinterpret_cast<uint32_t *>(queue.data), queue.header.size);
143#endif
144}
145
146void QueueImpl::invalidateHeader() const {
147#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
148 SCB_InvalidateDCache_by_Addr(reinterpret_cast<uint32_t *>(&queue.header), sizeof(queue.header));
149#endif
150}
151
152void QueueImpl::invalidateHeaderData() const {
153#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
154 SCB_InvalidateDCache_by_Addr(reinterpret_cast<uint32_t *>(&queue.header), sizeof(queue.header));
155 SCB_InvalidateDCache_by_Addr(reinterpret_cast<uint32_t *>(queue.data), queue.header.size);
156#endif
157}
158
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200159MessageProcess::MessageProcess(ethosu_core_queue &in,
160 ethosu_core_queue &out,
Jonny Svärd44398c82020-10-06 14:18:28 +0200161 Mailbox::Mailbox &mbox,
Per Åstrandbbd9c8f2020-09-25 15:07:35 +0200162 ::InferenceProcess::InferenceProcess &_inferenceProcess) :
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200163 queueIn(in),
Jonny Svärd44398c82020-10-06 14:18:28 +0200164 queueOut(out), mailbox(mbox), inferenceProcess(_inferenceProcess) {
165 mailbox.registerCallback(mailboxCallback, reinterpret_cast<void *>(this));
166}
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200167
168void MessageProcess::run() {
169 while (true) {
170 // Handle all messages in queue
171 while (handleMessage())
172 ;
173
174 // Wait for event
175 __WFE();
176 }
177}
178
179void MessageProcess::handleIrq() {
180 __SEV();
181}
182
183bool MessageProcess::handleMessage() {
184 ethosu_core_msg msg;
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200185
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200186 // Read msg header
187 if (!queueIn.read(msg)) {
188 return false;
189 }
190
Per Åstrand91a91732020-09-25 15:04:26 +0200191 printf("Message. type=%" PRIu32 ", length=%" PRIu32 "\n", msg.type, msg.length);
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200192
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200193 switch (msg.type) {
194 case ETHOSU_CORE_MSG_PING:
195 printf("Ping\n");
196 sendPong();
197 break;
198 case ETHOSU_CORE_MSG_INFERENCE_REQ: {
Per Åstranddc28b132020-09-28 13:02:18 +0200199 ethosu_core_inference_req req;
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200200
Per Åstranddc28b132020-09-28 13:02:18 +0200201 if (!queueIn.readOrSkip(req, msg.length)) {
202 printf("Failed to read payload.\n");
203 return false;
204 }
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200205
Kristofer Jonsson34e24962020-11-23 16:22:10 +0100206 printf("InferenceReq. user_arg=0x%" PRIx64 ", network={0x%" PRIx32 ", %" PRIu32 "}",
Per Åstrand91a91732020-09-25 15:04:26 +0200207 req.user_arg,
208 req.network.ptr,
209 req.network.size);
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200210
Per Åstrand91a91732020-09-25 15:04:26 +0200211 printf(", ifm_count=%" PRIu32 ", ifm=[", req.ifm_count);
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200212 for (uint32_t i = 0; i < req.ifm_count; ++i) {
213 if (i > 0) {
214 printf(", ");
215 }
216
Per Åstrand91a91732020-09-25 15:04:26 +0200217 printf("{0x%" PRIx32 ", %" PRIu32 "}", req.ifm[i].ptr, req.ifm[i].size);
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200218 }
219 printf("]");
220
Per Åstrand91a91732020-09-25 15:04:26 +0200221 printf(", ofm_count=%" PRIu32 ", ofm=[", req.ofm_count);
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200222 for (uint32_t i = 0; i < req.ofm_count; ++i) {
223 if (i > 0) {
224 printf(", ");
225 }
226
Per Åstrand91a91732020-09-25 15:04:26 +0200227 printf("{0x%" PRIx32 ", %" PRIu32 "}", req.ofm[i].ptr, req.ofm[i].size);
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200228 }
229 printf("]\n");
230
231 DataPtr networkModel(reinterpret_cast<void *>(req.network.ptr), req.network.size);
232
233 vector<DataPtr> ifm;
234 for (uint32_t i = 0; i < req.ifm_count; ++i) {
235 ifm.push_back(DataPtr(reinterpret_cast<void *>(req.ifm[i].ptr), req.ifm[i].size));
236 }
237
238 vector<DataPtr> ofm;
239 for (uint32_t i = 0; i < req.ofm_count; ++i) {
240 ofm.push_back(DataPtr(reinterpret_cast<void *>(req.ofm[i].ptr), req.ofm[i].size));
241 }
242
243 vector<DataPtr> expectedOutput;
244
Jonny Svärde9f57dc2020-12-10 11:12:44 +0100245 vector<uint8_t> pmuEventConfig(ETHOSU_CORE_PMU_MAX);
Bhavik Patelffe845d2020-11-16 12:13:56 +0100246 for (uint32_t i = 0; i < ETHOSU_CORE_PMU_MAX; i++) {
247 pmuEventConfig[i] = req.pmu_event_config[i];
248 }
249
250 InferenceJob job(
251 "job", networkModel, ifm, ofm, expectedOutput, -1, pmuEventConfig, req.pmu_cycle_counter_enable);
Kristofer Jonsson34e24962020-11-23 16:22:10 +0100252 job.invalidate();
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200253
254 bool failed = inferenceProcess.runJob(job);
Kristofer Jonsson34e24962020-11-23 16:22:10 +0100255 job.clean();
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200256
Bhavik Patelffe845d2020-11-16 12:13:56 +0100257 sendInferenceRsp(req.user_arg,
258 job.output,
259 failed,
260 job.pmuEventConfig,
261 job.pmuCycleCounterEnable,
262 job.pmuEventCount,
263 job.pmuCycleCounterCount);
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200264 break;
265 }
Per Åstranddc28b132020-09-28 13:02:18 +0200266 default: {
267 printf("Unexpected message type: %" PRIu32 ", skipping %" PRIu32 " bytes\n", msg.type, msg.length);
268
269 queueIn.skip(msg.length);
270 } break;
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200271 }
272
273 return true;
274}
275
276void MessageProcess::sendPong() {
277 if (!queueOut.write(ETHOSU_CORE_MSG_PONG)) {
278 printf("Failed to write pong.\n");
279 }
Jonny Svärd44398c82020-10-06 14:18:28 +0200280 mailbox.sendMessage();
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200281}
282
Bhavik Patelffe845d2020-11-16 12:13:56 +0100283void MessageProcess::sendInferenceRsp(uint64_t userArg,
284 vector<DataPtr> &ofm,
285 bool failed,
286 vector<uint8_t> &pmuEventConfig,
287 uint32_t pmuCycleCounterEnable,
288 vector<uint32_t> &pmuEventCount,
289 uint64_t pmuCycleCounterCount) {
290 ethosu_core_inference_rsp rsp = {
291 .pmu_event_count =
292 {
293 0,
294 },
295 };
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200296
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200297 rsp.user_arg = userArg;
298 rsp.ofm_count = ofm.size();
299 rsp.status = failed ? ETHOSU_CORE_STATUS_ERROR : ETHOSU_CORE_STATUS_OK;
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200300
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200301 for (size_t i = 0; i < ofm.size(); ++i) {
302 rsp.ofm_size[i] = ofm[i].size;
303 }
304
Bhavik Patelffe845d2020-11-16 12:13:56 +0100305 for (size_t i = 0; i < pmuEventConfig.size(); i++) {
306 rsp.pmu_event_config[i] = pmuEventConfig[i];
307 }
308 rsp.pmu_cycle_counter_enable = pmuCycleCounterEnable;
309 for (size_t i = 0; i < pmuEventCount.size(); i++) {
310 rsp.pmu_event_count[i] = pmuEventCount[i];
311 }
312 rsp.pmu_cycle_counter_count = pmuCycleCounterCount;
313
Per Åstrand91a91732020-09-25 15:04:26 +0200314 printf("Sending inference response. userArg=0x%" PRIx64 ", ofm_count=%" PRIu32 ", status=%" PRIu32 "\n",
Kristofer Jonsson72fa50b2020-09-10 13:26:41 +0200315 rsp.user_arg,
316 rsp.ofm_count,
317 rsp.status);
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200318
319 if (!queueOut.write(ETHOSU_CORE_MSG_INFERENCE_RSP, rsp)) {
320 printf("Failed to write inference.\n");
321 }
Jonny Svärd44398c82020-10-06 14:18:28 +0200322 mailbox.sendMessage();
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200323}
Jonny Svärd44398c82020-10-06 14:18:28 +0200324
325void MessageProcess::mailboxCallback(void *userArg) {
326 MessageProcess *_this = reinterpret_cast<MessageProcess *>(userArg);
327 _this->handleIrq();
328}
329
Kristofer Jonsson641c0912020-08-31 11:34:14 +0200330} // namespace MessageProcess