2 // Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
6 #include "Deserializer.hpp"
8 #include <armnn/Descriptors.hpp>
9 #include <armnn/Exceptions.hpp>
10 #include <armnn/TypesUtils.hpp>
11 #include <armnn/LstmParams.hpp>
12 #include <armnn/QuantizedLstmParams.hpp>
14 #include <armnnUtils/Permute.hpp>
15 #include <armnnUtils/Transpose.hpp>
16 #include <armnn/utility/Assert.hpp>
17 #include <armnn/utility/IgnoreUnused.hpp>
18 #include <armnn/utility/NumericCast.hpp>
20 #include <ParserHelper.hpp>
21 #include <VerificationHelpers.hpp>
23 #include <fmt/format.h>
30 using armnn::ParseException;
31 using namespace armnn;
32 using namespace armnnSerializer;
34 namespace armnnDeserializer
40 const uint32_t VIRTUAL_LAYER_ID = std::numeric_limits<uint32_t>::max();
42 void CheckGraph(const Deserializer::GraphPtr& graph,
43 unsigned int layersIndex,
44 const CheckLocation& location)
46 if (graph->layers() == nullptr)
48 throw ParseException(fmt::format("{0} was called with invalid (null) graph. "
49 "Possible reason is that the graph is not yet loaded and Unpack(ed). "
53 location.FileLine()));
55 else if (layersIndex >= graph->layers()->size())
57 throw ParseException(fmt::format("{0} was called with an invalid layers index. layers:{1} at {2}",
60 location.FileLine()));
64 void CheckLayers(const Deserializer::GraphPtr& graph,
65 unsigned int layersIndex,
66 unsigned int layerIndex,
67 const CheckLocation& location)
69 if (graph->layers() == nullptr)
71 throw ParseException(fmt::format("{0} was called with invalid (null) graph. "
72 "Possible reason is that the graph is not yet loaded and Unpack(ed). "
76 location.FileLine()));
78 else if (layersIndex >= graph->layers()->size())
80 throw ParseException(fmt::format("{0} was called with an invalid layers index. "
84 location.FileLine()));
86 else if (layerIndex >= graph->layers()[layersIndex].size()
87 && layerIndex != VIRTUAL_LAYER_ID)
89 throw ParseException(fmt::format("{0} was called with an invalid layer index. "
90 "layers:{1} layer:{2} at {3}",
94 location.FileLine()));
98 void CheckTensorPtr(Deserializer::TensorRawPtr rawPtr,
99 const CheckLocation& location)
101 if (rawPtr == nullptr)
103 throw ParseException(fmt::format("{0} was called with a null tensor pointer. at {1}",
105 location.FileLine()));
109 void CheckConstTensorPtr(Deserializer::ConstTensorRawPtr rawPtr,
110 const CheckLocation& location)
112 if (rawPtr == nullptr)
114 throw ParseException(fmt::format("{0} was called with a null const tensor pointer. at {1}",
116 location.FileLine()));
120 void CheckConstTensorSize(const unsigned int constTensorSize,
121 const unsigned int tensorSize,
122 const CheckLocation& location)
124 if (constTensorSize != tensorSize)
126 throw ParseException(fmt::format("{0} wrong number of components supplied to tensor. at:{1}",
128 location.FileLine()));
132 #define CHECK_TENSOR_PTR(TENSOR_PTR) \
133 CheckTensorPtr(TENSOR_PTR, CHECK_LOCATION())
135 #define CHECK_CONST_TENSOR_SIZE(CONST_TENSOR_SIZE, TENSOR_SIZE) \
136 CheckConstTensorSize(CONST_TENSOR_SIZE, TENSOR_SIZE, CHECK_LOCATION())
138 #define CHECK_CONST_TENSOR_PTR(TENSOR_PTR) \
139 CheckConstTensorPtr(TENSOR_PTR, CHECK_LOCATION())
141 #define CHECK_LAYERS(GRAPH, LAYERS_INDEX, LAYER_INDEX) \
142 CheckLayers(GRAPH, LAYERS_INDEX, LAYER_INDEX, CHECK_LOCATION())
144 #define CHECK_GRAPH(GRAPH, LAYERS_INDEX) \
145 CheckGraph(GRAPH, LAYERS_INDEX, CHECK_LOCATION())
148 bool CheckShape(const armnn::TensorShape& actual, const std::vector<uint32_t>& expected)
150 const unsigned int actualSize = actual.GetNumDimensions();
151 if (actualSize != expected.size())
156 for (unsigned int i = 0u; i < actualSize; i++)
158 if (actual[i] != static_cast<unsigned int>(expected[i]))
167 Deserializer::Deserializer()
168 : m_Network(nullptr, nullptr),
169 //May require LayerType_Max to be included
170 m_ParserFunctions(Layer_MAX+1, &Deserializer::ParseUnsupportedLayer)
172 // register supported layers
173 m_ParserFunctions[Layer_AbsLayer] = &Deserializer::ParseAbs;
174 m_ParserFunctions[Layer_ActivationLayer] = &Deserializer::ParseActivation;
175 m_ParserFunctions[Layer_AdditionLayer] = &Deserializer::ParseAdd;
176 m_ParserFunctions[Layer_ArgMinMaxLayer] = &Deserializer::ParseArgMinMax;
177 m_ParserFunctions[Layer_BatchToSpaceNdLayer] = &Deserializer::ParseBatchToSpaceNd;
178 m_ParserFunctions[Layer_BatchNormalizationLayer] = &Deserializer::ParseBatchNormalization;
179 m_ParserFunctions[Layer_ComparisonLayer] = &Deserializer::ParseComparison;
180 m_ParserFunctions[Layer_ConcatLayer] = &Deserializer::ParseConcat;
181 m_ParserFunctions[Layer_ConstantLayer] = &Deserializer::ParseConstant;
182 m_ParserFunctions[Layer_Convolution2dLayer] = &Deserializer::ParseConvolution2d;
183 m_ParserFunctions[Layer_DepthToSpaceLayer] = &Deserializer::ParseDepthToSpace;
184 m_ParserFunctions[Layer_DepthwiseConvolution2dLayer] = &Deserializer::ParseDepthwiseConvolution2d;
185 m_ParserFunctions[Layer_DequantizeLayer] = &Deserializer::ParseDequantize;
186 m_ParserFunctions[Layer_DetectionPostProcessLayer] = &Deserializer::ParseDetectionPostProcess;
187 m_ParserFunctions[Layer_DivisionLayer] = &Deserializer::ParseDivision;
188 m_ParserFunctions[Layer_ElementwiseUnaryLayer] = &Deserializer::ParseElementwiseUnary;
189 m_ParserFunctions[Layer_EqualLayer] = &Deserializer::ParseEqual;
190 m_ParserFunctions[Layer_FullyConnectedLayer] = &Deserializer::ParseFullyConnected;
191 m_ParserFunctions[Layer_FillLayer] = &Deserializer::ParseFill;
192 m_ParserFunctions[Layer_FloorLayer] = &Deserializer::ParseFloor;
193 m_ParserFunctions[Layer_GatherLayer] = &Deserializer::ParseGather;
194 m_ParserFunctions[Layer_GreaterLayer] = &Deserializer::ParseGreater;
195 m_ParserFunctions[Layer_InstanceNormalizationLayer] = &Deserializer::ParseInstanceNormalization;
196 m_ParserFunctions[Layer_L2NormalizationLayer] = &Deserializer::ParseL2Normalization;
197 m_ParserFunctions[Layer_LogicalBinaryLayer] = &Deserializer::ParseLogicalBinary;
198 m_ParserFunctions[Layer_LogSoftmaxLayer] = &Deserializer::ParseLogSoftmax;
199 m_ParserFunctions[Layer_LstmLayer] = &Deserializer::ParseLstm;
200 m_ParserFunctions[Layer_MaximumLayer] = &Deserializer::ParseMaximum;
201 m_ParserFunctions[Layer_MeanLayer] = &Deserializer::ParseMean;
202 m_ParserFunctions[Layer_MinimumLayer] = &Deserializer::ParseMinimum;
203 m_ParserFunctions[Layer_MergeLayer] = &Deserializer::ParseMerge;
204 m_ParserFunctions[Layer_MergerLayer] = &Deserializer::ParseConcat;
205 m_ParserFunctions[Layer_MultiplicationLayer] = &Deserializer::ParseMultiplication;
206 m_ParserFunctions[Layer_NormalizationLayer] = &Deserializer::ParseNormalization;
207 m_ParserFunctions[Layer_PadLayer] = &Deserializer::ParsePad;
208 m_ParserFunctions[Layer_PermuteLayer] = &Deserializer::ParsePermute;
209 m_ParserFunctions[Layer_Pooling2dLayer] = &Deserializer::ParsePooling2d;
210 m_ParserFunctions[Layer_PreluLayer] = &Deserializer::ParsePrelu;
211 m_ParserFunctions[Layer_QLstmLayer] = &Deserializer::ParseQLstm;
212 m_ParserFunctions[Layer_QuantizeLayer] = &Deserializer::ParseQuantize;
213 m_ParserFunctions[Layer_QuantizedLstmLayer] = &Deserializer::ParseQuantizedLstm;
214 m_ParserFunctions[Layer_RankLayer] = &Deserializer::ParseRank;
215 m_ParserFunctions[Layer_ReshapeLayer] = &Deserializer::ParseReshape;
216 m_ParserFunctions[Layer_ResizeBilinearLayer] = &Deserializer::ParseResizeBilinear;
217 m_ParserFunctions[Layer_ResizeLayer] = &Deserializer::ParseResize;
218 m_ParserFunctions[Layer_RsqrtLayer] = &Deserializer::ParseRsqrt;
219 m_ParserFunctions[Layer_SliceLayer] = &Deserializer::ParseSlice;
220 m_ParserFunctions[Layer_SoftmaxLayer] = &Deserializer::ParseSoftmax;
221 m_ParserFunctions[Layer_SpaceToBatchNdLayer] = &Deserializer::ParseSpaceToBatchNd;
222 m_ParserFunctions[Layer_SpaceToDepthLayer] = &Deserializer::ParseSpaceToDepth;
223 m_ParserFunctions[Layer_SplitterLayer] = &Deserializer::ParseSplitter;
224 m_ParserFunctions[Layer_StackLayer] = &Deserializer::ParseStack;
225 m_ParserFunctions[Layer_StandInLayer] = &Deserializer::ParseStandIn;
226 m_ParserFunctions[Layer_StridedSliceLayer] = &Deserializer::ParseStridedSlice;
227 m_ParserFunctions[Layer_SubtractionLayer] = &Deserializer::ParseSubtraction;
228 m_ParserFunctions[Layer_SwitchLayer] = &Deserializer::ParseSwitch;
229 m_ParserFunctions[Layer_TransposeConvolution2dLayer] = &Deserializer::ParseTransposeConvolution2d;
230 m_ParserFunctions[Layer_TransposeLayer] = &Deserializer::ParseTranspose;
233 Deserializer::LayerBaseRawPtr Deserializer::GetBaseLayer(const GraphPtr& graphPtr, unsigned int layerIndex)
235 auto layerType = graphPtr->layers()->Get(layerIndex)->layer_type();
239 case Layer::Layer_AbsLayer:
240 return graphPtr->layers()->Get(layerIndex)->layer_as_AbsLayer()->base();
241 case Layer::Layer_ActivationLayer:
242 return graphPtr->layers()->Get(layerIndex)->layer_as_ActivationLayer()->base();
243 case Layer::Layer_AdditionLayer:
244 return graphPtr->layers()->Get(layerIndex)->layer_as_AdditionLayer()->base();
245 case Layer::Layer_ArgMinMaxLayer:
246 return graphPtr->layers()->Get(layerIndex)->layer_as_ArgMinMaxLayer()->base();
247 case Layer::Layer_BatchToSpaceNdLayer:
248 return graphPtr->layers()->Get(layerIndex)->layer_as_BatchToSpaceNdLayer()->base();
249 case Layer::Layer_BatchNormalizationLayer:
250 return graphPtr->layers()->Get(layerIndex)->layer_as_BatchNormalizationLayer()->base();
251 case Layer::Layer_ComparisonLayer:
252 return graphPtr->layers()->Get(layerIndex)->layer_as_ComparisonLayer()->base();
253 case Layer::Layer_ConcatLayer:
254 return graphPtr->layers()->Get(layerIndex)->layer_as_ConcatLayer()->base();
255 case Layer::Layer_ConstantLayer:
256 return graphPtr->layers()->Get(layerIndex)->layer_as_ConstantLayer()->base();
257 case Layer::Layer_Convolution2dLayer:
258 return graphPtr->layers()->Get(layerIndex)->layer_as_Convolution2dLayer()->base();
259 case Layer::Layer_DepthToSpaceLayer:
260 return graphPtr->layers()->Get(layerIndex)->layer_as_DepthToSpaceLayer()->base();
261 case Layer::Layer_DepthwiseConvolution2dLayer:
262 return graphPtr->layers()->Get(layerIndex)->layer_as_DepthwiseConvolution2dLayer()->base();
263 case Layer::Layer_DequantizeLayer:
264 return graphPtr->layers()->Get(layerIndex)->layer_as_DequantizeLayer()->base();
265 case Layer::Layer_DetectionPostProcessLayer:
266 return graphPtr->layers()->Get(layerIndex)->layer_as_DetectionPostProcessLayer()->base();
267 case Layer::Layer_DivisionLayer:
268 return graphPtr->layers()->Get(layerIndex)->layer_as_DivisionLayer()->base();
269 case Layer::Layer_EqualLayer:
270 return graphPtr->layers()->Get(layerIndex)->layer_as_EqualLayer()->base();
271 case Layer::Layer_ElementwiseUnaryLayer:
272 return graphPtr->layers()->Get(layerIndex)->layer_as_ElementwiseUnaryLayer()->base();
273 case Layer::Layer_FullyConnectedLayer:
274 return graphPtr->layers()->Get(layerIndex)->layer_as_FullyConnectedLayer()->base();
275 case Layer::Layer_FillLayer:
276 return graphPtr->layers()->Get(layerIndex)->layer_as_FillLayer()->base();
277 case Layer::Layer_FloorLayer:
278 return graphPtr->layers()->Get(layerIndex)->layer_as_FloorLayer()->base();
279 case Layer::Layer_GatherLayer:
280 return graphPtr->layers()->Get(layerIndex)->layer_as_GatherLayer()->base();
281 case Layer::Layer_GreaterLayer:
282 return graphPtr->layers()->Get(layerIndex)->layer_as_GreaterLayer()->base();
283 case Layer::Layer_InputLayer:
284 return graphPtr->layers()->Get(layerIndex)->layer_as_InputLayer()->base()->base();
285 case Layer::Layer_InstanceNormalizationLayer:
286 return graphPtr->layers()->Get(layerIndex)->layer_as_InstanceNormalizationLayer()->base();
287 case Layer::Layer_L2NormalizationLayer:
288 return graphPtr->layers()->Get(layerIndex)->layer_as_L2NormalizationLayer()->base();
289 case Layer::Layer_LogicalBinaryLayer:
290 return graphPtr->layers()->Get(layerIndex)->layer_as_LogicalBinaryLayer()->base();
291 case Layer::Layer_LogSoftmaxLayer:
292 return graphPtr->layers()->Get(layerIndex)->layer_as_LogSoftmaxLayer()->base();
293 case Layer::Layer_LstmLayer:
294 return graphPtr->layers()->Get(layerIndex)->layer_as_LstmLayer()->base();
295 case Layer::Layer_MeanLayer:
296 return graphPtr->layers()->Get(layerIndex)->layer_as_MeanLayer()->base();
297 case Layer::Layer_MinimumLayer:
298 return graphPtr->layers()->Get(layerIndex)->layer_as_MinimumLayer()->base();
299 case Layer::Layer_MaximumLayer:
300 return graphPtr->layers()->Get(layerIndex)->layer_as_MaximumLayer()->base();
301 case Layer::Layer_MergeLayer:
302 return graphPtr->layers()->Get(layerIndex)->layer_as_MergeLayer()->base();
303 case Layer::Layer_MergerLayer:
304 return graphPtr->layers()->Get(layerIndex)->layer_as_MergerLayer()->base();
305 case Layer::Layer_MultiplicationLayer:
306 return graphPtr->layers()->Get(layerIndex)->layer_as_MultiplicationLayer()->base();
307 case Layer::Layer_NormalizationLayer:
308 return graphPtr->layers()->Get(layerIndex)->layer_as_NormalizationLayer()->base();
309 case Layer::Layer_OutputLayer:
310 return graphPtr->layers()->Get(layerIndex)->layer_as_OutputLayer()->base()->base();
311 case Layer::Layer_PadLayer:
312 return graphPtr->layers()->Get(layerIndex)->layer_as_PadLayer()->base();
313 case Layer::Layer_PermuteLayer:
314 return graphPtr->layers()->Get(layerIndex)->layer_as_PermuteLayer()->base();
315 case Layer::Layer_Pooling2dLayer:
316 return graphPtr->layers()->Get(layerIndex)->layer_as_Pooling2dLayer()->base();
317 case Layer::Layer_PreluLayer:
318 return graphPtr->layers()->Get(layerIndex)->layer_as_PreluLayer()->base();
319 case Layer::Layer_QLstmLayer:
320 return graphPtr->layers()->Get(layerIndex)->layer_as_QLstmLayer()->base();
321 case Layer::Layer_QuantizeLayer:
322 return graphPtr->layers()->Get(layerIndex)->layer_as_QuantizeLayer()->base();
323 case Layer::Layer_QuantizedLstmLayer:
324 return graphPtr->layers()->Get(layerIndex)->layer_as_QuantizedLstmLayer()->base();
325 case Layer::Layer_RankLayer:
326 return graphPtr->layers()->Get(layerIndex)->layer_as_RankLayer()->base();
327 case Layer::Layer_ReshapeLayer:
328 return graphPtr->layers()->Get(layerIndex)->layer_as_ReshapeLayer()->base();
329 case Layer::Layer_ResizeBilinearLayer:
330 return graphPtr->layers()->Get(layerIndex)->layer_as_ResizeBilinearLayer()->base();
331 case Layer::Layer_ResizeLayer:
332 return graphPtr->layers()->Get(layerIndex)->layer_as_ResizeLayer()->base();
333 case Layer::Layer_RsqrtLayer:
334 return graphPtr->layers()->Get(layerIndex)->layer_as_RsqrtLayer()->base();
335 case Layer::Layer_SliceLayer:
336 return graphPtr->layers()->Get(layerIndex)->layer_as_SliceLayer()->base();
337 case Layer::Layer_SoftmaxLayer:
338 return graphPtr->layers()->Get(layerIndex)->layer_as_SoftmaxLayer()->base();
339 case Layer::Layer_SpaceToBatchNdLayer:
340 return graphPtr->layers()->Get(layerIndex)->layer_as_SpaceToBatchNdLayer()->base();
341 case Layer::Layer_SpaceToDepthLayer:
342 return graphPtr->layers()->Get(layerIndex)->layer_as_SpaceToDepthLayer()->base();
343 case Layer::Layer_SplitterLayer:
344 return graphPtr->layers()->Get(layerIndex)->layer_as_SplitterLayer()->base();
345 case Layer::Layer_StackLayer:
346 return graphPtr->layers()->Get(layerIndex)->layer_as_StackLayer()->base();
347 case Layer::Layer_StandInLayer:
348 return graphPtr->layers()->Get(layerIndex)->layer_as_StandInLayer()->base();
349 case Layer::Layer_StridedSliceLayer:
350 return graphPtr->layers()->Get(layerIndex)->layer_as_StridedSliceLayer()->base();
351 case Layer::Layer_SubtractionLayer:
352 return graphPtr->layers()->Get(layerIndex)->layer_as_SubtractionLayer()->base();
353 case Layer::Layer_SwitchLayer:
354 return graphPtr->layers()->Get(layerIndex)->layer_as_SwitchLayer()->base();
355 case Layer::Layer_TransposeConvolution2dLayer:
356 return graphPtr->layers()->Get(layerIndex)->layer_as_TransposeConvolution2dLayer()->base();
357 case Layer::Layer_TransposeLayer:
358 return graphPtr->layers()->Get(layerIndex)->layer_as_TransposeLayer()->base();
359 case Layer::Layer_NONE:
361 throw ParseException(fmt::format("Layer type {} not recognized", layerType));
365 std::string Deserializer::GetLayerName(const GraphPtr& graph, unsigned int index)
367 auto layer = GetBaseLayer(graph, index);
369 return layer->layerName()->str();
372 int32_t Deserializer::GetBindingLayerInfo(const GraphPtr& graphPtr, unsigned int layerIndex)
374 auto layerType = graphPtr->layers()->Get(layerIndex)->layer_type();
376 if (layerType == Layer::Layer_InputLayer)
378 return graphPtr->layers()->Get(layerIndex)->layer_as_InputLayer()->base()->layerBindingId();
380 else if ( layerType == Layer::Layer_OutputLayer )
382 return graphPtr->layers()->Get(layerIndex)->layer_as_OutputLayer()->base()->layerBindingId();
387 armnn::DataLayout ToDataLayout(armnnSerializer::DataLayout dataLayout)
391 case armnnSerializer::DataLayout::DataLayout_NHWC:
392 return armnn::DataLayout::NHWC;
393 case armnnSerializer::DataLayout::DataLayout_NCHW:
395 return armnn::DataLayout::NCHW;
399 armnn::ActivationFunction ToActivationFunction(armnnSerializer::ActivationFunction function)
403 case armnnSerializer::ActivationFunction_Sigmoid:
404 return armnn::ActivationFunction::Sigmoid;
405 case armnnSerializer::ActivationFunction_TanH:
406 return armnn::ActivationFunction::TanH;
407 case armnnSerializer::ActivationFunction_Linear:
408 return armnn::ActivationFunction::Linear;
409 case armnnSerializer::ActivationFunction_ReLu:
410 return armnn::ActivationFunction::ReLu;
411 case armnnSerializer::ActivationFunction_BoundedReLu:
412 return armnn::ActivationFunction::BoundedReLu;
413 case armnnSerializer::ActivationFunction_LeakyReLu:
414 return armnn::ActivationFunction::LeakyReLu;
415 case armnnSerializer::ActivationFunction_Abs:
416 return armnn::ActivationFunction::Abs;
417 case armnnSerializer::ActivationFunction_Sqrt:
418 return armnn::ActivationFunction::Sqrt;
419 case armnnSerializer::ActivationFunction_Square:
420 return armnn::ActivationFunction::Square;
421 case armnnSerializer::ActivationFunction_Elu:
422 return armnn::ActivationFunction::Elu;
423 case armnnSerializer::ActivationFunction_HardSwish:
424 return armnn::ActivationFunction::HardSwish;
426 return armnn::ActivationFunction::Sigmoid;
430 armnn::ArgMinMaxFunction ToArgMinMaxFunction(armnnSerializer::ArgMinMaxFunction function)
434 case armnnSerializer::ArgMinMaxFunction::ArgMinMaxFunction_Max:
435 return armnn::ArgMinMaxFunction::Max;
436 case armnnSerializer::ArgMinMaxFunction::ArgMinMaxFunction_Min:
438 return armnn::ArgMinMaxFunction::Min;
442 armnn::ComparisonOperation ToComparisonOperation(armnnSerializer::ComparisonOperation operation)
446 case armnnSerializer::ComparisonOperation::ComparisonOperation_Equal:
447 return armnn::ComparisonOperation::Equal;
448 case armnnSerializer::ComparisonOperation::ComparisonOperation_Greater:
449 return armnn::ComparisonOperation::Greater;
450 case armnnSerializer::ComparisonOperation::ComparisonOperation_GreaterOrEqual:
451 return armnn::ComparisonOperation::GreaterOrEqual;
452 case armnnSerializer::ComparisonOperation::ComparisonOperation_Less:
453 return armnn::ComparisonOperation::Less;
454 case armnnSerializer::ComparisonOperation::ComparisonOperation_LessOrEqual:
455 return armnn::ComparisonOperation::LessOrEqual;
456 case armnnSerializer::ComparisonOperation::ComparisonOperation_NotEqual:
458 return armnn::ComparisonOperation::NotEqual;
462 armnn::LogicalBinaryOperation ToLogicalBinaryOperation(armnnSerializer::LogicalBinaryOperation operation)
466 case armnnSerializer::LogicalBinaryOperation::LogicalBinaryOperation_LogicalAnd:
467 return armnn::LogicalBinaryOperation::LogicalAnd;
468 case armnnSerializer::LogicalBinaryOperation::LogicalBinaryOperation_LogicalOr:
469 return armnn::LogicalBinaryOperation::LogicalOr;
471 throw armnn::InvalidArgumentException("Logical Binary operation unknown");
475 armnn::UnaryOperation ToUnaryOperation(armnnSerializer::UnaryOperation operation)
479 case armnnSerializer::UnaryOperation::UnaryOperation_Abs:
480 return armnn::UnaryOperation::Abs;
481 case armnnSerializer::UnaryOperation::UnaryOperation_Rsqrt:
482 return armnn::UnaryOperation::Rsqrt;
483 case armnnSerializer::UnaryOperation::UnaryOperation_Sqrt:
484 return armnn::UnaryOperation::Sqrt;
485 case armnnSerializer::UnaryOperation::UnaryOperation_Exp:
486 return armnn::UnaryOperation::Exp;
487 case armnnSerializer::UnaryOperation::UnaryOperation_Neg:
488 return armnn::UnaryOperation::Neg;
489 case armnnSerializer::UnaryOperation::UnaryOperation_LogicalNot:
490 return armnn::UnaryOperation::LogicalNot;
492 throw armnn::InvalidArgumentException("Unary operation unknown");
496 armnn::ResizeMethod ToResizeMethod(armnnSerializer::ResizeMethod method)
500 case armnnSerializer::ResizeMethod_NearestNeighbor:
501 return armnn::ResizeMethod::NearestNeighbor;
502 case armnnSerializer::ResizeMethod_Bilinear:
503 return armnn::ResizeMethod::Bilinear;
505 return armnn::ResizeMethod::NearestNeighbor;
509 armnn::TensorInfo ToTensorInfo(Deserializer::TensorRawPtr tensorPtr)
511 armnn::DataType type;
512 CHECK_TENSOR_PTR(tensorPtr);
514 switch (tensorPtr->dataType())
516 case DataType_QAsymmS8:
517 type = armnn::DataType::QAsymmS8;
519 case DataType_QSymmS8:
520 type = armnn::DataType::QSymmS8;
522 case DataType_QuantisedAsymm8:
523 case DataType_QAsymmU8:
524 type = armnn::DataType::QAsymmU8;
526 case DataType_QSymmS16:
527 case DataType_QuantisedSymm16:
528 type = armnn::DataType::QSymmS16;
530 case DataType_Signed32:
531 type = armnn::DataType::Signed32;
533 case DataType_Float32:
534 type = armnn::DataType::Float32;
536 case DataType_Float16:
537 type = armnn::DataType::Float16;
539 case DataType_Boolean:
540 type = armnn::DataType::Boolean;
544 CheckLocation location = CHECK_LOCATION();
545 throw ParseException(fmt::format("Unsupported data type {0} = {1}. {2}",
546 tensorPtr->dataType(),
547 EnumNameDataType(tensorPtr->dataType()),
548 location.AsString()));
552 if (tensorPtr->dimensionality() == static_cast<unsigned int>(Dimensionality::Scalar))
554 float quantizationScale = tensorPtr->quantizationScale();
555 int32_t quantizationOffset = tensorPtr->quantizationOffset();
557 return armnn::TensorInfo(armnn::TensorShape{armnn::Dimensionality::Scalar},
563 auto dimensions = tensorPtr->dimensions();
564 unsigned int size = dimensions->size();
565 std::vector<unsigned int> outputDims(dimensions->begin(), dimensions->begin() + size);
567 auto quantizationScales = tensorPtr->quantizationScales();
569 if (quantizationScales)
571 unsigned int quantizationScalesSize = quantizationScales->size();
572 std::vector<float> scales(quantizationScales->begin(), quantizationScales->begin() + quantizationScalesSize);
573 unsigned int quantizationDim = tensorPtr->quantizationDim();
574 armnn::TensorInfo result(size,
582 float quantizationScale = tensorPtr->quantizationScale();
583 int32_t quantizationOffset = tensorPtr->quantizationOffset();
585 // two statements (on purpose) for easier debugging:
586 armnn::TensorInfo result(size,
594 armnn::ConstTensor ToConstTensor(Deserializer::ConstTensorRawPtr constTensorPtr)
596 CHECK_CONST_TENSOR_PTR(constTensorPtr);
597 armnn::TensorInfo tensorInfo = ToTensorInfo(constTensorPtr->info());
599 switch (constTensorPtr->data_type())
601 case ConstTensorData_ByteData:
603 auto byteData = constTensorPtr->data_as_ByteData()->data();
604 CHECK_CONST_TENSOR_SIZE(byteData->size(), tensorInfo.GetNumElements());
605 return armnn::ConstTensor(tensorInfo, byteData->data());
607 case ConstTensorData_ShortData:
609 auto shortData = constTensorPtr->data_as_ShortData()->data();
610 CHECK_CONST_TENSOR_SIZE(shortData->size(), tensorInfo.GetNumElements());
611 return armnn::ConstTensor(tensorInfo, shortData->data());
613 case ConstTensorData_IntData:
615 auto intData = constTensorPtr->data_as_IntData()->data();
616 CHECK_CONST_TENSOR_SIZE(intData->size(), tensorInfo.GetNumElements());
617 return armnn::ConstTensor(tensorInfo, intData->data());
619 case ConstTensorData_LongData:
621 auto longData = constTensorPtr->data_as_LongData()->data();
622 CHECK_CONST_TENSOR_SIZE(longData->size(), tensorInfo.GetNumElements());
623 return armnn::ConstTensor(tensorInfo, longData->data());
627 CheckLocation location = CHECK_LOCATION();
628 throw ParseException(fmt::format("Unsupported data type {0} = {1}. {2}",
629 constTensorPtr->data_type(),
630 EnumNameConstTensorData(constTensorPtr->data_type()),
631 location.AsString()));
636 Deserializer::TensorRawPtrVector Deserializer::GetInputs(const GraphPtr& graphPtr,
637 unsigned int layerIndex)
639 CHECK_LAYERS(graphPtr, 0, layerIndex);
640 auto layer = GetBaseLayer(graphPtr, layerIndex);
641 const auto& numInputs = layer->inputSlots()->size();
643 TensorRawPtrVector result(numInputs);
645 for (unsigned int i=0; i<numInputs; ++i)
647 auto inputId = CHECKED_NON_NEGATIVE(static_cast<int32_t>
648 (layer->inputSlots()->Get(i)->connection()->sourceLayerIndex()));
649 result[i] = GetBaseLayer(graphPtr, inputId)->outputSlots()->Get(0)->tensorInfo();
654 Deserializer::TensorRawPtrVector Deserializer::GetOutputs(const GraphPtr& graphPtr,
655 unsigned int layerIndex)
657 CHECK_LAYERS(graphPtr, 0, layerIndex);
658 auto layer = GetBaseLayer(graphPtr, layerIndex);
659 const auto& numOutputs = layer->outputSlots()->size();
661 TensorRawPtrVector result(numOutputs);
663 for (unsigned int i=0; i<numOutputs; ++i)
665 result[i] = layer->outputSlots()->Get(i)->tensorInfo();
670 void Deserializer::ParseUnsupportedLayer(GraphPtr graph, unsigned int layerIndex)
672 CHECK_LAYERS(graph, 0, layerIndex);
673 const auto layerName = GetBaseLayer(graph, layerIndex)->layerName()->c_str();
674 throw ParseException(fmt::format("Layer not supported. layerIndex: {0} "
675 "layerName: {1} / {2}",
678 CHECK_LOCATION().AsString()));
681 void Deserializer::ResetParser()
683 m_Network = armnn::INetworkPtr(nullptr, nullptr);
684 m_InputBindings.clear();
685 m_OutputBindings.clear();
688 IDeserializer* IDeserializer::CreateRaw()
690 return new Deserializer();
693 IDeserializerPtr IDeserializer::Create()
695 return IDeserializerPtr(CreateRaw(), &IDeserializer::Destroy);
698 void IDeserializer::Destroy(IDeserializer* parser)
703 INetworkPtr Deserializer::CreateNetworkFromBinary(const std::vector<uint8_t>& binaryContent)
706 GraphPtr graph = LoadGraphFromBinary(binaryContent.data(), binaryContent.size());
707 return CreateNetworkFromGraph(graph);
710 armnn::INetworkPtr Deserializer::CreateNetworkFromBinary(std::istream& binaryContent)
713 std::vector<uint8_t> content((std::istreambuf_iterator<char>(binaryContent)), std::istreambuf_iterator<char>());
714 GraphPtr graph = LoadGraphFromBinary(content.data(), content.size());
715 return CreateNetworkFromGraph(graph);
718 Deserializer::GraphPtr Deserializer::LoadGraphFromBinary(const uint8_t* binaryContent, size_t len)
720 if (binaryContent == nullptr)
722 throw InvalidArgumentException(fmt::format("Invalid (null) binary content {}",
723 CHECK_LOCATION().AsString()));
725 flatbuffers::Verifier verifier(binaryContent, len);
726 if (verifier.VerifyBuffer<SerializedGraph>() == false)
728 throw ParseException(fmt::format("Buffer doesn't conform to the expected Armnn "
729 "flatbuffers format. size:{0} {1}",
731 CHECK_LOCATION().AsString()));
733 return GetSerializedGraph(binaryContent);
736 INetworkPtr Deserializer::CreateNetworkFromGraph(GraphPtr graph)
738 m_Network = INetwork::Create();
739 ARMNN_ASSERT(graph != nullptr);
740 unsigned int layerIndex = 0;
741 for (AnyLayer const* layer : *graph->layers())
743 if (layer->layer_type() != Layer_InputLayer &&
744 layer->layer_type() != Layer_OutputLayer)
746 // lookup and call the parser function
747 auto& parserFunction = m_ParserFunctions[layer->layer_type()];
748 (this->*parserFunction)(graph, layerIndex);
753 SetupInputLayers(graph);
754 SetupOutputLayers(graph);
756 // establish the connections from the layer outputs to the inputs of the subsequent layers
757 for (auto&& graphIt : m_GraphConnections)
759 Connections& connections = graphIt.second;
760 for (auto&& outputIt : connections.outputSlots)
762 const unsigned int outputSlotIndex = outputIt.first;
763 IOutputSlot* outputSlot = outputIt.second;
764 if (connections.inputSlots.find(outputSlotIndex) != connections.inputSlots.end())
766 for (IInputSlot* inputSlot : connections.inputSlots[outputSlotIndex])
768 outputSlot->Connect(*inputSlot);
774 return std::move(m_Network);
777 BindingPointInfo Deserializer::GetNetworkInputBindingInfo(unsigned int layerIndex,
778 const std::string& name) const
780 IgnoreUnused(layerIndex);
781 for (auto inputBinding : m_InputBindings)
783 if (inputBinding.first == name)
785 return inputBinding.second;
788 throw ParseException(fmt::format("No input binding found for layer:{0} / {1}",
790 CHECK_LOCATION().AsString()));
793 BindingPointInfo Deserializer::GetNetworkOutputBindingInfo(unsigned int layerIndex,
794 const std::string& name) const
796 IgnoreUnused(layerIndex);
797 for (auto outputBinding : m_OutputBindings)
799 if (outputBinding.first == name)
801 return outputBinding.second;
804 throw ParseException(fmt::format("No output binding found for layer:{0} / {1}",
806 CHECK_LOCATION().AsString()));
809 unsigned int Deserializer::GetInputLayerInVector(GraphPtr graph, int targetId)
811 for (unsigned int i = 0; i < graph->layers()->size(); i++)
813 auto layer = graph->layers()->Get(i);
814 if (layer->layer_type() == Layer::Layer_InputLayer)
816 auto layerBindingId = layer->layer_as_InputLayer()->base()->layerBindingId();
817 if (layerBindingId == targetId)
823 throw ParseException("Input layer with given layerBindingId not found");
826 unsigned int Deserializer::GetOutputLayerInVector(GraphPtr graph, int targetId)
828 for (unsigned int i = 0; i < graph->layers()->size(); i++)
830 auto layer = graph->layers()->Get(i);
831 if (layer->layer_type() == Layer::Layer_OutputLayer)
833 auto layerBindingId = layer->layer_as_OutputLayer()->base()->layerBindingId();
834 if (layerBindingId == targetId)
840 throw ParseException("Output layer with given layerBindingId not found");
843 unsigned int Deserializer::GetLayerIndexInVector(GraphPtr graph, unsigned int targetIndex)
845 for (unsigned int i = 0; i < graph->layers()->size(); i++)
847 LayerBaseRawPtr layer = GetBaseLayer(graph, i);
848 if (layer->index() == targetIndex)
853 throw ParseException("Layer with given index not found");
856 Deserializer::FeatureVersions Deserializer::GetFeatureVersions(GraphPtr graph)
858 Deserializer::FeatureVersions versions;
860 if (graph->featureVersions())
862 versions.m_BindingIdScheme = graph->featureVersions()->bindingIdsScheme();
868 void Deserializer::SetupInputLayers(GraphPtr graph)
870 CHECK_GRAPH(graph, 0);
871 const unsigned int numInputs = graph->inputIds()->size();
872 m_InputBindings.clear();
873 m_InputBindings.reserve(numInputs);
875 for (unsigned int i = 0; i < numInputs; i++)
877 unsigned int inputLayerIndex = 0xFFFFFFFF;
878 if (GetFeatureVersions(graph).m_BindingIdScheme == 0)
880 const unsigned int inputId = armnn::numeric_cast<unsigned int>(graph->inputIds()->Get(i));
881 inputLayerIndex = GetLayerIndexInVector(graph, inputId);
885 const int inputId = graph->inputIds()->Get(i);
886 inputLayerIndex = GetInputLayerInVector(graph, inputId);
889 LayerBaseRawPtr baseLayer = GetBaseLayer(graph, inputLayerIndex);
891 // GetBindingLayerInfo expect the index to be index in the vector not index property on each layer base
892 LayerBindingId bindingId = GetBindingLayerInfo(graph, inputLayerIndex);
893 ARMNN_ASSERT_MSG(baseLayer->layerName()->c_str(), "Input has no name.");
895 IConnectableLayer* inputLayer =
896 m_Network->AddInputLayer(bindingId, baseLayer->layerName()->c_str());
898 const armnn::TensorInfo& tensorInfo = ToTensorInfo(baseLayer->outputSlots()->Get(0)->tensorInfo());
899 inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
900 RegisterOutputSlots(graph, inputLayerIndex, inputLayer);
902 BindingPointInfo bindingInfo = {bindingId, tensorInfo};
903 m_InputBindings.push_back(std::make_pair(baseLayer->layerName()->c_str(), bindingInfo));
907 void Deserializer::SetupOutputLayers(GraphPtr graph)
909 CHECK_GRAPH(graph, 0);
910 const unsigned int numOutputs = graph->outputIds()->size();
911 m_OutputBindings.clear();
912 m_OutputBindings.reserve(numOutputs);
914 for (unsigned int i = 0; i < numOutputs; i++)
916 unsigned int outputLayerIndex = 0xFFFFFFFF;
917 if (GetFeatureVersions(graph).m_BindingIdScheme == 0)
919 const unsigned int outputId = armnn::numeric_cast<unsigned int>(graph->outputIds()->Get(i));
920 outputLayerIndex = GetLayerIndexInVector(graph, outputId);
924 const int outputId = graph->outputIds()->Get(i);
925 outputLayerIndex = GetOutputLayerInVector(graph, outputId);
928 LayerBaseRawPtr baseLayer = GetBaseLayer(graph, outputLayerIndex);
930 // GetBindingLayerInfo expect the index to be index in the vector not index property on each layer base
931 LayerBindingId bindingId = GetBindingLayerInfo(graph, outputLayerIndex);
932 ARMNN_ASSERT_MSG(baseLayer->layerName()->c_str(), "Output has no name.");
934 IConnectableLayer* outputLayer =
935 m_Network->AddOutputLayer(bindingId, baseLayer->layerName()->c_str());
937 RegisterInputSlots(graph, outputLayerIndex, outputLayer);
939 unsigned int sourceLayerIndex =
940 GetLayerIndexInVector(graph, baseLayer->inputSlots()->Get(0)->connection()->sourceLayerIndex());
941 LayerBaseRawPtr sourceBaseLayer = GetBaseLayer(graph, sourceLayerIndex);
942 const armnn::TensorInfo& tensorInfo = ToTensorInfo(sourceBaseLayer->outputSlots()->Get(i)->tensorInfo());
944 BindingPointInfo bindingInfo = {bindingId, tensorInfo};
945 m_OutputBindings.push_back(std::make_pair(baseLayer->layerName()->c_str(), bindingInfo));
949 void Deserializer::RegisterOutputSlots(GraphPtr graph,
951 IConnectableLayer* layer)
953 CHECK_LAYERS(graph, 0, layerIndex);
954 ARMNN_ASSERT(layer != nullptr);
955 LayerBaseRawPtr baseLayer = GetBaseLayer(graph, layerIndex);
956 if (baseLayer->outputSlots()->size() != layer->GetNumOutputSlots())
958 throw ParseException(fmt::format("The number of outputslots ({0}) does not match the number expected ({1})"
959 " for layer index: {2} {3}",
960 baseLayer->outputSlots()->size(),
961 layer->GetNumOutputSlots(),
963 CHECK_LOCATION().AsString()));
966 for (unsigned int i = 0; i < layer->GetNumOutputSlots(); ++i)
968 const unsigned int slotIndex = baseLayer->outputSlots()->Get(i)->index();
969 armnn::IOutputSlot* outputSlot = &(layer->GetOutputSlot(slotIndex));
970 // layerIndex is not necessarily the same as baseLayer->index(). The latter is needed here
971 RegisterOutputSlotOfConnection(baseLayer->index(), slotIndex, outputSlot);
975 void Deserializer::RegisterInputSlots(GraphPtr graph,
977 armnn::IConnectableLayer* layer)
979 CHECK_LAYERS(graph, 0, layerIndex);
980 ARMNN_ASSERT(layer != nullptr);
981 LayerBaseRawPtr baseLayer = GetBaseLayer(graph, layerIndex);
982 if (baseLayer->inputSlots()->size() != layer->GetNumInputSlots())
984 throw ParseException(fmt::format("The number of inputslots ({0}) does not match the number expected ({1})"
985 " for layer index:{2} {3}",
986 baseLayer->inputSlots()->size(),
987 layer->GetNumInputSlots(),
989 CHECK_LOCATION().AsString()));
992 for (unsigned int i = 0; i < layer->GetNumInputSlots(); ++i)
994 auto fbInputSlot = baseLayer->inputSlots()->Get(i);
995 auto fbConnection = fbInputSlot->connection();
996 armnn::IInputSlot* inputSlot = &(layer->GetInputSlot(fbInputSlot->index()));
997 RegisterInputSlotOfConnection(fbConnection->sourceLayerIndex(), fbConnection->outputSlotIndex(), inputSlot);
1001 void Deserializer::RegisterInputSlotOfConnection(uint32_t sourceLayerIndex,
1002 uint32_t outputSlotIndex,
1003 armnn::IInputSlot* inputSlot)
1005 if (m_GraphConnections.find(sourceLayerIndex) == m_GraphConnections.end())
1007 m_GraphConnections[sourceLayerIndex] = Connections();
1010 Connections& connections = m_GraphConnections[sourceLayerIndex];
1011 if (connections.inputSlots.find(outputSlotIndex) == connections.inputSlots.end())
1013 connections.inputSlots[outputSlotIndex] = {inputSlot};
1017 connections.inputSlots[outputSlotIndex].push_back(inputSlot);
1021 void Deserializer::RegisterOutputSlotOfConnection(uint32_t sourceLayerIndex,
1022 uint32_t outputSlotIndex,
1023 armnn::IOutputSlot* outputSlot)
1025 if (m_GraphConnections.find(sourceLayerIndex) == m_GraphConnections.end())
1027 m_GraphConnections[sourceLayerIndex] = Connections();
1030 Connections& connections = m_GraphConnections[sourceLayerIndex];
1031 if (connections.outputSlots.find(outputSlotIndex) != connections.outputSlots.end())
1033 throw ParseException("Same output slot index processed twice");
1036 connections.outputSlots[outputSlotIndex] = outputSlot;
1039 void Deserializer::ParseAbs(armnnDeserializer::Deserializer::GraphPtr graph, unsigned int layerIndex)
1041 CHECK_LAYERS(graph, 0, layerIndex);
1042 auto inputs = GetInputs(graph, layerIndex);
1044 CHECK_VALID_SIZE(inputs.size(), 1);
1046 auto outputs = GetOutputs(graph, layerIndex);
1047 CHECK_VALID_SIZE(outputs.size(), 1);
1049 auto layerName = GetLayerName(graph, layerIndex);
1051 armnn::ElementwiseUnaryDescriptor descriptor(armnn::UnaryOperation::Abs);
1052 IConnectableLayer* layer = m_Network->AddElementwiseUnaryLayer(descriptor, layerName.c_str());
1053 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1054 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1056 RegisterInputSlots(graph, layerIndex, layer);
1057 RegisterOutputSlots(graph, layerIndex, layer);
1060 void Deserializer::ParseActivation(GraphPtr graph, unsigned int layerIndex)
1062 CHECK_LAYERS(graph, 0, layerIndex);
1063 auto inputs = GetInputs(graph, layerIndex);
1065 CHECK_VALID_SIZE(inputs.size(), 1);
1067 auto outputs = GetOutputs(graph, layerIndex);
1068 CHECK_VALID_SIZE(outputs.size(), 1);
1070 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_ActivationLayer();
1071 auto layerName = GetLayerName(graph, layerIndex);
1072 auto serializerDescriptor = serializerLayer->descriptor();
1074 armnn::ActivationDescriptor descriptor;
1075 descriptor.m_Function = ToActivationFunction(serializerDescriptor->activationFunction());
1076 descriptor.m_A = serializerDescriptor->a();
1077 descriptor.m_B = serializerDescriptor->b();
1079 IConnectableLayer* layer = m_Network->AddActivationLayer(descriptor,
1081 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1082 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1084 RegisterInputSlots(graph, layerIndex, layer);
1085 RegisterOutputSlots(graph, layerIndex, layer);
1088 void Deserializer::ParseAdd(GraphPtr graph, unsigned int layerIndex)
1090 CHECK_LAYERS(graph, 0, layerIndex);
1091 auto inputs = GetInputs(graph, layerIndex);
1093 CHECK_VALID_SIZE(inputs.size(), 2);
1095 auto outputs = GetOutputs(graph, layerIndex);
1096 CHECK_VALID_SIZE(outputs.size(), 1);
1098 auto layerName = GetLayerName(graph, layerIndex);
1099 IConnectableLayer* layer = m_Network->AddAdditionLayer(layerName.c_str());
1101 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1102 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1104 RegisterInputSlots(graph, layerIndex, layer);
1105 RegisterOutputSlots(graph, layerIndex, layer);
1108 void Deserializer::ParseArgMinMax(GraphPtr graph, unsigned int layerIndex)
1110 CHECK_LAYERS(graph, 0, layerIndex);
1111 auto inputs = GetInputs(graph, layerIndex);
1113 CHECK_VALID_SIZE(inputs.size(), 1);
1115 auto outputs = GetOutputs(graph, layerIndex);
1116 CHECK_VALID_SIZE(outputs.size(), 1);
1118 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_ArgMinMaxLayer();
1119 auto serializerDescriptor = serializerLayer->descriptor();
1121 armnn::ArgMinMaxDescriptor descriptor;
1122 descriptor.m_Function = ToArgMinMaxFunction(serializerDescriptor->argMinMaxFunction());
1123 descriptor.m_Axis = serializerDescriptor->axis();
1124 auto layerName = GetLayerName(graph, layerIndex);
1125 IConnectableLayer* layer = m_Network->AddArgMinMaxLayer(descriptor, layerName.c_str());
1127 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1128 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1130 RegisterInputSlots(graph, layerIndex, layer);
1131 RegisterOutputSlots(graph, layerIndex, layer);
1134 void Deserializer::ParseBatchToSpaceNd(GraphPtr graph, unsigned int layerIndex)
1136 CHECK_LAYERS(graph, 0, layerIndex);
1138 Deserializer::TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
1139 CHECK_VALID_SIZE(inputs.size(), 1);
1141 Deserializer::TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
1142 CHECK_VALID_SIZE(outputs.size(), 1);
1144 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_BatchToSpaceNdLayer()->descriptor();
1145 auto flatBufferCrops = flatBufferDescriptor->crops();
1146 auto flatBufferBlockShape = flatBufferDescriptor->blockShape();
1148 if (flatBufferCrops->Length() % 2 != 0)
1150 throw ParseException(fmt::format("The size of crops must be divisible by 2 {}", CHECK_LOCATION().AsString()));
1153 std::vector<std::pair<unsigned int, unsigned int>> crops;
1154 crops.reserve(flatBufferCrops->Length() / 2);
1155 for (unsigned int i = 0; i < flatBufferCrops->Length() - 1; i += 2)
1157 crops.emplace_back(flatBufferCrops->Get(i), flatBufferCrops->Get(i+1));
1160 armnn::BatchToSpaceNdDescriptor descriptor;
1161 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
1162 descriptor.m_BlockShape =
1163 std::vector<unsigned int>(flatBufferBlockShape->begin(), flatBufferBlockShape->end());
1164 descriptor.m_Crops = crops;
1166 auto layerName = GetLayerName(graph, layerIndex);
1167 IConnectableLayer* layer = m_Network->AddBatchToSpaceNdLayer(descriptor, layerName.c_str());
1169 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1170 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1172 RegisterInputSlots(graph, layerIndex, layer);
1173 RegisterOutputSlots(graph, layerIndex, layer);
1176 void Deserializer::ParseBatchNormalization(GraphPtr graph, unsigned int layerIndex)
1178 CHECK_LAYERS(graph, 0, layerIndex);
1180 auto inputs = GetInputs(graph, layerIndex);
1181 CHECK_VALID_SIZE(inputs.size(), 1);
1183 auto outputs = GetOutputs(graph, layerIndex);
1184 CHECK_VALID_SIZE(outputs.size(), 1);
1185 auto outputInfo = ToTensorInfo(outputs[0]);
1187 auto layerName = GetLayerName(graph, layerIndex);
1189 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_BatchNormalizationLayer();
1190 auto serializerDescriptor = serializerLayer->descriptor();
1192 armnn::BatchNormalizationDescriptor descriptor;
1193 descriptor.m_Eps = serializerDescriptor->eps();
1194 descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
1196 armnn::ConstTensor mean = ToConstTensor(serializerLayer->mean());
1197 armnn::ConstTensor variance = ToConstTensor(serializerLayer->variance());
1198 armnn::ConstTensor beta = ToConstTensor(serializerLayer->beta());
1199 armnn::ConstTensor gamma = ToConstTensor(serializerLayer->gamma());
1201 IConnectableLayer* layer = m_Network->AddBatchNormalizationLayer(descriptor,
1207 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1209 RegisterInputSlots(graph, layerIndex, layer);
1210 RegisterOutputSlots(graph, layerIndex, layer);
1213 void Deserializer::ParseConstant(GraphPtr graph, unsigned int layerIndex)
1215 CHECK_LAYERS(graph, 0, layerIndex);
1218 auto outputs = GetOutputs(graph, layerIndex);
1219 CHECK_VALID_SIZE(outputs.size(), 1);
1221 auto layerName = GetLayerName(graph, layerIndex);
1223 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_ConstantLayer();
1224 auto serializerInput = serializerLayer->input();
1226 armnn::ConstTensor input = ToConstTensor(serializerInput);
1228 IConnectableLayer* layer = m_Network->AddConstantLayer(input, layerName.c_str());
1230 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1231 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1233 RegisterOutputSlots(graph, layerIndex, layer);
1236 void Deserializer::ParseConvolution2d(GraphPtr graph, unsigned int layerIndex)
1238 CHECK_LAYERS(graph, 0, layerIndex);
1239 auto inputs = GetInputs(graph, layerIndex);
1241 CHECK_VALID_SIZE(inputs.size(), 1);
1243 auto outputs = GetOutputs(graph, layerIndex);
1244 CHECK_VALID_SIZE(outputs.size(), 1);
1246 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_Convolution2dLayer();
1247 auto layerName = GetLayerName(graph, layerIndex);
1248 auto serializerDescriptor = serializerLayer->descriptor();
1250 armnn::Convolution2dDescriptor descriptor;
1251 descriptor.m_PadLeft = serializerDescriptor->padLeft();
1252 descriptor.m_PadRight = serializerDescriptor->padRight();
1253 descriptor.m_PadTop = serializerDescriptor->padTop();
1254 descriptor.m_PadBottom = serializerDescriptor->padBottom();
1255 descriptor.m_StrideX = serializerDescriptor->strideX();
1256 descriptor.m_StrideY = serializerDescriptor->strideY();;
1257 descriptor.m_DilationX = serializerDescriptor->dilationX();
1258 descriptor.m_DilationY = serializerDescriptor->dilationY();;
1259 descriptor.m_BiasEnabled = serializerDescriptor->biasEnabled();;
1260 descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
1262 armnn::ConstTensor weights = ToConstTensor(serializerLayer->weights());
1263 armnn::ConstTensor biases;
1265 armnn::Optional<armnn::ConstTensor> optionalBiases = armnn::EmptyOptional();
1266 if (descriptor.m_BiasEnabled)
1268 biases = ToConstTensor(serializerLayer->biases());
1269 optionalBiases = armnn::Optional<armnn::ConstTensor>(biases);
1271 IConnectableLayer* layer = m_Network->AddConvolution2dLayer(descriptor,
1275 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1276 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1278 RegisterInputSlots(graph, layerIndex, layer);
1279 RegisterOutputSlots(graph, layerIndex, layer);
1282 void Deserializer::ParseDepthToSpace(GraphPtr graph, unsigned int layerIndex)
1284 CHECK_LAYERS(graph, 0, layerIndex);
1286 auto inputs = GetInputs(graph, layerIndex);
1287 CHECK_VALID_SIZE(inputs.size(), 1);
1289 auto outputs = GetOutputs(graph, layerIndex);
1290 CHECK_VALID_SIZE(outputs.size(), 1);
1292 auto fbDescriptor = graph->layers()->Get(layerIndex)->layer_as_DepthToSpaceLayer()->descriptor();
1294 armnn::DepthToSpaceDescriptor descriptor;
1295 descriptor.m_BlockSize = fbDescriptor->blockSize();
1296 descriptor.m_DataLayout = ToDataLayout(fbDescriptor->dataLayout());
1298 auto layerName = GetLayerName(graph, layerIndex);
1299 IConnectableLayer* layer = m_Network->AddDepthToSpaceLayer(descriptor, layerName.c_str());
1301 armnn::TensorInfo outputInfo = ToTensorInfo(outputs[0]);
1302 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1304 RegisterInputSlots(graph, layerIndex, layer);
1305 RegisterOutputSlots(graph, layerIndex, layer);
1308 void Deserializer::ParseDepthwiseConvolution2d(GraphPtr graph, unsigned int layerIndex)
1310 CHECK_LAYERS(graph, 0, layerIndex);
1311 auto inputs = GetInputs(graph, layerIndex);
1313 CHECK_VALID_SIZE(inputs.size(), 1);
1315 auto outputs = GetOutputs(graph, layerIndex);
1316 CHECK_VALID_SIZE(outputs.size(), 1);
1318 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_DepthwiseConvolution2dLayer();
1319 auto layerName = GetLayerName(graph, layerIndex);
1320 auto serializerDescriptor = serializerLayer->descriptor();
1322 armnn::DepthwiseConvolution2dDescriptor descriptor;
1323 descriptor.m_PadLeft = serializerDescriptor->padLeft();
1324 descriptor.m_PadRight = serializerDescriptor->padRight();
1325 descriptor.m_PadTop = serializerDescriptor->padTop();
1326 descriptor.m_PadBottom = serializerDescriptor->padBottom();
1327 descriptor.m_StrideX = serializerDescriptor->strideX();
1328 descriptor.m_StrideY = serializerDescriptor->strideY();
1329 descriptor.m_DilationX = serializerDescriptor->dilationX();
1330 descriptor.m_DilationY = serializerDescriptor->dilationY();
1331 descriptor.m_BiasEnabled = serializerDescriptor->biasEnabled();;
1332 descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
1334 armnn::ConstTensor weights = ToConstTensor(serializerLayer->weights());
1335 armnn::ConstTensor biases;
1337 armnn::Optional<armnn::ConstTensor> optionalBiases = armnn::EmptyOptional();
1338 if (descriptor.m_BiasEnabled)
1340 biases = ToConstTensor(serializerLayer->biases());
1341 optionalBiases = armnn::Optional<armnn::ConstTensor>(biases);
1343 IConnectableLayer* layer = m_Network->AddDepthwiseConvolution2dLayer(descriptor,
1348 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1349 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1351 RegisterInputSlots(graph, layerIndex, layer);
1352 RegisterOutputSlots(graph, layerIndex, layer);
1355 void Deserializer::ParseDetectionPostProcess(GraphPtr graph, unsigned int layerIndex)
1357 CHECK_LAYERS(graph, 0, layerIndex);
1358 auto inputs = GetInputs(graph, layerIndex);
1360 CHECK_VALID_SIZE(inputs.size(), 2);
1362 auto outputs = GetOutputs(graph, layerIndex);
1363 CHECK_VALID_SIZE(outputs.size(), 4);
1365 auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_DetectionPostProcessLayer();
1366 auto layerName = GetLayerName(graph, layerIndex);
1367 auto flatBufferDescriptor = flatBufferLayer->descriptor();
1369 armnn::DetectionPostProcessDescriptor descriptor;
1370 descriptor.m_MaxDetections = flatBufferDescriptor->maxDetections();
1371 descriptor.m_MaxClassesPerDetection = flatBufferDescriptor->maxClassesPerDetection();
1372 descriptor.m_DetectionsPerClass = flatBufferDescriptor->detectionsPerClass();
1373 descriptor.m_NmsScoreThreshold = flatBufferDescriptor->nmsScoreThreshold();
1374 descriptor.m_NmsIouThreshold = flatBufferDescriptor->nmsIouThreshold();
1375 descriptor.m_NumClasses = flatBufferDescriptor->numClasses();
1376 descriptor.m_UseRegularNms = flatBufferDescriptor->useRegularNms();
1377 descriptor.m_ScaleX = flatBufferDescriptor->scaleX();
1378 descriptor.m_ScaleY = flatBufferDescriptor->scaleY();
1379 descriptor.m_ScaleW = flatBufferDescriptor->scaleW();
1380 descriptor.m_ScaleH = flatBufferDescriptor->scaleH();
1382 armnn::ConstTensor anchors = ToConstTensor(flatBufferLayer->anchors());
1384 IConnectableLayer* layer = m_Network->AddDetectionPostProcessLayer(descriptor,
1388 for (unsigned int i = 0; i < 4; i++)
1390 layer->GetOutputSlot(i).SetTensorInfo(ToTensorInfo(outputs[i]));
1393 RegisterInputSlots(graph, layerIndex, layer);
1394 RegisterOutputSlots(graph, layerIndex, layer);
1397 void Deserializer::ParseDivision(GraphPtr graph, unsigned int layerIndex)
1399 CHECK_LAYERS(graph, 0, layerIndex);
1400 auto inputs = GetInputs(graph, layerIndex);
1402 CHECK_VALID_SIZE(inputs.size(), 2);
1404 auto outputs = GetOutputs(graph, layerIndex);
1405 CHECK_VALID_SIZE(outputs.size(), 1);
1407 auto layerName = GetLayerName(graph, layerIndex);
1408 IConnectableLayer* layer = m_Network->AddDivisionLayer(layerName.c_str());
1410 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1411 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1413 RegisterInputSlots(graph, layerIndex, layer);
1414 RegisterOutputSlots(graph, layerIndex, layer);
1417 void Deserializer::ParseEqual(GraphPtr graph, unsigned int layerIndex)
1419 CHECK_LAYERS(graph, 0, layerIndex);
1420 auto inputs = GetInputs(graph, layerIndex);
1422 CHECK_VALID_SIZE(inputs.size(), 2);
1424 auto outputs = GetOutputs(graph, layerIndex);
1425 CHECK_VALID_SIZE(outputs.size(), 1);
1427 auto layerName = GetLayerName(graph, layerIndex);
1428 armnn::ComparisonDescriptor descriptor(armnn::ComparisonOperation::Equal);
1429 IConnectableLayer* layer = m_Network->AddComparisonLayer(descriptor, layerName.c_str());
1431 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1432 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1434 RegisterInputSlots(graph, layerIndex, layer);
1435 RegisterOutputSlots(graph, layerIndex, layer);
1438 void Deserializer::ParseFill(GraphPtr graph, unsigned int layerIndex)
1440 CHECK_LAYERS(graph, 0, layerIndex);
1441 auto inputs = GetInputs(graph, layerIndex);
1443 CHECK_VALID_SIZE(inputs.size(), 1);
1445 auto outputs = GetOutputs(graph, layerIndex);
1446 CHECK_VALID_SIZE(outputs.size(), 1);
1448 auto layerName = GetLayerName(graph, layerIndex);
1449 armnn::FillDescriptor descriptor(1.0f);
1450 IConnectableLayer* layer = m_Network->AddFillLayer(descriptor, layerName.c_str());
1452 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1453 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1455 RegisterInputSlots(graph, layerIndex, layer);
1456 RegisterOutputSlots(graph, layerIndex, layer);
1459 void Deserializer::ParseGreater(GraphPtr graph, unsigned int layerIndex)
1461 CHECK_LAYERS(graph, 0, layerIndex);
1462 auto inputs = GetInputs(graph, layerIndex);
1464 CHECK_VALID_SIZE(inputs.size(), 2);
1466 auto outputs = GetOutputs(graph, layerIndex);
1467 CHECK_VALID_SIZE(outputs.size(), 1);
1469 auto layerName = GetLayerName(graph, layerIndex);
1470 armnn::ComparisonDescriptor descriptor(armnn::ComparisonOperation::Greater);
1471 IConnectableLayer* layer = m_Network->AddComparisonLayer(descriptor, layerName.c_str());
1473 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1474 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1476 RegisterInputSlots(graph, layerIndex, layer);
1477 RegisterOutputSlots(graph, layerIndex, layer);
1480 void Deserializer::ParseInstanceNormalization(GraphPtr graph, unsigned int layerIndex)
1482 CHECK_LAYERS(graph, 0, layerIndex);
1484 auto inputs = GetInputs(graph, layerIndex);
1485 CHECK_VALID_SIZE(inputs.size(), 1);
1487 auto outputs = GetOutputs(graph, layerIndex);
1488 CHECK_VALID_SIZE(outputs.size(), 1);
1490 auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_InstanceNormalizationLayer();
1491 auto fbDescriptor = fbLayer->descriptor();
1493 armnn::InstanceNormalizationDescriptor descriptor;
1494 descriptor.m_Gamma = fbDescriptor->gamma();
1495 descriptor.m_Beta = fbDescriptor->beta();
1496 descriptor.m_Eps = fbDescriptor->eps();
1497 descriptor.m_DataLayout = ToDataLayout(fbDescriptor->dataLayout());
1499 const std::string layerName = GetLayerName(graph, layerIndex);
1500 const armnn::TensorInfo outputInfo = ToTensorInfo(outputs[0]);
1502 IConnectableLayer* layer = m_Network->AddInstanceNormalizationLayer(descriptor, layerName.c_str());
1503 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1505 RegisterInputSlots(graph, layerIndex, layer);
1506 RegisterOutputSlots(graph, layerIndex, layer);
1509 void Deserializer::ParseL2Normalization(GraphPtr graph, unsigned int layerIndex)
1511 CHECK_LAYERS(graph, 0, layerIndex);
1513 auto inputs = GetInputs(graph, layerIndex);
1514 CHECK_VALID_SIZE(inputs.size(), 1);
1516 auto outputs = GetOutputs(graph, layerIndex);
1517 CHECK_VALID_SIZE(outputs.size(), 1);
1518 auto outputInfo = ToTensorInfo(outputs[0]);
1520 auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_L2NormalizationLayer();
1521 auto flatBufferDescriptor = flatBufferLayer->descriptor();
1523 auto layerName = GetLayerName(graph, layerIndex);
1524 armnn::L2NormalizationDescriptor descriptor;
1525 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
1526 descriptor.m_Eps = flatBufferDescriptor->eps();
1528 IConnectableLayer* layer = m_Network->AddL2NormalizationLayer(descriptor, layerName.c_str());
1529 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1531 RegisterInputSlots(graph, layerIndex, layer);
1532 RegisterOutputSlots(graph, layerIndex, layer);
1535 void Deserializer::ParseLogicalBinary(GraphPtr graph, unsigned int layerIndex)
1537 CHECK_LAYERS(graph, 0, layerIndex);
1540 auto inputs = GetInputs(graph, layerIndex);
1541 CHECK_VALID_SIZE(inputs.size(), 2);
1543 auto outputs = GetOutputs(graph, layerIndex);
1544 CHECK_VALID_SIZE(outputs.size(), 1);
1546 auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_LogicalBinaryLayer();
1547 auto fbDescriptor = fbLayer->descriptor();
1549 armnn::LogicalBinaryDescriptor descriptor;
1550 descriptor.m_Operation = ToLogicalBinaryOperation(fbDescriptor->operation());
1552 const std::string& layerName = GetLayerName(graph, layerIndex);
1553 IConnectableLayer* layer = m_Network->AddLogicalBinaryLayer(descriptor, layerName.c_str());
1555 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1556 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1558 RegisterInputSlots(graph, layerIndex, layer);
1559 RegisterOutputSlots(graph, layerIndex, layer);
1562 void Deserializer::ParseLogSoftmax(GraphPtr graph, unsigned int layerIndex)
1564 CHECK_LAYERS(graph, 0, layerIndex);
1566 Deserializer::TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
1567 CHECK_VALID_SIZE(inputs.size(), 1);
1569 Deserializer::TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
1570 CHECK_VALID_SIZE(outputs.size(), 1);
1572 armnn::LogSoftmaxDescriptor descriptor;
1573 descriptor.m_Beta = graph->layers()->Get(layerIndex)->layer_as_LogSoftmaxLayer()->descriptor()->beta();
1574 descriptor.m_Axis = graph->layers()->Get(layerIndex)->layer_as_LogSoftmaxLayer()->descriptor()->axis();
1575 auto layerName = GetLayerName(graph, layerIndex);
1577 IConnectableLayer* layer = m_Network->AddLogSoftmaxLayer(descriptor, layerName.c_str());
1579 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1580 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1582 RegisterInputSlots(graph, layerIndex, layer);
1583 RegisterOutputSlots(graph, layerIndex, layer);
1586 void Deserializer::ParseMinimum(GraphPtr graph, unsigned int layerIndex)
1588 CHECK_LAYERS(graph, 0, layerIndex);
1589 auto inputs = GetInputs(graph, layerIndex);
1591 CHECK_VALID_SIZE(inputs.size(), 2);
1593 auto outputs = GetOutputs(graph, layerIndex);
1594 CHECK_VALID_SIZE(outputs.size(), 1);
1596 auto layerName = GetLayerName(graph, layerIndex);
1597 IConnectableLayer* layer = m_Network->AddMinimumLayer(layerName.c_str());
1599 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1600 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1602 RegisterInputSlots(graph, layerIndex, layer);
1603 RegisterOutputSlots(graph, layerIndex, layer);
1606 void Deserializer::ParseMaximum(GraphPtr graph, unsigned int layerIndex)
1608 CHECK_LAYERS(graph, 0, layerIndex);
1609 auto inputs = GetInputs(graph, layerIndex);
1611 CHECK_VALID_SIZE(inputs.size(), 2);
1613 auto outputs = GetOutputs(graph, layerIndex);
1614 CHECK_VALID_SIZE(outputs.size(), 1);
1616 auto layerName = GetLayerName(graph, layerIndex);
1617 IConnectableLayer* layer = m_Network->AddMaximumLayer(layerName.c_str());
1619 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1620 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1622 RegisterInputSlots(graph, layerIndex, layer);
1623 RegisterOutputSlots(graph, layerIndex, layer);
1626 const armnnSerializer::OriginsDescriptor* GetOriginsDescriptor(const armnnSerializer::SerializedGraph* graph,
1627 unsigned int layerIndex)
1629 auto layerType = graph->layers()->Get(layerIndex)->layer_type();
1633 case Layer::Layer_ConcatLayer:
1634 return graph->layers()->Get(layerIndex)->layer_as_ConcatLayer()->descriptor();
1635 case Layer::Layer_MergerLayer:
1636 return graph->layers()->Get(layerIndex)->layer_as_MergerLayer()->descriptor();
1638 throw armnn::Exception("unknown layer type, should be concat or merger");
1642 void Deserializer::ParseComparison(GraphPtr graph, unsigned int layerIndex)
1644 CHECK_LAYERS(graph, 0, layerIndex);
1647 auto inputs = GetInputs(graph, layerIndex);
1648 CHECK_VALID_SIZE(inputs.size(), 2);
1650 auto outputs = GetOutputs(graph, layerIndex);
1651 CHECK_VALID_SIZE(outputs.size(), 1);
1653 auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_ComparisonLayer();
1654 auto fbDescriptor = fbLayer->descriptor();
1656 armnn::ComparisonDescriptor descriptor;
1657 descriptor.m_Operation = ToComparisonOperation(fbDescriptor->operation());
1659 const std::string& layerName = GetLayerName(graph, layerIndex);
1660 IConnectableLayer* layer = m_Network->AddComparisonLayer(descriptor, layerName.c_str());
1662 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1663 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1665 RegisterInputSlots(graph, layerIndex, layer);
1666 RegisterOutputSlots(graph, layerIndex, layer);
1669 void Deserializer::ParseElementwiseUnary(GraphPtr graph, unsigned int layerIndex)
1671 CHECK_LAYERS(graph, 0, layerIndex);
1674 auto inputs = GetInputs(graph, layerIndex);
1675 CHECK_VALID_SIZE(inputs.size(), 1);
1677 auto outputs = GetOutputs(graph, layerIndex);
1678 CHECK_VALID_SIZE(outputs.size(), 1);
1680 auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_ElementwiseUnaryLayer();
1681 auto fbDescriptor = fbLayer->descriptor();
1683 armnn::ElementwiseUnaryDescriptor descriptor;
1684 descriptor.m_Operation = ToUnaryOperation(fbDescriptor->operation());
1686 const std::string& layerName = GetLayerName(graph, layerIndex);
1687 IConnectableLayer* layer = m_Network->AddElementwiseUnaryLayer(descriptor, layerName.c_str());
1689 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1690 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1692 RegisterInputSlots(graph, layerIndex, layer);
1693 RegisterOutputSlots(graph, layerIndex, layer);
1696 void Deserializer::ParseConcat(GraphPtr graph, unsigned int layerIndex)
1698 CHECK_LAYERS(graph, 0, layerIndex);
1701 auto outputs = GetOutputs(graph, layerIndex);
1702 CHECK_VALID_SIZE(outputs.size(), 1);
1704 auto layerName = GetLayerName(graph, layerIndex);
1705 auto originsDescriptor = GetOriginsDescriptor(graph, layerIndex);
1706 unsigned int numViews = originsDescriptor->numViews();
1707 unsigned int numDimensions = originsDescriptor->numDimensions();
1709 // can now check the number of inputs == number of views
1710 auto inputs = GetInputs(graph, layerIndex);
1711 CHECK_VALID_SIZE(inputs.size(), numViews);
1713 armnn::OriginsDescriptor descriptor(numViews, numDimensions);
1714 auto originsPtr = originsDescriptor->viewOrigins();
1715 for (unsigned int v = 0; v < numViews; ++v)
1717 auto originPtr = originsPtr->Get(v);
1718 for (unsigned int d = 0; d < numDimensions; ++d)
1720 uint32_t value = originPtr->data()->Get(d);
1721 descriptor.SetViewOriginCoord(v, d, value);
1724 descriptor.SetConcatAxis(originsDescriptor->concatAxis());
1726 IConnectableLayer* layer = m_Network->AddConcatLayer(descriptor, layerName.c_str());
1727 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1728 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1730 RegisterInputSlots(graph, layerIndex, layer);
1731 RegisterOutputSlots(graph, layerIndex, layer);
1734 void Deserializer::ParseMultiplication(GraphPtr graph, unsigned int layerIndex)
1736 CHECK_LAYERS(graph, 0, layerIndex);
1737 auto inputs = GetInputs(graph, layerIndex);
1739 CHECK_VALID_SIZE(inputs.size(), 2);
1741 auto outputs = GetOutputs(graph, layerIndex);
1742 CHECK_VALID_SIZE(outputs.size(), 1);
1744 auto layerName = GetLayerName(graph, layerIndex);
1745 IConnectableLayer* layer = m_Network->AddMultiplicationLayer(layerName.c_str());
1747 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1748 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1750 RegisterInputSlots(graph, layerIndex, layer);
1751 RegisterOutputSlots(graph, layerIndex, layer);
1754 void Deserializer::ParseFloor(GraphPtr graph, unsigned int layerIndex)
1756 CHECK_LAYERS(graph, 0, layerIndex);
1759 auto inputs = GetInputs(graph, layerIndex);
1760 CHECK_VALID_SIZE(inputs.size(), 1);
1762 auto outputs = GetOutputs(graph, layerIndex);
1763 CHECK_VALID_SIZE(outputs.size(), 1);
1765 auto layerName = GetLayerName(graph, layerIndex);
1767 armnn::IConnectableLayer* layer;
1769 layer = m_Network->AddFloorLayer(layerName.c_str());
1771 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1772 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1774 RegisterInputSlots(graph, layerIndex, layer);
1775 RegisterOutputSlots(graph, layerIndex, layer);
1778 void Deserializer::ParseFullyConnected(GraphPtr graph, unsigned int layerIndex)
1780 CHECK_LAYERS(graph, 0, layerIndex);
1781 auto inputs = GetInputs(graph, layerIndex);
1783 CHECK_VALID_SIZE(inputs.size(), 1);
1785 auto outputs = GetOutputs(graph, layerIndex);
1786 CHECK_VALID_SIZE(outputs.size(), 1);
1788 auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_FullyConnectedLayer();
1789 auto layerName = GetLayerName(graph, layerIndex);
1790 auto flatBufferDescriptor = flatBufferLayer->descriptor();
1792 armnn::FullyConnectedDescriptor fullyConnectedDescriptor;
1793 fullyConnectedDescriptor.m_BiasEnabled = flatBufferDescriptor->biasEnabled();
1794 fullyConnectedDescriptor.m_TransposeWeightMatrix = flatBufferDescriptor->transposeWeightsMatrix();
1796 armnn::ConstTensor weightsTensor = ToConstTensor(flatBufferLayer->weights());
1798 armnn::IConnectableLayer* layer;
1799 armnn::Optional<armnn::ConstTensor> optionalBiases = armnn::EmptyOptional();
1800 if (flatBufferDescriptor->biasEnabled())
1802 armnn::ConstTensor biasTensorData = ToConstTensor(flatBufferLayer->biases());
1803 optionalBiases = armnn::Optional<armnn::ConstTensor>(biasTensorData);
1805 layer = m_Network->AddFullyConnectedLayer(fullyConnectedDescriptor,
1810 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1811 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1813 RegisterInputSlots(graph, layerIndex, layer);
1814 RegisterOutputSlots(graph, layerIndex, layer);
1817 void Deserializer::ParsePad(GraphPtr graph, unsigned int layerIndex)
1819 CHECK_LAYERS(graph, 0, layerIndex);
1821 Deserializer::TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
1822 CHECK_VALID_SIZE(inputs.size(), 1);
1824 Deserializer::TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
1825 CHECK_VALID_SIZE(outputs.size(), 1);
1827 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_PadLayer()->descriptor();
1828 auto flatBufferPadList = flatBufferDescriptor->padList();
1829 float padValue = flatBufferDescriptor->padValue();
1831 if (flatBufferPadList->Length() % 2 != 0)
1833 throw ParseException(fmt::format("The size of the pad list must be divisible by 2 {}",
1834 CHECK_LOCATION().AsString()));
1837 std::vector<std::pair<unsigned int, unsigned int>> padList;
1838 padList.reserve(flatBufferPadList->Length() / 2);
1839 for (unsigned int i = 0; i < flatBufferPadList->Length() - 1; i += 2)
1841 padList.emplace_back(flatBufferPadList->Get(i), flatBufferPadList->Get(i+1));
1844 armnn::PadDescriptor descriptor(padList, padValue);
1846 auto layerName = GetLayerName(graph, layerIndex);
1847 IConnectableLayer* layer = m_Network->AddPadLayer(descriptor, layerName.c_str());
1849 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1850 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1852 RegisterInputSlots(graph, layerIndex, layer);
1853 RegisterOutputSlots(graph, layerIndex, layer);
1856 void Deserializer::ParsePermute(GraphPtr graph, unsigned int layerIndex)
1858 CHECK_LAYERS(graph, 0, layerIndex);
1861 graph->layers()->Get(layerIndex)->layer_as_PermuteLayer()->descriptor()->dimMappings();
1863 auto inputs = GetInputs(graph, layerIndex);
1864 CHECK_VALID_SIZE(inputs.size(), 1);
1866 auto outputs = GetOutputs(graph, layerIndex);
1867 CHECK_VALID_SIZE(outputs.size(), 1);
1868 auto outputInfo = ToTensorInfo(outputs[0]);
1870 auto layerName = GetLayerName(graph, layerIndex);
1871 const armnn::PermuteDescriptor descriptor(armnn::PermutationVector(dimsMapping->data(), dimsMapping->Length()));
1873 IConnectableLayer* layer = m_Network->AddPermuteLayer(descriptor, layerName.c_str());
1874 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1876 RegisterInputSlots(graph, layerIndex, layer);
1877 RegisterOutputSlots(graph, layerIndex, layer);
1880 armnn::Pooling2dDescriptor Deserializer::GetPoolingDescriptor(Deserializer::PoolingDescriptor pooling2dDesc,
1881 unsigned int layerIndex)
1883 IgnoreUnused(layerIndex);
1884 armnn::Pooling2dDescriptor desc;
1886 switch (pooling2dDesc->poolType())
1888 case PoolingAlgorithm_Average:
1890 desc.m_PoolType = armnn::PoolingAlgorithm::Average;
1893 case PoolingAlgorithm_Max:
1895 desc.m_PoolType = armnn::PoolingAlgorithm::Max;
1900 ARMNN_ASSERT_MSG(false, "Unsupported pooling algorithm");
1904 switch (pooling2dDesc->outputShapeRounding())
1906 case OutputShapeRounding_Floor:
1908 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
1911 case OutputShapeRounding_Ceiling:
1913 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Ceiling;
1918 ARMNN_ASSERT_MSG(false, "Unsupported output shape rounding");
1922 switch (pooling2dDesc->paddingMethod())
1924 case PaddingMethod_Exclude:
1926 desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
1929 case PaddingMethod_IgnoreValue:
1931 desc.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1936 ARMNN_ASSERT_MSG(false, "Unsupported padding method");
1940 switch (pooling2dDesc->dataLayout())
1942 case DataLayout_NCHW:
1944 desc.m_DataLayout = armnn::DataLayout::NCHW;
1947 case DataLayout_NHWC:
1949 desc.m_DataLayout = armnn::DataLayout::NHWC;
1954 ARMNN_ASSERT_MSG(false, "Unsupported data layout");
1958 desc.m_PadRight = pooling2dDesc->padRight();
1959 desc.m_PadLeft = pooling2dDesc->padLeft();
1960 desc.m_PadBottom = pooling2dDesc->padBottom();
1961 desc.m_PadTop = pooling2dDesc->padTop();
1962 desc.m_StrideX = pooling2dDesc->strideX();
1963 desc.m_StrideY = pooling2dDesc->strideY();
1964 desc.m_PoolWidth = pooling2dDesc->poolWidth();
1965 desc.m_PoolHeight = pooling2dDesc->poolHeight();
1970 void Deserializer::ParsePooling2d(GraphPtr graph, unsigned int layerIndex)
1972 CHECK_LAYERS(graph, 0, layerIndex);
1974 auto pooling2dDes = graph->layers()->Get(layerIndex)->layer_as_Pooling2dLayer()->descriptor();
1975 auto inputs = GetInputs(graph, layerIndex);
1976 CHECK_VALID_SIZE(inputs.size(), 1);
1978 auto outputs = GetOutputs(graph, layerIndex);
1979 CHECK_VALID_SIZE(outputs.size(), 1);
1980 auto outputInfo = ToTensorInfo(outputs[0]);
1982 auto pooling2dDescriptor = GetPoolingDescriptor(pooling2dDes, layerIndex);
1983 auto layerName = GetLayerName(graph, layerIndex);
1984 IConnectableLayer* layer = m_Network->AddPooling2dLayer(pooling2dDescriptor, layerName.c_str());
1985 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1987 RegisterInputSlots(graph, layerIndex, layer);
1988 RegisterOutputSlots(graph, layerIndex, layer);
1991 void Deserializer::ParseQuantize(GraphPtr graph, unsigned int layerIndex)
1993 CHECK_LAYERS(graph, 0, layerIndex);
1995 auto inputs = GetInputs(graph, layerIndex);
1996 CHECK_VALID_SIZE(inputs.size(), 1);
1998 auto outputs = GetOutputs(graph, layerIndex);
1999 CHECK_VALID_SIZE(outputs.size(), 1);
2000 auto outputInfo = ToTensorInfo(outputs[0]);
2002 auto layerName = GetLayerName(graph, layerIndex);
2003 IConnectableLayer* layer = m_Network->AddQuantizeLayer(layerName.c_str());
2004 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2006 RegisterInputSlots(graph, layerIndex, layer);
2007 RegisterOutputSlots(graph, layerIndex, layer);
2010 armnn::TensorInfo Deserializer::OutputShapeOfReshape(const armnn::TensorInfo& inputTensorInfo,
2011 const std::vector<uint32_t>& targetDimsIn)
2013 std::vector<unsigned int> outputDims(targetDimsIn.begin(), targetDimsIn.end());
2014 const auto stretchDim = std::find(targetDimsIn.begin(), targetDimsIn.end(), -1);
2016 if (stretchDim != targetDimsIn.end())
2018 if (std::find(std::next(stretchDim), targetDimsIn.end(), -1) != targetDimsIn.end())
2020 throw ParseException(fmt::format("At most one component of shape can be -1 {}",
2021 CHECK_LOCATION().AsString()));
2024 auto targetNumElements =
2025 armnn::numeric_cast<unsigned int>(
2026 std::accumulate(targetDimsIn.begin(), targetDimsIn.end(), -1, std::multiplies<int32_t>()));
2028 auto stretchIndex = static_cast<size_t>(std::distance(targetDimsIn.begin(), stretchDim));
2029 outputDims[stretchIndex] = inputTensorInfo.GetNumElements() / targetNumElements;
2032 TensorShape outputShape = TensorShape(static_cast<unsigned int>(outputDims.size()), outputDims.data());
2034 armnn::TensorInfo reshapeInfo = inputTensorInfo;
2035 reshapeInfo.SetShape(outputShape);
2040 void Deserializer::ParseRank(GraphPtr graph, unsigned int layerIndex)
2042 CHECK_LAYERS(graph, 0, layerIndex);
2044 Deserializer::TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2045 CHECK_VALID_SIZE(inputs.size(), 1);
2047 Deserializer::TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2048 CHECK_VALID_SIZE(outputs.size(), 1);
2050 auto layerName = GetLayerName(graph, layerIndex);
2051 IConnectableLayer* layer = m_Network->AddRankLayer( layerName.c_str());
2053 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2054 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2056 RegisterInputSlots(graph, layerIndex, layer);
2057 RegisterOutputSlots(graph, layerIndex, layer);
2060 void Deserializer::ParseReshape(GraphPtr graph, unsigned int layerIndex)
2062 CHECK_LAYERS(graph, 0, layerIndex);
2063 auto inputs = GetInputs(graph, layerIndex);
2065 auto outputs = GetOutputs(graph, layerIndex);
2066 CHECK_VALID_SIZE(outputs.size(), 1);
2068 armnn::TensorInfo inputTensorInfo = ToTensorInfo(inputs[0]);
2069 armnn::TensorInfo actualOutputTensorInfo = ToTensorInfo(outputs[0]);
2071 const auto targetDims = graph->layers()->Get(layerIndex)->layer_as_ReshapeLayer()->descriptor()->targetShape();
2072 std::vector<uint32_t> outputDims(targetDims->begin(), targetDims->begin() + targetDims->size());
2074 armnn::TensorInfo reshapeOutputTensorInfo = Deserializer::OutputShapeOfReshape(inputTensorInfo, outputDims);
2075 const armnn::TensorShape& reshapeOutputTensorShape = reshapeOutputTensorInfo.GetShape();
2077 const std::vector<uint32_t> expectedDims(outputs[0]->dimensions()->begin(),
2078 outputs[0]->dimensions()->begin() + outputs[0]->dimensions()->size());
2080 if (inputs.size() > 1 && !CheckShape(reshapeOutputTensorShape, expectedDims))
2082 std::stringstream ss;
2083 ss << "New shape defined in reshape parameters "
2084 << reshapeOutputTensorShape
2085 << " does not equal output shape "
2086 << actualOutputTensorInfo.GetShape()
2088 << CHECK_LOCATION().AsString();
2089 throw ParseException(ss.str());
2092 armnn::ReshapeDescriptor reshapeDesc;
2093 reshapeDesc.m_TargetShape = reshapeOutputTensorShape;
2095 auto layerName = GetLayerName(graph, layerIndex);
2096 IConnectableLayer* layer = m_Network->AddReshapeLayer(reshapeDesc, layerName.c_str());
2097 layer->GetOutputSlot(0).SetTensorInfo(reshapeOutputTensorInfo);
2099 RegisterInputSlots(graph, layerIndex, layer);
2100 RegisterOutputSlots(graph, layerIndex, layer);
2103 void Deserializer::ParseResize(GraphPtr graph, unsigned int layerIndex)
2105 CHECK_LAYERS(graph, 0, layerIndex);
2107 Deserializer::TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2108 CHECK_VALID_SIZE(inputs.size(), 1);
2110 Deserializer::TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2111 CHECK_VALID_SIZE(outputs.size(), 1);
2113 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_ResizeLayer()->descriptor();
2115 armnn::ResizeDescriptor descriptor;
2116 descriptor.m_TargetWidth = flatBufferDescriptor->targetWidth();
2117 descriptor.m_TargetHeight = flatBufferDescriptor->targetHeight();
2118 descriptor.m_Method = ToResizeMethod(flatBufferDescriptor->method());
2119 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2120 descriptor.m_AlignCorners = flatBufferDescriptor->alignCorners();
2121 descriptor.m_HalfPixelCenters = flatBufferDescriptor->halfPixelCenters();
2123 auto layerName = GetLayerName(graph, layerIndex);
2124 IConnectableLayer* layer = m_Network->AddResizeLayer(descriptor, layerName.c_str());
2126 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2127 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2129 RegisterInputSlots(graph, layerIndex, layer);
2130 RegisterOutputSlots(graph, layerIndex, layer);
2133 void Deserializer::ParseResizeBilinear(GraphPtr graph, unsigned int layerIndex)
2135 CHECK_LAYERS(graph, 0, layerIndex);
2137 Deserializer::TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2138 CHECK_VALID_SIZE(inputs.size(), 1);
2140 Deserializer::TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2141 CHECK_VALID_SIZE(outputs.size(), 1);
2143 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_ResizeBilinearLayer()->descriptor();
2145 armnn::ResizeDescriptor descriptor;
2146 descriptor.m_TargetWidth = flatBufferDescriptor->targetWidth();
2147 descriptor.m_TargetHeight = flatBufferDescriptor->targetHeight();
2148 descriptor.m_Method = armnn::ResizeMethod::Bilinear;
2149 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2150 descriptor.m_AlignCorners = flatBufferDescriptor->alignCorners();
2151 descriptor.m_HalfPixelCenters = flatBufferDescriptor->halfPixelCenters();
2153 auto layerName = GetLayerName(graph, layerIndex);
2154 IConnectableLayer* layer = m_Network->AddResizeLayer(descriptor, layerName.c_str());
2156 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2157 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2159 RegisterInputSlots(graph, layerIndex, layer);
2160 RegisterOutputSlots(graph, layerIndex, layer);
2163 void Deserializer::ParseSoftmax(GraphPtr graph, unsigned int layerIndex)
2165 CHECK_LAYERS(graph, 0, layerIndex);
2167 Deserializer::TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2168 CHECK_VALID_SIZE(inputs.size(), 1);
2170 Deserializer::TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2171 CHECK_VALID_SIZE(outputs.size(), 1);
2173 armnn::SoftmaxDescriptor descriptor;
2174 descriptor.m_Beta = graph->layers()->Get(layerIndex)->layer_as_SoftmaxLayer()->descriptor()->beta();
2175 auto layerName = GetLayerName(graph, layerIndex);
2177 IConnectableLayer* layer = m_Network->AddSoftmaxLayer(descriptor, layerName.c_str());
2179 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2180 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2182 RegisterInputSlots(graph, layerIndex, layer);
2183 RegisterOutputSlots(graph, layerIndex, layer);
2186 void Deserializer::ParseSpaceToBatchNd(GraphPtr graph, unsigned int layerIndex)
2188 CHECK_LAYERS(graph, 0, layerIndex);
2190 Deserializer::TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2191 CHECK_VALID_SIZE(inputs.size(), 1);
2193 Deserializer::TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2194 CHECK_VALID_SIZE(outputs.size(), 1);
2196 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_SpaceToBatchNdLayer()->descriptor();
2197 auto flatBufferPadList = flatBufferDescriptor->padList();
2198 auto flatBufferBlockShape = flatBufferDescriptor->blockShape();
2200 if (flatBufferPadList->Length() % 2 != 0)
2202 throw ParseException(fmt::format("The size of the pad list must be divisible by 2 {}",
2203 CHECK_LOCATION().AsString()));
2206 std::vector<std::pair<unsigned int, unsigned int>> padList;
2207 padList.reserve(flatBufferPadList->Length() / 2);
2208 for (unsigned int i = 0; i < flatBufferPadList->Length() - 1; i += 2)
2210 padList.emplace_back(flatBufferPadList->Get(i), flatBufferPadList->Get(i+1));
2213 armnn::SpaceToBatchNdDescriptor descriptor;
2214 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2215 descriptor.m_BlockShape =
2216 std::vector<unsigned int>(flatBufferBlockShape->begin(), flatBufferBlockShape->end());
2217 descriptor.m_PadList = padList;
2219 auto layerName = GetLayerName(graph, layerIndex);
2220 IConnectableLayer* layer = m_Network->AddSpaceToBatchNdLayer(descriptor, layerName.c_str());
2222 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2223 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2225 RegisterInputSlots(graph, layerIndex, layer);
2226 RegisterOutputSlots(graph, layerIndex, layer);
2229 void Deserializer::ParseSpaceToDepth(GraphPtr graph, unsigned int layerIndex)
2231 CHECK_LAYERS(graph, 0, layerIndex);
2233 Deserializer::TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2234 CHECK_VALID_SIZE(inputs.size(), 1);
2236 Deserializer::TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2237 CHECK_VALID_SIZE(outputs.size(), 1);
2239 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_SpaceToDepthLayer()->descriptor();
2241 armnn::SpaceToDepthDescriptor descriptor;
2242 descriptor.m_BlockSize = flatBufferDescriptor->blockSize();
2243 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2245 auto layerName = GetLayerName(graph, layerIndex);
2246 IConnectableLayer* layer = m_Network->AddSpaceToDepthLayer(descriptor, layerName.c_str());
2248 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2249 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2251 RegisterInputSlots(graph, layerIndex, layer);
2252 RegisterOutputSlots(graph, layerIndex, layer);
2255 armnn::NormalizationDescriptor Deserializer::GetNormalizationDescriptor(
2256 Deserializer::NormalizationDescriptorPtr normalizationDescriptor,
2257 unsigned int layerIndex)
2259 IgnoreUnused(layerIndex);
2260 armnn::NormalizationDescriptor desc;
2262 switch (normalizationDescriptor->normChannelType())
2264 case NormalizationAlgorithmChannel_Across:
2266 desc.m_NormChannelType = armnn::NormalizationAlgorithmChannel::Across;
2269 case NormalizationAlgorithmChannel_Within:
2271 desc.m_NormChannelType = armnn::NormalizationAlgorithmChannel::Within;
2276 ARMNN_ASSERT_MSG(false, "Unsupported normalization channel type");
2280 switch (normalizationDescriptor->normMethodType())
2282 case NormalizationAlgorithmMethod_LocalBrightness:
2284 desc.m_NormMethodType = armnn::NormalizationAlgorithmMethod::LocalBrightness;
2287 case NormalizationAlgorithmMethod_LocalContrast:
2289 desc.m_NormMethodType = armnn::NormalizationAlgorithmMethod::LocalContrast;
2294 ARMNN_ASSERT_MSG(false, "Unsupported normalization method type");
2298 switch (normalizationDescriptor->dataLayout())
2300 case DataLayout_NCHW:
2302 desc.m_DataLayout = armnn::DataLayout::NCHW;
2305 case DataLayout_NHWC:
2307 desc.m_DataLayout = armnn::DataLayout::NHWC;
2312 ARMNN_ASSERT_MSG(false, "Unsupported data layout");
2316 desc.m_Alpha = normalizationDescriptor->alpha();
2317 desc.m_Beta = normalizationDescriptor->beta();
2318 desc.m_K = normalizationDescriptor->k();
2319 desc.m_NormSize = normalizationDescriptor->normSize();
2324 void Deserializer::ParseNormalization(GraphPtr graph, unsigned int layerIndex)
2326 CHECK_LAYERS(graph, 0, layerIndex);
2328 auto normalizationDes = graph->layers()->Get(layerIndex)->layer_as_NormalizationLayer()->descriptor();
2330 Deserializer::TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2331 CHECK_VALID_SIZE(inputs.size(), 1);
2333 Deserializer::TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2334 CHECK_VALID_SIZE(outputs.size(), 1);
2336 auto outputInfo = ToTensorInfo(outputs[0]);
2338 auto normalizationDescriptor = GetNormalizationDescriptor(normalizationDes, layerIndex);
2339 auto layerName = GetLayerName(graph, layerIndex);
2341 IConnectableLayer* layer = m_Network->AddNormalizationLayer(normalizationDescriptor, layerName.c_str());
2342 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2344 RegisterInputSlots(graph, layerIndex, layer);
2345 RegisterOutputSlots(graph, layerIndex, layer);
2348 void Deserializer::ParseRsqrt(GraphPtr graph, unsigned int layerIndex)
2350 CHECK_LAYERS(graph, 0, layerIndex);
2351 auto inputs = GetInputs(graph, layerIndex);
2353 CHECK_VALID_SIZE(inputs.size(), 1);
2355 auto outputs = GetOutputs(graph, layerIndex);
2356 CHECK_VALID_SIZE(outputs.size(), 1);
2358 auto layerName = GetLayerName(graph, layerIndex);
2360 armnn::ElementwiseUnaryDescriptor descriptor(armnn::UnaryOperation::Rsqrt);
2361 IConnectableLayer* layer = m_Network->AddElementwiseUnaryLayer(descriptor, layerName.c_str());
2362 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2363 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2365 RegisterInputSlots(graph, layerIndex, layer);
2366 RegisterOutputSlots(graph, layerIndex, layer);
2369 void Deserializer::ParseSlice(GraphPtr graph, unsigned int layerIndex)
2371 CHECK_LAYERS(graph, 0, layerIndex);
2373 auto inputs = GetInputs(graph, layerIndex);
2374 CHECK_VALID_SIZE(inputs.size(), 1);
2376 auto outputs = GetOutputs(graph, layerIndex);
2377 CHECK_VALID_SIZE(outputs.size(), 1);
2379 auto fbDescriptor = graph->layers()->Get(layerIndex)->layer_as_SliceLayer()->descriptor();
2381 auto fbBegin = fbDescriptor->begin();
2382 auto fbSize = fbDescriptor->size();
2384 if (fbBegin->Length() != fbSize->Length())
2386 throw ParseException(fmt::format("Begin and size descriptors must have the same length {}",
2387 CHECK_LOCATION().AsString()));
2390 armnn::SliceDescriptor descriptor;
2391 descriptor.m_Begin.insert(descriptor.m_Begin.end(), fbBegin->begin(), fbBegin->end());
2392 descriptor.m_Size.insert(descriptor.m_Size.end(), fbSize->begin(), fbSize->end());
2394 auto layerName = GetLayerName(graph, layerIndex);
2395 IConnectableLayer* layer = m_Network->AddSliceLayer(descriptor, layerName.c_str());
2397 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2398 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2400 RegisterInputSlots(graph, layerIndex, layer);
2401 RegisterOutputSlots(graph, layerIndex, layer);
2404 void Deserializer::ParseStridedSlice(GraphPtr graph, unsigned int layerIndex)
2406 CHECK_LAYERS(graph, 0, layerIndex);
2408 Deserializer::TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2409 CHECK_VALID_SIZE(inputs.size(), 1);
2411 Deserializer::TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2412 CHECK_VALID_SIZE(outputs.size(), 1);
2414 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_StridedSliceLayer()->descriptor();
2416 auto flatBufferBegin = flatBufferDescriptor->begin();
2417 auto flatBufferEnd = flatBufferDescriptor->end();
2418 auto flatBufferStride = flatBufferDescriptor->stride();
2420 if (!(flatBufferBegin->Length() == flatBufferEnd->Length() &&
2421 flatBufferBegin->Length() == flatBufferStride->Length()))
2423 throw ParseException(fmt::format("The size of the begin, end, and stride must be equal {}",
2424 CHECK_LOCATION().AsString()));
2427 std::vector<int> begin(flatBufferBegin->begin(), flatBufferBegin->end());
2428 std::vector<int> end(flatBufferEnd->begin(), flatBufferEnd->end());
2429 std::vector<int> stride(flatBufferStride->begin(), flatBufferStride->end());
2431 armnn::StridedSliceDescriptor descriptor(begin, end, stride);
2432 descriptor.m_BeginMask = flatBufferDescriptor->beginMask();
2433 descriptor.m_EndMask = flatBufferDescriptor->endMask();
2434 descriptor.m_ShrinkAxisMask = flatBufferDescriptor->shrinkAxisMask();
2435 descriptor.m_EllipsisMask = flatBufferDescriptor->ellipsisMask();
2436 descriptor.m_NewAxisMask = flatBufferDescriptor->newAxisMask();
2437 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2439 auto layerName = GetLayerName(graph, layerIndex);
2440 IConnectableLayer* layer = m_Network->AddStridedSliceLayer(descriptor, layerName.c_str());
2442 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2443 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2445 RegisterInputSlots(graph, layerIndex, layer);
2446 RegisterOutputSlots(graph, layerIndex, layer);
2449 void Deserializer::ParseSubtraction(GraphPtr graph, unsigned int layerIndex)
2451 CHECK_LAYERS(graph, 0, layerIndex);
2452 auto inputs = GetInputs(graph, layerIndex);
2454 CHECK_VALID_SIZE(inputs.size(), 2);
2456 auto outputs = GetOutputs(graph, layerIndex);
2457 CHECK_VALID_SIZE(outputs.size(), 1);
2459 auto layerName = GetLayerName(graph, layerIndex);
2460 IConnectableLayer* layer = m_Network->AddSubtractionLayer(layerName.c_str());
2462 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2463 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2465 RegisterInputSlots(graph, layerIndex, layer);
2466 RegisterOutputSlots(graph, layerIndex, layer);
2469 void Deserializer::ParseGather(GraphPtr graph, unsigned int layerIndex)
2471 CHECK_LAYERS(graph, 0, layerIndex);
2473 Deserializer::TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2474 CHECK_VALID_SIZE(inputs.size(), 2);
2476 Deserializer::TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2477 CHECK_VALID_SIZE(outputs.size(), 1);
2479 armnn::GatherDescriptor descriptor;
2480 descriptor.m_Axis = graph->layers()->Get(layerIndex)->layer_as_GatherLayer()->descriptor()->axis();
2482 auto layerName = GetLayerName(graph, layerIndex);
2483 IConnectableLayer* layer = m_Network->AddGatherLayer(descriptor, layerName.c_str());
2485 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2486 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2488 RegisterInputSlots(graph, layerIndex, layer);
2489 RegisterOutputSlots(graph, layerIndex, layer);
2492 void Deserializer::ParseMean(GraphPtr graph, unsigned int layerIndex)
2494 CHECK_LAYERS(graph, 0, layerIndex);
2496 Deserializer::TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2497 CHECK_VALID_SIZE(inputs.size(), 1);
2499 Deserializer::TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2500 CHECK_VALID_SIZE(outputs.size(), 1);
2502 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_MeanLayer()->descriptor();
2503 auto flatBufferAxis = flatBufferDescriptor->axis();
2504 auto flatBufferKeepDims = flatBufferDescriptor->keepDims();
2506 armnn::MeanDescriptor descriptor;
2507 descriptor.m_Axis = std::vector<unsigned int>(flatBufferAxis->begin(), flatBufferAxis->end());
2508 descriptor.m_KeepDims = flatBufferKeepDims;
2510 auto layerName = GetLayerName(graph, layerIndex);
2511 IConnectableLayer* layer = m_Network->AddMeanLayer(descriptor, layerName.c_str());
2513 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2514 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2516 RegisterInputSlots(graph, layerIndex, layer);
2517 RegisterOutputSlots(graph, layerIndex, layer);
2520 void Deserializer::ParseSplitter(GraphPtr graph, unsigned int layerIndex)
2522 CHECK_LAYERS(graph, 0, layerIndex);
2524 Deserializer::TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2525 CHECK_VALID_SIZE(inputs.size(), 1);
2527 Deserializer::TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2529 auto flatBufferViewsDescriptor = graph->layers()->Get(layerIndex)->layer_as_SplitterLayer()->descriptor();
2530 auto flatBufferViewSizes = flatBufferViewsDescriptor->viewSizes();
2531 auto flatBufferOriginsDescriptor = flatBufferViewsDescriptor->origins();
2532 auto flatBufferViewOrigins = flatBufferOriginsDescriptor->viewOrigins();
2533 uint32_t numViews = flatBufferOriginsDescriptor->numViews();
2534 uint32_t numDimensions = flatBufferOriginsDescriptor->numDimensions();
2536 // Check numViews and numDimensions corresponds to the ones already serialized ...
2537 // numViews == flatBufferViewSizes.size();
2538 // foreach: numDimensions == flatBufferViewSizes[x].size();
2540 armnn::ViewsDescriptor viewsDescriptor(numViews, numDimensions);
2541 for(unsigned int vIdx = 0; vIdx < numViews; ++vIdx)
2543 for (unsigned int dIdx = 0; dIdx < numDimensions; ++dIdx)
2545 viewsDescriptor.SetViewSize(vIdx, dIdx, flatBufferViewSizes->Get(vIdx)->data()->Get(dIdx));
2546 viewsDescriptor.SetViewOriginCoord(vIdx, dIdx, flatBufferViewOrigins->Get(vIdx)->data()->Get(dIdx));
2550 auto layerName = GetLayerName(graph, layerIndex);
2551 IConnectableLayer* layer = m_Network->AddSplitterLayer(viewsDescriptor, layerName.c_str());
2553 // I could have as many outputs as views ...
2554 for(unsigned int vIdx = 0; vIdx < numViews; ++vIdx)
2556 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[vIdx]);
2557 layer->GetOutputSlot(vIdx).SetTensorInfo(outputTensorInfo);
2560 RegisterInputSlots(graph, layerIndex, layer);
2561 RegisterOutputSlots(graph, layerIndex, layer);
2564 armnn::LstmDescriptor Deserializer::GetLstmDescriptor(Deserializer::LstmDescriptorPtr lstmDescriptor)
2566 armnn::LstmDescriptor desc;
2568 desc.m_ActivationFunc = lstmDescriptor->activationFunc();
2569 desc.m_ClippingThresCell = lstmDescriptor->clippingThresCell();
2570 desc.m_ClippingThresProj = lstmDescriptor->clippingThresProj();
2571 desc.m_CifgEnabled = lstmDescriptor->cifgEnabled();
2572 desc.m_PeepholeEnabled = lstmDescriptor->peepholeEnabled();
2573 desc.m_ProjectionEnabled = lstmDescriptor->projectionEnabled();
2574 desc.m_LayerNormEnabled = lstmDescriptor->layerNormEnabled();
2579 void Deserializer::ParseLstm(GraphPtr graph, unsigned int layerIndex)
2581 CHECK_LAYERS(graph, 0, layerIndex);
2583 auto inputs = GetInputs(graph, layerIndex);
2584 CHECK_VALID_SIZE(inputs.size(), 3);
2586 auto outputs = GetOutputs(graph, layerIndex);
2587 CHECK_VALID_SIZE(outputs.size(), 4);
2589 auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_LstmLayer();
2590 auto layerName = GetLayerName(graph, layerIndex);
2591 auto flatBufferDescriptor = flatBufferLayer->descriptor();
2592 auto flatBufferInputParams = flatBufferLayer->inputParams();
2594 auto lstmDescriptor = GetLstmDescriptor(flatBufferDescriptor);
2596 armnn::LstmInputParams lstmInputParams;
2598 armnn::ConstTensor inputToForgetWeights = ToConstTensor(flatBufferInputParams->inputToForgetWeights());
2599 armnn::ConstTensor inputToCellWeights = ToConstTensor(flatBufferInputParams->inputToCellWeights());
2600 armnn::ConstTensor inputToOutputWeights = ToConstTensor(flatBufferInputParams->inputToOutputWeights());
2601 armnn::ConstTensor recurrentToForgetWeights = ToConstTensor(flatBufferInputParams->recurrentToForgetWeights());
2602 armnn::ConstTensor recurrentToCellWeights = ToConstTensor(flatBufferInputParams->recurrentToCellWeights());
2603 armnn::ConstTensor recurrentToOutputWeights = ToConstTensor(flatBufferInputParams->recurrentToOutputWeights());
2604 armnn::ConstTensor forgetGateBias = ToConstTensor(flatBufferInputParams->forgetGateBias());
2605 armnn::ConstTensor cellBias = ToConstTensor(flatBufferInputParams->cellBias());
2606 armnn::ConstTensor outputGateBias = ToConstTensor(flatBufferInputParams->outputGateBias());
2608 lstmInputParams.m_InputToForgetWeights = &inputToForgetWeights;
2609 lstmInputParams.m_InputToCellWeights = &inputToCellWeights;
2610 lstmInputParams.m_InputToOutputWeights = &inputToOutputWeights;
2611 lstmInputParams.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2612 lstmInputParams.m_RecurrentToCellWeights = &recurrentToCellWeights;
2613 lstmInputParams.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2614 lstmInputParams.m_ForgetGateBias = &forgetGateBias;
2615 lstmInputParams.m_CellBias = &cellBias;
2616 lstmInputParams.m_OutputGateBias = &outputGateBias;
2618 armnn::ConstTensor inputToInputWeights;
2619 armnn::ConstTensor recurrentToInputWeights;
2620 armnn::ConstTensor cellToInputWeights;
2621 armnn::ConstTensor inputGateBias;
2622 if (!lstmDescriptor.m_CifgEnabled)
2624 inputToInputWeights = ToConstTensor(flatBufferInputParams->inputToInputWeights());
2625 recurrentToInputWeights = ToConstTensor(flatBufferInputParams->recurrentToInputWeights());
2626 cellToInputWeights = ToConstTensor(flatBufferInputParams->cellToInputWeights());
2627 inputGateBias = ToConstTensor(flatBufferInputParams->inputGateBias());
2629 lstmInputParams.m_InputToInputWeights = &inputToInputWeights;
2630 lstmInputParams.m_RecurrentToInputWeights = &recurrentToInputWeights;
2631 lstmInputParams.m_CellToInputWeights = &cellToInputWeights;
2632 lstmInputParams.m_InputGateBias = &inputGateBias;
2635 armnn::ConstTensor projectionWeights;
2636 armnn::ConstTensor projectionBias;
2637 if (lstmDescriptor.m_ProjectionEnabled)
2639 projectionWeights = ToConstTensor(flatBufferInputParams->projectionWeights());
2640 projectionBias = ToConstTensor(flatBufferInputParams->projectionBias());
2642 lstmInputParams.m_ProjectionWeights = &projectionWeights;
2643 lstmInputParams.m_ProjectionBias = &projectionBias;
2646 armnn::ConstTensor cellToForgetWeights;
2647 armnn::ConstTensor cellToOutputWeights;
2648 if (lstmDescriptor.m_PeepholeEnabled)
2650 cellToForgetWeights = ToConstTensor(flatBufferInputParams->cellToForgetWeights());
2651 cellToOutputWeights = ToConstTensor(flatBufferInputParams->cellToOutputWeights());
2653 lstmInputParams.m_CellToForgetWeights = &cellToForgetWeights;
2654 lstmInputParams.m_CellToOutputWeights = &cellToOutputWeights;
2657 armnn::ConstTensor inputLayerNormWeights;
2658 armnn::ConstTensor forgetLayerNormWeights;
2659 armnn::ConstTensor cellLayerNormWeights;
2660 armnn::ConstTensor outputLayerNormWeights;
2661 if (lstmDescriptor.m_LayerNormEnabled)
2663 if (!lstmDescriptor.m_CifgEnabled)
2665 inputLayerNormWeights = ToConstTensor(flatBufferInputParams->inputLayerNormWeights());
2666 lstmInputParams.m_InputLayerNormWeights = &inputLayerNormWeights;
2668 forgetLayerNormWeights = ToConstTensor(flatBufferInputParams->forgetLayerNormWeights());
2669 cellLayerNormWeights = ToConstTensor(flatBufferInputParams->cellLayerNormWeights());
2670 outputLayerNormWeights = ToConstTensor(flatBufferInputParams->outputLayerNormWeights());
2672 lstmInputParams.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
2673 lstmInputParams.m_CellLayerNormWeights = &cellLayerNormWeights;
2674 lstmInputParams.m_OutputLayerNormWeights = &outputLayerNormWeights;
2677 IConnectableLayer* layer = m_Network->AddLstmLayer(lstmDescriptor, lstmInputParams, layerName.c_str());
2679 armnn::TensorInfo outputTensorInfo1 = ToTensorInfo(outputs[0]);
2680 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo1);
2682 armnn::TensorInfo outputTensorInfo2 = ToTensorInfo(outputs[1]);
2683 layer->GetOutputSlot(1).SetTensorInfo(outputTensorInfo2);
2685 armnn::TensorInfo outputTensorInfo3 = ToTensorInfo(outputs[2]);
2686 layer->GetOutputSlot(2).SetTensorInfo(outputTensorInfo3);
2688 armnn::TensorInfo outputTensorInfo4 = ToTensorInfo(outputs[3]);
2689 layer->GetOutputSlot(3).SetTensorInfo(outputTensorInfo4);
2691 RegisterInputSlots(graph, layerIndex, layer);
2692 RegisterOutputSlots(graph, layerIndex, layer);
2695 armnn::QLstmDescriptor Deserializer::GetQLstmDescriptor(Deserializer::QLstmDescriptorPtr qLstmDescriptor)
2697 armnn::QLstmDescriptor desc;
2699 desc.m_CifgEnabled = qLstmDescriptor->cifgEnabled();
2700 desc.m_PeepholeEnabled = qLstmDescriptor->peepholeEnabled();
2701 desc.m_ProjectionEnabled = qLstmDescriptor->projectionEnabled();
2702 desc.m_LayerNormEnabled = qLstmDescriptor->layerNormEnabled();
2704 desc.m_CellClip = qLstmDescriptor->cellClip();
2705 desc.m_ProjectionClip = qLstmDescriptor->projectionClip();
2707 desc.m_InputIntermediateScale = qLstmDescriptor->inputIntermediateScale();
2708 desc.m_ForgetIntermediateScale = qLstmDescriptor->forgetIntermediateScale();
2709 desc.m_CellIntermediateScale = qLstmDescriptor->cellIntermediateScale();
2710 desc.m_OutputIntermediateScale = qLstmDescriptor->outputIntermediateScale();
2712 desc.m_HiddenStateScale = qLstmDescriptor->hiddenStateScale();
2713 desc.m_HiddenStateZeroPoint = qLstmDescriptor->hiddenStateZeroPoint();
2718 void Deserializer::ParseQLstm(GraphPtr graph, unsigned int layerIndex)
2720 CHECK_LAYERS(graph, 0, layerIndex);
2722 auto inputs = GetInputs(graph, layerIndex);
2723 CHECK_VALID_SIZE(inputs.size(), 3);
2725 auto outputs = GetOutputs(graph, layerIndex);
2726 CHECK_VALID_SIZE(outputs.size(), 3);
2728 auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_QLstmLayer();
2729 auto layerName = GetLayerName(graph, layerIndex);
2730 auto flatBufferDescriptor = flatBufferLayer->descriptor();
2731 auto flatBufferInputParams = flatBufferLayer->inputParams();
2733 auto qLstmDescriptor = GetQLstmDescriptor(flatBufferDescriptor);
2734 armnn::LstmInputParams qLstmInputParams;
2737 armnn::ConstTensor inputToForgetWeights = ToConstTensor(flatBufferInputParams->inputToForgetWeights());
2738 armnn::ConstTensor inputToCellWeights = ToConstTensor(flatBufferInputParams->inputToCellWeights());
2739 armnn::ConstTensor inputToOutputWeights = ToConstTensor(flatBufferInputParams->inputToOutputWeights());
2740 armnn::ConstTensor recurrentToForgetWeights = ToConstTensor(flatBufferInputParams->recurrentToForgetWeights());
2741 armnn::ConstTensor recurrentToCellWeights = ToConstTensor(flatBufferInputParams->recurrentToCellWeights());
2742 armnn::ConstTensor recurrentToOutputWeights = ToConstTensor(flatBufferInputParams->recurrentToOutputWeights());
2743 armnn::ConstTensor forgetGateBias = ToConstTensor(flatBufferInputParams->forgetGateBias());
2744 armnn::ConstTensor cellBias = ToConstTensor(flatBufferInputParams->cellBias());
2745 armnn::ConstTensor outputGateBias = ToConstTensor(flatBufferInputParams->outputGateBias());
2747 qLstmInputParams.m_InputToForgetWeights = &inputToForgetWeights;
2748 qLstmInputParams.m_InputToCellWeights = &inputToCellWeights;
2749 qLstmInputParams.m_InputToOutputWeights = &inputToOutputWeights;
2750 qLstmInputParams.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2751 qLstmInputParams.m_RecurrentToCellWeights = &recurrentToCellWeights;
2752 qLstmInputParams.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2753 qLstmInputParams.m_ForgetGateBias = &forgetGateBias;
2754 qLstmInputParams.m_CellBias = &cellBias;
2755 qLstmInputParams.m_OutputGateBias = &outputGateBias;
2757 // Optional CIFG params
2758 armnn::ConstTensor inputToInputWeights;
2759 armnn::ConstTensor recurrentToInputWeights;
2760 armnn::ConstTensor inputGateBias;
2762 if (!qLstmDescriptor.m_CifgEnabled)
2764 inputToInputWeights = ToConstTensor(flatBufferInputParams->inputToInputWeights());
2765 recurrentToInputWeights = ToConstTensor(flatBufferInputParams->recurrentToInputWeights());
2766 inputGateBias = ToConstTensor(flatBufferInputParams->inputGateBias());
2768 qLstmInputParams.m_InputToInputWeights = &inputToInputWeights;
2769 qLstmInputParams.m_RecurrentToInputWeights = &recurrentToInputWeights;
2770 qLstmInputParams.m_InputGateBias = &inputGateBias;
2773 // Optional projection params
2774 armnn::ConstTensor projectionWeights;
2775 armnn::ConstTensor projectionBias;
2777 if (qLstmDescriptor.m_ProjectionEnabled)
2779 projectionWeights = ToConstTensor(flatBufferInputParams->projectionWeights());
2780 projectionBias = ToConstTensor(flatBufferInputParams->projectionBias());
2782 qLstmInputParams.m_ProjectionWeights = &projectionWeights;
2783 qLstmInputParams.m_ProjectionBias = &projectionBias;
2786 // Optional peephole params
2787 armnn::ConstTensor cellToInputWeights;
2788 armnn::ConstTensor cellToForgetWeights;
2789 armnn::ConstTensor cellToOutputWeights;
2791 if (qLstmDescriptor.m_PeepholeEnabled)
2793 if (!qLstmDescriptor.m_CifgEnabled)
2795 cellToInputWeights = ToConstTensor(flatBufferInputParams->cellToInputWeights());
2796 qLstmInputParams.m_CellToInputWeights = &cellToInputWeights;
2799 cellToForgetWeights = ToConstTensor(flatBufferInputParams->cellToForgetWeights());
2800 cellToOutputWeights = ToConstTensor(flatBufferInputParams->cellToOutputWeights());
2802 qLstmInputParams.m_CellToForgetWeights = &cellToForgetWeights;
2803 qLstmInputParams.m_CellToOutputWeights = &cellToOutputWeights;
2806 // Optional layer norm params
2807 armnn::ConstTensor inputLayerNormWeights;
2808 armnn::ConstTensor forgetLayerNormWeights;
2809 armnn::ConstTensor cellLayerNormWeights;
2810 armnn::ConstTensor outputLayerNormWeights;
2812 if (qLstmDescriptor.m_LayerNormEnabled)
2814 if (!qLstmDescriptor.m_CifgEnabled)
2816 inputLayerNormWeights = ToConstTensor(flatBufferInputParams->inputLayerNormWeights());
2817 qLstmInputParams.m_InputLayerNormWeights = &inputLayerNormWeights;
2820 forgetLayerNormWeights = ToConstTensor(flatBufferInputParams->forgetLayerNormWeights());
2821 cellLayerNormWeights = ToConstTensor(flatBufferInputParams->cellLayerNormWeights());
2822 outputLayerNormWeights = ToConstTensor(flatBufferInputParams->outputLayerNormWeights());
2824 qLstmInputParams.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
2825 qLstmInputParams.m_CellLayerNormWeights = &cellLayerNormWeights;
2826 qLstmInputParams.m_OutputLayerNormWeights = &outputLayerNormWeights;
2829 IConnectableLayer* layer = m_Network->AddQLstmLayer(qLstmDescriptor, qLstmInputParams, layerName.c_str());
2831 armnn::TensorInfo outputStateOutInfo = ToTensorInfo(outputs[0]);
2832 layer->GetOutputSlot(0).SetTensorInfo(outputStateOutInfo);
2834 armnn::TensorInfo cellStateOutInfo = ToTensorInfo(outputs[1]);
2835 layer->GetOutputSlot(1).SetTensorInfo(cellStateOutInfo);
2837 armnn::TensorInfo outputInfo = ToTensorInfo(outputs[2]);
2838 layer->GetOutputSlot(2).SetTensorInfo(outputInfo);
2840 RegisterInputSlots(graph, layerIndex, layer);
2841 RegisterOutputSlots(graph, layerIndex, layer);
2844 void Deserializer::ParseQuantizedLstm(GraphPtr graph, unsigned int layerIndex)
2846 CHECK_LAYERS(graph, 0, layerIndex);
2848 auto inputs = GetInputs(graph, layerIndex);
2849 CHECK_VALID_SIZE(inputs.size(), 3);
2851 auto outputs = GetOutputs(graph, layerIndex);
2852 CHECK_VALID_SIZE(outputs.size(), 2);
2854 auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_QuantizedLstmLayer();
2855 auto layerName = GetLayerName(graph, layerIndex);
2856 auto flatBufferInputParams = flatBufferLayer->inputParams();
2858 armnn::QuantizedLstmInputParams lstmInputParams;
2860 armnn::ConstTensor inputToInputWeights = ToConstTensor(flatBufferInputParams->inputToInputWeights());
2861 armnn::ConstTensor inputToForgetWeights = ToConstTensor(flatBufferInputParams->inputToForgetWeights());
2862 armnn::ConstTensor inputToCellWeights = ToConstTensor(flatBufferInputParams->inputToCellWeights());
2863 armnn::ConstTensor inputToOutputWeights = ToConstTensor(flatBufferInputParams->inputToOutputWeights());
2864 armnn::ConstTensor recurrentToInputWeights = ToConstTensor(flatBufferInputParams->recurrentToInputWeights());
2865 armnn::ConstTensor recurrentToForgetWeights = ToConstTensor(flatBufferInputParams->recurrentToForgetWeights());
2866 armnn::ConstTensor recurrentToCellWeights = ToConstTensor(flatBufferInputParams->recurrentToCellWeights());
2867 armnn::ConstTensor recurrentToOutputWeights = ToConstTensor(flatBufferInputParams->recurrentToOutputWeights());
2868 armnn::ConstTensor inputGateBias = ToConstTensor(flatBufferInputParams->inputGateBias());
2869 armnn::ConstTensor forgetGateBias = ToConstTensor(flatBufferInputParams->forgetGateBias());
2870 armnn::ConstTensor cellBias = ToConstTensor(flatBufferInputParams->cellBias());
2871 armnn::ConstTensor outputGateBias = ToConstTensor(flatBufferInputParams->outputGateBias());
2873 lstmInputParams.m_InputToInputWeights = &inputToInputWeights;
2874 lstmInputParams.m_InputToForgetWeights = &inputToForgetWeights;
2875 lstmInputParams.m_InputToCellWeights = &inputToCellWeights;
2876 lstmInputParams.m_InputToOutputWeights = &inputToOutputWeights;
2877 lstmInputParams.m_RecurrentToInputWeights = &recurrentToInputWeights;
2878 lstmInputParams.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2879 lstmInputParams.m_RecurrentToCellWeights = &recurrentToCellWeights;
2880 lstmInputParams.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2881 lstmInputParams.m_InputGateBias = &inputGateBias;
2882 lstmInputParams.m_ForgetGateBias = &forgetGateBias;
2883 lstmInputParams.m_CellBias = &cellBias;
2884 lstmInputParams.m_OutputGateBias = &outputGateBias;
2886 IConnectableLayer* layer = m_Network->AddQuantizedLstmLayer(lstmInputParams, layerName.c_str());
2888 armnn::TensorInfo outputTensorInfo1 = ToTensorInfo(outputs[0]);
2889 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo1);
2891 armnn::TensorInfo outputTensorInfo2 = ToTensorInfo(outputs[1]);
2892 layer->GetOutputSlot(1).SetTensorInfo(outputTensorInfo2);
2894 RegisterInputSlots(graph, layerIndex, layer);
2895 RegisterOutputSlots(graph, layerIndex, layer);
2898 void Deserializer::ParseDequantize(GraphPtr graph, unsigned int layerIndex)
2900 CHECK_LAYERS(graph, 0, layerIndex);
2902 Deserializer::TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2903 CHECK_VALID_SIZE(inputs.size(), 1);
2905 Deserializer::TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2906 CHECK_VALID_SIZE(outputs.size(), 1);
2908 const std::string layerName = GetLayerName(graph, layerIndex);
2909 IConnectableLayer* layer = m_Network->AddDequantizeLayer(layerName.c_str());
2911 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2912 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2914 RegisterInputSlots(graph, layerIndex, layer);
2915 RegisterOutputSlots(graph, layerIndex, layer);
2918 void Deserializer::ParseMerge(GraphPtr graph, unsigned int layerIndex)
2920 CHECK_LAYERS(graph, 0, layerIndex);
2922 Deserializer::TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2923 CHECK_VALID_SIZE(inputs.size(), 2);
2925 Deserializer::TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2926 CHECK_VALID_SIZE(outputs.size(), 1);
2928 const std::string layerName = GetLayerName(graph, layerIndex);
2929 IConnectableLayer* layer = m_Network->AddMergeLayer(layerName.c_str());
2931 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2932 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2934 RegisterInputSlots(graph, layerIndex, layer);
2935 RegisterOutputSlots(graph, layerIndex, layer);
2938 void Deserializer::ParseSwitch(GraphPtr graph, unsigned int layerIndex)
2940 CHECK_LAYERS(graph, 0, layerIndex);
2941 auto inputs = GetInputs(graph, layerIndex);
2943 CHECK_VALID_SIZE(inputs.size(), 2);
2945 auto outputs = GetOutputs(graph, layerIndex);
2946 CHECK_VALID_SIZE(outputs.size(), 2);
2948 auto layerName = GetLayerName(graph, layerIndex);
2949 IConnectableLayer* layer = m_Network->AddSwitchLayer(layerName.c_str());
2951 armnn::TensorInfo output0TensorInfo = ToTensorInfo(outputs[0]);
2952 layer->GetOutputSlot(0).SetTensorInfo(output0TensorInfo);
2954 armnn::TensorInfo output1TensorInfo = ToTensorInfo(outputs[1]);
2955 layer->GetOutputSlot(1).SetTensorInfo(output1TensorInfo);
2957 RegisterInputSlots(graph, layerIndex, layer);
2958 RegisterOutputSlots(graph, layerIndex, layer);
2961 void Deserializer::ParsePrelu(GraphPtr graph, unsigned int layerIndex)
2963 CHECK_LAYERS(graph, 0, layerIndex);
2964 auto inputs = GetInputs(graph, layerIndex);
2966 CHECK_VALID_SIZE(inputs.size(), 2);
2968 auto outputs = GetOutputs(graph, layerIndex);
2969 CHECK_VALID_SIZE(outputs.size(), 1);
2971 auto layerName = GetLayerName(graph, layerIndex);
2972 IConnectableLayer* layer = m_Network->AddPreluLayer(layerName.c_str());
2974 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2975 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2977 RegisterInputSlots(graph, layerIndex, layer);
2978 RegisterOutputSlots(graph, layerIndex, layer);
2981 void Deserializer::ParseTranspose(GraphPtr graph, unsigned int layerIndex)
2983 CHECK_LAYERS(graph, 0, layerIndex);
2985 auto dimsMapping = graph->layers()->Get(layerIndex)->layer_as_TransposeLayer()->descriptor()->dimMappings();
2987 auto inputs = GetInputs(graph, layerIndex);
2988 CHECK_VALID_SIZE(inputs.size(), 1);
2990 auto outputs = GetOutputs(graph, layerIndex);
2991 CHECK_VALID_SIZE(outputs.size(), 1);
2992 auto outputInfo = ToTensorInfo(outputs[0]);
2994 auto layerName = GetLayerName(graph, layerIndex);
2995 const armnn::TransposeDescriptor descriptor(armnn::PermutationVector(dimsMapping->data(), dimsMapping->Length()));
2997 IConnectableLayer* layer = m_Network->AddTransposeLayer(descriptor, layerName.c_str());
2998 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
3000 RegisterInputSlots(graph, layerIndex, layer);
3001 RegisterOutputSlots(graph, layerIndex, layer);
3004 void Deserializer::ParseTransposeConvolution2d(GraphPtr graph, unsigned int layerIndex)
3006 CHECK_LAYERS(graph, 0, layerIndex);
3008 auto inputs = GetInputs(graph, layerIndex);
3009 CHECK_VALID_SIZE(inputs.size(), 1);
3011 auto outputs = GetOutputs(graph, layerIndex);
3012 CHECK_VALID_SIZE(outputs.size(), 1);
3014 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_TransposeConvolution2dLayer();
3015 auto layerName = GetLayerName(graph, layerIndex);
3016 auto serializerDescriptor = serializerLayer->descriptor();
3018 armnn::TransposeConvolution2dDescriptor descriptor;
3019 descriptor.m_PadLeft = serializerDescriptor->padLeft();
3020 descriptor.m_PadRight = serializerDescriptor->padRight();
3021 descriptor.m_PadTop = serializerDescriptor->padTop();
3022 descriptor.m_PadBottom = serializerDescriptor->padBottom();
3023 descriptor.m_StrideX = serializerDescriptor->strideX();
3024 descriptor.m_StrideY = serializerDescriptor->strideY();;
3025 descriptor.m_BiasEnabled = serializerDescriptor->biasEnabled();;
3026 descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
3029 armnn::ConstTensor weights = ToConstTensor(serializerLayer->weights());
3030 armnn::Optional<armnn::ConstTensor> optionalBiases;
3031 if (descriptor.m_BiasEnabled)
3033 armnn::ConstTensor biases = ToConstTensor(serializerLayer->biases());
3034 optionalBiases = armnn::MakeOptional<armnn::ConstTensor>(biases);
3037 IConnectableLayer* layer = m_Network->AddTransposeConvolution2dLayer(descriptor,
3042 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
3043 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
3045 RegisterInputSlots(graph, layerIndex, layer);
3046 RegisterOutputSlots(graph, layerIndex, layer);
3049 void Deserializer::ParseStack(GraphPtr graph, unsigned int layerIndex)
3051 CHECK_LAYERS(graph, 0, layerIndex);
3052 auto inputs = GetInputs(graph, layerIndex);
3054 auto outputs = GetOutputs(graph, layerIndex);
3055 CHECK_VALID_SIZE(outputs.size(), 1);
3057 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_StackLayer()->descriptor();
3058 unsigned int axis = flatBufferDescriptor->axis();
3059 unsigned int numInputs = flatBufferDescriptor->numInputs();
3060 CHECK_VALID_SIZE(inputs.size(), numInputs);
3062 auto flatBufferInputShape = flatBufferDescriptor->inputShape();
3063 std::vector<uint32_t> vectorInputShape(flatBufferInputShape->begin(),
3064 flatBufferInputShape->begin() + flatBufferInputShape->size());
3066 TensorShape inputShape(static_cast<unsigned int>(vectorInputShape.size()), vectorInputShape.data());
3067 armnn::StackDescriptor descriptor(axis, numInputs, inputShape);
3069 for (unsigned int i=0; i<inputs.size(); ++i)
3071 armnn::TensorShape inputShape = ToTensorInfo(inputs[i]).GetShape();
3072 if (descriptor.m_InputShape != inputShape)
3074 std::stringstream ss;
3075 ss << "Shape of input "
3079 << " does not equal defined input shape "
3080 << descriptor.m_InputShape
3082 << CHECK_LOCATION().AsString();
3083 throw ParseException(ss.str());
3087 auto layerName = GetLayerName(graph, layerIndex);
3088 IConnectableLayer* layer = m_Network->AddStackLayer(descriptor, layerName.c_str());
3090 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
3091 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
3093 RegisterInputSlots(graph, layerIndex, layer);
3094 RegisterOutputSlots(graph, layerIndex, layer);
3097 void Deserializer::ParseStandIn(GraphPtr graph, unsigned int layerIndex)
3099 CHECK_LAYERS(graph, 0, layerIndex);
3101 auto inputs = GetInputs(graph, layerIndex);
3102 auto outputs = GetOutputs(graph, layerIndex);
3104 auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_StandInLayer();
3105 auto fbDescriptor = fbLayer->descriptor();
3107 armnn::StandInDescriptor descriptor;
3108 descriptor.m_NumInputs = fbDescriptor->numInputs();
3109 descriptor.m_NumOutputs = fbDescriptor->numOutputs();
3111 CHECK_VALID_SIZE(inputs.size(), descriptor.m_NumInputs);
3112 CHECK_VALID_SIZE(outputs.size(), descriptor.m_NumOutputs);
3114 const std::string layerName = GetLayerName(graph, layerIndex);
3115 armnn::IConnectableLayer* layer = m_Network->AddStandInLayer(descriptor, layerName.c_str());
3117 for (unsigned int i = 0u; i < descriptor.m_NumOutputs; ++i)
3119 armnn::TensorInfo outputInfo = ToTensorInfo(outputs[i]);
3120 layer->GetOutputSlot(i).SetTensorInfo(outputInfo);
3123 RegisterInputSlots(graph, layerIndex, layer);
3124 RegisterOutputSlots(graph, layerIndex, layer);
3127 } // namespace armnnDeserializer