blob: 0166f0afab4207a8da09c1b6ec24da309be9eb71 [file] [log] [blame]
Kristofer Jonsson116a6352020-08-20 17:25:23 +02001/*
Mikael Olssondc18cea2024-02-16 11:04:46 +01002 * SPDX-FileCopyrightText: Copyright 2020-2024 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)),
Mikael Olssondc18cea2024-02-16 11:04:46 +0100272 HardwareConfiguration(
273 uapi.hw_cfg.macs_per_cc, uapi.hw_cfg.cmd_stream_version, uapi.hw_cfg.type, bool(uapi.hw_cfg.custom_dma)),
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200274 SemanticVersion(uapi.driver_major_rev, uapi.driver_minor_rev, uapi.driver_patch_rev));
275 return capabilities;
276}
277
Mikael Olssondc18cea2024-02-16 11:04:46 +0100278ostream &operator<<(ostream &out, const HardwareConfiguration::DeviceType &deviceType) {
279 switch (deviceType) {
280 case HardwareConfiguration::DeviceType::UNKNOWN:
281 return out << "unknown";
282 case HardwareConfiguration::DeviceType::SUBSYSTEM:
283 return out << "subsystem";
284 case HardwareConfiguration::DeviceType::DIRECT:
285 return out << "direct";
286 default:
287 throw Exception(string("Invalid device type: ").append(to_string(static_cast<uint32_t>(deviceType))).c_str());
288 }
289}
290
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200291/****************************************************************************
292 * Buffer
293 ****************************************************************************/
294
Mikael Olsson07545152023-10-17 13:05:38 +0200295Buffer::Buffer(const Device &device, const size_t size) : fd(-1), dataPtr(nullptr), dataSize(size) {
296 ethosu_uapi_buffer_create uapi = {static_cast<uint32_t>(dataSize)};
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200297 fd = device.ioctl(ETHOSU_IOCTL_BUFFER_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200298
Davide Grohmann2ba3c1d2021-11-08 15:08:48 +0100299 void *d;
300 try {
Mikael Olsson07545152023-10-17 13:05:38 +0200301 d = emmap(nullptr, dataSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
Davide Grohmann2ba3c1d2021-11-08 15:08:48 +0100302 } catch (std::exception &e) {
303 try {
304 eclose(fd);
305 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200306 throw;
Davide Grohmann2ba3c1d2021-11-08 15:08:48 +0100307 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200308
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200309 dataPtr = reinterpret_cast<char *>(d);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200310
Mikael Olsson07545152023-10-17 13:05:38 +0200311 Log(Severity::Info) << "Buffer(" << &device << ", " << dec << size << "), this=" << this << ", fd=" << fd
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200312 << ", dataPtr=" << static_cast<void *>(dataPtr) << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200313}
314
Davide Grohmannfc495592022-04-25 15:27:52 +0200315Buffer::~Buffer() noexcept(false) {
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200316 try {
Mikael Olsson07545152023-10-17 13:05:38 +0200317 emunmap(dataPtr, dataSize);
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200318 } catch (std::exception &e) {
319 try {
320 eclose(fd);
321 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200322 throw;
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200323 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200324
Davide Grohmannfc495592022-04-25 15:27:52 +0200325 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200326
327 Log(Severity::Info) << "~Buffer(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200328}
329
Per Åstrandafb399f2021-11-26 12:50:35 +0100330void Buffer::clear() const {
Mikael Olsson07545152023-10-17 13:05:38 +0200331 memset(dataPtr, 0, dataSize);
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200332}
333
Per Åstrandafb399f2021-11-26 12:50:35 +0100334char *Buffer::data() const {
Mikael Olsson07545152023-10-17 13:05:38 +0200335 return dataPtr;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200336}
337
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200338size_t Buffer::size() const {
Mikael Olsson07545152023-10-17 13:05:38 +0200339 return dataSize;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200340}
341
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200342int Buffer::getFd() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200343 return fd;
344}
345
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200346/****************************************************************************
347 * Network
348 ****************************************************************************/
349
Mikael Olssonc081e592023-10-30 11:10:56 +0100350Network::Network(const Device &device, const unsigned char *networkData, size_t networkSize) : fd(-1) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200351 // Create buffer handle
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200352 ethosu_uapi_network_create uapi;
Mikael Olssonc081e592023-10-30 11:10:56 +0100353 uapi.type = ETHOSU_UAPI_NETWORK_USER_BUFFER;
354 uapi.network.data_ptr = reinterpret_cast<uintptr_t>(networkData);
355 uapi.network.size = networkSize;
356 fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100357 try {
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200358 collectNetworkInfo();
359 } catch (std::exception &e) {
360 try {
361 eclose(fd);
362 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200363 throw;
Jonny Svärd2c017132021-04-12 15:56:44 +0200364 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200365
Mikael Olssonc081e592023-10-30 11:10:56 +0100366 Log(Severity::Info) << "Network(" << &device << "), this=" << this << ", fd=" << fd << endl;
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100367}
Jonny Svärd2c017132021-04-12 15:56:44 +0200368
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100369Network::Network(const Device &device, const unsigned index) : fd(-1) {
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100370 // Create buffer handle
371 ethosu_uapi_network_create uapi;
372 uapi.type = ETHOSU_UAPI_NETWORK_INDEX;
373 uapi.index = index;
374 fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100375 try {
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200376 collectNetworkInfo();
377 } catch (std::exception &e) {
378 try {
379 eclose(fd);
380 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200381 throw;
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200382 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200383
384 Log(Severity::Info) << "Network(" << &device << ", " << index << "), this=" << this << ", fd=" << fd << endl;
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200385}
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100386
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200387void Network::collectNetworkInfo() {
388 ethosu_uapi_network_info info;
389 ioctl(ETHOSU_IOCTL_NETWORK_INFO, static_cast<void *>(&info));
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100390
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200391 for (uint32_t i = 0; i < info.ifm_count; i++) {
392 ifmDims.push_back(info.ifm_size[i]);
393 }
394
395 for (uint32_t i = 0; i < info.ofm_count; i++) {
396 ofmDims.push_back(info.ofm_size[i]);
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100397 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200398}
399
Davide Grohmannfc495592022-04-25 15:27:52 +0200400Network::~Network() noexcept(false) {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200401 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200402 Log(Severity::Info) << "~Network(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200403}
404
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200405int Network::ioctl(unsigned long cmd, void *data) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200406 return eioctl(fd, cmd, data);
407}
408
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200409const std::vector<size_t> &Network::getIfmDims() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200410 return ifmDims;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200411}
412
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200413size_t Network::getIfmSize() 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 : ifmDims) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200417 size += s;
418 }
419
420 return size;
421}
422
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200423const std::vector<size_t> &Network::getOfmDims() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200424 return ofmDims;
425}
426
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200427size_t Network::getOfmSize() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200428 size_t size = 0;
429
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200430 for (auto s : ofmDims) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200431 size += s;
432 }
433
434 return size;
435}
436
437/****************************************************************************
438 * Inference
439 ****************************************************************************/
440
Davide Grohmann82d22582022-04-25 12:52:38 +0200441ostream &operator<<(ostream &out, const InferenceStatus &status) {
442 switch (status) {
443 case InferenceStatus::OK:
444 return out << "ok";
445 case InferenceStatus::ERROR:
446 return out << "error";
447 case InferenceStatus::RUNNING:
448 return out << "running";
449 case InferenceStatus::REJECTED:
450 return out << "rejected";
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100451 case InferenceStatus::ABORTED:
452 return out << "aborted";
453 case InferenceStatus::ABORTING:
454 return out << "aborting";
Davide Grohmann82d22582022-04-25 12:52:38 +0200455 }
456 throw Exception("Unknown inference status");
457}
458
Davide Grohmannfc495592022-04-25 15:27:52 +0200459Inference::~Inference() noexcept(false) {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200460 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200461 Log(Severity::Info) << "~Inference(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200462}
463
Per Åstrand2354d3e2020-10-24 20:17:10 +0200464void Inference::create(std::vector<uint32_t> &counterConfigs, bool cycleCounterEnable = false) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200465 ethosu_uapi_inference_create uapi;
466
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200467 if (ifmBuffers.size() > ETHOSU_FD_MAX) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200468 throw Exception("IFM buffer overflow");
469 }
470
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200471 if (ofmBuffers.size() > ETHOSU_FD_MAX) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200472 throw Exception("OFM buffer overflow");
473 }
474
Per Åstrand2354d3e2020-10-24 20:17:10 +0200475 if (counterConfigs.size() != ETHOSU_PMU_EVENT_MAX) {
476 throw Exception("Wrong size of counter configurations");
477 }
478
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200479 uapi.ifm_count = 0;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200480 for (auto it : ifmBuffers) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200481 uapi.ifm_fd[uapi.ifm_count++] = it->getFd();
482 }
483
484 uapi.ofm_count = 0;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200485 for (auto it : ofmBuffers) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200486 uapi.ofm_fd[uapi.ofm_count++] = it->getFd();
487 }
488
Per Åstrand2354d3e2020-10-24 20:17:10 +0200489 for (int i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) {
490 uapi.pmu_config.events[i] = counterConfigs[i];
491 }
492
493 uapi.pmu_config.cycle_count = cycleCounterEnable;
494
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200495 fd = network->ioctl(ETHOSU_IOCTL_INFERENCE_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200496
497 Log(Severity::Info) << "Inference(" << &*network << "), this=" << this << ", fd=" << fd << endl;
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200498}
499
Per Åstrand2354d3e2020-10-24 20:17:10 +0200500std::vector<uint32_t> Inference::initializeCounterConfig() {
501 return std::vector<uint32_t>(ETHOSU_PMU_EVENT_MAX, 0);
502}
503
504uint32_t Inference::getMaxPmuEventCounters() {
505 return ETHOSU_PMU_EVENT_MAX;
506}
507
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100508bool Inference::wait(int64_t timeoutNanos) const {
Davide Grohmanne446b422021-10-19 15:33:23 +0200509 struct pollfd pfd;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200510 pfd.fd = fd;
511 pfd.events = POLLIN | POLLERR;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200512 pfd.revents = 0;
513
Davide Grohmanne446b422021-10-19 15:33:23 +0200514 // if timeout negative wait forever
515 if (timeoutNanos < 0) {
Davide Grohmannf0364232022-06-16 17:42:58 +0200516 return eppoll(&pfd, 1, NULL, NULL) == 0;
Davide Grohmanne446b422021-10-19 15:33:23 +0200517 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200518
Davide Grohmanne446b422021-10-19 15:33:23 +0200519 struct timespec tmo_p;
520 int64_t nanosec = 1000000000;
521 tmo_p.tv_sec = timeoutNanos / nanosec;
522 tmo_p.tv_nsec = timeoutNanos % nanosec;
Per Åstrand2354d3e2020-10-24 20:17:10 +0200523
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100524 return eppoll(&pfd, 1, &tmo_p, NULL) == 0;
525}
526
527bool Inference::cancel() const {
528 ethosu_uapi_cancel_inference_status uapi;
529 eioctl(fd, ETHOSU_IOCTL_INFERENCE_CANCEL, static_cast<void *>(&uapi));
530 return uapi.status == ETHOSU_UAPI_STATUS_OK;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200531}
532
Davide Grohmann82d22582022-04-25 12:52:38 +0200533InferenceStatus Inference::status() const {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200534 ethosu_uapi_result_status uapi;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200535
Per Åstrand2354d3e2020-10-24 20:17:10 +0200536 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
537
Davide Grohmann82d22582022-04-25 12:52:38 +0200538 switch (uapi.status) {
539 case ETHOSU_UAPI_STATUS_OK:
540 return InferenceStatus::OK;
541 case ETHOSU_UAPI_STATUS_ERROR:
542 return InferenceStatus::ERROR;
543 case ETHOSU_UAPI_STATUS_RUNNING:
544 return InferenceStatus::RUNNING;
545 case ETHOSU_UAPI_STATUS_REJECTED:
546 return InferenceStatus::REJECTED;
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100547 case ETHOSU_UAPI_STATUS_ABORTED:
548 return InferenceStatus::ABORTED;
549 case ETHOSU_UAPI_STATUS_ABORTING:
550 return InferenceStatus::ABORTING;
Davide Grohmann82d22582022-04-25 12:52:38 +0200551 }
552
553 throw Exception("Unknown inference status");
Per Åstrand2354d3e2020-10-24 20:17:10 +0200554}
555
Mikael Olssone87446c2023-12-15 17:17:06 +0100556const std::vector<uint64_t> Inference::getPmuCounters() const {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200557 ethosu_uapi_result_status uapi;
Mikael Olssone87446c2023-12-15 17:17:06 +0100558 std::vector<uint64_t> counterValues = std::vector<uint64_t>(ETHOSU_PMU_EVENT_MAX, 0);
Per Åstrand2354d3e2020-10-24 20:17:10 +0200559
560 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
561
562 for (int i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) {
563 if (uapi.pmu_config.events[i]) {
564 counterValues.at(i) = uapi.pmu_count.events[i];
565 }
566 }
567
568 return counterValues;
569}
570
Per Åstrandafb399f2021-11-26 12:50:35 +0100571uint64_t Inference::getCycleCounter() const {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200572 ethosu_uapi_result_status uapi;
573
574 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
575
576 return uapi.pmu_count.cycle_count;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200577}
578
Per Åstrandafb399f2021-11-26 12:50:35 +0100579int Inference::getFd() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200580 return fd;
581}
582
Per Åstrandafb399f2021-11-26 12:50:35 +0100583const shared_ptr<Network> Inference::getNetwork() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200584 return network;
585}
586
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200587vector<shared_ptr<Buffer>> &Inference::getIfmBuffers() {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200588 return ifmBuffers;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200589}
590
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200591vector<shared_ptr<Buffer>> &Inference::getOfmBuffers() {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200592 return ofmBuffers;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200593}
594
Mikael Olsson308e7f12023-06-12 15:00:55 +0200595static_assert(MAX_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION >= ETHOSU_KERNEL_DRIVER_VERSION_MAJOR &&
596 MIN_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION <= ETHOSU_KERNEL_DRIVER_VERSION_MAJOR,
597 "Unsupported major kernel driver version in UAPI");
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200598} // namespace EthosU