blob: 43300d3f0f3d4b0b97ce3243e19e800ae5d0f5c4 [file] [log] [blame]
Davide Grohmannf0364232022-06-16 17:42:58 +02001/*
2 * Copyright (c) 2022 Arm Limited.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the License); you may
7 * not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#include <ethosu.hpp>
20#include <uapi/ethosu.h>
21
22#include <cstring>
23#include <iostream>
24#include <list>
25#include <memory>
26#include <sstream>
27#include <stdio.h>
28#include <string>
29#include <unistd.h>
30
31#include "input.h"
32#include "model.h"
33#include "output.h"
34
35#define TEST_ASSERT(v) \
36 do { \
37 if (!(v)) { \
38 throw TestFailureException(__FILE__, ":", __LINE__, " ERROR test failed: '", #v, "'"); \
39 } \
40 } while (0)
41
42#define FAIL() TEST_ASSERT(false)
43
44using namespace EthosU;
45
46namespace {
47
48int64_t defaultTimeout = 60000000000;
49
50template <typename... Args>
51std::string string_format(std::ostringstream &stringStream) {
52 return stringStream.str();
53}
54
55template <typename T, typename... Args>
56std::string string_format(std::ostringstream &stringStream, T t, Args... args) {
57 stringStream << t;
58 return string_format(stringStream, args...);
59}
60
61class TestFailureException : public std::exception {
62public:
63 template <typename... Args>
64 TestFailureException(const char *msg, Args... args) {
65 std::ostringstream stringStream;
66 this->msg = string_format(stringStream, msg, args...);
67 }
68 const char *what() const throw() {
69 return msg.c_str();
70 }
71
72private:
73 std::string msg;
74};
75
76void testPing(const Device &device) {
77 int r;
78 try {
79 r = device.ioctl(ETHOSU_IOCTL_PING);
80 } catch (std::exception &e) { throw TestFailureException("Ping test: ", e.what()); }
81
82 TEST_ASSERT(r == 0);
83}
84
85void testVersion(const Device &device) {
86 int r;
87 try {
88 r = device.ioctl(ETHOSU_IOCTL_VERSION_REQ);
89 } catch (std::exception &e) { throw TestFailureException("Version test: ", e.what()); }
90
91 TEST_ASSERT(r == 0);
92}
93
94void testCapabilties(const Device &device) {
95 Capabilities capabilities;
96 try {
97 capabilities = device.capabilities();
98 } catch (std::exception &e) { throw TestFailureException("Capabilities test: ", e.what()); }
99
100 TEST_ASSERT(capabilities.hwId.architecture > SemanticVersion());
101}
102
103void testNetworkInfoNotExistentIndex(const Device &device) {
104 try {
105 Network(device, 0);
106 FAIL();
107 } catch (Exception &e) {
108 // good it should have thrown
109 } catch (std::exception &e) { throw TestFailureException("NetworkInfo no index test: ", e.what()); }
110}
111
112void testNetworkInfoBuffer(const Device &device) {
113 try {
114 std::shared_ptr<Buffer> buffer = std::make_shared<Buffer>(device, sizeof(networkModelData));
115 buffer->resize(sizeof(networkModelData));
116 std::memcpy(buffer->data(), networkModelData, sizeof(networkModelData));
117 Network network(device, buffer);
118
119 TEST_ASSERT(network.getIfmDims().size() == 1);
120 TEST_ASSERT(network.getOfmDims().size() == 1);
121 } catch (std::exception &e) { throw TestFailureException("NetworkInfo buffer test: ", e.what()); }
122}
123
124void testNetworkInfoUnparsableBuffer(const Device &device) {
125 try {
126 auto buffer = std::make_shared<Buffer>(device, sizeof(networkModelData) / 4);
127 buffer->resize(sizeof(networkModelData) / 4);
128 std::memcpy(buffer->data(), networkModelData + sizeof(networkModelData) / 4, sizeof(networkModelData) / 4);
129
130 try {
131 Network network(device, buffer);
132 FAIL();
133 } catch (Exception) {
134 // good, it should have thrown!
135 }
136 } catch (std::exception &e) { throw TestFailureException("NetworkInfo unparsable buffer test: ", e.what()); }
137}
138
139void testRunInferenceBuffer(const Device &device) {
140 try {
141 auto networkBuffer = std::make_shared<Buffer>(device, sizeof(networkModelData));
142 networkBuffer->resize(sizeof(networkModelData));
143 std::memcpy(networkBuffer->data(), networkModelData, sizeof(networkModelData));
144 auto network = std::make_shared<Network>(device, networkBuffer);
145
146 std::vector<std::shared_ptr<Buffer>> inputBuffers;
147 std::vector<std::shared_ptr<Buffer>> outputBuffers;
148
149 auto inputBuffer = std::make_shared<Buffer>(device, sizeof(inputData));
150 inputBuffer->resize(sizeof(inputData));
151 std::memcpy(inputBuffer->data(), inputData, sizeof(inputData));
152
153 inputBuffers.push_back(inputBuffer);
154 outputBuffers.push_back(std::make_shared<Buffer>(device, sizeof(expectedOutputData)));
155 std::vector<uint8_t> enabledCounters(Inference::getMaxPmuEventCounters());
156
157 auto inference = std::make_shared<Inference>(network,
158 inputBuffers.begin(),
159 inputBuffers.end(),
160 outputBuffers.begin(),
161 outputBuffers.end(),
162 enabledCounters,
163 false);
164
165 bool timedout = inference->wait(defaultTimeout);
166 TEST_ASSERT(!timedout);
167
168 TEST_ASSERT(std::memcmp(expectedOutputData, outputBuffers[0]->data(), sizeof(expectedOutputData)) == 0);
169
170 } catch (std::exception &e) { throw TestFailureException("Inference run test: ", e.what()); }
171}
172
173} // namespace
174
175int main() {
176 Device device;
177
178 try {
179 testPing(device);
180 testVersion(device);
181 testCapabilties(device);
182 testNetworkInfoNotExistentIndex(device);
183 testNetworkInfoBuffer(device);
184 testNetworkInfoUnparsableBuffer(device);
185 testRunInferenceBuffer(device);
186 } catch (TestFailureException &e) {
187 std::cerr << "Test failure: " << e.what() << std::endl;
188 return 1;
189 }
190
191 return 0;
192}