blob: 5e529e60c235548594b36268b933f384d5a6b5f4 [file] [log] [blame]
Davide Grohmannf0364232022-06-16 17:42:58 +02001/*
Mikael Olssondc18cea2024-02-16 11:04:46 +01002 * SPDX-FileCopyrightText: Copyright 2022-2024 Arm Limited and/or its affiliates <open-source-office@arm.com>
Davide Grohmannf0364232022-06-16 17:42:58 +02003 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the License); you may
6 * not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include <ethosu.hpp>
19#include <uapi/ethosu.h>
20
21#include <cstring>
Mikael Olsson07545152023-10-17 13:05:38 +020022#include <errno.h>
Davide Grohmannf0364232022-06-16 17:42:58 +020023#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"
Davide Grohmann6d2e5b72022-08-24 17:01:40 +020034#include "test_assertions.hpp"
Davide Grohmannf0364232022-06-16 17:42:58 +020035
36using namespace EthosU;
37
38namespace {
39
40int64_t defaultTimeout = 60000000000;
41
Davide Grohmannf0364232022-06-16 17:42:58 +020042void testPing(const Device &device) {
43 int r;
44 try {
45 r = device.ioctl(ETHOSU_IOCTL_PING);
46 } catch (std::exception &e) { throw TestFailureException("Ping test: ", e.what()); }
47
48 TEST_ASSERT(r == 0);
49}
50
Mikael Olsson8f918c62023-10-12 15:30:32 +020051void testDriverVersion(const Device &device) {
52 int r;
53 struct ethosu_uapi_kernel_driver_version version = {};
54 try {
55 r = device.ioctl(ETHOSU_IOCTL_DRIVER_VERSION_GET, &version);
56 } catch (std::exception &e) { throw TestFailureException("Driver version test: ", e.what()); }
57
58 TEST_ASSERT(r == 0);
59 TEST_ASSERT(version.major == ETHOSU_KERNEL_DRIVER_VERSION_MAJOR);
60 TEST_ASSERT(version.minor == ETHOSU_KERNEL_DRIVER_VERSION_MINOR);
61 TEST_ASSERT(version.patch == ETHOSU_KERNEL_DRIVER_VERSION_PATCH);
62}
63
Davide Grohmannf0364232022-06-16 17:42:58 +020064void testCapabilties(const Device &device) {
65 Capabilities capabilities;
66 try {
67 capabilities = device.capabilities();
68 } catch (std::exception &e) { throw TestFailureException("Capabilities test: ", e.what()); }
69
70 TEST_ASSERT(capabilities.hwId.architecture > SemanticVersion());
Mikael Olssondc18cea2024-02-16 11:04:46 +010071 TEST_ASSERT(capabilities.hwCfg.type == HardwareConfiguration::DeviceType::SUBSYSTEM);
Davide Grohmannf0364232022-06-16 17:42:58 +020072}
73
Mikael Olsson07545152023-10-17 13:05:38 +020074void testBufferSeek(const Device &device) {
75 try {
76 Buffer buf{device, 1024};
77
78 // SEEK_END should return the size of the buffer
79 TEST_ASSERT(lseek(buf.getFd(), 0, SEEK_END) == 1024);
80
81 // SEEK_SET is supported when moving the file pointer to the start
82 TEST_ASSERT(lseek(buf.getFd(), 0, SEEK_SET) == 0);
83
84 // SEEK_CUR is not supported
85 errno = 0;
86 TEST_ASSERT(lseek(buf.getFd(), 0, SEEK_CUR) == -1);
87 TEST_ASSERT(errno == EINVAL);
88
89 // Non-zero offset is not supported
90 errno = 0;
91 TEST_ASSERT(lseek(buf.getFd(), 1, SEEK_CUR) == -1);
92 TEST_ASSERT(errno == EINVAL);
93
94 errno = 0;
95 TEST_ASSERT(lseek(buf.getFd(), 2, SEEK_END) == -1);
96 TEST_ASSERT(errno == EINVAL);
97
98 errno = 0;
99 TEST_ASSERT(lseek(buf.getFd(), 3, SEEK_SET) == -1);
100 TEST_ASSERT(errno == EINVAL);
101 } catch (std::exception &e) { throw TestFailureException("Buffer seek test: ", e.what()); }
102}
103
Davide Grohmannf0364232022-06-16 17:42:58 +0200104void testNetworkInfoNotExistentIndex(const Device &device) {
105 try {
106 Network(device, 0);
107 FAIL();
108 } catch (Exception &e) {
109 // good it should have thrown
110 } catch (std::exception &e) { throw TestFailureException("NetworkInfo no index test: ", e.what()); }
111}
112
113void testNetworkInfoBuffer(const Device &device) {
114 try {
Mikael Olssonc081e592023-10-30 11:10:56 +0100115 Network network(device, networkModelData, sizeof(networkModelData));
Davide Grohmannf0364232022-06-16 17:42:58 +0200116 TEST_ASSERT(network.getIfmDims().size() == 1);
117 TEST_ASSERT(network.getOfmDims().size() == 1);
118 } catch (std::exception &e) { throw TestFailureException("NetworkInfo buffer test: ", e.what()); }
119}
120
121void testNetworkInfoUnparsableBuffer(const Device &device) {
122 try {
Davide Grohmannf0364232022-06-16 17:42:58 +0200123 try {
Mikael Olssonc081e592023-10-30 11:10:56 +0100124 Network network(device, networkModelData + sizeof(networkModelData) / 4, sizeof(networkModelData) / 4);
Davide Grohmannf0364232022-06-16 17:42:58 +0200125 FAIL();
126 } catch (Exception) {
127 // good, it should have thrown!
128 }
129 } catch (std::exception &e) { throw TestFailureException("NetworkInfo unparsable buffer test: ", e.what()); }
130}
131
Mikael Olsson45d47992023-10-12 15:32:56 +0200132void testNetworkInvalidType(const Device &device) {
Mikael Olssonb2f4a2c2024-04-04 15:27:50 +0200133 const std::string expected_error = std::string("IOCTL cmd=NETWORK_CREATE") + " failed: " + std::strerror(EINVAL);
Mikael Olsson45d47992023-10-12 15:32:56 +0200134 struct ethosu_uapi_network_create net_req = {};
135 net_req.type = ETHOSU_UAPI_NETWORK_INDEX + 1;
136 try {
137 int r = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, &net_req);
138 FAIL();
139 } catch (Exception &e) {
140 // The call is expected to throw
141 TEST_ASSERT(expected_error.compare(e.what()) == 0);
142 } catch (std::exception &e) { throw TestFailureException("NetworkCreate invalid type test: ", e.what()); }
143}
144
Mikael Olssonc081e592023-10-30 11:10:56 +0100145void testNetworkInvalidDataPtr(const Device &device) {
Mikael Olssonb2f4a2c2024-04-04 15:27:50 +0200146 const std::string expected_error = std::string("IOCTL cmd=NETWORK_CREATE") + " failed: " + std::strerror(EINVAL);
Mikael Olssonc081e592023-10-30 11:10:56 +0100147 struct ethosu_uapi_network_create net_req = {};
148 net_req.type = ETHOSU_UAPI_NETWORK_USER_BUFFER;
149 net_req.network.data_ptr = 0U;
150 net_req.network.size = 128U;
151 try {
152 int r = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, &net_req);
153 FAIL();
154 } catch (Exception &e) {
155 // The call is expected to throw
156 TEST_ASSERT(expected_error.compare(e.what()) == 0);
157 } catch (std::exception &e) { throw TestFailureException("NetworkCreate invalid data ptr: ", e.what()); }
158}
159
160void testNetworkInvalidDataSize(const Device &device) {
Mikael Olssonb2f4a2c2024-04-04 15:27:50 +0200161 const std::string expected_error = std::string("IOCTL cmd=NETWORK_CREATE") + " failed: " + std::strerror(EINVAL);
Mikael Olssonc081e592023-10-30 11:10:56 +0100162 struct ethosu_uapi_network_create net_req = {};
163 net_req.type = ETHOSU_UAPI_NETWORK_USER_BUFFER;
164 net_req.network.data_ptr = reinterpret_cast<uintptr_t>(networkModelData);
165 net_req.network.size = 0U;
166 try {
167 int r = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, &net_req);
168 FAIL();
169 } catch (Exception &e) {
170 // The call is expected to throw
171 TEST_ASSERT(expected_error.compare(e.what()) == 0);
172 } catch (std::exception &e) { throw TestFailureException("NetworkCreate invalid data size: ", e.what()); }
173}
174
Davide Grohmannf0364232022-06-16 17:42:58 +0200175void testRunInferenceBuffer(const Device &device) {
176 try {
Mikael Olssonc081e592023-10-30 11:10:56 +0100177 auto network = std::make_shared<Network>(device, networkModelData, sizeof(networkModelData));
Davide Grohmannf0364232022-06-16 17:42:58 +0200178
179 std::vector<std::shared_ptr<Buffer>> inputBuffers;
180 std::vector<std::shared_ptr<Buffer>> outputBuffers;
181
182 auto inputBuffer = std::make_shared<Buffer>(device, sizeof(inputData));
Davide Grohmannf0364232022-06-16 17:42:58 +0200183 std::memcpy(inputBuffer->data(), inputData, sizeof(inputData));
184
185 inputBuffers.push_back(inputBuffer);
186 outputBuffers.push_back(std::make_shared<Buffer>(device, sizeof(expectedOutputData)));
187 std::vector<uint8_t> enabledCounters(Inference::getMaxPmuEventCounters());
188
189 auto inference = std::make_shared<Inference>(network,
190 inputBuffers.begin(),
191 inputBuffers.end(),
192 outputBuffers.begin(),
193 outputBuffers.end(),
194 enabledCounters,
195 false);
196
197 bool timedout = inference->wait(defaultTimeout);
198 TEST_ASSERT(!timedout);
199
Davide Grohmann6d2e5b72022-08-24 17:01:40 +0200200 InferenceStatus status = inference->status();
201 TEST_ASSERT(status == InferenceStatus::OK);
202
203 bool success = inference->cancel();
204 TEST_ASSERT(!success);
205
Davide Grohmannf0364232022-06-16 17:42:58 +0200206 TEST_ASSERT(std::memcmp(expectedOutputData, outputBuffers[0]->data(), sizeof(expectedOutputData)) == 0);
207
208 } catch (std::exception &e) { throw TestFailureException("Inference run test: ", e.what()); }
209}
210
211} // namespace
212
213int main() {
214 Device device;
215
216 try {
217 testPing(device);
Mikael Olsson8f918c62023-10-12 15:30:32 +0200218 testDriverVersion(device);
Davide Grohmannf0364232022-06-16 17:42:58 +0200219 testCapabilties(device);
Mikael Olsson07545152023-10-17 13:05:38 +0200220 testBufferSeek(device);
Mikael Olsson45d47992023-10-12 15:32:56 +0200221 testNetworkInvalidType(device);
Mikael Olssonc081e592023-10-30 11:10:56 +0100222 testNetworkInvalidDataPtr(device);
223 testNetworkInvalidDataSize(device);
Davide Grohmannf0364232022-06-16 17:42:58 +0200224 testNetworkInfoNotExistentIndex(device);
225 testNetworkInfoBuffer(device);
226 testNetworkInfoUnparsableBuffer(device);
227 testRunInferenceBuffer(device);
228 } catch (TestFailureException &e) {
229 std::cerr << "Test failure: " << e.what() << std::endl;
230 return 1;
231 }
232
233 return 0;
234}