diff options
author | Kshitij Sisodia <kshitij.sisodia@arm.com> | 2022-09-30 16:42:50 +0100 |
---|---|---|
committer | Kristofer Jonsson <kristofer.jonsson@arm.com> | 2022-10-25 16:36:45 +0000 |
commit | f9efe0ddf865c55d28bcaa203fefffa94bf09b42 (patch) | |
tree | 928da5f68dafd7e5a0dee05a75f2f6fcd52df170 /driver_library/python/src/ethosu_driver/swig | |
parent | 569aa558f5e7638852a928feede1f21e7323f664 (diff) | |
download | ethos-u-linux-driver-stack-f9efe0ddf865c55d28bcaa203fefffa94bf09b42.tar.gz |
Added Python interface for Arm Ethos-U NPU driver library.22.11-rc1
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>
Diffstat (limited to 'driver_library/python/src/ethosu_driver/swig')
3 files changed, 646 insertions, 0 deletions
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; diff --git a/driver_library/python/src/ethosu_driver/swig/standard_header.i b/driver_library/python/src/ethosu_driver/swig/standard_header.i new file mode 100644 index 0000000..03cf015 --- /dev/null +++ b/driver_library/python/src/ethosu_driver/swig/standard_header.i @@ -0,0 +1,50 @@ +// +// SPDX-FileCopyrightText: Copyright 2021-2022 Arm Limited and/or its affiliates <open-source-office@arm.com> +// SPDX-License-Identifier: Apache-2.0 +// +%include "stl.i" +%include "cstring.i" +%include "std_string.i" +%include "std_vector.i" +%include "std_unordered_set.i" +%include "std_pair.i" +%include "stdint.i" +%include "carrays.i" +%include "exception.i" +%include "typemaps.i" +%include "std_iostream.i" +%include "std_shared_ptr.i" + +%ignore *::operator=; +%ignore *::operator[]; + + +// Define exception typemap to wrap exception into python exception. + +%exception{ + try { + $action + } catch (const EthosU::Exception& e) { + SWIG_exception(SWIG_RuntimeError, const_cast<char*>(e.what())); + } +}; + +%exception __getitem__ { + try { + $action + } catch (const std::out_of_range &e) { + SWIG_exception(SWIG_IndexError, const_cast<char*>(e.what())); + } catch (const std::exception &e) { + SWIG_exception(SWIG_RuntimeError, const_cast<char*>(e.what())); + } +}; + +%exception __setitem__ { + try { + $action + } catch (const std::out_of_range &e) { + SWIG_exception(SWIG_IndexError, const_cast<char*>(e.what())); + } catch (const std::exception &e) { + SWIG_exception(SWIG_RuntimeError, const_cast<char*>(e.what())); + } +}; diff --git a/driver_library/python/src/ethosu_driver/swig/typemaps/buffer.i b/driver_library/python/src/ethosu_driver/swig/typemaps/buffer.i new file mode 100644 index 0000000..13b7909 --- /dev/null +++ b/driver_library/python/src/ethosu_driver/swig/typemaps/buffer.i @@ -0,0 +1,42 @@ +// +// SPDX-FileCopyrightText: Copyright 2021-2022 Arm Limited and/or its affiliates <open-source-office@arm.com> +// SPDX-License-Identifier: Apache-2.0 +// +%define %mutable_buffer(TYPEMAP, SIZE) + %typemap(in) (TYPEMAP, SIZE) { + int res; void *buf = 0; size_t size = 0; + Py_buffer view; + res = PyObject_GetBuffer($input, &view, PyBUF_WRITABLE); + buf = view.buf; + size = view.len; + PyBuffer_Release(&view); + if (res < 0) { + PyErr_Clear(); + %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum); + } + $1 = ($1_ltype) buf; + $2 = ($2_ltype) size; + } + + %typemap(typecheck) (TYPEMAP, SIZE) { + $1 = PyObject_CheckBuffer($input) || PyTuple_Check($input) ? 1 : 0; + } +%enddef + +%define %clear_mutable_buffer(TYPEMAP, SIZE) + %typemap(in) (TYPEMAP, SIZE); + %typemap(typecheck) (TYPEMAP, SIZE); +%enddef + + +%define %driver_buffer_out + %typemap(out) (char*) { + auto size = arg1->size(); + int readOnly = 0; + $result = PyMemoryView_FromMemory($1, size, readOnly); + } +%enddef + +%define %clear_driver_buffer_out + %typemap(out) (char*); +%enddef |