blob: dcdde8c6848d73e0b560ae02cc48b7dc416d43b9 [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 *
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>
Mikael Olsson99429e12023-08-16 15:22:19 +020023#include <cerrno>
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +020024#include <cstdlib>
Mikael Olsson99429e12023-08-16 15:22:19 +020025#include <cstring>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020026#include <exception>
Kristofer Jonsson35de9e62022-03-08 13:25:45 +010027#include <fstream>
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +020028#include <iomanip>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020029#include <iostream>
Mikael Olsson308e7f12023-06-12 15:00:55 +020030#include <utility>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020031
Kristofer Jonsson116a6352020-08-20 17:25:23 +020032#include <fcntl.h>
33#include <poll.h>
Davide Grohmanne446b422021-10-19 15:33:23 +020034#include <signal.h>
Kristofer Jonsson79689c52020-10-16 14:42:19 +020035#include <sys/ioctl.h>
36#include <sys/mman.h>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020037#include <unistd.h>
38
39using namespace std;
40
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +020041namespace {
Mikael Olsson308e7f12023-06-12 15:00:55 +020042std::string driverVersionToString(const EthosU::ethosu_uapi_kernel_driver_version &version) {
43 return std::to_string(version.major) + "." + std::to_string(version.minor) + "." + std::to_string(version.patch);
44}
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +020045
46enum class Severity { Error, Warning, Info, Debug };
47
48class Log {
49public:
50 Log(const Severity _severity = Severity::Error) : severity(_severity) {}
51
52 ~Log() = default;
53
54 template <typename T>
55 const Log &operator<<(const T &d) const {
56 if (level >= severity) {
57 cout << d;
58 }
59
60 return *this;
61 }
62
63 const Log &operator<<(ostream &(*manip)(ostream &)) const {
64 if (level >= severity) {
65 manip(cout);
66 }
67
68 return *this;
69 }
70
71private:
72 static Severity getLogLevel() {
73 if (const char *e = getenv("ETHOSU_LOG_LEVEL")) {
74 const string env(e);
75
76 if (env == "Error") {
77 return Severity::Error;
78 } else if (env == "Warning") {
79 return Severity::Warning;
80 } else if (env == "Info") {
81 return Severity::Info;
82 } else if (env == "Debug") {
83 return Severity::Debug;
84 } else {
85 cerr << "Unsupported log level '" << env << "'" << endl;
86 }
87 }
88
89 return Severity::Warning;
90 }
91
92 static const Severity level;
93 const Severity severity;
94};
95
96const Severity Log::level = Log::getLogLevel();
97
98} // namespace
99
Per Åstrandec3f2b02021-06-09 10:43:38 +0200100namespace EthosU {
Mikael Olssone9c3f072023-06-12 15:58:10 +0200101
102const SemanticVersion getLibraryVersion() {
103 return {DRIVER_LIBRARY_VERSION_MAJOR, DRIVER_LIBRARY_VERSION_MINOR, DRIVER_LIBRARY_VERSION_PATCH};
104}
105
Per Åstrandec3f2b02021-06-09 10:43:38 +0200106__attribute__((weak)) int eioctl(int fd, unsigned long cmd, void *data = nullptr) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200107 int ret = ::ioctl(fd, cmd, data);
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200108 if (ret < 0) {
Mikael Olsson99429e12023-08-16 15:22:19 +0200109 throw EthosU::Exception(string("IOCTL cmd=").append(to_string(cmd) + " failed: " + strerror(errno)).c_str());
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200110 }
111
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200112 Log(Severity::Debug) << "ioctl. fd=" << fd << ", cmd=" << setw(8) << setfill('0') << hex << cmd << ", ret=" << ret
113 << endl;
114
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200115 return ret;
116}
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200117
Per Åstrandec3f2b02021-06-09 10:43:38 +0200118__attribute__((weak)) int eopen(const char *pathname, int flags) {
119 int fd = ::open(pathname, flags);
Per Åstrandec3f2b02021-06-09 10:43:38 +0200120 if (fd < 0) {
121 throw Exception("Failed to open device");
122 }
123
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200124 Log(Severity::Debug) << "open. fd=" << fd << ", path='" << pathname << "', flags=" << flags << endl;
125
Per Åstrandec3f2b02021-06-09 10:43:38 +0200126 return fd;
127}
128
Davide Grohmanne446b422021-10-19 15:33:23 +0200129__attribute__((weak)) int
130eppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmo_p, const sigset_t *sigmask) {
131 int result = ::ppoll(fds, nfds, tmo_p, sigmask);
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200132 if (result < 0) {
Davide Grohmanne446b422021-10-19 15:33:23 +0200133 throw Exception("Failed to wait for ppoll event or signal");
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200134 }
135
136 return result;
Per Åstrandec3f2b02021-06-09 10:43:38 +0200137}
138
139__attribute__((weak)) int eclose(int fd) {
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200140 Log(Severity::Debug) << "close. fd=" << fd << endl;
141
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200142 int result = ::close(fd);
143 if (result < 0) {
144 throw Exception("Failed to close file");
145 }
146
147 return result;
Per Åstrandec3f2b02021-06-09 10:43:38 +0200148}
149__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 +0200150 void *ptr = ::mmap(addr, length, prot, flags, fd, offset);
151 if (ptr == MAP_FAILED) {
152 throw Exception("Failed to mmap file");
153 }
154
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200155 Log(Severity::Debug) << "map. fd=" << fd << ", addr=" << setfill('0') << addr << ", length=" << dec << length
156 << ", ptr=" << hex << ptr << endl;
157
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200158 return ptr;
Per Åstrandec3f2b02021-06-09 10:43:38 +0200159}
160
161__attribute__((weak)) int emunmap(void *addr, size_t length) {
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200162 Log(Severity::Debug) << "unmap. addr=" << setfill('0') << addr << ", length=" << dec << length << endl;
163
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200164 int result = ::munmap(addr, length);
165 if (result < 0) {
166 throw Exception("Failed to munmap file");
167 }
168
169 return result;
Per Åstrandec3f2b02021-06-09 10:43:38 +0200170}
171
172} // namespace EthosU
173
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200174namespace EthosU {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200175
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200176/****************************************************************************
177 * Exception
178 ****************************************************************************/
179
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200180Exception::Exception(const char *msg) : msg(msg) {}
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200181
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200182Exception::~Exception() throw() {}
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200183
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200184const char *Exception::what() const throw() {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200185 return msg.c_str();
186}
187
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200188/****************************************************************************
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200189 * Semantic Version
190 ****************************************************************************/
191
192bool SemanticVersion::operator==(const SemanticVersion &other) {
193 return other.major == major && other.minor == minor && other.patch == patch;
194}
195
196bool SemanticVersion::operator<(const SemanticVersion &other) {
197 if (other.major > major)
198 return true;
199 if (other.minor > minor)
200 return true;
201 return other.patch > patch;
202}
203
204bool SemanticVersion::operator<=(const SemanticVersion &other) {
205 return *this < other || *this == other;
206}
207
208bool SemanticVersion::operator!=(const SemanticVersion &other) {
209 return !(*this == other);
210}
211
212bool SemanticVersion::operator>(const SemanticVersion &other) {
213 return !(*this <= other);
214}
215
216bool SemanticVersion::operator>=(const SemanticVersion &other) {
217 return !(*this < other);
218}
219
220ostream &operator<<(ostream &out, const SemanticVersion &v) {
221 return out << "{ major=" << unsigned(v.major) << ", minor=" << unsigned(v.minor) << ", patch=" << unsigned(v.patch)
222 << " }";
223}
224
225/****************************************************************************
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200226 * Device
227 ****************************************************************************/
Mikael Olsson308e7f12023-06-12 15:00:55 +0200228Device::Device(const char *device) : fd(eopen(device, O_RDWR | O_NONBLOCK)) {
229 ethosu_uapi_kernel_driver_version version = {};
230
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200231 Log(Severity::Info) << "Device(\"" << device << "\"). this=" << this << ", fd=" << fd << endl;
Mikael Olsson308e7f12023-06-12 15:00:55 +0200232
233 try {
234 eioctl(fd, ETHOSU_IOCTL_DRIVER_VERSION_GET, &version);
235
236 if (MAX_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION < version.major ||
237 MIN_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION > version.major) {
238 throw Exception(
239 std::string("Unsupported kernel driver version: ").append(driverVersionToString(version)).c_str());
240 }
241 } catch (std::exception &e) {
242 try {
243 eclose(fd);
244 } catch (...) { std::throw_with_nested(e); }
245 throw;
246 }
247
248 driverVersion = {version.major, version.minor, version.patch};
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200249}
250
Davide Grohmannfc495592022-04-25 15:27:52 +0200251Device::~Device() noexcept(false) {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200252 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200253 Log(Severity::Info) << "~Device(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200254}
255
Per Åstrandafb399f2021-11-26 12:50:35 +0100256int Device::ioctl(unsigned long cmd, void *data) const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200257 return eioctl(fd, cmd, data);
258}
259
Mikael Olsson308e7f12023-06-12 15:00:55 +0200260const SemanticVersion &Device::getDriverVersion() const {
261 return driverVersion;
262}
263
Per Åstrandafb399f2021-11-26 12:50:35 +0100264Capabilities Device::capabilities() const {
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200265 ethosu_uapi_device_capabilities uapi;
266 (void)eioctl(fd, ETHOSU_IOCTL_CAPABILITIES_REQ, static_cast<void *>(&uapi));
267
268 Capabilities capabilities(
269 HardwareId(uapi.hw_id.version_status,
270 SemanticVersion(uapi.hw_id.version_major, uapi.hw_id.version_minor),
271 SemanticVersion(uapi.hw_id.product_major),
272 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 +0200273 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 +0200274 SemanticVersion(uapi.driver_major_rev, uapi.driver_minor_rev, uapi.driver_patch_rev));
275 return capabilities;
276}
277
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200278/****************************************************************************
279 * Buffer
280 ****************************************************************************/
281
Per Åstrandafb399f2021-11-26 12:50:35 +0100282Buffer::Buffer(const Device &device, const size_t capacity) : fd(-1), dataPtr(nullptr), dataCapacity(capacity) {
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200283 ethosu_uapi_buffer_create uapi = {static_cast<uint32_t>(dataCapacity)};
284 fd = device.ioctl(ETHOSU_IOCTL_BUFFER_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200285
Davide Grohmann2ba3c1d2021-11-08 15:08:48 +0100286 void *d;
287 try {
288 d = emmap(nullptr, dataCapacity, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
289 } catch (std::exception &e) {
290 try {
291 eclose(fd);
292 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200293 throw;
Davide Grohmann2ba3c1d2021-11-08 15:08:48 +0100294 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200295
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200296 dataPtr = reinterpret_cast<char *>(d);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200297
298 Log(Severity::Info) << "Buffer(" << &device << ", " << dec << capacity << "), this=" << this << ", fd=" << fd
299 << ", dataPtr=" << static_cast<void *>(dataPtr) << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200300}
301
Davide Grohmannfc495592022-04-25 15:27:52 +0200302Buffer::~Buffer() noexcept(false) {
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200303 try {
304 emunmap(dataPtr, dataCapacity);
305 } catch (std::exception &e) {
306 try {
307 eclose(fd);
308 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200309 throw;
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200310 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200311
Davide Grohmannfc495592022-04-25 15:27:52 +0200312 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200313
314 Log(Severity::Info) << "~Buffer(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200315}
316
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200317size_t Buffer::capacity() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200318 return dataCapacity;
319}
320
Per Åstrandafb399f2021-11-26 12:50:35 +0100321void Buffer::clear() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200322 resize(0, 0);
323}
324
Per Åstrandafb399f2021-11-26 12:50:35 +0100325char *Buffer::data() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200326 return dataPtr + offset();
327}
328
Per Åstrandafb399f2021-11-26 12:50:35 +0100329void Buffer::resize(size_t size, size_t offset) const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200330 ethosu_uapi_buffer uapi;
331 uapi.offset = offset;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200332 uapi.size = size;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200333 eioctl(fd, ETHOSU_IOCTL_BUFFER_SET, static_cast<void *>(&uapi));
334}
335
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200336size_t Buffer::offset() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200337 ethosu_uapi_buffer uapi;
338 eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast<void *>(&uapi));
339 return uapi.offset;
340}
341
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200342size_t Buffer::size() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200343 ethosu_uapi_buffer uapi;
344 eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast<void *>(&uapi));
345 return uapi.size;
346}
347
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200348int Buffer::getFd() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200349 return fd;
350}
351
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200352/****************************************************************************
353 * Network
354 ****************************************************************************/
355
Per Åstrandafb399f2021-11-26 12:50:35 +0100356Network::Network(const Device &device, shared_ptr<Buffer> &buffer) : fd(-1), buffer(buffer) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200357 // Create buffer handle
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200358 ethosu_uapi_network_create uapi;
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100359 uapi.type = ETHOSU_UAPI_NETWORK_BUFFER;
360 uapi.fd = buffer->getFd();
361 fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100362 try {
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200363 collectNetworkInfo();
364 } catch (std::exception &e) {
365 try {
366 eclose(fd);
367 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200368 throw;
Jonny Svärd2c017132021-04-12 15:56:44 +0200369 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200370
371 Log(Severity::Info) << "Network(" << &device << ", " << &*buffer << "), this=" << this << ", fd=" << fd << endl;
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100372}
Jonny Svärd2c017132021-04-12 15:56:44 +0200373
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100374Network::Network(const Device &device, const unsigned index) : fd(-1) {
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100375 // Create buffer handle
376 ethosu_uapi_network_create uapi;
377 uapi.type = ETHOSU_UAPI_NETWORK_INDEX;
378 uapi.index = index;
379 fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100380 try {
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200381 collectNetworkInfo();
382 } catch (std::exception &e) {
383 try {
384 eclose(fd);
385 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200386 throw;
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200387 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200388
389 Log(Severity::Info) << "Network(" << &device << ", " << index << "), this=" << this << ", fd=" << fd << endl;
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200390}
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100391
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200392void Network::collectNetworkInfo() {
393 ethosu_uapi_network_info info;
394 ioctl(ETHOSU_IOCTL_NETWORK_INFO, static_cast<void *>(&info));
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100395
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200396 for (uint32_t i = 0; i < info.ifm_count; i++) {
397 ifmDims.push_back(info.ifm_size[i]);
398 }
399
400 for (uint32_t i = 0; i < info.ofm_count; i++) {
401 ofmDims.push_back(info.ofm_size[i]);
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100402 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200403}
404
Davide Grohmannfc495592022-04-25 15:27:52 +0200405Network::~Network() noexcept(false) {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200406 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200407 Log(Severity::Info) << "~Network(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200408}
409
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200410int Network::ioctl(unsigned long cmd, void *data) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200411 return eioctl(fd, cmd, data);
412}
413
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200414shared_ptr<Buffer> Network::getBuffer() {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200415 return buffer;
416}
417
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200418const std::vector<size_t> &Network::getIfmDims() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200419 return ifmDims;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200420}
421
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200422size_t Network::getIfmSize() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200423 size_t size = 0;
424
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200425 for (auto s : ifmDims) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200426 size += s;
427 }
428
429 return size;
430}
431
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200432const std::vector<size_t> &Network::getOfmDims() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200433 return ofmDims;
434}
435
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200436size_t Network::getOfmSize() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200437 size_t size = 0;
438
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200439 for (auto s : ofmDims) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200440 size += s;
441 }
442
443 return size;
444}
445
446/****************************************************************************
447 * Inference
448 ****************************************************************************/
449
Davide Grohmann82d22582022-04-25 12:52:38 +0200450ostream &operator<<(ostream &out, const InferenceStatus &status) {
451 switch (status) {
452 case InferenceStatus::OK:
453 return out << "ok";
454 case InferenceStatus::ERROR:
455 return out << "error";
456 case InferenceStatus::RUNNING:
457 return out << "running";
458 case InferenceStatus::REJECTED:
459 return out << "rejected";
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100460 case InferenceStatus::ABORTED:
461 return out << "aborted";
462 case InferenceStatus::ABORTING:
463 return out << "aborting";
Davide Grohmann82d22582022-04-25 12:52:38 +0200464 }
465 throw Exception("Unknown inference status");
466}
467
Davide Grohmannfc495592022-04-25 15:27:52 +0200468Inference::~Inference() noexcept(false) {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200469 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200470 Log(Severity::Info) << "~Inference(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200471}
472
Per Åstrand2354d3e2020-10-24 20:17:10 +0200473void Inference::create(std::vector<uint32_t> &counterConfigs, bool cycleCounterEnable = false) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200474 ethosu_uapi_inference_create uapi;
475
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200476 if (ifmBuffers.size() > ETHOSU_FD_MAX) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200477 throw Exception("IFM buffer overflow");
478 }
479
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200480 if (ofmBuffers.size() > ETHOSU_FD_MAX) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200481 throw Exception("OFM buffer overflow");
482 }
483
Per Åstrand2354d3e2020-10-24 20:17:10 +0200484 if (counterConfigs.size() != ETHOSU_PMU_EVENT_MAX) {
485 throw Exception("Wrong size of counter configurations");
486 }
487
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200488 uapi.ifm_count = 0;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200489 for (auto it : ifmBuffers) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200490 uapi.ifm_fd[uapi.ifm_count++] = it->getFd();
491 }
492
493 uapi.ofm_count = 0;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200494 for (auto it : ofmBuffers) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200495 uapi.ofm_fd[uapi.ofm_count++] = it->getFd();
496 }
497
Per Åstrand2354d3e2020-10-24 20:17:10 +0200498 for (int i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) {
499 uapi.pmu_config.events[i] = counterConfigs[i];
500 }
501
502 uapi.pmu_config.cycle_count = cycleCounterEnable;
503
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200504 fd = network->ioctl(ETHOSU_IOCTL_INFERENCE_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200505
506 Log(Severity::Info) << "Inference(" << &*network << "), this=" << this << ", fd=" << fd << endl;
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200507}
508
Per Åstrand2354d3e2020-10-24 20:17:10 +0200509std::vector<uint32_t> Inference::initializeCounterConfig() {
510 return std::vector<uint32_t>(ETHOSU_PMU_EVENT_MAX, 0);
511}
512
513uint32_t Inference::getMaxPmuEventCounters() {
514 return ETHOSU_PMU_EVENT_MAX;
515}
516
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100517bool Inference::wait(int64_t timeoutNanos) const {
Davide Grohmanne446b422021-10-19 15:33:23 +0200518 struct pollfd pfd;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200519 pfd.fd = fd;
520 pfd.events = POLLIN | POLLERR;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200521 pfd.revents = 0;
522
Davide Grohmanne446b422021-10-19 15:33:23 +0200523 // if timeout negative wait forever
524 if (timeoutNanos < 0) {
Davide Grohmannf0364232022-06-16 17:42:58 +0200525 return eppoll(&pfd, 1, NULL, NULL) == 0;
Davide Grohmanne446b422021-10-19 15:33:23 +0200526 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200527
Davide Grohmanne446b422021-10-19 15:33:23 +0200528 struct timespec tmo_p;
529 int64_t nanosec = 1000000000;
530 tmo_p.tv_sec = timeoutNanos / nanosec;
531 tmo_p.tv_nsec = timeoutNanos % nanosec;
Per Åstrand2354d3e2020-10-24 20:17:10 +0200532
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100533 return eppoll(&pfd, 1, &tmo_p, NULL) == 0;
534}
535
536bool Inference::cancel() const {
537 ethosu_uapi_cancel_inference_status uapi;
538 eioctl(fd, ETHOSU_IOCTL_INFERENCE_CANCEL, static_cast<void *>(&uapi));
539 return uapi.status == ETHOSU_UAPI_STATUS_OK;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200540}
541
Davide Grohmann82d22582022-04-25 12:52:38 +0200542InferenceStatus Inference::status() const {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200543 ethosu_uapi_result_status uapi;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200544
Per Åstrand2354d3e2020-10-24 20:17:10 +0200545 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
546
Davide Grohmann82d22582022-04-25 12:52:38 +0200547 switch (uapi.status) {
548 case ETHOSU_UAPI_STATUS_OK:
549 return InferenceStatus::OK;
550 case ETHOSU_UAPI_STATUS_ERROR:
551 return InferenceStatus::ERROR;
552 case ETHOSU_UAPI_STATUS_RUNNING:
553 return InferenceStatus::RUNNING;
554 case ETHOSU_UAPI_STATUS_REJECTED:
555 return InferenceStatus::REJECTED;
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100556 case ETHOSU_UAPI_STATUS_ABORTED:
557 return InferenceStatus::ABORTED;
558 case ETHOSU_UAPI_STATUS_ABORTING:
559 return InferenceStatus::ABORTING;
Davide Grohmann82d22582022-04-25 12:52:38 +0200560 }
561
562 throw Exception("Unknown inference status");
Per Åstrand2354d3e2020-10-24 20:17:10 +0200563}
564
Per Åstrandafb399f2021-11-26 12:50:35 +0100565const std::vector<uint32_t> Inference::getPmuCounters() const {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200566 ethosu_uapi_result_status uapi;
567 std::vector<uint32_t> counterValues = std::vector<uint32_t>(ETHOSU_PMU_EVENT_MAX, 0);
568
569 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
570
571 for (int i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) {
572 if (uapi.pmu_config.events[i]) {
573 counterValues.at(i) = uapi.pmu_count.events[i];
574 }
575 }
576
577 return counterValues;
578}
579
Per Åstrandafb399f2021-11-26 12:50:35 +0100580uint64_t Inference::getCycleCounter() const {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200581 ethosu_uapi_result_status uapi;
582
583 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
584
585 return uapi.pmu_count.cycle_count;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200586}
587
Per Åstrandafb399f2021-11-26 12:50:35 +0100588int Inference::getFd() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200589 return fd;
590}
591
Per Åstrandafb399f2021-11-26 12:50:35 +0100592const shared_ptr<Network> Inference::getNetwork() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200593 return network;
594}
595
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200596vector<shared_ptr<Buffer>> &Inference::getIfmBuffers() {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200597 return ifmBuffers;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200598}
599
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200600vector<shared_ptr<Buffer>> &Inference::getOfmBuffers() {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200601 return ofmBuffers;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200602}
603
Mikael Olsson308e7f12023-06-12 15:00:55 +0200604static_assert(MAX_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION >= ETHOSU_KERNEL_DRIVER_VERSION_MAJOR &&
605 MIN_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION <= ETHOSU_KERNEL_DRIVER_VERSION_MAJOR,
606 "Unsupported major kernel driver version in UAPI");
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200607} // namespace EthosU