IVGCVSW-5593 Implement Pimpl Idiom for serialization classes
[platform/upstream/armnn.git] / src / armnnDeserializer / Deserializer.cpp
1 //
2 // Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include "Deserializer.hpp"
7
8 #include <armnn/Descriptors.hpp>
9 #include <armnn/Exceptions.hpp>
10 #include <armnn/TypesUtils.hpp>
11 #include <armnn/LstmParams.hpp>
12 #include <armnn/QuantizedLstmParams.hpp>
13
14 #include <armnnUtils/Permute.hpp>
15 #include <armnnUtils/Transpose.hpp>
16 #include <armnn/utility/Assert.hpp>
17 #include <armnn/utility/IgnoreUnused.hpp>
18 #include <armnn/utility/NumericCast.hpp>
19
20 #include <ParserHelper.hpp>
21 #include <VerificationHelpers.hpp>
22
23 #include <fmt/format.h>
24
25 #include <fstream>
26 #include <algorithm>
27 #include <limits>
28 #include <numeric>
29
30 using armnn::ParseException;
31 using namespace armnn;
32 using namespace armnnSerializer;
33
34 namespace armnnDeserializer
35 {
36
37 IDeserializer::IDeserializer() : pDeserializerImpl(new DeserializerImpl()){}
38
39 IDeserializer::~IDeserializer() = default;
40
41 IDeserializer *IDeserializer::CreateRaw()
42 {
43     return new IDeserializer();
44 }
45
46 IDeserializerPtr IDeserializer::Create()
47 {
48     return IDeserializerPtr(CreateRaw(), &IDeserializer::Destroy);
49 }
50
51 void IDeserializer::Destroy(IDeserializer *parser)
52 {
53     delete parser;
54 }
55
56 armnn::INetworkPtr IDeserializer::CreateNetworkFromBinary(const std::vector<uint8_t> &binaryContent)
57 {
58     return pDeserializerImpl->CreateNetworkFromBinary(binaryContent);
59 }
60
61 armnn::INetworkPtr IDeserializer::CreateNetworkFromBinary(std::istream &binaryContent)
62 {
63     return pDeserializerImpl->CreateNetworkFromBinary(binaryContent);
64 }
65
66 BindingPointInfo IDeserializer::GetNetworkInputBindingInfo(unsigned int layerId, const std::string &name) const
67 {
68     return pDeserializerImpl->GetNetworkInputBindingInfo(layerId, name);
69 }
70
71 BindingPointInfo IDeserializer::GetNetworkOutputBindingInfo(unsigned int layerId, const std::string &name) const
72 {
73     return pDeserializerImpl->GetNetworkOutputBindingInfo(layerId, name);
74 }
75
76 namespace
77 {
78
79 const uint32_t VIRTUAL_LAYER_ID = std::numeric_limits<uint32_t>::max();
80
81  void CheckGraph(const GraphPtr& graph,
82                  unsigned int layersIndex,
83                  const CheckLocation& location)
84 {
85     if (graph->layers() == nullptr)
86     {
87         throw ParseException(fmt::format("{0} was called with invalid (null) graph. "
88                                          "Possible reason is that the graph is not yet loaded and Unpack(ed). "
89                                          "layers:{1} at {2}",
90                                          location.m_Function,
91                                          layersIndex,
92                                          location.FileLine()));
93     }
94     else if (layersIndex >= graph->layers()->size())
95     {
96         throw ParseException(fmt::format("{0} was called with an invalid layers index. layers:{1} at {2}",
97                                          location.m_Function,
98                                          layersIndex,
99                                          location.FileLine()));
100     }
101 }
102
103 void CheckLayers(const GraphPtr& graph,
104                  unsigned int layersIndex,
105                  unsigned int layerIndex,
106                  const CheckLocation& location)
107 {
108     if (graph->layers() == nullptr)
109     {
110         throw ParseException(fmt::format("{0} was called with invalid (null) graph. "
111                                          "Possible reason is that the graph is not yet loaded and Unpack(ed). "
112                                          "layers:{1} at {2}",
113                                          location.m_Function,
114                                          layersIndex,
115                                          location.FileLine()));
116     }
117     else if (layersIndex >= graph->layers()->size())
118     {
119         throw ParseException(fmt::format("{0} was called with an invalid layers index. "
120                                          "layers:{1} at {2}",
121                                          location.m_Function,
122                                          layersIndex,
123                                          location.FileLine()));
124     }
125     else if (layerIndex >= graph->layers()[layersIndex].size()
126             && layerIndex != VIRTUAL_LAYER_ID)
127     {
128         throw ParseException(fmt::format("{0} was called with an invalid layer index. "
129                                          "layers:{1} layer:{2} at {3}",
130                                          location.m_Function,
131                                          layersIndex,
132                                          layerIndex,
133                                          location.FileLine()));
134     }
135 }
136
137 void CheckTensorPtr(TensorRawPtr rawPtr,
138                     const CheckLocation& location)
139 {
140     if (rawPtr == nullptr)
141     {
142         throw ParseException(fmt::format("{0} was called with a null tensor pointer. at {1}",
143                                          location.m_Function,
144                                          location.FileLine()));
145     }
146 }
147
148 void CheckConstTensorPtr(ConstTensorRawPtr rawPtr,
149                          const CheckLocation& location)
150 {
151     if (rawPtr == nullptr)
152     {
153         throw ParseException(fmt::format("{0} was called with a null const tensor pointer. at {1}",
154                                          location.m_Function,
155                                          location.FileLine()));
156     }
157 }
158
159 void CheckConstTensorSize(const unsigned int constTensorSize,
160                           const unsigned int tensorSize,
161                           const CheckLocation& location)
162 {
163     if (constTensorSize != tensorSize)
164     {
165         throw ParseException(fmt::format("{0} wrong number of components supplied to tensor. at:{1}",
166                                          location.m_Function,
167                                          location.FileLine()));
168     }
169 }
170
171 #define CHECK_TENSOR_PTR(TENSOR_PTR) \
172     CheckTensorPtr(TENSOR_PTR, CHECK_LOCATION())
173
174 #define CHECK_CONST_TENSOR_SIZE(CONST_TENSOR_SIZE, TENSOR_SIZE) \
175     CheckConstTensorSize(CONST_TENSOR_SIZE, TENSOR_SIZE, CHECK_LOCATION())
176
177 #define CHECK_CONST_TENSOR_PTR(TENSOR_PTR) \
178     CheckConstTensorPtr(TENSOR_PTR, CHECK_LOCATION())
179
180 #define CHECK_LAYERS(GRAPH, LAYERS_INDEX, LAYER_INDEX) \
181     CheckLayers(GRAPH, LAYERS_INDEX, LAYER_INDEX, CHECK_LOCATION())
182
183 #define CHECK_GRAPH(GRAPH, LAYERS_INDEX) \
184     CheckGraph(GRAPH, LAYERS_INDEX, CHECK_LOCATION())
185 }
186
187 bool CheckShape(const armnn::TensorShape& actual, const std::vector<uint32_t>& expected)
188 {
189     const unsigned int actualSize = actual.GetNumDimensions();
190     if (actualSize != expected.size())
191     {
192         return false;
193     }
194
195     for (unsigned int i = 0u; i < actualSize; i++)
196     {
197         if (actual[i] != static_cast<unsigned int>(expected[i]))
198         {
199             return false;
200         }
201     }
202
203     return true;
204 }
205
206 IDeserializer::DeserializerImpl::DeserializerImpl()
207 : m_Network(nullptr, nullptr),
208 //May require LayerType_Max to be included
209 m_ParserFunctions(Layer_MAX+1, &IDeserializer::DeserializerImpl::ParseUnsupportedLayer)
210 {
211     // register supported layers
212     m_ParserFunctions[Layer_AbsLayer]                    = &DeserializerImpl::ParseAbs;
213     m_ParserFunctions[Layer_ActivationLayer]             = &DeserializerImpl::ParseActivation;
214     m_ParserFunctions[Layer_AdditionLayer]               = &DeserializerImpl::ParseAdd;
215     m_ParserFunctions[Layer_ArgMinMaxLayer]              = &DeserializerImpl::ParseArgMinMax;
216     m_ParserFunctions[Layer_BatchToSpaceNdLayer]         = &DeserializerImpl::ParseBatchToSpaceNd;
217     m_ParserFunctions[Layer_BatchNormalizationLayer]     = &DeserializerImpl::ParseBatchNormalization;
218     m_ParserFunctions[Layer_ComparisonLayer]             = &DeserializerImpl::ParseComparison;
219     m_ParserFunctions[Layer_ConcatLayer]                 = &DeserializerImpl::ParseConcat;
220     m_ParserFunctions[Layer_ConstantLayer]               = &DeserializerImpl::ParseConstant;
221     m_ParserFunctions[Layer_Convolution2dLayer]          = &DeserializerImpl::ParseConvolution2d;
222     m_ParserFunctions[Layer_DepthToSpaceLayer]           = &DeserializerImpl::ParseDepthToSpace;
223     m_ParserFunctions[Layer_DepthwiseConvolution2dLayer] = &DeserializerImpl::ParseDepthwiseConvolution2d;
224     m_ParserFunctions[Layer_DequantizeLayer]             = &DeserializerImpl::ParseDequantize;
225     m_ParserFunctions[Layer_DetectionPostProcessLayer]   = &DeserializerImpl::ParseDetectionPostProcess;
226     m_ParserFunctions[Layer_DivisionLayer]               = &DeserializerImpl::ParseDivision;
227     m_ParserFunctions[Layer_ElementwiseUnaryLayer]       = &DeserializerImpl::ParseElementwiseUnary;
228     m_ParserFunctions[Layer_EqualLayer]                  = &DeserializerImpl::ParseEqual;
229     m_ParserFunctions[Layer_FullyConnectedLayer]         = &DeserializerImpl::ParseFullyConnected;
230     m_ParserFunctions[Layer_FillLayer]                   = &DeserializerImpl::ParseFill;
231     m_ParserFunctions[Layer_FloorLayer]                  = &DeserializerImpl::ParseFloor;
232     m_ParserFunctions[Layer_GatherLayer]                 = &DeserializerImpl::ParseGather;
233     m_ParserFunctions[Layer_GreaterLayer]                = &DeserializerImpl::ParseGreater;
234     m_ParserFunctions[Layer_InstanceNormalizationLayer]  = &DeserializerImpl::ParseInstanceNormalization;
235     m_ParserFunctions[Layer_L2NormalizationLayer]        = &DeserializerImpl::ParseL2Normalization;
236     m_ParserFunctions[Layer_LogicalBinaryLayer]          = &DeserializerImpl::ParseLogicalBinary;
237     m_ParserFunctions[Layer_LogSoftmaxLayer]             = &DeserializerImpl::ParseLogSoftmax;
238     m_ParserFunctions[Layer_LstmLayer]                   = &DeserializerImpl::ParseLstm;
239     m_ParserFunctions[Layer_MaximumLayer]                = &DeserializerImpl::ParseMaximum;
240     m_ParserFunctions[Layer_MeanLayer]                   = &DeserializerImpl::ParseMean;
241     m_ParserFunctions[Layer_MinimumLayer]                = &DeserializerImpl::ParseMinimum;
242     m_ParserFunctions[Layer_MergeLayer]                  = &DeserializerImpl::ParseMerge;
243     m_ParserFunctions[Layer_MergerLayer]                 = &DeserializerImpl::ParseConcat;
244     m_ParserFunctions[Layer_MultiplicationLayer]         = &DeserializerImpl::ParseMultiplication;
245     m_ParserFunctions[Layer_NormalizationLayer]          = &DeserializerImpl::ParseNormalization;
246     m_ParserFunctions[Layer_PadLayer]                    = &DeserializerImpl::ParsePad;
247     m_ParserFunctions[Layer_PermuteLayer]                = &DeserializerImpl::ParsePermute;
248     m_ParserFunctions[Layer_Pooling2dLayer]              = &DeserializerImpl::ParsePooling2d;
249     m_ParserFunctions[Layer_PreluLayer]                  = &DeserializerImpl::ParsePrelu;
250     m_ParserFunctions[Layer_QLstmLayer]                  = &DeserializerImpl::ParseQLstm;
251     m_ParserFunctions[Layer_QuantizeLayer]               = &DeserializerImpl::ParseQuantize;
252     m_ParserFunctions[Layer_QuantizedLstmLayer]          = &DeserializerImpl::ParseQuantizedLstm;
253     m_ParserFunctions[Layer_RankLayer]                   = &DeserializerImpl::ParseRank;
254     m_ParserFunctions[Layer_ReshapeLayer]                = &DeserializerImpl::ParseReshape;
255     m_ParserFunctions[Layer_ResizeBilinearLayer]         = &DeserializerImpl::ParseResizeBilinear;
256     m_ParserFunctions[Layer_ResizeLayer]                 = &DeserializerImpl::ParseResize;
257     m_ParserFunctions[Layer_RsqrtLayer]                  = &DeserializerImpl::ParseRsqrt;
258     m_ParserFunctions[Layer_SliceLayer]                  = &DeserializerImpl::ParseSlice;
259     m_ParserFunctions[Layer_SoftmaxLayer]                = &DeserializerImpl::ParseSoftmax;
260     m_ParserFunctions[Layer_SpaceToBatchNdLayer]         = &DeserializerImpl::ParseSpaceToBatchNd;
261     m_ParserFunctions[Layer_SpaceToDepthLayer]           = &DeserializerImpl::ParseSpaceToDepth;
262     m_ParserFunctions[Layer_SplitterLayer]               = &DeserializerImpl::ParseSplitter;
263     m_ParserFunctions[Layer_StackLayer]                  = &DeserializerImpl::ParseStack;
264     m_ParserFunctions[Layer_StandInLayer]                = &DeserializerImpl::ParseStandIn;
265     m_ParserFunctions[Layer_StridedSliceLayer]           = &DeserializerImpl::ParseStridedSlice;
266     m_ParserFunctions[Layer_SubtractionLayer]            = &DeserializerImpl::ParseSubtraction;
267     m_ParserFunctions[Layer_SwitchLayer]                 = &DeserializerImpl::ParseSwitch;
268     m_ParserFunctions[Layer_TransposeConvolution2dLayer] = &DeserializerImpl::ParseTransposeConvolution2d;
269     m_ParserFunctions[Layer_TransposeLayer]              = &DeserializerImpl::ParseTranspose;
270 }
271
272 LayerBaseRawPtr IDeserializer::DeserializerImpl::GetBaseLayer(const GraphPtr& graphPtr, unsigned int layerIndex)
273 {
274     auto layerType = graphPtr->layers()->Get(layerIndex)->layer_type();
275
276     switch(layerType)
277     {
278         case Layer::Layer_AbsLayer:
279             return graphPtr->layers()->Get(layerIndex)->layer_as_AbsLayer()->base();
280         case Layer::Layer_ActivationLayer:
281             return graphPtr->layers()->Get(layerIndex)->layer_as_ActivationLayer()->base();
282         case Layer::Layer_AdditionLayer:
283             return graphPtr->layers()->Get(layerIndex)->layer_as_AdditionLayer()->base();
284         case Layer::Layer_ArgMinMaxLayer:
285             return graphPtr->layers()->Get(layerIndex)->layer_as_ArgMinMaxLayer()->base();
286         case Layer::Layer_BatchToSpaceNdLayer:
287             return graphPtr->layers()->Get(layerIndex)->layer_as_BatchToSpaceNdLayer()->base();
288         case Layer::Layer_BatchNormalizationLayer:
289             return graphPtr->layers()->Get(layerIndex)->layer_as_BatchNormalizationLayer()->base();
290         case Layer::Layer_ComparisonLayer:
291             return graphPtr->layers()->Get(layerIndex)->layer_as_ComparisonLayer()->base();
292         case Layer::Layer_ConcatLayer:
293             return graphPtr->layers()->Get(layerIndex)->layer_as_ConcatLayer()->base();
294         case Layer::Layer_ConstantLayer:
295             return graphPtr->layers()->Get(layerIndex)->layer_as_ConstantLayer()->base();
296         case Layer::Layer_Convolution2dLayer:
297             return graphPtr->layers()->Get(layerIndex)->layer_as_Convolution2dLayer()->base();
298         case Layer::Layer_DepthToSpaceLayer:
299             return graphPtr->layers()->Get(layerIndex)->layer_as_DepthToSpaceLayer()->base();
300         case Layer::Layer_DepthwiseConvolution2dLayer:
301             return graphPtr->layers()->Get(layerIndex)->layer_as_DepthwiseConvolution2dLayer()->base();
302         case Layer::Layer_DequantizeLayer:
303             return graphPtr->layers()->Get(layerIndex)->layer_as_DequantizeLayer()->base();
304         case Layer::Layer_DetectionPostProcessLayer:
305             return graphPtr->layers()->Get(layerIndex)->layer_as_DetectionPostProcessLayer()->base();
306         case Layer::Layer_DivisionLayer:
307             return graphPtr->layers()->Get(layerIndex)->layer_as_DivisionLayer()->base();
308         case Layer::Layer_EqualLayer:
309             return graphPtr->layers()->Get(layerIndex)->layer_as_EqualLayer()->base();
310         case Layer::Layer_ElementwiseUnaryLayer:
311             return graphPtr->layers()->Get(layerIndex)->layer_as_ElementwiseUnaryLayer()->base();
312         case Layer::Layer_FullyConnectedLayer:
313             return graphPtr->layers()->Get(layerIndex)->layer_as_FullyConnectedLayer()->base();
314         case Layer::Layer_FillLayer:
315             return graphPtr->layers()->Get(layerIndex)->layer_as_FillLayer()->base();
316         case Layer::Layer_FloorLayer:
317             return graphPtr->layers()->Get(layerIndex)->layer_as_FloorLayer()->base();
318         case Layer::Layer_GatherLayer:
319             return graphPtr->layers()->Get(layerIndex)->layer_as_GatherLayer()->base();
320         case Layer::Layer_GreaterLayer:
321             return graphPtr->layers()->Get(layerIndex)->layer_as_GreaterLayer()->base();
322         case Layer::Layer_InputLayer:
323             return graphPtr->layers()->Get(layerIndex)->layer_as_InputLayer()->base()->base();
324         case Layer::Layer_InstanceNormalizationLayer:
325             return graphPtr->layers()->Get(layerIndex)->layer_as_InstanceNormalizationLayer()->base();
326         case Layer::Layer_L2NormalizationLayer:
327             return graphPtr->layers()->Get(layerIndex)->layer_as_L2NormalizationLayer()->base();
328         case Layer::Layer_LogicalBinaryLayer:
329             return graphPtr->layers()->Get(layerIndex)->layer_as_LogicalBinaryLayer()->base();
330         case Layer::Layer_LogSoftmaxLayer:
331             return graphPtr->layers()->Get(layerIndex)->layer_as_LogSoftmaxLayer()->base();
332         case Layer::Layer_LstmLayer:
333             return graphPtr->layers()->Get(layerIndex)->layer_as_LstmLayer()->base();
334         case Layer::Layer_MeanLayer:
335             return graphPtr->layers()->Get(layerIndex)->layer_as_MeanLayer()->base();
336         case Layer::Layer_MinimumLayer:
337             return graphPtr->layers()->Get(layerIndex)->layer_as_MinimumLayer()->base();
338         case Layer::Layer_MaximumLayer:
339             return graphPtr->layers()->Get(layerIndex)->layer_as_MaximumLayer()->base();
340         case Layer::Layer_MergeLayer:
341             return graphPtr->layers()->Get(layerIndex)->layer_as_MergeLayer()->base();
342         case Layer::Layer_MergerLayer:
343             return graphPtr->layers()->Get(layerIndex)->layer_as_MergerLayer()->base();
344         case Layer::Layer_MultiplicationLayer:
345             return graphPtr->layers()->Get(layerIndex)->layer_as_MultiplicationLayer()->base();
346         case Layer::Layer_NormalizationLayer:
347             return graphPtr->layers()->Get(layerIndex)->layer_as_NormalizationLayer()->base();
348         case Layer::Layer_OutputLayer:
349             return graphPtr->layers()->Get(layerIndex)->layer_as_OutputLayer()->base()->base();
350         case Layer::Layer_PadLayer:
351             return graphPtr->layers()->Get(layerIndex)->layer_as_PadLayer()->base();
352         case Layer::Layer_PermuteLayer:
353             return graphPtr->layers()->Get(layerIndex)->layer_as_PermuteLayer()->base();
354         case Layer::Layer_Pooling2dLayer:
355             return graphPtr->layers()->Get(layerIndex)->layer_as_Pooling2dLayer()->base();
356         case Layer::Layer_PreluLayer:
357             return graphPtr->layers()->Get(layerIndex)->layer_as_PreluLayer()->base();
358         case Layer::Layer_QLstmLayer:
359             return graphPtr->layers()->Get(layerIndex)->layer_as_QLstmLayer()->base();
360         case Layer::Layer_QuantizeLayer:
361             return graphPtr->layers()->Get(layerIndex)->layer_as_QuantizeLayer()->base();
362         case Layer::Layer_QuantizedLstmLayer:
363             return graphPtr->layers()->Get(layerIndex)->layer_as_QuantizedLstmLayer()->base();
364         case Layer::Layer_RankLayer:
365             return graphPtr->layers()->Get(layerIndex)->layer_as_RankLayer()->base();
366         case Layer::Layer_ReshapeLayer:
367             return graphPtr->layers()->Get(layerIndex)->layer_as_ReshapeLayer()->base();
368         case Layer::Layer_ResizeBilinearLayer:
369             return graphPtr->layers()->Get(layerIndex)->layer_as_ResizeBilinearLayer()->base();
370         case Layer::Layer_ResizeLayer:
371             return graphPtr->layers()->Get(layerIndex)->layer_as_ResizeLayer()->base();
372         case Layer::Layer_RsqrtLayer:
373             return graphPtr->layers()->Get(layerIndex)->layer_as_RsqrtLayer()->base();
374         case Layer::Layer_SliceLayer:
375             return graphPtr->layers()->Get(layerIndex)->layer_as_SliceLayer()->base();
376         case Layer::Layer_SoftmaxLayer:
377             return graphPtr->layers()->Get(layerIndex)->layer_as_SoftmaxLayer()->base();
378         case Layer::Layer_SpaceToBatchNdLayer:
379             return graphPtr->layers()->Get(layerIndex)->layer_as_SpaceToBatchNdLayer()->base();
380         case Layer::Layer_SpaceToDepthLayer:
381             return graphPtr->layers()->Get(layerIndex)->layer_as_SpaceToDepthLayer()->base();
382         case Layer::Layer_SplitterLayer:
383             return graphPtr->layers()->Get(layerIndex)->layer_as_SplitterLayer()->base();
384         case Layer::Layer_StackLayer:
385             return graphPtr->layers()->Get(layerIndex)->layer_as_StackLayer()->base();
386         case Layer::Layer_StandInLayer:
387             return graphPtr->layers()->Get(layerIndex)->layer_as_StandInLayer()->base();
388         case Layer::Layer_StridedSliceLayer:
389             return graphPtr->layers()->Get(layerIndex)->layer_as_StridedSliceLayer()->base();
390         case Layer::Layer_SubtractionLayer:
391             return graphPtr->layers()->Get(layerIndex)->layer_as_SubtractionLayer()->base();
392         case Layer::Layer_SwitchLayer:
393             return graphPtr->layers()->Get(layerIndex)->layer_as_SwitchLayer()->base();
394         case Layer::Layer_TransposeConvolution2dLayer:
395             return graphPtr->layers()->Get(layerIndex)->layer_as_TransposeConvolution2dLayer()->base();
396         case Layer::Layer_TransposeLayer:
397             return graphPtr->layers()->Get(layerIndex)->layer_as_TransposeLayer()->base();
398         case Layer::Layer_NONE:
399         default:
400             throw ParseException(fmt::format("Layer type {} not recognized", layerType));
401     }
402 }
403
404 std::string IDeserializer::DeserializerImpl::GetLayerName(const GraphPtr& graph, unsigned int index)
405 {
406     auto layer = GetBaseLayer(graph, index);
407     assert(layer);
408     return layer->layerName()->str();
409 }
410
411 int32_t IDeserializer::DeserializerImpl::GetBindingLayerInfo(const GraphPtr& graphPtr, unsigned int layerIndex)
412 {
413     auto layerType = graphPtr->layers()->Get(layerIndex)->layer_type();
414
415     if (layerType == Layer::Layer_InputLayer)
416     {
417         return graphPtr->layers()->Get(layerIndex)->layer_as_InputLayer()->base()->layerBindingId();
418     }
419     else if ( layerType == Layer::Layer_OutputLayer )
420     {
421         return graphPtr->layers()->Get(layerIndex)->layer_as_OutputLayer()->base()->layerBindingId();
422     }
423     return 0;
424 }
425
426 armnn::DataLayout ToDataLayout(armnnSerializer::DataLayout dataLayout)
427 {
428     switch (dataLayout)
429     {
430         case armnnSerializer::DataLayout::DataLayout_NHWC:
431             return armnn::DataLayout::NHWC;
432         case armnnSerializer::DataLayout::DataLayout_NCHW:
433         default:
434             return armnn::DataLayout::NCHW;
435     }
436 }
437
438 armnn::ActivationFunction ToActivationFunction(armnnSerializer::ActivationFunction function)
439 {
440     switch (function)
441     {
442         case armnnSerializer::ActivationFunction_Sigmoid:
443             return armnn::ActivationFunction::Sigmoid;
444         case armnnSerializer::ActivationFunction_TanH:
445             return armnn::ActivationFunction::TanH;
446         case armnnSerializer::ActivationFunction_Linear:
447             return armnn::ActivationFunction::Linear;
448         case armnnSerializer::ActivationFunction_ReLu:
449             return armnn::ActivationFunction::ReLu;
450         case armnnSerializer::ActivationFunction_BoundedReLu:
451             return armnn::ActivationFunction::BoundedReLu;
452         case armnnSerializer::ActivationFunction_LeakyReLu:
453             return armnn::ActivationFunction::LeakyReLu;
454         case armnnSerializer::ActivationFunction_Abs:
455             return armnn::ActivationFunction::Abs;
456         case armnnSerializer::ActivationFunction_Sqrt:
457             return armnn::ActivationFunction::Sqrt;
458         case armnnSerializer::ActivationFunction_Square:
459             return armnn::ActivationFunction::Square;
460         case armnnSerializer::ActivationFunction_Elu:
461             return armnn::ActivationFunction::Elu;
462         case armnnSerializer::ActivationFunction_HardSwish:
463             return armnn::ActivationFunction::HardSwish;
464         default:
465             return armnn::ActivationFunction::Sigmoid;
466     }
467 }
468
469 armnn::ArgMinMaxFunction ToArgMinMaxFunction(armnnSerializer::ArgMinMaxFunction function)
470 {
471     switch (function)
472     {
473         case armnnSerializer::ArgMinMaxFunction::ArgMinMaxFunction_Max:
474             return armnn::ArgMinMaxFunction::Max;
475         case armnnSerializer::ArgMinMaxFunction::ArgMinMaxFunction_Min:
476         default:
477             return armnn::ArgMinMaxFunction::Min;
478     }
479 }
480
481 armnn::ComparisonOperation ToComparisonOperation(armnnSerializer::ComparisonOperation operation)
482 {
483     switch (operation)
484     {
485         case armnnSerializer::ComparisonOperation::ComparisonOperation_Equal:
486             return armnn::ComparisonOperation::Equal;
487         case armnnSerializer::ComparisonOperation::ComparisonOperation_Greater:
488             return armnn::ComparisonOperation::Greater;
489         case armnnSerializer::ComparisonOperation::ComparisonOperation_GreaterOrEqual:
490             return armnn::ComparisonOperation::GreaterOrEqual;
491         case armnnSerializer::ComparisonOperation::ComparisonOperation_Less:
492             return armnn::ComparisonOperation::Less;
493         case armnnSerializer::ComparisonOperation::ComparisonOperation_LessOrEqual:
494             return armnn::ComparisonOperation::LessOrEqual;
495         case armnnSerializer::ComparisonOperation::ComparisonOperation_NotEqual:
496         default:
497             return armnn::ComparisonOperation::NotEqual;
498     }
499 }
500
501 armnn::LogicalBinaryOperation ToLogicalBinaryOperation(armnnSerializer::LogicalBinaryOperation operation)
502 {
503     switch (operation)
504     {
505         case armnnSerializer::LogicalBinaryOperation::LogicalBinaryOperation_LogicalAnd:
506             return armnn::LogicalBinaryOperation::LogicalAnd;
507         case armnnSerializer::LogicalBinaryOperation::LogicalBinaryOperation_LogicalOr:
508             return armnn::LogicalBinaryOperation::LogicalOr;
509         default:
510             throw armnn::InvalidArgumentException("Logical Binary operation unknown");
511     }
512 }
513
514 armnn::UnaryOperation ToUnaryOperation(armnnSerializer::UnaryOperation operation)
515 {
516     switch (operation)
517     {
518         case armnnSerializer::UnaryOperation::UnaryOperation_Abs:
519             return armnn::UnaryOperation::Abs;
520         case armnnSerializer::UnaryOperation::UnaryOperation_Rsqrt:
521             return armnn::UnaryOperation::Rsqrt;
522         case armnnSerializer::UnaryOperation::UnaryOperation_Sqrt:
523             return armnn::UnaryOperation::Sqrt;
524         case armnnSerializer::UnaryOperation::UnaryOperation_Exp:
525             return armnn::UnaryOperation::Exp;
526         case armnnSerializer::UnaryOperation::UnaryOperation_Neg:
527             return armnn::UnaryOperation::Neg;
528         case armnnSerializer::UnaryOperation::UnaryOperation_LogicalNot:
529             return armnn::UnaryOperation::LogicalNot;
530         default:
531             throw armnn::InvalidArgumentException("Unary operation unknown");
532     }
533 }
534
535 armnn::ResizeMethod ToResizeMethod(armnnSerializer::ResizeMethod method)
536 {
537     switch (method)
538     {
539         case armnnSerializer::ResizeMethod_NearestNeighbor:
540             return armnn::ResizeMethod::NearestNeighbor;
541         case armnnSerializer::ResizeMethod_Bilinear:
542             return armnn::ResizeMethod::Bilinear;
543         default:
544             return armnn::ResizeMethod::NearestNeighbor;
545     }
546 }
547
548 armnn::TensorInfo ToTensorInfo(TensorRawPtr tensorPtr)
549 {
550     armnn::DataType type;
551     CHECK_TENSOR_PTR(tensorPtr);
552
553     switch (tensorPtr->dataType())
554     {
555         case DataType_QAsymmS8:
556             type = armnn::DataType::QAsymmS8;
557             break;
558         case DataType_QSymmS8:
559             type = armnn::DataType::QSymmS8;
560             break;
561         case DataType_QuantisedAsymm8:
562         case DataType_QAsymmU8:
563             type = armnn::DataType::QAsymmU8;
564             break;
565         case DataType_QSymmS16:
566         case DataType_QuantisedSymm16:
567             type = armnn::DataType::QSymmS16;
568             break;
569         case DataType_Signed32:
570             type = armnn::DataType::Signed32;
571             break;
572         case DataType_Float32:
573             type = armnn::DataType::Float32;
574             break;
575         case DataType_Float16:
576             type = armnn::DataType::Float16;
577             break;
578         case DataType_Boolean:
579             type = armnn::DataType::Boolean;
580             break;
581         default:
582         {
583             CheckLocation location = CHECK_LOCATION();
584             throw ParseException(fmt::format("Unsupported data type {0} = {1}. {2}",
585                                              tensorPtr->dataType(),
586                                              EnumNameDataType(tensorPtr->dataType()),
587                                              location.AsString()));
588         }
589     }
590
591     if (tensorPtr->dimensionality() == static_cast<unsigned int>(Dimensionality::Scalar))
592     {
593         float quantizationScale = tensorPtr->quantizationScale();
594         int32_t quantizationOffset = tensorPtr->quantizationOffset();
595
596         return armnn::TensorInfo(armnn::TensorShape{armnn::Dimensionality::Scalar},
597                                  type,
598                                  quantizationScale,
599                                  quantizationOffset);
600     }
601
602     auto dimensions = tensorPtr->dimensions();
603     unsigned int size = dimensions->size();
604     std::vector<unsigned int> outputDims(dimensions->begin(), dimensions->begin() + size);
605
606     auto quantizationScales = tensorPtr->quantizationScales();
607
608     if (quantizationScales)
609     {
610         unsigned int quantizationScalesSize = quantizationScales->size();
611         std::vector<float> scales(quantizationScales->begin(), quantizationScales->begin() + quantizationScalesSize);
612         unsigned int quantizationDim = tensorPtr->quantizationDim();
613         armnn::TensorInfo result(size,
614                                  outputDims.data(),
615                                  type,
616                                  scales,
617                                  quantizationDim);
618         return result;
619     }
620
621     float quantizationScale = tensorPtr->quantizationScale();
622     int32_t quantizationOffset = tensorPtr->quantizationOffset();
623
624     // two statements (on purpose) for easier debugging:
625     armnn::TensorInfo result(size,
626                              outputDims.data(),
627                              type,
628                              quantizationScale,
629                              quantizationOffset);
630     return result;
631 }
632
633 armnn::ConstTensor ToConstTensor(ConstTensorRawPtr constTensorPtr)
634 {
635     CHECK_CONST_TENSOR_PTR(constTensorPtr);
636     armnn::TensorInfo tensorInfo = ToTensorInfo(constTensorPtr->info());
637
638     switch (constTensorPtr->data_type())
639     {
640         case ConstTensorData_ByteData:
641         {
642             auto byteData = constTensorPtr->data_as_ByteData()->data();
643             CHECK_CONST_TENSOR_SIZE(byteData->size(), tensorInfo.GetNumElements());
644             return armnn::ConstTensor(tensorInfo, byteData->data());
645         }
646         case ConstTensorData_ShortData:
647         {
648             auto shortData = constTensorPtr->data_as_ShortData()->data();
649             CHECK_CONST_TENSOR_SIZE(shortData->size(), tensorInfo.GetNumElements());
650             return armnn::ConstTensor(tensorInfo, shortData->data());
651         }
652         case ConstTensorData_IntData:
653         {
654             auto intData = constTensorPtr->data_as_IntData()->data();
655             CHECK_CONST_TENSOR_SIZE(intData->size(), tensorInfo.GetNumElements());
656             return armnn::ConstTensor(tensorInfo, intData->data());
657         }
658         case ConstTensorData_LongData:
659         {
660             auto longData = constTensorPtr->data_as_LongData()->data();
661             CHECK_CONST_TENSOR_SIZE(longData->size(), tensorInfo.GetNumElements());
662             return armnn::ConstTensor(tensorInfo, longData->data());
663         }
664         default:
665         {
666             CheckLocation location = CHECK_LOCATION();
667             throw ParseException(fmt::format("Unsupported data type {0} = {1}. {2}",
668                                              constTensorPtr->data_type(),
669                                              EnumNameConstTensorData(constTensorPtr->data_type()),
670                                              location.AsString()));
671         }
672     }
673 }
674
675 TensorRawPtrVector IDeserializer::DeserializerImpl::GetInputs(const GraphPtr& graphPtr, unsigned int layerIndex)
676 {
677     CHECK_LAYERS(graphPtr, 0, layerIndex);
678     auto layer = GetBaseLayer(graphPtr, layerIndex);
679     const auto& numInputs = layer->inputSlots()->size();
680
681     TensorRawPtrVector result(numInputs);
682
683    for (unsigned int i=0; i<numInputs; ++i)
684    {
685        auto inputId = CHECKED_NON_NEGATIVE(static_cast<int32_t>
686                                           (layer->inputSlots()->Get(i)->connection()->sourceLayerIndex()));
687        result[i] = GetBaseLayer(graphPtr, inputId)->outputSlots()->Get(0)->tensorInfo();
688    }
689    return result;
690 }
691
692 TensorRawPtrVector IDeserializer::DeserializerImpl::GetOutputs(const GraphPtr& graphPtr, unsigned int layerIndex)
693 {
694     CHECK_LAYERS(graphPtr, 0, layerIndex);
695     auto layer = GetBaseLayer(graphPtr, layerIndex);
696     const auto& numOutputs = layer->outputSlots()->size();
697
698     TensorRawPtrVector result(numOutputs);
699
700     for (unsigned int i=0; i<numOutputs; ++i)
701     {
702         result[i] = layer->outputSlots()->Get(i)->tensorInfo();
703     }
704     return result;
705 }
706
707 void IDeserializer::DeserializerImpl::ParseUnsupportedLayer(GraphPtr graph, unsigned int layerIndex)
708 {
709     CHECK_LAYERS(graph, 0, layerIndex);
710     const auto layerName = GetBaseLayer(graph, layerIndex)->layerName()->c_str();
711     throw ParseException(fmt::format("Layer not supported. layerIndex: {0} "
712                                      "layerName: {1} / {2}",
713                                      layerIndex,
714                                      layerName,
715                                      CHECK_LOCATION().AsString()));
716 }
717
718 void IDeserializer::DeserializerImpl::ResetParser()
719 {
720     m_Network = armnn::INetworkPtr(nullptr, nullptr);
721     m_InputBindings.clear();
722     m_OutputBindings.clear();
723 }
724
725
726 INetworkPtr IDeserializer::DeserializerImpl::CreateNetworkFromBinary(const std::vector<uint8_t>& binaryContent)
727 {
728      ResetParser();
729      GraphPtr graph = LoadGraphFromBinary(binaryContent.data(), binaryContent.size());
730      return CreateNetworkFromGraph(graph);
731 }
732
733 armnn::INetworkPtr IDeserializer::DeserializerImpl::CreateNetworkFromBinary(std::istream& binaryContent)
734 {
735     ResetParser();
736     std::vector<uint8_t> content((std::istreambuf_iterator<char>(binaryContent)), std::istreambuf_iterator<char>());
737     GraphPtr graph = LoadGraphFromBinary(content.data(), content.size());
738     return CreateNetworkFromGraph(graph);
739 }
740
741 GraphPtr IDeserializer::DeserializerImpl::LoadGraphFromBinary(const uint8_t* binaryContent, size_t len)
742 {
743     if (binaryContent == nullptr)
744     {
745         throw InvalidArgumentException(fmt::format("Invalid (null) binary content {}",
746                                                    CHECK_LOCATION().AsString()));
747     }
748     flatbuffers::Verifier verifier(binaryContent, len);
749     if (verifier.VerifyBuffer<SerializedGraph>() == false)
750     {
751         throw ParseException(fmt::format("Buffer doesn't conform to the expected Armnn "
752                                          "flatbuffers format. size:{0} {1}",
753                                          len,
754                                          CHECK_LOCATION().AsString()));
755     }
756     return GetSerializedGraph(binaryContent);
757 }
758
759 INetworkPtr IDeserializer::DeserializerImpl::CreateNetworkFromGraph(GraphPtr graph)
760 {
761     m_Network = INetwork::Create();
762     ARMNN_ASSERT(graph != nullptr);
763     unsigned int layerIndex = 0;
764     for (AnyLayer const* layer : *graph->layers())
765     {
766         if (layer->layer_type() != Layer_InputLayer &&
767             layer->layer_type() != Layer_OutputLayer)
768         {
769             // lookup and call the parser function
770             auto& parserFunction = m_ParserFunctions[layer->layer_type()];
771             (this->*parserFunction)(graph, layerIndex);
772         }
773         ++layerIndex;
774     }
775
776     SetupInputLayers(graph);
777     SetupOutputLayers(graph);
778
779     // establish the connections from the layer outputs to the inputs of the subsequent layers
780     for (auto&& graphIt : m_GraphConnections)
781     {
782         Connections& connections = graphIt.second;
783         for (auto&& outputIt : connections.outputSlots)
784         {
785             const unsigned int outputSlotIndex = outputIt.first;
786             IOutputSlot* outputSlot = outputIt.second;
787             if (connections.inputSlots.find(outputSlotIndex) != connections.inputSlots.end())
788             {
789                 for (IInputSlot* inputSlot : connections.inputSlots[outputSlotIndex])
790                 {
791                     outputSlot->Connect(*inputSlot);
792                 }
793             }
794         }
795     }
796
797     return std::move(m_Network);
798 }
799
800 BindingPointInfo IDeserializer::DeserializerImpl::GetNetworkInputBindingInfo(unsigned int layerIndex,
801                                                           const std::string& name) const
802 {
803     IgnoreUnused(layerIndex);
804     for (auto inputBinding : m_InputBindings)
805     {
806         if (inputBinding.first == name)
807         {
808             return inputBinding.second;
809         }
810     }
811     throw ParseException(fmt::format("No input binding found for layer:{0} / {1}",
812                                      name,
813                                      CHECK_LOCATION().AsString()));
814 }
815
816 BindingPointInfo IDeserializer::DeserializerImpl::GetNetworkOutputBindingInfo(unsigned int layerIndex,
817                                                                 const std::string& name) const
818 {
819     IgnoreUnused(layerIndex);
820     for (auto outputBinding : m_OutputBindings)
821     {
822         if (outputBinding.first == name)
823         {
824             return outputBinding.second;
825         }
826     }
827     throw ParseException(fmt::format("No output binding found for layer:{0} / {1}",
828                                      name,
829                                      CHECK_LOCATION().AsString()));
830 }
831
832 unsigned int IDeserializer::DeserializerImpl::GetInputLayerInVector(GraphPtr graph, int targetId)
833 {
834     for (unsigned int i = 0; i < graph->layers()->size(); i++)
835     {
836         auto layer = graph->layers()->Get(i);
837         if (layer->layer_type() == Layer::Layer_InputLayer)
838         {
839             auto layerBindingId = layer->layer_as_InputLayer()->base()->layerBindingId();
840             if (layerBindingId == targetId)
841             {
842                 return i;
843             }
844         }
845     }
846     throw ParseException("Input layer with given layerBindingId not found");
847 }
848
849 unsigned int IDeserializer::DeserializerImpl::GetOutputLayerInVector(GraphPtr graph, int targetId)
850 {
851     for (unsigned int i = 0; i < graph->layers()->size(); i++)
852     {
853         auto layer = graph->layers()->Get(i);
854         if (layer->layer_type() == Layer::Layer_OutputLayer)
855         {
856             auto layerBindingId = layer->layer_as_OutputLayer()->base()->layerBindingId();
857             if (layerBindingId == targetId)
858             {
859                 return i;
860             }
861         }
862     }
863     throw ParseException("Output layer with given layerBindingId not found");
864 }
865
866 unsigned int IDeserializer::DeserializerImpl::GetLayerIndexInVector(GraphPtr graph, unsigned int targetIndex)
867 {
868     for (unsigned int i = 0; i < graph->layers()->size(); i++)
869     {
870         LayerBaseRawPtr layer = GetBaseLayer(graph, i);
871         if (layer->index() == targetIndex)
872         {
873             return i;
874         }
875     }
876     throw ParseException("Layer with given index not found");
877 }
878
879 IDeserializer::DeserializerImpl::FeatureVersions IDeserializer::DeserializerImpl::GetFeatureVersions(GraphPtr graph)
880 {
881     IDeserializer::DeserializerImpl::FeatureVersions versions;
882
883     if (graph->featureVersions())
884     {
885         versions.m_BindingIdScheme = graph->featureVersions()->bindingIdsScheme();
886     }
887
888     return versions;
889 }
890
891 void IDeserializer::DeserializerImpl::SetupInputLayers(GraphPtr graph)
892 {
893     CHECK_GRAPH(graph, 0);
894     const unsigned int numInputs = graph->inputIds()->size();
895     m_InputBindings.clear();
896     m_InputBindings.reserve(numInputs);
897
898     for (unsigned int i = 0; i < numInputs; i++)
899     {
900         unsigned int inputLayerIndex = 0xFFFFFFFF;
901         if (GetFeatureVersions(graph).m_BindingIdScheme == 0)
902         {
903             const unsigned int inputId = armnn::numeric_cast<unsigned int>(graph->inputIds()->Get(i));
904             inputLayerIndex = GetLayerIndexInVector(graph, inputId);
905         }
906         else
907         {
908             const int inputId = graph->inputIds()->Get(i);
909             inputLayerIndex = GetInputLayerInVector(graph, inputId);
910         }
911
912         LayerBaseRawPtr baseLayer = GetBaseLayer(graph, inputLayerIndex);
913
914         // GetBindingLayerInfo expect the index to be index in the vector not index property on each layer base
915         LayerBindingId bindingId = GetBindingLayerInfo(graph, inputLayerIndex);
916         ARMNN_ASSERT_MSG(baseLayer->layerName()->c_str(), "Input has no name.");
917
918         IConnectableLayer* inputLayer =
919             m_Network->AddInputLayer(bindingId, baseLayer->layerName()->c_str());
920
921         const armnn::TensorInfo& tensorInfo = ToTensorInfo(baseLayer->outputSlots()->Get(0)->tensorInfo());
922         inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
923         RegisterOutputSlots(graph, inputLayerIndex, inputLayer);
924
925         BindingPointInfo bindingInfo = {bindingId, tensorInfo};
926         m_InputBindings.push_back(std::make_pair(baseLayer->layerName()->c_str(), bindingInfo));
927     }
928 }
929
930 void IDeserializer::DeserializerImpl::SetupOutputLayers(GraphPtr graph)
931 {
932     CHECK_GRAPH(graph, 0);
933     const unsigned int numOutputs = graph->outputIds()->size();
934     m_OutputBindings.clear();
935     m_OutputBindings.reserve(numOutputs);
936
937     for (unsigned int i = 0; i < numOutputs; i++)
938     {
939         unsigned int outputLayerIndex = 0xFFFFFFFF;
940         if (GetFeatureVersions(graph).m_BindingIdScheme == 0)
941         {
942             const unsigned int outputId = armnn::numeric_cast<unsigned int>(graph->outputIds()->Get(i));
943             outputLayerIndex = GetLayerIndexInVector(graph, outputId);
944         }
945         else
946         {
947             const int outputId = graph->outputIds()->Get(i);
948             outputLayerIndex = GetOutputLayerInVector(graph, outputId);
949         }
950
951         LayerBaseRawPtr baseLayer = GetBaseLayer(graph, outputLayerIndex);
952
953         // GetBindingLayerInfo expect the index to be index in the vector not index property on each layer base
954         LayerBindingId bindingId = GetBindingLayerInfo(graph, outputLayerIndex);
955         ARMNN_ASSERT_MSG(baseLayer->layerName()->c_str(), "Output has no name.");
956
957         IConnectableLayer* outputLayer =
958             m_Network->AddOutputLayer(bindingId, baseLayer->layerName()->c_str());
959
960         RegisterInputSlots(graph, outputLayerIndex, outputLayer);
961
962         unsigned int sourceLayerIndex =
963             GetLayerIndexInVector(graph, baseLayer->inputSlots()->Get(0)->connection()->sourceLayerIndex());
964         LayerBaseRawPtr sourceBaseLayer = GetBaseLayer(graph, sourceLayerIndex);
965         const armnn::TensorInfo& tensorInfo = ToTensorInfo(sourceBaseLayer->outputSlots()->Get(i)->tensorInfo());
966
967         BindingPointInfo bindingInfo = {bindingId, tensorInfo};
968         m_OutputBindings.push_back(std::make_pair(baseLayer->layerName()->c_str(), bindingInfo));
969     }
970 }
971
972 void IDeserializer::DeserializerImpl::RegisterOutputSlots(GraphPtr graph,
973                                        uint32_t layerIndex,
974                                        IConnectableLayer* layer)
975 {
976     CHECK_LAYERS(graph, 0, layerIndex);
977     ARMNN_ASSERT(layer != nullptr);
978     LayerBaseRawPtr baseLayer = GetBaseLayer(graph, layerIndex);
979     if (baseLayer->outputSlots()->size() != layer->GetNumOutputSlots())
980     {
981         throw ParseException(fmt::format("The number of outputslots ({0}) does not match the number expected ({1})"
982                                          " for layer index: {2} {3}",
983                                          baseLayer->outputSlots()->size(),
984                                          layer->GetNumOutputSlots(),
985                                          layerIndex,
986                                          CHECK_LOCATION().AsString()));
987     }
988
989     for (unsigned int i = 0; i < layer->GetNumOutputSlots(); ++i)
990     {
991         const unsigned int slotIndex = baseLayer->outputSlots()->Get(i)->index();
992         armnn::IOutputSlot* outputSlot = &(layer->GetOutputSlot(slotIndex));
993         // layerIndex is not necessarily the same as baseLayer->index(). The latter is needed here
994         RegisterOutputSlotOfConnection(baseLayer->index(), slotIndex, outputSlot);
995     }
996 }
997
998 void IDeserializer::DeserializerImpl::RegisterInputSlots(GraphPtr graph,
999                                       uint32_t layerIndex,
1000                                       armnn::IConnectableLayer* layer)
1001 {
1002     CHECK_LAYERS(graph, 0, layerIndex);
1003     ARMNN_ASSERT(layer != nullptr);
1004     LayerBaseRawPtr baseLayer = GetBaseLayer(graph, layerIndex);
1005     if (baseLayer->inputSlots()->size() != layer->GetNumInputSlots())
1006     {
1007         throw ParseException(fmt::format("The number of inputslots ({0}) does not match the number expected ({1})"
1008                                          " for layer index:{2} {3}",
1009                                          baseLayer->inputSlots()->size(),
1010                                          layer->GetNumInputSlots(),
1011                                          layerIndex,
1012                                          CHECK_LOCATION().AsString()));
1013     }
1014
1015     for (unsigned int i = 0; i < layer->GetNumInputSlots(); ++i)
1016     {
1017         auto fbInputSlot = baseLayer->inputSlots()->Get(i);
1018         auto fbConnection = fbInputSlot->connection();
1019         armnn::IInputSlot* inputSlot = &(layer->GetInputSlot(fbInputSlot->index()));
1020         RegisterInputSlotOfConnection(fbConnection->sourceLayerIndex(), fbConnection->outputSlotIndex(), inputSlot);
1021     }
1022 }
1023
1024 void IDeserializer::DeserializerImpl::RegisterInputSlotOfConnection(uint32_t sourceLayerIndex,
1025                                                  uint32_t outputSlotIndex,
1026                                                  armnn::IInputSlot* inputSlot)
1027 {
1028     if (m_GraphConnections.find(sourceLayerIndex) == m_GraphConnections.end())
1029     {
1030         m_GraphConnections[sourceLayerIndex] = Connections();
1031     }
1032
1033     Connections& connections = m_GraphConnections[sourceLayerIndex];
1034     if (connections.inputSlots.find(outputSlotIndex) == connections.inputSlots.end())
1035     {
1036         connections.inputSlots[outputSlotIndex] = {inputSlot};
1037     }
1038     else
1039     {
1040         connections.inputSlots[outputSlotIndex].push_back(inputSlot);
1041     }
1042 }
1043
1044 void IDeserializer::DeserializerImpl::RegisterOutputSlotOfConnection(uint32_t sourceLayerIndex,
1045                                                   uint32_t outputSlotIndex,
1046                                                   armnn::IOutputSlot* outputSlot)
1047 {
1048     if (m_GraphConnections.find(sourceLayerIndex) == m_GraphConnections.end())
1049     {
1050         m_GraphConnections[sourceLayerIndex] = Connections();
1051     }
1052
1053     Connections& connections = m_GraphConnections[sourceLayerIndex];
1054     if (connections.outputSlots.find(outputSlotIndex) != connections.outputSlots.end())
1055     {
1056         throw ParseException("Same output slot index processed twice");
1057     }
1058
1059     connections.outputSlots[outputSlotIndex] = outputSlot;
1060 }
1061
1062 void IDeserializer::DeserializerImpl::ParseAbs(GraphPtr graph, unsigned int layerIndex)
1063 {
1064     CHECK_LAYERS(graph, 0, layerIndex);
1065     auto inputs = GetInputs(graph, layerIndex);
1066     CHECK_LOCATION();
1067     CHECK_VALID_SIZE(inputs.size(), 1);
1068
1069     auto outputs = GetOutputs(graph, layerIndex);
1070     CHECK_VALID_SIZE(outputs.size(), 1);
1071
1072     auto layerName = GetLayerName(graph, layerIndex);
1073
1074     armnn::ElementwiseUnaryDescriptor descriptor(armnn::UnaryOperation::Abs);
1075     IConnectableLayer* layer = m_Network->AddElementwiseUnaryLayer(descriptor, layerName.c_str());
1076     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1077     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1078
1079     RegisterInputSlots(graph, layerIndex, layer);
1080     RegisterOutputSlots(graph, layerIndex, layer);
1081 }
1082
1083 void IDeserializer::DeserializerImpl::ParseActivation(GraphPtr graph, unsigned int layerIndex)
1084 {
1085     CHECK_LAYERS(graph, 0, layerIndex);
1086     auto inputs = GetInputs(graph, layerIndex);
1087     CHECK_LOCATION();
1088     CHECK_VALID_SIZE(inputs.size(), 1);
1089
1090     auto outputs = GetOutputs(graph, layerIndex);
1091     CHECK_VALID_SIZE(outputs.size(), 1);
1092
1093     auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_ActivationLayer();
1094     auto layerName = GetLayerName(graph, layerIndex);
1095     auto serializerDescriptor = serializerLayer->descriptor();
1096
1097     armnn::ActivationDescriptor descriptor;
1098     descriptor.m_Function = ToActivationFunction(serializerDescriptor->activationFunction());
1099     descriptor.m_A = serializerDescriptor->a();
1100     descriptor.m_B = serializerDescriptor->b();
1101
1102     IConnectableLayer* layer = m_Network->AddActivationLayer(descriptor,
1103                                                              layerName.c_str());
1104     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1105     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1106
1107     RegisterInputSlots(graph, layerIndex, layer);
1108     RegisterOutputSlots(graph, layerIndex, layer);
1109 }
1110
1111 void IDeserializer::DeserializerImpl::ParseAdd(GraphPtr graph, unsigned int layerIndex)
1112 {
1113     CHECK_LAYERS(graph, 0, layerIndex);
1114     auto inputs = GetInputs(graph, layerIndex);
1115     CHECK_LOCATION();
1116     CHECK_VALID_SIZE(inputs.size(), 2);
1117
1118     auto outputs = GetOutputs(graph, layerIndex);
1119     CHECK_VALID_SIZE(outputs.size(), 1);
1120
1121     auto layerName = GetLayerName(graph, layerIndex);
1122     IConnectableLayer* layer = m_Network->AddAdditionLayer(layerName.c_str());
1123
1124     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1125     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1126
1127     RegisterInputSlots(graph, layerIndex, layer);
1128     RegisterOutputSlots(graph, layerIndex, layer);
1129 }
1130
1131 void IDeserializer::DeserializerImpl::ParseArgMinMax(GraphPtr graph, unsigned int layerIndex)
1132 {
1133     CHECK_LAYERS(graph, 0, layerIndex);
1134     auto inputs = GetInputs(graph, layerIndex);
1135     CHECK_LOCATION();
1136     CHECK_VALID_SIZE(inputs.size(), 1);
1137
1138     auto outputs = GetOutputs(graph, layerIndex);
1139     CHECK_VALID_SIZE(outputs.size(), 1);
1140
1141     auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_ArgMinMaxLayer();
1142     auto serializerDescriptor = serializerLayer->descriptor();
1143
1144     armnn::ArgMinMaxDescriptor descriptor;
1145     descriptor.m_Function = ToArgMinMaxFunction(serializerDescriptor->argMinMaxFunction());
1146     descriptor.m_Axis = serializerDescriptor->axis();
1147     auto layerName = GetLayerName(graph, layerIndex);
1148     IConnectableLayer* layer = m_Network->AddArgMinMaxLayer(descriptor, layerName.c_str());
1149
1150     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1151     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1152
1153     RegisterInputSlots(graph, layerIndex, layer);
1154     RegisterOutputSlots(graph, layerIndex, layer);
1155 }
1156
1157 void IDeserializer::DeserializerImpl::ParseBatchToSpaceNd(GraphPtr graph, unsigned int layerIndex)
1158 {
1159     CHECK_LAYERS(graph, 0, layerIndex);
1160
1161     TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
1162     CHECK_VALID_SIZE(inputs.size(), 1);
1163
1164     TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
1165     CHECK_VALID_SIZE(outputs.size(), 1);
1166
1167     auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_BatchToSpaceNdLayer()->descriptor();
1168     auto flatBufferCrops = flatBufferDescriptor->crops();
1169     auto flatBufferBlockShape = flatBufferDescriptor->blockShape();
1170
1171     if (flatBufferCrops->Length() % 2 != 0)
1172     {
1173         throw ParseException(fmt::format("The size of crops must be divisible by 2 {}", CHECK_LOCATION().AsString()));
1174     }
1175
1176     std::vector<std::pair<unsigned int, unsigned int>> crops;
1177     crops.reserve(flatBufferCrops->Length() / 2);
1178     for (unsigned int i = 0; i < flatBufferCrops->Length() - 1; i += 2)
1179     {
1180         crops.emplace_back(flatBufferCrops->Get(i), flatBufferCrops->Get(i+1));
1181     }
1182
1183     armnn::BatchToSpaceNdDescriptor descriptor;
1184     descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
1185     descriptor.m_BlockShape =
1186         std::vector<unsigned int>(flatBufferBlockShape->begin(), flatBufferBlockShape->end());
1187     descriptor.m_Crops = crops;
1188
1189     auto layerName = GetLayerName(graph, layerIndex);
1190     IConnectableLayer* layer = m_Network->AddBatchToSpaceNdLayer(descriptor, layerName.c_str());
1191
1192     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1193     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1194
1195     RegisterInputSlots(graph, layerIndex, layer);
1196     RegisterOutputSlots(graph, layerIndex, layer);
1197 }
1198
1199 void IDeserializer::DeserializerImpl::ParseBatchNormalization(GraphPtr graph, unsigned int layerIndex)
1200 {
1201     CHECK_LAYERS(graph, 0, layerIndex);
1202
1203     auto inputs = GetInputs(graph, layerIndex);
1204     CHECK_VALID_SIZE(inputs.size(), 1);
1205
1206     auto outputs = GetOutputs(graph, layerIndex);
1207     CHECK_VALID_SIZE(outputs.size(), 1);
1208     auto outputInfo = ToTensorInfo(outputs[0]);
1209
1210     auto layerName = GetLayerName(graph, layerIndex);
1211
1212     auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_BatchNormalizationLayer();
1213     auto serializerDescriptor = serializerLayer->descriptor();
1214
1215     armnn::BatchNormalizationDescriptor descriptor;
1216     descriptor.m_Eps = serializerDescriptor->eps();
1217     descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
1218
1219     armnn::ConstTensor mean     = ToConstTensor(serializerLayer->mean());
1220     armnn::ConstTensor variance = ToConstTensor(serializerLayer->variance());
1221     armnn::ConstTensor beta     = ToConstTensor(serializerLayer->beta());
1222     armnn::ConstTensor gamma    = ToConstTensor(serializerLayer->gamma());
1223
1224     IConnectableLayer* layer = m_Network->AddBatchNormalizationLayer(descriptor,
1225                                                                      mean,
1226                                                                      variance,
1227                                                                      beta,
1228                                                                      gamma,
1229                                                                      layerName.c_str());
1230     layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1231
1232     RegisterInputSlots(graph, layerIndex, layer);
1233     RegisterOutputSlots(graph, layerIndex, layer);
1234 }
1235
1236 void IDeserializer::DeserializerImpl::ParseConstant(GraphPtr graph, unsigned int layerIndex)
1237 {
1238     CHECK_LAYERS(graph, 0, layerIndex);
1239     CHECK_LOCATION();
1240
1241     auto outputs = GetOutputs(graph, layerIndex);
1242     CHECK_VALID_SIZE(outputs.size(), 1);
1243
1244     auto layerName = GetLayerName(graph, layerIndex);
1245
1246     auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_ConstantLayer();
1247     auto serializerInput = serializerLayer->input();
1248
1249     armnn::ConstTensor input = ToConstTensor(serializerInput);
1250
1251     IConnectableLayer* layer = m_Network->AddConstantLayer(input, layerName.c_str());
1252
1253     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1254     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1255
1256     RegisterOutputSlots(graph, layerIndex, layer);
1257 }
1258
1259 void IDeserializer::DeserializerImpl::ParseConvolution2d(GraphPtr graph, unsigned int layerIndex)
1260 {
1261     CHECK_LAYERS(graph, 0, layerIndex);
1262     auto inputs = GetInputs(graph, layerIndex);
1263     CHECK_LOCATION();
1264     CHECK_VALID_SIZE(inputs.size(), 1);
1265
1266     auto outputs = GetOutputs(graph, layerIndex);
1267     CHECK_VALID_SIZE(outputs.size(), 1);
1268
1269     auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_Convolution2dLayer();
1270     auto layerName = GetLayerName(graph, layerIndex);
1271     auto serializerDescriptor = serializerLayer->descriptor();
1272
1273     armnn::Convolution2dDescriptor descriptor;
1274     descriptor.m_PadLeft = serializerDescriptor->padLeft();
1275     descriptor.m_PadRight = serializerDescriptor->padRight();
1276     descriptor.m_PadTop = serializerDescriptor->padTop();
1277     descriptor.m_PadBottom = serializerDescriptor->padBottom();
1278     descriptor.m_StrideX = serializerDescriptor->strideX();
1279     descriptor.m_StrideY = serializerDescriptor->strideY();;
1280     descriptor.m_DilationX = serializerDescriptor->dilationX();
1281     descriptor.m_DilationY = serializerDescriptor->dilationY();;
1282     descriptor.m_BiasEnabled = serializerDescriptor->biasEnabled();;
1283     descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
1284
1285     armnn::ConstTensor weights = ToConstTensor(serializerLayer->weights());
1286     armnn::ConstTensor biases;
1287
1288     armnn::Optional<armnn::ConstTensor> optionalBiases = armnn::EmptyOptional();
1289     if (descriptor.m_BiasEnabled)
1290     {
1291         biases = ToConstTensor(serializerLayer->biases());
1292         optionalBiases = armnn::Optional<armnn::ConstTensor>(biases);
1293     }
1294     IConnectableLayer* layer = m_Network->AddConvolution2dLayer(descriptor,
1295                                                                 weights,
1296                                                                 optionalBiases,
1297                                                                 layerName.c_str());
1298     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1299     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1300
1301     RegisterInputSlots(graph, layerIndex, layer);
1302     RegisterOutputSlots(graph, layerIndex, layer);
1303 }
1304
1305 void IDeserializer::DeserializerImpl::ParseDepthToSpace(GraphPtr graph, unsigned int layerIndex)
1306 {
1307     CHECK_LAYERS(graph, 0, layerIndex);
1308
1309     auto inputs = GetInputs(graph, layerIndex);
1310     CHECK_VALID_SIZE(inputs.size(), 1);
1311
1312     auto outputs = GetOutputs(graph, layerIndex);
1313     CHECK_VALID_SIZE(outputs.size(), 1);
1314
1315     auto fbDescriptor = graph->layers()->Get(layerIndex)->layer_as_DepthToSpaceLayer()->descriptor();
1316
1317     armnn::DepthToSpaceDescriptor descriptor;
1318     descriptor.m_BlockSize  = fbDescriptor->blockSize();
1319     descriptor.m_DataLayout = ToDataLayout(fbDescriptor->dataLayout());
1320
1321     auto layerName = GetLayerName(graph, layerIndex);
1322     IConnectableLayer* layer = m_Network->AddDepthToSpaceLayer(descriptor, layerName.c_str());
1323
1324     armnn::TensorInfo outputInfo = ToTensorInfo(outputs[0]);
1325     layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1326
1327     RegisterInputSlots(graph, layerIndex, layer);
1328     RegisterOutputSlots(graph, layerIndex, layer);
1329 }
1330
1331 void IDeserializer::DeserializerImpl::ParseDepthwiseConvolution2d(GraphPtr graph, unsigned int layerIndex)
1332 {
1333     CHECK_LAYERS(graph, 0, layerIndex);
1334     auto inputs = GetInputs(graph, layerIndex);
1335     CHECK_LOCATION();
1336     CHECK_VALID_SIZE(inputs.size(), 1);
1337
1338     auto outputs = GetOutputs(graph, layerIndex);
1339     CHECK_VALID_SIZE(outputs.size(), 1);
1340
1341     auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_DepthwiseConvolution2dLayer();
1342     auto layerName = GetLayerName(graph, layerIndex);
1343     auto serializerDescriptor = serializerLayer->descriptor();
1344
1345     armnn::DepthwiseConvolution2dDescriptor descriptor;
1346     descriptor.m_PadLeft     = serializerDescriptor->padLeft();
1347     descriptor.m_PadRight    = serializerDescriptor->padRight();
1348     descriptor.m_PadTop      = serializerDescriptor->padTop();
1349     descriptor.m_PadBottom   = serializerDescriptor->padBottom();
1350     descriptor.m_StrideX     = serializerDescriptor->strideX();
1351     descriptor.m_StrideY     = serializerDescriptor->strideY();
1352     descriptor.m_DilationX   = serializerDescriptor->dilationX();
1353     descriptor.m_DilationY   = serializerDescriptor->dilationY();
1354     descriptor.m_BiasEnabled = serializerDescriptor->biasEnabled();;
1355     descriptor.m_DataLayout  = ToDataLayout(serializerDescriptor->dataLayout());
1356
1357     armnn::ConstTensor weights = ToConstTensor(serializerLayer->weights());
1358     armnn::ConstTensor biases;
1359
1360     armnn::Optional<armnn::ConstTensor> optionalBiases = armnn::EmptyOptional();
1361     if (descriptor.m_BiasEnabled)
1362     {
1363         biases = ToConstTensor(serializerLayer->biases());
1364         optionalBiases = armnn::Optional<armnn::ConstTensor>(biases);
1365     }
1366     IConnectableLayer* layer = m_Network->AddDepthwiseConvolution2dLayer(descriptor,
1367                                                                          weights,
1368                                                                          optionalBiases,
1369                                                                          layerName.c_str());
1370
1371     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1372     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1373
1374     RegisterInputSlots(graph, layerIndex, layer);
1375     RegisterOutputSlots(graph, layerIndex, layer);
1376 }
1377
1378 void IDeserializer::DeserializerImpl::ParseDetectionPostProcess(GraphPtr graph, unsigned int layerIndex)
1379 {
1380     CHECK_LAYERS(graph, 0, layerIndex);
1381     auto inputs = GetInputs(graph, layerIndex);
1382     CHECK_LOCATION();
1383     CHECK_VALID_SIZE(inputs.size(), 2);
1384
1385     auto outputs = GetOutputs(graph, layerIndex);
1386     CHECK_VALID_SIZE(outputs.size(), 4);
1387
1388     auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_DetectionPostProcessLayer();
1389     auto layerName = GetLayerName(graph, layerIndex);
1390     auto flatBufferDescriptor = flatBufferLayer->descriptor();
1391
1392     armnn::DetectionPostProcessDescriptor descriptor;
1393     descriptor.m_MaxDetections = flatBufferDescriptor->maxDetections();
1394     descriptor.m_MaxClassesPerDetection = flatBufferDescriptor->maxClassesPerDetection();
1395     descriptor.m_DetectionsPerClass = flatBufferDescriptor->detectionsPerClass();
1396     descriptor.m_NmsScoreThreshold = flatBufferDescriptor->nmsScoreThreshold();
1397     descriptor.m_NmsIouThreshold = flatBufferDescriptor->nmsIouThreshold();
1398     descriptor.m_NumClasses = flatBufferDescriptor->numClasses();
1399     descriptor.m_UseRegularNms = flatBufferDescriptor->useRegularNms();
1400     descriptor.m_ScaleX = flatBufferDescriptor->scaleX();
1401     descriptor.m_ScaleY = flatBufferDescriptor->scaleY();
1402     descriptor.m_ScaleW = flatBufferDescriptor->scaleW();
1403     descriptor.m_ScaleH = flatBufferDescriptor->scaleH();
1404
1405     armnn::ConstTensor anchors = ToConstTensor(flatBufferLayer->anchors());
1406
1407     IConnectableLayer* layer = m_Network->AddDetectionPostProcessLayer(descriptor,
1408                                                                        anchors,
1409                                                                        layerName.c_str());
1410
1411     for (unsigned int i = 0; i < 4; i++)
1412     {
1413         layer->GetOutputSlot(i).SetTensorInfo(ToTensorInfo(outputs[i]));
1414     }
1415
1416     RegisterInputSlots(graph, layerIndex, layer);
1417     RegisterOutputSlots(graph, layerIndex, layer);
1418 }
1419
1420 void IDeserializer::DeserializerImpl::ParseDivision(GraphPtr graph, unsigned int layerIndex)
1421 {
1422     CHECK_LAYERS(graph, 0, layerIndex);
1423     auto inputs = GetInputs(graph, layerIndex);
1424     CHECK_LOCATION();
1425     CHECK_VALID_SIZE(inputs.size(), 2);
1426
1427     auto outputs = GetOutputs(graph, layerIndex);
1428     CHECK_VALID_SIZE(outputs.size(), 1);
1429
1430     auto layerName = GetLayerName(graph, layerIndex);
1431     IConnectableLayer* layer = m_Network->AddDivisionLayer(layerName.c_str());
1432
1433     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1434     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1435
1436     RegisterInputSlots(graph, layerIndex, layer);
1437     RegisterOutputSlots(graph, layerIndex, layer);
1438 }
1439
1440 void IDeserializer::DeserializerImpl::ParseEqual(GraphPtr graph, unsigned int layerIndex)
1441 {
1442     CHECK_LAYERS(graph, 0, layerIndex);
1443     auto inputs = GetInputs(graph, layerIndex);
1444     CHECK_LOCATION();
1445     CHECK_VALID_SIZE(inputs.size(), 2);
1446
1447     auto outputs = GetOutputs(graph, layerIndex);
1448     CHECK_VALID_SIZE(outputs.size(), 1);
1449
1450     auto layerName = GetLayerName(graph, layerIndex);
1451     armnn::ComparisonDescriptor descriptor(armnn::ComparisonOperation::Equal);
1452     IConnectableLayer* layer = m_Network->AddComparisonLayer(descriptor, layerName.c_str());
1453
1454     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1455     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1456
1457     RegisterInputSlots(graph, layerIndex, layer);
1458     RegisterOutputSlots(graph, layerIndex, layer);
1459 }
1460
1461 void IDeserializer::DeserializerImpl::ParseFill(GraphPtr graph, unsigned int layerIndex)
1462 {
1463     CHECK_LAYERS(graph, 0, layerIndex);
1464     auto inputs = GetInputs(graph, layerIndex);
1465     CHECK_LOCATION();
1466     CHECK_VALID_SIZE(inputs.size(), 1);
1467
1468     auto outputs = GetOutputs(graph, layerIndex);
1469     CHECK_VALID_SIZE(outputs.size(), 1);
1470
1471     auto layerName = GetLayerName(graph, layerIndex);
1472     armnn::FillDescriptor descriptor(1.0f);
1473     IConnectableLayer* layer = m_Network->AddFillLayer(descriptor, layerName.c_str());
1474
1475     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1476     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1477
1478     RegisterInputSlots(graph, layerIndex, layer);
1479     RegisterOutputSlots(graph, layerIndex, layer);
1480 }
1481
1482 void IDeserializer::DeserializerImpl::ParseGreater(GraphPtr graph, unsigned int layerIndex)
1483 {
1484     CHECK_LAYERS(graph, 0, layerIndex);
1485     auto inputs = GetInputs(graph, layerIndex);
1486     CHECK_LOCATION();
1487     CHECK_VALID_SIZE(inputs.size(), 2);
1488
1489     auto outputs = GetOutputs(graph, layerIndex);
1490     CHECK_VALID_SIZE(outputs.size(), 1);
1491
1492     auto layerName = GetLayerName(graph, layerIndex);
1493     armnn::ComparisonDescriptor descriptor(armnn::ComparisonOperation::Greater);
1494     IConnectableLayer* layer = m_Network->AddComparisonLayer(descriptor, layerName.c_str());
1495
1496     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1497     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1498
1499     RegisterInputSlots(graph, layerIndex, layer);
1500     RegisterOutputSlots(graph, layerIndex, layer);
1501 }
1502
1503 void IDeserializer::DeserializerImpl::ParseInstanceNormalization(GraphPtr graph, unsigned int layerIndex)
1504 {
1505     CHECK_LAYERS(graph, 0, layerIndex);
1506
1507     auto inputs = GetInputs(graph, layerIndex);
1508     CHECK_VALID_SIZE(inputs.size(), 1);
1509
1510     auto outputs = GetOutputs(graph, layerIndex);
1511     CHECK_VALID_SIZE(outputs.size(), 1);
1512
1513     auto fbLayer      = graph->layers()->Get(layerIndex)->layer_as_InstanceNormalizationLayer();
1514     auto fbDescriptor = fbLayer->descriptor();
1515
1516     armnn::InstanceNormalizationDescriptor descriptor;
1517     descriptor.m_Gamma      = fbDescriptor->gamma();
1518     descriptor.m_Beta       = fbDescriptor->beta();
1519     descriptor.m_Eps        = fbDescriptor->eps();
1520     descriptor.m_DataLayout = ToDataLayout(fbDescriptor->dataLayout());
1521
1522     const std::string layerName        = GetLayerName(graph, layerIndex);
1523     const armnn::TensorInfo outputInfo = ToTensorInfo(outputs[0]);
1524
1525     IConnectableLayer* layer = m_Network->AddInstanceNormalizationLayer(descriptor, layerName.c_str());
1526     layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1527
1528     RegisterInputSlots(graph, layerIndex, layer);
1529     RegisterOutputSlots(graph, layerIndex, layer);
1530 }
1531
1532 void IDeserializer::DeserializerImpl::ParseL2Normalization(GraphPtr graph, unsigned int layerIndex)
1533 {
1534     CHECK_LAYERS(graph, 0, layerIndex);
1535
1536     auto inputs = GetInputs(graph, layerIndex);
1537     CHECK_VALID_SIZE(inputs.size(), 1);
1538
1539     auto outputs = GetOutputs(graph, layerIndex);
1540     CHECK_VALID_SIZE(outputs.size(), 1);
1541     auto outputInfo = ToTensorInfo(outputs[0]);
1542
1543     auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_L2NormalizationLayer();
1544     auto flatBufferDescriptor = flatBufferLayer->descriptor();
1545
1546     auto layerName = GetLayerName(graph, layerIndex);
1547     armnn::L2NormalizationDescriptor descriptor;
1548     descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
1549     descriptor.m_Eps = flatBufferDescriptor->eps();
1550
1551     IConnectableLayer* layer = m_Network->AddL2NormalizationLayer(descriptor, layerName.c_str());
1552     layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1553
1554     RegisterInputSlots(graph, layerIndex, layer);
1555     RegisterOutputSlots(graph, layerIndex, layer);
1556 }
1557
1558 void IDeserializer::DeserializerImpl::ParseLogicalBinary(GraphPtr graph, unsigned int layerIndex)
1559 {
1560     CHECK_LAYERS(graph, 0, layerIndex);
1561     CHECK_LOCATION();
1562
1563     auto inputs = GetInputs(graph, layerIndex);
1564     CHECK_VALID_SIZE(inputs.size(), 2);
1565
1566     auto outputs = GetOutputs(graph, layerIndex);
1567     CHECK_VALID_SIZE(outputs.size(), 1);
1568
1569     auto fbLayer      = graph->layers()->Get(layerIndex)->layer_as_LogicalBinaryLayer();
1570     auto fbDescriptor = fbLayer->descriptor();
1571
1572     armnn::LogicalBinaryDescriptor descriptor;
1573     descriptor.m_Operation = ToLogicalBinaryOperation(fbDescriptor->operation());
1574
1575     const std::string& layerName = GetLayerName(graph, layerIndex);
1576     IConnectableLayer* layer     = m_Network->AddLogicalBinaryLayer(descriptor, layerName.c_str());
1577
1578     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1579     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1580
1581     RegisterInputSlots(graph, layerIndex, layer);
1582     RegisterOutputSlots(graph, layerIndex, layer);
1583 }
1584
1585 void IDeserializer::DeserializerImpl::ParseLogSoftmax(GraphPtr graph, unsigned int layerIndex)
1586 {
1587     CHECK_LAYERS(graph, 0, layerIndex);
1588
1589     TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
1590     CHECK_VALID_SIZE(inputs.size(), 1);
1591
1592     TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
1593     CHECK_VALID_SIZE(outputs.size(), 1);
1594
1595     armnn::LogSoftmaxDescriptor descriptor;
1596     descriptor.m_Beta = graph->layers()->Get(layerIndex)->layer_as_LogSoftmaxLayer()->descriptor()->beta();
1597     descriptor.m_Axis = graph->layers()->Get(layerIndex)->layer_as_LogSoftmaxLayer()->descriptor()->axis();
1598     auto layerName = GetLayerName(graph, layerIndex);
1599
1600     IConnectableLayer* layer = m_Network->AddLogSoftmaxLayer(descriptor, layerName.c_str());
1601
1602     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1603     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1604
1605     RegisterInputSlots(graph, layerIndex, layer);
1606     RegisterOutputSlots(graph, layerIndex, layer);
1607 }
1608
1609 void IDeserializer::DeserializerImpl::ParseMinimum(GraphPtr graph, unsigned int layerIndex)
1610 {
1611     CHECK_LAYERS(graph, 0, layerIndex);
1612     auto inputs = GetInputs(graph, layerIndex);
1613     CHECK_LOCATION();
1614     CHECK_VALID_SIZE(inputs.size(), 2);
1615
1616     auto outputs = GetOutputs(graph, layerIndex);
1617     CHECK_VALID_SIZE(outputs.size(), 1);
1618
1619     auto layerName = GetLayerName(graph, layerIndex);
1620     IConnectableLayer* layer = m_Network->AddMinimumLayer(layerName.c_str());
1621
1622     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1623     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1624
1625     RegisterInputSlots(graph, layerIndex, layer);
1626     RegisterOutputSlots(graph, layerIndex, layer);
1627 }
1628
1629 void IDeserializer::DeserializerImpl::ParseMaximum(GraphPtr graph, unsigned int layerIndex)
1630 {
1631     CHECK_LAYERS(graph, 0, layerIndex);
1632     auto inputs = GetInputs(graph, layerIndex);
1633     CHECK_LOCATION();
1634     CHECK_VALID_SIZE(inputs.size(), 2);
1635
1636     auto outputs = GetOutputs(graph, layerIndex);
1637     CHECK_VALID_SIZE(outputs.size(), 1);
1638
1639     auto layerName = GetLayerName(graph, layerIndex);
1640     IConnectableLayer* layer = m_Network->AddMaximumLayer(layerName.c_str());
1641
1642     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1643     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1644
1645     RegisterInputSlots(graph, layerIndex, layer);
1646     RegisterOutputSlots(graph, layerIndex, layer);
1647 }
1648
1649 const armnnSerializer::OriginsDescriptor* GetOriginsDescriptor(const armnnSerializer::SerializedGraph* graph,
1650                                                                unsigned int layerIndex)
1651 {
1652     auto layerType = graph->layers()->Get(layerIndex)->layer_type();
1653
1654     switch (layerType)
1655     {
1656         case Layer::Layer_ConcatLayer:
1657             return graph->layers()->Get(layerIndex)->layer_as_ConcatLayer()->descriptor();
1658         case Layer::Layer_MergerLayer:
1659             return graph->layers()->Get(layerIndex)->layer_as_MergerLayer()->descriptor();
1660         default:
1661             throw armnn::Exception("unknown layer type, should be concat or merger");
1662     }
1663 }
1664
1665 void IDeserializer::DeserializerImpl::ParseComparison(GraphPtr graph, unsigned int layerIndex)
1666 {
1667     CHECK_LAYERS(graph, 0, layerIndex);
1668     CHECK_LOCATION();
1669
1670     auto inputs = GetInputs(graph, layerIndex);
1671     CHECK_VALID_SIZE(inputs.size(), 2);
1672
1673     auto outputs = GetOutputs(graph, layerIndex);
1674     CHECK_VALID_SIZE(outputs.size(), 1);
1675
1676     auto fbLayer      = graph->layers()->Get(layerIndex)->layer_as_ComparisonLayer();
1677     auto fbDescriptor = fbLayer->descriptor();
1678
1679     armnn::ComparisonDescriptor descriptor;
1680     descriptor.m_Operation = ToComparisonOperation(fbDescriptor->operation());
1681
1682     const std::string& layerName = GetLayerName(graph, layerIndex);
1683     IConnectableLayer* layer     = m_Network->AddComparisonLayer(descriptor, layerName.c_str());
1684
1685     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1686     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1687
1688     RegisterInputSlots(graph, layerIndex, layer);
1689     RegisterOutputSlots(graph, layerIndex, layer);
1690 }
1691
1692 void IDeserializer::DeserializerImpl::ParseElementwiseUnary(GraphPtr graph, unsigned int layerIndex)
1693 {
1694     CHECK_LAYERS(graph, 0, layerIndex);
1695     CHECK_LOCATION();
1696
1697     auto inputs = GetInputs(graph, layerIndex);
1698     CHECK_VALID_SIZE(inputs.size(), 1);
1699
1700     auto outputs = GetOutputs(graph, layerIndex);
1701     CHECK_VALID_SIZE(outputs.size(), 1);
1702
1703     auto fbLayer      = graph->layers()->Get(layerIndex)->layer_as_ElementwiseUnaryLayer();
1704     auto fbDescriptor = fbLayer->descriptor();
1705
1706     armnn::ElementwiseUnaryDescriptor descriptor;
1707     descriptor.m_Operation = ToUnaryOperation(fbDescriptor->operation());
1708
1709     const std::string& layerName = GetLayerName(graph, layerIndex);
1710     IConnectableLayer* layer     = m_Network->AddElementwiseUnaryLayer(descriptor, layerName.c_str());
1711
1712     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1713     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1714
1715     RegisterInputSlots(graph, layerIndex, layer);
1716     RegisterOutputSlots(graph, layerIndex, layer);
1717 }
1718
1719 void IDeserializer::DeserializerImpl::ParseConcat(GraphPtr graph, unsigned int layerIndex)
1720 {
1721     CHECK_LAYERS(graph, 0, layerIndex);
1722     CHECK_LOCATION();
1723
1724     auto outputs = GetOutputs(graph, layerIndex);
1725     CHECK_VALID_SIZE(outputs.size(), 1);
1726
1727     auto layerName = GetLayerName(graph, layerIndex);
1728     auto originsDescriptor = GetOriginsDescriptor(graph, layerIndex);
1729     unsigned int numViews = originsDescriptor->numViews();
1730     unsigned int numDimensions = originsDescriptor->numDimensions();
1731
1732     // can now check the number of inputs == number of views
1733     auto inputs = GetInputs(graph, layerIndex);
1734     CHECK_VALID_SIZE(inputs.size(), numViews);
1735
1736     armnn::OriginsDescriptor descriptor(numViews, numDimensions);
1737     auto originsPtr = originsDescriptor->viewOrigins();
1738     for (unsigned int v = 0; v < numViews; ++v)
1739     {
1740         auto originPtr = originsPtr->Get(v);
1741         for (unsigned int d = 0; d < numDimensions; ++d)
1742         {
1743             uint32_t value = originPtr->data()->Get(d);
1744             descriptor.SetViewOriginCoord(v, d, value);
1745         }
1746     }
1747     descriptor.SetConcatAxis(originsDescriptor->concatAxis());
1748
1749     IConnectableLayer* layer = m_Network->AddConcatLayer(descriptor, layerName.c_str());
1750     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1751     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1752
1753     RegisterInputSlots(graph, layerIndex, layer);
1754     RegisterOutputSlots(graph, layerIndex, layer);
1755 }
1756
1757 void IDeserializer::DeserializerImpl::ParseMultiplication(GraphPtr graph, unsigned int layerIndex)
1758 {
1759     CHECK_LAYERS(graph, 0, layerIndex);
1760     auto inputs = GetInputs(graph, layerIndex);
1761     CHECK_LOCATION();
1762     CHECK_VALID_SIZE(inputs.size(), 2);
1763
1764     auto outputs = GetOutputs(graph, layerIndex);
1765     CHECK_VALID_SIZE(outputs.size(), 1);
1766
1767     auto layerName = GetLayerName(graph, layerIndex);
1768     IConnectableLayer* layer = m_Network->AddMultiplicationLayer(layerName.c_str());
1769
1770     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1771     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1772
1773     RegisterInputSlots(graph, layerIndex, layer);
1774     RegisterOutputSlots(graph, layerIndex, layer);
1775 }
1776
1777 void IDeserializer::DeserializerImpl::ParseFloor(GraphPtr graph, unsigned int layerIndex)
1778 {
1779     CHECK_LAYERS(graph, 0, layerIndex);
1780     CHECK_LOCATION();
1781
1782     auto inputs = GetInputs(graph, layerIndex);
1783     CHECK_VALID_SIZE(inputs.size(), 1);
1784
1785     auto outputs = GetOutputs(graph, layerIndex);
1786     CHECK_VALID_SIZE(outputs.size(), 1);
1787
1788     auto layerName = GetLayerName(graph, layerIndex);
1789
1790     armnn::IConnectableLayer* layer;
1791
1792     layer = m_Network->AddFloorLayer(layerName.c_str());
1793
1794     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1795     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1796
1797     RegisterInputSlots(graph, layerIndex, layer);
1798     RegisterOutputSlots(graph, layerIndex, layer);
1799 }
1800
1801 void IDeserializer::DeserializerImpl::ParseFullyConnected(GraphPtr graph, unsigned int layerIndex)
1802 {
1803     CHECK_LAYERS(graph, 0, layerIndex);
1804     auto inputs = GetInputs(graph, layerIndex);
1805     CHECK_LOCATION();
1806     CHECK_VALID_SIZE(inputs.size(), 1);
1807
1808     auto outputs = GetOutputs(graph, layerIndex);
1809     CHECK_VALID_SIZE(outputs.size(), 1);
1810
1811     auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_FullyConnectedLayer();
1812     auto layerName = GetLayerName(graph, layerIndex);
1813     auto flatBufferDescriptor = flatBufferLayer->descriptor();
1814
1815     armnn::FullyConnectedDescriptor fullyConnectedDescriptor;
1816     fullyConnectedDescriptor.m_BiasEnabled = flatBufferDescriptor->biasEnabled();
1817     fullyConnectedDescriptor.m_TransposeWeightMatrix = flatBufferDescriptor->transposeWeightsMatrix();
1818
1819     armnn::ConstTensor weightsTensor = ToConstTensor(flatBufferLayer->weights());
1820
1821     armnn::IConnectableLayer* layer;
1822     armnn::Optional<armnn::ConstTensor> optionalBiases = armnn::EmptyOptional();
1823     if (flatBufferDescriptor->biasEnabled())
1824     {
1825         armnn::ConstTensor biasTensorData = ToConstTensor(flatBufferLayer->biases());
1826         optionalBiases = armnn::Optional<armnn::ConstTensor>(biasTensorData);
1827     }
1828     layer = m_Network->AddFullyConnectedLayer(fullyConnectedDescriptor,
1829                                               weightsTensor,
1830                                               optionalBiases,
1831                                               layerName.c_str());
1832
1833     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1834     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1835
1836     RegisterInputSlots(graph, layerIndex, layer);
1837     RegisterOutputSlots(graph, layerIndex, layer);
1838 }
1839
1840 void IDeserializer::DeserializerImpl::ParsePad(GraphPtr graph, unsigned int layerIndex)
1841 {
1842     CHECK_LAYERS(graph, 0, layerIndex);
1843
1844     TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
1845     CHECK_VALID_SIZE(inputs.size(), 1);
1846
1847     TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
1848     CHECK_VALID_SIZE(outputs.size(), 1);
1849
1850     auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_PadLayer()->descriptor();
1851     auto flatBufferPadList = flatBufferDescriptor->padList();
1852     float padValue = flatBufferDescriptor->padValue();
1853
1854     if (flatBufferPadList->Length() % 2 != 0)
1855     {
1856         throw ParseException(fmt::format("The size of the pad list must be divisible by 2 {}",
1857                                          CHECK_LOCATION().AsString()));
1858     }
1859
1860     std::vector<std::pair<unsigned int, unsigned int>> padList;
1861     padList.reserve(flatBufferPadList->Length() / 2);
1862     for (unsigned int i = 0; i < flatBufferPadList->Length() - 1; i += 2)
1863     {
1864         padList.emplace_back(flatBufferPadList->Get(i), flatBufferPadList->Get(i+1));
1865     }
1866
1867     armnn::PadDescriptor descriptor(padList, padValue);
1868
1869     auto layerName = GetLayerName(graph, layerIndex);
1870     IConnectableLayer* layer = m_Network->AddPadLayer(descriptor, layerName.c_str());
1871
1872     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1873     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1874
1875     RegisterInputSlots(graph, layerIndex, layer);
1876     RegisterOutputSlots(graph, layerIndex, layer);
1877 }
1878
1879 void IDeserializer::DeserializerImpl::ParsePermute(GraphPtr graph, unsigned int layerIndex)
1880 {
1881     CHECK_LAYERS(graph, 0, layerIndex);
1882
1883     auto dimsMapping =
1884     graph->layers()->Get(layerIndex)->layer_as_PermuteLayer()->descriptor()->dimMappings();
1885
1886     auto inputs = GetInputs(graph, layerIndex);
1887     CHECK_VALID_SIZE(inputs.size(), 1);
1888
1889     auto outputs = GetOutputs(graph, layerIndex);
1890     CHECK_VALID_SIZE(outputs.size(), 1);
1891     auto outputInfo = ToTensorInfo(outputs[0]);
1892
1893     auto layerName = GetLayerName(graph, layerIndex);
1894     const armnn::PermuteDescriptor descriptor(armnn::PermutationVector(dimsMapping->data(), dimsMapping->Length()));
1895
1896     IConnectableLayer* layer = m_Network->AddPermuteLayer(descriptor, layerName.c_str());
1897     layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1898
1899     RegisterInputSlots(graph, layerIndex, layer);
1900     RegisterOutputSlots(graph, layerIndex, layer);
1901 }
1902
1903 armnn::Pooling2dDescriptor IDeserializer::DeserializerImpl::GetPoolingDescriptor(PoolingDescriptor pooling2dDesc,
1904                                                               unsigned int layerIndex)
1905 {
1906     IgnoreUnused(layerIndex);
1907     armnn::Pooling2dDescriptor desc;
1908
1909     switch (pooling2dDesc->poolType())
1910     {
1911         case PoolingAlgorithm_Average:
1912         {
1913             desc.m_PoolType = armnn::PoolingAlgorithm::Average;
1914             break;
1915         }
1916         case PoolingAlgorithm_Max:
1917         {
1918             desc.m_PoolType = armnn::PoolingAlgorithm::Max;
1919             break;
1920         }
1921         default:
1922         {
1923             ARMNN_ASSERT_MSG(false, "Unsupported pooling algorithm");
1924         }
1925     }
1926
1927     switch (pooling2dDesc->outputShapeRounding())
1928     {
1929         case OutputShapeRounding_Floor:
1930         {
1931             desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
1932             break;
1933         }
1934         case OutputShapeRounding_Ceiling:
1935         {
1936             desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Ceiling;
1937             break;
1938         }
1939         default:
1940         {
1941             ARMNN_ASSERT_MSG(false, "Unsupported output shape rounding");
1942         }
1943     }
1944
1945     switch (pooling2dDesc->paddingMethod())
1946     {
1947         case PaddingMethod_Exclude:
1948         {
1949             desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
1950             break;
1951         }
1952         case PaddingMethod_IgnoreValue:
1953         {
1954             desc.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1955             break;
1956         }
1957         default:
1958         {
1959             ARMNN_ASSERT_MSG(false, "Unsupported padding method");
1960         }
1961     }
1962
1963     switch (pooling2dDesc->dataLayout())
1964     {
1965         case DataLayout_NCHW:
1966         {
1967             desc.m_DataLayout = armnn::DataLayout::NCHW;
1968             break;
1969         }
1970         case DataLayout_NHWC:
1971         {
1972             desc.m_DataLayout = armnn::DataLayout::NHWC;
1973             break;
1974         }
1975         default:
1976         {
1977             ARMNN_ASSERT_MSG(false, "Unsupported data layout");
1978         }
1979     }
1980
1981     desc.m_PadRight   = pooling2dDesc->padRight();
1982     desc.m_PadLeft    = pooling2dDesc->padLeft();
1983     desc.m_PadBottom  = pooling2dDesc->padBottom();
1984     desc.m_PadTop     = pooling2dDesc->padTop();
1985     desc.m_StrideX    = pooling2dDesc->strideX();
1986     desc.m_StrideY    = pooling2dDesc->strideY();
1987     desc.m_PoolWidth  = pooling2dDesc->poolWidth();
1988     desc.m_PoolHeight = pooling2dDesc->poolHeight();
1989
1990     return desc;
1991 }
1992
1993
1994
1995 void IDeserializer::DeserializerImpl::ParsePooling2d(GraphPtr graph, unsigned int layerIndex)
1996 {
1997     CHECK_LAYERS(graph, 0, layerIndex);
1998
1999     auto pooling2dDes = graph->layers()->Get(layerIndex)->layer_as_Pooling2dLayer()->descriptor();
2000     auto inputs = GetInputs(graph, layerIndex);
2001     CHECK_VALID_SIZE(inputs.size(), 1);
2002
2003     auto outputs = GetOutputs(graph, layerIndex);
2004     CHECK_VALID_SIZE(outputs.size(), 1);
2005     auto outputInfo = ToTensorInfo(outputs[0]);
2006
2007     auto pooling2dDescriptor = GetPoolingDescriptor(pooling2dDes, layerIndex);
2008     auto layerName = GetLayerName(graph, layerIndex);
2009     IConnectableLayer* layer = m_Network->AddPooling2dLayer(pooling2dDescriptor, layerName.c_str());
2010     layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2011
2012     RegisterInputSlots(graph, layerIndex, layer);
2013     RegisterOutputSlots(graph, layerIndex, layer);
2014 }
2015
2016 void IDeserializer::DeserializerImpl::ParseQuantize(GraphPtr graph, unsigned int layerIndex)
2017 {
2018     CHECK_LAYERS(graph, 0, layerIndex);
2019
2020     auto inputs = GetInputs(graph, layerIndex);
2021     CHECK_VALID_SIZE(inputs.size(), 1);
2022
2023     auto outputs = GetOutputs(graph, layerIndex);
2024     CHECK_VALID_SIZE(outputs.size(), 1);
2025     auto outputInfo = ToTensorInfo(outputs[0]);
2026
2027     auto layerName = GetLayerName(graph, layerIndex);
2028     IConnectableLayer* layer = m_Network->AddQuantizeLayer(layerName.c_str());
2029     layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2030
2031     RegisterInputSlots(graph, layerIndex, layer);
2032     RegisterOutputSlots(graph, layerIndex, layer);
2033 }
2034
2035 armnn::TensorInfo IDeserializer::DeserializerImpl::OutputShapeOfReshape(const armnn::TensorInfo& inputTensorInfo,
2036                                                           const std::vector<uint32_t>& targetDimsIn)
2037 {
2038     std::vector<unsigned int> outputDims(targetDimsIn.begin(), targetDimsIn.end());
2039     const auto stretchDim = std::find(targetDimsIn.begin(), targetDimsIn.end(), -1);
2040
2041     if (stretchDim != targetDimsIn.end())
2042     {
2043         if (std::find(std::next(stretchDim), targetDimsIn.end(), -1) != targetDimsIn.end())
2044         {
2045             throw ParseException(fmt::format("At most one component of shape can be -1 {}",
2046                                              CHECK_LOCATION().AsString()));
2047         }
2048
2049         auto targetNumElements =
2050            armnn::numeric_cast<unsigned int>(
2051                std::accumulate(targetDimsIn.begin(), targetDimsIn.end(), -1, std::multiplies<int32_t>()));
2052
2053         auto stretchIndex = static_cast<size_t>(std::distance(targetDimsIn.begin(), stretchDim));
2054         outputDims[stretchIndex] = inputTensorInfo.GetNumElements() / targetNumElements;
2055     }
2056
2057     TensorShape outputShape = TensorShape(static_cast<unsigned int>(outputDims.size()), outputDims.data());
2058
2059     armnn::TensorInfo reshapeInfo = inputTensorInfo;
2060     reshapeInfo.SetShape(outputShape);
2061
2062     return reshapeInfo;
2063 }
2064
2065 void IDeserializer::DeserializerImpl::ParseRank(GraphPtr graph, unsigned int layerIndex)
2066 {
2067     CHECK_LAYERS(graph, 0, layerIndex);
2068
2069     TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2070     CHECK_VALID_SIZE(inputs.size(), 1);
2071
2072     TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2073     CHECK_VALID_SIZE(outputs.size(), 1);
2074
2075     auto layerName = GetLayerName(graph, layerIndex);
2076     IConnectableLayer* layer = m_Network->AddRankLayer( layerName.c_str());
2077
2078     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2079     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2080
2081     RegisterInputSlots(graph, layerIndex, layer);
2082     RegisterOutputSlots(graph, layerIndex, layer);
2083 }
2084
2085 void IDeserializer::DeserializerImpl::ParseReshape(GraphPtr graph, unsigned int layerIndex)
2086 {
2087     CHECK_LAYERS(graph, 0, layerIndex);
2088     auto inputs = GetInputs(graph, layerIndex);
2089
2090     auto outputs = GetOutputs(graph, layerIndex);
2091     CHECK_VALID_SIZE(outputs.size(), 1);
2092
2093     armnn::TensorInfo inputTensorInfo = ToTensorInfo(inputs[0]);
2094     armnn::TensorInfo actualOutputTensorInfo = ToTensorInfo(outputs[0]);
2095
2096     const auto targetDims = graph->layers()->Get(layerIndex)->layer_as_ReshapeLayer()->descriptor()->targetShape();
2097     std::vector<uint32_t> outputDims(targetDims->begin(), targetDims->begin() + targetDims->size());
2098
2099     armnn::TensorInfo reshapeOutputTensorInfo = DeserializerImpl::OutputShapeOfReshape(inputTensorInfo, outputDims);
2100     const armnn::TensorShape& reshapeOutputTensorShape = reshapeOutputTensorInfo.GetShape();
2101
2102     const std::vector<uint32_t> expectedDims(outputs[0]->dimensions()->begin(),
2103                                              outputs[0]->dimensions()->begin() + outputs[0]->dimensions()->size());
2104
2105     if (inputs.size() > 1 && !CheckShape(reshapeOutputTensorShape, expectedDims))
2106     {
2107         std::stringstream ss;
2108         ss << "New shape defined in reshape parameters "
2109            << reshapeOutputTensorShape
2110            << " does not equal output shape "
2111            << actualOutputTensorInfo.GetShape()
2112            << ": "
2113            << CHECK_LOCATION().AsString();
2114         throw ParseException(ss.str());
2115     }
2116
2117     armnn::ReshapeDescriptor reshapeDesc;
2118     reshapeDesc.m_TargetShape = reshapeOutputTensorShape;
2119
2120     auto layerName = GetLayerName(graph, layerIndex);
2121     IConnectableLayer* layer = m_Network->AddReshapeLayer(reshapeDesc, layerName.c_str());
2122     layer->GetOutputSlot(0).SetTensorInfo(reshapeOutputTensorInfo);
2123
2124     RegisterInputSlots(graph, layerIndex, layer);
2125     RegisterOutputSlots(graph, layerIndex, layer);
2126 }
2127
2128 void IDeserializer::DeserializerImpl::ParseResize(GraphPtr graph, unsigned int layerIndex)
2129 {
2130     CHECK_LAYERS(graph, 0, layerIndex);
2131
2132     TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2133     CHECK_VALID_SIZE(inputs.size(), 1);
2134
2135     TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2136     CHECK_VALID_SIZE(outputs.size(), 1);
2137
2138     auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_ResizeLayer()->descriptor();
2139
2140     armnn::ResizeDescriptor descriptor;
2141     descriptor.m_TargetWidth = flatBufferDescriptor->targetWidth();
2142     descriptor.m_TargetHeight = flatBufferDescriptor->targetHeight();
2143     descriptor.m_Method = ToResizeMethod(flatBufferDescriptor->method());
2144     descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2145     descriptor.m_AlignCorners = flatBufferDescriptor->alignCorners();
2146     descriptor.m_HalfPixelCenters = flatBufferDescriptor->halfPixelCenters();
2147
2148     auto layerName = GetLayerName(graph, layerIndex);
2149     IConnectableLayer* layer = m_Network->AddResizeLayer(descriptor, layerName.c_str());
2150
2151     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2152     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2153
2154     RegisterInputSlots(graph, layerIndex, layer);
2155     RegisterOutputSlots(graph, layerIndex, layer);
2156 }
2157
2158 void IDeserializer::DeserializerImpl::ParseResizeBilinear(GraphPtr graph, unsigned int layerIndex)
2159 {
2160     CHECK_LAYERS(graph, 0, layerIndex);
2161
2162     TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2163     CHECK_VALID_SIZE(inputs.size(), 1);
2164
2165     TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2166     CHECK_VALID_SIZE(outputs.size(), 1);
2167
2168     auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_ResizeBilinearLayer()->descriptor();
2169
2170     armnn::ResizeDescriptor descriptor;
2171     descriptor.m_TargetWidth  = flatBufferDescriptor->targetWidth();
2172     descriptor.m_TargetHeight = flatBufferDescriptor->targetHeight();
2173     descriptor.m_Method       = armnn::ResizeMethod::Bilinear;
2174     descriptor.m_DataLayout   = ToDataLayout(flatBufferDescriptor->dataLayout());
2175     descriptor.m_AlignCorners = flatBufferDescriptor->alignCorners();
2176     descriptor.m_HalfPixelCenters = flatBufferDescriptor->halfPixelCenters();
2177
2178     auto layerName = GetLayerName(graph, layerIndex);
2179     IConnectableLayer* layer = m_Network->AddResizeLayer(descriptor, layerName.c_str());
2180
2181     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2182     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2183
2184     RegisterInputSlots(graph, layerIndex, layer);
2185     RegisterOutputSlots(graph, layerIndex, layer);
2186 }
2187
2188 void IDeserializer::DeserializerImpl::ParseSoftmax(GraphPtr graph, unsigned int layerIndex)
2189 {
2190     CHECK_LAYERS(graph, 0, layerIndex);
2191
2192     TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2193     CHECK_VALID_SIZE(inputs.size(), 1);
2194
2195     TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2196     CHECK_VALID_SIZE(outputs.size(), 1);
2197
2198     armnn::SoftmaxDescriptor descriptor;
2199     descriptor.m_Beta = graph->layers()->Get(layerIndex)->layer_as_SoftmaxLayer()->descriptor()->beta();
2200     auto layerName = GetLayerName(graph, layerIndex);
2201
2202     IConnectableLayer* layer = m_Network->AddSoftmaxLayer(descriptor, layerName.c_str());
2203
2204     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2205     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2206
2207     RegisterInputSlots(graph, layerIndex, layer);
2208     RegisterOutputSlots(graph, layerIndex, layer);
2209 }
2210
2211 void IDeserializer::DeserializerImpl::ParseSpaceToBatchNd(GraphPtr graph, unsigned int layerIndex)
2212 {
2213     CHECK_LAYERS(graph, 0, layerIndex);
2214
2215     TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2216     CHECK_VALID_SIZE(inputs.size(), 1);
2217
2218     TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2219     CHECK_VALID_SIZE(outputs.size(), 1);
2220
2221     auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_SpaceToBatchNdLayer()->descriptor();
2222     auto flatBufferPadList = flatBufferDescriptor->padList();
2223     auto flatBufferBlockShape = flatBufferDescriptor->blockShape();
2224
2225     if (flatBufferPadList->Length() % 2 != 0)
2226     {
2227         throw ParseException(fmt::format("The size of the pad list must be divisible by 2 {}",
2228                                          CHECK_LOCATION().AsString()));
2229     }
2230
2231     std::vector<std::pair<unsigned int, unsigned int>> padList;
2232     padList.reserve(flatBufferPadList->Length() / 2);
2233     for (unsigned int i = 0; i < flatBufferPadList->Length() - 1; i += 2)
2234     {
2235         padList.emplace_back(flatBufferPadList->Get(i), flatBufferPadList->Get(i+1));
2236     }
2237
2238     armnn::SpaceToBatchNdDescriptor descriptor;
2239     descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2240     descriptor.m_BlockShape =
2241         std::vector<unsigned int>(flatBufferBlockShape->begin(), flatBufferBlockShape->end());
2242     descriptor.m_PadList = padList;
2243
2244     auto layerName = GetLayerName(graph, layerIndex);
2245     IConnectableLayer* layer = m_Network->AddSpaceToBatchNdLayer(descriptor, layerName.c_str());
2246
2247     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2248     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2249
2250     RegisterInputSlots(graph, layerIndex, layer);
2251     RegisterOutputSlots(graph, layerIndex, layer);
2252 }
2253
2254 void IDeserializer::DeserializerImpl::ParseSpaceToDepth(GraphPtr graph, unsigned int layerIndex)
2255 {
2256     CHECK_LAYERS(graph, 0, layerIndex);
2257
2258     TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2259     CHECK_VALID_SIZE(inputs.size(), 1);
2260
2261     TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2262     CHECK_VALID_SIZE(outputs.size(), 1);
2263
2264     auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_SpaceToDepthLayer()->descriptor();
2265
2266     armnn::SpaceToDepthDescriptor descriptor;
2267     descriptor.m_BlockSize  = flatBufferDescriptor->blockSize();
2268     descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2269
2270     auto layerName = GetLayerName(graph, layerIndex);
2271     IConnectableLayer* layer = m_Network->AddSpaceToDepthLayer(descriptor, layerName.c_str());
2272
2273     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2274     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2275
2276     RegisterInputSlots(graph, layerIndex, layer);
2277     RegisterOutputSlots(graph, layerIndex, layer);
2278 }
2279
2280 armnn::NormalizationDescriptor IDeserializer::DeserializerImpl::GetNormalizationDescriptor(
2281     NormalizationDescriptorPtr normalizationDescriptor,
2282     unsigned int layerIndex)
2283 {
2284     IgnoreUnused(layerIndex);
2285     armnn::NormalizationDescriptor desc;
2286
2287     switch (normalizationDescriptor->normChannelType())
2288     {
2289         case NormalizationAlgorithmChannel_Across:
2290         {
2291             desc.m_NormChannelType = armnn::NormalizationAlgorithmChannel::Across;
2292             break;
2293         }
2294         case NormalizationAlgorithmChannel_Within:
2295         {
2296             desc.m_NormChannelType = armnn::NormalizationAlgorithmChannel::Within;
2297             break;
2298         }
2299         default:
2300         {
2301             ARMNN_ASSERT_MSG(false, "Unsupported normalization channel type");
2302         }
2303     }
2304
2305     switch (normalizationDescriptor->normMethodType())
2306     {
2307         case NormalizationAlgorithmMethod_LocalBrightness:
2308         {
2309             desc.m_NormMethodType = armnn::NormalizationAlgorithmMethod::LocalBrightness;
2310             break;
2311         }
2312         case NormalizationAlgorithmMethod_LocalContrast:
2313         {
2314             desc.m_NormMethodType = armnn::NormalizationAlgorithmMethod::LocalContrast;
2315             break;
2316         }
2317         default:
2318         {
2319             ARMNN_ASSERT_MSG(false, "Unsupported normalization method type");
2320         }
2321     }
2322
2323     switch (normalizationDescriptor->dataLayout())
2324     {
2325         case DataLayout_NCHW:
2326         {
2327             desc.m_DataLayout = armnn::DataLayout::NCHW;
2328             break;
2329         }
2330         case DataLayout_NHWC:
2331         {
2332             desc.m_DataLayout = armnn::DataLayout::NHWC;
2333             break;
2334         }
2335         default:
2336         {
2337             ARMNN_ASSERT_MSG(false, "Unsupported data layout");
2338         }
2339     }
2340
2341     desc.m_Alpha    = normalizationDescriptor->alpha();
2342     desc.m_Beta     = normalizationDescriptor->beta();
2343     desc.m_K        = normalizationDescriptor->k();
2344     desc.m_NormSize = normalizationDescriptor->normSize();
2345
2346     return desc;
2347 }
2348
2349 void IDeserializer::DeserializerImpl::ParseNormalization(GraphPtr graph, unsigned int layerIndex)
2350 {
2351     CHECK_LAYERS(graph, 0, layerIndex);
2352
2353     auto normalizationDes = graph->layers()->Get(layerIndex)->layer_as_NormalizationLayer()->descriptor();
2354
2355     TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2356     CHECK_VALID_SIZE(inputs.size(), 1);
2357
2358     TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2359     CHECK_VALID_SIZE(outputs.size(), 1);
2360
2361     auto outputInfo = ToTensorInfo(outputs[0]);
2362
2363     auto normalizationDescriptor = GetNormalizationDescriptor(normalizationDes, layerIndex);
2364     auto layerName = GetLayerName(graph, layerIndex);
2365
2366     IConnectableLayer* layer = m_Network->AddNormalizationLayer(normalizationDescriptor, layerName.c_str());
2367     layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2368
2369     RegisterInputSlots(graph, layerIndex, layer);
2370     RegisterOutputSlots(graph, layerIndex, layer);
2371 }
2372
2373 void IDeserializer::DeserializerImpl::ParseRsqrt(GraphPtr graph, unsigned int layerIndex)
2374 {
2375     CHECK_LAYERS(graph, 0, layerIndex);
2376     auto inputs = GetInputs(graph, layerIndex);
2377     CHECK_LOCATION();
2378     CHECK_VALID_SIZE(inputs.size(), 1);
2379
2380     auto outputs = GetOutputs(graph, layerIndex);
2381     CHECK_VALID_SIZE(outputs.size(), 1);
2382
2383     auto layerName = GetLayerName(graph, layerIndex);
2384
2385     armnn::ElementwiseUnaryDescriptor descriptor(armnn::UnaryOperation::Rsqrt);
2386     IConnectableLayer* layer = m_Network->AddElementwiseUnaryLayer(descriptor, layerName.c_str());
2387     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2388     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2389
2390     RegisterInputSlots(graph, layerIndex, layer);
2391     RegisterOutputSlots(graph, layerIndex, layer);
2392 }
2393
2394 void IDeserializer::DeserializerImpl::ParseSlice(GraphPtr graph, unsigned int layerIndex)
2395 {
2396     CHECK_LAYERS(graph, 0, layerIndex);
2397
2398     auto inputs = GetInputs(graph, layerIndex);
2399     CHECK_VALID_SIZE(inputs.size(), 1);
2400
2401     auto outputs = GetOutputs(graph, layerIndex);
2402     CHECK_VALID_SIZE(outputs.size(), 1);
2403
2404     auto fbDescriptor = graph->layers()->Get(layerIndex)->layer_as_SliceLayer()->descriptor();
2405
2406     auto fbBegin = fbDescriptor->begin();
2407     auto fbSize  = fbDescriptor->size();
2408
2409     if (fbBegin->Length() != fbSize->Length())
2410     {
2411         throw ParseException(fmt::format("Begin and size descriptors must have the same length {}",
2412                                          CHECK_LOCATION().AsString()));
2413     }
2414
2415     armnn::SliceDescriptor descriptor;
2416     descriptor.m_Begin.insert(descriptor.m_Begin.end(), fbBegin->begin(), fbBegin->end());
2417     descriptor.m_Size.insert(descriptor.m_Size.end(), fbSize->begin(), fbSize->end());
2418
2419     auto layerName = GetLayerName(graph, layerIndex);
2420     IConnectableLayer* layer = m_Network->AddSliceLayer(descriptor, layerName.c_str());
2421
2422     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2423     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2424
2425     RegisterInputSlots(graph, layerIndex, layer);
2426     RegisterOutputSlots(graph, layerIndex, layer);
2427 }
2428
2429 void IDeserializer::DeserializerImpl::ParseStridedSlice(GraphPtr graph, unsigned int layerIndex)
2430 {
2431     CHECK_LAYERS(graph, 0, layerIndex);
2432
2433     TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2434     CHECK_VALID_SIZE(inputs.size(), 1);
2435
2436     TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2437     CHECK_VALID_SIZE(outputs.size(), 1);
2438
2439     auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_StridedSliceLayer()->descriptor();
2440
2441     auto flatBufferBegin = flatBufferDescriptor->begin();
2442     auto flatBufferEnd = flatBufferDescriptor->end();
2443     auto flatBufferStride = flatBufferDescriptor->stride();
2444
2445     if (!(flatBufferBegin->Length() == flatBufferEnd->Length() &&
2446           flatBufferBegin->Length() == flatBufferStride->Length()))
2447     {
2448         throw ParseException(fmt::format("The size of the begin, end, and stride must be equal {}",
2449                                          CHECK_LOCATION().AsString()));
2450     }
2451
2452     std::vector<int> begin(flatBufferBegin->begin(), flatBufferBegin->end());
2453     std::vector<int> end(flatBufferEnd->begin(), flatBufferEnd->end());
2454     std::vector<int> stride(flatBufferStride->begin(), flatBufferStride->end());
2455
2456     armnn::StridedSliceDescriptor descriptor(begin, end, stride);
2457     descriptor.m_BeginMask = flatBufferDescriptor->beginMask();
2458     descriptor.m_EndMask = flatBufferDescriptor->endMask();
2459     descriptor.m_ShrinkAxisMask = flatBufferDescriptor->shrinkAxisMask();
2460     descriptor.m_EllipsisMask = flatBufferDescriptor->ellipsisMask();
2461     descriptor.m_NewAxisMask = flatBufferDescriptor->newAxisMask();
2462     descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2463
2464     auto layerName = GetLayerName(graph, layerIndex);
2465     IConnectableLayer* layer = m_Network->AddStridedSliceLayer(descriptor, layerName.c_str());
2466
2467     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2468     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2469
2470     RegisterInputSlots(graph, layerIndex, layer);
2471     RegisterOutputSlots(graph, layerIndex, layer);
2472 }
2473
2474 void IDeserializer::DeserializerImpl::ParseSubtraction(GraphPtr graph, unsigned int layerIndex)
2475 {
2476     CHECK_LAYERS(graph, 0, layerIndex);
2477     auto inputs = GetInputs(graph, layerIndex);
2478     CHECK_LOCATION();
2479     CHECK_VALID_SIZE(inputs.size(), 2);
2480
2481     auto outputs = GetOutputs(graph, layerIndex);
2482     CHECK_VALID_SIZE(outputs.size(), 1);
2483
2484     auto layerName = GetLayerName(graph, layerIndex);
2485     IConnectableLayer* layer = m_Network->AddSubtractionLayer(layerName.c_str());
2486
2487     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2488     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2489
2490     RegisterInputSlots(graph, layerIndex, layer);
2491     RegisterOutputSlots(graph, layerIndex, layer);
2492 }
2493
2494 void IDeserializer::DeserializerImpl::ParseGather(GraphPtr graph, unsigned int layerIndex)
2495 {
2496     CHECK_LAYERS(graph, 0, layerIndex);
2497
2498     TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2499     CHECK_VALID_SIZE(inputs.size(), 2);
2500
2501     TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2502     CHECK_VALID_SIZE(outputs.size(), 1);
2503
2504     armnn::GatherDescriptor descriptor;
2505     descriptor.m_Axis = graph->layers()->Get(layerIndex)->layer_as_GatherLayer()->descriptor()->axis();
2506
2507     auto layerName = GetLayerName(graph, layerIndex);
2508     IConnectableLayer* layer = m_Network->AddGatherLayer(descriptor, layerName.c_str());
2509
2510     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2511     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2512
2513     RegisterInputSlots(graph, layerIndex, layer);
2514     RegisterOutputSlots(graph, layerIndex, layer);
2515 }
2516
2517 void IDeserializer::DeserializerImpl::ParseMean(GraphPtr graph, unsigned int layerIndex)
2518 {
2519     CHECK_LAYERS(graph, 0, layerIndex);
2520
2521     TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2522     CHECK_VALID_SIZE(inputs.size(), 1);
2523
2524     TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2525     CHECK_VALID_SIZE(outputs.size(), 1);
2526
2527     auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_MeanLayer()->descriptor();
2528     auto flatBufferAxis = flatBufferDescriptor->axis();
2529     auto flatBufferKeepDims = flatBufferDescriptor->keepDims();
2530
2531     armnn::MeanDescriptor descriptor;
2532     descriptor.m_Axis = std::vector<unsigned int>(flatBufferAxis->begin(), flatBufferAxis->end());
2533     descriptor.m_KeepDims = flatBufferKeepDims;
2534
2535     auto layerName = GetLayerName(graph, layerIndex);
2536     IConnectableLayer* layer = m_Network->AddMeanLayer(descriptor, layerName.c_str());
2537
2538     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2539     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2540
2541     RegisterInputSlots(graph, layerIndex, layer);
2542     RegisterOutputSlots(graph, layerIndex, layer);
2543 }
2544
2545 void IDeserializer::DeserializerImpl::ParseSplitter(GraphPtr graph, unsigned int layerIndex)
2546 {
2547     CHECK_LAYERS(graph, 0, layerIndex);
2548
2549     TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2550     CHECK_VALID_SIZE(inputs.size(), 1);
2551
2552     TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2553
2554     auto flatBufferViewsDescriptor = graph->layers()->Get(layerIndex)->layer_as_SplitterLayer()->descriptor();
2555     auto flatBufferViewSizes = flatBufferViewsDescriptor->viewSizes();
2556     auto flatBufferOriginsDescriptor = flatBufferViewsDescriptor->origins();
2557     auto flatBufferViewOrigins = flatBufferOriginsDescriptor->viewOrigins();
2558     uint32_t numViews = flatBufferOriginsDescriptor->numViews();
2559     uint32_t numDimensions = flatBufferOriginsDescriptor->numDimensions();
2560
2561     // Check numViews and numDimensions corresponds to the ones already serialized ...
2562     // numViews ==  flatBufferViewSizes.size();
2563     // foreach: numDimensions == flatBufferViewSizes[x].size();
2564
2565     armnn::ViewsDescriptor viewsDescriptor(numViews, numDimensions);
2566     for(unsigned int vIdx = 0; vIdx < numViews; ++vIdx)
2567     {
2568         for (unsigned int dIdx = 0; dIdx < numDimensions; ++dIdx)
2569         {
2570             viewsDescriptor.SetViewSize(vIdx, dIdx, flatBufferViewSizes->Get(vIdx)->data()->Get(dIdx));
2571             viewsDescriptor.SetViewOriginCoord(vIdx, dIdx, flatBufferViewOrigins->Get(vIdx)->data()->Get(dIdx));
2572         }
2573     }
2574
2575     auto layerName = GetLayerName(graph, layerIndex);
2576     IConnectableLayer* layer = m_Network->AddSplitterLayer(viewsDescriptor, layerName.c_str());
2577
2578     // I could have as many outputs as views ...
2579     for(unsigned int vIdx = 0; vIdx < numViews; ++vIdx)
2580     {
2581         armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[vIdx]);
2582         layer->GetOutputSlot(vIdx).SetTensorInfo(outputTensorInfo);
2583     }
2584
2585     RegisterInputSlots(graph, layerIndex, layer);
2586     RegisterOutputSlots(graph, layerIndex, layer);
2587 }
2588
2589 armnn::LstmDescriptor IDeserializer::DeserializerImpl::GetLstmDescriptor(LstmDescriptorPtr lstmDescriptor)
2590 {
2591     armnn::LstmDescriptor desc;
2592
2593     desc.m_ActivationFunc = lstmDescriptor->activationFunc();
2594     desc.m_ClippingThresCell = lstmDescriptor->clippingThresCell();
2595     desc.m_ClippingThresProj = lstmDescriptor->clippingThresProj();
2596     desc.m_CifgEnabled = lstmDescriptor->cifgEnabled();
2597     desc.m_PeepholeEnabled = lstmDescriptor->peepholeEnabled();
2598     desc.m_ProjectionEnabled = lstmDescriptor->projectionEnabled();
2599     desc.m_LayerNormEnabled = lstmDescriptor->layerNormEnabled();
2600
2601     return desc;
2602 }
2603
2604 void IDeserializer::DeserializerImpl::ParseLstm(GraphPtr graph, unsigned int layerIndex)
2605 {
2606     CHECK_LAYERS(graph, 0, layerIndex);
2607
2608     auto inputs = GetInputs(graph, layerIndex);
2609     CHECK_VALID_SIZE(inputs.size(), 3);
2610
2611     auto outputs = GetOutputs(graph, layerIndex);
2612     CHECK_VALID_SIZE(outputs.size(), 4);
2613
2614     auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_LstmLayer();
2615     auto layerName = GetLayerName(graph, layerIndex);
2616     auto flatBufferDescriptor = flatBufferLayer->descriptor();
2617     auto flatBufferInputParams = flatBufferLayer->inputParams();
2618
2619     auto lstmDescriptor = GetLstmDescriptor(flatBufferDescriptor);
2620
2621     armnn::LstmInputParams lstmInputParams;
2622
2623     armnn::ConstTensor inputToForgetWeights = ToConstTensor(flatBufferInputParams->inputToForgetWeights());
2624     armnn::ConstTensor inputToCellWeights = ToConstTensor(flatBufferInputParams->inputToCellWeights());
2625     armnn::ConstTensor inputToOutputWeights = ToConstTensor(flatBufferInputParams->inputToOutputWeights());
2626     armnn::ConstTensor recurrentToForgetWeights = ToConstTensor(flatBufferInputParams->recurrentToForgetWeights());
2627     armnn::ConstTensor recurrentToCellWeights = ToConstTensor(flatBufferInputParams->recurrentToCellWeights());
2628     armnn::ConstTensor recurrentToOutputWeights = ToConstTensor(flatBufferInputParams->recurrentToOutputWeights());
2629     armnn::ConstTensor forgetGateBias = ToConstTensor(flatBufferInputParams->forgetGateBias());
2630     armnn::ConstTensor cellBias = ToConstTensor(flatBufferInputParams->cellBias());
2631     armnn::ConstTensor outputGateBias = ToConstTensor(flatBufferInputParams->outputGateBias());
2632
2633     lstmInputParams.m_InputToForgetWeights = &inputToForgetWeights;
2634     lstmInputParams.m_InputToCellWeights = &inputToCellWeights;
2635     lstmInputParams.m_InputToOutputWeights = &inputToOutputWeights;
2636     lstmInputParams.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2637     lstmInputParams.m_RecurrentToCellWeights = &recurrentToCellWeights;
2638     lstmInputParams.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2639     lstmInputParams.m_ForgetGateBias = &forgetGateBias;
2640     lstmInputParams.m_CellBias = &cellBias;
2641     lstmInputParams.m_OutputGateBias = &outputGateBias;
2642
2643     armnn::ConstTensor inputToInputWeights;
2644     armnn::ConstTensor recurrentToInputWeights;
2645     armnn::ConstTensor cellToInputWeights;
2646     armnn::ConstTensor inputGateBias;
2647     if (!lstmDescriptor.m_CifgEnabled)
2648     {
2649         inputToInputWeights = ToConstTensor(flatBufferInputParams->inputToInputWeights());
2650         recurrentToInputWeights = ToConstTensor(flatBufferInputParams->recurrentToInputWeights());
2651         cellToInputWeights = ToConstTensor(flatBufferInputParams->cellToInputWeights());
2652         inputGateBias = ToConstTensor(flatBufferInputParams->inputGateBias());
2653
2654         lstmInputParams.m_InputToInputWeights = &inputToInputWeights;
2655         lstmInputParams.m_RecurrentToInputWeights = &recurrentToInputWeights;
2656         lstmInputParams.m_CellToInputWeights = &cellToInputWeights;
2657         lstmInputParams.m_InputGateBias = &inputGateBias;
2658     }
2659
2660     armnn::ConstTensor projectionWeights;
2661     armnn::ConstTensor projectionBias;
2662     if (lstmDescriptor.m_ProjectionEnabled)
2663     {
2664         projectionWeights = ToConstTensor(flatBufferInputParams->projectionWeights());
2665         projectionBias = ToConstTensor(flatBufferInputParams->projectionBias());
2666
2667         lstmInputParams.m_ProjectionWeights = &projectionWeights;
2668         lstmInputParams.m_ProjectionBias = &projectionBias;
2669     }
2670
2671     armnn::ConstTensor cellToForgetWeights;
2672     armnn::ConstTensor cellToOutputWeights;
2673     if (lstmDescriptor.m_PeepholeEnabled)
2674     {
2675         cellToForgetWeights = ToConstTensor(flatBufferInputParams->cellToForgetWeights());
2676         cellToOutputWeights = ToConstTensor(flatBufferInputParams->cellToOutputWeights());
2677
2678         lstmInputParams.m_CellToForgetWeights = &cellToForgetWeights;
2679         lstmInputParams.m_CellToOutputWeights = &cellToOutputWeights;
2680     }
2681
2682     armnn::ConstTensor inputLayerNormWeights;
2683     armnn::ConstTensor forgetLayerNormWeights;
2684     armnn::ConstTensor cellLayerNormWeights;
2685     armnn::ConstTensor outputLayerNormWeights;
2686     if (lstmDescriptor.m_LayerNormEnabled)
2687     {
2688         if (!lstmDescriptor.m_CifgEnabled)
2689         {
2690             inputLayerNormWeights = ToConstTensor(flatBufferInputParams->inputLayerNormWeights());
2691             lstmInputParams.m_InputLayerNormWeights = &inputLayerNormWeights;
2692         }
2693         forgetLayerNormWeights = ToConstTensor(flatBufferInputParams->forgetLayerNormWeights());
2694         cellLayerNormWeights = ToConstTensor(flatBufferInputParams->cellLayerNormWeights());
2695         outputLayerNormWeights = ToConstTensor(flatBufferInputParams->outputLayerNormWeights());
2696
2697         lstmInputParams.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
2698         lstmInputParams.m_CellLayerNormWeights = &cellLayerNormWeights;
2699         lstmInputParams.m_OutputLayerNormWeights = &outputLayerNormWeights;
2700     }
2701
2702     IConnectableLayer* layer = m_Network->AddLstmLayer(lstmDescriptor, lstmInputParams, layerName.c_str());
2703
2704     armnn::TensorInfo outputTensorInfo1 = ToTensorInfo(outputs[0]);
2705     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo1);
2706
2707     armnn::TensorInfo outputTensorInfo2 = ToTensorInfo(outputs[1]);
2708     layer->GetOutputSlot(1).SetTensorInfo(outputTensorInfo2);
2709
2710     armnn::TensorInfo outputTensorInfo3 = ToTensorInfo(outputs[2]);
2711     layer->GetOutputSlot(2).SetTensorInfo(outputTensorInfo3);
2712
2713     armnn::TensorInfo outputTensorInfo4 = ToTensorInfo(outputs[3]);
2714     layer->GetOutputSlot(3).SetTensorInfo(outputTensorInfo4);
2715
2716     RegisterInputSlots(graph, layerIndex, layer);
2717     RegisterOutputSlots(graph, layerIndex, layer);
2718 }
2719
2720 armnn::QLstmDescriptor IDeserializer::DeserializerImpl::GetQLstmDescriptor(QLstmDescriptorPtr qLstmDescriptor)
2721 {
2722     armnn::QLstmDescriptor desc;
2723
2724     desc.m_CifgEnabled       = qLstmDescriptor->cifgEnabled();
2725     desc.m_PeepholeEnabled   = qLstmDescriptor->peepholeEnabled();
2726     desc.m_ProjectionEnabled = qLstmDescriptor->projectionEnabled();
2727     desc.m_LayerNormEnabled  = qLstmDescriptor->layerNormEnabled();
2728
2729     desc.m_CellClip       = qLstmDescriptor->cellClip();
2730     desc.m_ProjectionClip = qLstmDescriptor->projectionClip();
2731
2732     desc.m_InputIntermediateScale  = qLstmDescriptor->inputIntermediateScale();
2733     desc.m_ForgetIntermediateScale = qLstmDescriptor->forgetIntermediateScale();
2734     desc.m_CellIntermediateScale   = qLstmDescriptor->cellIntermediateScale();
2735     desc.m_OutputIntermediateScale = qLstmDescriptor->outputIntermediateScale();
2736
2737     desc.m_HiddenStateScale     = qLstmDescriptor->hiddenStateScale();
2738     desc.m_HiddenStateZeroPoint = qLstmDescriptor->hiddenStateZeroPoint();
2739
2740     return desc;
2741 }
2742
2743 void IDeserializer::DeserializerImpl::ParseQLstm(GraphPtr graph, unsigned int layerIndex)
2744 {
2745     CHECK_LAYERS(graph, 0, layerIndex);
2746
2747     auto inputs = GetInputs(graph, layerIndex);
2748     CHECK_VALID_SIZE(inputs.size(), 3);
2749
2750     auto outputs = GetOutputs(graph, layerIndex);
2751     CHECK_VALID_SIZE(outputs.size(), 3);
2752
2753     auto flatBufferLayer       = graph->layers()->Get(layerIndex)->layer_as_QLstmLayer();
2754     auto layerName             = GetLayerName(graph, layerIndex);
2755     auto flatBufferDescriptor  = flatBufferLayer->descriptor();
2756     auto flatBufferInputParams = flatBufferLayer->inputParams();
2757
2758     auto qLstmDescriptor = GetQLstmDescriptor(flatBufferDescriptor);
2759     armnn::LstmInputParams qLstmInputParams;
2760
2761     // Mandatory params
2762     armnn::ConstTensor inputToForgetWeights     = ToConstTensor(flatBufferInputParams->inputToForgetWeights());
2763     armnn::ConstTensor inputToCellWeights       = ToConstTensor(flatBufferInputParams->inputToCellWeights());
2764     armnn::ConstTensor inputToOutputWeights     = ToConstTensor(flatBufferInputParams->inputToOutputWeights());
2765     armnn::ConstTensor recurrentToForgetWeights = ToConstTensor(flatBufferInputParams->recurrentToForgetWeights());
2766     armnn::ConstTensor recurrentToCellWeights   = ToConstTensor(flatBufferInputParams->recurrentToCellWeights());
2767     armnn::ConstTensor recurrentToOutputWeights = ToConstTensor(flatBufferInputParams->recurrentToOutputWeights());
2768     armnn::ConstTensor forgetGateBias           = ToConstTensor(flatBufferInputParams->forgetGateBias());
2769     armnn::ConstTensor cellBias                 = ToConstTensor(flatBufferInputParams->cellBias());
2770     armnn::ConstTensor outputGateBias           = ToConstTensor(flatBufferInputParams->outputGateBias());
2771
2772     qLstmInputParams.m_InputToForgetWeights = &inputToForgetWeights;
2773     qLstmInputParams.m_InputToCellWeights = &inputToCellWeights;
2774     qLstmInputParams.m_InputToOutputWeights = &inputToOutputWeights;
2775     qLstmInputParams.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2776     qLstmInputParams.m_RecurrentToCellWeights = &recurrentToCellWeights;
2777     qLstmInputParams.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2778     qLstmInputParams.m_ForgetGateBias = &forgetGateBias;
2779     qLstmInputParams.m_CellBias = &cellBias;
2780     qLstmInputParams.m_OutputGateBias = &outputGateBias;
2781
2782     // Optional CIFG params
2783     armnn::ConstTensor inputToInputWeights;
2784     armnn::ConstTensor recurrentToInputWeights;
2785     armnn::ConstTensor inputGateBias;
2786
2787     if (!qLstmDescriptor.m_CifgEnabled)
2788     {
2789         inputToInputWeights     = ToConstTensor(flatBufferInputParams->inputToInputWeights());
2790         recurrentToInputWeights = ToConstTensor(flatBufferInputParams->recurrentToInputWeights());
2791         inputGateBias           = ToConstTensor(flatBufferInputParams->inputGateBias());
2792
2793         qLstmInputParams.m_InputToInputWeights     = &inputToInputWeights;
2794         qLstmInputParams.m_RecurrentToInputWeights = &recurrentToInputWeights;
2795         qLstmInputParams.m_InputGateBias           = &inputGateBias;
2796     }
2797
2798     // Optional projection params
2799     armnn::ConstTensor projectionWeights;
2800     armnn::ConstTensor projectionBias;
2801
2802     if (qLstmDescriptor.m_ProjectionEnabled)
2803     {
2804         projectionWeights = ToConstTensor(flatBufferInputParams->projectionWeights());
2805         projectionBias = ToConstTensor(flatBufferInputParams->projectionBias());
2806
2807         qLstmInputParams.m_ProjectionWeights = &projectionWeights;
2808         qLstmInputParams.m_ProjectionBias = &projectionBias;
2809     }
2810
2811     // Optional peephole params
2812     armnn::ConstTensor cellToInputWeights;
2813     armnn::ConstTensor cellToForgetWeights;
2814     armnn::ConstTensor cellToOutputWeights;
2815
2816     if (qLstmDescriptor.m_PeepholeEnabled)
2817     {
2818         if (!qLstmDescriptor.m_CifgEnabled)
2819         {
2820             cellToInputWeights = ToConstTensor(flatBufferInputParams->cellToInputWeights());
2821             qLstmInputParams.m_CellToInputWeights = &cellToInputWeights;
2822         }
2823
2824         cellToForgetWeights = ToConstTensor(flatBufferInputParams->cellToForgetWeights());
2825         cellToOutputWeights = ToConstTensor(flatBufferInputParams->cellToOutputWeights());
2826
2827         qLstmInputParams.m_CellToForgetWeights = &cellToForgetWeights;
2828         qLstmInputParams.m_CellToOutputWeights = &cellToOutputWeights;
2829     }
2830
2831     // Optional layer norm params
2832     armnn::ConstTensor inputLayerNormWeights;
2833     armnn::ConstTensor forgetLayerNormWeights;
2834     armnn::ConstTensor cellLayerNormWeights;
2835     armnn::ConstTensor outputLayerNormWeights;
2836
2837     if (qLstmDescriptor.m_LayerNormEnabled)
2838     {
2839         if (!qLstmDescriptor.m_CifgEnabled)
2840         {
2841             inputLayerNormWeights = ToConstTensor(flatBufferInputParams->inputLayerNormWeights());
2842             qLstmInputParams.m_InputLayerNormWeights = &inputLayerNormWeights;
2843         }
2844
2845         forgetLayerNormWeights = ToConstTensor(flatBufferInputParams->forgetLayerNormWeights());
2846         cellLayerNormWeights   = ToConstTensor(flatBufferInputParams->cellLayerNormWeights());
2847         outputLayerNormWeights = ToConstTensor(flatBufferInputParams->outputLayerNormWeights());
2848
2849         qLstmInputParams.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
2850         qLstmInputParams.m_CellLayerNormWeights   = &cellLayerNormWeights;
2851         qLstmInputParams.m_OutputLayerNormWeights = &outputLayerNormWeights;
2852     }
2853
2854     IConnectableLayer* layer = m_Network->AddQLstmLayer(qLstmDescriptor, qLstmInputParams, layerName.c_str());
2855
2856     armnn::TensorInfo outputStateOutInfo = ToTensorInfo(outputs[0]);
2857     layer->GetOutputSlot(0).SetTensorInfo(outputStateOutInfo);
2858
2859     armnn::TensorInfo cellStateOutInfo = ToTensorInfo(outputs[1]);
2860     layer->GetOutputSlot(1).SetTensorInfo(cellStateOutInfo);
2861
2862     armnn::TensorInfo outputInfo = ToTensorInfo(outputs[2]);
2863     layer->GetOutputSlot(2).SetTensorInfo(outputInfo);
2864
2865     RegisterInputSlots(graph, layerIndex, layer);
2866     RegisterOutputSlots(graph, layerIndex, layer);
2867 }
2868
2869 void IDeserializer::DeserializerImpl::ParseQuantizedLstm(GraphPtr graph, unsigned int layerIndex)
2870 {
2871     CHECK_LAYERS(graph, 0, layerIndex);
2872
2873     auto inputs = GetInputs(graph, layerIndex);
2874     CHECK_VALID_SIZE(inputs.size(), 3);
2875
2876     auto outputs = GetOutputs(graph, layerIndex);
2877     CHECK_VALID_SIZE(outputs.size(), 2);
2878
2879     auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_QuantizedLstmLayer();
2880     auto layerName = GetLayerName(graph, layerIndex);
2881     auto flatBufferInputParams = flatBufferLayer->inputParams();
2882
2883     armnn::QuantizedLstmInputParams lstmInputParams;
2884
2885     armnn::ConstTensor inputToInputWeights = ToConstTensor(flatBufferInputParams->inputToInputWeights());
2886     armnn::ConstTensor inputToForgetWeights = ToConstTensor(flatBufferInputParams->inputToForgetWeights());
2887     armnn::ConstTensor inputToCellWeights = ToConstTensor(flatBufferInputParams->inputToCellWeights());
2888     armnn::ConstTensor inputToOutputWeights = ToConstTensor(flatBufferInputParams->inputToOutputWeights());
2889     armnn::ConstTensor recurrentToInputWeights = ToConstTensor(flatBufferInputParams->recurrentToInputWeights());
2890     armnn::ConstTensor recurrentToForgetWeights = ToConstTensor(flatBufferInputParams->recurrentToForgetWeights());
2891     armnn::ConstTensor recurrentToCellWeights = ToConstTensor(flatBufferInputParams->recurrentToCellWeights());
2892     armnn::ConstTensor recurrentToOutputWeights = ToConstTensor(flatBufferInputParams->recurrentToOutputWeights());
2893     armnn::ConstTensor inputGateBias = ToConstTensor(flatBufferInputParams->inputGateBias());
2894     armnn::ConstTensor forgetGateBias = ToConstTensor(flatBufferInputParams->forgetGateBias());
2895     armnn::ConstTensor cellBias = ToConstTensor(flatBufferInputParams->cellBias());
2896     armnn::ConstTensor outputGateBias = ToConstTensor(flatBufferInputParams->outputGateBias());
2897
2898     lstmInputParams.m_InputToInputWeights = &inputToInputWeights;
2899     lstmInputParams.m_InputToForgetWeights = &inputToForgetWeights;
2900     lstmInputParams.m_InputToCellWeights = &inputToCellWeights;
2901     lstmInputParams.m_InputToOutputWeights = &inputToOutputWeights;
2902     lstmInputParams.m_RecurrentToInputWeights = &recurrentToInputWeights;
2903     lstmInputParams.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2904     lstmInputParams.m_RecurrentToCellWeights = &recurrentToCellWeights;
2905     lstmInputParams.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2906     lstmInputParams.m_InputGateBias = &inputGateBias;
2907     lstmInputParams.m_ForgetGateBias = &forgetGateBias;
2908     lstmInputParams.m_CellBias = &cellBias;
2909     lstmInputParams.m_OutputGateBias = &outputGateBias;
2910
2911     IConnectableLayer* layer = m_Network->AddQuantizedLstmLayer(lstmInputParams, layerName.c_str());
2912
2913     armnn::TensorInfo outputTensorInfo1 = ToTensorInfo(outputs[0]);
2914     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo1);
2915
2916     armnn::TensorInfo outputTensorInfo2 = ToTensorInfo(outputs[1]);
2917     layer->GetOutputSlot(1).SetTensorInfo(outputTensorInfo2);
2918
2919     RegisterInputSlots(graph, layerIndex, layer);
2920     RegisterOutputSlots(graph, layerIndex, layer);
2921 }
2922
2923 void IDeserializer::DeserializerImpl::ParseDequantize(GraphPtr graph, unsigned int layerIndex)
2924 {
2925     CHECK_LAYERS(graph, 0, layerIndex);
2926
2927     TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2928     CHECK_VALID_SIZE(inputs.size(), 1);
2929
2930     TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2931     CHECK_VALID_SIZE(outputs.size(), 1);
2932
2933     const std::string layerName = GetLayerName(graph, layerIndex);
2934     IConnectableLayer* layer = m_Network->AddDequantizeLayer(layerName.c_str());
2935
2936     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2937     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2938
2939     RegisterInputSlots(graph, layerIndex, layer);
2940     RegisterOutputSlots(graph, layerIndex, layer);
2941 }
2942
2943 void IDeserializer::DeserializerImpl::ParseMerge(GraphPtr graph, unsigned int layerIndex)
2944 {
2945     CHECK_LAYERS(graph, 0, layerIndex);
2946
2947     TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2948     CHECK_VALID_SIZE(inputs.size(), 2);
2949
2950     TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2951     CHECK_VALID_SIZE(outputs.size(), 1);
2952
2953     const std::string layerName = GetLayerName(graph, layerIndex);
2954     IConnectableLayer* layer = m_Network->AddMergeLayer(layerName.c_str());
2955
2956     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2957     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2958
2959     RegisterInputSlots(graph, layerIndex, layer);
2960     RegisterOutputSlots(graph, layerIndex, layer);
2961 }
2962
2963 void IDeserializer::DeserializerImpl::ParseSwitch(GraphPtr graph, unsigned int layerIndex)
2964 {
2965     CHECK_LAYERS(graph, 0, layerIndex);
2966     auto inputs = GetInputs(graph, layerIndex);
2967     CHECK_LOCATION();
2968     CHECK_VALID_SIZE(inputs.size(), 2);
2969
2970     auto outputs = GetOutputs(graph, layerIndex);
2971     CHECK_VALID_SIZE(outputs.size(), 2);
2972
2973     auto layerName = GetLayerName(graph, layerIndex);
2974     IConnectableLayer* layer = m_Network->AddSwitchLayer(layerName.c_str());
2975
2976     armnn::TensorInfo output0TensorInfo = ToTensorInfo(outputs[0]);
2977     layer->GetOutputSlot(0).SetTensorInfo(output0TensorInfo);
2978
2979     armnn::TensorInfo output1TensorInfo = ToTensorInfo(outputs[1]);
2980     layer->GetOutputSlot(1).SetTensorInfo(output1TensorInfo);
2981
2982     RegisterInputSlots(graph, layerIndex, layer);
2983     RegisterOutputSlots(graph, layerIndex, layer);
2984 }
2985
2986 void IDeserializer::DeserializerImpl::ParsePrelu(GraphPtr graph, unsigned int layerIndex)
2987 {
2988     CHECK_LAYERS(graph, 0, layerIndex);
2989     auto inputs = GetInputs(graph, layerIndex);
2990     CHECK_LOCATION();
2991     CHECK_VALID_SIZE(inputs.size(), 2);
2992
2993     auto outputs = GetOutputs(graph, layerIndex);
2994     CHECK_VALID_SIZE(outputs.size(), 1);
2995
2996     auto layerName = GetLayerName(graph, layerIndex);
2997     IConnectableLayer* layer = m_Network->AddPreluLayer(layerName.c_str());
2998
2999     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
3000     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
3001
3002     RegisterInputSlots(graph, layerIndex, layer);
3003     RegisterOutputSlots(graph, layerIndex, layer);
3004 }
3005
3006 void IDeserializer::DeserializerImpl::ParseTranspose(GraphPtr graph, unsigned int layerIndex)
3007 {
3008     CHECK_LAYERS(graph, 0, layerIndex);
3009
3010     auto dimsMapping = graph->layers()->Get(layerIndex)->layer_as_TransposeLayer()->descriptor()->dimMappings();
3011
3012     auto inputs = GetInputs(graph, layerIndex);
3013     CHECK_VALID_SIZE(inputs.size(), 1);
3014
3015     auto outputs = GetOutputs(graph, layerIndex);
3016     CHECK_VALID_SIZE(outputs.size(), 1);
3017     auto outputInfo = ToTensorInfo(outputs[0]);
3018
3019     auto layerName = GetLayerName(graph, layerIndex);
3020     const armnn::TransposeDescriptor descriptor(armnn::PermutationVector(dimsMapping->data(), dimsMapping->Length()));
3021
3022     IConnectableLayer* layer = m_Network->AddTransposeLayer(descriptor, layerName.c_str());
3023     layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
3024
3025     RegisterInputSlots(graph, layerIndex, layer);
3026     RegisterOutputSlots(graph, layerIndex, layer);
3027 }
3028
3029 void IDeserializer::DeserializerImpl::ParseTransposeConvolution2d(GraphPtr graph, unsigned int layerIndex)
3030 {
3031     CHECK_LAYERS(graph, 0, layerIndex);
3032
3033     auto inputs = GetInputs(graph, layerIndex);
3034     CHECK_VALID_SIZE(inputs.size(), 1);
3035
3036     auto outputs = GetOutputs(graph, layerIndex);
3037     CHECK_VALID_SIZE(outputs.size(), 1);
3038
3039     auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_TransposeConvolution2dLayer();
3040     auto layerName = GetLayerName(graph, layerIndex);
3041     auto serializerDescriptor = serializerLayer->descriptor();
3042
3043     armnn::TransposeConvolution2dDescriptor descriptor;
3044     descriptor.m_PadLeft     = serializerDescriptor->padLeft();
3045     descriptor.m_PadRight    = serializerDescriptor->padRight();
3046     descriptor.m_PadTop      = serializerDescriptor->padTop();
3047     descriptor.m_PadBottom   = serializerDescriptor->padBottom();
3048     descriptor.m_StrideX     = serializerDescriptor->strideX();
3049     descriptor.m_StrideY     = serializerDescriptor->strideY();;
3050     descriptor.m_BiasEnabled = serializerDescriptor->biasEnabled();;
3051     descriptor.m_DataLayout  = ToDataLayout(serializerDescriptor->dataLayout());
3052
3053     // weights & biases
3054     armnn::ConstTensor weights = ToConstTensor(serializerLayer->weights());
3055     armnn::Optional<armnn::ConstTensor> optionalBiases;
3056     if (descriptor.m_BiasEnabled)
3057     {
3058         armnn::ConstTensor biases = ToConstTensor(serializerLayer->biases());
3059         optionalBiases = armnn::MakeOptional<armnn::ConstTensor>(biases);
3060     }
3061
3062     IConnectableLayer* layer = m_Network->AddTransposeConvolution2dLayer(descriptor,
3063                                                                          weights,
3064                                                                          optionalBiases,
3065                                                                          layerName.c_str());
3066
3067     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
3068     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
3069
3070     RegisterInputSlots(graph, layerIndex, layer);
3071     RegisterOutputSlots(graph, layerIndex, layer);
3072 }
3073
3074 void IDeserializer::DeserializerImpl::ParseStack(GraphPtr graph, unsigned int layerIndex)
3075 {
3076     CHECK_LAYERS(graph, 0, layerIndex);
3077     auto inputs = GetInputs(graph, layerIndex);
3078
3079     auto outputs = GetOutputs(graph, layerIndex);
3080     CHECK_VALID_SIZE(outputs.size(), 1);
3081
3082     auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_StackLayer()->descriptor();
3083     unsigned int axis = flatBufferDescriptor->axis();
3084     unsigned int numInputs = flatBufferDescriptor->numInputs();
3085     CHECK_VALID_SIZE(inputs.size(), numInputs);
3086
3087     auto flatBufferInputShape = flatBufferDescriptor->inputShape();
3088     std::vector<uint32_t> vectorInputShape(flatBufferInputShape->begin(),
3089                                            flatBufferInputShape->begin() + flatBufferInputShape->size());
3090
3091     TensorShape inputShape(static_cast<unsigned int>(vectorInputShape.size()), vectorInputShape.data());
3092     armnn::StackDescriptor descriptor(axis, numInputs, inputShape);
3093
3094     for (unsigned int i=0; i<inputs.size(); ++i)
3095     {
3096         armnn::TensorShape inputShape = ToTensorInfo(inputs[i]).GetShape();
3097         if (descriptor.m_InputShape != inputShape)
3098         {
3099             std::stringstream ss;
3100             ss << "Shape of input  "
3101                << i
3102                << " "
3103                << inputShape
3104                << " does not equal defined input shape "
3105                << descriptor.m_InputShape
3106                << ": "
3107                << CHECK_LOCATION().AsString();
3108             throw ParseException(ss.str());
3109         }
3110     }
3111
3112     auto layerName = GetLayerName(graph, layerIndex);
3113     IConnectableLayer* layer = m_Network->AddStackLayer(descriptor, layerName.c_str());
3114
3115     armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
3116     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
3117
3118     RegisterInputSlots(graph, layerIndex, layer);
3119     RegisterOutputSlots(graph, layerIndex, layer);
3120 }
3121
3122 void IDeserializer::DeserializerImpl::ParseStandIn(GraphPtr graph, unsigned int layerIndex)
3123 {
3124     CHECK_LAYERS(graph, 0, layerIndex);
3125
3126     auto inputs  = GetInputs(graph, layerIndex);
3127     auto outputs = GetOutputs(graph, layerIndex);
3128
3129     auto fbLayer      = graph->layers()->Get(layerIndex)->layer_as_StandInLayer();
3130     auto fbDescriptor = fbLayer->descriptor();
3131
3132     armnn::StandInDescriptor descriptor;
3133     descriptor.m_NumInputs  = fbDescriptor->numInputs();
3134     descriptor.m_NumOutputs = fbDescriptor->numOutputs();
3135
3136     CHECK_VALID_SIZE(inputs.size(),  descriptor.m_NumInputs);
3137     CHECK_VALID_SIZE(outputs.size(), descriptor.m_NumOutputs);
3138
3139     const std::string layerName     = GetLayerName(graph, layerIndex);
3140     armnn::IConnectableLayer* layer = m_Network->AddStandInLayer(descriptor, layerName.c_str());
3141
3142     for (unsigned int i = 0u; i < descriptor.m_NumOutputs; ++i)
3143     {
3144         armnn::TensorInfo outputInfo = ToTensorInfo(outputs[i]);
3145         layer->GetOutputSlot(i).SetTensorInfo(outputInfo);
3146     }
3147
3148     RegisterInputSlots(graph, layerIndex, layer);
3149     RegisterOutputSlots(graph, layerIndex, layer);
3150 }
3151
3152 } // namespace armnnDeserializer