From 116a635581f292cb4882ea1a086f842904f85c3c Mon Sep 17 00:00:00 2001 From: Kristofer Jonsson Date: Thu, 20 Aug 2020 17:25:23 +0200 Subject: Initial commit Change-Id: I14b6becc908a0ac215769c32ee9c43db192ae6c8 --- driver_library/src/ethosu.cpp | 232 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 driver_library/src/ethosu.cpp (limited to 'driver_library/src') diff --git a/driver_library/src/ethosu.cpp b/driver_library/src/ethosu.cpp new file mode 100644 index 0000000..6b2b3b1 --- /dev/null +++ b/driver_library/src/ethosu.cpp @@ -0,0 +1,232 @@ +/* + * 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 +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +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(dataCapacity) }; + fd = device.ioctl(ETHOSU_IOCTL_BUFFER_CREATE, static_cast(&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(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(&uapi)); +} + +size_t Buffer::offset() const +{ + ethosu_uapi_buffer uapi; + eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast(&uapi)); + return uapi.offset; +} + +size_t Buffer::size() const +{ + ethosu_uapi_buffer uapi; + eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast(&uapi)); + return uapi.size; +} + +int Buffer::getFd() const +{ + return fd; +} + +Network::Network(Device &device, shared_ptr &buffer) : + fd(-1), + buffer(buffer) +{ + ethosu_uapi_network_create uapi; + + uapi.fd = buffer->getFd(); + + fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast(&uapi)); +} + +Network::~Network() +{ + close(fd); +} + +int Network::ioctl(unsigned long cmd, void *data) +{ + return eioctl(fd, cmd, data); +} + +std::shared_ptr Network::getBuffer() +{ + return buffer; +} + +Inference::Inference(std::shared_ptr &network, std::shared_ptr &ifmBuffer, std::shared_ptr &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(&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(eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS)); + + return status != ETHOSU_UAPI_STATUS_OK; +} + +int Inference::getFd() +{ + return fd; +} + +std::shared_ptr Inference::getNetwork() +{ + return network; +} + +std::shared_ptr Inference::getIfmBuffer() +{ + return ifmBuffer; +} + +std::shared_ptr Inference::getOfmBuffer() +{ + return ofmBuffer; +} + +} -- cgit v1.2.1