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