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
37 IDeserializer::IDeserializer() : pDeserializerImpl(new DeserializerImpl()){}
39 IDeserializer::~IDeserializer() = default;
41 IDeserializer *IDeserializer::CreateRaw()
43 return new IDeserializer();
46 IDeserializerPtr IDeserializer::Create()
48 return IDeserializerPtr(CreateRaw(), &IDeserializer::Destroy);
51 void IDeserializer::Destroy(IDeserializer *parser)
56 armnn::INetworkPtr IDeserializer::CreateNetworkFromBinary(const std::vector<uint8_t> &binaryContent)
58 return pDeserializerImpl->CreateNetworkFromBinary(binaryContent);
61 armnn::INetworkPtr IDeserializer::CreateNetworkFromBinary(std::istream &binaryContent)
63 return pDeserializerImpl->CreateNetworkFromBinary(binaryContent);
66 BindingPointInfo IDeserializer::GetNetworkInputBindingInfo(unsigned int layerId, const std::string &name) const
68 return pDeserializerImpl->GetNetworkInputBindingInfo(layerId, name);
71 BindingPointInfo IDeserializer::GetNetworkOutputBindingInfo(unsigned int layerId, const std::string &name) const
73 return pDeserializerImpl->GetNetworkOutputBindingInfo(layerId, name);
79 const uint32_t VIRTUAL_LAYER_ID = std::numeric_limits<uint32_t>::max();
81 void CheckGraph(const GraphPtr& graph,
82 unsigned int layersIndex,
83 const CheckLocation& location)
85 if (graph->layers() == nullptr)
87 throw ParseException(fmt::format("{0} was called with invalid (null) graph. "
88 "Possible reason is that the graph is not yet loaded and Unpack(ed). "
92 location.FileLine()));
94 else if (layersIndex >= graph->layers()->size())
96 throw ParseException(fmt::format("{0} was called with an invalid layers index. layers:{1} at {2}",
99 location.FileLine()));
103 void CheckLayers(const GraphPtr& graph,
104 unsigned int layersIndex,
105 unsigned int layerIndex,
106 const CheckLocation& location)
108 if (graph->layers() == nullptr)
110 throw ParseException(fmt::format("{0} was called with invalid (null) graph. "
111 "Possible reason is that the graph is not yet loaded and Unpack(ed). "
115 location.FileLine()));
117 else if (layersIndex >= graph->layers()->size())
119 throw ParseException(fmt::format("{0} was called with an invalid layers index. "
123 location.FileLine()));
125 else if (layerIndex >= graph->layers()[layersIndex].size()
126 && layerIndex != VIRTUAL_LAYER_ID)
128 throw ParseException(fmt::format("{0} was called with an invalid layer index. "
129 "layers:{1} layer:{2} at {3}",
133 location.FileLine()));
137 void CheckTensorPtr(TensorRawPtr rawPtr,
138 const CheckLocation& location)
140 if (rawPtr == nullptr)
142 throw ParseException(fmt::format("{0} was called with a null tensor pointer. at {1}",
144 location.FileLine()));
148 void CheckConstTensorPtr(ConstTensorRawPtr rawPtr,
149 const CheckLocation& location)
151 if (rawPtr == nullptr)
153 throw ParseException(fmt::format("{0} was called with a null const tensor pointer. at {1}",
155 location.FileLine()));
159 void CheckConstTensorSize(const unsigned int constTensorSize,
160 const unsigned int tensorSize,
161 const CheckLocation& location)
163 if (constTensorSize != tensorSize)
165 throw ParseException(fmt::format("{0} wrong number of components supplied to tensor. at:{1}",
167 location.FileLine()));
171 #define CHECK_TENSOR_PTR(TENSOR_PTR) \
172 CheckTensorPtr(TENSOR_PTR, CHECK_LOCATION())
174 #define CHECK_CONST_TENSOR_SIZE(CONST_TENSOR_SIZE, TENSOR_SIZE) \
175 CheckConstTensorSize(CONST_TENSOR_SIZE, TENSOR_SIZE, CHECK_LOCATION())
177 #define CHECK_CONST_TENSOR_PTR(TENSOR_PTR) \
178 CheckConstTensorPtr(TENSOR_PTR, CHECK_LOCATION())
180 #define CHECK_LAYERS(GRAPH, LAYERS_INDEX, LAYER_INDEX) \
181 CheckLayers(GRAPH, LAYERS_INDEX, LAYER_INDEX, CHECK_LOCATION())
183 #define CHECK_GRAPH(GRAPH, LAYERS_INDEX) \
184 CheckGraph(GRAPH, LAYERS_INDEX, CHECK_LOCATION())
187 bool CheckShape(const armnn::TensorShape& actual, const std::vector<uint32_t>& expected)
189 const unsigned int actualSize = actual.GetNumDimensions();
190 if (actualSize != expected.size())
195 for (unsigned int i = 0u; i < actualSize; i++)
197 if (actual[i] != static_cast<unsigned int>(expected[i]))
206 IDeserializer::DeserializerImpl::DeserializerImpl()
207 : m_Network(nullptr, nullptr),
208 //May require LayerType_Max to be included
209 m_ParserFunctions(Layer_MAX+1, &IDeserializer::DeserializerImpl::ParseUnsupportedLayer)
211 // register supported layers
212 m_ParserFunctions[Layer_AbsLayer] = &DeserializerImpl::ParseAbs;
213 m_ParserFunctions[Layer_ActivationLayer] = &DeserializerImpl::ParseActivation;
214 m_ParserFunctions[Layer_AdditionLayer] = &DeserializerImpl::ParseAdd;
215 m_ParserFunctions[Layer_ArgMinMaxLayer] = &DeserializerImpl::ParseArgMinMax;
216 m_ParserFunctions[Layer_BatchToSpaceNdLayer] = &DeserializerImpl::ParseBatchToSpaceNd;
217 m_ParserFunctions[Layer_BatchNormalizationLayer] = &DeserializerImpl::ParseBatchNormalization;
218 m_ParserFunctions[Layer_ComparisonLayer] = &DeserializerImpl::ParseComparison;
219 m_ParserFunctions[Layer_ConcatLayer] = &DeserializerImpl::ParseConcat;
220 m_ParserFunctions[Layer_ConstantLayer] = &DeserializerImpl::ParseConstant;
221 m_ParserFunctions[Layer_Convolution2dLayer] = &DeserializerImpl::ParseConvolution2d;
222 m_ParserFunctions[Layer_DepthToSpaceLayer] = &DeserializerImpl::ParseDepthToSpace;
223 m_ParserFunctions[Layer_DepthwiseConvolution2dLayer] = &DeserializerImpl::ParseDepthwiseConvolution2d;
224 m_ParserFunctions[Layer_DequantizeLayer] = &DeserializerImpl::ParseDequantize;
225 m_ParserFunctions[Layer_DetectionPostProcessLayer] = &DeserializerImpl::ParseDetectionPostProcess;
226 m_ParserFunctions[Layer_DivisionLayer] = &DeserializerImpl::ParseDivision;
227 m_ParserFunctions[Layer_ElementwiseUnaryLayer] = &DeserializerImpl::ParseElementwiseUnary;
228 m_ParserFunctions[Layer_EqualLayer] = &DeserializerImpl::ParseEqual;
229 m_ParserFunctions[Layer_FullyConnectedLayer] = &DeserializerImpl::ParseFullyConnected;
230 m_ParserFunctions[Layer_FillLayer] = &DeserializerImpl::ParseFill;
231 m_ParserFunctions[Layer_FloorLayer] = &DeserializerImpl::ParseFloor;
232 m_ParserFunctions[Layer_GatherLayer] = &DeserializerImpl::ParseGather;
233 m_ParserFunctions[Layer_GreaterLayer] = &DeserializerImpl::ParseGreater;
234 m_ParserFunctions[Layer_InstanceNormalizationLayer] = &DeserializerImpl::ParseInstanceNormalization;
235 m_ParserFunctions[Layer_L2NormalizationLayer] = &DeserializerImpl::ParseL2Normalization;
236 m_ParserFunctions[Layer_LogicalBinaryLayer] = &DeserializerImpl::ParseLogicalBinary;
237 m_ParserFunctions[Layer_LogSoftmaxLayer] = &DeserializerImpl::ParseLogSoftmax;
238 m_ParserFunctions[Layer_LstmLayer] = &DeserializerImpl::ParseLstm;
239 m_ParserFunctions[Layer_MaximumLayer] = &DeserializerImpl::ParseMaximum;
240 m_ParserFunctions[Layer_MeanLayer] = &DeserializerImpl::ParseMean;
241 m_ParserFunctions[Layer_MinimumLayer] = &DeserializerImpl::ParseMinimum;
242 m_ParserFunctions[Layer_MergeLayer] = &DeserializerImpl::ParseMerge;
243 m_ParserFunctions[Layer_MergerLayer] = &DeserializerImpl::ParseConcat;
244 m_ParserFunctions[Layer_MultiplicationLayer] = &DeserializerImpl::ParseMultiplication;
245 m_ParserFunctions[Layer_NormalizationLayer] = &DeserializerImpl::ParseNormalization;
246 m_ParserFunctions[Layer_PadLayer] = &DeserializerImpl::ParsePad;
247 m_ParserFunctions[Layer_PermuteLayer] = &DeserializerImpl::ParsePermute;
248 m_ParserFunctions[Layer_Pooling2dLayer] = &DeserializerImpl::ParsePooling2d;
249 m_ParserFunctions[Layer_PreluLayer] = &DeserializerImpl::ParsePrelu;
250 m_ParserFunctions[Layer_QLstmLayer] = &DeserializerImpl::ParseQLstm;
251 m_ParserFunctions[Layer_QuantizeLayer] = &DeserializerImpl::ParseQuantize;
252 m_ParserFunctions[Layer_QuantizedLstmLayer] = &DeserializerImpl::ParseQuantizedLstm;
253 m_ParserFunctions[Layer_RankLayer] = &DeserializerImpl::ParseRank;
254 m_ParserFunctions[Layer_ReshapeLayer] = &DeserializerImpl::ParseReshape;
255 m_ParserFunctions[Layer_ResizeBilinearLayer] = &DeserializerImpl::ParseResizeBilinear;
256 m_ParserFunctions[Layer_ResizeLayer] = &DeserializerImpl::ParseResize;
257 m_ParserFunctions[Layer_RsqrtLayer] = &DeserializerImpl::ParseRsqrt;
258 m_ParserFunctions[Layer_SliceLayer] = &DeserializerImpl::ParseSlice;
259 m_ParserFunctions[Layer_SoftmaxLayer] = &DeserializerImpl::ParseSoftmax;
260 m_ParserFunctions[Layer_SpaceToBatchNdLayer] = &DeserializerImpl::ParseSpaceToBatchNd;
261 m_ParserFunctions[Layer_SpaceToDepthLayer] = &DeserializerImpl::ParseSpaceToDepth;
262 m_ParserFunctions[Layer_SplitterLayer] = &DeserializerImpl::ParseSplitter;
263 m_ParserFunctions[Layer_StackLayer] = &DeserializerImpl::ParseStack;
264 m_ParserFunctions[Layer_StandInLayer] = &DeserializerImpl::ParseStandIn;
265 m_ParserFunctions[Layer_StridedSliceLayer] = &DeserializerImpl::ParseStridedSlice;
266 m_ParserFunctions[Layer_SubtractionLayer] = &DeserializerImpl::ParseSubtraction;
267 m_ParserFunctions[Layer_SwitchLayer] = &DeserializerImpl::ParseSwitch;
268 m_ParserFunctions[Layer_TransposeConvolution2dLayer] = &DeserializerImpl::ParseTransposeConvolution2d;
269 m_ParserFunctions[Layer_TransposeLayer] = &DeserializerImpl::ParseTranspose;
272 LayerBaseRawPtr IDeserializer::DeserializerImpl::GetBaseLayer(const GraphPtr& graphPtr, unsigned int layerIndex)
274 auto layerType = graphPtr->layers()->Get(layerIndex)->layer_type();
278 case Layer::Layer_AbsLayer:
279 return graphPtr->layers()->Get(layerIndex)->layer_as_AbsLayer()->base();
280 case Layer::Layer_ActivationLayer:
281 return graphPtr->layers()->Get(layerIndex)->layer_as_ActivationLayer()->base();
282 case Layer::Layer_AdditionLayer:
283 return graphPtr->layers()->Get(layerIndex)->layer_as_AdditionLayer()->base();
284 case Layer::Layer_ArgMinMaxLayer:
285 return graphPtr->layers()->Get(layerIndex)->layer_as_ArgMinMaxLayer()->base();
286 case Layer::Layer_BatchToSpaceNdLayer:
287 return graphPtr->layers()->Get(layerIndex)->layer_as_BatchToSpaceNdLayer()->base();
288 case Layer::Layer_BatchNormalizationLayer:
289 return graphPtr->layers()->Get(layerIndex)->layer_as_BatchNormalizationLayer()->base();
290 case Layer::Layer_ComparisonLayer:
291 return graphPtr->layers()->Get(layerIndex)->layer_as_ComparisonLayer()->base();
292 case Layer::Layer_ConcatLayer:
293 return graphPtr->layers()->Get(layerIndex)->layer_as_ConcatLayer()->base();
294 case Layer::Layer_ConstantLayer:
295 return graphPtr->layers()->Get(layerIndex)->layer_as_ConstantLayer()->base();
296 case Layer::Layer_Convolution2dLayer:
297 return graphPtr->layers()->Get(layerIndex)->layer_as_Convolution2dLayer()->base();
298 case Layer::Layer_DepthToSpaceLayer:
299 return graphPtr->layers()->Get(layerIndex)->layer_as_DepthToSpaceLayer()->base();
300 case Layer::Layer_DepthwiseConvolution2dLayer:
301 return graphPtr->layers()->Get(layerIndex)->layer_as_DepthwiseConvolution2dLayer()->base();
302 case Layer::Layer_DequantizeLayer:
303 return graphPtr->layers()->Get(layerIndex)->layer_as_DequantizeLayer()->base();
304 case Layer::Layer_DetectionPostProcessLayer:
305 return graphPtr->layers()->Get(layerIndex)->layer_as_DetectionPostProcessLayer()->base();
306 case Layer::Layer_DivisionLayer:
307 return graphPtr->layers()->Get(layerIndex)->layer_as_DivisionLayer()->base();
308 case Layer::Layer_EqualLayer:
309 return graphPtr->layers()->Get(layerIndex)->layer_as_EqualLayer()->base();
310 case Layer::Layer_ElementwiseUnaryLayer:
311 return graphPtr->layers()->Get(layerIndex)->layer_as_ElementwiseUnaryLayer()->base();
312 case Layer::Layer_FullyConnectedLayer:
313 return graphPtr->layers()->Get(layerIndex)->layer_as_FullyConnectedLayer()->base();
314 case Layer::Layer_FillLayer:
315 return graphPtr->layers()->Get(layerIndex)->layer_as_FillLayer()->base();
316 case Layer::Layer_FloorLayer:
317 return graphPtr->layers()->Get(layerIndex)->layer_as_FloorLayer()->base();
318 case Layer::Layer_GatherLayer:
319 return graphPtr->layers()->Get(layerIndex)->layer_as_GatherLayer()->base();
320 case Layer::Layer_GreaterLayer:
321 return graphPtr->layers()->Get(layerIndex)->layer_as_GreaterLayer()->base();
322 case Layer::Layer_InputLayer:
323 return graphPtr->layers()->Get(layerIndex)->layer_as_InputLayer()->base()->base();
324 case Layer::Layer_InstanceNormalizationLayer:
325 return graphPtr->layers()->Get(layerIndex)->layer_as_InstanceNormalizationLayer()->base();
326 case Layer::Layer_L2NormalizationLayer:
327 return graphPtr->layers()->Get(layerIndex)->layer_as_L2NormalizationLayer()->base();
328 case Layer::Layer_LogicalBinaryLayer:
329 return graphPtr->layers()->Get(layerIndex)->layer_as_LogicalBinaryLayer()->base();
330 case Layer::Layer_LogSoftmaxLayer:
331 return graphPtr->layers()->Get(layerIndex)->layer_as_LogSoftmaxLayer()->base();
332 case Layer::Layer_LstmLayer:
333 return graphPtr->layers()->Get(layerIndex)->layer_as_LstmLayer()->base();
334 case Layer::Layer_MeanLayer:
335 return graphPtr->layers()->Get(layerIndex)->layer_as_MeanLayer()->base();
336 case Layer::Layer_MinimumLayer:
337 return graphPtr->layers()->Get(layerIndex)->layer_as_MinimumLayer()->base();
338 case Layer::Layer_MaximumLayer:
339 return graphPtr->layers()->Get(layerIndex)->layer_as_MaximumLayer()->base();
340 case Layer::Layer_MergeLayer:
341 return graphPtr->layers()->Get(layerIndex)->layer_as_MergeLayer()->base();
342 case Layer::Layer_MergerLayer:
343 return graphPtr->layers()->Get(layerIndex)->layer_as_MergerLayer()->base();
344 case Layer::Layer_MultiplicationLayer:
345 return graphPtr->layers()->Get(layerIndex)->layer_as_MultiplicationLayer()->base();
346 case Layer::Layer_NormalizationLayer:
347 return graphPtr->layers()->Get(layerIndex)->layer_as_NormalizationLayer()->base();
348 case Layer::Layer_OutputLayer:
349 return graphPtr->layers()->Get(layerIndex)->layer_as_OutputLayer()->base()->base();
350 case Layer::Layer_PadLayer:
351 return graphPtr->layers()->Get(layerIndex)->layer_as_PadLayer()->base();
352 case Layer::Layer_PermuteLayer:
353 return graphPtr->layers()->Get(layerIndex)->layer_as_PermuteLayer()->base();
354 case Layer::Layer_Pooling2dLayer:
355 return graphPtr->layers()->Get(layerIndex)->layer_as_Pooling2dLayer()->base();
356 case Layer::Layer_PreluLayer:
357 return graphPtr->layers()->Get(layerIndex)->layer_as_PreluLayer()->base();
358 case Layer::Layer_QLstmLayer:
359 return graphPtr->layers()->Get(layerIndex)->layer_as_QLstmLayer()->base();
360 case Layer::Layer_QuantizeLayer:
361 return graphPtr->layers()->Get(layerIndex)->layer_as_QuantizeLayer()->base();
362 case Layer::Layer_QuantizedLstmLayer:
363 return graphPtr->layers()->Get(layerIndex)->layer_as_QuantizedLstmLayer()->base();
364 case Layer::Layer_RankLayer:
365 return graphPtr->layers()->Get(layerIndex)->layer_as_RankLayer()->base();
366 case Layer::Layer_ReshapeLayer:
367 return graphPtr->layers()->Get(layerIndex)->layer_as_ReshapeLayer()->base();
368 case Layer::Layer_ResizeBilinearLayer:
369 return graphPtr->layers()->Get(layerIndex)->layer_as_ResizeBilinearLayer()->base();
370 case Layer::Layer_ResizeLayer:
371 return graphPtr->layers()->Get(layerIndex)->layer_as_ResizeLayer()->base();
372 case Layer::Layer_RsqrtLayer:
373 return graphPtr->layers()->Get(layerIndex)->layer_as_RsqrtLayer()->base();
374 case Layer::Layer_SliceLayer:
375 return graphPtr->layers()->Get(layerIndex)->layer_as_SliceLayer()->base();
376 case Layer::Layer_SoftmaxLayer:
377 return graphPtr->layers()->Get(layerIndex)->layer_as_SoftmaxLayer()->base();
378 case Layer::Layer_SpaceToBatchNdLayer:
379 return graphPtr->layers()->Get(layerIndex)->layer_as_SpaceToBatchNdLayer()->base();
380 case Layer::Layer_SpaceToDepthLayer:
381 return graphPtr->layers()->Get(layerIndex)->layer_as_SpaceToDepthLayer()->base();
382 case Layer::Layer_SplitterLayer:
383 return graphPtr->layers()->Get(layerIndex)->layer_as_SplitterLayer()->base();
384 case Layer::Layer_StackLayer:
385 return graphPtr->layers()->Get(layerIndex)->layer_as_StackLayer()->base();
386 case Layer::Layer_StandInLayer:
387 return graphPtr->layers()->Get(layerIndex)->layer_as_StandInLayer()->base();
388 case Layer::Layer_StridedSliceLayer:
389 return graphPtr->layers()->Get(layerIndex)->layer_as_StridedSliceLayer()->base();
390 case Layer::Layer_SubtractionLayer:
391 return graphPtr->layers()->Get(layerIndex)->layer_as_SubtractionLayer()->base();
392 case Layer::Layer_SwitchLayer:
393 return graphPtr->layers()->Get(layerIndex)->layer_as_SwitchLayer()->base();
394 case Layer::Layer_TransposeConvolution2dLayer:
395 return graphPtr->layers()->Get(layerIndex)->layer_as_TransposeConvolution2dLayer()->base();
396 case Layer::Layer_TransposeLayer:
397 return graphPtr->layers()->Get(layerIndex)->layer_as_TransposeLayer()->base();
398 case Layer::Layer_NONE:
400 throw ParseException(fmt::format("Layer type {} not recognized", layerType));
404 std::string IDeserializer::DeserializerImpl::GetLayerName(const GraphPtr& graph, unsigned int index)
406 auto layer = GetBaseLayer(graph, index);
408 return layer->layerName()->str();
411 int32_t IDeserializer::DeserializerImpl::GetBindingLayerInfo(const GraphPtr& graphPtr, unsigned int layerIndex)
413 auto layerType = graphPtr->layers()->Get(layerIndex)->layer_type();
415 if (layerType == Layer::Layer_InputLayer)
417 return graphPtr->layers()->Get(layerIndex)->layer_as_InputLayer()->base()->layerBindingId();
419 else if ( layerType == Layer::Layer_OutputLayer )
421 return graphPtr->layers()->Get(layerIndex)->layer_as_OutputLayer()->base()->layerBindingId();
426 armnn::DataLayout ToDataLayout(armnnSerializer::DataLayout dataLayout)
430 case armnnSerializer::DataLayout::DataLayout_NHWC:
431 return armnn::DataLayout::NHWC;
432 case armnnSerializer::DataLayout::DataLayout_NCHW:
434 return armnn::DataLayout::NCHW;
438 armnn::ActivationFunction ToActivationFunction(armnnSerializer::ActivationFunction function)
442 case armnnSerializer::ActivationFunction_Sigmoid:
443 return armnn::ActivationFunction::Sigmoid;
444 case armnnSerializer::ActivationFunction_TanH:
445 return armnn::ActivationFunction::TanH;
446 case armnnSerializer::ActivationFunction_Linear:
447 return armnn::ActivationFunction::Linear;
448 case armnnSerializer::ActivationFunction_ReLu:
449 return armnn::ActivationFunction::ReLu;
450 case armnnSerializer::ActivationFunction_BoundedReLu:
451 return armnn::ActivationFunction::BoundedReLu;
452 case armnnSerializer::ActivationFunction_LeakyReLu:
453 return armnn::ActivationFunction::LeakyReLu;
454 case armnnSerializer::ActivationFunction_Abs:
455 return armnn::ActivationFunction::Abs;
456 case armnnSerializer::ActivationFunction_Sqrt:
457 return armnn::ActivationFunction::Sqrt;
458 case armnnSerializer::ActivationFunction_Square:
459 return armnn::ActivationFunction::Square;
460 case armnnSerializer::ActivationFunction_Elu:
461 return armnn::ActivationFunction::Elu;
462 case armnnSerializer::ActivationFunction_HardSwish:
463 return armnn::ActivationFunction::HardSwish;
465 return armnn::ActivationFunction::Sigmoid;
469 armnn::ArgMinMaxFunction ToArgMinMaxFunction(armnnSerializer::ArgMinMaxFunction function)
473 case armnnSerializer::ArgMinMaxFunction::ArgMinMaxFunction_Max:
474 return armnn::ArgMinMaxFunction::Max;
475 case armnnSerializer::ArgMinMaxFunction::ArgMinMaxFunction_Min:
477 return armnn::ArgMinMaxFunction::Min;
481 armnn::ComparisonOperation ToComparisonOperation(armnnSerializer::ComparisonOperation operation)
485 case armnnSerializer::ComparisonOperation::ComparisonOperation_Equal:
486 return armnn::ComparisonOperation::Equal;
487 case armnnSerializer::ComparisonOperation::ComparisonOperation_Greater:
488 return armnn::ComparisonOperation::Greater;
489 case armnnSerializer::ComparisonOperation::ComparisonOperation_GreaterOrEqual:
490 return armnn::ComparisonOperation::GreaterOrEqual;
491 case armnnSerializer::ComparisonOperation::ComparisonOperation_Less:
492 return armnn::ComparisonOperation::Less;
493 case armnnSerializer::ComparisonOperation::ComparisonOperation_LessOrEqual:
494 return armnn::ComparisonOperation::LessOrEqual;
495 case armnnSerializer::ComparisonOperation::ComparisonOperation_NotEqual:
497 return armnn::ComparisonOperation::NotEqual;
501 armnn::LogicalBinaryOperation ToLogicalBinaryOperation(armnnSerializer::LogicalBinaryOperation operation)
505 case armnnSerializer::LogicalBinaryOperation::LogicalBinaryOperation_LogicalAnd:
506 return armnn::LogicalBinaryOperation::LogicalAnd;
507 case armnnSerializer::LogicalBinaryOperation::LogicalBinaryOperation_LogicalOr:
508 return armnn::LogicalBinaryOperation::LogicalOr;
510 throw armnn::InvalidArgumentException("Logical Binary operation unknown");
514 armnn::UnaryOperation ToUnaryOperation(armnnSerializer::UnaryOperation operation)
518 case armnnSerializer::UnaryOperation::UnaryOperation_Abs:
519 return armnn::UnaryOperation::Abs;
520 case armnnSerializer::UnaryOperation::UnaryOperation_Rsqrt:
521 return armnn::UnaryOperation::Rsqrt;
522 case armnnSerializer::UnaryOperation::UnaryOperation_Sqrt:
523 return armnn::UnaryOperation::Sqrt;
524 case armnnSerializer::UnaryOperation::UnaryOperation_Exp:
525 return armnn::UnaryOperation::Exp;
526 case armnnSerializer::UnaryOperation::UnaryOperation_Neg:
527 return armnn::UnaryOperation::Neg;
528 case armnnSerializer::UnaryOperation::UnaryOperation_LogicalNot:
529 return armnn::UnaryOperation::LogicalNot;
531 throw armnn::InvalidArgumentException("Unary operation unknown");
535 armnn::ResizeMethod ToResizeMethod(armnnSerializer::ResizeMethod method)
539 case armnnSerializer::ResizeMethod_NearestNeighbor:
540 return armnn::ResizeMethod::NearestNeighbor;
541 case armnnSerializer::ResizeMethod_Bilinear:
542 return armnn::ResizeMethod::Bilinear;
544 return armnn::ResizeMethod::NearestNeighbor;
548 armnn::TensorInfo ToTensorInfo(TensorRawPtr tensorPtr)
550 armnn::DataType type;
551 CHECK_TENSOR_PTR(tensorPtr);
553 switch (tensorPtr->dataType())
555 case DataType_QAsymmS8:
556 type = armnn::DataType::QAsymmS8;
558 case DataType_QSymmS8:
559 type = armnn::DataType::QSymmS8;
561 case DataType_QuantisedAsymm8:
562 case DataType_QAsymmU8:
563 type = armnn::DataType::QAsymmU8;
565 case DataType_QSymmS16:
566 case DataType_QuantisedSymm16:
567 type = armnn::DataType::QSymmS16;
569 case DataType_Signed32:
570 type = armnn::DataType::Signed32;
572 case DataType_Float32:
573 type = armnn::DataType::Float32;
575 case DataType_Float16:
576 type = armnn::DataType::Float16;
578 case DataType_Boolean:
579 type = armnn::DataType::Boolean;
583 CheckLocation location = CHECK_LOCATION();
584 throw ParseException(fmt::format("Unsupported data type {0} = {1}. {2}",
585 tensorPtr->dataType(),
586 EnumNameDataType(tensorPtr->dataType()),
587 location.AsString()));
591 if (tensorPtr->dimensionality() == static_cast<unsigned int>(Dimensionality::Scalar))
593 float quantizationScale = tensorPtr->quantizationScale();
594 int32_t quantizationOffset = tensorPtr->quantizationOffset();
596 return armnn::TensorInfo(armnn::TensorShape{armnn::Dimensionality::Scalar},
602 auto dimensions = tensorPtr->dimensions();
603 unsigned int size = dimensions->size();
604 std::vector<unsigned int> outputDims(dimensions->begin(), dimensions->begin() + size);
606 auto quantizationScales = tensorPtr->quantizationScales();
608 if (quantizationScales)
610 unsigned int quantizationScalesSize = quantizationScales->size();
611 std::vector<float> scales(quantizationScales->begin(), quantizationScales->begin() + quantizationScalesSize);
612 unsigned int quantizationDim = tensorPtr->quantizationDim();
613 armnn::TensorInfo result(size,
621 float quantizationScale = tensorPtr->quantizationScale();
622 int32_t quantizationOffset = tensorPtr->quantizationOffset();
624 // two statements (on purpose) for easier debugging:
625 armnn::TensorInfo result(size,
633 armnn::ConstTensor ToConstTensor(ConstTensorRawPtr constTensorPtr)
635 CHECK_CONST_TENSOR_PTR(constTensorPtr);
636 armnn::TensorInfo tensorInfo = ToTensorInfo(constTensorPtr->info());
638 switch (constTensorPtr->data_type())
640 case ConstTensorData_ByteData:
642 auto byteData = constTensorPtr->data_as_ByteData()->data();
643 CHECK_CONST_TENSOR_SIZE(byteData->size(), tensorInfo.GetNumElements());
644 return armnn::ConstTensor(tensorInfo, byteData->data());
646 case ConstTensorData_ShortData:
648 auto shortData = constTensorPtr->data_as_ShortData()->data();
649 CHECK_CONST_TENSOR_SIZE(shortData->size(), tensorInfo.GetNumElements());
650 return armnn::ConstTensor(tensorInfo, shortData->data());
652 case ConstTensorData_IntData:
654 auto intData = constTensorPtr->data_as_IntData()->data();
655 CHECK_CONST_TENSOR_SIZE(intData->size(), tensorInfo.GetNumElements());
656 return armnn::ConstTensor(tensorInfo, intData->data());
658 case ConstTensorData_LongData:
660 auto longData = constTensorPtr->data_as_LongData()->data();
661 CHECK_CONST_TENSOR_SIZE(longData->size(), tensorInfo.GetNumElements());
662 return armnn::ConstTensor(tensorInfo, longData->data());
666 CheckLocation location = CHECK_LOCATION();
667 throw ParseException(fmt::format("Unsupported data type {0} = {1}. {2}",
668 constTensorPtr->data_type(),
669 EnumNameConstTensorData(constTensorPtr->data_type()),
670 location.AsString()));
675 TensorRawPtrVector IDeserializer::DeserializerImpl::GetInputs(const GraphPtr& graphPtr, unsigned int layerIndex)
677 CHECK_LAYERS(graphPtr, 0, layerIndex);
678 auto layer = GetBaseLayer(graphPtr, layerIndex);
679 const auto& numInputs = layer->inputSlots()->size();
681 TensorRawPtrVector result(numInputs);
683 for (unsigned int i=0; i<numInputs; ++i)
685 auto inputId = CHECKED_NON_NEGATIVE(static_cast<int32_t>
686 (layer->inputSlots()->Get(i)->connection()->sourceLayerIndex()));
687 result[i] = GetBaseLayer(graphPtr, inputId)->outputSlots()->Get(0)->tensorInfo();
692 TensorRawPtrVector IDeserializer::DeserializerImpl::GetOutputs(const GraphPtr& graphPtr, unsigned int layerIndex)
694 CHECK_LAYERS(graphPtr, 0, layerIndex);
695 auto layer = GetBaseLayer(graphPtr, layerIndex);
696 const auto& numOutputs = layer->outputSlots()->size();
698 TensorRawPtrVector result(numOutputs);
700 for (unsigned int i=0; i<numOutputs; ++i)
702 result[i] = layer->outputSlots()->Get(i)->tensorInfo();
707 void IDeserializer::DeserializerImpl::ParseUnsupportedLayer(GraphPtr graph, unsigned int layerIndex)
709 CHECK_LAYERS(graph, 0, layerIndex);
710 const auto layerName = GetBaseLayer(graph, layerIndex)->layerName()->c_str();
711 throw ParseException(fmt::format("Layer not supported. layerIndex: {0} "
712 "layerName: {1} / {2}",
715 CHECK_LOCATION().AsString()));
718 void IDeserializer::DeserializerImpl::ResetParser()
720 m_Network = armnn::INetworkPtr(nullptr, nullptr);
721 m_InputBindings.clear();
722 m_OutputBindings.clear();
726 INetworkPtr IDeserializer::DeserializerImpl::CreateNetworkFromBinary(const std::vector<uint8_t>& binaryContent)
729 GraphPtr graph = LoadGraphFromBinary(binaryContent.data(), binaryContent.size());
730 return CreateNetworkFromGraph(graph);
733 armnn::INetworkPtr IDeserializer::DeserializerImpl::CreateNetworkFromBinary(std::istream& binaryContent)
736 std::vector<uint8_t> content((std::istreambuf_iterator<char>(binaryContent)), std::istreambuf_iterator<char>());
737 GraphPtr graph = LoadGraphFromBinary(content.data(), content.size());
738 return CreateNetworkFromGraph(graph);
741 GraphPtr IDeserializer::DeserializerImpl::LoadGraphFromBinary(const uint8_t* binaryContent, size_t len)
743 if (binaryContent == nullptr)
745 throw InvalidArgumentException(fmt::format("Invalid (null) binary content {}",
746 CHECK_LOCATION().AsString()));
748 flatbuffers::Verifier verifier(binaryContent, len);
749 if (verifier.VerifyBuffer<SerializedGraph>() == false)
751 throw ParseException(fmt::format("Buffer doesn't conform to the expected Armnn "
752 "flatbuffers format. size:{0} {1}",
754 CHECK_LOCATION().AsString()));
756 return GetSerializedGraph(binaryContent);
759 INetworkPtr IDeserializer::DeserializerImpl::CreateNetworkFromGraph(GraphPtr graph)
761 m_Network = INetwork::Create();
762 ARMNN_ASSERT(graph != nullptr);
763 unsigned int layerIndex = 0;
764 for (AnyLayer const* layer : *graph->layers())
766 if (layer->layer_type() != Layer_InputLayer &&
767 layer->layer_type() != Layer_OutputLayer)
769 // lookup and call the parser function
770 auto& parserFunction = m_ParserFunctions[layer->layer_type()];
771 (this->*parserFunction)(graph, layerIndex);
776 SetupInputLayers(graph);
777 SetupOutputLayers(graph);
779 // establish the connections from the layer outputs to the inputs of the subsequent layers
780 for (auto&& graphIt : m_GraphConnections)
782 Connections& connections = graphIt.second;
783 for (auto&& outputIt : connections.outputSlots)
785 const unsigned int outputSlotIndex = outputIt.first;
786 IOutputSlot* outputSlot = outputIt.second;
787 if (connections.inputSlots.find(outputSlotIndex) != connections.inputSlots.end())
789 for (IInputSlot* inputSlot : connections.inputSlots[outputSlotIndex])
791 outputSlot->Connect(*inputSlot);
797 return std::move(m_Network);
800 BindingPointInfo IDeserializer::DeserializerImpl::GetNetworkInputBindingInfo(unsigned int layerIndex,
801 const std::string& name) const
803 IgnoreUnused(layerIndex);
804 for (auto inputBinding : m_InputBindings)
806 if (inputBinding.first == name)
808 return inputBinding.second;
811 throw ParseException(fmt::format("No input binding found for layer:{0} / {1}",
813 CHECK_LOCATION().AsString()));
816 BindingPointInfo IDeserializer::DeserializerImpl::GetNetworkOutputBindingInfo(unsigned int layerIndex,
817 const std::string& name) const
819 IgnoreUnused(layerIndex);
820 for (auto outputBinding : m_OutputBindings)
822 if (outputBinding.first == name)
824 return outputBinding.second;
827 throw ParseException(fmt::format("No output binding found for layer:{0} / {1}",
829 CHECK_LOCATION().AsString()));
832 unsigned int IDeserializer::DeserializerImpl::GetInputLayerInVector(GraphPtr graph, int targetId)
834 for (unsigned int i = 0; i < graph->layers()->size(); i++)
836 auto layer = graph->layers()->Get(i);
837 if (layer->layer_type() == Layer::Layer_InputLayer)
839 auto layerBindingId = layer->layer_as_InputLayer()->base()->layerBindingId();
840 if (layerBindingId == targetId)
846 throw ParseException("Input layer with given layerBindingId not found");
849 unsigned int IDeserializer::DeserializerImpl::GetOutputLayerInVector(GraphPtr graph, int targetId)
851 for (unsigned int i = 0; i < graph->layers()->size(); i++)
853 auto layer = graph->layers()->Get(i);
854 if (layer->layer_type() == Layer::Layer_OutputLayer)
856 auto layerBindingId = layer->layer_as_OutputLayer()->base()->layerBindingId();
857 if (layerBindingId == targetId)
863 throw ParseException("Output layer with given layerBindingId not found");
866 unsigned int IDeserializer::DeserializerImpl::GetLayerIndexInVector(GraphPtr graph, unsigned int targetIndex)
868 for (unsigned int i = 0; i < graph->layers()->size(); i++)
870 LayerBaseRawPtr layer = GetBaseLayer(graph, i);
871 if (layer->index() == targetIndex)
876 throw ParseException("Layer with given index not found");
879 IDeserializer::DeserializerImpl::FeatureVersions IDeserializer::DeserializerImpl::GetFeatureVersions(GraphPtr graph)
881 IDeserializer::DeserializerImpl::FeatureVersions versions;
883 if (graph->featureVersions())
885 versions.m_BindingIdScheme = graph->featureVersions()->bindingIdsScheme();
891 void IDeserializer::DeserializerImpl::SetupInputLayers(GraphPtr graph)
893 CHECK_GRAPH(graph, 0);
894 const unsigned int numInputs = graph->inputIds()->size();
895 m_InputBindings.clear();
896 m_InputBindings.reserve(numInputs);
898 for (unsigned int i = 0; i < numInputs; i++)
900 unsigned int inputLayerIndex = 0xFFFFFFFF;
901 if (GetFeatureVersions(graph).m_BindingIdScheme == 0)
903 const unsigned int inputId = armnn::numeric_cast<unsigned int>(graph->inputIds()->Get(i));
904 inputLayerIndex = GetLayerIndexInVector(graph, inputId);
908 const int inputId = graph->inputIds()->Get(i);
909 inputLayerIndex = GetInputLayerInVector(graph, inputId);
912 LayerBaseRawPtr baseLayer = GetBaseLayer(graph, inputLayerIndex);
914 // GetBindingLayerInfo expect the index to be index in the vector not index property on each layer base
915 LayerBindingId bindingId = GetBindingLayerInfo(graph, inputLayerIndex);
916 ARMNN_ASSERT_MSG(baseLayer->layerName()->c_str(), "Input has no name.");
918 IConnectableLayer* inputLayer =
919 m_Network->AddInputLayer(bindingId, baseLayer->layerName()->c_str());
921 const armnn::TensorInfo& tensorInfo = ToTensorInfo(baseLayer->outputSlots()->Get(0)->tensorInfo());
922 inputLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
923 RegisterOutputSlots(graph, inputLayerIndex, inputLayer);
925 BindingPointInfo bindingInfo = {bindingId, tensorInfo};
926 m_InputBindings.push_back(std::make_pair(baseLayer->layerName()->c_str(), bindingInfo));
930 void IDeserializer::DeserializerImpl::SetupOutputLayers(GraphPtr graph)
932 CHECK_GRAPH(graph, 0);
933 const unsigned int numOutputs = graph->outputIds()->size();
934 m_OutputBindings.clear();
935 m_OutputBindings.reserve(numOutputs);
937 for (unsigned int i = 0; i < numOutputs; i++)
939 unsigned int outputLayerIndex = 0xFFFFFFFF;
940 if (GetFeatureVersions(graph).m_BindingIdScheme == 0)
942 const unsigned int outputId = armnn::numeric_cast<unsigned int>(graph->outputIds()->Get(i));
943 outputLayerIndex = GetLayerIndexInVector(graph, outputId);
947 const int outputId = graph->outputIds()->Get(i);
948 outputLayerIndex = GetOutputLayerInVector(graph, outputId);
951 LayerBaseRawPtr baseLayer = GetBaseLayer(graph, outputLayerIndex);
953 // GetBindingLayerInfo expect the index to be index in the vector not index property on each layer base
954 LayerBindingId bindingId = GetBindingLayerInfo(graph, outputLayerIndex);
955 ARMNN_ASSERT_MSG(baseLayer->layerName()->c_str(), "Output has no name.");
957 IConnectableLayer* outputLayer =
958 m_Network->AddOutputLayer(bindingId, baseLayer->layerName()->c_str());
960 RegisterInputSlots(graph, outputLayerIndex, outputLayer);
962 unsigned int sourceLayerIndex =
963 GetLayerIndexInVector(graph, baseLayer->inputSlots()->Get(0)->connection()->sourceLayerIndex());
964 LayerBaseRawPtr sourceBaseLayer = GetBaseLayer(graph, sourceLayerIndex);
965 const armnn::TensorInfo& tensorInfo = ToTensorInfo(sourceBaseLayer->outputSlots()->Get(i)->tensorInfo());
967 BindingPointInfo bindingInfo = {bindingId, tensorInfo};
968 m_OutputBindings.push_back(std::make_pair(baseLayer->layerName()->c_str(), bindingInfo));
972 void IDeserializer::DeserializerImpl::RegisterOutputSlots(GraphPtr graph,
974 IConnectableLayer* layer)
976 CHECK_LAYERS(graph, 0, layerIndex);
977 ARMNN_ASSERT(layer != nullptr);
978 LayerBaseRawPtr baseLayer = GetBaseLayer(graph, layerIndex);
979 if (baseLayer->outputSlots()->size() != layer->GetNumOutputSlots())
981 throw ParseException(fmt::format("The number of outputslots ({0}) does not match the number expected ({1})"
982 " for layer index: {2} {3}",
983 baseLayer->outputSlots()->size(),
984 layer->GetNumOutputSlots(),
986 CHECK_LOCATION().AsString()));
989 for (unsigned int i = 0; i < layer->GetNumOutputSlots(); ++i)
991 const unsigned int slotIndex = baseLayer->outputSlots()->Get(i)->index();
992 armnn::IOutputSlot* outputSlot = &(layer->GetOutputSlot(slotIndex));
993 // layerIndex is not necessarily the same as baseLayer->index(). The latter is needed here
994 RegisterOutputSlotOfConnection(baseLayer->index(), slotIndex, outputSlot);
998 void IDeserializer::DeserializerImpl::RegisterInputSlots(GraphPtr graph,
1000 armnn::IConnectableLayer* layer)
1002 CHECK_LAYERS(graph, 0, layerIndex);
1003 ARMNN_ASSERT(layer != nullptr);
1004 LayerBaseRawPtr baseLayer = GetBaseLayer(graph, layerIndex);
1005 if (baseLayer->inputSlots()->size() != layer->GetNumInputSlots())
1007 throw ParseException(fmt::format("The number of inputslots ({0}) does not match the number expected ({1})"
1008 " for layer index:{2} {3}",
1009 baseLayer->inputSlots()->size(),
1010 layer->GetNumInputSlots(),
1012 CHECK_LOCATION().AsString()));
1015 for (unsigned int i = 0; i < layer->GetNumInputSlots(); ++i)
1017 auto fbInputSlot = baseLayer->inputSlots()->Get(i);
1018 auto fbConnection = fbInputSlot->connection();
1019 armnn::IInputSlot* inputSlot = &(layer->GetInputSlot(fbInputSlot->index()));
1020 RegisterInputSlotOfConnection(fbConnection->sourceLayerIndex(), fbConnection->outputSlotIndex(), inputSlot);
1024 void IDeserializer::DeserializerImpl::RegisterInputSlotOfConnection(uint32_t sourceLayerIndex,
1025 uint32_t outputSlotIndex,
1026 armnn::IInputSlot* inputSlot)
1028 if (m_GraphConnections.find(sourceLayerIndex) == m_GraphConnections.end())
1030 m_GraphConnections[sourceLayerIndex] = Connections();
1033 Connections& connections = m_GraphConnections[sourceLayerIndex];
1034 if (connections.inputSlots.find(outputSlotIndex) == connections.inputSlots.end())
1036 connections.inputSlots[outputSlotIndex] = {inputSlot};
1040 connections.inputSlots[outputSlotIndex].push_back(inputSlot);
1044 void IDeserializer::DeserializerImpl::RegisterOutputSlotOfConnection(uint32_t sourceLayerIndex,
1045 uint32_t outputSlotIndex,
1046 armnn::IOutputSlot* outputSlot)
1048 if (m_GraphConnections.find(sourceLayerIndex) == m_GraphConnections.end())
1050 m_GraphConnections[sourceLayerIndex] = Connections();
1053 Connections& connections = m_GraphConnections[sourceLayerIndex];
1054 if (connections.outputSlots.find(outputSlotIndex) != connections.outputSlots.end())
1056 throw ParseException("Same output slot index processed twice");
1059 connections.outputSlots[outputSlotIndex] = outputSlot;
1062 void IDeserializer::DeserializerImpl::ParseAbs(GraphPtr graph, unsigned int layerIndex)
1064 CHECK_LAYERS(graph, 0, layerIndex);
1065 auto inputs = GetInputs(graph, layerIndex);
1067 CHECK_VALID_SIZE(inputs.size(), 1);
1069 auto outputs = GetOutputs(graph, layerIndex);
1070 CHECK_VALID_SIZE(outputs.size(), 1);
1072 auto layerName = GetLayerName(graph, layerIndex);
1074 armnn::ElementwiseUnaryDescriptor descriptor(armnn::UnaryOperation::Abs);
1075 IConnectableLayer* layer = m_Network->AddElementwiseUnaryLayer(descriptor, layerName.c_str());
1076 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1077 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1079 RegisterInputSlots(graph, layerIndex, layer);
1080 RegisterOutputSlots(graph, layerIndex, layer);
1083 void IDeserializer::DeserializerImpl::ParseActivation(GraphPtr graph, unsigned int layerIndex)
1085 CHECK_LAYERS(graph, 0, layerIndex);
1086 auto inputs = GetInputs(graph, layerIndex);
1088 CHECK_VALID_SIZE(inputs.size(), 1);
1090 auto outputs = GetOutputs(graph, layerIndex);
1091 CHECK_VALID_SIZE(outputs.size(), 1);
1093 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_ActivationLayer();
1094 auto layerName = GetLayerName(graph, layerIndex);
1095 auto serializerDescriptor = serializerLayer->descriptor();
1097 armnn::ActivationDescriptor descriptor;
1098 descriptor.m_Function = ToActivationFunction(serializerDescriptor->activationFunction());
1099 descriptor.m_A = serializerDescriptor->a();
1100 descriptor.m_B = serializerDescriptor->b();
1102 IConnectableLayer* layer = m_Network->AddActivationLayer(descriptor,
1104 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1105 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1107 RegisterInputSlots(graph, layerIndex, layer);
1108 RegisterOutputSlots(graph, layerIndex, layer);
1111 void IDeserializer::DeserializerImpl::ParseAdd(GraphPtr graph, unsigned int layerIndex)
1113 CHECK_LAYERS(graph, 0, layerIndex);
1114 auto inputs = GetInputs(graph, layerIndex);
1116 CHECK_VALID_SIZE(inputs.size(), 2);
1118 auto outputs = GetOutputs(graph, layerIndex);
1119 CHECK_VALID_SIZE(outputs.size(), 1);
1121 auto layerName = GetLayerName(graph, layerIndex);
1122 IConnectableLayer* layer = m_Network->AddAdditionLayer(layerName.c_str());
1124 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1125 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1127 RegisterInputSlots(graph, layerIndex, layer);
1128 RegisterOutputSlots(graph, layerIndex, layer);
1131 void IDeserializer::DeserializerImpl::ParseArgMinMax(GraphPtr graph, unsigned int layerIndex)
1133 CHECK_LAYERS(graph, 0, layerIndex);
1134 auto inputs = GetInputs(graph, layerIndex);
1136 CHECK_VALID_SIZE(inputs.size(), 1);
1138 auto outputs = GetOutputs(graph, layerIndex);
1139 CHECK_VALID_SIZE(outputs.size(), 1);
1141 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_ArgMinMaxLayer();
1142 auto serializerDescriptor = serializerLayer->descriptor();
1144 armnn::ArgMinMaxDescriptor descriptor;
1145 descriptor.m_Function = ToArgMinMaxFunction(serializerDescriptor->argMinMaxFunction());
1146 descriptor.m_Axis = serializerDescriptor->axis();
1147 auto layerName = GetLayerName(graph, layerIndex);
1148 IConnectableLayer* layer = m_Network->AddArgMinMaxLayer(descriptor, layerName.c_str());
1150 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1151 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1153 RegisterInputSlots(graph, layerIndex, layer);
1154 RegisterOutputSlots(graph, layerIndex, layer);
1157 void IDeserializer::DeserializerImpl::ParseBatchToSpaceNd(GraphPtr graph, unsigned int layerIndex)
1159 CHECK_LAYERS(graph, 0, layerIndex);
1161 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
1162 CHECK_VALID_SIZE(inputs.size(), 1);
1164 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
1165 CHECK_VALID_SIZE(outputs.size(), 1);
1167 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_BatchToSpaceNdLayer()->descriptor();
1168 auto flatBufferCrops = flatBufferDescriptor->crops();
1169 auto flatBufferBlockShape = flatBufferDescriptor->blockShape();
1171 if (flatBufferCrops->Length() % 2 != 0)
1173 throw ParseException(fmt::format("The size of crops must be divisible by 2 {}", CHECK_LOCATION().AsString()));
1176 std::vector<std::pair<unsigned int, unsigned int>> crops;
1177 crops.reserve(flatBufferCrops->Length() / 2);
1178 for (unsigned int i = 0; i < flatBufferCrops->Length() - 1; i += 2)
1180 crops.emplace_back(flatBufferCrops->Get(i), flatBufferCrops->Get(i+1));
1183 armnn::BatchToSpaceNdDescriptor descriptor;
1184 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
1185 descriptor.m_BlockShape =
1186 std::vector<unsigned int>(flatBufferBlockShape->begin(), flatBufferBlockShape->end());
1187 descriptor.m_Crops = crops;
1189 auto layerName = GetLayerName(graph, layerIndex);
1190 IConnectableLayer* layer = m_Network->AddBatchToSpaceNdLayer(descriptor, layerName.c_str());
1192 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1193 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1195 RegisterInputSlots(graph, layerIndex, layer);
1196 RegisterOutputSlots(graph, layerIndex, layer);
1199 void IDeserializer::DeserializerImpl::ParseBatchNormalization(GraphPtr graph, unsigned int layerIndex)
1201 CHECK_LAYERS(graph, 0, layerIndex);
1203 auto inputs = GetInputs(graph, layerIndex);
1204 CHECK_VALID_SIZE(inputs.size(), 1);
1206 auto outputs = GetOutputs(graph, layerIndex);
1207 CHECK_VALID_SIZE(outputs.size(), 1);
1208 auto outputInfo = ToTensorInfo(outputs[0]);
1210 auto layerName = GetLayerName(graph, layerIndex);
1212 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_BatchNormalizationLayer();
1213 auto serializerDescriptor = serializerLayer->descriptor();
1215 armnn::BatchNormalizationDescriptor descriptor;
1216 descriptor.m_Eps = serializerDescriptor->eps();
1217 descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
1219 armnn::ConstTensor mean = ToConstTensor(serializerLayer->mean());
1220 armnn::ConstTensor variance = ToConstTensor(serializerLayer->variance());
1221 armnn::ConstTensor beta = ToConstTensor(serializerLayer->beta());
1222 armnn::ConstTensor gamma = ToConstTensor(serializerLayer->gamma());
1224 IConnectableLayer* layer = m_Network->AddBatchNormalizationLayer(descriptor,
1230 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1232 RegisterInputSlots(graph, layerIndex, layer);
1233 RegisterOutputSlots(graph, layerIndex, layer);
1236 void IDeserializer::DeserializerImpl::ParseConstant(GraphPtr graph, unsigned int layerIndex)
1238 CHECK_LAYERS(graph, 0, layerIndex);
1241 auto outputs = GetOutputs(graph, layerIndex);
1242 CHECK_VALID_SIZE(outputs.size(), 1);
1244 auto layerName = GetLayerName(graph, layerIndex);
1246 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_ConstantLayer();
1247 auto serializerInput = serializerLayer->input();
1249 armnn::ConstTensor input = ToConstTensor(serializerInput);
1251 IConnectableLayer* layer = m_Network->AddConstantLayer(input, layerName.c_str());
1253 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1254 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1256 RegisterOutputSlots(graph, layerIndex, layer);
1259 void IDeserializer::DeserializerImpl::ParseConvolution2d(GraphPtr graph, unsigned int layerIndex)
1261 CHECK_LAYERS(graph, 0, layerIndex);
1262 auto inputs = GetInputs(graph, layerIndex);
1264 CHECK_VALID_SIZE(inputs.size(), 1);
1266 auto outputs = GetOutputs(graph, layerIndex);
1267 CHECK_VALID_SIZE(outputs.size(), 1);
1269 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_Convolution2dLayer();
1270 auto layerName = GetLayerName(graph, layerIndex);
1271 auto serializerDescriptor = serializerLayer->descriptor();
1273 armnn::Convolution2dDescriptor descriptor;
1274 descriptor.m_PadLeft = serializerDescriptor->padLeft();
1275 descriptor.m_PadRight = serializerDescriptor->padRight();
1276 descriptor.m_PadTop = serializerDescriptor->padTop();
1277 descriptor.m_PadBottom = serializerDescriptor->padBottom();
1278 descriptor.m_StrideX = serializerDescriptor->strideX();
1279 descriptor.m_StrideY = serializerDescriptor->strideY();;
1280 descriptor.m_DilationX = serializerDescriptor->dilationX();
1281 descriptor.m_DilationY = serializerDescriptor->dilationY();;
1282 descriptor.m_BiasEnabled = serializerDescriptor->biasEnabled();;
1283 descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
1285 armnn::ConstTensor weights = ToConstTensor(serializerLayer->weights());
1286 armnn::ConstTensor biases;
1288 armnn::Optional<armnn::ConstTensor> optionalBiases = armnn::EmptyOptional();
1289 if (descriptor.m_BiasEnabled)
1291 biases = ToConstTensor(serializerLayer->biases());
1292 optionalBiases = armnn::Optional<armnn::ConstTensor>(biases);
1294 IConnectableLayer* layer = m_Network->AddConvolution2dLayer(descriptor,
1298 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1299 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1301 RegisterInputSlots(graph, layerIndex, layer);
1302 RegisterOutputSlots(graph, layerIndex, layer);
1305 void IDeserializer::DeserializerImpl::ParseDepthToSpace(GraphPtr graph, unsigned int layerIndex)
1307 CHECK_LAYERS(graph, 0, layerIndex);
1309 auto inputs = GetInputs(graph, layerIndex);
1310 CHECK_VALID_SIZE(inputs.size(), 1);
1312 auto outputs = GetOutputs(graph, layerIndex);
1313 CHECK_VALID_SIZE(outputs.size(), 1);
1315 auto fbDescriptor = graph->layers()->Get(layerIndex)->layer_as_DepthToSpaceLayer()->descriptor();
1317 armnn::DepthToSpaceDescriptor descriptor;
1318 descriptor.m_BlockSize = fbDescriptor->blockSize();
1319 descriptor.m_DataLayout = ToDataLayout(fbDescriptor->dataLayout());
1321 auto layerName = GetLayerName(graph, layerIndex);
1322 IConnectableLayer* layer = m_Network->AddDepthToSpaceLayer(descriptor, layerName.c_str());
1324 armnn::TensorInfo outputInfo = ToTensorInfo(outputs[0]);
1325 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1327 RegisterInputSlots(graph, layerIndex, layer);
1328 RegisterOutputSlots(graph, layerIndex, layer);
1331 void IDeserializer::DeserializerImpl::ParseDepthwiseConvolution2d(GraphPtr graph, unsigned int layerIndex)
1333 CHECK_LAYERS(graph, 0, layerIndex);
1334 auto inputs = GetInputs(graph, layerIndex);
1336 CHECK_VALID_SIZE(inputs.size(), 1);
1338 auto outputs = GetOutputs(graph, layerIndex);
1339 CHECK_VALID_SIZE(outputs.size(), 1);
1341 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_DepthwiseConvolution2dLayer();
1342 auto layerName = GetLayerName(graph, layerIndex);
1343 auto serializerDescriptor = serializerLayer->descriptor();
1345 armnn::DepthwiseConvolution2dDescriptor descriptor;
1346 descriptor.m_PadLeft = serializerDescriptor->padLeft();
1347 descriptor.m_PadRight = serializerDescriptor->padRight();
1348 descriptor.m_PadTop = serializerDescriptor->padTop();
1349 descriptor.m_PadBottom = serializerDescriptor->padBottom();
1350 descriptor.m_StrideX = serializerDescriptor->strideX();
1351 descriptor.m_StrideY = serializerDescriptor->strideY();
1352 descriptor.m_DilationX = serializerDescriptor->dilationX();
1353 descriptor.m_DilationY = serializerDescriptor->dilationY();
1354 descriptor.m_BiasEnabled = serializerDescriptor->biasEnabled();;
1355 descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
1357 armnn::ConstTensor weights = ToConstTensor(serializerLayer->weights());
1358 armnn::ConstTensor biases;
1360 armnn::Optional<armnn::ConstTensor> optionalBiases = armnn::EmptyOptional();
1361 if (descriptor.m_BiasEnabled)
1363 biases = ToConstTensor(serializerLayer->biases());
1364 optionalBiases = armnn::Optional<armnn::ConstTensor>(biases);
1366 IConnectableLayer* layer = m_Network->AddDepthwiseConvolution2dLayer(descriptor,
1371 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1372 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1374 RegisterInputSlots(graph, layerIndex, layer);
1375 RegisterOutputSlots(graph, layerIndex, layer);
1378 void IDeserializer::DeserializerImpl::ParseDetectionPostProcess(GraphPtr graph, unsigned int layerIndex)
1380 CHECK_LAYERS(graph, 0, layerIndex);
1381 auto inputs = GetInputs(graph, layerIndex);
1383 CHECK_VALID_SIZE(inputs.size(), 2);
1385 auto outputs = GetOutputs(graph, layerIndex);
1386 CHECK_VALID_SIZE(outputs.size(), 4);
1388 auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_DetectionPostProcessLayer();
1389 auto layerName = GetLayerName(graph, layerIndex);
1390 auto flatBufferDescriptor = flatBufferLayer->descriptor();
1392 armnn::DetectionPostProcessDescriptor descriptor;
1393 descriptor.m_MaxDetections = flatBufferDescriptor->maxDetections();
1394 descriptor.m_MaxClassesPerDetection = flatBufferDescriptor->maxClassesPerDetection();
1395 descriptor.m_DetectionsPerClass = flatBufferDescriptor->detectionsPerClass();
1396 descriptor.m_NmsScoreThreshold = flatBufferDescriptor->nmsScoreThreshold();
1397 descriptor.m_NmsIouThreshold = flatBufferDescriptor->nmsIouThreshold();
1398 descriptor.m_NumClasses = flatBufferDescriptor->numClasses();
1399 descriptor.m_UseRegularNms = flatBufferDescriptor->useRegularNms();
1400 descriptor.m_ScaleX = flatBufferDescriptor->scaleX();
1401 descriptor.m_ScaleY = flatBufferDescriptor->scaleY();
1402 descriptor.m_ScaleW = flatBufferDescriptor->scaleW();
1403 descriptor.m_ScaleH = flatBufferDescriptor->scaleH();
1405 armnn::ConstTensor anchors = ToConstTensor(flatBufferLayer->anchors());
1407 IConnectableLayer* layer = m_Network->AddDetectionPostProcessLayer(descriptor,
1411 for (unsigned int i = 0; i < 4; i++)
1413 layer->GetOutputSlot(i).SetTensorInfo(ToTensorInfo(outputs[i]));
1416 RegisterInputSlots(graph, layerIndex, layer);
1417 RegisterOutputSlots(graph, layerIndex, layer);
1420 void IDeserializer::DeserializerImpl::ParseDivision(GraphPtr graph, unsigned int layerIndex)
1422 CHECK_LAYERS(graph, 0, layerIndex);
1423 auto inputs = GetInputs(graph, layerIndex);
1425 CHECK_VALID_SIZE(inputs.size(), 2);
1427 auto outputs = GetOutputs(graph, layerIndex);
1428 CHECK_VALID_SIZE(outputs.size(), 1);
1430 auto layerName = GetLayerName(graph, layerIndex);
1431 IConnectableLayer* layer = m_Network->AddDivisionLayer(layerName.c_str());
1433 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1434 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1436 RegisterInputSlots(graph, layerIndex, layer);
1437 RegisterOutputSlots(graph, layerIndex, layer);
1440 void IDeserializer::DeserializerImpl::ParseEqual(GraphPtr graph, unsigned int layerIndex)
1442 CHECK_LAYERS(graph, 0, layerIndex);
1443 auto inputs = GetInputs(graph, layerIndex);
1445 CHECK_VALID_SIZE(inputs.size(), 2);
1447 auto outputs = GetOutputs(graph, layerIndex);
1448 CHECK_VALID_SIZE(outputs.size(), 1);
1450 auto layerName = GetLayerName(graph, layerIndex);
1451 armnn::ComparisonDescriptor descriptor(armnn::ComparisonOperation::Equal);
1452 IConnectableLayer* layer = m_Network->AddComparisonLayer(descriptor, layerName.c_str());
1454 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1455 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1457 RegisterInputSlots(graph, layerIndex, layer);
1458 RegisterOutputSlots(graph, layerIndex, layer);
1461 void IDeserializer::DeserializerImpl::ParseFill(GraphPtr graph, unsigned int layerIndex)
1463 CHECK_LAYERS(graph, 0, layerIndex);
1464 auto inputs = GetInputs(graph, layerIndex);
1466 CHECK_VALID_SIZE(inputs.size(), 1);
1468 auto outputs = GetOutputs(graph, layerIndex);
1469 CHECK_VALID_SIZE(outputs.size(), 1);
1471 auto layerName = GetLayerName(graph, layerIndex);
1472 armnn::FillDescriptor descriptor(1.0f);
1473 IConnectableLayer* layer = m_Network->AddFillLayer(descriptor, layerName.c_str());
1475 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1476 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1478 RegisterInputSlots(graph, layerIndex, layer);
1479 RegisterOutputSlots(graph, layerIndex, layer);
1482 void IDeserializer::DeserializerImpl::ParseGreater(GraphPtr graph, unsigned int layerIndex)
1484 CHECK_LAYERS(graph, 0, layerIndex);
1485 auto inputs = GetInputs(graph, layerIndex);
1487 CHECK_VALID_SIZE(inputs.size(), 2);
1489 auto outputs = GetOutputs(graph, layerIndex);
1490 CHECK_VALID_SIZE(outputs.size(), 1);
1492 auto layerName = GetLayerName(graph, layerIndex);
1493 armnn::ComparisonDescriptor descriptor(armnn::ComparisonOperation::Greater);
1494 IConnectableLayer* layer = m_Network->AddComparisonLayer(descriptor, layerName.c_str());
1496 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1497 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1499 RegisterInputSlots(graph, layerIndex, layer);
1500 RegisterOutputSlots(graph, layerIndex, layer);
1503 void IDeserializer::DeserializerImpl::ParseInstanceNormalization(GraphPtr graph, unsigned int layerIndex)
1505 CHECK_LAYERS(graph, 0, layerIndex);
1507 auto inputs = GetInputs(graph, layerIndex);
1508 CHECK_VALID_SIZE(inputs.size(), 1);
1510 auto outputs = GetOutputs(graph, layerIndex);
1511 CHECK_VALID_SIZE(outputs.size(), 1);
1513 auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_InstanceNormalizationLayer();
1514 auto fbDescriptor = fbLayer->descriptor();
1516 armnn::InstanceNormalizationDescriptor descriptor;
1517 descriptor.m_Gamma = fbDescriptor->gamma();
1518 descriptor.m_Beta = fbDescriptor->beta();
1519 descriptor.m_Eps = fbDescriptor->eps();
1520 descriptor.m_DataLayout = ToDataLayout(fbDescriptor->dataLayout());
1522 const std::string layerName = GetLayerName(graph, layerIndex);
1523 const armnn::TensorInfo outputInfo = ToTensorInfo(outputs[0]);
1525 IConnectableLayer* layer = m_Network->AddInstanceNormalizationLayer(descriptor, layerName.c_str());
1526 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1528 RegisterInputSlots(graph, layerIndex, layer);
1529 RegisterOutputSlots(graph, layerIndex, layer);
1532 void IDeserializer::DeserializerImpl::ParseL2Normalization(GraphPtr graph, unsigned int layerIndex)
1534 CHECK_LAYERS(graph, 0, layerIndex);
1536 auto inputs = GetInputs(graph, layerIndex);
1537 CHECK_VALID_SIZE(inputs.size(), 1);
1539 auto outputs = GetOutputs(graph, layerIndex);
1540 CHECK_VALID_SIZE(outputs.size(), 1);
1541 auto outputInfo = ToTensorInfo(outputs[0]);
1543 auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_L2NormalizationLayer();
1544 auto flatBufferDescriptor = flatBufferLayer->descriptor();
1546 auto layerName = GetLayerName(graph, layerIndex);
1547 armnn::L2NormalizationDescriptor descriptor;
1548 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
1549 descriptor.m_Eps = flatBufferDescriptor->eps();
1551 IConnectableLayer* layer = m_Network->AddL2NormalizationLayer(descriptor, layerName.c_str());
1552 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1554 RegisterInputSlots(graph, layerIndex, layer);
1555 RegisterOutputSlots(graph, layerIndex, layer);
1558 void IDeserializer::DeserializerImpl::ParseLogicalBinary(GraphPtr graph, unsigned int layerIndex)
1560 CHECK_LAYERS(graph, 0, layerIndex);
1563 auto inputs = GetInputs(graph, layerIndex);
1564 CHECK_VALID_SIZE(inputs.size(), 2);
1566 auto outputs = GetOutputs(graph, layerIndex);
1567 CHECK_VALID_SIZE(outputs.size(), 1);
1569 auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_LogicalBinaryLayer();
1570 auto fbDescriptor = fbLayer->descriptor();
1572 armnn::LogicalBinaryDescriptor descriptor;
1573 descriptor.m_Operation = ToLogicalBinaryOperation(fbDescriptor->operation());
1575 const std::string& layerName = GetLayerName(graph, layerIndex);
1576 IConnectableLayer* layer = m_Network->AddLogicalBinaryLayer(descriptor, layerName.c_str());
1578 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1579 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1581 RegisterInputSlots(graph, layerIndex, layer);
1582 RegisterOutputSlots(graph, layerIndex, layer);
1585 void IDeserializer::DeserializerImpl::ParseLogSoftmax(GraphPtr graph, unsigned int layerIndex)
1587 CHECK_LAYERS(graph, 0, layerIndex);
1589 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
1590 CHECK_VALID_SIZE(inputs.size(), 1);
1592 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
1593 CHECK_VALID_SIZE(outputs.size(), 1);
1595 armnn::LogSoftmaxDescriptor descriptor;
1596 descriptor.m_Beta = graph->layers()->Get(layerIndex)->layer_as_LogSoftmaxLayer()->descriptor()->beta();
1597 descriptor.m_Axis = graph->layers()->Get(layerIndex)->layer_as_LogSoftmaxLayer()->descriptor()->axis();
1598 auto layerName = GetLayerName(graph, layerIndex);
1600 IConnectableLayer* layer = m_Network->AddLogSoftmaxLayer(descriptor, layerName.c_str());
1602 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1603 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1605 RegisterInputSlots(graph, layerIndex, layer);
1606 RegisterOutputSlots(graph, layerIndex, layer);
1609 void IDeserializer::DeserializerImpl::ParseMinimum(GraphPtr graph, unsigned int layerIndex)
1611 CHECK_LAYERS(graph, 0, layerIndex);
1612 auto inputs = GetInputs(graph, layerIndex);
1614 CHECK_VALID_SIZE(inputs.size(), 2);
1616 auto outputs = GetOutputs(graph, layerIndex);
1617 CHECK_VALID_SIZE(outputs.size(), 1);
1619 auto layerName = GetLayerName(graph, layerIndex);
1620 IConnectableLayer* layer = m_Network->AddMinimumLayer(layerName.c_str());
1622 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1623 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1625 RegisterInputSlots(graph, layerIndex, layer);
1626 RegisterOutputSlots(graph, layerIndex, layer);
1629 void IDeserializer::DeserializerImpl::ParseMaximum(GraphPtr graph, unsigned int layerIndex)
1631 CHECK_LAYERS(graph, 0, layerIndex);
1632 auto inputs = GetInputs(graph, layerIndex);
1634 CHECK_VALID_SIZE(inputs.size(), 2);
1636 auto outputs = GetOutputs(graph, layerIndex);
1637 CHECK_VALID_SIZE(outputs.size(), 1);
1639 auto layerName = GetLayerName(graph, layerIndex);
1640 IConnectableLayer* layer = m_Network->AddMaximumLayer(layerName.c_str());
1642 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1643 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1645 RegisterInputSlots(graph, layerIndex, layer);
1646 RegisterOutputSlots(graph, layerIndex, layer);
1649 const armnnSerializer::OriginsDescriptor* GetOriginsDescriptor(const armnnSerializer::SerializedGraph* graph,
1650 unsigned int layerIndex)
1652 auto layerType = graph->layers()->Get(layerIndex)->layer_type();
1656 case Layer::Layer_ConcatLayer:
1657 return graph->layers()->Get(layerIndex)->layer_as_ConcatLayer()->descriptor();
1658 case Layer::Layer_MergerLayer:
1659 return graph->layers()->Get(layerIndex)->layer_as_MergerLayer()->descriptor();
1661 throw armnn::Exception("unknown layer type, should be concat or merger");
1665 void IDeserializer::DeserializerImpl::ParseComparison(GraphPtr graph, unsigned int layerIndex)
1667 CHECK_LAYERS(graph, 0, layerIndex);
1670 auto inputs = GetInputs(graph, layerIndex);
1671 CHECK_VALID_SIZE(inputs.size(), 2);
1673 auto outputs = GetOutputs(graph, layerIndex);
1674 CHECK_VALID_SIZE(outputs.size(), 1);
1676 auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_ComparisonLayer();
1677 auto fbDescriptor = fbLayer->descriptor();
1679 armnn::ComparisonDescriptor descriptor;
1680 descriptor.m_Operation = ToComparisonOperation(fbDescriptor->operation());
1682 const std::string& layerName = GetLayerName(graph, layerIndex);
1683 IConnectableLayer* layer = m_Network->AddComparisonLayer(descriptor, layerName.c_str());
1685 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1686 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1688 RegisterInputSlots(graph, layerIndex, layer);
1689 RegisterOutputSlots(graph, layerIndex, layer);
1692 void IDeserializer::DeserializerImpl::ParseElementwiseUnary(GraphPtr graph, unsigned int layerIndex)
1694 CHECK_LAYERS(graph, 0, layerIndex);
1697 auto inputs = GetInputs(graph, layerIndex);
1698 CHECK_VALID_SIZE(inputs.size(), 1);
1700 auto outputs = GetOutputs(graph, layerIndex);
1701 CHECK_VALID_SIZE(outputs.size(), 1);
1703 auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_ElementwiseUnaryLayer();
1704 auto fbDescriptor = fbLayer->descriptor();
1706 armnn::ElementwiseUnaryDescriptor descriptor;
1707 descriptor.m_Operation = ToUnaryOperation(fbDescriptor->operation());
1709 const std::string& layerName = GetLayerName(graph, layerIndex);
1710 IConnectableLayer* layer = m_Network->AddElementwiseUnaryLayer(descriptor, layerName.c_str());
1712 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1713 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1715 RegisterInputSlots(graph, layerIndex, layer);
1716 RegisterOutputSlots(graph, layerIndex, layer);
1719 void IDeserializer::DeserializerImpl::ParseConcat(GraphPtr graph, unsigned int layerIndex)
1721 CHECK_LAYERS(graph, 0, layerIndex);
1724 auto outputs = GetOutputs(graph, layerIndex);
1725 CHECK_VALID_SIZE(outputs.size(), 1);
1727 auto layerName = GetLayerName(graph, layerIndex);
1728 auto originsDescriptor = GetOriginsDescriptor(graph, layerIndex);
1729 unsigned int numViews = originsDescriptor->numViews();
1730 unsigned int numDimensions = originsDescriptor->numDimensions();
1732 // can now check the number of inputs == number of views
1733 auto inputs = GetInputs(graph, layerIndex);
1734 CHECK_VALID_SIZE(inputs.size(), numViews);
1736 armnn::OriginsDescriptor descriptor(numViews, numDimensions);
1737 auto originsPtr = originsDescriptor->viewOrigins();
1738 for (unsigned int v = 0; v < numViews; ++v)
1740 auto originPtr = originsPtr->Get(v);
1741 for (unsigned int d = 0; d < numDimensions; ++d)
1743 uint32_t value = originPtr->data()->Get(d);
1744 descriptor.SetViewOriginCoord(v, d, value);
1747 descriptor.SetConcatAxis(originsDescriptor->concatAxis());
1749 IConnectableLayer* layer = m_Network->AddConcatLayer(descriptor, layerName.c_str());
1750 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1751 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1753 RegisterInputSlots(graph, layerIndex, layer);
1754 RegisterOutputSlots(graph, layerIndex, layer);
1757 void IDeserializer::DeserializerImpl::ParseMultiplication(GraphPtr graph, unsigned int layerIndex)
1759 CHECK_LAYERS(graph, 0, layerIndex);
1760 auto inputs = GetInputs(graph, layerIndex);
1762 CHECK_VALID_SIZE(inputs.size(), 2);
1764 auto outputs = GetOutputs(graph, layerIndex);
1765 CHECK_VALID_SIZE(outputs.size(), 1);
1767 auto layerName = GetLayerName(graph, layerIndex);
1768 IConnectableLayer* layer = m_Network->AddMultiplicationLayer(layerName.c_str());
1770 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1771 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1773 RegisterInputSlots(graph, layerIndex, layer);
1774 RegisterOutputSlots(graph, layerIndex, layer);
1777 void IDeserializer::DeserializerImpl::ParseFloor(GraphPtr graph, unsigned int layerIndex)
1779 CHECK_LAYERS(graph, 0, layerIndex);
1782 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 layerName = GetLayerName(graph, layerIndex);
1790 armnn::IConnectableLayer* layer;
1792 layer = m_Network->AddFloorLayer(layerName.c_str());
1794 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1795 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1797 RegisterInputSlots(graph, layerIndex, layer);
1798 RegisterOutputSlots(graph, layerIndex, layer);
1801 void IDeserializer::DeserializerImpl::ParseFullyConnected(GraphPtr graph, unsigned int layerIndex)
1803 CHECK_LAYERS(graph, 0, layerIndex);
1804 auto inputs = GetInputs(graph, layerIndex);
1806 CHECK_VALID_SIZE(inputs.size(), 1);
1808 auto outputs = GetOutputs(graph, layerIndex);
1809 CHECK_VALID_SIZE(outputs.size(), 1);
1811 auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_FullyConnectedLayer();
1812 auto layerName = GetLayerName(graph, layerIndex);
1813 auto flatBufferDescriptor = flatBufferLayer->descriptor();
1815 armnn::FullyConnectedDescriptor fullyConnectedDescriptor;
1816 fullyConnectedDescriptor.m_BiasEnabled = flatBufferDescriptor->biasEnabled();
1817 fullyConnectedDescriptor.m_TransposeWeightMatrix = flatBufferDescriptor->transposeWeightsMatrix();
1819 armnn::ConstTensor weightsTensor = ToConstTensor(flatBufferLayer->weights());
1821 armnn::IConnectableLayer* layer;
1822 armnn::Optional<armnn::ConstTensor> optionalBiases = armnn::EmptyOptional();
1823 if (flatBufferDescriptor->biasEnabled())
1825 armnn::ConstTensor biasTensorData = ToConstTensor(flatBufferLayer->biases());
1826 optionalBiases = armnn::Optional<armnn::ConstTensor>(biasTensorData);
1828 layer = m_Network->AddFullyConnectedLayer(fullyConnectedDescriptor,
1833 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1834 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1836 RegisterInputSlots(graph, layerIndex, layer);
1837 RegisterOutputSlots(graph, layerIndex, layer);
1840 void IDeserializer::DeserializerImpl::ParsePad(GraphPtr graph, unsigned int layerIndex)
1842 CHECK_LAYERS(graph, 0, layerIndex);
1844 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
1845 CHECK_VALID_SIZE(inputs.size(), 1);
1847 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
1848 CHECK_VALID_SIZE(outputs.size(), 1);
1850 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_PadLayer()->descriptor();
1851 auto flatBufferPadList = flatBufferDescriptor->padList();
1852 float padValue = flatBufferDescriptor->padValue();
1854 if (flatBufferPadList->Length() % 2 != 0)
1856 throw ParseException(fmt::format("The size of the pad list must be divisible by 2 {}",
1857 CHECK_LOCATION().AsString()));
1860 std::vector<std::pair<unsigned int, unsigned int>> padList;
1861 padList.reserve(flatBufferPadList->Length() / 2);
1862 for (unsigned int i = 0; i < flatBufferPadList->Length() - 1; i += 2)
1864 padList.emplace_back(flatBufferPadList->Get(i), flatBufferPadList->Get(i+1));
1867 armnn::PadDescriptor descriptor(padList, padValue);
1869 auto layerName = GetLayerName(graph, layerIndex);
1870 IConnectableLayer* layer = m_Network->AddPadLayer(descriptor, layerName.c_str());
1872 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
1873 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
1875 RegisterInputSlots(graph, layerIndex, layer);
1876 RegisterOutputSlots(graph, layerIndex, layer);
1879 void IDeserializer::DeserializerImpl::ParsePermute(GraphPtr graph, unsigned int layerIndex)
1881 CHECK_LAYERS(graph, 0, layerIndex);
1884 graph->layers()->Get(layerIndex)->layer_as_PermuteLayer()->descriptor()->dimMappings();
1886 auto inputs = GetInputs(graph, layerIndex);
1887 CHECK_VALID_SIZE(inputs.size(), 1);
1889 auto outputs = GetOutputs(graph, layerIndex);
1890 CHECK_VALID_SIZE(outputs.size(), 1);
1891 auto outputInfo = ToTensorInfo(outputs[0]);
1893 auto layerName = GetLayerName(graph, layerIndex);
1894 const armnn::PermuteDescriptor descriptor(armnn::PermutationVector(dimsMapping->data(), dimsMapping->Length()));
1896 IConnectableLayer* layer = m_Network->AddPermuteLayer(descriptor, layerName.c_str());
1897 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
1899 RegisterInputSlots(graph, layerIndex, layer);
1900 RegisterOutputSlots(graph, layerIndex, layer);
1903 armnn::Pooling2dDescriptor IDeserializer::DeserializerImpl::GetPoolingDescriptor(PoolingDescriptor pooling2dDesc,
1904 unsigned int layerIndex)
1906 IgnoreUnused(layerIndex);
1907 armnn::Pooling2dDescriptor desc;
1909 switch (pooling2dDesc->poolType())
1911 case PoolingAlgorithm_Average:
1913 desc.m_PoolType = armnn::PoolingAlgorithm::Average;
1916 case PoolingAlgorithm_Max:
1918 desc.m_PoolType = armnn::PoolingAlgorithm::Max;
1923 ARMNN_ASSERT_MSG(false, "Unsupported pooling algorithm");
1927 switch (pooling2dDesc->outputShapeRounding())
1929 case OutputShapeRounding_Floor:
1931 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
1934 case OutputShapeRounding_Ceiling:
1936 desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Ceiling;
1941 ARMNN_ASSERT_MSG(false, "Unsupported output shape rounding");
1945 switch (pooling2dDesc->paddingMethod())
1947 case PaddingMethod_Exclude:
1949 desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
1952 case PaddingMethod_IgnoreValue:
1954 desc.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1959 ARMNN_ASSERT_MSG(false, "Unsupported padding method");
1963 switch (pooling2dDesc->dataLayout())
1965 case DataLayout_NCHW:
1967 desc.m_DataLayout = armnn::DataLayout::NCHW;
1970 case DataLayout_NHWC:
1972 desc.m_DataLayout = armnn::DataLayout::NHWC;
1977 ARMNN_ASSERT_MSG(false, "Unsupported data layout");
1981 desc.m_PadRight = pooling2dDesc->padRight();
1982 desc.m_PadLeft = pooling2dDesc->padLeft();
1983 desc.m_PadBottom = pooling2dDesc->padBottom();
1984 desc.m_PadTop = pooling2dDesc->padTop();
1985 desc.m_StrideX = pooling2dDesc->strideX();
1986 desc.m_StrideY = pooling2dDesc->strideY();
1987 desc.m_PoolWidth = pooling2dDesc->poolWidth();
1988 desc.m_PoolHeight = pooling2dDesc->poolHeight();
1995 void IDeserializer::DeserializerImpl::ParsePooling2d(GraphPtr graph, unsigned int layerIndex)
1997 CHECK_LAYERS(graph, 0, layerIndex);
1999 auto pooling2dDes = graph->layers()->Get(layerIndex)->layer_as_Pooling2dLayer()->descriptor();
2000 auto inputs = GetInputs(graph, layerIndex);
2001 CHECK_VALID_SIZE(inputs.size(), 1);
2003 auto outputs = GetOutputs(graph, layerIndex);
2004 CHECK_VALID_SIZE(outputs.size(), 1);
2005 auto outputInfo = ToTensorInfo(outputs[0]);
2007 auto pooling2dDescriptor = GetPoolingDescriptor(pooling2dDes, layerIndex);
2008 auto layerName = GetLayerName(graph, layerIndex);
2009 IConnectableLayer* layer = m_Network->AddPooling2dLayer(pooling2dDescriptor, layerName.c_str());
2010 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2012 RegisterInputSlots(graph, layerIndex, layer);
2013 RegisterOutputSlots(graph, layerIndex, layer);
2016 void IDeserializer::DeserializerImpl::ParseQuantize(GraphPtr graph, unsigned int layerIndex)
2018 CHECK_LAYERS(graph, 0, layerIndex);
2020 auto inputs = GetInputs(graph, layerIndex);
2021 CHECK_VALID_SIZE(inputs.size(), 1);
2023 auto outputs = GetOutputs(graph, layerIndex);
2024 CHECK_VALID_SIZE(outputs.size(), 1);
2025 auto outputInfo = ToTensorInfo(outputs[0]);
2027 auto layerName = GetLayerName(graph, layerIndex);
2028 IConnectableLayer* layer = m_Network->AddQuantizeLayer(layerName.c_str());
2029 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2031 RegisterInputSlots(graph, layerIndex, layer);
2032 RegisterOutputSlots(graph, layerIndex, layer);
2035 armnn::TensorInfo IDeserializer::DeserializerImpl::OutputShapeOfReshape(const armnn::TensorInfo& inputTensorInfo,
2036 const std::vector<uint32_t>& targetDimsIn)
2038 std::vector<unsigned int> outputDims(targetDimsIn.begin(), targetDimsIn.end());
2039 const auto stretchDim = std::find(targetDimsIn.begin(), targetDimsIn.end(), -1);
2041 if (stretchDim != targetDimsIn.end())
2043 if (std::find(std::next(stretchDim), targetDimsIn.end(), -1) != targetDimsIn.end())
2045 throw ParseException(fmt::format("At most one component of shape can be -1 {}",
2046 CHECK_LOCATION().AsString()));
2049 auto targetNumElements =
2050 armnn::numeric_cast<unsigned int>(
2051 std::accumulate(targetDimsIn.begin(), targetDimsIn.end(), -1, std::multiplies<int32_t>()));
2053 auto stretchIndex = static_cast<size_t>(std::distance(targetDimsIn.begin(), stretchDim));
2054 outputDims[stretchIndex] = inputTensorInfo.GetNumElements() / targetNumElements;
2057 TensorShape outputShape = TensorShape(static_cast<unsigned int>(outputDims.size()), outputDims.data());
2059 armnn::TensorInfo reshapeInfo = inputTensorInfo;
2060 reshapeInfo.SetShape(outputShape);
2065 void IDeserializer::DeserializerImpl::ParseRank(GraphPtr graph, unsigned int layerIndex)
2067 CHECK_LAYERS(graph, 0, layerIndex);
2069 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2070 CHECK_VALID_SIZE(inputs.size(), 1);
2072 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2073 CHECK_VALID_SIZE(outputs.size(), 1);
2075 auto layerName = GetLayerName(graph, layerIndex);
2076 IConnectableLayer* layer = m_Network->AddRankLayer( layerName.c_str());
2078 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2079 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2081 RegisterInputSlots(graph, layerIndex, layer);
2082 RegisterOutputSlots(graph, layerIndex, layer);
2085 void IDeserializer::DeserializerImpl::ParseReshape(GraphPtr graph, unsigned int layerIndex)
2087 CHECK_LAYERS(graph, 0, layerIndex);
2088 auto inputs = GetInputs(graph, layerIndex);
2090 auto outputs = GetOutputs(graph, layerIndex);
2091 CHECK_VALID_SIZE(outputs.size(), 1);
2093 armnn::TensorInfo inputTensorInfo = ToTensorInfo(inputs[0]);
2094 armnn::TensorInfo actualOutputTensorInfo = ToTensorInfo(outputs[0]);
2096 const auto targetDims = graph->layers()->Get(layerIndex)->layer_as_ReshapeLayer()->descriptor()->targetShape();
2097 std::vector<uint32_t> outputDims(targetDims->begin(), targetDims->begin() + targetDims->size());
2099 armnn::TensorInfo reshapeOutputTensorInfo = DeserializerImpl::OutputShapeOfReshape(inputTensorInfo, outputDims);
2100 const armnn::TensorShape& reshapeOutputTensorShape = reshapeOutputTensorInfo.GetShape();
2102 const std::vector<uint32_t> expectedDims(outputs[0]->dimensions()->begin(),
2103 outputs[0]->dimensions()->begin() + outputs[0]->dimensions()->size());
2105 if (inputs.size() > 1 && !CheckShape(reshapeOutputTensorShape, expectedDims))
2107 std::stringstream ss;
2108 ss << "New shape defined in reshape parameters "
2109 << reshapeOutputTensorShape
2110 << " does not equal output shape "
2111 << actualOutputTensorInfo.GetShape()
2113 << CHECK_LOCATION().AsString();
2114 throw ParseException(ss.str());
2117 armnn::ReshapeDescriptor reshapeDesc;
2118 reshapeDesc.m_TargetShape = reshapeOutputTensorShape;
2120 auto layerName = GetLayerName(graph, layerIndex);
2121 IConnectableLayer* layer = m_Network->AddReshapeLayer(reshapeDesc, layerName.c_str());
2122 layer->GetOutputSlot(0).SetTensorInfo(reshapeOutputTensorInfo);
2124 RegisterInputSlots(graph, layerIndex, layer);
2125 RegisterOutputSlots(graph, layerIndex, layer);
2128 void IDeserializer::DeserializerImpl::ParseResize(GraphPtr graph, unsigned int layerIndex)
2130 CHECK_LAYERS(graph, 0, layerIndex);
2132 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2133 CHECK_VALID_SIZE(inputs.size(), 1);
2135 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2136 CHECK_VALID_SIZE(outputs.size(), 1);
2138 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_ResizeLayer()->descriptor();
2140 armnn::ResizeDescriptor descriptor;
2141 descriptor.m_TargetWidth = flatBufferDescriptor->targetWidth();
2142 descriptor.m_TargetHeight = flatBufferDescriptor->targetHeight();
2143 descriptor.m_Method = ToResizeMethod(flatBufferDescriptor->method());
2144 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2145 descriptor.m_AlignCorners = flatBufferDescriptor->alignCorners();
2146 descriptor.m_HalfPixelCenters = flatBufferDescriptor->halfPixelCenters();
2148 auto layerName = GetLayerName(graph, layerIndex);
2149 IConnectableLayer* layer = m_Network->AddResizeLayer(descriptor, layerName.c_str());
2151 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2152 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2154 RegisterInputSlots(graph, layerIndex, layer);
2155 RegisterOutputSlots(graph, layerIndex, layer);
2158 void IDeserializer::DeserializerImpl::ParseResizeBilinear(GraphPtr graph, unsigned int layerIndex)
2160 CHECK_LAYERS(graph, 0, layerIndex);
2162 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2163 CHECK_VALID_SIZE(inputs.size(), 1);
2165 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2166 CHECK_VALID_SIZE(outputs.size(), 1);
2168 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_ResizeBilinearLayer()->descriptor();
2170 armnn::ResizeDescriptor descriptor;
2171 descriptor.m_TargetWidth = flatBufferDescriptor->targetWidth();
2172 descriptor.m_TargetHeight = flatBufferDescriptor->targetHeight();
2173 descriptor.m_Method = armnn::ResizeMethod::Bilinear;
2174 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2175 descriptor.m_AlignCorners = flatBufferDescriptor->alignCorners();
2176 descriptor.m_HalfPixelCenters = flatBufferDescriptor->halfPixelCenters();
2178 auto layerName = GetLayerName(graph, layerIndex);
2179 IConnectableLayer* layer = m_Network->AddResizeLayer(descriptor, layerName.c_str());
2181 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2182 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2184 RegisterInputSlots(graph, layerIndex, layer);
2185 RegisterOutputSlots(graph, layerIndex, layer);
2188 void IDeserializer::DeserializerImpl::ParseSoftmax(GraphPtr graph, unsigned int layerIndex)
2190 CHECK_LAYERS(graph, 0, layerIndex);
2192 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2193 CHECK_VALID_SIZE(inputs.size(), 1);
2195 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2196 CHECK_VALID_SIZE(outputs.size(), 1);
2198 armnn::SoftmaxDescriptor descriptor;
2199 descriptor.m_Beta = graph->layers()->Get(layerIndex)->layer_as_SoftmaxLayer()->descriptor()->beta();
2200 auto layerName = GetLayerName(graph, layerIndex);
2202 IConnectableLayer* layer = m_Network->AddSoftmaxLayer(descriptor, layerName.c_str());
2204 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2205 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2207 RegisterInputSlots(graph, layerIndex, layer);
2208 RegisterOutputSlots(graph, layerIndex, layer);
2211 void IDeserializer::DeserializerImpl::ParseSpaceToBatchNd(GraphPtr graph, unsigned int layerIndex)
2213 CHECK_LAYERS(graph, 0, layerIndex);
2215 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2216 CHECK_VALID_SIZE(inputs.size(), 1);
2218 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2219 CHECK_VALID_SIZE(outputs.size(), 1);
2221 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_SpaceToBatchNdLayer()->descriptor();
2222 auto flatBufferPadList = flatBufferDescriptor->padList();
2223 auto flatBufferBlockShape = flatBufferDescriptor->blockShape();
2225 if (flatBufferPadList->Length() % 2 != 0)
2227 throw ParseException(fmt::format("The size of the pad list must be divisible by 2 {}",
2228 CHECK_LOCATION().AsString()));
2231 std::vector<std::pair<unsigned int, unsigned int>> padList;
2232 padList.reserve(flatBufferPadList->Length() / 2);
2233 for (unsigned int i = 0; i < flatBufferPadList->Length() - 1; i += 2)
2235 padList.emplace_back(flatBufferPadList->Get(i), flatBufferPadList->Get(i+1));
2238 armnn::SpaceToBatchNdDescriptor descriptor;
2239 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2240 descriptor.m_BlockShape =
2241 std::vector<unsigned int>(flatBufferBlockShape->begin(), flatBufferBlockShape->end());
2242 descriptor.m_PadList = padList;
2244 auto layerName = GetLayerName(graph, layerIndex);
2245 IConnectableLayer* layer = m_Network->AddSpaceToBatchNdLayer(descriptor, layerName.c_str());
2247 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2248 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2250 RegisterInputSlots(graph, layerIndex, layer);
2251 RegisterOutputSlots(graph, layerIndex, layer);
2254 void IDeserializer::DeserializerImpl::ParseSpaceToDepth(GraphPtr graph, unsigned int layerIndex)
2256 CHECK_LAYERS(graph, 0, layerIndex);
2258 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2259 CHECK_VALID_SIZE(inputs.size(), 1);
2261 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2262 CHECK_VALID_SIZE(outputs.size(), 1);
2264 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_SpaceToDepthLayer()->descriptor();
2266 armnn::SpaceToDepthDescriptor descriptor;
2267 descriptor.m_BlockSize = flatBufferDescriptor->blockSize();
2268 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2270 auto layerName = GetLayerName(graph, layerIndex);
2271 IConnectableLayer* layer = m_Network->AddSpaceToDepthLayer(descriptor, layerName.c_str());
2273 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2274 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2276 RegisterInputSlots(graph, layerIndex, layer);
2277 RegisterOutputSlots(graph, layerIndex, layer);
2280 armnn::NormalizationDescriptor IDeserializer::DeserializerImpl::GetNormalizationDescriptor(
2281 NormalizationDescriptorPtr normalizationDescriptor,
2282 unsigned int layerIndex)
2284 IgnoreUnused(layerIndex);
2285 armnn::NormalizationDescriptor desc;
2287 switch (normalizationDescriptor->normChannelType())
2289 case NormalizationAlgorithmChannel_Across:
2291 desc.m_NormChannelType = armnn::NormalizationAlgorithmChannel::Across;
2294 case NormalizationAlgorithmChannel_Within:
2296 desc.m_NormChannelType = armnn::NormalizationAlgorithmChannel::Within;
2301 ARMNN_ASSERT_MSG(false, "Unsupported normalization channel type");
2305 switch (normalizationDescriptor->normMethodType())
2307 case NormalizationAlgorithmMethod_LocalBrightness:
2309 desc.m_NormMethodType = armnn::NormalizationAlgorithmMethod::LocalBrightness;
2312 case NormalizationAlgorithmMethod_LocalContrast:
2314 desc.m_NormMethodType = armnn::NormalizationAlgorithmMethod::LocalContrast;
2319 ARMNN_ASSERT_MSG(false, "Unsupported normalization method type");
2323 switch (normalizationDescriptor->dataLayout())
2325 case DataLayout_NCHW:
2327 desc.m_DataLayout = armnn::DataLayout::NCHW;
2330 case DataLayout_NHWC:
2332 desc.m_DataLayout = armnn::DataLayout::NHWC;
2337 ARMNN_ASSERT_MSG(false, "Unsupported data layout");
2341 desc.m_Alpha = normalizationDescriptor->alpha();
2342 desc.m_Beta = normalizationDescriptor->beta();
2343 desc.m_K = normalizationDescriptor->k();
2344 desc.m_NormSize = normalizationDescriptor->normSize();
2349 void IDeserializer::DeserializerImpl::ParseNormalization(GraphPtr graph, unsigned int layerIndex)
2351 CHECK_LAYERS(graph, 0, layerIndex);
2353 auto normalizationDes = graph->layers()->Get(layerIndex)->layer_as_NormalizationLayer()->descriptor();
2355 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2356 CHECK_VALID_SIZE(inputs.size(), 1);
2358 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2359 CHECK_VALID_SIZE(outputs.size(), 1);
2361 auto outputInfo = ToTensorInfo(outputs[0]);
2363 auto normalizationDescriptor = GetNormalizationDescriptor(normalizationDes, layerIndex);
2364 auto layerName = GetLayerName(graph, layerIndex);
2366 IConnectableLayer* layer = m_Network->AddNormalizationLayer(normalizationDescriptor, layerName.c_str());
2367 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
2369 RegisterInputSlots(graph, layerIndex, layer);
2370 RegisterOutputSlots(graph, layerIndex, layer);
2373 void IDeserializer::DeserializerImpl::ParseRsqrt(GraphPtr graph, unsigned int layerIndex)
2375 CHECK_LAYERS(graph, 0, layerIndex);
2376 auto inputs = GetInputs(graph, layerIndex);
2378 CHECK_VALID_SIZE(inputs.size(), 1);
2380 auto outputs = GetOutputs(graph, layerIndex);
2381 CHECK_VALID_SIZE(outputs.size(), 1);
2383 auto layerName = GetLayerName(graph, layerIndex);
2385 armnn::ElementwiseUnaryDescriptor descriptor(armnn::UnaryOperation::Rsqrt);
2386 IConnectableLayer* layer = m_Network->AddElementwiseUnaryLayer(descriptor, layerName.c_str());
2387 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2388 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2390 RegisterInputSlots(graph, layerIndex, layer);
2391 RegisterOutputSlots(graph, layerIndex, layer);
2394 void IDeserializer::DeserializerImpl::ParseSlice(GraphPtr graph, unsigned int layerIndex)
2396 CHECK_LAYERS(graph, 0, layerIndex);
2398 auto inputs = GetInputs(graph, layerIndex);
2399 CHECK_VALID_SIZE(inputs.size(), 1);
2401 auto outputs = GetOutputs(graph, layerIndex);
2402 CHECK_VALID_SIZE(outputs.size(), 1);
2404 auto fbDescriptor = graph->layers()->Get(layerIndex)->layer_as_SliceLayer()->descriptor();
2406 auto fbBegin = fbDescriptor->begin();
2407 auto fbSize = fbDescriptor->size();
2409 if (fbBegin->Length() != fbSize->Length())
2411 throw ParseException(fmt::format("Begin and size descriptors must have the same length {}",
2412 CHECK_LOCATION().AsString()));
2415 armnn::SliceDescriptor descriptor;
2416 descriptor.m_Begin.insert(descriptor.m_Begin.end(), fbBegin->begin(), fbBegin->end());
2417 descriptor.m_Size.insert(descriptor.m_Size.end(), fbSize->begin(), fbSize->end());
2419 auto layerName = GetLayerName(graph, layerIndex);
2420 IConnectableLayer* layer = m_Network->AddSliceLayer(descriptor, layerName.c_str());
2422 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2423 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2425 RegisterInputSlots(graph, layerIndex, layer);
2426 RegisterOutputSlots(graph, layerIndex, layer);
2429 void IDeserializer::DeserializerImpl::ParseStridedSlice(GraphPtr graph, unsigned int layerIndex)
2431 CHECK_LAYERS(graph, 0, layerIndex);
2433 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2434 CHECK_VALID_SIZE(inputs.size(), 1);
2436 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2437 CHECK_VALID_SIZE(outputs.size(), 1);
2439 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_StridedSliceLayer()->descriptor();
2441 auto flatBufferBegin = flatBufferDescriptor->begin();
2442 auto flatBufferEnd = flatBufferDescriptor->end();
2443 auto flatBufferStride = flatBufferDescriptor->stride();
2445 if (!(flatBufferBegin->Length() == flatBufferEnd->Length() &&
2446 flatBufferBegin->Length() == flatBufferStride->Length()))
2448 throw ParseException(fmt::format("The size of the begin, end, and stride must be equal {}",
2449 CHECK_LOCATION().AsString()));
2452 std::vector<int> begin(flatBufferBegin->begin(), flatBufferBegin->end());
2453 std::vector<int> end(flatBufferEnd->begin(), flatBufferEnd->end());
2454 std::vector<int> stride(flatBufferStride->begin(), flatBufferStride->end());
2456 armnn::StridedSliceDescriptor descriptor(begin, end, stride);
2457 descriptor.m_BeginMask = flatBufferDescriptor->beginMask();
2458 descriptor.m_EndMask = flatBufferDescriptor->endMask();
2459 descriptor.m_ShrinkAxisMask = flatBufferDescriptor->shrinkAxisMask();
2460 descriptor.m_EllipsisMask = flatBufferDescriptor->ellipsisMask();
2461 descriptor.m_NewAxisMask = flatBufferDescriptor->newAxisMask();
2462 descriptor.m_DataLayout = ToDataLayout(flatBufferDescriptor->dataLayout());
2464 auto layerName = GetLayerName(graph, layerIndex);
2465 IConnectableLayer* layer = m_Network->AddStridedSliceLayer(descriptor, layerName.c_str());
2467 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2468 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2470 RegisterInputSlots(graph, layerIndex, layer);
2471 RegisterOutputSlots(graph, layerIndex, layer);
2474 void IDeserializer::DeserializerImpl::ParseSubtraction(GraphPtr graph, unsigned int layerIndex)
2476 CHECK_LAYERS(graph, 0, layerIndex);
2477 auto inputs = GetInputs(graph, layerIndex);
2479 CHECK_VALID_SIZE(inputs.size(), 2);
2481 auto outputs = GetOutputs(graph, layerIndex);
2482 CHECK_VALID_SIZE(outputs.size(), 1);
2484 auto layerName = GetLayerName(graph, layerIndex);
2485 IConnectableLayer* layer = m_Network->AddSubtractionLayer(layerName.c_str());
2487 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2488 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2490 RegisterInputSlots(graph, layerIndex, layer);
2491 RegisterOutputSlots(graph, layerIndex, layer);
2494 void IDeserializer::DeserializerImpl::ParseGather(GraphPtr graph, unsigned int layerIndex)
2496 CHECK_LAYERS(graph, 0, layerIndex);
2498 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2499 CHECK_VALID_SIZE(inputs.size(), 2);
2501 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2502 CHECK_VALID_SIZE(outputs.size(), 1);
2504 armnn::GatherDescriptor descriptor;
2505 descriptor.m_Axis = graph->layers()->Get(layerIndex)->layer_as_GatherLayer()->descriptor()->axis();
2507 auto layerName = GetLayerName(graph, layerIndex);
2508 IConnectableLayer* layer = m_Network->AddGatherLayer(descriptor, layerName.c_str());
2510 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2511 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2513 RegisterInputSlots(graph, layerIndex, layer);
2514 RegisterOutputSlots(graph, layerIndex, layer);
2517 void IDeserializer::DeserializerImpl::ParseMean(GraphPtr graph, unsigned int layerIndex)
2519 CHECK_LAYERS(graph, 0, layerIndex);
2521 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2522 CHECK_VALID_SIZE(inputs.size(), 1);
2524 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2525 CHECK_VALID_SIZE(outputs.size(), 1);
2527 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_MeanLayer()->descriptor();
2528 auto flatBufferAxis = flatBufferDescriptor->axis();
2529 auto flatBufferKeepDims = flatBufferDescriptor->keepDims();
2531 armnn::MeanDescriptor descriptor;
2532 descriptor.m_Axis = std::vector<unsigned int>(flatBufferAxis->begin(), flatBufferAxis->end());
2533 descriptor.m_KeepDims = flatBufferKeepDims;
2535 auto layerName = GetLayerName(graph, layerIndex);
2536 IConnectableLayer* layer = m_Network->AddMeanLayer(descriptor, layerName.c_str());
2538 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2539 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2541 RegisterInputSlots(graph, layerIndex, layer);
2542 RegisterOutputSlots(graph, layerIndex, layer);
2545 void IDeserializer::DeserializerImpl::ParseSplitter(GraphPtr graph, unsigned int layerIndex)
2547 CHECK_LAYERS(graph, 0, layerIndex);
2549 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2550 CHECK_VALID_SIZE(inputs.size(), 1);
2552 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2554 auto flatBufferViewsDescriptor = graph->layers()->Get(layerIndex)->layer_as_SplitterLayer()->descriptor();
2555 auto flatBufferViewSizes = flatBufferViewsDescriptor->viewSizes();
2556 auto flatBufferOriginsDescriptor = flatBufferViewsDescriptor->origins();
2557 auto flatBufferViewOrigins = flatBufferOriginsDescriptor->viewOrigins();
2558 uint32_t numViews = flatBufferOriginsDescriptor->numViews();
2559 uint32_t numDimensions = flatBufferOriginsDescriptor->numDimensions();
2561 // Check numViews and numDimensions corresponds to the ones already serialized ...
2562 // numViews == flatBufferViewSizes.size();
2563 // foreach: numDimensions == flatBufferViewSizes[x].size();
2565 armnn::ViewsDescriptor viewsDescriptor(numViews, numDimensions);
2566 for(unsigned int vIdx = 0; vIdx < numViews; ++vIdx)
2568 for (unsigned int dIdx = 0; dIdx < numDimensions; ++dIdx)
2570 viewsDescriptor.SetViewSize(vIdx, dIdx, flatBufferViewSizes->Get(vIdx)->data()->Get(dIdx));
2571 viewsDescriptor.SetViewOriginCoord(vIdx, dIdx, flatBufferViewOrigins->Get(vIdx)->data()->Get(dIdx));
2575 auto layerName = GetLayerName(graph, layerIndex);
2576 IConnectableLayer* layer = m_Network->AddSplitterLayer(viewsDescriptor, layerName.c_str());
2578 // I could have as many outputs as views ...
2579 for(unsigned int vIdx = 0; vIdx < numViews; ++vIdx)
2581 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[vIdx]);
2582 layer->GetOutputSlot(vIdx).SetTensorInfo(outputTensorInfo);
2585 RegisterInputSlots(graph, layerIndex, layer);
2586 RegisterOutputSlots(graph, layerIndex, layer);
2589 armnn::LstmDescriptor IDeserializer::DeserializerImpl::GetLstmDescriptor(LstmDescriptorPtr lstmDescriptor)
2591 armnn::LstmDescriptor desc;
2593 desc.m_ActivationFunc = lstmDescriptor->activationFunc();
2594 desc.m_ClippingThresCell = lstmDescriptor->clippingThresCell();
2595 desc.m_ClippingThresProj = lstmDescriptor->clippingThresProj();
2596 desc.m_CifgEnabled = lstmDescriptor->cifgEnabled();
2597 desc.m_PeepholeEnabled = lstmDescriptor->peepholeEnabled();
2598 desc.m_ProjectionEnabled = lstmDescriptor->projectionEnabled();
2599 desc.m_LayerNormEnabled = lstmDescriptor->layerNormEnabled();
2604 void IDeserializer::DeserializerImpl::ParseLstm(GraphPtr graph, unsigned int layerIndex)
2606 CHECK_LAYERS(graph, 0, layerIndex);
2608 auto inputs = GetInputs(graph, layerIndex);
2609 CHECK_VALID_SIZE(inputs.size(), 3);
2611 auto outputs = GetOutputs(graph, layerIndex);
2612 CHECK_VALID_SIZE(outputs.size(), 4);
2614 auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_LstmLayer();
2615 auto layerName = GetLayerName(graph, layerIndex);
2616 auto flatBufferDescriptor = flatBufferLayer->descriptor();
2617 auto flatBufferInputParams = flatBufferLayer->inputParams();
2619 auto lstmDescriptor = GetLstmDescriptor(flatBufferDescriptor);
2621 armnn::LstmInputParams lstmInputParams;
2623 armnn::ConstTensor inputToForgetWeights = ToConstTensor(flatBufferInputParams->inputToForgetWeights());
2624 armnn::ConstTensor inputToCellWeights = ToConstTensor(flatBufferInputParams->inputToCellWeights());
2625 armnn::ConstTensor inputToOutputWeights = ToConstTensor(flatBufferInputParams->inputToOutputWeights());
2626 armnn::ConstTensor recurrentToForgetWeights = ToConstTensor(flatBufferInputParams->recurrentToForgetWeights());
2627 armnn::ConstTensor recurrentToCellWeights = ToConstTensor(flatBufferInputParams->recurrentToCellWeights());
2628 armnn::ConstTensor recurrentToOutputWeights = ToConstTensor(flatBufferInputParams->recurrentToOutputWeights());
2629 armnn::ConstTensor forgetGateBias = ToConstTensor(flatBufferInputParams->forgetGateBias());
2630 armnn::ConstTensor cellBias = ToConstTensor(flatBufferInputParams->cellBias());
2631 armnn::ConstTensor outputGateBias = ToConstTensor(flatBufferInputParams->outputGateBias());
2633 lstmInputParams.m_InputToForgetWeights = &inputToForgetWeights;
2634 lstmInputParams.m_InputToCellWeights = &inputToCellWeights;
2635 lstmInputParams.m_InputToOutputWeights = &inputToOutputWeights;
2636 lstmInputParams.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2637 lstmInputParams.m_RecurrentToCellWeights = &recurrentToCellWeights;
2638 lstmInputParams.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2639 lstmInputParams.m_ForgetGateBias = &forgetGateBias;
2640 lstmInputParams.m_CellBias = &cellBias;
2641 lstmInputParams.m_OutputGateBias = &outputGateBias;
2643 armnn::ConstTensor inputToInputWeights;
2644 armnn::ConstTensor recurrentToInputWeights;
2645 armnn::ConstTensor cellToInputWeights;
2646 armnn::ConstTensor inputGateBias;
2647 if (!lstmDescriptor.m_CifgEnabled)
2649 inputToInputWeights = ToConstTensor(flatBufferInputParams->inputToInputWeights());
2650 recurrentToInputWeights = ToConstTensor(flatBufferInputParams->recurrentToInputWeights());
2651 cellToInputWeights = ToConstTensor(flatBufferInputParams->cellToInputWeights());
2652 inputGateBias = ToConstTensor(flatBufferInputParams->inputGateBias());
2654 lstmInputParams.m_InputToInputWeights = &inputToInputWeights;
2655 lstmInputParams.m_RecurrentToInputWeights = &recurrentToInputWeights;
2656 lstmInputParams.m_CellToInputWeights = &cellToInputWeights;
2657 lstmInputParams.m_InputGateBias = &inputGateBias;
2660 armnn::ConstTensor projectionWeights;
2661 armnn::ConstTensor projectionBias;
2662 if (lstmDescriptor.m_ProjectionEnabled)
2664 projectionWeights = ToConstTensor(flatBufferInputParams->projectionWeights());
2665 projectionBias = ToConstTensor(flatBufferInputParams->projectionBias());
2667 lstmInputParams.m_ProjectionWeights = &projectionWeights;
2668 lstmInputParams.m_ProjectionBias = &projectionBias;
2671 armnn::ConstTensor cellToForgetWeights;
2672 armnn::ConstTensor cellToOutputWeights;
2673 if (lstmDescriptor.m_PeepholeEnabled)
2675 cellToForgetWeights = ToConstTensor(flatBufferInputParams->cellToForgetWeights());
2676 cellToOutputWeights = ToConstTensor(flatBufferInputParams->cellToOutputWeights());
2678 lstmInputParams.m_CellToForgetWeights = &cellToForgetWeights;
2679 lstmInputParams.m_CellToOutputWeights = &cellToOutputWeights;
2682 armnn::ConstTensor inputLayerNormWeights;
2683 armnn::ConstTensor forgetLayerNormWeights;
2684 armnn::ConstTensor cellLayerNormWeights;
2685 armnn::ConstTensor outputLayerNormWeights;
2686 if (lstmDescriptor.m_LayerNormEnabled)
2688 if (!lstmDescriptor.m_CifgEnabled)
2690 inputLayerNormWeights = ToConstTensor(flatBufferInputParams->inputLayerNormWeights());
2691 lstmInputParams.m_InputLayerNormWeights = &inputLayerNormWeights;
2693 forgetLayerNormWeights = ToConstTensor(flatBufferInputParams->forgetLayerNormWeights());
2694 cellLayerNormWeights = ToConstTensor(flatBufferInputParams->cellLayerNormWeights());
2695 outputLayerNormWeights = ToConstTensor(flatBufferInputParams->outputLayerNormWeights());
2697 lstmInputParams.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
2698 lstmInputParams.m_CellLayerNormWeights = &cellLayerNormWeights;
2699 lstmInputParams.m_OutputLayerNormWeights = &outputLayerNormWeights;
2702 IConnectableLayer* layer = m_Network->AddLstmLayer(lstmDescriptor, lstmInputParams, layerName.c_str());
2704 armnn::TensorInfo outputTensorInfo1 = ToTensorInfo(outputs[0]);
2705 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo1);
2707 armnn::TensorInfo outputTensorInfo2 = ToTensorInfo(outputs[1]);
2708 layer->GetOutputSlot(1).SetTensorInfo(outputTensorInfo2);
2710 armnn::TensorInfo outputTensorInfo3 = ToTensorInfo(outputs[2]);
2711 layer->GetOutputSlot(2).SetTensorInfo(outputTensorInfo3);
2713 armnn::TensorInfo outputTensorInfo4 = ToTensorInfo(outputs[3]);
2714 layer->GetOutputSlot(3).SetTensorInfo(outputTensorInfo4);
2716 RegisterInputSlots(graph, layerIndex, layer);
2717 RegisterOutputSlots(graph, layerIndex, layer);
2720 armnn::QLstmDescriptor IDeserializer::DeserializerImpl::GetQLstmDescriptor(QLstmDescriptorPtr qLstmDescriptor)
2722 armnn::QLstmDescriptor desc;
2724 desc.m_CifgEnabled = qLstmDescriptor->cifgEnabled();
2725 desc.m_PeepholeEnabled = qLstmDescriptor->peepholeEnabled();
2726 desc.m_ProjectionEnabled = qLstmDescriptor->projectionEnabled();
2727 desc.m_LayerNormEnabled = qLstmDescriptor->layerNormEnabled();
2729 desc.m_CellClip = qLstmDescriptor->cellClip();
2730 desc.m_ProjectionClip = qLstmDescriptor->projectionClip();
2732 desc.m_InputIntermediateScale = qLstmDescriptor->inputIntermediateScale();
2733 desc.m_ForgetIntermediateScale = qLstmDescriptor->forgetIntermediateScale();
2734 desc.m_CellIntermediateScale = qLstmDescriptor->cellIntermediateScale();
2735 desc.m_OutputIntermediateScale = qLstmDescriptor->outputIntermediateScale();
2737 desc.m_HiddenStateScale = qLstmDescriptor->hiddenStateScale();
2738 desc.m_HiddenStateZeroPoint = qLstmDescriptor->hiddenStateZeroPoint();
2743 void IDeserializer::DeserializerImpl::ParseQLstm(GraphPtr graph, unsigned int layerIndex)
2745 CHECK_LAYERS(graph, 0, layerIndex);
2747 auto inputs = GetInputs(graph, layerIndex);
2748 CHECK_VALID_SIZE(inputs.size(), 3);
2750 auto outputs = GetOutputs(graph, layerIndex);
2751 CHECK_VALID_SIZE(outputs.size(), 3);
2753 auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_QLstmLayer();
2754 auto layerName = GetLayerName(graph, layerIndex);
2755 auto flatBufferDescriptor = flatBufferLayer->descriptor();
2756 auto flatBufferInputParams = flatBufferLayer->inputParams();
2758 auto qLstmDescriptor = GetQLstmDescriptor(flatBufferDescriptor);
2759 armnn::LstmInputParams qLstmInputParams;
2762 armnn::ConstTensor inputToForgetWeights = ToConstTensor(flatBufferInputParams->inputToForgetWeights());
2763 armnn::ConstTensor inputToCellWeights = ToConstTensor(flatBufferInputParams->inputToCellWeights());
2764 armnn::ConstTensor inputToOutputWeights = ToConstTensor(flatBufferInputParams->inputToOutputWeights());
2765 armnn::ConstTensor recurrentToForgetWeights = ToConstTensor(flatBufferInputParams->recurrentToForgetWeights());
2766 armnn::ConstTensor recurrentToCellWeights = ToConstTensor(flatBufferInputParams->recurrentToCellWeights());
2767 armnn::ConstTensor recurrentToOutputWeights = ToConstTensor(flatBufferInputParams->recurrentToOutputWeights());
2768 armnn::ConstTensor forgetGateBias = ToConstTensor(flatBufferInputParams->forgetGateBias());
2769 armnn::ConstTensor cellBias = ToConstTensor(flatBufferInputParams->cellBias());
2770 armnn::ConstTensor outputGateBias = ToConstTensor(flatBufferInputParams->outputGateBias());
2772 qLstmInputParams.m_InputToForgetWeights = &inputToForgetWeights;
2773 qLstmInputParams.m_InputToCellWeights = &inputToCellWeights;
2774 qLstmInputParams.m_InputToOutputWeights = &inputToOutputWeights;
2775 qLstmInputParams.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2776 qLstmInputParams.m_RecurrentToCellWeights = &recurrentToCellWeights;
2777 qLstmInputParams.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2778 qLstmInputParams.m_ForgetGateBias = &forgetGateBias;
2779 qLstmInputParams.m_CellBias = &cellBias;
2780 qLstmInputParams.m_OutputGateBias = &outputGateBias;
2782 // Optional CIFG params
2783 armnn::ConstTensor inputToInputWeights;
2784 armnn::ConstTensor recurrentToInputWeights;
2785 armnn::ConstTensor inputGateBias;
2787 if (!qLstmDescriptor.m_CifgEnabled)
2789 inputToInputWeights = ToConstTensor(flatBufferInputParams->inputToInputWeights());
2790 recurrentToInputWeights = ToConstTensor(flatBufferInputParams->recurrentToInputWeights());
2791 inputGateBias = ToConstTensor(flatBufferInputParams->inputGateBias());
2793 qLstmInputParams.m_InputToInputWeights = &inputToInputWeights;
2794 qLstmInputParams.m_RecurrentToInputWeights = &recurrentToInputWeights;
2795 qLstmInputParams.m_InputGateBias = &inputGateBias;
2798 // Optional projection params
2799 armnn::ConstTensor projectionWeights;
2800 armnn::ConstTensor projectionBias;
2802 if (qLstmDescriptor.m_ProjectionEnabled)
2804 projectionWeights = ToConstTensor(flatBufferInputParams->projectionWeights());
2805 projectionBias = ToConstTensor(flatBufferInputParams->projectionBias());
2807 qLstmInputParams.m_ProjectionWeights = &projectionWeights;
2808 qLstmInputParams.m_ProjectionBias = &projectionBias;
2811 // Optional peephole params
2812 armnn::ConstTensor cellToInputWeights;
2813 armnn::ConstTensor cellToForgetWeights;
2814 armnn::ConstTensor cellToOutputWeights;
2816 if (qLstmDescriptor.m_PeepholeEnabled)
2818 if (!qLstmDescriptor.m_CifgEnabled)
2820 cellToInputWeights = ToConstTensor(flatBufferInputParams->cellToInputWeights());
2821 qLstmInputParams.m_CellToInputWeights = &cellToInputWeights;
2824 cellToForgetWeights = ToConstTensor(flatBufferInputParams->cellToForgetWeights());
2825 cellToOutputWeights = ToConstTensor(flatBufferInputParams->cellToOutputWeights());
2827 qLstmInputParams.m_CellToForgetWeights = &cellToForgetWeights;
2828 qLstmInputParams.m_CellToOutputWeights = &cellToOutputWeights;
2831 // Optional layer norm params
2832 armnn::ConstTensor inputLayerNormWeights;
2833 armnn::ConstTensor forgetLayerNormWeights;
2834 armnn::ConstTensor cellLayerNormWeights;
2835 armnn::ConstTensor outputLayerNormWeights;
2837 if (qLstmDescriptor.m_LayerNormEnabled)
2839 if (!qLstmDescriptor.m_CifgEnabled)
2841 inputLayerNormWeights = ToConstTensor(flatBufferInputParams->inputLayerNormWeights());
2842 qLstmInputParams.m_InputLayerNormWeights = &inputLayerNormWeights;
2845 forgetLayerNormWeights = ToConstTensor(flatBufferInputParams->forgetLayerNormWeights());
2846 cellLayerNormWeights = ToConstTensor(flatBufferInputParams->cellLayerNormWeights());
2847 outputLayerNormWeights = ToConstTensor(flatBufferInputParams->outputLayerNormWeights());
2849 qLstmInputParams.m_ForgetLayerNormWeights = &forgetLayerNormWeights;
2850 qLstmInputParams.m_CellLayerNormWeights = &cellLayerNormWeights;
2851 qLstmInputParams.m_OutputLayerNormWeights = &outputLayerNormWeights;
2854 IConnectableLayer* layer = m_Network->AddQLstmLayer(qLstmDescriptor, qLstmInputParams, layerName.c_str());
2856 armnn::TensorInfo outputStateOutInfo = ToTensorInfo(outputs[0]);
2857 layer->GetOutputSlot(0).SetTensorInfo(outputStateOutInfo);
2859 armnn::TensorInfo cellStateOutInfo = ToTensorInfo(outputs[1]);
2860 layer->GetOutputSlot(1).SetTensorInfo(cellStateOutInfo);
2862 armnn::TensorInfo outputInfo = ToTensorInfo(outputs[2]);
2863 layer->GetOutputSlot(2).SetTensorInfo(outputInfo);
2865 RegisterInputSlots(graph, layerIndex, layer);
2866 RegisterOutputSlots(graph, layerIndex, layer);
2869 void IDeserializer::DeserializerImpl::ParseQuantizedLstm(GraphPtr graph, unsigned int layerIndex)
2871 CHECK_LAYERS(graph, 0, layerIndex);
2873 auto inputs = GetInputs(graph, layerIndex);
2874 CHECK_VALID_SIZE(inputs.size(), 3);
2876 auto outputs = GetOutputs(graph, layerIndex);
2877 CHECK_VALID_SIZE(outputs.size(), 2);
2879 auto flatBufferLayer = graph->layers()->Get(layerIndex)->layer_as_QuantizedLstmLayer();
2880 auto layerName = GetLayerName(graph, layerIndex);
2881 auto flatBufferInputParams = flatBufferLayer->inputParams();
2883 armnn::QuantizedLstmInputParams lstmInputParams;
2885 armnn::ConstTensor inputToInputWeights = ToConstTensor(flatBufferInputParams->inputToInputWeights());
2886 armnn::ConstTensor inputToForgetWeights = ToConstTensor(flatBufferInputParams->inputToForgetWeights());
2887 armnn::ConstTensor inputToCellWeights = ToConstTensor(flatBufferInputParams->inputToCellWeights());
2888 armnn::ConstTensor inputToOutputWeights = ToConstTensor(flatBufferInputParams->inputToOutputWeights());
2889 armnn::ConstTensor recurrentToInputWeights = ToConstTensor(flatBufferInputParams->recurrentToInputWeights());
2890 armnn::ConstTensor recurrentToForgetWeights = ToConstTensor(flatBufferInputParams->recurrentToForgetWeights());
2891 armnn::ConstTensor recurrentToCellWeights = ToConstTensor(flatBufferInputParams->recurrentToCellWeights());
2892 armnn::ConstTensor recurrentToOutputWeights = ToConstTensor(flatBufferInputParams->recurrentToOutputWeights());
2893 armnn::ConstTensor inputGateBias = ToConstTensor(flatBufferInputParams->inputGateBias());
2894 armnn::ConstTensor forgetGateBias = ToConstTensor(flatBufferInputParams->forgetGateBias());
2895 armnn::ConstTensor cellBias = ToConstTensor(flatBufferInputParams->cellBias());
2896 armnn::ConstTensor outputGateBias = ToConstTensor(flatBufferInputParams->outputGateBias());
2898 lstmInputParams.m_InputToInputWeights = &inputToInputWeights;
2899 lstmInputParams.m_InputToForgetWeights = &inputToForgetWeights;
2900 lstmInputParams.m_InputToCellWeights = &inputToCellWeights;
2901 lstmInputParams.m_InputToOutputWeights = &inputToOutputWeights;
2902 lstmInputParams.m_RecurrentToInputWeights = &recurrentToInputWeights;
2903 lstmInputParams.m_RecurrentToForgetWeights = &recurrentToForgetWeights;
2904 lstmInputParams.m_RecurrentToCellWeights = &recurrentToCellWeights;
2905 lstmInputParams.m_RecurrentToOutputWeights = &recurrentToOutputWeights;
2906 lstmInputParams.m_InputGateBias = &inputGateBias;
2907 lstmInputParams.m_ForgetGateBias = &forgetGateBias;
2908 lstmInputParams.m_CellBias = &cellBias;
2909 lstmInputParams.m_OutputGateBias = &outputGateBias;
2911 IConnectableLayer* layer = m_Network->AddQuantizedLstmLayer(lstmInputParams, layerName.c_str());
2913 armnn::TensorInfo outputTensorInfo1 = ToTensorInfo(outputs[0]);
2914 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo1);
2916 armnn::TensorInfo outputTensorInfo2 = ToTensorInfo(outputs[1]);
2917 layer->GetOutputSlot(1).SetTensorInfo(outputTensorInfo2);
2919 RegisterInputSlots(graph, layerIndex, layer);
2920 RegisterOutputSlots(graph, layerIndex, layer);
2923 void IDeserializer::DeserializerImpl::ParseDequantize(GraphPtr graph, unsigned int layerIndex)
2925 CHECK_LAYERS(graph, 0, layerIndex);
2927 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2928 CHECK_VALID_SIZE(inputs.size(), 1);
2930 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2931 CHECK_VALID_SIZE(outputs.size(), 1);
2933 const std::string layerName = GetLayerName(graph, layerIndex);
2934 IConnectableLayer* layer = m_Network->AddDequantizeLayer(layerName.c_str());
2936 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2937 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2939 RegisterInputSlots(graph, layerIndex, layer);
2940 RegisterOutputSlots(graph, layerIndex, layer);
2943 void IDeserializer::DeserializerImpl::ParseMerge(GraphPtr graph, unsigned int layerIndex)
2945 CHECK_LAYERS(graph, 0, layerIndex);
2947 TensorRawPtrVector inputs = GetInputs(graph, layerIndex);
2948 CHECK_VALID_SIZE(inputs.size(), 2);
2950 TensorRawPtrVector outputs = GetOutputs(graph, layerIndex);
2951 CHECK_VALID_SIZE(outputs.size(), 1);
2953 const std::string layerName = GetLayerName(graph, layerIndex);
2954 IConnectableLayer* layer = m_Network->AddMergeLayer(layerName.c_str());
2956 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
2957 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
2959 RegisterInputSlots(graph, layerIndex, layer);
2960 RegisterOutputSlots(graph, layerIndex, layer);
2963 void IDeserializer::DeserializerImpl::ParseSwitch(GraphPtr graph, unsigned int layerIndex)
2965 CHECK_LAYERS(graph, 0, layerIndex);
2966 auto inputs = GetInputs(graph, layerIndex);
2968 CHECK_VALID_SIZE(inputs.size(), 2);
2970 auto outputs = GetOutputs(graph, layerIndex);
2971 CHECK_VALID_SIZE(outputs.size(), 2);
2973 auto layerName = GetLayerName(graph, layerIndex);
2974 IConnectableLayer* layer = m_Network->AddSwitchLayer(layerName.c_str());
2976 armnn::TensorInfo output0TensorInfo = ToTensorInfo(outputs[0]);
2977 layer->GetOutputSlot(0).SetTensorInfo(output0TensorInfo);
2979 armnn::TensorInfo output1TensorInfo = ToTensorInfo(outputs[1]);
2980 layer->GetOutputSlot(1).SetTensorInfo(output1TensorInfo);
2982 RegisterInputSlots(graph, layerIndex, layer);
2983 RegisterOutputSlots(graph, layerIndex, layer);
2986 void IDeserializer::DeserializerImpl::ParsePrelu(GraphPtr graph, unsigned int layerIndex)
2988 CHECK_LAYERS(graph, 0, layerIndex);
2989 auto inputs = GetInputs(graph, layerIndex);
2991 CHECK_VALID_SIZE(inputs.size(), 2);
2993 auto outputs = GetOutputs(graph, layerIndex);
2994 CHECK_VALID_SIZE(outputs.size(), 1);
2996 auto layerName = GetLayerName(graph, layerIndex);
2997 IConnectableLayer* layer = m_Network->AddPreluLayer(layerName.c_str());
2999 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
3000 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
3002 RegisterInputSlots(graph, layerIndex, layer);
3003 RegisterOutputSlots(graph, layerIndex, layer);
3006 void IDeserializer::DeserializerImpl::ParseTranspose(GraphPtr graph, unsigned int layerIndex)
3008 CHECK_LAYERS(graph, 0, layerIndex);
3010 auto dimsMapping = graph->layers()->Get(layerIndex)->layer_as_TransposeLayer()->descriptor()->dimMappings();
3012 auto inputs = GetInputs(graph, layerIndex);
3013 CHECK_VALID_SIZE(inputs.size(), 1);
3015 auto outputs = GetOutputs(graph, layerIndex);
3016 CHECK_VALID_SIZE(outputs.size(), 1);
3017 auto outputInfo = ToTensorInfo(outputs[0]);
3019 auto layerName = GetLayerName(graph, layerIndex);
3020 const armnn::TransposeDescriptor descriptor(armnn::PermutationVector(dimsMapping->data(), dimsMapping->Length()));
3022 IConnectableLayer* layer = m_Network->AddTransposeLayer(descriptor, layerName.c_str());
3023 layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
3025 RegisterInputSlots(graph, layerIndex, layer);
3026 RegisterOutputSlots(graph, layerIndex, layer);
3029 void IDeserializer::DeserializerImpl::ParseTransposeConvolution2d(GraphPtr graph, unsigned int layerIndex)
3031 CHECK_LAYERS(graph, 0, layerIndex);
3033 auto inputs = GetInputs(graph, layerIndex);
3034 CHECK_VALID_SIZE(inputs.size(), 1);
3036 auto outputs = GetOutputs(graph, layerIndex);
3037 CHECK_VALID_SIZE(outputs.size(), 1);
3039 auto serializerLayer = graph->layers()->Get(layerIndex)->layer_as_TransposeConvolution2dLayer();
3040 auto layerName = GetLayerName(graph, layerIndex);
3041 auto serializerDescriptor = serializerLayer->descriptor();
3043 armnn::TransposeConvolution2dDescriptor descriptor;
3044 descriptor.m_PadLeft = serializerDescriptor->padLeft();
3045 descriptor.m_PadRight = serializerDescriptor->padRight();
3046 descriptor.m_PadTop = serializerDescriptor->padTop();
3047 descriptor.m_PadBottom = serializerDescriptor->padBottom();
3048 descriptor.m_StrideX = serializerDescriptor->strideX();
3049 descriptor.m_StrideY = serializerDescriptor->strideY();;
3050 descriptor.m_BiasEnabled = serializerDescriptor->biasEnabled();;
3051 descriptor.m_DataLayout = ToDataLayout(serializerDescriptor->dataLayout());
3054 armnn::ConstTensor weights = ToConstTensor(serializerLayer->weights());
3055 armnn::Optional<armnn::ConstTensor> optionalBiases;
3056 if (descriptor.m_BiasEnabled)
3058 armnn::ConstTensor biases = ToConstTensor(serializerLayer->biases());
3059 optionalBiases = armnn::MakeOptional<armnn::ConstTensor>(biases);
3062 IConnectableLayer* layer = m_Network->AddTransposeConvolution2dLayer(descriptor,
3067 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
3068 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
3070 RegisterInputSlots(graph, layerIndex, layer);
3071 RegisterOutputSlots(graph, layerIndex, layer);
3074 void IDeserializer::DeserializerImpl::ParseStack(GraphPtr graph, unsigned int layerIndex)
3076 CHECK_LAYERS(graph, 0, layerIndex);
3077 auto inputs = GetInputs(graph, layerIndex);
3079 auto outputs = GetOutputs(graph, layerIndex);
3080 CHECK_VALID_SIZE(outputs.size(), 1);
3082 auto flatBufferDescriptor = graph->layers()->Get(layerIndex)->layer_as_StackLayer()->descriptor();
3083 unsigned int axis = flatBufferDescriptor->axis();
3084 unsigned int numInputs = flatBufferDescriptor->numInputs();
3085 CHECK_VALID_SIZE(inputs.size(), numInputs);
3087 auto flatBufferInputShape = flatBufferDescriptor->inputShape();
3088 std::vector<uint32_t> vectorInputShape(flatBufferInputShape->begin(),
3089 flatBufferInputShape->begin() + flatBufferInputShape->size());
3091 TensorShape inputShape(static_cast<unsigned int>(vectorInputShape.size()), vectorInputShape.data());
3092 armnn::StackDescriptor descriptor(axis, numInputs, inputShape);
3094 for (unsigned int i=0; i<inputs.size(); ++i)
3096 armnn::TensorShape inputShape = ToTensorInfo(inputs[i]).GetShape();
3097 if (descriptor.m_InputShape != inputShape)
3099 std::stringstream ss;
3100 ss << "Shape of input "
3104 << " does not equal defined input shape "
3105 << descriptor.m_InputShape
3107 << CHECK_LOCATION().AsString();
3108 throw ParseException(ss.str());
3112 auto layerName = GetLayerName(graph, layerIndex);
3113 IConnectableLayer* layer = m_Network->AddStackLayer(descriptor, layerName.c_str());
3115 armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
3116 layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
3118 RegisterInputSlots(graph, layerIndex, layer);
3119 RegisterOutputSlots(graph, layerIndex, layer);
3122 void IDeserializer::DeserializerImpl::ParseStandIn(GraphPtr graph, unsigned int layerIndex)
3124 CHECK_LAYERS(graph, 0, layerIndex);
3126 auto inputs = GetInputs(graph, layerIndex);
3127 auto outputs = GetOutputs(graph, layerIndex);
3129 auto fbLayer = graph->layers()->Get(layerIndex)->layer_as_StandInLayer();
3130 auto fbDescriptor = fbLayer->descriptor();
3132 armnn::StandInDescriptor descriptor;
3133 descriptor.m_NumInputs = fbDescriptor->numInputs();
3134 descriptor.m_NumOutputs = fbDescriptor->numOutputs();
3136 CHECK_VALID_SIZE(inputs.size(), descriptor.m_NumInputs);
3137 CHECK_VALID_SIZE(outputs.size(), descriptor.m_NumOutputs);
3139 const std::string layerName = GetLayerName(graph, layerIndex);
3140 armnn::IConnectableLayer* layer = m_Network->AddStandInLayer(descriptor, layerName.c_str());
3142 for (unsigned int i = 0u; i < descriptor.m_NumOutputs; ++i)
3144 armnn::TensorInfo outputInfo = ToTensorInfo(outputs[i]);
3145 layer->GetOutputSlot(i).SetTensorInfo(outputInfo);
3148 RegisterInputSlots(graph, layerIndex, layer);
3149 RegisterOutputSlots(graph, layerIndex, layer);
3152 } // namespace armnnDeserializer