xref: /aosp_15_r20/external/armnn/src/armnnSerializer/test/SerializerTests.cpp (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
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 }