Initial commit

Change-Id: I14b6becc908a0ac215769c32ee9c43db192ae6c8
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 <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;
+}
+
+}