26 #include <schema_generated.h> 28 #include <flatbuffers/flexbuffers.h> 30 #include <fmt/format.h> 38 #define ARMNN_THROW_PARSE_EXCEPTION(msg) \ 40 throw armnn::ParseException( static_cast<const std::stringstream&>( std::stringstream() << msg \ 42 << CHECK_LOCATION().AsString()).str()); \ 45 using namespace armnn;
52 const uint32_t VIRTUAL_OPERATOR_ID = std::numeric_limits<uint32_t>::max();
58 if (model.get() ==
nullptr)
61 fmt::format(
"{} was called with invalid (null) model. " 62 "Possible reason is that the model is not yet loaded and Unpack(ed). " 68 else if (subgraphIndex >= model->subgraphs.size())
71 fmt::format(
"{} was called with an invalid subgraph index. " 79 #define CHECK_SUBGRAPH(MODEL, SUBGRAPH_INDEX) \ 80 CheckSubgraph(MODEL, SUBGRAPH_INDEX, CHECK_LOCATION()) 87 if (model.get() ==
nullptr)
90 fmt::format(
"{} was called with invalid (null) model. " 91 "Possible reason is that the model is not yet loaded and Unpack(ed). " 92 "subgraph:{} operator:{} at {}",
98 else if (subgraphIndex >= model->subgraphs.size())
101 fmt::format(
"{} was called with an invalid subgraph index. " 102 "subgraph:{} operator:{} at {}",
108 else if (operatorIndex >= model->subgraphs[subgraphIndex]->operators.size() &&
109 operatorIndex != VIRTUAL_OPERATOR_ID)
112 fmt::format(
"{} was called with an invalid operator index. " 113 "subgraph:{} operator:{} at {}",
121 #define CHECK_MODEL(MODEL, SUBGRAPH_INDEX, OPERATOR_INDEX) \ 122 CheckModel(MODEL, SUBGRAPH_INDEX, OPERATOR_INDEX, CHECK_LOCATION()) 125 size_t subgraphIndex,
131 ARMNN_ASSERT_MSG(model.get() !=
nullptr,
"Expecting a valid model in this function");
135 ARMNN_ASSERT_MSG(subgraphIndex < model->subgraphs.size(),
"Expecting a valid subgraph index");
138 if (tensorIndex >= model->subgraphs[subgraphIndex]->tensors.size())
141 fmt::format(
"{} was called with an invalid tensor index. " 142 "subgraph:{} tensor:{} at {}",
150 #define CHECK_TENSOR(MODEL, SUBGRAPH_INDEX, TENSOR_INDEX) \ 151 CheckTensor(MODEL, SUBGRAPH_INDEX, TENSOR_INDEX, CHECK_LOCATION()) 156 if (rawPtr ==
nullptr)
159 fmt::format(
"{} was called with a null tensor pointer at {}", location.
m_Function, location.
FileLine()));
163 #define CHECK_TENSOR_PTR(TENSOR_PTR) \ 164 CheckTensorPtr(TENSOR_PTR, CHECK_LOCATION()) 170 if (model.get() ==
nullptr)
173 fmt::format(
"{} was called with invalid (null) model. " 174 "Possible reason is that the model is not yet loaded and Unpack(ed). " 180 else if (bufferIndex >= model->buffers.size())
183 fmt::format(
"{} was called with an invalid buffer index. " 184 "buffer index:{} at {}",
189 else if (model->buffers[bufferIndex].get() ==
nullptr)
192 fmt::format(
"The buffer #{} is null. {}",
198 #define CHECK_BUFFER(MODEL, BUFFER_INDEX) \ 199 CheckBuffer(MODEL, BUFFER_INDEX, CHECK_LOCATION()) 201 void CheckBufferSize(TfLiteParser::BufferRawPtr bufferPtr,
206 if (bufferPtr ==
nullptr)
209 fmt::format(
"BufferPtr is null for buffer:{}. {}",
216 std::stringstream ss;
217 ss <<
"Buffer #" << bufferId <<
" has " << bufferPtr->data.size() <<
" bytes. " 218 <<
"For tensor: " << tensorInfo.
GetShape()
219 <<
" expecting: " << tensorInfo.
GetNumBytes() <<
" bytes and " 225 #define CHECK_BUFFER_SIZE(BUFFER_PTR, TENSOR_INFO, BUFFER_ID) \ 226 CheckBufferSize(BUFFER_PTR, TENSOR_INFO, BUFFER_ID, CHECK_LOCATION()) 230 switch(activationType)
232 case tflite::ActivationFunctionType_NONE:
233 case tflite::ActivationFunctionType_RELU:
234 case tflite::ActivationFunctionType_RELU6:
235 case tflite::ActivationFunctionType_TANH:
246 #define CHECK_SUPPORTED_FUSED_ACTIVATION(OPTION, SUBGRAPH_INDEX, OPERATOR_INDEX) \ 248 if (IsActivationSupported(OPTION->fused_activation_function) == false) \ 250 throw ParseException( \ 251 fmt::format("TfLite parser doesn't suppport fused activation: " \ 252 "{}/{} in {} subgraph:{} operator:{} at {}", \ 253 OPTION->fused_activation_function, \ 254 tflite::EnumNameActivationFunctionType(\ 255 OPTION->fused_activation_function), \ 259 CHECK_LOCATION().FileLine())); \ 264 std::vector<unsigned int> AsUnsignedVector(
const std::vector<int32_t> & in)
266 std::vector<unsigned int> result;
267 result.reserve(in.size());
279 uint32_t& paddingFront,
280 uint32_t& paddingBack,
281 tflite::Padding padding)
285 if (padding == tflite::Padding_SAME)
287 uint32_t outputSize = (inputSize + stride - 1) / stride;
288 uint32_t dilatedSize = filterSize + (dilation - 1) * (filterSize - 1);
289 uint32_t temp = (outputSize - 1) * stride + dilatedSize;
290 if (temp > inputSize)
292 paddingFront = (temp - inputSize) / 2;
293 paddingBack = (temp - inputSize) - paddingFront;
299 const std::vector<unsigned int>& shapes,
301 const bool outputTensor =
false)
306 switch (tensorPtr->type)
308 case tflite::TensorType_UINT8:
311 case tflite::TensorType_FLOAT32:
314 case tflite::TensorType_INT8:
315 if (tensorPtr->quantization->zero_point.size() == 1)
326 case tflite::TensorType_INT16:
329 case tflite::TensorType_INT32:
332 case tflite::TensorType_INT64:
339 fmt::format(
"Unsupported data type {} = {} for tensor: {}. {}",
341 tflite::EnumNameTensorType(tensorPtr->type),
346 std::vector<unsigned int> safeShape = shapes;
347 bool isDynamic =
false;
348 if (safeShape.size() == 0)
350 safeShape.push_back(1);
357 float quantizationScale = 0.0f;
358 int32_t quantizationOffset = 0;
360 if (tensorPtr->quantization.get())
362 if (tensorPtr->quantization->scale.size() <= 1)
367 if (tensorPtr->quantization->scale.size() == 1)
369 quantizationScale = tensorPtr->quantization->scale[0];
371 if (tensorPtr->quantization->zero_point.size() == 1)
378 TensorShape tensorShape(armnn::numeric_cast<unsigned int>(safeShape.size()),
392 std::vector<float> quantizationScales;
393 std::vector<int32_t> quantizationOffsets;
396 std::copy(tensorPtr->quantization->scale.begin(),
397 tensorPtr->quantization->scale.end(),
398 std::back_inserter(quantizationScales));
401 TensorShape tensorShape(armnn::numeric_cast<unsigned int>(safeShape.size()),
410 dimensionMappings[armnn::numeric_cast<unsigned int>(
411 tensorPtr->quantization->quantized_dimension)]);
417 TensorShape tensorShape(armnn::numeric_cast<unsigned int>(safeShape.size()),
434 auto const & dimensions = AsUnsignedVector(tensorPtr->shape);
435 return ToTensorInfo(tensorPtr, dimensions, dimensionMappings);
439 const bool outputTensor)
441 auto const & dimensions = AsUnsignedVector(tensorPtr->shape);
443 return ToTensorInfo(tensorPtr, dimensions, dimensionMappings, outputTensor);
447 std::pair<armnn::ConstTensor, std::unique_ptr<T[]>>
448 CreateConstTensorImpl(TfLiteParser::BufferRawPtr bufferPtr,
456 fmt::format(
"Buffer for buffer:{} is null", tensorPtr->buffer).c_str());
464 reinterpret_cast<const T*
>(bufferPtr->data.data()), data.get(),
sizeof(T));
468 ::memcpy(data.get(), bufferPtr->data.data(), tensorInfo.
GetNumBytes());
471 return std::make_pair(
ConstTensor(tensorInfo, data.get()), std::move(data));
484 if (actualSize != expected.size())
489 for (
unsigned int i = 0u; i < actualSize; i++)
491 if (expected[i] < 0 ||
492 actual[i] != static_cast<unsigned int>(expected[i]))
501 void CheckMatchingQuantization(
const TensorInfo& first,
503 const std::string& descName,
504 std::string
const& firstName,
505 std::string
const& secondName)
517 if (firstDataType != secondDataType)
520 " must be of the same quantized type, " +
528 " must have the same quantization space, " +
540 , m_Network(nullptr, nullptr)
541 , m_ParserFunctions(tflite::BuiltinOperator_MAX+1, &
TfLiteParser::ParseUnsupportedOperator)
544 m_ParserFunctions[tflite::BuiltinOperator_ADD] = &TfLiteParser::ParseAdd;
545 m_ParserFunctions[tflite::BuiltinOperator_AVERAGE_POOL_2D] = &TfLiteParser::ParseAveragePool2D;
546 m_ParserFunctions[tflite::BuiltinOperator_BATCH_TO_SPACE_ND] = &TfLiteParser::ParseBatchToSpaceND;
547 m_ParserFunctions[tflite::BuiltinOperator_CONCATENATION] = &TfLiteParser::ParseConcatenation;
548 m_ParserFunctions[tflite::BuiltinOperator_CONV_2D] = &TfLiteParser::ParseConv2D;
549 m_ParserFunctions[tflite::BuiltinOperator_CUSTOM] = &TfLiteParser::ParseCustomOperator;
550 m_ParserFunctions[tflite::BuiltinOperator_DEPTHWISE_CONV_2D] = &TfLiteParser::ParseDepthwiseConv2D;
551 m_ParserFunctions[tflite::BuiltinOperator_DEQUANTIZE] = &TfLiteParser::ParseDequantize;
552 m_ParserFunctions[tflite::BuiltinOperator_EXP] = &TfLiteParser::ParseExp;
553 m_ParserFunctions[tflite::BuiltinOperator_FULLY_CONNECTED] = &TfLiteParser::ParseFullyConnected;
554 m_ParserFunctions[tflite::BuiltinOperator_HARD_SWISH] = &TfLiteParser::ParseHardSwish;
555 m_ParserFunctions[tflite::BuiltinOperator_LEAKY_RELU] = &TfLiteParser::ParseLeakyRelu;
556 m_ParserFunctions[tflite::BuiltinOperator_LOGISTIC] = &TfLiteParser::ParseLogistic;
557 m_ParserFunctions[tflite::BuiltinOperator_L2_NORMALIZATION] = &TfLiteParser::ParseL2Normalization;
558 m_ParserFunctions[tflite::BuiltinOperator_MAX_POOL_2D] = &TfLiteParser::ParseMaxPool2D;
559 m_ParserFunctions[tflite::BuiltinOperator_MAXIMUM] = &TfLiteParser::ParseMaximum;
560 m_ParserFunctions[tflite::BuiltinOperator_MEAN] = &TfLiteParser::ParseMean;
561 m_ParserFunctions[tflite::BuiltinOperator_MINIMUM] = &TfLiteParser::ParseMinimum;
562 m_ParserFunctions[tflite::BuiltinOperator_MUL] = &TfLiteParser::ParseMul;
563 m_ParserFunctions[tflite::BuiltinOperator_NEG] = &TfLiteParser::ParseNeg;
564 m_ParserFunctions[tflite::BuiltinOperator_PACK] = &TfLiteParser::ParsePack;
565 m_ParserFunctions[tflite::BuiltinOperator_PAD] = &TfLiteParser::ParsePad;
566 m_ParserFunctions[tflite::BuiltinOperator_QUANTIZE] = &TfLiteParser::ParseQuantize;
567 m_ParserFunctions[tflite::BuiltinOperator_RELU] = &TfLiteParser::ParseRelu;
568 m_ParserFunctions[tflite::BuiltinOperator_RELU6] = &TfLiteParser::ParseRelu6;
569 m_ParserFunctions[tflite::BuiltinOperator_RESHAPE] = &TfLiteParser::ParseReshape;
570 m_ParserFunctions[tflite::BuiltinOperator_RESIZE_BILINEAR] = &TfLiteParser::ParseResizeBilinear;
571 m_ParserFunctions[tflite::BuiltinOperator_RESIZE_NEAREST_NEIGHBOR] = &TfLiteParser::ParseResizeNearestNeighbor;
572 m_ParserFunctions[tflite::BuiltinOperator_SLICE] = &TfLiteParser::ParseSlice;
573 m_ParserFunctions[tflite::BuiltinOperator_SOFTMAX] = &TfLiteParser::ParseSoftmax;
574 m_ParserFunctions[tflite::BuiltinOperator_SPACE_TO_BATCH_ND] = &TfLiteParser::ParseSpaceToBatchND;
575 m_ParserFunctions[tflite::BuiltinOperator_SPLIT] = &TfLiteParser::ParseSplit;
576 m_ParserFunctions[tflite::BuiltinOperator_SPLIT_V] = &TfLiteParser::ParseSplitV;
577 m_ParserFunctions[tflite::BuiltinOperator_SQUEEZE] = &TfLiteParser::ParseSqueeze;
578 m_ParserFunctions[tflite::BuiltinOperator_STRIDED_SLICE] = &TfLiteParser::ParseStridedSlice;
579 m_ParserFunctions[tflite::BuiltinOperator_SUB] = &TfLiteParser::ParseSub;
580 m_ParserFunctions[tflite::BuiltinOperator_TANH] = &TfLiteParser::ParseTanH;
581 m_ParserFunctions[tflite::BuiltinOperator_TRANSPOSE] = &TfLiteParser::ParseTranspose;
582 m_ParserFunctions[tflite::BuiltinOperator_TRANSPOSE_CONV] = &TfLiteParser::ParseTransposeConv;
583 m_ParserFunctions[tflite::BuiltinOperator_UNPACK] = &TfLiteParser::ParseUnpack;
584 m_ParserFunctions[tflite::BuiltinOperator_DIV] = &TfLiteParser::ParseDiv;
585 m_ParserFunctions[tflite::BuiltinOperator_ARG_MAX] = &TfLiteParser::ParseArgMax;
587 m_CustomParserFunctions[
"TFLite_Detection_PostProcess"] = &TfLiteParser::ParseDetectionPostProcess;
590 void TfLiteParser::ResetParser()
594 m_SubgraphConnections.clear();
601 return CreateNetworkFromModel();
608 return CreateNetworkFromModel();
616 if (m_Options && m_Options.value().m_InferAndValidate)
620 {
"InferAndValidate",
true }
623 networkOptions.push_back(shapeInferenceMethodOption);
626 m_Network = INetwork::Create(networkOptions);
629 if (m_Model->subgraphs.size() != 1)
632 fmt::format(
"Current TfLite parser only supports 1 subgraph. Current one has: {} {}",
633 m_Model->subgraphs.size(),
637 size_t subgraphIndex = 0;
638 size_t operatorIndex = 0;
641 for (
SubgraphPtr const& subgraph : m_Model->subgraphs)
643 m_SubgraphConnections.emplace_back(subgraph->tensors.size());
646 auto const& opCodePtr = m_Model->operator_codes[op->opcode_index];
647 auto builtinCode = opCodePtr->builtin_code;
649 if (builtinCode > tflite::BuiltinOperator_MAX)
651 throw ParseException(fmt::format(
"Operator code {} is out of range 0-{}. " 652 "subgraph:{} operator idx:{}. {}",
653 builtinCode, tflite::BuiltinOperator_MAX, subgraphIndex,
658 auto& parserFunction = m_ParserFunctions[builtinCode];
659 (this->*parserFunction)(subgraphIndex, operatorIndex);
663 SetupInputLayers(subgraphIndex);
664 SetupOutputLayers(subgraphIndex);
665 SetupConstantLayers(subgraphIndex);
673 std::stringstream errorString;
674 errorString <<
"Failed to parse operator #" << operatorIndex <<
" within subgraph #" 675 << subgraphIndex <<
" error: " << e.
what();
677 std::stringstream errors;
678 errors << errorString.str() <<
"\n";
683 for (subgraphIndex = 0; subgraphIndex < m_SubgraphConnections.size(); ++subgraphIndex)
685 for (
size_t tensorIndex = 0; tensorIndex < m_SubgraphConnections[subgraphIndex].size(); ++tensorIndex)
687 if (m_SubgraphConnections[subgraphIndex][tensorIndex].outputSlot !=
nullptr)
689 for (
size_t inputSlotIdx = 0;
690 inputSlotIdx < m_SubgraphConnections[subgraphIndex][tensorIndex].inputSlots.size();
693 m_SubgraphConnections[subgraphIndex][tensorIndex].outputSlot->Connect(
694 *(m_SubgraphConnections[subgraphIndex][tensorIndex].inputSlots[inputSlotIdx]));
700 return std::move(m_Network);
703 void TfLiteParser::RegisterProducerOfTensor(
size_t subgraphIndex,
708 ARMNN_ASSERT(m_SubgraphConnections.size() > subgraphIndex);
709 ARMNN_ASSERT(m_SubgraphConnections[subgraphIndex].size() > tensorIndex);
711 TensorSlots & tensorSlots = m_SubgraphConnections[subgraphIndex][tensorIndex];
714 if (tensorSlots.outputSlot !=
nullptr)
716 throw ParseException(fmt::format(
"Another layer has already registered itself as the producer of " 717 "subgraph:{} tensor:{} {}",
723 tensorSlots.outputSlot = slot;
726 void TfLiteParser::RegisterConsumerOfTensor(
size_t subgraphIndex,
731 ARMNN_ASSERT(m_SubgraphConnections.size() > subgraphIndex);
732 ARMNN_ASSERT(m_SubgraphConnections[subgraphIndex].size() > tensorIndex);
734 TensorSlots & tensorSlots = m_SubgraphConnections[subgraphIndex][tensorIndex];
735 tensorSlots.inputSlots.push_back(slot);
738 void TfLiteParser::ParseCustomOperator(
size_t subgraphIndex,
size_t operatorIndex)
740 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
743 auto customParserFunction = &TfLiteParser::ParseUnsupportedOperator;
746 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
747 const auto& customCode = m_Model->operator_codes[operatorPtr->opcode_index]->custom_code;
750 auto iterator = m_CustomParserFunctions.find(customCode);
751 if (iterator != m_CustomParserFunctions.end())
753 customParserFunction = iterator->second;
757 (this->*customParserFunction)(subgraphIndex, operatorIndex);
760 void TfLiteParser::ParseUnsupportedOperator(
size_t subgraphIndex,
size_t operatorIndex)
762 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
764 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
766 auto opcodeIndex = operatorPtr->opcode_index;
767 auto opcode = m_Model->operator_codes[opcodeIndex]->builtin_code;
769 if (!m_Options || !m_Options.value().m_StandInLayerForUnsupported)
773 fmt::format(
"Operator not supported. " 774 "subgraph:{} operator:{} " 775 "opcode_index:{} opcode:{} / {} {}",
780 tflite::EnumNameBuiltinOperator(opcode),
784 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
785 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
791 auto layerName = fmt::format(
"StandIn:{}:{}:{}", subgraphIndex, operatorIndex, opcode);
794 IConnectableLayer* layer = m_Network->AddStandInLayer(descriptor, layerName.c_str());
797 for (
unsigned int i = 0u; i < numOutputs; ++i)
802 auto inputTensorIds = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
803 auto outputTensorIds = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
805 RegisterInputSlots(subgraphIndex, operatorIndex, layer, inputTensorIds);
806 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIds);
809 void TfLiteParser::ParseConv2D(
size_t subgraphIndex,
size_t operatorIndex)
811 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
813 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
814 const auto * options = operatorPtr->builtin_options.AsConv2DOptions();
826 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
829 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
836 unsigned int inputHeight = inputTensorInfo.GetShape()[1];
837 unsigned int inputWidth = inputTensorInfo.GetShape()[2];
841 unsigned int filterHeight = filterTensorInfo.
GetShape()[1];
842 unsigned int filterWidth = filterTensorInfo.
GetShape()[2];
849 auto filterTensorAndData = CreateConstTensor(inputs[1],
854 auto layerName = fmt::format(
"Conv2D:{}:{}", subgraphIndex, operatorIndex);
856 if (inputs.size() == 3)
860 auto biasTensorAndData = CreateConstTensor(inputs[2],
863 layer = m_Network->AddConvolution2dLayer(desc,
864 filterTensorAndData.first,
870 layer = m_Network->AddConvolution2dLayer(desc,
871 filterTensorAndData.first,
883 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
884 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
886 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
888 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
889 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
892 void TfLiteParser::ParseDepthwiseConv2D(
size_t subgraphIndex,
size_t operatorIndex)
894 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
896 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
897 const auto * options = operatorPtr->builtin_options.AsDepthwiseConv2DOptions();
908 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
910 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
922 unsigned int inputHeight = inputTensorInfo.
GetShape()[1];
923 unsigned int inputWidth = inputTensorInfo.
GetShape()[2];
926 unsigned int filterHeight = filterTensorInfo.
GetShape()[1];
927 unsigned int filterWidth = filterTensorInfo.
GetShape()[2];
930 filterTensorInfo.
SetShape({ filterHeight,
940 auto filterTensorAndData = CreateConstTensor(inputs[1], filterTensorInfo, permutationVector);
942 auto layerName = fmt::format(
"DepthwiseConv2D:{}:{}", subgraphIndex, operatorIndex);
944 if (inputs.size() == 3)
948 auto biasTensorAndData = CreateConstTensor(inputs[2],
951 layer = m_Network->AddDepthwiseConvolution2dLayer(desc,
952 filterTensorAndData.first,
958 layer = m_Network->AddDepthwiseConvolution2dLayer(desc,
959 filterTensorAndData.first,
970 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
971 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
973 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
975 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
976 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
979 void TfLiteParser::ParseDequantize(
size_t subgraphIndex,
size_t operatorIndex)
981 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
983 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
986 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
989 auto layerName = fmt::format(
"Dequantize:{}:{}", subgraphIndex, operatorIndex);
997 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
998 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1000 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1001 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
1004 void TfLiteParser::ParseExp(
size_t subgraphIndex,
size_t operatorIndex)
1006 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1008 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1011 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1014 auto layerName = fmt::format(
"Exp:{}:{}", subgraphIndex, operatorIndex);
1018 IConnectableLayer* layer = m_Network->AddElementwiseUnaryLayer(desc, layerName.c_str());
1024 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1025 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1027 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1028 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
1031 void TfLiteParser::ParseTranspose(
size_t subgraphIndex,
size_t operatorIndex)
1033 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1035 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1038 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1041 auto layerName = fmt::format(
"Transpose:{}:{}", subgraphIndex, operatorIndex);
1044 if (inputs.size() == 2)
1049 std::vector<unsigned int> permuteShape(numPermVecElements);
1050 ::memcpy(permuteShape.data(), permuteBufferPtr->data.data(), permuteTensorInfo.
GetNumBytes());
1058 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1060 IConnectableLayer* layer = m_Network->AddTransposeLayer(desc, layerName.c_str());
1064 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1065 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1067 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1068 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1071 void TfLiteParser::ParseTransposeConv(
size_t subgraphIndex,
size_t operatorIndex)
1073 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1075 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1076 const auto * options = operatorPtr->builtin_options.AsTransposeConvOptions();
1084 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1087 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1094 if (tensorInfo.
GetDataType() == DataType::Signed32)
1096 ::memcpy(output_shape.data(),
GetBuffer(m_Model, inputs[0]->buffer)->data.data(), tensorInfo.
GetNumBytes());
1098 if (tensorInfo.
GetDataType() == DataType::QAsymmU8)
1102 output_shape[i] =
GetBuffer(m_Model, inputs[0]->buffer)->data.data()[i];
1106 for (
int dimension : output_shape)
1108 desc.
m_OutputShape.push_back(static_cast<unsigned int>(dimension));
1116 const unsigned int inputHeight = inputTensorInfo.
GetShape()[1];
1117 const unsigned int inputWidth = inputTensorInfo.
GetShape()[2];
1119 const unsigned int filterHeight = filterTensorInfo.
GetShape()[1];
1120 const unsigned int filterWidth = filterTensorInfo.
GetShape()[2];
1138 auto filterTensorAndData = CreateConstTensor(inputs[1],
1143 auto layerName = fmt::format(
"TransposeConv:{}:{}", subgraphIndex, operatorIndex);
1145 layer = m_Network->AddTransposeConvolution2dLayer(desc,
1146 filterTensorAndData.first,
1156 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1157 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[2]});
1159 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1160 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1163 void TfLiteParser::ParseAveragePool2D(
size_t subgraphIndex,
size_t operatorIndex)
1165 ParsePool(subgraphIndex, operatorIndex, PoolingAlgorithm::Average);
1168 void TfLiteParser::ParseBatchToSpaceND(
size_t subgraphIndex,
size_t operatorIndex)
1170 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1172 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1175 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1184 std::vector<unsigned int> blockShape(blockShapeTensorInfo.GetNumElements());
1185 ::memcpy(blockShape.data(), blockShapeBufferPtr->data.data(), blockShapeTensorInfo.GetNumBytes());
1187 std::vector<unsigned int> cropsVector(cropsTensorInfo.
GetNumElements());
1188 ::memcpy(cropsVector.data(), cropsBufferPtr->data.data(), cropsTensorInfo.
GetNumBytes());
1191 std::vector<std::pair<unsigned int, unsigned int>> crops;
1192 for (
unsigned int i = 0; i < cropsTensorInfo.
GetNumElements() / step; ++i)
1194 crops.emplace_back(cropsVector[i * step], cropsVector[i * step + 1]);
1202 auto layerName = fmt::format(
"BatchToSpaceND:{}:{}", subgraphIndex, operatorIndex);
1206 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1208 IConnectableLayer* layer = m_Network->AddBatchToSpaceNdLayer(desc, layerName.c_str());
1212 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1213 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1215 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1216 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1219 void TfLiteParser::ParseL2Normalization(
size_t subgraphIndex,
size_t operatorIndex)
1221 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1223 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1226 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1231 auto layerName = fmt::format(
"L2Normalization:{}:{}", subgraphIndex, operatorIndex);
1232 IConnectableLayer* layer = m_Network->AddL2NormalizationLayer(desc, layerName.c_str());
1239 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1240 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1242 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1243 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1246 void TfLiteParser::ParseMaxPool2D(
size_t subgraphIndex,
size_t operatorIndex)
1248 ParsePool(subgraphIndex, operatorIndex, PoolingAlgorithm::Max);
1251 void TfLiteParser::ParseMaximum(
size_t subgraphIndex,
size_t operatorIndex)
1253 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1255 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1258 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1261 auto layerName = fmt::format(
"Maximum:{}:{}", subgraphIndex, operatorIndex);
1265 CheckMatchingQuantization(inputTensorInfo, input1TensorInfo, layerName,
"Input 0",
"Input 1");
1268 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1274 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1275 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
1277 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1278 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1281 void TfLiteParser::ParseMinimum(
size_t subgraphIndex,
size_t operatorIndex)
1283 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1285 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1288 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1291 auto layerName = fmt::format(
"Minimum:{}:{}", subgraphIndex, operatorIndex);
1295 CheckMatchingQuantization(inputTensorInfo, input1TensorInfo, layerName,
"Input 0",
"Input 1");
1298 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1304 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1305 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
1307 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1308 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1311 void TfLiteParser::ParsePool(
size_t subgraphIndex,
1312 size_t operatorIndex,
1315 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1317 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1318 const auto * options = operatorPtr->builtin_options.AsPool2DOptions();
1322 std::string layerName;
1326 case PoolingAlgorithm::Average:
1328 fmt::format(
"AveragePool2D:{}:{}", subgraphIndex, operatorIndex);
1330 case PoolingAlgorithm::Max:
1332 fmt::format(
"MaxPool2D:{}:{}", subgraphIndex, operatorIndex);
1349 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1354 unsigned int inputHeight = inputTensorInfo.GetShape()[1];
1355 unsigned int inputWidth = inputTensorInfo.GetShape()[2];
1362 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1366 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1368 IConnectableLayer* layer = m_Network->AddPooling2dLayer(desc, layerName.c_str());
1374 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1375 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1377 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
1379 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1380 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1383 void TfLiteParser::ParseSlice(
size_t subgraphIndex,
size_t operatorIndex)
1385 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1387 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1389 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1398 std::vector<unsigned int> begin(beginTensorInfo.
GetNumElements());
1399 ::memcpy(begin.data(), beginBufferPtr->data.data(), beginTensorInfo.
GetNumBytes());
1405 std::vector<unsigned int> size(sizeTensorInfo.GetNumElements());
1406 ::memcpy(size.data(), sizeBufferPtr->data.data(), sizeTensorInfo.GetNumBytes());
1409 auto layerName = fmt::format(
"Slice:{}:{}", subgraphIndex, operatorIndex);
1413 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1415 IConnectableLayer*
const layer = m_Network->AddSliceLayer(desc, layerName.c_str());
1420 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1421 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1424 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1425 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1428 void TfLiteParser::ParseSoftmax(
size_t subgraphIndex,
size_t operatorIndex)
1430 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1431 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1432 const auto * options = operatorPtr->builtin_options.AsSoftmaxOptions();
1435 desc.
m_Beta = options->beta;
1437 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1439 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1442 auto layerName = fmt::format(
"Softmax:{}:{}", subgraphIndex, operatorIndex);
1443 IConnectableLayer*
const layer = m_Network->AddSoftmaxLayer(desc, layerName.c_str());
1450 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1451 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1454 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1455 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1458 void TfLiteParser::ParseSpaceToBatchND(
size_t subgraphIndex,
size_t operatorIndex)
1460 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1462 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1465 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1474 std::vector<unsigned int> blockShape(blockShapeTensorInfo.GetNumElements());
1475 ::memcpy(blockShape.data(), blockShapeBufferPtr->data.data(), blockShapeTensorInfo.GetNumBytes());
1477 std::vector<unsigned int> padListVector(padListTensorInfo.
GetNumElements());
1478 ::memcpy(padListVector.data(), padListBufferPtr->data.data(), padListTensorInfo.
GetNumBytes());
1481 std::vector<std::pair<unsigned int, unsigned int>> padList;
1482 for (
unsigned int i = 0; i < padListTensorInfo.
GetNumElements() / step; ++i)
1484 padList.emplace_back(padListVector[i * step], padListVector[i * step + 1]);
1492 auto layerName = fmt::format(
"SpaceToBatchND:{}:{}", subgraphIndex, operatorIndex);
1496 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1498 IConnectableLayer* layer = m_Network->AddSpaceToBatchNdLayer(desc, layerName.c_str());
1502 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1503 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1505 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1506 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1513 std::vector<uint32_t> squeezeDims = squeezeDimsIn;
1514 static const uint32_t dimensionSequence[] = { 0, 1, 2, 3 };
1518 std::stringstream ss;
1519 ss <<
"Input tensor has unexpected number of dimensions:" << inputTensorInfo.
GetNumDimensions()
1520 <<
" shape:" << inputTensorInfo.
GetShape() <<
" " 1525 if (squeezeDims.empty())
1527 squeezeDims.assign(dimensionSequence,
1531 std::vector<uint32_t> outputDims;
1534 bool skipSqueeze = (std::find(squeezeDims.begin(), squeezeDims.end(), i) == squeezeDims.end());
1535 auto currentDimension = inputTensorInfo.
GetShape()[i];
1536 if (skipSqueeze || currentDimension != 1)
1538 outputDims.push_back(currentDimension);
1542 if (outputDims.size() > 4)
1544 std::stringstream ss;
1545 ss <<
"Output tensor has unexpected number of dimensions:" << inputTensorInfo.
GetNumDimensions()
1546 <<
" shape:" << inputTensorInfo.
GetShape() <<
" " 1558 return outTensorInfo;
1561 void TfLiteParser::ParseSqueeze(
size_t subgraphIndex,
size_t operatorIndex)
1563 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1565 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1568 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1571 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1572 const auto * options = operatorPtr->builtin_options.AsSqueezeOptions();
1573 auto layerName = fmt::format(
"Squeeze:{}:{}", subgraphIndex, operatorIndex);
1579 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1584 IConnectableLayer* layer = m_Network->AddReshapeLayer(reshapeDesc, layerName.c_str());
1588 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1589 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1591 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1592 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1595 void TfLiteParser::ParseStridedSlice(
size_t subgraphIndex,
size_t operatorIndex)
1597 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1599 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1602 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1605 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1606 const auto * options = operatorPtr->builtin_options.AsStridedSliceOptions();
1620 ::memcpy(begin.data(), beginBufferPtr->data.data(), beginTensorInfo.
GetNumBytes());
1625 std::vector<int> end(endTensorInfo.GetNumElements());
1626 ::memcpy(end.data(), endBufferPtr->data.data(), endTensorInfo.GetNumBytes());
1631 std::vector<int> stride(strideTensorInfo.GetNumElements());
1632 ::memcpy(stride.data(), strideBufferPtr->data.data(), strideTensorInfo.GetNumBytes());
1638 auto layerName = fmt::format(
"StridedSlice:{}:{}", subgraphIndex, operatorIndex);
1639 IConnectableLayer* layer = m_Network->AddStridedSliceLayer(desc, layerName.c_str());
1645 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1646 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1648 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1649 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1652 void TfLiteParser::ParseSub(
size_t subgraphIndex,
size_t operatorIndex)
1654 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1656 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1657 const auto * options = operatorPtr->builtin_options.AsSubOptions();
1659 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1662 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1668 auto layerName = fmt::format(
"Sub:{}:{}", subgraphIndex, operatorIndex);
1675 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1676 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
1678 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
1680 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1681 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1684 void TfLiteParser::ParseDiv(
size_t subgraphIndex,
size_t operatorIndex)
1686 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1688 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1689 const auto * options = operatorPtr->builtin_options.AsDivOptions();
1691 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1694 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1700 auto layerName = fmt::format(
"Div:{}:{}", subgraphIndex, operatorIndex);
1707 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1708 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
1709 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
1711 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1712 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1715 void TfLiteParser::ParseAdd(
size_t subgraphIndex,
size_t operatorIndex)
1717 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1719 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1720 const auto * options = operatorPtr->builtin_options.AsAddOptions();
1722 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1725 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1731 auto layerName = fmt::format(
"Add:{}:{}", subgraphIndex, operatorIndex);
1738 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1739 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
1740 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
1742 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1743 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1746 void TfLiteParser::ParseMul(
size_t subgraphIndex,
size_t operatorIndex)
1748 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1750 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1751 const auto * options = operatorPtr->builtin_options.AsMulOptions();
1753 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1756 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1762 auto layerName = fmt::format(
"Mul:{}:{}", subgraphIndex, operatorIndex);
1763 IConnectableLayer* layer = m_Network->AddMultiplicationLayer(layerName.c_str());
1769 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1770 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
1771 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
1773 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1774 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1777 void TfLiteParser::ParseMean(
size_t subgraphIndex,
size_t operatorIndex)
1779 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1781 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1783 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1790 std::vector<unsigned int> axis(dimTensorInfo.GetNumElements());
1791 ::memcpy(axis.data(), bufferPtr->data.data(), dimTensorInfo.GetNumBytes());
1801 auto layerName = fmt::format(
"Mean:{}:{}", subgraphIndex, operatorIndex);
1807 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1808 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1810 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1811 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1814 void TfLiteParser::ParseNeg(
size_t subgraphIndex,
size_t operatorIndex)
1816 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1818 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1821 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1824 auto layerName = fmt::format(
"Neg:{}:{}", subgraphIndex, operatorIndex);
1826 IConnectableLayer* layer = m_Network->AddElementwiseUnaryLayer(descriptor, layerName.c_str());
1832 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1833 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1835 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1836 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
1839 void TfLiteParser::ParsePad(
size_t subgraphIndex,
size_t operatorIndex)
1841 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1851 std::vector<unsigned int> padBuffer(padTensorInfo.GetNumElements());
1852 ::memcpy(padBuffer.data(), bufferPtr->data.data(), padTensorInfo.GetNumBytes());
1856 for (
unsigned int i = 0; i < padTensorInfo.GetNumElements() / step; ++i)
1858 desc.
m_PadList.emplace_back(padBuffer[i * step], padBuffer[i * step + 1]);
1861 auto layerName = fmt::format(
"Pad:{}:{}", subgraphIndex, operatorIndex);
1868 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1869 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1871 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1872 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1875 void TfLiteParser::ParseQuantize(
size_t subgraphIndex,
size_t operatorIndex)
1877 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1879 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1882 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1885 auto layerName = fmt::format(
"Quantize:{}:{}", subgraphIndex, operatorIndex);
1893 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1894 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1896 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1897 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
1900 void TfLiteParser::ParseRelu(
size_t subgraphIndex,
size_t operatorIndex)
1902 ParseActivation(subgraphIndex,operatorIndex, ActivationFunction::ReLu);
1905 void TfLiteParser::ParseRelu6(
size_t subgraphIndex,
size_t operatorIndex)
1907 ParseActivation(subgraphIndex,operatorIndex, ActivationFunction::BoundedReLu);
1910 void TfLiteParser::ParseLeakyRelu(
size_t subgraphIndex,
size_t operatorIndex)
1912 ParseActivation(subgraphIndex, operatorIndex, ActivationFunction::LeakyReLu);
1915 void TfLiteParser::ParseLogistic(
size_t subgraphIndex,
size_t operatorIndex)
1917 ParseActivation(subgraphIndex,operatorIndex,ActivationFunction::Sigmoid);
1920 void TfLiteParser::ParseTanH(
size_t subgraphIndex,
size_t operatorIndex)
1922 ParseActivation(subgraphIndex,operatorIndex,ActivationFunction::TanH);
1925 void TfLiteParser::ParseHardSwish(
size_t subgraphIndex,
size_t operatorIndex)
1927 ParseActivation(subgraphIndex, operatorIndex, ActivationFunction::HardSwish);
1930 void TfLiteParser::ParseActivation(
size_t subgraphIndex,
size_t operatorIndex,
ActivationFunction activationType)
1932 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1933 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1936 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1939 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1942 auto layerName = fmt::format(
"Activation:");
1946 switch (activationType)
1948 case ActivationFunction::ReLu:
1950 layerName += fmt::format(
"RELU:{}:{}", subgraphIndex, operatorIndex);
1953 case ActivationFunction::BoundedReLu:
1955 layerName += fmt::format(
"RELU6:{}:{}", subgraphIndex, operatorIndex);
1956 activationDesc.
m_A = 6.0f;
1957 activationDesc.
m_B = 0.0f;
1960 case ActivationFunction::Sigmoid:
1962 layerName += fmt::format(
"SIGMOID:{}:{}", subgraphIndex, operatorIndex);
1965 case ActivationFunction::TanH:
1967 layerName += fmt::format(
"TANH:{}:{}", subgraphIndex, operatorIndex);
1968 activationDesc.
m_A = 1.0f;
1969 activationDesc.
m_B = 1.0f;
1972 case ActivationFunction::LeakyReLu:
1974 layerName += fmt::format(
"LEAKYRELU:{}:{}", subgraphIndex, operatorIndex);
1975 const auto * options = operatorPtr->builtin_options.AsLeakyReluOptions();
1976 activationDesc.
m_A = options->alpha;
1979 case ActivationFunction::HardSwish:
1980 layerName += fmt::format(
"HARDSWISH:{}:{}", subgraphIndex, operatorIndex);
1985 fmt::format(
"Unexpected ActivationFunction[{}] when creating layerName {} ",
1990 IConnectableLayer*
const layer = m_Network->AddActivationLayer(activationDesc, layerName.c_str());
1997 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1998 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2001 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2002 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2005 const std::vector<int32_t> & targetDimsIn)
2007 std::vector<unsigned int> outputDims(targetDimsIn.begin(), targetDimsIn.end());
2008 const auto stretchDim = std::find(targetDimsIn.begin(), targetDimsIn.end(), -1);
2010 if (stretchDim != targetDimsIn.end())
2012 if (std::find(std::next(stretchDim), targetDimsIn.end(), -1) != targetDimsIn.end())
2015 fmt::format(
"At most one component of shape can be -1 {}",
CHECK_LOCATION().AsString()));
2018 auto targetNumElements =
2020 std::accumulate(targetDimsIn.begin(), targetDimsIn.end(), -1, std::multiplies<int32_t>()));
2022 auto stretchIndex =
static_cast<size_t>(std::distance(targetDimsIn.begin(), stretchDim));
2023 outputDims[stretchIndex] = inputTensorInfo.
GetNumElements() / targetNumElements;
2034 void TfLiteParser::ParseReshape(
size_t subgraphIndex,
size_t operatorIndex)
2036 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2038 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2040 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2043 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2044 const auto * options = operatorPtr->builtin_options.AsReshapeOptions();
2045 auto layerName = fmt::format(
"Reshape:{}:{}", subgraphIndex, operatorIndex);
2049 CheckMatchingQuantization(inputTensorInfo, actualOutputTensorInfo, layerName,
"Input 0",
"Output 0");
2055 std::vector<int32_t> targetShape;
2056 bool targetShapeFound =
false;
2058 if (options !=
nullptr)
2061 if (options->new_shape.empty() ==
false)
2063 targetShape = options->new_shape;
2064 targetShapeFound =
true;
2069 if (!targetShapeFound)
2072 if (inputs.size() > 1 && inputs[1] !=
nullptr)
2074 if (inputs[1]->is_variable)
2079 if (inputs[1]->shape.size() != 1)
2084 if (inputs[1]->type != tflite::TensorType_INT32)
2090 auto bufferPtr =
GetBuffer(m_Model, inputs[1]->buffer);
2091 auto values =
reinterpret_cast<const int32_t*
>(bufferPtr->data.data());
2092 for (
int i=0; i < inputs[1]->shape[0]; ++i)
2094 targetShape.push_back(values[i]);
2100 "At least one method required");
2109 if (inputs.size() > 1 && !
CheckShape(reshapeOutputTensorShape, outputs[0]->shape))
2111 std::stringstream ss;
2112 ss <<
"New shape defined in reshape parameters " 2113 << reshapeOutputTensorShape
2114 <<
" does not equal output shape " 2115 << actualOutputTensorInfo.
GetShape()
2124 IConnectableLayer* layer = m_Network->AddReshapeLayer(reshapeDesc, layerName.c_str());
2128 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2129 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2131 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2132 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2135 void TfLiteParser::ParseResizeBilinear(
size_t subgraphIndex,
size_t operatorIndex)
2137 ParseResize(subgraphIndex, operatorIndex, ResizeMethod::Bilinear);
2140 void TfLiteParser::ParseResizeNearestNeighbor(
size_t subgraphIndex,
size_t operatorIndex)
2142 ParseResize(subgraphIndex, operatorIndex, ResizeMethod::NearestNeighbor);
2145 void TfLiteParser::ParseResize(
size_t subgraphIndex,
size_t operatorIndex,
ResizeMethod resizeMethod)
2147 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2149 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2152 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2158 std::vector<int32_t> sizeTensorData(sizeTensorInfo.GetNumElements());
2161 ::memcpy(sizeTensorData.data(), sizeBufferPtr->data.data(), sizeTensorInfo.GetNumBytes());
2165 desc.m_TargetHeight =
static_cast<uint32_t
> (sizeTensorData[0]);
2166 desc.m_TargetWidth =
static_cast<uint32_t
> (sizeTensorData[1]);
2169 auto layerName = fmt::format(
"Resize:");
2171 switch (resizeMethod)
2173 case ResizeMethod::Bilinear:
2175 layerName += fmt::format(
"BILINEAR:{}:{}", subgraphIndex, operatorIndex);
2177 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2178 const auto * options = operatorPtr->builtin_options.AsResizeBilinearOptions();
2180 desc.m_AlignCorners = options->align_corners;
2183 case ResizeMethod::NearestNeighbor:
2185 layerName += fmt::format(
"NEARESTNEIGHBOR:{}:{}", subgraphIndex, operatorIndex);
2191 fmt::format(
"Unexpected ResizeMethod[{}] when creating layerName {} ",
2198 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
2204 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2205 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2207 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2208 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
2211 void TfLiteParser::ParseConcatenation(
size_t subgraphIndex,
size_t operatorIndex)
2213 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2215 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2216 const auto * options = operatorPtr->builtin_options.AsConcatenationOptions();
2220 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2221 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2224 unsigned int numConcatView =
static_cast<unsigned int>(inputs.size());
2227 const unsigned int concatDimInput =
static_cast<unsigned int>(
2228 (
static_cast<int>(inputRank) + options->axis) %
static_cast<int>(inputRank));
2230 OriginsDescriptor concatDescriptor(static_cast<uint32_t>(numConcatView), inputRank);
2233 unsigned int mergeDimOrigin = 0;
2235 for (
unsigned int viewIndex = 0; viewIndex < numConcatView; ++viewIndex)
2241 inputTensorInfo, concatDescriptor, concatDimInput, viewIndex, mergeDimOrigin);
2244 auto layerName = fmt::format(
"Concatenation:{}:{}", subgraphIndex, operatorIndex);
2247 IConnectableLayer* layer = m_Network->AddConcatLayer(concatDescriptor, layerName.c_str());
2251 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2252 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes});
2255 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
2257 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2258 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2261 void TfLiteParser::ParseFullyConnected(
size_t subgraphIndex,
size_t operatorIndex)
2263 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2265 const auto & operatorRfr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2266 const auto options = operatorRfr->builtin_options.AsFullyConnectedOptions();
2274 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2275 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2281 int32_t weightsDimension =
static_cast<int32_t
>(filterTensorInfo.GetNumDimensions());
2282 if (weightsDimension != 2)
2285 fmt::format(
"Dimension {} for Fully Connected weights is not supported by Armnn. " 2291 auto filterTensorAndData = CreateConstTensor(inputs[1],
2295 auto layerName = fmt::format(
"FullyConnected:{}:{}", subgraphIndex, operatorIndex);
2297 if (inputs.size() == 3)
2301 auto biasTensorAndData = CreateConstTensor(inputs[2],
2304 layer = m_Network->AddFullyConnectedLayer(desc,
2305 filterTensorAndData.first,
2311 layer = m_Network->AddFullyConnectedLayer(desc,
2312 filterTensorAndData.first,
2320 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2328 std::vector<unsigned int> reshapedDimensions(2);
2329 reshapedDimensions[1] = filterTensorInfo.GetShape()[1];
2330 reshapedDimensions[0] = inputTensorInfo.
GetNumElements() / reshapedDimensions[1];
2332 if (inputTensorInfo.
GetNumElements() % reshapedDimensions[1] != 0)
2335 fmt::format(
"Failed to deduce input tensor shape from filter size {} {}",
2336 reshapedDimensions[1],
2343 std::string reshapeLayerName = fmt::format(
"Reshape_for:{}", layer->
GetName());
2345 desc.m_TargetShape = reshapedTensorInfo.
GetShape();
2351 RegisterInputSlots(subgraphIndex, operatorIndex, reshapeLayer, {inputTensorIndexes[0]});
2357 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2365 options->fused_activation_function);
2368 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2369 RegisterOutputSlots(subgraphIndex, operatorIndex, fusedActivationLayer, {outputTensorIndexes[0]});
2372 void TfLiteParser::ParseDetectionPostProcess(
size_t subgraphIndex,
size_t operatorIndex)
2374 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2376 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2378 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2379 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2383 auto custom_options = operatorPtr->custom_options;
2384 const flexbuffers::Map& m = flexbuffers::GetRoot(custom_options.data(), custom_options.size()).AsMap();
2393 desc.
m_ScaleH = m[
"h_scale"].AsFloat();
2394 desc.
m_ScaleW = m[
"w_scale"].AsFloat();
2395 desc.
m_ScaleX = m[
"x_scale"].AsFloat();
2396 desc.
m_ScaleY = m[
"y_scale"].AsFloat();
2398 if (!(m[
"use_regular_nms"].IsNull()))
2402 if (!(m[
"detections_per_class"].IsNull()))
2410 "must be positive and less than or equal to 1.");
2414 auto anchorTensorAndData = CreateConstTensor(inputs[2], anchorTensorInfo,
2417 auto layerName = fmt::format(
"DetectionPostProcess:{}:{}", subgraphIndex, operatorIndex);
2418 IConnectableLayer* layer = m_Network->AddDetectionPostProcessLayer(desc, anchorTensorAndData.first,
2426 m_OverridenOutputShapes.push_back({ 1, numDetectedBox, 4 });
2427 m_OverridenOutputShapes.push_back({ 1, numDetectedBox });
2428 m_OverridenOutputShapes.push_back({ 1, numDetectedBox });
2429 m_OverridenOutputShapes.push_back({ 1 });
2431 for (
unsigned int i = 0 ; i < outputs.size() ; ++i)
2439 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2440 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
2443 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2444 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0],
2445 outputTensorIndexes[1],
2446 outputTensorIndexes[2],
2447 outputTensorIndexes[3]});
2451 void TfLiteParser::ParsePack(
size_t subgraphIndex,
size_t operatorIndex)
2453 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2455 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2456 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2459 if (inputs.size() < 1)
2464 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2465 const auto* options = operatorPtr->builtin_options.AsPackOptions();
2468 desc.
m_Axis =
static_cast<uint32_t
>(options->axis);
2469 desc.
m_NumInputs =
static_cast<uint32_t
>(inputs.size());
2475 auto layerName = fmt::format(
"Pack:{}:{}", subgraphIndex, operatorIndex);
2483 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2484 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes});
2486 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2487 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2490 void TfLiteParser::ParseUnpack(
size_t subgraphIndex,
size_t operatorIndex)
2492 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2494 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2495 const auto * options = operatorPtr->builtin_options.AsUnpackOptions();
2500 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2505 if (unpackAxis >= inputTensorInfo.GetNumDimensions())
2508 fmt::format(
"The unpack axis: {} cannot be greater than or equal to " 2509 "the number of input dimension {} {}",
2511 inputTensorInfo.GetNumDimensions(),
2519 unpackNum = inputTensorInfo.GetShape()[unpackAxis];
2525 throw ParseException(
"Number to unpack must greater than zero.");
2528 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2531 auto inputDimSize = inputTensorInfo.GetNumDimensions();
2532 std::vector<unsigned int> unpackDimSizes(inputDimSize);
2535 for (
unsigned int i = 0; i < inputDimSize; ++i)
2537 unpackDimSizes[i] = inputTensorInfo.GetShape()[i];
2540 if (unpackDimSizes[unpackAxis] != unpackNum)
2542 throw ParseException(
"Number to unpack must be the same as length of the dimension to " 2546 unpackDimSizes[unpackAxis] /= unpackNum;
2548 SplitterDescriptor splitDesc(unpackNum, static_cast<unsigned int>(unpackDimSizes.size()));
2549 for (
unsigned int j = 0; j < unpackNum; ++j)
2552 for (
unsigned int dimIdx = 0; dimIdx < unpackDimSizes.size(); ++dimIdx)
2554 splitDesc.
SetViewSize(j, dimIdx, unpackDimSizes[dimIdx]);
2559 auto layerName = fmt::format(
"Unpack:{}:{}", subgraphIndex, operatorIndex);
2560 IConnectableLayer* layer = m_Network->AddSplitterLayer(splitDesc, layerName.c_str());
2564 unpackDimSizes.data());
2566 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2567 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2573 std::string reshapeLayerName = fmt::format(
"Reshape_for:{}", layer->
GetName());
2588 RegisterProducerOfTensor(subgraphIndex, reshapedOutputId, slot);
2592 void TfLiteParser::ParseSplit(
size_t subgraphIndex,
size_t operatorIndex)
2594 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2596 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2597 const auto * options = operatorPtr->builtin_options.AsSplitOptions();
2604 throw ParseException(
"Number to splits must greater than zero.");
2607 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2609 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2616 std::vector<unsigned int> axisData(axisTensorInfo.
GetNumElements());
2617 ::memcpy(axisData.data(), axisBufferPtr->data.data(), axisTensorInfo.
GetNumBytes());
2620 const unsigned int splitDim = axisData[0];
2622 auto inputDimSize = inputTensorInfo.GetNumDimensions();
2626 fmt::format(
"The number of dimensions: {} for input tensors of the split op cannot be greater than {} {}",
2627 inputTensorInfo.GetNumDimensions(),
2632 std::vector<unsigned int> splitterDimSizes(inputDimSize);
2635 for (
unsigned int i = 0; i < inputDimSize; ++i)
2637 splitterDimSizes[i] = inputTensorInfo.GetShape()[i];
2640 if (splitterDimSizes[splitDim] % numSplits != 0)
2642 throw ParseException(
"Number of splits must evenly divide the dimension");
2644 splitterDimSizes[splitDim] /= numSplits;
2647 for (
unsigned int j = 0; j < numSplits; ++j)
2650 for (
unsigned int dimIdx = 0; dimIdx < splitterDimSizes.size(); ++dimIdx)
2652 splitDesc.
SetViewSize(j, dimIdx, splitterDimSizes[dimIdx]);
2657 auto layerName = fmt::format(
"Split:{}:{}", subgraphIndex, operatorIndex);
2658 IConnectableLayer* layer = m_Network->AddSplitterLayer(splitDesc, layerName.c_str());
2661 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2662 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[1]});
2670 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2671 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
2677 int v = idx < 0 ? numDims + idx : idx;
2681 return static_cast<unsigned int>(v);
2684 void TfLiteParser::ParseSplitV(
size_t subgraphIndex,
size_t operatorIndex)
2686 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2688 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2689 const auto * options = operatorPtr->builtin_options.AsSplitVOptions();
2691 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2694 auto& inputTensor = inputs[0];
2695 auto& splitsTensor = inputs[1];
2696 auto& axisTensor = inputs[2];
2708 fmt::format(
"The number of dimensions: {} for input tensors of the " 2709 "SplitV op cannot be greater than {} {}",
2718 ::memcpy(axisData.data(), axisBufferPtr->data.data(), axisTensorInfo.
GetNumBytes());
2723 unsigned int numSplits{0};
2739 std::vector<int> splitsData(numSplits);
2741 ::memcpy(splitsData.data(), splitsBufferPtr->data.data(), splitsInfo.
GetNumBytes());
2743 unsigned int idx = 0;
2745 unsigned int inferIdx{0};
2747 for (
auto split : splitsData)
2761 if (numInferred == 0)
2763 if (splitSum != armnn::numeric_cast<int>(inputTensorInfo.
GetShape()[splitDim]))
2765 throw ParseException(
"SplitV split_sizes does not sum to the dimension of value along split_dim.");
2768 else if (numInferred == 1)
2774 throw ParseException(
"Cannot infer split size for more than one split");
2778 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2783 unsigned int accumSplit = 0;
2784 for (
unsigned int j = 0; j < numSplits; ++j)
2789 for (
unsigned int dimIdx = 0; dimIdx < inputTensorInfo.
GetNumDimensions(); ++dimIdx)
2791 unsigned int dimSize = inputTensorInfo.
GetShape()[dimIdx];
2792 if (dimIdx == splitDim)
2794 dimSize = splitSize;
2796 splitDesc.SetViewSize(j, dimIdx, dimSize);
2799 splitDesc.SetViewOriginCoord(j, splitDim, accumSplit);
2800 accumSplit += splitSize;
2803 auto layerName = fmt::format(
"SplitV:{}:{}", subgraphIndex, operatorIndex);
2804 IConnectableLayer* layer = m_Network->AddSplitterLayer(splitDesc, layerName.c_str());
2807 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2808 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2816 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2817 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
2820 void TfLiteParser::ParseArgMax(
size_t subgraphIndex,
size_t operatorIndex)
2822 const auto &operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2823 const auto *options = operatorPtr->builtin_options.AsArgMaxOptions();
2825 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2826 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2829 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2832 auto layerName = fmt::format(
"ArgMax:{}:{}", subgraphIndex, operatorIndex);
2841 desc.
m_Axis = axisBufferPtr->data.data()[0];
2847 IConnectableLayer *layer = m_Network->AddArgMinMaxLayer(desc, layerName.c_str());
2853 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2854 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2857 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2858 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
2862 unsigned int outputSlot,
2863 tflite::ActivationFunctionType activationType)
2866 std::string layerName = prevLayer->
GetName();
2868 switch(activationType)
2870 case tflite::ActivationFunctionType_NONE:
2875 case tflite::ActivationFunctionType_RELU:
2877 activationDesc.
m_Function = ActivationFunction::ReLu;
2878 layerName +=
":RELU";
2881 case tflite::ActivationFunctionType_RELU6:
2883 activationDesc.
m_Function = ActivationFunction::BoundedReLu;
2884 activationDesc.
m_A = 6.0f;
2885 activationDesc.
m_B = 0.0f;
2886 layerName +=
":RELU6";
2889 case tflite::ActivationFunctionType_TANH:
2891 activationDesc.
m_Function = ActivationFunction::TanH;
2892 activationDesc.
m_A = 1.0f;
2893 activationDesc.
m_B = 1.0f;
2894 layerName +=
":TANH";
2899 case tflite::ActivationFunctionType_RELU_N1_TO_1:
2900 case tflite::ActivationFunctionType_SIGN_BIT:
2904 fmt::format(
"TfLite parser doesn't suppport fused activation: " 2907 tflite::EnumNameActivationFunctionType(activationType),
2914 m_Network->AddActivationLayer(activationDesc, layerName.c_str());
2916 auto & prevOutputSlot = prevLayer->
GetOutputSlot(outputSlot);
2919 return activationLayer;
2924 if (fileName ==
nullptr)
2929 std::error_code errorCode;
2930 fs::path pathToFile(fileName);
2931 if (!fs::exists(pathToFile, errorCode))
2934 std::stringstream msg;
2935 msg <<
"Cannot find the file (" << fileName <<
") errorCode: " << errorCode
2940 std::ifstream file(fileName, std::ios::binary);
2941 std::string fileContent((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
2943 fileContent.size());
2948 if (binaryContent ==
nullptr)
2953 flatbuffers::Verifier verifier(binaryContent, len);
2954 if (verifier.VerifyBuffer<tflite::Model>() ==
false)
2957 fmt::format(
"Buffer doesn't conform to the expected Tensorflow Lite " 2958 "flatbuffers format. size:{} {}",
2962 return tflite::UnPackModel(binaryContent);
2966 size_t subgraphIndex,
2967 size_t operatorIndex)
2971 const auto & subgraphPtr = model->subgraphs[subgraphIndex];
2972 const auto & operatorPtr = subgraphPtr->operators[operatorIndex];
2974 size_t inputCount = operatorPtr->inputs.size();
2976 for (
size_t i=0; i<inputCount; ++i)
2979 result[i] = subgraphPtr->tensors[inputId].get();
2985 size_t subgraphIndex,
2986 size_t operatorIndex)
2990 const auto & subgraphPtr = model->subgraphs[subgraphIndex];
2991 const auto & operatorPtr = subgraphPtr->operators[operatorIndex];
2993 size_t outputCount = operatorPtr->outputs.size();
2995 for (
size_t i=0; i<outputCount; ++i)
2999 result[i] = subgraphPtr->tensors[outputId].get();
3005 size_t subgraphIndex)
3008 const auto & subgraphPtr = model->subgraphs[subgraphIndex];
3010 size_t inputCount = subgraphPtr->inputs.size();
3012 for (
size_t i=0; i<inputCount; ++i)
3016 result[i] = std::make_pair(inputId, subgraphPtr->tensors[inputId].get());
3022 size_t subgraphIndex)
3025 const auto & subgraphPtr = model->subgraphs[subgraphIndex];
3027 size_t outputCount = subgraphPtr->outputs.size();
3029 for (
size_t i=0; i<outputCount; ++i)
3032 result[i] = std::make_pair(outputId, subgraphPtr->tensors[outputId].get());
3038 size_t subgraphIndex,
3039 size_t operatorIndex)
3042 const auto & subgraphPtr = model->subgraphs[subgraphIndex];
3043 const auto & operatorPtr = subgraphPtr->operators[operatorIndex];
3044 return operatorPtr->inputs;
3048 size_t subgraphIndex,
3049 size_t operatorIndex)
3052 const auto & subgraphPtr = model->subgraphs[subgraphIndex];
3053 const auto & operatorPtr = subgraphPtr->operators[operatorIndex];
3054 return operatorPtr->outputs;
3057 void TfLiteParser::RegisterInputSlots(
size_t subgraphIndex,
3058 size_t operatorIndex,
3060 const std::vector<unsigned int>& tensorIndexes)
3062 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3067 fmt::format(
"The number of tensor inputs ({}) does not match the number expected ({})" 3068 " for subgraph:{} operator index:{} {}",
3069 tensorIndexes.size(),
3076 for (
unsigned int slotIndex = 0; slotIndex < layer->
GetNumInputSlots(); ++slotIndex)
3078 unsigned int tensorIndex = tensorIndexes[slotIndex];
3080 RegisterConsumerOfTensor(subgraphIndex, tensorIndex, slot);
3084 void TfLiteParser::RegisterOutputSlots(
size_t subgraphIndex,
3085 size_t operatorIndex,
3087 const std::vector<unsigned int>& tensorIndexes)
3089 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3094 fmt::format(
"The number of tensor outputs ({}) does not match the number expected ({})" 3095 " for subgraph:{} operator index:{} {}",
3096 tensorIndexes.size(),
3103 for (
unsigned int slotIndex = 0; slotIndex < layer->
GetNumOutputSlots(); ++slotIndex)
3105 unsigned int tensorIndex = tensorIndexes[slotIndex];
3107 RegisterProducerOfTensor(subgraphIndex, tensorIndex, slot);
3111 void TfLiteParser::SetupInputLayers(
size_t subgraphIndex)
3116 for (
auto const & tensorIdAndPtr : inputs)
3118 auto bindingId = GenerateLayerBindingId(subgraphIndex, tensorIdAndPtr.first);
3120 m_Network->AddInputLayer(bindingId, tensorIdAndPtr.second->name.c_str());
3125 RegisterOutputSlots(subgraphIndex,
3126 VIRTUAL_OPERATOR_ID,
3128 {
static_cast<uint32_t
>(tensorIdAndPtr.first) });
3132 void TfLiteParser::SetupOutputLayers(
size_t subgraphIndex)
3137 for (
auto const & tensorIdAndPtr : outputs)
3139 auto bindingId = GenerateLayerBindingId(subgraphIndex, tensorIdAndPtr.first);
3141 m_Network->AddOutputLayer(bindingId, tensorIdAndPtr.second->name.c_str());
3143 RegisterInputSlots(subgraphIndex,
3144 VIRTUAL_OPERATOR_ID,
3146 {
static_cast<uint32_t
>(tensorIdAndPtr.first) });
3150 void TfLiteParser::SetupConstantLayers(
size_t subgraphIndex)
3154 const auto & subgraphPtr = m_Model->subgraphs[subgraphIndex];
3155 for (
unsigned int subgraphIndex = 0; subgraphIndex < m_SubgraphConnections.size(); ++subgraphIndex)
3157 for (
unsigned int tensorIndex = 0; tensorIndex < m_SubgraphConnections[subgraphIndex].size(); ++tensorIndex)
3159 if (m_SubgraphConnections[subgraphIndex][tensorIndex].outputSlot ==
nullptr &&
3160 m_SubgraphConnections[subgraphIndex][tensorIndex].inputSlots.size() > 0)
3162 TensorRawPtr tensorPtr = subgraphPtr->tensors[tensorIndex].get();
3164 auto tensorAndData = CreateConstTensor(tensorPtr,
3168 std::string layerName = fmt::format(
"Constant:{}", tensorPtr->name);
3170 m_Network->AddConstantLayer(tensorAndData.first, layerName.c_str());
3173 RegisterOutputSlots(subgraphIndex,
3174 VIRTUAL_OPERATOR_ID,
3187 return model->buffers[bufferIndex].get();
3190 template<
typename T>
3191 std::pair<armnn::ConstTensor, TfLiteParser::SupportedDataStorage>
3197 auto constData = CreateConstTensorImpl<T>(bufferPtr,
3201 TfLiteParser::SupportedDataStorage storage(std::move(constData.second));
3202 return std::make_pair(constData.first, std::move(storage));
3205 std::pair<armnn::ConstTensor, TfLiteParser::SupportedDataStorage>
3206 TfLiteParser::CreateConstTensor(
TensorRawPtr tensorPtr,
3211 auto bufferPtr =
GetBuffer(m_Model, tensorPtr->buffer);
3217 return CreateConstTensorAndStoreData<float>(bufferPtr,
3222 return CreateConstTensorAndStoreData<uint8_t>(bufferPtr,
3227 return CreateConstTensorAndStoreData<int8_t>(bufferPtr,
3232 return CreateConstTensorAndStoreData<int8_t>(bufferPtr,
3237 return CreateConstTensorAndStoreData<int32_t>(bufferPtr,
3243 std::stringstream errString;
3244 errString <<
"Unexpected datatype when creating const tensor: " 3246 <<
" shape:" << tensorInfo.GetShape()
3254 const std::string& name)
const 3258 for (
auto const & input : inputs)
3260 if (input.second->name == name)
3262 auto bindingId = GenerateLayerBindingId(subgraphId, input.first);
3263 return std::make_pair(bindingId,
ToTensorInfo(input.second));
3267 std::stringstream bindings;
3268 for (
auto const & input : inputs)
3270 bindings <<
"'" << input.second->name <<
"' ";
3274 fmt::format(
"No input binding found for subgraph:{} and name:{}. " 3275 "Possible inputs are: [{}] {}",
3283 const std::string& name)
const 3287 for (
unsigned int i = 0; i < outputs.size(); ++i)
3289 auto const output = outputs[i];
3290 if (output.second->name == name)
3292 auto bindingId = GenerateLayerBindingId(subgraphId, output.first);
3293 std::vector<unsigned int> shape = m_OverridenOutputShapes.size() > 0 ?
3294 m_OverridenOutputShapes[i] : AsUnsignedVector(output.second->shape);
3295 return std::make_pair(bindingId,
ToTensorInfo(output.second, shape));
3299 std::stringstream bindings;
3300 for (
auto const & output : outputs)
3302 bindings <<
"'" << output.second->name <<
"' ";
3306 fmt::format(
"No output binding found for subgraph:{} and name:{}. " 3307 "Possible outputs are: [{}] {}",
3316 return m_Model->subgraphs.size();
3323 std::vector<std::string> result;
3324 result.reserve(inputs.size());
3325 for (
auto const & input : inputs)
3327 result.push_back(input.second->name);
3336 std::vector<std::string> result;
3337 result.reserve(outputs.size());
3338 for (
auto const & output : outputs)
3340 result.push_back(output.second->name);
3360 TfLiteParser::SupportedDataStorage::SupportedDataStorage(std::unique_ptr<
float[]> && data)
3361 : m_FloatData(std::move(data))
3362 , m_Uint8Data(
nullptr)
3363 , m_Int8Data(
nullptr)
3364 , m_Int32Data(
nullptr)
3368 TfLiteParser::SupportedDataStorage::SupportedDataStorage(std::unique_ptr<uint8_t[]> && data)
3369 : m_FloatData(
nullptr)
3370 , m_Uint8Data(std::move(data))
3371 , m_Int8Data(
nullptr)
3372 , m_Int32Data(
nullptr)
3376 TfLiteParser::SupportedDataStorage::SupportedDataStorage(std::unique_ptr<int8_t[]> && data)
3377 : m_FloatData(
nullptr)
3378 , m_Uint8Data(
nullptr)
3379 , m_Int8Data(std::move(data))
3380 , m_Int32Data(
nullptr)
3384 TfLiteParser::SupportedDataStorage::SupportedDataStorage(std::unique_ptr<int32_t[]> && data)
3385 : m_FloatData(
nullptr)
3386 , m_Uint8Data(
nullptr)
3387 , m_Int8Data(
nullptr)
3388 , 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).
ArgMinMaxFunction m_Function
Specify if the function is to find Min or Max.
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
An ArgMinMaxDescriptor for ArgMinMaxLayer.
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.
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
std::enable_if_t< std::is_unsigned< Source >::value &&std::is_unsigned< Dest >::value, Dest > numeric_cast(Source source)
uint32_t m_PadRight
Padding right value in the width dimension.
A TransposeDescriptor for the TransposeLayer.
A StridedSliceDescriptor for the StridedSliceLayer.
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
int m_Axis
Axis to reduce across the input tensor.
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).
armnn::DataType m_Output_Type
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.