blob: 16d2db0c06f0fa60dbfde755e65dc57c2c257f60 [file] [log] [blame]
Kristofer Jonsson116a6352020-08-20 17:25:23 +02001/*
Kristofer Jonsson35de9e62022-03-08 13:25:45 +01002 * Copyright (c) 2020-2022 Arm Limited. All rights reserved.
Kristofer Jonsson116a6352020-08-20 17:25:23 +02003 *
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
Kristofer Jonssonb74492c2020-09-10 13:26:01 +020019#include "autogen/tflite_schema.hpp"
20
Kristofer Jonsson116a6352020-08-20 17:25:23 +020021#include <ethosu.hpp>
22#include <uapi/ethosu.h>
23
24#include <algorithm>
25#include <exception>
Kristofer Jonsson35de9e62022-03-08 13:25:45 +010026#include <fstream>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020027#include <iostream>
28
Kristofer Jonsson116a6352020-08-20 17:25:23 +020029#include <fcntl.h>
30#include <poll.h>
Davide Grohmanne446b422021-10-19 15:33:23 +020031#include <signal.h>
Kristofer Jonsson79689c52020-10-16 14:42:19 +020032#include <sys/ioctl.h>
33#include <sys/mman.h>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020034#include <unistd.h>
35
36using namespace std;
37
Per Åstrandec3f2b02021-06-09 10:43:38 +020038namespace EthosU {
39__attribute__((weak)) int eioctl(int fd, unsigned long cmd, void *data = nullptr) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +020040 int ret = ::ioctl(fd, cmd, data);
Kristofer Jonsson79689c52020-10-16 14:42:19 +020041 if (ret < 0) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +020042 throw EthosU::Exception("IOCTL failed");
43 }
44
45 return ret;
46}
Kristofer Jonssonb74492c2020-09-10 13:26:01 +020047
Per Åstrandec3f2b02021-06-09 10:43:38 +020048__attribute__((weak)) int eopen(const char *pathname, int flags) {
49 int fd = ::open(pathname, flags);
Per Åstrandec3f2b02021-06-09 10:43:38 +020050 if (fd < 0) {
51 throw Exception("Failed to open device");
52 }
53
54 return fd;
55}
56
Davide Grohmanne446b422021-10-19 15:33:23 +020057__attribute__((weak)) int
58eppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmo_p, const sigset_t *sigmask) {
59 int result = ::ppoll(fds, nfds, tmo_p, sigmask);
Davide Grohmannc90bfab2021-10-19 13:59:27 +020060 if (result < 0) {
Davide Grohmanne446b422021-10-19 15:33:23 +020061 throw Exception("Failed to wait for ppoll event or signal");
Davide Grohmannc90bfab2021-10-19 13:59:27 +020062 }
63
64 return result;
Per Åstrandec3f2b02021-06-09 10:43:38 +020065}
66
67__attribute__((weak)) int eclose(int fd) {
Davide Grohmannc90bfab2021-10-19 13:59:27 +020068 int result = ::close(fd);
69 if (result < 0) {
70 throw Exception("Failed to close file");
71 }
72
73 return result;
Per Åstrandec3f2b02021-06-09 10:43:38 +020074}
75__attribute((weak)) void *emmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) {
Davide Grohmannc90bfab2021-10-19 13:59:27 +020076 void *ptr = ::mmap(addr, length, prot, flags, fd, offset);
77 if (ptr == MAP_FAILED) {
78 throw Exception("Failed to mmap file");
79 }
80
81 return ptr;
Per Åstrandec3f2b02021-06-09 10:43:38 +020082}
83
84__attribute__((weak)) int emunmap(void *addr, size_t length) {
Davide Grohmannc90bfab2021-10-19 13:59:27 +020085 int result = ::munmap(addr, length);
86 if (result < 0) {
87 throw Exception("Failed to munmap file");
88 }
89
90 return result;
Per Åstrandec3f2b02021-06-09 10:43:38 +020091}
92
93} // namespace EthosU
94
Kristofer Jonssonb74492c2020-09-10 13:26:01 +020095/****************************************************************************
96 * TFL micro helpers
97 ****************************************************************************/
Per Åstrandec3f2b02021-06-09 10:43:38 +020098namespace {
Kristofer Jonsson79689c52020-10-16 14:42:19 +020099size_t getShapeSize(const flatbuffers::Vector<int32_t> *shape) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200100 size_t size = 1;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200101
Jonny Svärd2c017132021-04-12 15:56:44 +0200102 if (shape == nullptr) {
103 throw EthosU::Exception("getShapeSize(): nullptr arg");
104 }
105
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200106 for (auto it = shape->begin(); it != shape->end(); ++it) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200107 size *= *it;
108 }
109
110 return size;
111}
112
Kristofer Jonsson5e632c22020-11-25 10:58:38 +0100113size_t getTensorTypeSize(const enum tflite::TensorType type) {
114 switch (type) {
115 case tflite::TensorType::TensorType_UINT8:
116 case tflite::TensorType::TensorType_INT8:
117 return 1;
118 case tflite::TensorType::TensorType_INT16:
119 return 2;
Henrik Hoglind3db0ffa2021-11-23 11:55:48 +0100120 case tflite::TensorType::TensorType_INT32:
Henrik Hoglind031f4c12021-03-25 08:32:23 +0100121 case tflite::TensorType::TensorType_FLOAT32:
122 return 4;
Kristofer Jonsson5e632c22020-11-25 10:58:38 +0100123 default:
124 throw EthosU::Exception("Unsupported tensor type");
125 }
126}
127
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200128vector<size_t> getSubGraphDims(const tflite::SubGraph *subgraph, const flatbuffers::Vector<int32_t> *tensorMap) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200129 vector<size_t> dims;
130
Jonny Svärd2c017132021-04-12 15:56:44 +0200131 if (subgraph == nullptr || tensorMap == nullptr) {
132 throw EthosU::Exception("getSubGraphDims(): nullptr arg(s)");
133 }
134
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200135 for (auto index = tensorMap->begin(); index != tensorMap->end(); ++index) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200136 auto tensor = subgraph->tensors()->Get(*index);
137 size_t size = getShapeSize(tensor->shape());
Kristofer Jonsson5e632c22020-11-25 10:58:38 +0100138 size *= getTensorTypeSize(tensor->type());
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200139
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200140 if (size > 0) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200141 dims.push_back(size);
142 }
143 }
144
145 return dims;
146}
147
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200148} // namespace
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200149
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200150namespace EthosU {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200151
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200152/****************************************************************************
153 * Exception
154 ****************************************************************************/
155
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200156Exception::Exception(const char *msg) : msg(msg) {}
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200157
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200158Exception::~Exception() throw() {}
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200159
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200160const char *Exception::what() const throw() {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200161 return msg.c_str();
162}
163
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200164/****************************************************************************
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200165 * Semantic Version
166 ****************************************************************************/
167
168bool SemanticVersion::operator==(const SemanticVersion &other) {
169 return other.major == major && other.minor == minor && other.patch == patch;
170}
171
172bool SemanticVersion::operator<(const SemanticVersion &other) {
173 if (other.major > major)
174 return true;
175 if (other.minor > minor)
176 return true;
177 return other.patch > patch;
178}
179
180bool SemanticVersion::operator<=(const SemanticVersion &other) {
181 return *this < other || *this == other;
182}
183
184bool SemanticVersion::operator!=(const SemanticVersion &other) {
185 return !(*this == other);
186}
187
188bool SemanticVersion::operator>(const SemanticVersion &other) {
189 return !(*this <= other);
190}
191
192bool SemanticVersion::operator>=(const SemanticVersion &other) {
193 return !(*this < other);
194}
195
196ostream &operator<<(ostream &out, const SemanticVersion &v) {
197 return out << "{ major=" << unsigned(v.major) << ", minor=" << unsigned(v.minor) << ", patch=" << unsigned(v.patch)
198 << " }";
199}
200
201/****************************************************************************
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200202 * Device
203 ****************************************************************************/
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200204Device::Device(const char *device) {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200205 fd = eopen(device, O_RDWR | O_NONBLOCK);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200206}
207
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200208Device::~Device() {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200209 eclose(fd);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200210}
211
Per Åstrandafb399f2021-11-26 12:50:35 +0100212int Device::ioctl(unsigned long cmd, void *data) const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200213 return eioctl(fd, cmd, data);
214}
215
Per Åstrandafb399f2021-11-26 12:50:35 +0100216Capabilities Device::capabilities() const {
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200217 ethosu_uapi_device_capabilities uapi;
218 (void)eioctl(fd, ETHOSU_IOCTL_CAPABILITIES_REQ, static_cast<void *>(&uapi));
219
220 Capabilities capabilities(
221 HardwareId(uapi.hw_id.version_status,
222 SemanticVersion(uapi.hw_id.version_major, uapi.hw_id.version_minor),
223 SemanticVersion(uapi.hw_id.product_major),
224 SemanticVersion(uapi.hw_id.arch_major_rev, uapi.hw_id.arch_minor_rev, uapi.hw_id.arch_patch_rev)),
Davide Grohmann40e23d12021-06-17 09:59:40 +0200225 HardwareConfiguration(uapi.hw_cfg.macs_per_cc, uapi.hw_cfg.cmd_stream_version, bool(uapi.hw_cfg.custom_dma)),
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200226 SemanticVersion(uapi.driver_major_rev, uapi.driver_minor_rev, uapi.driver_patch_rev));
227 return capabilities;
228}
229
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200230/****************************************************************************
231 * Buffer
232 ****************************************************************************/
233
Per Åstrandafb399f2021-11-26 12:50:35 +0100234Buffer::Buffer(const Device &device, const size_t capacity) : fd(-1), dataPtr(nullptr), dataCapacity(capacity) {
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200235 ethosu_uapi_buffer_create uapi = {static_cast<uint32_t>(dataCapacity)};
236 fd = device.ioctl(ETHOSU_IOCTL_BUFFER_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200237
Davide Grohmann2ba3c1d2021-11-08 15:08:48 +0100238 void *d;
239 try {
240 d = emmap(nullptr, dataCapacity, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
241 } catch (std::exception &e) {
242 try {
243 eclose(fd);
244 } catch (...) { std::throw_with_nested(e); }
245 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200246 dataPtr = reinterpret_cast<char *>(d);
247}
248
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200249Buffer::~Buffer() {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200250 emunmap(dataPtr, dataCapacity);
251 eclose(fd);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200252}
253
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200254size_t Buffer::capacity() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200255 return dataCapacity;
256}
257
Per Åstrandafb399f2021-11-26 12:50:35 +0100258void Buffer::clear() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200259 resize(0, 0);
260}
261
Per Åstrandafb399f2021-11-26 12:50:35 +0100262char *Buffer::data() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200263 return dataPtr + offset();
264}
265
Per Åstrandafb399f2021-11-26 12:50:35 +0100266void Buffer::resize(size_t size, size_t offset) const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200267 ethosu_uapi_buffer uapi;
268 uapi.offset = offset;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200269 uapi.size = size;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200270 eioctl(fd, ETHOSU_IOCTL_BUFFER_SET, static_cast<void *>(&uapi));
271}
272
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200273size_t Buffer::offset() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200274 ethosu_uapi_buffer uapi;
275 eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast<void *>(&uapi));
276 return uapi.offset;
277}
278
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200279size_t Buffer::size() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200280 ethosu_uapi_buffer uapi;
281 eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast<void *>(&uapi));
282 return uapi.size;
283}
284
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200285int Buffer::getFd() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200286 return fd;
287}
288
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200289/****************************************************************************
290 * Network
291 ****************************************************************************/
292
Per Åstrandafb399f2021-11-26 12:50:35 +0100293Network::Network(const Device &device, shared_ptr<Buffer> &buffer) : fd(-1), buffer(buffer) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200294 // Create buffer handle
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200295 ethosu_uapi_network_create uapi;
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100296 uapi.type = ETHOSU_UAPI_NETWORK_BUFFER;
297 uapi.fd = buffer->getFd();
298 fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast<void *>(&uapi));
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200299
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100300 try {
301 parseModel(buffer->data());
302 } catch (...) {
303 eclose(fd);
304 throw;
Jonny Svärd2c017132021-04-12 15:56:44 +0200305 }
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100306}
Jonny Svärd2c017132021-04-12 15:56:44 +0200307
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100308Network::Network(const Device &device, const string &model, const unsigned index) : fd(-1) {
309 // Create buffer handle
310 ethosu_uapi_network_create uapi;
311 uapi.type = ETHOSU_UAPI_NETWORK_INDEX;
312 uapi.index = index;
313 fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast<void *>(&uapi));
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200314
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100315 try {
316 // Open file
317 ifstream ifs(model, std::ios::binary);
318 if (!ifs.is_open()) {
319 throw Exception("Failed to open model file.");
320 }
321
322 // Get file size
323 ifs.seekg(0, ios_base::end);
324 size_t size = ifs.tellg();
325 ifs.seekg(0, ios_base::beg);
326
327 // Read data into buffer
328 vector<char> buffer(size);
329 ifs.read(buffer.data(), size);
330
331 parseModel(buffer.data());
332 } catch (...) {
333 eclose(fd);
334 throw;
335 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200336}
337
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200338Network::~Network() {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200339 eclose(fd);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200340}
341
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200342int Network::ioctl(unsigned long cmd, void *data) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200343 return eioctl(fd, cmd, data);
344}
345
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200346shared_ptr<Buffer> Network::getBuffer() {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200347 return buffer;
348}
349
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200350const std::vector<size_t> &Network::getIfmDims() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200351 return ifmDims;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200352}
353
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200354size_t Network::getIfmSize() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200355 size_t size = 0;
356
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200357 for (auto s : ifmDims) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200358 size += s;
359 }
360
361 return size;
362}
363
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200364const std::vector<size_t> &Network::getOfmDims() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200365 return ofmDims;
366}
367
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200368size_t Network::getOfmSize() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200369 size_t size = 0;
370
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200371 for (auto s : ofmDims) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200372 size += s;
373 }
374
375 return size;
376}
377
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100378void Network::parseModel(const char *data) {
379 // Create model handle
380 const tflite::Model *model = tflite::GetModel(reinterpret_cast<const void *>(data));
381
382 if (model->subgraphs() == nullptr) {
383 EthosU::Exception("Failed to get subgraphs: nullptr");
384 }
385
386 // Get input dimensions for first subgraph
387 auto *subgraph = *model->subgraphs()->begin();
388 ifmDims = getSubGraphDims(subgraph, subgraph->inputs());
389
390 // Get output dimensions for last subgraph
391 subgraph = *model->subgraphs()->rbegin();
392 ofmDims = getSubGraphDims(subgraph, subgraph->outputs());
393}
394
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200395/****************************************************************************
396 * Inference
397 ****************************************************************************/
398
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200399Inference::~Inference() {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200400 eclose(fd);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200401}
402
Per Åstrand2354d3e2020-10-24 20:17:10 +0200403void Inference::create(std::vector<uint32_t> &counterConfigs, bool cycleCounterEnable = false) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200404 ethosu_uapi_inference_create uapi;
405
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200406 if (ifmBuffers.size() > ETHOSU_FD_MAX) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200407 throw Exception("IFM buffer overflow");
408 }
409
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200410 if (ofmBuffers.size() > ETHOSU_FD_MAX) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200411 throw Exception("OFM buffer overflow");
412 }
413
Per Åstrand2354d3e2020-10-24 20:17:10 +0200414 if (counterConfigs.size() != ETHOSU_PMU_EVENT_MAX) {
415 throw Exception("Wrong size of counter configurations");
416 }
417
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200418 uapi.ifm_count = 0;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200419 for (auto it : ifmBuffers) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200420 uapi.ifm_fd[uapi.ifm_count++] = it->getFd();
421 }
422
423 uapi.ofm_count = 0;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200424 for (auto it : ofmBuffers) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200425 uapi.ofm_fd[uapi.ofm_count++] = it->getFd();
426 }
427
Per Åstrand2354d3e2020-10-24 20:17:10 +0200428 for (int i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) {
429 uapi.pmu_config.events[i] = counterConfigs[i];
430 }
431
432 uapi.pmu_config.cycle_count = cycleCounterEnable;
433
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200434 fd = network->ioctl(ETHOSU_IOCTL_INFERENCE_CREATE, static_cast<void *>(&uapi));
435}
436
Per Åstrand2354d3e2020-10-24 20:17:10 +0200437std::vector<uint32_t> Inference::initializeCounterConfig() {
438 return std::vector<uint32_t>(ETHOSU_PMU_EVENT_MAX, 0);
439}
440
441uint32_t Inference::getMaxPmuEventCounters() {
442 return ETHOSU_PMU_EVENT_MAX;
443}
444
Per Åstrandafb399f2021-11-26 12:50:35 +0100445int Inference::wait(int64_t timeoutNanos) const {
Davide Grohmanne446b422021-10-19 15:33:23 +0200446 struct pollfd pfd;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200447 pfd.fd = fd;
448 pfd.events = POLLIN | POLLERR;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200449 pfd.revents = 0;
450
Davide Grohmanne446b422021-10-19 15:33:23 +0200451 // if timeout negative wait forever
452 if (timeoutNanos < 0) {
453 return eppoll(&pfd, 1, NULL, NULL);
454 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200455
Davide Grohmanne446b422021-10-19 15:33:23 +0200456 struct timespec tmo_p;
457 int64_t nanosec = 1000000000;
458 tmo_p.tv_sec = timeoutNanos / nanosec;
459 tmo_p.tv_nsec = timeoutNanos % nanosec;
Per Åstrand2354d3e2020-10-24 20:17:10 +0200460
Davide Grohmanne446b422021-10-19 15:33:23 +0200461 return eppoll(&pfd, 1, &tmo_p, NULL);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200462}
463
Per Åstrandafb399f2021-11-26 12:50:35 +0100464bool Inference::failed() const {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200465 ethosu_uapi_result_status uapi;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200466
Per Åstrand2354d3e2020-10-24 20:17:10 +0200467 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
468
469 return uapi.status != ETHOSU_UAPI_STATUS_OK;
470}
471
Per Åstrandafb399f2021-11-26 12:50:35 +0100472const std::vector<uint32_t> Inference::getPmuCounters() const {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200473 ethosu_uapi_result_status uapi;
474 std::vector<uint32_t> counterValues = std::vector<uint32_t>(ETHOSU_PMU_EVENT_MAX, 0);
475
476 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
477
478 for (int i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) {
479 if (uapi.pmu_config.events[i]) {
480 counterValues.at(i) = uapi.pmu_count.events[i];
481 }
482 }
483
484 return counterValues;
485}
486
Per Åstrandafb399f2021-11-26 12:50:35 +0100487uint64_t Inference::getCycleCounter() const {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200488 ethosu_uapi_result_status uapi;
489
490 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
491
492 return uapi.pmu_count.cycle_count;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200493}
494
Per Åstrandafb399f2021-11-26 12:50:35 +0100495int Inference::getFd() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200496 return fd;
497}
498
Per Åstrandafb399f2021-11-26 12:50:35 +0100499const shared_ptr<Network> Inference::getNetwork() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200500 return network;
501}
502
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200503vector<shared_ptr<Buffer>> &Inference::getIfmBuffers() {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200504 return ifmBuffers;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200505}
506
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200507vector<shared_ptr<Buffer>> &Inference::getOfmBuffers() {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200508 return ofmBuffers;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200509}
510
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200511} // namespace EthosU