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