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