blob: 16b9654d82ef48a6ea12a3aefb20d0d0d0e42acd [file] [log] [blame]
Kristofer Jonsson116a6352020-08-20 17:25:23 +02001/*
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +01002 * Copyright (c) 2020-2022 Arm Limited.
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
19#include <ethosu.hpp>
20#include <uapi/ethosu.h>
21
22#include <algorithm>
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +020023#include <cstdlib>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020024#include <exception>
Kristofer Jonsson35de9e62022-03-08 13:25:45 +010025#include <fstream>
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +020026#include <iomanip>
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
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +020038namespace {
39
40enum class Severity { Error, Warning, Info, Debug };
41
42class Log {
43public:
44 Log(const Severity _severity = Severity::Error) : severity(_severity) {}
45
46 ~Log() = default;
47
48 template <typename T>
49 const Log &operator<<(const T &d) const {
50 if (level >= severity) {
51 cout << d;
52 }
53
54 return *this;
55 }
56
57 const Log &operator<<(ostream &(*manip)(ostream &)) const {
58 if (level >= severity) {
59 manip(cout);
60 }
61
62 return *this;
63 }
64
65private:
66 static Severity getLogLevel() {
67 if (const char *e = getenv("ETHOSU_LOG_LEVEL")) {
68 const string env(e);
69
70 if (env == "Error") {
71 return Severity::Error;
72 } else if (env == "Warning") {
73 return Severity::Warning;
74 } else if (env == "Info") {
75 return Severity::Info;
76 } else if (env == "Debug") {
77 return Severity::Debug;
78 } else {
79 cerr << "Unsupported log level '" << env << "'" << endl;
80 }
81 }
82
83 return Severity::Warning;
84 }
85
86 static const Severity level;
87 const Severity severity;
88};
89
90const Severity Log::level = Log::getLogLevel();
91
92} // namespace
93
Per Åstrandec3f2b02021-06-09 10:43:38 +020094namespace EthosU {
95__attribute__((weak)) int eioctl(int fd, unsigned long cmd, void *data = nullptr) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +020096 int ret = ::ioctl(fd, cmd, data);
Kristofer Jonsson79689c52020-10-16 14:42:19 +020097 if (ret < 0) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +020098 throw EthosU::Exception("IOCTL failed");
99 }
100
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200101 Log(Severity::Debug) << "ioctl. fd=" << fd << ", cmd=" << setw(8) << setfill('0') << hex << cmd << ", ret=" << ret
102 << endl;
103
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200104 return ret;
105}
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200106
Per Åstrandec3f2b02021-06-09 10:43:38 +0200107__attribute__((weak)) int eopen(const char *pathname, int flags) {
108 int fd = ::open(pathname, flags);
Per Åstrandec3f2b02021-06-09 10:43:38 +0200109 if (fd < 0) {
110 throw Exception("Failed to open device");
111 }
112
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200113 Log(Severity::Debug) << "open. fd=" << fd << ", path='" << pathname << "', flags=" << flags << endl;
114
Per Åstrandec3f2b02021-06-09 10:43:38 +0200115 return fd;
116}
117
Davide Grohmanne446b422021-10-19 15:33:23 +0200118__attribute__((weak)) int
119eppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmo_p, const sigset_t *sigmask) {
120 int result = ::ppoll(fds, nfds, tmo_p, sigmask);
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200121 if (result < 0) {
Davide Grohmanne446b422021-10-19 15:33:23 +0200122 throw Exception("Failed to wait for ppoll event or signal");
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200123 }
124
125 return result;
Per Åstrandec3f2b02021-06-09 10:43:38 +0200126}
127
128__attribute__((weak)) int eclose(int fd) {
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200129 Log(Severity::Debug) << "close. fd=" << fd << endl;
130
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200131 int result = ::close(fd);
132 if (result < 0) {
133 throw Exception("Failed to close file");
134 }
135
136 return result;
Per Åstrandec3f2b02021-06-09 10:43:38 +0200137}
138__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 +0200139 void *ptr = ::mmap(addr, length, prot, flags, fd, offset);
140 if (ptr == MAP_FAILED) {
141 throw Exception("Failed to mmap file");
142 }
143
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200144 Log(Severity::Debug) << "map. fd=" << fd << ", addr=" << setfill('0') << addr << ", length=" << dec << length
145 << ", ptr=" << hex << ptr << endl;
146
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200147 return ptr;
Per Åstrandec3f2b02021-06-09 10:43:38 +0200148}
149
150__attribute__((weak)) int emunmap(void *addr, size_t length) {
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200151 Log(Severity::Debug) << "unmap. addr=" << setfill('0') << addr << ", length=" << dec << length << endl;
152
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200153 int result = ::munmap(addr, length);
154 if (result < 0) {
155 throw Exception("Failed to munmap file");
156 }
157
158 return result;
Per Åstrandec3f2b02021-06-09 10:43:38 +0200159}
160
161} // namespace EthosU
162
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200163namespace EthosU {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200164
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200165/****************************************************************************
166 * Exception
167 ****************************************************************************/
168
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200169Exception::Exception(const char *msg) : msg(msg) {}
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200170
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200171Exception::~Exception() throw() {}
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200172
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200173const char *Exception::what() const throw() {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200174 return msg.c_str();
175}
176
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200177/****************************************************************************
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200178 * Semantic Version
179 ****************************************************************************/
180
181bool SemanticVersion::operator==(const SemanticVersion &other) {
182 return other.major == major && other.minor == minor && other.patch == patch;
183}
184
185bool SemanticVersion::operator<(const SemanticVersion &other) {
186 if (other.major > major)
187 return true;
188 if (other.minor > minor)
189 return true;
190 return other.patch > patch;
191}
192
193bool SemanticVersion::operator<=(const SemanticVersion &other) {
194 return *this < other || *this == other;
195}
196
197bool SemanticVersion::operator!=(const SemanticVersion &other) {
198 return !(*this == other);
199}
200
201bool SemanticVersion::operator>(const SemanticVersion &other) {
202 return !(*this <= other);
203}
204
205bool SemanticVersion::operator>=(const SemanticVersion &other) {
206 return !(*this < other);
207}
208
209ostream &operator<<(ostream &out, const SemanticVersion &v) {
210 return out << "{ major=" << unsigned(v.major) << ", minor=" << unsigned(v.minor) << ", patch=" << unsigned(v.patch)
211 << " }";
212}
213
214/****************************************************************************
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200215 * Device
216 ****************************************************************************/
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200217Device::Device(const char *device) {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200218 fd = eopen(device, O_RDWR | O_NONBLOCK);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200219 Log(Severity::Info) << "Device(\"" << device << "\"). this=" << this << ", fd=" << fd << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200220}
221
Davide Grohmannfc495592022-04-25 15:27:52 +0200222Device::~Device() noexcept(false) {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200223 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200224 Log(Severity::Info) << "~Device(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200225}
226
Per Åstrandafb399f2021-11-26 12:50:35 +0100227int Device::ioctl(unsigned long cmd, void *data) const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200228 return eioctl(fd, cmd, data);
229}
230
Per Åstrandafb399f2021-11-26 12:50:35 +0100231Capabilities Device::capabilities() const {
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200232 ethosu_uapi_device_capabilities uapi;
233 (void)eioctl(fd, ETHOSU_IOCTL_CAPABILITIES_REQ, static_cast<void *>(&uapi));
234
235 Capabilities capabilities(
236 HardwareId(uapi.hw_id.version_status,
237 SemanticVersion(uapi.hw_id.version_major, uapi.hw_id.version_minor),
238 SemanticVersion(uapi.hw_id.product_major),
239 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 +0200240 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 +0200241 SemanticVersion(uapi.driver_major_rev, uapi.driver_minor_rev, uapi.driver_patch_rev));
242 return capabilities;
243}
244
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200245/****************************************************************************
246 * Buffer
247 ****************************************************************************/
248
Per Åstrandafb399f2021-11-26 12:50:35 +0100249Buffer::Buffer(const Device &device, const size_t capacity) : fd(-1), dataPtr(nullptr), dataCapacity(capacity) {
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200250 ethosu_uapi_buffer_create uapi = {static_cast<uint32_t>(dataCapacity)};
251 fd = device.ioctl(ETHOSU_IOCTL_BUFFER_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200252
Davide Grohmann2ba3c1d2021-11-08 15:08:48 +0100253 void *d;
254 try {
255 d = emmap(nullptr, dataCapacity, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
256 } catch (std::exception &e) {
257 try {
258 eclose(fd);
259 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200260 throw;
Davide Grohmann2ba3c1d2021-11-08 15:08:48 +0100261 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200262
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200263 dataPtr = reinterpret_cast<char *>(d);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200264
265 Log(Severity::Info) << "Buffer(" << &device << ", " << dec << capacity << "), this=" << this << ", fd=" << fd
266 << ", dataPtr=" << static_cast<void *>(dataPtr) << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200267}
268
Davide Grohmannfc495592022-04-25 15:27:52 +0200269Buffer::~Buffer() noexcept(false) {
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200270 try {
271 emunmap(dataPtr, dataCapacity);
272 } catch (std::exception &e) {
273 try {
274 eclose(fd);
275 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200276 throw;
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200277 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200278
Davide Grohmannfc495592022-04-25 15:27:52 +0200279 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200280
281 Log(Severity::Info) << "~Buffer(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200282}
283
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200284size_t Buffer::capacity() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200285 return dataCapacity;
286}
287
Per Åstrandafb399f2021-11-26 12:50:35 +0100288void Buffer::clear() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200289 resize(0, 0);
290}
291
Per Åstrandafb399f2021-11-26 12:50:35 +0100292char *Buffer::data() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200293 return dataPtr + offset();
294}
295
Per Åstrandafb399f2021-11-26 12:50:35 +0100296void Buffer::resize(size_t size, size_t offset) const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200297 ethosu_uapi_buffer uapi;
298 uapi.offset = offset;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200299 uapi.size = size;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200300 eioctl(fd, ETHOSU_IOCTL_BUFFER_SET, static_cast<void *>(&uapi));
301}
302
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200303size_t Buffer::offset() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200304 ethosu_uapi_buffer uapi;
305 eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast<void *>(&uapi));
306 return uapi.offset;
307}
308
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200309size_t Buffer::size() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200310 ethosu_uapi_buffer uapi;
311 eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast<void *>(&uapi));
312 return uapi.size;
313}
314
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200315int Buffer::getFd() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200316 return fd;
317}
318
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200319/****************************************************************************
320 * Network
321 ****************************************************************************/
322
Per Åstrandafb399f2021-11-26 12:50:35 +0100323Network::Network(const Device &device, shared_ptr<Buffer> &buffer) : fd(-1), buffer(buffer) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200324 // Create buffer handle
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200325 ethosu_uapi_network_create uapi;
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100326 uapi.type = ETHOSU_UAPI_NETWORK_BUFFER;
327 uapi.fd = buffer->getFd();
328 fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100329 try {
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200330 collectNetworkInfo();
331 } catch (std::exception &e) {
332 try {
333 eclose(fd);
334 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200335 throw;
Jonny Svärd2c017132021-04-12 15:56:44 +0200336 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200337
338 Log(Severity::Info) << "Network(" << &device << ", " << &*buffer << "), this=" << this << ", fd=" << fd << endl;
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100339}
Jonny Svärd2c017132021-04-12 15:56:44 +0200340
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100341Network::Network(const Device &device, const unsigned index) : fd(-1) {
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100342 // Create buffer handle
343 ethosu_uapi_network_create uapi;
344 uapi.type = ETHOSU_UAPI_NETWORK_INDEX;
345 uapi.index = index;
346 fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100347 try {
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200348 collectNetworkInfo();
349 } catch (std::exception &e) {
350 try {
351 eclose(fd);
352 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200353 throw;
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200354 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200355
356 Log(Severity::Info) << "Network(" << &device << ", " << index << "), this=" << this << ", fd=" << fd << endl;
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200357}
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100358
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200359void Network::collectNetworkInfo() {
360 ethosu_uapi_network_info info;
361 ioctl(ETHOSU_IOCTL_NETWORK_INFO, static_cast<void *>(&info));
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100362
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200363 for (uint32_t i = 0; i < info.ifm_count; i++) {
364 ifmDims.push_back(info.ifm_size[i]);
365 }
366
367 for (uint32_t i = 0; i < info.ofm_count; i++) {
368 ofmDims.push_back(info.ofm_size[i]);
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100369 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200370}
371
Davide Grohmannfc495592022-04-25 15:27:52 +0200372Network::~Network() noexcept(false) {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200373 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200374 Log(Severity::Info) << "~Network(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200375}
376
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200377int Network::ioctl(unsigned long cmd, void *data) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200378 return eioctl(fd, cmd, data);
379}
380
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200381shared_ptr<Buffer> Network::getBuffer() {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200382 return buffer;
383}
384
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200385const std::vector<size_t> &Network::getIfmDims() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200386 return ifmDims;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200387}
388
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200389size_t Network::getIfmSize() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200390 size_t size = 0;
391
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200392 for (auto s : ifmDims) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200393 size += s;
394 }
395
396 return size;
397}
398
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200399const std::vector<size_t> &Network::getOfmDims() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200400 return ofmDims;
401}
402
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200403size_t Network::getOfmSize() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200404 size_t size = 0;
405
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200406 for (auto s : ofmDims) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200407 size += s;
408 }
409
410 return size;
411}
412
413/****************************************************************************
414 * Inference
415 ****************************************************************************/
416
Davide Grohmann82d22582022-04-25 12:52:38 +0200417ostream &operator<<(ostream &out, const InferenceStatus &status) {
418 switch (status) {
419 case InferenceStatus::OK:
420 return out << "ok";
421 case InferenceStatus::ERROR:
422 return out << "error";
423 case InferenceStatus::RUNNING:
424 return out << "running";
425 case InferenceStatus::REJECTED:
426 return out << "rejected";
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100427 case InferenceStatus::ABORTED:
428 return out << "aborted";
429 case InferenceStatus::ABORTING:
430 return out << "aborting";
Davide Grohmann82d22582022-04-25 12:52:38 +0200431 }
432 throw Exception("Unknown inference status");
433}
434
Davide Grohmannfc495592022-04-25 15:27:52 +0200435Inference::~Inference() noexcept(false) {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200436 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200437 Log(Severity::Info) << "~Inference(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200438}
439
Per Åstrand2354d3e2020-10-24 20:17:10 +0200440void Inference::create(std::vector<uint32_t> &counterConfigs, bool cycleCounterEnable = false) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200441 ethosu_uapi_inference_create uapi;
442
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200443 if (ifmBuffers.size() > ETHOSU_FD_MAX) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200444 throw Exception("IFM buffer overflow");
445 }
446
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200447 if (ofmBuffers.size() > ETHOSU_FD_MAX) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200448 throw Exception("OFM buffer overflow");
449 }
450
Per Åstrand2354d3e2020-10-24 20:17:10 +0200451 if (counterConfigs.size() != ETHOSU_PMU_EVENT_MAX) {
452 throw Exception("Wrong size of counter configurations");
453 }
454
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200455 uapi.ifm_count = 0;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200456 for (auto it : ifmBuffers) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200457 uapi.ifm_fd[uapi.ifm_count++] = it->getFd();
458 }
459
460 uapi.ofm_count = 0;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200461 for (auto it : ofmBuffers) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200462 uapi.ofm_fd[uapi.ofm_count++] = it->getFd();
463 }
464
Per Åstrand2354d3e2020-10-24 20:17:10 +0200465 for (int i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) {
466 uapi.pmu_config.events[i] = counterConfigs[i];
467 }
468
469 uapi.pmu_config.cycle_count = cycleCounterEnable;
470
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200471 fd = network->ioctl(ETHOSU_IOCTL_INFERENCE_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200472
473 Log(Severity::Info) << "Inference(" << &*network << "), this=" << this << ", fd=" << fd << endl;
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200474}
475
Per Åstrand2354d3e2020-10-24 20:17:10 +0200476std::vector<uint32_t> Inference::initializeCounterConfig() {
477 return std::vector<uint32_t>(ETHOSU_PMU_EVENT_MAX, 0);
478}
479
480uint32_t Inference::getMaxPmuEventCounters() {
481 return ETHOSU_PMU_EVENT_MAX;
482}
483
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100484bool Inference::wait(int64_t timeoutNanos) const {
Davide Grohmanne446b422021-10-19 15:33:23 +0200485 struct pollfd pfd;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200486 pfd.fd = fd;
487 pfd.events = POLLIN | POLLERR;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200488 pfd.revents = 0;
489
Davide Grohmanne446b422021-10-19 15:33:23 +0200490 // if timeout negative wait forever
491 if (timeoutNanos < 0) {
Davide Grohmannf0364232022-06-16 17:42:58 +0200492 return eppoll(&pfd, 1, NULL, NULL) == 0;
Davide Grohmanne446b422021-10-19 15:33:23 +0200493 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200494
Davide Grohmanne446b422021-10-19 15:33:23 +0200495 struct timespec tmo_p;
496 int64_t nanosec = 1000000000;
497 tmo_p.tv_sec = timeoutNanos / nanosec;
498 tmo_p.tv_nsec = timeoutNanos % nanosec;
Per Åstrand2354d3e2020-10-24 20:17:10 +0200499
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100500 return eppoll(&pfd, 1, &tmo_p, NULL) == 0;
501}
502
503bool Inference::cancel() const {
504 ethosu_uapi_cancel_inference_status uapi;
505 eioctl(fd, ETHOSU_IOCTL_INFERENCE_CANCEL, static_cast<void *>(&uapi));
506 return uapi.status == ETHOSU_UAPI_STATUS_OK;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200507}
508
Davide Grohmann82d22582022-04-25 12:52:38 +0200509InferenceStatus Inference::status() const {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200510 ethosu_uapi_result_status uapi;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200511
Per Åstrand2354d3e2020-10-24 20:17:10 +0200512 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
513
Davide Grohmann82d22582022-04-25 12:52:38 +0200514 switch (uapi.status) {
515 case ETHOSU_UAPI_STATUS_OK:
516 return InferenceStatus::OK;
517 case ETHOSU_UAPI_STATUS_ERROR:
518 return InferenceStatus::ERROR;
519 case ETHOSU_UAPI_STATUS_RUNNING:
520 return InferenceStatus::RUNNING;
521 case ETHOSU_UAPI_STATUS_REJECTED:
522 return InferenceStatus::REJECTED;
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100523 case ETHOSU_UAPI_STATUS_ABORTED:
524 return InferenceStatus::ABORTED;
525 case ETHOSU_UAPI_STATUS_ABORTING:
526 return InferenceStatus::ABORTING;
Davide Grohmann82d22582022-04-25 12:52:38 +0200527 }
528
529 throw Exception("Unknown inference status");
Per Åstrand2354d3e2020-10-24 20:17:10 +0200530}
531
Per Åstrandafb399f2021-11-26 12:50:35 +0100532const std::vector<uint32_t> Inference::getPmuCounters() const {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200533 ethosu_uapi_result_status uapi;
534 std::vector<uint32_t> counterValues = std::vector<uint32_t>(ETHOSU_PMU_EVENT_MAX, 0);
535
536 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
537
538 for (int i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) {
539 if (uapi.pmu_config.events[i]) {
540 counterValues.at(i) = uapi.pmu_count.events[i];
541 }
542 }
543
544 return counterValues;
545}
546
Per Åstrandafb399f2021-11-26 12:50:35 +0100547uint64_t Inference::getCycleCounter() const {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200548 ethosu_uapi_result_status uapi;
549
550 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
551
552 return uapi.pmu_count.cycle_count;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200553}
554
Per Åstrandafb399f2021-11-26 12:50:35 +0100555int Inference::getFd() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200556 return fd;
557}
558
Per Åstrandafb399f2021-11-26 12:50:35 +0100559const shared_ptr<Network> Inference::getNetwork() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200560 return network;
561}
562
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200563vector<shared_ptr<Buffer>> &Inference::getIfmBuffers() {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200564 return ifmBuffers;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200565}
566
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200567vector<shared_ptr<Buffer>> &Inference::getOfmBuffers() {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200568 return ofmBuffers;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200569}
570
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200571} // namespace EthosU