1 //
2 // Copyright © 2017,2020-2023 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include "../Serializer.hpp"
7 #include "SerializerTestUtils.hpp"
8
9 #include <armnn/Descriptors.hpp>
10 #include <armnn/INetwork.hpp>
11 #include <armnn/TypesUtils.hpp>
12 #include <armnn/LstmParams.hpp>
13 #include <armnn/QuantizedLstmParams.hpp>
14 #include <armnnDeserializer/IDeserializer.hpp>
15 #include <armnn/utility/IgnoreUnused.hpp>
16
17 #include <random>
18 #include <vector>
19
20 #include <doctest/doctest.h>
21
22 using armnnDeserializer::IDeserializer;
23
24 TEST_SUITE("SerializerTests")
25 {
26
27 TEST_CASE("SerializeAddition")
28 {
29 const std::string layerName("addition");
30 const armnn::TensorInfo tensorInfo({1, 2, 3}, armnn::DataType::Float32);
31
32 armnn::INetworkPtr network = armnn::INetwork::Create();
33 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
34 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
35 ARMNN_NO_DEPRECATE_WARN_BEGIN
36 armnn::IConnectableLayer* const additionLayer = network->AddAdditionLayer(layerName.c_str());
37 ARMNN_NO_DEPRECATE_WARN_END
38 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
39
40 inputLayer0->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(0));
41 inputLayer1->GetOutputSlot(0).Connect(additionLayer->GetInputSlot(1));
42 additionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
43
44 inputLayer0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
45 inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
46 additionLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
47
48 std::string serializedNetwork = SerializeNetwork(*network);
49 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(serializedNetwork);
50 CHECK(deserializedNetwork);
51
52 LayerVerifierBase verifier(layerName, {tensorInfo, tensorInfo}, {tensorInfo});
53 deserializedNetwork->ExecuteStrategy(verifier);
54 }
55
SerializeArgMinMaxTest(armnn::DataType dataType)56 void SerializeArgMinMaxTest(armnn::DataType dataType)
57 {
58 const std::string layerName("argminmax");
59 const armnn::TensorInfo inputInfo({1, 2, 3}, armnn::DataType::Float32);
60 const armnn::TensorInfo outputInfo({1, 3}, dataType);
61
62 armnn::ArgMinMaxDescriptor descriptor;
63 descriptor.m_Function = armnn::ArgMinMaxFunction::Max;
64 descriptor.m_Axis = 1;
65
66 armnn::INetworkPtr network = armnn::INetwork::Create();
67 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
68 armnn::IConnectableLayer* const argMinMaxLayer = network->AddArgMinMaxLayer(descriptor, layerName.c_str());
69 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
70
71 inputLayer->GetOutputSlot(0).Connect(argMinMaxLayer->GetInputSlot(0));
72 argMinMaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
73
74 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
75 argMinMaxLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
76
77 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
78 CHECK(deserializedNetwork);
79
80 LayerVerifierBaseWithDescriptor<armnn::ArgMinMaxDescriptor> verifier(layerName,
81 {inputInfo},
82 {outputInfo},
83 descriptor);
84 deserializedNetwork->ExecuteStrategy(verifier);
85 }
86
87 TEST_CASE("SerializeArgMinMaxSigned32")
88 {
89 SerializeArgMinMaxTest(armnn::DataType::Signed32);
90 }
91
92 TEST_CASE("SerializeArgMinMaxSigned64")
93 {
94 SerializeArgMinMaxTest(armnn::DataType::Signed64);
95 }
96
97 TEST_CASE("SerializeBatchMatMul")
98 {
99 const std::string layerName("batchMatMul");
100 const armnn::TensorInfo inputXInfo({2, 3, 4, 5}, armnn::DataType::Float32);
101 const armnn::TensorInfo inputYInfo({2, 4, 3, 5}, armnn::DataType::Float32);
102
103 const armnn::TensorInfo outputInfo({2, 3, 3, 5}, armnn::DataType::Float32);
104
105 armnn::BatchMatMulDescriptor descriptor(false,
106 false,
107 false,
108 false,
109 armnn::DataLayout::NHWC,
110 armnn::DataLayout::NHWC);
111
112 armnn::INetworkPtr network = armnn::INetwork::Create();
113 armnn::IConnectableLayer* const inputXLayer = network->AddInputLayer(0);
114 armnn::IConnectableLayer* const inputYLayer = network->AddInputLayer(1);
115
116 armnn::IConnectableLayer* const batchMatMulLayer =
117 network->AddBatchMatMulLayer(descriptor, layerName.c_str());
118 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
119
120 inputXLayer->GetOutputSlot(0).Connect(batchMatMulLayer->GetInputSlot(0));
121 inputYLayer->GetOutputSlot(0).Connect(batchMatMulLayer->GetInputSlot(1));
122 batchMatMulLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
123
124 inputXLayer->GetOutputSlot(0).SetTensorInfo(inputXInfo);
125 inputYLayer->GetOutputSlot(0).SetTensorInfo(inputYInfo);
126 batchMatMulLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
127
128 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
129 CHECK(deserializedNetwork);
130
131 LayerVerifierBaseWithDescriptor<armnn::BatchMatMulDescriptor> verifier(layerName,
132 {inputXInfo, inputYInfo},
133 {outputInfo},
134 descriptor);
135 deserializedNetwork->ExecuteStrategy(verifier);
136 }
137
138 TEST_CASE("SerializeBatchNormalization")
139 {
140 const std::string layerName("batchNormalization");
141 const armnn::TensorInfo inputInfo ({ 1, 3, 3, 1 }, armnn::DataType::Float32);
142 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
143
144 const armnn::TensorInfo meanInfo({1}, armnn::DataType::Float32, 0.0f, 0, true);
145 const armnn::TensorInfo varianceInfo({1}, armnn::DataType::Float32, 0.0f, 0, true);
146 const armnn::TensorInfo betaInfo({1}, armnn::DataType::Float32, 0.0f, 0, true);
147 const armnn::TensorInfo gammaInfo({1}, armnn::DataType::Float32, 0.0f, 0, true);
148
149 armnn::BatchNormalizationDescriptor descriptor;
150 descriptor.m_Eps = 0.0010000000475f;
151 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
152
153 std::vector<float> meanData({5.0});
154 std::vector<float> varianceData({2.0});
155 std::vector<float> betaData({1.0});
156 std::vector<float> gammaData({0.0});
157
158 std::vector<armnn::ConstTensor> constants;
159 constants.emplace_back(armnn::ConstTensor(meanInfo, meanData));
160 constants.emplace_back(armnn::ConstTensor(varianceInfo, varianceData));
161 constants.emplace_back(armnn::ConstTensor(betaInfo, betaData));
162 constants.emplace_back(armnn::ConstTensor(gammaInfo, gammaData));
163
164 armnn::INetworkPtr network = armnn::INetwork::Create();
165 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
166 armnn::IConnectableLayer* const batchNormalizationLayer =
167 network->AddBatchNormalizationLayer(descriptor,
168 constants[0],
169 constants[1],
170 constants[2],
171 constants[3],
172 layerName.c_str());
173 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
174
175 inputLayer->GetOutputSlot(0).Connect(batchNormalizationLayer->GetInputSlot(0));
176 batchNormalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
177
178 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
179 batchNormalizationLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
180
181 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
182 CHECK(deserializedNetwork);
183
184 LayerVerifierBaseWithDescriptorAndConstants<armnn::BatchNormalizationDescriptor> verifier(
185 layerName, {inputInfo}, {outputInfo}, descriptor, constants);
186 deserializedNetwork->ExecuteStrategy(verifier);
187 }
188
189 TEST_CASE("SerializeBatchToSpaceNd")
190 {
191 const std::string layerName("spaceToBatchNd");
192 const armnn::TensorInfo inputInfo({4, 1, 2, 2}, armnn::DataType::Float32);
193 const armnn::TensorInfo outputInfo({1, 1, 4, 4}, armnn::DataType::Float32);
194
195 armnn::BatchToSpaceNdDescriptor desc;
196 desc.m_DataLayout = armnn::DataLayout::NCHW;
197 desc.m_BlockShape = {2, 2};
198 desc.m_Crops = {{0, 0}, {0, 0}};
199
200 armnn::INetworkPtr network = armnn::INetwork::Create();
201 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
202 armnn::IConnectableLayer* const batchToSpaceNdLayer = network->AddBatchToSpaceNdLayer(desc, layerName.c_str());
203 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
204
205 inputLayer->GetOutputSlot(0).Connect(batchToSpaceNdLayer->GetInputSlot(0));
206 batchToSpaceNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
207
208 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
209 batchToSpaceNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
210
211 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
212 CHECK(deserializedNetwork);
213
214 LayerVerifierBaseWithDescriptor<armnn::BatchToSpaceNdDescriptor> verifier(layerName,
215 {inputInfo},
216 {outputInfo},
217 desc);
218 deserializedNetwork->ExecuteStrategy(verifier);
219 }
220
221 TEST_CASE("SerializeCast")
222 {
223 const std::string layerName("cast");
224
225 const armnn::TensorShape shape{1, 5, 2, 3};
226
227 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Signed32);
228 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
229
230 armnn::INetworkPtr network = armnn::INetwork::Create();
231 armnn::IConnectableLayer* inputLayer = network->AddInputLayer(0);
232 armnn::IConnectableLayer* castLayer = network->AddCastLayer(layerName.c_str());
233 armnn::IConnectableLayer* outputLayer = network->AddOutputLayer(0);
234
235 inputLayer->GetOutputSlot(0).Connect(castLayer->GetInputSlot(0));
236 castLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
237
238 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
239 castLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
240
241 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
242 CHECK(deserializedNetwork);
243
244 LayerVerifierBase verifier(layerName, {inputInfo}, {outputInfo});
245 deserializedNetwork->ExecuteStrategy(verifier);
246 }
247
248 TEST_CASE("SerializeChannelShuffle")
249 {
250 const std::string layerName("channelShuffle");
251 const armnn::TensorInfo inputInfo({1, 9}, armnn::DataType::Float32);
252 const armnn::TensorInfo outputInfo({1, 9}, armnn::DataType::Float32);
253
254 armnn::ChannelShuffleDescriptor descriptor({3, 1});
255
256 armnn::INetworkPtr network = armnn::INetwork::Create();
257 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
258 armnn::IConnectableLayer* const ChannelShuffleLayer =
259 network->AddChannelShuffleLayer(descriptor, layerName.c_str());
260 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
261
262 inputLayer->GetOutputSlot(0).Connect(ChannelShuffleLayer->GetInputSlot(0));
263 ChannelShuffleLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
264
265 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
266 ChannelShuffleLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
267
268 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
269 CHECK(deserializedNetwork);
270
271 LayerVerifierBaseWithDescriptor<armnn::ChannelShuffleDescriptor> verifier(
272 layerName, {inputInfo}, {outputInfo}, descriptor);
273 deserializedNetwork->ExecuteStrategy(verifier);
274 }
275
276 TEST_CASE("SerializeComparison")
277 {
278 const std::string layerName("comparison");
279
280 const armnn::TensorShape shape{2, 1, 2, 4};
281
282 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
283 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
284
285 armnn::ComparisonDescriptor descriptor(armnn::ComparisonOperation::NotEqual);
286
287 armnn::INetworkPtr network = armnn::INetwork::Create();
288 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
289 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
290 armnn::IConnectableLayer* const comparisonLayer = network->AddComparisonLayer(descriptor, layerName.c_str());
291 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
292
293 inputLayer0->GetOutputSlot(0).Connect(comparisonLayer->GetInputSlot(0));
294 inputLayer1->GetOutputSlot(0).Connect(comparisonLayer->GetInputSlot(1));
295 comparisonLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
296
297 inputLayer0->GetOutputSlot(0).SetTensorInfo(inputInfo);
298 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputInfo);
299 comparisonLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
300
301 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
302 CHECK(deserializedNetwork);
303
304 LayerVerifierBaseWithDescriptor<armnn::ComparisonDescriptor> verifier(layerName,
305 { inputInfo, inputInfo },
306 { outputInfo },
307 descriptor);
308 deserializedNetwork->ExecuteStrategy(verifier);
309 }
310
311 TEST_CASE("SerializeConstant")
312 {
313 class ConstantLayerVerifier : public LayerVerifierBase
314 {
315 public:
ConstantLayerVerifier(const std::string & layerName,const std::vector<armnn::TensorInfo> & inputInfos,const std::vector<armnn::TensorInfo> & outputInfos,const std::vector<armnn::ConstTensor> & constants)316 ConstantLayerVerifier(const std::string& layerName,
317 const std::vector<armnn::TensorInfo>& inputInfos,
318 const std::vector<armnn::TensorInfo>& outputInfos,
319 const std::vector<armnn::ConstTensor>& constants)
320 : LayerVerifierBase(layerName, inputInfos, outputInfos)
321 , m_Constants(constants) {}
322
ExecuteStrategy(const armnn::IConnectableLayer * layer,const armnn::BaseDescriptor & descriptor,const std::vector<armnn::ConstTensor> & constants,const char * name,const armnn::LayerBindingId id=0)323 void ExecuteStrategy(const armnn::IConnectableLayer* layer,
324 const armnn::BaseDescriptor& descriptor,
325 const std::vector<armnn::ConstTensor>& constants,
326 const char* name,
327 const armnn::LayerBindingId id = 0) override
328 {
329 armnn::IgnoreUnused(descriptor, id);
330
331 switch (layer->GetType())
332 {
333 case armnn::LayerType::Input: break;
334 case armnn::LayerType::Output: break;
335 case armnn::LayerType::Addition: break;
336 case armnn::LayerType::ElementwiseBinary: break;
337 default:
338 {
339 this->VerifyNameAndConnections(layer, name);
340
341 for (std::size_t i = 0; i < constants.size(); i++)
342 {
343 CompareConstTensor(constants[i], m_Constants[i]);
344 }
345 }
346 }
347 }
348
349 private:
350 const std::vector<armnn::ConstTensor> m_Constants;
351 };
352
353 const std::string layerName("constant");
354 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32, 0.0f, 0, true);
355
356 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
357 armnn::ConstTensor constTensor(info, constantData);
358
359 armnn::INetworkPtr network(armnn::INetwork::Create());
360 armnn::IConnectableLayer* input = network->AddInputLayer(0);
361 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
362 ARMNN_NO_DEPRECATE_WARN_BEGIN
363 armnn::IConnectableLayer* add = network->AddAdditionLayer();
364 ARMNN_NO_DEPRECATE_WARN_END
365 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
366
367 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
368 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
369 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
370
371 input->GetOutputSlot(0).SetTensorInfo(info);
372 constant->GetOutputSlot(0).SetTensorInfo(info);
373 add->GetOutputSlot(0).SetTensorInfo(info);
374
375 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
376 CHECK(deserializedNetwork);
377
378 ConstantLayerVerifier verifier(layerName, {}, {info}, {constTensor});
379 deserializedNetwork->ExecuteStrategy(verifier);
380 }
381
382 using Convolution2dDescriptor = armnn::Convolution2dDescriptor;
383 class Convolution2dLayerVerifier : public LayerVerifierBaseWithDescriptor<Convolution2dDescriptor>
384 {
385 public:
Convolution2dLayerVerifier(const std::string & layerName,const std::vector<armnn::TensorInfo> & inputInfos,const std::vector<armnn::TensorInfo> & outputInfos,const Convolution2dDescriptor & descriptor)386 Convolution2dLayerVerifier(const std::string& layerName,
387 const std::vector<armnn::TensorInfo>& inputInfos,
388 const std::vector<armnn::TensorInfo>& outputInfos,
389 const Convolution2dDescriptor& descriptor)
390 : LayerVerifierBaseWithDescriptor<Convolution2dDescriptor>(layerName, inputInfos, outputInfos, descriptor) {}
391
ExecuteStrategy(const armnn::IConnectableLayer * layer,const armnn::BaseDescriptor & descriptor,const std::vector<armnn::ConstTensor> & constants,const char * name,const armnn::LayerBindingId id=0)392 void ExecuteStrategy(const armnn::IConnectableLayer* layer,
393 const armnn::BaseDescriptor& descriptor,
394 const std::vector<armnn::ConstTensor>& constants,
395 const char* name,
396 const armnn::LayerBindingId id = 0) override
397 {
398 armnn::IgnoreUnused(constants, id);
399 switch (layer->GetType())
400 {
401 case armnn::LayerType::Input: break;
402 case armnn::LayerType::Output: break;
403 case armnn::LayerType::Constant: break;
404 default:
405 {
406 VerifyNameAndConnections(layer, name);
407 const Convolution2dDescriptor& layerDescriptor =
408 static_cast<const Convolution2dDescriptor&>(descriptor);
409 CHECK(layerDescriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
410 }
411 }
412 }
413 };
414
415 TEST_CASE("SerializeConvolution2d")
416 {
417 const std::string layerName("convolution2d");
418 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32);
419 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
420
421 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32, 0.0f, 0, true);
422 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32, 0.0f, 0, true);
423
424 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
425 armnn::ConstTensor weights(weightsInfo, weightsData);
426
427 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
428 armnn::ConstTensor biases(biasesInfo, biasesData);
429
430 armnn::Convolution2dDescriptor descriptor;
431 descriptor.m_PadLeft = 1;
432 descriptor.m_PadRight = 1;
433 descriptor.m_PadTop = 1;
434 descriptor.m_PadBottom = 1;
435 descriptor.m_StrideX = 2;
436 descriptor.m_StrideY = 2;
437 descriptor.m_DilationX = 2;
438 descriptor.m_DilationY = 2;
439 descriptor.m_BiasEnabled = true;
440 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
441
442 armnn::INetworkPtr network = armnn::INetwork::Create();
443 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
444 armnn::IConnectableLayer* const weightsLayer = network->AddConstantLayer(weights, "weights");
445 armnn::IConnectableLayer* const biasLayer = network->AddConstantLayer(biases, "bias");
446 armnn::IConnectableLayer* const convLayer = network->AddConvolution2dLayer(descriptor, layerName.c_str());
447 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
448
449 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
450 weightsLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(1));
451 biasLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(2));
452 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
453
454 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
455 weightsLayer->GetOutputSlot(0).SetTensorInfo(weightsInfo);
456 biasLayer->GetOutputSlot(0).SetTensorInfo(biasesInfo);
457 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
458
459 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
460 CHECK(deserializedNetwork);
461
462 Convolution2dLayerVerifier verifier(layerName, {inputInfo, weightsInfo, biasesInfo}, {outputInfo}, descriptor);
463 deserializedNetwork->ExecuteStrategy(verifier);
464 }
465
466 TEST_CASE("SerializeConvolution2dWithPerAxisParams")
467 {
468 using namespace armnn;
469
470 const std::string layerName("convolution2dWithPerAxis");
471 const TensorInfo inputInfo ({ 1, 3, 1, 2 }, DataType::QAsymmU8, 0.55f, 128);
472 const TensorInfo outputInfo({ 1, 3, 1, 3 }, DataType::QAsymmU8, 0.75f, 128);
473
474 const std::vector<float> quantScales{ 0.75f, 0.65f, 0.85f };
475 constexpr unsigned int quantDimension = 0;
476
477 const TensorInfo kernelInfo({ 3, 1, 1, 2 }, DataType::QSymmS8, quantScales, quantDimension, true);
478
479 const std::vector<float> biasQuantScales{ 0.25f, 0.50f, 0.75f };
480 const TensorInfo biasInfo({ 3 }, DataType::Signed32, biasQuantScales, quantDimension, true);
481
482 std::vector<int8_t> kernelData = GenerateRandomData<int8_t>(kernelInfo.GetNumElements());
483 armnn::ConstTensor weights(kernelInfo, kernelData);
484 std::vector<int32_t> biasData = GenerateRandomData<int32_t>(biasInfo.GetNumElements());
485 armnn::ConstTensor biases(biasInfo, biasData);
486
487 Convolution2dDescriptor descriptor;
488 descriptor.m_StrideX = 1;
489 descriptor.m_StrideY = 1;
490 descriptor.m_PadLeft = 0;
491 descriptor.m_PadRight = 0;
492 descriptor.m_PadTop = 0;
493 descriptor.m_PadBottom = 0;
494 descriptor.m_BiasEnabled = true;
495 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
496
497 armnn::INetworkPtr network = armnn::INetwork::Create();
498 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
499 armnn::IConnectableLayer* const weightsLayer = network->AddConstantLayer(weights, "weights");
500 armnn::IConnectableLayer* const biasLayer = network->AddConstantLayer(weights, "bias");
501 armnn::IConnectableLayer* const convLayer = network->AddConvolution2dLayer(descriptor, layerName.c_str());
502 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
503
504 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
505 weightsLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(1));
506 biasLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(2));
507 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
508
509 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
510 weightsLayer->GetOutputSlot(0).SetTensorInfo(kernelInfo);
511 biasLayer->GetOutputSlot(0).SetTensorInfo(biasInfo);
512 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
513
514 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
515 CHECK(deserializedNetwork);
516
517 Convolution2dLayerVerifier verifier(layerName, {inputInfo, kernelInfo, biasInfo}, {outputInfo}, descriptor);
518
519 deserializedNetwork->ExecuteStrategy(verifier);
520 }
521
522 TEST_CASE("SerializeConvolution2dWeightsAndBiasesAsConstantLayers")
523 {
524 const std::string layerName("convolution2d");
525 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32);
526 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
527
528 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32, 0.0f, 0, true);
529 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32, 0.0f, 0, true);
530
531 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
532 armnn::ConstTensor weights(weightsInfo, weightsData);
533
534 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
535 armnn::ConstTensor biases(biasesInfo, biasesData);
536
537 armnn::Convolution2dDescriptor descriptor;
538 descriptor.m_PadLeft = 1;
539 descriptor.m_PadRight = 1;
540 descriptor.m_PadTop = 1;
541 descriptor.m_PadBottom = 1;
542 descriptor.m_StrideX = 2;
543 descriptor.m_StrideY = 2;
544 descriptor.m_DilationX = 2;
545 descriptor.m_DilationY = 2;
546 descriptor.m_BiasEnabled = true;
547 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
548
549 armnn::INetworkPtr network = armnn::INetwork::Create();
550 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
551 armnn::IConnectableLayer* const weightsLayer = network->AddConstantLayer(weights, "Weights");
552 armnn::IConnectableLayer* const biasesLayer = network->AddConstantLayer(biases, "Biases");
553 armnn::IConnectableLayer* const convLayer = network->AddConvolution2dLayer(descriptor,
554 layerName.c_str());
555 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
556
557 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
558 weightsLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(1));
559 biasesLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(2));
560 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
561
562 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
563 weightsLayer->GetOutputSlot(0).SetTensorInfo(weightsInfo);
564 biasesLayer->GetOutputSlot(0).SetTensorInfo(biasesInfo);
565 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
566
567 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
568 CHECK(deserializedNetwork);
569
570 const std::vector<armnn::ConstTensor>& constants {weights, biases};
571 LayerVerifierBaseWithDescriptorAndConstants<armnn::Convolution2dDescriptor> verifier(
572 layerName, {inputInfo, weightsInfo, biasesInfo}, {outputInfo}, descriptor, constants);
573
574 deserializedNetwork->ExecuteStrategy(verifier);
575 }
576
577 TEST_CASE("SerializeConvolution3d")
578 {
579 const std::string layerName("convolution3d");
580 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 5, 1 }, armnn::DataType::Float32);
581 const armnn::TensorInfo outputInfo({ 1, 2, 2, 2, 1 }, armnn::DataType::Float32);
582
583 const armnn::TensorInfo weightsInfo({ 3, 3, 3, 1, 1 }, armnn::DataType::Float32, 0.0f, 0, true);
584 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32, 0.0f, 0, true);
585
586 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
587 armnn::ConstTensor weights(weightsInfo, weightsData);
588
589 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
590 armnn::ConstTensor biases(biasesInfo, biasesData);
591
592 armnn::Convolution3dDescriptor descriptor;
593 descriptor.m_PadLeft = 0;
594 descriptor.m_PadRight = 0;
595 descriptor.m_PadTop = 0;
596 descriptor.m_PadBottom = 0;
597 descriptor.m_PadFront = 0;
598 descriptor.m_PadBack = 0;
599 descriptor.m_DilationX = 1;
600 descriptor.m_DilationY = 1;
601 descriptor.m_DilationZ = 1;
602 descriptor.m_StrideX = 2;
603 descriptor.m_StrideY = 2;
604 descriptor.m_StrideZ = 2;
605 descriptor.m_BiasEnabled = true;
606 descriptor.m_DataLayout = armnn::DataLayout::NDHWC;
607
608 armnn::INetworkPtr network = armnn::INetwork::Create();
609 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
610 armnn::IConnectableLayer* const weightsLayer = network->AddConstantLayer(weights, "Weights");
611 armnn::IConnectableLayer* const biasesLayer = network->AddConstantLayer(biases, "Biases");
612 armnn::IConnectableLayer* const convLayer = network->AddConvolution3dLayer(descriptor, layerName.c_str());
613 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
614
615 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
616 weightsLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(1));
617 biasesLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(2));
618 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
619
620 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
621 weightsLayer->GetOutputSlot(0).SetTensorInfo(weightsInfo);
622 biasesLayer->GetOutputSlot(0).SetTensorInfo(biasesInfo);
623 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
624
625 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
626 CHECK(deserializedNetwork);
627
628 LayerVerifierBaseWithDescriptor<armnn::Convolution3dDescriptor> verifier(
629 layerName, {inputInfo, weightsInfo, biasesInfo}, {outputInfo}, descriptor);
630 deserializedNetwork->ExecuteStrategy(verifier);
631 }
632
633 TEST_CASE("SerializeDepthToSpace")
634 {
635 const std::string layerName("depthToSpace");
636
637 const armnn::TensorInfo inputInfo ({ 1, 8, 4, 12 }, armnn::DataType::Float32);
638 const armnn::TensorInfo outputInfo({ 1, 16, 8, 3 }, armnn::DataType::Float32);
639
640 armnn::DepthToSpaceDescriptor desc;
641 desc.m_BlockSize = 2;
642 desc.m_DataLayout = armnn::DataLayout::NHWC;
643
644 armnn::INetworkPtr network = armnn::INetwork::Create();
645 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
646 armnn::IConnectableLayer* const depthToSpaceLayer = network->AddDepthToSpaceLayer(desc, layerName.c_str());
647 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
648
649 inputLayer->GetOutputSlot(0).Connect(depthToSpaceLayer->GetInputSlot(0));
650 depthToSpaceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
651
652 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
653 depthToSpaceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
654
655 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
656 CHECK(deserializedNetwork);
657
658 LayerVerifierBaseWithDescriptor<armnn::DepthToSpaceDescriptor> verifier(layerName, {inputInfo}, {outputInfo}, desc);
659 deserializedNetwork->ExecuteStrategy(verifier);
660 }
661
662 TEST_CASE("SerializeDepthwiseConvolution2d")
663 {
664 const std::string layerName("depwiseConvolution2d");
665 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 3 }, armnn::DataType::Float32);
666 const armnn::TensorInfo outputInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32);
667
668 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 3 }, armnn::DataType::Float32, 0.0f, 0, true);
669 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32, 0.0f, 0, true);
670
671 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
672 armnn::ConstTensor weights(weightsInfo, weightsData);
673
674 std::vector<int32_t> biasesData = GenerateRandomData<int32_t>(biasesInfo.GetNumElements());
675 armnn::ConstTensor biases(biasesInfo, biasesData);
676
677 armnn::DepthwiseConvolution2dDescriptor descriptor;
678 descriptor.m_PadLeft = 1;
679 descriptor.m_PadRight = 1;
680 descriptor.m_PadTop = 1;
681 descriptor.m_PadBottom = 1;
682 descriptor.m_StrideX = 2;
683 descriptor.m_StrideY = 2;
684 descriptor.m_DilationX = 2;
685 descriptor.m_DilationY = 2;
686 descriptor.m_BiasEnabled = true;
687 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
688
689 armnn::INetworkPtr network = armnn::INetwork::Create();
690 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
691 armnn::IConnectableLayer* const depthwiseConvLayer = network->AddDepthwiseConvolution2dLayer(descriptor,
692 layerName.c_str());
693 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
694
695 inputLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(0));
696 depthwiseConvLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
697
698 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
699 depthwiseConvLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
700
701 armnn::IConnectableLayer* const weightsLayer = network->AddConstantLayer(weights);
702 weightsLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(1u));
703 weightsLayer->GetOutputSlot(0).SetTensorInfo(weights.GetInfo());
704
705 armnn::IConnectableLayer* const biasLayer = network->AddConstantLayer(biases);
706 biasLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(2u));
707 biasLayer->GetOutputSlot(0).SetTensorInfo(biases.GetInfo());
708
709 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
710 CHECK(deserializedNetwork);
711
712 const std::vector<armnn::ConstTensor>& constants {weights, biases};
713 LayerVerifierBaseWithDescriptorAndConstants<armnn::DepthwiseConvolution2dDescriptor> verifier(
714 layerName, {inputInfo, weightsInfo, biasesInfo}, {outputInfo}, descriptor, constants);
715 deserializedNetwork->ExecuteStrategy(verifier);
716 }
717
718 TEST_CASE("SerializeDepthwiseConvolution2dWithPerAxisParams")
719 {
720 using namespace armnn;
721
722 const std::string layerName("depwiseConvolution2dWithPerAxis");
723 const TensorInfo inputInfo ({ 1, 3, 3, 2 }, DataType::QAsymmU8, 0.55f, 128);
724 const TensorInfo outputInfo({ 1, 2, 2, 4 }, DataType::QAsymmU8, 0.75f, 128);
725
726 const std::vector<float> quantScales{ 0.75f, 0.80f, 0.90f, 0.95f };
727 const unsigned int quantDimension = 0;
728 TensorInfo kernelInfo({ 2, 2, 2, 2 }, DataType::QSymmS8, quantScales, quantDimension, true);
729
730 const std::vector<float> biasQuantScales{ 0.25f, 0.35f, 0.45f, 0.55f };
731 constexpr unsigned int biasQuantDimension = 0;
732 TensorInfo biasInfo({ 4 }, DataType::Signed32, biasQuantScales, biasQuantDimension, true);
733
734 std::vector<int8_t> kernelData = GenerateRandomData<int8_t>(kernelInfo.GetNumElements());
735 armnn::ConstTensor weights(kernelInfo, kernelData);
736 std::vector<int32_t> biasData = GenerateRandomData<int32_t>(biasInfo.GetNumElements());
737 armnn::ConstTensor biases(biasInfo, biasData);
738
739 DepthwiseConvolution2dDescriptor descriptor;
740 descriptor.m_StrideX = 1;
741 descriptor.m_StrideY = 1;
742 descriptor.m_PadLeft = 0;
743 descriptor.m_PadRight = 0;
744 descriptor.m_PadTop = 0;
745 descriptor.m_PadBottom = 0;
746 descriptor.m_DilationX = 1;
747 descriptor.m_DilationY = 1;
748 descriptor.m_BiasEnabled = true;
749 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
750
751 armnn::INetworkPtr network = armnn::INetwork::Create();
752 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
753 armnn::IConnectableLayer* const depthwiseConvLayer = network->AddDepthwiseConvolution2dLayer(descriptor,
754 layerName.c_str());
755 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
756
757 inputLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(0));
758 depthwiseConvLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
759
760 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
761 depthwiseConvLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
762
763 armnn::IConnectableLayer* const weightsLayer = network->AddConstantLayer(weights);
764 weightsLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(1u));
765 weightsLayer->GetOutputSlot(0).SetTensorInfo(weights.GetInfo());
766
767 armnn::IConnectableLayer* const biasLayer = network->AddConstantLayer(biases);
768 biasLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(2u));
769 biasLayer->GetOutputSlot(0).SetTensorInfo(biases.GetInfo());
770
771 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
772 CHECK(deserializedNetwork);
773
774 const std::vector<armnn::ConstTensor>& constants {weights, biases};
775 LayerVerifierBaseWithDescriptorAndConstants<armnn::DepthwiseConvolution2dDescriptor> verifier(
776 layerName, {inputInfo, kernelInfo, biasInfo}, {outputInfo}, descriptor, constants);
777 deserializedNetwork->ExecuteStrategy(verifier);
778 }
779
780 TEST_CASE("SerializeDepthwiseConvolution2dWeightsAndBiasesAsConstantLayers")
781 {
782 const std::string layerName("depthwiseConvolution2d");
783 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32);
784 const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
785
786 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32, 0.0f, 0, true);
787 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32, 0.0f, 0, true);
788
789 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
790 armnn::ConstTensor weights(weightsInfo, weightsData);
791
792 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
793 armnn::ConstTensor biases(biasesInfo, biasesData);
794
795 armnn::DepthwiseConvolution2dDescriptor descriptor;
796 descriptor.m_PadLeft = 1;
797 descriptor.m_PadRight = 1;
798 descriptor.m_PadTop = 1;
799 descriptor.m_PadBottom = 1;
800 descriptor.m_StrideX = 2;
801 descriptor.m_StrideY = 2;
802 descriptor.m_DilationX = 2;
803 descriptor.m_DilationY = 2;
804 descriptor.m_BiasEnabled = true;
805 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
806
807 armnn::INetworkPtr network = armnn::INetwork::Create();
808 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
809 armnn::IConnectableLayer* const weightsLayer = network->AddConstantLayer(weights, "Weights");
810 armnn::IConnectableLayer* const biasesLayer = network->AddConstantLayer(biases, "Biases");
811 armnn::IConnectableLayer* const convLayer = network->AddDepthwiseConvolution2dLayer(descriptor,
812 layerName.c_str());
813 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
814
815 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
816 weightsLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(1));
817 biasesLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(2));
818 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
819
820 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
821 weightsLayer->GetOutputSlot(0).SetTensorInfo(weightsInfo);
822 biasesLayer->GetOutputSlot(0).SetTensorInfo(biasesInfo);
823 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
824
825 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
826 CHECK(deserializedNetwork);
827
828 const std::vector<armnn::ConstTensor>& constants {weights, biases};
829 LayerVerifierBaseWithDescriptorAndConstants<armnn::DepthwiseConvolution2dDescriptor> verifier(
830 layerName, {inputInfo, weightsInfo, biasesInfo}, {outputInfo}, descriptor, constants);
831
832 deserializedNetwork->ExecuteStrategy(verifier);
833 }
834
835 TEST_CASE("SerializeDequantize")
836 {
837 const std::string layerName("dequantize");
838 const armnn::TensorInfo inputInfo({ 1, 5, 2, 3 }, armnn::DataType::QAsymmU8, 0.5f, 1);
839 const armnn::TensorInfo outputInfo({ 1, 5, 2, 3 }, armnn::DataType::Float32);
840
841 armnn::INetworkPtr network = armnn::INetwork::Create();
842 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
843 armnn::IConnectableLayer* const dequantizeLayer = network->AddDequantizeLayer(layerName.c_str());
844 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
845
846 inputLayer->GetOutputSlot(0).Connect(dequantizeLayer->GetInputSlot(0));
847 dequantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
848
849 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
850 dequantizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
851
852 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
853 CHECK(deserializedNetwork);
854
855 LayerVerifierBase verifier(layerName, {inputInfo}, {outputInfo});
856 deserializedNetwork->ExecuteStrategy(verifier);
857 }
858
859 TEST_CASE("SerializeDeserializeDetectionPostProcess")
860 {
861 const std::string layerName("detectionPostProcess");
862
863 const std::vector<armnn::TensorInfo> inputInfos({
864 armnn::TensorInfo({ 1, 6, 4 }, armnn::DataType::Float32),
865 armnn::TensorInfo({ 1, 6, 3}, armnn::DataType::Float32)
866 });
867
868 const std::vector<armnn::TensorInfo> outputInfos({
869 armnn::TensorInfo({ 1, 3, 4 }, armnn::DataType::Float32),
870 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
871 armnn::TensorInfo({ 1, 3 }, armnn::DataType::Float32),
872 armnn::TensorInfo({ 1 }, armnn::DataType::Float32)
873 });
874
875 armnn::DetectionPostProcessDescriptor descriptor;
876 descriptor.m_UseRegularNms = true;
877 descriptor.m_MaxDetections = 3;
878 descriptor.m_MaxClassesPerDetection = 1;
879 descriptor.m_DetectionsPerClass =1;
880 descriptor.m_NmsScoreThreshold = 0.0;
881 descriptor.m_NmsIouThreshold = 0.5;
882 descriptor.m_NumClasses = 2;
883 descriptor.m_ScaleY = 10.0;
884 descriptor.m_ScaleX = 10.0;
885 descriptor.m_ScaleH = 5.0;
886 descriptor.m_ScaleW = 5.0;
887
888 const armnn::TensorInfo anchorsInfo({ 6, 4 }, armnn::DataType::Float32, 0.0f, 0, true);
889 const std::vector<float> anchorsData({
890 0.5f, 0.5f, 1.0f, 1.0f,
891 0.5f, 0.5f, 1.0f, 1.0f,
892 0.5f, 0.5f, 1.0f, 1.0f,
893 0.5f, 10.5f, 1.0f, 1.0f,
894 0.5f, 10.5f, 1.0f, 1.0f,
895 0.5f, 100.5f, 1.0f, 1.0f
896 });
897 armnn::ConstTensor anchors(anchorsInfo, anchorsData);
898
899 armnn::INetworkPtr network = armnn::INetwork::Create();
900 armnn::IConnectableLayer* const detectionLayer =
901 network->AddDetectionPostProcessLayer(descriptor, anchors, layerName.c_str());
902
903 for (unsigned int i = 0; i < 2; i++)
904 {
905 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(static_cast<int>(i));
906 inputLayer->GetOutputSlot(0).Connect(detectionLayer->GetInputSlot(i));
907 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfos[i]);
908 }
909
910 for (unsigned int i = 0; i < 4; i++)
911 {
912 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(static_cast<int>(i));
913 detectionLayer->GetOutputSlot(i).Connect(outputLayer->GetInputSlot(0));
914 detectionLayer->GetOutputSlot(i).SetTensorInfo(outputInfos[i]);
915 }
916
917 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
918 CHECK(deserializedNetwork);
919
920 const std::vector<armnn::ConstTensor>& constants {anchors};
921 LayerVerifierBaseWithDescriptorAndConstants<armnn::DetectionPostProcessDescriptor> verifier(
922 layerName, inputInfos, outputInfos, descriptor, constants);
923 deserializedNetwork->ExecuteStrategy(verifier);
924 }
925
926 TEST_CASE("SerializeDivision")
927 {
928 const std::string layerName("division");
929 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
930
931 armnn::INetworkPtr network = armnn::INetwork::Create();
932 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
933 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
934 ARMNN_NO_DEPRECATE_WARN_BEGIN
935 armnn::IConnectableLayer* const divisionLayer = network->AddDivisionLayer(layerName.c_str());
936 ARMNN_NO_DEPRECATE_WARN_END
937 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
938
939 inputLayer0->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(0));
940 inputLayer1->GetOutputSlot(0).Connect(divisionLayer->GetInputSlot(1));
941 divisionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
942
943 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
944 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
945 divisionLayer->GetOutputSlot(0).SetTensorInfo(info);
946
947 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
948 CHECK(deserializedNetwork);
949
950 LayerVerifierBase verifier(layerName, {info, info}, {info});
951 deserializedNetwork->ExecuteStrategy(verifier);
952 }
953
954 TEST_CASE("SerializeDeserializeComparisonEqual")
955 {
956 const std::string layerName("EqualLayer");
957 const armnn::TensorInfo inputTensorInfo1 = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Float32);
958 const armnn::TensorInfo inputTensorInfo2 = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Float32);
959 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({2, 1, 2, 4}, armnn::DataType::Boolean);
960
961 armnn::INetworkPtr network = armnn::INetwork::Create();
962 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
963 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
964 armnn::ComparisonDescriptor equalDescriptor(armnn::ComparisonOperation::Equal);
965 armnn::IConnectableLayer* const equalLayer = network->AddComparisonLayer(equalDescriptor, layerName.c_str());
966 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
967
968 inputLayer1->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(0));
969 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo1);
970 inputLayer2->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(1));
971 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo2);
972 equalLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
973 equalLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
974
975 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
976 CHECK(deserializedNetwork);
977
978 LayerVerifierBase verifier(layerName, {inputTensorInfo1, inputTensorInfo2}, {outputTensorInfo});
979 deserializedNetwork->ExecuteStrategy(verifier);
980 }
981
SerializeElementwiseBinaryTest(armnn::BinaryOperation binaryOperation)982 void SerializeElementwiseBinaryTest(armnn::BinaryOperation binaryOperation)
983 {
984 auto layerName = GetBinaryOperationAsCString(binaryOperation);
985 const armnn::TensorInfo tensorInfo({ 1, 5, 2, 3 }, armnn::DataType::Float32);
986 armnn::ElementwiseBinaryDescriptor descriptor(binaryOperation);
987
988 armnn::INetworkPtr network = armnn::INetwork::Create();
989 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
990 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
991 armnn::IConnectableLayer* const elementwiseBinaryLayer = network->AddElementwiseBinaryLayer(descriptor,
992 layerName);
993 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
994
995 inputLayer0->GetOutputSlot(0).Connect(elementwiseBinaryLayer->GetInputSlot(0));
996 inputLayer1->GetOutputSlot(0).Connect(elementwiseBinaryLayer->GetInputSlot(1));
997 elementwiseBinaryLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
998
999 inputLayer0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1000 inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1001 elementwiseBinaryLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1002
1003 std::string serializedNetwork = SerializeNetwork(*network);
1004 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(serializedNetwork);
1005 CHECK(deserializedNetwork);
1006
1007 LayerVerifierBaseWithDescriptor<armnn::ElementwiseBinaryDescriptor>
1008 verifier(layerName, { tensorInfo, tensorInfo }, { tensorInfo }, descriptor);
1009 deserializedNetwork->ExecuteStrategy(verifier);
1010 }
1011
1012 TEST_CASE("SerializeElementwiseBinary")
1013 {
1014 using op = armnn::BinaryOperation;
1015 std::initializer_list<op> allBinaryOperations = {op::Add, op::Div, op::Maximum, op::Minimum, op::Mul, op::Sub};
1016
1017 for (auto binaryOperation : allBinaryOperations)
1018 {
1019 SerializeElementwiseBinaryTest(binaryOperation);
1020 }
1021 }
1022
SerializeElementwiseUnaryTest(armnn::UnaryOperation unaryOperation)1023 void SerializeElementwiseUnaryTest(armnn::UnaryOperation unaryOperation)
1024 {
1025 auto layerName = GetUnaryOperationAsCString(unaryOperation);
1026
1027 const armnn::TensorShape shape{2, 1, 2, 2};
1028
1029 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
1030 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
1031
1032 armnn::ElementwiseUnaryDescriptor descriptor(unaryOperation);
1033
1034 armnn::INetworkPtr network = armnn::INetwork::Create();
1035 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1036 armnn::IConnectableLayer* const elementwiseUnaryLayer =
1037 network->AddElementwiseUnaryLayer(descriptor, layerName);
1038 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1039
1040 inputLayer->GetOutputSlot(0).Connect(elementwiseUnaryLayer->GetInputSlot(0));
1041 elementwiseUnaryLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1042
1043 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1044 elementwiseUnaryLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1045
1046 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1047
1048 CHECK(deserializedNetwork);
1049
1050 LayerVerifierBaseWithDescriptor<armnn::ElementwiseUnaryDescriptor>
1051 verifier(layerName, { inputInfo }, { outputInfo }, descriptor);
1052
1053 deserializedNetwork->ExecuteStrategy(verifier);
1054 }
1055
1056 TEST_CASE("SerializeElementwiseUnary")
1057 {
1058 using op = armnn::UnaryOperation;
1059 std::initializer_list<op> allUnaryOperations = {op::Abs, op::Ceil, op::Exp, op::Sqrt, op::Rsqrt, op::Neg,
1060 op::LogicalNot, op::Log, op::Sin};
1061
1062 for (auto unaryOperation : allUnaryOperations)
1063 {
1064 SerializeElementwiseUnaryTest(unaryOperation);
1065 }
1066 }
1067
1068 TEST_CASE("SerializeFill")
1069 {
1070 const std::string layerName("fill");
1071 const armnn::TensorInfo inputInfo({4}, armnn::DataType::Signed32);
1072 const armnn::TensorInfo outputInfo({1, 3, 3, 1}, armnn::DataType::Float32);
1073
1074 armnn::FillDescriptor descriptor(1.0f);
1075
1076 armnn::INetworkPtr network = armnn::INetwork::Create();
1077 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1078 armnn::IConnectableLayer* const fillLayer = network->AddFillLayer(descriptor, layerName.c_str());
1079 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1080
1081 inputLayer->GetOutputSlot(0).Connect(fillLayer->GetInputSlot(0));
1082 fillLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1083
1084 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1085 fillLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1086
1087 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1088 CHECK(deserializedNetwork);
1089
1090 LayerVerifierBaseWithDescriptor<armnn::FillDescriptor> verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
1091
1092 deserializedNetwork->ExecuteStrategy(verifier);
1093 }
1094
1095 TEST_CASE("SerializeFloor")
1096 {
1097 const std::string layerName("floor");
1098 const armnn::TensorInfo info({4,4}, armnn::DataType::Float32);
1099
1100 armnn::INetworkPtr network = armnn::INetwork::Create();
1101 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1102 armnn::IConnectableLayer* const floorLayer = network->AddFloorLayer(layerName.c_str());
1103 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1104
1105 inputLayer->GetOutputSlot(0).Connect(floorLayer->GetInputSlot(0));
1106 floorLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1107
1108 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1109 floorLayer->GetOutputSlot(0).SetTensorInfo(info);
1110
1111 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1112 CHECK(deserializedNetwork);
1113
1114 LayerVerifierBase verifier(layerName, {info}, {info});
1115 deserializedNetwork->ExecuteStrategy(verifier);
1116 }
1117
1118 using FullyConnectedDescriptor = armnn::FullyConnectedDescriptor;
1119 class FullyConnectedLayerVerifier : public LayerVerifierBaseWithDescriptor<FullyConnectedDescriptor>
1120 {
1121 public:
FullyConnectedLayerVerifier(const std::string & layerName,const std::vector<armnn::TensorInfo> & inputInfos,const std::vector<armnn::TensorInfo> & outputInfos,const FullyConnectedDescriptor & descriptor)1122 FullyConnectedLayerVerifier(const std::string& layerName,
1123 const std::vector<armnn::TensorInfo>& inputInfos,
1124 const std::vector<armnn::TensorInfo>& outputInfos,
1125 const FullyConnectedDescriptor& descriptor)
1126 : LayerVerifierBaseWithDescriptor<FullyConnectedDescriptor>(layerName, inputInfos, outputInfos, descriptor) {}
1127
ExecuteStrategy(const armnn::IConnectableLayer * layer,const armnn::BaseDescriptor & descriptor,const std::vector<armnn::ConstTensor> & constants,const char * name,const armnn::LayerBindingId id=0)1128 void ExecuteStrategy(const armnn::IConnectableLayer* layer,
1129 const armnn::BaseDescriptor& descriptor,
1130 const std::vector<armnn::ConstTensor>& constants,
1131 const char* name,
1132 const armnn::LayerBindingId id = 0) override
1133 {
1134 armnn::IgnoreUnused(constants, id);
1135 switch (layer->GetType())
1136 {
1137 case armnn::LayerType::Input: break;
1138 case armnn::LayerType::Output: break;
1139 case armnn::LayerType::Constant: break;
1140 default:
1141 {
1142 VerifyNameAndConnections(layer, name);
1143 const FullyConnectedDescriptor& layerDescriptor =
1144 static_cast<const FullyConnectedDescriptor&>(descriptor);
1145 CHECK(layerDescriptor.m_ConstantWeights == m_Descriptor.m_ConstantWeights);
1146 CHECK(layerDescriptor.m_BiasEnabled == m_Descriptor.m_BiasEnabled);
1147 CHECK(layerDescriptor.m_TransposeWeightMatrix == m_Descriptor.m_TransposeWeightMatrix);
1148 }
1149 }
1150 }
1151 };
1152
1153 TEST_CASE("SerializeFullyConnected")
1154 {
1155 const std::string layerName("fullyConnected");
1156 const armnn::TensorInfo inputInfo ({ 2, 5, 1, 1 }, armnn::DataType::Float32);
1157 const armnn::TensorInfo outputInfo({ 2, 3 }, armnn::DataType::Float32);
1158
1159 const armnn::TensorInfo weightsInfo({ 5, 3 }, armnn::DataType::Float32, 0.0f, 0, true);
1160 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32, 0.0f, 0, true);
1161 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
1162 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
1163 armnn::ConstTensor weights(weightsInfo, weightsData);
1164 armnn::ConstTensor biases(biasesInfo, biasesData);
1165
1166 armnn::FullyConnectedDescriptor descriptor;
1167 descriptor.m_BiasEnabled = true;
1168 descriptor.m_TransposeWeightMatrix = false;
1169 descriptor.m_ConstantWeights = true;
1170
1171 armnn::INetworkPtr network = armnn::INetwork::Create();
1172 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1173 armnn::IConnectableLayer* const weightsInputLayer = network->AddInputLayer(1);
1174 armnn::IConnectableLayer* const biasInputLayer = network->AddInputLayer(2);
1175 armnn::IConnectableLayer* const fullyConnectedLayer =
1176 network->AddFullyConnectedLayer(descriptor,
1177 layerName.c_str());
1178 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1179
1180 inputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(0));
1181 weightsInputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(1));
1182 biasInputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(2));
1183 fullyConnectedLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1184
1185 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1186 weightsInputLayer->GetOutputSlot(0).SetTensorInfo(weightsInfo);
1187 biasInputLayer->GetOutputSlot(0).SetTensorInfo(biasesInfo);
1188 fullyConnectedLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1189
1190 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1191 CHECK(deserializedNetwork);
1192
1193 FullyConnectedLayerVerifier verifier(layerName, {inputInfo, weightsInfo, biasesInfo}, {outputInfo}, descriptor);
1194 deserializedNetwork->ExecuteStrategy(verifier);
1195 }
1196
1197 TEST_CASE("SerializeFullyConnectedWeightsAndBiasesAsInputs")
1198 {
1199 const std::string layerName("fullyConnected_weights_as_inputs");
1200 const armnn::TensorInfo inputInfo ({ 2, 5, 1, 1 }, armnn::DataType::Float32);
1201 const armnn::TensorInfo outputInfo({ 2, 3 }, armnn::DataType::Float32);
1202
1203 const armnn::TensorInfo weightsInfo({ 5, 3 }, armnn::DataType::Float32);
1204 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32);
1205
1206 armnn::Optional<armnn::ConstTensor> weights = armnn::EmptyOptional();
1207 armnn::Optional<armnn::ConstTensor> bias = armnn::EmptyOptional();
1208
1209 armnn::FullyConnectedDescriptor descriptor;
1210 descriptor.m_BiasEnabled = true;
1211 descriptor.m_TransposeWeightMatrix = false;
1212 descriptor.m_ConstantWeights = false;
1213
1214 armnn::INetworkPtr network = armnn::INetwork::Create();
1215 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1216 armnn::IConnectableLayer* const weightsInputLayer = network->AddInputLayer(1);
1217 armnn::IConnectableLayer* const biasInputLayer = network->AddInputLayer(2);
1218 armnn::IConnectableLayer* const fullyConnectedLayer =
1219 network->AddFullyConnectedLayer(descriptor,
1220 layerName.c_str());
1221 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1222
1223 inputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(0));
1224 weightsInputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(1));
1225 biasInputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(2));
1226 fullyConnectedLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1227
1228 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1229 weightsInputLayer->GetOutputSlot(0).SetTensorInfo(weightsInfo);
1230 biasInputLayer->GetOutputSlot(0).SetTensorInfo(biasesInfo);
1231 fullyConnectedLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1232
1233 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1234 CHECK(deserializedNetwork);
1235
1236 const std::vector<armnn::ConstTensor> constants {};
1237 LayerVerifierBaseWithDescriptorAndConstants<armnn::FullyConnectedDescriptor> verifier(
1238 layerName, {inputInfo, weightsInfo, biasesInfo}, {outputInfo}, descriptor, constants);
1239 deserializedNetwork->ExecuteStrategy(verifier);
1240 }
1241
1242 TEST_CASE("SerializeFullyConnectedWeightsAndBiasesAsConstantLayers")
1243 {
1244 const std::string layerName("fullyConnected_weights_as_inputs");
1245 const armnn::TensorInfo inputInfo ({ 2, 5, 1, 1 }, armnn::DataType::Float32);
1246 const armnn::TensorInfo outputInfo({ 2, 3 }, armnn::DataType::Float32);
1247
1248 const armnn::TensorInfo weightsInfo({ 5, 3 }, armnn::DataType::Float32, 0.0f, 0, true);
1249 const armnn::TensorInfo biasesInfo ({ 3 }, armnn::DataType::Float32, 0.0f, 0, true);
1250
1251 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
1252 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
1253 armnn::ConstTensor weights(weightsInfo, weightsData);
1254 armnn::ConstTensor biases(biasesInfo, biasesData);
1255
1256 armnn::FullyConnectedDescriptor descriptor;
1257 descriptor.m_BiasEnabled = true;
1258 descriptor.m_TransposeWeightMatrix = false;
1259 descriptor.m_ConstantWeights = true;
1260
1261 armnn::INetworkPtr network = armnn::INetwork::Create();
1262 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1263 armnn::IConnectableLayer* const weightsLayer = network->AddConstantLayer(weights, "Weights");
1264 armnn::IConnectableLayer* const biasesLayer = network->AddConstantLayer(biases, "Biases");
1265 armnn::IConnectableLayer* const fullyConnectedLayer = network->AddFullyConnectedLayer(descriptor,layerName.c_str());
1266 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1267
1268 inputLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(0));
1269 weightsLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(1));
1270 biasesLayer->GetOutputSlot(0).Connect(fullyConnectedLayer->GetInputSlot(2));
1271 fullyConnectedLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1272
1273 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1274 weightsLayer->GetOutputSlot(0).SetTensorInfo(weightsInfo);
1275 biasesLayer->GetOutputSlot(0).SetTensorInfo(biasesInfo);
1276 fullyConnectedLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1277
1278 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1279 CHECK(deserializedNetwork);
1280
1281 FullyConnectedLayerVerifier verifier(layerName, {inputInfo, weightsInfo, biasesInfo}, {outputInfo}, descriptor);
1282 deserializedNetwork->ExecuteStrategy(verifier);
1283 }
1284
1285 TEST_CASE("SerializeGather")
1286 {
1287 using GatherDescriptor = armnn::GatherDescriptor;
1288 class GatherLayerVerifier : public LayerVerifierBaseWithDescriptor<GatherDescriptor>
1289 {
1290 public:
GatherLayerVerifier(const std::string & layerName,const std::vector<armnn::TensorInfo> & inputInfos,const std::vector<armnn::TensorInfo> & outputInfos,const GatherDescriptor & descriptor)1291 GatherLayerVerifier(const std::string& layerName,
1292 const std::vector<armnn::TensorInfo>& inputInfos,
1293 const std::vector<armnn::TensorInfo>& outputInfos,
1294 const GatherDescriptor& descriptor)
1295 : LayerVerifierBaseWithDescriptor<GatherDescriptor>(layerName, inputInfos, outputInfos, descriptor) {}
1296
ExecuteStrategy(const armnn::IConnectableLayer * layer,const armnn::BaseDescriptor & descriptor,const std::vector<armnn::ConstTensor> & constants,const char * name,const armnn::LayerBindingId id=0)1297 void ExecuteStrategy(const armnn::IConnectableLayer* layer,
1298 const armnn::BaseDescriptor& descriptor,
1299 const std::vector<armnn::ConstTensor>& constants,
1300 const char* name,
1301 const armnn::LayerBindingId id = 0) override
1302 {
1303 armnn::IgnoreUnused(constants, id);
1304 switch (layer->GetType())
1305 {
1306 case armnn::LayerType::Input: break;
1307 case armnn::LayerType::Output: break;
1308 case armnn::LayerType::Constant: break;
1309 default:
1310 {
1311 VerifyNameAndConnections(layer, name);
1312 const GatherDescriptor& layerDescriptor = static_cast<const GatherDescriptor&>(descriptor);
1313 CHECK(layerDescriptor.m_Axis == m_Descriptor.m_Axis);
1314 }
1315 }
1316 }
1317 };
1318
1319 const std::string layerName("gather");
1320 armnn::TensorInfo paramsInfo({ 8 }, armnn::DataType::QAsymmU8);
1321 armnn::TensorInfo outputInfo({ 3 }, armnn::DataType::QAsymmU8);
1322 const armnn::TensorInfo indicesInfo({ 3 }, armnn::DataType::Signed32, 0.0f, 0, true);
1323 GatherDescriptor descriptor;
1324 descriptor.m_Axis = 1;
1325
1326 paramsInfo.SetQuantizationScale(1.0f);
1327 paramsInfo.SetQuantizationOffset(0);
1328 outputInfo.SetQuantizationScale(1.0f);
1329 outputInfo.SetQuantizationOffset(0);
1330
1331 const std::vector<int32_t>& indicesData = {7, 6, 5};
1332
1333 armnn::INetworkPtr network = armnn::INetwork::Create();
1334 armnn::IConnectableLayer *const inputLayer = network->AddInputLayer(0);
1335 armnn::IConnectableLayer *const constantLayer =
1336 network->AddConstantLayer(armnn::ConstTensor(indicesInfo, indicesData));
1337 armnn::IConnectableLayer *const gatherLayer = network->AddGatherLayer(descriptor, layerName.c_str());
1338 armnn::IConnectableLayer *const outputLayer = network->AddOutputLayer(0);
1339
1340 inputLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(0));
1341 constantLayer->GetOutputSlot(0).Connect(gatherLayer->GetInputSlot(1));
1342 gatherLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1343
1344 inputLayer->GetOutputSlot(0).SetTensorInfo(paramsInfo);
1345 constantLayer->GetOutputSlot(0).SetTensorInfo(indicesInfo);
1346 gatherLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1347
1348 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1349 CHECK(deserializedNetwork);
1350
1351 GatherLayerVerifier verifier(layerName, {paramsInfo, indicesInfo}, {outputInfo}, descriptor);
1352 deserializedNetwork->ExecuteStrategy(verifier);
1353 }
1354
1355 TEST_CASE("SerializeGatherNd")
1356 {
1357 class GatherNdLayerVerifier : public LayerVerifierBase
1358 {
1359 public:
GatherNdLayerVerifier(const std::string & layerName,const std::vector<armnn::TensorInfo> & inputInfos,const std::vector<armnn::TensorInfo> & outputInfos)1360 GatherNdLayerVerifier(const std::string& layerName,
1361 const std::vector<armnn::TensorInfo>& inputInfos,
1362 const std::vector<armnn::TensorInfo>& outputInfos)
1363 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
1364
ExecuteStrategy(const armnn::IConnectableLayer * layer,const armnn::BaseDescriptor &,const std::vector<armnn::ConstTensor> & constants,const char * name,const armnn::LayerBindingId id=0)1365 void ExecuteStrategy(const armnn::IConnectableLayer* layer,
1366 const armnn::BaseDescriptor&,
1367 const std::vector<armnn::ConstTensor>& constants,
1368 const char* name,
1369 const armnn::LayerBindingId id = 0) override
1370 {
1371 armnn::IgnoreUnused(constants, id);
1372 switch (layer->GetType())
1373 {
1374 case armnn::LayerType::Input:
1375 case armnn::LayerType::Output:
1376 case armnn::LayerType::Constant:
1377 break;
1378 default:
1379 {
1380 VerifyNameAndConnections(layer, name);
1381 }
1382 }
1383 }
1384 };
1385
1386 const std::string layerName("gatherNd");
1387 armnn::TensorInfo paramsInfo({ 6, 3 }, armnn::DataType::QAsymmU8);
1388 armnn::TensorInfo outputInfo({ 3, 3 }, armnn::DataType::QAsymmU8);
1389 const armnn::TensorInfo indicesInfo({ 3, 1 }, armnn::DataType::Signed32, 0.0f, 0, true);
1390
1391 paramsInfo.SetQuantizationScale(1.0f);
1392 paramsInfo.SetQuantizationOffset(0);
1393 outputInfo.SetQuantizationScale(1.0f);
1394 outputInfo.SetQuantizationOffset(0);
1395
1396 const std::vector<int32_t>& indicesData = {5, 1, 0};
1397
1398 armnn::INetworkPtr network = armnn::INetwork::Create();
1399 armnn::IConnectableLayer *const inputLayer = network->AddInputLayer(0);
1400 armnn::IConnectableLayer *const constantLayer =
1401 network->AddConstantLayer(armnn::ConstTensor(indicesInfo, indicesData));
1402 armnn::IConnectableLayer *const gatherNdLayer = network->AddGatherNdLayer(layerName.c_str());
1403 armnn::IConnectableLayer *const outputLayer = network->AddOutputLayer(0);
1404
1405 inputLayer->GetOutputSlot(0).Connect(gatherNdLayer->GetInputSlot(0));
1406 constantLayer->GetOutputSlot(0).Connect(gatherNdLayer->GetInputSlot(1));
1407 gatherNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1408
1409 inputLayer->GetOutputSlot(0).SetTensorInfo(paramsInfo);
1410 constantLayer->GetOutputSlot(0).SetTensorInfo(indicesInfo);
1411 gatherNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1412
1413 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1414 CHECK(deserializedNetwork);
1415
1416 GatherNdLayerVerifier verifier(layerName, {paramsInfo, indicesInfo}, {outputInfo});
1417 deserializedNetwork->ExecuteStrategy(verifier);
1418 }
1419
1420 TEST_CASE("SerializeComparisonGreater")
1421 {
1422 const std::string layerName("greater");
1423
1424 const armnn::TensorShape shape{2, 1, 2, 4};
1425
1426 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Float32);
1427 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
1428
1429 armnn::INetworkPtr network = armnn::INetwork::Create();
1430 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1431 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1432 armnn::ComparisonDescriptor greaterDescriptor(armnn::ComparisonOperation::Greater);
1433 armnn::IConnectableLayer* const equalLayer = network->AddComparisonLayer(greaterDescriptor, layerName.c_str());
1434 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1435
1436 inputLayer0->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(0));
1437 inputLayer1->GetOutputSlot(0).Connect(equalLayer->GetInputSlot(1));
1438 equalLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1439
1440 inputLayer0->GetOutputSlot(0).SetTensorInfo(inputInfo);
1441 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputInfo);
1442 equalLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1443
1444 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1445 CHECK(deserializedNetwork);
1446
1447 LayerVerifierBase verifier(layerName, { inputInfo, inputInfo }, { outputInfo });
1448 deserializedNetwork->ExecuteStrategy(verifier);
1449 }
1450
1451
1452 TEST_CASE("SerializeInstanceNormalization")
1453 {
1454 const std::string layerName("instanceNormalization");
1455 const armnn::TensorInfo info({ 1, 2, 1, 5 }, armnn::DataType::Float32);
1456
1457 armnn::InstanceNormalizationDescriptor descriptor;
1458 descriptor.m_Gamma = 1.1f;
1459 descriptor.m_Beta = 0.1f;
1460 descriptor.m_Eps = 0.0001f;
1461 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
1462
1463 armnn::INetworkPtr network = armnn::INetwork::Create();
1464 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1465 armnn::IConnectableLayer* const instanceNormLayer =
1466 network->AddInstanceNormalizationLayer(descriptor, layerName.c_str());
1467 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1468
1469 inputLayer->GetOutputSlot(0).Connect(instanceNormLayer->GetInputSlot(0));
1470 instanceNormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1471
1472 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1473 instanceNormLayer->GetOutputSlot(0).SetTensorInfo(info);
1474
1475 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1476 CHECK(deserializedNetwork);
1477
1478 LayerVerifierBaseWithDescriptor<armnn::InstanceNormalizationDescriptor> verifier(
1479 layerName, {info}, {info}, descriptor);
1480 deserializedNetwork->ExecuteStrategy(verifier);
1481 }
1482
1483 TEST_CASE("SerializeL2Normalization")
1484 {
1485 const std::string l2NormLayerName("l2Normalization");
1486 const armnn::TensorInfo info({1, 2, 1, 5}, armnn::DataType::Float32);
1487
1488 armnn::L2NormalizationDescriptor desc;
1489 desc.m_DataLayout = armnn::DataLayout::NCHW;
1490 desc.m_Eps = 0.0001f;
1491
1492 armnn::INetworkPtr network = armnn::INetwork::Create();
1493 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1494 armnn::IConnectableLayer* const l2NormLayer = network->AddL2NormalizationLayer(desc, l2NormLayerName.c_str());
1495 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1496
1497 inputLayer0->GetOutputSlot(0).Connect(l2NormLayer->GetInputSlot(0));
1498 l2NormLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1499
1500 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1501 l2NormLayer->GetOutputSlot(0).SetTensorInfo(info);
1502
1503 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1504 CHECK(deserializedNetwork);
1505
1506 LayerVerifierBaseWithDescriptor<armnn::L2NormalizationDescriptor> verifier(
1507 l2NormLayerName, {info}, {info}, desc);
1508 deserializedNetwork->ExecuteStrategy(verifier);
1509 }
1510
1511 TEST_CASE("EnsureL2NormalizationBackwardCompatibility")
1512 {
1513 // The hex data below is a flat buffer containing a simple network with one input
1514 // a L2Normalization layer and an output layer with dimensions as per the tensor infos below.
1515 //
1516 // This test verifies that we can still read back these old style
1517 // models without the normalization epsilon value.
1518 const std::vector<uint8_t> l2NormalizationModel =
1519 {
1520 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1521 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1522 0x3C, 0x01, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1523 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xE8, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
1524 0x04, 0x00, 0x00, 0x00, 0xD6, 0xFE, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00,
1525 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x9E, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
1526 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1528 0x4C, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
1529 0x00, 0x20, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1530 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
1531 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1532 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x20, 0x00,
1533 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x6C, 0x32, 0x4E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x69, 0x7A, 0x61, 0x74,
1534 0x69, 0x6F, 0x6E, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00,
1535 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1536 0x52, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
1537 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
1538 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1539 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1540 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1541 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1542 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1543 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1544 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1545 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1546 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1547 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1548 0x05, 0x00, 0x00, 0x00, 0x00
1549 };
1550
1551 armnn::INetworkPtr deserializedNetwork =
1552 DeserializeNetwork(std::string(l2NormalizationModel.begin(), l2NormalizationModel.end()));
1553 CHECK(deserializedNetwork);
1554
1555 const std::string layerName("l2Normalization");
1556 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 2, 1, 5}, armnn::DataType::Float32, 0.0f, 0);
1557
1558 armnn::L2NormalizationDescriptor desc;
1559 desc.m_DataLayout = armnn::DataLayout::NCHW;
1560 // Since this variable does not exist in the l2NormalizationModel dump, the default value will be loaded
1561 desc.m_Eps = 1e-12f;
1562
1563 LayerVerifierBaseWithDescriptor<armnn::L2NormalizationDescriptor> verifier(
1564 layerName, {inputInfo}, {inputInfo}, desc);
1565 deserializedNetwork->ExecuteStrategy(verifier);
1566 }
1567
1568 TEST_CASE("SerializeLogicalBinary")
1569 {
1570 const std::string layerName("logicalBinaryAnd");
1571
1572 const armnn::TensorShape shape{2, 1, 2, 2};
1573
1574 const armnn::TensorInfo inputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
1575 const armnn::TensorInfo outputInfo = armnn::TensorInfo(shape, armnn::DataType::Boolean);
1576
1577 armnn::LogicalBinaryDescriptor descriptor(armnn::LogicalBinaryOperation::LogicalAnd);
1578
1579 armnn::INetworkPtr network = armnn::INetwork::Create();
1580 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1581 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1582 armnn::IConnectableLayer* const logicalBinaryLayer = network->AddLogicalBinaryLayer(descriptor, layerName.c_str());
1583 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1584
1585 inputLayer0->GetOutputSlot(0).Connect(logicalBinaryLayer->GetInputSlot(0));
1586 inputLayer1->GetOutputSlot(0).Connect(logicalBinaryLayer->GetInputSlot(1));
1587 logicalBinaryLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1588
1589 inputLayer0->GetOutputSlot(0).SetTensorInfo(inputInfo);
1590 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputInfo);
1591 logicalBinaryLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1592
1593 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1594 CHECK(deserializedNetwork);
1595
1596 LayerVerifierBaseWithDescriptor<armnn::LogicalBinaryDescriptor> verifier(
1597 layerName, { inputInfo, inputInfo }, { outputInfo }, descriptor);
1598 deserializedNetwork->ExecuteStrategy(verifier);
1599 }
1600
1601 TEST_CASE("SerializeLogSoftmax")
1602 {
1603 const std::string layerName("log_softmax");
1604 const armnn::TensorInfo info({1, 10}, armnn::DataType::Float32);
1605
1606 armnn::LogSoftmaxDescriptor descriptor;
1607 descriptor.m_Beta = 1.0f;
1608 descriptor.m_Axis = -1;
1609
1610 armnn::INetworkPtr network = armnn::INetwork::Create();
1611 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1612 armnn::IConnectableLayer* const logSoftmaxLayer = network->AddLogSoftmaxLayer(descriptor, layerName.c_str());
1613 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1614
1615 inputLayer->GetOutputSlot(0).Connect(logSoftmaxLayer->GetInputSlot(0));
1616 logSoftmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1617
1618 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1619 logSoftmaxLayer->GetOutputSlot(0).SetTensorInfo(info);
1620
1621 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1622 CHECK(deserializedNetwork);
1623
1624 LayerVerifierBaseWithDescriptor<armnn::LogSoftmaxDescriptor> verifier(layerName, {info}, {info}, descriptor);
1625 deserializedNetwork->ExecuteStrategy(verifier);
1626 }
1627
1628 TEST_CASE("SerializeMaximum")
1629 {
1630 const std::string layerName("maximum");
1631 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1632
1633 armnn::INetworkPtr network = armnn::INetwork::Create();
1634 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1635 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1636 ARMNN_NO_DEPRECATE_WARN_BEGIN
1637 armnn::IConnectableLayer* const maximumLayer = network->AddMaximumLayer(layerName.c_str());
1638 ARMNN_NO_DEPRECATE_WARN_END
1639 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1640
1641 inputLayer0->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(0));
1642 inputLayer1->GetOutputSlot(0).Connect(maximumLayer->GetInputSlot(1));
1643 maximumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1644
1645 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1646 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1647 maximumLayer->GetOutputSlot(0).SetTensorInfo(info);
1648
1649 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1650 CHECK(deserializedNetwork);
1651
1652 LayerVerifierBase verifier(layerName, {info, info}, {info});
1653 deserializedNetwork->ExecuteStrategy(verifier);
1654 }
1655
1656 TEST_CASE("SerializeMean")
1657 {
1658 const std::string layerName("mean");
1659 const armnn::TensorInfo inputInfo({1, 1, 3, 2}, armnn::DataType::Float32);
1660 const armnn::TensorInfo outputInfo({1, 1, 1, 2}, armnn::DataType::Float32);
1661
1662 armnn::MeanDescriptor descriptor;
1663 descriptor.m_Axis = { 2 };
1664 descriptor.m_KeepDims = true;
1665
1666 armnn::INetworkPtr network = armnn::INetwork::Create();
1667 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1668 armnn::IConnectableLayer* const meanLayer = network->AddMeanLayer(descriptor, layerName.c_str());
1669 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1670
1671 inputLayer->GetOutputSlot(0).Connect(meanLayer->GetInputSlot(0));
1672 meanLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1673
1674 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
1675 meanLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1676
1677 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1678 CHECK(deserializedNetwork);
1679
1680 LayerVerifierBaseWithDescriptor<armnn::MeanDescriptor> verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
1681 deserializedNetwork->ExecuteStrategy(verifier);
1682 }
1683
1684 TEST_CASE("SerializeMerge")
1685 {
1686 const std::string layerName("merge");
1687 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1688
1689 armnn::INetworkPtr network = armnn::INetwork::Create();
1690 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1691 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1692 armnn::IConnectableLayer* const mergeLayer = network->AddMergeLayer(layerName.c_str());
1693 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1694
1695 inputLayer0->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(0));
1696 inputLayer1->GetOutputSlot(0).Connect(mergeLayer->GetInputSlot(1));
1697 mergeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1698
1699 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1700 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1701 mergeLayer->GetOutputSlot(0).SetTensorInfo(info);
1702
1703 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1704 CHECK(deserializedNetwork);
1705
1706 LayerVerifierBase verifier(layerName, {info, info}, {info});
1707 deserializedNetwork->ExecuteStrategy(verifier);
1708 }
1709
1710 class MergerLayerVerifier : public LayerVerifierBaseWithDescriptor<armnn::OriginsDescriptor>
1711 {
1712 public:
MergerLayerVerifier(const std::string & layerName,const std::vector<armnn::TensorInfo> & inputInfos,const std::vector<armnn::TensorInfo> & outputInfos,const armnn::OriginsDescriptor & descriptor)1713 MergerLayerVerifier(const std::string& layerName,
1714 const std::vector<armnn::TensorInfo>& inputInfos,
1715 const std::vector<armnn::TensorInfo>& outputInfos,
1716 const armnn::OriginsDescriptor& descriptor)
1717 : LayerVerifierBaseWithDescriptor<armnn::OriginsDescriptor>(layerName, inputInfos, outputInfos, descriptor) {}
1718
ExecuteStrategy(const armnn::IConnectableLayer * layer,const armnn::BaseDescriptor & descriptor,const std::vector<armnn::ConstTensor> & constants,const char * name,const armnn::LayerBindingId id=0)1719 void ExecuteStrategy(const armnn::IConnectableLayer* layer,
1720 const armnn::BaseDescriptor& descriptor,
1721 const std::vector<armnn::ConstTensor>& constants,
1722 const char* name,
1723 const armnn::LayerBindingId id = 0) override
1724 {
1725 armnn::IgnoreUnused(descriptor, constants, id);
1726 switch (layer->GetType())
1727 {
1728 case armnn::LayerType::Input: break;
1729 case armnn::LayerType::Output: break;
1730 case armnn::LayerType::Merge:
1731 {
1732 throw armnn::Exception("MergerLayer should have translated to ConcatLayer");
1733 break;
1734 }
1735 case armnn::LayerType::Concat:
1736 {
1737 VerifyNameAndConnections(layer, name);
1738 const armnn::MergerDescriptor& layerDescriptor =
1739 static_cast<const armnn::MergerDescriptor&>(descriptor);
1740 VerifyDescriptor(layerDescriptor);
1741 break;
1742 }
1743 default:
1744 {
1745 throw armnn::Exception("Unexpected layer type in Merge test model");
1746 }
1747 }
1748 }
1749 };
1750
1751 TEST_CASE("EnsureMergerLayerBackwardCompatibility")
1752 {
1753 // The hex data below is a flat buffer containing a simple network with two inputs
1754 // a merger layer (now deprecated) and an output layer with dimensions as per the tensor infos below.
1755 //
1756 // This test verifies that we can still read back these old style
1757 // models replacing the MergerLayers with ConcatLayers with the same parameters.
1758 const std::vector<uint8_t> mergerModel =
1759 {
1760 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
1761 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1762 0x38, 0x02, 0x00, 0x00, 0x8C, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00,
1763 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
1764 0xF4, 0xFD, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x04, 0x00,
1765 0x00, 0x00, 0x9A, 0xFE, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x7E, 0xFE, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00,
1766 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
1767 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1768 0xF8, 0xFE, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xFE, 0xFF, 0xFF, 0x00, 0x00,
1769 0x00, 0x1F, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1770 0x68, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
1771 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
1772 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x22, 0xFF, 0xFF, 0xFF, 0x04, 0x00,
1773 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1774 0x00, 0x00, 0x00, 0x00, 0x3E, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
1775 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0xFF, 0xFF, 0xFF,
1776 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1C, 0x00,
1777 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x6D, 0x65, 0x72, 0x67, 0x65, 0x72, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1778 0x5C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x34, 0xFF,
1779 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x92, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
1780 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00,
1781 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
1782 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00,
1783 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1784 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
1785 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00,
1786 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1787 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
1788 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00,
1789 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
1790 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
1791 0x00, 0x00, 0x66, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1792 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
1793 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
1794 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00,
1795 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00,
1796 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
1797 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1798 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00,
1799 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00,
1800 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
1801 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
1802 0x02, 0x00, 0x00, 0x00
1803 };
1804
1805 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(mergerModel.begin(), mergerModel.end()));
1806 CHECK(deserializedNetwork);
1807
1808 const armnn::TensorInfo inputInfo = armnn::TensorInfo({ 2, 3, 2, 2 }, armnn::DataType::Float32, 0.0f, 0);
1809 const armnn::TensorInfo outputInfo = armnn::TensorInfo({ 4, 3, 2, 2 }, armnn::DataType::Float32, 0.0f, 0);
1810
1811 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1812
1813 armnn::OriginsDescriptor descriptor =
1814 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
1815
1816 MergerLayerVerifier verifier("merger", { inputInfo, inputInfo }, { outputInfo }, descriptor);
1817 deserializedNetwork->ExecuteStrategy(verifier);
1818 }
1819
1820 TEST_CASE("SerializeConcat")
1821 {
1822 const std::string layerName("concat");
1823 const armnn::TensorInfo inputInfo = armnn::TensorInfo({2, 3, 2, 2}, armnn::DataType::Float32);
1824 const armnn::TensorInfo outputInfo = armnn::TensorInfo({4, 3, 2, 2}, armnn::DataType::Float32);
1825
1826 const std::vector<armnn::TensorShape> shapes({inputInfo.GetShape(), inputInfo.GetShape()});
1827
1828 armnn::OriginsDescriptor descriptor =
1829 armnn::CreateDescriptorForConcatenation(shapes.begin(), shapes.end(), 0);
1830
1831 armnn::INetworkPtr network = armnn::INetwork::Create();
1832 armnn::IConnectableLayer* const inputLayerOne = network->AddInputLayer(0);
1833 armnn::IConnectableLayer* const inputLayerTwo = network->AddInputLayer(1);
1834 armnn::IConnectableLayer* const concatLayer = network->AddConcatLayer(descriptor, layerName.c_str());
1835 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1836
1837 inputLayerOne->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(0));
1838 inputLayerTwo->GetOutputSlot(0).Connect(concatLayer->GetInputSlot(1));
1839 concatLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1840
1841 inputLayerOne->GetOutputSlot(0).SetTensorInfo(inputInfo);
1842 inputLayerTwo->GetOutputSlot(0).SetTensorInfo(inputInfo);
1843 concatLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1844
1845 std::string concatLayerNetwork = SerializeNetwork(*network);
1846 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(concatLayerNetwork);
1847 CHECK(deserializedNetwork);
1848
1849 // NOTE: using the MergerLayerVerifier to ensure that it is a concat layer and not a
1850 // merger layer that gets placed into the graph.
1851 MergerLayerVerifier verifier(layerName, {inputInfo, inputInfo}, {outputInfo}, descriptor);
1852 deserializedNetwork->ExecuteStrategy(verifier);
1853 }
1854
1855 TEST_CASE("SerializeMinimum")
1856 {
1857 const std::string layerName("minimum");
1858 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
1859
1860 armnn::INetworkPtr network = armnn::INetwork::Create();
1861 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1862 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1863 ARMNN_NO_DEPRECATE_WARN_BEGIN
1864 armnn::IConnectableLayer* const minimumLayer = network->AddMinimumLayer(layerName.c_str());
1865 ARMNN_NO_DEPRECATE_WARN_END
1866 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1867
1868 inputLayer0->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(0));
1869 inputLayer1->GetOutputSlot(0).Connect(minimumLayer->GetInputSlot(1));
1870 minimumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1871
1872 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1873 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1874 minimumLayer->GetOutputSlot(0).SetTensorInfo(info);
1875
1876 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1877 CHECK(deserializedNetwork);
1878
1879 LayerVerifierBase verifier(layerName, {info, info}, {info});
1880 deserializedNetwork->ExecuteStrategy(verifier);
1881 }
1882
1883 TEST_CASE("SerializeMultiplication")
1884 {
1885 const std::string layerName("multiplication");
1886 const armnn::TensorInfo info({ 1, 5, 2, 3 }, armnn::DataType::Float32);
1887
1888 armnn::INetworkPtr network = armnn::INetwork::Create();
1889 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
1890 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
1891 ARMNN_NO_DEPRECATE_WARN_BEGIN
1892 armnn::IConnectableLayer* const multiplicationLayer = network->AddMultiplicationLayer(layerName.c_str());
1893 ARMNN_NO_DEPRECATE_WARN_END
1894 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1895
1896 inputLayer0->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(0));
1897 inputLayer1->GetOutputSlot(0).Connect(multiplicationLayer->GetInputSlot(1));
1898 multiplicationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1899
1900 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
1901 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
1902 multiplicationLayer->GetOutputSlot(0).SetTensorInfo(info);
1903
1904 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1905 CHECK(deserializedNetwork);
1906
1907 LayerVerifierBase verifier(layerName, {info, info}, {info});
1908 deserializedNetwork->ExecuteStrategy(verifier);
1909 }
1910
1911 TEST_CASE("SerializePrelu")
1912 {
1913 const std::string layerName("prelu");
1914
1915 armnn::TensorInfo inputTensorInfo ({ 4, 1, 2 }, armnn::DataType::Float32);
1916 armnn::TensorInfo alphaTensorInfo ({ 5, 4, 3, 1 }, armnn::DataType::Float32);
1917 armnn::TensorInfo outputTensorInfo({ 5, 4, 3, 2 }, armnn::DataType::Float32);
1918
1919 armnn::INetworkPtr network = armnn::INetwork::Create();
1920 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1921 armnn::IConnectableLayer* const alphaLayer = network->AddInputLayer(1);
1922 armnn::IConnectableLayer* const preluLayer = network->AddPreluLayer(layerName.c_str());
1923 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1924
1925 inputLayer->GetOutputSlot(0).Connect(preluLayer->GetInputSlot(0));
1926 alphaLayer->GetOutputSlot(0).Connect(preluLayer->GetInputSlot(1));
1927 preluLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1928
1929 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1930 alphaLayer->GetOutputSlot(0).SetTensorInfo(alphaTensorInfo);
1931 preluLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1932
1933 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1934 CHECK(deserializedNetwork);
1935
1936 LayerVerifierBase verifier(layerName, {inputTensorInfo, alphaTensorInfo}, {outputTensorInfo});
1937 deserializedNetwork->ExecuteStrategy(verifier);
1938 }
1939
1940 TEST_CASE("SerializeNormalization")
1941 {
1942 const std::string layerName("normalization");
1943 const armnn::TensorInfo info({2, 1, 2, 2}, armnn::DataType::Float32);
1944
1945 armnn::NormalizationDescriptor desc;
1946 desc.m_DataLayout = armnn::DataLayout::NCHW;
1947 desc.m_NormSize = 3;
1948 desc.m_Alpha = 1;
1949 desc.m_Beta = 1;
1950 desc.m_K = 1;
1951
1952 armnn::INetworkPtr network = armnn::INetwork::Create();
1953 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1954 armnn::IConnectableLayer* const normalizationLayer = network->AddNormalizationLayer(desc, layerName.c_str());
1955 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1956
1957 inputLayer->GetOutputSlot(0).Connect(normalizationLayer->GetInputSlot(0));
1958 normalizationLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1959
1960 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
1961 normalizationLayer->GetOutputSlot(0).SetTensorInfo(info);
1962
1963 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1964 CHECK(deserializedNetwork);
1965
1966 LayerVerifierBaseWithDescriptor<armnn::NormalizationDescriptor> verifier(layerName, {info}, {info}, desc);
1967 deserializedNetwork->ExecuteStrategy(verifier);
1968 }
1969
1970 TEST_CASE("SerializePad")
1971 {
1972 const std::string layerName("pad");
1973 const armnn::TensorInfo inputTensorInfo = armnn::TensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
1974 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 5, 7}, armnn::DataType::Float32);
1975
1976 armnn::PadDescriptor desc({{0, 0}, {1, 0}, {1, 1}, {1, 2}});
1977
1978 armnn::INetworkPtr network = armnn::INetwork::Create();
1979 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
1980 armnn::IConnectableLayer* const padLayer = network->AddPadLayer(desc, layerName.c_str());
1981 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
1982
1983 inputLayer->GetOutputSlot(0).Connect(padLayer->GetInputSlot(0));
1984 padLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1985
1986 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
1987 padLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1988
1989 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
1990 CHECK(deserializedNetwork);
1991
1992 LayerVerifierBaseWithDescriptor<armnn::PadDescriptor> verifier(layerName,
1993 {inputTensorInfo},
1994 {outputTensorInfo},
1995 desc);
1996 deserializedNetwork->ExecuteStrategy(verifier);
1997 }
1998
1999 TEST_CASE("SerializePadReflect")
2000 {
2001 const std::string layerName("padReflect");
2002 const armnn::TensorInfo inputTensorInfo = armnn::TensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
2003 const armnn::TensorInfo outputTensorInfo = armnn::TensorInfo({1, 3, 5, 7}, armnn::DataType::Float32);
2004
2005 armnn::PadDescriptor desc({{0, 0}, {1, 0}, {1, 1}, {1, 2}});
2006 desc.m_PaddingMode = armnn::PaddingMode::Reflect;
2007
2008 armnn::INetworkPtr network = armnn::INetwork::Create();
2009 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2010 armnn::IConnectableLayer* const padLayer = network->AddPadLayer(desc, layerName.c_str());
2011 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2012
2013 inputLayer->GetOutputSlot(0).Connect(padLayer->GetInputSlot(0));
2014 padLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2015
2016 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2017 padLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2018
2019 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2020 CHECK(deserializedNetwork);
2021
2022 LayerVerifierBaseWithDescriptor<armnn::PadDescriptor> verifier(layerName,
2023 {inputTensorInfo},
2024 {outputTensorInfo},
2025 desc);
2026 deserializedNetwork->ExecuteStrategy(verifier);
2027 }
2028
2029 TEST_CASE("EnsurePadBackwardCompatibility")
2030 {
2031 // The PadDescriptor is being extended with a float PadValue (so a value other than 0
2032 // can be used to pad the tensor.
2033 //
2034 // This test contains a binary representation of a simple input->pad->output network
2035 // prior to this change to test that the descriptor has been updated in a backward
2036 // compatible way with respect to Deserialization of older binary dumps
2037 const std::vector<uint8_t> padModel =
2038 {
2039 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
2040 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
2041 0x54, 0x01, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
2042 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xD0, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
2043 0x04, 0x00, 0x00, 0x00, 0x96, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x9E, 0xFF, 0xFF, 0xFF, 0x04, 0x00,
2044 0x00, 0x00, 0x72, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
2045 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
2046 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00,
2047 0x00, 0x00, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x16, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00,
2048 0x0E, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
2049 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00,
2050 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2051 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
2052 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00, 0x00, 0x00,
2053 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00,
2054 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
2055 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
2056 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
2057 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00,
2058 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
2059 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00,
2060 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00,
2061 0x00, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
2062 0x0E, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00,
2063 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
2064 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
2065 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
2066 0x0A, 0x00, 0x10, 0x00, 0x08, 0x00, 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
2067 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
2068 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00
2069 };
2070
2071 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(std::string(padModel.begin(), padModel.end()));
2072 CHECK(deserializedNetwork);
2073
2074 const armnn::TensorInfo inputInfo = armnn::TensorInfo({ 1, 2, 3, 4 }, armnn::DataType::Float32, 0.0f, 0);
2075 const armnn::TensorInfo outputInfo = armnn::TensorInfo({ 1, 3, 5, 7 }, armnn::DataType::Float32, 0.0f, 0);
2076
2077 armnn::PadDescriptor descriptor({{ 0, 0 }, { 1, 0 }, { 1, 1 }, { 1, 2 }});
2078
2079 LayerVerifierBaseWithDescriptor<armnn::PadDescriptor> verifier("pad", { inputInfo }, { outputInfo }, descriptor);
2080 deserializedNetwork->ExecuteStrategy(verifier);
2081 }
2082
2083 TEST_CASE("SerializePermute")
2084 {
2085 const std::string layerName("permute");
2086 const armnn::TensorInfo inputTensorInfo({4, 3, 2, 1}, armnn::DataType::Float32);
2087 const armnn::TensorInfo outputTensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
2088
2089 armnn::PermuteDescriptor descriptor(armnn::PermutationVector({3, 2, 1, 0}));
2090
2091 armnn::INetworkPtr network = armnn::INetwork::Create();
2092 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2093 armnn::IConnectableLayer* const permuteLayer = network->AddPermuteLayer(descriptor, layerName.c_str());
2094 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2095
2096 inputLayer->GetOutputSlot(0).Connect(permuteLayer->GetInputSlot(0));
2097 permuteLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2098
2099 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2100 permuteLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2101
2102 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2103 CHECK(deserializedNetwork);
2104
2105 LayerVerifierBaseWithDescriptor<armnn::PermuteDescriptor> verifier(
2106 layerName, {inputTensorInfo}, {outputTensorInfo}, descriptor);
2107 deserializedNetwork->ExecuteStrategy(verifier);
2108 }
2109
2110 TEST_CASE("SerializePooling2d")
2111 {
2112 const std::string layerName("pooling2d");
2113 const armnn::TensorInfo inputInfo({1, 2, 2, 1}, armnn::DataType::Float32);
2114 const armnn::TensorInfo outputInfo({1, 1, 1, 1}, armnn::DataType::Float32);
2115
2116 armnn::Pooling2dDescriptor desc;
2117 desc.m_DataLayout = armnn::DataLayout::NHWC;
2118 desc.m_PadTop = 0;
2119 desc.m_PadBottom = 0;
2120 desc.m_PadLeft = 0;
2121 desc.m_PadRight = 0;
2122 desc.m_PoolType = armnn::PoolingAlgorithm::Average;
2123 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
2124 desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
2125 desc.m_PoolHeight = 2;
2126 desc.m_PoolWidth = 2;
2127 desc.m_StrideX = 2;
2128 desc.m_StrideY = 2;
2129
2130 armnn::INetworkPtr network = armnn::INetwork::Create();
2131 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2132 armnn::IConnectableLayer* const pooling2dLayer = network->AddPooling2dLayer(desc, layerName.c_str());
2133 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2134
2135 inputLayer->GetOutputSlot(0).Connect(pooling2dLayer->GetInputSlot(0));
2136 pooling2dLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2137
2138 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2139 pooling2dLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2140
2141 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2142 CHECK(deserializedNetwork);
2143
2144 LayerVerifierBaseWithDescriptor<armnn::Pooling2dDescriptor> verifier(
2145 layerName, {inputInfo}, {outputInfo}, desc);
2146 deserializedNetwork->ExecuteStrategy(verifier);
2147 }
2148
2149 TEST_CASE("SerializePooling3d")
2150 {
2151 const std::string layerName("pooling3d");
2152 const armnn::TensorInfo inputInfo({1, 1, 2, 2, 2}, armnn::DataType::Float32);
2153 const armnn::TensorInfo outputInfo({1, 1, 1, 1, 1}, armnn::DataType::Float32);
2154
2155 armnn::Pooling3dDescriptor desc;
2156 desc.m_DataLayout = armnn::DataLayout::NDHWC;
2157 desc.m_PadFront = 0;
2158 desc.m_PadBack = 0;
2159 desc.m_PadTop = 0;
2160 desc.m_PadBottom = 0;
2161 desc.m_PadLeft = 0;
2162 desc.m_PadRight = 0;
2163 desc.m_PoolType = armnn::PoolingAlgorithm::Average;
2164 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
2165 desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
2166 desc.m_PoolHeight = 2;
2167 desc.m_PoolWidth = 2;
2168 desc.m_PoolDepth = 2;
2169 desc.m_StrideX = 2;
2170 desc.m_StrideY = 2;
2171 desc.m_StrideZ = 2;
2172
2173 armnn::INetworkPtr network = armnn::INetwork::Create();
2174 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2175 armnn::IConnectableLayer* const pooling3dLayer = network->AddPooling3dLayer(desc, layerName.c_str());
2176 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2177
2178 inputLayer->GetOutputSlot(0).Connect(pooling3dLayer->GetInputSlot(0));
2179 pooling3dLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2180
2181 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2182 pooling3dLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2183
2184 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2185 CHECK(deserializedNetwork);
2186
2187 LayerVerifierBaseWithDescriptor<armnn::Pooling3dDescriptor> verifier(
2188 layerName, {inputInfo}, {outputInfo}, desc);
2189 deserializedNetwork->ExecuteStrategy(verifier);
2190 }
2191
2192 TEST_CASE("SerializeQuantize")
2193 {
2194 const std::string layerName("quantize");
2195 const armnn::TensorInfo info({ 1, 2, 2, 3 }, armnn::DataType::Float32);
2196
2197 armnn::INetworkPtr network = armnn::INetwork::Create();
2198 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2199 armnn::IConnectableLayer* const quantizeLayer = network->AddQuantizeLayer(layerName.c_str());
2200 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2201
2202 inputLayer->GetOutputSlot(0).Connect(quantizeLayer->GetInputSlot(0));
2203 quantizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2204
2205 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2206 quantizeLayer->GetOutputSlot(0).SetTensorInfo(info);
2207
2208 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2209 CHECK(deserializedNetwork);
2210
2211 LayerVerifierBase verifier(layerName, {info}, {info});
2212 deserializedNetwork->ExecuteStrategy(verifier);
2213 }
2214
2215 TEST_CASE("SerializeRank")
2216 {
2217 const std::string layerName("rank");
2218 const armnn::TensorInfo inputInfo({1, 9}, armnn::DataType::Float32);
2219 const armnn::TensorInfo outputInfo({1}, armnn::DataType::Signed32);
2220
2221 armnn::INetworkPtr network = armnn::INetwork::Create();
2222 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2223 armnn::IConnectableLayer* const rankLayer = network->AddRankLayer(layerName.c_str());
2224 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2225
2226 inputLayer->GetOutputSlot(0).Connect(rankLayer->GetInputSlot(0));
2227 rankLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2228
2229 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2230 rankLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2231
2232 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2233 CHECK(deserializedNetwork);
2234
2235 LayerVerifierBase verifier(layerName, {inputInfo}, {outputInfo});
2236 deserializedNetwork->ExecuteStrategy(verifier);
2237 }
2238
2239 TEST_CASE("SerializeReduceSum")
2240 {
2241 const std::string layerName("Reduce_Sum");
2242 const armnn::TensorInfo inputInfo({1, 1, 3, 2}, armnn::DataType::Float32);
2243 const armnn::TensorInfo outputInfo({1, 1, 1, 2}, armnn::DataType::Float32);
2244
2245 armnn::ReduceDescriptor descriptor;
2246 descriptor.m_vAxis = { 2 };
2247 descriptor.m_ReduceOperation = armnn::ReduceOperation::Sum;
2248
2249 armnn::INetworkPtr network = armnn::INetwork::Create();
2250 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2251 armnn::IConnectableLayer* const reduceSumLayer = network->AddReduceLayer(descriptor, layerName.c_str());
2252 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2253
2254 inputLayer->GetOutputSlot(0).Connect(reduceSumLayer->GetInputSlot(0));
2255 reduceSumLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2256
2257 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2258 reduceSumLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2259
2260 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2261 CHECK(deserializedNetwork);
2262
2263 LayerVerifierBaseWithDescriptor<armnn::ReduceDescriptor> verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
2264 deserializedNetwork->ExecuteStrategy(verifier);
2265 }
2266
2267 TEST_CASE("SerializeReshape")
2268 {
2269 const std::string layerName("reshape");
2270 const armnn::TensorInfo inputInfo({1, 9}, armnn::DataType::Float32);
2271 const armnn::TensorInfo outputInfo({3, 3}, armnn::DataType::Float32);
2272
2273 armnn::ReshapeDescriptor descriptor({3, 3});
2274
2275 armnn::INetworkPtr network = armnn::INetwork::Create();
2276 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2277 armnn::IConnectableLayer* const reshapeLayer = network->AddReshapeLayer(descriptor, layerName.c_str());
2278 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2279
2280 inputLayer->GetOutputSlot(0).Connect(reshapeLayer->GetInputSlot(0));
2281 reshapeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2282
2283 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2284 reshapeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2285
2286 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2287 CHECK(deserializedNetwork);
2288
2289 LayerVerifierBaseWithDescriptor<armnn::ReshapeDescriptor> verifier(
2290 layerName, {inputInfo}, {outputInfo}, descriptor);
2291 deserializedNetwork->ExecuteStrategy(verifier);
2292 }
2293
2294 TEST_CASE("SerializeResize")
2295 {
2296 const std::string layerName("resize");
2297 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
2298 const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
2299
2300 armnn::ResizeDescriptor desc;
2301 desc.m_TargetWidth = 4;
2302 desc.m_TargetHeight = 2;
2303 desc.m_Method = armnn::ResizeMethod::NearestNeighbor;
2304 desc.m_AlignCorners = true;
2305 desc.m_HalfPixelCenters = true;
2306
2307 armnn::INetworkPtr network = armnn::INetwork::Create();
2308 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2309 armnn::IConnectableLayer* const resizeLayer = network->AddResizeLayer(desc, layerName.c_str());
2310 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2311
2312 inputLayer->GetOutputSlot(0).Connect(resizeLayer->GetInputSlot(0));
2313 resizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2314
2315 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2316 resizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2317
2318 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2319 CHECK(deserializedNetwork);
2320
2321 LayerVerifierBaseWithDescriptor<armnn::ResizeDescriptor> verifier(layerName, {inputInfo}, {outputInfo}, desc);
2322 deserializedNetwork->ExecuteStrategy(verifier);
2323 }
2324
2325 class ResizeBilinearLayerVerifier : public LayerVerifierBaseWithDescriptor<armnn::ResizeDescriptor>
2326 {
2327 public:
ResizeBilinearLayerVerifier(const std::string & layerName,const std::vector<armnn::TensorInfo> & inputInfos,const std::vector<armnn::TensorInfo> & outputInfos,const armnn::ResizeDescriptor & descriptor)2328 ResizeBilinearLayerVerifier(const std::string& layerName,
2329 const std::vector<armnn::TensorInfo>& inputInfos,
2330 const std::vector<armnn::TensorInfo>& outputInfos,
2331 const armnn::ResizeDescriptor& descriptor)
2332 : LayerVerifierBaseWithDescriptor<armnn::ResizeDescriptor>(
2333 layerName, inputInfos, outputInfos, descriptor) {}
2334
ExecuteStrategy(const armnn::IConnectableLayer * layer,const armnn::BaseDescriptor & descriptor,const std::vector<armnn::ConstTensor> & constants,const char * name,const armnn::LayerBindingId id=0)2335 void ExecuteStrategy(const armnn::IConnectableLayer* layer,
2336 const armnn::BaseDescriptor& descriptor,
2337 const std::vector<armnn::ConstTensor>& constants,
2338 const char* name,
2339 const armnn::LayerBindingId id = 0) override
2340 {
2341 armnn::IgnoreUnused(descriptor, constants, id);
2342 switch (layer->GetType())
2343 {
2344 case armnn::LayerType::Input: break;
2345 case armnn::LayerType::Output: break;
2346 case armnn::LayerType::Resize:
2347 {
2348 VerifyNameAndConnections(layer, name);
2349 const armnn::ResizeDescriptor& layerDescriptor =
2350 static_cast<const armnn::ResizeDescriptor&>(descriptor);
2351 CHECK(layerDescriptor.m_Method == armnn::ResizeMethod::Bilinear);
2352 CHECK(layerDescriptor.m_TargetWidth == m_Descriptor.m_TargetWidth);
2353 CHECK(layerDescriptor.m_TargetHeight == m_Descriptor.m_TargetHeight);
2354 CHECK(layerDescriptor.m_DataLayout == m_Descriptor.m_DataLayout);
2355 CHECK(layerDescriptor.m_AlignCorners == m_Descriptor.m_AlignCorners);
2356 CHECK(layerDescriptor.m_HalfPixelCenters == m_Descriptor.m_HalfPixelCenters);
2357 break;
2358 }
2359 default:
2360 {
2361 throw armnn::Exception("Unexpected layer type in test model. ResizeBiliniar "
2362 "should have translated to Resize");
2363 }
2364 }
2365 }
2366 };
2367
2368 TEST_CASE("SerializeResizeBilinear")
2369 {
2370 const std::string layerName("resizeBilinear");
2371 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32);
2372 const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32);
2373
2374 armnn::ResizeDescriptor desc;
2375 desc.m_Method = armnn::ResizeMethod::Bilinear;
2376 desc.m_TargetWidth = 4u;
2377 desc.m_TargetHeight = 2u;
2378 desc.m_AlignCorners = true;
2379 desc.m_HalfPixelCenters = true;
2380
2381 armnn::INetworkPtr network = armnn::INetwork::Create();
2382 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2383 armnn::IConnectableLayer* const resizeLayer = network->AddResizeLayer(desc, layerName.c_str());
2384 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2385
2386 inputLayer->GetOutputSlot(0).Connect(resizeLayer->GetInputSlot(0));
2387 resizeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2388
2389 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2390 resizeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2391
2392 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2393 CHECK(deserializedNetwork);
2394
2395 ResizeBilinearLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, desc);
2396 deserializedNetwork->ExecuteStrategy(verifier);
2397 }
2398
2399 TEST_CASE("EnsureResizeBilinearBackwardCompatibility")
2400 {
2401 // The hex data below is a flat buffer containing a simple network with an input,
2402 // a ResizeBilinearLayer (now deprecated and removed) and an output
2403 //
2404 // This test verifies that we can still deserialize this old-style model by replacing
2405 // the ResizeBilinearLayer with an equivalent ResizeLayer
2406 const std::vector<uint8_t> resizeBilinearModel =
2407 {
2408 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x0A, 0x00,
2409 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
2410 0x50, 0x01, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
2411 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xD4, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0B,
2412 0x04, 0x00, 0x00, 0x00, 0xC2, 0xFE, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00,
2413 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8A, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
2414 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
2415 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2416 0x38, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
2417 0x00, 0x1A, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0E, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
2418 0x34, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x12, 0x00, 0x08, 0x00, 0x0C, 0x00,
2419 0x07, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
2420 0x00, 0x00, 0x0E, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x14, 0x00, 0x0E, 0x00,
2421 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
2422 0x20, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x72, 0x65, 0x73, 0x69, 0x7A, 0x65, 0x42, 0x69, 0x6C, 0x69,
2423 0x6E, 0x65, 0x61, 0x72, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
2424 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
2425 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2426 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00,
2427 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2428 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
2429 0x00, 0x09, 0x04, 0x00, 0x00, 0x00, 0xF6, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
2430 0x0A, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x14, 0x00,
2431 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
2432 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2433 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0A, 0x00,
2434 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x10, 0x00,
2435 0x08, 0x00, 0x07, 0x00, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
2436 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00,
2437 0x00, 0x00, 0x05, 0x00, 0x00, 0x00
2438 };
2439
2440 armnn::INetworkPtr deserializedNetwork =
2441 DeserializeNetwork(std::string(resizeBilinearModel.begin(), resizeBilinearModel.end()));
2442 CHECK(deserializedNetwork);
2443
2444 const armnn::TensorInfo inputInfo = armnn::TensorInfo({1, 3, 5, 5}, armnn::DataType::Float32, 0.0f, 0);
2445 const armnn::TensorInfo outputInfo = armnn::TensorInfo({1, 3, 2, 4}, armnn::DataType::Float32, 0.0f, 0);
2446
2447 armnn::ResizeDescriptor descriptor;
2448 descriptor.m_TargetWidth = 4u;
2449 descriptor.m_TargetHeight = 2u;
2450
2451 ResizeBilinearLayerVerifier verifier("resizeBilinear", { inputInfo }, { outputInfo }, descriptor);
2452 deserializedNetwork->ExecuteStrategy(verifier);
2453 }
2454
2455 TEST_CASE("SerializeShape")
2456 {
2457 const std::string layerName("shape");
2458 const armnn::TensorInfo inputInfo({1, 3, 3, 1}, armnn::DataType::Signed32);
2459 const armnn::TensorInfo outputInfo({ 4 }, armnn::DataType::Signed32);
2460
2461 armnn::INetworkPtr network = armnn::INetwork::Create();
2462 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2463 armnn::IConnectableLayer* const shapeLayer = network->AddShapeLayer(layerName.c_str());
2464 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2465
2466 inputLayer->GetOutputSlot(0).Connect(shapeLayer->GetInputSlot(0));
2467 shapeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2468
2469 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2470 shapeLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2471
2472 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2473 CHECK(deserializedNetwork);
2474
2475 LayerVerifierBase verifier(layerName, {inputInfo}, {outputInfo});
2476
2477 deserializedNetwork->ExecuteStrategy(verifier);
2478 }
2479
2480 TEST_CASE("SerializeSlice")
2481 {
2482 const std::string layerName{"slice"};
2483
2484 const armnn::TensorInfo inputInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32);
2485 const armnn::TensorInfo outputInfo = armnn::TensorInfo({2, 2, 2, 1}, armnn::DataType::Float32);
2486
2487 armnn::SliceDescriptor descriptor({ 0, 0, 1, 0}, {2, 2, 2, 1});
2488
2489 armnn::INetworkPtr network = armnn::INetwork::Create();
2490
2491 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2492 armnn::IConnectableLayer* const sliceLayer = network->AddSliceLayer(descriptor, layerName.c_str());
2493 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2494
2495 inputLayer->GetOutputSlot(0).Connect(sliceLayer->GetInputSlot(0));
2496 sliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2497
2498 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2499 sliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2500
2501 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2502 CHECK(deserializedNetwork);
2503
2504 LayerVerifierBaseWithDescriptor<armnn::SliceDescriptor> verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
2505 deserializedNetwork->ExecuteStrategy(verifier);
2506 }
2507
2508 TEST_CASE("SerializeSoftmax")
2509 {
2510 const std::string layerName("softmax");
2511 const armnn::TensorInfo info({1, 10}, armnn::DataType::Float32);
2512
2513 armnn::SoftmaxDescriptor descriptor;
2514 descriptor.m_Beta = 1.0f;
2515
2516 armnn::INetworkPtr network = armnn::INetwork::Create();
2517 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2518 armnn::IConnectableLayer* const softmaxLayer = network->AddSoftmaxLayer(descriptor, layerName.c_str());
2519 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2520
2521 inputLayer->GetOutputSlot(0).Connect(softmaxLayer->GetInputSlot(0));
2522 softmaxLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2523
2524 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2525 softmaxLayer->GetOutputSlot(0).SetTensorInfo(info);
2526
2527 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2528 CHECK(deserializedNetwork);
2529
2530 LayerVerifierBaseWithDescriptor<armnn::SoftmaxDescriptor> verifier(layerName, {info}, {info}, descriptor);
2531 deserializedNetwork->ExecuteStrategy(verifier);
2532 }
2533
2534 TEST_CASE("SerializeSpaceToBatchNd")
2535 {
2536 const std::string layerName("spaceToBatchNd");
2537 const armnn::TensorInfo inputInfo({2, 1, 2, 4}, armnn::DataType::Float32);
2538 const armnn::TensorInfo outputInfo({8, 1, 1, 3}, armnn::DataType::Float32);
2539
2540 armnn::SpaceToBatchNdDescriptor desc;
2541 desc.m_DataLayout = armnn::DataLayout::NCHW;
2542 desc.m_BlockShape = {2, 2};
2543 desc.m_PadList = {{0, 0}, {2, 0}};
2544
2545 armnn::INetworkPtr network = armnn::INetwork::Create();
2546 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2547 armnn::IConnectableLayer* const spaceToBatchNdLayer = network->AddSpaceToBatchNdLayer(desc, layerName.c_str());
2548 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2549
2550 inputLayer->GetOutputSlot(0).Connect(spaceToBatchNdLayer->GetInputSlot(0));
2551 spaceToBatchNdLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2552
2553 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2554 spaceToBatchNdLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2555
2556 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2557 CHECK(deserializedNetwork);
2558
2559 LayerVerifierBaseWithDescriptor<armnn::SpaceToBatchNdDescriptor> verifier(
2560 layerName, {inputInfo}, {outputInfo}, desc);
2561 deserializedNetwork->ExecuteStrategy(verifier);
2562 }
2563
2564 TEST_CASE("SerializeSpaceToDepth")
2565 {
2566 const std::string layerName("spaceToDepth");
2567
2568 const armnn::TensorInfo inputInfo ({ 1, 16, 8, 3 }, armnn::DataType::Float32);
2569 const armnn::TensorInfo outputInfo({ 1, 8, 4, 12 }, armnn::DataType::Float32);
2570
2571 armnn::SpaceToDepthDescriptor desc;
2572 desc.m_BlockSize = 2;
2573 desc.m_DataLayout = armnn::DataLayout::NHWC;
2574
2575 armnn::INetworkPtr network = armnn::INetwork::Create();
2576 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2577 armnn::IConnectableLayer* const spaceToDepthLayer = network->AddSpaceToDepthLayer(desc, layerName.c_str());
2578 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2579
2580 inputLayer->GetOutputSlot(0).Connect(spaceToDepthLayer->GetInputSlot(0));
2581 spaceToDepthLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2582
2583 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2584 spaceToDepthLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2585
2586 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2587 CHECK(deserializedNetwork);
2588
2589 LayerVerifierBaseWithDescriptor<armnn::SpaceToDepthDescriptor> verifier(
2590 layerName, {inputInfo}, {outputInfo}, desc);
2591 deserializedNetwork->ExecuteStrategy(verifier);
2592 }
2593
2594 TEST_CASE("SerializeSplitter")
2595 {
2596 const unsigned int numViews = 3;
2597 const unsigned int numDimensions = 4;
2598 const unsigned int inputShape[] = {1, 18, 4, 4};
2599 const unsigned int outputShape[] = {1, 6, 4, 4};
2600
2601 // This is modelled on how the caffe parser sets up a splitter layer to partition an input along dimension one.
2602 unsigned int splitterDimSizes[4] = {static_cast<unsigned int>(inputShape[0]),
2603 static_cast<unsigned int>(inputShape[1]),
2604 static_cast<unsigned int>(inputShape[2]),
2605 static_cast<unsigned int>(inputShape[3])};
2606 splitterDimSizes[1] /= numViews;
2607 armnn::ViewsDescriptor desc(numViews, numDimensions);
2608
2609 for (unsigned int g = 0; g < numViews; ++g)
2610 {
2611 desc.SetViewOriginCoord(g, 1, splitterDimSizes[1] * g);
2612
2613 for (unsigned int dimIdx=0; dimIdx < 4; dimIdx++)
2614 {
2615 desc.SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]);
2616 }
2617 }
2618
2619 const std::string layerName("splitter");
2620 const armnn::TensorInfo inputInfo(numDimensions, inputShape, armnn::DataType::Float32);
2621 const armnn::TensorInfo outputInfo(numDimensions, outputShape, armnn::DataType::Float32);
2622
2623 armnn::INetworkPtr network = armnn::INetwork::Create();
2624 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2625 armnn::IConnectableLayer* const splitterLayer = network->AddSplitterLayer(desc, layerName.c_str());
2626 armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
2627 armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1);
2628 armnn::IConnectableLayer* const outputLayer2 = network->AddOutputLayer(2);
2629
2630 inputLayer->GetOutputSlot(0).Connect(splitterLayer->GetInputSlot(0));
2631 splitterLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
2632 splitterLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0));
2633 splitterLayer->GetOutputSlot(2).Connect(outputLayer2->GetInputSlot(0));
2634
2635 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2636 splitterLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2637 splitterLayer->GetOutputSlot(1).SetTensorInfo(outputInfo);
2638 splitterLayer->GetOutputSlot(2).SetTensorInfo(outputInfo);
2639
2640 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2641 CHECK(deserializedNetwork);
2642
2643 LayerVerifierBaseWithDescriptor<armnn::ViewsDescriptor> verifier(
2644 layerName, {inputInfo}, {outputInfo, outputInfo, outputInfo}, desc);
2645 deserializedNetwork->ExecuteStrategy(verifier);
2646 }
2647
2648 TEST_CASE("SerializeStack")
2649 {
2650 const std::string layerName("stack");
2651
2652 armnn::TensorInfo inputTensorInfo ({4, 3, 5}, armnn::DataType::Float32);
2653 armnn::TensorInfo outputTensorInfo({4, 3, 2, 5}, armnn::DataType::Float32);
2654
2655 armnn::StackDescriptor descriptor(2, 2, {4, 3, 5});
2656
2657 armnn::INetworkPtr network = armnn::INetwork::Create();
2658 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(0);
2659 armnn::IConnectableLayer* const inputLayer2 = network->AddInputLayer(1);
2660 armnn::IConnectableLayer* const stackLayer = network->AddStackLayer(descriptor, layerName.c_str());
2661 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2662
2663 inputLayer1->GetOutputSlot(0).Connect(stackLayer->GetInputSlot(0));
2664 inputLayer2->GetOutputSlot(0).Connect(stackLayer->GetInputSlot(1));
2665 stackLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2666
2667 inputLayer1->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2668 inputLayer2->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2669 stackLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2670
2671 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2672 CHECK(deserializedNetwork);
2673
2674 LayerVerifierBaseWithDescriptor<armnn::StackDescriptor> verifier(
2675 layerName, {inputTensorInfo, inputTensorInfo}, {outputTensorInfo}, descriptor);
2676 deserializedNetwork->ExecuteStrategy(verifier);
2677 }
2678
2679 TEST_CASE("SerializeStandIn")
2680 {
2681 const std::string layerName("standIn");
2682
2683 armnn::TensorInfo tensorInfo({ 1u }, armnn::DataType::Float32);
2684 armnn::StandInDescriptor descriptor(2u, 2u);
2685
2686 armnn::INetworkPtr network = armnn::INetwork::Create();
2687 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
2688 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
2689 armnn::IConnectableLayer* const standInLayer = network->AddStandInLayer(descriptor, layerName.c_str());
2690 armnn::IConnectableLayer* const outputLayer0 = network->AddOutputLayer(0);
2691 armnn::IConnectableLayer* const outputLayer1 = network->AddOutputLayer(1);
2692
2693 inputLayer0->GetOutputSlot(0).Connect(standInLayer->GetInputSlot(0));
2694 inputLayer0->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2695
2696 inputLayer1->GetOutputSlot(0).Connect(standInLayer->GetInputSlot(1));
2697 inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2698
2699 standInLayer->GetOutputSlot(0).Connect(outputLayer0->GetInputSlot(0));
2700 standInLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
2701
2702 standInLayer->GetOutputSlot(1).Connect(outputLayer1->GetInputSlot(0));
2703 standInLayer->GetOutputSlot(1).SetTensorInfo(tensorInfo);
2704
2705 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2706 CHECK(deserializedNetwork);
2707
2708 LayerVerifierBaseWithDescriptor<armnn::StandInDescriptor> verifier(
2709 layerName, { tensorInfo, tensorInfo }, { tensorInfo, tensorInfo }, descriptor);
2710 deserializedNetwork->ExecuteStrategy(verifier);
2711 }
2712
2713 TEST_CASE("SerializeStridedSlice")
2714 {
2715 const std::string layerName("stridedSlice");
2716 const armnn::TensorInfo inputInfo = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32);
2717 const armnn::TensorInfo outputInfo = armnn::TensorInfo({3, 1}, armnn::DataType::Float32);
2718
2719 armnn::StridedSliceDescriptor desc({0, 0, 1, 0}, {1, 1, 1, 1}, {1, 1, 1, 1});
2720 desc.m_EndMask = (1 << 4) - 1;
2721 desc.m_ShrinkAxisMask = (1 << 1) | (1 << 2);
2722 desc.m_DataLayout = armnn::DataLayout::NCHW;
2723
2724 armnn::INetworkPtr network = armnn::INetwork::Create();
2725 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2726 armnn::IConnectableLayer* const stridedSliceLayer = network->AddStridedSliceLayer(desc, layerName.c_str());
2727 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2728
2729 inputLayer->GetOutputSlot(0).Connect(stridedSliceLayer->GetInputSlot(0));
2730 stridedSliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2731
2732 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2733 stridedSliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2734
2735 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2736 CHECK(deserializedNetwork);
2737
2738 LayerVerifierBaseWithDescriptor<armnn::StridedSliceDescriptor> verifier(
2739 layerName, {inputInfo}, {outputInfo}, desc);
2740 deserializedNetwork->ExecuteStrategy(verifier);
2741 }
2742
2743 TEST_CASE("SerializeSubtraction")
2744 {
2745 const std::string layerName("subtraction");
2746 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32);
2747
2748 armnn::INetworkPtr network = armnn::INetwork::Create();
2749 armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
2750 armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
2751 ARMNN_NO_DEPRECATE_WARN_BEGIN
2752 armnn::IConnectableLayer* const subtractionLayer = network->AddSubtractionLayer(layerName.c_str());
2753 ARMNN_NO_DEPRECATE_WARN_END
2754 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2755
2756 inputLayer0->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(0));
2757 inputLayer1->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(1));
2758 subtractionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2759
2760 inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
2761 inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
2762 subtractionLayer->GetOutputSlot(0).SetTensorInfo(info);
2763
2764 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2765 CHECK(deserializedNetwork);
2766
2767 LayerVerifierBase verifier(layerName, {info, info}, {info});
2768 deserializedNetwork->ExecuteStrategy(verifier);
2769 }
2770
2771 TEST_CASE("SerializeSwitch")
2772 {
2773 class SwitchLayerVerifier : public LayerVerifierBase
2774 {
2775 public:
SwitchLayerVerifier(const std::string & layerName,const std::vector<armnn::TensorInfo> & inputInfos,const std::vector<armnn::TensorInfo> & outputInfos)2776 SwitchLayerVerifier(const std::string& layerName,
2777 const std::vector<armnn::TensorInfo>& inputInfos,
2778 const std::vector<armnn::TensorInfo>& outputInfos)
2779 : LayerVerifierBase(layerName, inputInfos, outputInfos) {}
2780
ExecuteStrategy(const armnn::IConnectableLayer * layer,const armnn::BaseDescriptor & descriptor,const std::vector<armnn::ConstTensor> & constants,const char * name,const armnn::LayerBindingId id=0)2781 void ExecuteStrategy(const armnn::IConnectableLayer* layer,
2782 const armnn::BaseDescriptor& descriptor,
2783 const std::vector<armnn::ConstTensor>& constants,
2784 const char* name,
2785 const armnn::LayerBindingId id = 0) override
2786 {
2787 armnn::IgnoreUnused(descriptor, constants, id);
2788 switch (layer->GetType())
2789 {
2790 case armnn::LayerType::Input: break;
2791 case armnn::LayerType::Output: break;
2792 case armnn::LayerType::Constant: break;
2793 case armnn::LayerType::Switch:
2794 {
2795 VerifyNameAndConnections(layer, name);
2796 break;
2797 }
2798 default:
2799 {
2800 throw armnn::Exception("Unexpected layer type in Switch test model");
2801 }
2802 }
2803 }
2804 };
2805
2806 const std::string layerName("switch");
2807 const armnn::TensorInfo info({ 1, 4 }, armnn::DataType::Float32, 0.0f, 0, true);
2808
2809 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2810 armnn::ConstTensor constTensor(info, constantData);
2811
2812 armnn::INetworkPtr network = armnn::INetwork::Create();
2813 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2814 armnn::IConnectableLayer* const constantLayer = network->AddConstantLayer(constTensor, "constant");
2815 armnn::IConnectableLayer* const switchLayer = network->AddSwitchLayer(layerName.c_str());
2816 armnn::IConnectableLayer* const trueOutputLayer = network->AddOutputLayer(0);
2817 armnn::IConnectableLayer* const falseOutputLayer = network->AddOutputLayer(1);
2818
2819 inputLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(0));
2820 constantLayer->GetOutputSlot(0).Connect(switchLayer->GetInputSlot(1));
2821 switchLayer->GetOutputSlot(0).Connect(trueOutputLayer->GetInputSlot(0));
2822 switchLayer->GetOutputSlot(1).Connect(falseOutputLayer->GetInputSlot(0));
2823
2824 inputLayer->GetOutputSlot(0).SetTensorInfo(info);
2825 constantLayer->GetOutputSlot(0).SetTensorInfo(info);
2826 switchLayer->GetOutputSlot(0).SetTensorInfo(info);
2827 switchLayer->GetOutputSlot(1).SetTensorInfo(info);
2828
2829 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2830 CHECK(deserializedNetwork);
2831
2832 SwitchLayerVerifier verifier(layerName, {info, info}, {info, info});
2833 deserializedNetwork->ExecuteStrategy(verifier);
2834 }
2835
2836 TEST_CASE("SerializeTranspose")
2837 {
2838 const std::string layerName("transpose");
2839 const armnn::TensorInfo inputTensorInfo({4, 3, 2, 1}, armnn::DataType::Float32);
2840 const armnn::TensorInfo outputTensorInfo({1, 2, 3, 4}, armnn::DataType::Float32);
2841
2842 armnn::TransposeDescriptor descriptor(armnn::PermutationVector({3, 2, 1, 0}));
2843
2844 armnn::INetworkPtr network = armnn::INetwork::Create();
2845 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2846 armnn::IConnectableLayer* const transposeLayer = network->AddTransposeLayer(descriptor, layerName.c_str());
2847 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2848
2849 inputLayer->GetOutputSlot(0).Connect(transposeLayer->GetInputSlot(0));
2850 transposeLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2851
2852 inputLayer->GetOutputSlot(0).SetTensorInfo(inputTensorInfo);
2853 transposeLayer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2854
2855 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2856 CHECK(deserializedNetwork);
2857
2858 LayerVerifierBaseWithDescriptor<armnn::TransposeDescriptor> verifier(
2859 layerName, {inputTensorInfo}, {outputTensorInfo}, descriptor);
2860 deserializedNetwork->ExecuteStrategy(verifier);
2861 }
2862
2863 TEST_CASE("SerializeTransposeConvolution2d")
2864 {
2865 const std::string layerName("transposeConvolution2d");
2866 const armnn::TensorInfo inputInfo ({ 1, 7, 7, 1 }, armnn::DataType::Float32);
2867 const armnn::TensorInfo outputInfo({ 1, 9, 9, 1 }, armnn::DataType::Float32);
2868
2869 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32, 0.0f, 0, true);
2870 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32, 0.0f, 0, true);
2871
2872 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
2873 armnn::ConstTensor weights(weightsInfo, weightsData);
2874
2875 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
2876 armnn::ConstTensor biases(biasesInfo, biasesData);
2877
2878 armnn::TransposeConvolution2dDescriptor descriptor;
2879 descriptor.m_PadLeft = 1;
2880 descriptor.m_PadRight = 1;
2881 descriptor.m_PadTop = 1;
2882 descriptor.m_PadBottom = 1;
2883 descriptor.m_StrideX = 1;
2884 descriptor.m_StrideY = 1;
2885 descriptor.m_BiasEnabled = true;
2886 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
2887
2888 armnn::INetworkPtr network = armnn::INetwork::Create();
2889 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
2890 armnn::IConnectableLayer* const convLayer =
2891 network->AddTransposeConvolution2dLayer(descriptor,
2892 weights,
2893 armnn::Optional<armnn::ConstTensor>(biases),
2894 layerName.c_str());
2895 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
2896
2897 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
2898 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
2899
2900 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
2901 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2902
2903 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2904 CHECK(deserializedNetwork);
2905
2906 const std::vector<armnn::ConstTensor> constants {weights, biases};
2907 LayerVerifierBaseWithDescriptorAndConstants<armnn::TransposeConvolution2dDescriptor> verifier(
2908 layerName, {inputInfo}, {outputInfo}, descriptor, constants);
2909 deserializedNetwork->ExecuteStrategy(verifier);
2910 }
2911
2912 TEST_CASE("SerializeDeserializeNonLinearNetwork")
2913 {
2914 class ConstantLayerVerifier : public LayerVerifierBase
2915 {
2916 public:
ConstantLayerVerifier(const std::string & layerName,const std::vector<armnn::TensorInfo> & inputInfos,const std::vector<armnn::TensorInfo> & outputInfos,const armnn::ConstTensor & layerInput)2917 ConstantLayerVerifier(const std::string& layerName,
2918 const std::vector<armnn::TensorInfo>& inputInfos,
2919 const std::vector<armnn::TensorInfo>& outputInfos,
2920 const armnn::ConstTensor& layerInput)
2921 : LayerVerifierBase(layerName, inputInfos, outputInfos)
2922 , m_LayerInput(layerInput) {}
2923
ExecuteStrategy(const armnn::IConnectableLayer * layer,const armnn::BaseDescriptor & descriptor,const std::vector<armnn::ConstTensor> & constants,const char * name,const armnn::LayerBindingId id=0)2924 void ExecuteStrategy(const armnn::IConnectableLayer* layer,
2925 const armnn::BaseDescriptor& descriptor,
2926 const std::vector<armnn::ConstTensor>& constants,
2927 const char* name,
2928 const armnn::LayerBindingId id = 0) override
2929 {
2930 armnn::IgnoreUnused(descriptor, constants, id);
2931 switch (layer->GetType())
2932 {
2933 case armnn::LayerType::Input: break;
2934 case armnn::LayerType::Output: break;
2935 case armnn::LayerType::Addition: break;
2936 case armnn::LayerType::Constant:
2937 {
2938 VerifyNameAndConnections(layer, name);
2939 CompareConstTensor(constants.at(0), m_LayerInput);
2940 break;
2941 }
2942 case armnn::LayerType::ElementwiseBinary: break;
2943 default:
2944 {
2945 throw armnn::Exception("Unexpected layer type in test model");
2946 }
2947 }
2948 }
2949
2950 private:
2951 armnn::ConstTensor m_LayerInput;
2952 };
2953
2954 const std::string layerName("constant");
2955 const armnn::TensorInfo info({ 2, 3 }, armnn::DataType::Float32, 0.0f, 0, true);
2956
2957 std::vector<float> constantData = GenerateRandomData<float>(info.GetNumElements());
2958 armnn::ConstTensor constTensor(info, constantData);
2959
2960 armnn::INetworkPtr network(armnn::INetwork::Create());
2961 armnn::IConnectableLayer* input = network->AddInputLayer(0);
2962 ARMNN_NO_DEPRECATE_WARN_BEGIN
2963 armnn::IConnectableLayer* add = network->AddAdditionLayer();
2964 ARMNN_NO_DEPRECATE_WARN_END
2965 armnn::IConnectableLayer* constant = network->AddConstantLayer(constTensor, layerName.c_str());
2966 armnn::IConnectableLayer* output = network->AddOutputLayer(0);
2967
2968 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
2969 constant->GetOutputSlot(0).Connect(add->GetInputSlot(1));
2970 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
2971
2972 input->GetOutputSlot(0).SetTensorInfo(info);
2973 constant->GetOutputSlot(0).SetTensorInfo(info);
2974 add->GetOutputSlot(0).SetTensorInfo(info);
2975
2976 armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
2977 CHECK(deserializedNetwork);
2978
2979 ConstantLayerVerifier verifier(layerName, {}, {info}, constTensor);
2980 deserializedNetwork->ExecuteStrategy(verifier);
2981 }
2982
2983 }