diff options
Diffstat (limited to 'driver_library')
-rw-r--r-- | driver_library/include/ethosu.hpp | 10 | ||||
-rw-r--r-- | driver_library/python/README.md | 14 | ||||
-rw-r--r-- | driver_library/python/src/ethosu_driver/_utilities/driver_utilities.py | 3 | ||||
-rw-r--r-- | driver_library/python/src/ethosu_driver/swig/driver.i | 51 | ||||
-rw-r--r-- | driver_library/python/src/ethosu_driver/swig/typemaps/buffer.i | 23 | ||||
-rw-r--r-- | driver_library/python/test/test_driver.py | 86 | ||||
-rw-r--r-- | driver_library/src/ethosu.cpp | 15 |
7 files changed, 117 insertions, 85 deletions
diff --git a/driver_library/include/ethosu.hpp b/driver_library/include/ethosu.hpp index 47c1868..eaa1ce7 100644 --- a/driver_library/include/ethosu.hpp +++ b/driver_library/include/ethosu.hpp @@ -39,12 +39,12 @@ namespace EthosU { -constexpr uint32_t DRIVER_LIBRARY_VERSION_MAJOR = 2; +constexpr uint32_t DRIVER_LIBRARY_VERSION_MAJOR = 3; constexpr uint32_t DRIVER_LIBRARY_VERSION_MINOR = 0; constexpr uint32_t DRIVER_LIBRARY_VERSION_PATCH = 0; -constexpr uint32_t MAX_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION = 2; -constexpr uint32_t MIN_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION = 2; +constexpr uint32_t MAX_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION = 3; +constexpr uint32_t MIN_SUPPORTED_KERNEL_DRIVER_MAJOR_VERSION = 3; class Exception : public std::exception { public: @@ -168,12 +168,11 @@ private: class Network { public: - Network(const Device &device, std::shared_ptr<Buffer> &buffer); + Network(const Device &device, const unsigned char *networkData, size_t networkSize); Network(const Device &device, const unsigned index); virtual ~Network() noexcept(false); int ioctl(unsigned long cmd, void *data = nullptr); - std::shared_ptr<Buffer> getBuffer(); const std::vector<size_t> &getIfmDims() const; size_t getIfmSize() const; const std::vector<size_t> &getOfmDims() const; @@ -183,7 +182,6 @@ private: void collectNetworkInfo(); int fd; - std::shared_ptr<Buffer> buffer; std::vector<size_t> ifmDims; std::vector<size_t> ofmDims; }; diff --git a/driver_library/python/README.md b/driver_library/python/README.md index 7fae749..cc67ad9 100644 --- a/driver_library/python/README.md +++ b/driver_library/python/README.md @@ -165,8 +165,8 @@ object: ```python # from file: -network_file = "/path/to/model.tflite" -network_buffer = driver.Buffer(device, network_file) +data_file = "/path/to/data.bin" +buffer = driver.Buffer(device, data_file) # from numpy: ifm_zeros = numpy.zeros(ifm_size, dtype=np.uint8) @@ -174,11 +174,15 @@ ifm_buffer = driver.Buffer(device, ifm_size) ifm_buffer.from_buffer(ifm_zeros.data) ``` -To create a network object, provide memory buffer for the model file and -created device: +To create a network object, provide the model file or a byte array with the +network data and the created device: ```python -network = driver.Network(device, network_buffer) +# from file: +network = driver.Network(device, "path/to/model.tflite") + +# from byte array: +network = driver.Network(device, network_data) ``` Inference object is instantiated with a network object and lists of input diff --git a/driver_library/python/src/ethosu_driver/_utilities/driver_utilities.py b/driver_library/python/src/ethosu_driver/_utilities/driver_utilities.py index fcea91f..ca39751 100644 --- a/driver_library/python/src/ethosu_driver/_utilities/driver_utilities.py +++ b/driver_library/python/src/ethosu_driver/_utilities/driver_utilities.py @@ -30,8 +30,7 @@ def load_model(device: Device, model: str) -> Network: `Network`: Return the object that represent the neural __network file descriptor received from the Ethos-U device. """ logging.info("Creating network") - network_buffer = Buffer(device, model) - return Network(device, network_buffer) + return Network(device, model) def populate_buffers(input_data: List[bytearray], buffers: List[Buffer]): diff --git a/driver_library/python/src/ethosu_driver/swig/driver.i b/driver_library/python/src/ethosu_driver/swig/driver.i index 3e4e384..6e0ad25 100644 --- a/driver_library/python/src/ethosu_driver/swig/driver.i +++ b/driver_library/python/src/ethosu_driver/swig/driver.i @@ -293,12 +293,12 @@ public: buffer: data to be copied to the mapped memory. ") from_buffer; - %mutable_buffer(char* buffer, size_t size); + %buffer_in(char* buffer, size_t size, BUFFER_FLAG_RW); void from_buffer(char* buffer, size_t size) { char* data = $self->data(); std::memcpy(data, buffer, size); } - %clear_mutable_buffer(char* buffer, size_t size); + %clear_buffer_in(char* buffer, size_t size); } %feature("docstring", @@ -329,15 +329,6 @@ public: %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: @@ -374,21 +365,41 @@ public: }; %extend Network { - Network(const Device &device, std::shared_ptr<Buffer> &buffer) + + Network(const Device &device, const std::string& filename) { - if(buffer == nullptr){ - throw EthosU::Exception(std::string("Failed to create the network, buffer is nullptr.").c_str()); + std::ifstream stream(filename, std::ios::binary); + if (!stream.is_open()) { + throw EthosU::Exception(std::string("Failed to open file: ").append(filename).c_str()); } - auto network = new EthosU::Network(device, buffer); - return network; + + stream.seekg(0, std::ios_base::end); + size_t size = stream.tellg(); + stream.seekg(0, std::ios_base::beg); + + std::unique_ptr<unsigned char[]> buffer = std::make_unique<unsigned char[]>(size); + stream.read(reinterpret_cast<char*>(buffer.get()), size); + return new EthosU::Network(device, buffer.get(), size); } -} -%extend Network { + %buffer_in(const unsigned char* networkData, size_t networkSize, BUFFER_FLAG_RO); + Network(const Device &device, const unsigned char* networkData, size_t networkSize) + { + if(networkData == nullptr){ + throw EthosU::Exception(std::string("Failed to create the network, networkData is nullptr.").c_str()); + } + + if(networkSize == 0U){ + throw EthosU::Exception(std::string("Failed to create the network, networkSize is zero.").c_str()); + } + + return new EthosU::Network(device, networkData, networkSize); + } + %clear_buffer_in(const unsigned char* networkData, size_t networkSize); + Network(const Device &device, const unsigned int index) { - auto network = new EthosU::Network(device, index); - return network; + return new EthosU::Network(device, index); } } diff --git a/driver_library/python/src/ethosu_driver/swig/typemaps/buffer.i b/driver_library/python/src/ethosu_driver/swig/typemaps/buffer.i index 13b7909..bb4627c 100644 --- a/driver_library/python/src/ethosu_driver/swig/typemaps/buffer.i +++ b/driver_library/python/src/ethosu_driver/swig/typemaps/buffer.i @@ -1,19 +1,25 @@ // -// SPDX-FileCopyrightText: Copyright 2021-2022 Arm Limited and/or its affiliates <open-source-office@arm.com> +// SPDX-FileCopyrightText: Copyright 2021-2023 Arm Limited and/or its affiliates <open-source-office@arm.com> // SPDX-License-Identifier: Apache-2.0 // -%define %mutable_buffer(TYPEMAP, SIZE) + +%define BUFFER_FLAG_RO 0 %enddef +%define BUFFER_FLAG_RW PyBUF_WRITABLE %enddef + +%define %buffer_in(TYPEMAP, SIZE, FLAG) %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); + + int res = PyObject_GetBuffer($input, &view, FLAG); if (res < 0) { PyErr_Clear(); %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum); } + + void *buf = view.buf; + size_t size = view.len; + PyBuffer_Release(&view); + $1 = ($1_ltype) buf; $2 = ($2_ltype) size; } @@ -23,12 +29,11 @@ } %enddef -%define %clear_mutable_buffer(TYPEMAP, SIZE) +%define %clear_buffer_in(TYPEMAP, SIZE) %typemap(in) (TYPEMAP, SIZE); %typemap(typecheck) (TYPEMAP, SIZE); %enddef - %define %driver_buffer_out %typemap(out) (char*) { auto size = arg1->size(); diff --git a/driver_library/python/test/test_driver.py b/driver_library/python/test/test_driver.py index 0dd207f..e9cb5c8 100644 --- a/driver_library/python/test/test_driver.py +++ b/driver_library/python/test/test_driver.py @@ -15,11 +15,14 @@ def device(device_name): @pytest.fixture() -def network_buffer(device, model_name, shared_data_folder): +def network_file(model_name, shared_data_folder): network_file = os.path.join(shared_data_folder, model_name) - network_buffer = driver.Buffer(device, network_file) - yield network_buffer + yield network_file +@pytest.fixture() +def network(device, network_file): + network = driver.Network(device, network_file) + yield network @pytest.mark.parametrize('device_name', ['ethosu0']) def test_check_device_swig_ownership(device): @@ -44,12 +47,33 @@ def test_device_wrong_name(device_name): @pytest.mark.parametrize('device_name', ['ethosu0']) -def test_driver_network_filenotfound_exception(device, shared_data_folder): +@pytest.mark.parametrize('model_name', ['model.tflite']) +def test_driver_network_from_bytearray(device, network_file): + network_data = None + with open(network_file, 'rb') as file: + network_data = file.read() + network = driver.Network(device, network_data) - network_file = os.path.join(shared_data_folder, "some_unknown_model.tflite") +@pytest.mark.parametrize('device_name', ['ethosu0']) +def test_driver_network_from_empty_bytearray(device): with pytest.raises(RuntimeError) as err: - network_buffer = driver.Buffer(device, network_file) + network = driver.Network(device, bytearray()) + + assert 'Failed to create the network, networkSize is zero' in str(err.value) + + +@pytest.mark.parametrize('device_name', ['ethosu0']) +@pytest.mark.parametrize('model_name', ['model.tflite']) +def test_driver_network_from_file(device, network_file): + network = driver.Network(device, network_file) + + +@pytest.mark.parametrize('device_name', ['ethosu0']) +@pytest.mark.parametrize('model_name', ['some_unknown_model.tflite']) +def test_driver_network_filenotfound_exception(device, network_file): + with pytest.raises(RuntimeError) as err: + network = driver.Network(device, network_file) # Only check for part of the exception since the exception returns # absolute path which will change on different machines. @@ -58,57 +82,51 @@ def test_driver_network_filenotfound_exception(device, shared_data_folder): @pytest.mark.parametrize('device_name', ['ethosu0']) @pytest.mark.parametrize('model_name', ['model.tflite']) -def test_check_buffer_swig_ownership(network_buffer): +def test_check_network_swig_ownership(network): # Check to see that SWIG has ownership for parser. This instructs SWIG to take # ownership of the return value. This allows the value to be automatically # garbage-collected when it is no longer in use - assert network_buffer.thisown + assert network.thisown @pytest.mark.parametrize('device_name', ['ethosu0']) @pytest.mark.parametrize('model_name', ['model.tflite']) -def test_check_buffer_size(network_buffer): - assert network_buffer.size() > 0 +def test_check_network_ifm_size(device, network): + assert network.getIfmSize() > 0 @pytest.mark.parametrize('device_name', ['ethosu0']) @pytest.mark.parametrize('model_name', ['model.tflite']) -def test_check_buffer_clear(network_buffer): - network_buffer.clear() - for i in range(network_buffer.size()): - assert network_buffer.data()[i] == 0 +def test_check_network_ofm_size(device, network): + assert network.getOfmSize() > 0 @pytest.mark.parametrize('device_name', ['ethosu0']) -@pytest.mark.parametrize('model_name', ['model.tflite']) -def test_check_buffer_getFd(network_buffer): - assert network_buffer.getFd() >= 0 +def test_check_buffer_swig_ownership(device): + buffer = driver.Buffer(device, 1024) + assert buffer.thisown @pytest.mark.parametrize('device_name', ['ethosu0']) -@pytest.mark.parametrize('model_name', ['model.tflite']) -def test_check_network_ifm_size(device, network_buffer): - network = driver.Network(device, network_buffer) - assert network.getIfmSize() > 0 - assert network_buffer.thisown - - -@pytest.mark.parametrize('device_name', [('ethosu0')]) -def test_check_network_buffer_none(device): +def test_check_buffer_getFd(device): + buffer = driver.Buffer(device, 1024) + assert buffer.getFd() >= 0 - with pytest.raises(RuntimeError) as err: - driver.Network(device, None) - # Only check for part of the exception since the exception returns - # absolute path which will change on different machines. - assert 'Failed to create the network' in str(err.value) +@pytest.mark.parametrize('device_name', ['ethosu0']) +def test_check_buffer_size(device): + buffer = driver.Buffer(device, 1024) + assert buffer.size() == 1024 @pytest.mark.parametrize('device_name', ['ethosu0']) @pytest.mark.parametrize('model_name', ['model.tflite']) -def test_check_network_ofm_size(device, network_buffer): - network = driver.Network(device, network_buffer) - assert network.getOfmSize() > 0 +def test_check_buffer_clear(device, network_file): + buffer = driver.Buffer(device, network_file) + + buffer.clear() + for i in range(buffer.size()): + assert buffer.data()[i] == 0 def test_getMaxPmuEventCounters(): diff --git a/driver_library/src/ethosu.cpp b/driver_library/src/ethosu.cpp index 3c7dc31..7aec696 100644 --- a/driver_library/src/ethosu.cpp +++ b/driver_library/src/ethosu.cpp @@ -333,12 +333,13 @@ int Buffer::getFd() const { * Network ****************************************************************************/ -Network::Network(const Device &device, shared_ptr<Buffer> &buffer) : fd(-1), buffer(buffer) { +Network::Network(const Device &device, const unsigned char *networkData, size_t networkSize) : fd(-1) { // Create buffer handle ethosu_uapi_network_create uapi; - uapi.type = ETHOSU_UAPI_NETWORK_BUFFER; - uapi.fd = buffer->getFd(); - fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast<void *>(&uapi)); + uapi.type = ETHOSU_UAPI_NETWORK_USER_BUFFER; + uapi.network.data_ptr = reinterpret_cast<uintptr_t>(networkData); + uapi.network.size = networkSize; + fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast<void *>(&uapi)); try { collectNetworkInfo(); } catch (std::exception &e) { @@ -348,7 +349,7 @@ Network::Network(const Device &device, shared_ptr<Buffer> &buffer) : fd(-1), buf throw; } - Log(Severity::Info) << "Network(" << &device << ", " << &*buffer << "), this=" << this << ", fd=" << fd << endl; + Log(Severity::Info) << "Network(" << &device << "), this=" << this << ", fd=" << fd << endl; } Network::Network(const Device &device, const unsigned index) : fd(-1) { @@ -391,10 +392,6 @@ int Network::ioctl(unsigned long cmd, void *data) { return eioctl(fd, cmd, data); } -shared_ptr<Buffer> Network::getBuffer() { - return buffer; -} - const std::vector<size_t> &Network::getIfmDims() const { return ifmDims; } |