Added Python interface for Arm Ethos-U NPU driver library.

Python `ethosu_driver` could be built as part of Arm Ethos-U Linux
driver library CMake flow.

See driver_library/python/README.md for more details.

Change-Id: I177a890add5c13df9a839f4f43621f972afe5ab1
Signed-off-by: Kshitij Sisodia <kshitij.sisodia@arm.com>
diff --git a/driver_library/python/src/ethosu_driver/swig/driver.i b/driver_library/python/src/ethosu_driver/swig/driver.i
new file mode 100644
index 0000000..4cd8bdf
--- /dev/null
+++ b/driver_library/python/src/ethosu_driver/swig/driver.i
@@ -0,0 +1,554 @@
+//
+// SPDX-FileCopyrightText: Copyright 2020, 2022 Arm Limited and/or its affiliates <open-source-office@arm.com>
+// SPDX-License-Identifier: Apache-2.0
+//
+%module driver
+%{
+#define SWIG_FILE_WITH_INIT
+%}
+
+//typemap definitions and other common stuff
+%include "standard_header.i"
+
+%{
+#include "ethosu.hpp"
+#include <fstream>
+#include <list>
+#include <string>
+#include <cstring>
+#include <sstream>
+#include <linux/ioctl.h>
+
+#define ETHOSU_IOCTL_BASE               0x01
+#define ETHOSU_IO(nr)                   _IO(ETHOSU_IOCTL_BASE, nr)
+#define ETHOSU_IOCTL_PING               ETHOSU_IO(0x00)
+
+%}
+%include <typemaps/buffer.i>
+
+%shared_ptr(EthosU::Buffer);
+%shared_ptr(EthosU::Network);
+
+
+namespace std {
+   %template(UintVector) vector<unsigned int>;
+   %template(SizeTVector) vector<size_t>;
+   %template(SharedBufferVector) vector<shared_ptr<EthosU::Buffer>>;
+}
+
+namespace EthosU
+{
+
+%feature("docstring",
+"
+Semantic Version : major.minor.patch
+") SemanticVersion;
+%nodefaultctor SemanticVersion;
+class SemanticVersion {
+public:
+    SemanticVersion(uint32_t major = 0, uint32_t minor = 0, uint32_t patch = 0);
+
+    uint32_t major;
+    uint32_t minor;
+    uint32_t patch;
+};
+
+%extend SemanticVersion {
+    std::string __str__() const {
+        std::ostringstream out;
+        out << *$self;
+        return out.str();
+    }
+}
+
+%feature("docstring",
+"
+Hardware Identifier which consists of version status, version revision, product revision and architecture revision.
+") HardwareId;
+class HardwareId {
+public:
+    HardwareId(uint32_t versionStatus, SemanticVersion& version, SemanticVersion& product, SemanticVersion& arch);
+
+    uint32_t versionStatus{0};
+    SemanticVersion version{};
+    SemanticVersion product{};
+    SemanticVersion architecture{};
+};
+
+%extend HardwareId {
+    std::string __str__() const {
+        std::ostringstream out;
+        out << "{versionStatus=" << $self->versionStatus <<
+        ", version=" << EthosU_SemanticVersion___str__(&$self->version) <<
+        ", product=" << EthosU_SemanticVersion___str__(&$self->product) <<
+        ", architecture=" << EthosU_SemanticVersion___str__(&$self->architecture) << "}";
+        return out.str();
+    }
+}
+
+%feature("docstring",
+"
+Hardware Configuration object defines specific configuration including MACs per clock cycle and NPU command stream
+version. This also specifies is custom DMA is enabled or not.
+") HardwareConfiguration;
+%nodefaultctor HardwareConfiguration;
+class HardwareConfiguration {
+    public:
+    HardwareConfiguration(uint32_t macs = 0, uint32_t cmdStreamVersion = 0, bool customDma = false);
+
+    uint32_t macsPerClockCycle;
+    uint32_t cmdStreamVersion;
+    bool customDma;
+};
+
+%extend HardwareConfiguration {
+    std::string __str__() const {
+        std::ostringstream out;
+        out << "{macsPerClockCycle=" << $self->macsPerClockCycle <<
+        ", cmdStreamVersion=" << $self->cmdStreamVersion <<
+        ", customDma=" <<  ($self->customDma? "True": "False") << "}";
+        return out.str();
+    }
+}
+
+%feature("docstring",
+"
+Device capabilities object which specifies capabilities based on hardware ID, configuration and semantic version.
+") Capabilities;
+class Capabilities {
+    public:
+    Capabilities() {}
+    Capabilities(const HardwareId& hwId, const HardwareConfiguration& hwCfg, const SemanticVersion& driverVersion);
+
+    HardwareId hwId;
+    HardwareConfiguration hwCfg;
+    SemanticVersion driver;
+};
+
+%extend Capabilities {
+    std::string __str__() const {
+        std::ostringstream out;
+        out << "{hwId=" << EthosU_HardwareId___str__(&$self->hwId) <<
+        ", hwCfg=" << EthosU_HardwareConfiguration___str__(&$self->hwCfg) <<
+        ", driver=" <<  EthosU_SemanticVersion___str__(&$self->driver) << "}";
+        return out.str();
+    }
+}
+
+%feature("docstring",
+"
+Device object represents Ethos-U device file descriptor and manages Ethos-U device lifecycle.
+Constructor accepts device name and opens file descriptor with O_RDWR | O_NONBLOCK flags.
+When the object is destroyed - device file descriptor is closed.
+") Device;
+%nodefaultctor Device;
+class Device {
+public:
+    Device(const char *device);
+
+    %feature("docstring",
+    "
+    Performs the I/O control operation on the Ethos-U device.
+
+    Args:
+        cmd: Command code
+        data: Command data
+    Returns:
+        int: Return value depends on command. Usually -1 indicates error.
+    ") ioctl;
+    int ioctl(unsigned long cmd, void *data = nullptr) const;
+
+    %feature("docstring",
+    "
+    Returns the capabilities of the Ethos-U device.
+
+    Returns:
+    Capabilities: Return capabilities of device.
+    ") capabilities;
+    Capabilities capabilities() const;
+};
+
+%extend Device {
+
+    %feature("docstring",
+    "
+    Sends ping command to the Ethos-U device.
+
+    See ETHOSU_IOCTL_PING from kernel module uapi/ethosu.h
+    ") ping;
+    void ping() {
+        $self->ioctl(ETHOSU_IOCTL_PING);
+    }
+}
+
+%feature("docstring",
+    "
+    Buffer object represents a RW mapping in the virtual address space of the caller.
+
+    Created mapping is shareable, updates to the mapping are visible to other processes mapping the same region.
+    Issues ETHOSU_IOCTL_BUFFER_CREATE I/O request to the device with given Maximum capacity.
+
+    Buffer could be created for a device with given maximum capacity or instantiated directly from
+    a file containing binary data.
+
+    Examples:
+        >>> import ethosu_driver as driver
+        >>> # from file:
+        >>> buf = driver.Buffer(device, '/path/to/file')
+        >>> # Empty, with maximum capacity:
+        >>> buf = driver.Buffer(device, 1024)
+    ") Buffer;
+%nodefaultctor Buffer;
+class Buffer {
+public:
+    Buffer(const Device &device, const size_t capacity);
+
+    %feature("docstring",
+    "
+    Returns maximum buffer capacity set during initialisation.
+
+    Returns:
+        int: maximum buffer capacity.
+    ") capacity;
+    size_t capacity() const;
+
+    %feature("docstring",
+    "
+    Sets the size of the device buffer to 0.
+    ") clear;
+    void clear() const;
+
+    %feature("docstring",
+    "
+    Returns a readonly view to the mapped memory.
+
+    Returns:
+        memoryview: readonly memory data.
+    ") data;
+    %driver_buffer_out;
+    char* data() const;
+    %clear_driver_buffer_out;
+
+    %feature("docstring",
+    "
+    Sets a size of the memory buffer for the device.
+
+    'offset + size' must not exceed the capacity of the buffer.
+    Does not change the size of the mapped region.
+
+    Issues ETHOSU_IOCTL_BUFFER_SET I/O request with a given size and offset.
+
+    Args:
+        size (int): Device buffer size.
+        offset (int): Offset to where the data starts.
+    ") resize;
+    void resize(size_t size, size_t offset = 0) const;
+
+    %feature("docstring",
+    "
+    Queries device and returns buffer data offset.
+
+    Issues ETHOSU_IOCTL_BUFFER_GET I/O request.
+
+    Returns:
+        int: data offset
+    ") offset;
+    size_t offset() const;
+
+    %feature("docstring",
+    "
+    Queries device and returns buffer data size.
+
+    Issues ETHOSU_IOCTL_BUFFER_GET I/O request.
+
+    Returns:
+        int: current device buffer size.
+    ") size;
+    size_t size() const;
+
+    %feature("docstring",
+    "
+    Returns buffer file descriptor id.
+
+    Returns:
+        int: file descriptor id.
+    ") getFd;
+    int getFd() const;
+};
+
+%extend Buffer {
+
+    Buffer(const Device& device, const std::string& filename) {
+        std::ifstream stream(filename, std::ios::binary);
+        if (!stream.is_open()) {
+            throw EthosU::Exception(std::string("Failed to open file: ").append(filename).c_str());
+        }
+
+        stream.seekg(0, std::ios_base::end);
+        size_t size = stream.tellg();
+        stream.seekg(0, std::ios_base::beg);
+
+        auto buffer = new EthosU::Buffer(device, size);
+        buffer->resize(size);
+        stream.read(buffer->data(), size);
+
+        return buffer;
+    }
+
+    %feature("docstring",
+    "
+    Fills the buffer from python buffer.
+
+    Copies python buffer data to the mapped memory region.
+    Input buffer size must be within `Buffer` maximum capacity.
+
+    Args:
+        buffer: data to be copied to the mapped memory.
+
+    ") from_buffer;
+    %mutable_buffer(char* buffer, size_t size);
+    void from_buffer(char* buffer, size_t size) {
+        self->resize(size);
+        char* data = $self->data();
+        std::memcpy(data, buffer, size);
+    }
+    %clear_mutable_buffer(char* buffer, size_t size);
+}
+
+%feature("docstring",
+    "
+    Represents the neural network file descriptor received from the Ethos-U device.
+
+    `Network` is created providing `Device` object and a `Buffer` containing tflite file data.
+    Network creation issues ETHOSU_IOCTL_NETWORK_CREATE I/O request with buffer file descriptor id.
+    Provided `Buffer` data is parsed into tflite Model object and input/output feature maps sizes are saved.
+
+    Destruction of the object closes network file descriptor.
+    ") Network;
+%nodefaultctor Network;
+class Network {
+public:
+
+    %feature("docstring",
+    "
+    Performs the I/O control operation with network buffer device.
+
+    Args:
+        cmd: Command code
+        data: Command data
+    Returns:
+        int: Return value depends on command. Usually -1 indicates error.
+    ") ioctl;
+    int ioctl(unsigned long cmd, void *data);
+
+    %feature("docstring",
+    "
+    Returns associated memory buffer.
+
+    Returns:
+        `Buffer`: buffer object used during initialisation.
+    ") getBuffer;
+    std::shared_ptr<Buffer> getBuffer();
+
+    %feature("docstring",
+    "
+    Returns saved sizes of the neural network model input feature maps.
+
+    Returns:
+        list: sizes of all input feature maps
+    ") getIfmDims;
+    const std::vector<size_t> &getIfmDims() const;
+
+    %feature("docstring",
+    "
+    Returns total size of all input feature maps.
+
+    Returns:
+        int: total size of all input feature maps
+    ") getIfmSize;
+    size_t getIfmSize() const;
+
+    %feature("docstring",
+    "
+    Returns saved sizes of the neural network model output feature maps.
+
+    Returns:
+        list: sizes of all output feature maps
+    ") getOfmDims;
+    const std::vector<size_t> &getOfmDims() const;
+
+    %feature("docstring",
+    "
+    Returns total size of all output feature maps.
+
+    Returns:
+        int: total size of all output feature maps
+    ") getOfmSize;
+    size_t getOfmSize() const;
+};
+
+%extend Network {
+    Network(const Device &device, std::shared_ptr<Buffer> &buffer)
+    {
+        if(buffer == nullptr){
+            throw EthosU::Exception(std::string("Failed to create the network, buffer is nullptr.").c_str());
+        }
+        auto network = new EthosU::Network(device, buffer);
+        return network;
+    }
+}
+
+%extend Network {
+    Network(const Device &device, const unsigned int index)
+    {
+        auto network = new EthosU::Network(device, index);
+        return network;
+    }
+}
+
+%feature("docstring",
+    "
+    InferenceStatus enumeration
+    ") InferenceStatus;
+enum class InferenceStatus {
+    OK,
+    ERROR,
+    RUNNING,
+    REJECTED,
+    ABORTED,
+    ABORTING
+    };
+
+%feature("docstring",
+    "
+    Represents the inference file descriptor received from the Ethos-U device.
+
+    `Inference` is created providing `Network` object and lists of input and output feature maps buffers.
+    Feature map buffers are copied.
+
+    Inference creation issues ETHOSU_IOCTL_INFERENCE_CREATE I/O request with
+    file descriptor ids for all input and output buffers.
+
+    The number of input/output buffers must not exceed ETHOSU_FD_MAX value defined in the kernel module
+    uapi/ethosu.h.
+
+    Destruction of the object closes inference file descriptor.
+    ") Inference;
+%nodefaultctor Inference;
+class Inference {
+public:
+
+    %feature("docstring",
+    "
+    Polls inference file descriptor for events.
+
+    Args:
+        timeoutNanos (int64_t): polling timeout in nanoseconds.
+
+    Returns:
+        bool: True for success, False otherwise.
+    ") wait;
+    void wait(int64_t timeoutNanos = -1) const;
+
+    %feature("docstring",
+    "
+    Aborts the current inference job.
+
+    Returns:
+        bool: True if gracefully stopped, False otherwise.
+    ") cancel;
+    bool cancel() const;
+
+    %feature("docstring",
+    "
+    Gets the current inference job status.
+
+    Returns:
+        InferenceStatus.
+    ") status;
+    EthosU::InferenceStatus status() const;
+
+    %feature("docstring",
+    "
+    Returns inference file descriptor.
+
+    Returns:
+        int: file descriptor id
+    ") getFd;
+    int getFd() const;
+
+    %feature("docstring",
+    "
+    Returns associated `Network` object.
+
+    Returns:
+        `Network`: network used during initialisation
+    ") getNetwork;
+    std::shared_ptr<Network> getNetwork() const;
+
+    %feature("docstring",
+    "
+    Returns copied input feature maps buffers.
+
+    Returns:
+       list: input feature map buffers
+    ") getIfmBuffers;
+    std::vector<std::shared_ptr<Buffer>> &getIfmBuffers();
+
+    %feature("docstring",
+    "
+    Returns copied output feature maps buffers.
+
+    Returns:
+       list: output feature map buffers
+    ") getOfmBuffers;
+    std::vector<std::shared_ptr<Buffer>> &getOfmBuffers();
+
+    %feature("docstring",
+    "
+    Returns PMU event data.
+
+    Returns:
+        list: PMU event data
+    ") getPmuCounters;
+    const std::vector<uint32_t> getPmuCounters();
+
+    %feature("docstring",
+    "
+    Returns the total cycle count, including idle cycles, as reported by the PMU.
+
+    Returns:
+        int: total cycle count
+    ") getCycleCounter;
+    uint64_t getCycleCounter();
+
+    %feature("docstring",
+    "
+    Returns maximum supported number of PMU events.
+
+    Returns:
+        int: PMU event max
+    ") getMaxPmuEventCounters;
+    static uint32_t getMaxPmuEventCounters();
+};
+
+%extend Inference {
+    Inference(const std::shared_ptr<Network> &network,
+            const std::vector<std::shared_ptr<Buffer>> &ifm,
+            const std::vector<std::shared_ptr<Buffer>> &ofm)
+   {
+        return new EthosU::Inference(network, ifm.begin(), ifm.end(), ofm.begin(), ofm.end());
+   }
+   Inference(const std::shared_ptr<Network> & network,
+             const std::vector<std::shared_ptr<Buffer>> &ifm,
+             const std::vector<std::shared_ptr<Buffer>> &ofm,
+             const std::vector<unsigned int> &enabledCounters,
+             bool enableCycleCounter)
+   {
+       return new EthosU::Inference(network, ifm.begin(), ifm.end(), ofm.begin(), ofm.end(), enabledCounters, enableCycleCounter);
+   }
+}
+
+}
+// Clear exception typemap.
+%exception;