1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #include "DriverTestHelpers.hpp"
6
7 #include "../1.0/HalPolicy.hpp"
8
9 #include <boost/test/unit_test.hpp>
10
11 #include <log/log.h>
12
13 BOOST_AUTO_TEST_SUITE(FullyConnectedTests)
14
15 using namespace android::hardware;
16 using namespace driverTestHelpers;
17 using namespace armnn_driver;
18
19 using HalPolicy = hal_1_0::HalPolicy;
20
21 // Add our own test here since we fail the fc tests which Google supplies (because of non-const weights)
BOOST_AUTO_TEST_CASE(FullyConnected)22 BOOST_AUTO_TEST_CASE(FullyConnected)
23 {
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));
28 HalPolicy::Model model = {};
29
30 // add operands
31 int32_t actValue = 0;
32 float weightValue[] = {2, 4, 1};
33 float biasValue[] = {4};
34
35 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});
40
41 // make the fully connected operation
42 model.operations.resize(1);
43 model.operations[0].type = HalPolicy::OperationType::FULLY_CONNECTED;
44 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
48 android::sp<V1_0::IPreparedModel> preparedModel = PrepareModel(model, *driver);
49
50 // construct the request
51 DataLocation inloc = {};
52 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
59 DataLocation outloc = {};
60 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
67 V1_0::Request request = {};
68 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};
73 AddPoolAndSetData<float>(3, request, indata);
74
75 // add memory for the output
76 android::sp<IMemory> outMemory = AddPoolAndGetData<float>(1, request);
77 float* outdata = static_cast<float*>(static_cast<void*>(outMemory->getPointer()));
78
79 // run the execution
80 if (preparedModel.get() != nullptr)
81 {
82 Execute(preparedModel, request);
83 }
84
85 // check the result
86 BOOST_TEST(outdata[0] == 152);
87 }
88
BOOST_AUTO_TEST_CASE(TestFullyConnected4dInput)89 BOOST_AUTO_TEST_CASE(TestFullyConnected4dInput)
90 {
91 auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
92
93 V1_0::ErrorStatus error;
94 std::vector<bool> sup;
95
96 ArmnnDriver::getSupportedOperations_cb cb = [&](V1_0::ErrorStatus status, const std::vector<bool>& supported)
97 {
98 error = status;
99 sup = supported;
100 };
101
102 HalPolicy::Model model = {};
103
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
117 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});
122
123 model.operations.resize(1);
124
125 model.operations[0].type = HalPolicy::OperationType::FULLY_CONNECTED;
126 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
130 android::sp<V1_0::IPreparedModel> preparedModel = PrepareModel(model, *driver);
131
132 // construct the request
133 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>{};
140
141 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>{};
148
149 V1_0::Request request = {};
150 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
158 android::sp<IMemory> outMemory = AddPoolAndGetData<float>(8, request);
159 float* outdata = static_cast<float*>(static_cast<void*>(outMemory->getPointer()));
160
161 // run the execution
162 if (preparedModel != nullptr)
163 {
164 Execute(preparedModel, request);
165 }
166
167 // check the result
168 BOOST_TEST(outdata[0] == 1);
169 BOOST_TEST(outdata[1] == 2);
170 BOOST_TEST(outdata[2] == 3);
171 BOOST_TEST(outdata[3] == 4);
172 BOOST_TEST(outdata[4] == 5);
173 BOOST_TEST(outdata[5] == 6);
174 BOOST_TEST(outdata[6] == 7);
175 BOOST_TEST(outdata[7] == 8);
176 }
177
BOOST_AUTO_TEST_CASE(TestFullyConnected4dInputReshape)178 BOOST_AUTO_TEST_CASE(TestFullyConnected4dInputReshape)
179 {
180 auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
181
182 V1_0::ErrorStatus error;
183 std::vector<bool> sup;
184
185 ArmnnDriver::getSupportedOperations_cb cb = [&](V1_0::ErrorStatus status, const std::vector<bool>& supported)
186 {
187 error = status;
188 sup = supported;
189 };
190
191 HalPolicy::Model model = {};
192
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
206 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});
211
212 model.operations.resize(1);
213
214 model.operations[0].type = HalPolicy::OperationType::FULLY_CONNECTED;
215 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
219 android::sp<V1_0::IPreparedModel> preparedModel = PrepareModel(model, *driver);
220
221 // construct the request
222 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>{};
229
230 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>{};
237
238 V1_0::Request request = {};
239 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
247 android::sp<IMemory> outMemory = AddPoolAndGetData<float>(8, request);
248 float* outdata = static_cast<float*>(static_cast<void*>(outMemory->getPointer()));
249
250 // run the execution
251 if (preparedModel != nullptr)
252 {
253 Execute(preparedModel, request);
254 }
255
256 // check the result
257 BOOST_TEST(outdata[0] == 1);
258 BOOST_TEST(outdata[1] == 2);
259 BOOST_TEST(outdata[2] == 3);
260 BOOST_TEST(outdata[3] == 4);
261 BOOST_TEST(outdata[4] == 5);
262 BOOST_TEST(outdata[5] == 6);
263 BOOST_TEST(outdata[6] == 7);
264 BOOST_TEST(outdata[7] == 8);
265 }
266
267 BOOST_AUTO_TEST_SUITE_END()
268