blob: 6b2b3b1aa3d4c5e93117990ee69da6454d508f68 [file] [log] [blame]
/*
* Copyright (c) 2020 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <ethosu.hpp>
#include <uapi/ethosu.h>
#include <algorithm>
#include <exception>
#include <iostream>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <poll.h>
#include <unistd.h>
using namespace std;
namespace
{
int eioctl(int fd, unsigned long cmd, void *data = nullptr)
{
int ret = ::ioctl(fd, cmd, data);
if (ret < 0)
{
throw EthosU::Exception("IOCTL failed");
}
return ret;
}
}
namespace EthosU
{
Exception::Exception(const char *msg) :
msg(msg)
{}
Exception::~Exception() throw()
{}
const char *Exception::what() const throw()
{
return msg.c_str();
}
Device::Device(const char *device)
{
fd = open(device, O_RDWR | O_NONBLOCK);
if (fd < 0)
{
throw Exception("Failed to open device");
}
}
Device::~Device()
{
close(fd);
}
int Device::ioctl(unsigned long cmd, void *data)
{
return eioctl(fd, cmd, data);
}
Buffer::Buffer(Device &device, const size_t capacity) :
fd(-1),
dataPtr(nullptr),
dataCapacity(capacity)
{
ethosu_uapi_buffer_create uapi = { static_cast<uint32_t>(dataCapacity) };
fd = device.ioctl(ETHOSU_IOCTL_BUFFER_CREATE, static_cast<void *>(&uapi));
void *d = ::mmap(nullptr, dataCapacity, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (d == MAP_FAILED)
{
throw Exception("MMap failed");
}
dataPtr = reinterpret_cast<char *>(d);
}
Buffer::~Buffer()
{
close(fd);
}
size_t Buffer::capacity() const
{
return dataCapacity;
}
void Buffer::clear()
{
resize(0, 0);
}
char *Buffer::data()
{
return dataPtr + offset();
}
void Buffer::resize(size_t size, size_t offset)
{
ethosu_uapi_buffer uapi;
uapi.offset = offset;
uapi.size = size;
eioctl(fd, ETHOSU_IOCTL_BUFFER_SET, static_cast<void *>(&uapi));
}
size_t Buffer::offset() const
{
ethosu_uapi_buffer uapi;
eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast<void *>(&uapi));
return uapi.offset;
}
size_t Buffer::size() const
{
ethosu_uapi_buffer uapi;
eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast<void *>(&uapi));
return uapi.size;
}
int Buffer::getFd() const
{
return fd;
}
Network::Network(Device &device, shared_ptr<Buffer> &buffer) :
fd(-1),
buffer(buffer)
{
ethosu_uapi_network_create uapi;
uapi.fd = buffer->getFd();
fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast<void *>(&uapi));
}
Network::~Network()
{
close(fd);
}
int Network::ioctl(unsigned long cmd, void *data)
{
return eioctl(fd, cmd, data);
}
std::shared_ptr<Buffer> Network::getBuffer()
{
return buffer;
}
Inference::Inference(std::shared_ptr<Network> &network, std::shared_ptr<Buffer> &ifmBuffer, std::shared_ptr<Buffer> &ofmBuffer) :
fd(-1),
network(network),
ifmBuffer(ifmBuffer),
ofmBuffer(ofmBuffer)
{
ethosu_uapi_inference_create uapi;
uapi.ifm_fd = ifmBuffer->getFd();
uapi.ofm_fd = ofmBuffer->getFd();
fd = network->ioctl(ETHOSU_IOCTL_INFERENCE_CREATE, static_cast<void *>(&uapi));
}
Inference::~Inference()
{
close(fd);
}
void Inference::wait(int timeoutSec)
{
pollfd pfd;
pfd.fd = fd;
pfd.events = POLLIN | POLLERR;
pfd.revents = 0;
int ret = ::poll(&pfd, 1, timeoutSec * 1000);
cout << "Poll. ret=" << ret << ", revents=" << pfd.revents << endl;
}
bool Inference::failed()
{
ethosu_uapi_status status = static_cast<ethosu_uapi_status>(eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS));
return status != ETHOSU_UAPI_STATUS_OK;
}
int Inference::getFd()
{
return fd;
}
std::shared_ptr<Network> Inference::getNetwork()
{
return network;
}
std::shared_ptr<Buffer> Inference::getIfmBuffer()
{
return ifmBuffer;
}
std::shared_ptr<Buffer> Inference::getOfmBuffer()
{
return ofmBuffer;
}
}