blob: 704de44aee0a64ecd9182dcb83f58cca0277cd79 [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#include "DriverTestHelpers.hpp"
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +01006
7#include "../1.0/HalPolicy.hpp"
8
Sadik Armagan9150bff2021-05-26 15:40:53 +01009#include <doctest/doctest.h>
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +010010
surmeh0149b9e102018-05-17 14:11:25 +010011#include <log/log.h>
12
Sadik Armagan9150bff2021-05-26 15:40:53 +010013TEST_SUITE("FullyConnectedTests")
14{
telsoa01ce3e84a2018-08-31 09:31:35 +010015using namespace android::hardware;
surmeh0149b9e102018-05-17 14:11:25 +010016using namespace driverTestHelpers;
telsoa01ce3e84a2018-08-31 09:31:35 +010017using namespace armnn_driver;
surmeh0149b9e102018-05-17 14:11:25 +010018
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +010019using HalPolicy = hal_1_0::HalPolicy;
20
surmeh0149b9e102018-05-17 14:11:25 +010021// Add our own test here since we fail the fc tests which Google supplies (because of non-const weights)
Sadik Armagan9150bff2021-05-26 15:40:53 +010022TEST_CASE("FullyConnected")
surmeh0149b9e102018-05-17 14:11:25 +010023{
24 // this should ideally replicate fully_connected_float.model.cpp
25 // but that uses slightly weird dimensions which I don't think we need to support for now
26
27 auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +010028 HalPolicy::Model model = {};
surmeh0149b9e102018-05-17 14:11:25 +010029
30 // add operands
31 int32_t actValue = 0;
32 float weightValue[] = {2, 4, 1};
33 float biasValue[] = {4};
34
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +010035 AddInputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 3});
36 AddTensorOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 3}, weightValue);
37 AddTensorOperand<HalPolicy>(model, hidl_vec<uint32_t>{1}, biasValue);
38 AddIntOperand<HalPolicy>(model, actValue);
39 AddOutputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 1});
surmeh0149b9e102018-05-17 14:11:25 +010040
41 // make the fully connected operation
42 model.operations.resize(1);
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +010043 model.operations[0].type = HalPolicy::OperationType::FULLY_CONNECTED;
surmeh0149b9e102018-05-17 14:11:25 +010044 model.operations[0].inputs = hidl_vec<uint32_t>{0, 1, 2, 3};
45 model.operations[0].outputs = hidl_vec<uint32_t>{4};
46
47 // make the prepared model
Sadik Armagane6e54a82019-05-08 10:18:05 +010048 android::sp<V1_0::IPreparedModel> preparedModel = PrepareModel(model, *driver);
surmeh0149b9e102018-05-17 14:11:25 +010049
50 // construct the request
Sadik Armagan188675f2021-02-12 17:16:42 +000051 V1_0::DataLocation inloc = {};
surmeh0149b9e102018-05-17 14:11:25 +010052 inloc.poolIndex = 0;
53 inloc.offset = 0;
54 inloc.length = 3 * sizeof(float);
55 RequestArgument input = {};
56 input.location = inloc;
57 input.dimensions = hidl_vec<uint32_t>{};
58
Sadik Armagan188675f2021-02-12 17:16:42 +000059 V1_0::DataLocation outloc = {};
surmeh0149b9e102018-05-17 14:11:25 +010060 outloc.poolIndex = 1;
61 outloc.offset = 0;
62 outloc.length = 1 * sizeof(float);
63 RequestArgument output = {};
64 output.location = outloc;
65 output.dimensions = hidl_vec<uint32_t>{};
66
Kevin Mayec1e5b82020-02-26 17:00:39 +000067 V1_0::Request request = {};
surmeh0149b9e102018-05-17 14:11:25 +010068 request.inputs = hidl_vec<RequestArgument>{input};
69 request.outputs = hidl_vec<RequestArgument>{output};
70
71 // set the input data (matching source test)
72 float indata[] = {2, 32, 16};
Ellen Norris-Thompson976ad3e2019-08-21 15:21:14 +010073 AddPoolAndSetData<float>(3, request, indata);
surmeh0149b9e102018-05-17 14:11:25 +010074
75 // add memory for the output
Ellen Norris-Thompson976ad3e2019-08-21 15:21:14 +010076 android::sp<IMemory> outMemory = AddPoolAndGetData<float>(1, request);
surmeh0149b9e102018-05-17 14:11:25 +010077 float* outdata = static_cast<float*>(static_cast<void*>(outMemory->getPointer()));
78
79 // run the execution
Sadik Armagand4636872020-04-27 10:15:41 +010080 if (preparedModel.get() != nullptr)
81 {
82 Execute(preparedModel, request);
83 }
surmeh0149b9e102018-05-17 14:11:25 +010084
85 // check the result
Sadik Armagan9150bff2021-05-26 15:40:53 +010086 CHECK(outdata[0] == 152);
surmeh0149b9e102018-05-17 14:11:25 +010087}
88
Sadik Armagan9150bff2021-05-26 15:40:53 +010089TEST_CASE("TestFullyConnected4dInput")
surmeh0149b9e102018-05-17 14:11:25 +010090{
91 auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
92
Kevin Mayec1e5b82020-02-26 17:00:39 +000093 V1_0::ErrorStatus error;
surmeh0149b9e102018-05-17 14:11:25 +010094 std::vector<bool> sup;
95
Kevin Mayec1e5b82020-02-26 17:00:39 +000096 ArmnnDriver::getSupportedOperations_cb cb = [&](V1_0::ErrorStatus status, const std::vector<bool>& supported)
surmeh0149b9e102018-05-17 14:11:25 +010097 {
98 error = status;
99 sup = supported;
100 };
101
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100102 HalPolicy::Model model = {};
surmeh0149b9e102018-05-17 14:11:25 +0100103
104 // operands
105 int32_t actValue = 0;
106 float weightValue[] = {1, 0, 0, 0, 0, 0, 0, 0,
107 0, 1, 0, 0, 0, 0, 0, 0,
108 0, 0, 1, 0, 0, 0, 0, 0,
109 0, 0, 0, 1, 0, 0, 0, 0,
110 0, 0, 0, 0, 1, 0, 0, 0,
111 0, 0, 0, 0, 0, 1, 0, 0,
112 0, 0, 0, 0, 0, 0, 1, 0,
113 0, 0, 0, 0, 0, 0, 0, 1}; //identity
114 float biasValue[] = {0, 0, 0, 0, 0, 0, 0, 0};
115
116 // fully connected operation
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100117 AddInputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 1, 1, 8});
118 AddTensorOperand<HalPolicy>(model, hidl_vec<uint32_t>{8, 8}, weightValue);
119 AddTensorOperand<HalPolicy>(model, hidl_vec<uint32_t>{8}, biasValue);
120 AddIntOperand<HalPolicy>(model, actValue);
121 AddOutputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 8});
surmeh0149b9e102018-05-17 14:11:25 +0100122
123 model.operations.resize(1);
124
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100125 model.operations[0].type = HalPolicy::OperationType::FULLY_CONNECTED;
surmeh0149b9e102018-05-17 14:11:25 +0100126 model.operations[0].inputs = hidl_vec<uint32_t>{0,1,2,3};
127 model.operations[0].outputs = hidl_vec<uint32_t>{4};
128
129 // make the prepared model
Sadik Armagane6e54a82019-05-08 10:18:05 +0100130 android::sp<V1_0::IPreparedModel> preparedModel = PrepareModel(model, *driver);
surmeh0149b9e102018-05-17 14:11:25 +0100131
surmeh0149b9e102018-05-17 14:11:25 +0100132 // construct the request
Sadik Armagan188675f2021-02-12 17:16:42 +0000133 V1_0::DataLocation inloc = {};
134 inloc.poolIndex = 0;
135 inloc.offset = 0;
136 inloc.length = 8 * sizeof(float);
137 RequestArgument input = {};
138 input.location = inloc;
139 input.dimensions = hidl_vec<uint32_t>{};
surmeh0149b9e102018-05-17 14:11:25 +0100140
Sadik Armagan188675f2021-02-12 17:16:42 +0000141 V1_0::DataLocation outloc = {};
142 outloc.poolIndex = 1;
143 outloc.offset = 0;
144 outloc.length = 8 * sizeof(float);
145 RequestArgument output = {};
146 output.location = outloc;
147 output.dimensions = hidl_vec<uint32_t>{};
surmeh0149b9e102018-05-17 14:11:25 +0100148
Kevin Mayec1e5b82020-02-26 17:00:39 +0000149 V1_0::Request request = {};
surmeh0149b9e102018-05-17 14:11:25 +0100150 request.inputs = hidl_vec<RequestArgument>{input};
151 request.outputs = hidl_vec<RequestArgument>{output};
152
153 // set the input data
154 float indata[] = {1,2,3,4,5,6,7,8};
155 AddPoolAndSetData(8, request, indata);
156
157 // add memory for the output
Ellen Norris-Thompson976ad3e2019-08-21 15:21:14 +0100158 android::sp<IMemory> outMemory = AddPoolAndGetData<float>(8, request);
surmeh0149b9e102018-05-17 14:11:25 +0100159 float* outdata = static_cast<float*>(static_cast<void*>(outMemory->getPointer()));
160
161 // run the execution
Sadik Armagand4636872020-04-27 10:15:41 +0100162 if (preparedModel != nullptr)
163 {
164 Execute(preparedModel, request);
165 }
surmeh0149b9e102018-05-17 14:11:25 +0100166
167 // check the result
Sadik Armagan9150bff2021-05-26 15:40:53 +0100168 CHECK(outdata[0] == 1);
169 CHECK(outdata[1] == 2);
170 CHECK(outdata[2] == 3);
171 CHECK(outdata[3] == 4);
172 CHECK(outdata[4] == 5);
173 CHECK(outdata[5] == 6);
174 CHECK(outdata[6] == 7);
175 CHECK(outdata[7] == 8);
surmeh0149b9e102018-05-17 14:11:25 +0100176}
177
Sadik Armagan9150bff2021-05-26 15:40:53 +0100178TEST_CASE("TestFullyConnected4dInputReshape")
surmeh0149b9e102018-05-17 14:11:25 +0100179{
180 auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
181
Kevin Mayec1e5b82020-02-26 17:00:39 +0000182 V1_0::ErrorStatus error;
surmeh0149b9e102018-05-17 14:11:25 +0100183 std::vector<bool> sup;
184
Kevin Mayec1e5b82020-02-26 17:00:39 +0000185 ArmnnDriver::getSupportedOperations_cb cb = [&](V1_0::ErrorStatus status, const std::vector<bool>& supported)
surmeh0149b9e102018-05-17 14:11:25 +0100186 {
187 error = status;
188 sup = supported;
189 };
190
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100191 HalPolicy::Model model = {};
surmeh0149b9e102018-05-17 14:11:25 +0100192
193 // operands
194 int32_t actValue = 0;
195 float weightValue[] = {1, 0, 0, 0, 0, 0, 0, 0,
196 0, 1, 0, 0, 0, 0, 0, 0,
197 0, 0, 1, 0, 0, 0, 0, 0,
198 0, 0, 0, 1, 0, 0, 0, 0,
199 0, 0, 0, 0, 1, 0, 0, 0,
200 0, 0, 0, 0, 0, 1, 0, 0,
201 0, 0, 0, 0, 0, 0, 1, 0,
202 0, 0, 0, 0, 0, 0, 0, 1}; //identity
203 float biasValue[] = {0, 0, 0, 0, 0, 0, 0, 0};
204
205 // fully connected operation
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100206 AddInputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 2, 2, 2});
207 AddTensorOperand<HalPolicy>(model, hidl_vec<uint32_t>{8, 8}, weightValue);
208 AddTensorOperand<HalPolicy>(model, hidl_vec<uint32_t>{8}, biasValue);
209 AddIntOperand<HalPolicy>(model, actValue);
210 AddOutputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 8});
surmeh0149b9e102018-05-17 14:11:25 +0100211
212 model.operations.resize(1);
213
Aron Virginas-Tar44cfd842019-06-14 15:45:03 +0100214 model.operations[0].type = HalPolicy::OperationType::FULLY_CONNECTED;
surmeh0149b9e102018-05-17 14:11:25 +0100215 model.operations[0].inputs = hidl_vec<uint32_t>{0,1,2,3};
216 model.operations[0].outputs = hidl_vec<uint32_t>{4};
217
218 // make the prepared model
Sadik Armagane6e54a82019-05-08 10:18:05 +0100219 android::sp<V1_0::IPreparedModel> preparedModel = PrepareModel(model, *driver);
surmeh0149b9e102018-05-17 14:11:25 +0100220
surmeh0149b9e102018-05-17 14:11:25 +0100221 // construct the request
Sadik Armagan188675f2021-02-12 17:16:42 +0000222 V1_0::DataLocation inloc = {};
223 inloc.poolIndex = 0;
224 inloc.offset = 0;
225 inloc.length = 8 * sizeof(float);
226 RequestArgument input = {};
227 input.location = inloc;
228 input.dimensions = hidl_vec<uint32_t>{};
surmeh0149b9e102018-05-17 14:11:25 +0100229
Sadik Armagan188675f2021-02-12 17:16:42 +0000230 V1_0::DataLocation outloc = {};
231 outloc.poolIndex = 1;
232 outloc.offset = 0;
233 outloc.length = 8 * sizeof(float);
234 RequestArgument output = {};
235 output.location = outloc;
236 output.dimensions = hidl_vec<uint32_t>{};
surmeh0149b9e102018-05-17 14:11:25 +0100237
Kevin Mayec1e5b82020-02-26 17:00:39 +0000238 V1_0::Request request = {};
surmeh0149b9e102018-05-17 14:11:25 +0100239 request.inputs = hidl_vec<RequestArgument>{input};
240 request.outputs = hidl_vec<RequestArgument>{output};
241
242 // set the input data
243 float indata[] = {1,2,3,4,5,6,7,8};
244 AddPoolAndSetData(8, request, indata);
245
246 // add memory for the output
Ellen Norris-Thompson976ad3e2019-08-21 15:21:14 +0100247 android::sp<IMemory> outMemory = AddPoolAndGetData<float>(8, request);
surmeh0149b9e102018-05-17 14:11:25 +0100248 float* outdata = static_cast<float*>(static_cast<void*>(outMemory->getPointer()));
249
250 // run the execution
Sadik Armagand4636872020-04-27 10:15:41 +0100251 if (preparedModel != nullptr)
252 {
253 Execute(preparedModel, request);
254 }
surmeh0149b9e102018-05-17 14:11:25 +0100255
256 // check the result
Sadik Armagan9150bff2021-05-26 15:40:53 +0100257 CHECK(outdata[0] == 1);
258 CHECK(outdata[1] == 2);
259 CHECK(outdata[2] == 3);
260 CHECK(outdata[3] == 4);
261 CHECK(outdata[4] == 5);
262 CHECK(outdata[5] == 6);
263 CHECK(outdata[6] == 7);
264 CHECK(outdata[7] == 8);
surmeh0149b9e102018-05-17 14:11:25 +0100265}
266
Sadik Armagan9150bff2021-05-26 15:40:53 +0100267TEST_CASE("TestFullyConnectedWeightsAsInput")
Sadik Armagan2e4a24a2021-03-18 13:59:40 +0000268{
269 auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
270
271 V1_0::ErrorStatus error;
272 std::vector<bool> sup;
273
274 ArmnnDriver::getSupportedOperations_cb cb = [&](V1_0::ErrorStatus status, const std::vector<bool>& supported)
275 {
276 error = status;
277 sup = supported;
278 };
279
280 HalPolicy::Model model = {};
281
282 // operands
283 int32_t actValue = 0;
284 float weightValue[] = {1, 0, 0, 0, 0, 0, 0, 0,
285 0, 1, 0, 0, 0, 0, 0, 0,
286 0, 0, 1, 0, 0, 0, 0, 0,
287 0, 0, 0, 1, 0, 0, 0, 0,
288 0, 0, 0, 0, 1, 0, 0, 0,
289 0, 0, 0, 0, 0, 1, 0, 0,
290 0, 0, 0, 0, 0, 0, 1, 0,
291 0, 0, 0, 0, 0, 0, 0, 1}; //identity
292 float biasValue[] = {0, 0, 0, 0, 0, 0, 0, 0};
293
294 // fully connected operation
295 AddInputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 1, 1, 8});
296 AddInputOperand<HalPolicy>(model, hidl_vec<uint32_t>{8, 8});
297 AddInputOperand<HalPolicy>(model, hidl_vec<uint32_t>{8});
298 AddIntOperand<HalPolicy>(model, actValue);
299 AddOutputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 8});
300
301 model.operations.resize(1);
302
303 model.operations[0].type = HalPolicy::OperationType::FULLY_CONNECTED;
304 model.operations[0].inputs = hidl_vec<uint32_t>{0,1,2,3};
305 model.operations[0].outputs = hidl_vec<uint32_t>{4};
306
307 // make the prepared model
308 android::sp<V1_0::IPreparedModel> preparedModel = PrepareModel(model, *driver);
309
310 // construct the request for input
311 V1_0::DataLocation inloc = {};
312 inloc.poolIndex = 0;
313 inloc.offset = 0;
314 inloc.length = 8 * sizeof(float);
315 RequestArgument input = {};
316 input.location = inloc;
317 input.dimensions = hidl_vec<uint32_t>{1, 1, 1, 8};
318
319 // construct the request for weights as input
320 V1_0::DataLocation wloc = {};
321 wloc.poolIndex = 1;
322 wloc.offset = 0;
323 wloc.length = 64 * sizeof(float);
324 RequestArgument weights = {};
325 weights.location = wloc;
326 weights.dimensions = hidl_vec<uint32_t>{8, 8};
327
328 // construct the request for bias as input
329 V1_0::DataLocation bloc = {};
330 bloc.poolIndex = 2;
331 bloc.offset = 0;
332 bloc.length = 8 * sizeof(float);
333 RequestArgument bias = {};
334 bias.location = bloc;
335 bias.dimensions = hidl_vec<uint32_t>{8};
336
337 V1_0::DataLocation outloc = {};
338 outloc.poolIndex = 3;
339 outloc.offset = 0;
340 outloc.length = 8 * sizeof(float);
341 RequestArgument output = {};
342 output.location = outloc;
343 output.dimensions = hidl_vec<uint32_t>{1, 8};
344
345 V1_0::Request request = {};
346 request.inputs = hidl_vec<RequestArgument>{input, weights, bias};
347 request.outputs = hidl_vec<RequestArgument>{output};
348
349 // set the input data
350 float indata[] = {1,2,3,4,5,6,7,8};
351 AddPoolAndSetData(8, request, indata);
352
353 // set the weights data
354 AddPoolAndSetData(64, request, weightValue);
355 // set the bias data
356 AddPoolAndSetData(8, request, biasValue);
357
358 // add memory for the output
359 android::sp<IMemory> outMemory = AddPoolAndGetData<float>(8, request);
360 float* outdata = static_cast<float*>(static_cast<void*>(outMemory->getPointer()));
361
362 // run the execution
363 if (preparedModel != nullptr)
364 {
365 Execute(preparedModel, request);
366 }
367
368 // check the result
Sadik Armagan9150bff2021-05-26 15:40:53 +0100369 CHECK(outdata[0] == 1);
370 CHECK(outdata[1] == 2);
371 CHECK(outdata[2] == 3);
372 CHECK(outdata[3] == 4);
373 CHECK(outdata[4] == 5);
374 CHECK(outdata[5] == 6);
375 CHECK(outdata[6] == 7);
376 CHECK(outdata[7] == 8);
Sadik Armagan2e4a24a2021-03-18 13:59:40 +0000377}
378
Sadik Armagan9150bff2021-05-26 15:40:53 +0100379}