blob: a4feef18b5cd53272e1b00ee97711b09cfa8bc86 [file] [log] [blame]
Kristofer Jonsson116a6352020-08-20 17:25:23 +02001/*
Mikael Olsson308e7f12023-06-12 15:00:55 +02002 * SPDX-FileCopyrightText: Copyright 2020-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
Kristofer Jonsson116a6352020-08-20 17:25:23 +02003 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the License); you may
6 * not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include <ethosu.hpp>
19#include <uapi/ethosu.h>
20
21#include <algorithm>
Mikael Olsson99429e12023-08-16 15:22:19 +020022#include <cerrno>
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +020023#include <cstdlib>
Mikael Olsson99429e12023-08-16 15:22:19 +020024#include <cstring>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020025#include <exception>
Kristofer Jonsson35de9e62022-03-08 13:25:45 +010026#include <fstream>
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +020027#include <iomanip>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020028#include <iostream>
Mikael Olsson308e7f12023-06-12 15:00:55 +020029#include <utility>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020030
Kristofer Jonsson116a6352020-08-20 17:25:23 +020031#include <fcntl.h>
32#include <poll.h>
Davide Grohmanne446b422021-10-19 15:33:23 +020033#include <signal.h>
Kristofer Jonsson79689c52020-10-16 14:42:19 +020034#include <sys/ioctl.h>
35#include <sys/mman.h>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020036#include <unistd.h>
37
38using namespace std;
39
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +020040namespace {
Mikael Olsson308e7f12023-06-12 15:00:55 +020041std::string driverVersionToString(const EthosU::ethosu_uapi_kernel_driver_version &version) {
42 return std::to_string(version.major) + "." + std::to_string(version.minor) + "." + std::to_string(version.patch);
43}
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +020044
45enum class Severity { Error, Warning, Info, Debug };
46
47class Log {
48public:
49 Log(const Severity _severity = Severity::Error) : severity(_severity) {}
50
51 ~Log() = default;
52
53 template <typename T>
54 const Log &operator<<(const T &d) const {
55 if (level >= severity) {
56 cout << d;
57 }
58
59 return *this;
60 }
61
62 const Log &operator<<(ostream &(*manip)(ostream &)) const {
63 if (level >= severity) {
64 manip(cout);
65 }
66
67 return *this;
68 }
69
70private:
71 static Severity getLogLevel() {
72 if (const char *e = getenv("ETHOSU_LOG_LEVEL")) {
73 const string env(e);
74
75 if (env == "Error") {
76 return Severity::Error;
77 } else if (env == "Warning") {
78 return Severity::Warning;
79 } else if (env == "Info") {
80 return Severity::Info;
81 } else if (env == "Debug") {
82 return Severity::Debug;
83 } else {
84 cerr << "Unsupported log level '" << env << "'" << endl;
85 }
86 }
87
88 return Severity::Warning;
89 }
90
91 static const Severity level;
92 const Severity severity;
93};
94
95const Severity Log::level = Log::getLogLevel();
96
97} // namespace
98
Per Åstrandec3f2b02021-06-09 10:43:38 +020099namespace EthosU {
Mikael Olssone9c3f072023-06-12 15:58:10 +0200100
101const SemanticVersion getLibraryVersion() {
102 return {DRIVER_LIBRARY_VERSION_MAJOR, DRIVER_LIBRARY_VERSION_MINOR, DRIVER_LIBRARY_VERSION_PATCH};
103}
104
Per Åstrandec3f2b02021-06-09 10:43:38 +0200105__attribute__((weak)) int eioctl(int fd, unsigned long cmd, void *data = nullptr) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200106 int ret = ::ioctl(fd, cmd, data);
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200107 if (ret < 0) {
Mikael Olsson99429e12023-08-16 15:22:19 +0200108 throw EthosU::Exception(string("IOCTL cmd=").append(to_string(cmd) + " failed: " + strerror(errno)).c_str());
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200109 }
110
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200111 Log(Severity::Debug) << "ioctl. fd=" << fd << ", cmd=" << setw(8) << setfill('0') << hex << cmd << ", ret=" << ret
112 << endl;
113
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200114 return ret;
115}
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200116
Per Åstrandec3f2b02021-06-09 10:43:38 +0200117__attribute__((weak)) int eopen(const char *pathname, int flags) {
118 int fd = ::open(pathname, flags);
Per Åstrandec3f2b02021-06-09 10:43:38 +0200119 if (fd < 0) {
120 throw Exception("Failed to open device");
121 }
122
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200123 Log(Severity::Debug) << "open. fd=" << fd << ", path='" << pathname << "', flags=" << flags << endl;
124
Per Åstrandec3f2b02021-06-09 10:43:38 +0200125 return fd;
126}
127
Davide Grohmanne446b422021-10-19 15:33:23 +0200128__attribute__((weak)) int
129eppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmo_p, const sigset_t *sigmask) {
130 int result = ::ppoll(fds, nfds, tmo_p, sigmask);
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200131 if (result < 0) {
Davide Grohmanne446b422021-10-19 15:33:23 +0200132 throw Exception("Failed to wait for ppoll event or signal");
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200133 }
134
135 return result;
Per Åstrandec3f2b02021-06-09 10:43:38 +0200136}
137
138__attribute__((weak)) int eclose(int fd) {
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200139 Log(Severity::Debug) << "close. fd=" << fd << endl;
140
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200141 int result = ::close(fd);
142 if (result < 0) {
143 throw Exception("Failed to close file");
144 }
145
146 return result;
Per Åstrandec3f2b02021-06-09 10:43:38 +0200147}
148__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 +0200149 void *ptr = ::mmap(addr, length, prot, flags, fd, offset);
150 if (ptr == MAP_FAILED) {
151 throw Exception("Failed to mmap file");
152 }
153
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200154 Log(Severity::Debug) << "map. fd=" << fd << ", addr=" << setfill('0') << addr << ", length=" << dec << length
155 << ", ptr=" << hex << ptr << endl;
156
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200157 return ptr;
Per Åstrandec3f2b02021-06-09 10:43:38 +0200158}
159
160__attribute__((weak)) int emunmap(void *addr, size_t length) {
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200161 Log(Severity::Debug) << "unmap. addr=" << setfill('0') << addr << ", length=" << dec << length << endl;
162
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200163 int result = ::munmap(addr, length);
164 if (result < 0) {
165 throw Exception("Failed to munmap file");
166 }
167
168 return result;
Per Åstrandec3f2b02021-06-09 10:43:38 +0200169}
170
171} // namespace EthosU
172
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200173namespace EthosU {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200174
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200175/****************************************************************************
176 * Exception
177 ****************************************************************************/
178
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200179Exception::Exception(const char *msg) : msg(msg) {}
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200180
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200181Exception::~Exception() throw() {}
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200182
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200183const char *Exception::what() const throw() {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200184 return msg.c_str();
185}
186
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200187/****************************************************************************
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200188 * Semantic Version
189 ****************************************************************************/
190
191bool SemanticVersion::operator==(const SemanticVersion &other) {
192 return other.major == major && other.minor == minor && other.patch == patch;
193}
194
195bool SemanticVersion::operator<(const SemanticVersion &other) {
196 if (other.major > major)
197 return true;
198 if (other.minor > minor)
199 return true;
200 return other.patch > patch;
201}
202
203bool SemanticVersion::operator<=(const SemanticVersion &other) {
204 return *this < other || *this == other;
205}
206
207bool SemanticVersion::operator!=(const SemanticVersion &other) {
208 return !(*this == other);
209}
210
211bool SemanticVersion::operator>(const SemanticVersion &other) {
212 return !(*this <= other);
213}
214
215bool SemanticVersion::operator>=(const SemanticVersion &other) {
216 return !(*this < other);
217}
218
219ostream &operator<<(ostream &out, const SemanticVersion &v) {
220 return out << "{ major=" << unsigned(v.major) << ", minor=" << unsigned(v.minor) << ", patch=" << unsigned(v.patch)
221 << " }";
222}
223
224/****************************************************************************
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200225 * Device
226 ****************************************************************************/
Mikael Olsson308e7f12023-06-12 15:00:55 +0200227Device::Device(const char *device) : fd(eopen(device, O_RDWR | O_NONBLOCK)) {
228 ethosu_uapi_kernel_driver_version version = {};
229
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200230 Log(Severity::Info) << "Device(\"" << device << "\"). this=" << this << ", fd=" << fd << endl;
Mikael Olsson308e7f12023-06-12 15:00:55 +0200231
232 try {
233 eioctl(fd, ETHOSU_IOCTL_DRIVER_VERSION_GET, &version);
234
235 if (MAX_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION < version.major ||
236 MIN_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION > version.major) {
237 throw Exception(
238 std::string("Unsupported kernel driver version: ").append(driverVersionToString(version)).c_str());
239 }
240 } catch (std::exception &e) {
241 try {
242 eclose(fd);
243 } catch (...) { std::throw_with_nested(e); }
244 throw;
245 }
246
247 driverVersion = {version.major, version.minor, version.patch};
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200248}
249
Davide Grohmannfc495592022-04-25 15:27:52 +0200250Device::~Device() noexcept(false) {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200251 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200252 Log(Severity::Info) << "~Device(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200253}
254
Per Åstrandafb399f2021-11-26 12:50:35 +0100255int Device::ioctl(unsigned long cmd, void *data) const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200256 return eioctl(fd, cmd, data);
257}
258
Mikael Olsson308e7f12023-06-12 15:00:55 +0200259const SemanticVersion &Device::getDriverVersion() const {
260 return driverVersion;
261}
262
Per Åstrandafb399f2021-11-26 12:50:35 +0100263Capabilities Device::capabilities() const {
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200264 ethosu_uapi_device_capabilities uapi;
265 (void)eioctl(fd, ETHOSU_IOCTL_CAPABILITIES_REQ, static_cast<void *>(&uapi));
266
267 Capabilities capabilities(
268 HardwareId(uapi.hw_id.version_status,
269 SemanticVersion(uapi.hw_id.version_major, uapi.hw_id.version_minor),
270 SemanticVersion(uapi.hw_id.product_major),
271 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 +0200272 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 +0200273 SemanticVersion(uapi.driver_major_rev, uapi.driver_minor_rev, uapi.driver_patch_rev));
274 return capabilities;
275}
276
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200277/****************************************************************************
278 * Buffer
279 ****************************************************************************/
280
Mikael Olsson07545152023-10-17 13:05:38 +0200281Buffer::Buffer(const Device &device, const size_t size) : fd(-1), dataPtr(nullptr), dataSize(size) {
282 ethosu_uapi_buffer_create uapi = {static_cast<uint32_t>(dataSize)};
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200283 fd = device.ioctl(ETHOSU_IOCTL_BUFFER_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200284
Davide Grohmann2ba3c1d2021-11-08 15:08:48 +0100285 void *d;
286 try {
Mikael Olsson07545152023-10-17 13:05:38 +0200287 d = emmap(nullptr, dataSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
Davide Grohmann2ba3c1d2021-11-08 15:08:48 +0100288 } catch (std::exception &e) {
289 try {
290 eclose(fd);
291 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200292 throw;
Davide Grohmann2ba3c1d2021-11-08 15:08:48 +0100293 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200294
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200295 dataPtr = reinterpret_cast<char *>(d);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200296
Mikael Olsson07545152023-10-17 13:05:38 +0200297 Log(Severity::Info) << "Buffer(" << &device << ", " << dec << size << "), this=" << this << ", fd=" << fd
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200298 << ", dataPtr=" << static_cast<void *>(dataPtr) << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200299}
300
Davide Grohmannfc495592022-04-25 15:27:52 +0200301Buffer::~Buffer() noexcept(false) {
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200302 try {
Mikael Olsson07545152023-10-17 13:05:38 +0200303 emunmap(dataPtr, dataSize);
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200304 } catch (std::exception &e) {
305 try {
306 eclose(fd);
307 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200308 throw;
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200309 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200310
Davide Grohmannfc495592022-04-25 15:27:52 +0200311 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200312
313 Log(Severity::Info) << "~Buffer(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200314}
315
Per Åstrandafb399f2021-11-26 12:50:35 +0100316void Buffer::clear() const {
Mikael Olsson07545152023-10-17 13:05:38 +0200317 memset(dataPtr, 0, dataSize);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200318}
319
Per Åstrandafb399f2021-11-26 12:50:35 +0100320char *Buffer::data() const {
Mikael Olsson07545152023-10-17 13:05:38 +0200321 return dataPtr;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200322}
323
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200324size_t Buffer::size() const {
Mikael Olsson07545152023-10-17 13:05:38 +0200325 return dataSize;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200326}
327
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200328int Buffer::getFd() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200329 return fd;
330}
331
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200332/****************************************************************************
333 * Network
334 ****************************************************************************/
335
Mikael Olssonc081e592023-10-30 11:10:56 +0100336Network::Network(const Device &device, const unsigned char *networkData, size_t networkSize) : fd(-1) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200337 // Create buffer handle
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200338 ethosu_uapi_network_create uapi;
Mikael Olssonc081e592023-10-30 11:10:56 +0100339 uapi.type = ETHOSU_UAPI_NETWORK_USER_BUFFER;
340 uapi.network.data_ptr = reinterpret_cast<uintptr_t>(networkData);
341 uapi.network.size = networkSize;
342 fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100343 try {
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200344 collectNetworkInfo();
345 } catch (std::exception &e) {
346 try {
347 eclose(fd);
348 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200349 throw;
Jonny Svärd2c017132021-04-12 15:56:44 +0200350 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200351
Mikael Olssonc081e592023-10-30 11:10:56 +0100352 Log(Severity::Info) << "Network(" << &device << "), this=" << this << ", fd=" << fd << endl;
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100353}
Jonny Svärd2c017132021-04-12 15:56:44 +0200354
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100355Network::Network(const Device &device, const unsigned index) : fd(-1) {
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100356 // Create buffer handle
357 ethosu_uapi_network_create uapi;
358 uapi.type = ETHOSU_UAPI_NETWORK_INDEX;
359 uapi.index = index;
360 fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100361 try {
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200362 collectNetworkInfo();
363 } catch (std::exception &e) {
364 try {
365 eclose(fd);
366 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200367 throw;
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200368 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200369
370 Log(Severity::Info) << "Network(" << &device << ", " << index << "), this=" << this << ", fd=" << fd << endl;
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200371}
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100372
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200373void Network::collectNetworkInfo() {
374 ethosu_uapi_network_info info;
375 ioctl(ETHOSU_IOCTL_NETWORK_INFO, static_cast<void *>(&info));
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100376
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200377 for (uint32_t i = 0; i < info.ifm_count; i++) {
378 ifmDims.push_back(info.ifm_size[i]);
379 }
380
381 for (uint32_t i = 0; i < info.ofm_count; i++) {
382 ofmDims.push_back(info.ofm_size[i]);
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100383 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200384}
385
Davide Grohmannfc495592022-04-25 15:27:52 +0200386Network::~Network() noexcept(false) {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200387 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200388 Log(Severity::Info) << "~Network(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200389}
390
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200391int Network::ioctl(unsigned long cmd, void *data) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200392 return eioctl(fd, cmd, data);
393}
394
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200395const std::vector<size_t> &Network::getIfmDims() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200396 return ifmDims;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200397}
398
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200399size_t Network::getIfmSize() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200400 size_t size = 0;
401
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200402 for (auto s : ifmDims) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200403 size += s;
404 }
405
406 return size;
407}
408
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200409const std::vector<size_t> &Network::getOfmDims() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200410 return ofmDims;
411}
412
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200413size_t Network::getOfmSize() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200414 size_t size = 0;
415
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200416 for (auto s : ofmDims) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200417 size += s;
418 }
419
420 return size;
421}
422
423/****************************************************************************
424 * Inference
425 ****************************************************************************/
426
Davide Grohmann82d22582022-04-25 12:52:38 +0200427ostream &operator<<(ostream &out, const InferenceStatus &status) {
428 switch (status) {
429 case InferenceStatus::OK:
430 return out << "ok";
431 case InferenceStatus::ERROR:
432 return out << "error";
433 case InferenceStatus::RUNNING:
434 return out << "running";
435 case InferenceStatus::REJECTED:
436 return out << "rejected";
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100437 case InferenceStatus::ABORTED:
438 return out << "aborted";
439 case InferenceStatus::ABORTING:
440 return out << "aborting";
Davide Grohmann82d22582022-04-25 12:52:38 +0200441 }
442 throw Exception("Unknown inference status");
443}
444
Davide Grohmannfc495592022-04-25 15:27:52 +0200445Inference::~Inference() noexcept(false) {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200446 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200447 Log(Severity::Info) << "~Inference(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200448}
449
Per Åstrand2354d3e2020-10-24 20:17:10 +0200450void Inference::create(std::vector<uint32_t> &counterConfigs, bool cycleCounterEnable = false) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200451 ethosu_uapi_inference_create uapi;
452
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200453 if (ifmBuffers.size() > ETHOSU_FD_MAX) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200454 throw Exception("IFM buffer overflow");
455 }
456
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200457 if (ofmBuffers.size() > ETHOSU_FD_MAX) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200458 throw Exception("OFM buffer overflow");
459 }
460
Per Åstrand2354d3e2020-10-24 20:17:10 +0200461 if (counterConfigs.size() != ETHOSU_PMU_EVENT_MAX) {
462 throw Exception("Wrong size of counter configurations");
463 }
464
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200465 uapi.ifm_count = 0;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200466 for (auto it : ifmBuffers) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200467 uapi.ifm_fd[uapi.ifm_count++] = it->getFd();
468 }
469
470 uapi.ofm_count = 0;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200471 for (auto it : ofmBuffers) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200472 uapi.ofm_fd[uapi.ofm_count++] = it->getFd();
473 }
474
Per Åstrand2354d3e2020-10-24 20:17:10 +0200475 for (int i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) {
476 uapi.pmu_config.events[i] = counterConfigs[i];
477 }
478
479 uapi.pmu_config.cycle_count = cycleCounterEnable;
480
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200481 fd = network->ioctl(ETHOSU_IOCTL_INFERENCE_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200482
483 Log(Severity::Info) << "Inference(" << &*network << "), this=" << this << ", fd=" << fd << endl;
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200484}
485
Per Åstrand2354d3e2020-10-24 20:17:10 +0200486std::vector<uint32_t> Inference::initializeCounterConfig() {
487 return std::vector<uint32_t>(ETHOSU_PMU_EVENT_MAX, 0);
488}
489
490uint32_t Inference::getMaxPmuEventCounters() {
491 return ETHOSU_PMU_EVENT_MAX;
492}
493
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100494bool Inference::wait(int64_t timeoutNanos) const {
Davide Grohmanne446b422021-10-19 15:33:23 +0200495 struct pollfd pfd;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200496 pfd.fd = fd;
497 pfd.events = POLLIN | POLLERR;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200498 pfd.revents = 0;
499
Davide Grohmanne446b422021-10-19 15:33:23 +0200500 // if timeout negative wait forever
501 if (timeoutNanos < 0) {
Davide Grohmannf0364232022-06-16 17:42:58 +0200502 return eppoll(&pfd, 1, NULL, NULL) == 0;
Davide Grohmanne446b422021-10-19 15:33:23 +0200503 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200504
Davide Grohmanne446b422021-10-19 15:33:23 +0200505 struct timespec tmo_p;
506 int64_t nanosec = 1000000000;
507 tmo_p.tv_sec = timeoutNanos / nanosec;
508 tmo_p.tv_nsec = timeoutNanos % nanosec;
Per Åstrand2354d3e2020-10-24 20:17:10 +0200509
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100510 return eppoll(&pfd, 1, &tmo_p, NULL) == 0;
511}
512
513bool Inference::cancel() const {
514 ethosu_uapi_cancel_inference_status uapi;
515 eioctl(fd, ETHOSU_IOCTL_INFERENCE_CANCEL, static_cast<void *>(&uapi));
516 return uapi.status == ETHOSU_UAPI_STATUS_OK;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200517}
518
Davide Grohmann82d22582022-04-25 12:52:38 +0200519InferenceStatus Inference::status() const {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200520 ethosu_uapi_result_status uapi;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200521
Per Åstrand2354d3e2020-10-24 20:17:10 +0200522 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
523
Davide Grohmann82d22582022-04-25 12:52:38 +0200524 switch (uapi.status) {
525 case ETHOSU_UAPI_STATUS_OK:
526 return InferenceStatus::OK;
527 case ETHOSU_UAPI_STATUS_ERROR:
528 return InferenceStatus::ERROR;
529 case ETHOSU_UAPI_STATUS_RUNNING:
530 return InferenceStatus::RUNNING;
531 case ETHOSU_UAPI_STATUS_REJECTED:
532 return InferenceStatus::REJECTED;
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100533 case ETHOSU_UAPI_STATUS_ABORTED:
534 return InferenceStatus::ABORTED;
535 case ETHOSU_UAPI_STATUS_ABORTING:
536 return InferenceStatus::ABORTING;
Davide Grohmann82d22582022-04-25 12:52:38 +0200537 }
538
539 throw Exception("Unknown inference status");
Per Åstrand2354d3e2020-10-24 20:17:10 +0200540}
541
Mikael Olssone87446c2023-12-15 17:17:06 +0100542const std::vector<uint64_t> Inference::getPmuCounters() const {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200543 ethosu_uapi_result_status uapi;
Mikael Olssone87446c2023-12-15 17:17:06 +0100544 std::vector<uint64_t> counterValues = std::vector<uint64_t>(ETHOSU_PMU_EVENT_MAX, 0);
Per Åstrand2354d3e2020-10-24 20:17:10 +0200545
546 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
547
548 for (int i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) {
549 if (uapi.pmu_config.events[i]) {
550 counterValues.at(i) = uapi.pmu_count.events[i];
551 }
552 }
553
554 return counterValues;
555}
556
Per Åstrandafb399f2021-11-26 12:50:35 +0100557uint64_t Inference::getCycleCounter() const {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200558 ethosu_uapi_result_status uapi;
559
560 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
561
562 return uapi.pmu_count.cycle_count;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200563}
564
Per Åstrandafb399f2021-11-26 12:50:35 +0100565int Inference::getFd() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200566 return fd;
567}
568
Per Åstrandafb399f2021-11-26 12:50:35 +0100569const shared_ptr<Network> Inference::getNetwork() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200570 return network;
571}
572
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200573vector<shared_ptr<Buffer>> &Inference::getIfmBuffers() {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200574 return ifmBuffers;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200575}
576
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200577vector<shared_ptr<Buffer>> &Inference::getOfmBuffers() {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200578 return ofmBuffers;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200579}
580
Mikael Olsson308e7f12023-06-12 15:00:55 +0200581static_assert(MAX_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION >= ETHOSU_KERNEL_DRIVER_VERSION_MAJOR &&
582 MIN_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION <= ETHOSU_KERNEL_DRIVER_VERSION_MAJOR,
583 "Unsupported major kernel driver version in UAPI");
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200584} // namespace EthosU