blob: 1758b074257ea13db6895e708d8eb9907b9005fb [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 {
99__attribute__((weak)) int eioctl(int fd, unsigned long cmd, void *data = nullptr) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200100 int ret = ::ioctl(fd, cmd, data);
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200101 if (ret < 0) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200102 throw EthosU::Exception("IOCTL failed");
103 }
104
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200105 Log(Severity::Debug) << "ioctl. fd=" << fd << ", cmd=" << setw(8) << setfill('0') << hex << cmd << ", ret=" << ret
106 << endl;
107
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200108 return ret;
109}
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200110
Per Åstrandec3f2b02021-06-09 10:43:38 +0200111__attribute__((weak)) int eopen(const char *pathname, int flags) {
112 int fd = ::open(pathname, flags);
Per Åstrandec3f2b02021-06-09 10:43:38 +0200113 if (fd < 0) {
114 throw Exception("Failed to open device");
115 }
116
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200117 Log(Severity::Debug) << "open. fd=" << fd << ", path='" << pathname << "', flags=" << flags << endl;
118
Per Åstrandec3f2b02021-06-09 10:43:38 +0200119 return fd;
120}
121
Davide Grohmanne446b422021-10-19 15:33:23 +0200122__attribute__((weak)) int
123eppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmo_p, const sigset_t *sigmask) {
124 int result = ::ppoll(fds, nfds, tmo_p, sigmask);
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200125 if (result < 0) {
Davide Grohmanne446b422021-10-19 15:33:23 +0200126 throw Exception("Failed to wait for ppoll event or signal");
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200127 }
128
129 return result;
Per Åstrandec3f2b02021-06-09 10:43:38 +0200130}
131
132__attribute__((weak)) int eclose(int fd) {
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200133 Log(Severity::Debug) << "close. fd=" << fd << endl;
134
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200135 int result = ::close(fd);
136 if (result < 0) {
137 throw Exception("Failed to close file");
138 }
139
140 return result;
Per Åstrandec3f2b02021-06-09 10:43:38 +0200141}
142__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 +0200143 void *ptr = ::mmap(addr, length, prot, flags, fd, offset);
144 if (ptr == MAP_FAILED) {
145 throw Exception("Failed to mmap file");
146 }
147
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200148 Log(Severity::Debug) << "map. fd=" << fd << ", addr=" << setfill('0') << addr << ", length=" << dec << length
149 << ", ptr=" << hex << ptr << endl;
150
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200151 return ptr;
Per Åstrandec3f2b02021-06-09 10:43:38 +0200152}
153
154__attribute__((weak)) int emunmap(void *addr, size_t length) {
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200155 Log(Severity::Debug) << "unmap. addr=" << setfill('0') << addr << ", length=" << dec << length << endl;
156
Davide Grohmannc90bfab2021-10-19 13:59:27 +0200157 int result = ::munmap(addr, length);
158 if (result < 0) {
159 throw Exception("Failed to munmap file");
160 }
161
162 return result;
Per Åstrandec3f2b02021-06-09 10:43:38 +0200163}
164
165} // namespace EthosU
166
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200167namespace EthosU {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200168
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200169/****************************************************************************
170 * Exception
171 ****************************************************************************/
172
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200173Exception::Exception(const char *msg) : msg(msg) {}
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200174
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200175Exception::~Exception() throw() {}
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200176
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200177const char *Exception::what() const throw() {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200178 return msg.c_str();
179}
180
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200181/****************************************************************************
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200182 * Semantic Version
183 ****************************************************************************/
184
185bool SemanticVersion::operator==(const SemanticVersion &other) {
186 return other.major == major && other.minor == minor && other.patch == patch;
187}
188
189bool SemanticVersion::operator<(const SemanticVersion &other) {
190 if (other.major > major)
191 return true;
192 if (other.minor > minor)
193 return true;
194 return other.patch > patch;
195}
196
197bool SemanticVersion::operator<=(const SemanticVersion &other) {
198 return *this < other || *this == other;
199}
200
201bool SemanticVersion::operator!=(const SemanticVersion &other) {
202 return !(*this == other);
203}
204
205bool SemanticVersion::operator>(const SemanticVersion &other) {
206 return !(*this <= other);
207}
208
209bool SemanticVersion::operator>=(const SemanticVersion &other) {
210 return !(*this < other);
211}
212
213ostream &operator<<(ostream &out, const SemanticVersion &v) {
214 return out << "{ major=" << unsigned(v.major) << ", minor=" << unsigned(v.minor) << ", patch=" << unsigned(v.patch)
215 << " }";
216}
217
218/****************************************************************************
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200219 * Device
220 ****************************************************************************/
Mikael Olsson308e7f12023-06-12 15:00:55 +0200221Device::Device(const char *device) : fd(eopen(device, O_RDWR | O_NONBLOCK)) {
222 ethosu_uapi_kernel_driver_version version = {};
223
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200224 Log(Severity::Info) << "Device(\"" << device << "\"). this=" << this << ", fd=" << fd << endl;
Mikael Olsson308e7f12023-06-12 15:00:55 +0200225
226 try {
227 eioctl(fd, ETHOSU_IOCTL_DRIVER_VERSION_GET, &version);
228
229 if (MAX_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION < version.major ||
230 MIN_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION > version.major) {
231 throw Exception(
232 std::string("Unsupported kernel driver version: ").append(driverVersionToString(version)).c_str());
233 }
234 } catch (std::exception &e) {
235 try {
236 eclose(fd);
237 } catch (...) { std::throw_with_nested(e); }
238 throw;
239 }
240
241 driverVersion = {version.major, version.minor, version.patch};
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200242}
243
Davide Grohmannfc495592022-04-25 15:27:52 +0200244Device::~Device() noexcept(false) {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200245 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200246 Log(Severity::Info) << "~Device(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200247}
248
Per Åstrandafb399f2021-11-26 12:50:35 +0100249int Device::ioctl(unsigned long cmd, void *data) const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200250 return eioctl(fd, cmd, data);
251}
252
Mikael Olsson308e7f12023-06-12 15:00:55 +0200253const SemanticVersion &Device::getDriverVersion() const {
254 return driverVersion;
255}
256
Per Åstrandafb399f2021-11-26 12:50:35 +0100257Capabilities Device::capabilities() const {
Davide Grohmann35ce6c82021-06-01 15:03:51 +0200258 ethosu_uapi_device_capabilities uapi;
259 (void)eioctl(fd, ETHOSU_IOCTL_CAPABILITIES_REQ, static_cast<void *>(&uapi));
260
261 Capabilities capabilities(
262 HardwareId(uapi.hw_id.version_status,
263 SemanticVersion(uapi.hw_id.version_major, uapi.hw_id.version_minor),
264 SemanticVersion(uapi.hw_id.product_major),
265 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 +0200266 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 +0200267 SemanticVersion(uapi.driver_major_rev, uapi.driver_minor_rev, uapi.driver_patch_rev));
268 return capabilities;
269}
270
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200271/****************************************************************************
272 * Buffer
273 ****************************************************************************/
274
Per Åstrandafb399f2021-11-26 12:50:35 +0100275Buffer::Buffer(const Device &device, const size_t capacity) : fd(-1), dataPtr(nullptr), dataCapacity(capacity) {
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200276 ethosu_uapi_buffer_create uapi = {static_cast<uint32_t>(dataCapacity)};
277 fd = device.ioctl(ETHOSU_IOCTL_BUFFER_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200278
Davide Grohmann2ba3c1d2021-11-08 15:08:48 +0100279 void *d;
280 try {
281 d = emmap(nullptr, dataCapacity, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
282 } catch (std::exception &e) {
283 try {
284 eclose(fd);
285 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200286 throw;
Davide Grohmann2ba3c1d2021-11-08 15:08:48 +0100287 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200288
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200289 dataPtr = reinterpret_cast<char *>(d);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200290
291 Log(Severity::Info) << "Buffer(" << &device << ", " << dec << capacity << "), this=" << this << ", fd=" << fd
292 << ", dataPtr=" << static_cast<void *>(dataPtr) << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200293}
294
Davide Grohmannfc495592022-04-25 15:27:52 +0200295Buffer::~Buffer() noexcept(false) {
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200296 try {
297 emunmap(dataPtr, dataCapacity);
298 } catch (std::exception &e) {
299 try {
300 eclose(fd);
301 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200302 throw;
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200303 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200304
Davide Grohmannfc495592022-04-25 15:27:52 +0200305 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200306
307 Log(Severity::Info) << "~Buffer(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200308}
309
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200310size_t Buffer::capacity() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200311 return dataCapacity;
312}
313
Per Åstrandafb399f2021-11-26 12:50:35 +0100314void Buffer::clear() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200315 resize(0, 0);
316}
317
Per Åstrandafb399f2021-11-26 12:50:35 +0100318char *Buffer::data() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200319 return dataPtr + offset();
320}
321
Per Åstrandafb399f2021-11-26 12:50:35 +0100322void Buffer::resize(size_t size, size_t offset) const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200323 ethosu_uapi_buffer uapi;
324 uapi.offset = offset;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200325 uapi.size = size;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200326 eioctl(fd, ETHOSU_IOCTL_BUFFER_SET, static_cast<void *>(&uapi));
327}
328
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200329size_t Buffer::offset() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200330 ethosu_uapi_buffer uapi;
331 eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast<void *>(&uapi));
332 return uapi.offset;
333}
334
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200335size_t Buffer::size() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200336 ethosu_uapi_buffer uapi;
337 eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast<void *>(&uapi));
338 return uapi.size;
339}
340
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200341int Buffer::getFd() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200342 return fd;
343}
344
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200345/****************************************************************************
346 * Network
347 ****************************************************************************/
348
Per Åstrandafb399f2021-11-26 12:50:35 +0100349Network::Network(const Device &device, shared_ptr<Buffer> &buffer) : fd(-1), buffer(buffer) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200350 // Create buffer handle
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200351 ethosu_uapi_network_create uapi;
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100352 uapi.type = ETHOSU_UAPI_NETWORK_BUFFER;
353 uapi.fd = buffer->getFd();
354 fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100355 try {
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200356 collectNetworkInfo();
357 } catch (std::exception &e) {
358 try {
359 eclose(fd);
360 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200361 throw;
Jonny Svärd2c017132021-04-12 15:56:44 +0200362 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200363
364 Log(Severity::Info) << "Network(" << &device << ", " << &*buffer << "), this=" << this << ", fd=" << fd << endl;
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100365}
Jonny Svärd2c017132021-04-12 15:56:44 +0200366
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100367Network::Network(const Device &device, const unsigned index) : fd(-1) {
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100368 // Create buffer handle
369 ethosu_uapi_network_create uapi;
370 uapi.type = ETHOSU_UAPI_NETWORK_INDEX;
371 uapi.index = index;
372 fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100373 try {
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200374 collectNetworkInfo();
375 } catch (std::exception &e) {
376 try {
377 eclose(fd);
378 } catch (...) { std::throw_with_nested(e); }
Davide Grohmannfc495592022-04-25 15:27:52 +0200379 throw;
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200380 }
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200381
382 Log(Severity::Info) << "Network(" << &device << ", " << index << "), this=" << this << ", fd=" << fd << endl;
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200383}
Kristofer Jonsson3c6a2602022-03-10 11:17:29 +0100384
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200385void Network::collectNetworkInfo() {
386 ethosu_uapi_network_info info;
387 ioctl(ETHOSU_IOCTL_NETWORK_INFO, static_cast<void *>(&info));
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100388
Davide Grohmann80f8ddf2022-04-07 14:50:50 +0200389 for (uint32_t i = 0; i < info.ifm_count; i++) {
390 ifmDims.push_back(info.ifm_size[i]);
391 }
392
393 for (uint32_t i = 0; i < info.ofm_count; i++) {
394 ofmDims.push_back(info.ofm_size[i]);
Kristofer Jonsson35de9e62022-03-08 13:25:45 +0100395 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200396}
397
Davide Grohmannfc495592022-04-25 15:27:52 +0200398Network::~Network() noexcept(false) {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200399 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200400 Log(Severity::Info) << "~Network(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200401}
402
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200403int Network::ioctl(unsigned long cmd, void *data) {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200404 return eioctl(fd, cmd, data);
405}
406
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200407shared_ptr<Buffer> Network::getBuffer() {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200408 return buffer;
409}
410
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200411const std::vector<size_t> &Network::getIfmDims() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200412 return ifmDims;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200413}
414
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200415size_t Network::getIfmSize() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200416 size_t size = 0;
417
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200418 for (auto s : ifmDims) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200419 size += s;
420 }
421
422 return size;
423}
424
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200425const std::vector<size_t> &Network::getOfmDims() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200426 return ofmDims;
427}
428
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200429size_t Network::getOfmSize() const {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200430 size_t size = 0;
431
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200432 for (auto s : ofmDims) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200433 size += s;
434 }
435
436 return size;
437}
438
439/****************************************************************************
440 * Inference
441 ****************************************************************************/
442
Davide Grohmann82d22582022-04-25 12:52:38 +0200443ostream &operator<<(ostream &out, const InferenceStatus &status) {
444 switch (status) {
445 case InferenceStatus::OK:
446 return out << "ok";
447 case InferenceStatus::ERROR:
448 return out << "error";
449 case InferenceStatus::RUNNING:
450 return out << "running";
451 case InferenceStatus::REJECTED:
452 return out << "rejected";
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100453 case InferenceStatus::ABORTED:
454 return out << "aborted";
455 case InferenceStatus::ABORTING:
456 return out << "aborting";
Davide Grohmann82d22582022-04-25 12:52:38 +0200457 }
458 throw Exception("Unknown inference status");
459}
460
Davide Grohmannfc495592022-04-25 15:27:52 +0200461Inference::~Inference() noexcept(false) {
Per Åstrandec3f2b02021-06-09 10:43:38 +0200462 eclose(fd);
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200463 Log(Severity::Info) << "~Inference(). this=" << this << endl;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200464}
465
Per Åstrand2354d3e2020-10-24 20:17:10 +0200466void Inference::create(std::vector<uint32_t> &counterConfigs, bool cycleCounterEnable = false) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200467 ethosu_uapi_inference_create uapi;
468
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200469 if (ifmBuffers.size() > ETHOSU_FD_MAX) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200470 throw Exception("IFM buffer overflow");
471 }
472
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200473 if (ofmBuffers.size() > ETHOSU_FD_MAX) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200474 throw Exception("OFM buffer overflow");
475 }
476
Per Åstrand2354d3e2020-10-24 20:17:10 +0200477 if (counterConfigs.size() != ETHOSU_PMU_EVENT_MAX) {
478 throw Exception("Wrong size of counter configurations");
479 }
480
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200481 uapi.ifm_count = 0;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200482 for (auto it : ifmBuffers) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200483 uapi.ifm_fd[uapi.ifm_count++] = it->getFd();
484 }
485
486 uapi.ofm_count = 0;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200487 for (auto it : ofmBuffers) {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200488 uapi.ofm_fd[uapi.ofm_count++] = it->getFd();
489 }
490
Per Åstrand2354d3e2020-10-24 20:17:10 +0200491 for (int i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) {
492 uapi.pmu_config.events[i] = counterConfigs[i];
493 }
494
495 uapi.pmu_config.cycle_count = cycleCounterEnable;
496
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200497 fd = network->ioctl(ETHOSU_IOCTL_INFERENCE_CREATE, static_cast<void *>(&uapi));
Kristofer Jonsson53fd03d2022-06-21 16:58:45 +0200498
499 Log(Severity::Info) << "Inference(" << &*network << "), this=" << this << ", fd=" << fd << endl;
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200500}
501
Per Åstrand2354d3e2020-10-24 20:17:10 +0200502std::vector<uint32_t> Inference::initializeCounterConfig() {
503 return std::vector<uint32_t>(ETHOSU_PMU_EVENT_MAX, 0);
504}
505
506uint32_t Inference::getMaxPmuEventCounters() {
507 return ETHOSU_PMU_EVENT_MAX;
508}
509
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100510bool Inference::wait(int64_t timeoutNanos) const {
Davide Grohmanne446b422021-10-19 15:33:23 +0200511 struct pollfd pfd;
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200512 pfd.fd = fd;
513 pfd.events = POLLIN | POLLERR;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200514 pfd.revents = 0;
515
Davide Grohmanne446b422021-10-19 15:33:23 +0200516 // if timeout negative wait forever
517 if (timeoutNanos < 0) {
Davide Grohmannf0364232022-06-16 17:42:58 +0200518 return eppoll(&pfd, 1, NULL, NULL) == 0;
Davide Grohmanne446b422021-10-19 15:33:23 +0200519 }
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200520
Davide Grohmanne446b422021-10-19 15:33:23 +0200521 struct timespec tmo_p;
522 int64_t nanosec = 1000000000;
523 tmo_p.tv_sec = timeoutNanos / nanosec;
524 tmo_p.tv_nsec = timeoutNanos % nanosec;
Per Åstrand2354d3e2020-10-24 20:17:10 +0200525
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100526 return eppoll(&pfd, 1, &tmo_p, NULL) == 0;
527}
528
529bool Inference::cancel() const {
530 ethosu_uapi_cancel_inference_status uapi;
531 eioctl(fd, ETHOSU_IOCTL_INFERENCE_CANCEL, static_cast<void *>(&uapi));
532 return uapi.status == ETHOSU_UAPI_STATUS_OK;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200533}
534
Davide Grohmann82d22582022-04-25 12:52:38 +0200535InferenceStatus Inference::status() const {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200536 ethosu_uapi_result_status uapi;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200537
Per Åstrand2354d3e2020-10-24 20:17:10 +0200538 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
539
Davide Grohmann82d22582022-04-25 12:52:38 +0200540 switch (uapi.status) {
541 case ETHOSU_UAPI_STATUS_OK:
542 return InferenceStatus::OK;
543 case ETHOSU_UAPI_STATUS_ERROR:
544 return InferenceStatus::ERROR;
545 case ETHOSU_UAPI_STATUS_RUNNING:
546 return InferenceStatus::RUNNING;
547 case ETHOSU_UAPI_STATUS_REJECTED:
548 return InferenceStatus::REJECTED;
Davide Grohmann7e8f5082022-03-23 12:48:45 +0100549 case ETHOSU_UAPI_STATUS_ABORTED:
550 return InferenceStatus::ABORTED;
551 case ETHOSU_UAPI_STATUS_ABORTING:
552 return InferenceStatus::ABORTING;
Davide Grohmann82d22582022-04-25 12:52:38 +0200553 }
554
555 throw Exception("Unknown inference status");
Per Åstrand2354d3e2020-10-24 20:17:10 +0200556}
557
Per Åstrandafb399f2021-11-26 12:50:35 +0100558const std::vector<uint32_t> Inference::getPmuCounters() const {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200559 ethosu_uapi_result_status uapi;
560 std::vector<uint32_t> counterValues = std::vector<uint32_t>(ETHOSU_PMU_EVENT_MAX, 0);
561
562 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
563
564 for (int i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) {
565 if (uapi.pmu_config.events[i]) {
566 counterValues.at(i) = uapi.pmu_count.events[i];
567 }
568 }
569
570 return counterValues;
571}
572
Per Åstrandafb399f2021-11-26 12:50:35 +0100573uint64_t Inference::getCycleCounter() const {
Per Åstrand2354d3e2020-10-24 20:17:10 +0200574 ethosu_uapi_result_status uapi;
575
576 eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast<void *>(&uapi));
577
578 return uapi.pmu_count.cycle_count;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200579}
580
Per Åstrandafb399f2021-11-26 12:50:35 +0100581int Inference::getFd() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200582 return fd;
583}
584
Per Åstrandafb399f2021-11-26 12:50:35 +0100585const shared_ptr<Network> Inference::getNetwork() const {
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200586 return network;
587}
588
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200589vector<shared_ptr<Buffer>> &Inference::getIfmBuffers() {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200590 return ifmBuffers;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200591}
592
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200593vector<shared_ptr<Buffer>> &Inference::getOfmBuffers() {
Kristofer Jonssonb74492c2020-09-10 13:26:01 +0200594 return ofmBuffers;
Kristofer Jonsson116a6352020-08-20 17:25:23 +0200595}
596
Mikael Olsson308e7f12023-06-12 15:00:55 +0200597static_assert(MAX_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION >= ETHOSU_KERNEL_DRIVER_VERSION_MAJOR &&
598 MIN_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION <= ETHOSU_KERNEL_DRIVER_VERSION_MAJOR,
599 "Unsupported major kernel driver version in UAPI");
Kristofer Jonsson79689c52020-10-16 14:42:19 +0200600} // namespace EthosU