ArmNN
 21.11
Deserializer.cpp
Go to the documentation of this file.
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>
13 
14 #include <armnnUtils/Permute.hpp>
15 #include <armnnUtils/Transpose.hpp>
16 #include <armnn/utility/Assert.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 
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_CastLayer] = &DeserializerImpl::ParseCast;
219  m_ParserFunctions[Layer_ChannelShuffleLayer] = &DeserializerImpl::ParseChannelShuffle;
220  m_ParserFunctions[Layer_ComparisonLayer] = &DeserializerImpl::ParseComparison;
221  m_ParserFunctions[Layer_ConcatLayer] = &DeserializerImpl::ParseConcat;
222  m_ParserFunctions[Layer_ConstantLayer] = &DeserializerImpl::ParseConstant;
223  m_ParserFunctions[Layer_Convolution2dLayer] = &DeserializerImpl::ParseConvolution2d;
224  m_ParserFunctions[Layer_Convolution3dLayer] = &DeserializerImpl::ParseConvolution3d;
225  m_ParserFunctions[Layer_DepthToSpaceLayer] = &DeserializerImpl::ParseDepthToSpace;
226  m_ParserFunctions[Layer_DepthwiseConvolution2dLayer] = &DeserializerImpl::ParseDepthwiseConvolution2d;
227  m_ParserFunctions[Layer_DequantizeLayer] = &DeserializerImpl::ParseDequantize;
228  m_ParserFunctions[Layer_DetectionPostProcessLayer] = &DeserializerImpl::ParseDetectionPostProcess;
229  m_ParserFunctions[Layer_DivisionLayer] = &DeserializerImpl::ParseDivision;
230  m_ParserFunctions[Layer_ElementwiseUnaryLayer] = &DeserializerImpl::ParseElementwiseUnary;
231  m_ParserFunctions[Layer_EqualLayer] = &DeserializerImpl::ParseEqual;
232  m_ParserFunctions[Layer_FullyConnectedLayer] = &DeserializerImpl::ParseFullyConnected;
233  m_ParserFunctions[Layer_FillLayer] = &DeserializerImpl::ParseFill;
234  m_ParserFunctions[Layer_FloorLayer] = &DeserializerImpl::ParseFloor;
235  m_ParserFunctions[Layer_GatherLayer] = &DeserializerImpl::ParseGather;
236  m_ParserFunctions[Layer_GreaterLayer] = &DeserializerImpl::ParseGreater;
237  m_ParserFunctions[Layer_InstanceNormalizationLayer] = &DeserializerImpl::ParseInstanceNormalization;
238  m_ParserFunctions[Layer_L2NormalizationLayer] = &DeserializerImpl::ParseL2Normalization;
239  m_ParserFunctions[Layer_LogicalBinaryLayer] = &DeserializerImpl::ParseLogicalBinary;
240  m_ParserFunctions[Layer_LogSoftmaxLayer] = &DeserializerImpl::ParseLogSoftmax;
241  m_ParserFunctions[Layer_LstmLayer] = &DeserializerImpl::ParseLstm;
242  m_ParserFunctions[Layer_MaximumLayer] = &DeserializerImpl::ParseMaximum;
243  m_ParserFunctions[Layer_MeanLayer] = &DeserializerImpl::ParseMean;
244  m_ParserFunctions[Layer_MinimumLayer] = &DeserializerImpl::ParseMinimum;
245  m_ParserFunctions[Layer_MergeLayer] = &DeserializerImpl::ParseMerge;
246  m_ParserFunctions[Layer_MergerLayer] = &DeserializerImpl::ParseConcat;
247  m_ParserFunctions[Layer_MultiplicationLayer] = &DeserializerImpl::ParseMultiplication;
248  m_ParserFunctions[Layer_NormalizationLayer] = &DeserializerImpl::ParseNormalization;
249  m_ParserFunctions[Layer_PadLayer] = &DeserializerImpl::ParsePad;
250  m_ParserFunctions[Layer_PermuteLayer] = &DeserializerImpl::ParsePermute;
251  m_ParserFunctions[Layer_Pooling2dLayer] = &DeserializerImpl::ParsePooling2d;
252  m_ParserFunctions[Layer_PreluLayer] = &DeserializerImpl::ParsePrelu;
253  m_ParserFunctions[Layer_QLstmLayer] = &DeserializerImpl::ParseQLstm;
254  m_ParserFunctions[Layer_QuantizeLayer] = &DeserializerImpl::ParseQuantize;
255  m_ParserFunctions[Layer_QuantizedLstmLayer] = &DeserializerImpl::ParseQuantizedLstm;
256  m_ParserFunctions[Layer_RankLayer] = &DeserializerImpl::ParseRank;
257  m_ParserFunctions[Layer_ReduceLayer] = &DeserializerImpl::ParseReduce;
258  m_ParserFunctions[Layer_ReshapeLayer] = &DeserializerImpl::ParseReshape;
259  m_ParserFunctions[Layer_ResizeBilinearLayer] = &DeserializerImpl::ParseResizeBilinear;
260  m_ParserFunctions[Layer_ResizeLayer] = &DeserializerImpl::ParseResize;
261  m_ParserFunctions[Layer_RsqrtLayer] = &DeserializerImpl::ParseRsqrt;
262  m_ParserFunctions[Layer_ShapeLayer] = &DeserializerImpl::ParseShape;
263  m_ParserFunctions[Layer_SliceLayer] = &DeserializerImpl::ParseSlice;
264  m_ParserFunctions[Layer_SoftmaxLayer] = &DeserializerImpl::ParseSoftmax;
265  m_ParserFunctions[Layer_SpaceToBatchNdLayer] = &DeserializerImpl::ParseSpaceToBatchNd;
266  m_ParserFunctions[Layer_SpaceToDepthLayer] = &DeserializerImpl::ParseSpaceToDepth;
267  m_ParserFunctions[Layer_SplitterLayer] = &DeserializerImpl::ParseSplitter;
268  m_ParserFunctions[Layer_StackLayer] = &DeserializerImpl::ParseStack;
269  m_ParserFunctions[Layer_StandInLayer] = &DeserializerImpl::ParseStandIn;
270  m_ParserFunctions[Layer_StridedSliceLayer] = &DeserializerImpl::ParseStridedSlice;
271  m_ParserFunctions[Layer_SubtractionLayer] = &DeserializerImpl::ParseSubtraction;
272  m_ParserFunctions[Layer_SwitchLayer] = &DeserializerImpl::ParseSwitch;
273  m_ParserFunctions[Layer_TransposeConvolution2dLayer] = &DeserializerImpl::ParseTransposeConvolution2d;
274  m_ParserFunctions[Layer_TransposeLayer] = &DeserializerImpl::ParseTranspose;
275  m_ParserFunctions[Layer_UnidirectionalSequenceLstmLayer] = &DeserializerImpl::ParseUnidirectionalSequenceLstm;
276 }
277 
279 {
280  auto layerType = graphPtr->layers()->Get(layerIndex)->layer_type();
281 
282  switch(layerType)
283  {
285  return graphPtr->layers()->Get(layerIndex)->layer_as_AbsLayer()->base();
287  return graphPtr->layers()->Get(layerIndex)->layer_as_ActivationLayer()->base();
289  return graphPtr->layers()->Get(layerIndex)->layer_as_AdditionLayer()->base();
291  return graphPtr->layers()->Get(layerIndex)->layer_as_ArgMinMaxLayer()->base();
293  return graphPtr->layers()->Get(layerIndex)->layer_as_BatchToSpaceNdLayer()->base();
295  return graphPtr->layers()->Get(layerIndex)->layer_as_BatchNormalizationLayer()->base();
297  return graphPtr->layers()->Get(layerIndex)->layer_as_CastLayer()->base();
299  return graphPtr->layers()->Get(layerIndex)->layer_as_ChannelShuffleLayer()->base();
301  return graphPtr->layers()->Get(layerIndex)->layer_as_ComparisonLayer()->base();
303  return graphPtr->layers()->Get(layerIndex)->layer_as_ConcatLayer()->base();
305  return graphPtr->layers()->Get(layerIndex)->layer_as_ConstantLayer()->base();
307  return graphPtr->layers()->Get(layerIndex)->layer_as_Convolution2dLayer()->base();
309  return graphPtr->layers()->Get(layerIndex)->layer_as_Convolution3dLayer()->base();
311  return graphPtr->layers()->Get(layerIndex)->layer_as_DepthToSpaceLayer()->base();
313  return graphPtr->layers()->Get(layerIndex)->layer_as_DepthwiseConvolution2dLayer()->base();
315  return graphPtr->layers()->Get(layerIndex)->layer_as_DequantizeLayer()->base();
317  return graphPtr->layers()->Get(layerIndex)->layer_as_DetectionPostProcessLayer()->base();
319  return graphPtr->layers()->Get(layerIndex)->layer_as_DivisionLayer()->base();
321  return graphPtr->layers()->Get(layerIndex)->layer_as_EqualLayer()->base();
323  return graphPtr->layers()->Get(layerIndex)->layer_as_ElementwiseUnaryLayer()->base();
325  return graphPtr->layers()->Get(layerIndex)->layer_as_FullyConnectedLayer()->base();
327  return graphPtr->layers()->Get(layerIndex)->layer_as_FillLayer()->base();
329  return graphPtr->layers()->Get(layerIndex)->layer_as_FloorLayer()->base();
331  return graphPtr->layers()->Get(layerIndex)->layer_as_GatherLayer()->base();
333  return graphPtr->layers()->Get(layerIndex)->layer_as_GreaterLayer()->base();
335  return graphPtr->layers()->Get(layerIndex)->layer_as_InputLayer()->base()->base();
337  return graphPtr->layers()->Get(layerIndex)->layer_as_InstanceNormalizationLayer()->base();
339  return graphPtr->layers()->Get(layerIndex)->layer_as_L2NormalizationLayer()->base();
341  return graphPtr->layers()->Get(layerIndex)->layer_as_LogicalBinaryLayer()->base();
343  return graphPtr->layers()->Get(layerIndex)->layer_as_LogSoftmaxLayer()->base();
345  return graphPtr->layers()->Get(layerIndex)->layer_as_LstmLayer()->base();
347  return graphPtr->layers()->Get(layerIndex)->layer_as_MeanLayer()->base();
349  return graphPtr->layers()->Get(layerIndex)->layer_as_MinimumLayer()->base();
351  return graphPtr->layers()->Get(layerIndex)->layer_as_MaximumLayer()->base();
353  return graphPtr->layers()->Get(layerIndex)->layer_as_MergeLayer()->base();
355  return graphPtr->layers()->Get(layerIndex)->layer_as_MergerLayer()->base();
357  return graphPtr->layers()->Get(layerIndex)->layer_as_MultiplicationLayer()->base();
359  return graphPtr->layers()->Get(layerIndex)->layer_as_NormalizationLayer()->base();
361  return graphPtr->layers()->Get(layerIndex)->layer_as_OutputLayer()->base()->base();
363  return graphPtr->layers()->Get(layerIndex)->layer_as_PadLayer()->base();
365  return graphPtr->layers()->Get(layerIndex)->layer_as_PermuteLayer()->base();
367  return graphPtr->layers()->Get(layerIndex)->layer_as_Pooling2dLayer()->base();
369  return graphPtr->layers()->Get(layerIndex)->layer_as_PreluLayer()->base();
371  return graphPtr->layers()->Get(layerIndex)->layer_as_QLstmLayer()->base();
373  return graphPtr->layers()->Get(layerIndex)->layer_as_QuantizeLayer()->base();
375  return graphPtr->layers()->Get(layerIndex)->layer_as_QuantizedLstmLayer()->base();
377  return graphPtr->layers()->Get(layerIndex)->layer_as_RankLayer()->base();
379  return graphPtr->layers()->Get(layerIndex)->layer_as_ReduceLayer()->base();
381  return graphPtr->layers()->Get(layerIndex)->layer_as_ReshapeLayer()->base();
383  return graphPtr->layers()->Get(layerIndex)->layer_as_ResizeBilinearLayer()->base();
385  return graphPtr->layers()->Get(layerIndex)->layer_as_ResizeLayer()->base();
387  return graphPtr->layers()->Get(layerIndex)->layer_as_RsqrtLayer()->base();
389  return graphPtr->layers()->Get(layerIndex)->layer_as_ShapeLayer()->base();
391  return graphPtr->layers()->Get(layerIndex)->layer_as_SliceLayer()->base();
393  return graphPtr->layers()->Get(layerIndex)->layer_as_SoftmaxLayer()->base();
395  return graphPtr->layers()->Get(layerIndex)->layer_as_SpaceToBatchNdLayer()->base();
397  return graphPtr->layers()->Get(layerIndex)->layer_as_SpaceToDepthLayer()->base();
399  return graphPtr->layers()->Get(layerIndex)->layer_as_SplitterLayer()->base();
401  return graphPtr->layers()->Get(layerIndex)->layer_as_StackLayer()->base();
403  return graphPtr->layers()->Get(layerIndex)->layer_as_StandInLayer()->base();
405  return graphPtr->layers()->Get(layerIndex)->layer_as_StridedSliceLayer()->base();
407  return graphPtr->layers()->Get(layerIndex)->layer_as_SubtractionLayer()->base();
409  return graphPtr->layers()->Get(layerIndex)->layer_as_SwitchLayer()->base();
411  return graphPtr->layers()->Get(layerIndex)->layer_as_TransposeConvolution2dLayer()->base();
413  return graphPtr->layers()->Get(layerIndex)->layer_as_TransposeLayer()->base();
415  return graphPtr->layers()->Get(layerIndex)->layer_as_UnidirectionalSequenceLstmLayer()->base();
416  case Layer::Layer_NONE:
417  default:
418  throw ParseException(fmt::format("Layer type {} not recognized", layerType));
419  }
420 }
421 
422 std::string IDeserializer::DeserializerImpl::GetLayerName(const GraphPtr& graph, unsigned int index)
423 {
424  auto layer = GetBaseLayer(graph, index);
425  assert(layer);
426  return layer->layerName()->str();
427 }
428 
429 int32_t IDeserializer::DeserializerImpl::GetBindingLayerInfo(const GraphPtr& graphPtr, unsigned int layerIndex)
430 {
431  auto layerType = graphPtr->layers()->Get(layerIndex)->layer_type();
432 
433  if (layerType == Layer::Layer_InputLayer)
434  {
435  return graphPtr->layers()->Get(layerIndex)->layer_as_InputLayer()->base()->layerBindingId();
436  }
437  else if ( layerType == Layer::Layer_OutputLayer )
438  {
439  return graphPtr->layers()->Get(layerIndex)->layer_as_OutputLayer()->base()->layerBindingId();
440  }
441  return 0;
442 }
443 
445 {
446  switch (dataLayout)
447  {
455  default:
457  }
458 }
459 
461 {
462  switch (function)
463  {
486  default:
488  }
489 }
490 
492 {
493  switch (function)
494  {
498  default:
500  }
501 }
502 
504 {
505  switch (operation)
506  {
518  default:
520  }
521 }
522 
524 {
525  switch (operation)
526  {
537  default:
539  }
540 }
541 
543 {
544  switch (operation)
545  {
550  default:
551  throw armnn::InvalidArgumentException("Logical Binary operation unknown");
552  }
553 }
554 
556 {
557  switch (operation)
558  {
575  default:
576  throw armnn::InvalidArgumentException("Unary operation unknown");
577  }
578 }
579 
581 {
582  switch (paddingMode)
583  {
588  default:
590  }
591 }
592 
594 {
595  switch (method)
596  {
601  default:
603  }
604 }
605 
607 {
608  armnn::DataType type;
609  CHECK_TENSOR_PTR(tensorPtr);
610 
611  switch (tensorPtr->dataType())
612  {
613  case DataType_QAsymmS8:
615  break;
616  case DataType_QSymmS8:
618  break;
620  case DataType_QAsymmU8:
622  break;
623  case DataType_QSymmS16:
626  break;
627  case DataType_Signed32:
629  break;
630  case DataType_Signed64:
632  break;
633  case DataType_Float32:
635  break;
636  case DataType_Float16:
638  break;
639  case DataType_Boolean:
641  break;
642  default:
643  {
644  CheckLocation location = CHECK_LOCATION();
645  throw ParseException(fmt::format("Unsupported data type {0} = {1}. {2}",
646  tensorPtr->dataType(),
647  EnumNameDataType(tensorPtr->dataType()),
648  location.AsString()));
649  }
650  }
651 
652  float quantizationScale = tensorPtr->quantizationScale();
653  int32_t quantizationOffset = tensorPtr->quantizationOffset();
654 
655  if (tensorPtr->dimensionality() == static_cast<unsigned int>(Dimensionality::Scalar))
656  {
658  type,
659  quantizationScale,
660  quantizationOffset);
661  }
662  else if (tensorPtr->dimensionality() == static_cast<unsigned int>(Dimensionality::NotSpecified))
663  {
664  armnn::TensorInfo result(TensorShape{Dimensionality::NotSpecified},
665  type,
666  quantizationScale,
667  quantizationOffset);
668  return result;
669  }
670 
671  auto dimensions = tensorPtr->dimensions();
672  unsigned int size = dimensions->size();
673  std::vector<unsigned int> outputDims(dimensions->begin(), dimensions->begin() + size);
674  bool dimensionsSpecificity[armnn::MaxNumOfTensorDimensions];
675  std::fill_n(dimensionsSpecificity, armnn::MaxNumOfTensorDimensions, true);
676  // For backwards compatibility check if the dimensionSpecificity vector is present first.
677  // The default is to have dimensionSpecificity set to all true's anyway.
678  if (tensorPtr->dimensionSpecificity() != nullptr)
679  {
680  auto dimensionSpecificity = tensorPtr->dimensionSpecificity();
681  size = dimensionSpecificity->size();
682  for (unsigned int i = 0; i < size; ++i)
683  {
684  dimensionsSpecificity[i] = dimensionSpecificity->Get(i);
685  }
686  }
687  // Construct a TensorShape
688  TensorShape shape(size, outputDims.data(), dimensionsSpecificity);
689 
690  auto quantizationScales = tensorPtr->quantizationScales();
691  if (quantizationScales)
692  {
693  unsigned int quantizationScalesSize = quantizationScales->size();
694  std::vector<float> scales(quantizationScales->begin(), quantizationScales->begin() + quantizationScalesSize);
695  unsigned int quantizationDim = tensorPtr->quantizationDim();
696  armnn::TensorInfo result(shape,
697  type,
698  scales,
699  quantizationDim);
700  return result;
701  }
702 
703  // two statements (on purpose) for easier debugging:
704  armnn::TensorInfo result(shape,
705  type,
706  quantizationScale,
707  quantizationOffset);
708 
709  return result;
710 }
711 
713 {
714  CHECK_CONST_TENSOR_PTR(constTensorPtr);
715  armnn::TensorInfo tensorInfo = ToTensorInfo(constTensorPtr->info());
716  tensorInfo.SetConstant();
717 
718  switch (constTensorPtr->data_type())
719  {
721  {
722  auto byteData = constTensorPtr->data_as_ByteData()->data();
723  CHECK_CONST_TENSOR_SIZE(byteData->size(), tensorInfo.GetNumElements());
724  return armnn::ConstTensor(tensorInfo, byteData->data());
725  }
727  {
728  auto shortData = constTensorPtr->data_as_ShortData()->data();
729  CHECK_CONST_TENSOR_SIZE(shortData->size(), tensorInfo.GetNumElements());
730  return armnn::ConstTensor(tensorInfo, shortData->data());
731  }
733  {
734  auto intData = constTensorPtr->data_as_IntData()->data();
735  CHECK_CONST_TENSOR_SIZE(intData->size(), tensorInfo.GetNumElements());
736  return armnn::ConstTensor(tensorInfo, intData->data());
737  }
739  {
740  auto longData = constTensorPtr->data_as_LongData()->data();
741  CHECK_CONST_TENSOR_SIZE(longData->size(), tensorInfo.GetNumElements());
742  return armnn::ConstTensor(tensorInfo, longData->data());
743  }
744  default:
745  {
746  CheckLocation location = CHECK_LOCATION();
747  throw ParseException(fmt::format("Unsupported data type {0} = {1}. {2}",
748  constTensorPtr->data_type(),
749  EnumNameConstTensorData(constTensorPtr->data_type()),
750  location.AsString()));
751  }
752  }
753 }
754 
756 {
757  CHECK_LAYERS(graphPtr, 0, layerIndex);
758  auto layer = GetBaseLayer(graphPtr, layerIndex);
759  const auto& numInputs = layer->inputSlots()->size();
760 
761  TensorRawPtrVector result(numInputs);
762 
763  for (unsigned int i=0; i<numInputs; ++i)
764  {
765  auto inputId = CHECKED_NON_NEGATIVE(static_cast<int32_t>
766  (layer->inputSlots()->Get(i)->connection()->sourceLayerIndex()));
767  result[i] = GetBaseLayer(graphPtr, inputId)->outputSlots()->Get(0)->tensorInfo();
768  }
769  return result;
770 }
771 
773 {
774  CHECK_LAYERS(graphPtr, 0, layerIndex);
775  auto layer = GetBaseLayer(graphPtr, layerIndex);
776  const auto& numOutputs = layer->outputSlots()->size();
777 
778  TensorRawPtrVector result(numOutputs);
779 
780  for (unsigned int i=0; i<numOutputs; ++i)
781  {
782  result[i] = layer->outputSlots()->Get(i)->tensorInfo();
783  }
784  return result;
785 }
786 
787 void IDeserializer::DeserializerImpl::ParseUnsupportedLayer(GraphPtr graph, unsigned int layerIndex)
788 {
789  CHECK_LAYERS(graph, 0, layerIndex);
790  const auto layerName = GetBaseLayer(graph, layerIndex)->layerName()->c_str();
791  throw ParseException(fmt::format("Layer not supported. layerIndex: {0} "
792  "layerName: {1} / {2}",
793  layerIndex,
794  layerName,
795  CHECK_LOCATION().AsString()));
796 }
797 
798 void IDeserializer::DeserializerImpl::ResetParser()
799 {
800  m_Network = armnn::INetworkPtr(nullptr, nullptr);
801  m_InputBindings.clear();
802  m_OutputBindings.clear();
803 }
804 
805 
807 {
808  ResetParser();
809  GraphPtr graph = LoadGraphFromBinary(binaryContent.data(), binaryContent.size());
810  return CreateNetworkFromGraph(graph);
811 }
812 
814 {
815  ResetParser();
816  std::vector<uint8_t> content((std::istreambuf_iterator<char>(binaryContent)), std::istreambuf_iterator<char>());
817  GraphPtr graph = LoadGraphFromBinary(content.data(), content.size());
818  return CreateNetworkFromGraph(graph);
819 }
820 
821 GraphPtr IDeserializer::DeserializerImpl::LoadGraphFromBinary(const uint8_t* binaryContent, size_t len)
822 {
823  if (binaryContent == nullptr)
824  {
825  throw InvalidArgumentException(fmt::format("Invalid (null) binary content {}",
826  CHECK_LOCATION().AsString()));
827  }
828  flatbuffers::Verifier verifier(binaryContent, len);
829  if (verifier.VerifyBuffer<SerializedGraph>() == false)
830  {
831  throw ParseException(fmt::format("Buffer doesn't conform to the expected Armnn "
832  "flatbuffers format. size:{0} {1}",
833  len,
834  CHECK_LOCATION().AsString()));
835  }
836  return GetSerializedGraph(binaryContent);
837 }
838 
839 INetworkPtr IDeserializer::DeserializerImpl::CreateNetworkFromGraph(GraphPtr graph)
840 {
841  m_Network = INetwork::Create();
842  ARMNN_ASSERT(graph != nullptr);
843  unsigned int layerIndex = 0;
844  for (AnyLayer const* layer : *graph->layers())
845  {
846  if (layer->layer_type() != Layer_InputLayer &&
847  layer->layer_type() != Layer_OutputLayer)
848  {
849  // lookup and call the parser function
850  auto& parserFunction = m_ParserFunctions[layer->layer_type()];
851  (this->*parserFunction)(graph, layerIndex);
852  }
853  ++layerIndex;
854  }
855 
856  SetupInputLayers(graph);
857  SetupOutputLayers(graph);
858 
859  // establish the connections from the layer outputs to the inputs of the subsequent layers
860  for (auto&& graphIt : m_GraphConnections)
861  {
862  Connections& connections = graphIt.second;
863  for (auto&& outputIt : connections.outputSlots)
864  {
865  const unsigned int outputSlotIndex = outputIt.first;
866  IOutputSlot* outputSlot = outputIt.second;
867  if (connections.inputSlots.find(outputSlotIndex) != connections.inputSlots.end())
868  {
869  for (IInputSlot* inputSlot : connections.inputSlots[outputSlotIndex])
870  {
871  outputSlot->Connect(*inputSlot);
872  }
873  }
874  }
875  }
876 
877  return std::move(m_Network);
878 }
879 
881  const std::string& name) const
882 {
883  IgnoreUnused(layerIndex);
884  for (auto inputBinding : m_InputBindings)
885  {
886  if (inputBinding.first == name)
887  {
888  return inputBinding.second;
889  }
890  }
891  throw ParseException(fmt::format("No input binding found for layer:{0} / {1}",
892  name,
893  CHECK_LOCATION().AsString()));
894 }
895 
897  const std::string& name) const
898 {
899  IgnoreUnused(layerIndex);
900  for (auto outputBinding : m_OutputBindings)
901  {
902  if (outputBinding.first == name)
903  {
904  return outputBinding.second;
905  }
906  }
907  throw ParseException(fmt::format("No output binding found for layer:{0} / {1}",
908  name,
909  CHECK_LOCATION().AsString()));
910 }
911 
912 unsigned int IDeserializer::DeserializerImpl::GetInputLayerInVector(GraphPtr graph, int targetId)
913 {
914  for (unsigned int i = 0; i < graph->layers()->size(); i++)
915  {
916  auto layer = graph->layers()->Get(i);
917  if (layer->layer_type() == Layer::Layer_InputLayer)
918  {
919  auto layerBindingId = layer->layer_as_InputLayer()->base()->layerBindingId();
920  if (layerBindingId == targetId)
921  {
922  return i;
923  }
924  }
925  }
926  throw ParseException("Input layer with given layerBindingId not found");
927 }
928 
929 unsigned int IDeserializer::DeserializerImpl::GetOutputLayerInVector(GraphPtr graph, int targetId)
930 {
931  for (unsigned int i = 0; i < graph->layers()->size(); i++)
932  {
933  auto layer = graph->layers()->Get(i);
934  if (layer->layer_type() == Layer::Layer_OutputLayer)
935  {
936  auto layerBindingId = layer->layer_as_OutputLayer()->base()->layerBindingId();
937  if (layerBindingId == targetId)
938  {
939  return i;
940  }
941  }
942  }
943  throw ParseException("Output layer with given layerBindingId not found");
944 }
945 
946 unsigned int IDeserializer::DeserializerImpl::GetLayerIndexInVector(GraphPtr graph, unsigned int targetIndex)
947 {
948  for (unsigned int i = 0; i < graph->layers()->size(); i++)
949  {
950  LayerBaseRawPtr layer = GetBaseLayer(graph, i);
951  if (layer->index() == targetIndex)
952  {
953  return i;
954  }
955  }
956  throw ParseException("Layer with given index not found");
957 }
958 
959 IDeserializer::DeserializerImpl::FeatureVersions IDeserializer::DeserializerImpl::GetFeatureVersions(GraphPtr graph)
960 {
961  IDeserializer::DeserializerImpl::FeatureVersions versions;
962 
963  if (graph->featureVersions())
964  {
965  versions.m_BindingIdScheme = graph->featureVersions()->bindingIdsScheme();
966  versions.m_WeightsLayoutScheme = graph->featureVersions()->weightsLayoutScheme();
967  versions.m_ConstTensorsAsInputs = graph->featureVersions()->constantTensorsAsInputs();
968  }
969 
970  return versions;
971 }
972 
973 void IDeserializer::DeserializerImpl::SetupInputLayers(GraphPtr graph)
974 {
975  CHECK_GRAPH(graph, 0);
976  const unsigned int numInputs = graph->inputIds()->size();
977  m_InputBindings.clear();
978  m_InputBindings.reserve(numInputs);
979 
980  for (unsigned int i = 0; i < numInputs; i++)
981  {
982  unsigned int inputLayerIndex = 0xFFFFFFFF;
983  if (GetFeatureVersions(graph).m_BindingIdScheme == 0)
984  {
985  const unsigned int inputId = armnn::numeric_cast<unsigned int>(graph->inputIds()->Get(i));
986  inputLayerIndex = GetLayerIndexInVector(graph, inputId);
987  }
988  else
989  {
990  const int inputId = graph->inputIds()->Get(i);
991  inputLayerIndex = GetInputLayerInVector(graph, inputId);
992  }
993 
994  LayerBaseRawPtr baseLayer = GetBaseLayer(graph, inputLayerIndex);
995 
996  // GetBindingLayerInfo expect the index to be index in the vector not index property on each layer base
997  LayerBindingId bindingId = GetBindingLayerInfo(graph, inputLayerIndex);
998  ARMNN_ASSERT_MSG(baseLayer->layerName()->c_str(), "Input has no name.");
999 
1000  IConnectableLayer* inputLayer =
1001  m_Network->AddInputLayer(bindingId, baseLayer->layerName()->c_str());
1002 
1003  const armnn::TensorInfo& tensorInfo = ToTensorInfo(baseLayer->outputSlots()->Get(0)->tensorInfo());
1004  inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1005  RegisterOutputSlots(graph, inputLayerIndex, inputLayer);
1006 
1007  BindingPointInfo bindingInfo = {bindingId, tensorInfo};
1008  m_InputBindings.push_back(std::make_pair(baseLayer->layerName()->c_str(), bindingInfo));
1009  }
1010 }
1011 
1012 void IDeserializer::DeserializerImpl::SetupOutputLayers(GraphPtr graph)
1013 {
1014  CHECK_GRAPH(graph, 0);
1015  const unsigned int numOutputs = graph->outputIds()->size();
1016  m_OutputBindings.clear();
1017  m_OutputBindings.reserve(numOutputs);
1018 
1019  for (unsigned int i = 0; i < numOutputs; i++)
1020  {
1021  unsigned int outputLayerIndex = 0xFFFFFFFF;
1022  if (GetFeatureVersions(graph).m_BindingIdScheme == 0)
1023  {
1024  const unsigned int outputId = armnn::numeric_cast<unsigned int>(graph->outputIds()->Get(i));
1025  outputLayerIndex = GetLayerIndexInVector(graph, outputId);
1026  }
1027  else
1028  {
1029  const int outputId = graph->outputIds()->Get(i);
1030  outputLayerIndex = GetOutputLayerInVector(graph, outputId);
1031  }
1032 
1033  LayerBaseRawPtr baseLayer = GetBaseLayer(graph, outputLayerIndex);
1034 
1035  // GetBindingLayerInfo expect the index to be index in the vector not index property on each layer base
1036  LayerBindingId bindingId = GetBindingLayerInfo(graph, outputLayerIndex);
1037  ARMNN_ASSERT_MSG(baseLayer->layerName()->c_str(), "Output has no name.");
1038 
1039  IConnectableLayer* outputLayer =
1040  m_Network->AddOutputLayer(bindingId, baseLayer->layerName()->c_str());
1041 
1042  RegisterInputSlots(graph, outputLayerIndex, outputLayer);
1043  unsigned int sourceLayerIndex =
1044  GetLayerIndexInVector(graph, baseLayer->inputSlots()->Get(0)->connection()->sourceLayerIndex());
1045  unsigned int outputSlotIndex =
1046  GetLayerIndexInVector(graph, baseLayer->inputSlots()->Get(0)->connection()->outputSlotIndex());
1047  LayerBaseRawPtr sourceBaseLayer = GetBaseLayer(graph, sourceLayerIndex);
1048  const armnn::TensorInfo& tensorInfo = ToTensorInfo(
1049  sourceBaseLayer->outputSlots()->Get(outputSlotIndex)->tensorInfo());
1050  BindingPointInfo bindingInfo = {bindingId, tensorInfo};
1051  m_OutputBindings.push_back(std::make_pair(baseLayer->layerName()->c_str(), bindingInfo));
1052  }
1053 }
1054 
1055 void IDeserializer::DeserializerImpl::RegisterOutputSlots(GraphPtr graph,
1056  uint32_t layerIndex,
1057  IConnectableLayer* layer)
1058 {
1059  CHECK_LAYERS(graph, 0, layerIndex);
1060  ARMNN_ASSERT(layer != nullptr);
1061  LayerBaseRawPtr baseLayer = GetBaseLayer(graph, layerIndex);
1062  if (baseLayer->outputSlots()->size() != layer->GetNumOutputSlots())
1063  {
1064  throw ParseException(fmt::format("The number of outputslots ({0}) does not match the number expected ({1})"
1065  " for layer index: {2} {3}",
1066  baseLayer->outputSlots()->size(),
1067  layer->GetNumOutputSlots(),
1068  layerIndex,
1069  CHECK_LOCATION().AsString()));
1070  }
1071 
1072  for (unsigned int i = 0; i < layer->GetNumOutputSlots(); ++i)
1073  {
1074  const unsigned int slotIndex = baseLayer->outputSlots()->Get(i)->index();
1075  armnn::IOutputSlot* outputSlot = &(layer->GetOutputSlot(slotIndex));
1076  // layerIndex is not necessarily the same as baseLayer->index(). The latter is needed here
1077  RegisterOutputSlotOfConnection(baseLayer->index(), slotIndex, outputSlot);
1078  }
1079 }
1080 
1081 void IDeserializer::DeserializerImpl::RegisterInputSlots(GraphPtr graph,
1082  uint32_t layerIndex,
1083  armnn::IConnectableLayer* layer,
1084  std::vector<unsigned int> ignoreSlots)
1085 {
1086  CHECK_LAYERS(graph, 0, layerIndex);
1087  ARMNN_ASSERT(layer != nullptr);
1088  LayerBaseRawPtr baseLayer = GetBaseLayer(graph, layerIndex);
1089 
1090  if (baseLayer->inputSlots()->size() != (layer->GetNumInputSlots() - ignoreSlots.size()))
1091  {
1092  throw ParseException(fmt::format("The number of inputslots ({0}) does not match the number expected ({1})"
1093  " for layer index:{2} {3}",
1094  baseLayer->inputSlots()->size(),
1095  layer->GetNumInputSlots(),
1096  layerIndex,
1097  CHECK_LOCATION().AsString()));
1098  }
1099 
1100  for (unsigned int i = 0; i < layer->GetNumInputSlots(); ++i)
1101  {
1102  // Check if slot should be ignored.
1103  if (std::find(ignoreSlots.begin(), ignoreSlots.end(), i) == ignoreSlots.end())
1104  {
1105  auto fbInputSlot = baseLayer->inputSlots()->Get(i);
1106  auto fbConnection = fbInputSlot->connection();
1107  armnn::IInputSlot* inputSlot = &(layer->GetInputSlot(fbInputSlot->index()));
1108  RegisterInputSlotOfConnection(fbConnection->sourceLayerIndex(), fbConnection->outputSlotIndex(), inputSlot);
1109  }
1110  }
1111 }
1112 
1113 void IDeserializer::DeserializerImpl::RegisterInputSlotOfConnection(uint32_t sourceLayerIndex,
1114  uint32_t outputSlotIndex,
1115  armnn::IInputSlot* inputSlot)
1116 {
1117  if (m_GraphConnections.find(sourceLayerIndex) == m_GraphConnections.end())
1118  {
1119  m_GraphConnections[sourceLayerIndex] = Connections();
1120  }
1121 
1122  Connections& connections = m_GraphConnections[sourceLayerIndex];
1123  if (connections.inputSlots.find(outputSlotIndex) == connections.inputSlots.end())
1124  {
1125  connections.inputSlots[outputSlotIndex] = {inputSlot};
1126  }
1127  else
1128  {
1129  connections.inputSlots[outputSlotIndex].push_back(inputSlot);
1130  }
1131 }
1132 
1133 void IDeserializer::DeserializerImpl::RegisterOutputSlotOfConnection(uint32_t sourceLayerIndex,
1134  uint32_t outputSlotIndex,
1135  armnn::IOutputSlot* outputSlot)
1136 {
1137  if (m_GraphConnections.find(sourceLayerIndex) == m_GraphConnections.end())
1138  {
1139  m_GraphConnections[sourceLayerIndex] = Connections();
1140  }
1141 
1142  Connections& connections = m_GraphConnections[sourceLayerIndex];
1143  if (connections.outputSlots.find(outputSlotIndex) != connections.outputSlots.end())
1144  {
1145  throw ParseException("Same output slot index processed twice");
1146  }
1147 
1148  connections.outputSlots[outputSlotIndex] = outputSlot;
1149 }
1150 
1151 void IDeserializer::DeserializerImpl::ParseAbs(GraphPtr graph, unsigned int layerIndex)
1152 {
1153  CHECK_LAYERS(graph, 0, layerIndex);
1154  auto inputs = GetInputs(graph, layerIndex);
1155  CHECK_LOCATION();
1156  CHECK_VALID_SIZE(inputs.size(), 1);
1157 
1158  auto outputs = GetOutputs(graph, layerIndex);
1159  CHECK_VALID_SIZE(outputs.size(), 1);
1160 
1161  auto layerName = GetLayerName(graph, layerIndex);
1162 
1164  IConnectableLayer* layer = m_Network->AddElementwiseUnaryLayer(descriptor, layerName.c_str());
1165  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1166  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1167 
1168  RegisterInputSlots(graph, layerIndex, layer);
1169  RegisterOutputSlots(graph, layerIndex, layer);
1170 }
1171 
1172 void IDeserializer::DeserializerImpl::ParseActivation(GraphPtr graph, unsigned int layerIndex)
1173 {
1174  CHECK_LAYERS(graph, 0, layerIndex);
1175  auto inputs = GetInputs(graph, layerIndex);
1176  CHECK_LOCATION();
1177  CHECK_VALID_SIZE(inputs.size(), 1);
1178 
1179  auto outputs = GetOutputs(graph, layerIndex);
1180  CHECK_VALID_SIZE(outputs.size(), 1);
1181 
1182  auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_ActivationLayer();
1183  auto layerName = GetLayerName(graph, layerIndex);
1184  auto serializerDescriptor = serializerLayer->descriptor();
1185 
1186  armnn::ActivationDescriptor descriptor;
1187  descriptor.m_Function = ToActivationFunction(serializerDescriptor->activationFunction());
1188  descriptor.m_A = serializerDescriptor->a();
1189  descriptor.m_B = serializerDescriptor->b();
1190 
1191  IConnectableLayer* layer = m_Network->AddActivationLayer(descriptor,
1192  layerName.c_str());
1193  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1194  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1195 
1196  RegisterInputSlots(graph, layerIndex, layer);
1197  RegisterOutputSlots(graph, layerIndex, layer);
1198 }
1199 
1200 void IDeserializer::DeserializerImpl::ParseAdd(GraphPtr graph, unsigned int layerIndex)
1201 {
1202  CHECK_LAYERS(graph, 0, layerIndex);
1203  auto inputs = GetInputs(graph, layerIndex);
1204  CHECK_LOCATION();
1205  CHECK_VALID_SIZE(inputs.size(), 2);
1206 
1207  auto outputs = GetOutputs(graph, layerIndex);
1208  CHECK_VALID_SIZE(outputs.size(), 1);
1209 
1210  auto layerName = GetLayerName(graph, layerIndex);
1211  IConnectableLayer* layer = m_Network->AddAdditionLayer(layerName.c_str());
1212 
1213  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1214  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1215 
1216  RegisterInputSlots(graph, layerIndex, layer);
1217  RegisterOutputSlots(graph, layerIndex, layer);
1218 }
1219 
1220 void IDeserializer::DeserializerImpl::ParseArgMinMax(GraphPtr graph, unsigned int layerIndex)
1221 {
1222  CHECK_LAYERS(graph, 0, layerIndex);
1223  auto inputs = GetInputs(graph, layerIndex);
1224  CHECK_LOCATION();
1225  CHECK_VALID_SIZE(inputs.size(), 1);
1226 
1227  auto outputs = GetOutputs(graph, layerIndex);
1228  CHECK_VALID_SIZE(outputs.size(), 1);
1229 
1230  auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_ArgMinMaxLayer();
1231  auto serializerDescriptor = serializerLayer->descriptor();
1232 
1233  armnn::ArgMinMaxDescriptor descriptor;
1234  descriptor.m_Function = ToArgMinMaxFunction(serializerDescriptor->argMinMaxFunction());
1235  descriptor.m_Axis = serializerDescriptor->axis();
1236  auto layerName = GetLayerName(graph, layerIndex);
1237  IConnectableLayer* layer = m_Network->AddArgMinMaxLayer(descriptor, layerName.c_str());
1238 
1239  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1240  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1241 
1242  RegisterInputSlots(graph, layerIndex, layer);
1243  RegisterOutputSlots(graph, layerIndex, layer);
1244 }
1245 
1246 void IDeserializer::DeserializerImpl::ParseBatchToSpaceNd(GraphPtr graph, unsigned int layerIndex)
1247 {
1248  CHECK_LAYERS(graph, 0, layerIndex);
1249 
1250  TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
1251  CHECK_VALID_SIZE(inputs.size(), 1);
1252 
1253  TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
1254  CHECK_VALID_SIZE(outputs.size(), 1);
1255 
1256  auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_BatchToSpaceNdLayer()->descriptor();
1257  auto flatBufferCrops = flatBufferDescriptor->crops();
1258  auto flatBufferBlockShape = flatBufferDescriptor->blockShape();
1259 
1260  if (flatBufferCrops->Length() % 2 != 0)
1261  {
1262  throw ParseException(fmt::format("The size of crops must be divisible by 2 {}", CHECK_LOCATION().AsString()));
1263  }
1264 
1265  std::vector<std::pair<unsigned int, unsigned int>> crops;
1266  crops.reserve(flatBufferCrops->Length() / 2);
1267  for (unsigned int i = 0; i < flatBufferCrops->Length() - 1; i += 2)
1268  {
1269  crops.emplace_back(flatBufferCrops->Get(i), flatBufferCrops->Get(i+1));
1270  }
1271 
1273  descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
1274  descriptor.m_BlockShape =
1275  std::vector<unsigned int>(flatBufferBlockShape->begin(), flatBufferBlockShape->end());
1276  descriptor.m_Crops = crops;
1277 
1278  auto layerName = GetLayerName(graph, layerIndex);
1279  IConnectableLayer* layer = m_Network->AddBatchToSpaceNdLayer(descriptor, layerName.c_str());
1280 
1281  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1282  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1283 
1284  RegisterInputSlots(graph, layerIndex, layer);
1285  RegisterOutputSlots(graph, layerIndex, layer);
1286 }
1287 
1288 void IDeserializer::DeserializerImpl::ParseBatchNormalization(GraphPtr graph, unsigned int layerIndex)
1289 {
1290  CHECK_LAYERS(graph, 0, layerIndex);
1291 
1292  auto inputs = GetInputs(graph, layerIndex);
1293  CHECK_VALID_SIZE(inputs.size(), 1);
1294 
1295  auto outputs = GetOutputs(graph, layerIndex);
1296  CHECK_VALID_SIZE(outputs.size(), 1);
1297  auto outputInfo = ToTensorInfo(outputs[0]);
1298 
1299  auto layerName = GetLayerName(graph, layerIndex);
1300 
1301  auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_BatchNormalizationLayer();
1302  auto serializerDescriptor = serializerLayer->descriptor();
1303 
1305  descriptor.m_Eps = serializerDescriptor->eps();
1306  descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
1307 
1308  armnn::ConstTensor mean = ToConstTensor(serializerLayer->mean());
1309  armnn::ConstTensor variance = ToConstTensor(serializerLayer->variance());
1310  armnn::ConstTensor beta = ToConstTensor(serializerLayer->beta());
1311  armnn::ConstTensor gamma = ToConstTensor(serializerLayer->gamma());
1312 
1313  IConnectableLayer* layer = m_Network->AddBatchNormalizationLayer(descriptor,
1314  mean,
1315  variance,
1316  beta,
1317  gamma,
1318  layerName.c_str());
1319  layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1320 
1321  RegisterInputSlots(graph, layerIndex, layer);
1322  RegisterOutputSlots(graph, layerIndex, layer);
1323 }
1324 
1325 void IDeserializer::DeserializerImpl::ParseCast(GraphPtr graph, unsigned int layerIndex)
1326 {
1327  CHECK_LAYERS(graph, 0, layerIndex);
1328  TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
1329  CHECK_LOCATION();
1330  CHECK_VALID_SIZE(inputs.size(), 1);
1331 
1332  TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
1333  CHECK_VALID_SIZE(outputs.size(), 1);
1334 
1335  auto layerName = GetLayerName(graph, layerIndex);
1336 
1337  IConnectableLayer* layer = m_Network->AddCastLayer(layerName.c_str());
1338 
1339  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1340  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1341 
1342  RegisterInputSlots(graph, layerIndex, layer);
1343  RegisterOutputSlots(graph, layerIndex, layer);
1344 }
1345 
1346 void IDeserializer::DeserializerImpl::ParseConstant(GraphPtr graph, unsigned int layerIndex)
1347 {
1348  CHECK_LAYERS(graph, 0, layerIndex);
1349  CHECK_LOCATION();
1350 
1351  auto outputs = GetOutputs(graph, layerIndex);
1352  CHECK_VALID_SIZE(outputs.size(), 1);
1353 
1354  auto layerName = GetLayerName(graph, layerIndex);
1355 
1356  auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_ConstantLayer();
1357  auto serializerInput = serializerLayer->input();
1358 
1359  armnn::ConstTensor input = ToConstTensor(serializerInput);
1360 
1361  IConnectableLayer* layer = m_Network->AddConstantLayer(input, layerName.c_str());
1362 
1363  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1364  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1365 
1366  RegisterOutputSlots(graph, layerIndex, layer);
1367 }
1368 
1369 void IDeserializer::DeserializerImpl::ParseConvolution2d(GraphPtr graph, unsigned int layerIndex)
1370 {
1371  CHECK_LAYERS(graph, 0, layerIndex);
1372  auto inputs = GetInputs(graph, layerIndex);
1373  CHECK_LOCATION();
1374  CHECK_VALID_SIZE(inputs.size(), 1);
1375 
1376  auto outputs = GetOutputs(graph, layerIndex);
1377  CHECK_VALID_SIZE(outputs.size(), 1);
1378 
1379  auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_Convolution2dLayer();
1380  auto layerName = GetLayerName(graph, layerIndex);
1381  auto serializerDescriptor = serializerLayer->descriptor();
1382 
1383  armnn::Convolution2dDescriptor descriptor;
1384  descriptor.m_PadLeft = serializerDescriptor->padLeft();
1385  descriptor.m_PadRight = serializerDescriptor->padRight();
1386  descriptor.m_PadTop = serializerDescriptor->padTop();
1387  descriptor.m_PadBottom = serializerDescriptor->padBottom();
1388  descriptor.m_StrideX = serializerDescriptor->strideX();
1389  descriptor.m_StrideY = serializerDescriptor->strideY();;
1390  descriptor.m_DilationX = serializerDescriptor->dilationX();
1391  descriptor.m_DilationY = serializerDescriptor->dilationY();;
1392  descriptor.m_BiasEnabled = serializerDescriptor->biasEnabled();;
1393  descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
1394 
1395  armnn::ConstTensor weights = ToConstTensor(serializerLayer->weights());
1396  armnn::ConstTensor biases;
1397 
1399  if (descriptor.m_BiasEnabled)
1400  {
1401  biases = ToConstTensor(serializerLayer->biases());
1402  optionalBiases = armnn::Optional<armnn::ConstTensor>(biases);
1403  }
1404  IConnectableLayer* layer = m_Network->AddConvolution2dLayer(descriptor,
1405  weights,
1406  optionalBiases,
1407  layerName.c_str());
1408  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1409  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1410 
1411  RegisterInputSlots(graph, layerIndex, layer);
1412  RegisterOutputSlots(graph, layerIndex, layer);
1413 }
1414 
1415 void IDeserializer::DeserializerImpl::ParseConvolution3d(GraphPtr graph, unsigned int layerIndex)
1416 {
1417  CHECK_LAYERS(graph, 0, layerIndex);
1418  auto inputs = GetInputs(graph, layerIndex);
1419  CHECK_LOCATION();
1420 
1421  auto outputs = GetOutputs(graph, layerIndex);
1422  CHECK_VALID_SIZE(outputs.size(), 1);
1423 
1424  auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_Convolution3dLayer();
1425  auto layerName = GetLayerName(graph, layerIndex);
1426  auto serializerDescriptor = serializerLayer->descriptor();
1427 
1428  armnn::Convolution3dDescriptor descriptor;
1429  descriptor.m_PadLeft = serializerDescriptor->padLeft();
1430  descriptor.m_PadRight = serializerDescriptor->padRight();
1431  descriptor.m_PadTop = serializerDescriptor->padTop();
1432  descriptor.m_PadBottom = serializerDescriptor->padBottom();
1433  descriptor.m_PadFront = serializerDescriptor->padFront();
1434  descriptor.m_PadBack = serializerDescriptor->padBack();
1435  descriptor.m_StrideX = serializerDescriptor->strideX();
1436  descriptor.m_StrideY = serializerDescriptor->strideY();
1437  descriptor.m_StrideZ = serializerDescriptor->strideZ();
1438  descriptor.m_DilationX = serializerDescriptor->dilationX();
1439  descriptor.m_DilationY = serializerDescriptor->dilationY();
1440  descriptor.m_DilationZ = serializerDescriptor->dilationZ();
1441  descriptor.m_BiasEnabled = serializerDescriptor->biasEnabled();
1442  descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
1443 
1444  uint32_t numInputs = descriptor.GetNumInputs();
1445  CHECK_VALID_SIZE(inputs.size(), numInputs);
1446 
1447  IConnectableLayer* layer = m_Network->AddConvolution3dLayer(descriptor, layerName.c_str());
1448 
1449  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1450  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1451 
1452  RegisterInputSlots(graph, layerIndex, layer);
1453  RegisterOutputSlots(graph, layerIndex, layer);
1454 }
1455 
1456 void IDeserializer::DeserializerImpl::ParseDepthToSpace(GraphPtr graph, unsigned int layerIndex)
1457 {
1458  CHECK_LAYERS(graph, 0, layerIndex);
1459 
1460  auto inputs = GetInputs(graph, layerIndex);
1461  CHECK_VALID_SIZE(inputs.size(), 1);
1462 
1463  auto outputs = GetOutputs(graph, layerIndex);
1464  CHECK_VALID_SIZE(outputs.size(), 1);
1465 
1466  auto fbDescriptor = graph->layers()->Get(layerIndex)->layer_as_DepthToSpaceLayer()->descriptor();
1467 
1468  armnn::DepthToSpaceDescriptor descriptor;
1469  descriptor.m_BlockSize = fbDescriptor->blockSize();
1470  descriptor.m_DataLayout = ToDataLayout(fbDescriptor->dataLayout());
1471 
1472  auto layerName = GetLayerName(graph, layerIndex);
1473  IConnectableLayer* layer = m_Network->AddDepthToSpaceLayer(descriptor, layerName.c_str());
1474 
1475  armnn::TensorInfo outputInfo = ToTensorInfo(outputs[0]);
1476  layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1477 
1478  RegisterInputSlots(graph, layerIndex, layer);
1479  RegisterOutputSlots(graph, layerIndex, layer);
1480 }
1481 
1482 void IDeserializer::DeserializerImpl::ParseDepthwiseConvolution2d(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(), 1);
1488 
1489  auto outputs = GetOutputs(graph, layerIndex);
1490  CHECK_VALID_SIZE(outputs.size(), 1);
1491 
1492  auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_DepthwiseConvolution2dLayer();
1493  auto layerName = GetLayerName(graph, layerIndex);
1494  auto serializerDescriptor = serializerLayer->descriptor();
1495 
1497  descriptor.m_PadLeft = serializerDescriptor->padLeft();
1498  descriptor.m_PadRight = serializerDescriptor->padRight();
1499  descriptor.m_PadTop = serializerDescriptor->padTop();
1500  descriptor.m_PadBottom = serializerDescriptor->padBottom();
1501  descriptor.m_StrideX = serializerDescriptor->strideX();
1502  descriptor.m_StrideY = serializerDescriptor->strideY();
1503  descriptor.m_DilationX = serializerDescriptor->dilationX();
1504  descriptor.m_DilationY = serializerDescriptor->dilationY();
1505  descriptor.m_BiasEnabled = serializerDescriptor->biasEnabled();;
1506  descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
1507 
1508  IConnectableLayer* layer;
1509 
1511  if (descriptor.m_BiasEnabled)
1512  {
1513  armnn::ConstTensor biases = ToConstTensor(serializerLayer->biases());
1514  optionalBiases = armnn::Optional<armnn::ConstTensor>(biases);
1515  }
1516 
1517  armnn::ConstTensor weights = ToConstTensor(serializerLayer->weights());
1518  // The data layout for weights in ArmNN used to be [M,I,H,W] but now it's changed to [1,H,W,I*M]
1519  // When reading older flatbuffer files we need to add a permutation to get to the new layout.
1520  if (this->GetFeatureVersions(graph).m_WeightsLayoutScheme <= 0)
1521  {
1522  // Permute weights [ H, W, M, I ] --> [ 1, H, W, I*M ]
1523  // Step1: [ M, I, H, W ] --> [ H, W, I, M]
1524  PermutationVector permutationVector = { 3, 2, 0, 1 };
1525  armnn::TensorInfo weightsInfo = weights.GetInfo();
1526  std::unique_ptr<unsigned char[]> permuteBuffer(new unsigned char[weightsInfo.GetNumBytes()]);
1527  weightsInfo = armnnUtils::Permuted(weightsInfo, permutationVector);
1528  armnnUtils::Permute(weightsInfo.GetShape(), permutationVector,
1529  weights.GetMemoryArea(), permuteBuffer.get(),
1530  GetDataTypeSize(weightsInfo.GetDataType()));
1531 
1532  // Step2: Reshape [ H, W, I, M] --> [ 1, H, W, I*M ]
1533  auto weightsShape = weightsInfo.GetShape();
1534  weightsInfo.SetShape({1,
1535  weightsShape[0],
1536  weightsShape[1],
1537  weightsShape[2]*weightsShape[3]});
1538 
1539  armnn::ConstTensor weightsPermuted(weightsInfo, permuteBuffer.get());
1540 
1541  layer = m_Network->AddDepthwiseConvolution2dLayer(descriptor,
1542  weightsPermuted,
1543  optionalBiases,
1544  layerName.c_str());
1545  }
1546  else
1547  {
1548  layer = m_Network->AddDepthwiseConvolution2dLayer(descriptor,
1549  weights,
1550  optionalBiases,
1551  layerName.c_str());
1552  }
1553 
1554  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1555  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1556 
1557  RegisterInputSlots(graph, layerIndex, layer);
1558  RegisterOutputSlots(graph, layerIndex, layer);
1559 }
1560 
1561 void IDeserializer::DeserializerImpl::ParseDetectionPostProcess(GraphPtr graph, unsigned int layerIndex)
1562 {
1563  CHECK_LAYERS(graph, 0, layerIndex);
1564  auto inputs = GetInputs(graph, layerIndex);
1565  CHECK_LOCATION();
1566  CHECK_VALID_SIZE(inputs.size(), 2);
1567 
1568  auto outputs = GetOutputs(graph, layerIndex);
1569  CHECK_VALID_SIZE(outputs.size(), 4);
1570 
1571  auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_DetectionPostProcessLayer();
1572  auto layerName = GetLayerName(graph, layerIndex);
1573  auto flatBufferDescriptor = flatBufferLayer->descriptor();
1574 
1576  descriptor.m_MaxDetections = flatBufferDescriptor->maxDetections();
1577  descriptor.m_MaxClassesPerDetection = flatBufferDescriptor->maxClassesPerDetection();
1578  descriptor.m_DetectionsPerClass = flatBufferDescriptor->detectionsPerClass();
1579  descriptor.m_NmsScoreThreshold = flatBufferDescriptor->nmsScoreThreshold();
1580  descriptor.m_NmsIouThreshold = flatBufferDescriptor->nmsIouThreshold();
1581  descriptor.m_NumClasses = flatBufferDescriptor->numClasses();
1582  descriptor.m_UseRegularNms = flatBufferDescriptor->useRegularNms();
1583  descriptor.m_ScaleX = flatBufferDescriptor->scaleX();
1584  descriptor.m_ScaleY = flatBufferDescriptor->scaleY();
1585  descriptor.m_ScaleW = flatBufferDescriptor->scaleW();
1586  descriptor.m_ScaleH = flatBufferDescriptor->scaleH();
1587 
1588  armnn::ConstTensor anchors = ToConstTensor(flatBufferLayer->anchors());
1589 
1590  IConnectableLayer* layer = m_Network->AddDetectionPostProcessLayer(descriptor,
1591  anchors,
1592  layerName.c_str());
1593 
1594  for (unsigned int i = 0; i < 4; i++)
1595  {
1596  layer->GetOutputSlot(i).SetTensorInfo(ToTensorInfo(outputs[i]));
1597  }
1598 
1599  RegisterInputSlots(graph, layerIndex, layer);
1600  RegisterOutputSlots(graph, layerIndex, layer);
1601 }
1602 
1603 void IDeserializer::DeserializerImpl::ParseDivision(GraphPtr graph, unsigned int layerIndex)
1604 {
1605  CHECK_LAYERS(graph, 0, layerIndex);
1606  auto inputs = GetInputs(graph, layerIndex);
1607  CHECK_LOCATION();
1608  CHECK_VALID_SIZE(inputs.size(), 2);
1609 
1610  auto outputs = GetOutputs(graph, layerIndex);
1611  CHECK_VALID_SIZE(outputs.size(), 1);
1612 
1613  auto layerName = GetLayerName(graph, layerIndex);
1614  IConnectableLayer* layer = m_Network->AddDivisionLayer(layerName.c_str());
1615 
1616  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1617  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1618 
1619  RegisterInputSlots(graph, layerIndex, layer);
1620  RegisterOutputSlots(graph, layerIndex, layer);
1621 }
1622 
1623 void IDeserializer::DeserializerImpl::ParseEqual(GraphPtr graph, unsigned int layerIndex)
1624 {
1625  CHECK_LAYERS(graph, 0, layerIndex);
1626  auto inputs = GetInputs(graph, layerIndex);
1627  CHECK_LOCATION();
1628  CHECK_VALID_SIZE(inputs.size(), 2);
1629 
1630  auto outputs = GetOutputs(graph, layerIndex);
1631  CHECK_VALID_SIZE(outputs.size(), 1);
1632 
1633  auto layerName = GetLayerName(graph, layerIndex);
1635  IConnectableLayer* layer = m_Network->AddComparisonLayer(descriptor, layerName.c_str());
1636 
1637  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1638  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1639 
1640  RegisterInputSlots(graph, layerIndex, layer);
1641  RegisterOutputSlots(graph, layerIndex, layer);
1642 }
1643 
1644 void IDeserializer::DeserializerImpl::ParseFill(GraphPtr graph, unsigned int layerIndex)
1645 {
1646  CHECK_LAYERS(graph, 0, layerIndex);
1647  auto inputs = GetInputs(graph, layerIndex);
1648  CHECK_LOCATION();
1649  CHECK_VALID_SIZE(inputs.size(), 1);
1650 
1651  auto outputs = GetOutputs(graph, layerIndex);
1652  CHECK_VALID_SIZE(outputs.size(), 1);
1653 
1654  auto layerName = GetLayerName(graph, layerIndex);
1655  armnn::FillDescriptor descriptor;
1656  descriptor.m_Value = graph->layers()->Get(layerIndex)->layer_as_FillLayer()->descriptor()->value();
1657  IConnectableLayer* layer = m_Network->AddFillLayer(descriptor, layerName.c_str());
1658 
1659  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1660  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1661 
1662  RegisterInputSlots(graph, layerIndex, layer);
1663  RegisterOutputSlots(graph, layerIndex, layer);
1664 }
1665 
1666 void IDeserializer::DeserializerImpl::ParseGreater(GraphPtr graph, unsigned int layerIndex)
1667 {
1668  CHECK_LAYERS(graph, 0, layerIndex);
1669  auto inputs = GetInputs(graph, layerIndex);
1670  CHECK_LOCATION();
1671  CHECK_VALID_SIZE(inputs.size(), 2);
1672 
1673  auto outputs = GetOutputs(graph, layerIndex);
1674  CHECK_VALID_SIZE(outputs.size(), 1);
1675 
1676  auto layerName = GetLayerName(graph, layerIndex);
1678  IConnectableLayer* layer = m_Network->AddComparisonLayer(descriptor, layerName.c_str());
1679 
1680  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1681  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1682 
1683  RegisterInputSlots(graph, layerIndex, layer);
1684  RegisterOutputSlots(graph, layerIndex, layer);
1685 }
1686 
1687 void IDeserializer::DeserializerImpl::ParseInstanceNormalization(GraphPtr graph, unsigned int layerIndex)
1688 {
1689  CHECK_LAYERS(graph, 0, layerIndex);
1690 
1691  auto inputs = GetInputs(graph, layerIndex);
1692  CHECK_VALID_SIZE(inputs.size(), 1);
1693 
1694  auto outputs = GetOutputs(graph, layerIndex);
1695  CHECK_VALID_SIZE(outputs.size(), 1);
1696 
1697  auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_InstanceNormalizationLayer();
1698  auto fbDescriptor = fbLayer->descriptor();
1699 
1701  descriptor.m_Gamma = fbDescriptor->gamma();
1702  descriptor.m_Beta = fbDescriptor->beta();
1703  descriptor.m_Eps = fbDescriptor->eps();
1704  descriptor.m_DataLayout = ToDataLayout(fbDescriptor->dataLayout());
1705 
1706  const std::string layerName = GetLayerName(graph, layerIndex);
1707  const armnn::TensorInfo outputInfo = ToTensorInfo(outputs[0]);
1708 
1709  IConnectableLayer* layer = m_Network->AddInstanceNormalizationLayer(descriptor, layerName.c_str());
1710  layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1711 
1712  RegisterInputSlots(graph, layerIndex, layer);
1713  RegisterOutputSlots(graph, layerIndex, layer);
1714 }
1715 
1716 void IDeserializer::DeserializerImpl::ParseL2Normalization(GraphPtr graph, unsigned int layerIndex)
1717 {
1718  CHECK_LAYERS(graph, 0, layerIndex);
1719 
1720  auto inputs = GetInputs(graph, layerIndex);
1721  CHECK_VALID_SIZE(inputs.size(), 1);
1722 
1723  auto outputs = GetOutputs(graph, layerIndex);
1724  CHECK_VALID_SIZE(outputs.size(), 1);
1725  auto outputInfo = ToTensorInfo(outputs[0]);
1726 
1727  auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_L2NormalizationLayer();
1728  auto flatBufferDescriptor = flatBufferLayer->descriptor();
1729 
1730  auto layerName = GetLayerName(graph, layerIndex);
1732  descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
1733  descriptor.m_Eps = flatBufferDescriptor->eps();
1734 
1735  IConnectableLayer* layer = m_Network->AddL2NormalizationLayer(descriptor, layerName.c_str());
1736  layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1737 
1738  RegisterInputSlots(graph, layerIndex, layer);
1739  RegisterOutputSlots(graph, layerIndex, layer);
1740 }
1741 
1742 void IDeserializer::DeserializerImpl::ParseLogicalBinary(GraphPtr graph, unsigned int layerIndex)
1743 {
1744  CHECK_LAYERS(graph, 0, layerIndex);
1745  CHECK_LOCATION();
1746 
1747  auto inputs = GetInputs(graph, layerIndex);
1748  CHECK_VALID_SIZE(inputs.size(), 2);
1749 
1750  auto outputs = GetOutputs(graph, layerIndex);
1751  CHECK_VALID_SIZE(outputs.size(), 1);
1752 
1753  auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_LogicalBinaryLayer();
1754  auto fbDescriptor = fbLayer->descriptor();
1755 
1756  armnn::LogicalBinaryDescriptor descriptor;
1757  descriptor.m_Operation = ToLogicalBinaryOperation(fbDescriptor->operation());
1758 
1759  const std::string& layerName = GetLayerName(graph, layerIndex);
1760  IConnectableLayer* layer = m_Network->AddLogicalBinaryLayer(descriptor, layerName.c_str());
1761 
1762  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1763  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1764 
1765  RegisterInputSlots(graph, layerIndex, layer);
1766  RegisterOutputSlots(graph, layerIndex, layer);
1767 }
1768 
1769 void IDeserializer::DeserializerImpl::ParseLogSoftmax(GraphPtr graph, unsigned int layerIndex)
1770 {
1771  CHECK_LAYERS(graph, 0, layerIndex);
1772 
1773  TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
1774  CHECK_VALID_SIZE(inputs.size(), 1);
1775 
1776  TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
1777  CHECK_VALID_SIZE(outputs.size(), 1);
1778 
1779  armnn::LogSoftmaxDescriptor descriptor;
1780  descriptor.m_Beta = graph->layers()->Get(layerIndex)->layer_as_LogSoftmaxLayer()->descriptor()->beta();
1781  descriptor.m_Axis = graph->layers()->Get(layerIndex)->layer_as_LogSoftmaxLayer()->descriptor()->axis();
1782  auto layerName = GetLayerName(graph, layerIndex);
1783 
1784  IConnectableLayer* layer = m_Network->AddLogSoftmaxLayer(descriptor, layerName.c_str());
1785 
1786  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1787  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1788 
1789  RegisterInputSlots(graph, layerIndex, layer);
1790  RegisterOutputSlots(graph, layerIndex, layer);
1791 }
1792 
1793 void IDeserializer::DeserializerImpl::ParseMinimum(GraphPtr graph, unsigned int layerIndex)
1794 {
1795  CHECK_LAYERS(graph, 0, layerIndex);
1796  auto inputs = GetInputs(graph, layerIndex);
1797  CHECK_LOCATION();
1798  CHECK_VALID_SIZE(inputs.size(), 2);
1799 
1800  auto outputs = GetOutputs(graph, layerIndex);
1801  CHECK_VALID_SIZE(outputs.size(), 1);
1802 
1803  auto layerName = GetLayerName(graph, layerIndex);
1804  IConnectableLayer* layer = m_Network->AddMinimumLayer(layerName.c_str());
1805 
1806  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1807  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1808 
1809  RegisterInputSlots(graph, layerIndex, layer);
1810  RegisterOutputSlots(graph, layerIndex, layer);
1811 }
1812 
1813 void IDeserializer::DeserializerImpl::ParseMaximum(GraphPtr graph, unsigned int layerIndex)
1814 {
1815  CHECK_LAYERS(graph, 0, layerIndex);
1816  auto inputs = GetInputs(graph, layerIndex);
1817  CHECK_LOCATION();
1818  CHECK_VALID_SIZE(inputs.size(), 2);
1819 
1820  auto outputs = GetOutputs(graph, layerIndex);
1821  CHECK_VALID_SIZE(outputs.size(), 1);
1822 
1823  auto layerName = GetLayerName(graph, layerIndex);
1824  IConnectableLayer* layer = m_Network->AddMaximumLayer(layerName.c_str());
1825 
1826  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1827  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1828 
1829  RegisterInputSlots(graph, layerIndex, layer);
1830  RegisterOutputSlots(graph, layerIndex, layer);
1831 }
1832 
1833 const armnnSerializer::OriginsDescriptor* GetOriginsDescriptor(const armnnSerializer::SerializedGraph* graph,
1834  unsigned int layerIndex)
1835 {
1836  auto layerType = graph->layers()->Get(layerIndex)->layer_type();
1837 
1838  switch (layerType)
1839  {
1841  return graph->layers()->Get(layerIndex)->layer_as_ConcatLayer()->descriptor();
1843  return graph->layers()->Get(layerIndex)->layer_as_MergerLayer()->descriptor();
1844  default:
1845  throw armnn::Exception("unknown layer type, should be concat or merger");
1846  }
1847 }
1848 void IDeserializer::DeserializerImpl::ParseChannelShuffle(GraphPtr graph, unsigned int layerIndex)
1849 {
1850  CHECK_LAYERS(graph, 0, layerIndex);
1851 
1852  TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
1853  CHECK_VALID_SIZE(inputs.size(), 1);
1854 
1855  TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
1856  CHECK_VALID_SIZE(outputs.size(), 1);
1857 
1859  descriptor.m_Axis = graph->layers()->Get(layerIndex)->layer_as_ChannelShuffleLayer()->descriptor()->axis();
1860  descriptor.m_NumGroups =
1861  graph->layers()->Get(layerIndex)->layer_as_ChannelShuffleLayer()->descriptor()->numGroups();
1862 
1863  auto layerName = GetLayerName(graph, layerIndex);
1864  IConnectableLayer* layer = m_Network->AddChannelShuffleLayer(descriptor, layerName.c_str());
1865 
1866  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1867  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1868 
1869  RegisterInputSlots(graph, layerIndex, layer);
1870  RegisterOutputSlots(graph, layerIndex, layer);
1871 }
1872 void IDeserializer::DeserializerImpl::ParseComparison(GraphPtr graph, unsigned int layerIndex)
1873 {
1874  CHECK_LAYERS(graph, 0, layerIndex);
1875  CHECK_LOCATION();
1876 
1877  auto inputs = GetInputs(graph, layerIndex);
1878  CHECK_VALID_SIZE(inputs.size(), 2);
1879 
1880  auto outputs = GetOutputs(graph, layerIndex);
1881  CHECK_VALID_SIZE(outputs.size(), 1);
1882 
1883  auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_ComparisonLayer();
1884  auto fbDescriptor = fbLayer->descriptor();
1885 
1886  armnn::ComparisonDescriptor descriptor;
1887  descriptor.m_Operation = ToComparisonOperation(fbDescriptor->operation());
1888 
1889  const std::string& layerName = GetLayerName(graph, layerIndex);
1890  IConnectableLayer* layer = m_Network->AddComparisonLayer(descriptor, layerName.c_str());
1891 
1892  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1893  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1894 
1895  RegisterInputSlots(graph, layerIndex, layer);
1896  RegisterOutputSlots(graph, layerIndex, layer);
1897 }
1898 
1899 void IDeserializer::DeserializerImpl::ParseElementwiseUnary(GraphPtr graph, unsigned int layerIndex)
1900 {
1901  CHECK_LAYERS(graph, 0, layerIndex);
1902  CHECK_LOCATION();
1903 
1904  auto inputs = GetInputs(graph, layerIndex);
1905  CHECK_VALID_SIZE(inputs.size(), 1);
1906 
1907  auto outputs = GetOutputs(graph, layerIndex);
1908  CHECK_VALID_SIZE(outputs.size(), 1);
1909 
1910  auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_ElementwiseUnaryLayer();
1911  auto fbDescriptor = fbLayer->descriptor();
1912 
1914  descriptor.m_Operation = ToUnaryOperation(fbDescriptor->operation());
1915 
1916  const std::string& layerName = GetLayerName(graph, layerIndex);
1917  IConnectableLayer* layer = m_Network->AddElementwiseUnaryLayer(descriptor, layerName.c_str());
1918 
1919  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1920  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1921 
1922  RegisterInputSlots(graph, layerIndex, layer);
1923  RegisterOutputSlots(graph, layerIndex, layer);
1924 }
1925 
1926 void IDeserializer::DeserializerImpl::ParseConcat(GraphPtr graph, unsigned int layerIndex)
1927 {
1928  CHECK_LAYERS(graph, 0, layerIndex);
1929  CHECK_LOCATION();
1930 
1931  auto outputs = GetOutputs(graph, layerIndex);
1932  CHECK_VALID_SIZE(outputs.size(), 1);
1933 
1934  auto layerName = GetLayerName(graph, layerIndex);
1935  auto originsDescriptor = GetOriginsDescriptor(graph, layerIndex);
1936  unsigned int numViews = originsDescriptor->numViews();
1937  unsigned int numDimensions = originsDescriptor->numDimensions();
1938 
1939  // can now check the number of inputs == number of views
1940  auto inputs = GetInputs(graph, layerIndex);
1941  CHECK_VALID_SIZE(inputs.size(), numViews);
1942 
1943  armnn::OriginsDescriptor descriptor(numViews, numDimensions);
1944  auto originsPtr = originsDescriptor->viewOrigins();
1945  for (unsigned int v = 0; v < numViews; ++v)
1946  {
1947  auto originPtr = originsPtr->Get(v);
1948  for (unsigned int d = 0; d < numDimensions; ++d)
1949  {
1950  uint32_t value = originPtr->data()->Get(d);
1951  descriptor.SetViewOriginCoord(v, d, value);
1952  }
1953  }
1954  descriptor.SetConcatAxis(originsDescriptor->concatAxis());
1955 
1956  IConnectableLayer* layer = m_Network->AddConcatLayer(descriptor, layerName.c_str());
1957  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1958  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1959 
1960  RegisterInputSlots(graph, layerIndex, layer);
1961  RegisterOutputSlots(graph, layerIndex, layer);
1962 }
1963 
1964 void IDeserializer::DeserializerImpl::ParseMultiplication(GraphPtr graph, unsigned int layerIndex)
1965 {
1966  CHECK_LAYERS(graph, 0, layerIndex);
1967  auto inputs = GetInputs(graph, layerIndex);
1968  CHECK_LOCATION();
1969  CHECK_VALID_SIZE(inputs.size(), 2);
1970 
1971  auto outputs = GetOutputs(graph, layerIndex);
1972  CHECK_VALID_SIZE(outputs.size(), 1);
1973 
1974  auto layerName = GetLayerName(graph, layerIndex);
1975  IConnectableLayer* layer = m_Network->AddMultiplicationLayer(layerName.c_str());
1976 
1977  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1978  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1979 
1980  RegisterInputSlots(graph, layerIndex, layer);
1981  RegisterOutputSlots(graph, layerIndex, layer);
1982 }
1983 
1984 void IDeserializer::DeserializerImpl::ParseFloor(GraphPtr graph, unsigned int layerIndex)
1985 {
1986  CHECK_LAYERS(graph, 0, layerIndex);
1987  CHECK_LOCATION();
1988 
1989  auto inputs = GetInputs(graph, layerIndex);
1990  CHECK_VALID_SIZE(inputs.size(), 1);
1991 
1992  auto outputs = GetOutputs(graph, layerIndex);
1993  CHECK_VALID_SIZE(outputs.size(), 1);
1994 
1995  auto layerName = GetLayerName(graph, layerIndex);
1996 
1997  armnn::IConnectableLayer* layer;
1998 
1999  layer = m_Network->AddFloorLayer(layerName.c_str());
2000 
2001  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2002  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2003 
2004  RegisterInputSlots(graph, layerIndex, layer);
2005  RegisterOutputSlots(graph, layerIndex, layer);
2006 }
2007 
2008 void IDeserializer::DeserializerImpl::ParseFullyConnected(GraphPtr graph, unsigned int layerIndex)
2009 {
2010  CHECK_LAYERS(graph, 0, layerIndex);
2011  auto inputs = GetInputs(graph, layerIndex);
2012  CHECK_LOCATION();
2013 
2014  auto outputs = GetOutputs(graph, layerIndex);
2015  CHECK_VALID_SIZE(outputs.size(), 1);
2016 
2017  auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_FullyConnectedLayer();
2018  auto layerName = GetLayerName(graph, layerIndex);
2019  auto flatBufferDescriptor = flatBufferLayer->descriptor();
2020 
2021  armnn::FullyConnectedDescriptor fullyConnectedDescriptor;
2022  fullyConnectedDescriptor.m_BiasEnabled = flatBufferDescriptor->biasEnabled();
2023  fullyConnectedDescriptor.m_TransposeWeightMatrix = flatBufferDescriptor->transposeWeightsMatrix();
2024  fullyConnectedDescriptor.m_ConstantWeights = flatBufferDescriptor->constantWeights();
2025 
2026  armnn::IConnectableLayer* layer;
2027  std::vector<unsigned int> ignoreSlots {};
2028 
2029  // Weights and biases used to be always constant and were stored as members of the layer. This has changed and
2030  // they are now passed as inputs. If they are constant then they will be stored in a ConstantLayer.
2031  if (this->GetFeatureVersions(graph).m_ConstTensorsAsInputs <= 0)
2032  {
2033  // If the model stores weights and biases as members of the layer we have to read them from there
2034  // but add them to their own ConstantLayer for compatibility
2035  CHECK_VALID_SIZE(inputs.size(), 1);
2036  layer = m_Network->AddFullyConnectedLayer(fullyConnectedDescriptor,
2037  layerName.c_str());
2038 
2039  armnn::ConstTensor weightsTensor = ToConstTensor(flatBufferLayer->weights());
2040  auto weightsLayer = m_Network->AddConstantLayer(weightsTensor);
2041  weightsLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(1u));
2042  weightsLayer->GetOutputSlot(0).SetTensorInfo(weightsTensor.GetInfo());
2043  ignoreSlots.emplace_back(1u);
2044 
2045  if (fullyConnectedDescriptor.m_BiasEnabled)
2046  {
2047  armnn::ConstTensor biasTensor = ToConstTensor(flatBufferLayer->biases());
2048  auto biasLayer = m_Network->AddConstantLayer(biasTensor);
2049  biasLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(2u));
2050  biasLayer->GetOutputSlot(0).SetTensorInfo(biasTensor.GetInfo());
2051  ignoreSlots.emplace_back(2u);
2052  }
2053  }
2054  else
2055  {
2056  layer = m_Network->AddFullyConnectedLayer(fullyConnectedDescriptor,
2057  layerName.c_str());
2058  uint32_t numInputs = fullyConnectedDescriptor.GetNumInputs();
2059  CHECK_VALID_SIZE(inputs.size(), numInputs);
2060  }
2061 
2062  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2063  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2064 
2065  RegisterInputSlots(graph, layerIndex, layer, ignoreSlots);
2066  RegisterOutputSlots(graph, layerIndex, layer);
2067 }
2068 
2069 void IDeserializer::DeserializerImpl::ParsePad(GraphPtr graph, unsigned int layerIndex)
2070 {
2071  CHECK_LAYERS(graph, 0, layerIndex);
2072 
2073  TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2074  CHECK_VALID_SIZE(inputs.size(), 1);
2075 
2076  TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2077  CHECK_VALID_SIZE(outputs.size(), 1);
2078 
2079  auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_PadLayer()->descriptor();
2080  auto flatBufferPadList = flatBufferDescriptor->padList();
2081  auto paddingMode = flatBufferDescriptor->paddingMode();
2082  float padValue = flatBufferDescriptor->padValue();
2083 
2084  if (flatBufferPadList->Length() % 2 != 0)
2085  {
2086  throw ParseException(fmt::format("The size of the pad list must be divisible by 2 {}",
2087  CHECK_LOCATION().AsString()));
2088  }
2089 
2090  std::vector<std::pair<unsigned int, unsigned int>> padList;
2091  padList.reserve(flatBufferPadList->Length() / 2);
2092  for (unsigned int i = 0; i < flatBufferPadList->Length() - 1; i += 2)
2093  {
2094  padList.emplace_back(flatBufferPadList->Get(i), flatBufferPadList->Get(i+1));
2095  }
2096 
2097  armnn::PadDescriptor descriptor(padList, padValue, ToPaddingMode(paddingMode));
2098 
2099  auto layerName = GetLayerName(graph, layerIndex);
2100  IConnectableLayer* layer = m_Network->AddPadLayer(descriptor, layerName.c_str());
2101 
2102  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2103  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2104 
2105  RegisterInputSlots(graph, layerIndex, layer);
2106  RegisterOutputSlots(graph, layerIndex, layer);
2107 }
2108 
2109 void IDeserializer::DeserializerImpl::ParsePermute(GraphPtr graph, unsigned int layerIndex)
2110 {
2111  CHECK_LAYERS(graph, 0, layerIndex);
2112 
2113  auto dimsMapping =
2114  graph->layers()->Get(layerIndex)->layer_as_PermuteLayer()->descriptor()->dimMappings();
2115 
2116  auto inputs = GetInputs(graph, layerIndex);
2117  CHECK_VALID_SIZE(inputs.size(), 1);
2118 
2119  auto outputs = GetOutputs(graph, layerIndex);
2120  CHECK_VALID_SIZE(outputs.size(), 1);
2121  auto outputInfo = ToTensorInfo(outputs[0]);
2122 
2123  auto layerName = GetLayerName(graph, layerIndex);
2124  const armnn::PermuteDescriptor descriptor(armnn::PermutationVector(dimsMapping->data(), dimsMapping->Length()));
2125 
2126  IConnectableLayer* layer = m_Network->AddPermuteLayer(descriptor, layerName.c_str());
2127  layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2128 
2129  RegisterInputSlots(graph, layerIndex, layer);
2130  RegisterOutputSlots(graph, layerIndex, layer);
2131 }
2132 
2134  unsigned int layerIndex)
2135 {
2136  IgnoreUnused(layerIndex);
2138 
2139  switch (pooling2dDesc->poolType())
2140  {
2142  {
2144  break;
2145  }
2146  case PoolingAlgorithm_Max:
2147  {
2149  break;
2150  }
2151  case PoolingAlgorithm_L2:
2152  {
2154  break;
2155  }
2156  default:
2157  {
2158  ARMNN_ASSERT_MSG(false, "Unsupported pooling algorithm");
2159  }
2160  }
2161 
2162  switch (pooling2dDesc->outputShapeRounding())
2163  {
2165  {
2167  break;
2168  }
2170  {
2172  break;
2173  }
2174  default:
2175  {
2176  ARMNN_ASSERT_MSG(false, "Unsupported output shape rounding");
2177  }
2178  }
2179 
2180  switch (pooling2dDesc->paddingMethod())
2181  {
2182  case PaddingMethod_Exclude:
2183  {
2185  break;
2186  }
2188  {
2190  break;
2191  }
2192  default:
2193  {
2194  ARMNN_ASSERT_MSG(false, "Unsupported padding method");
2195  }
2196  }
2197 
2198  switch (pooling2dDesc->dataLayout())
2199  {
2200  case DataLayout_NCHW:
2201  {
2203  break;
2204  }
2205  case DataLayout_NHWC:
2206  {
2208  break;
2209  }
2210  default:
2211  {
2212  ARMNN_ASSERT_MSG(false, "Unsupported data layout");
2213  }
2214  }
2215 
2216  desc.m_PadRight = pooling2dDesc->padRight();
2217  desc.m_PadLeft = pooling2dDesc->padLeft();
2218  desc.m_PadBottom = pooling2dDesc->padBottom();
2219  desc.m_PadTop = pooling2dDesc->padTop();
2220  desc.m_StrideX = pooling2dDesc->strideX();
2221  desc.m_StrideY = pooling2dDesc->strideY();
2222  desc.m_PoolWidth = pooling2dDesc->poolWidth();
2223  desc.m_PoolHeight = pooling2dDesc->poolHeight();
2224 
2225  return desc;
2226 }
2227 
2228 
2229 
2230 void IDeserializer::DeserializerImpl::ParsePooling2d(GraphPtr graph, unsigned int layerIndex)
2231 {
2232  CHECK_LAYERS(graph, 0, layerIndex);
2233 
2234  auto pooling2dDes = graph->layers()->Get(layerIndex)->layer_as_Pooling2dLayer()->descriptor();
2235  auto inputs = GetInputs(graph, layerIndex);
2236  CHECK_VALID_SIZE(inputs.size(), 1);
2237 
2238  auto outputs = GetOutputs(graph, layerIndex);
2239  CHECK_VALID_SIZE(outputs.size(), 1);
2240  auto outputInfo = ToTensorInfo(outputs[0]);
2241 
2242  auto pooling2dDescriptor = GetPoolingDescriptor(pooling2dDes, layerIndex);
2243  auto layerName = GetLayerName(graph, layerIndex);
2244  IConnectableLayer* layer = m_Network->AddPooling2dLayer(pooling2dDescriptor, layerName.c_str());
2245  layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2246 
2247  RegisterInputSlots(graph, layerIndex, layer);
2248  RegisterOutputSlots(graph, layerIndex, layer);
2249 }
2250 
2251 void IDeserializer::DeserializerImpl::ParseQuantize(GraphPtr graph, unsigned int layerIndex)
2252 {
2253  CHECK_LAYERS(graph, 0, layerIndex);
2254 
2255  auto inputs = GetInputs(graph, layerIndex);
2256  CHECK_VALID_SIZE(inputs.size(), 1);
2257 
2258  auto outputs = GetOutputs(graph, layerIndex);
2259  CHECK_VALID_SIZE(outputs.size(), 1);
2260  auto outputInfo = ToTensorInfo(outputs[0]);
2261 
2262  auto layerName = GetLayerName(graph, layerIndex);
2263  IConnectableLayer* layer = m_Network->AddQuantizeLayer(layerName.c_str());
2264  layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2265 
2266  RegisterInputSlots(graph, layerIndex, layer);
2267  RegisterOutputSlots(graph, layerIndex, layer);
2268 }
2269 
2271  const std::vector<uint32_t>& targetDimsIn)
2272 {
2273  std::vector<unsigned int> outputDims(targetDimsIn.begin(), targetDimsIn.end());
2274  const auto stretchDim = std::find(targetDimsIn.begin(), targetDimsIn.end(), -1);
2275 
2276  if (stretchDim != targetDimsIn.end())
2277  {
2278  if (std::find(std::next(stretchDim), targetDimsIn.end(), -1) != targetDimsIn.end())
2279  {
2280  throw ParseException(fmt::format("At most one component of shape can be -1 {}",
2281  CHECK_LOCATION().AsString()));
2282  }
2283 
2284  auto targetNumElements =
2285  armnn::numeric_cast<unsigned int>(
2286  std::accumulate(targetDimsIn.begin(), targetDimsIn.end(), -1, std::multiplies<int32_t>()));
2287 
2288  auto stretchIndex = static_cast<size_t>(std::distance(targetDimsIn.begin(), stretchDim));
2289  outputDims[stretchIndex] = inputTensorInfo.GetNumElements() / targetNumElements;
2290  }
2291 
2292  TensorShape outputShape = TensorShape(static_cast<unsigned int>(outputDims.size()), outputDims.data());
2293 
2294  armnn::TensorInfo reshapeInfo = inputTensorInfo;
2295  reshapeInfo.SetShape(outputShape);
2296 
2297  return reshapeInfo;
2298 }
2299 
2300 void IDeserializer::DeserializerImpl::ParseRank(GraphPtr graph, unsigned int layerIndex)
2301 {
2302  CHECK_LAYERS(graph, 0, layerIndex);
2303 
2304  TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2305  CHECK_VALID_SIZE(inputs.size(), 1);
2306 
2307  TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2308  CHECK_VALID_SIZE(outputs.size(), 1);
2309 
2310  auto layerName = GetLayerName(graph, layerIndex);
2311  IConnectableLayer* layer = m_Network->AddRankLayer( layerName.c_str());
2312 
2313  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2314  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2315 
2316  RegisterInputSlots(graph, layerIndex, layer);
2317  RegisterOutputSlots(graph, layerIndex, layer);
2318 }
2319 
2320 void IDeserializer::DeserializerImpl::ParseReduce(GraphPtr graph, unsigned int layerIndex)
2321 {
2322  CHECK_LAYERS(graph, 0, layerIndex);
2323  CHECK_LOCATION();
2324 
2325  auto inputs = GetInputs(graph, layerIndex);
2326  CHECK_VALID_SIZE(inputs.size(), 1);
2327 
2328  auto outputs = GetOutputs(graph, layerIndex);
2329  CHECK_VALID_SIZE(outputs.size(), 1);
2330 
2331  auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_ReduceLayer();
2332  auto fbDescriptor = fbLayer->descriptor();
2333  auto flatBufferAxis = fbDescriptor->axis();
2334 
2335  armnn::ReduceDescriptor descriptor;
2336  descriptor.m_KeepDims = fbDescriptor->keepDims();
2337  descriptor.m_vAxis = std::vector<unsigned int>(flatBufferAxis->begin(), flatBufferAxis->end());
2338  descriptor.m_ReduceOperation = ToReduceOperation(fbDescriptor->reduceOperation());
2339 
2340  const std::string& layerName = GetLayerName(graph, layerIndex);
2341  IConnectableLayer* layer = m_Network->AddReduceLayer(descriptor, layerName.c_str());
2342 
2343  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2344  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2345 
2346  RegisterInputSlots(graph, layerIndex, layer);
2347  RegisterOutputSlots(graph, layerIndex, layer);
2348 }
2349 
2350 void IDeserializer::DeserializerImpl::ParseReshape(GraphPtr graph, unsigned int layerIndex)
2351 {
2352  CHECK_LAYERS(graph, 0, layerIndex);
2353  auto inputs = GetInputs(graph, layerIndex);
2354 
2355  auto outputs = GetOutputs(graph, layerIndex);
2356  CHECK_VALID_SIZE(outputs.size(), 1);
2357 
2358  armnn::TensorInfo inputTensorInfo = ToTensorInfo(inputs[0]);
2359  armnn::TensorInfo actualOutputTensorInfo = ToTensorInfo(outputs[0]);
2360 
2361  const auto targetDims = graph->layers()->Get(layerIndex)->layer_as_ReshapeLayer()->descriptor()->targetShape();
2362  std::vector<uint32_t> outputDims(targetDims->begin(), targetDims->begin() + targetDims->size());
2363 
2364  armnn::TensorInfo reshapeOutputTensorInfo = DeserializerImpl::OutputShapeOfReshape(inputTensorInfo, outputDims);
2365  const armnn::TensorShape& reshapeOutputTensorShape = reshapeOutputTensorInfo.GetShape();
2366 
2367  const std::vector<uint32_t> expectedDims(outputs[0]->dimensions()->begin(),
2368  outputs[0]->dimensions()->begin() + outputs[0]->dimensions()->size());
2369 
2370  if (inputs.size() > 1 && !CheckShape(reshapeOutputTensorShape, expectedDims))
2371  {
2372  std::stringstream ss;
2373  ss << "New shape defined in reshape parameters "
2374  << reshapeOutputTensorShape
2375  << " does not equal output shape "
2376  << actualOutputTensorInfo.GetShape()
2377  << ": "
2378  << CHECK_LOCATION().AsString();
2379  throw ParseException(ss.str());
2380  }
2381 
2382  armnn::ReshapeDescriptor reshapeDesc;
2383  reshapeDesc.m_TargetShape = reshapeOutputTensorShape;
2384 
2385  auto layerName = GetLayerName(graph, layerIndex);
2386  IConnectableLayer* layer = m_Network->AddReshapeLayer(reshapeDesc, layerName.c_str());
2387  layer->GetOutputSlot(0).SetTensorInfo(reshapeOutputTensorInfo);
2388 
2389  RegisterInputSlots(graph, layerIndex, layer);
2390  RegisterOutputSlots(graph, layerIndex, layer);
2391 }
2392 
2393 void IDeserializer::DeserializerImpl::ParseResize(GraphPtr graph, unsigned int layerIndex)
2394 {
2395  CHECK_LAYERS(graph, 0, layerIndex);
2396 
2397  TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2398  CHECK_VALID_SIZE(inputs.size(), 1);
2399 
2400  TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2401  CHECK_VALID_SIZE(outputs.size(), 1);
2402 
2403  auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_ResizeLayer()->descriptor();
2404 
2405  armnn::ResizeDescriptor descriptor;
2406  descriptor.m_TargetWidth = flatBufferDescriptor->targetWidth();
2407  descriptor.m_TargetHeight = flatBufferDescriptor->targetHeight();
2408  descriptor.m_Method = ToResizeMethod(flatBufferDescriptor->method());
2409  descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2410  descriptor.m_AlignCorners = flatBufferDescriptor->alignCorners();
2411  descriptor.m_HalfPixelCenters = flatBufferDescriptor->halfPixelCenters();
2412 
2413  auto layerName = GetLayerName(graph, layerIndex);
2414  IConnectableLayer* layer = m_Network->AddResizeLayer(descriptor, layerName.c_str());
2415 
2416  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2417  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2418 
2419  RegisterInputSlots(graph, layerIndex, layer);
2420  RegisterOutputSlots(graph, layerIndex, layer);
2421 }
2422 
2423 
2424 /// @Note The ResizeBiliniar operation was deprecated and removed in favor of the Resize operation.
2425 /// This function is kept for backwards compatibility.
2426 void IDeserializer::DeserializerImpl::ParseResizeBilinear(GraphPtr graph, unsigned int layerIndex)
2427 {
2428  CHECK_LAYERS(graph, 0, layerIndex);
2429 
2430  TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2431  CHECK_VALID_SIZE(inputs.size(), 1);
2432 
2433  TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2434  CHECK_VALID_SIZE(outputs.size(), 1);
2435 
2436  auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_ResizeBilinearLayer()->descriptor();
2437 
2438  armnn::ResizeDescriptor descriptor;
2439  descriptor.m_TargetWidth = flatBufferDescriptor->targetWidth();
2440  descriptor.m_TargetHeight = flatBufferDescriptor->targetHeight();
2442  descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2443  descriptor.m_AlignCorners = flatBufferDescriptor->alignCorners();
2444  descriptor.m_HalfPixelCenters = flatBufferDescriptor->halfPixelCenters();
2445 
2446  auto layerName = GetLayerName(graph, layerIndex);
2447  IConnectableLayer* layer = m_Network->AddResizeLayer(descriptor, layerName.c_str());
2448 
2449  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2450  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2451 
2452  RegisterInputSlots(graph, layerIndex, layer);
2453  RegisterOutputSlots(graph, layerIndex, layer);
2454 }
2455 
2456 void IDeserializer::DeserializerImpl::ParseShape(GraphPtr graph, unsigned int layerIndex)
2457 {
2458  CHECK_LAYERS(graph, 0, layerIndex);
2459 
2460  TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2461  CHECK_VALID_SIZE(inputs.size(), 1);
2462 
2463  TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2464  CHECK_VALID_SIZE(outputs.size(), 1);
2465 
2466  auto layerName = GetLayerName(graph, layerIndex);
2467  IConnectableLayer* layer = m_Network->AddShapeLayer( layerName.c_str());
2468 
2469  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2470  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2471 
2472  RegisterInputSlots(graph, layerIndex, layer);
2473  RegisterOutputSlots(graph, layerIndex, layer);
2474 }
2475 
2476 void IDeserializer::DeserializerImpl::ParseSoftmax(GraphPtr graph, unsigned int layerIndex)
2477 {
2478  CHECK_LAYERS(graph, 0, layerIndex);
2479 
2480  TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2481  CHECK_VALID_SIZE(inputs.size(), 1);
2482 
2483  TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2484  CHECK_VALID_SIZE(outputs.size(), 1);
2485 
2486  armnn::SoftmaxDescriptor descriptor;
2487  descriptor.m_Beta = graph->layers()->Get(layerIndex)->layer_as_SoftmaxLayer()->descriptor()->beta();
2488  descriptor.m_Axis = graph->layers()->Get(layerIndex)->layer_as_SoftmaxLayer()->descriptor()->axis();
2489  auto layerName = GetLayerName(graph, layerIndex);
2490 
2491  IConnectableLayer* layer = m_Network->AddSoftmaxLayer(descriptor, layerName.c_str());
2492 
2493  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2494  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2495 
2496  RegisterInputSlots(graph, layerIndex, layer);
2497  RegisterOutputSlots(graph, layerIndex, layer);
2498 }
2499 
2500 void IDeserializer::DeserializerImpl::ParseSpaceToBatchNd(GraphPtr graph, unsigned int layerIndex)
2501 {
2502  CHECK_LAYERS(graph, 0, layerIndex);
2503 
2504  TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2505  CHECK_VALID_SIZE(inputs.size(), 1);
2506 
2507  TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2508  CHECK_VALID_SIZE(outputs.size(), 1);
2509 
2510  auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_SpaceToBatchNdLayer()->descriptor();
2511  auto flatBufferPadList = flatBufferDescriptor->padList();
2512  auto flatBufferBlockShape = flatBufferDescriptor->blockShape();
2513 
2514  if (flatBufferPadList->Length() % 2 != 0)
2515  {
2516  throw ParseException(fmt::format("The size of the pad list must be divisible by 2 {}",
2517  CHECK_LOCATION().AsString()));
2518  }
2519 
2520  std::vector<std::pair<unsigned int, unsigned int>> padList;
2521  padList.reserve(flatBufferPadList->Length() / 2);
2522  for (unsigned int i = 0; i < flatBufferPadList->Length() - 1; i += 2)
2523  {
2524  padList.emplace_back(flatBufferPadList->Get(i), flatBufferPadList->Get(i+1));
2525  }
2526 
2528  descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2529  descriptor.m_BlockShape =
2530  std::vector<unsigned int>(flatBufferBlockShape->begin(), flatBufferBlockShape->end());
2531  descriptor.m_PadList = padList;
2532 
2533  auto layerName = GetLayerName(graph, layerIndex);
2534  IConnectableLayer* layer = m_Network->AddSpaceToBatchNdLayer(descriptor, layerName.c_str());
2535 
2536  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2537  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2538 
2539  RegisterInputSlots(graph, layerIndex, layer);
2540  RegisterOutputSlots(graph, layerIndex, layer);
2541 }
2542 
2543 void IDeserializer::DeserializerImpl::ParseSpaceToDepth(GraphPtr graph, unsigned int layerIndex)
2544 {
2545  CHECK_LAYERS(graph, 0, layerIndex);
2546 
2547  TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2548  CHECK_VALID_SIZE(inputs.size(), 1);
2549 
2550  TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2551  CHECK_VALID_SIZE(outputs.size(), 1);
2552 
2553  auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_SpaceToDepthLayer()->descriptor();
2554 
2555  armnn::SpaceToDepthDescriptor descriptor;
2556  descriptor.m_BlockSize = flatBufferDescriptor->blockSize();
2557  descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2558 
2559  auto layerName = GetLayerName(graph, layerIndex);
2560  IConnectableLayer* layer = m_Network->AddSpaceToDepthLayer(descriptor, layerName.c_str());
2561 
2562  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2563  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2564 
2565  RegisterInputSlots(graph, layerIndex, layer);
2566  RegisterOutputSlots(graph, layerIndex, layer);
2567 }
2568 
2570  NormalizationDescriptorPtr normalizationDescriptor,
2571  unsigned int layerIndex)
2572 {
2573  IgnoreUnused(layerIndex);
2575 
2576  switch (normalizationDescriptor->normChannelType())
2577  {
2579  {
2581  break;
2582  }
2584  {
2586  break;
2587  }
2588  default:
2589  {
2590  ARMNN_ASSERT_MSG(false, "Unsupported normalization channel type");
2591  }
2592  }
2593 
2594  switch (normalizationDescriptor->normMethodType())
2595  {
2597  {
2599  break;
2600  }
2602  {
2604  break;
2605  }
2606  default:
2607  {
2608  ARMNN_ASSERT_MSG(false, "Unsupported normalization method type");
2609  }
2610  }
2611 
2612  switch (normalizationDescriptor->dataLayout())
2613  {
2614  case DataLayout_NCHW:
2615  {
2617  break;
2618  }
2619  case DataLayout_NHWC:
2620  {
2622  break;
2623  }
2624  default:
2625  {
2626  ARMNN_ASSERT_MSG(false, "Unsupported data layout");
2627  }
2628  }
2629 
2630  desc.m_Alpha = normalizationDescriptor->alpha();
2631  desc.m_Beta = normalizationDescriptor->beta();
2632  desc.m_K = normalizationDescriptor->k();
2633  desc.m_NormSize = normalizationDescriptor->normSize();
2634 
2635  return desc;
2636 }
2637 
2638 void IDeserializer::DeserializerImpl::ParseNormalization(GraphPtr graph, unsigned int layerIndex)
2639 {
2640  CHECK_LAYERS(graph, 0, layerIndex);
2641 
2642  auto normalizationDes = graph->layers()->Get(layerIndex)->layer_as_NormalizationLayer()->descriptor();
2643 
2644  TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2645  CHECK_VALID_SIZE(inputs.size(), 1);
2646 
2647  TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2648  CHECK_VALID_SIZE(outputs.size(), 1);
2649 
2650  auto outputInfo = ToTensorInfo(outputs[0]);
2651 
2652  auto normalizationDescriptor = GetNormalizationDescriptor(normalizationDes, layerIndex);
2653  auto layerName = GetLayerName(graph, layerIndex);
2654 
2655  IConnectableLayer* layer = m_Network->AddNormalizationLayer(normalizationDescriptor, layerName.c_str());
2656  layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2657 
2658  RegisterInputSlots(graph, layerIndex, layer);
2659  RegisterOutputSlots(graph, layerIndex, layer);
2660 }
2661 
2662 void IDeserializer::DeserializerImpl::ParseRsqrt(GraphPtr graph, unsigned int layerIndex)
2663 {
2664  CHECK_LAYERS(graph, 0, layerIndex);
2665  auto inputs = GetInputs(graph, layerIndex);
2666  CHECK_LOCATION();
2667  CHECK_VALID_SIZE(inputs.size(), 1);
2668 
2669  auto outputs = GetOutputs(graph, layerIndex);
2670  CHECK_VALID_SIZE(outputs.size(), 1);
2671 
2672  auto layerName = GetLayerName(graph, layerIndex);
2673 
2675  IConnectableLayer* layer = m_Network->AddElementwiseUnaryLayer(descriptor, layerName.c_str());
2676  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2677  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2678 
2679  RegisterInputSlots(graph, layerIndex, layer);
2680  RegisterOutputSlots(graph, layerIndex, layer);
2681 }
2682 
2683 void IDeserializer::DeserializerImpl::ParseSlice(GraphPtr graph, unsigned int layerIndex)
2684 {
2685  CHECK_LAYERS(graph, 0, layerIndex);
2686 
2687  auto inputs = GetInputs(graph, layerIndex);
2688  CHECK_VALID_SIZE(inputs.size(), 1);
2689 
2690  auto outputs = GetOutputs(graph, layerIndex);
2691  CHECK_VALID_SIZE(outputs.size(), 1);
2692 
2693  auto fbDescriptor = graph->layers()->Get(layerIndex)->layer_as_SliceLayer()->descriptor();
2694 
2695  auto fbBegin = fbDescriptor->begin();
2696  auto fbSize = fbDescriptor->size();
2697 
2698  if (fbBegin->Length() != fbSize->Length())
2699  {
2700  throw ParseException(fmt::format("Begin and size descriptors must have the same length {}",
2701  CHECK_LOCATION().AsString()));
2702  }
2703 
2704  armnn::SliceDescriptor descriptor;
2705  descriptor.m_Begin.insert(descriptor.m_Begin.end(), fbBegin->begin(), fbBegin->end());
2706  descriptor.m_Size.insert(descriptor.m_Size.end(), fbSize->begin(), fbSize->end());
2707 
2708  auto layerName = GetLayerName(graph, layerIndex);
2709  IConnectableLayer* layer = m_Network->AddSliceLayer(descriptor, layerName.c_str());
2710 
2711  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2712  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2713 
2714  RegisterInputSlots(graph, layerIndex, layer);
2715  RegisterOutputSlots(graph, layerIndex, layer);
2716 }
2717 
2718 void IDeserializer::DeserializerImpl::ParseStridedSlice(GraphPtr graph, unsigned int layerIndex)
2719 {
2720  CHECK_LAYERS(graph, 0, layerIndex);
2721 
2722  TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2723  CHECK_VALID_SIZE(inputs.size(), 1);
2724 
2725  TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2726  CHECK_VALID_SIZE(outputs.size(), 1);
2727 
2728  auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_StridedSliceLayer()->descriptor();
2729 
2730  auto flatBufferBegin = flatBufferDescriptor->begin();
2731  auto flatBufferEnd = flatBufferDescriptor->end();
2732  auto flatBufferStride = flatBufferDescriptor->stride();
2733 
2734  if (!(flatBufferBegin->Length() == flatBufferEnd->Length() &&
2735  flatBufferBegin->Length() == flatBufferStride->Length()))
2736  {
2737  throw ParseException(fmt::format("The size of the begin, end, and stride must be equal {}",
2738  CHECK_LOCATION().AsString()));
2739  }
2740 
2741  std::vector<int> begin(flatBufferBegin->begin(), flatBufferBegin->end());
2742  std::vector<int> end(flatBufferEnd->begin(), flatBufferEnd->end());
2743  std::vector<int> stride(flatBufferStride->begin(), flatBufferStride->end());
2744 
2745  armnn::StridedSliceDescriptor descriptor(begin, end, stride);
2746  descriptor.m_BeginMask = flatBufferDescriptor->beginMask();
2747  descriptor.m_EndMask = flatBufferDescriptor->endMask();
2748  descriptor.m_ShrinkAxisMask = flatBufferDescriptor->shrinkAxisMask();
2749  descriptor.m_EllipsisMask = flatBufferDescriptor->ellipsisMask();
2750  descriptor.m_NewAxisMask = flatBufferDescriptor->newAxisMask();
2751  descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2752 
2753  auto layerName = GetLayerName(graph, layerIndex);
2754  IConnectableLayer* layer = m_Network->AddStridedSliceLayer(descriptor, layerName.c_str());
2755 
2756  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2757  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2758 
2759  RegisterInputSlots(graph, layerIndex, layer);
2760  RegisterOutputSlots(graph, layerIndex, layer);
2761 }
2762 
2763 void IDeserializer::DeserializerImpl::ParseSubtraction(GraphPtr graph, unsigned int layerIndex)
2764 {
2765  CHECK_LAYERS(graph, 0, layerIndex);
2766  auto inputs = GetInputs(graph, layerIndex);
2767  CHECK_LOCATION();
2768  CHECK_VALID_SIZE(inputs.size(), 2);
2769 
2770  auto outputs = GetOutputs(graph, layerIndex);
2771  CHECK_VALID_SIZE(outputs.size(), 1);
2772 
2773  auto layerName = GetLayerName(graph, layerIndex);
2774  IConnectableLayer* layer = m_Network->AddSubtractionLayer(layerName.c_str());
2775 
2776  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2777  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2778 
2779  RegisterInputSlots(graph, layerIndex, layer);
2780  RegisterOutputSlots(graph, layerIndex, layer);
2781 }
2782 
2783 void IDeserializer::DeserializerImpl::ParseGather(GraphPtr graph, unsigned int layerIndex)
2784 {
2785  CHECK_LAYERS(graph, 0, layerIndex);
2786 
2787  TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2788  CHECK_VALID_SIZE(inputs.size(), 2);
2789 
2790  TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2791  CHECK_VALID_SIZE(outputs.size(), 1);
2792 
2793  armnn::GatherDescriptor descriptor;
2794  descriptor.m_Axis = graph->layers()->Get(layerIndex)->layer_as_GatherLayer()->descriptor()->axis();
2795 
2796  auto layerName = GetLayerName(graph, layerIndex);
2797  IConnectableLayer* layer = m_Network->AddGatherLayer(descriptor, layerName.c_str());
2798 
2799  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2800  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2801 
2802  RegisterInputSlots(graph, layerIndex, layer);
2803  RegisterOutputSlots(graph, layerIndex, layer);
2804 }
2805 
2806 void IDeserializer::DeserializerImpl::ParseMean(GraphPtr graph, unsigned int layerIndex)
2807 {
2808  CHECK_LAYERS(graph, 0, layerIndex);
2809 
2810  TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2811  CHECK_VALID_SIZE(inputs.size(), 1);
2812 
2813  TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2814  CHECK_VALID_SIZE(outputs.size(), 1);
2815 
2816  auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_MeanLayer()->descriptor();
2817  auto flatBufferAxis = flatBufferDescriptor->axis();
2818  auto flatBufferKeepDims = flatBufferDescriptor->keepDims();
2819 
2820  armnn::MeanDescriptor descriptor;
2821  descriptor.m_Axis = std::vector<unsigned int>(flatBufferAxis->begin(), flatBufferAxis->end());
2822  descriptor.m_KeepDims = flatBufferKeepDims;
2823 
2824  auto layerName = GetLayerName(graph, layerIndex);
2825  IConnectableLayer* layer = m_Network->AddMeanLayer(descriptor, layerName.c_str());
2826 
2827  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2828  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2829 
2830  RegisterInputSlots(graph, layerIndex, layer);
2831  RegisterOutputSlots(graph, layerIndex, layer);
2832 }
2833 
2834 void IDeserializer::DeserializerImpl::ParseSplitter(GraphPtr graph, unsigned int layerIndex)
2835 {
2836  CHECK_LAYERS(graph, 0, layerIndex);
2837 
2838  TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2839  CHECK_VALID_SIZE(inputs.size(), 1);
2840 
2841  TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2842 
2843  auto flatBufferViewsDescriptor = graph->layers()->Get(layerIndex)->layer_as_SplitterLayer()->descriptor();
2844  auto flatBufferViewSizes = flatBufferViewsDescriptor->viewSizes();
2845  auto flatBufferOriginsDescriptor = flatBufferViewsDescriptor->origins();
2846  auto flatBufferViewOrigins = flatBufferOriginsDescriptor->viewOrigins();
2847  uint32_t numViews = flatBufferOriginsDescriptor->numViews();
2848  uint32_t numDimensions = flatBufferOriginsDescriptor->numDimensions();
2849 
2850  // Check numViews and numDimensions corresponds to the ones already serialized ...
2851  // numViews == flatBufferViewSizes.size();
2852  // foreach: numDimensions == flatBufferViewSizes[x].size();
2853 
2854  armnn::ViewsDescriptor viewsDescriptor(numViews, numDimensions);
2855  for(unsigned int vIdx = 0; vIdx < numViews; ++vIdx)
2856  {
2857  for (unsigned int dIdx = 0; dIdx < numDimensions; ++dIdx)
2858  {
2859  viewsDescriptor.SetViewSize(vIdx, dIdx, flatBufferViewSizes->Get(vIdx)->data()->Get(dIdx));
2860  viewsDescriptor.SetViewOriginCoord(vIdx, dIdx, flatBufferViewOrigins->Get(vIdx)->data()->Get(dIdx));
2861  }
2862  }
2863 
2864  auto layerName = GetLayerName(graph, layerIndex);
2865  IConnectableLayer* layer = m_Network->AddSplitterLayer(viewsDescriptor, layerName.c_str());
2866 
2867  // I could have as many outputs as views ...
2868  for(unsigned int vIdx = 0; vIdx < numViews; ++vIdx)
2869  {
2870  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[vIdx]);
2871  layer->GetOutputSlot(vIdx).SetTensorInfo(outputTensorInfo);
2872  }
2873 
2874  RegisterInputSlots(graph, layerIndex, layer);
2875  RegisterOutputSlots(graph, layerIndex, layer);
2876 }
2877 
2879 {
2880  armnn::LstmDescriptor desc;
2881 
2882  desc.m_ActivationFunc = lstmDescriptor->activationFunc();
2883  desc.m_ClippingThresCell = lstmDescriptor->clippingThresCell();
2884  desc.m_ClippingThresProj = lstmDescriptor->clippingThresProj();
2885  desc.m_CifgEnabled = lstmDescriptor->cifgEnabled();
2886  desc.m_PeepholeEnabled = lstmDescriptor->peepholeEnabled();
2887  desc.m_ProjectionEnabled = lstmDescriptor->projectionEnabled();
2888  desc.m_LayerNormEnabled = lstmDescriptor->layerNormEnabled();
2889 
2890  return desc;
2891 }
2892 
2893 void IDeserializer::DeserializerImpl::ParseLstm(GraphPtr graph, unsigned int layerIndex)
2894 {
2895  CHECK_LAYERS(graph, 0, layerIndex);
2896 
2897  auto inputs = GetInputs(graph, layerIndex);
2898  CHECK_VALID_SIZE(inputs.size(), 3);
2899 
2900  auto outputs = GetOutputs(graph, layerIndex);
2901  CHECK_VALID_SIZE(outputs.size(), 4);
2902 
2903  auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_LstmLayer();
2904  auto layerName = GetLayerName(graph, layerIndex);
2905  auto flatBufferDescriptor = flatBufferLayer->descriptor();
2906  auto flatBufferInputParams = flatBufferLayer->inputParams();
2907 
2908  auto lstmDescriptor = GetLstmDescriptor(flatBufferDescriptor);
2909 
2910  armnn::LstmInputParams lstmInputParams;
2911 
2912  armnn::ConstTensor inputToForgetWeights = ToConstTensor(flatBufferInputParams->inputToForgetWeights());
2913  armnn::ConstTensor inputToCellWeights = ToConstTensor(flatBufferInputParams->inputToCellWeights());
2914  armnn::ConstTensor inputToOutputWeights = ToConstTensor(flatBufferInputParams->inputToOutputWeights());
2915  armnn::ConstTensor recurrentToForgetWeights = ToConstTensor(flatBufferInputParams->recurrentToForgetWeights());
2916  armnn::ConstTensor recurrentToCellWeights = ToConstTensor(flatBufferInputParams->recurrentToCellWeights());
2917  armnn::ConstTensor recurrentToOutputWeights = ToConstTensor(flatBufferInputParams->recurrentToOutputWeights());
2918  armnn::ConstTensor forgetGateBias = ToConstTensor(flatBufferInputParams->forgetGateBias());
2919  armnn::ConstTensor cellBias = ToConstTensor(flatBufferInputParams->cellBias());
2920  armnn::ConstTensor outputGateBias = ToConstTensor(flatBufferInputParams->outputGateBias());
2921 
2922  lstmInputParams.m_InputToForgetWeights = &inputToForgetWeights;
2923  lstmInputParams.m_InputToCellWeights = &inputToCellWeights;
2924  lstmInputParams.m_InputToOutputWeights = &inputToOutputWeights;
2925  lstmInputParams.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2926  lstmInputParams.m_RecurrentToCellWeights = &recurrentToCellWeights;
2927  lstmInputParams.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2928  lstmInputParams.m_ForgetGateBias = &forgetGateBias;
2929  lstmInputParams.m_CellBias = &cellBias;
2930  lstmInputParams.m_OutputGateBias = &outputGateBias;
2931 
2932  armnn::ConstTensor inputToInputWeights;
2933  armnn::ConstTensor recurrentToInputWeights;
2934  armnn::ConstTensor cellToInputWeights;
2935  armnn::ConstTensor inputGateBias;
2936  if (!lstmDescriptor.m_CifgEnabled)
2937  {
2938  inputToInputWeights = ToConstTensor(flatBufferInputParams->inputToInputWeights());
2939  recurrentToInputWeights = ToConstTensor(flatBufferInputParams->recurrentToInputWeights());
2940  cellToInputWeights = ToConstTensor(flatBufferInputParams->cellToInputWeights());
2941  inputGateBias = ToConstTensor(flatBufferInputParams->inputGateBias());
2942 
2943  lstmInputParams.m_InputToInputWeights = &inputToInputWeights;
2944  lstmInputParams.m_RecurrentToInputWeights = &recurrentToInputWeights;
2945  lstmInputParams.m_CellToInputWeights = &cellToInputWeights;
2946  lstmInputParams.m_InputGateBias = &inputGateBias;
2947  }
2948 
2949  armnn::ConstTensor projectionWeights;
2950  armnn::ConstTensor projectionBias;
2951  if (lstmDescriptor.m_ProjectionEnabled)
2952  {
2953  projectionWeights = ToConstTensor(flatBufferInputParams->projectionWeights());
2954  projectionBias = ToConstTensor(flatBufferInputParams->projectionBias());
2955 
2956  lstmInputParams.m_ProjectionWeights = &projectionWeights;
2957  lstmInputParams.m_ProjectionBias = &projectionBias;
2958  }
2959 
2960  armnn::ConstTensor cellToForgetWeights;
2961  armnn::ConstTensor cellToOutputWeights;
2962  if (lstmDescriptor.m_PeepholeEnabled)
2963  {
2964  cellToForgetWeights = ToConstTensor(flatBufferInputParams->cellToForgetWeights());
2965  cellToOutputWeights = ToConstTensor(flatBufferInputParams->cellToOutputWeights());
2966 
2967  lstmInputParams.m_CellToForgetWeights = &cellToForgetWeights;
2968  lstmInputParams.m_CellToOutputWeights = &cellToOutputWeights;
2969  }
2970 
2971  armnn::ConstTensor inputLayerNormWeights;
2972  armnn::ConstTensor forgetLayerNormWeights;
2973  armnn::ConstTensor cellLayerNormWeights;
2974  armnn::ConstTensor outputLayerNormWeights;
2975  if (lstmDescriptor.m_LayerNormEnabled)
2976  {
2977  if (!lstmDescriptor.m_CifgEnabled)
2978  {
2979  inputLayerNormWeights = ToConstTensor(flatBufferInputParams->inputLayerNormWeights());
2980  lstmInputParams.m_InputLayerNormWeights = &inputLayerNormWeights;
2981  }
2982  forgetLayerNormWeights = ToConstTensor(flatBufferInputParams->forgetLayerNormWeights());
2983  cellLayerNormWeights = ToConstTensor(flatBufferInputParams->cellLayerNormWeights());
2984  outputLayerNormWeights = ToConstTensor(flatBufferInputParams->outputLayerNormWeights());
2985 
2986  lstmInputParams.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
2987  lstmInputParams.m_CellLayerNormWeights = &cellLayerNormWeights;
2988  lstmInputParams.m_OutputLayerNormWeights = &outputLayerNormWeights;
2989  }
2990 
2991  IConnectableLayer* layer = m_Network->AddLstmLayer(lstmDescriptor, lstmInputParams, layerName.c_str());
2992 
2993  armnn::TensorInfo outputTensorInfo1 = ToTensorInfo(outputs[0]);
2994  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo1);
2995 
2996  armnn::TensorInfo outputTensorInfo2 = ToTensorInfo(outputs[1]);
2997  layer->GetOutputSlot(1).SetTensorInfo(outputTensorInfo2);
2998 
2999  armnn::TensorInfo outputTensorInfo3 = ToTensorInfo(outputs[2]);
3000  layer->GetOutputSlot(2).SetTensorInfo(outputTensorInfo3);
3001 
3002  armnn::TensorInfo outputTensorInfo4 = ToTensorInfo(outputs[3]);
3003  layer->GetOutputSlot(3).SetTensorInfo(outputTensorInfo4);
3004 
3005  RegisterInputSlots(graph, layerIndex, layer);
3006  RegisterOutputSlots(graph, layerIndex, layer);
3007 }
3008 
3010 {
3012 
3013  desc.m_CifgEnabled = qLstmDescriptor->cifgEnabled();
3014  desc.m_PeepholeEnabled = qLstmDescriptor->peepholeEnabled();
3015  desc.m_ProjectionEnabled = qLstmDescriptor->projectionEnabled();
3016  desc.m_LayerNormEnabled = qLstmDescriptor->layerNormEnabled();
3017 
3018  desc.m_CellClip = qLstmDescriptor->cellClip();
3019  desc.m_ProjectionClip = qLstmDescriptor->projectionClip();
3020 
3021  desc.m_InputIntermediateScale = qLstmDescriptor->inputIntermediateScale();
3022  desc.m_ForgetIntermediateScale = qLstmDescriptor->forgetIntermediateScale();
3023  desc.m_CellIntermediateScale = qLstmDescriptor->cellIntermediateScale();
3024  desc.m_OutputIntermediateScale = qLstmDescriptor->outputIntermediateScale();
3025 
3026  desc.m_HiddenStateScale = qLstmDescriptor->hiddenStateScale();
3027  desc.m_HiddenStateZeroPoint = qLstmDescriptor->hiddenStateZeroPoint();
3028 
3029  return desc;
3030 }
3031 
3032 void IDeserializer::DeserializerImpl::ParseQLstm(GraphPtr graph, unsigned int layerIndex)
3033 {
3034  CHECK_LAYERS(graph, 0, layerIndex);
3035 
3036  auto inputs = GetInputs(graph, layerIndex);
3037  CHECK_VALID_SIZE(inputs.size(), 3);
3038 
3039  auto outputs = GetOutputs(graph, layerIndex);
3040  CHECK_VALID_SIZE(outputs.size(), 3);
3041 
3042  auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_QLstmLayer();
3043  auto layerName = GetLayerName(graph, layerIndex);
3044  auto flatBufferDescriptor = flatBufferLayer->descriptor();
3045  auto flatBufferInputParams = flatBufferLayer->inputParams();
3046 
3047  auto qLstmDescriptor = GetQLstmDescriptor(flatBufferDescriptor);
3048  armnn::LstmInputParams qLstmInputParams;
3049 
3050  // Mandatory params
3051  armnn::ConstTensor inputToForgetWeights = ToConstTensor(flatBufferInputParams->inputToForgetWeights());
3052  armnn::ConstTensor inputToCellWeights = ToConstTensor(flatBufferInputParams->inputToCellWeights());
3053  armnn::ConstTensor inputToOutputWeights = ToConstTensor(flatBufferInputParams->inputToOutputWeights());
3054  armnn::ConstTensor recurrentToForgetWeights = ToConstTensor(flatBufferInputParams->recurrentToForgetWeights());
3055  armnn::ConstTensor recurrentToCellWeights = ToConstTensor(flatBufferInputParams->recurrentToCellWeights());
3056  armnn::ConstTensor recurrentToOutputWeights = ToConstTensor(flatBufferInputParams->recurrentToOutputWeights());
3057  armnn::ConstTensor forgetGateBias = ToConstTensor(flatBufferInputParams->forgetGateBias());
3058  armnn::ConstTensor cellBias = ToConstTensor(flatBufferInputParams->cellBias());
3059  armnn::ConstTensor outputGateBias = ToConstTensor(flatBufferInputParams->outputGateBias());
3060 
3061  qLstmInputParams.m_InputToForgetWeights = &inputToForgetWeights;
3062  qLstmInputParams.m_InputToCellWeights = &inputToCellWeights;
3063  qLstmInputParams.m_InputToOutputWeights = &inputToOutputWeights;
3064  qLstmInputParams.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3065  qLstmInputParams.m_RecurrentToCellWeights = &recurrentToCellWeights;
3066  qLstmInputParams.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3067  qLstmInputParams.m_ForgetGateBias = &forgetGateBias;
3068  qLstmInputParams.m_CellBias = &cellBias;
3069  qLstmInputParams.m_OutputGateBias = &outputGateBias;
3070 
3071  // Optional CIFG params
3072  armnn::ConstTensor inputToInputWeights;
3073  armnn::ConstTensor recurrentToInputWeights;
3074  armnn::ConstTensor inputGateBias;
3075 
3076  if (!qLstmDescriptor.m_CifgEnabled)
3077  {
3078  inputToInputWeights = ToConstTensor(flatBufferInputParams->inputToInputWeights());
3079  recurrentToInputWeights = ToConstTensor(flatBufferInputParams->recurrentToInputWeights());
3080  inputGateBias = ToConstTensor(flatBufferInputParams->inputGateBias());
3081 
3082  qLstmInputParams.m_InputToInputWeights = &inputToInputWeights;
3083  qLstmInputParams.m_RecurrentToInputWeights = &recurrentToInputWeights;
3084  qLstmInputParams.m_InputGateBias = &inputGateBias;
3085  }
3086 
3087  // Optional projection params
3088  armnn::ConstTensor projectionWeights;
3089  armnn::ConstTensor projectionBias;
3090 
3091  if (qLstmDescriptor.m_ProjectionEnabled)
3092  {
3093  projectionWeights = ToConstTensor(flatBufferInputParams->projectionWeights());
3094  projectionBias = ToConstTensor(flatBufferInputParams->projectionBias());
3095 
3096  qLstmInputParams.m_ProjectionWeights = &projectionWeights;
3097  qLstmInputParams.m_ProjectionBias = &projectionBias;
3098  }
3099 
3100  // Optional peephole params
3101  armnn::ConstTensor cellToInputWeights;
3102  armnn::ConstTensor cellToForgetWeights;
3103  armnn::ConstTensor cellToOutputWeights;
3104 
3105  if (qLstmDescriptor.m_PeepholeEnabled)
3106  {
3107  if (!qLstmDescriptor.m_CifgEnabled)
3108  {
3109  cellToInputWeights = ToConstTensor(flatBufferInputParams->cellToInputWeights());
3110  qLstmInputParams.m_CellToInputWeights = &cellToInputWeights;
3111  }
3112 
3113  cellToForgetWeights = ToConstTensor(flatBufferInputParams->cellToForgetWeights());
3114  cellToOutputWeights = ToConstTensor(flatBufferInputParams->cellToOutputWeights());
3115 
3116  qLstmInputParams.m_CellToForgetWeights = &cellToForgetWeights;
3117  qLstmInputParams.m_CellToOutputWeights = &cellToOutputWeights;
3118  }
3119 
3120  // Optional layer norm params
3121  armnn::ConstTensor inputLayerNormWeights;
3122  armnn::ConstTensor forgetLayerNormWeights;
3123  armnn::ConstTensor cellLayerNormWeights;
3124  armnn::ConstTensor outputLayerNormWeights;
3125 
3126  if (qLstmDescriptor.m_LayerNormEnabled)
3127  {
3128  if (!qLstmDescriptor.m_CifgEnabled)
3129  {
3130  inputLayerNormWeights = ToConstTensor(flatBufferInputParams->inputLayerNormWeights());
3131  qLstmInputParams.m_InputLayerNormWeights = &inputLayerNormWeights;
3132  }
3133 
3134  forgetLayerNormWeights = ToConstTensor(flatBufferInputParams->forgetLayerNormWeights());
3135  cellLayerNormWeights = ToConstTensor(flatBufferInputParams->cellLayerNormWeights());
3136  outputLayerNormWeights = ToConstTensor(flatBufferInputParams->outputLayerNormWeights());
3137 
3138  qLstmInputParams.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
3139  qLstmInputParams.m_CellLayerNormWeights = &cellLayerNormWeights;
3140  qLstmInputParams.m_OutputLayerNormWeights = &outputLayerNormWeights;
3141  }
3142 
3143  IConnectableLayer* layer = m_Network->AddQLstmLayer(qLstmDescriptor, qLstmInputParams, layerName.c_str());
3144 
3145  armnn::TensorInfo outputStateOutInfo = ToTensorInfo(outputs[0]);
3146  layer->GetOutputSlot(0).SetTensorInfo(outputStateOutInfo);
3147 
3148  armnn::TensorInfo cellStateOutInfo = ToTensorInfo(outputs[1]);
3149  layer->GetOutputSlot(1).SetTensorInfo(cellStateOutInfo);
3150 
3151  armnn::TensorInfo outputInfo = ToTensorInfo(outputs[2]);
3152  layer->GetOutputSlot(2).SetTensorInfo(outputInfo);
3153 
3154  RegisterInputSlots(graph, layerIndex, layer);
3155  RegisterOutputSlots(graph, layerIndex, layer);
3156 }
3157 
3158 void IDeserializer::DeserializerImpl::ParseQuantizedLstm(GraphPtr graph, unsigned int layerIndex)
3159 {
3160  CHECK_LAYERS(graph, 0, layerIndex);
3161 
3162  auto inputs = GetInputs(graph, layerIndex);
3163  CHECK_VALID_SIZE(inputs.size(), 3);
3164 
3165  auto outputs = GetOutputs(graph, layerIndex);
3166  CHECK_VALID_SIZE(outputs.size(), 2);
3167 
3168  auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_QuantizedLstmLayer();
3169  auto layerName = GetLayerName(graph, layerIndex);
3170  auto flatBufferInputParams = flatBufferLayer->inputParams();
3171 
3172  armnn::QuantizedLstmInputParams lstmInputParams;
3173 
3174  armnn::ConstTensor inputToInputWeights = ToConstTensor(flatBufferInputParams->inputToInputWeights());
3175  armnn::ConstTensor inputToForgetWeights = ToConstTensor(flatBufferInputParams->inputToForgetWeights());
3176  armnn::ConstTensor inputToCellWeights = ToConstTensor(flatBufferInputParams->inputToCellWeights());
3177  armnn::ConstTensor inputToOutputWeights = ToConstTensor(flatBufferInputParams->inputToOutputWeights());
3178  armnn::ConstTensor recurrentToInputWeights = ToConstTensor(flatBufferInputParams->recurrentToInputWeights());
3179  armnn::ConstTensor recurrentToForgetWeights = ToConstTensor(flatBufferInputParams->recurrentToForgetWeights());
3180  armnn::ConstTensor recurrentToCellWeights = ToConstTensor(flatBufferInputParams->recurrentToCellWeights());
3181  armnn::ConstTensor recurrentToOutputWeights = ToConstTensor(flatBufferInputParams->recurrentToOutputWeights());
3182  armnn::ConstTensor inputGateBias = ToConstTensor(flatBufferInputParams->inputGateBias());
3183  armnn::ConstTensor forgetGateBias = ToConstTensor(flatBufferInputParams->forgetGateBias());
3184  armnn::ConstTensor cellBias = ToConstTensor(flatBufferInputParams->cellBias());
3185  armnn::ConstTensor outputGateBias = ToConstTensor(flatBufferInputParams->outputGateBias());
3186 
3187  lstmInputParams.m_InputToInputWeights = &inputToInputWeights;
3188  lstmInputParams.m_InputToForgetWeights = &inputToForgetWeights;
3189  lstmInputParams.m_InputToCellWeights = &inputToCellWeights;
3190  lstmInputParams.m_InputToOutputWeights = &inputToOutputWeights;
3191  lstmInputParams.m_RecurrentToInputWeights = &recurrentToInputWeights;
3192  lstmInputParams.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3193  lstmInputParams.m_RecurrentToCellWeights = &recurrentToCellWeights;
3194  lstmInputParams.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3195  lstmInputParams.m_InputGateBias = &inputGateBias;
3196  lstmInputParams.m_ForgetGateBias = &forgetGateBias;
3197  lstmInputParams.m_CellBias = &cellBias;
3198  lstmInputParams.m_OutputGateBias = &outputGateBias;
3199 
3200  IConnectableLayer* layer = m_Network->AddQuantizedLstmLayer(lstmInputParams, layerName.c_str());
3201 
3202  armnn::TensorInfo outputTensorInfo1 = ToTensorInfo(outputs[0]);
3203  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo1);
3204 
3205  armnn::TensorInfo outputTensorInfo2 = ToTensorInfo(outputs[1]);
3206  layer->GetOutputSlot(1).SetTensorInfo(outputTensorInfo2);
3207 
3208  RegisterInputSlots(graph, layerIndex, layer);
3209  RegisterOutputSlots(graph, layerIndex, layer);
3210 }
3211 
3212 void IDeserializer::DeserializerImpl::ParseDequantize(GraphPtr graph, unsigned int layerIndex)
3213 {
3214  CHECK_LAYERS(graph, 0, layerIndex);
3215 
3216  TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
3217  CHECK_VALID_SIZE(inputs.size(), 1);
3218 
3219  TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
3220  CHECK_VALID_SIZE(outputs.size(), 1);
3221 
3222  const std::string layerName = GetLayerName(graph, layerIndex);
3223  IConnectableLayer* layer = m_Network->AddDequantizeLayer(layerName.c_str());
3224 
3225  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
3226  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
3227 
3228  RegisterInputSlots(graph, layerIndex, layer);
3229  RegisterOutputSlots(graph, layerIndex, layer);
3230 }
3231 
3232 void IDeserializer::DeserializerImpl::ParseMerge(GraphPtr graph, unsigned int layerIndex)
3233 {
3234  CHECK_LAYERS(graph, 0, layerIndex);
3235 
3236  TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
3237  CHECK_VALID_SIZE(inputs.size(), 2);
3238 
3239  TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
3240  CHECK_VALID_SIZE(outputs.size(), 1);
3241 
3242  const std::string layerName = GetLayerName(graph, layerIndex);
3243  IConnectableLayer* layer = m_Network->AddMergeLayer(layerName.c_str());
3244 
3245  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
3246  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
3247 
3248  RegisterInputSlots(graph, layerIndex, layer);
3249  RegisterOutputSlots(graph, layerIndex, layer);
3250 }
3251 
3252 void IDeserializer::DeserializerImpl::ParseSwitch(GraphPtr graph, unsigned int layerIndex)
3253 {
3254  CHECK_LAYERS(graph, 0, layerIndex);
3255  auto inputs = GetInputs(graph, layerIndex);
3256  CHECK_LOCATION();
3257  CHECK_VALID_SIZE(inputs.size(), 2);
3258 
3259  auto outputs = GetOutputs(graph, layerIndex);
3260  CHECK_VALID_SIZE(outputs.size(), 2);
3261 
3262  auto layerName = GetLayerName(graph, layerIndex);
3263  IConnectableLayer* layer = m_Network->AddSwitchLayer(layerName.c_str());
3264 
3265  armnn::TensorInfo output0TensorInfo = ToTensorInfo(outputs[0]);
3266  layer->GetOutputSlot(0).SetTensorInfo(output0TensorInfo);
3267 
3268  armnn::TensorInfo output1TensorInfo = ToTensorInfo(outputs[1]);
3269  layer->GetOutputSlot(1).SetTensorInfo(output1TensorInfo);
3270 
3271  RegisterInputSlots(graph, layerIndex, layer);
3272  RegisterOutputSlots(graph, layerIndex, layer);
3273 }
3274 
3275 void IDeserializer::DeserializerImpl::ParsePrelu(GraphPtr graph, unsigned int layerIndex)
3276 {
3277  CHECK_LAYERS(graph, 0, layerIndex);
3278  auto inputs = GetInputs(graph, layerIndex);
3279  CHECK_LOCATION();
3280  CHECK_VALID_SIZE(inputs.size(), 2);
3281 
3282  auto outputs = GetOutputs(graph, layerIndex);
3283  CHECK_VALID_SIZE(outputs.size(), 1);
3284 
3285  auto layerName = GetLayerName(graph, layerIndex);
3286  IConnectableLayer* layer = m_Network->AddPreluLayer(layerName.c_str());
3287 
3288  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
3289  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
3290 
3291  RegisterInputSlots(graph, layerIndex, layer);
3292  RegisterOutputSlots(graph, layerIndex, layer);
3293 }
3294 
3295 void IDeserializer::DeserializerImpl::ParseTranspose(GraphPtr graph, unsigned int layerIndex)
3296 {
3297  CHECK_LAYERS(graph, 0, layerIndex);
3298 
3299  auto dimsMapping = graph->layers()->Get(layerIndex)->layer_as_TransposeLayer()->descriptor()->dimMappings();
3300 
3301  auto inputs = GetInputs(graph, layerIndex);
3302  CHECK_VALID_SIZE(inputs.size(), 1);
3303 
3304  auto outputs = GetOutputs(graph, layerIndex);
3305  CHECK_VALID_SIZE(outputs.size(), 1);
3306  auto outputInfo = ToTensorInfo(outputs[0]);
3307 
3308  auto layerName = GetLayerName(graph, layerIndex);
3309  const armnn::TransposeDescriptor descriptor(armnn::PermutationVector(dimsMapping->data(), dimsMapping->Length()));
3310 
3311  IConnectableLayer* layer = m_Network->AddTransposeLayer(descriptor, layerName.c_str());
3312  layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
3313 
3314  RegisterInputSlots(graph, layerIndex, layer);
3315  RegisterOutputSlots(graph, layerIndex, layer);
3316 }
3317 
3318 void IDeserializer::DeserializerImpl::ParseTransposeConvolution2d(GraphPtr graph, unsigned int layerIndex)
3319 {
3320  CHECK_LAYERS(graph, 0, layerIndex);
3321 
3322  auto inputs = GetInputs(graph, layerIndex);
3323  CHECK_VALID_SIZE(inputs.size(), 1);
3324 
3325  auto outputs = GetOutputs(graph, layerIndex);
3326  CHECK_VALID_SIZE(outputs.size(), 1);
3327 
3328  auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_TransposeConvolution2dLayer();
3329  auto layerName = GetLayerName(graph, layerIndex);
3330  auto serializerDescriptor = serializerLayer->descriptor();
3331 
3333  descriptor.m_PadLeft = serializerDescriptor->padLeft();
3334  descriptor.m_PadRight = serializerDescriptor->padRight();
3335  descriptor.m_PadTop = serializerDescriptor->padTop();
3336  descriptor.m_PadBottom = serializerDescriptor->padBottom();
3337  descriptor.m_StrideX = serializerDescriptor->strideX();
3338  descriptor.m_StrideY = serializerDescriptor->strideY();;
3339  descriptor.m_BiasEnabled = serializerDescriptor->biasEnabled();;
3340  descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
3341 
3342  // weights & biases
3343  armnn::ConstTensor weights = ToConstTensor(serializerLayer->weights());
3344  armnn::Optional<armnn::ConstTensor> optionalBiases;
3345  if (descriptor.m_BiasEnabled)
3346  {
3347  armnn::ConstTensor biases = ToConstTensor(serializerLayer->biases());
3348  optionalBiases = armnn::MakeOptional<armnn::ConstTensor>(biases);
3349  }
3350 
3351  IConnectableLayer* layer = m_Network->AddTransposeConvolution2dLayer(descriptor,
3352  weights,
3353  optionalBiases,
3354  layerName.c_str());
3355 
3356  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
3357  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
3358 
3359  RegisterInputSlots(graph, layerIndex, layer);
3360  RegisterOutputSlots(graph, layerIndex, layer);
3361 }
3362 
3363 void IDeserializer::DeserializerImpl::ParseStack(GraphPtr graph, unsigned int layerIndex)
3364 {
3365  CHECK_LAYERS(graph, 0, layerIndex);
3366  auto inputs = GetInputs(graph, layerIndex);
3367 
3368  auto outputs = GetOutputs(graph, layerIndex);
3369  CHECK_VALID_SIZE(outputs.size(), 1);
3370 
3371  auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_StackLayer()->descriptor();
3372  unsigned int axis = flatBufferDescriptor->axis();
3373  unsigned int numInputs = flatBufferDescriptor->numInputs();
3374  CHECK_VALID_SIZE(inputs.size(), numInputs);
3375 
3376  auto flatBufferInputShape = flatBufferDescriptor->inputShape();
3377  std::vector<uint32_t> vectorInputShape(flatBufferInputShape->begin(),
3378  flatBufferInputShape->begin() + flatBufferInputShape->size());
3379 
3380  TensorShape inputShape(static_cast<unsigned int>(vectorInputShape.size()), vectorInputShape.data());
3381  armnn::StackDescriptor descriptor(axis, numInputs, inputShape);
3382 
3383  for (unsigned int i=0; i<inputs.size(); ++i)
3384  {
3385  armnn::TensorShape inputShape = ToTensorInfo(inputs[i]).GetShape();
3386  if (descriptor.m_InputShape != inputShape)
3387  {
3388  std::stringstream ss;
3389  ss << "Shape of input "
3390  << i
3391  << " "
3392  << inputShape
3393  << " does not equal defined input shape "
3394  << descriptor.m_InputShape
3395  << ": "
3396  << CHECK_LOCATION().AsString();
3397  throw ParseException(ss.str());
3398  }
3399  }
3400 
3401  auto layerName = GetLayerName(graph, layerIndex);
3402  IConnectableLayer* layer = m_Network->AddStackLayer(descriptor, layerName.c_str());
3403 
3404  armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
3405  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
3406 
3407  RegisterInputSlots(graph, layerIndex, layer);
3408  RegisterOutputSlots(graph, layerIndex, layer);
3409 }
3410 
3411 void IDeserializer::DeserializerImpl::ParseStandIn(GraphPtr graph, unsigned int layerIndex)
3412 {
3413  CHECK_LAYERS(graph, 0, layerIndex);
3414 
3415  auto inputs = GetInputs(graph, layerIndex);
3416  auto outputs = GetOutputs(graph, layerIndex);
3417 
3418  auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_StandInLayer();
3419  auto fbDescriptor = fbLayer->descriptor();
3420 
3421  armnn::StandInDescriptor descriptor;
3422  descriptor.m_NumInputs = fbDescriptor->numInputs();
3423  descriptor.m_NumOutputs = fbDescriptor->numOutputs();
3424 
3425  CHECK_VALID_SIZE(inputs.size(), descriptor.m_NumInputs);
3426  CHECK_VALID_SIZE(outputs.size(), descriptor.m_NumOutputs);
3427 
3428  const std::string layerName = GetLayerName(graph, layerIndex);
3429  armnn::IConnectableLayer* layer = m_Network->AddStandInLayer(descriptor, layerName.c_str());
3430 
3431  for (unsigned int i = 0u; i < descriptor.m_NumOutputs; ++i)
3432  {
3433  armnn::TensorInfo outputInfo = ToTensorInfo(outputs[i]);
3434  layer->GetOutputSlot(i).SetTensorInfo(outputInfo);
3435  }
3436 
3437  RegisterInputSlots(graph, layerIndex, layer);
3438  RegisterOutputSlots(graph, layerIndex, layer);
3439 }
3440 
3443 {
3445 
3446  desc.m_ActivationFunc = descriptor->activationFunc();
3447  desc.m_ClippingThresCell = descriptor->clippingThresCell();
3448  desc.m_ClippingThresProj = descriptor->clippingThresProj();
3449  desc.m_CifgEnabled = descriptor->cifgEnabled();
3450  desc.m_PeepholeEnabled = descriptor->peepholeEnabled();
3451  desc.m_ProjectionEnabled = descriptor->projectionEnabled();
3452  desc.m_LayerNormEnabled = descriptor->layerNormEnabled();
3453  desc.m_TimeMajor = descriptor->timeMajor();
3454 
3455  return desc;
3456 }
3457 
3458 void IDeserializer::DeserializerImpl::ParseUnidirectionalSequenceLstm(GraphPtr graph, unsigned int layerIndex)
3459 {
3460  CHECK_LAYERS(graph, 0, layerIndex);
3461 
3462  auto inputs = GetInputs(graph, layerIndex);
3463  CHECK_VALID_SIZE(inputs.size(), 3);
3464 
3465  auto outputs = GetOutputs(graph, layerIndex);
3466  CHECK_VALID_SIZE(outputs.size(), 1);
3467 
3468  auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_UnidirectionalSequenceLstmLayer();
3469  auto layerName = GetLayerName(graph, layerIndex);
3470  auto flatBufferDescriptor = flatBufferLayer->descriptor();
3471  auto flatBufferInputParams = flatBufferLayer->inputParams();
3472 
3473  auto descriptor = GetUnidirectionalSequenceLstmDescriptor(flatBufferDescriptor);
3474 
3475  armnn::LstmInputParams lstmInputParams;
3476 
3477  armnn::ConstTensor inputToForgetWeights = ToConstTensor(flatBufferInputParams->inputToForgetWeights());
3478  armnn::ConstTensor inputToCellWeights = ToConstTensor(flatBufferInputParams->inputToCellWeights());
3479  armnn::ConstTensor inputToOutputWeights = ToConstTensor(flatBufferInputParams->inputToOutputWeights());
3480  armnn::ConstTensor recurrentToForgetWeights = ToConstTensor(flatBufferInputParams->recurrentToForgetWeights());
3481  armnn::ConstTensor recurrentToCellWeights = ToConstTensor(flatBufferInputParams->recurrentToCellWeights());
3482  armnn::ConstTensor recurrentToOutputWeights = ToConstTensor(flatBufferInputParams->recurrentToOutputWeights());
3483  armnn::ConstTensor forgetGateBias = ToConstTensor(flatBufferInputParams->forgetGateBias());
3484  armnn::ConstTensor cellBias = ToConstTensor(flatBufferInputParams->cellBias());
3485  armnn::ConstTensor outputGateBias = ToConstTensor(flatBufferInputParams->outputGateBias());
3486 
3487  lstmInputParams.m_InputToForgetWeights = &inputToForgetWeights;
3488  lstmInputParams.m_InputToCellWeights = &inputToCellWeights;
3489  lstmInputParams.m_InputToOutputWeights = &inputToOutputWeights;
3490  lstmInputParams.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
3491  lstmInputParams.m_RecurrentToCellWeights = &recurrentToCellWeights;
3492  lstmInputParams.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
3493  lstmInputParams.m_ForgetGateBias = &forgetGateBias;
3494  lstmInputParams.m_CellBias = &cellBias;
3495  lstmInputParams.m_OutputGateBias = &outputGateBias;
3496 
3497  armnn::ConstTensor inputToInputWeights;
3498  armnn::ConstTensor recurrentToInputWeights;
3499  armnn::ConstTensor cellToInputWeights;
3500  armnn::ConstTensor inputGateBias;
3501  if (!descriptor.m_CifgEnabled)
3502  {
3503  inputToInputWeights = ToConstTensor(flatBufferInputParams->inputToInputWeights());
3504  recurrentToInputWeights = ToConstTensor(flatBufferInputParams->recurrentToInputWeights());
3505  inputGateBias = ToConstTensor(flatBufferInputParams->inputGateBias());
3506 
3507  lstmInputParams.m_InputToInputWeights = &inputToInputWeights;
3508  lstmInputParams.m_RecurrentToInputWeights = &recurrentToInputWeights;
3509  lstmInputParams.m_InputGateBias = &inputGateBias;
3510 
3511  if (descriptor.m_PeepholeEnabled)
3512  {
3513  cellToInputWeights = ToConstTensor(flatBufferInputParams->cellToInputWeights());
3514  lstmInputParams.m_CellToInputWeights = &cellToInputWeights;
3515  }
3516  }
3517 
3518  armnn::ConstTensor projectionWeights;
3519  armnn::ConstTensor projectionBias;
3520  if (descriptor.m_ProjectionEnabled)
3521  {
3522  projectionWeights = ToConstTensor(flatBufferInputParams->projectionWeights());
3523  projectionBias = ToConstTensor(flatBufferInputParams->projectionBias());
3524 
3525  lstmInputParams.m_ProjectionWeights = &projectionWeights;
3526  lstmInputParams.m_ProjectionBias = &projectionBias;
3527  }
3528 
3529  armnn::ConstTensor cellToForgetWeights;
3530  armnn::ConstTensor cellToOutputWeights;
3531  if (descriptor.m_PeepholeEnabled)
3532  {
3533  cellToForgetWeights = ToConstTensor(flatBufferInputParams->cellToForgetWeights());
3534  cellToOutputWeights = ToConstTensor(flatBufferInputParams->cellToOutputWeights());
3535 
3536  lstmInputParams.m_CellToForgetWeights = &cellToForgetWeights;
3537  lstmInputParams.m_CellToOutputWeights = &cellToOutputWeights;
3538  }
3539 
3540  armnn::ConstTensor inputLayerNormWeights;
3541  armnn::ConstTensor forgetLayerNormWeights;
3542  armnn::ConstTensor cellLayerNormWeights;
3543  armnn::ConstTensor outputLayerNormWeights;
3544  if (descriptor.m_LayerNormEnabled)
3545  {
3546  if (!descriptor.m_CifgEnabled)
3547  {
3548  inputLayerNormWeights = ToConstTensor(flatBufferInputParams->inputLayerNormWeights());
3549  lstmInputParams.m_InputLayerNormWeights = &inputLayerNormWeights;
3550  }
3551  forgetLayerNormWeights = ToConstTensor(flatBufferInputParams->forgetLayerNormWeights());
3552  cellLayerNormWeights = ToConstTensor(flatBufferInputParams->cellLayerNormWeights());
3553  outputLayerNormWeights = ToConstTensor(flatBufferInputParams->outputLayerNormWeights());
3554 
3555  lstmInputParams.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
3556  lstmInputParams.m_CellLayerNormWeights = &cellLayerNormWeights;
3557  lstmInputParams.m_OutputLayerNormWeights = &outputLayerNormWeights;
3558  }
3559 
3560  IConnectableLayer* layer = m_Network->AddUnidirectionalSequenceLstmLayer(descriptor,
3561  lstmInputParams,
3562  layerName.c_str());
3563 
3564  armnn::TensorInfo outputTensorInfo1 = ToTensorInfo(outputs[0]);
3565  layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo1);
3566 
3567  RegisterInputSlots(graph, layerIndex, layer);
3568  RegisterOutputSlots(graph, layerIndex, layer);
3569 }
3570 
3571 } // namespace armnnDeserializer
static armnn::NormalizationDescriptor GetNormalizationDescriptor(NormalizationDescriptorPtr normalizationDescriptor, unsigned int layerIndex)
uint32_t m_PadBottom
Padding bottom value in the height dimension.
bool m_BiasEnabled
Enable/disable bias.
float m_Eps
Used to avoid dividing by zero.
virtual unsigned int GetNumOutputSlots() const =0
Returns the number of connectable output slots.
armnn::LogicalBinaryOperation ToLogicalBinaryOperation(armnnSerializer::LogicalBinaryOperation operation)
bool m_ProjectionEnabled
Enable/disable the projection layer.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
const ConstTensor * m_ProjectionWeights
Definition: LstmParams.hpp:55
UnaryOperation m_Operation
Specifies the elementwiseUnary operation to execute.
static TensorRawPtrVector GetOutputs(const GraphPtr &graph, unsigned int layerIndex)
A ViewsDescriptor for the SplitterLayer.
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:61
float m_ScaleW
Center size encoding scale weight.
#define CHECK_LAYERS(GRAPH, LAYERS_INDEX, LAYER_INDEX)
const ConstTensor * m_CellBias
Definition: LstmParams.hpp:53
uint32_t m_PadBottom
Padding bottom value in the height dimension.
bool m_BiasEnabled
Enable/disable bias.
armnn::ReduceOperation ToReduceOperation(armnnSerializer::ReduceOperation operation)
virtual unsigned int GetNumInputSlots() const =0
Returns the number of connectable input slots.
DataLayout
Definition: Types.hpp:49
float m_K
Kappa value used for the across channel normalization equation.
A TransposeConvolution2dDescriptor for the TransposeConvolution2dLayer.
const TensorShape & GetShape() const
Definition: Tensor.hpp:191
const ConstTensor * m_RecurrentToOutputWeights
uint32_t m_PadBottom
Padding bottom value in the height dimension.
uint32_t m_PadLeft
Padding left value in the width dimension.
float m_ClippingThresProj
Clipping threshold value for the projection.
std::string AsString() const
Definition: Exceptions.hpp:29
static LayerBaseRawPtr GetBaseLayer(const GraphPtr &graphPtr, unsigned int layerIndex)
A ReshapeDescriptor for the ReshapeLayer.
const armnnSerializer::ConstTensor * ConstTensorRawPtr
const ConstTensor * m_CellToOutputWeights
Definition: LstmParams.hpp:50
uint32_t m_PadBack
Padding back value in the depth dimension.
const ConstTensor * m_RecurrentToForgetWeights
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
const armnnSerializer::NormalizationDescriptor * NormalizationDescriptorPtr
A ComparisonDescriptor for the ComparisonLayer.
Definition: Descriptors.hpp:78
static GraphPtr LoadGraphFromBinary(const uint8_t *binaryContent, size_t len)
float m_ScaleX
Center size encoding scale x.
bool m_TransposeWeightMatrix
Enable/disable transpose weight matrix.
uint32_t m_PoolWidth
Pooling width value.
bool m_PeepholeEnabled
Enable/disable peephole.
#define CHECK_TENSOR_PTR(TENSOR_PTR)
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
A Convolution2dDescriptor for the Convolution2dLayer.
float m_Alpha
Alpha value for the normalization equation.
uint32_t m_PadLeft
Padding left value in the width dimension.
const armnnSerializer::QLstmDescriptor * QLstmDescriptorPtr
static armnn::UnidirectionalSequenceLstmDescriptor GetUnidirectionalSequenceLstmDescriptor(UnidirectionalSequenceLstmDescriptorPtr descriptor)
bool m_KeepDims
if true then output shape has no change.
float m_HiddenStateScale
Hidden State quantization scale.
const char * EnumNameConstTensorData(ConstTensorData e)
bool m_BiasEnabled
Enable/disable bias.
const ConstTensor * m_CellToInputWeights
Definition: LstmParams.hpp:48
unsigned int GetNumBytes() const
Definition: Tensor.cpp:429
float m_OutputIntermediateScale
Output intermediate quantization scale.
ResizeMethod m_Method
The Interpolation method to use (Bilinear, NearestNeighbor).
float m_Gamma
Gamma, the scale scalar value applied for the normalized tensor. Defaults to 1.0. ...
float m_Beta
Exponentiation value.
BindingPointInfo GetNetworkInputBindingInfo(unsigned int layerId, const std::string &name) const
Retrieve binding info (layer id and tensor info) for the network input identified by the given layer ...
std::vector< unsigned int > m_Size
Size of the slice in each dimension.
armnn::INetworkPtr CreateNetworkFromBinary(const std::vector< uint8_t > &binaryContent)
Create an input network from binary file contents.
The padding fields don&#39;t count and are ignored.
float m_Eps
Value to add to the variance. Used to avoid dividing by zero.
const ConstTensor * m_InputGateBias
Definition: LstmParams.hpp:51
PaddingMethod m_PaddingMethod
The padding method to be used. (Exclude, IgnoreValue).
ArgMinMaxFunction m_Function
Specify if the function is to find Min or Max.
Definition: Descriptors.hpp:70
uint32_t m_DetectionsPerClass
Detections per classes, used in Regular NMS.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
void CheckLayers(Graph &graph)
const armnnSerializer::SerializedGraph * GetSerializedGraph(const void *buf)
uint32_t m_PadTop
Padding top value in the height dimension.
const ConstTensor * m_RecurrentToCellWeights
Definition: LstmParams.hpp:46
uint32_t m_PadBottom
Padding bottom value in the height dimension.
bool m_BiasEnabled
Enable/disable bias.
A LogicalBinaryDescriptor for the LogicalBinaryLayer.
uint32_t m_PadRight
Padding right value in the width dimension.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
const ConstTensor * m_ForgetLayerNormWeights
Definition: LstmParams.hpp:58
ReduceOperation m_ReduceOperation
Specifies the reduction operation to execute.
const ConstTensor * m_CellToForgetWeights
Definition: LstmParams.hpp:49
bool m_TimeMajor
Enable/disable time major.
Copyright (c) 2021 ARM Limited and Contributors.
void IgnoreUnused(Ts &&...)
uint32_t m_PadBottom
Padding bottom value in the height dimension.
#define CHECK_GRAPH(GRAPH, LAYERS_INDEX)
uint32_t m_DilationY
Dilation along y axis.
A SpaceToDepthDescriptor for the SpaceToDepthLayer.
const armnnSerializer::SerializedGraph * GraphPtr
std::vector< std::pair< unsigned int, unsigned int > > m_PadList
Specifies the padding values for the input dimension: heightPad{top, bottom} widthPad{left, right}.
uint32_t m_DilationX
Dilation along x axis.
uint32_t m_DilationY
Dilation factor value for height dimension.
LogicalBinaryOperation m_Operation
Specifies the logical operation to execute.
A BatchToSpaceNdDescriptor for the BatchToSpaceNdLayer.
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
LogicalBinaryOperation
Definition: Types.hpp:105
int LayerBindingId
Type of identifiers for bindable layers (inputs, outputs).
Definition: Types.hpp:277
const ConstTensor * m_OutputGateBias
Definition: LstmParams.hpp:54
armnn::ComparisonOperation ToComparisonOperation(armnnSerializer::ComparisonOperation operation)
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
static int32_t GetBindingLayerInfo(const GraphPtr &graphPtr, unsigned int layerIndex)
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
uint32_t m_NumOutputs
Number of output tensors.
NormalizationAlgorithmMethod m_NormMethodType
Normalization method algorithm to use (LocalBrightness, LocalContrast).
void SetShape(const TensorShape &newShape)
Definition: Tensor.hpp:193
A ResizeBilinearDescriptor for the ResizeBilinearLayer.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
uint32_t m_MaxClassesPerDetection
Maximum numbers of classes per detection, used in Fast NMS.
const armnnSerializer::LayerBase * LayerBaseRawPtr
std::vector< unsigned int > m_Axis
Values for the dimensions to reduce.
A StackDescriptor for the StackLayer.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
TensorShape m_TargetShape
Target shape value.
uint32_t m_PoolHeight
Pooling height value.
uint32_t m_PadTop
Padding top value in the height dimension.
uint32_t m_MaxDetections
Maximum numbers of detections.
A PadDescriptor for the PadLayer.
std::vector< TensorRawPtr > TensorRawPtrVector
void Permute(const armnn::TensorShape &dstShape, const armnn::PermutationVector &mappings, const void *src, void *dst, size_t dataTypeSize)
Definition: Permute.cpp:131
#define CHECK_CONST_TENSOR_SIZE(CONST_TENSOR_SIZE, TENSOR_SIZE)
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
const armnnSerializer::UnidirectionalSequenceLstmDescriptor * UnidirectionalSequenceLstmDescriptorPtr
const ConstTensor * m_InputLayerNormWeights
Definition: LstmParams.hpp:57
ComparisonOperation
Definition: Types.hpp:95
armnn::INetworkPtr CreateNetworkFromBinary(const std::vector< uint8_t > &binaryContent)
Create an input network from binary file contents.
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
ReduceOperation
Definition: Types.hpp:130
bool m_LayerNormEnabled
Enable/disable layer normalization.
const armnnSerializer::LstmDescriptor * LstmDescriptorPtr
armnn::DataLayout ToDataLayout(armnnSerializer::DataLayout dataLayout)
bool CheckShape(const armnn::TensorShape &actual, const std::vector< uint32_t > &expected)
DataType
Definition: Types.hpp:35
float m_NmsIouThreshold
Intersection over union threshold.
const ConstTensor * m_RecurrentToOutputWeights
Definition: LstmParams.hpp:47
static armnn::LstmDescriptor GetLstmDescriptor(LstmDescriptorPtr lstmDescriptor)
An LstmDescriptor for the LstmLayer.
uint32_t m_PadRight
Padding right value in the width dimension.
uint32_t m_DilationX
Dilation factor value for width dimension.
uint32_t m_PadTop
Padding top value in the height dimension.
std::string FileLine() const
Definition: Exceptions.hpp:37
Status SetViewSize(uint32_t view, uint32_t coord, uint32_t value)
Set the size of the views.
#define ARMNN_ASSERT_MSG(COND, MSG)
Definition: Assert.hpp:15
std::vector< unsigned int > m_Begin
Beginning indices of the slice in each dimension.
bool m_KeepDims
Enable/disable keep dimensions. If true, then the reduced dimensions that are of length 1 are kept...
std::vector< unsigned int > m_BlockShape
Block shape values.
float m_Eps
Epsilon, small scalar value added to variance to avoid dividing by zero. Defaults to 1e-12f...
An output connection slot for a layer.
Definition: INetwork.hpp:37
A L2NormalizationDescriptor for the L2NormalizationLayer.
const ConstTensor * m_ProjectionBias
Definition: LstmParams.hpp:56
static TensorRawPtrVector GetInputs(const GraphPtr &graph, unsigned int layerIndex)
const ConstTensor * m_InputToForgetWeights
An ArgMinMaxDescriptor for ArgMinMaxLayer.
Definition: Descriptors.hpp:56
An OriginsDescriptor for the ConcatLayer.
A ReduceDescriptor for the REDUCE operators.
float m_ProjectionClip
Clipping threshold value for the projection.
A FullyConnectedDescriptor for the FullyConnectedLayer.
BindingPointInfo GetNetworkOutputBindingInfo(unsigned int layerId, const std::string &name) const
Retrieve binding info (layer id and tensor info) for the network output identified by the given layer...
bool m_BiasEnabled
Enable/disable bias.
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:327
float m_InputIntermediateScale
Input intermediate quantization scale.
static armnn::Pooling2dDescriptor GetPoolingDescriptor(PoolingDescriptor pooling2dDescriptor, unsigned int layerIndex)
uint32_t m_TargetWidth
Target width value.
A GatherDescriptor for the GatherLayer.
#define CHECK_VALID_SIZE(ACTUAL,...)
bool m_PeepholeEnabled
Enable/disable peephole.
uint32_t m_NumClasses
Number of classes.
#define CHECKED_NON_NEGATIVE(VALUE)
bool m_HalfPixelCenters
Half Pixel Centers.
std::unique_ptr< IDeserializer, void(*)(IDeserializer *parser)> IDeserializerPtr
armnn::ConstTensor ToConstTensor(ConstTensorRawPtr constTensorPtr)
armnn::ActivationFunction ToActivationFunction(armnnSerializer::ActivationFunction function)
uint32_t m_PadTop
Padding top value in the height dimension.
armnn::UnaryOperation ToUnaryOperation(armnnSerializer::UnaryOperation operation)
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
A StandInDescriptor for the StandIn layer.
A QLstmDescriptor for the QLstmLayer.
#define CHECK_CONST_TENSOR_PTR(TENSOR_PTR)
bool m_UseRegularNms
Use Regular NMS.
uint32_t m_PadFront
Padding front value in the depth dimension.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
std::vector< unsigned int > m_BlockShape
Block shape value.
PaddingMode
The padding mode controls whether the padding should be filled with constant values (Constant)...
Definition: Types.hpp:173
An ActivationDescriptor for the ActivationLayer.
Definition: Descriptors.hpp:25
const TensorInfo & GetInfo() const
Definition: Tensor.hpp:295
min(a, max(b, input)) ReLu1 & ReLu6.
#define CHECK_LOCATION()
Definition: Exceptions.hpp:209
uint32_t m_PadLeft
Padding left value in the width dimension.
uint32_t m_TargetHeight
Target height value.
uint32_t m_ActivationFunc
The activation function to use.
A SliceDescriptor for the SliceLayer.
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
A Convolution3dDescriptor for the Convolution3dLayer.
uint32_t m_PadRight
Padding right value in the width dimension.
const ConstTensor * m_RecurrentToInputWeights
float m_ClippingThresCell
Clipping threshold value for the cell state.
unsigned int m_BlockSize
Scalar specifying the input block size. It must be >= 1.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
float m_ForgetIntermediateScale
Forget intermediate quantization scale.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
float m_Beta
Beta, the offset scalar value applied for the normalized tensor. Defaults to 1.0. ...
armnn::ResizeMethod ToResizeMethod(armnnSerializer::ResizeMethod method)
armnn::PaddingMode ToPaddingMode(armnnSerializer::PaddingMode paddingMode)
std::vector< uint32_t > m_vAxis
The indices of the dimensions to reduce.
float m_ScaleH
Center size encoding scale height.
ComparisonOperation m_Operation
Specifies the comparison operation to execute.
Definition: Descriptors.hpp:94
const ConstTensor * m_CellLayerNormWeights
Definition: LstmParams.hpp:59
const ConstTensor * m_ForgetGateBias
Definition: LstmParams.hpp:52
A SpaceToBatchNdDescriptor for the SpaceToBatchNdLayer.
const ConstTensor * m_InputToCellWeights
Definition: LstmParams.hpp:42
DataLayout m_DataLayout
The data layout to be used (NDHWC, NCDHW).
const ConstTensor * m_InputToOutputWeights
Definition: LstmParams.hpp:43
NormalizationAlgorithmChannel m_NormChannelType
Normalization channel algorithm to use (Across, Within).
float m_CellClip
Clipping threshold value for the cell state.
float m_A
Alpha upper bound value used by the activation functions. (BoundedReLu, Linear, TanH, Elu).
Definition: Descriptors.hpp:50
uint32_t m_DilationX
Dilation along x axis.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
const armnnSerializer::TensorInfo * TensorRawPtr
bool m_CifgEnabled
Enable/disable cifg (coupled input & forget gate).
armnn::ArgMinMaxFunction ToArgMinMaxFunction(armnnSerializer::ArgMinMaxFunction function)
uint32_t GetNumInputs() const
Get the number of views/inputs.
uint32_t m_PadLeft
Padding left value in the width dimension.
EmptyOptional is used to initialize the Optional class in case we want to have default value for an O...
Definition: Optional.hpp:32
bool m_AlignCorners
Aligned corners.
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
int32_t m_Axis
The axis in params to gather indices from.
A ElementwiseUnaryDescriptor for the ElementwiseUnaryLayer.
Definition: Descriptors.hpp:98
PoolingAlgorithm m_PoolType
The pooling algorithm to use (Max. Average, L2).
const ConstTensor * m_RecurrentToForgetWeights
Definition: LstmParams.hpp:45
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
The padding fields count, but are ignored.
std::vector< std::pair< unsigned int, unsigned int > > m_Crops
The values to crop from the input dimension.
Base class for all ArmNN exceptions so that users can filter to just those.
Definition: Exceptions.hpp:46
static std::string GetLayerName(const GraphPtr &graph, unsigned int index)
uint32_t m_PadTop
Padding top value in the height dimension.
unsigned int GetNumDimensions() const
Function that returns the tensor rank.
Definition: Tensor.cpp:174
bool m_ProjectionEnabled
Enable/disable the projection layer.
Jarret 2009: Local Contrast Normalization.
ArgMinMaxFunction
Definition: Types.hpp:89
OutputShapeRounding m_OutputShapeRounding
The rounding method for the output shape. (Floor, Ceiling).
uint32_t m_NumInputs
Number of input tensors.
const ConstTensor * m_RecurrentToCellWeights
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
ResizeMethod
Definition: Types.hpp:139
const ConstTensor * m_RecurrentToInputWeights
Definition: LstmParams.hpp:44
A MeanDescriptor for the MeanLayer.
void SetConstant(const bool IsConstant=true)
Marks the data corresponding to this tensor info as constant.
Definition: Tensor.cpp:516
const ConstTensor * m_InputToOutputWeights
UnaryOperation
Definition: Types.hpp:111
static armnn::QLstmDescriptor GetQLstmDescriptor(QLstmDescriptorPtr qLstmDescriptorPtr)
static armnn::TensorInfo OutputShapeOfReshape(const armnn::TensorInfo &inputTensorInfo, const std::vector< uint32_t > &targetDimsIn)
bool m_LayerNormEnabled
Enable/disable layer normalization.
std::enable_if_t< std::is_unsigned< Source >::value &&std::is_unsigned< Dest >::value, Dest > numeric_cast(Source source)
Definition: NumericCast.hpp:35
armnn::TensorInfo ToTensorInfo(TensorRawPtr tensorPtr)
uint32_t m_PadRight
Padding right value in the width dimension.
A TransposeDescriptor for the TransposeLayer.
A StridedSliceDescriptor for the StridedSliceLayer.
uint32_t m_Axis
Axis to apply channel shuffle operation on.
uint32_t GetNumInputs() const
Get the number of views/inputs.
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
int m_Axis
Axis to reduce across the input tensor.
Definition: Descriptors.hpp:72
float m_ScaleY
Center size encoding scale y.
float m_NmsScoreThreshold
NMS score threshold.
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
Definition: INetwork.hpp:197
virtual int Connect(IInputSlot &destination)=0
Krichevsky 2012: Local Brightness Normalization.
const char * m_Function
Definition: Exceptions.hpp:16
const char * EnumNameDataType(DataType e)
A Pooling2dDescriptor for the Pooling2dLayer.
const ConstTensor * m_OutputLayerNormWeights
Definition: LstmParams.hpp:60
A NormalizationDescriptor for the NormalizationLayer.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
An InstanceNormalizationDescriptor for InstanceNormalizationLayer.
A ChannelShuffleDescriptor for the ChannelShuffle operator.
float m_CellIntermediateScale
Cell intermediate quantization scale.
uint32_t m_DilationZ
Dilation along z axis.
float m_B
Beta lower bound value used by the activation functions. (BoundedReLu, Linear, TanH).
Definition: Descriptors.hpp:52
armnn::TensorShape Permuted(const armnn::TensorShape &srcShape, const armnn::PermutationVector &mappings)
Definition: Permute.cpp:98
A SoftmaxDescriptor for the SoftmaxLayer.
float m_Beta
Beta value for the normalization equation.
uint32_t m_StrideZ
Stride value when proceeding through input for the depth dimension.
const armnnSerializer::OriginsDescriptor * GetOriginsDescriptor(const armnnSerializer::SerializedGraph *graph, unsigned int layerIndex)
bool m_CifgEnabled
Enable/disable CIFG (coupled input & forget gate).
uint32_t m_NormSize
Depth radius value.
Status SetViewOriginCoord(uint32_t view, uint32_t coord, uint32_t value)
Set the view origin coordinates.
ActivationFunction m_Function
The activation function to use (Sigmoid, TanH, Linear, ReLu, BoundedReLu, SoftReLu, LeakyReLu, Abs, Sqrt, Square, Elu).
Definition: Descriptors.hpp:48
An input connection slot for a layer.
Definition: INetwork.hpp:24
const armnnSerializer::Pooling2dDescriptor * PoolingDescriptor
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
A DepthwiseConvolution2dDescriptor for the DepthwiseConvolution2dLayer.
constexpr unsigned int MaxNumOfTensorDimensions
Definition: Types.hpp:18
uint32_t m_DilationY
Dilation along y axis.
A FillDescriptor for the FillLayer.
A BatchNormalizationDescriptor for the BatchNormalizationLayer.
uint32_t m_PadLeft
Padding left value in the width dimension.
unsigned int GetNumElements() const
Definition: Tensor.hpp:196
const ConstTensor * m_InputToForgetWeights
Definition: LstmParams.hpp:41
ActivationFunction
Definition: Types.hpp:73
constexpr unsigned int GetDataTypeSize(DataType dataType)
Definition: TypesUtils.hpp:151
A PermuteDescriptor for the PermuteLayer.
uint32_t m_PadRight
Padding right value in the width dimension.
int32_t m_HiddenStateZeroPoint
Hidden State zero point.
bool m_ConstantWeights
Enable/disable constant weights and biases.
const ConstTensor * m_InputToInputWeights
Definition: LstmParams.hpp:40