aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavide Grohmann <davide.grohmann@arm.com>2022-06-16 17:42:58 +0200
committerDavide Grohmann <davide.grohmann@arm.com>2022-08-29 09:52:15 +0200
commitf03642331f1028bdeba1c24bc5d9bd65b42c7603 (patch)
treed299be4d2f9a3b5292b141d531c1a3824b7424ce
parent43e7dc41eb7f0701951ac84d82f877be37338d41 (diff)
downloadethos-u-linux-driver-stack-f03642331f1028bdeba1c24bc5d9bd65b42c7603.tar.gz
Add linux_driver_stack tests
Change-Id: I303f1424eb46576847312672f7ed5ac03c05aee1
-rw-r--r--CMakeLists.txt9
-rw-r--r--driver_library/include/ethosu.hpp11
-rw-r--r--driver_library/src/ethosu.cpp2
-rw-r--r--kernel/CMakeLists.txt2
-rw-r--r--tests/CMakeLists.txt37
-rw-r--r--tests/main.cpp192
6 files changed, 244 insertions, 9 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 603e19b..f2a121d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -46,11 +46,11 @@ if(BUILD_KERNEL)
add_subdirectory(kernel)
endif()
-if (BUILD_MAILBOX)
+if(BUILD_MAILBOX)
add_subdirectory(mailbox)
endif()
-if (BUILD_REMOTEPROC)
+if(BUILD_REMOTEPROC)
add_subdirectory(remoteproc)
endif()
@@ -59,3 +59,8 @@ add_subdirectory(driver_library)
# Build utils
add_subdirectory(utils)
+
+# Build tests
+if(ETHOSU_TARGET_NPU_CONFIG)
+ add_subdirectory(tests)
+endif()
diff --git a/driver_library/include/ethosu.hpp b/driver_library/include/ethosu.hpp
index da8dbbd..74f8abb 100644
--- a/driver_library/include/ethosu.hpp
+++ b/driver_library/include/ethosu.hpp
@@ -81,10 +81,10 @@ std::ostream &operator<<(std::ostream &out, const SemanticVersion &v);
*/
struct HardwareId {
public:
- HardwareId(uint32_t _versionStatus,
- const SemanticVersion &_version,
- const SemanticVersion &_product,
- const SemanticVersion &_architecture) :
+ HardwareId(uint32_t _versionStatus = 0,
+ const SemanticVersion &_version = SemanticVersion(),
+ const SemanticVersion &_product = SemanticVersion(),
+ const SemanticVersion &_architecture = SemanticVersion()) :
versionStatus(_versionStatus),
version(_version), product(_product), architecture(_architecture) {}
@@ -102,7 +102,7 @@ public:
*/
struct HardwareConfiguration {
public:
- HardwareConfiguration(uint32_t _macsPerClockCycle, uint32_t _cmdStreamVersion, bool _customDma) :
+ HardwareConfiguration(uint32_t _macsPerClockCycle = 0, uint32_t _cmdStreamVersion = 0, bool _customDma = false) :
macsPerClockCycle(_macsPerClockCycle), cmdStreamVersion(_cmdStreamVersion), customDma(_customDma) {}
uint32_t macsPerClockCycle;
@@ -118,6 +118,7 @@ public:
*/
class Capabilities {
public:
+ Capabilities() {}
Capabilities(const HardwareId &_hwId, const HardwareConfiguration &_hwCfg, const SemanticVersion &_driver) :
hwId(_hwId), hwCfg(_hwCfg), driver(_driver) {}
diff --git a/driver_library/src/ethosu.cpp b/driver_library/src/ethosu.cpp
index 662fed7..16b9654 100644
--- a/driver_library/src/ethosu.cpp
+++ b/driver_library/src/ethosu.cpp
@@ -489,7 +489,7 @@ bool Inference::wait(int64_t timeoutNanos) const {
// if timeout negative wait forever
if (timeoutNanos < 0) {
- return eppoll(&pfd, 1, NULL, NULL);
+ return eppoll(&pfd, 1, NULL, NULL) == 0;
}
struct timespec tmo_p;
diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt
index 6d2beb5..236b0ea 100644
--- a/kernel/CMakeLists.txt
+++ b/kernel/CMakeLists.txt
@@ -17,7 +17,7 @@
#
# SPDX-License-Identifier: GPL-2.0-only
#
-
+
cmake_minimum_required(VERSION 3.0.2)
# Set the project name and version
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 0000000..37b7d8b
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2022 Arm Limited.
+#
+# 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.
+#
+
+set(CORE_PLATFORM_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../core_platform)
+
+file(GLOB models LIST_DIRECTORIES true "${CORE_PLATFORM_PATH}/applications/baremetal/models/${ETHOSU_TARGET_NPU_CONFIG}/*")
+
+# Build executable
+foreach(model ${models})
+ get_filename_component(modelname ${model} NAME)
+
+ add_executable(lds_${modelname}_tests "main.cpp")
+
+ target_include_directories(lds_${modelname}_tests PRIVATE
+ ${model})
+
+ # Link agains ethosu library
+ target_link_libraries(lds_${modelname}_tests PRIVATE ethosu)
+
+ # Install target
+ install(TARGETS lds_${modelname}_tests DESTINATION "bin")
+endforeach()
diff --git a/tests/main.cpp b/tests/main.cpp
new file mode 100644
index 0000000..43300d3
--- /dev/null
+++ b/tests/main.cpp
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2022 Arm Limited.
+ *
+ * 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 <cstring>
+#include <iostream>
+#include <list>
+#include <memory>
+#include <sstream>
+#include <stdio.h>
+#include <string>
+#include <unistd.h>
+
+#include "input.h"
+#include "model.h"
+#include "output.h"
+
+#define TEST_ASSERT(v) \
+ do { \
+ if (!(v)) { \
+ throw TestFailureException(__FILE__, ":", __LINE__, " ERROR test failed: '", #v, "'"); \
+ } \
+ } while (0)
+
+#define FAIL() TEST_ASSERT(false)
+
+using namespace EthosU;
+
+namespace {
+
+int64_t defaultTimeout = 60000000000;
+
+template <typename... Args>
+std::string string_format(std::ostringstream &stringStream) {
+ return stringStream.str();
+}
+
+template <typename T, typename... Args>
+std::string string_format(std::ostringstream &stringStream, T t, Args... args) {
+ stringStream << t;
+ return string_format(stringStream, args...);
+}
+
+class TestFailureException : public std::exception {
+public:
+ template <typename... Args>
+ TestFailureException(const char *msg, Args... args) {
+ std::ostringstream stringStream;
+ this->msg = string_format(stringStream, msg, args...);
+ }
+ const char *what() const throw() {
+ return msg.c_str();
+ }
+
+private:
+ std::string msg;
+};
+
+void testPing(const Device &device) {
+ int r;
+ try {
+ r = device.ioctl(ETHOSU_IOCTL_PING);
+ } catch (std::exception &e) { throw TestFailureException("Ping test: ", e.what()); }
+
+ TEST_ASSERT(r == 0);
+}
+
+void testVersion(const Device &device) {
+ int r;
+ try {
+ r = device.ioctl(ETHOSU_IOCTL_VERSION_REQ);
+ } catch (std::exception &e) { throw TestFailureException("Version test: ", e.what()); }
+
+ TEST_ASSERT(r == 0);
+}
+
+void testCapabilties(const Device &device) {
+ Capabilities capabilities;
+ try {
+ capabilities = device.capabilities();
+ } catch (std::exception &e) { throw TestFailureException("Capabilities test: ", e.what()); }
+
+ TEST_ASSERT(capabilities.hwId.architecture > SemanticVersion());
+}
+
+void testNetworkInfoNotExistentIndex(const Device &device) {
+ try {
+ Network(device, 0);
+ FAIL();
+ } catch (Exception &e) {
+ // good it should have thrown
+ } catch (std::exception &e) { throw TestFailureException("NetworkInfo no index test: ", e.what()); }
+}
+
+void testNetworkInfoBuffer(const Device &device) {
+ try {
+ std::shared_ptr<Buffer> buffer = std::make_shared<Buffer>(device, sizeof(networkModelData));
+ buffer->resize(sizeof(networkModelData));
+ std::memcpy(buffer->data(), networkModelData, sizeof(networkModelData));
+ Network network(device, buffer);
+
+ TEST_ASSERT(network.getIfmDims().size() == 1);
+ TEST_ASSERT(network.getOfmDims().size() == 1);
+ } catch (std::exception &e) { throw TestFailureException("NetworkInfo buffer test: ", e.what()); }
+}
+
+void testNetworkInfoUnparsableBuffer(const Device &device) {
+ try {
+ auto buffer = std::make_shared<Buffer>(device, sizeof(networkModelData) / 4);
+ buffer->resize(sizeof(networkModelData) / 4);
+ std::memcpy(buffer->data(), networkModelData + sizeof(networkModelData) / 4, sizeof(networkModelData) / 4);
+
+ try {
+ Network network(device, buffer);
+ FAIL();
+ } catch (Exception) {
+ // good, it should have thrown!
+ }
+ } catch (std::exception &e) { throw TestFailureException("NetworkInfo unparsable buffer test: ", e.what()); }
+}
+
+void testRunInferenceBuffer(const Device &device) {
+ try {
+ auto networkBuffer = std::make_shared<Buffer>(device, sizeof(networkModelData));
+ networkBuffer->resize(sizeof(networkModelData));
+ std::memcpy(networkBuffer->data(), networkModelData, sizeof(networkModelData));
+ auto network = std::make_shared<Network>(device, networkBuffer);
+
+ std::vector<std::shared_ptr<Buffer>> inputBuffers;
+ std::vector<std::shared_ptr<Buffer>> outputBuffers;
+
+ auto inputBuffer = std::make_shared<Buffer>(device, sizeof(inputData));
+ inputBuffer->resize(sizeof(inputData));
+ std::memcpy(inputBuffer->data(), inputData, sizeof(inputData));
+
+ inputBuffers.push_back(inputBuffer);
+ outputBuffers.push_back(std::make_shared<Buffer>(device, sizeof(expectedOutputData)));
+ std::vector<uint8_t> enabledCounters(Inference::getMaxPmuEventCounters());
+
+ auto inference = std::make_shared<Inference>(network,
+ inputBuffers.begin(),
+ inputBuffers.end(),
+ outputBuffers.begin(),
+ outputBuffers.end(),
+ enabledCounters,
+ false);
+
+ bool timedout = inference->wait(defaultTimeout);
+ TEST_ASSERT(!timedout);
+
+ TEST_ASSERT(std::memcmp(expectedOutputData, outputBuffers[0]->data(), sizeof(expectedOutputData)) == 0);
+
+ } catch (std::exception &e) { throw TestFailureException("Inference run test: ", e.what()); }
+}
+
+} // namespace
+
+int main() {
+ Device device;
+
+ try {
+ testPing(device);
+ testVersion(device);
+ testCapabilties(device);
+ testNetworkInfoNotExistentIndex(device);
+ testNetworkInfoBuffer(device);
+ testNetworkInfoUnparsableBuffer(device);
+ testRunInferenceBuffer(device);
+ } catch (TestFailureException &e) {
+ std::cerr << "Test failure: " << e.what() << std::endl;
+ return 1;
+ }
+
+ return 0;
+}