blob: 4fc431b0959685e1bf1e9cbaaa9d1569e54f95be [file] [log] [blame]
Kristofer Jonsson116a6352020-08-20 17:25:23 +02001/*
Anton Moberg4e5e0562021-03-31 11:11:36 +02002 * Copyright (c) 2020-2021 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>
26#include <iostream>
27
Kristofer Jonsson116a6352020-08-20 17:25:23 +020028#include <fcntl.h>
29#include <poll.h>
Davide Grohmanne446b422021-10-19 15:33:23 +020030#include <signal.h>
Kristofer Jonsson79689c52020-10-16 14:42:19 +020031#include <sys/ioctl.h>
32#include <sys/mman.h>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020033#include <unistd.h>
34
35using namespace std;
36
Per Åstrandec3f2b02021-06-09 10:43:38 +020037namespace EthosU {
38__attribute__((weak)) int eioctl(int fd, unsigned long cmd, void *data = nullptr) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +020039 int ret = ::ioctl(fd, cmd, data);
Kristofer Jonsson79689c52020-10-16 14:42:19 +020040 if (ret < 0) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +020041 throw EthosU::Exception("IOCTL failed");
42 }
43
44 return ret;
45}
Kristofer Jonssonb74492c2020-09-10 13:26:01 +020046
Per Åstrandec3f2b02021-06-09 10:43:38 +020047__attribute__((weak)) int eopen(const char *pathname, int flags) {
48 int fd = ::open(pathname, flags);
Per Åstrandec3f2b02021-06-09 10:43:38 +020049 if (fd < 0) {
50 throw Exception("Failed to open device");
51 }
52
53 return fd;
54}
55
Davide Grohmanne446b422021-10-19 15:33:23 +020056__attribute__((weak)) int
57eppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmo_p, const sigset_t *sigmask) {
58 int result = ::ppoll(fds, nfds, tmo_p, sigmask);
Davide Grohmannc90bfab2021-10-19 13:59:27 +020059 if (result < 0) {
Davide Grohmanne446b422021-10-19 15:33:23 +020060 throw Exception("Failed to wait for ppoll event or signal");
Davide Grohmannc90bfab2021-10-19 13:59:27 +020061 }
62
63 return result;
Per Åstrandec3f2b02021-06-09 10:43:38 +020064}
65
66__attribute__((weak)) int eclose(int fd) {
Davide Grohmannc90bfab2021-10-19 13:59:27 +020067 int result = ::close(fd);
68 if (result < 0) {
69 throw Exception("Failed to close file");
70 }
71
72 return result;
Per Åstrandec3f2b02021-06-09 10:43:38 +020073}
74__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 +020075 void *ptr = ::mmap(addr, length, prot, flags, fd, offset);
76 if (ptr == MAP_FAILED) {
77 throw Exception("Failed to mmap file");
78 }
79
80 return ptr;
Per Åstrandec3f2b02021-06-09 10:43:38 +020081}
82
83__attribute__((weak)) int emunmap(void *addr, size_t length) {
Davide Grohmannc90bfab2021-10-19 13:59:27 +020084 int result = ::munmap(addr, length);
85 if (result < 0) {
86 throw Exception("Failed to munmap file");
87 }
88
89 return result;
Per Åstrandec3f2b02021-06-09 10:43:38 +020090}
91
92} // namespace EthosU
93
Kristofer Jonssonb74492c2020-09-10 13:26:01 +020094/****************************************************************************
95 * TFL micro helpers
96 ****************************************************************************/
Per Åstrandec3f2b02021-06-09 10:43:38 +020097namespace {
Kristofer Jonsson79689c52020-10-16 14:42:19 +020098size_t getShapeSize(const flatbuffers::Vector<int32_t> *shape) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +020099 size_t size = 1;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200100
Jonny Svärd2c017132021-04-12 15:56:44 +0200101 if (shape == nullptr) {
102 throw EthosU::Exception("getShapeSize(): nullptr arg");
103 }
104
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200105 for (auto it = shape->begin(); it != shape->end(); ++it) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200106 size *= *it;
107 }
108
109 return size;
110}
111
Kristofer Jonsson5e632c22020-11-25 10:58:38 +0100112size_t getTensorTypeSize(const enum tflite::TensorType type) {
113 switch (type) {
114 case tflite::TensorType::TensorType_UINT8:
115 case tflite::TensorType::TensorType_INT8:
116 return 1;
117 case tflite::TensorType::TensorType_INT16:
118 return 2;
Henrik Hoglind031f4c12021-03-25 08:32:23 +0100119 case tflite::TensorType::TensorType_FLOAT32:
120 return 4;
Kristofer Jonsson5e632c22020-11-25 10:58:38 +0100121 default:
122 throw EthosU::Exception("Unsupported tensor type");
123 }
124}
125
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200126vector<size_t> getSubGraphDims(const tflite::SubGraph *subgraph, const flatbuffers::Vector<int32_t> *tensorMap) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200127 vector<size_t> dims;
128
Jonny Svärd2c017132021-04-12 15:56:44 +0200129 if (subgraph == nullptr || tensorMap == nullptr) {
130 throw EthosU::Exception("getSubGraphDims(): nullptr arg(s)");
131 }
132
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200133 for (auto index = tensorMap->begin(); index != tensorMap->end(); ++index) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200134 auto tensor = subgraph->tensors()->Get(*index);
135 size_t size = getShapeSize(tensor->shape());
Kristofer Jonsson5e632c22020-11-25 10:58:38 +0100136 size *= getTensorTypeSize(tensor->type());
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200137
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200138 if (size > 0) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200139 dims.push_back(size);
140 }
141 }
142
143 return dims;
144}
145
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200146} // namespace
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200147
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200148namespace EthosU {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200149
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200150/****************************************************************************
151 * Exception
152 ****************************************************************************/
153
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200154Exception::Exception(const char *msg) : msg(msg) {}
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200155
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200156Exception::~Exception() throw() {}
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200157
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200158const char *Exception::what() const throw() {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200159 return msg.c_str();
160}
161
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200162/****************************************************************************
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200163 * Semantic Version
164 ****************************************************************************/
165
166bool SemanticVersion::operator==(const SemanticVersion &other) {
167 return other.major == major && other.minor == minor && other.patch == patch;
168}
169
170bool SemanticVersion::operator<(const SemanticVersion &other) {
171 if (other.major > major)
172 return true;
173 if (other.minor > minor)
174 return true;
175 return other.patch > patch;
176}
177
178bool SemanticVersion::operator<=(const SemanticVersion &other) {
179 return *this < other || *this == other;
180}
181
182bool SemanticVersion::operator!=(const SemanticVersion &other) {
183 return !(*this == other);
184}
185
186bool SemanticVersion::operator>(const SemanticVersion &other) {
187 return !(*this <= other);
188}
189
190bool SemanticVersion::operator>=(const SemanticVersion &other) {
191 return !(*this < other);
192}
193
194ostream &operator<<(ostream &out, const SemanticVersion &v) {
195 return out << "{ major=" << unsigned(v.major) << ", minor=" << unsigned(v.minor) << ", patch=" << unsigned(v.patch)
196 << " }";
197}
198
199/****************************************************************************
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200200 * Device
201 ****************************************************************************/
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200202Device::Device(const char *device) {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200203 fd = eopen(device, O_RDWR | O_NONBLOCK);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200204}
205
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200206Device::~Device() {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200207 eclose(fd);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200208}
209
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200210int Device::ioctl(unsigned long cmd, void *data) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200211 return eioctl(fd, cmd, data);
212}
213
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200214Capabilities Device::capabilities() {
215 ethosu_uapi_device_capabilities uapi;
216 (void)eioctl(fd, ETHOSU_IOCTL_CAPABILITIES_REQ, static_cast<void *>(&uapi));
217
218 Capabilities capabilities(
219 HardwareId(uapi.hw_id.version_status,
220 SemanticVersion(uapi.hw_id.version_major, uapi.hw_id.version_minor),
221 SemanticVersion(uapi.hw_id.product_major),
222 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 +0200223 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 +0200224 SemanticVersion(uapi.driver_major_rev, uapi.driver_minor_rev, uapi.driver_patch_rev));
225 return capabilities;
226}
227
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200228/****************************************************************************
229 * Buffer
230 ****************************************************************************/
231
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200232Buffer::Buffer(Device &device, const size_t capacity) : fd(-1), dataPtr(nullptr), dataCapacity(capacity) {
233 ethosu_uapi_buffer_create uapi = {static_cast<uint32_t>(dataCapacity)};
234 fd = device.ioctl(ETHOSU_IOCTL_BUFFER_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200235
Davide Grohmann2ba3c1d2021-11-08 15:08:48 +0100236 void *d;
237 try {
238 d = emmap(nullptr, dataCapacity, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
239 } catch (std::exception &e) {
240 try {
241 eclose(fd);
242 } catch (...) { std::throw_with_nested(e); }
243 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200244 dataPtr = reinterpret_cast<char *>(d);
245}
246
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200247Buffer::~Buffer() {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200248 emunmap(dataPtr, dataCapacity);
249 eclose(fd);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200250}
251
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200252size_t Buffer::capacity() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200253 return dataCapacity;
254}
255
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200256void Buffer::clear() {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200257 resize(0, 0);
258}
259
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200260char *Buffer::data() {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200261 return dataPtr + offset();
262}
263
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200264void Buffer::resize(size_t size, size_t offset) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200265 ethosu_uapi_buffer uapi;
266 uapi.offset = offset;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200267 uapi.size = size;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200268 eioctl(fd, ETHOSU_IOCTL_BUFFER_SET, static_cast<void *>(&uapi));
269}
270
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200271size_t Buffer::offset() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200272 ethosu_uapi_buffer uapi;
273 eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast<void *>(&uapi));
274 return uapi.offset;
275}
276
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200277size_t Buffer::size() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200278 ethosu_uapi_buffer uapi;
279 eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast<void *>(&uapi));
280 return uapi.size;
281}
282
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200283int Buffer::getFd() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200284 return fd;
285}
286
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200287/****************************************************************************
288 * Network
289 ****************************************************************************/
290
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200291Network::Network(Device &device, shared_ptr<Buffer> &buffer) : fd(-1), buffer(buffer) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200292 // Create buffer handle
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200293 ethosu_uapi_network_create uapi;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200294 uapi.fd = buffer->getFd();
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200295 fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast<void *>(&uapi));
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200296
297 // Create model handle
298 const tflite::Model *model = tflite::GetModel(reinterpret_cast<void *>(buffer->data()));
299
Jonny Svärd2c017132021-04-12 15:56:44 +0200300 if (model->subgraphs() == nullptr) {
Davide Grohmann2ba3c1d2021-11-08 15:08:48 +0100301 try {
302 eclose(fd);
303 } catch (...) { std::throw_with_nested(EthosU::Exception("Failed to get subgraphs: nullptr")); }
Jonny Svärd2c017132021-04-12 15:56:44 +0200304 }
305
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200306 // Get input dimensions for first subgraph
307 auto *subgraph = *model->subgraphs()->begin();
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200308 ifmDims = getSubGraphDims(subgraph, subgraph->inputs());
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200309
310 // Get output dimensions for last subgraph
311 subgraph = *model->subgraphs()->rbegin();
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200312 ofmDims = getSubGraphDims(subgraph, subgraph->outputs());
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200313}
314
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200315Network::~Network() {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200316 eclose(fd);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200317}
318
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200319int Network::ioctl(unsigned long cmd, void *data) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200320 return eioctl(fd, cmd, data);
321}
322
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200323shared_ptr<Buffer> Network::getBuffer() {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200324 return buffer;
325}
326
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200327const std::vector<size_t> &Network::getIfmDims() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200328 return ifmDims;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200329}
330
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200331size_t Network::getIfmSize() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200332 size_t size = 0;
333
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200334 for (auto s : ifmDims) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200335 size += s;
336 }
337
338 return size;
339}
340
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200341const std::vector<size_t> &Network::getOfmDims() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200342 return ofmDims;
343}
344
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200345size_t Network::getOfmSize() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200346 size_t size = 0;
347
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200348 for (auto s : ofmDims) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200349 size += s;
350 }
351
352 return size;
353}
354
355/****************************************************************************
356 * Inference
357 ****************************************************************************/
358
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200359Inference::~Inference() {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200360 eclose(fd);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200361}
362
Per Åstrand2354d3e2020-10-24 20:17:10 +0200363void Inference::create(std::vector<uint32_t> &counterConfigs, bool cycleCounterEnable = false) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200364 ethosu_uapi_inference_create uapi;
365
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200366 if (ifmBuffers.size() > ETHOSU_FD_MAX) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200367 throw Exception("IFM buffer overflow");
368 }
369
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200370 if (ofmBuffers.size() > ETHOSU_FD_MAX) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200371 throw Exception("OFM buffer overflow");
372 }
373
Per Åstrand2354d3e2020-10-24 20:17:10 +0200374 if (counterConfigs.size() != ETHOSU_PMU_EVENT_MAX) {
375 throw Exception("Wrong size of counter configurations");
376 }
377
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200378 uapi.ifm_count = 0;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200379 for (auto it : ifmBuffers) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200380 uapi.ifm_fd[uapi.ifm_count++] = it->getFd();
381 }
382
383 uapi.ofm_count = 0;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200384 for (auto it : ofmBuffers) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200385 uapi.ofm_fd[uapi.ofm_count++] = it->getFd();
386 }
387
Per Åstrand2354d3e2020-10-24 20:17:10 +0200388 for (int i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) {
389 uapi.pmu_config.events[i] = counterConfigs[i];
390 }
391
392 uapi.pmu_config.cycle_count = cycleCounterEnable;
393
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200394 fd = network->ioctl(ETHOSU_IOCTL_INFERENCE_CREATE, static_cast<void *>(&uapi));
395}
396
Per Åstrand2354d3e2020-10-24 20:17:10 +0200397std::vector<uint32_t> Inference::initializeCounterConfig() {
398 return std::vector<uint32_t>(ETHOSU_PMU_EVENT_MAX, 0);
399}
400
401uint32_t Inference::getMaxPmuEventCounters() {
402 return ETHOSU_PMU_EVENT_MAX;
403}
404
Davide Grohmanne446b422021-10-19 15:33:23 +0200405int Inference::wait(int64_t timeoutNanos) {
406 struct pollfd pfd;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200407 pfd.fd = fd;
408 pfd.events = POLLIN | POLLERR;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200409 pfd.revents = 0;
410
Davide Grohmanne446b422021-10-19 15:33:23 +0200411 // if timeout negative wait forever
412 if (timeoutNanos < 0) {
413 return eppoll(&pfd, 1, NULL, NULL);
414 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200415
Davide Grohmanne446b422021-10-19 15:33:23 +0200416 struct timespec tmo_p;
417 int64_t nanosec = 1000000000;
418 tmo_p.tv_sec = timeoutNanos / nanosec;
419 tmo_p.tv_nsec = timeoutNanos % nanosec;
Per Åstrand2354d3e2020-10-24 20:17:10 +0200420
Davide Grohmanne446b422021-10-19 15:33:23 +0200421 return eppoll(&pfd, 1, &tmo_p, NULL);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200422}
423
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200424bool Inference::failed() {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200425 ethosu_uapi_result_status uapi;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200426
Per Åstrand2354d3e2020-10-24 20:17:10 +0200427 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
428
429 return uapi.status != ETHOSU_UAPI_STATUS_OK;
430}
431
432const std::vector<uint32_t> Inference::getPmuCounters() {
433 ethosu_uapi_result_status uapi;
434 std::vector<uint32_t> counterValues = std::vector<uint32_t>(ETHOSU_PMU_EVENT_MAX, 0);
435
436 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
437
438 for (int i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) {
439 if (uapi.pmu_config.events[i]) {
440 counterValues.at(i) = uapi.pmu_count.events[i];
441 }
442 }
443
444 return counterValues;
445}
446
447uint64_t Inference::getCycleCounter() {
448 ethosu_uapi_result_status uapi;
449
450 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
451
452 return uapi.pmu_count.cycle_count;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200453}
454
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200455int Inference::getFd() {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200456 return fd;
457}
458
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200459shared_ptr<Network> Inference::getNetwork() {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200460 return network;
461}
462
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200463vector<shared_ptr<Buffer>> &Inference::getIfmBuffers() {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200464 return ifmBuffers;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200465}
466
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200467vector<shared_ptr<Buffer>> &Inference::getOfmBuffers() {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200468 return ofmBuffers;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200469}
470
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200471} // namespace EthosU