8 #define FLATBUFFERS_LOCALE_INDEPENDENT 0
34 #include <schema_generated.h>
36 #include <flatbuffers/flexbuffers.h>
38 #include <fmt/format.h>
45 #define ARMNN_THROW_PARSE_EXCEPTION(msg) \
47 throw armnn::ParseException( static_cast<const std::stringstream&>( std::stringstream() << msg \
49 << CHECK_LOCATION().AsString()).str()); \
52 using namespace armnn;
58 pTfLiteParserImpl(
new TfLiteParserImpl(options)) {}
60 ITfLiteParser::~ITfLiteParser() =
default;
82 armnn::INetworkPtr ITfLiteParser::CreateNetworkFromBinary(
const std::vector<uint8_t>& binaryContent)
84 return pTfLiteParserImpl->CreateNetworkFromBinary(binaryContent);
88 const std::string& name)
const
90 return pTfLiteParserImpl->GetNetworkInputBindingInfo(subgraphId, name);
94 const std::string& name)
const
96 return pTfLiteParserImpl->GetNetworkOutputBindingInfo(subgraphId, name);
99 size_t ITfLiteParser::GetSubgraphCount()
const
101 return pTfLiteParserImpl->GetSubgraphCount();
104 std::vector<std::string> ITfLiteParser::GetSubgraphInputTensorNames(
size_t subgraphId)
const
106 return pTfLiteParserImpl->GetSubgraphInputTensorNames(subgraphId);
109 std::vector<std::string> ITfLiteParser::GetSubgraphOutputTensorNames(
size_t subgraphId)
const
111 return pTfLiteParserImpl->GetSubgraphOutputTensorNames(subgraphId);
117 const uint32_t VIRTUAL_OPERATOR_ID = std::numeric_limits<uint32_t>::max();
120 size_t subgraphIndex,
123 if (model.get() ==
nullptr)
126 fmt::format(
"{} was called with invalid (null) model. "
127 "Possible reason is that the model is not yet loaded and Unpack(ed). "
133 else if (subgraphIndex >= model->subgraphs.size())
136 fmt::format(
"{} was called with an invalid subgraph index. "
144 #define CHECK_SUBGRAPH(MODEL, SUBGRAPH_INDEX) \
145 CheckSubgraph(MODEL, SUBGRAPH_INDEX, CHECK_LOCATION())
148 size_t subgraphIndex,
149 size_t operatorIndex,
152 if (model.get() ==
nullptr)
155 fmt::format(
"{} was called with invalid (null) model. "
156 "Possible reason is that the model is not yet loaded and Unpack(ed). "
157 "subgraph:{} operator:{} at {}",
163 else if (subgraphIndex >= model->subgraphs.size())
166 fmt::format(
"{} was called with an invalid subgraph index. "
167 "subgraph:{} operator:{} at {}",
173 else if (operatorIndex >= model->subgraphs[subgraphIndex]->operators.size() &&
174 operatorIndex != VIRTUAL_OPERATOR_ID)
177 fmt::format(
"{} was called with an invalid operator index. "
178 "subgraph:{} operator:{} at {}",
186 #define CHECK_MODEL(MODEL, SUBGRAPH_INDEX, OPERATOR_INDEX) \
187 CheckModel(MODEL, SUBGRAPH_INDEX, OPERATOR_INDEX, CHECK_LOCATION())
190 size_t subgraphIndex,
195 if (tensorIndex >= model->subgraphs[subgraphIndex]->tensors.size())
198 fmt::format(
"{} was called with an invalid tensor index. "
199 "subgraph:{} tensor:{} at {}",
207 #define CHECK_TENSOR(MODEL, SUBGRAPH_INDEX, TENSOR_INDEX) \
208 CheckTensor(MODEL, SUBGRAPH_INDEX, TENSOR_INDEX, CHECK_LOCATION())
213 if (rawPtr ==
nullptr)
216 fmt::format(
"{} was called with a null tensor pointer at {}", location.
m_Function, location.
FileLine()));
220 #define CHECK_TENSOR_PTR(TENSOR_PTR) \
221 CheckTensorPtr(TENSOR_PTR, CHECK_LOCATION())
227 if (model.get() ==
nullptr)
230 fmt::format(
"{} was called with invalid (null) model. "
231 "Possible reason is that the model is not yet loaded and Unpack(ed). "
237 else if (bufferIndex >= model->buffers.size())
240 fmt::format(
"{} was called with an invalid buffer index. "
241 "buffer index:{} at {}",
246 else if (model->buffers[bufferIndex].get() ==
nullptr)
249 fmt::format(
"The buffer #{} is null. {}",
255 #define CHECK_BUFFER(MODEL, BUFFER_INDEX) \
256 CheckBuffer(MODEL, BUFFER_INDEX, CHECK_LOCATION())
258 void CheckBufferSize(TfLiteParserImpl::BufferRawPtr bufferPtr,
263 if (bufferPtr ==
nullptr)
266 fmt::format(
"BufferPtr is null for buffer:{}. {}",
273 std::stringstream ss;
274 ss <<
"Buffer #" << bufferId <<
" has " << bufferPtr->data.size() <<
" bytes. "
275 <<
"For tensor: " << tensorInfo.
GetShape()
276 <<
" expecting: " << tensorInfo.
GetNumBytes() <<
" bytes and "
285 const auto& operatorPtr = model->subgraphs[subgraphIndex]->operators[operatorIndex];
286 auto opcodeIndex = operatorPtr->opcode_index;
289 #if defined(ARMNN_POST_TFLITE_2_3)
290 auto opcode = std::max(model->operator_codes[opcodeIndex]->builtin_code,
291 static_cast<tflite::BuiltinOperator
>(model->operator_codes[opcodeIndex]->deprecated_builtin_code));
293 auto opcode = model->operator_codes[opcodeIndex]->builtin_code;
302 TfLiteParserImpl::BufferRawPtr bufferPtr = TfLiteParserImpl::GetBuffer(model, bufferIndex);
303 std::vector<unsigned int> buffer(
info.GetNumElements());
307 ::memcpy(buffer.data(), bufferPtr->data.data(), bufferPtr->data.size());
311 std::vector<uint64_t> uint64Buffer(
info.GetNumElements());
312 ::memcpy(uint64Buffer.data(), bufferPtr->data.data(), bufferPtr->data.size());
313 buffer.assign(std::begin(uint64Buffer), std::end(uint64Buffer));
319 fmt::format(
"Unsupported data type for uint buffer {}, only Signed 32 or Signed 64 are supported. {}",
326 #define CHECK_BUFFER_SIZE(BUFFER_PTR, TENSOR_INFO, BUFFER_ID) \
327 CheckBufferSize(BUFFER_PTR, TENSOR_INFO, BUFFER_ID, CHECK_LOCATION())
329 bool IsActivationSupported(tflite::ActivationFunctionType activationType)
331 switch(activationType)
333 case tflite::ActivationFunctionType_NONE:
334 case tflite::ActivationFunctionType_RELU:
335 case tflite::ActivationFunctionType_RELU6:
336 case tflite::ActivationFunctionType_TANH:
347 #define CHECK_SUPPORTED_FUSED_ACTIVATION(OPTION, SUBGRAPH_INDEX, OPERATOR_INDEX) \
349 if (IsActivationSupported(OPTION->fused_activation_function) == false) \
351 throw ParseException( \
352 fmt::format("TfLite parser doesn't support fused activation: " \
353 "{}/{} in {} subgraph:{} operator:{} at {}", \
354 OPTION->fused_activation_function, \
355 tflite::EnumNameActivationFunctionType(\
356 OPTION->fused_activation_function), \
360 CHECK_LOCATION().FileLine())); \
365 std::vector<unsigned int> AsUnsignedVector(
const std::vector<int32_t>& in)
367 std::vector<unsigned int> result;
368 result.reserve(in.size());
381 bool IsOptionalOperandPresent(
int input)
386 void CalcPadding(uint32_t inputSize,
390 uint32_t& paddingFront,
391 uint32_t& paddingBack,
392 tflite::Padding padding)
396 if (padding == tflite::Padding_SAME)
398 uint32_t outputSize = (inputSize + stride - 1) / stride;
399 uint32_t dilatedSize = filterSize + (dilation - 1) * (filterSize - 1);
400 uint32_t temp = (outputSize - 1) * stride + dilatedSize;
401 if (temp > inputSize)
403 paddingFront = (temp - inputSize) / 2;
404 paddingBack = (temp - inputSize) - paddingFront;
412 void CalcPadding(uint32_t inputSize,
416 uint32_t& paddingFront,
417 uint32_t& paddingBack,
418 tflite::Padding padding,
424 if (padding == tflite::Padding_SAME)
426 uint32_t totalPadding = (inputSize - 1) * stride + filterSize - outputSize;
427 paddingFront = totalPadding / 2;
428 paddingBack = totalPadding - paddingFront;
433 const std::vector<unsigned int>& shape,
434 const bool outputTensor =
false)
439 switch (tensorPtr->type)
441 case tflite::TensorType_UINT8:
444 case tflite::TensorType_FLOAT32:
447 case tflite::TensorType_FLOAT16:
450 case tflite::TensorType_INT8:
451 if (tensorPtr->quantization->zero_point.size() == 1)
462 case tflite::TensorType_INT16:
465 case tflite::TensorType_INT32:
468 case tflite::TensorType_INT64:
471 case tflite::TensorType_BOOL:
478 fmt::format(
"Unsupported data type {} = {} for tensor: {}. {}",
480 tflite::EnumNameTensorType(tensorPtr->type),
487 std::vector<unsigned int> safeShape = shape;
488 if (shape.size() == 0)
490 safeShape.push_back(1);
495 tensorShape =
TensorShape(armnn::numeric_cast<unsigned int>(safeShape.size()), safeShape.data());
499 size_t shapeSignatureSize = tensorPtr->shape_signature.size();
502 if (shapeSignatureSize != 0)
505 if (shapeSignatureSize != shape.size())
509 for (
unsigned int i = 0; i < shapeSignatureSize; ++i)
511 unsigned int dim = tensorPtr->shape_signature[i] > -1 ?
512 static_cast<unsigned int>(tensorPtr->shape_signature[i]) : 0;
513 safeShape.push_back(dim);
517 std::unique_ptr<bool[]> dimMask = std::make_unique<bool[]>(tensorPtr->shape_signature.size());
518 bool batchOnly =
true;
519 for (
unsigned int i = 0; i < tensorPtr->shape_signature.size(); ++i)
521 dimMask[i] = tensorPtr->shape_signature[i] != -1;
523 if (i > 0 && !dimMask[i])
532 tensorShape =
TensorShape(
static_cast<unsigned int>(safeShape.size()), safeShape.data(), dimMask.get());
535 else if (shape.size() == 0)
541 tensorShape =
TensorShape(armnn::numeric_cast<unsigned int>(shape.size()), shape.data());
545 float quantizationScale = 1.0f;
546 int32_t quantizationOffset = 0;
548 if (tensorPtr->quantization.get())
550 if (tensorPtr->quantization->scale.size() <= 1)
555 if (tensorPtr->quantization->scale.size() == 1)
557 quantizationScale = tensorPtr->quantization->scale[0];
559 if (tensorPtr->quantization->zero_point.size() == 1)
563 quantizationOffset = armnn::numeric_cast<int32_t>(tensorPtr->quantization->zero_point[0]);
574 std::vector<float> quantizationScales;
575 std::vector<int32_t> quantizationOffsets;
578 std::copy(tensorPtr->quantization->scale.begin(),
579 tensorPtr->quantization->scale.end(),
580 std::back_inserter(quantizationScales));
586 armnn::numeric_cast<unsigned int>(tensorPtr->quantization->quantized_dimension));
601 const bool outputTensor =
false)
603 auto const& dimensions = AsUnsignedVector(tensorPtr->shape);
604 return ToTensorInfo(tensorPtr, dimensions, outputTensor);
608 std::pair<armnn::ConstTensor, std::unique_ptr<T[]>>
628 if (permutationVector.
has_value() && permutationVector.
value().GetSize() > 0)
632 reinterpret_cast<const T*
>(bufferPtr->data.data()), data.get(),
sizeof(T));
636 ::memcpy(data.get(), bufferPtr->data.data(), tensorInfo.
GetNumBytes());
642 return std::make_pair(
ConstTensor(tensorInfo, data.get()), std::move(data));
655 if (actualSize != expected.size())
660 for (
unsigned int i = 0u; i < actualSize; i++)
662 if (expected[i] < 0 ||
663 actual[i] !=
static_cast<unsigned int>(expected[i]))
674 std::vector<int32_t> expectedVec;
677 expectedVec.push_back(expected[i]);
682 void CheckMatchingQuantization(
const TensorInfo& first,
684 const std::string& descName,
685 std::string
const& firstName,
686 std::string
const& secondName)
698 if (firstDataType != secondDataType)
701 " must be of the same quantized type, " +
709 " must have the same quantization space, " +
719 auto shape = tensorPtr->shape;
725 auto shapeSig = tensorPtr->shape_signature;
727 if (shapeSig.empty())
732 for (
unsigned int i = 0; i < shapeSig.size() ; ++i)
734 if (shapeSig[i] == -1)
746 , m_Network(nullptr, nullptr)
750 m_ParserFunctions[tflite::BuiltinOperator_ABS] = &TfLiteParserImpl::ParseAbs;
751 m_ParserFunctions[tflite::BuiltinOperator_ADD] = &TfLiteParserImpl::ParseAdd;
752 m_ParserFunctions[tflite::BuiltinOperator_ARG_MIN] = &TfLiteParserImpl::ParseArgMin;
753 m_ParserFunctions[tflite::BuiltinOperator_ARG_MAX] = &TfLiteParserImpl::ParseArgMax;
754 m_ParserFunctions[tflite::BuiltinOperator_AVERAGE_POOL_2D] = &TfLiteParserImpl::ParseAveragePool2D;
755 m_ParserFunctions[tflite::BuiltinOperator_BATCH_TO_SPACE_ND] = &TfLiteParserImpl::ParseBatchToSpaceND;
756 m_ParserFunctions[tflite::BuiltinOperator_BATCH_MATMUL] = &TfLiteParserImpl::ParseBatchMatMul;
757 m_ParserFunctions[tflite::BuiltinOperator_BROADCAST_TO] = &TfLiteParserImpl::ParseBroadcastTo;
758 m_ParserFunctions[tflite::BuiltinOperator_CEIL] = &TfLiteParserImpl::ParseCeil;
759 m_ParserFunctions[tflite::BuiltinOperator_CAST] = &TfLiteParserImpl::ParseCast;
760 m_ParserFunctions[tflite::BuiltinOperator_CONCATENATION] = &TfLiteParserImpl::ParseConcatenation;
761 m_ParserFunctions[tflite::BuiltinOperator_CONV_2D] = &TfLiteParserImpl::ParseConv2D;
763 #if defined(ARMNN_POST_TFLITE_2_4)
764 m_ParserFunctions[tflite::BuiltinOperator_CONV_3D] = &TfLiteParserImpl::ParseConv3D;
766 m_ParserFunctions[tflite::BuiltinOperator_CUSTOM] = &TfLiteParserImpl::ParseCustomOperator;
767 m_ParserFunctions[tflite::BuiltinOperator_DEPTH_TO_SPACE] = &TfLiteParserImpl::ParseDepthToSpace;
768 m_ParserFunctions[tflite::BuiltinOperator_DEPTHWISE_CONV_2D] = &TfLiteParserImpl::ParseDepthwiseConv2D;
769 m_ParserFunctions[tflite::BuiltinOperator_DEQUANTIZE] = &TfLiteParserImpl::ParseDequantize;
770 m_ParserFunctions[tflite::BuiltinOperator_DIV] = &TfLiteParserImpl::ParseDiv;
771 m_ParserFunctions[tflite::BuiltinOperator_ELU] = &TfLiteParserImpl::ParseElu;
772 m_ParserFunctions[tflite::BuiltinOperator_EQUAL] = &TfLiteParserImpl::ParseEqual;
773 m_ParserFunctions[tflite::BuiltinOperator_EXP] = &TfLiteParserImpl::ParseExp;
774 m_ParserFunctions[tflite::BuiltinOperator_EXPAND_DIMS] = &TfLiteParserImpl::ParseExpandDims;
775 m_ParserFunctions[tflite::BuiltinOperator_FLOOR_DIV] = &TfLiteParserImpl::ParseFloorDiv;
776 m_ParserFunctions[tflite::BuiltinOperator_FULLY_CONNECTED] = &TfLiteParserImpl::ParseFullyConnected;
777 m_ParserFunctions[tflite::BuiltinOperator_GATHER] = &TfLiteParserImpl::ParseGather;
778 m_ParserFunctions[tflite::BuiltinOperator_GELU] = &TfLiteParserImpl::ParseGelu;
779 m_ParserFunctions[tflite::BuiltinOperator_GATHER_ND] = &TfLiteParserImpl::ParseGatherNd;
780 m_ParserFunctions[tflite::BuiltinOperator_GREATER] = &TfLiteParserImpl::ParseGreater;
781 m_ParserFunctions[tflite::BuiltinOperator_GREATER_EQUAL] = &TfLiteParserImpl::ParseGreaterOrEqual;
782 m_ParserFunctions[tflite::BuiltinOperator_HARD_SWISH] = &TfLiteParserImpl::ParseHardSwish;
783 m_ParserFunctions[tflite::BuiltinOperator_LEAKY_RELU] = &TfLiteParserImpl::ParseLeakyRelu;
784 m_ParserFunctions[tflite::BuiltinOperator_LESS] = &TfLiteParserImpl::ParseLess;
785 m_ParserFunctions[tflite::BuiltinOperator_LESS_EQUAL] = &TfLiteParserImpl::ParseLessOrEqual;
786 m_ParserFunctions[tflite::BuiltinOperator_LOCAL_RESPONSE_NORMALIZATION]
787 = &TfLiteParserImpl::ParseLocalResponseNormalization;
788 m_ParserFunctions[tflite::BuiltinOperator_LOG] = &TfLiteParserImpl::ParseLog;
789 m_ParserFunctions[tflite::BuiltinOperator_LOGICAL_NOT] = &TfLiteParserImpl::ParseLogicalNot;
790 m_ParserFunctions[tflite::BuiltinOperator_LOGISTIC] = &TfLiteParserImpl::ParseLogistic;
791 m_ParserFunctions[tflite::BuiltinOperator_LOG_SOFTMAX] = &TfLiteParserImpl::ParseLogSoftmax;
792 m_ParserFunctions[tflite::BuiltinOperator_L2_NORMALIZATION] = &TfLiteParserImpl::ParseL2Normalization;
793 m_ParserFunctions[tflite::BuiltinOperator_MAX_POOL_2D] = &TfLiteParserImpl::ParseMaxPool2D;
794 m_ParserFunctions[tflite::BuiltinOperator_MAXIMUM] = &TfLiteParserImpl::ParseMaximum;
795 m_ParserFunctions[tflite::BuiltinOperator_MEAN] = &TfLiteParserImpl::ParseMean;
796 m_ParserFunctions[tflite::BuiltinOperator_MINIMUM] = &TfLiteParserImpl::ParseMinimum;
797 m_ParserFunctions[tflite::BuiltinOperator_MIRROR_PAD] = &TfLiteParserImpl::ParseMirrorPad;
798 m_ParserFunctions[tflite::BuiltinOperator_MUL] = &TfLiteParserImpl::ParseMul;
799 m_ParserFunctions[tflite::BuiltinOperator_NEG] = &TfLiteParserImpl::ParseNeg;
800 m_ParserFunctions[tflite::BuiltinOperator_NOT_EQUAL] = &TfLiteParserImpl::ParseNotEqual;
801 m_ParserFunctions[tflite::BuiltinOperator_PACK] = &TfLiteParserImpl::ParsePack;
802 m_ParserFunctions[tflite::BuiltinOperator_PAD] = &TfLiteParserImpl::ParsePad;
803 m_ParserFunctions[tflite::BuiltinOperator_PADV2] = &TfLiteParserImpl::ParsePad;
804 m_ParserFunctions[tflite::BuiltinOperator_POW] = &TfLiteParserImpl::ParsePower;
805 m_ParserFunctions[tflite::BuiltinOperator_PRELU] = &TfLiteParserImpl::ParsePrelu;
806 m_ParserFunctions[tflite::BuiltinOperator_QUANTIZE] = &TfLiteParserImpl::ParseQuantize;
807 m_ParserFunctions[tflite::BuiltinOperator_RELU] = &TfLiteParserImpl::ParseRelu;
808 m_ParserFunctions[tflite::BuiltinOperator_RELU6] = &TfLiteParserImpl::ParseRelu6;
809 m_ParserFunctions[tflite::BuiltinOperator_REDUCE_MAX] = &TfLiteParserImpl::ParseReduceMax;
810 m_ParserFunctions[tflite::BuiltinOperator_REDUCE_MIN] = &TfLiteParserImpl::ParseReduceMin;
811 m_ParserFunctions[tflite::BuiltinOperator_REDUCE_PROD] = &TfLiteParserImpl::ParseReduceProd;
812 m_ParserFunctions[tflite::BuiltinOperator_RESHAPE] = &TfLiteParserImpl::ParseReshape;
813 m_ParserFunctions[tflite::BuiltinOperator_RESIZE_BILINEAR] = &TfLiteParserImpl::ParseResizeBilinear;
814 m_ParserFunctions[tflite::BuiltinOperator_RESIZE_NEAREST_NEIGHBOR] = &TfLiteParserImpl::ParseResizeNearestNeighbor;
815 m_ParserFunctions[tflite::BuiltinOperator_REVERSE_V2] = &TfLiteParserImpl::ParseReverseV2;
816 m_ParserFunctions[tflite::BuiltinOperator_RSQRT] = &TfLiteParserImpl::ParseRsqrt;
817 m_ParserFunctions[tflite::BuiltinOperator_SCATTER_ND] = &TfLiteParserImpl::ParseScatterNd;
818 m_ParserFunctions[tflite::BuiltinOperator_SQRT] = &TfLiteParserImpl::ParseSqrt;
819 m_ParserFunctions[tflite::BuiltinOperator_SHAPE] = &TfLiteParserImpl::ParseShape;
820 m_ParserFunctions[tflite::BuiltinOperator_SIN] = &TfLiteParserImpl::ParseSin;
821 m_ParserFunctions[tflite::BuiltinOperator_SLICE] = &TfLiteParserImpl::ParseSlice;
822 m_ParserFunctions[tflite::BuiltinOperator_SOFTMAX] = &TfLiteParserImpl::ParseSoftmax;
823 m_ParserFunctions[tflite::BuiltinOperator_SPACE_TO_BATCH_ND] = &TfLiteParserImpl::ParseSpaceToBatchND;
824 m_ParserFunctions[tflite::BuiltinOperator_SPACE_TO_DEPTH] = &TfLiteParserImpl::ParseSpaceToDepth;
825 m_ParserFunctions[tflite::BuiltinOperator_SPLIT] = &TfLiteParserImpl::ParseSplit;
826 m_ParserFunctions[tflite::BuiltinOperator_SPLIT_V] = &TfLiteParserImpl::ParseSplitV;
827 m_ParserFunctions[tflite::BuiltinOperator_SQUEEZE] = &TfLiteParserImpl::ParseSqueeze;
828 m_ParserFunctions[tflite::BuiltinOperator_SQUARE] = &TfLiteParserImpl::ParseSquare;
829 m_ParserFunctions[tflite::BuiltinOperator_SQUARED_DIFFERENCE] = &TfLiteParserImpl::ParseSquaredDifference;
830 m_ParserFunctions[tflite::BuiltinOperator_STRIDED_SLICE] = &TfLiteParserImpl::ParseStridedSlice;
831 m_ParserFunctions[tflite::BuiltinOperator_SUB] = &TfLiteParserImpl::ParseSub;
832 m_ParserFunctions[tflite::BuiltinOperator_SUM] = &TfLiteParserImpl::ParseSum;
833 m_ParserFunctions[tflite::BuiltinOperator_TANH] = &TfLiteParserImpl::ParseTanH;
834 m_ParserFunctions[tflite::BuiltinOperator_TILE] = &TfLiteParserImpl::ParseTile;
835 m_ParserFunctions[tflite::BuiltinOperator_TRANSPOSE] = &TfLiteParserImpl::ParseTranspose;
836 m_ParserFunctions[tflite::BuiltinOperator_TRANSPOSE_CONV] = &TfLiteParserImpl::ParseTransposeConv;
837 m_ParserFunctions[tflite::BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM]
838 = &TfLiteParserImpl::ParseUnidirectionalSequenceLSTM;
839 m_ParserFunctions[tflite::BuiltinOperator_UNPACK] = &TfLiteParserImpl::ParseUnpack;
842 m_CustomParserFunctions[
"TFLite_Detection_PostProcess"] = &TfLiteParserImpl::ParseDetectionPostProcess;
846 size_t operatorIndex,
849 const auto& subgraphPtr = m_Model->subgraphs[subgraphIndex];
850 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
853 auto search = armnnTfLiteParser::TfLiteParserImpl::m_TensorInfos.find(inputId);
855 if (search != m_TensorInfos.end())
857 return m_TensorInfos[inputId];
862 m_TensorInfos.insert({ inputId, tensorInfo });
867 armnn::TensorInfo TfLiteParserImpl::OutputTensorInfoFromInputs(
size_t subgraphIndex,
868 size_t operatorIndex,
871 std::vector<int> inputs)
873 const auto& subgraphPtr = m_Model->subgraphs[subgraphIndex];
874 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
878 auto outputSearch = armnnTfLiteParser::TfLiteParserImpl::m_TensorInfos.find(outputId);
880 if (outputSearch != m_TensorInfos.end())
882 return m_TensorInfos[outputId];
885 const auto& outputTensorPtr = subgraphPtr->tensors[outputId].get();
888 if (IsDynamic(outputTensorPtr))
894 inputs.emplace_back(i);
898 std::vector<armnn::TensorShape> inputShapes;
900 for (
unsigned int i = 0; i < inputs.size(); ++i)
903 auto search = armnnTfLiteParser::TfLiteParserImpl::m_TensorInfos.find(inputId);
905 if (search != m_TensorInfos.end())
907 auto &inputTensorInfo = m_TensorInfos[inputId];
908 inputShapes.push_back(inputTensorInfo.GetShape());
913 m_TensorInfos.insert({ inputId, inputTensorInfo});
914 inputShapes.push_back(inputTensorInfo.GetShape());
920 m_TensorInfos.insert({ outputId, tensor});
924 armnn::TensorInfo TfLiteParserImpl::OutputTensorInfoFromShapes(
size_t subgraphIndex,
925 size_t operatorIndex,
928 std::vector<armnn::TensorShape> inputShapes)
930 const auto& subgraphPtr = m_Model->subgraphs[subgraphIndex];
931 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
934 const auto& outputTensorPtr = subgraphPtr->tensors[outputId].get();
937 if (IsDynamic(outputTensorPtr))
942 m_TensorInfos.insert({ outputId, tensor});
946 void TfLiteParserImpl::ResetParser()
950 m_SubgraphConnections.clear();
951 m_OverriddenOutputShapes.clear();
952 m_ConstantsToDequantize.clear();
953 m_ConstantsToBeCreated.clear();
954 m_TensorInfos.clear();
961 return CreateNetworkFromModel();
968 return CreateNetworkFromModel();
975 m_Model = std::move(model);
977 return CreateNetworkFromModel();
980 INetworkPtr TfLiteParserImpl::CreateNetworkFromModel()
987 if (m_Options.value().m_InferAndValidate)
991 {
"InferAndValidate",
true }
994 networkOptions.push_back(shapeInferenceMethodOption);
996 if (m_Options.value().m_AllowExpandedDims)
1000 {
"AllowExpandedDims",
true }
1003 networkOptions.push_back(shapeInferenceMethodOption);
1006 m_Network = INetwork::Create(networkOptions);
1008 if (m_Model.get() ==
nullptr)
1016 size_t subgraphIndex = 0;
1017 uint8_t usableSubgraphs = 0;
1018 for (
size_t i = 0; i < m_Model->subgraphs.size(); i++)
1020 if (m_Model->subgraphs[i]->name.rfind(
"VALIDATION:", 0) != 0)
1027 if (usableSubgraphs > 1)
1030 fmt::format(
"Current TfLite parser only supports 1 non validation subgraph. This model has: {} {}",
1034 size_t operatorIndex = 0;
1037 const SubgraphPtr& subgraph = m_Model->subgraphs[subgraphIndex];
1038 SetupInputLayerTensorInfos(subgraphIndex);
1039 SetupConstantLayerTensorInfos(subgraphIndex);
1041 m_SubgraphConnections.emplace_back(subgraph->tensors.size());
1044 const auto& opCodePtr = m_Model->operator_codes[op->opcode_index];
1047 #if defined(ARMNN_POST_TFLITE_2_3)
1048 auto builtinCode = std::max(opCodePtr->builtin_code,
1049 static_cast<tflite::BuiltinOperator
>(opCodePtr->deprecated_builtin_code));
1051 auto builtinCode = opCodePtr->builtin_code;
1054 if (builtinCode > tflite::BuiltinOperator_MAX)
1056 throw ParseException(fmt::format(
"Operator code {} is out of range 0-{}. "
1057 "subgraph:{} operator idx:{}. {}",
1058 builtinCode, tflite::BuiltinOperator_MAX, subgraphIndex,
1063 auto& parserFunction = m_ParserFunctions[builtinCode];
1064 (this->*parserFunction)(subgraphIndex, operatorIndex);
1068 SetupInputLayers(subgraphIndex);
1069 SetupOutputLayers(subgraphIndex);
1070 SetupConstantLayers(subgraphIndex);
1074 std::stringstream errorString;
1075 errorString <<
"Failed to parse operator #" << operatorIndex <<
" within subgraph #"
1076 << subgraphIndex <<
" error: " << e.
what();
1078 std::stringstream errors;
1079 errors << errorString.str() <<
"\n";
1084 for (subgraphIndex = 0; subgraphIndex < m_SubgraphConnections.size(); ++subgraphIndex)
1086 for (
size_t tensorIndex = 0; tensorIndex < m_SubgraphConnections[subgraphIndex].size(); ++tensorIndex)
1088 if (m_SubgraphConnections[subgraphIndex][tensorIndex].outputSlot !=
nullptr)
1090 for (
size_t inputSlotIdx = 0;
1091 inputSlotIdx < m_SubgraphConnections[subgraphIndex][tensorIndex].inputSlots.size();
1094 m_SubgraphConnections[subgraphIndex][tensorIndex].outputSlot->Connect(
1095 *(m_SubgraphConnections[subgraphIndex][tensorIndex].inputSlots[inputSlotIdx]));
1100 return std::move(m_Network);
1107 return (TfLiteParserImpl::IsConstTensor(tensorPtr) && inputDataType == DataType::Float32 &&
1108 (tensorDataType == DataType::QAsymmU8 ||
1109 tensorDataType == DataType::QAsymmS8 ||
1110 tensorDataType == DataType::QSymmS8 ||
1111 tensorDataType == DataType::Signed32 ||
1112 tensorDataType == DataType::Signed64));
1115 void TfLiteParserImpl::RegisterProducerOfTensor(
size_t subgraphIndex,
1121 TensorSlots & tensorSlots = m_SubgraphConnections[subgraphIndex][tensorIndex];
1127 if (tensorSlots.outputSlot !=
nullptr)
1129 throw ParseException(fmt::format(
"Another layer has already registered itself as the producer of "
1130 "subgraph:{} tensor:{} {}",
1136 tensorSlots.outputSlot = slot;
1139 void TfLiteParserImpl::RegisterConsumerOfTensor(
size_t subgraphIndex,
1145 TensorSlots& tensorSlots = m_SubgraphConnections[subgraphIndex][tensorIndex];
1146 tensorSlots.inputSlots.push_back(slot);
1149 void TfLiteParserImpl::ParseCustomOperator(
size_t subgraphIndex,
size_t operatorIndex)
1151 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1154 auto customParserFunction = &TfLiteParserImpl::ParseUnsupportedOperator;
1157 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1158 const auto& customCode = m_Model->operator_codes[operatorPtr->opcode_index]->custom_code;
1161 auto iterator = m_CustomParserFunctions.find(customCode);
1162 if (iterator != m_CustomParserFunctions.end())
1164 customParserFunction = iterator->second;
1168 (this->*customParserFunction)(subgraphIndex, operatorIndex);
1171 void TfLiteParserImpl::ParseUnsupportedOperator(
size_t subgraphIndex,
size_t operatorIndex)
1173 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1175 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1177 auto opcodeIndex = operatorPtr->opcode_index;
1180 #if defined(ARMNN_POST_TFLITE_2_3)
1181 auto opcode = std::max(m_Model->operator_codes[opcodeIndex]->builtin_code,
1182 static_cast<tflite::BuiltinOperator
>(m_Model->operator_codes[opcodeIndex]->deprecated_builtin_code));
1184 auto opcode = m_Model->operator_codes[opcodeIndex]->builtin_code;
1187 if (!m_Options || !m_Options.value().m_StandInLayerForUnsupported)
1191 fmt::format(
"Operator not supported. "
1192 "subgraph:{} operator:{} "
1193 "opcode_index:{} opcode:{} / {} {}",
1198 tflite::EnumNameBuiltinOperator(opcode),
1202 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1203 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1205 const unsigned int numInputs = armnn::numeric_cast<unsigned int>(inputs.size());
1206 const unsigned int numOutputs = armnn::numeric_cast<unsigned int>(outputs.size());
1209 auto layerName = fmt::format(
"StandIn:{}:{}:{}", subgraphIndex, operatorIndex, opcode);
1212 IConnectableLayer* layer = m_Network->AddStandInLayer(descriptor, layerName.c_str());
1220 for (
unsigned int i = 0u; i < numOutputs; ++i)
1225 auto inputTensorIds = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1226 auto outputTensorIds = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1228 RegisterInputSlots(subgraphIndex, operatorIndex, layer, inputTensorIds);
1229 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIds);
1232 void TfLiteParserImpl::ParseCast(
size_t subgraphIndex,
size_t operatorIndex)
1234 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1236 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1238 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1241 auto layerName = fmt::format(
"Cast:{}:{}", subgraphIndex, operatorIndex);
1251 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
1254 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1255 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1257 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1258 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
1261 void TfLiteParserImpl::ParseConv2D(
size_t subgraphIndex,
size_t operatorIndex)
1263 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1265 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1266 const auto* options = operatorPtr->builtin_options.AsConv2DOptions();
1270 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1271 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1275 inputs.size() == 3 ?
1283 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
1284 armnn::TensorInfo filterTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
1287 unsigned int inputHeight = inputTensorInfo.
GetShape()[1];
1288 unsigned int inputWidth = inputTensorInfo.
GetShape()[2];
1292 unsigned int filterHeight = filterTensorInfo.
GetShape()[1];
1293 unsigned int filterWidth = filterTensorInfo.
GetShape()[2];
1295 CalcPadding(inputHeight, filterHeight, desc.
m_StrideY,
1297 CalcPadding(inputWidth, filterWidth, desc.
m_StrideX,
1302 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1303 std::vector<unsigned int> tensorIndexesToRegister = { inputTensorIndexes[0], inputTensorIndexes[1] };
1305 auto layerName = fmt::format(
"Conv2D:{}:{}", subgraphIndex, operatorIndex);
1308 if (ShouldConstantTensorBeConverted(inputs[1], inputTensorInfo.
GetDataType(), filterTensorInfo.
GetDataType()))
1310 m_ConstantsToDequantize.emplace_back(inputs[1]->buffer);
1315 armnn::TensorInfo biasTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
1318 tensorIndexesToRegister.emplace_back(inputTensorIndexes[2]);
1320 if (ShouldConstantTensorBeConverted(inputs[2], inputTensorInfo.
GetDataType(), biasTensorInfo.
GetDataType()))
1322 m_ConstantsToDequantize.emplace_back(inputs[2]->buffer);
1332 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
1337 RegisterInputSlots(subgraphIndex, operatorIndex, layer, tensorIndexesToRegister);
1339 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
1341 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1342 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, { outputTensorIndexes[0] });
1346 #if defined(ARMNN_POST_TFLITE_2_4)
1347 void TfLiteParserImpl::ParseConv3D(
size_t subgraphIndex,
size_t operatorIndex)
1349 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1351 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1352 const auto* options = operatorPtr->builtin_options.AsConv3DOptions();
1366 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1369 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1372 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
1373 armnn::TensorInfo filterTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
1376 unsigned int inputDepth = inputTensorInfo.
GetShape()[1];
1377 unsigned int inputHeight = inputTensorInfo.
GetShape()[2];
1378 unsigned int inputWidth = inputTensorInfo.
GetShape()[3];
1381 unsigned int filterDepth = filterTensorInfo.
GetShape()[0];
1382 unsigned int filterHeight = filterTensorInfo.
GetShape()[1];
1383 unsigned int filterWidth = filterTensorInfo.
GetShape()[2];
1385 CalcPadding(inputDepth, filterDepth, desc.
m_StrideZ,
1387 CalcPadding(inputHeight, filterHeight, desc.
m_StrideY,
1389 CalcPadding(inputWidth, filterWidth, desc.
m_StrideX,
1392 auto filterTensorAndData = CreateConstTensorNonPermuted(inputs[1], filterTensorInfo, inputTensorInfo.
GetDataType());
1394 auto layerName = fmt::format(
"Conv3D:{}:{}", subgraphIndex, operatorIndex);
1396 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1399 std::vector<unsigned int> tensorIndexesToRegister = {inputTensorIndexes[0], inputTensorIndexes[1]};
1401 if (inputs.size() == 3)
1406 tensorIndexesToRegister.emplace_back(inputTensorIndexes[2]);
1417 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
1421 RegisterInputSlots(subgraphIndex, operatorIndex, layer, tensorIndexesToRegister);
1423 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
1425 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1426 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1430 void TfLiteParserImpl::ParseDepthwiseConv2D(
size_t subgraphIndex,
size_t operatorIndex)
1432 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1434 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1435 const auto* options = operatorPtr->builtin_options.AsDepthwiseConv2DOptions();
1445 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1447 if (inputs.size() == 3)
1452 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1457 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
1458 armnn::TensorInfo filterTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
1461 unsigned int inputHeight = inputTensorInfo.
GetShape()[1];
1462 unsigned int inputWidth = inputTensorInfo.
GetShape()[2];
1465 unsigned int filterHeight = filterTensorInfo.
GetShape()[1];
1466 unsigned int filterWidth = filterTensorInfo.
GetShape()[2];
1468 CalcPadding(inputHeight, filterHeight, desc.
m_StrideY,
1470 CalcPadding(inputWidth, filterWidth, desc.
m_StrideX,
1474 auto layerName = fmt::format(
"DepthwiseConv2D:{}:{}", subgraphIndex, operatorIndex);
1476 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1479 std::vector<unsigned int> tensorIndexesToRegister = {inputTensorIndexes[0], inputTensorIndexes[1]};
1486 TensorInfo biasTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
1489 tensorIndexesToRegister.emplace_back(inputTensorIndexes[2]);
1498 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
1503 RegisterInputSlots(subgraphIndex, operatorIndex, layer, tensorIndexesToRegister);
1505 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
1507 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1508 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1511 void TfLiteParserImpl::ParseDequantize(
size_t subgraphIndex,
size_t operatorIndex)
1513 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1515 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1518 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1521 auto layerName = fmt::format(
"Dequantize:{}:{}", subgraphIndex, operatorIndex);
1531 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
1534 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1535 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1537 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1538 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
1541 void TfLiteParserImpl::ParseExpandDims(
size_t subgraphIndex,
size_t operatorIndex)
1543 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1545 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1548 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1551 auto layerName = fmt::format(
"ExpandDims:{}:{}", subgraphIndex, operatorIndex);
1553 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
1555 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1557 armnn::TensorInfo axisTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
1560 if (axisBufferPtr ==
nullptr)
1562 throw ParseException(fmt::format(
"{}: Operation has invalid inputs. Failed to read axis.",
1567 ::memcpy(axisData.data(), axisBufferPtr->data.data(), axisTensorInfo.
GetNumBytes());
1568 int32_t axis = axisData[0];
1571 auto outputRank = inputRank + 1;
1572 if((axis < -1 * outputRank) || (outputRank <= axis))
1574 throw ParseException(fmt::format(
"{}: Axis {} is not within [-{}, {}) range.",
1578 axis = axis < 0 ? (axis + outputRank) : axis;
1580 std::vector<unsigned int> shape(
static_cast<unsigned int>(outputRank));
1581 unsigned int inputShapeIndex = 0;
1582 for (
unsigned int i = 0; i < static_cast<unsigned int>(outputRank); ++i)
1584 if (i ==
static_cast<unsigned int>(axis))
1590 shape[i] = inputTensorInfo.
GetShape()[inputShapeIndex];
1599 IConnectableLayer* layer = m_Network->AddReshapeLayer(reshapeDesc, layerName.c_str());
1608 m_TensorInfos[outputTensorIds[0]] = outputTensorInfo;
1610 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1611 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1613 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1614 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1617 void TfLiteParserImpl::ParseTranspose(
size_t subgraphIndex,
size_t operatorIndex)
1619 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1621 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1624 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1627 auto layerName = fmt::format(
"Transpose:{}:{}", subgraphIndex, operatorIndex);
1630 if (inputs.size() == 2)
1632 armnn::TensorInfo permuteTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
1635 std::vector<unsigned int> permuteShape(numPermVecElements);
1636 ::memcpy(permuteShape.data(), permuteBufferPtr->data.data(), permuteTensorInfo.
GetNumBytes());
1641 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
1643 IConnectableLayer* layer = m_Network->AddTransposeLayer(desc, layerName.c_str());
1651 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
1652 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1655 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1656 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1658 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1659 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1662 void TfLiteParserImpl::ParseTransposeConv(
size_t subgraphIndex,
size_t operatorIndex)
1664 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1666 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1667 const auto* options = operatorPtr->builtin_options.AsTransposeConvOptions();
1675 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1676 if (inputs.size() == 4)
1685 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1689 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
1690 armnn::TensorInfo filterTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
1693 const unsigned int inputHeight = inputTensorInfo.
GetShape()[1];
1694 const unsigned int inputWidth = inputTensorInfo.
GetShape()[2];
1696 const unsigned int filterHeight = filterTensorInfo.
GetShape()[1];
1697 const unsigned int filterWidth = filterTensorInfo.
GetShape()[2];
1703 if (inputs[0] && IsConstTensor(inputs[0]))
1705 armnn::TensorInfo tensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
1708 if (tensorInfo.
GetDataType() == DataType::Signed32)
1710 ::memcpy(output_shape.data(),
GetBuffer(m_Model, inputs[0]->buffer)->data.data(), tensorInfo.
GetNumBytes());
1712 if (tensorInfo.
GetDataType() == DataType::QAsymmU8)
1716 output_shape[i] =
GetBuffer(m_Model, inputs[0]->buffer)->data.data()[i];
1720 for (
int dimension : output_shape)
1722 desc.
m_OutputShape.push_back(
static_cast<unsigned int>(dimension));
1730 CalcPadding(inputHeight,
1739 CalcPadding(inputWidth,
1750 CalcPadding(inputHeight,
1758 CalcPadding(inputWidth,
1767 auto filterTensorAndData = CreateConstTensorNonPermuted(inputs[1], filterTensorInfo, inputTensorInfo.
GetDataType());
1770 auto layerName = fmt::format(
"TransposeConv:{}:{}", subgraphIndex, operatorIndex);
1774 auto biasTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 3);
1775 auto biasConstTensor = CreateConstTensorNonPermuted(inputs[3], biasTensorInfo, inputTensorInfo.
GetDataType());
1776 layer = m_Network->AddTransposeConvolution2dLayer(desc,
1777 filterTensorAndData.first,
1778 biasConstTensor.first,
1783 layer = m_Network->AddTransposeConvolution2dLayer(desc,
1784 filterTensorAndData.first,
1795 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0 , { 2, 1 });
1799 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1800 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[2]});
1802 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1803 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1806 void TfLiteParserImpl::ParseAveragePool2D(
size_t subgraphIndex,
size_t operatorIndex)
1808 ParsePool(subgraphIndex, operatorIndex, PoolingAlgorithm::Average);
1811 void TfLiteParserImpl::ParseBatchMatMul(
size_t subgraphIndex,
size_t operatorIndex)
1813 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1815 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1818 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1821 auto layerName = fmt::format(
"BatchMatMul:{}:{}", subgraphIndex, operatorIndex);
1823 TensorInfo inputXTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
1824 TensorInfo inputYTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
1826 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1827 const auto* options = operatorPtr->builtin_options.AsBatchMatMulOptions();
1836 IConnectableLayer* layer = m_Network->AddBatchMatMulLayer(descriptor, layerName.c_str());
1844 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
1847 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1848 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
1850 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1851 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1854 void TfLiteParserImpl::ParseBatchToSpaceND(
size_t subgraphIndex,
size_t operatorIndex)
1856 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1858 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1861 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1864 armnn::TensorInfo blockShapeTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
1867 armnn::TensorInfo cropsTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
1870 std::vector<unsigned int> blockShape(blockShapeTensorInfo.
GetNumElements());
1871 ::memcpy(blockShape.data(), blockShapeBufferPtr->data.data(), blockShapeTensorInfo.
GetNumBytes());
1873 std::vector<unsigned int> cropsVector(cropsTensorInfo.
GetNumElements());
1874 ::memcpy(cropsVector.data(), cropsBufferPtr->data.data(), cropsTensorInfo.
GetNumBytes());
1877 std::vector<std::pair<unsigned int, unsigned int>> crops;
1878 for (
unsigned int i = 0; i < cropsTensorInfo.
GetNumElements() / step; ++i)
1880 crops.emplace_back(cropsVector[i * step], cropsVector[i * step + 1]);
1888 auto layerName = fmt::format(
"BatchToSpaceND:{}:{}", subgraphIndex, operatorIndex);
1890 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
1892 IConnectableLayer* layer = m_Network->AddBatchToSpaceNdLayer(desc, layerName.c_str());
1900 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
1901 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1904 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1905 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1907 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1908 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1911 void TfLiteParserImpl::ParseBroadcastTo(
size_t subgraphIndex,
size_t operatorIndex)
1913 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1915 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1918 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1925 auto layerName = fmt::format(
"Broadcast_to:{}:{}", subgraphIndex, operatorIndex);
1929 auto shapeBufferPtr =
GetBuffer(m_Model, inputs[1]->buffer);
1930 if (shapeBufferPtr !=
nullptr)
1932 std::vector<unsigned int> targetShape;
1934 auto shapeData =
reinterpret_cast<const int32_t*
>(shapeBufferPtr->data.data());
1937 for (
unsigned int i = 0; i < numElement; ++i)
1939 targetShape.push_back(armnn::numeric_cast<unsigned int>(shapeData[i]));
1949 "data and output shape are not found in the buffer.");
1959 IConnectableLayer* layer = m_Network->AddBroadcastToLayer(descriptor, layerName.c_str());
1964 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1965 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1967 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1968 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1971 void TfLiteParserImpl::ParseL2Normalization(
size_t subgraphIndex,
size_t operatorIndex)
1973 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1975 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1978 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1983 auto layerName = fmt::format(
"L2Normalization:{}:{}", subgraphIndex, operatorIndex);
1984 IConnectableLayer* layer = m_Network->AddL2NormalizationLayer(desc, layerName.c_str());
1992 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
1995 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1996 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1998 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1999 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2002 void TfLiteParserImpl::ParseMaxPool2D(
size_t subgraphIndex,
size_t operatorIndex)
2004 ParsePool(subgraphIndex, operatorIndex, PoolingAlgorithm::Max);
2007 void TfLiteParserImpl::ParseMaximum(
size_t subgraphIndex,
size_t operatorIndex)
2009 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2011 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2014 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2017 auto layerName = fmt::format(
"Maximum:{}:{}", subgraphIndex, operatorIndex);
2019 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2020 TensorInfo input1TensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2021 CheckMatchingQuantization(inputTensorInfo, input1TensorInfo, layerName,
"Input 0",
"Input 1");
2023 IConnectableLayer* layer = m_Network->AddElementwiseBinaryLayer(BinaryOperation::Maximum, layerName.c_str());
2031 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
2032 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
2035 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2036 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
2038 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2039 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2042 void TfLiteParserImpl::ParseMinimum(
size_t subgraphIndex,
size_t operatorIndex)
2044 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2046 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2049 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2052 auto layerName = fmt::format(
"Minimum:{}:{}", subgraphIndex, operatorIndex);
2054 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2055 TensorInfo input1TensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2056 CheckMatchingQuantization(inputTensorInfo, input1TensorInfo, layerName,
"Input 0",
"Input 1");
2058 IConnectableLayer* layer = m_Network->AddElementwiseBinaryLayer(BinaryOperation::Minimum, layerName.c_str());
2066 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
2067 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
2070 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2071 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
2073 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2074 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2077 void TfLiteParserImpl::ParsePool(
size_t subgraphIndex,
2078 size_t operatorIndex,
2081 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2083 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2084 const auto* options = operatorPtr->builtin_options.AsPool2DOptions();
2088 std::string layerName;
2092 case PoolingAlgorithm::Average:
2094 fmt::format(
"AveragePool2D:{}:{}", subgraphIndex, operatorIndex);
2096 case PoolingAlgorithm::Max:
2098 fmt::format(
"MaxPool2D:{}:{}", subgraphIndex, operatorIndex);
2115 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2117 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2120 unsigned int inputHeight = inputTensorInfo.
GetShape()[1];
2121 unsigned int inputWidth = inputTensorInfo.
GetShape()[2];
2128 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2131 IConnectableLayer* layer = m_Network->AddPooling2dLayer(desc, layerName.c_str());
2139 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
2140 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
2145 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2146 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2148 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
2150 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2151 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2154 void TfLiteParserImpl::ParseSlice(
size_t subgraphIndex,
size_t operatorIndex)
2156 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2158 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2160 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2166 armnn::TensorInfo beginTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2169 std::vector<unsigned int> begin(beginTensorInfo.
GetNumElements());
2170 ::memcpy(begin.data(), beginBufferPtr->data.data(), beginTensorInfo.
GetNumBytes());
2173 armnn::TensorInfo sizeTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
2179 if (sizeBufferPtr->data.data())
2181 ::memcpy(signedSize.data(), sizeBufferPtr->data.data(), sizeTensorInfo.
GetNumBytes());
2185 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2187 for (
unsigned int i = 0; i < signedSize.size(); ++i)
2189 int signedValue = signedSize[i];
2191 if (signedValue < -1 || signedValue >
static_cast<int>(inputTensorInfo.
GetShape()[i] - begin[i]))
2193 throw ParseException(fmt::format(
"Invalid value for size {} size must be in range "
2194 "[-1, inputDimSize - begin] [-1, {}] inclusive {}",
2196 inputTensorInfo.
GetShape()[i] - begin[i],
2200 if (signedValue == -1)
2202 size[i] = inputTensorInfo.
GetShape()[i] - begin[i];
2206 size[i] =
static_cast<unsigned int>(signedValue);
2212 auto layerName = fmt::format(
"Slice:{}:{}", subgraphIndex, operatorIndex);
2214 IConnectableLayer*
const layer = m_Network->AddSliceLayer(desc, layerName.c_str());
2216 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
2217 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
2222 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2223 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2226 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2227 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2230 void TfLiteParserImpl::ParseSoftmax(
size_t subgraphIndex,
size_t operatorIndex)
2232 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2233 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2234 const auto* options = operatorPtr->builtin_options.AsSoftmaxOptions();
2237 desc.
m_Beta = options->beta;
2239 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2241 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2244 auto layerName = fmt::format(
"Softmax:{}:{}", subgraphIndex, operatorIndex);
2245 IConnectableLayer*
const layer = m_Network->AddSoftmaxLayer(desc, layerName.c_str());
2247 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
2252 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2253 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2256 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2257 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2260 void TfLiteParserImpl::ParseLogSoftmax(
size_t subgraphIndex,
size_t operatorIndex)
2262 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2266 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2268 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2271 auto layerName = fmt::format(
"LogSoftmax:{}:{}", subgraphIndex, operatorIndex);
2272 IConnectableLayer*
const layer = m_Network->AddLogSoftmaxLayer(desc, layerName.c_str());
2274 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
2279 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2280 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2283 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2284 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2287 void TfLiteParserImpl::ParseScatterNd(
size_t subgraphIndex,
size_t operatorIndex)
2289 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2296 armnn::TensorInfo indicesTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2297 armnn::TensorInfo updatesTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2298 armnn::TensorInfo shapeTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
2304 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2305 const auto* options = operatorPtr->builtin_options.AsScatterNdOptions();
2308 auto layerName = fmt::format(
"ScatterND:{}:{}", subgraphIndex, operatorIndex);
2310 IConnectableLayer* layer = m_Network->AddScatterNdLayer(descriptor, layerName.c_str());
2318 outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1, 2});
2321 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2322 RegisterInputSlots(subgraphIndex,
2325 {inputTensorIndexes[2], inputTensorIndexes[0], inputTensorIndexes[1]});
2327 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2328 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2331 void TfLiteParserImpl::ParseSpaceToBatchND(
size_t subgraphIndex,
size_t operatorIndex)
2333 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2335 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2338 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2341 armnn::TensorInfo blockShapeTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2344 armnn::TensorInfo padListTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
2347 std::vector<unsigned int> blockShape(blockShapeTensorInfo.
GetNumElements());
2348 ::memcpy(blockShape.data(), blockShapeBufferPtr->data.data(), blockShapeTensorInfo.
GetNumBytes());
2350 std::vector<unsigned int> padListVector(padListTensorInfo.
GetNumElements());
2351 ::memcpy(padListVector.data(), padListBufferPtr->data.data(), padListTensorInfo.
GetNumBytes());
2354 std::vector<std::pair<unsigned int, unsigned int>> padList;
2355 for (
unsigned int i = 0; i < padListTensorInfo.
GetNumElements() / step; ++i)
2357 padList.emplace_back(padListVector[i * step], padListVector[i * step + 1]);
2365 auto layerName = fmt::format(
"SpaceToBatchND:{}:{}", subgraphIndex, operatorIndex);
2367 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2369 IConnectableLayer* layer = m_Network->AddSpaceToBatchNdLayer(desc, layerName.c_str());
2377 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
2378 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
2381 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2382 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2384 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2385 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2388 void TfLiteParserImpl::ParseSpaceToDepth(
size_t subgraphIndex,
size_t operatorIndex)
2390 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2399 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2400 const auto* options = operatorPtr->builtin_options.AsSpaceToDepthOptions();
2401 auto blockSize = options->block_size;
2405 fmt::format(
"Operation has invalid block size: {} Block size should be >= 2 {}",
2409 descriptor.
m_BlockSize = armnn::numeric_cast<uint32_t>(blockSize);
2411 auto layerName = fmt::format(
"SpaceToDepth:{}:{}", subgraphIndex, operatorIndex);
2412 IConnectableLayer* layer = m_Network->AddSpaceToDepthLayer(descriptor, layerName.c_str());
2420 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
2423 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2424 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2426 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2427 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2434 static const uint32_t dimensionSequence[] = { 0, 1, 2, 3 };
2438 std::stringstream ss;
2439 ss <<
"Input tensor has unexpected number of dimensions:" << inputTensorInfo.
GetNumDimensions()
2440 <<
" shape:" << inputTensorInfo.
GetShape() <<
" "
2445 if (squeezeDims.empty())
2447 squeezeDims.assign(dimensionSequence,
2451 std::vector<uint32_t> outputDims;
2454 bool skipSqueeze = (std::find(squeezeDims.begin(), squeezeDims.end(), i) == squeezeDims.end());
2455 auto currentDimension = inputTensorInfo.
GetShape()[i];
2456 if (skipSqueeze || currentDimension != 1)
2458 outputDims.push_back(currentDimension);
2462 if (outputDims.size() > 4)
2464 std::stringstream ss;
2465 ss <<
"Output tensor has unexpected number of dimensions:" << inputTensorInfo.
GetNumDimensions()
2466 <<
" shape:" << inputTensorInfo.
GetShape() <<
" "
2478 return outTensorInfo;
2481 void TfLiteParserImpl::ParseShape(
size_t subgraphIndex,
size_t operatorIndex)
2483 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2485 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2487 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2490 auto layerName = fmt::format(
"Shape:{}:{}", subgraphIndex, operatorIndex);
2500 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
2509 "Output tensor data type is not supported. (Supported types: Signed32 & Signed64) {}",
2513 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2514 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2516 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2517 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
2520 void TfLiteParserImpl::ParseSqueeze(
size_t subgraphIndex,
size_t operatorIndex)
2522 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2524 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2527 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2530 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2531 const auto * options = operatorPtr->builtin_options.AsSqueezeOptions();
2532 auto layerName = fmt::format(
"Squeeze:{}:{}", subgraphIndex, operatorIndex);
2534 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2536 std::vector<uint32_t> squeezeDim;
2539 if (options->squeeze_dims.size() == 1 && options->squeeze_dims[0] < 0)
2542 squeezeDim.push_back(
static_cast<uint32_t
>(dim));
2546 squeezeDim = AsUnsignedVector(options->squeeze_dims);
2551 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
2557 m_TensorInfos[outputTensorIds[0]] = outputTensorInfo;
2559 IConnectableLayer* layer = m_Network->AddReshapeLayer(reshapeDesc, layerName.c_str());
2569 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2570 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2572 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2573 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2576 void TfLiteParserImpl::ParseStridedSlice(
size_t subgraphIndex,
size_t operatorIndex)
2578 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2580 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2583 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2586 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2587 const auto* options = operatorPtr->builtin_options.AsStridedSliceOptions();
2597 armnn::TensorInfo beginTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2601 if (beginBufferPtr->data.data() !=
nullptr)
2603 ::memcpy(begin.data(), beginBufferPtr->data.data(), beginTensorInfo.
GetNumBytes());
2607 throw ParseException(
"ParseStridedSlice: Invalid input - the begin vector is null");
2610 armnn::TensorInfo endTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
2614 if (endBufferPtr->data.data() !=
nullptr)
2616 ::memcpy(end.data(), endBufferPtr->data.data(), endTensorInfo.
GetNumBytes());
2620 throw ParseException(
"ParseStridedSlice: Invalid input - the end vector is null");
2623 armnn::TensorInfo strideTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 3);
2628 if (strideBufferPtr->data.data() !=
nullptr)
2630 ::memcpy(stride.data(), strideBufferPtr->data.data(), strideTensorInfo.
GetNumBytes());
2634 throw ParseException(
"ParseStridedSlice: Invalid input - the stride vector is null");
2641 auto layerName = fmt::format(
"StridedSlice:{}:{}", subgraphIndex, operatorIndex);
2642 IConnectableLayer* layer = m_Network->AddStridedSliceLayer(desc, layerName.c_str());
2650 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
2653 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2654 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2656 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2657 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2660 void TfLiteParserImpl::ParseSub(
size_t subgraphIndex,
size_t operatorIndex)
2662 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2664 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2665 const auto* options = operatorPtr->builtin_options.AsSubOptions();
2667 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2670 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2673 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2674 armnn::TensorInfo input1TensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2676 auto layerName = fmt::format(
"Sub:{}:{}", subgraphIndex, operatorIndex);
2677 IConnectableLayer* layer = m_Network->AddElementwiseBinaryLayer(BinaryOperation::Sub, layerName.c_str());
2685 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
2688 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2689 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
2692 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
2695 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2696 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2699 void TfLiteParserImpl::ParseDiv(
size_t subgraphIndex,
size_t operatorIndex)
2701 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2703 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2704 const auto* options = operatorPtr->builtin_options.AsDivOptions();
2706 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2709 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2712 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2713 armnn::TensorInfo input1TensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2715 auto layerName = fmt::format(
"Div:{}:{}", subgraphIndex, operatorIndex);
2716 IConnectableLayer* layer = m_Network->AddElementwiseBinaryLayer(BinaryOperation::Div, layerName.c_str());
2724 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
2727 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2728 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
2731 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
2734 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2735 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2738 void TfLiteParserImpl::ParseFloorDiv(
size_t subgraphIndex,
size_t operatorIndex)
2740 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2742 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2745 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2748 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2749 armnn::TensorInfo input1TensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2751 auto layerName = fmt::format(
"FloorDiv:{}:{}", subgraphIndex, operatorIndex);
2752 IConnectableLayer* layer = m_Network->AddElementwiseBinaryLayer(BinaryOperation::FloorDiv, layerName.c_str());
2760 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
2763 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2764 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
2765 layer = AddFusedFloorLayer(layer, 0);
2767 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2768 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2771 void TfLiteParserImpl::ParseAdd(
size_t subgraphIndex,
size_t operatorIndex)
2773 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2775 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2776 const auto* options = operatorPtr->builtin_options.AsAddOptions();
2778 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2781 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2784 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2785 armnn::TensorInfo input1TensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2787 auto layerName = fmt::format(
"Add:{}:{}", subgraphIndex, operatorIndex);
2788 IConnectableLayer* layer = m_Network->AddElementwiseBinaryLayer(BinaryOperation::Add, layerName.c_str());
2796 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
2799 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2800 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
2803 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
2806 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2807 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2810 void TfLiteParserImpl::ParseMul(
size_t subgraphIndex,
size_t operatorIndex)
2812 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2814 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2815 const auto* options = operatorPtr->builtin_options.AsMulOptions();
2817 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2820 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2823 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2824 armnn::TensorInfo input1TensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2826 auto layerName = fmt::format(
"Mul:{}:{}", subgraphIndex, operatorIndex);
2827 IConnectableLayer* layer = m_Network->AddElementwiseBinaryLayer(BinaryOperation::Mul, layerName.c_str());
2835 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
2838 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2839 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
2842 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
2845 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2846 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2849 void TfLiteParserImpl::ParseMean(
size_t subgraphIndex,
size_t operatorIndex)
2851 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2853 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2855 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2858 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2859 TensorInfo dimTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2864 if (axisBufferPtr !=
nullptr)
2867 ::memcpy(axisData.data(), axisBufferPtr->data.data(), dimTensorInfo.
GetNumBytes());
2871 std::set<unsigned int> uniqueAxis;
2872 std::transform(axisData.begin(),
2874 std::inserter(uniqueAxis, uniqueAxis.begin()),
2875 [rank](
int i)->unsigned
int{
2876 return static_cast<uint32_t>(((i + rank) % rank)); });
2877 desc.
m_Axis.assign(uniqueAxis.begin(), uniqueAxis.end());
2883 desc.
m_Axis.push_back(i);
2891 auto layerName = fmt::format(
"Mean:{}:{}", subgraphIndex, operatorIndex);
2900 outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
2903 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2904 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2906 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2907 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2910 void TfLiteParserImpl::ParsePad(
size_t subgraphIndex,
size_t operatorIndex)
2912 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2919 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2920 armnn::TensorInfo padTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2922 std::vector<unsigned int> padBuffer = GetUIntBuffer(padTensorInfo, m_Model, inputs[1]->buffer);
2926 auto opcode = GetOpCode(m_Model, subgraphIndex, operatorIndex);
2928 if (opcode == tflite::BuiltinOperator_PAD)
2937 else if (opcode == tflite::BuiltinOperator_PADV2)
2941 armnn::TensorInfo padValueTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
2950 if (padValueBufferPtr->data.size() > 0)
2956 std::vector<float> padValueBuffer(padValueTensorInfo.
GetNumElements());
2957 ::memcpy(padValueBuffer.data(), padValueBufferPtr->data.data(), padValueBufferPtr->data.size());
2963 std::vector<uint8_t> padValueBuffer(padValueTensorInfo.
GetNumElements());
2964 ::memcpy(padValueBuffer.data(), padValueBufferPtr->data.data(), padValueBufferPtr->data.size());
2965 desc.
m_PadValue = armnn::Dequantize<uint8_t>(padValueBuffer[0],
2973 std::vector<int8_t> padValueBuffer(padValueTensorInfo.
GetNumElements());
2974 ::memcpy(padValueBuffer.data(), padValueBufferPtr->data.data(), padValueBufferPtr->data.size());
2975 desc.
m_PadValue = armnn::Dequantize<int8_t>(padValueBuffer[0],
2989 for (
unsigned int i = 0; i < padTensorInfo.
GetNumElements() / step; ++i)
2991 desc.
m_PadList.emplace_back(padBuffer[i * step], padBuffer[i * step + 1]);
2994 auto layerName = (opcode == tflite::BuiltinOperator_PAD) ? fmt::format(
"Pad:{}:{}", subgraphIndex, operatorIndex)
2995 : fmt::format(
"PadV2:{}:{}", subgraphIndex, operatorIndex);
3005 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
3008 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3009 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
3011 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3012 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
3015 void TfLiteParserImpl::ParseMirrorPad(
size_t subgraphIndex,
size_t operatorIndex)
3017 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3025 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
3027 armnn::TensorInfo padTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
3030 std::vector<unsigned int> padBuffer(padTensorInfo.
GetNumElements());
3031 ::memcpy(padBuffer.data(), bufferPtr->data.data(), padTensorInfo.
GetNumBytes());
3035 for (
unsigned int i = 0; i < padTensorInfo.
GetNumElements() / step; ++i)
3037 desc.
m_PadList.emplace_back(padBuffer[i * step], padBuffer[i * step + 1]);
3040 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
3041 const auto* options = operatorPtr->builtin_options.AsMirrorPadOptions();
3043 if (options->mode == tflite::MirrorPadMode_REFLECT)
3047 else if (options->mode == tflite::MirrorPadMode_SYMMETRIC)
3058 auto inputShape = inputTensorInfo.
GetShape();
3061 const unsigned int isReflect =
static_cast<unsigned int>(desc.
m_PaddingMode == PaddingMode::Reflect);
3062 for(
unsigned int i = 0; i < padList.size(); ++i)
3064 if(padList.at(i).first > (inputShape[i] - isReflect) ||
3065 padList.at(i).second > (inputShape[i] - isReflect))
3068 "equal (Symmetric) to the dimension size.");
3072 auto layerName = fmt::format(
"MirrorPad:{}:{}", subgraphIndex, operatorIndex);
3082 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
3085 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3086 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
3088 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3089 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
3092 void TfLiteParserImpl::ParsePrelu(
size_t subgraphIndex,
size_t operatorIndex)
3094 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3096 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
3099 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
3102 auto layerName = fmt::format(
"Prelu:{}:{}", subgraphIndex, operatorIndex);
3104 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
3105 armnn::TensorInfo alphaTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
3115 if (IsConstTensor(inputs[1]))
3117 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3119 RegisterConsumerOfTensor(subgraphIndex, inputTensorIndexes[0], slot);
3121 auto alphaTensorAndData = CreateConstTensorNonPermuted(inputs[1], alphaTensorInfo,
3123 std::string constLayerName = fmt::format(
"Constant:{}", inputs[1]->name);
3125 m_Network->AddConstantLayer(alphaTensorAndData.first, constLayerName.c_str());
3135 RegisterOutputSlots(subgraphIndex,
3136 VIRTUAL_OPERATOR_ID,
3138 { inputTensorIndexes[1] });
3142 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3143 RegisterInputSlots(subgraphIndex, operatorIndex, layer, inputTensorIndexes);
3146 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
3149 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3150 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
3153 void TfLiteParserImpl::ParseQuantize(
size_t subgraphIndex,
size_t operatorIndex)
3155 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3157 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
3160 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
3163 auto layerName = fmt::format(
"Quantize:{}:{}", subgraphIndex, operatorIndex);
3173 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
3176 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3177 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
3179 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3180 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
3183 void TfLiteParserImpl::ParseRelu(
size_t subgraphIndex,
size_t operatorIndex)
3185 ParseActivation(subgraphIndex,operatorIndex, ActivationFunction::ReLu);
3188 void TfLiteParserImpl::ParseRelu6(
size_t subgraphIndex,
size_t operatorIndex)
3190 ParseActivation(subgraphIndex,operatorIndex, ActivationFunction::BoundedReLu);
3193 void TfLiteParserImpl::ParseLeakyRelu(
size_t subgraphIndex,
size_t operatorIndex)
3195 ParseActivation(subgraphIndex, operatorIndex, ActivationFunction::LeakyReLu);
3198 void TfLiteParserImpl::ParseLogistic(
size_t subgraphIndex,
size_t operatorIndex)
3200 ParseActivation(subgraphIndex,operatorIndex,ActivationFunction::Sigmoid);
3203 void TfLiteParserImpl::ParseTanH(
size_t subgraphIndex,
size_t operatorIndex)
3205 ParseActivation(subgraphIndex,operatorIndex,ActivationFunction::TanH);
3208 void TfLiteParserImpl::ParseElu(
size_t subgraphIndex,
size_t operatorIndex)
3210 ParseActivation(subgraphIndex, operatorIndex, ActivationFunction::Elu);
3213 void TfLiteParserImpl::ParseHardSwish(
size_t subgraphIndex,
size_t operatorIndex)
3215 ParseActivation(subgraphIndex, operatorIndex, ActivationFunction::HardSwish);
3218 void TfLiteParserImpl::ParseGelu(
size_t subgraphIndex,
size_t operatorIndex)
3220 ParseActivation(subgraphIndex,operatorIndex,ActivationFunction::Gelu);
3223 void TfLiteParserImpl::ParseActivation(
size_t subgraphIndex,
size_t operatorIndex,
ActivationFunction activationType)
3225 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3226 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
3229 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
3232 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
3235 auto layerName = fmt::format(
"Activation:");
3239 switch (activationType)
3241 case ActivationFunction::ReLu:
3243 layerName += fmt::format(
"RELU:{}:{}", subgraphIndex, operatorIndex);
3246 case ActivationFunction::BoundedReLu:
3248 layerName += fmt::format(
"RELU6:{}:{}", subgraphIndex, operatorIndex);
3249 activationDesc.
m_A = 6.0f;
3250 activationDesc.
m_B = 0.0f;
3253 case ActivationFunction::Sigmoid:
3255 layerName += fmt::format(
"SIGMOID:{}:{}", subgraphIndex, operatorIndex);
3258 case ActivationFunction::TanH:
3260 layerName += fmt::format(
"TANH:{}:{}", subgraphIndex, operatorIndex);
3261 activationDesc.
m_A = 1.0f;
3262 activationDesc.
m_B = 1.0f;
3265 case ActivationFunction::LeakyReLu:
3267 layerName += fmt::format(
"LEAKYRELU:{}:{}", subgraphIndex, operatorIndex);
3268 const auto* options = operatorPtr->builtin_options.AsLeakyReluOptions();
3269 activationDesc.
m_A = options->alpha;
3272 case ActivationFunction::Elu:
3274 layerName += fmt::format(
"ELU:{}:{}", subgraphIndex, operatorIndex);
3275 activationDesc.
m_A = 1.0f;
3278 case ActivationFunction::HardSwish:
3280 layerName += fmt::format(
"HARDSWISH:{}:{}", subgraphIndex, operatorIndex);
3283 case ActivationFunction::Gelu:
3285 layerName += fmt::format(
"GELU:{}:{}", subgraphIndex, operatorIndex);
3291 fmt::format(
"Unexpected ActivationFunction[{}] when creating layerName {} ",
3296 IConnectableLayer*
const layer = m_Network->AddActivationLayer(activationDesc, layerName.c_str());
3298 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
3303 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3304 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
3307 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3308 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
3312 const std::vector<int32_t>& targetDimsIn)
3314 std::vector<unsigned int> outputDims(targetDimsIn.begin(), targetDimsIn.end());
3315 const auto stretchDim = std::find(targetDimsIn.begin(), targetDimsIn.end(), -1);
3317 if (stretchDim != targetDimsIn.end())
3319 if (std::find(std::next(stretchDim), targetDimsIn.end(), -1) != targetDimsIn.end())
3322 fmt::format(
"At most one component of shape can be -1 {}",
CHECK_LOCATION().AsString()));
3325 auto targetNumElements =
3326 armnn::numeric_cast<unsigned int>(
3327 std::accumulate(targetDimsIn.begin(), targetDimsIn.end(), -1, std::multiplies<int32_t>()));
3329 auto stretchIndex =
static_cast<size_t>(std::distance(targetDimsIn.begin(), stretchDim));
3331 if (targetNumElements == 0)
3335 outputDims[stretchIndex] = 0;
3340 fmt::format(
"Input to reshape is a tensor with elements, but the requested shape has 0. {}",
3346 outputDims[stretchIndex] = inputTensorInfo.
GetNumElements() / targetNumElements;
3358 void TfLiteParserImpl::ParseReshape(
size_t subgraphIndex,
size_t operatorIndex)
3360 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3362 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
3364 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
3367 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
3368 const auto* options = operatorPtr->builtin_options.AsReshapeOptions();
3369 auto layerName = fmt::format(
"Reshape:{}:{}", subgraphIndex, operatorIndex);
3371 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
3373 CheckMatchingQuantization(inputTensorInfo, actualOutputTensorInfo, layerName,
"Input 0",
"Output 0");
3379 std::vector<int32_t> targetShape;
3380 bool targetShapeFound =
false;
3382 if (options !=
nullptr)
3385 if (options->new_shape.empty() ==
false)
3387 targetShape = options->new_shape;
3388 targetShapeFound =
true;
3393 if (!targetShapeFound)
3396 if (inputs.size() > 1 && inputs[1] !=
nullptr)
3398 if (inputs[1]->is_variable)
3403 if (inputs[1]->shape.size() != 1)
3408 if (inputs[1]->type != tflite::TensorType_INT32)
3414 auto bufferPtr =
GetBuffer(m_Model, inputs[1]->buffer);
3415 auto values =
reinterpret_cast<const int32_t*
>(bufferPtr->data.data());
3418 for (
int i = 0; i < inputs[1]->shape[0]; ++i)
3420 targetShape.push_back(values[i]);
3432 for (
unsigned int i = 0; i < actualOutputTensorInfo.
GetShape().GetNumDimensions(); ++i)
3434 targetShape.push_back(actualOutputTensorInfo.
GetShape()[i]);
3438 else if (reshapeShapes[0] > 2)
3440 throw ParseException(fmt::format(
"Invalid input shape '{}' in Reshape layer '{}' {}. "
3441 "When inferring during runtime, the parser only supports "
3442 "shape (batch, -1) or (-1) for target shape input.",
3449 const int32_t numInputElements = inputTensorInfo.
GetNumElements();
3450 const int32_t inputTensorShape = inputTensorInfo.
GetShape()[0];
3451 if (reshapeShapes[0] == 1)
3453 targetShape = {numInputElements};
3455 else if (reshapeShapes[0] == 2)
3457 targetShape = {inputTensorShape, numInputElements / inputTensorShape};
3461 catch (
const std::exception& exc)
3464 "Reshape operation. Reshape operator target shape input buffer data "
3465 "is null. " << exc.what());
3472 "At least one method required");
3484 if (inputs.size() > 1 && !
CheckShape(reshapeOutputTensorShape, outputs[0]->shape)
3485 && !outputs[0]->shape_signature.empty())
3489 std::vector<int32_t> secondaryOutputTargetShape = outputs[0]->shape_signature;
3496 if (!
CheckShape(reshapeOutputTensorShape, secondaryReshapeOutputTensorInfo.
GetShape()))
3498 std::stringstream ss;
3499 ss <<
"New shape defined in reshape parameters "
3500 << reshapeOutputTensorShape
3501 <<
" does not equal output shape "
3502 << actualOutputTensorInfo.
GetShape()
3512 m_TensorInfos[outputTensorIds[0]] = reshapeOutputTensorInfo;
3514 IConnectableLayer* layer = m_Network->AddReshapeLayer(reshapeDesc, layerName.c_str());
3524 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3525 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
3527 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3528 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
3531 void TfLiteParserImpl::ParseResizeBilinear(
size_t subgraphIndex,
size_t operatorIndex)
3533 ParseResize(subgraphIndex, operatorIndex, ResizeMethod::Bilinear);
3536 void TfLiteParserImpl::ParseResizeNearestNeighbor(
size_t subgraphIndex,
size_t operatorIndex)
3538 ParseResize(subgraphIndex, operatorIndex, ResizeMethod::NearestNeighbor);
3541 void TfLiteParserImpl::ParseResize(
size_t subgraphIndex,
size_t operatorIndex,
ResizeMethod resizeMethod)
3543 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3545 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
3548 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
3551 armnn::TensorInfo sizeTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
3554 std::vector<int32_t> sizeTensorData(sizeTensorInfo.
GetNumElements());
3557 ::memcpy(sizeTensorData.data(), sizeBufferPtr->data.data(), sizeTensorInfo.
GetNumBytes());
3562 desc.
m_TargetWidth =
static_cast<uint32_t
> (sizeTensorData[1]);
3565 auto layerName = fmt::format(
"Resize:");
3567 switch (resizeMethod)
3569 case ResizeMethod::Bilinear:
3571 layerName += fmt::format(
"BILINEAR:{}:{}", subgraphIndex, operatorIndex);
3573 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
3574 const auto * options = operatorPtr->builtin_options.AsResizeBilinearOptions();
3580 case ResizeMethod::NearestNeighbor:
3582 layerName += fmt::format(
"NEARESTNEIGHBOR:{}:{}", subgraphIndex, operatorIndex);
3588 fmt::format(
"Unexpected ResizeMethod[{}] when creating layerName {} ",
3593 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
3603 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
3604 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
3607 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3608 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
3610 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3611 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
3614 void TfLiteParserImpl::ParseReverseV2(
size_t subgraphIndex,
size_t operatorIndex)
3616 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3618 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
3621 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
3624 auto layerName = fmt::format(
"ReverseV2:{}:{}", subgraphIndex, operatorIndex);
3635 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3636 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
3638 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3639 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
3642 void TfLiteParserImpl::ParseTile(
size_t subgraphIndex,
size_t operatorIndex)
3644 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3646 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
3649 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
3656 auto layerName = fmt::format(
"Tile:{}:{}", subgraphIndex, operatorIndex);
3661 if (multiplesBufferPtr !=
nullptr)
3663 std::vector<int32_t> multiplesData(multiplesTensorInfo.
GetNumElements());
3664 ::memcpy(multiplesData.data(), multiplesBufferPtr->data.data(), multiplesTensorInfo.
GetNumBytes());
3665 descriptor.
m_Multiples.assign(multiplesData.begin(), multiplesData.end());
3672 IConnectableLayer* layer = m_Network->AddTileLayer(descriptor, layerName.c_str());
3677 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3678 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
3680 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3681 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
3684 void TfLiteParserImpl::ParseConcatenation(
size_t subgraphIndex,
size_t operatorIndex)
3686 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3688 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
3689 const auto* options = operatorPtr->builtin_options.AsConcatenationOptions();
3693 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
3694 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
3699 unsigned int numConcatView =
static_cast<unsigned int>(inputs.size());
3700 uint32_t inputRank = InputTensorInfo(subgraphIndex, operatorIndex, 0).
GetNumDimensions();
3702 const unsigned int concatDimInput =
static_cast<unsigned int>(
3703 (
static_cast<int>(inputRank) + options->axis) %
static_cast<int>(inputRank));
3705 OriginsDescriptor concatDescriptor(
static_cast<uint32_t
>(numConcatView), inputRank);
3706 concatDescriptor.SetConcatAxis(concatDimInput);
3707 unsigned int mergeDimOrigin = 0;
3709 for (
unsigned int viewIndex = 0; viewIndex < numConcatView; ++viewIndex)
3711 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, viewIndex);
3715 inputTensorInfo, concatDescriptor, concatDimInput, viewIndex, mergeDimOrigin);
3718 auto layerName = fmt::format(
"Concatenation:{}:{}", subgraphIndex, operatorIndex);
3720 IConnectableLayer* layer = m_Network->AddConcatLayer(concatDescriptor, layerName.c_str());
3728 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {});
3731 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3732 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes});
3735 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
3737 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3738 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
3741 void TfLiteParserImpl::ParseFullyConnected(
size_t subgraphIndex,
size_t operatorIndex)
3743 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3745 const auto& operatorRfr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
3746 const auto options = operatorRfr->builtin_options.AsFullyConnectedOptions();
3754 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
3755 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
3758 armnn::TensorInfo filterTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
3761 int32_t weightsDimension =
static_cast<int32_t
>(filterTensorInfo.
GetNumDimensions());
3762 if (weightsDimension != 2)
3765 fmt::format(
"Dimension {} for Fully Connected weights is not supported by Armnn. "
3772 auto layerName = fmt::format(
"FullyConnected:{}:{}", subgraphIndex, operatorIndex);
3774 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3776 std::vector<unsigned int> tensorIndexesToRegister = {inputTensorIndexes[0]};
3777 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
3782 tensorIndexesToRegister.emplace_back(inputTensorIndexes[1]);
3784 if (ShouldConstantTensorBeConverted(inputs[1], inputTensorInfo.
GetDataType(), filterTensorInfo.
GetDataType()))
3786 m_ConstantsToDequantize.emplace_back(inputs[1]->buffer);
3789 if (inputs.size() == 3)
3792 armnn::TensorInfo biasTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
3795 tensorIndexesToRegister.emplace_back(inputTensorIndexes[2]);
3797 if (ShouldConstantTensorBeConverted(inputs[2], inputTensorInfo.
GetDataType(), biasTensorInfo.
GetDataType()))
3799 m_ConstantsToDequantize.emplace_back(inputs[2]->buffer);
3804 layer = m_Network->AddFullyConnectedLayer(desc, layerName.c_str());
3812 unsigned int startingSlotIndex = 0;
3819 std::vector<unsigned int> reshapedDimensions(2);
3820 reshapedDimensions[1] = filterTensorInfo.
GetShape()[1];
3821 reshapedDimensions[0] = inputTensorInfo.
GetNumElements() / reshapedDimensions[1];
3823 if (inputTensorInfo.
GetNumElements() % reshapedDimensions[1] != 0)
3826 fmt::format(
"Failed to deduce input tensor shape from filter size {} {}",
3827 reshapedDimensions[1],
3831 armnn::TensorInfo reshapedTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
3833 inputTensorInfo = reshapedTensorInfo;
3835 std::string reshapeLayerName = fmt::format(
"Reshape_for:{}", layer->
GetName());
3839 reshapeLayerName.c_str());
3844 RegisterInputSlots(subgraphIndex, operatorIndex, reshapeLayer, {inputTensorIndexes[0]});
3846 tensorIndexesToRegister.erase(tensorIndexesToRegister.begin());
3847 startingSlotIndex = 1;
3850 RegisterInputSlots(subgraphIndex, operatorIndex, layer, tensorIndexesToRegister, startingSlotIndex);
3852 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromShapes(subgraphIndex, operatorIndex, layer, 0,
3861 std::vector<unsigned int> reshapedDimensions(2);
3862 reshapedDimensions[1] = filterTensorInfo.
GetShape()[0];
3863 reshapedDimensions[0] = outputTensorInfo.
GetNumElements() / reshapedDimensions[1];
3865 if (outputTensorInfo.
GetNumElements() % reshapedDimensions[1] != 0)
3868 fmt::format(
"Failed to deduce output tensor shape from filter size {} {}",
3869 reshapedDimensions[1],
3875 std::string reshapeLayerName = fmt::format(
"ExpandDims:{}:{}", subgraphIndex, operatorIndex);
3876 layer = AddReshapeLayer(layer, 0, reshapeLayerName, outputTensorInfo);
3881 options->fused_activation_function);
3884 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3885 RegisterOutputSlots(subgraphIndex, operatorIndex, fusedActivationLayer, {outputTensorIndexes[0]});
3890 void TfLiteParserImpl::ParseDetectionPostProcess(
size_t subgraphIndex,
size_t operatorIndex)
3892 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3894 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
3896 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
3897 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
3901 auto custom_options = operatorPtr->custom_options;
3902 const flexbuffers::Map& m = flexbuffers::GetRoot(custom_options.data(), custom_options.size()).AsMap();
3911 desc.
m_ScaleH = m[
"h_scale"].AsFloat();
3912 desc.
m_ScaleW = m[
"w_scale"].AsFloat();
3913 desc.
m_ScaleX = m[
"x_scale"].AsFloat();
3914 desc.
m_ScaleY = m[
"y_scale"].AsFloat();
3916 if (!(m[
"use_regular_nms"].IsNull()))
3920 if (!(m[
"detections_per_class"].IsNull()))
3928 "must be positive and less than or equal to 1.");
3931 armnn::TensorInfo anchorTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
3932 auto anchorTensorAndData = CreateConstTensorNonPermuted(inputs[2], anchorTensorInfo);
3934 auto layerName = fmt::format(
"DetectionPostProcess:{}:{}", subgraphIndex, operatorIndex);
3935 IConnectableLayer* layer = m_Network->AddDetectionPostProcessLayer(desc, anchorTensorAndData,
3947 m_OverriddenOutputShapes.push_back({ 1, numDetectedBox, 4 });
3948 m_OverriddenOutputShapes.push_back({ 1, numDetectedBox });
3949 m_OverriddenOutputShapes.push_back({ 1, numDetectedBox });
3950 m_OverriddenOutputShapes.push_back({ 1 });
3952 for (
unsigned int i = 0 ; i < outputs.size() ; ++i)
3960 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3961 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
3964 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3965 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0],
3966 outputTensorIndexes[1],
3967 outputTensorIndexes[2],
3968 outputTensorIndexes[3]});
3972 void TfLiteParserImpl::ParsePack(
size_t subgraphIndex,
size_t operatorIndex)
3974 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3976 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
3977 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
3980 if (inputs.size() < 1)
3985 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
3986 const auto* options = operatorPtr->builtin_options.AsPackOptions();
3989 desc.
m_Axis =
static_cast<uint32_t
>(options->axis);
3990 desc.
m_NumInputs =
static_cast<uint32_t
>(inputs.size());
3993 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
3996 auto layerName = fmt::format(
"Pack:{}:{}", subgraphIndex, operatorIndex);
4005 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {});
4008 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
4009 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes});
4011 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
4012 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
4015 void TfLiteParserImpl::ParseUnidirectionalSequenceLSTM(
size_t subgraphIndex,
size_t operatorIndex)
4017 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
4019 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
4020 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
4022 if (inputs.size() < 2)
4024 throw ParseException(
"UnidirectionalSequenceLSTM must have at least 2 input.");
4027 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
4028 const auto& subgraphPtr = m_Model->subgraphs[subgraphIndex];
4029 const auto nodeParams = operatorPtr->builtin_options.AsUnidirectionalSequenceLSTMOptions();
4031 auto inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
4039 if (IsOptionalOperandPresent(operatorPtr->inputs[1]))
4041 params.
m_InputToInputWeights = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[1]].get(),
4042 inputTensorInfo).first;
4046 inputTensorInfo).first;
4047 params.
m_InputToCellWeights = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[3]].get(),
4048 inputTensorInfo).first;
4050 inputTensorInfo).first;
4053 if (IsOptionalOperandPresent(operatorPtr->inputs[5]))
4056 inputTensorInfo).first;
4060 inputTensorInfo).first;
4062 inputTensorInfo).first;
4064 inputTensorInfo).first;
4067 if (IsOptionalOperandPresent(operatorPtr->inputs[9]))
4069 params.
m_CellToInputWeights = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[9]].get(),
4070 inputTensorInfo).first;
4073 if (IsOptionalOperandPresent(operatorPtr->inputs[10]))
4075 params.
m_CellToForgetWeights = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[10]].get(),
4076 inputTensorInfo).first;
4079 if (IsOptionalOperandPresent(operatorPtr->inputs[11]))
4081 params.
m_CellToOutputWeights = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[11]].get(),
4082 inputTensorInfo).first;
4086 if (IsOptionalOperandPresent(operatorPtr->inputs[12]))
4088 params.
m_InputGateBias = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[12]].get(),
4089 inputTensorInfo).first;
4092 params.
m_ForgetGateBias = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[13]].get(),
4093 inputTensorInfo).first;
4094 params.
m_CellBias = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[14]].get(),
4095 inputTensorInfo).first;
4096 params.
m_OutputGateBias = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[15]].get(),
4097 inputTensorInfo).first;
4100 if (IsOptionalOperandPresent(operatorPtr->inputs[16]))
4102 params.
m_ProjectionWeights = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[16]].get(),
4103 inputTensorInfo).first;
4106 if (IsOptionalOperandPresent(operatorPtr->inputs[17]))
4108 params.
m_ProjectionBias = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[17]].get(),
4109 inputTensorInfo).first;
4114 m_ConstantsToBeCreated.push_back(operatorPtr->inputs[18]);
4116 m_ConstantsToBeCreated.push_back(operatorPtr->inputs[19]);
4119 if (inputs.size() >= 21 && IsOptionalOperandPresent(operatorPtr->inputs[20]))
4122 inputTensorInfo).first;
4125 if (inputs.size() >= 22 && IsOptionalOperandPresent(operatorPtr->inputs[21]))
4128 inputTensorInfo).first;
4131 if (inputs.size() >= 23 && IsOptionalOperandPresent(operatorPtr->inputs[22]))
4133 params.
m_CellLayerNormWeights = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[22]].get(),
4134 inputTensorInfo).first;
4137 if (inputs.size() >= 24 && IsOptionalOperandPresent(operatorPtr->inputs[23]))
4140 inputTensorInfo).first;
4161 auto inputIntermediate = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->intermediates[0]].get(),
4162 inputTensorInfo).first;
4163 auto inputIntermediateTensorInfo = inputIntermediate->GetInfo();
4166 auto forgetIntermediate = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->intermediates[1]].get(),
4167 inputTensorInfo).first;
4168 auto forgetIntermediateTensorInfo = forgetIntermediate->GetInfo();
4171 auto cellIntermediate = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->intermediates[2]].get(),
4172 inputTensorInfo).first;
4173 auto cellIntermediateTensorInfo = cellIntermediate->GetInfo();
4176 auto outputIntermediate = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->intermediates[3]].get(),
4177 inputTensorInfo).first;
4178 auto outputIntermediateTensorInfo = outputIntermediate->GetInfo();
4183 float defaultIntermediate = std::pow(2, -12);
4190 if (operatorPtr->intermediates.size() > 4)
4192 auto hiddentensor = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->intermediates[4]].get(),
4193 inputTensorInfo).first;
4199 unsigned int outputSize = outputTensorInfo.
GetShape()[2];
4200 unsigned int numUnits = cellStateInInfo.
GetShape()[1];
4206 armnn::TensorInfo scratchBufferTensorInfo({batchSize, numUnits * 3}, dataType, qScale, qOffset);
4209 scratchBufferTensorInfo =
armnn::TensorInfo({batchSize, numUnits * 4}, dataType, qScale, qOffset);
4215 armnn::TensorInfo outputStateOutTensorInfo({batchSize, outputSize}, dataType, qScale, qOffset);
4265 auto layerName = fmt::format(
"UnidirectionalSequenceLSTM:{}:{}", subgraphIndex, operatorIndex);
4276 auto inputTensorIndexes = AsUnsignedVector({operatorPtr->inputs[0],
4277 operatorPtr->inputs[18],
4278 operatorPtr->inputs[19]});
4279 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0],
4280 inputTensorIndexes[1],
4281 inputTensorIndexes[2]});
4283 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
4289 unsigned int tensorIndex = outputTensorIndexes[0];
4291 RegisterProducerOfTensor(subgraphIndex, tensorIndex, slot);
4294 void TfLiteParserImpl::ParseUnpack(
size_t subgraphIndex,
size_t operatorIndex)
4296 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
4298 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
4299 const auto* options = operatorPtr->builtin_options.AsUnpackOptions();
4304 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
4307 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
4312 fmt::format(
"The unpack axis: {} cannot be greater than or equal to "
4313 "the number of input dimension {} {}",
4323 unpackNum = inputTensorInfo.
GetShape()[unpackAxis];
4329 throw ParseException(
"Number to unpack must greater than zero.");
4332 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
4336 std::vector<unsigned int> unpackDimSizes(inputDimSize);
4339 for (
unsigned int i = 0; i < inputDimSize; ++i)
4341 unpackDimSizes[i] = inputTensorInfo.
GetShape()[i];
4344 if (unpackDimSizes[unpackAxis] != unpackNum)
4346 throw ParseException(
"Number to unpack must be the same as length of the dimension to "
4350 unpackDimSizes[unpackAxis] /= unpackNum;
4352 SplitterDescriptor splitDesc(unpackNum,
static_cast<unsigned int>(unpackDimSizes.size()));
4353 for (
unsigned int j = 0; j < unpackNum; ++j)
4356 for (
unsigned int dimIdx = 0; dimIdx < unpackDimSizes.size(); ++dimIdx)
4358 splitDesc.SetViewSize(j, dimIdx, unpackDimSizes[dimIdx]);
4360 splitDesc.SetViewOriginCoord(j, unpackAxis, unpackDimSizes[unpackAxis] * j);
4362 splitDesc.SetAxis(unpackAxis);
4363 auto layerName = fmt::format(
"Unpack:{}:{}", subgraphIndex, operatorIndex);
4364 IConnectableLayer* layer = m_Network->AddSplitterLayer(splitDesc, layerName.c_str());
4373 unpackDimSizes.data());
4375 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
4376 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
4378 std::vector<unsigned int> reshapeDims;
4379 for (
unsigned int axis = 0; axis < splitOutShape.
GetNumDimensions(); ++axis)
4381 if (axis != unpackAxis)
4383 reshapeDims.push_back(splitOutShape[axis]);
4393 std::string reshapeLayerName = fmt::format(
"Reshape_for:{}", layer->
GetName());
4408 RegisterProducerOfTensor(subgraphIndex, reshapedOutputId, slot);
4412 void TfLiteParserImpl::ParseSplit(
size_t subgraphIndex,
size_t operatorIndex)
4414 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
4416 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
4417 const auto* options = operatorPtr->builtin_options.AsSplitOptions();
4424 throw ParseException(
"Number to splits must greater than zero.");
4427 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
4429 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
4432 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
4433 armnn::TensorInfo axisTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
4437 throw ParseException(fmt::format(
"Axis tensor can only have 1 element {}",
4442 if (axisBufferPtr ==
nullptr)
4445 fmt::format(
"Operation has invalid inputs. Failed to read axis. {}",
4450 ::memcpy(axisData.data(), axisBufferPtr->data.data(), axisTensorInfo.
GetNumBytes());
4451 int32_t axis = axisData[0];
4453 auto inputDimensions =
static_cast<int32_t
>(inputTensorInfo.
GetNumDimensions());
4454 if (((axis < -inputDimensions) && (axis < 0)) || ((axis >= inputDimensions) && (axis > 0)))
4460 fmt::format(
"Operation has invalid axis: {}. Axis must be in range [-n, n) {}",
4471 fmt::format(
"The number of dimensions: {} for input tensors of the split op cannot be greater than {} {}",
4477 std::vector<unsigned int> splitterDimSizes(inputDimSize);
4480 for (
unsigned int i = 0; i < inputDimSize; ++i)
4482 splitterDimSizes[i] = inputTensorInfo.
GetShape()[i];
4485 if (splitterDimSizes[splitDim] % numSplits != 0)
4487 throw ParseException(
"Number of splits must evenly divide the dimension");
4489 splitterDimSizes[splitDim] /= numSplits;
4492 for (
unsigned int j = 0; j < numSplits; ++j)
4495 for (
unsigned int dimIdx = 0; dimIdx < splitterDimSizes.size(); ++dimIdx)
4497 splitDesc.SetViewSize(j, dimIdx, splitterDimSizes[dimIdx]);
4499 splitDesc.SetViewOriginCoord(j, splitDim, splitterDimSizes[splitDim] * j);
4503 splitDesc.SetAxis(axis);
4505 auto layerName = fmt::format(
"Split:{}:{}", subgraphIndex, operatorIndex);
4506 IConnectableLayer* layer = m_Network->AddSplitterLayer(splitDesc, layerName.c_str());
4514 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
4515 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[1]});
4523 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
4524 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
4529 int numDims = armnn::numeric_cast<int>(numDimsIn);
4530 int v = idx < 0 ? numDims + idx : idx;
4532 if (v < 0 || v > numDims)
4537 return static_cast<unsigned int>(v);
4540 void TfLiteParserImpl::ParseSplitV(
size_t subgraphIndex,
size_t operatorIndex)
4542 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
4544 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
4545 const auto* options = operatorPtr->builtin_options.AsSplitVOptions();
4547 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
4550 auto& inputTensor = inputs[0];
4551 auto& splitsTensor = inputs[1];
4552 auto& axisTensor = inputs[2];
4560 throw ParseException(fmt::format(
"Axis tensor can only have 1 element {}",
4569 fmt::format(
"The number of dimensions: {} for input tensors of the "
4570 "SplitV op cannot be greater than {} {}",
4578 if (axisBufferPtr ==
nullptr)
4581 fmt::format(
"Operation has invalid inputs. Failed to read axis. {}",
4586 ::memcpy(axisData.data(), axisBufferPtr->data.data(), axisTensorInfo.
GetNumBytes());
4587 int32_t axis = axisData[0];
4589 auto inputDimensions =
static_cast<int32_t
>(inputTensorInfo.
GetNumDimensions());
4590 if (((axis < -inputDimensions) && (axis < 0)) || ((axis >= inputDimensions) && (axis > 0)))
4596 fmt::format(
"Operation has invalid axis: {}. Axis must be in range [-n, n) {}",
4604 unsigned int numSplits{0};
4620 std::vector<int> splitsData(numSplits);
4622 ::memcpy(splitsData.data(), splitsBufferPtr->data.data(), splitsInfo.
GetNumBytes());
4624 unsigned int idx = 0;
4626 unsigned int inferIdx{0};
4628 for (
auto split : splitsData)
4642 if (numInferred == 0)
4644 if (splitSum != armnn::numeric_cast<int>(inputTensorInfo.
GetShape()[splitDim]))
4646 throw ParseException(
"SplitV split_sizes does not sum to the dimension of value along split_dim.");
4649 else if (numInferred == 1)
4651 splitsData[inferIdx] = armnn::numeric_cast<int>(inputTensorInfo.
GetShape()[splitDim]) - splitSum;
4655 throw ParseException(
"Cannot infer split size for more than one split");
4659 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
4664 unsigned int accumSplit = 0;
4665 for (
unsigned int j = 0; j < numSplits; ++j)
4667 unsigned int splitSize = armnn::numeric_cast<unsigned int>(splitsData[j]);
4670 for (
unsigned int dimIdx = 0; dimIdx < inputTensorInfo.
GetNumDimensions(); ++dimIdx)
4672 unsigned int dimSize = inputTensorInfo.
GetShape()[dimIdx];
4673 if (dimIdx == splitDim)
4675 dimSize = splitSize;
4677 splitDesc.SetViewSize(j, dimIdx, dimSize);
4680 splitDesc.SetViewOriginCoord(j, splitDim, accumSplit);
4681 accumSplit += splitSize;
4683 splitDesc.SetAxis(axis);
4685 auto layerName = fmt::format(
"SplitV:{}:{}", subgraphIndex, operatorIndex);
4686 IConnectableLayer* layer = m_Network->AddSplitterLayer(splitDesc, layerName.c_str());
4694 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
4695 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
4703 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
4704 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
4707 void TfLiteParserImpl::ParseArgMin(
size_t subgraphIndex,
size_t operatorIndex)
4712 void TfLiteParserImpl::ParseArgMax(
size_t subgraphIndex,
size_t operatorIndex)
4717 void TfLiteParserImpl::ParseArgMinMax(
size_t subgraphIndex,
size_t operatorIndex,
ArgMinMaxFunction argMinMaxFunction)
4719 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
4720 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
4723 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
4726 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
4727 armnn::TensorInfo axisTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
4732 throw ParseException(fmt::format(
"Axis tensor can only have 1 element {}",
4742 "Output tensor data type is not supported. (Supported types: Signed32 & Signed64) {}",
4748 if (axisBufferPtr ==
nullptr)
4751 fmt::format(
"Operation has invalid inputs. Failed to read axis. {}",
4756 ::memcpy(axisData.data(), axisBufferPtr->data.data(), axisTensorInfo.
GetNumBytes());
4757 int32_t axis = axisData.front();
4759 auto inputDimensions =
static_cast<int32_t
>(inputTensorInfo.
GetNumDimensions());
4760 if (((axis < -inputDimensions) && (axis < 0)) || ((axis >= inputDimensions) && (axis > 0)))
4766 fmt::format(
"Operation has invalid axis: {}. Axis must be in range [-n, n) {}",
4776 auto layerName = argMinMaxFunction == ArgMinMaxFunction::Max ?
"ArgMax:{}:{}" :
"ArgMin:{}:{}";
4777 auto layerNameFormatted = fmt::format(layerName, subgraphIndex, operatorIndex);
4778 IConnectableLayer *layer = m_Network->AddArgMinMaxLayer(desc, layerNameFormatted.c_str());
4786 outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
4790 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
4791 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
4794 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
4795 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
4798 void TfLiteParserImpl::ParseGather(
size_t subgraphIndex,
size_t operatorIndex)
4800 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
4807 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
4808 armnn::TensorInfo indicesTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
4813 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
4814 const auto* options = operatorPtr->builtin_options.AsGatherOptions();
4815 auto axis = options->axis;
4817 auto layerName = fmt::format(
"Gather:{}:{}", subgraphIndex, operatorIndex);
4819 auto inputDimensions =
static_cast<int32_t
>(inputTensorInfo.
GetNumDimensions());
4822 if (((axis < -inputDimensions) && (axis < 0)) || ((axis >= inputDimensions) && (axis > 0)))
4825 fmt::format(
"Operation has invalid axis: {} It is out of bounds [ -{}, {} ) {}",
4827 inputDimensions, inputDimensions,
4830 if (outputDimensions !=
static_cast<unsigned int>(inputDimensions) + indicesDimensions - 1)
4833 fmt::format(
"Operation has invalid output dimensions: {} Output must be an ({} + {} - 1) -D tensor {}",
4835 inputDimensions, indicesDimensions,
4839 gatherDescriptor.
m_Axis = axis;
4841 IConnectableLayer* layer = m_Network->AddGatherLayer(gatherDescriptor, layerName.c_str());
4849 outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
4852 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
4853 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
4855 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
4856 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
4859 void TfLiteParserImpl::ParseGatherNd(
size_t subgraphIndex,
size_t operatorIndex)
4861 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
4868 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
4869 armnn::TensorInfo indicesTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
4871 auto layerName = fmt::format(
"GatherNd:{}:{}", subgraphIndex, operatorIndex);
4880 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
4883 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
4884 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
4886 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
4887 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
4890 void TfLiteParserImpl::ParseDepthToSpace(
size_t subgraphIndex,
size_t operatorIndex)
4892 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
4901 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
4902 const auto* options = operatorPtr->builtin_options.AsDepthToSpaceOptions();
4903 auto blockSize = options->block_size;
4907 fmt::format(
"Operation has invalid block size: {} Block size should be >= 2 {}",
4911 descriptor.
m_BlockSize = armnn::numeric_cast<uint32_t>(blockSize);
4913 auto layerName = fmt::format(
"DepthToSpace:{}:{}", subgraphIndex, operatorIndex);
4914 IConnectableLayer* layer = m_Network->AddDepthToSpaceLayer(descriptor, layerName.c_str());
4922 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
4925 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
4926 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
4928 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
4929 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
4932 void TfLiteParserImpl::ParseSum(
size_t subgraphIndex,
size_t operatorIndex)
4937 void TfLiteParserImpl::ParseReduceProd(
size_t subgraphIndex,
size_t operatorIndex)
4942 void TfLiteParserImpl::ParseReduceMax(
size_t subgraphIndex,
size_t operatorIndex)
4947 void TfLiteParserImpl::ParseReduceMin(
size_t subgraphIndex,
size_t operatorIndex)
4952 void TfLiteParserImpl::ParseReduce(
size_t subgraphIndex,
size_t operatorIndex,
ReduceOperation reduceOperation)
4954 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
4956 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
4957 const auto* options = operatorPtr->builtin_options.AsReducerOptions();
4959 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
4962 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
4965 auto layerName = fmt::format(
"Reduce:{}:{}", subgraphIndex, operatorIndex);
4967 armnn::TensorInfo inputTensorInfo0 = InputTensorInfo(subgraphIndex, operatorIndex, 0);
4968 armnn::TensorInfo inputTensorInfo1 = InputTensorInfo(subgraphIndex, operatorIndex, 1);
4973 if (axisBufferPtr !=
nullptr)
4975 std::vector<int32_t> axisData(inputTensorInfo1.
GetNumElements());
4976 ::memcpy(axisData.data(), axisBufferPtr->data.data(), inputTensorInfo1.
GetNumBytes());
4980 std::set<unsigned int> uniqueAxis;
4981 std::transform(axisData.begin(),
4983 std::inserter(uniqueAxis, uniqueAxis.begin()),
4984 [rank](
int i)->unsigned
int{
4985 return static_cast<uint32_t>(((i + rank) % rank)); });
4986 desc.
m_vAxis.assign(uniqueAxis.begin(), uniqueAxis.end());
5002 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
5006 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
5007 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
5010 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
5011 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
5014 void TfLiteParserImpl::ParseLocalResponseNormalization(
size_t subgraphIndex,
size_t operatorIndex)
5016 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
5018 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
5021 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
5024 auto layerName = fmt::format(
"LRN:{}:{}", subgraphIndex, operatorIndex);
5025 std::string layerNameFormatted = fmt::format(layerName, subgraphIndex, operatorIndex);
5027 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
5029 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
5030 const auto* options = operatorPtr->builtin_options.AsLocalResponseNormalizationOptions();
5036 descriptor.
m_NormSize =
static_cast<uint32_t
>(options->radius);
5037 descriptor.
m_K = options->bias;
5038 descriptor.
m_Alpha = options->alpha;
5039 descriptor.
m_Beta = options->beta;
5045 IConnectableLayer* layer = m_Network->AddNormalizationLayer(descriptor, layerNameFormatted.c_str());
5053 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
5056 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
5057 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
5059 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
5060 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
5063 void TfLiteParserImpl::ParseAbs(
size_t subgraphIndex,
size_t operatorIndex)
5068 void TfLiteParserImpl::ParseCeil(
size_t subgraphIndex,
size_t operatorIndex)
5073 void TfLiteParserImpl::ParseExp(
size_t subgraphIndex,
size_t operatorIndex)
5078 void TfLiteParserImpl::ParseLog(
size_t subgraphIndex,
size_t operatorIndex)
5083 void TfLiteParserImpl::ParseLogicalNot(
size_t subgraphIndex,
size_t operatorIndex)
5088 void TfLiteParserImpl::ParseNeg(
size_t subgraphIndex,
size_t operatorIndex)
5093 void TfLiteParserImpl::ParsePower(
size_t subgraphIndex,
size_t operatorIndex)
5095 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
5097 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
5100 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
5103 auto layerName = fmt::format(
"Power:{}:{}", subgraphIndex, operatorIndex);
5105 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
5106 TensorInfo input1TensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
5107 CheckMatchingQuantization(inputTensorInfo, input1TensorInfo, layerName,
"Input 0",
"Input 1");
5109 IConnectableLayer* layer = m_Network->AddElementwiseBinaryLayer(BinaryOperation::Power, layerName.c_str());
5117 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
5118 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
5121 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
5122 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
5124 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
5125 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
5128 void TfLiteParserImpl::ParseRsqrt(
size_t subgraphIndex,
size_t operatorIndex)
5133 void TfLiteParserImpl::ParseSin(
size_t subgraphIndex,
size_t operatorIndex)
5138 void TfLiteParserImpl::ParseSqrt(
size_t subgraphIndex,
size_t operatorIndex)
5143 void TfLiteParserImpl::ParseSquare(
size_t subgraphIndex,
size_t operatorIndex)
5145 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
5147 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
5150 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
5153 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
5155 auto layerName = fmt::format(
"Square:{}:{}", subgraphIndex, operatorIndex);
5156 IConnectableLayer* layer = m_Network->AddElementwiseBinaryLayer(BinaryOperation::Mul, layerName.c_str());
5159 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 0});
5160 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
5163 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
5164 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[0]});
5166 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
5167 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
5170 void TfLiteParserImpl::ParseSquaredDifference(
size_t subgraphIndex,
size_t operatorIndex)
5172 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
5174 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
5177 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
5180 auto layerName = fmt::format(
"SquaredDifference:{}:{}", subgraphIndex, operatorIndex);
5182 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
5183 TensorInfo input1TensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
5185 IConnectableLayer* layer = m_Network->AddElementwiseBinaryLayer(BinaryOperation::SqDiff, layerName.c_str());
5193 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
5196 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
5197 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
5199 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
5200 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
5203 void TfLiteParserImpl::ParseElementwiseUnary(
size_t subgraphIndex,
size_t operatorIndex,
UnaryOperation unaryOperation)
5205 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
5207 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
5210 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
5214 std::string layerNameFormatted = fmt::format(layerName, subgraphIndex, operatorIndex);
5218 IConnectableLayer* layer = m_Network->AddElementwiseUnaryLayer(desc, layerNameFormatted.c_str());
5226 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
5229 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
5230 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
5232 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
5233 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
5236 void TfLiteParserImpl::ParseEqual(
size_t subgraphIndex,
size_t operatorIndex)
5241 void TfLiteParserImpl::ParseNotEqual(
size_t subgraphIndex,
size_t operatorIndex)
5246 void TfLiteParserImpl::ParseGreater(
size_t subgraphIndex,
size_t operatorIndex)
5251 void TfLiteParserImpl::ParseGreaterOrEqual(
size_t subgraphIndex,
size_t operatorIndex)
5256 void TfLiteParserImpl::ParseLess(
size_t subgraphIndex,
size_t operatorIndex)
5261 void TfLiteParserImpl::ParseLessOrEqual(
size_t subgraphIndex,
size_t operatorIndex)
5266 void TfLiteParserImpl::ParseComparison(
size_t subgraphIndex,
size_t operatorIndex,
5269 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
5271 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
5274 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
5278 std::string layerNameFormatted = fmt::format(layerName, subgraphIndex, operatorIndex);
5280 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
5281 armnn::TensorInfo input1TensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
5282 CheckMatchingQuantization(inputTensorInfo, input1TensorInfo, layerNameFormatted,
"Input 0",
"Input 1");
5286 IConnectableLayer* layer = m_Network->AddComparisonLayer(desc, layerNameFormatted.c_str());
5294 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
5297 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
5298 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
5300 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
5301 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
5305 unsigned int outputSlot,
5306 std::string reshapeLayerName,
5313 m_Network->AddReshapeLayer(desc, reshapeLayerName.c_str());
5318 return reshapeLayer;
5322 unsigned int outputSlot,
5323 tflite::ActivationFunctionType activationType)
5326 std::string layerName = prevLayer->
GetName();
5328 switch(activationType)
5330 case tflite::ActivationFunctionType_NONE:
5335 case tflite::ActivationFunctionType_RELU:
5337 activationDesc.
m_Function = ActivationFunction::ReLu;
5338 layerName +=
":RELU";
5341 case tflite::ActivationFunctionType_RELU6:
5343 activationDesc.
m_Function = ActivationFunction::BoundedReLu;
5344 activationDesc.
m_A = 6.0f;
5345 activationDesc.
m_B = 0.0f;
5346 layerName +=
":RELU6";
5349 case tflite::ActivationFunctionType_TANH:
5351 activationDesc.
m_Function = ActivationFunction::TanH;
5352 activationDesc.
m_A = 1.0f;
5353 activationDesc.
m_B = 1.0f;
5354 layerName +=
":TANH";
5359 case tflite::ActivationFunctionType_RELU_N1_TO_1:
5360 case tflite::ActivationFunctionType_SIGN_BIT:
5364 fmt::format(
"TfLite parser doesn't support fused activation: "
5367 tflite::EnumNameActivationFunctionType(activationType),
5374 m_Network->AddActivationLayer(activationDesc, layerName.c_str());
5376 auto & prevOutputSlot = prevLayer->
GetOutputSlot(outputSlot);
5379 return activationLayer;
5383 unsigned int outputSlot)
5386 auto& prevOutputSlot = prevLayer->
GetOutputSlot(outputSlot);
5389 if (dataType == DataType::Signed32)
5394 std::string layerName = prevLayer->
GetName();
5405 if (fileName ==
nullptr)
5410 std::error_code errorCode;
5411 fs::path pathToFile(fileName);
5412 if (!fs::exists(pathToFile, errorCode))
5415 std::stringstream msg;
5416 msg <<
"Cannot find the file (" << fileName <<
") errorCode: " << errorCode
5420 if (!fs::is_regular_file(pathToFile))
5424 pathToFile.c_str()));
5427 std::ifstream file(fileName, std::ios::binary);
5428 std::string fileContent((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
5430 fileContent.size());
5435 if (binaryContent ==
nullptr)
5440 flatbuffers::Verifier verifier(binaryContent, len);
5441 if (verifier.VerifyBuffer<tflite::Model>() ==
false)
5444 fmt::format(
"Buffer doesn't conform to the expected Tensorflow Lite "
5445 "flatbuffers format. size:{} {}",
5449 return tflite::UnPackModel(binaryContent);
5453 size_t subgraphIndex,
5454 size_t operatorIndex)
5458 const auto& subgraphPtr = model->subgraphs[subgraphIndex];
5459 const auto& operatorPtr = subgraphPtr->operators[operatorIndex];
5461 size_t inputCount = operatorPtr->inputs.size();
5463 for (
size_t i = 0; i < inputCount; ++i)
5466 if (operatorPtr->inputs[i] == -1)
5473 result.push_back(subgraphPtr->tensors[inputId].get());
5480 size_t subgraphIndex,
5481 size_t operatorIndex)
5485 const auto& subgraphPtr = model->subgraphs[subgraphIndex];
5486 const auto& operatorPtr = subgraphPtr->operators[operatorIndex];
5488 size_t outputCount = operatorPtr->outputs.size();
5490 for (
size_t i = 0; i < outputCount; ++i)
5494 result[i] = subgraphPtr->tensors[outputId].get();
5500 size_t subgraphIndex)
5503 const auto& subgraphPtr = model->subgraphs[subgraphIndex];
5505 size_t inputCount = subgraphPtr->inputs.size();
5507 for (
size_t i = 0; i < inputCount; ++i)
5511 result[i] = std::make_pair(inputId, subgraphPtr->tensors[inputId].get());
5517 size_t subgraphIndex)
5520 const auto& subgraphPtr = model->subgraphs[subgraphIndex];
5522 size_t outputCount = subgraphPtr->outputs.size();
5524 for (
size_t i = 0; i < outputCount; ++i)
5527 result[i] = std::make_pair(outputId, subgraphPtr->tensors[outputId].get());
5533 size_t subgraphIndex,
5534 size_t operatorIndex)
5537 const auto& subgraphPtr = model->subgraphs[subgraphIndex];
5538 const auto& operatorPtr = subgraphPtr->operators[operatorIndex];
5539 return operatorPtr->inputs;
5543 size_t subgraphIndex,
5544 size_t operatorIndex)
5547 const auto& subgraphPtr = model->subgraphs[subgraphIndex];
5548 const auto& operatorPtr = subgraphPtr->operators[operatorIndex];
5549 return operatorPtr->outputs;
5552 void TfLiteParserImpl::RegisterInputSlots(
size_t subgraphIndex,
5553 size_t operatorIndex,
5555 const std::vector<unsigned int>& tensorIndexes,
5556 unsigned int startingSlotIndex)
5558 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
5569 fmt::format(
"The number of tensor inputs ({}) does not match the number expected ({})"
5570 " for subgraph:{} operator index:{} {}",
5571 tensorIndexes.size(),
5578 for (
unsigned int index = 0; index < tensorIndexes.size() ; ++index)
5580 unsigned int tensorIndex = tensorIndexes[index];
5582 RegisterConsumerOfTensor(subgraphIndex, tensorIndex, slot);
5586 void TfLiteParserImpl::RegisterOutputSlots(
size_t subgraphIndex,
5587 size_t operatorIndex,
5589 const std::vector<unsigned int>& tensorIndexes)
5591 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
5602 fmt::format(
"The number of tensor outputs ({}) does not match the number expected ({})"
5603 " for subgraph:{} operator index:{} {}",
5604 tensorIndexes.size(),
5611 for (
unsigned int slotIndex = 0; slotIndex < layer->
GetNumOutputSlots(); ++slotIndex)
5613 unsigned int tensorIndex = tensorIndexes[slotIndex];
5615 RegisterProducerOfTensor(subgraphIndex, tensorIndex, slot);
5619 void TfLiteParserImpl::SetupInputLayerTensorInfos(
size_t subgraphIndex)
5624 for (
auto const& tensorIdAndPtr : inputs)
5627 m_TensorInfos.insert({tensorIdAndPtr.first, tensorInfo});
5631 void TfLiteParserImpl::SetupInputLayers(
size_t subgraphIndex)
5636 for (
auto const& tensorIdAndPtr : inputs)
5638 auto bindingId = GenerateLayerBindingId(subgraphIndex, tensorIdAndPtr.first);
5640 m_Network->AddInputLayer(bindingId, tensorIdAndPtr.second->name.c_str());
5645 RegisterOutputSlots(subgraphIndex,
5646 VIRTUAL_OPERATOR_ID,
5648 {
static_cast<uint32_t
>(tensorIdAndPtr.first) });
5652 void TfLiteParserImpl::SetupOutputLayers(
size_t subgraphIndex)
5657 for (
auto const& tensorIdAndPtr : outputs)
5659 auto bindingId = GenerateLayerBindingId(subgraphIndex, tensorIdAndPtr.first);
5661 m_Network->AddOutputLayer(bindingId, tensorIdAndPtr.second->name.c_str());
5663 RegisterInputSlots(subgraphIndex,
5664 VIRTUAL_OPERATOR_ID,
5666 {
static_cast<uint32_t
>(tensorIdAndPtr.first) });
5670 void TfLiteParserImpl::SetupConstantLayerTensorInfos(
size_t subgraph)
5674 const auto & subgraphPtr = m_Model->subgraphs[subgraph];
5675 for (
unsigned int subgraphIndex = 0; subgraphIndex < m_SubgraphConnections.size(); ++subgraphIndex)
5677 for (
unsigned int tensorIndex = 0; tensorIndex < m_SubgraphConnections[subgraphIndex].size(); ++tensorIndex)
5679 if (m_SubgraphConnections[subgraphIndex][tensorIndex].outputSlot ==
nullptr &&
5680 m_SubgraphConnections[subgraphIndex][tensorIndex].inputSlots.size() > 0)
5682 TensorRawPtr tensorPtr = subgraphPtr->tensors[tensorIndex].get();
5686 m_TensorInfos.insert({tensorIndex, tensorInfo});
5692 void TfLiteParserImpl::SetupConstantLayers(
size_t subgraph)
5696 const auto & subgraphPtr = m_Model->subgraphs[subgraph];
5697 for (
unsigned int subgraphIndex = 0; subgraphIndex < m_SubgraphConnections.size(); ++subgraphIndex)
5699 for (
unsigned int tensorIndex = 0; tensorIndex < m_SubgraphConnections[subgraphIndex].size(); ++tensorIndex)
5701 if (m_SubgraphConnections[subgraphIndex][tensorIndex].outputSlot ==
nullptr &&
5702 m_SubgraphConnections[subgraphIndex][tensorIndex].inputSlots.size() > 0)
5704 TensorRawPtr tensorPtr = subgraphPtr->tensors[tensorIndex].get();
5706 if (IsConstTensor(tensorPtr))
5711 if (std::find(m_ConstantsToDequantize.begin(), m_ConstantsToDequantize.end(), tensorPtr->buffer)
5712 != m_ConstantsToDequantize.end())
5714 dataType = DataType::Float32;
5716 auto tensorAndData = CreateConstTensorNonPermuted(tensorPtr, tensorInfo, dataType);
5718 std::string layerName = fmt::format(
"Constant:{}", tensorPtr->name);
5719 IConnectableLayer *layer = m_Network->AddConstantLayer(tensorAndData.first, layerName.c_str());
5722 RegisterOutputSlots(subgraphIndex,
5723 VIRTUAL_OPERATOR_ID,
5727 else if (ShouldConstantTensorBeCreated(tensorIndex))
5732 if (std::find(m_ConstantsToDequantize.begin(), m_ConstantsToDequantize.end(), tensorPtr->buffer)
5733 != m_ConstantsToDequantize.end())
5735 dataType = DataType::Float32;
5743 std::string layerName = fmt::format(
"Constant:{}", tensorPtr->name);
5744 IConnectableLayer* layer = m_Network->AddConstantLayer(tensorAndData, layerName.c_str());
5747 RegisterOutputSlots(subgraphIndex,
5748 VIRTUAL_OPERATOR_ID,
5755 fmt::format(
"Invalid Tensor: Tensor should be constant. {}",
5767 return model->buffers[bufferIndex].get();
5770 template<
typename T>
5771 std::pair<armnn::ConstTensor, TfLiteParserImpl::SupportedDataStorage>
5780 auto constData = CreateConstTensorImpl<T>(bufferPtr,
5784 TfLiteParserImpl::SupportedDataStorage storage(std::move(constData.second));
5785 return std::make_pair(constData.first, std::move(storage));
5788 bool TfLiteParserImpl::ShouldConstantTensorBeCreated(
unsigned int tensorIndex)
5791 return (std::find(m_ConstantsToBeCreated.begin(), m_ConstantsToBeCreated.end(), tensorIndex)
5792 != m_ConstantsToBeCreated.end());
5795 bool TfLiteParserImpl::IsConstTensor(
TensorRawPtr tensorPtr)
5798 bool isConst =
true;
5800 auto buffer =
GetBuffer(m_Model, tensorPtr->buffer);
5801 if (buffer->data.size() == 0)
5809 std::pair<armnn::ConstTensor, TfLiteParserImpl::SupportedDataStorage>
5810 TfLiteParserImpl::CreateConstTensorPermuted(
TensorRawPtr tensorPtr,
5815 auto bufferPtr =
GetBuffer(m_Model, tensorPtr->buffer);
5824 return CreateConstTensorAndStoreData<float>(bufferPtr,
5829 return CreateConstTensorAndStoreData<uint8_t>(bufferPtr,
5834 return CreateConstTensorAndStoreData<int8_t>(bufferPtr,
5839 return CreateConstTensorAndStoreData<int8_t>(bufferPtr,
5844 return CreateConstTensorAndStoreData<int32_t>(bufferPtr,
5850 std::stringstream errString;
5851 errString <<
"Unexpected datatype when creating const tensor: "
5853 <<
" shape:" << tensorInfo.
GetShape()
5864 auto bufferPtr =
GetBuffer(m_Model, tensorPtr->buffer);
5870 return ConstTensor(tensorInfo, bufferPtr->data.data());
5873 std::pair<armnn::ConstTensor, std::unique_ptr<float[]>>
5874 TfLiteParserImpl::CreateConstTensorNonPermuted(
TensorRawPtr tensorPtr,
5879 auto bufferPtr =
GetBuffer(m_Model, tensorPtr->buffer);
5885 if (inputDataType == DataType::Float32 && tensorInfo.
GetDataType() != DataType::Float32)
5891 return std::make_pair(
ConstTensor(constTensorInfo, data.get()), std::move(data));
5896 fmt::format(
"Unsupported input/weights combination: Input {} not supported with Weights {}",
5904 return std::make_pair(
ConstTensor(tensorInfo, bufferPtr->data.data()), std::unique_ptr<
float[]>());
5908 std::pair<armnn::ConstTensor*, std::unique_ptr<float[]>>
5913 auto bufferPtr =
GetBuffer(m_Model, tensorPtr->buffer);
5925 return std::make_pair(
new ConstTensor(constTensorInfo, data.get()), std::move(data));
5930 fmt::format(
"Unsupported input/weights combination: Input {} not supported with Weights {}",
5938 return std::make_pair(
new ConstTensor(tensorInfo, bufferPtr->data.data()), std::unique_ptr<
float[]>());
5943 const std::string& name)
const
5947 for (
auto const& input : inputs)
5949 if (input.second->name == name)
5951 auto bindingId = GenerateLayerBindingId(subgraphId, input.first);
5955 return std::make_pair(bindingId, inputTensorInfo);
5959 std::stringstream bindings;
5960 for (
auto const& input : inputs)
5962 bindings <<
"'" << input.second->name <<
"' ";
5966 fmt::format(
"No input binding found for subgraph:{} and name:{}. "
5967 "Possible inputs are: [{}] {}",
5975 const std::string& name)
const
5979 for (
unsigned int i = 0; i < outputs.size(); ++i)
5981 auto const output = outputs[i];
5982 if (output.second->name == name)
5984 auto bindingId = GenerateLayerBindingId(subgraphId, output.first);
5985 std::vector<unsigned int> shape = m_OverriddenOutputShapes.size() > 0 ?
5986 m_OverriddenOutputShapes[i] : AsUnsignedVector(output.second->shape);
5987 return std::make_pair(bindingId,
ToTensorInfo(output.second, shape));
5991 std::stringstream bindings;
5992 for (
auto const& output : outputs)
5994 bindings <<
"'" << output.second->name <<
"' ";
5998 fmt::format(
"No output binding found for subgraph:{} and name:{}. "
5999 "Possible outputs are: [{}] {}",
6008 return m_Model->subgraphs.size();
6015 std::vector<std::string> result;
6016 result.reserve(inputs.size());
6017 for (
auto const& input : inputs)
6019 result.push_back(input.second->name);
6028 std::vector<std::string> result;
6029 result.reserve(outputs.size());
6030 for (
auto const& output : outputs)
6032 result.push_back(output.second->name);
6042 TfLiteParserImpl::SupportedDataStorage::SupportedDataStorage(std::unique_ptr<
float[]>&& data)
6043 : m_FloatData(
std::move(data))
6044 , m_Uint8Data(nullptr)
6045 , m_Int8Data(nullptr)
6046 , m_Int32Data(nullptr)
6050 TfLiteParserImpl::SupportedDataStorage::SupportedDataStorage(std::unique_ptr<uint8_t[]>&& data)
6051 : m_FloatData(nullptr)
6052 , m_Uint8Data(
std::move(data))
6053 , m_Int8Data(nullptr)
6054 , m_Int32Data(nullptr)
6058 TfLiteParserImpl::SupportedDataStorage::SupportedDataStorage(std::unique_ptr<int8_t[]>&& data)
6059 : m_FloatData(nullptr)
6060 , m_Uint8Data(nullptr)
6061 , m_Int8Data(
std::move(data))
6062 , m_Int32Data(nullptr)
6066 TfLiteParserImpl::SupportedDataStorage::SupportedDataStorage(std::unique_ptr<int32_t[]>&& data)
6067 : m_FloatData(nullptr)
6068 , m_Uint8Data(nullptr)
6069 , m_Int8Data(nullptr)
6070 , m_Int32Data(
std::move(data))
#define ARMNN_ASSERT(COND)
#define ARMNN_LOG(severity)
#define CHECK_SUBGRAPH(MODEL, SUBGRAPH_INDEX)
#define ARMNN_THROW_PARSE_EXCEPTION(msg)
#define CHECK_BUFFER(MODEL, BUFFER_INDEX)
#define CHECK_TENSOR(MODEL, SUBGRAPH_INDEX, TENSOR_INDEX)
#define CHECK_SUPPORTED_FUSED_ACTIVATION(OPTION, SUBGRAPH_INDEX, OPERATOR_INDEX)
#define CHECK_TENSOR_PTR(TENSOR_PTR)
#define CHECK_BUFFER_SIZE(BUFFER_PTR, TENSOR_INFO, BUFFER_ID)
#define CHECK_MODEL(MODEL, SUBGRAPH_INDEX, OPERATOR_INDEX)
#define CHECK_VALID_SIZE(ACTUAL,...)
#define CHECKED_NON_NEGATIVE(VALUE)
const TensorInfo & GetInfo() const
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
virtual const char * what() const noexcept override
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
virtual unsigned int GetNumInputSlots() const =0
Returns the number of connectable input slots.
virtual std::vector< TensorShape > InferOutputShapes(const std::vector< TensorShape > &inputShapes) const =0
Infer the shape of the output(s) based on the provided input shape(s)
virtual unsigned int GetNumOutputSlots() const =0
Returns the number of connectable output slots.
virtual LayerType GetType() const =0
Returns the armnn::LayerType of this layer.
virtual const char * GetName() const =0
Returns the name of the layer.
An output connection slot for a layer.
virtual const IConnectableLayer & GetOwningIConnectableLayer() const =0
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
virtual const TensorInfo & GetTensorInfo() const =0
virtual int Connect(IInputSlot &destination)=0
bool has_value() const noexcept
float GetQuantizationScale() const
unsigned int GetNumDimensions() const
bool IsTypeSpaceMatch(const TensorInfo &other) const
Check that the types are the same and, if quantize, that the quantization parameters are the same.
void SetDataType(DataType type)
int32_t GetQuantizationOffset() const
unsigned int GetNumElements() const
const TensorShape & GetShape() const
void SetConstant(const bool IsConstant=true)
Marks the data corresponding to this tensor info as constant.
unsigned int GetNumBytes() const
void SetShape(const TensorShape &newShape)
DataType GetDataType() const
unsigned int GetNumDimensions() const
Function that returns the tensor rank.
unsigned int GetNumElements() const
Function that calculates the tensor elements by multiplying all dimension size which are Specified.
armnn::INetworkPtr CreateNetworkFromBinaryFile(const char *graphFile)
Create the network from a flatbuffers binary file on disk.
armnn::INetworkPtr LoadModel(std::unique_ptr< tflite::ModelT > model)
size_t GetSubgraphCount() const
Return the number of subgraphs in the parsed model.
static TensorIdRawPtrVector GetSubgraphOutputs(const ModelPtr &model, size_t subgraphIndex)
static TensorIdRawPtrVector GetSubgraphInputs(const ModelPtr &model, size_t subgraphIndex)
static TensorRawPtrVector GetOutputs(const ModelPtr &model, size_t subgraphIndex, size_t operatorIndex)
armnn::INetworkPtr CreateNetworkFromBinary(const std::vector< uint8_t > &binaryContent)
Create the network from a flatbuffers binary.
static TensorRawPtrVector GetInputs(const ModelPtr &model, size_t subgraphIndex, size_t operatorIndex)
BindingPointInfo GetNetworkOutputBindingInfo(size_t subgraphId, const std::string &name) const
Retrieve binding info (layer id and tensor info) for the network output identified by the given layer...
static BufferRawPtr GetBuffer(const ModelPtr &model, size_t bufferIndex)
static armnn::TensorInfo OutputShapeOfSqueeze(std::vector< uint32_t > squeezeDims, const armnn::TensorInfo &inputTensorInfo)
static ModelPtr LoadModelFromBinary(const uint8_t *binaryContent, size_t len)
std::vector< TensorIdRawPtr > TensorIdRawPtrVector
static std::vector< int32_t > & GetInputTensorIds(const ModelPtr &model, size_t subgraphIndex, size_t operatorIndex)
BindingPointInfo GetNetworkInputBindingInfo(size_t subgraphId, const std::string &name) const
Retrieve binding info (layer id and tensor info) for the network input identified by the given layer ...
std::vector< std::string > GetSubgraphOutputTensorNames(size_t subgraphId) const
Return the output tensor names for a given subgraph.
std::unique_ptr< tflite::SubGraphT > SubgraphPtr
static const std::string GetVersion()
Retrieve version in X.Y.Z form.
const tflite::BufferT * BufferRawPtr
std::unique_ptr< tflite::OperatorT > OperatorPtr
static armnn::TensorInfo OutputShapeOfReshape(const armnn::TensorInfo &inputTensorInfo, const std::vector< int32_t > &targetDimsIn)
std::vector< TensorRawPtr > TensorRawPtrVector
std::unique_ptr< tflite::ModelT > ModelPtr
const tflite::TensorT * TensorRawPtr
armnn::INetworkPtr CreateNetworkFromBinaryFile(const char *graphFile)
Create the network from a flatbuffers binary file on disk.
static ModelPtr LoadModelFromFile(const char *fileName)
std::vector< std::string > GetSubgraphInputTensorNames(size_t subgraphId) const
Return the input tensor names for a given subgraph.
static std::vector< int32_t > & GetOutputTensorIds(const ModelPtr &model, size_t subgraphIndex, size_t operatorIndex)
#define TFLITE_PARSER_VERSION
TFLITE_PARSER_VERSION: "X.Y.Z" where: X = Major version number Y = Minor version number Z = Patch ver...
const armnnSerializer::TensorInfo * TensorRawPtr
armnn::TensorInfo ToTensorInfo(TensorRawPtr tensorPtr)
bool CheckShape(const armnn::TensorShape &actual, const std::vector< uint32_t > &expected)
Copyright (c) 2021 ARM Limited and Contributors.
void IgnoreUnused(Ts &&...)
std::vector< BackendOptions > NetworkOptions
constexpr char const * GetUnaryOperationAsCString(UnaryOperation operation)
constexpr const char * GetDataTypeName(DataType dataType)
constexpr char const * GetComparisonOperationAsCString(ComparisonOperation operation)
int LayerBindingId
Type of identifiers for bindable layers (inputs, outputs).
constexpr unsigned int MaxNumOfTensorDimensions
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
@ LocalBrightness
Krichevsky 2012: Local Brightness Normalization.
std::unique_ptr< onnx::ModelProto > ModelPtr
std::pair< armnn::ConstTensor, std::unique_ptr< T[]> > CreateConstTensorImpl(const T *bufferPtr, armnn::TensorInfo &tensorInfo, const armnn::Optional< armnn::PermutationVector & > permutationVector)
unsigned int ComputeWrappedIndex(int idx, unsigned int numDimsIn)
armnn::BindingPointInfo BindingPointInfo
std::unique_ptr< ITfLiteParser, void(*)(ITfLiteParser *parser)> ITfLiteParserPtr
void ProcessConcatInputTensorInfo(armnn::TensorInfo &inputTensorInfo, armnn::OriginsDescriptor &concatDescriptor, const unsigned int &concatAxis, unsigned int inputIndex, unsigned int &mergeDimOrigin)
std::unique_ptr< float[]> ToFloatArray(const std::vector< PrimitiveType > &data, const armnn::TensorInfo &tensorInfo)
armnn::TensorShape Permuted(const armnn::TensorShape &srcShape, const armnn::PermutationVector &mappings)
unsigned int GetUnsignedAxis(const unsigned int inputDimension, const int axis)
void Permute(const armnn::TensorShape &dstShape, const armnn::PermutationVector &mappings, const void *src, void *dst, size_t dataTypeSize)
An ActivationDescriptor for the ActivationLayer.
float m_A
Alpha upper bound value used by the activation functions. (BoundedReLu, Linear, TanH,...
float m_B
Beta lower bound value used by the activation functions. (BoundedReLu, Linear, TanH).
ActivationFunction m_Function
The activation function to use (Sigmoid, TanH, Linear, ReLu, BoundedReLu, SoftReLu,...
An ArgMinMaxDescriptor for ArgMinMaxLayer.
int m_Axis
Axis to reduce across the input tensor.
ArgMinMaxFunction m_Function
Specify if the function is to find Min or Max.
Struct for the users to pass backend specific options.
A BatchMatMulDescriptor for the BatchMatMul operator.
A BatchToSpaceNdDescriptor for the BatchToSpaceNdLayer.
std::vector< unsigned int > m_BlockShape
Block shape values.
std::vector< std::pair< unsigned int, unsigned int > > m_Crops
The values to crop from the input dimension.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
TensorShape m_BroadcastToShape
Target shape value.
std::string AsString() const
std::string FileLine() const
A ComparisonDescriptor for the ComparisonLayer.
ComparisonOperation m_Operation
Specifies the comparison operation to execute.
A Convolution2dDescriptor for the Convolution2dLayer.
uint32_t m_PadRight
Padding right value in the width dimension.
uint32_t m_DilationY
Dilation along y axis.
uint32_t m_PadTop
Padding top value in the height dimension.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
uint32_t m_DilationX
Dilation along x axis.
uint32_t m_PadBottom
Padding bottom value in the height dimension.
uint32_t m_PadLeft
Padding left value in the width dimension.
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
bool m_BiasEnabled
Enable/disable bias.
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
A Convolution3dDescriptor for the Convolution3dLayer.
uint32_t m_PadRight
Padding right value in the width dimension.
uint32_t m_PadBack
Padding back value in the depth dimension.
uint32_t m_DilationZ
Dilation along z axis.
uint32_t m_DilationY
Dilation along y axis.
uint32_t m_StrideZ
Stride value when proceeding through input for the depth dimension.
uint32_t m_PadTop
Padding top value in the height dimension.
DataLayout m_DataLayout
The data layout to be used (NDHWC, NCDHW).
uint32_t m_PadFront
Padding front value in the depth dimension.
uint32_t m_DilationX
Dilation along x axis.
uint32_t m_PadBottom
Padding bottom value in the height dimension.
uint32_t m_PadLeft
Padding left value in the width dimension.
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
bool m_BiasEnabled
Enable/disable bias.
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
A DepthwiseConvolution2dDescriptor for the DepthwiseConvolution2dLayer.
uint32_t m_PadRight
Padding right value in the width dimension.
uint32_t m_DilationY
Dilation factor value for height dimension.
uint32_t m_PadTop
Padding top value in the height dimension.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
uint32_t m_DilationX
Dilation factor value for width dimension.
uint32_t m_PadBottom
Padding bottom value in the height dimension.
uint32_t m_PadLeft
Padding left value in the width dimension.
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
bool m_BiasEnabled
Enable/disable bias.
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
uint32_t m_NumClasses
Number of classes.
float m_NmsScoreThreshold
NMS score threshold.
float m_NmsIouThreshold
Intersection over union threshold.
float m_ScaleY
Center size encoding scale y.
uint32_t m_DetectionsPerClass
Detections per classes, used in Regular NMS.
bool m_UseRegularNms
Use Regular NMS.
uint32_t m_MaxClassesPerDetection
Maximum numbers of classes per detection, used in Fast NMS.
float m_ScaleH
Center size encoding scale height.
float m_ScaleW
Center size encoding scale weight.
float m_ScaleX
Center size encoding scale x.
uint32_t m_MaxDetections
Maximum numbers of detections.
A ElementwiseUnaryDescriptor for the ElementwiseUnaryLayer.
UnaryOperation m_Operation
Specifies the elementwiseUnary operation to execute.
EmptyOptional is used to initialize the Optional class in case we want to have default value for an O...
A FullyConnectedDescriptor for the FullyConnectedLayer.
bool m_TransposeWeightMatrix
Enable/disable transpose weight matrix.
bool m_ConstantWeights
Enable/disable constant weights and biases.
bool m_BiasEnabled
Enable/disable bias.
A GatherDescriptor for the GatherLayer.
int32_t m_Axis
The axis in params to gather indices from.
A L2NormalizationDescriptor for the L2NormalizationLayer.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
An LstmDescriptor for the LstmLayer.
float m_CellIntermediateScale
Cell intermediate quantization scale.
float m_InputIntermediateScale
Input intermediate quantization scale.
bool m_PeepholeEnabled
Enable/disable peephole.
bool m_TimeMajor
Enable/disable time major.
int32_t m_HiddenStateZeroPoint
Hidden State zero point.
bool m_LayerNormEnabled
Enable/disable layer normalization.
float m_ClippingThresCell
Clipping threshold value for the cell state.
bool m_ProjectionEnabled
Enable/disable the projection layer.
float m_ClippingThresProj
Clipping threshold value for the projection.
float m_OutputIntermediateScale
Output intermediate quantization scale.
bool m_CifgEnabled
Enable/disable cifg (coupled input & forget gate).
uint32_t m_ActivationFunc
The activation function to use.
float m_HiddenStateScale
Hidden State quantization scale.
float m_ForgetIntermediateScale
Forget intermediate quantization scale.
A MeanDescriptor for the MeanLayer.
std::vector< unsigned int > m_Axis
Values for the dimensions to reduce.
bool m_KeepDims
Enable/disable keep dimensions. If true, then the reduced dimensions that are of length 1 are kept.
A NormalizationDescriptor for the NormalizationLayer.
NormalizationAlgorithmMethod m_NormMethodType
Normalization method algorithm to use (LocalBrightness, LocalContrast).
float m_Alpha
Alpha value for the normalization equation.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
float m_Beta
Beta value for the normalization equation.
float m_K
Kappa value used for the across channel normalization equation.
uint32_t m_NormSize
Depth radius value.
NormalizationAlgorithmChannel m_NormChannelType
Normalization channel algorithm to use (Across, Within).
An OriginsDescriptor for the ConcatLayer.
A PadDescriptor for the PadLayer.
float m_PadValue
Optional value to use for padding, defaults to 0.
PaddingMode m_PaddingMode
Specifies the Padding mode (Constant, Reflect or Symmetric)
std::vector< std::pair< unsigned int, unsigned int > > m_PadList
Specifies the padding for input dimension.
A Pooling2dDescriptor for the Pooling2dLayer.
uint32_t m_PadRight
Padding right value in the width dimension.
PoolingAlgorithm m_PoolType
The pooling algorithm to use (Max. Average, L2).
uint32_t m_PoolHeight
Pooling height value.
uint32_t m_PadTop
Padding top value in the height dimension.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
uint32_t m_PoolWidth
Pooling width value.
PaddingMethod m_PaddingMethod
The padding method to be used. (Exclude, IgnoreValue).
uint32_t m_PadBottom
Padding bottom value in the height dimension.
uint32_t m_PadLeft
Padding left value in the width dimension.
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
OutputShapeRounding m_OutputShapeRounding
The rounding method for the output shape. (Floor, Ceiling).
A ReduceDescriptor for the REDUCE operators.
bool m_KeepDims
if true then output shape has no change.
std::vector< uint32_t > m_vAxis
The indices of the dimensions to reduce.
ReduceOperation m_ReduceOperation
Specifies the reduction operation to execute.
A ReshapeDescriptor for the ReshapeLayer.
TensorShape m_TargetShape
Target shape value.
A ResizeDescriptor for the ResizeLayer.
bool m_HalfPixelCenters
Half Pixel Centers.
uint32_t m_TargetHeight
Target height value.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
ResizeMethod m_Method
The Interpolation method to use (Bilinear, NearestNeighbor).
uint32_t m_TargetWidth
Target width value.
bool m_AlignCorners
Aligned corners.
A ScatterNdDescriptor for the ScatterNdLayer.
A SliceDescriptor for the SliceLayer.
A SoftmaxDescriptor for the SoftmaxLayer.
float m_Beta
Exponentiation value.
A SpaceToBatchNdDescriptor for the SpaceToBatchNdLayer.
std::vector< unsigned int > m_BlockShape
Block shape value.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
std::vector< std::pair< unsigned int, unsigned int > > m_PadList
Specifies the padding values for the input dimension: heightPad{top, bottom} widthPad{left,...
A SpaceToDepthDescriptor for the SpaceToDepthLayer.
unsigned int m_BlockSize
Scalar specifying the input block size. It must be >= 1.
A StackDescriptor for the StackLayer.
TensorShape m_InputShape
Required shape of all input tensors.
uint32_t m_Axis
0-based axis along which to stack the input tensors.
uint32_t m_NumInputs
Number of input tensors.
A StandInDescriptor for the StandIn layer.
A StridedSliceDescriptor for the StridedSliceLayer.
std::vector< int > m_Stride
Stride values for the input that will be sliced.
std::vector< int > m_Begin
Begin values for the input that will be sliced.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
int32_t m_BeginMask
Begin mask value.
int32_t m_ShrinkAxisMask
Shrink axis mask value. If set, the nth specification shrinks the dimensionality by 1.
int32_t m_NewAxisMask
New axis mask value.
std::vector< int > m_End
End values for the input that will be sliced.
int32_t m_EndMask
End mask value.
int32_t m_EllipsisMask
Ellipsis mask value.
std::vector< uint32_t > m_Multiples
The vector to multiply the input shape by.
A TransposeConvolution2dDescriptor for the TransposeConvolution2dLayer.
uint32_t m_PadRight
Padding right value in the width dimension.
uint32_t m_PadTop
Padding top value in the height dimension.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
std::vector< unsigned int > m_OutputShape
bool m_OutputShapeEnabled
Output shape if it has been specified.
uint32_t m_PadBottom
Padding bottom value in the height dimension.
uint32_t m_PadLeft
Padding left value in the width dimension.
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.
bool m_BiasEnabled
Enable/disable bias.
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
A TransposeDescriptor for the TransposeLayer.
A ViewsDescriptor for the SplitterLayer.