xref: /aosp_15_r20/external/android-nn-driver/test/DriverTestHelpers.hpp (revision 3e777be0405cee09af5d5785ff37f7cfb5bee59a)
1*3e777be0SXin Li //
2*3e777be0SXin Li // Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
3*3e777be0SXin Li // SPDX-License-Identifier: MIT
4*3e777be0SXin Li //
5*3e777be0SXin Li #pragma once
6*3e777be0SXin Li 
7*3e777be0SXin Li #ifndef LOG_TAG
8*3e777be0SXin Li #define LOG_TAG "ArmnnDriverTests"
9*3e777be0SXin Li #endif // LOG_TAG
10*3e777be0SXin Li 
11*3e777be0SXin Li #include "../ArmnnDriver.hpp"
12*3e777be0SXin Li #include <iosfwd>
13*3e777be0SXin Li #include <android/hidl/allocator/1.0/IAllocator.h>
14*3e777be0SXin Li 
15*3e777be0SXin Li // Some of the short name macros from 'third-party/doctest/doctest.h' clash with macros in
16*3e777be0SXin Li // 'system/core/base/include/android-base/logging.h' so we use the full DOCTEST macro names
17*3e777be0SXin Li #ifndef DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES
18*3e777be0SXin Li #define DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES
19*3e777be0SXin Li #endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES
20*3e777be0SXin Li 
21*3e777be0SXin Li #include <doctest/doctest.h>
22*3e777be0SXin Li 
23*3e777be0SXin Li using RequestArgument = V1_0::RequestArgument;
24*3e777be0SXin Li using ::android::hidl::allocator::V1_0::IAllocator;
25*3e777be0SXin Li 
26*3e777be0SXin Li using ::android::hidl::memory::V1_0::IMemory;
27*3e777be0SXin Li 
28*3e777be0SXin Li namespace android
29*3e777be0SXin Li {
30*3e777be0SXin Li namespace hardware
31*3e777be0SXin Li {
32*3e777be0SXin Li namespace neuralnetworks
33*3e777be0SXin Li {
34*3e777be0SXin Li namespace V1_0
35*3e777be0SXin Li {
36*3e777be0SXin Li 
37*3e777be0SXin Li std::ostream& operator<<(std::ostream& os, V1_0::ErrorStatus stat);
38*3e777be0SXin Li 
39*3e777be0SXin Li } // namespace android::hardware::neuralnetworks::V1_0
40*3e777be0SXin Li 
41*3e777be0SXin Li #ifdef ARMNN_ANDROID_NN_V1_3
42*3e777be0SXin Li namespace V1_3
43*3e777be0SXin Li {
44*3e777be0SXin Li 
45*3e777be0SXin Li std::ostream& operator<<(std::ostream& os, V1_3::ErrorStatus stat);
46*3e777be0SXin Li 
47*3e777be0SXin Li } // namespace android::hardware::neuralnetworks::V1_3
48*3e777be0SXin Li #endif
49*3e777be0SXin Li 
50*3e777be0SXin Li } // namespace android::hardware::neuralnetworks
51*3e777be0SXin Li } // namespace android::hardware
52*3e777be0SXin Li } // namespace android
53*3e777be0SXin Li 
54*3e777be0SXin Li namespace driverTestHelpers
55*3e777be0SXin Li {
56*3e777be0SXin Li 
57*3e777be0SXin Li std::ostream& operator<<(std::ostream& os, V1_0::ErrorStatus stat);
58*3e777be0SXin Li 
59*3e777be0SXin Li #ifdef ARMNN_ANDROID_NN_V1_3
60*3e777be0SXin Li std::ostream& operator<<(std::ostream& os, V1_3::ErrorStatus stat);
61*3e777be0SXin Li #endif
62*3e777be0SXin Li 
63*3e777be0SXin Li struct ExecutionCallback : public V1_0::IExecutionCallback
64*3e777be0SXin Li {
ExecutionCallbackdriverTestHelpers::ExecutionCallback65*3e777be0SXin Li     ExecutionCallback() : mNotified(false) {}
66*3e777be0SXin Li     Return<void> notify(V1_0::ErrorStatus status) override;
67*3e777be0SXin Li     /// wait until the callback has notified us that it is done
68*3e777be0SXin Li     Return<void> wait();
69*3e777be0SXin Li 
70*3e777be0SXin Li private:
71*3e777be0SXin Li     // use a mutex and a condition variable to wait for asynchronous callbacks
72*3e777be0SXin Li     std::mutex mMutex;
73*3e777be0SXin Li     std::condition_variable mCondition;
74*3e777be0SXin Li     // and a flag, in case we are notified before the wait call
75*3e777be0SXin Li     bool mNotified;
76*3e777be0SXin Li };
77*3e777be0SXin Li 
78*3e777be0SXin Li class PreparedModelCallback : public V1_0::IPreparedModelCallback
79*3e777be0SXin Li {
80*3e777be0SXin Li public:
PreparedModelCallback()81*3e777be0SXin Li     PreparedModelCallback()
82*3e777be0SXin Li         : m_ErrorStatus(V1_0::ErrorStatus::NONE)
83*3e777be0SXin Li         , m_PreparedModel()
84*3e777be0SXin Li     { }
~PreparedModelCallback()85*3e777be0SXin Li     ~PreparedModelCallback() override { }
86*3e777be0SXin Li 
87*3e777be0SXin Li     Return<void> notify(V1_0::ErrorStatus status,
88*3e777be0SXin Li                         const android::sp<V1_0::IPreparedModel>& preparedModel) override;
GetErrorStatus()89*3e777be0SXin Li     V1_0::ErrorStatus GetErrorStatus() { return m_ErrorStatus; }
GetPreparedModel()90*3e777be0SXin Li     android::sp<V1_0::IPreparedModel> GetPreparedModel() { return m_PreparedModel; }
91*3e777be0SXin Li 
92*3e777be0SXin Li private:
93*3e777be0SXin Li     V1_0::ErrorStatus                  m_ErrorStatus;
94*3e777be0SXin Li     android::sp<V1_0::IPreparedModel>  m_PreparedModel;
95*3e777be0SXin Li };
96*3e777be0SXin Li 
97*3e777be0SXin Li #if defined(ARMNN_ANDROID_NN_V1_2) || defined(ARMNN_ANDROID_NN_V1_3)
98*3e777be0SXin Li 
99*3e777be0SXin Li class PreparedModelCallback_1_2 : public V1_2::IPreparedModelCallback
100*3e777be0SXin Li {
101*3e777be0SXin Li public:
PreparedModelCallback_1_2()102*3e777be0SXin Li     PreparedModelCallback_1_2()
103*3e777be0SXin Li             : m_ErrorStatus(V1_0::ErrorStatus::NONE)
104*3e777be0SXin Li             , m_PreparedModel()
105*3e777be0SXin Li             , m_PreparedModel_1_2()
106*3e777be0SXin Li     { }
~PreparedModelCallback_1_2()107*3e777be0SXin Li     ~PreparedModelCallback_1_2() override { }
108*3e777be0SXin Li 
109*3e777be0SXin Li     Return<void> notify(V1_0::ErrorStatus status, const android::sp<V1_0::IPreparedModel>& preparedModel) override;
110*3e777be0SXin Li 
111*3e777be0SXin Li     Return<void> notify_1_2(V1_0::ErrorStatus status, const android::sp<V1_2::IPreparedModel>& preparedModel) override;
112*3e777be0SXin Li 
GetErrorStatus()113*3e777be0SXin Li     V1_0::ErrorStatus GetErrorStatus() { return m_ErrorStatus; }
114*3e777be0SXin Li 
GetPreparedModel()115*3e777be0SXin Li     android::sp<V1_0::IPreparedModel> GetPreparedModel() { return m_PreparedModel; }
116*3e777be0SXin Li 
GetPreparedModel_1_2()117*3e777be0SXin Li     android::sp<V1_2::IPreparedModel> GetPreparedModel_1_2() { return m_PreparedModel_1_2; }
118*3e777be0SXin Li 
119*3e777be0SXin Li private:
120*3e777be0SXin Li     V1_0::ErrorStatus                   m_ErrorStatus;
121*3e777be0SXin Li     android::sp<V1_0::IPreparedModel>  m_PreparedModel;
122*3e777be0SXin Li     android::sp<V1_2::IPreparedModel>  m_PreparedModel_1_2;
123*3e777be0SXin Li };
124*3e777be0SXin Li 
125*3e777be0SXin Li #endif
126*3e777be0SXin Li 
127*3e777be0SXin Li #ifdef ARMNN_ANDROID_NN_V1_3
128*3e777be0SXin Li 
129*3e777be0SXin Li class PreparedModelCallback_1_3 : public V1_3::IPreparedModelCallback
130*3e777be0SXin Li {
131*3e777be0SXin Li public:
PreparedModelCallback_1_3()132*3e777be0SXin Li     PreparedModelCallback_1_3()
133*3e777be0SXin Li             : m_1_0_ErrorStatus(V1_0::ErrorStatus::NONE)
134*3e777be0SXin Li             , m_1_3_ErrorStatus(V1_3::ErrorStatus::NONE)
135*3e777be0SXin Li             , m_PreparedModel()
136*3e777be0SXin Li             , m_PreparedModel_1_2()
137*3e777be0SXin Li             , m_PreparedModel_1_3()
138*3e777be0SXin Li     { }
~PreparedModelCallback_1_3()139*3e777be0SXin Li     ~PreparedModelCallback_1_3() override { }
140*3e777be0SXin Li 
141*3e777be0SXin Li     Return<void> notify(V1_0::ErrorStatus status, const android::sp<V1_0::IPreparedModel>& preparedModel) override;
142*3e777be0SXin Li 
143*3e777be0SXin Li     Return<void> notify_1_2(V1_0::ErrorStatus status, const android::sp<V1_2::IPreparedModel>& preparedModel) override;
144*3e777be0SXin Li 
145*3e777be0SXin Li     Return<void> notify_1_3(V1_3::ErrorStatus status, const android::sp<V1_3::IPreparedModel>& preparedModel) override;
146*3e777be0SXin Li 
GetErrorStatus()147*3e777be0SXin Li     V1_0::ErrorStatus GetErrorStatus() { return m_1_0_ErrorStatus; }
148*3e777be0SXin Li 
Get_1_3_ErrorStatus()149*3e777be0SXin Li     V1_3::ErrorStatus Get_1_3_ErrorStatus() { return m_1_3_ErrorStatus; }
150*3e777be0SXin Li 
GetPreparedModel()151*3e777be0SXin Li     android::sp<V1_0::IPreparedModel> GetPreparedModel() { return m_PreparedModel; }
152*3e777be0SXin Li 
GetPreparedModel_1_2()153*3e777be0SXin Li     android::sp<V1_2::IPreparedModel> GetPreparedModel_1_2() { return m_PreparedModel_1_2; }
154*3e777be0SXin Li 
GetPreparedModel_1_3()155*3e777be0SXin Li     android::sp<V1_3::IPreparedModel> GetPreparedModel_1_3() { return m_PreparedModel_1_3; }
156*3e777be0SXin Li 
157*3e777be0SXin Li private:
158*3e777be0SXin Li     V1_0::ErrorStatus                   m_1_0_ErrorStatus;
159*3e777be0SXin Li     V1_3::ErrorStatus                   m_1_3_ErrorStatus;
160*3e777be0SXin Li     android::sp<V1_0::IPreparedModel>  m_PreparedModel;
161*3e777be0SXin Li     android::sp<V1_2::IPreparedModel>  m_PreparedModel_1_2;
162*3e777be0SXin Li     android::sp<V1_3::IPreparedModel>  m_PreparedModel_1_3;
163*3e777be0SXin Li };
164*3e777be0SXin Li 
165*3e777be0SXin Li #endif
166*3e777be0SXin Li 
167*3e777be0SXin Li hidl_memory allocateSharedMemory(int64_t size);
168*3e777be0SXin Li 
169*3e777be0SXin Li template<typename T>
AddPoolAndGetData(uint32_t size,V1_0::Request & request)170*3e777be0SXin Li android::sp<IMemory> AddPoolAndGetData(uint32_t size, V1_0::Request& request)
171*3e777be0SXin Li {
172*3e777be0SXin Li     hidl_memory pool;
173*3e777be0SXin Li 
174*3e777be0SXin Li     android::sp<IAllocator> allocator = IAllocator::getService("ashmem");
175*3e777be0SXin Li     allocator->allocate(sizeof(T) * size, [&](bool success, const hidl_memory& mem) {
176*3e777be0SXin Li         DOCTEST_CHECK(success);
177*3e777be0SXin Li         pool = mem;
178*3e777be0SXin Li     });
179*3e777be0SXin Li 
180*3e777be0SXin Li     request.pools.resize(request.pools.size() + 1);
181*3e777be0SXin Li     request.pools[request.pools.size() - 1] = pool;
182*3e777be0SXin Li 
183*3e777be0SXin Li     android::sp<IMemory> mapped = mapMemory(pool);
184*3e777be0SXin Li     mapped->update();
185*3e777be0SXin Li     return mapped;
186*3e777be0SXin Li }
187*3e777be0SXin Li 
188*3e777be0SXin Li template<typename T>
AddPoolAndSetData(uint32_t size,V1_0::Request & request,const T * data)189*3e777be0SXin Li android::sp<IMemory> AddPoolAndSetData(uint32_t size, V1_0::Request& request, const T* data)
190*3e777be0SXin Li {
191*3e777be0SXin Li     android::sp<IMemory> memory = AddPoolAndGetData<T>(size, request);
192*3e777be0SXin Li 
193*3e777be0SXin Li     T* dst = static_cast<T*>(static_cast<void*>(memory->getPointer()));
194*3e777be0SXin Li 
195*3e777be0SXin Li     memcpy(dst, data, size * sizeof(T));
196*3e777be0SXin Li 
197*3e777be0SXin Li     return memory;
198*3e777be0SXin Li }
199*3e777be0SXin Li 
200*3e777be0SXin Li template<typename HalPolicy,
201*3e777be0SXin Li          typename HalModel   = typename HalPolicy::Model,
202*3e777be0SXin Li          typename HalOperand = typename HalPolicy::Operand>
AddOperand(HalModel & model,const HalOperand & op)203*3e777be0SXin Li void AddOperand(HalModel& model, const HalOperand& op)
204*3e777be0SXin Li {
205*3e777be0SXin Li     model.operands.resize(model.operands.size() + 1);
206*3e777be0SXin Li     model.operands[model.operands.size() - 1] = op;
207*3e777be0SXin Li }
208*3e777be0SXin Li 
209*3e777be0SXin Li template<typename HalPolicy, typename HalModel = typename HalPolicy::Model>
AddBoolOperand(HalModel & model,bool value,uint32_t numberOfConsumers=1)210*3e777be0SXin Li void AddBoolOperand(HalModel& model, bool value, uint32_t numberOfConsumers = 1)
211*3e777be0SXin Li {
212*3e777be0SXin Li     using HalOperand         = typename HalPolicy::Operand;
213*3e777be0SXin Li     using HalOperandType     = typename HalPolicy::OperandType;
214*3e777be0SXin Li     using HalOperandLifeTime = typename HalPolicy::OperandLifeTime;
215*3e777be0SXin Li 
216*3e777be0SXin Li     V1_0::DataLocation location = {};
217*3e777be0SXin Li     location.offset = model.operandValues.size();
218*3e777be0SXin Li     location.length = sizeof(uint8_t);
219*3e777be0SXin Li 
220*3e777be0SXin Li     HalOperand op           = {};
221*3e777be0SXin Li     op.type                 = HalOperandType::BOOL;
222*3e777be0SXin Li     op.dimensions           = hidl_vec<uint32_t>{};
223*3e777be0SXin Li     op.lifetime             = HalOperandLifeTime::CONSTANT_COPY;
224*3e777be0SXin Li     op.location             = location;
225*3e777be0SXin Li     op.numberOfConsumers    = numberOfConsumers;
226*3e777be0SXin Li 
227*3e777be0SXin Li     model.operandValues.resize(model.operandValues.size() + location.length);
228*3e777be0SXin Li     *reinterpret_cast<uint8_t*>(&model.operandValues[location.offset]) = static_cast<uint8_t>(value);
229*3e777be0SXin Li 
230*3e777be0SXin Li     AddOperand<HalModel>(model, op);
231*3e777be0SXin Li }
232*3e777be0SXin Li 
233*3e777be0SXin Li template<typename T>
234*3e777be0SXin Li OperandType TypeToOperandType();
235*3e777be0SXin Li 
236*3e777be0SXin Li template<>
237*3e777be0SXin Li OperandType TypeToOperandType<float>();
238*3e777be0SXin Li 
239*3e777be0SXin Li template<>
240*3e777be0SXin Li OperandType TypeToOperandType<int32_t>();
241*3e777be0SXin Li 
242*3e777be0SXin Li template<typename HalPolicy,
243*3e777be0SXin Li     typename HalModel       = typename HalPolicy::Model,
244*3e777be0SXin Li     typename HalOperandType = typename HalPolicy::OperandType>
AddInputOperand(HalModel & model,const hidl_vec<uint32_t> & dimensions,HalOperandType operandType=HalOperandType::TENSOR_FLOAT32,double scale=0.f,int offset=0,uint32_t numberOfConsumers=1)245*3e777be0SXin Li void AddInputOperand(HalModel& model,
246*3e777be0SXin Li                      const hidl_vec<uint32_t>& dimensions,
247*3e777be0SXin Li                      HalOperandType operandType = HalOperandType::TENSOR_FLOAT32,
248*3e777be0SXin Li                      double scale = 0.f,
249*3e777be0SXin Li                      int offset = 0,
250*3e777be0SXin Li                      uint32_t numberOfConsumers = 1)
251*3e777be0SXin Li {
252*3e777be0SXin Li     using HalOperand         = typename HalPolicy::Operand;
253*3e777be0SXin Li     using HalOperandLifeTime = typename HalPolicy::OperandLifeTime;
254*3e777be0SXin Li 
255*3e777be0SXin Li     HalOperand op           = {};
256*3e777be0SXin Li     op.type                 = operandType;
257*3e777be0SXin Li     op.scale                = scale;
258*3e777be0SXin Li     op.zeroPoint            = offset;
259*3e777be0SXin Li     op.dimensions           = dimensions;
260*3e777be0SXin Li     op.lifetime             = HalOperandLifeTime::MODEL_INPUT;
261*3e777be0SXin Li     op.numberOfConsumers    = numberOfConsumers;
262*3e777be0SXin Li 
263*3e777be0SXin Li     AddOperand<HalPolicy>(model, op);
264*3e777be0SXin Li 
265*3e777be0SXin Li     model.inputIndexes.resize(model.inputIndexes.size() + 1);
266*3e777be0SXin Li     model.inputIndexes[model.inputIndexes.size() - 1] = model.operands.size() - 1;
267*3e777be0SXin Li }
268*3e777be0SXin Li 
269*3e777be0SXin Li template<typename HalPolicy,
270*3e777be0SXin Li     typename HalModel       = typename HalPolicy::Model,
271*3e777be0SXin Li     typename HalOperandType = typename HalPolicy::OperandType>
AddOutputOperand(HalModel & model,const hidl_vec<uint32_t> & dimensions,HalOperandType operandType=HalOperandType::TENSOR_FLOAT32,double scale=0.f,int offset=0,uint32_t numberOfConsumers=0)272*3e777be0SXin Li void AddOutputOperand(HalModel& model,
273*3e777be0SXin Li                       const hidl_vec<uint32_t>& dimensions,
274*3e777be0SXin Li                       HalOperandType operandType = HalOperandType::TENSOR_FLOAT32,
275*3e777be0SXin Li                       double scale = 0.f,
276*3e777be0SXin Li                       int offset = 0,
277*3e777be0SXin Li                       uint32_t numberOfConsumers = 0)
278*3e777be0SXin Li {
279*3e777be0SXin Li     using HalOperand         = typename HalPolicy::Operand;
280*3e777be0SXin Li     using HalOperandLifeTime = typename HalPolicy::OperandLifeTime;
281*3e777be0SXin Li 
282*3e777be0SXin Li     HalOperand op           = {};
283*3e777be0SXin Li     op.type                 = operandType;
284*3e777be0SXin Li     op.scale                = scale;
285*3e777be0SXin Li     op.zeroPoint            = offset;
286*3e777be0SXin Li     op.dimensions           = dimensions;
287*3e777be0SXin Li     op.lifetime             = HalOperandLifeTime::MODEL_OUTPUT;
288*3e777be0SXin Li     op.numberOfConsumers    = numberOfConsumers;
289*3e777be0SXin Li 
290*3e777be0SXin Li     AddOperand<HalPolicy>(model, op);
291*3e777be0SXin Li 
292*3e777be0SXin Li     model.outputIndexes.resize(model.outputIndexes.size() + 1);
293*3e777be0SXin Li     model.outputIndexes[model.outputIndexes.size() - 1] = model.operands.size() - 1;
294*3e777be0SXin Li }
295*3e777be0SXin Li 
296*3e777be0SXin Li android::sp<V1_0::IPreparedModel> PrepareModelWithStatus(const V1_0::Model& model,
297*3e777be0SXin Li                                                          armnn_driver::ArmnnDriver& driver,
298*3e777be0SXin Li                                                          V1_0::ErrorStatus& prepareStatus,
299*3e777be0SXin Li                                                          V1_0::ErrorStatus expectedStatus = V1_0::ErrorStatus::NONE);
300*3e777be0SXin Li 
301*3e777be0SXin Li #if defined(ARMNN_ANDROID_NN_V1_1) || defined(ARMNN_ANDROID_NN_V1_2) || defined(ARMNN_ANDROID_NN_V1_3)
302*3e777be0SXin Li 
303*3e777be0SXin Li android::sp<V1_0::IPreparedModel> PrepareModelWithStatus(const V1_1::Model& model,
304*3e777be0SXin Li                                                          armnn_driver::ArmnnDriver& driver,
305*3e777be0SXin Li                                                          V1_0::ErrorStatus& prepareStatus,
306*3e777be0SXin Li                                                          V1_0::ErrorStatus expectedStatus = V1_0::ErrorStatus::NONE);
307*3e777be0SXin Li 
308*3e777be0SXin Li #endif
309*3e777be0SXin Li 
310*3e777be0SXin Li template<typename HalModel>
PrepareModel(const HalModel & model,armnn_driver::ArmnnDriver & driver)311*3e777be0SXin Li android::sp<V1_0::IPreparedModel> PrepareModel(const HalModel& model,
312*3e777be0SXin Li                                                armnn_driver::ArmnnDriver& driver)
313*3e777be0SXin Li {
314*3e777be0SXin Li     V1_0::ErrorStatus prepareStatus = V1_0::ErrorStatus::NONE;
315*3e777be0SXin Li     return PrepareModelWithStatus(model, driver, prepareStatus);
316*3e777be0SXin Li }
317*3e777be0SXin Li 
318*3e777be0SXin Li #if defined(ARMNN_ANDROID_NN_V1_2) || defined(ARMNN_ANDROID_NN_V1_3)
319*3e777be0SXin Li 
320*3e777be0SXin Li android::sp<V1_2::IPreparedModel> PrepareModelWithStatus_1_2(const armnn_driver::hal_1_2::HalPolicy::Model& model,
321*3e777be0SXin Li                                                             armnn_driver::ArmnnDriver& driver,
322*3e777be0SXin Li                                                             V1_0::ErrorStatus& prepareStatus,
323*3e777be0SXin Li                                                             V1_0::ErrorStatus expectedStatus = V1_0::ErrorStatus::NONE);
324*3e777be0SXin Li 
325*3e777be0SXin Li template<typename HalModel>
PrepareModel_1_2(const HalModel & model,armnn_driver::ArmnnDriver & driver)326*3e777be0SXin Li android::sp<V1_2::IPreparedModel> PrepareModel_1_2(const HalModel& model,
327*3e777be0SXin Li                                                    armnn_driver::ArmnnDriver& driver)
328*3e777be0SXin Li {
329*3e777be0SXin Li     V1_0::ErrorStatus prepareStatus = V1_0::ErrorStatus::NONE;
330*3e777be0SXin Li     return PrepareModelWithStatus_1_2(model, driver, prepareStatus);
331*3e777be0SXin Li }
332*3e777be0SXin Li 
333*3e777be0SXin Li #endif
334*3e777be0SXin Li 
335*3e777be0SXin Li #ifdef ARMNN_ANDROID_NN_V1_3
336*3e777be0SXin Li 
337*3e777be0SXin Li template<typename HalPolicy>
AddOperand(armnn_driver::hal_1_3::HalPolicy::Model & model,const armnn_driver::hal_1_3::HalPolicy::Operand & op)338*3e777be0SXin Li void AddOperand(armnn_driver::hal_1_3::HalPolicy::Model& model,
339*3e777be0SXin Li                 const armnn_driver::hal_1_3::HalPolicy::Operand& op)
340*3e777be0SXin Li {
341*3e777be0SXin Li     model.main.operands.resize(model.main.operands.size() + 1);
342*3e777be0SXin Li     model.main.operands[model.main.operands.size() - 1] = op;
343*3e777be0SXin Li }
344*3e777be0SXin Li 
345*3e777be0SXin Li template<typename HalPolicy>
AddInputOperand(armnn_driver::hal_1_3::HalPolicy::Model & model,const hidl_vec<uint32_t> & dimensions,armnn_driver::hal_1_3::HalPolicy::OperandType operandType=armnn_driver::hal_1_3::HalPolicy::OperandType::TENSOR_FLOAT32,double scale=0.f,int offset=0,uint32_t numberOfConsumers=1)346*3e777be0SXin Li void AddInputOperand(armnn_driver::hal_1_3::HalPolicy::Model& model,
347*3e777be0SXin Li                      const hidl_vec<uint32_t>& dimensions,
348*3e777be0SXin Li                      armnn_driver::hal_1_3::HalPolicy::OperandType operandType =
349*3e777be0SXin Li                      armnn_driver::hal_1_3::HalPolicy::OperandType::TENSOR_FLOAT32,
350*3e777be0SXin Li                      double scale = 0.f,
351*3e777be0SXin Li                      int offset = 0,
352*3e777be0SXin Li                      uint32_t numberOfConsumers = 1)
353*3e777be0SXin Li {
354*3e777be0SXin Li     using HalOperand         = typename armnn_driver::hal_1_3::HalPolicy::Operand;
355*3e777be0SXin Li     using HalOperandLifeTime = typename armnn_driver::hal_1_3::HalPolicy::OperandLifeTime;
356*3e777be0SXin Li 
357*3e777be0SXin Li     HalOperand op           = {};
358*3e777be0SXin Li     op.type                 = operandType;
359*3e777be0SXin Li     op.scale                = scale;
360*3e777be0SXin Li     op.zeroPoint            = offset;
361*3e777be0SXin Li     op.dimensions           = dimensions;
362*3e777be0SXin Li     op.lifetime             = HalOperandLifeTime::SUBGRAPH_INPUT;
363*3e777be0SXin Li     op.numberOfConsumers    = numberOfConsumers;
364*3e777be0SXin Li 
365*3e777be0SXin Li     AddOperand<HalPolicy>(model, op);
366*3e777be0SXin Li 
367*3e777be0SXin Li     model.main.inputIndexes.resize(model.main.inputIndexes.size() + 1);
368*3e777be0SXin Li     model.main.inputIndexes[model.main.inputIndexes.size() - 1] = model.main.operands.size() - 1;
369*3e777be0SXin Li }
370*3e777be0SXin Li 
371*3e777be0SXin Li template<typename HalPolicy>
AddOutputOperand(armnn_driver::hal_1_3::HalPolicy::Model & model,const hidl_vec<uint32_t> & dimensions,armnn_driver::hal_1_3::HalPolicy::OperandType operandType=armnn_driver::hal_1_3::HalPolicy::OperandType::TENSOR_FLOAT32,double scale=0.f,int offset=0,uint32_t numberOfConsumers=0)372*3e777be0SXin Li void AddOutputOperand(armnn_driver::hal_1_3::HalPolicy::Model& model,
373*3e777be0SXin Li                       const hidl_vec<uint32_t>& dimensions,
374*3e777be0SXin Li                       armnn_driver::hal_1_3::HalPolicy::OperandType operandType =
375*3e777be0SXin Li                       armnn_driver::hal_1_3::HalPolicy::OperandType::TENSOR_FLOAT32,
376*3e777be0SXin Li                       double scale = 0.f,
377*3e777be0SXin Li                       int offset = 0,
378*3e777be0SXin Li                       uint32_t numberOfConsumers = 0)
379*3e777be0SXin Li {
380*3e777be0SXin Li     using HalOperand         = typename armnn_driver::hal_1_3::HalPolicy::Operand;
381*3e777be0SXin Li     using HalOperandLifeTime = typename armnn_driver::hal_1_3::HalPolicy::OperandLifeTime;
382*3e777be0SXin Li 
383*3e777be0SXin Li     HalOperand op           = {};
384*3e777be0SXin Li     op.type                 = operandType;
385*3e777be0SXin Li     op.scale                = scale;
386*3e777be0SXin Li     op.zeroPoint            = offset;
387*3e777be0SXin Li     op.dimensions           = dimensions;
388*3e777be0SXin Li     op.lifetime             = HalOperandLifeTime::SUBGRAPH_OUTPUT;
389*3e777be0SXin Li     op.numberOfConsumers    = numberOfConsumers;
390*3e777be0SXin Li 
391*3e777be0SXin Li     AddOperand<HalPolicy>(model, op);
392*3e777be0SXin Li 
393*3e777be0SXin Li     model.main.outputIndexes.resize(model.main.outputIndexes.size() + 1);
394*3e777be0SXin Li     model.main.outputIndexes[model.main.outputIndexes.size() - 1] = model.main.operands.size() - 1;
395*3e777be0SXin Li }
396*3e777be0SXin Li 
397*3e777be0SXin Li android::sp<V1_3::IPreparedModel> PrepareModelWithStatus_1_3(const armnn_driver::hal_1_3::HalPolicy::Model& model,
398*3e777be0SXin Li                                                             armnn_driver::ArmnnDriver& driver,
399*3e777be0SXin Li                                                             V1_3::ErrorStatus& prepareStatus,
400*3e777be0SXin Li                                                             V1_3::Priority priority = V1_3::Priority::LOW);
401*3e777be0SXin Li 
402*3e777be0SXin Li template<typename HalModel>
PrepareModel_1_3(const HalModel & model,armnn_driver::ArmnnDriver & driver)403*3e777be0SXin Li android::sp<V1_3::IPreparedModel> PrepareModel_1_3(const HalModel& model,
404*3e777be0SXin Li                                                    armnn_driver::ArmnnDriver& driver)
405*3e777be0SXin Li {
406*3e777be0SXin Li     V1_3::ErrorStatus prepareStatus = V1_3::ErrorStatus::NONE;
407*3e777be0SXin Li     return PrepareModelWithStatus_1_3(model, driver, prepareStatus);
408*3e777be0SXin Li }
409*3e777be0SXin Li 
410*3e777be0SXin Li #endif
411*3e777be0SXin Li 
412*3e777be0SXin Li template<typename HalPolicy,
413*3e777be0SXin Li     typename T,
414*3e777be0SXin Li     typename HalModel           = typename HalPolicy::Model,
415*3e777be0SXin Li     typename HalOperandType     = typename HalPolicy::OperandType,
416*3e777be0SXin Li     typename HalOperandLifeTime = typename HalPolicy::OperandLifeTime>
AddTensorOperand(HalModel & model,const hidl_vec<uint32_t> & dimensions,const T * values,HalOperandType operandType=HalOperandType::TENSOR_FLOAT32,HalOperandLifeTime operandLifeTime=V1_0::OperandLifeTime::CONSTANT_COPY,double scale=0.f,int offset=0,uint32_t numberOfConsumers=1)417*3e777be0SXin Li void AddTensorOperand(HalModel& model,
418*3e777be0SXin Li                       const hidl_vec<uint32_t>& dimensions,
419*3e777be0SXin Li                       const T* values,
420*3e777be0SXin Li                       HalOperandType operandType = HalOperandType::TENSOR_FLOAT32,
421*3e777be0SXin Li                       HalOperandLifeTime operandLifeTime = V1_0::OperandLifeTime::CONSTANT_COPY,
422*3e777be0SXin Li                       double scale = 0.f,
423*3e777be0SXin Li                       int offset = 0,
424*3e777be0SXin Li                       uint32_t numberOfConsumers = 1)
425*3e777be0SXin Li {
426*3e777be0SXin Li     using HalOperand = typename HalPolicy::Operand;
427*3e777be0SXin Li 
428*3e777be0SXin Li     uint32_t totalElements = 1;
429*3e777be0SXin Li     for (uint32_t dim : dimensions)
430*3e777be0SXin Li     {
431*3e777be0SXin Li         totalElements *= dim;
432*3e777be0SXin Li     }
433*3e777be0SXin Li 
434*3e777be0SXin Li     V1_0::DataLocation location = {};
435*3e777be0SXin Li     location.length = totalElements * sizeof(T);
436*3e777be0SXin Li 
437*3e777be0SXin Li     if(operandLifeTime == HalOperandLifeTime::CONSTANT_COPY)
438*3e777be0SXin Li     {
439*3e777be0SXin Li         location.offset = model.operandValues.size();
440*3e777be0SXin Li     }
441*3e777be0SXin Li 
442*3e777be0SXin Li     HalOperand op           = {};
443*3e777be0SXin Li     op.type                 = operandType;
444*3e777be0SXin Li     op.dimensions           = dimensions;
445*3e777be0SXin Li     op.scale                = scale;
446*3e777be0SXin Li     op.zeroPoint            = offset;
447*3e777be0SXin Li     op.lifetime             = HalOperandLifeTime::CONSTANT_COPY;
448*3e777be0SXin Li     op.location             = location;
449*3e777be0SXin Li     op.numberOfConsumers    = numberOfConsumers;
450*3e777be0SXin Li 
451*3e777be0SXin Li     model.operandValues.resize(model.operandValues.size() + location.length);
452*3e777be0SXin Li     for (uint32_t i = 0; i < totalElements; i++)
453*3e777be0SXin Li     {
454*3e777be0SXin Li         *(reinterpret_cast<T*>(&model.operandValues[location.offset]) + i) = values[i];
455*3e777be0SXin Li     }
456*3e777be0SXin Li 
457*3e777be0SXin Li     AddOperand<HalPolicy>(model, op);
458*3e777be0SXin Li }
459*3e777be0SXin Li 
460*3e777be0SXin Li template<typename HalPolicy,
461*3e777be0SXin Li     typename T,
462*3e777be0SXin Li     typename HalModel           = typename HalPolicy::Model,
463*3e777be0SXin Li     typename HalOperandType     = typename HalPolicy::OperandType,
464*3e777be0SXin Li     typename HalOperandLifeTime = typename HalPolicy::OperandLifeTime>
AddTensorOperand(HalModel & model,const hidl_vec<uint32_t> & dimensions,const std::vector<T> & values,HalOperandType operandType=HalPolicy::OperandType::TENSOR_FLOAT32,HalOperandLifeTime operandLifeTime=V1_0::OperandLifeTime::CONSTANT_COPY,double scale=0.f,int offset=0,uint32_t numberOfConsumers=1)465*3e777be0SXin Li void AddTensorOperand(HalModel& model,
466*3e777be0SXin Li                       const hidl_vec<uint32_t>& dimensions,
467*3e777be0SXin Li                       const std::vector<T>& values,
468*3e777be0SXin Li                       HalOperandType operandType = HalPolicy::OperandType::TENSOR_FLOAT32,
469*3e777be0SXin Li                       HalOperandLifeTime operandLifeTime = V1_0::OperandLifeTime::CONSTANT_COPY,
470*3e777be0SXin Li                       double scale = 0.f,
471*3e777be0SXin Li                       int offset = 0,
472*3e777be0SXin Li                       uint32_t numberOfConsumers = 1)
473*3e777be0SXin Li {
474*3e777be0SXin Li     AddTensorOperand<HalPolicy, T>(model,
475*3e777be0SXin Li                                    dimensions,
476*3e777be0SXin Li                                    values.data(),
477*3e777be0SXin Li                                    operandType,
478*3e777be0SXin Li                                    operandLifeTime,
479*3e777be0SXin Li                                    scale,
480*3e777be0SXin Li                                    offset,
481*3e777be0SXin Li                                    numberOfConsumers);
482*3e777be0SXin Li }
483*3e777be0SXin Li 
484*3e777be0SXin Li template<typename HalPolicy, typename HalModel = typename HalPolicy::Model>
AddIntOperand(HalModel & model,int32_t value,uint32_t numberOfConsumers=1)485*3e777be0SXin Li void AddIntOperand(HalModel& model, int32_t value, uint32_t numberOfConsumers = 1)
486*3e777be0SXin Li {
487*3e777be0SXin Li     using HalOperand         = typename HalPolicy::Operand;
488*3e777be0SXin Li     using HalOperandType     = typename HalPolicy::OperandType;
489*3e777be0SXin Li     using HalOperandLifeTime = typename HalPolicy::OperandLifeTime;
490*3e777be0SXin Li 
491*3e777be0SXin Li     V1_0::DataLocation location = {};
492*3e777be0SXin Li     location.offset = model.operandValues.size();
493*3e777be0SXin Li     location.length = sizeof(int32_t);
494*3e777be0SXin Li 
495*3e777be0SXin Li     HalOperand op           = {};
496*3e777be0SXin Li     op.type                 = HalOperandType::INT32;
497*3e777be0SXin Li     op.dimensions           = hidl_vec<uint32_t>{};
498*3e777be0SXin Li     op.lifetime             = HalOperandLifeTime::CONSTANT_COPY;
499*3e777be0SXin Li     op.location             = location;
500*3e777be0SXin Li     op.numberOfConsumers    = numberOfConsumers;
501*3e777be0SXin Li 
502*3e777be0SXin Li     model.operandValues.resize(model.operandValues.size() + location.length);
503*3e777be0SXin Li     *reinterpret_cast<int32_t*>(&model.operandValues[location.offset]) = value;
504*3e777be0SXin Li 
505*3e777be0SXin Li     AddOperand<HalPolicy>(model, op);
506*3e777be0SXin Li }
507*3e777be0SXin Li 
508*3e777be0SXin Li template<typename HalPolicy, typename HalModel = typename HalPolicy::Model>
AddFloatOperand(HalModel & model,float value,uint32_t numberOfConsumers=1)509*3e777be0SXin Li void AddFloatOperand(HalModel& model,
510*3e777be0SXin Li                      float value,
511*3e777be0SXin Li                      uint32_t numberOfConsumers = 1)
512*3e777be0SXin Li {
513*3e777be0SXin Li     using HalOperand         = typename HalPolicy::Operand;
514*3e777be0SXin Li     using HalOperandType     = typename HalPolicy::OperandType;
515*3e777be0SXin Li     using HalOperandLifeTime = typename HalPolicy::OperandLifeTime;
516*3e777be0SXin Li 
517*3e777be0SXin Li     V1_0::DataLocation location = {};
518*3e777be0SXin Li     location.offset = model.operandValues.size();
519*3e777be0SXin Li     location.length = sizeof(float);
520*3e777be0SXin Li 
521*3e777be0SXin Li     HalOperand op           = {};
522*3e777be0SXin Li     op.type                 = HalOperandType::FLOAT32;
523*3e777be0SXin Li     op.dimensions           = hidl_vec<uint32_t>{};
524*3e777be0SXin Li     op.lifetime             = HalOperandLifeTime::CONSTANT_COPY;
525*3e777be0SXin Li     op.location             = location;
526*3e777be0SXin Li     op.numberOfConsumers    = numberOfConsumers;
527*3e777be0SXin Li 
528*3e777be0SXin Li     model.operandValues.resize(model.operandValues.size() + location.length);
529*3e777be0SXin Li     *reinterpret_cast<float*>(&model.operandValues[location.offset]) = value;
530*3e777be0SXin Li 
531*3e777be0SXin Li     AddOperand<HalPolicy>(model, op);
532*3e777be0SXin Li }
533*3e777be0SXin Li 
534*3e777be0SXin Li V1_0::ErrorStatus Execute(android::sp<V1_0::IPreparedModel> preparedModel,
535*3e777be0SXin Li                           const V1_0::Request& request,
536*3e777be0SXin Li                           V1_0::ErrorStatus expectedStatus = V1_0::ErrorStatus::NONE);
537*3e777be0SXin Li 
538*3e777be0SXin Li android::sp<ExecutionCallback> ExecuteNoWait(android::sp<V1_0::IPreparedModel> preparedModel,
539*3e777be0SXin Li                                              const V1_0::Request& request);
540*3e777be0SXin Li 
541*3e777be0SXin Li } // namespace driverTestHelpers
542