blob: 64aee4d36afcea1b6531c36c76d1bab6cb58b15d [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>
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>
Mikael Olsson308e7f12023-06-12 15:00:55 +020028#include <utility>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020029
Kristofer Jonsson116a6352020-08-20 17:25:23 +020030#include <fcntl.h>
31#include <poll.h>
Davide Grohmanne446b422021-10-19 15:33:23 +020032#include <signal.h>
Kristofer Jonsson79689c52020-10-16 14:42:19 +020033#include <sys/ioctl.h>
34#include <sys/mman.h>
Kristofer Jonsson116a6352020-08-20 17:25:23 +020035#include <unistd.h>
36
37using namespace std;
38
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +020039namespace {
Mikael Olsson308e7f12023-06-12 15:00:55 +020040std::string driverVersionToString(const EthosU::ethosu_uapi_kernel_driver_version &version) {
41 return std::to_string(version.major) + "." + std::to_string(version.minor) + "." + std::to_string(version.patch);
42}
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +020043
44enum class Severity { Error, Warning, Info, Debug };
45
46class Log {
47public:
48 Log(const Severity _severity = Severity::Error) : severity(_severity) {}
49
50 ~Log() = default;
51
52 template <typename T>
53 const Log &operator<<(const T &d) const {
54 if (level >= severity) {
55 cout << d;
56 }
57
58 return *this;
59 }
60
61 const Log &operator<<(ostream &(*manip)(ostream &)) const {
62 if (level >= severity) {
63 manip(cout);
64 }
65
66 return *this;
67 }
68
69private:
70 static Severity getLogLevel() {
71 if (const char *e = getenv("ETHOSU_LOG_LEVEL")) {
72 const string env(e);
73
74 if (env == "Error") {
75 return Severity::Error;
76 } else if (env == "Warning") {
77 return Severity::Warning;
78 } else if (env == "Info") {
79 return Severity::Info;
80 } else if (env == "Debug") {
81 return Severity::Debug;
82 } else {
83 cerr << "Unsupported log level '" << env << "'" << endl;
84 }
85 }
86
87 return Severity::Warning;
88 }
89
90 static const Severity level;
91 const Severity severity;
92};
93
94const Severity Log::level = Log::getLogLevel();
95
96} // namespace
97
Per Åstrandec3f2b02021-06-09 10:43:38 +020098namespace EthosU {
Mikael Olssone9c3f072023-06-12 15:58:10 +020099
100const SemanticVersion getLibraryVersion() {
101 return {DRIVER_LIBRARY_VERSION_MAJOR, DRIVER_LIBRARY_VERSION_MINOR, DRIVER_LIBRARY_VERSION_PATCH};
102}
103
Per Åstrandec3f2b02021-06-09 10:43:38 +0200104__attribute__((weak)) int eioctl(int fd, unsigned long cmd, void *data = nullptr) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200105 int ret = ::ioctl(fd, cmd, data);
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200106 if (ret < 0) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200107 throw EthosU::Exception("IOCTL failed");
108 }
109
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200110 Log(Severity::Debug) << "ioctl. fd=" << fd << ", cmd=" << setw(8) << setfill('0') << hex << cmd << ", ret=" << ret
111 << endl;
112
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200113 return ret;
114}
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200115
Per Åstrandec3f2b02021-06-09 10:43:38 +0200116__attribute__((weak)) int eopen(const char *pathname, int flags) {
117 int fd = ::open(pathname, flags);
Per Åstrandec3f2b02021-06-09 10:43:38 +0200118 if (fd < 0) {
119 throw Exception("Failed to open device");
120 }
121
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200122 Log(Severity::Debug) << "open. fd=" << fd << ", path='" << pathname << "', flags=" << flags << endl;
123
Per Åstrandec3f2b02021-06-09 10:43:38 +0200124 return fd;
125}
126
Davide Grohmanne446b422021-10-19 15:33:23 +0200127__attribute__((weak)) int
128eppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmo_p, const sigset_t *sigmask) {
129 int result = ::ppoll(fds, nfds, tmo_p, sigmask);
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200130 if (result < 0) {
Davide Grohmanne446b422021-10-19 15:33:23 +0200131 throw Exception("Failed to wait for ppoll event or signal");
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200132 }
133
134 return result;
Per Åstrandec3f2b02021-06-09 10:43:38 +0200135}
136
137__attribute__((weak)) int eclose(int fd) {
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200138 Log(Severity::Debug) << "close. fd=" << fd << endl;
139
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200140 int result = ::close(fd);
141 if (result < 0) {
142 throw Exception("Failed to close file");
143 }
144
145 return result;
Per Åstrandec3f2b02021-06-09 10:43:38 +0200146}
147__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 +0200148 void *ptr = ::mmap(addr, length, prot, flags, fd, offset);
149 if (ptr == MAP_FAILED) {
150 throw Exception("Failed to mmap file");
151 }
152
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200153 Log(Severity::Debug) << "map. fd=" << fd << ", addr=" << setfill('0') << addr << ", length=" << dec << length
154 << ", ptr=" << hex << ptr << endl;
155
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200156 return ptr;
Per Åstrandec3f2b02021-06-09 10:43:38 +0200157}
158
159__attribute__((weak)) int emunmap(void *addr, size_t length) {
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200160 Log(Severity::Debug) << "unmap. addr=" << setfill('0') << addr << ", length=" << dec << length << endl;
161
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200162 int result = ::munmap(addr, length);
163 if (result < 0) {
164 throw Exception("Failed to munmap file");
165 }
166
167 return result;
Per Åstrandec3f2b02021-06-09 10:43:38 +0200168}
169
170} // namespace EthosU
171
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200172namespace EthosU {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200173
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200174/****************************************************************************
175 * Exception
176 ****************************************************************************/
177
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200178Exception::Exception(const char *msg) : msg(msg) {}
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200179
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200180Exception::~Exception() throw() {}
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200181
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200182const char *Exception::what() const throw() {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200183 return msg.c_str();
184}
185
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200186/****************************************************************************
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200187 * Semantic Version
188 ****************************************************************************/
189
190bool SemanticVersion::operator==(const SemanticVersion &other) {
191 return other.major == major && other.minor == minor && other.patch == patch;
192}
193
194bool SemanticVersion::operator<(const SemanticVersion &other) {
195 if (other.major > major)
196 return true;
197 if (other.minor > minor)
198 return true;
199 return other.patch > patch;
200}
201
202bool SemanticVersion::operator<=(const SemanticVersion &other) {
203 return *this < other || *this == other;
204}
205
206bool SemanticVersion::operator!=(const SemanticVersion &other) {
207 return !(*this == other);
208}
209
210bool SemanticVersion::operator>(const SemanticVersion &other) {
211 return !(*this <= other);
212}
213
214bool SemanticVersion::operator>=(const SemanticVersion &other) {
215 return !(*this < other);
216}
217
218ostream &operator<<(ostream &out, const SemanticVersion &v) {
219 return out << "{ major=" << unsigned(v.major) << ", minor=" << unsigned(v.minor) << ", patch=" << unsigned(v.patch)
220 << " }";
221}
222
223/****************************************************************************
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200224 * Device
225 ****************************************************************************/
Mikael Olsson308e7f12023-06-12 15:00:55 +0200226Device::Device(const char *device) : fd(eopen(device, O_RDWR | O_NONBLOCK)) {
227 ethosu_uapi_kernel_driver_version version = {};
228
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200229 Log(Severity::Info) << "Device(\"" << device << "\"). this=" << this << ", fd=" << fd << endl;
Mikael Olsson308e7f12023-06-12 15:00:55 +0200230
231 try {
232 eioctl(fd, ETHOSU_IOCTL_DRIVER_VERSION_GET, &version);
233
234 if (MAX_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION < version.major ||
235 MIN_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION > version.major) {
236 throw Exception(
237 std::string("Unsupported kernel driver version: ").append(driverVersionToString(version)).c_str());
238 }
239 } catch (std::exception &e) {
240 try {
241 eclose(fd);
242 } catch (...) { std::throw_with_nested(e); }
243 throw;
244 }
245
246 driverVersion = {version.major, version.minor, version.patch};
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200247}
248
Davide Grohmannfc495592022-04-25 15:27:52 +0200249Device::~Device() noexcept(false) {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200250 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200251 Log(Severity::Info) << "~Device(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200252}
253
Per Åstrandafb399f2021-11-26 12:50:35 +0100254int Device::ioctl(unsigned long cmd, void *data) const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200255 return eioctl(fd, cmd, data);
256}
257
Mikael Olsson308e7f12023-06-12 15:00:55 +0200258const SemanticVersion &Device::getDriverVersion() const {
259 return driverVersion;
260}
261
Per Åstrandafb399f2021-11-26 12:50:35 +0100262Capabilities Device::capabilities() const {
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200263 ethosu_uapi_device_capabilities uapi;
264 (void)eioctl(fd, ETHOSU_IOCTL_CAPABILITIES_REQ, static_cast<void *>(&uapi));
265
266 Capabilities capabilities(
267 HardwareId(uapi.hw_id.version_status,
268 SemanticVersion(uapi.hw_id.version_major, uapi.hw_id.version_minor),
269 SemanticVersion(uapi.hw_id.product_major),
270 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 +0200271 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 +0200272 SemanticVersion(uapi.driver_major_rev, uapi.driver_minor_rev, uapi.driver_patch_rev));
273 return capabilities;
274}
275
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200276/****************************************************************************
277 * Buffer
278 ****************************************************************************/
279
Per Åstrandafb399f2021-11-26 12:50:35 +0100280Buffer::Buffer(const Device &device, const size_t capacity) : fd(-1), dataPtr(nullptr), dataCapacity(capacity) {
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200281 ethosu_uapi_buffer_create uapi = {static_cast<uint32_t>(dataCapacity)};
282 fd = device.ioctl(ETHOSU_IOCTL_BUFFER_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200283
Davide Grohmann2ba3c1d2021-11-08 15:08:48 +0100284 void *d;
285 try {
286 d = emmap(nullptr, dataCapacity, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
287 } catch (std::exception &e) {
288 try {
289 eclose(fd);
290 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200291 throw;
Davide Grohmann2ba3c1d2021-11-08 15:08:48 +0100292 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200293
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200294 dataPtr = reinterpret_cast<char *>(d);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200295
296 Log(Severity::Info) << "Buffer(" << &device << ", " << dec << capacity << "), this=" << this << ", fd=" << fd
297 << ", dataPtr=" << static_cast<void *>(dataPtr) << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200298}
299
Davide Grohmannfc495592022-04-25 15:27:52 +0200300Buffer::~Buffer() noexcept(false) {
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200301 try {
302 emunmap(dataPtr, dataCapacity);
303 } catch (std::exception &e) {
304 try {
305 eclose(fd);
306 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200307 throw;
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200308 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200309
Davide Grohmannfc495592022-04-25 15:27:52 +0200310 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200311
312 Log(Severity::Info) << "~Buffer(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200313}
314
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200315size_t Buffer::capacity() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200316 return dataCapacity;
317}
318
Per Åstrandafb399f2021-11-26 12:50:35 +0100319void Buffer::clear() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200320 resize(0, 0);
321}
322
Per Åstrandafb399f2021-11-26 12:50:35 +0100323char *Buffer::data() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200324 return dataPtr + offset();
325}
326
Per Åstrandafb399f2021-11-26 12:50:35 +0100327void Buffer::resize(size_t size, size_t offset) const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200328 ethosu_uapi_buffer uapi;
329 uapi.offset = offset;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200330 uapi.size = size;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200331 eioctl(fd, ETHOSU_IOCTL_BUFFER_SET, static_cast<void *>(&uapi));
332}
333
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200334size_t Buffer::offset() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200335 ethosu_uapi_buffer uapi;
336 eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast<void *>(&uapi));
337 return uapi.offset;
338}
339
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200340size_t Buffer::size() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200341 ethosu_uapi_buffer uapi;
342 eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast<void *>(&uapi));
343 return uapi.size;
344}
345
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200346int Buffer::getFd() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200347 return fd;
348}
349
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200350/****************************************************************************
351 * Network
352 ****************************************************************************/
353
Per Åstrandafb399f2021-11-26 12:50:35 +0100354Network::Network(const Device &device, shared_ptr<Buffer> &buffer) : fd(-1), buffer(buffer) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200355 // Create buffer handle
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200356 ethosu_uapi_network_create uapi;
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100357 uapi.type = ETHOSU_UAPI_NETWORK_BUFFER;
358 uapi.fd = buffer->getFd();
359 fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100360 try {
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200361 collectNetworkInfo();
362 } catch (std::exception &e) {
363 try {
364 eclose(fd);
365 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200366 throw;
Jonny Svärd2c017132021-04-12 15:56:44 +0200367 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200368
369 Log(Severity::Info) << "Network(" << &device << ", " << &*buffer << "), this=" << this << ", fd=" << fd << endl;
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100370}
Jonny Svärd2c017132021-04-12 15:56:44 +0200371
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100372Network::Network(const Device &device, const unsigned index) : fd(-1) {
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100373 // Create buffer handle
374 ethosu_uapi_network_create uapi;
375 uapi.type = ETHOSU_UAPI_NETWORK_INDEX;
376 uapi.index = index;
377 fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100378 try {
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200379 collectNetworkInfo();
380 } catch (std::exception &e) {
381 try {
382 eclose(fd);
383 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200384 throw;
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200385 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200386
387 Log(Severity::Info) << "Network(" << &device << ", " << index << "), this=" << this << ", fd=" << fd << endl;
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200388}
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100389
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200390void Network::collectNetworkInfo() {
391 ethosu_uapi_network_info info;
392 ioctl(ETHOSU_IOCTL_NETWORK_INFO, static_cast<void *>(&info));
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100393
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200394 for (uint32_t i = 0; i < info.ifm_count; i++) {
395 ifmDims.push_back(info.ifm_size[i]);
396 }
397
398 for (uint32_t i = 0; i < info.ofm_count; i++) {
399 ofmDims.push_back(info.ofm_size[i]);
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100400 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200401}
402
Davide Grohmannfc495592022-04-25 15:27:52 +0200403Network::~Network() noexcept(false) {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200404 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200405 Log(Severity::Info) << "~Network(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200406}
407
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200408int Network::ioctl(unsigned long cmd, void *data) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200409 return eioctl(fd, cmd, data);
410}
411
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200412shared_ptr<Buffer> Network::getBuffer() {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200413 return buffer;
414}
415
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200416const std::vector<size_t> &Network::getIfmDims() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200417 return ifmDims;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200418}
419
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200420size_t Network::getIfmSize() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200421 size_t size = 0;
422
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200423 for (auto s : ifmDims) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200424 size += s;
425 }
426
427 return size;
428}
429
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200430const std::vector<size_t> &Network::getOfmDims() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200431 return ofmDims;
432}
433
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200434size_t Network::getOfmSize() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200435 size_t size = 0;
436
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200437 for (auto s : ofmDims) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200438 size += s;
439 }
440
441 return size;
442}
443
444/****************************************************************************
445 * Inference
446 ****************************************************************************/
447
Davide Grohmann82d22582022-04-25 12:52:38 +0200448ostream &operator<<(ostream &out, const InferenceStatus &status) {
449 switch (status) {
450 case InferenceStatus::OK:
451 return out << "ok";
452 case InferenceStatus::ERROR:
453 return out << "error";
454 case InferenceStatus::RUNNING:
455 return out << "running";
456 case InferenceStatus::REJECTED:
457 return out << "rejected";
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100458 case InferenceStatus::ABORTED:
459 return out << "aborted";
460 case InferenceStatus::ABORTING:
461 return out << "aborting";
Davide Grohmann82d22582022-04-25 12:52:38 +0200462 }
463 throw Exception("Unknown inference status");
464}
465
Davide Grohmannfc495592022-04-25 15:27:52 +0200466Inference::~Inference() noexcept(false) {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200467 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200468 Log(Severity::Info) << "~Inference(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200469}
470
Per Åstrand2354d3e2020-10-24 20:17:10 +0200471void Inference::create(std::vector<uint32_t> &counterConfigs, bool cycleCounterEnable = false) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200472 ethosu_uapi_inference_create uapi;
473
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200474 if (ifmBuffers.size() > ETHOSU_FD_MAX) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200475 throw Exception("IFM buffer overflow");
476 }
477
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200478 if (ofmBuffers.size() > ETHOSU_FD_MAX) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200479 throw Exception("OFM buffer overflow");
480 }
481
Per Åstrand2354d3e2020-10-24 20:17:10 +0200482 if (counterConfigs.size() != ETHOSU_PMU_EVENT_MAX) {
483 throw Exception("Wrong size of counter configurations");
484 }
485
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200486 uapi.ifm_count = 0;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200487 for (auto it : ifmBuffers) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200488 uapi.ifm_fd[uapi.ifm_count++] = it->getFd();
489 }
490
491 uapi.ofm_count = 0;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200492 for (auto it : ofmBuffers) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200493 uapi.ofm_fd[uapi.ofm_count++] = it->getFd();
494 }
495
Per Åstrand2354d3e2020-10-24 20:17:10 +0200496 for (int i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) {
497 uapi.pmu_config.events[i] = counterConfigs[i];
498 }
499
500 uapi.pmu_config.cycle_count = cycleCounterEnable;
501
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200502 fd = network->ioctl(ETHOSU_IOCTL_INFERENCE_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200503
504 Log(Severity::Info) << "Inference(" << &*network << "), this=" << this << ", fd=" << fd << endl;
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200505}
506
Per Åstrand2354d3e2020-10-24 20:17:10 +0200507std::vector<uint32_t> Inference::initializeCounterConfig() {
508 return std::vector<uint32_t>(ETHOSU_PMU_EVENT_MAX, 0);
509}
510
511uint32_t Inference::getMaxPmuEventCounters() {
512 return ETHOSU_PMU_EVENT_MAX;
513}
514
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100515bool Inference::wait(int64_t timeoutNanos) const {
Davide Grohmanne446b422021-10-19 15:33:23 +0200516 struct pollfd pfd;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200517 pfd.fd = fd;
518 pfd.events = POLLIN | POLLERR;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200519 pfd.revents = 0;
520
Davide Grohmanne446b422021-10-19 15:33:23 +0200521 // if timeout negative wait forever
522 if (timeoutNanos < 0) {
Davide Grohmannf0364232022-06-16 17:42:58 +0200523 return eppoll(&pfd, 1, NULL, NULL) == 0;
Davide Grohmanne446b422021-10-19 15:33:23 +0200524 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200525
Davide Grohmanne446b422021-10-19 15:33:23 +0200526 struct timespec tmo_p;
527 int64_t nanosec = 1000000000;
528 tmo_p.tv_sec = timeoutNanos / nanosec;
529 tmo_p.tv_nsec = timeoutNanos % nanosec;
Per Åstrand2354d3e2020-10-24 20:17:10 +0200530
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100531 return eppoll(&pfd, 1, &tmo_p, NULL) == 0;
532}
533
534bool Inference::cancel() const {
535 ethosu_uapi_cancel_inference_status uapi;
536 eioctl(fd, ETHOSU_IOCTL_INFERENCE_CANCEL, static_cast<void *>(&uapi));
537 return uapi.status == ETHOSU_UAPI_STATUS_OK;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200538}
539
Davide Grohmann82d22582022-04-25 12:52:38 +0200540InferenceStatus Inference::status() const {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200541 ethosu_uapi_result_status uapi;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200542
Per Åstrand2354d3e2020-10-24 20:17:10 +0200543 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
544
Davide Grohmann82d22582022-04-25 12:52:38 +0200545 switch (uapi.status) {
546 case ETHOSU_UAPI_STATUS_OK:
547 return InferenceStatus::OK;
548 case ETHOSU_UAPI_STATUS_ERROR:
549 return InferenceStatus::ERROR;
550 case ETHOSU_UAPI_STATUS_RUNNING:
551 return InferenceStatus::RUNNING;
552 case ETHOSU_UAPI_STATUS_REJECTED:
553 return InferenceStatus::REJECTED;
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100554 case ETHOSU_UAPI_STATUS_ABORTED:
555 return InferenceStatus::ABORTED;
556 case ETHOSU_UAPI_STATUS_ABORTING:
557 return InferenceStatus::ABORTING;
Davide Grohmann82d22582022-04-25 12:52:38 +0200558 }
559
560 throw Exception("Unknown inference status");
Per Åstrand2354d3e2020-10-24 20:17:10 +0200561}
562
Per Åstrandafb399f2021-11-26 12:50:35 +0100563const std::vector<uint32_t> Inference::getPmuCounters() const {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200564 ethosu_uapi_result_status uapi;
565 std::vector<uint32_t> counterValues = std::vector<uint32_t>(ETHOSU_PMU_EVENT_MAX, 0);
566
567 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
568
569 for (int i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) {
570 if (uapi.pmu_config.events[i]) {
571 counterValues.at(i) = uapi.pmu_count.events[i];
572 }
573 }
574
575 return counterValues;
576}
577
Per Åstrandafb399f2021-11-26 12:50:35 +0100578uint64_t Inference::getCycleCounter() const {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200579 ethosu_uapi_result_status uapi;
580
581 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
582
583 return uapi.pmu_count.cycle_count;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200584}
585
Per Åstrandafb399f2021-11-26 12:50:35 +0100586int Inference::getFd() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200587 return fd;
588}
589
Per Åstrandafb399f2021-11-26 12:50:35 +0100590const shared_ptr<Network> Inference::getNetwork() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200591 return network;
592}
593
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200594vector<shared_ptr<Buffer>> &Inference::getIfmBuffers() {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200595 return ifmBuffers;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200596}
597
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200598vector<shared_ptr<Buffer>> &Inference::getOfmBuffers() {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200599 return ofmBuffers;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200600}
601
Mikael Olsson308e7f12023-06-12 15:00:55 +0200602static_assert(MAX_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION >= ETHOSU_KERNEL_DRIVER_VERSION_MAJOR &&
603 MIN_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION <= ETHOSU_KERNEL_DRIVER_VERSION_MAJOR,
604 "Unsupported major kernel driver version in UAPI");
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200605} // namespace EthosU