blob: 82087961f5cedfde5c69ee38d29761dca1c1113b [file] [log] [blame]
surmeh0149b9e102018-05-17 14:11:25 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// See LICENSE file in the project root for full license information.
4//
5#include "DriverTestHelpers.hpp"
6#include <log/log.h>
7#include <boost/test/unit_test.hpp>
8
9namespace android
10{
11namespace hardware
12{
13namespace neuralnetworks
14{
15namespace V1_0
16{
17
18std::ostream& operator<<(std::ostream& os, ErrorStatus stat)
19{
20 return os << static_cast<int>(stat);
21}
22
23} // namespace android::hardware::neuralnetworks::V1_0
24} // namespace android::hardware::neuralnetworks
25} // namespace android::hardware
26} // namespace android
27
surmeh0149b9e102018-05-17 14:11:25 +010028namespace driverTestHelpers
29{
30
telsoa01ce3e84a2018-08-31 09:31:35 +010031using namespace android::hardware;
32using namespace armnn_driver;
33
surmeh0149b9e102018-05-17 14:11:25 +010034Return<void> ExecutionCallback::notify(ErrorStatus status)
35{
36 (void)status;
37 ALOGI("ExecutionCallback::notify invoked");
38 std::lock_guard<std::mutex> executionLock(mMutex);
39 mNotified = true;
40 mCondition.notify_one();
41 return Void();
42}
43
44Return<void> ExecutionCallback::wait()
45{
46 ALOGI("ExecutionCallback::wait invoked");
47 std::unique_lock<std::mutex> executionLock(mMutex);
48 while (!mNotified)
49 {
50 mCondition.wait(executionLock);
51 }
52 mNotified = false;
53 return Void();
54}
55
56Return<void> PreparedModelCallback::notify(ErrorStatus status,
57 const android::sp<IPreparedModel>& preparedModel)
58{
59 m_ErrorStatus = status;
60 m_PreparedModel = preparedModel;
61 return Void();
62}
63
64// lifted from common/Utils.cpp
65hidl_memory allocateSharedMemory(int64_t size)
66{
67 hidl_memory memory;
68
69 const std::string& type = "ashmem";
70 android::sp<IAllocator> allocator = IAllocator::getService(type);
71 allocator->allocate(size, [&](bool success, const hidl_memory& mem) {
72 if (!success)
73 {
74 ALOGE("unable to allocate %li bytes of %s", size, type.c_str());
75 }
76 else
77 {
78 memory = mem;
79 }
80 });
81
82 return memory;
83}
84
85android::sp<IMemory> AddPoolAndGetData(uint32_t size, Request& request)
86{
87 hidl_memory pool;
88
89 android::sp<IAllocator> allocator = IAllocator::getService("ashmem");
90 allocator->allocate(sizeof(float) * size, [&](bool success, const hidl_memory& mem) {
91 BOOST_TEST(success);
92 pool = mem;
93 });
94
95 request.pools.resize(request.pools.size() + 1);
96 request.pools[request.pools.size() - 1] = pool;
97
98 android::sp<IMemory> mapped = mapMemory(pool);
99 mapped->update();
100 return mapped;
101}
102
103void AddPoolAndSetData(uint32_t size, Request& request, const float* data)
104{
105 android::sp<IMemory> memory = AddPoolAndGetData(size, request);
106
107 float* dst = static_cast<float*>(static_cast<void*>(memory->getPointer()));
108
109 memcpy(dst, data, size * sizeof(float));
110}
111
telsoa01ce3e84a2018-08-31 09:31:35 +0100112void AddOperand(neuralnetworks::V1_0::Model& model, const Operand& op)
surmeh0149b9e102018-05-17 14:11:25 +0100113{
114 model.operands.resize(model.operands.size() + 1);
115 model.operands[model.operands.size() - 1] = op;
116}
117
telsoa01ce3e84a2018-08-31 09:31:35 +0100118void AddIntOperand(neuralnetworks::V1_0::Model& model, int32_t value)
surmeh0149b9e102018-05-17 14:11:25 +0100119{
120 DataLocation location = {};
121 location.offset = model.operandValues.size();
122 location.length = sizeof(int32_t);
123
124 Operand op = {};
125 op.type = OperandType::INT32;
126 op.dimensions = hidl_vec<uint32_t>{};
127 op.lifetime = OperandLifeTime::CONSTANT_COPY;
128 op.location = location;
129
130 model.operandValues.resize(model.operandValues.size() + location.length);
131 *reinterpret_cast<int32_t*>(&model.operandValues[location.offset]) = value;
132
133 AddOperand(model, op);
134}
135
telsoa01ce3e84a2018-08-31 09:31:35 +0100136void AddInputOperand(neuralnetworks::V1_0::Model& model,
137 hidl_vec<uint32_t> dimensions,
138 neuralnetworks::V1_0::OperandType operandType)
surmeh0149b9e102018-05-17 14:11:25 +0100139{
140 Operand op = {};
telsoa01ce3e84a2018-08-31 09:31:35 +0100141 op.type = operandType;
surmeh0149b9e102018-05-17 14:11:25 +0100142 op.dimensions = dimensions;
143 op.lifetime = OperandLifeTime::MODEL_INPUT;
144
145 AddOperand(model, op);
146
147 model.inputIndexes.resize(model.inputIndexes.size() + 1);
148 model.inputIndexes[model.inputIndexes.size() - 1] = model.operands.size() - 1;
149}
150
telsoa01ce3e84a2018-08-31 09:31:35 +0100151void AddOutputOperand(neuralnetworks::V1_0::Model& model,
152 hidl_vec<uint32_t> dimensions,
153 neuralnetworks::V1_0::OperandType operandType)
surmeh0149b9e102018-05-17 14:11:25 +0100154{
155 Operand op = {};
telsoa01ce3e84a2018-08-31 09:31:35 +0100156 op.type = operandType;
157 op.scale = operandType == neuralnetworks::V1_0::OperandType::TENSOR_QUANT8_ASYMM ? 1.f / 255.f : 0.f;
surmeh0149b9e102018-05-17 14:11:25 +0100158 op.dimensions = dimensions;
159 op.lifetime = OperandLifeTime::MODEL_OUTPUT;
160
161 AddOperand(model, op);
162
163 model.outputIndexes.resize(model.outputIndexes.size() + 1);
164 model.outputIndexes[model.outputIndexes.size() - 1] = model.operands.size() - 1;
165}
166
167
telsoa01ce3e84a2018-08-31 09:31:35 +0100168android::sp<IPreparedModel> PrepareModelWithStatus(const neuralnetworks::V1_0::Model& model,
surmeh0149b9e102018-05-17 14:11:25 +0100169 armnn_driver::ArmnnDriver& driver,
170 ErrorStatus & prepareStatus,
171 ErrorStatus expectedStatus)
172{
173
174 android::sp<PreparedModelCallback> cb(new PreparedModelCallback());
175 driver.prepareModel(model, cb);
176
177 prepareStatus = cb->GetErrorStatus();
178 BOOST_TEST(prepareStatus == expectedStatus);
179 if (expectedStatus == ErrorStatus::NONE)
180 {
181 BOOST_TEST((cb->GetPreparedModel() != nullptr));
182 }
183 return cb->GetPreparedModel();
184}
185
telsoa01ce3e84a2018-08-31 09:31:35 +0100186android::sp<IPreparedModel> PrepareModel(const neuralnetworks::V1_0::Model& model,
surmeh0149b9e102018-05-17 14:11:25 +0100187 armnn_driver::ArmnnDriver& driver)
188{
189 ErrorStatus prepareStatus = ErrorStatus::NONE;
190 return PrepareModelWithStatus(model, driver, prepareStatus);
191}
192
193ErrorStatus Execute(android::sp<IPreparedModel> preparedModel,
194 const Request& request,
195 ErrorStatus expectedStatus)
196{
telsoa01ce3e84a2018-08-31 09:31:35 +0100197 BOOST_TEST(preparedModel.get() != nullptr);
surmeh0149b9e102018-05-17 14:11:25 +0100198 android::sp<ExecutionCallback> cb(new ExecutionCallback());
199 ErrorStatus execStatus = preparedModel->execute(request, cb);
200 BOOST_TEST(execStatus == expectedStatus);
201 ALOGI("Execute: waiting for callback to be invoked");
202 cb->wait();
203 return execStatus;
204}
205
206android::sp<ExecutionCallback> ExecuteNoWait(android::sp<IPreparedModel> preparedModel, const Request& request)
207{
208 android::sp<ExecutionCallback> cb(new ExecutionCallback());
209 BOOST_TEST(preparedModel->execute(request, cb) == ErrorStatus::NONE);
210 ALOGI("ExecuteNoWait: returning callback object");
211 return cb;
212}
213
214template<>
215OperandType TypeToOperandType<float>()
216{
217 return OperandType::TENSOR_FLOAT32;
218};
219
220template<>
221OperandType TypeToOperandType<int32_t>()
222{
223 return OperandType::TENSOR_INT32;
224};
225
226} // namespace driverTestHelpers