blob: 66d6ac5cd4abb9b05bcadb738910f1794e4a947b [file] [log] [blame]
surmeh0149b9e102018-05-17 14:11:25 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
David Beck93e48982018-09-05 13:05:09 +01003// SPDX-License-Identifier: MIT
surmeh0149b9e102018-05-17 14:11:25 +01004//
5#pragma once
6
7#ifndef LOG_TAG
8#define LOG_TAG "ArmnnDriverTests"
9#endif // LOG_TAG
10
11#include "../ArmnnDriver.hpp"
12#include <iosfwd>
Nikhil Raj77605822018-09-03 11:25:56 +010013#include <boost/test/unit_test.hpp>
surmeh0149b9e102018-05-17 14:11:25 +010014
Kevin Mayec1e5b82020-02-26 17:00:39 +000015#include <android/hidl/allocator/1.0/IAllocator.h>
16
17using ::android::hidl::allocator::V1_0::IAllocator;
18
surmeh0149b9e102018-05-17 14:11:25 +010019namespace android
20{
21namespace hardware
22{
23namespace neuralnetworks
24{
25namespace V1_0
26{
27
Kevin Mayec1e5b82020-02-26 17:00:39 +000028std::ostream& operator<<(std::ostream& os, V1_0::ErrorStatus stat);
surmeh0149b9e102018-05-17 14:11:25 +010029
30} // namespace android::hardware::neuralnetworks::V1_0
31} // namespace android::hardware::neuralnetworks
32} // namespace android::hardware
33} // namespace android
34
35namespace driverTestHelpers
36{
37
Matteo Martincigh8b287c22018-09-07 09:25:10 +010038std::ostream& operator<<(std::ostream& os, V1_0::ErrorStatus stat);
surmeh0149b9e102018-05-17 14:11:25 +010039
Sadik Armagane6e54a82019-05-08 10:18:05 +010040struct ExecutionCallback : public V1_0::IExecutionCallback
surmeh0149b9e102018-05-17 14:11:25 +010041{
42 ExecutionCallback() : mNotified(false) {}
Kevin Mayec1e5b82020-02-26 17:00:39 +000043 Return<void> notify(V1_0::ErrorStatus status) override;
surmeh0149b9e102018-05-17 14:11:25 +010044 /// wait until the callback has notified us that it is done
45 Return<void> wait();
46
47private:
48 // use a mutex and a condition variable to wait for asynchronous callbacks
49 std::mutex mMutex;
50 std::condition_variable mCondition;
51 // and a flag, in case we are notified before the wait call
52 bool mNotified;
53};
54
Sadik Armagane6e54a82019-05-08 10:18:05 +010055class PreparedModelCallback : public V1_0::IPreparedModelCallback
surmeh0149b9e102018-05-17 14:11:25 +010056{
57public:
58 PreparedModelCallback()
Kevin Mayec1e5b82020-02-26 17:00:39 +000059 : m_ErrorStatus(V1_0::ErrorStatus::NONE)
surmeh0149b9e102018-05-17 14:11:25 +010060 , m_PreparedModel()
61 { }
62 ~PreparedModelCallback() override { }
63
Kevin Mayec1e5b82020-02-26 17:00:39 +000064 Return<void> notify(V1_0::ErrorStatus status,
Sadik Armagane6e54a82019-05-08 10:18:05 +010065 const android::sp<V1_0::IPreparedModel>& preparedModel) override;
Kevin Mayec1e5b82020-02-26 17:00:39 +000066 V1_0::ErrorStatus GetErrorStatus() { return m_ErrorStatus; }
Sadik Armagane6e54a82019-05-08 10:18:05 +010067 android::sp<V1_0::IPreparedModel> GetPreparedModel() { return m_PreparedModel; }
surmeh0149b9e102018-05-17 14:11:25 +010068
69private:
Kevin Mayec1e5b82020-02-26 17:00:39 +000070 V1_0::ErrorStatus m_ErrorStatus;
Sadik Armagane6e54a82019-05-08 10:18:05 +010071 android::sp<V1_0::IPreparedModel> m_PreparedModel;
surmeh0149b9e102018-05-17 14:11:25 +010072};
73
Ferran Balaguerb2397fd2019-07-25 12:12:39 +010074#ifdef ARMNN_ANDROID_NN_V1_2
75
76class PreparedModelCallback_1_2 : public V1_2::IPreparedModelCallback
77{
78public:
79 PreparedModelCallback_1_2()
Kevin Mayec1e5b82020-02-26 17:00:39 +000080 : m_ErrorStatus(V1_0::ErrorStatus::NONE)
Ferran Balaguerb2397fd2019-07-25 12:12:39 +010081 , m_PreparedModel()
82 , m_PreparedModel_1_2()
83 { }
84 ~PreparedModelCallback_1_2() override { }
85
Kevin Mayec1e5b82020-02-26 17:00:39 +000086 Return<void> notify(V1_0::ErrorStatus status, const android::sp<V1_0::IPreparedModel>& preparedModel) override;
Ferran Balaguerb2397fd2019-07-25 12:12:39 +010087
Kevin Mayec1e5b82020-02-26 17:00:39 +000088 Return<void> notify_1_2(V1_0::ErrorStatus status, const android::sp<V1_2::IPreparedModel>& preparedModel) override;
Ferran Balaguerb2397fd2019-07-25 12:12:39 +010089
Kevin Mayec1e5b82020-02-26 17:00:39 +000090 V1_0::ErrorStatus GetErrorStatus() { return m_ErrorStatus; }
Ferran Balaguerb2397fd2019-07-25 12:12:39 +010091
92 android::sp<V1_0::IPreparedModel> GetPreparedModel() { return m_PreparedModel; }
93
94 android::sp<V1_2::IPreparedModel> GetPreparedModel_1_2() { return m_PreparedModel_1_2; }
95
96private:
Kevin Mayec1e5b82020-02-26 17:00:39 +000097 V1_0::ErrorStatus m_ErrorStatus;
Ferran Balaguerb2397fd2019-07-25 12:12:39 +010098 android::sp<V1_0::IPreparedModel> m_PreparedModel;
99 android::sp<V1_2::IPreparedModel> m_PreparedModel_1_2;
100};
101
102#endif
103
surmeh0149b9e102018-05-17 14:11:25 +0100104hidl_memory allocateSharedMemory(int64_t size);
105
Ellen Norris-Thompson976ad3e2019-08-21 15:21:14 +0100106template<typename T>
Kevin Mayec1e5b82020-02-26 17:00:39 +0000107android::sp<IMemory> AddPoolAndGetData(uint32_t size, V1_0::Request& request)
Ellen Norris-Thompson976ad3e2019-08-21 15:21:14 +0100108{
109 hidl_memory pool;
surmeh0149b9e102018-05-17 14:11:25 +0100110
Ellen Norris-Thompson976ad3e2019-08-21 15:21:14 +0100111 android::sp<IAllocator> allocator = IAllocator::getService("ashmem");
112 allocator->allocate(sizeof(T) * size, [&](bool success, const hidl_memory& mem) {
113 BOOST_TEST(success);
114 pool = mem;
115 });
116
117 request.pools.resize(request.pools.size() + 1);
118 request.pools[request.pools.size() - 1] = pool;
119
120 android::sp<IMemory> mapped = mapMemory(pool);
121 mapped->update();
122 return mapped;
123}
124
125template<typename T>
Kevin Mayec1e5b82020-02-26 17:00:39 +0000126void AddPoolAndSetData(uint32_t size, V1_0::Request& request, const T* data)
Ellen Norris-Thompson976ad3e2019-08-21 15:21:14 +0100127{
128 android::sp<IMemory> memory = AddPoolAndGetData<T>(size, request);
129
130 T* dst = static_cast<T*>(static_cast<void*>(memory->getPointer()));
131
132 memcpy(dst, data, size * sizeof(T));
133}
surmeh0149b9e102018-05-17 14:11:25 +0100134
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100135template<typename HalPolicy,
136 typename HalModel = typename HalPolicy::Model,
137 typename HalOperand = typename HalPolicy::Operand>
138void AddOperand(HalModel& model, const HalOperand& op)
Nikhil Raj77605822018-09-03 11:25:56 +0100139{
140 model.operands.resize(model.operands.size() + 1);
141 model.operands[model.operands.size() - 1] = op;
142}
surmeh0149b9e102018-05-17 14:11:25 +0100143
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100144template<typename HalPolicy, typename HalModel = typename HalPolicy::Model>
David Monahanc60d0fd2020-05-19 14:58:34 +0100145void AddIntOperand(HalModel& model, int32_t value, uint32_t numberOfConsumers = 1)
Nikhil Raj77605822018-09-03 11:25:56 +0100146{
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100147 using HalOperand = typename HalPolicy::Operand;
148 using HalOperandType = typename HalPolicy::OperandType;
149 using HalOperandLifeTime = typename HalPolicy::OperandLifeTime;
150
Nikhil Raj77605822018-09-03 11:25:56 +0100151 DataLocation location = {};
152 location.offset = model.operandValues.size();
153 location.length = sizeof(int32_t);
154
David Monahanc60d0fd2020-05-19 14:58:34 +0100155 HalOperand op = {};
156 op.type = HalOperandType::INT32;
157 op.dimensions = hidl_vec<uint32_t>{};
158 op.lifetime = HalOperandLifeTime::CONSTANT_COPY;
159 op.location = location;
160 op.numberOfConsumers = numberOfConsumers;
Nikhil Raj77605822018-09-03 11:25:56 +0100161
162 model.operandValues.resize(model.operandValues.size() + location.length);
163 *reinterpret_cast<int32_t*>(&model.operandValues[location.offset]) = value;
164
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100165 AddOperand<HalPolicy>(model, op);
166}
167
168template<typename HalPolicy, typename HalModel = typename HalPolicy::Model>
David Monahanc60d0fd2020-05-19 14:58:34 +0100169void AddBoolOperand(HalModel& model, bool value, uint32_t numberOfConsumers = 1)
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100170{
171 using HalOperand = typename HalPolicy::Operand;
172 using HalOperandType = typename HalPolicy::OperandType;
173 using HalOperandLifeTime = typename HalPolicy::OperandLifeTime;
174
175 DataLocation location = {};
176 location.offset = model.operandValues.size();
177 location.length = sizeof(uint8_t);
178
David Monahanc60d0fd2020-05-19 14:58:34 +0100179 HalOperand op = {};
180 op.type = HalOperandType::BOOL;
181 op.dimensions = hidl_vec<uint32_t>{};
182 op.lifetime = HalOperandLifeTime::CONSTANT_COPY;
183 op.location = location;
184 op.numberOfConsumers = numberOfConsumers;
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100185
186 model.operandValues.resize(model.operandValues.size() + location.length);
187 *reinterpret_cast<uint8_t*>(&model.operandValues[location.offset]) = static_cast<uint8_t>(value);
188
Nikhil Raj77605822018-09-03 11:25:56 +0100189 AddOperand<HalModel>(model, op);
190}
surmeh0149b9e102018-05-17 14:11:25 +0100191
192template<typename T>
193OperandType TypeToOperandType();
194
195template<>
196OperandType TypeToOperandType<float>();
197
198template<>
199OperandType TypeToOperandType<int32_t>();
200
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100201template<typename HalPolicy,
202 typename T,
203 typename HalModel = typename HalPolicy::Model,
204 typename HalOperandType = typename HalPolicy::OperandType,
205 typename HalOperandLifeTime = typename HalPolicy::OperandLifeTime>
Nikhil Raj77605822018-09-03 11:25:56 +0100206void AddTensorOperand(HalModel& model,
Matteo Martincighc7434122018-11-14 12:27:04 +0000207 const hidl_vec<uint32_t>& dimensions,
208 const T* values,
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100209 HalOperandType operandType = HalOperandType::TENSOR_FLOAT32,
Kevin Mayec1e5b82020-02-26 17:00:39 +0000210 HalOperandLifeTime operandLifeTime = V1_0::OperandLifeTime::CONSTANT_COPY,
Ellen Norris-Thompson976ad3e2019-08-21 15:21:14 +0100211 double scale = 0.f,
David Monahanc60d0fd2020-05-19 14:58:34 +0100212 int offset = 0,
213 uint32_t numberOfConsumers = 1)
surmeh0149b9e102018-05-17 14:11:25 +0100214{
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100215 using HalOperand = typename HalPolicy::Operand;
216
surmeh0149b9e102018-05-17 14:11:25 +0100217 uint32_t totalElements = 1;
218 for (uint32_t dim : dimensions)
219 {
220 totalElements *= dim;
221 }
222
223 DataLocation location = {};
surmeh0149b9e102018-05-17 14:11:25 +0100224 location.length = totalElements * sizeof(T);
225
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100226 if(operandLifeTime == HalOperandLifeTime::CONSTANT_COPY)
Kevin Mayf29a2c52019-03-14 11:56:32 +0000227 {
228 location.offset = model.operandValues.size();
229 }
230
David Monahanc60d0fd2020-05-19 14:58:34 +0100231 HalOperand op = {};
232 op.type = operandType;
233 op.dimensions = dimensions;
234 op.scale = scale;
235 op.zeroPoint = offset;
236 op.lifetime = HalOperandLifeTime::CONSTANT_COPY;
237 op.location = location;
238 op.numberOfConsumers = numberOfConsumers;
surmeh0149b9e102018-05-17 14:11:25 +0100239
240 model.operandValues.resize(model.operandValues.size() + location.length);
241 for (uint32_t i = 0; i < totalElements; i++)
242 {
243 *(reinterpret_cast<T*>(&model.operandValues[location.offset]) + i) = values[i];
244 }
245
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100246 AddOperand<HalPolicy>(model, op);
surmeh0149b9e102018-05-17 14:11:25 +0100247}
248
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100249template<typename HalPolicy,
250 typename T,
251 typename HalModel = typename HalPolicy::Model,
252 typename HalOperandType = typename HalPolicy::OperandType,
253 typename HalOperandLifeTime = typename HalPolicy::OperandLifeTime>
Matteo Martincighc7434122018-11-14 12:27:04 +0000254void AddTensorOperand(HalModel& model,
255 const hidl_vec<uint32_t>& dimensions,
256 const std::vector<T>& values,
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100257 HalOperandType operandType = HalPolicy::OperandType::TENSOR_FLOAT32,
Kevin Mayec1e5b82020-02-26 17:00:39 +0000258 HalOperandLifeTime operandLifeTime = V1_0::OperandLifeTime::CONSTANT_COPY,
Ellen Norris-Thompson976ad3e2019-08-21 15:21:14 +0100259 double scale = 0.f,
David Monahanc60d0fd2020-05-19 14:58:34 +0100260 int offset = 0,
261 uint32_t numberOfConsumers = 1)
Matteo Martincighc7434122018-11-14 12:27:04 +0000262{
David Monahanc60d0fd2020-05-19 14:58:34 +0100263 AddTensorOperand<HalPolicy, T>(model,
264 dimensions,
265 values.data(),
266 operandType,
267 operandLifeTime,
268 scale,
269 offset,
270 numberOfConsumers);
Matteo Martincighc7434122018-11-14 12:27:04 +0000271}
272
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100273template<typename HalPolicy,
274 typename HalModel = typename HalPolicy::Model,
275 typename HalOperandType = typename HalPolicy::OperandType>
Nikhil Raj77605822018-09-03 11:25:56 +0100276void AddInputOperand(HalModel& model,
Matteo Martincighc7434122018-11-14 12:27:04 +0000277 const hidl_vec<uint32_t>& dimensions,
Ellen Norris-Thompson976ad3e2019-08-21 15:21:14 +0100278 HalOperandType operandType = HalOperandType::TENSOR_FLOAT32,
279 double scale = 0.f,
David Monahanc60d0fd2020-05-19 14:58:34 +0100280 int offset = 0,
281 uint32_t numberOfConsumers = 1)
Nikhil Raj77605822018-09-03 11:25:56 +0100282{
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100283 using HalOperand = typename HalPolicy::Operand;
284 using HalOperandLifeTime = typename HalPolicy::OperandLifeTime;
surmeh0149b9e102018-05-17 14:11:25 +0100285
David Monahanc60d0fd2020-05-19 14:58:34 +0100286 HalOperand op = {};
287 op.type = operandType;
288 op.scale = scale;
289 op.zeroPoint = offset;
290 op.dimensions = dimensions;
291 op.lifetime = HalOperandLifeTime::MODEL_INPUT;
292 op.numberOfConsumers = numberOfConsumers;
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100293
294 AddOperand<HalPolicy>(model, op);
Nikhil Raj77605822018-09-03 11:25:56 +0100295
296 model.inputIndexes.resize(model.inputIndexes.size() + 1);
297 model.inputIndexes[model.inputIndexes.size() - 1] = model.operands.size() - 1;
298}
299
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100300template<typename HalPolicy,
301 typename HalModel = typename HalPolicy::Model,
302 typename HalOperandType = typename HalPolicy::OperandType>
Nikhil Raj77605822018-09-03 11:25:56 +0100303void AddOutputOperand(HalModel& model,
Matteo Martincighc7434122018-11-14 12:27:04 +0000304 const hidl_vec<uint32_t>& dimensions,
Ellen Norris-Thompson976ad3e2019-08-21 15:21:14 +0100305 HalOperandType operandType = HalOperandType::TENSOR_FLOAT32,
306 double scale = 0.f,
David Monahanc60d0fd2020-05-19 14:58:34 +0100307 int offset = 0,
308 uint32_t numberOfConsumers = 0)
Nikhil Raj77605822018-09-03 11:25:56 +0100309{
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100310 using HalOperand = typename HalPolicy::Operand;
311 using HalOperandLifeTime = typename HalPolicy::OperandLifeTime;
surmeh0149b9e102018-05-17 14:11:25 +0100312
David Monahanc60d0fd2020-05-19 14:58:34 +0100313 HalOperand op = {};
314 op.type = operandType;
315 op.scale = scale;
316 op.zeroPoint = offset;
317 op.dimensions = dimensions;
318 op.lifetime = HalOperandLifeTime::MODEL_OUTPUT;
319 op.numberOfConsumers = numberOfConsumers;
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100320
321 AddOperand<HalPolicy>(model, op);
Nikhil Raj77605822018-09-03 11:25:56 +0100322
323 model.outputIndexes.resize(model.outputIndexes.size() + 1);
324 model.outputIndexes[model.outputIndexes.size() - 1] = model.operands.size() - 1;
325}
surmeh0149b9e102018-05-17 14:11:25 +0100326
Sadik Armagane6e54a82019-05-08 10:18:05 +0100327android::sp<V1_0::IPreparedModel> PrepareModelWithStatus(const V1_0::Model& model,
328 armnn_driver::ArmnnDriver& driver,
Kevin Mayec1e5b82020-02-26 17:00:39 +0000329 V1_0::ErrorStatus& prepareStatus,
330 V1_0::ErrorStatus expectedStatus = V1_0::ErrorStatus::NONE);
Nikhil Raj77605822018-09-03 11:25:56 +0100331
Matteo Martincigha5f9e762019-06-17 13:26:34 +0100332#if defined(ARMNN_ANDROID_NN_V1_1) || defined(ARMNN_ANDROID_NN_V1_2)
Nikhil Raj77605822018-09-03 11:25:56 +0100333
Sadik Armagane6e54a82019-05-08 10:18:05 +0100334android::sp<V1_0::IPreparedModel> PrepareModelWithStatus(const V1_1::Model& model,
Matteo Martincigha5f9e762019-06-17 13:26:34 +0100335 armnn_driver::ArmnnDriver& driver,
Kevin Mayec1e5b82020-02-26 17:00:39 +0000336 V1_0::ErrorStatus& prepareStatus,
337 V1_0::ErrorStatus expectedStatus = V1_0::ErrorStatus::NONE);
Nikhil Raj77605822018-09-03 11:25:56 +0100338
339#endif
340
341template<typename HalModel>
Sadik Armagane6e54a82019-05-08 10:18:05 +0100342android::sp<V1_0::IPreparedModel> PrepareModel(const HalModel& model,
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100343 armnn_driver::ArmnnDriver& driver)
Nikhil Raj77605822018-09-03 11:25:56 +0100344{
Kevin Mayec1e5b82020-02-26 17:00:39 +0000345 V1_0::ErrorStatus prepareStatus = V1_0::ErrorStatus::NONE;
Nikhil Raj77605822018-09-03 11:25:56 +0100346 return PrepareModelWithStatus(model, driver, prepareStatus);
347}
surmeh0149b9e102018-05-17 14:11:25 +0100348
Ferran Balaguerb2397fd2019-07-25 12:12:39 +0100349#ifdef ARMNN_ANDROID_NN_V1_2
350
351android::sp<V1_2::IPreparedModel> PrepareModelWithStatus_1_2(const armnn_driver::hal_1_2::HalPolicy::Model& model,
352 armnn_driver::ArmnnDriver& driver,
Kevin Mayec1e5b82020-02-26 17:00:39 +0000353 V1_0::ErrorStatus& prepareStatus,
354 V1_0::ErrorStatus expectedStatus = V1_0::ErrorStatus::NONE);
Ferran Balaguerb2397fd2019-07-25 12:12:39 +0100355
356template<typename HalModel>
357android::sp<V1_2::IPreparedModel> PrepareModel_1_2(const HalModel& model,
358 armnn_driver::ArmnnDriver& driver)
359{
Kevin Mayec1e5b82020-02-26 17:00:39 +0000360 V1_0::ErrorStatus prepareStatus = V1_0::ErrorStatus::NONE;
Ferran Balaguerb2397fd2019-07-25 12:12:39 +0100361 return PrepareModelWithStatus_1_2(model, driver, prepareStatus);
362}
363
364#endif
365
366
Kevin Mayec1e5b82020-02-26 17:00:39 +0000367V1_0::ErrorStatus Execute(android::sp<V1_0::IPreparedModel> preparedModel,
368 const V1_0::Request& request,
369 V1_0::ErrorStatus expectedStatus = V1_0::ErrorStatus::NONE);
surmeh0149b9e102018-05-17 14:11:25 +0100370
Sadik Armagane6e54a82019-05-08 10:18:05 +0100371android::sp<ExecutionCallback> ExecuteNoWait(android::sp<V1_0::IPreparedModel> preparedModel,
Kevin Mayec1e5b82020-02-26 17:00:39 +0000372 const V1_0::Request& request);
surmeh0149b9e102018-05-17 14:11:25 +0100373
374} // namespace driverTestHelpers