blob: 6b2b3b1aa3d4c5e93117990ee69da6454d508f68 [file] [log] [blame]
Kristofer Jonsson116a6352020-08-20 17:25:23 +02001/*
2 * Copyright (c) 2020 Arm Limited. All rights reserved.
3 *
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>
23#include <exception>
24#include <iostream>
25
26#include <sys/ioctl.h>
27#include <sys/mman.h>
28#include <fcntl.h>
29#include <poll.h>
30#include <unistd.h>
31
32using namespace std;
33
34namespace
35{
36int eioctl(int fd, unsigned long cmd, void *data = nullptr)
37{
38 int ret = ::ioctl(fd, cmd, data);
39 if (ret < 0)
40 {
41 throw EthosU::Exception("IOCTL failed");
42 }
43
44 return ret;
45}
46}
47
48namespace EthosU
49{
50
51Exception::Exception(const char *msg) :
52 msg(msg)
53{}
54
55Exception::~Exception() throw()
56{}
57
58const char *Exception::what() const throw()
59{
60 return msg.c_str();
61}
62
63Device::Device(const char *device)
64{
65 fd = open(device, O_RDWR | O_NONBLOCK);
66 if (fd < 0)
67 {
68 throw Exception("Failed to open device");
69 }
70}
71
72Device::~Device()
73{
74 close(fd);
75}
76
77int Device::ioctl(unsigned long cmd, void *data)
78{
79 return eioctl(fd, cmd, data);
80}
81
82Buffer::Buffer(Device &device, const size_t capacity) :
83 fd(-1),
84 dataPtr(nullptr),
85 dataCapacity(capacity)
86{
87 ethosu_uapi_buffer_create uapi = { static_cast<uint32_t>(dataCapacity) };
88 fd = device.ioctl(ETHOSU_IOCTL_BUFFER_CREATE, static_cast<void *>(&uapi));
89
90 void *d = ::mmap(nullptr, dataCapacity, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
91 if (d == MAP_FAILED)
92 {
93 throw Exception("MMap failed");
94 }
95
96 dataPtr = reinterpret_cast<char *>(d);
97}
98
99Buffer::~Buffer()
100{
101 close(fd);
102}
103
104size_t Buffer::capacity() const
105{
106 return dataCapacity;
107}
108
109void Buffer::clear()
110{
111 resize(0, 0);
112}
113
114char *Buffer::data()
115{
116 return dataPtr + offset();
117}
118
119void Buffer::resize(size_t size, size_t offset)
120{
121 ethosu_uapi_buffer uapi;
122 uapi.offset = offset;
123 uapi.size = size;
124
125 eioctl(fd, ETHOSU_IOCTL_BUFFER_SET, static_cast<void *>(&uapi));
126}
127
128size_t Buffer::offset() const
129{
130 ethosu_uapi_buffer uapi;
131 eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast<void *>(&uapi));
132 return uapi.offset;
133}
134
135size_t Buffer::size() const
136{
137 ethosu_uapi_buffer uapi;
138 eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast<void *>(&uapi));
139 return uapi.size;
140}
141
142int Buffer::getFd() const
143{
144 return fd;
145}
146
147Network::Network(Device &device, shared_ptr<Buffer> &buffer) :
148 fd(-1),
149 buffer(buffer)
150{
151 ethosu_uapi_network_create uapi;
152
153 uapi.fd = buffer->getFd();
154
155 fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast<void *>(&uapi));
156}
157
158Network::~Network()
159{
160 close(fd);
161}
162
163int Network::ioctl(unsigned long cmd, void *data)
164{
165 return eioctl(fd, cmd, data);
166}
167
168std::shared_ptr<Buffer> Network::getBuffer()
169{
170 return buffer;
171}
172
173Inference::Inference(std::shared_ptr<Network> &network, std::shared_ptr<Buffer> &ifmBuffer, std::shared_ptr<Buffer> &ofmBuffer) :
174 fd(-1),
175 network(network),
176 ifmBuffer(ifmBuffer),
177 ofmBuffer(ofmBuffer)
178{
179 ethosu_uapi_inference_create uapi;
180
181 uapi.ifm_fd = ifmBuffer->getFd();
182 uapi.ofm_fd = ofmBuffer->getFd();
183
184 fd = network->ioctl(ETHOSU_IOCTL_INFERENCE_CREATE, static_cast<void *>(&uapi));
185}
186
187Inference::~Inference()
188{
189 close(fd);
190}
191
192void Inference::wait(int timeoutSec)
193{
194 pollfd pfd;
195
196 pfd.fd = fd;
197 pfd.events = POLLIN | POLLERR;
198 pfd.revents = 0;
199
200 int ret = ::poll(&pfd, 1, timeoutSec * 1000);
201
202 cout << "Poll. ret=" << ret << ", revents=" << pfd.revents << endl;
203}
204
205bool Inference::failed()
206{
207 ethosu_uapi_status status = static_cast<ethosu_uapi_status>(eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS));
208
209 return status != ETHOSU_UAPI_STATUS_OK;
210}
211
212int Inference::getFd()
213{
214 return fd;
215}
216
217std::shared_ptr<Network> Inference::getNetwork()
218{
219 return network;
220}
221
222std::shared_ptr<Buffer> Inference::getIfmBuffer()
223{
224 return ifmBuffer;
225}
226
227std::shared_ptr<Buffer> Inference::getOfmBuffer()
228{
229 return ofmBuffer;
230}
231
232}