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