blob: 63198b4cbfc9059e056d46b57b5c48bcd7d871d6 [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"
6#include <boost/test/unit_test.hpp>
7#include <log/log.h>
8
9BOOST_AUTO_TEST_SUITE(GenericLayerTests)
10
telsoa01ce3e84a2018-08-31 09:31:35 +010011using namespace android::hardware;
surmeh0149b9e102018-05-17 14:11:25 +010012using namespace driverTestHelpers;
telsoa01ce3e84a2018-08-31 09:31:35 +010013using namespace armnn_driver;
surmeh0149b9e102018-05-17 14:11:25 +010014
15BOOST_AUTO_TEST_CASE(GetSupportedOperations)
16{
17 auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
18
telsoa01ce3e84a2018-08-31 09:31:35 +010019 ErrorStatus errorStatus;
20 std::vector<bool> supported;
surmeh0149b9e102018-05-17 14:11:25 +010021
telsoa01ce3e84a2018-08-31 09:31:35 +010022 auto cb = [&](ErrorStatus _errorStatus, const std::vector<bool>& _supported)
surmeh0149b9e102018-05-17 14:11:25 +010023 {
telsoa01ce3e84a2018-08-31 09:31:35 +010024 errorStatus = _errorStatus;
25 supported = _supported;
surmeh0149b9e102018-05-17 14:11:25 +010026 };
27
Matteo Martincigh8b287c22018-09-07 09:25:10 +010028 V1_0::Model model0 = {};
surmeh0149b9e102018-05-17 14:11:25 +010029
telsoa01ce3e84a2018-08-31 09:31:35 +010030 // Add operands
surmeh0149b9e102018-05-17 14:11:25 +010031 int32_t actValue = 0;
32 float weightValue[] = {2, 4, 1};
33 float biasValue[] = {4};
34
telsoa01ce3e84a2018-08-31 09:31:35 +010035 AddInputOperand (model0, hidl_vec<uint32_t>{1, 3});
36 AddTensorOperand(model0, hidl_vec<uint32_t>{1, 3}, weightValue);
37 AddTensorOperand(model0, hidl_vec<uint32_t>{1}, biasValue);
38 AddIntOperand (model0, actValue);
39 AddOutputOperand(model0, hidl_vec<uint32_t>{1, 1});
40
41 model0.operations.resize(1);
42
43 // Make a correct fully connected operation
Matteo Martincigh8b287c22018-09-07 09:25:10 +010044 model0.operations[0].type = V1_0::OperationType::FULLY_CONNECTED;
telsoa01ce3e84a2018-08-31 09:31:35 +010045 model0.operations[0].inputs = hidl_vec<uint32_t>{0, 1, 2, 3};
46 model0.operations[0].outputs = hidl_vec<uint32_t>{4};
47
48 driver->getSupportedOperations(model0, cb);
49 BOOST_TEST((int)errorStatus == (int)ErrorStatus::NONE);
50 BOOST_TEST(supported.size() == (size_t)1);
51 BOOST_TEST(supported[0] == true);
52
Matteo Martincigh8b287c22018-09-07 09:25:10 +010053 V1_0::Model model1 = {};
telsoa01ce3e84a2018-08-31 09:31:35 +010054
55 AddInputOperand (model1, hidl_vec<uint32_t>{1, 3});
surmeh0149b9e102018-05-17 14:11:25 +010056 AddTensorOperand(model1, hidl_vec<uint32_t>{1, 3}, weightValue);
57 AddTensorOperand(model1, hidl_vec<uint32_t>{1}, biasValue);
telsoa01ce3e84a2018-08-31 09:31:35 +010058 AddIntOperand (model1, actValue);
surmeh0149b9e102018-05-17 14:11:25 +010059 AddOutputOperand(model1, hidl_vec<uint32_t>{1, 1});
60
surmeh0149b9e102018-05-17 14:11:25 +010061 model1.operations.resize(2);
telsoa01ce3e84a2018-08-31 09:31:35 +010062
63 // Make a correct fully connected operation
Matteo Martincigh8b287c22018-09-07 09:25:10 +010064 model1.operations[0].type = V1_0::OperationType::FULLY_CONNECTED;
surmeh0149b9e102018-05-17 14:11:25 +010065 model1.operations[0].inputs = hidl_vec<uint32_t>{0, 1, 2, 3};
66 model1.operations[0].outputs = hidl_vec<uint32_t>{4};
67
telsoa01ce3e84a2018-08-31 09:31:35 +010068 // Add an incorrect fully connected operation
69 AddIntOperand (model1, actValue);
surmeh0149b9e102018-05-17 14:11:25 +010070 AddOutputOperand(model1, hidl_vec<uint32_t>{1, 1});
Matteo Martincigh8b287c22018-09-07 09:25:10 +010071 model1.operations[1].type = V1_0::OperationType::FULLY_CONNECTED;
telsoa01ce3e84a2018-08-31 09:31:35 +010072 model1.operations[1].inputs = hidl_vec<uint32_t>{4}; // Only 1 input operand, expected 4
surmeh0149b9e102018-05-17 14:11:25 +010073 model1.operations[1].outputs = hidl_vec<uint32_t>{5};
74
75 driver->getSupportedOperations(model1, cb);
surmeh0149b9e102018-05-17 14:11:25 +010076
telsoa01ce3e84a2018-08-31 09:31:35 +010077#if defined(ARMNN_ANDROID_P)
78 // In Android P, android::nn::validateModel returns INVALID_ARGUMENT, because of the wrong number of inputs for the
79 // fully connected layer (1 instead of 4)
80 BOOST_TEST((int)errorStatus == (int)ErrorStatus::INVALID_ARGUMENT);
81 BOOST_TEST(supported.empty());
82#else
83 // In Android O, android::nn::validateModel indicates that the second (wrong) fully connected layer in unsupported
84 // in the vector of flags returned by the callback
85 BOOST_TEST((int)errorStatus == (int)ErrorStatus::NONE);
86 BOOST_TEST(supported.size() == (size_t)2);
87 BOOST_TEST(supported[0] == true);
88 BOOST_TEST(supported[1] == false);
89#endif
surmeh0149b9e102018-05-17 14:11:25 +010090
telsoa01ce3e84a2018-08-31 09:31:35 +010091 // Test Broadcast on add/mul operators
Matteo Martincigh8b287c22018-09-07 09:25:10 +010092 V1_0::Model model2 = {};
telsoa01ce3e84a2018-08-31 09:31:35 +010093
94 AddInputOperand (model2, hidl_vec<uint32_t>{1, 1, 3, 4});
95 AddInputOperand (model2, hidl_vec<uint32_t>{4});
96 AddIntOperand (model2, actValue);
surmeh0149b9e102018-05-17 14:11:25 +010097 AddOutputOperand(model2, hidl_vec<uint32_t>{1, 1, 3, 4});
98 AddOutputOperand(model2, hidl_vec<uint32_t>{1, 1, 3, 4});
99
100 model2.operations.resize(2);
101
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100102 model2.operations[0].type = V1_0::OperationType::ADD;
telsoa01ce3e84a2018-08-31 09:31:35 +0100103 model2.operations[0].inputs = hidl_vec<uint32_t>{0, 1, 2};
104 model2.operations[0].outputs = hidl_vec<uint32_t>{3};
surmeh0149b9e102018-05-17 14:11:25 +0100105
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100106 model2.operations[1].type = V1_0::OperationType::MUL;
telsoa01ce3e84a2018-08-31 09:31:35 +0100107 model2.operations[1].inputs = hidl_vec<uint32_t>{0, 1, 2};
108 model2.operations[1].outputs = hidl_vec<uint32_t>{4};
surmeh0149b9e102018-05-17 14:11:25 +0100109
110 driver->getSupportedOperations(model2, cb);
telsoa01ce3e84a2018-08-31 09:31:35 +0100111 BOOST_TEST((int)errorStatus == (int)ErrorStatus::NONE);
112 BOOST_TEST(supported.size() == (size_t)2);
113 BOOST_TEST(supported[0] == true);
114 BOOST_TEST(supported[1] == true);
surmeh0149b9e102018-05-17 14:11:25 +0100115
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100116 V1_0::Model model3 = {};
telsoa01ce3e84a2018-08-31 09:31:35 +0100117
118 AddInputOperand (model3, hidl_vec<uint32_t>{1, 1, 1, 8});
119 AddIntOperand (model3, 2);
120 AddOutputOperand(model3, hidl_vec<uint32_t>{1, 2, 2, 2});
121
122 model3.operations.resize(1);
surmeh0149b9e102018-05-17 14:11:25 +0100123
124 // Add unsupported operation, should return no error but we don't support it
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100125 model3.operations[0].type = V1_0::OperationType::DEPTH_TO_SPACE;
telsoa01ce3e84a2018-08-31 09:31:35 +0100126 model3.operations[0].inputs = hidl_vec<uint32_t>{0, 1};
surmeh0149b9e102018-05-17 14:11:25 +0100127 model3.operations[0].outputs = hidl_vec<uint32_t>{2};
128
129 driver->getSupportedOperations(model3, cb);
telsoa01ce3e84a2018-08-31 09:31:35 +0100130 BOOST_TEST((int)errorStatus == (int)ErrorStatus::NONE);
131 BOOST_TEST(supported.size() == (size_t)1);
132 BOOST_TEST(supported[0] == false);
133
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100134 V1_0::Model model4 = {};
telsoa01ce3e84a2018-08-31 09:31:35 +0100135
136 AddIntOperand(model4, 0);
137
138 model4.operations.resize(1);
surmeh0149b9e102018-05-17 14:11:25 +0100139
140 // Add invalid operation
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100141 model4.operations[0].type = static_cast<V1_0::OperationType>(100);
surmeh0149b9e102018-05-17 14:11:25 +0100142 model4.operations[0].outputs = hidl_vec<uint32_t>{0};
143
144 driver->getSupportedOperations(model4, cb);
telsoa01ce3e84a2018-08-31 09:31:35 +0100145 BOOST_TEST((int)errorStatus == (int)ErrorStatus::INVALID_ARGUMENT);
146 BOOST_TEST(supported.empty());
surmeh0149b9e102018-05-17 14:11:25 +0100147}
148
149// The purpose of this test is to ensure that when encountering an unsupported operation
telsoa01ce3e84a2018-08-31 09:31:35 +0100150// it is skipped and getSupportedOperations() continues (rather than failing and stopping).
151// As per IVGCVSW-710.
surmeh0149b9e102018-05-17 14:11:25 +0100152BOOST_AUTO_TEST_CASE(UnsupportedLayerContinueOnFailure)
153{
154 auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
155
telsoa01ce3e84a2018-08-31 09:31:35 +0100156 ErrorStatus errorStatus;
157 std::vector<bool> supported;
surmeh0149b9e102018-05-17 14:11:25 +0100158
telsoa01ce3e84a2018-08-31 09:31:35 +0100159 auto cb = [&](ErrorStatus _errorStatus, const std::vector<bool>& _supported)
surmeh0149b9e102018-05-17 14:11:25 +0100160 {
telsoa01ce3e84a2018-08-31 09:31:35 +0100161 errorStatus = _errorStatus;
162 supported = _supported;
surmeh0149b9e102018-05-17 14:11:25 +0100163 };
164
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100165 V1_0::Model model = {};
surmeh0149b9e102018-05-17 14:11:25 +0100166
telsoa01ce3e84a2018-08-31 09:31:35 +0100167 // Operands
surmeh0149b9e102018-05-17 14:11:25 +0100168 int32_t actValue = 0;
169 float weightValue[] = {2, 4, 1};
170 float biasValue[] = {4};
171
telsoa01ce3e84a2018-08-31 09:31:35 +0100172 // HASHTABLE_LOOKUP is unsupported at the time of writing this test, but any unsupported layer will do
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100173 AddInputOperand (model, hidl_vec<uint32_t>{1, 1, 3, 4}, V1_0::OperandType::TENSOR_INT32);
174 AddInputOperand (model, hidl_vec<uint32_t>{4}, V1_0::OperandType::TENSOR_INT32);
telsoa01ce3e84a2018-08-31 09:31:35 +0100175 AddInputOperand (model, hidl_vec<uint32_t>{1, 1, 3, 4});
surmeh0149b9e102018-05-17 14:11:25 +0100176 AddOutputOperand(model, hidl_vec<uint32_t>{1, 1, 3, 4});
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100177 AddOutputOperand(model, hidl_vec<uint32_t>{1, 1, 3, 4}, V1_0::OperandType::TENSOR_QUANT8_ASYMM);
surmeh0149b9e102018-05-17 14:11:25 +0100178
telsoa01ce3e84a2018-08-31 09:31:35 +0100179 // Fully connected is supported
180 AddInputOperand (model, hidl_vec<uint32_t>{1, 3});
surmeh0149b9e102018-05-17 14:11:25 +0100181 AddTensorOperand(model, hidl_vec<uint32_t>{1, 3}, weightValue);
182 AddTensorOperand(model, hidl_vec<uint32_t>{1}, biasValue);
telsoa01ce3e84a2018-08-31 09:31:35 +0100183 AddIntOperand (model, actValue);
surmeh0149b9e102018-05-17 14:11:25 +0100184 AddOutputOperand(model, hidl_vec<uint32_t>{1, 1});
185
telsoa01ce3e84a2018-08-31 09:31:35 +0100186 // EMBEDDING_LOOKUP is unsupported
surmeh0149b9e102018-05-17 14:11:25 +0100187 AddOutputOperand(model, hidl_vec<uint32_t>{1, 1, 3, 4});
188
189 model.operations.resize(3);
190
telsoa01ce3e84a2018-08-31 09:31:35 +0100191 // Unsupported
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100192 model.operations[0].type = V1_0::OperationType::HASHTABLE_LOOKUP;
telsoa01ce3e84a2018-08-31 09:31:35 +0100193 model.operations[0].inputs = hidl_vec<uint32_t>{0, 1, 2};
194 model.operations[0].outputs = hidl_vec<uint32_t>{3, 4};
surmeh0149b9e102018-05-17 14:11:25 +0100195
telsoa01ce3e84a2018-08-31 09:31:35 +0100196 // Supported
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100197 model.operations[1].type = V1_0::OperationType::FULLY_CONNECTED;
telsoa01ce3e84a2018-08-31 09:31:35 +0100198 model.operations[1].inputs = hidl_vec<uint32_t>{5, 6, 7, 8};
199 model.operations[1].outputs = hidl_vec<uint32_t>{9};
surmeh0149b9e102018-05-17 14:11:25 +0100200
telsoa01ce3e84a2018-08-31 09:31:35 +0100201 // Unsupported
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100202 model.operations[2].type = V1_0::OperationType::EMBEDDING_LOOKUP;
telsoa01ce3e84a2018-08-31 09:31:35 +0100203 model.operations[2].inputs = hidl_vec<uint32_t>{1, 2};
204 model.operations[2].outputs = hidl_vec<uint32_t>{10};
surmeh0149b9e102018-05-17 14:11:25 +0100205
telsoa01ce3e84a2018-08-31 09:31:35 +0100206 // We are testing that the unsupported layers return false and the test continues rather than failing and stopping
surmeh0149b9e102018-05-17 14:11:25 +0100207 driver->getSupportedOperations(model, cb);
telsoa01ce3e84a2018-08-31 09:31:35 +0100208 BOOST_TEST((int)errorStatus == (int)ErrorStatus::NONE);
209 BOOST_TEST(supported.size() == (size_t)3);
210 BOOST_TEST(supported[0] == false);
211 BOOST_TEST(supported[1] == true);
212 BOOST_TEST(supported[2] == false);
surmeh0149b9e102018-05-17 14:11:25 +0100213}
214
215// The purpose of this test is to ensure that when encountering an failure
telsoa01ce3e84a2018-08-31 09:31:35 +0100216// during mem pool mapping we properly report an error to the framework via a callback
surmeh0149b9e102018-05-17 14:11:25 +0100217BOOST_AUTO_TEST_CASE(ModelToINetworkConverterMemPoolFail)
218{
Nikhil Raj77605822018-09-03 11:25:56 +0100219 auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
surmeh0149b9e102018-05-17 14:11:25 +0100220
telsoa01ce3e84a2018-08-31 09:31:35 +0100221 ErrorStatus errorStatus;
222 std::vector<bool> supported;
surmeh0149b9e102018-05-17 14:11:25 +0100223
telsoa01ce3e84a2018-08-31 09:31:35 +0100224 auto cb = [&](ErrorStatus _errorStatus, const std::vector<bool>& _supported)
surmeh0149b9e102018-05-17 14:11:25 +0100225 {
telsoa01ce3e84a2018-08-31 09:31:35 +0100226 errorStatus = _errorStatus;
227 supported = _supported;
surmeh0149b9e102018-05-17 14:11:25 +0100228 };
229
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100230 V1_0::Model model = {};
surmeh0149b9e102018-05-17 14:11:25 +0100231
232 model.pools = hidl_vec<hidl_memory>{hidl_memory("Unsuported hidl memory type", nullptr, 0)};
233
telsoa01ce3e84a2018-08-31 09:31:35 +0100234 // Memory pool mapping should fail, we should report an error
surmeh0149b9e102018-05-17 14:11:25 +0100235 driver->getSupportedOperations(model, cb);
telsoa01ce3e84a2018-08-31 09:31:35 +0100236 BOOST_TEST((int)errorStatus != (int)ErrorStatus::NONE);
237 BOOST_TEST(supported.empty());
surmeh0149b9e102018-05-17 14:11:25 +0100238}
239
240BOOST_AUTO_TEST_SUITE_END()