26 #include <schema_generated.h> 28 #include <flatbuffers/flexbuffers.h> 30 #include <boost/format.hpp> 31 #include <boost/numeric/conversion/cast.hpp> 39 #define ARMNN_THROW_PARSE_EXCEPTION(msg) \ 41 throw armnn::ParseException( static_cast<const std::stringstream&>( std::stringstream() << msg \ 43 << CHECK_LOCATION().AsString()).str()); \ 46 using namespace armnn;
53 const uint32_t VIRTUAL_OPERATOR_ID = std::numeric_limits<uint32_t>::max();
59 if (model.get() ==
nullptr)
63 boost::format(
"%1% was called with invalid (null) model. " 64 "Possible reason is that the model is not yet loaded and Unpack(ed). " 65 "subgraph:%2% at %3%") %
70 else if (subgraphIndex >= model->subgraphs.size())
74 boost::format(
"%1% was called with an invalid subgraph index. " 75 "subgraph:%2% at %3%") %
82 #define CHECK_SUBGRAPH(MODEL, SUBGRAPH_INDEX) \ 83 CheckSubgraph(MODEL, SUBGRAPH_INDEX, CHECK_LOCATION()) 90 if (model.get() ==
nullptr)
94 boost::format(
"%1% was called with invalid (null) model. " 95 "Possible reason is that the model is not yet loaded and Unpack(ed). " 96 "subgraph:%2% operator:%3% at %4%") %
102 else if (subgraphIndex >= model->subgraphs.size())
106 boost::format(
"%1% was called with an invalid subgraph index. " 107 "subgraph:%2% operator:%3% at %4%") %
113 else if (operatorIndex >= model->subgraphs[subgraphIndex]->operators.size() &&
114 operatorIndex != VIRTUAL_OPERATOR_ID)
118 boost::format(
"%1% was called with an invalid operator index. " 119 "subgraph:%2% operator:%3% at %4%") %
127 #define CHECK_MODEL(MODEL, SUBGRAPH_INDEX, OPERATOR_INDEX) \ 128 CheckModel(MODEL, SUBGRAPH_INDEX, OPERATOR_INDEX, CHECK_LOCATION()) 131 size_t subgraphIndex,
137 ARMNN_ASSERT_MSG(model.get() !=
nullptr,
"Expecting a valid model in this function");
141 ARMNN_ASSERT_MSG(subgraphIndex < model->subgraphs.size(),
"Expecting a valid subgraph index");
144 if (tensorIndex >= model->subgraphs[subgraphIndex]->tensors.size())
148 boost::format(
"%1% was called with an invalid tensor index. " 149 "subgraph:%2% tensor:%3% at %4%") %
157 #define CHECK_TENSOR(MODEL, SUBGRAPH_INDEX, TENSOR_INDEX) \ 158 CheckTensor(MODEL, SUBGRAPH_INDEX, TENSOR_INDEX, CHECK_LOCATION()) 163 if (rawPtr ==
nullptr)
167 boost::format(
"%1% was called with a null tensor pointer. " 175 #define CHECK_TENSOR_PTR(TENSOR_PTR) \ 176 CheckTensorPtr(TENSOR_PTR, CHECK_LOCATION()) 182 if (model.get() ==
nullptr)
186 boost::format(
"%1% was called with invalid (null) model. " 187 "Possible reason is that the model is not yet loaded and Unpack(ed). " 188 "buffer:%2% at %3%") %
193 else if (bufferIndex >= model->buffers.size())
197 boost::format(
"%1% was called with an invalid buffer index. " 198 "buffer index:%2% at %3%") %
203 else if (model->buffers[bufferIndex].get() ==
nullptr)
207 boost::format(
"The buffer #%1% is null. %3%") %
213 #define CHECK_BUFFER(MODEL, BUFFER_INDEX) \ 214 CheckBuffer(MODEL, BUFFER_INDEX, CHECK_LOCATION()) 216 void CheckBufferSize(TfLiteParser::BufferRawPtr bufferPtr,
221 if (bufferPtr ==
nullptr)
225 boost::format(
"BufferPtr is null for buffer:%1%. %2%") %
232 std::stringstream ss;
233 ss <<
"Buffer #" << bufferId <<
" has " << bufferPtr->data.size() <<
" bytes. " 234 <<
"For tensor: " << tensorInfo.
GetShape()
235 <<
" expecting: " << tensorInfo.
GetNumBytes() <<
" bytes and " 241 #define CHECK_BUFFER_SIZE(BUFFER_PTR, TENSOR_INFO, BUFFER_ID) \ 242 CheckBufferSize(BUFFER_PTR, TENSOR_INFO, BUFFER_ID, CHECK_LOCATION()) 246 switch(activationType)
248 case tflite::ActivationFunctionType_NONE:
249 case tflite::ActivationFunctionType_RELU:
250 case tflite::ActivationFunctionType_RELU6:
251 case tflite::ActivationFunctionType_TANH:
262 #define CHECK_SUPPORTED_FUSED_ACTIVATION(OPTION, SUBGRAPH_INDEX, OPERATOR_INDEX) \ 264 if (IsActivationSupported(OPTION->fused_activation_function) == false) \ 266 throw ParseException( \ 268 boost::format("TfLite parser doesn't suppport fused activation: " \ 269 "%1%/%2% in %3% subgraph:%4% operator:%5% at %6%") % \ 270 OPTION->fused_activation_function % \ 271 tflite::EnumNameActivationFunctionType(\ 272 OPTION->fused_activation_function) % \ 276 CHECK_LOCATION().FileLine())); \ 281 std::vector<unsigned int> AsUnsignedVector(
const std::vector<int32_t> & in)
283 std::vector<unsigned int> result;
284 result.reserve(in.size());
296 uint32_t& paddingFront,
297 uint32_t& paddingBack,
298 tflite::Padding padding)
302 if (padding == tflite::Padding_SAME)
304 uint32_t outputSize = (inputSize + stride - 1) / stride;
305 uint32_t dilatedSize = filterSize + (dilation - 1) * (filterSize - 1);
306 uint32_t temp = (outputSize - 1) * stride + dilatedSize;
307 if (temp > inputSize)
309 paddingFront = (temp - inputSize) / 2;
310 paddingBack = (temp - inputSize) - paddingFront;
316 const std::vector<unsigned int>& shapes,
318 const bool outputTensor =
false)
323 switch (tensorPtr->type)
325 case tflite::TensorType_UINT8:
328 case tflite::TensorType_FLOAT32:
331 case tflite::TensorType_INT8:
332 if (tensorPtr->quantization->zero_point.size() == 1)
343 case tflite::TensorType_INT16:
346 case tflite::TensorType_INT32:
355 boost::format(
"Unsupported data type %1% = %2% for tensor: %3%. %4%") %
357 tflite::EnumNameTensorType(tensorPtr->type) %
362 std::vector<unsigned int> safeShape = shapes;
363 bool isDynamic =
false;
364 if (safeShape.size() == 0)
366 safeShape.push_back(1);
373 float quantizationScale = 0.0f;
374 int32_t quantizationOffset = 0;
376 if (tensorPtr->quantization.get())
378 if (tensorPtr->quantization->scale.size() <= 1)
383 if (tensorPtr->quantization->scale.size() == 1)
385 quantizationScale = tensorPtr->quantization->scale[0];
387 if (tensorPtr->quantization->zero_point.size() == 1)
394 TensorShape tensorShape(boost::numeric_cast<unsigned int>(safeShape.size()),
408 std::vector<float> quantizationScales;
409 std::vector<int32_t> quantizationOffsets;
412 std::copy(tensorPtr->quantization->scale.begin(),
413 tensorPtr->quantization->scale.end(),
414 std::back_inserter(quantizationScales));
417 TensorShape tensorShape(boost::numeric_cast<unsigned int>(safeShape.size()),
426 dimensionMappings[boost::numeric_cast<unsigned int>(
427 tensorPtr->quantization->quantized_dimension)]);
433 TensorShape tensorShape(boost::numeric_cast<unsigned int>(safeShape.size()),
450 auto const & dimensions = AsUnsignedVector(tensorPtr->shape);
451 return ToTensorInfo(tensorPtr, dimensions, dimensionMappings);
455 const bool outputTensor)
457 auto const & dimensions = AsUnsignedVector(tensorPtr->shape);
459 return ToTensorInfo(tensorPtr, dimensions, dimensionMappings, outputTensor);
463 std::pair<armnn::ConstTensor, std::unique_ptr<T[]>>
464 CreateConstTensorImpl(TfLiteParser::BufferRawPtr bufferPtr,
473 boost::format(
"Buffer for buffer:%1% is null") % tensorPtr->buffer).c_str());
481 reinterpret_cast<const T*
>(bufferPtr->data.data()), data.get(),
sizeof(T));
485 ::memcpy(data.get(), bufferPtr->data.data(), tensorInfo.
GetNumBytes());
488 return std::make_pair(
ConstTensor(tensorInfo, data.get()), std::move(data));
501 if (actualSize != expected.size())
506 for (
unsigned int i = 0u; i < actualSize; i++)
508 if (expected[i] < 0 ||
509 actual[i] != static_cast<unsigned int>(expected[i]))
518 void CheckMatchingQuantization(
const TensorInfo& first,
520 const std::string& descName,
521 std::string
const& firstName,
522 std::string
const& secondName)
534 if (firstDataType != secondDataType)
537 " must be of the same quantized type, " +
545 " must have the same quantization space, " +
557 , m_Network(nullptr, nullptr)
558 , m_ParserFunctions(tflite::BuiltinOperator_MAX+1, &
TfLiteParser::ParseUnsupportedOperator)
561 m_ParserFunctions[tflite::BuiltinOperator_ADD] = &TfLiteParser::ParseAdd;
562 m_ParserFunctions[tflite::BuiltinOperator_AVERAGE_POOL_2D] = &TfLiteParser::ParseAveragePool2D;
563 m_ParserFunctions[tflite::BuiltinOperator_BATCH_TO_SPACE_ND] = &TfLiteParser::ParseBatchToSpaceND;
564 m_ParserFunctions[tflite::BuiltinOperator_CONCATENATION] = &TfLiteParser::ParseConcatenation;
565 m_ParserFunctions[tflite::BuiltinOperator_CONV_2D] = &TfLiteParser::ParseConv2D;
566 m_ParserFunctions[tflite::BuiltinOperator_CUSTOM] = &TfLiteParser::ParseCustomOperator;
567 m_ParserFunctions[tflite::BuiltinOperator_DEPTHWISE_CONV_2D] = &TfLiteParser::ParseDepthwiseConv2D;
568 m_ParserFunctions[tflite::BuiltinOperator_DEQUANTIZE] = &TfLiteParser::ParseDequantize;
569 m_ParserFunctions[tflite::BuiltinOperator_EXP] = &TfLiteParser::ParseExp;
570 m_ParserFunctions[tflite::BuiltinOperator_FULLY_CONNECTED] = &TfLiteParser::ParseFullyConnected;
571 m_ParserFunctions[tflite::BuiltinOperator_HARD_SWISH] = &TfLiteParser::ParseHardSwish;
572 m_ParserFunctions[tflite::BuiltinOperator_LEAKY_RELU] = &TfLiteParser::ParseLeakyRelu;
573 m_ParserFunctions[tflite::BuiltinOperator_LOGISTIC] = &TfLiteParser::ParseLogistic;
574 m_ParserFunctions[tflite::BuiltinOperator_L2_NORMALIZATION] = &TfLiteParser::ParseL2Normalization;
575 m_ParserFunctions[tflite::BuiltinOperator_MAX_POOL_2D] = &TfLiteParser::ParseMaxPool2D;
576 m_ParserFunctions[tflite::BuiltinOperator_MAXIMUM] = &TfLiteParser::ParseMaximum;
577 m_ParserFunctions[tflite::BuiltinOperator_MEAN] = &TfLiteParser::ParseMean;
578 m_ParserFunctions[tflite::BuiltinOperator_MINIMUM] = &TfLiteParser::ParseMinimum;
579 m_ParserFunctions[tflite::BuiltinOperator_MUL] = &TfLiteParser::ParseMul;
580 m_ParserFunctions[tflite::BuiltinOperator_NEG] = &TfLiteParser::ParseNeg;
581 m_ParserFunctions[tflite::BuiltinOperator_PACK] = &TfLiteParser::ParsePack;
582 m_ParserFunctions[tflite::BuiltinOperator_PAD] = &TfLiteParser::ParsePad;
583 m_ParserFunctions[tflite::BuiltinOperator_QUANTIZE] = &TfLiteParser::ParseQuantize;
584 m_ParserFunctions[tflite::BuiltinOperator_RELU] = &TfLiteParser::ParseRelu;
585 m_ParserFunctions[tflite::BuiltinOperator_RELU6] = &TfLiteParser::ParseRelu6;
586 m_ParserFunctions[tflite::BuiltinOperator_RESHAPE] = &TfLiteParser::ParseReshape;
587 m_ParserFunctions[tflite::BuiltinOperator_RESIZE_BILINEAR] = &TfLiteParser::ParseResizeBilinear;
588 m_ParserFunctions[tflite::BuiltinOperator_RESIZE_NEAREST_NEIGHBOR] = &TfLiteParser::ParseResizeNearestNeighbor;
589 m_ParserFunctions[tflite::BuiltinOperator_SLICE] = &TfLiteParser::ParseSlice;
590 m_ParserFunctions[tflite::BuiltinOperator_SOFTMAX] = &TfLiteParser::ParseSoftmax;
591 m_ParserFunctions[tflite::BuiltinOperator_SPACE_TO_BATCH_ND] = &TfLiteParser::ParseSpaceToBatchND;
592 m_ParserFunctions[tflite::BuiltinOperator_SPLIT] = &TfLiteParser::ParseSplit;
593 m_ParserFunctions[tflite::BuiltinOperator_SPLIT_V] = &TfLiteParser::ParseSplitV;
594 m_ParserFunctions[tflite::BuiltinOperator_SQUEEZE] = &TfLiteParser::ParseSqueeze;
595 m_ParserFunctions[tflite::BuiltinOperator_STRIDED_SLICE] = &TfLiteParser::ParseStridedSlice;
596 m_ParserFunctions[tflite::BuiltinOperator_SUB] = &TfLiteParser::ParseSub;
597 m_ParserFunctions[tflite::BuiltinOperator_TANH] = &TfLiteParser::ParseTanH;
598 m_ParserFunctions[tflite::BuiltinOperator_TRANSPOSE] = &TfLiteParser::ParseTranspose;
599 m_ParserFunctions[tflite::BuiltinOperator_TRANSPOSE_CONV] = &TfLiteParser::ParseTransposeConv;
600 m_ParserFunctions[tflite::BuiltinOperator_UNPACK] = &TfLiteParser::ParseUnpack;
601 m_ParserFunctions[tflite::BuiltinOperator_DIV] = &TfLiteParser::ParseDiv;
603 m_CustomParserFunctions[
"TFLite_Detection_PostProcess"] = &TfLiteParser::ParseDetectionPostProcess;
606 void TfLiteParser::ResetParser()
610 m_SubgraphConnections.clear();
613 void TfLiteParser::AddBroadcastReshapeLayer(
size_t subgraphIndex,
614 size_t operatorIndex,
617 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
620 const auto & subgraphPtr = m_Model->subgraphs[subgraphIndex];
621 const auto & operatorPtr = subgraphPtr->operators[operatorIndex];
626 TensorRawPtr tensorPtr = subgraphPtr->tensors[reshapedInputId].get();
628 TensorRawPtr tensorPtr1 = subgraphPtr->tensors[inputId].get();
633 uint32_t inputSlotId = 1;
634 uint32_t reshapeSlotId = 0;
638 uint32_t
id = reshapedInputId;
639 reshapedInputId = inputId;
651 std::vector<unsigned> reshapedDim;
654 reshapedDim.push_back(reshapedTensorInfo.
GetShape()[i]);
657 std::vector<unsigned int> reshapedDimensions(numDimensions, 1);
658 std::copy_backward (reshapedDim.begin(), reshapedDim.end(), reshapedDimensions.end());
662 std::string layerName = boost::str(boost::format(
"Reshape_for:%1%") % layer->
GetName());
670 RegisterInputSlots(subgraphIndex, operatorIndex, reshapeLayer, {reshapedInputId});
673 RegisterConsumerOfTensor(subgraphIndex, inputId, input1Slot);
680 return CreateNetworkFromModel();
687 return CreateNetworkFromModel();
695 if (m_Options && m_Options.value().m_InferAndValidate)
699 {
"InferAndValidate",
true }
702 networkOptions.push_back(shapeInferenceMethodOption);
705 m_Network = INetwork::Create(networkOptions);
708 if (m_Model->subgraphs.size() != 1)
712 boost::format(
"Current TfLite parser only supports 1 subgraph. Current one has: %1% %2%") %
713 m_Model->subgraphs.size() %
717 size_t subgraphIndex = 0;
718 size_t operatorIndex = 0;
721 for (
SubgraphPtr const& subgraph : m_Model->subgraphs)
723 m_SubgraphConnections.emplace_back(subgraph->tensors.size());
726 auto const& opCodePtr = m_Model->operator_codes[op->opcode_index];
727 auto builtinCode = opCodePtr->builtin_code;
729 if (builtinCode > tflite::BuiltinOperator_MAX)
731 throw ParseException(boost::str(boost::format(
"Operator code %1% is out of range 0-%2%. " 732 "subgraph:%3% operator idx:%4%. %5%") %
733 builtinCode % tflite::BuiltinOperator_MAX % subgraphIndex %
738 auto& parserFunction = m_ParserFunctions[builtinCode];
739 (this->*parserFunction)(subgraphIndex, operatorIndex);
743 SetupInputLayers(subgraphIndex);
744 SetupOutputLayers(subgraphIndex);
745 SetupConstantLayers(subgraphIndex);
753 std::stringstream errorString;
754 errorString <<
"Failed to parse operator #" << operatorIndex <<
" within subgraph #" 755 << subgraphIndex <<
" error: " << e.
what();
757 std::stringstream errors;
758 errors << errorString.str() <<
"\n";
763 for (subgraphIndex = 0; subgraphIndex < m_SubgraphConnections.size(); ++subgraphIndex)
765 for (
size_t tensorIndex = 0; tensorIndex < m_SubgraphConnections[subgraphIndex].size(); ++tensorIndex)
767 if (m_SubgraphConnections[subgraphIndex][tensorIndex].outputSlot !=
nullptr)
769 for (
size_t inputSlotIdx = 0;
770 inputSlotIdx < m_SubgraphConnections[subgraphIndex][tensorIndex].inputSlots.size();
773 m_SubgraphConnections[subgraphIndex][tensorIndex].outputSlot->Connect(
774 *(m_SubgraphConnections[subgraphIndex][tensorIndex].inputSlots[inputSlotIdx]));
781 if (m_Options && m_Options.value().m_InferAndValidate)
783 for (subgraphIndex = 0;
784 subgraphIndex < m_SubgraphConnections.size();
787 if (m_SubgraphConnections[subgraphIndex].size() > 0)
791 m_SubgraphConnections[subgraphIndex][m_SubgraphConnections[subgraphIndex].size() - 1].outputSlot;
792 if (outputSlot !=
nullptr)
794 outputSlot->IsTensorInfoSet();
800 return std::move(m_Network);
803 void TfLiteParser::RegisterProducerOfTensor(
size_t subgraphIndex,
808 ARMNN_ASSERT(m_SubgraphConnections.size() > subgraphIndex);
809 ARMNN_ASSERT(m_SubgraphConnections[subgraphIndex].size() > tensorIndex);
811 TensorSlots & tensorSlots = m_SubgraphConnections[subgraphIndex][tensorIndex];
814 if (tensorSlots.outputSlot !=
nullptr)
817 boost::format(
"Another layer has already registered itself as the producer of " 818 "subgraph:%1% tensor:%2% %3%") %
824 tensorSlots.outputSlot = slot;
827 void TfLiteParser::RegisterConsumerOfTensor(
size_t subgraphIndex,
832 ARMNN_ASSERT(m_SubgraphConnections.size() > subgraphIndex);
833 ARMNN_ASSERT(m_SubgraphConnections[subgraphIndex].size() > tensorIndex);
835 TensorSlots & tensorSlots = m_SubgraphConnections[subgraphIndex][tensorIndex];
836 tensorSlots.inputSlots.push_back(slot);
839 void TfLiteParser::ParseCustomOperator(
size_t subgraphIndex,
size_t operatorIndex)
841 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
844 auto customParserFunction = &TfLiteParser::ParseUnsupportedOperator;
847 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
848 const auto& customCode = m_Model->operator_codes[operatorPtr->opcode_index]->custom_code;
851 auto iterator = m_CustomParserFunctions.find(customCode);
852 if (iterator != m_CustomParserFunctions.end())
854 customParserFunction = iterator->second;
858 (this->*customParserFunction)(subgraphIndex, operatorIndex);
861 void TfLiteParser::ParseUnsupportedOperator(
size_t subgraphIndex,
size_t operatorIndex)
863 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
865 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
867 auto opcodeIndex = operatorPtr->opcode_index;
868 auto opcode = m_Model->operator_codes[opcodeIndex]->builtin_code;
870 if (!m_Options || !m_Options.value().m_StandInLayerForUnsupported)
875 boost::format(
"Operator not supported. " 876 "subgraph:%1% operator:%2% " 877 "opcode_index:%3% opcode:%4% / %5% %6%") %
882 tflite::EnumNameBuiltinOperator(opcode) %
886 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
887 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
893 auto layerName = boost::str(boost::format(
"StandIn:%1%:%2%:%3%") % subgraphIndex % operatorIndex % opcode);
896 IConnectableLayer* layer = m_Network->AddStandInLayer(descriptor, layerName.c_str());
899 for (
unsigned int i = 0u; i < numOutputs; ++i)
904 auto inputTensorIds = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
905 auto outputTensorIds = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
907 RegisterInputSlots(subgraphIndex, operatorIndex, layer, inputTensorIds);
908 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIds);
911 void TfLiteParser::ParseConv2D(
size_t subgraphIndex,
size_t operatorIndex)
913 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
915 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
916 const auto * options = operatorPtr->builtin_options.AsConv2DOptions();
928 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
931 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
938 unsigned int inputHeight = inputTensorInfo.GetShape()[1];
939 unsigned int inputWidth = inputTensorInfo.GetShape()[2];
943 unsigned int filterHeight = filterTensorInfo.
GetShape()[1];
944 unsigned int filterWidth = filterTensorInfo.
GetShape()[2];
951 auto filterTensorAndData = CreateConstTensor(inputs[1],
956 auto layerName = boost::str(boost::format(
"Conv2D:%1%:%2%") % subgraphIndex % operatorIndex);
958 if (inputs.size() == 3)
962 auto biasTensorAndData = CreateConstTensor(inputs[2],
965 layer = m_Network->AddConvolution2dLayer(desc,
966 filterTensorAndData.first,
972 layer = m_Network->AddConvolution2dLayer(desc,
973 filterTensorAndData.first,
985 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
986 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
988 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
990 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
991 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
994 void TfLiteParser::ParseDepthwiseConv2D(
size_t subgraphIndex,
size_t operatorIndex)
996 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
998 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
999 const auto * options = operatorPtr->builtin_options.AsDepthwiseConv2DOptions();
1010 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1012 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1024 unsigned int inputHeight = inputTensorInfo.
GetShape()[1];
1025 unsigned int inputWidth = inputTensorInfo.
GetShape()[2];
1028 unsigned int filterHeight = filterTensorInfo.
GetShape()[1];
1029 unsigned int filterWidth = filterTensorInfo.
GetShape()[2];
1032 filterTensorInfo.
SetShape({ filterHeight,
1042 auto filterTensorAndData = CreateConstTensor(inputs[1], filterTensorInfo, permutationVector);
1044 auto layerName = boost::str(boost::format(
"DepthwiseConv2D:%1%:%2%") % subgraphIndex % operatorIndex);
1046 if (inputs.size() == 3)
1050 auto biasTensorAndData = CreateConstTensor(inputs[2],
1053 layer = m_Network->AddDepthwiseConvolution2dLayer(desc,
1054 filterTensorAndData.first,
1060 layer = m_Network->AddDepthwiseConvolution2dLayer(desc,
1061 filterTensorAndData.first,
1072 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1073 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1075 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
1077 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1078 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1081 void TfLiteParser::ParseDequantize(
size_t subgraphIndex,
size_t operatorIndex)
1083 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1085 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1088 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1091 auto layerName = boost::str(boost::format(
"Dequantize:%1%:%2%") % subgraphIndex % operatorIndex);
1099 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1100 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1102 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1103 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
1106 void TfLiteParser::ParseExp(
size_t subgraphIndex,
size_t operatorIndex)
1108 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1110 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1113 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1116 auto layerName = boost::str(boost::format(
"Exp:%1%:%2%") % subgraphIndex % operatorIndex);
1120 IConnectableLayer* layer = m_Network->AddElementwiseUnaryLayer(desc, layerName.c_str());
1126 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1127 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1129 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1130 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
1133 void TfLiteParser::ParseTranspose(
size_t subgraphIndex,
size_t operatorIndex)
1135 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1137 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1140 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1143 auto layerName = boost::str(boost::format(
"Transpose:%1%:%2%") % subgraphIndex % operatorIndex);
1146 if (inputs.size() == 2)
1151 std::vector<unsigned int> permuteShape(numPermVecElements);
1152 ::memcpy(permuteShape.data(), permuteBufferPtr->data.data(), permuteTensorInfo.
GetNumBytes());
1160 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1162 IConnectableLayer* layer = m_Network->AddTransposeLayer(desc, layerName.c_str());
1166 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1167 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1169 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1170 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1173 void TfLiteParser::ParseTransposeConv(
size_t subgraphIndex,
size_t operatorIndex)
1175 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1177 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1178 const auto * options = operatorPtr->builtin_options.AsTransposeConvOptions();
1186 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1189 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1196 if (tensorInfo.
GetDataType() == DataType::Signed32)
1198 ::memcpy(output_shape.data(),
GetBuffer(m_Model, inputs[0]->buffer)->data.data(), tensorInfo.
GetNumBytes());
1200 if (tensorInfo.
GetDataType() == DataType::QAsymmU8)
1204 output_shape[i] =
GetBuffer(m_Model, inputs[0]->buffer)->data.data()[i];
1208 for (
int dimension : output_shape)
1210 desc.
m_OutputShape.push_back(static_cast<unsigned int>(dimension));
1218 const unsigned int inputHeight = inputTensorInfo.
GetShape()[1];
1219 const unsigned int inputWidth = inputTensorInfo.
GetShape()[2];
1221 const unsigned int filterHeight = filterTensorInfo.
GetShape()[1];
1222 const unsigned int filterWidth = filterTensorInfo.
GetShape()[2];
1240 auto filterTensorAndData = CreateConstTensor(inputs[1],
1245 auto layerName = boost::str(boost::format(
"TransposeConv:%1%:%2%") % subgraphIndex % operatorIndex);
1247 layer = m_Network->AddTransposeConvolution2dLayer(desc,
1248 filterTensorAndData.first,
1258 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1259 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[2]});
1261 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1262 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1265 void TfLiteParser::ParseAveragePool2D(
size_t subgraphIndex,
size_t operatorIndex)
1267 ParsePool(subgraphIndex, operatorIndex, PoolingAlgorithm::Average);
1270 void TfLiteParser::ParseBatchToSpaceND(
size_t subgraphIndex,
size_t operatorIndex)
1272 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1274 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1277 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1286 std::vector<unsigned int> blockShape(blockShapeTensorInfo.GetNumElements());
1287 ::memcpy(blockShape.data(), blockShapeBufferPtr->data.data(), blockShapeTensorInfo.GetNumBytes());
1289 std::vector<unsigned int> cropsVector(cropsTensorInfo.
GetNumElements());
1290 ::memcpy(cropsVector.data(), cropsBufferPtr->data.data(), cropsTensorInfo.
GetNumBytes());
1293 std::vector<std::pair<unsigned int, unsigned int>> crops;
1294 for (
unsigned int i = 0; i < cropsTensorInfo.
GetNumElements() / step; ++i)
1296 crops.emplace_back(cropsVector[i * step], cropsVector[i * step + 1]);
1304 auto layerName = boost::str(boost::format(
"BatchToSpaceND:%1%:%2%") % subgraphIndex % operatorIndex);
1308 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1310 IConnectableLayer* layer = m_Network->AddBatchToSpaceNdLayer(desc, layerName.c_str());
1314 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1315 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1317 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1318 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1321 void TfLiteParser::ParseL2Normalization(
size_t subgraphIndex,
size_t operatorIndex)
1323 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1325 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1328 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1333 auto layerName = boost::str(boost::format(
"L2Normalization:%1%:%2%") % subgraphIndex % operatorIndex);
1334 IConnectableLayer* layer = m_Network->AddL2NormalizationLayer(desc, layerName.c_str());
1341 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1342 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1344 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1345 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1348 void TfLiteParser::ParseMaxPool2D(
size_t subgraphIndex,
size_t operatorIndex)
1350 ParsePool(subgraphIndex, operatorIndex, PoolingAlgorithm::Max);
1353 void TfLiteParser::ParseMaximum(
size_t subgraphIndex,
size_t operatorIndex)
1355 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1357 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1360 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1363 auto layerName = boost::str(boost::format(
"Maximum:%1%:%2%") % subgraphIndex % operatorIndex);
1367 CheckMatchingQuantization(inputTensorInfo, input1TensorInfo, layerName,
"Input 0",
"Input 1");
1370 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1376 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1379 AddBroadcastReshapeLayer(subgraphIndex, operatorIndex, layer);
1383 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
1386 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1387 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1390 void TfLiteParser::ParseMinimum(
size_t subgraphIndex,
size_t operatorIndex)
1392 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1394 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1397 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1400 auto layerName = boost::str(boost::format(
"Minimum:%1%:%2%") % subgraphIndex % operatorIndex);
1404 CheckMatchingQuantization(inputTensorInfo, input1TensorInfo, layerName,
"Input 0",
"Input 1");
1407 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1413 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1416 AddBroadcastReshapeLayer(subgraphIndex, operatorIndex, layer);
1420 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
1423 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1424 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1427 void TfLiteParser::ParsePool(
size_t subgraphIndex,
1428 size_t operatorIndex,
1431 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1433 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1434 const auto * options = operatorPtr->builtin_options.AsPool2DOptions();
1438 std::string layerName;
1442 case PoolingAlgorithm::Average:
1444 boost::str(boost::format(
"AveragePool2D:%1%:%2%") % subgraphIndex % operatorIndex);
1446 case PoolingAlgorithm::Max:
1448 boost::str(boost::format(
"MaxPool2D:%1%:%2%") % subgraphIndex % operatorIndex);
1465 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1470 unsigned int inputHeight = inputTensorInfo.GetShape()[1];
1471 unsigned int inputWidth = inputTensorInfo.GetShape()[2];
1478 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1482 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1484 IConnectableLayer* layer = m_Network->AddPooling2dLayer(desc, layerName.c_str());
1490 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1491 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1493 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
1495 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1496 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1499 void TfLiteParser::ParseSlice(
size_t subgraphIndex,
size_t operatorIndex)
1501 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1503 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1505 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1514 std::vector<unsigned int> begin(beginTensorInfo.
GetNumElements());
1515 ::memcpy(begin.data(), beginBufferPtr->data.data(), beginTensorInfo.
GetNumBytes());
1521 std::vector<unsigned int> size(sizeTensorInfo.GetNumElements());
1522 ::memcpy(size.data(), sizeBufferPtr->data.data(), sizeTensorInfo.GetNumBytes());
1525 auto layerName = boost::str(boost::format(
"Slice:%1%:%2%") % subgraphIndex % operatorIndex);
1529 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1531 IConnectableLayer*
const layer = m_Network->AddSliceLayer(desc, layerName.c_str());
1536 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1537 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1540 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1541 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1544 void TfLiteParser::ParseSoftmax(
size_t subgraphIndex,
size_t operatorIndex)
1546 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1547 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1548 const auto * options = operatorPtr->builtin_options.AsSoftmaxOptions();
1551 desc.
m_Beta = options->beta;
1553 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1555 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1558 auto layerName = boost::str(boost::format(
"Softmax:%1%:%2%") % subgraphIndex % operatorIndex);
1559 IConnectableLayer*
const layer = m_Network->AddSoftmaxLayer(desc, layerName.c_str());
1566 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1567 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1570 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1571 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1574 void TfLiteParser::ParseSpaceToBatchND(
size_t subgraphIndex,
size_t operatorIndex)
1576 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1578 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1581 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1590 std::vector<unsigned int> blockShape(blockShapeTensorInfo.GetNumElements());
1591 ::memcpy(blockShape.data(), blockShapeBufferPtr->data.data(), blockShapeTensorInfo.GetNumBytes());
1593 std::vector<unsigned int> padListVector(padListTensorInfo.
GetNumElements());
1594 ::memcpy(padListVector.data(), padListBufferPtr->data.data(), padListTensorInfo.
GetNumBytes());
1597 std::vector<std::pair<unsigned int, unsigned int>> padList;
1598 for (
unsigned int i = 0; i < padListTensorInfo.
GetNumElements() / step; ++i)
1600 padList.emplace_back(padListVector[i * step], padListVector[i * step + 1]);
1608 auto layerName = boost::str(boost::format(
"SpaceToBatchND:%1%:%2%") % subgraphIndex % operatorIndex);
1612 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1614 IConnectableLayer* layer = m_Network->AddSpaceToBatchNdLayer(desc, layerName.c_str());
1618 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1619 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1621 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1622 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1629 std::vector<uint32_t> squeezeDims = squeezeDimsIn;
1630 static const uint32_t dimensionSequence[] = { 0, 1, 2, 3 };
1634 std::stringstream ss;
1635 ss <<
"Input tensor has unexpected number of dimensions:" << inputTensorInfo.
GetNumDimensions()
1636 <<
" shape:" << inputTensorInfo.
GetShape() <<
" " 1641 if (squeezeDims.empty())
1643 squeezeDims.assign(dimensionSequence,
1647 std::vector<uint32_t> outputDims;
1650 bool skipSqueeze = (std::find(squeezeDims.begin(), squeezeDims.end(), i) == squeezeDims.end());
1651 auto currentDimension = inputTensorInfo.
GetShape()[i];
1652 if (skipSqueeze || currentDimension != 1)
1654 outputDims.push_back(currentDimension);
1658 if (outputDims.size() > 4)
1660 std::stringstream ss;
1661 ss <<
"Output tensor has unexpected number of dimensions:" << inputTensorInfo.
GetNumDimensions()
1662 <<
" shape:" << inputTensorInfo.
GetShape() <<
" " 1674 return outTensorInfo;
1677 void TfLiteParser::ParseSqueeze(
size_t subgraphIndex,
size_t operatorIndex)
1679 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1681 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1684 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1687 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1688 const auto * options = operatorPtr->builtin_options.AsSqueezeOptions();
1689 auto layerName = boost::str(boost::format(
"Squeeze:%1%:%2%") % subgraphIndex % operatorIndex);
1695 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1700 IConnectableLayer* layer = m_Network->AddReshapeLayer(reshapeDesc, layerName.c_str());
1704 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1705 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1707 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1708 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1711 void TfLiteParser::ParseStridedSlice(
size_t subgraphIndex,
size_t operatorIndex)
1713 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1715 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1718 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1721 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1722 const auto * options = operatorPtr->builtin_options.AsStridedSliceOptions();
1736 ::memcpy(begin.data(), beginBufferPtr->data.data(), beginTensorInfo.
GetNumBytes());
1741 std::vector<int> end(endTensorInfo.GetNumElements());
1742 ::memcpy(end.data(), endBufferPtr->data.data(), endTensorInfo.GetNumBytes());
1747 std::vector<int> stride(strideTensorInfo.GetNumElements());
1748 ::memcpy(stride.data(), strideBufferPtr->data.data(), strideTensorInfo.GetNumBytes());
1754 auto layerName = boost::str(boost::format(
"StridedSlice:%1%:%2%") % subgraphIndex % operatorIndex);
1755 IConnectableLayer* layer = m_Network->AddStridedSliceLayer(desc, layerName.c_str());
1761 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1762 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1764 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1765 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1768 void TfLiteParser::ParseSub(
size_t subgraphIndex,
size_t operatorIndex)
1770 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1772 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1773 const auto * options = operatorPtr->builtin_options.AsSubOptions();
1775 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1778 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1784 auto layerName = boost::str(boost::format(
"Sub:%1%:%2%") % subgraphIndex % operatorIndex);
1791 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1792 if (inputTensorInfo.GetNumDimensions() != input1TensorInfo.
GetNumDimensions())
1794 AddBroadcastReshapeLayer(subgraphIndex, operatorIndex, layer);
1798 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
1801 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
1803 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1804 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1807 void TfLiteParser::ParseDiv(
size_t subgraphIndex,
size_t operatorIndex)
1809 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1811 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1812 const auto * options = operatorPtr->builtin_options.AsDivOptions();
1814 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1817 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1823 auto layerName = boost::str(boost::format(
"Div:%1%:%2%") % subgraphIndex % operatorIndex);
1830 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1831 if (inputTensorInfo.GetNumDimensions() != input1TensorInfo.
GetNumDimensions())
1833 AddBroadcastReshapeLayer(subgraphIndex, operatorIndex, layer);
1837 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
1840 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
1842 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1843 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1846 void TfLiteParser::ParseAdd(
size_t subgraphIndex,
size_t operatorIndex)
1848 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1850 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1851 const auto * options = operatorPtr->builtin_options.AsAddOptions();
1853 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1856 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1862 auto layerName = boost::str(boost::format(
"Add:%1%:%2%") % subgraphIndex % operatorIndex);
1869 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1870 if (inputTensorInfo.GetNumDimensions() != input1TensorInfo.
GetNumDimensions())
1872 AddBroadcastReshapeLayer(subgraphIndex, operatorIndex, layer);
1876 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
1879 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
1881 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1882 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1885 void TfLiteParser::ParseMul(
size_t subgraphIndex,
size_t operatorIndex)
1887 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1889 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1890 const auto * options = operatorPtr->builtin_options.AsMulOptions();
1892 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1895 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1901 auto layerName = boost::str(boost::format(
"Mul:%1%:%2%") % subgraphIndex % operatorIndex);
1902 IConnectableLayer* layer = m_Network->AddMultiplicationLayer(layerName.c_str());
1908 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1909 if (inputTensorInfo.GetNumDimensions() != input1TensorInfo.
GetNumDimensions())
1911 AddBroadcastReshapeLayer(subgraphIndex, operatorIndex, layer);
1915 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
1918 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
1920 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1921 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1924 void TfLiteParser::ParseMean(
size_t subgraphIndex,
size_t operatorIndex)
1926 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1928 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1930 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1937 std::vector<unsigned int> axis(dimTensorInfo.GetNumElements());
1938 ::memcpy(axis.data(), bufferPtr->data.data(), dimTensorInfo.GetNumBytes());
1948 auto layerName = boost::str(boost::format(
"Mean:%1%:%2%") % subgraphIndex % operatorIndex);
1954 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1955 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1957 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1958 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1961 void TfLiteParser::ParseNeg(
size_t subgraphIndex,
size_t operatorIndex)
1963 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1965 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1968 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1971 auto layerName = boost::str(boost::format(
"Neg:%1%:%2%") % subgraphIndex % operatorIndex);
1973 IConnectableLayer* layer = m_Network->AddElementwiseUnaryLayer(descriptor, layerName.c_str());
1979 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1980 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1982 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1983 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
1986 void TfLiteParser::ParsePad(
size_t subgraphIndex,
size_t operatorIndex)
1988 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1998 std::vector<unsigned int> padBuffer(padTensorInfo.GetNumElements());
1999 ::memcpy(padBuffer.data(), bufferPtr->data.data(), padTensorInfo.GetNumBytes());
2003 for (
unsigned int i = 0; i < padTensorInfo.GetNumElements() / step; ++i)
2005 desc.
m_PadList.emplace_back(padBuffer[i * step], padBuffer[i * step + 1]);
2008 auto layerName = boost::str(boost::format(
"Pad:%1%:%2%") % subgraphIndex % operatorIndex);
2015 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2016 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2018 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2019 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2022 void TfLiteParser::ParseQuantize(
size_t subgraphIndex,
size_t operatorIndex)
2024 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2026 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2029 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2032 auto layerName = boost::str(boost::format(
"Quantize:%1%:%2%") % subgraphIndex % operatorIndex);
2040 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2041 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2043 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2044 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
2047 void TfLiteParser::ParseRelu(
size_t subgraphIndex,
size_t operatorIndex)
2049 ParseActivation(subgraphIndex,operatorIndex, ActivationFunction::ReLu);
2052 void TfLiteParser::ParseRelu6(
size_t subgraphIndex,
size_t operatorIndex)
2054 ParseActivation(subgraphIndex,operatorIndex, ActivationFunction::BoundedReLu);
2057 void TfLiteParser::ParseLeakyRelu(
size_t subgraphIndex,
size_t operatorIndex)
2059 ParseActivation(subgraphIndex, operatorIndex, ActivationFunction::LeakyReLu);
2062 void TfLiteParser::ParseLogistic(
size_t subgraphIndex,
size_t operatorIndex)
2064 ParseActivation(subgraphIndex,operatorIndex,ActivationFunction::Sigmoid);
2067 void TfLiteParser::ParseTanH(
size_t subgraphIndex,
size_t operatorIndex)
2069 ParseActivation(subgraphIndex,operatorIndex,ActivationFunction::TanH);
2072 void TfLiteParser::ParseHardSwish(
size_t subgraphIndex,
size_t operatorIndex)
2074 ParseActivation(subgraphIndex, operatorIndex, ActivationFunction::HardSwish);
2077 void TfLiteParser::ParseActivation(
size_t subgraphIndex,
size_t operatorIndex,
ActivationFunction activationType)
2079 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2080 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2083 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2086 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2089 auto layerName = str(boost::format(
"Activation:"));
2093 switch (activationType)
2095 case ActivationFunction::ReLu:
2097 layerName += str(boost::format(
"RELU:%1%:%2%") % subgraphIndex % operatorIndex);
2100 case ActivationFunction::BoundedReLu:
2102 layerName += str(boost::format(
"RELU6:%1%:%2%") % subgraphIndex % operatorIndex);
2103 activationDesc.
m_A = 6.0f;
2104 activationDesc.
m_B = 0.0f;
2107 case ActivationFunction::Sigmoid:
2109 layerName += str(boost::format(
"SIGMOID:%1%:%2%") % subgraphIndex % operatorIndex);
2112 case ActivationFunction::TanH:
2114 layerName += str(boost::format(
"TANH:%1%:%2%") % subgraphIndex % operatorIndex);
2115 activationDesc.
m_A = 1.0f;
2116 activationDesc.
m_B = 1.0f;
2119 case ActivationFunction::LeakyReLu:
2121 layerName += str(boost::format(
"LEAKYRELU:%1%:%2%") % subgraphIndex % operatorIndex);
2122 const auto * options = operatorPtr->builtin_options.AsLeakyReluOptions();
2123 activationDesc.
m_A = options->alpha;
2126 case ActivationFunction::HardSwish:
2127 layerName += str(boost::format(
"HARDSWISH:%1%:%2%") % subgraphIndex % operatorIndex);
2132 boost::str(boost::format(
"Unexpected ActivationFunction[%1%] when creating layerName " 2133 " %2% ") %static_cast<int>(activationType)%
CHECK_LOCATION().AsString()));
2137 IConnectableLayer*
const layer = m_Network->AddActivationLayer(activationDesc, layerName.c_str());
2144 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2145 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2148 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2149 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2152 const std::vector<int32_t> & targetDimsIn)
2154 std::vector<unsigned int> outputDims(targetDimsIn.begin(), targetDimsIn.end());
2155 const auto stretchDim = std::find(targetDimsIn.begin(), targetDimsIn.end(), -1);
2157 if (stretchDim != targetDimsIn.end())
2159 if (std::find(std::next(stretchDim), targetDimsIn.end(), -1) != targetDimsIn.end())
2163 boost::format(
"At most one component of shape can be -1 %1%") %
CHECK_LOCATION().AsString()));
2166 auto targetNumElements =
2168 std::accumulate(targetDimsIn.begin(), targetDimsIn.end(), -1, std::multiplies<int32_t>()));
2170 auto stretchIndex =
static_cast<size_t>(std::distance(targetDimsIn.begin(), stretchDim));
2171 outputDims[stretchIndex] = inputTensorInfo.
GetNumElements() / targetNumElements;
2182 void TfLiteParser::ParseReshape(
size_t subgraphIndex,
size_t operatorIndex)
2184 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2186 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2188 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2191 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2192 const auto * options = operatorPtr->builtin_options.AsReshapeOptions();
2193 auto layerName = boost::str(boost::format(
"Reshape:%1%:%2%") % subgraphIndex % operatorIndex);
2197 CheckMatchingQuantization(inputTensorInfo, actualOutputTensorInfo, layerName,
"Input 0",
"Output 0");
2203 std::vector<int32_t> targetShape;
2204 bool targetShapeFound =
false;
2206 if (options !=
nullptr)
2209 if (options->new_shape.empty() ==
false)
2211 targetShape = options->new_shape;
2212 targetShapeFound =
true;
2217 if (!targetShapeFound)
2220 if (inputs.size() > 1 && inputs[1] !=
nullptr)
2222 if (inputs[1]->is_variable)
2227 if (inputs[1]->shape.size() != 1)
2232 if (inputs[1]->type != tflite::TensorType_INT32)
2238 auto bufferPtr =
GetBuffer(m_Model, inputs[1]->buffer);
2239 auto values =
reinterpret_cast<const int32_t*
>(bufferPtr->data.data());
2240 for (
int i=0; i < inputs[1]->shape[0]; ++i)
2242 targetShape.push_back(values[i]);
2248 "At least one method required");
2257 if (inputs.size() > 1 && !
CheckShape(reshapeOutputTensorShape, outputs[0]->shape))
2259 std::stringstream ss;
2260 ss <<
"New shape defined in reshape parameters " 2261 << reshapeOutputTensorShape
2262 <<
" does not equal output shape " 2263 << actualOutputTensorInfo.
GetShape()
2272 IConnectableLayer* layer = m_Network->AddReshapeLayer(reshapeDesc, layerName.c_str());
2276 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2277 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2279 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2280 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2283 void TfLiteParser::ParseResizeBilinear(
size_t subgraphIndex,
size_t operatorIndex)
2285 ParseResize(subgraphIndex, operatorIndex, ResizeMethod::Bilinear);
2288 void TfLiteParser::ParseResizeNearestNeighbor(
size_t subgraphIndex,
size_t operatorIndex)
2290 ParseResize(subgraphIndex, operatorIndex, ResizeMethod::NearestNeighbor);
2293 void TfLiteParser::ParseResize(
size_t subgraphIndex,
size_t operatorIndex,
ResizeMethod resizeMethod)
2295 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2297 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2300 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2306 std::vector<int32_t> sizeTensorData(sizeTensorInfo.GetNumElements());
2309 ::memcpy(sizeTensorData.data(), sizeBufferPtr->data.data(), sizeTensorInfo.GetNumBytes());
2313 desc.m_TargetHeight =
static_cast<uint32_t
> (sizeTensorData[0]);
2314 desc.m_TargetWidth =
static_cast<uint32_t
> (sizeTensorData[1]);
2317 auto layerName = str(boost::format(
"Resize:"));
2319 switch (resizeMethod)
2321 case ResizeMethod::Bilinear:
2323 layerName += str(boost::format(
"BILINEAR:%1%:%2%") % subgraphIndex % operatorIndex);
2325 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2326 const auto * options = operatorPtr->builtin_options.AsResizeBilinearOptions();
2328 desc.m_AlignCorners = options->align_corners;
2331 case ResizeMethod::NearestNeighbor:
2333 layerName += str(boost::format(
"NEARESTNEIGHBOR:%1%:%2%") % subgraphIndex % operatorIndex);
2339 boost::str(boost::format(
"Unexpected ResizeMethod[%1%] when creating layerName " 2340 " %2% ") %static_cast<int>(resizeMethod)%
CHECK_LOCATION().AsString()));
2346 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
2352 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2353 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2355 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2356 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
2359 void TfLiteParser::ParseConcatenation(
size_t subgraphIndex,
size_t operatorIndex)
2361 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2363 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2364 const auto * options = operatorPtr->builtin_options.AsConcatenationOptions();
2368 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2369 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2372 unsigned int numConcatView =
static_cast<unsigned int>(inputs.size());
2375 const unsigned int concatDimInput =
static_cast<unsigned int>(
2376 (
static_cast<int>(inputRank) + options->axis) %
static_cast<int>(inputRank));
2378 OriginsDescriptor concatDescriptor(static_cast<uint32_t>(numConcatView), inputRank);
2381 unsigned int mergeDimOrigin = 0;
2383 for (
unsigned int viewIndex = 0; viewIndex < numConcatView; ++viewIndex)
2389 inputTensorInfo, concatDescriptor, concatDimInput, viewIndex, mergeDimOrigin);
2392 auto layerName = boost::str(boost::format(
"Concatenation:%1%:%2%") % subgraphIndex % operatorIndex);
2395 IConnectableLayer* layer = m_Network->AddConcatLayer(concatDescriptor, layerName.c_str());
2399 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2400 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes});
2403 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
2405 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2406 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2409 void TfLiteParser::ParseFullyConnected(
size_t subgraphIndex,
size_t operatorIndex)
2411 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2413 const auto & operatorRfr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2414 const auto options = operatorRfr->builtin_options.AsFullyConnectedOptions();
2422 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2423 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2429 int32_t weightsDimension =
static_cast<int32_t
>(filterTensorInfo.GetNumDimensions());
2430 if (weightsDimension != 2)
2435 "Dimension %1% for Fully Connected weights is not supported by Armnn. " 2441 auto filterTensorAndData = CreateConstTensor(inputs[1],
2445 auto layerName = boost::str(boost::format(
"FullyConnected:%1%:%2%") % subgraphIndex % operatorIndex);
2447 if (inputs.size() == 3)
2451 auto biasTensorAndData = CreateConstTensor(inputs[2],
2454 layer = m_Network->AddFullyConnectedLayer(desc,
2455 filterTensorAndData.first,
2461 layer = m_Network->AddFullyConnectedLayer(desc,
2462 filterTensorAndData.first,
2470 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2478 std::vector<unsigned int> reshapedDimensions(2);
2479 reshapedDimensions[1] = filterTensorInfo.GetShape()[1];
2480 reshapedDimensions[0] = inputTensorInfo.
GetNumElements() / reshapedDimensions[1];
2482 if (inputTensorInfo.
GetNumElements() % reshapedDimensions[1] != 0)
2487 "Failed to deduce input tensor shape from filter size %1%")
2488 % reshapedDimensions[1]
2495 std::string reshapeLayerName = boost::str(boost::format(
"Reshape_for:%1%") % layer->
GetName());
2497 desc.m_TargetShape = reshapedTensorInfo.
GetShape();
2503 RegisterInputSlots(subgraphIndex, operatorIndex, reshapeLayer, {inputTensorIndexes[0]});
2509 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2517 options->fused_activation_function);
2520 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2521 RegisterOutputSlots(subgraphIndex, operatorIndex, fusedActivationLayer, {outputTensorIndexes[0]});
2524 void TfLiteParser::ParseDetectionPostProcess(
size_t subgraphIndex,
size_t operatorIndex)
2526 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2528 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2530 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2531 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2535 auto custom_options = operatorPtr->custom_options;
2536 const flexbuffers::Map& m = flexbuffers::GetRoot(custom_options.data(), custom_options.size()).AsMap();
2545 desc.
m_ScaleH = m[
"h_scale"].AsFloat();
2546 desc.
m_ScaleW = m[
"w_scale"].AsFloat();
2547 desc.
m_ScaleX = m[
"x_scale"].AsFloat();
2548 desc.
m_ScaleY = m[
"y_scale"].AsFloat();
2550 if (!(m[
"use_regular_nms"].IsNull()))
2554 if (!(m[
"detections_per_class"].IsNull()))
2562 "must be positive and less than or equal to 1.");
2566 auto anchorTensorAndData = CreateConstTensor(inputs[2], anchorTensorInfo,
2569 auto layerName = boost::str(boost::format(
"DetectionPostProcess:%1%:%2%") % subgraphIndex % operatorIndex);
2570 IConnectableLayer* layer = m_Network->AddDetectionPostProcessLayer(desc, anchorTensorAndData.first,
2578 m_OverridenOutputShapes.push_back({ 1, numDetectedBox, 4 });
2579 m_OverridenOutputShapes.push_back({ 1, numDetectedBox });
2580 m_OverridenOutputShapes.push_back({ 1, numDetectedBox });
2581 m_OverridenOutputShapes.push_back({ 1 });
2583 for (
unsigned int i = 0 ; i < outputs.size() ; ++i)
2591 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2592 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
2595 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2596 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0],
2597 outputTensorIndexes[1],
2598 outputTensorIndexes[2],
2599 outputTensorIndexes[3]});
2603 void TfLiteParser::ParsePack(
size_t subgraphIndex,
size_t operatorIndex)
2605 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2607 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2608 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2611 if (inputs.size() < 1)
2616 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2617 const auto* options = operatorPtr->builtin_options.AsPackOptions();
2620 desc.
m_Axis =
static_cast<uint32_t
>(options->axis);
2621 desc.
m_NumInputs =
static_cast<uint32_t
>(inputs.size());
2627 auto layerName = boost::str(boost::format(
"Pack:%1%:%2%") % subgraphIndex % operatorIndex);
2635 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2636 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes});
2638 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2639 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2642 void TfLiteParser::ParseUnpack(
size_t subgraphIndex,
size_t operatorIndex)
2644 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2646 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2647 const auto * options = operatorPtr->builtin_options.AsUnpackOptions();
2652 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2657 if (unpackAxis >= inputTensorInfo.GetNumDimensions())
2662 "The unpack axis: %1% cannot be greater than or equal to " 2663 "the number of input dimension %2% %3%")
2665 % inputTensorInfo.GetNumDimensions()
2673 unpackNum = inputTensorInfo.GetShape()[unpackAxis];
2679 throw ParseException(
"Number to unpack must greater than zero.");
2682 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2685 auto inputDimSize = inputTensorInfo.GetNumDimensions();
2686 std::vector<unsigned int> unpackDimSizes(inputDimSize);
2689 for (
unsigned int i = 0; i < inputDimSize; ++i)
2691 unpackDimSizes[i] = inputTensorInfo.GetShape()[i];
2694 if (unpackDimSizes[unpackAxis] != unpackNum)
2696 throw ParseException(
"Number to unpack must be the same as length of the dimension to " 2700 unpackDimSizes[unpackAxis] /= unpackNum;
2702 SplitterDescriptor splitDesc(unpackNum, static_cast<unsigned int>(unpackDimSizes.size()));
2703 for (
unsigned int j = 0; j < unpackNum; ++j)
2706 for (
unsigned int dimIdx = 0; dimIdx < unpackDimSizes.size(); ++dimIdx)
2708 splitDesc.
SetViewSize(j, dimIdx, unpackDimSizes[dimIdx]);
2713 auto layerName = boost::str(boost::format(
"Unpack:%1%:%2%") % subgraphIndex % operatorIndex);
2714 IConnectableLayer* layer = m_Network->AddSplitterLayer(splitDesc, layerName.c_str());
2718 unpackDimSizes.data());
2720 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2721 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2727 std::string reshapeLayerName = boost::str(boost::format(
"Reshape_for:%1%") % layer->
GetName());
2742 RegisterProducerOfTensor(subgraphIndex, reshapedOutputId, slot);
2746 void TfLiteParser::ParseSplit(
size_t subgraphIndex,
size_t operatorIndex)
2748 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2750 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2751 const auto * options = operatorPtr->builtin_options.AsSplitOptions();
2758 throw ParseException(
"Number to splits must greater than zero.");
2761 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2763 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2770 std::vector<unsigned int> axisData(axisTensorInfo.
GetNumElements());
2771 ::memcpy(axisData.data(), axisBufferPtr->data.data(), axisTensorInfo.
GetNumBytes());
2774 const unsigned int splitDim = axisData[0];
2776 auto inputDimSize = inputTensorInfo.GetNumDimensions();
2782 "The number of dimensions: %1% for input tensors of the " 2783 "split op cannot be greater than %2% %3%")
2784 % inputTensorInfo.GetNumDimensions()
2789 std::vector<unsigned int> splitterDimSizes(inputDimSize);
2792 for (
unsigned int i = 0; i < inputDimSize; ++i)
2794 splitterDimSizes[i] = inputTensorInfo.GetShape()[i];
2797 if (splitterDimSizes[splitDim] % numSplits != 0)
2799 throw ParseException(
"Number of splits must evenly divide the dimension");
2801 splitterDimSizes[splitDim] /= numSplits;
2804 for (
unsigned int j = 0; j < numSplits; ++j)
2807 for (
unsigned int dimIdx = 0; dimIdx < splitterDimSizes.size(); ++dimIdx)
2809 splitDesc.
SetViewSize(j, dimIdx, splitterDimSizes[dimIdx]);
2814 auto layerName = boost::str(boost::format(
"Split:%1%:%2%") % subgraphIndex % operatorIndex);
2815 IConnectableLayer* layer = m_Network->AddSplitterLayer(splitDesc, layerName.c_str());
2818 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2819 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[1]});
2827 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2828 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
2834 int v = idx < 0 ? numDims + idx : idx;
2838 return static_cast<unsigned int>(v);
2841 void TfLiteParser::ParseSplitV(
size_t subgraphIndex,
size_t operatorIndex)
2843 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2845 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2846 const auto * options = operatorPtr->builtin_options.AsSplitVOptions();
2848 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2851 auto& inputTensor = inputs[0];
2852 auto& splitsTensor = inputs[1];
2853 auto& axisTensor = inputs[2];
2867 "The number of dimensions: %1% for input tensors of the " 2868 "SplitV op cannot be greater than %2% %3%")
2877 ::memcpy(axisData.data(), axisBufferPtr->data.data(), axisTensorInfo.
GetNumBytes());
2882 unsigned int numSplits{0};
2898 std::vector<int> splitsData(numSplits);
2900 ::memcpy(splitsData.data(), splitsBufferPtr->data.data(), splitsInfo.
GetNumBytes());
2902 unsigned int idx = 0;
2904 unsigned int inferIdx{0};
2906 for (
auto split : splitsData)
2920 if (numInferred == 0)
2922 if (splitSum != numeric_cast<int>(inputTensorInfo.
GetShape()[splitDim]))
2924 throw ParseException(
"SplitV split_sizes does not sum to the dimension of value along split_dim.");
2927 else if (numInferred == 1)
2933 throw ParseException(
"Cannot infer split size for more than one split");
2937 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2942 unsigned int accumSplit = 0;
2943 for (
unsigned int j = 0; j < numSplits; ++j)
2945 unsigned int splitSize =
numeric_cast<
unsigned int>(splitsData[j]);
2948 for (
unsigned int dimIdx = 0; dimIdx < inputTensorInfo.
GetNumDimensions(); ++dimIdx)
2950 unsigned int dimSize = inputTensorInfo.
GetShape()[dimIdx];
2951 if (dimIdx == splitDim)
2953 dimSize = splitSize;
2955 splitDesc.SetViewSize(j, dimIdx, dimSize);
2958 splitDesc.SetViewOriginCoord(j, splitDim, accumSplit);
2959 accumSplit += splitSize;
2962 auto layerName = boost::str(boost::format(
"SplitV:%1%:%2%") % subgraphIndex % operatorIndex);
2963 IConnectableLayer* layer = m_Network->AddSplitterLayer(splitDesc, layerName.c_str());
2966 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2967 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2975 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2976 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
2980 unsigned int outputSlot,
2981 tflite::ActivationFunctionType activationType)
2984 std::string layerName = prevLayer->
GetName();
2986 switch(activationType)
2988 case tflite::ActivationFunctionType_NONE:
2993 case tflite::ActivationFunctionType_RELU:
2995 activationDesc.
m_Function = ActivationFunction::ReLu;
2996 layerName +=
":RELU";
2999 case tflite::ActivationFunctionType_RELU6:
3001 activationDesc.
m_Function = ActivationFunction::BoundedReLu;
3002 activationDesc.
m_A = 6.0f;
3003 activationDesc.
m_B = 0.0f;
3004 layerName +=
":RELU6";
3007 case tflite::ActivationFunctionType_TANH:
3009 activationDesc.
m_Function = ActivationFunction::TanH;
3010 activationDesc.
m_A = 1.0f;
3011 activationDesc.
m_B = 1.0f;
3012 layerName +=
":TANH";
3017 case tflite::ActivationFunctionType_RELU_N1_TO_1:
3018 case tflite::ActivationFunctionType_SIGN_BIT:
3023 boost::format(
"TfLite parser doesn't suppport fused activation: " 3026 tflite::EnumNameActivationFunctionType(activationType) %
3033 m_Network->AddActivationLayer(activationDesc, layerName.c_str());
3035 auto & prevOutputSlot = prevLayer->
GetOutputSlot(outputSlot);
3038 return activationLayer;
3043 if (fileName ==
nullptr)
3048 std::error_code errorCode;
3049 fs::path pathToFile(fileName);
3050 if (!fs::exists(pathToFile, errorCode))
3053 std::string msg = boost::str(boost::format(
"Cannot find the file (%1%) errorCode: %2% %3%") %
3059 std::ifstream file(fileName, std::ios::binary);
3060 std::string fileContent((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
3062 fileContent.size());
3067 if (binaryContent ==
nullptr)
3072 flatbuffers::Verifier verifier(binaryContent, len);
3073 if (verifier.VerifyBuffer<tflite::Model>() ==
false)
3076 boost::str(boost::format(
"Buffer doesn't conform to the expected Tensorflow Lite " 3077 "flatbuffers format. size:%1% %2%") %
3081 return tflite::UnPackModel(binaryContent);
3085 size_t subgraphIndex,
3086 size_t operatorIndex)
3090 const auto & subgraphPtr = model->subgraphs[subgraphIndex];
3091 const auto & operatorPtr = subgraphPtr->operators[operatorIndex];
3093 size_t inputCount = operatorPtr->inputs.size();
3095 for (
size_t i=0; i<inputCount; ++i)
3098 result[i] = subgraphPtr->tensors[inputId].get();
3104 size_t subgraphIndex,
3105 size_t operatorIndex)
3109 const auto & subgraphPtr = model->subgraphs[subgraphIndex];
3110 const auto & operatorPtr = subgraphPtr->operators[operatorIndex];
3112 size_t outputCount = operatorPtr->outputs.size();
3114 for (
size_t i=0; i<outputCount; ++i)
3118 result[i] = subgraphPtr->tensors[outputId].get();
3124 size_t subgraphIndex)
3127 const auto & subgraphPtr = model->subgraphs[subgraphIndex];
3129 size_t inputCount = subgraphPtr->inputs.size();
3131 for (
size_t i=0; i<inputCount; ++i)
3135 result[i] = std::make_pair(inputId, subgraphPtr->tensors[inputId].get());
3141 size_t subgraphIndex)
3144 const auto & subgraphPtr = model->subgraphs[subgraphIndex];
3146 size_t outputCount = subgraphPtr->outputs.size();
3148 for (
size_t i=0; i<outputCount; ++i)
3151 result[i] = std::make_pair(outputId, subgraphPtr->tensors[outputId].get());
3157 size_t subgraphIndex,
3158 size_t operatorIndex)
3161 const auto & subgraphPtr = model->subgraphs[subgraphIndex];
3162 const auto & operatorPtr = subgraphPtr->operators[operatorIndex];
3163 return operatorPtr->inputs;
3167 size_t subgraphIndex,
3168 size_t operatorIndex)
3171 const auto & subgraphPtr = model->subgraphs[subgraphIndex];
3172 const auto & operatorPtr = subgraphPtr->operators[operatorIndex];
3173 return operatorPtr->outputs;
3176 void TfLiteParser::RegisterInputSlots(
size_t subgraphIndex,
3177 size_t operatorIndex,
3179 const std::vector<unsigned int>& tensorIndexes)
3181 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3186 boost::str(boost::format(
"The number of tensor inputs (%1%) does not match the number expected (%2%)" 3187 " for subgraph:%3% operator index:%4% %5%") %
3188 tensorIndexes.size() %
3195 for (
unsigned int slotIndex = 0; slotIndex < layer->
GetNumInputSlots(); ++slotIndex)
3197 unsigned int tensorIndex = tensorIndexes[slotIndex];
3199 RegisterConsumerOfTensor(subgraphIndex, tensorIndex, slot);
3203 void TfLiteParser::RegisterOutputSlots(
size_t subgraphIndex,
3204 size_t operatorIndex,
3206 const std::vector<unsigned int>& tensorIndexes)
3208 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3213 boost::str(boost::format(
"The number of tensor outputs (%1%) does not match the number expected (%2%)" 3214 " for subgraph:%3% operator index:%4% %5%") %
3215 tensorIndexes.size() %
3222 for (
unsigned int slotIndex = 0; slotIndex < layer->
GetNumOutputSlots(); ++slotIndex)
3224 unsigned int tensorIndex = tensorIndexes[slotIndex];
3226 RegisterProducerOfTensor(subgraphIndex, tensorIndex, slot);
3230 void TfLiteParser::SetupInputLayers(
size_t subgraphIndex)
3235 for (
auto const & tensorIdAndPtr : inputs)
3237 auto bindingId = GenerateLayerBindingId(subgraphIndex, tensorIdAndPtr.first);
3239 m_Network->AddInputLayer(bindingId, tensorIdAndPtr.second->name.c_str());
3244 RegisterOutputSlots(subgraphIndex,
3245 VIRTUAL_OPERATOR_ID,
3247 {
static_cast<uint32_t
>(tensorIdAndPtr.first) });
3251 void TfLiteParser::SetupOutputLayers(
size_t subgraphIndex)
3256 for (
auto const & tensorIdAndPtr : outputs)
3258 auto bindingId = GenerateLayerBindingId(subgraphIndex, tensorIdAndPtr.first);
3260 m_Network->AddOutputLayer(bindingId, tensorIdAndPtr.second->name.c_str());
3262 RegisterInputSlots(subgraphIndex,
3263 VIRTUAL_OPERATOR_ID,
3265 {
static_cast<uint32_t
>(tensorIdAndPtr.first) });
3269 void TfLiteParser::SetupConstantLayers(
size_t subgraphIndex)
3273 const auto & subgraphPtr = m_Model->subgraphs[subgraphIndex];
3274 for (
unsigned int subgraphIndex = 0; subgraphIndex < m_SubgraphConnections.size(); ++subgraphIndex)
3276 for (
unsigned int tensorIndex = 0; tensorIndex < m_SubgraphConnections[subgraphIndex].size(); ++tensorIndex)
3278 if (m_SubgraphConnections[subgraphIndex][tensorIndex].outputSlot ==
nullptr &&
3279 m_SubgraphConnections[subgraphIndex][tensorIndex].inputSlots.size() > 0)
3281 TensorRawPtr tensorPtr = subgraphPtr->tensors[tensorIndex].get();
3283 auto tensorAndData = CreateConstTensor(tensorPtr,
3287 std::string layerName = boost::str(boost::format(
"Constant:%1%") % tensorPtr->name);
3289 m_Network->AddConstantLayer(tensorAndData.first, layerName.c_str());
3292 RegisterOutputSlots(subgraphIndex,
3293 VIRTUAL_OPERATOR_ID,
3306 return model->buffers[bufferIndex].get();
3309 template<
typename T>
3310 std::pair<armnn::ConstTensor, TfLiteParser::SupportedDataStorage>
3316 auto constData = CreateConstTensorImpl<T>(bufferPtr,
3320 TfLiteParser::SupportedDataStorage storage(std::move(constData.second));
3321 return std::make_pair(constData.first, std::move(storage));
3324 std::pair<armnn::ConstTensor, TfLiteParser::SupportedDataStorage>
3325 TfLiteParser::CreateConstTensor(
TensorRawPtr tensorPtr,
3330 auto bufferPtr =
GetBuffer(m_Model, tensorPtr->buffer);
3336 return CreateConstTensorAndStoreData<float>(bufferPtr,
3341 return CreateConstTensorAndStoreData<uint8_t>(bufferPtr,
3346 return CreateConstTensorAndStoreData<int8_t>(bufferPtr,
3351 return CreateConstTensorAndStoreData<int8_t>(bufferPtr,
3356 return CreateConstTensorAndStoreData<int32_t>(bufferPtr,
3362 std::stringstream errString;
3363 errString <<
"Unexpected datatype when creating const tensor: " 3365 <<
" shape:" << tensorInfo.GetShape()
3373 const std::string& name)
const 3377 for (
auto const & input : inputs)
3379 if (input.second->name == name)
3381 auto bindingId = GenerateLayerBindingId(subgraphId, input.first);
3382 return std::make_pair(bindingId,
ToTensorInfo(input.second));
3386 std::stringstream bindings;
3387 for (
auto const & input : inputs)
3389 bindings <<
"'" << input.second->name <<
"' ";
3394 boost::format(
"No input binding found for subgraph:%1% and name:%2%. " 3395 "Possible inputs are: [%3%] %4%") %
3403 const std::string& name)
const 3407 for (
unsigned int i = 0; i < outputs.size(); ++i)
3409 auto const output = outputs[i];
3410 if (output.second->name == name)
3412 auto bindingId = GenerateLayerBindingId(subgraphId, output.first);
3413 std::vector<unsigned int> shape = m_OverridenOutputShapes.size() > 0 ?
3414 m_OverridenOutputShapes[i] : AsUnsignedVector(output.second->shape);
3415 return std::make_pair(bindingId,
ToTensorInfo(output.second, shape));
3419 std::stringstream bindings;
3420 for (
auto const & output : outputs)
3422 bindings <<
"'" << output.second->name <<
"' ";
3427 boost::format(
"No output binding found for subgraph:%1% and name:%2%. " 3428 "Possible outputs are: [%3%] %4%") %
3437 return m_Model->subgraphs.size();
3444 std::vector<std::string> result;
3445 result.reserve(inputs.size());
3446 for (
auto const & input : inputs)
3448 result.push_back(input.second->name);
3457 std::vector<std::string> result;
3458 result.reserve(outputs.size());
3459 for (
auto const & output : outputs)
3461 result.push_back(output.second->name);
3481 TfLiteParser::SupportedDataStorage::SupportedDataStorage(std::unique_ptr<
float[]> && data)
3482 : m_FloatData(std::move(data))
3483 , m_Uint8Data(
nullptr)
3484 , m_Int8Data(
nullptr)
3485 , m_Int32Data(
nullptr)
3489 TfLiteParser::SupportedDataStorage::SupportedDataStorage(std::unique_ptr<uint8_t[]> && data)
3490 : m_FloatData(
nullptr)
3491 , m_Uint8Data(std::move(data))
3492 , m_Int8Data(
nullptr)
3493 , m_Int32Data(
nullptr)
3497 TfLiteParser::SupportedDataStorage::SupportedDataStorage(std::unique_ptr<int8_t[]> && data)
3498 : m_FloatData(
nullptr)
3499 , m_Uint8Data(
nullptr)
3500 , m_Int8Data(std::move(data))
3501 , m_Int32Data(
nullptr)
3505 TfLiteParser::SupportedDataStorage::SupportedDataStorage(std::unique_ptr<int32_t[]> && data)
3506 : m_FloatData(
nullptr)
3507 , m_Uint8Data(
nullptr)
3508 , m_Int8Data(
nullptr)
3509 , m_Int32Data(std::move(data))
virtual armnn::INetworkPtr CreateNetworkFromBinaryFile(const char *graphFile) override
Create the network from a flatbuffers binary file on disk.
uint32_t m_PadBottom
Padding bottom value in the height dimension.
bool m_BiasEnabled
Enable/disable bias.
#define CHECK_MODEL(MODEL, SUBGRAPH_INDEX, OPERATOR_INDEX)
virtual unsigned int GetNumOutputSlots() const =0
Returns the number of connectable output slots.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
virtual BindingPointInfo GetNetworkOutputBindingInfo(size_t subgraphId, const std::string &name) const override
Retrieve binding info (layer id and tensor info) for the network output identified by the given layer...
UnaryOperation m_Operation
Specifies the elementwiseUnary operation to execute.
uint32_t m_Axis
0-based axis along which to stack the input tensors.
std::unique_ptr< tflite::SubGraphT > SubgraphPtr
static BufferRawPtr GetBuffer(const ModelPtr &model, size_t bufferIndex)
A ViewsDescriptor for the SplitterLayer.
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
float m_ScaleW
Center size encoding scale weight.
bool IsTypeSpaceMatch(const TensorInfo &other) const
Check that the types are the same and, if quantize, that the quantization parameters are the same...
uint32_t m_PadBottom
Padding bottom value in the height dimension.
bool m_BiasEnabled
Enable/disable bias.
static ModelPtr LoadModelFromBinary(const uint8_t *binaryContent, size_t len)
virtual unsigned int GetNumInputSlots() const =0
Returns the number of connectable input slots.
A TransposeConvolution2dDescriptor for the TransposeConvolution2dLayer.
#define ARMNN_THROW_PARSE_EXCEPTION(msg)
const TensorShape & GetShape() const
uint32_t m_PadBottom
Padding bottom value in the height dimension.
uint32_t m_PadLeft
Padding left value in the width dimension.
virtual armnn::INetworkPtr CreateNetworkFromBinary(const std::vector< uint8_t > &binaryContent) override
Create the network from a flatbuffers binary.
std::string AsString() const
int32_t m_ShrinkAxisMask
Shrink axis mask value. If set, the nth specification shrinks the dimensionality by 1...
A ReshapeDescriptor for the ReshapeLayer.
std::vector< int > m_Begin
Begin values for the input that will be sliced.
std::vector< TensorRawPtr > TensorRawPtrVector
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
float m_ScaleX
Center size encoding scale x.
TensorShape m_InputShape
Required shape of all input tensors.
bool m_TransposeWeightMatrix
Enable/disable transpose weight matrix.
uint32_t m_PoolWidth
Pooling width value.
A Convolution2dDescriptor for the Convolution2dLayer.
uint32_t m_PadLeft
Padding left value in the width dimension.
static ModelPtr LoadModelFromFile(const char *fileName)
bool m_BiasEnabled
Enable/disable bias.
std::vector< unsigned int > m_OutputShape
unsigned int GetNumBytes() const
ResizeMethod m_Method
The Interpolation method to use (Bilinear, NearestNeighbor).
float m_Beta
Exponentiation value.
PaddingMethod m_PaddingMethod
The padding method to be used. (Exclude, IgnoreValue).
uint32_t m_DetectionsPerClass
Detections per classes, used in Regular NMS.
bool m_OutputShapeEnabled
Output shape if it has been specified.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
#define CHECK_BUFFER(MODEL, BUFFER_INDEX)
static TensorRawPtrVector GetInputs(const ModelPtr &model, size_t subgraphIndex, size_t operatorIndex)
virtual const char * what() const noexcept override
#define ARMNN_LOG(severity)
uint32_t m_PadTop
Padding top value in the height dimension.
std::vector< BackendOptions > NetworkOptions
void ProcessConcatInputTensorInfo(armnn::TensorInfo &inputTensorInfo, armnn::OriginsDescriptor &concatDescriptor, const unsigned int &concatAxis, unsigned int inputIndex, unsigned int &mergeDimOrigin)
void CalcPadding(uint32_t input, uint32_t kernel, uint32_t stride, uint32_t &outPadHead, uint32_t &outPadTail, bool samePadding)
uint32_t m_PadRight
Padding right value in the width dimension.
std::vector< std::pair< unsigned int, unsigned int > > m_PadList
Specifies the padding for input dimension.
std::unique_ptr< ITfLiteParser, void(*)(ITfLiteParser *parser)> ITfLiteParserPtr
virtual BindingPointInfo GetNetworkInputBindingInfo(size_t subgraphId, const std::string &name) const override
Retrieve binding info (layer id and tensor info) for the network input identified by the given layer ...
unsigned int ComputeWrappedIndex(int idx, unsigned int numDimsIn)
Copyright (c) 2020 ARM Limited.
void IgnoreUnused(Ts &&...)
uint32_t m_PadBottom
Padding bottom value in the height dimension.
int32_t m_BeginMask
Begin mask value.
virtual size_t GetSubgraphCount() const override
Return the number of subgraphs in the parsed model.
uint32_t m_DilationY
Dilation along y axis.
int32_t m_EndMask
End mask value.
std::vector< std::pair< unsigned int, unsigned int > > m_PadList
Specifies the padding values for the input dimension: heightPad{top, bottom} widthPad{left, right}.
uint32_t m_DilationY
Dilation factor value for height dimension.
A BatchToSpaceNdDescriptor for the BatchToSpaceNdLayer.
static armnn::TensorInfo OutputShapeOfReshape(const armnn::TensorInfo &inputTensorInfo, const std::vector< int32_t > &targetDimsIn)
static ITfLiteParserPtr Create(const armnn::Optional< TfLiteParserOptions > &options=armnn::EmptyOptional())
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
int LayerBindingId
Type of identifiers for bindable layers (inputs, outputs).
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
#define CHECK_TENSOR(MODEL, SUBGRAPH_INDEX, TENSOR_INDEX)
constexpr const char * GetDataTypeName(DataType dataType)
void SetShape(const TensorShape &newShape)
A ResizeDescriptor for the ResizeLayer.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
uint32_t m_MaxClassesPerDetection
Maximum numbers of classes per detection, used in Fast NMS.
std::vector< unsigned int > m_Axis
Values for the dimensions to reduce.
A StackDescriptor for the StackLayer.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
TensorShape m_TargetShape
Target shape value.
static TensorIdRawPtrVector GetSubgraphInputs(const ModelPtr &model, size_t subgraphIndex)
static TensorRawPtrVector GetOutputs(const ModelPtr &model, size_t subgraphIndex, size_t operatorIndex)
uint32_t m_PoolHeight
Pooling height value.
uint32_t m_PadTop
Padding top value in the height dimension.
uint32_t m_MaxDetections
Maximum numbers of detections.
A PadDescriptor for the PadLayer.
armnn::TensorInfo ToTensorInfo(Deserializer::TensorRawPtr tensorPtr)
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
std::unique_ptr< onnx::ModelProto > ModelPtr
#define CHECK_SUBGRAPH(MODEL, SUBGRAPH_INDEX)
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
void CheckTensor(const ConstTensor &t)
static TensorIdRawPtrVector GetSubgraphOutputs(const ModelPtr &model, size_t subgraphIndex)
bool CheckShape(const armnn::TensorShape &actual, const std::vector< uint32_t > &expected)
float m_NmsIouThreshold
Intersection over union threshold.
uint32_t m_PadRight
Padding right value in the width dimension.
uint32_t m_DilationX
Dilation factor value for width dimension.
uint32_t m_PadTop
Padding top value in the height dimension.
std::string FileLine() const
Status SetViewSize(uint32_t view, uint32_t coord, uint32_t value)
Set the size of the views.
#define ARMNN_ASSERT_MSG(COND, MSG)
int32_t m_NewAxisMask
New axis mask value.
bool m_KeepDims
Enable/disable keep dimensions. If true, then the reduced dimensions that are of length 1 are kept...
armnnSerializer::TensorInfo * TensorRawPtr
std::vector< unsigned int > m_BlockShape
Block shape values.
static void Destroy(ITfLiteParser *parser)
An output connection slot for a layer.
A L2NormalizationDescriptor for the L2NormalizationLayer.
int32_t GetQuantizationOffset() const
float GetQuantizationScale() const
static std::vector< int32_t > & GetOutputTensorIds(const ModelPtr &model, size_t subgraphIndex, size_t operatorIndex)
DataType GetDataType() const
An OriginsDescriptor for the ConcatLayer.
bool has_value() const noexcept
A FullyConnectedDescriptor for the FullyConnectedLayer.
int32_t m_EllipsisMask
Ellipsis mask value.
bool m_BiasEnabled
Enable/disable bias.
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
static ITfLiteParser * CreateRaw(const armnn::Optional< TfLiteParserOptions > &options=armnn::EmptyOptional())
#define CHECK_VALID_SIZE(ACTUAL,...)
uint32_t m_NumClasses
Number of classes.
#define CHECKED_NON_NEGATIVE(VALUE)
uint32_t m_PadTop
Padding top value in the height dimension.
#define ARMNN_ASSERT(COND)
A StandInDescriptor for the StandIn layer.
std::enable_if_t< std::is_unsigned< Source >::value &&std::is_unsigned< Dest >::value, Dest > numeric_cast(Source source)
bool m_UseRegularNms
Use Regular NMS.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
std::vector< unsigned int > m_BlockShape
Block shape value.
std::vector< int > m_Stride
Stride values for the input that will be sliced.
bool IsActivationSupported(const BackendId &backend, const TensorInfo &input, const TensorInfo &output, const ActivationDescriptor &descriptor, char *reasonIfUnsupported=nullptr, size_t reasonIfUnsupportedMaxLength=1024)
Deprecated in favor of IBackend and ILayerSupport interfaces.
An ActivationDescriptor for the ActivationLayer.
uint32_t m_NumInputs
Number of input tensors.
A SliceDescriptor for the SliceLayer.
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
static std::vector< int32_t > & GetInputTensorIds(const ModelPtr &model, size_t subgraphIndex, size_t operatorIndex)
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
#define CHECK_TENSOR_PTR(TENSOR_PTR)
float m_ScaleH
Center size encoding scale height.
std::vector< int > m_End
End values for the input that will be sliced.
A SpaceToBatchNdDescriptor for the SpaceToBatchNdLayer.
Struct for the users to pass backend specific options.
float m_A
Alpha upper bound value used by the activation functions. (BoundedReLu, Linear, TanH, Elu).
uint32_t m_DilationX
Dilation along x axis.
uint32_t m_PadLeft
Padding left value in the width dimension.
EmptyOptional is used to initialize the Optional class in case we want to have default value for an O...
static armnn::TensorInfo OutputShapeOfSqueeze(const std::vector< uint32_t > &squeezeDims, const armnn::TensorInfo &inputTensorInfo)
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
#define CHECK_SUPPORTED_FUSED_ACTIVATION(OPTION, SUBGRAPH_INDEX, OPERATOR_INDEX)
A ElementwiseUnaryDescriptor for the ElementwiseUnaryLayer.
PoolingAlgorithm m_PoolType
The pooling algorithm to use (Max. Average, L2).
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
std::vector< std::pair< unsigned int, unsigned int > > m_Crops
The values to crop from the input dimension.
unsigned int GetNumDimensions() const
Function that returns the tensor rank.
OutputShapeRounding m_OutputShapeRounding
The rounding method for the output shape. (Floor, Ceiling).
void SetConcatAxis(unsigned int concatAxis)
Set the concatenation axis value.
const tflite::BufferT * BufferRawPtr
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
A MeanDescriptor for the MeanLayer.
virtual std::vector< std::string > GetSubgraphInputTensorNames(size_t subgraphId) const override
Return the input tensor names for a given subgraph.
armnn::BindingPointInfo BindingPointInfo
uint32_t m_PadRight
Padding right value in the width dimension.
A TransposeDescriptor for the TransposeLayer.
A StridedSliceDescriptor for the StridedSliceLayer.
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
virtual const char * GetName() const =0
Returns the name of the layer.
virtual std::vector< std::string > GetSubgraphOutputTensorNames(size_t subgraphId) const override
Return the output tensor names for a given subgraph.
float m_ScaleY
Center size encoding scale y.
float m_NmsScoreThreshold
NMS score threshold.
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
virtual int Connect(IInputSlot &destination)=0
A Pooling2dDescriptor for the Pooling2dLayer.
std::unique_ptr< tflite::ModelT > ModelPtr
unsigned int GetNumDimensions() const
#define CHECK_BUFFER_SIZE(BUFFER_PTR, TENSOR_INFO, BUFFER_ID)
float m_B
Beta lower bound value used by the activation functions. (BoundedReLu, Linear, TanH).
armnn::TensorShape Permuted(const armnn::TensorShape &srcShape, const armnn::PermutationVector &mappings)
A SoftmaxDescriptor for the SoftmaxLayer.
const tflite::TensorT * TensorRawPtr
DataLayout::NCHW DataLayout::NCHW DataLayout::NHWC DataLayout::NHWC true
Status SetViewOriginCoord(uint32_t view, uint32_t coord, uint32_t value)
Set the view origin coordinates.
ActivationFunction m_Function
The activation function to use (Sigmoid, TanH, Linear, ReLu, BoundedReLu, SoftReLu, LeakyReLu, Abs, Sqrt, Square, Elu).
std::unique_ptr< tflite::OperatorT > OperatorPtr
TfLiteParser(const armnn::Optional< ITfLiteParser::TfLiteParserOptions > &options=armnn::EmptyOptional())
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
A DepthwiseConvolution2dDescriptor for the DepthwiseConvolution2dLayer.
constexpr unsigned int MaxNumOfTensorDimensions
uint32_t m_PadLeft
Padding left value in the width dimension.
unsigned int GetNumElements() const
std::vector< TensorIdRawPtr > TensorIdRawPtrVector
uint32_t m_PadRight
Padding right value in the width dimension.