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()); \
58 pTfLiteParserImpl(
new TfLiteParserImpl(options)) {}
60ITfLiteParser::~ITfLiteParser() =
default;
64 return new ITfLiteParser(options);
79 return pTfLiteParserImpl->CreateNetworkFromBinaryFile(graphFile);
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);
101 return pTfLiteParserImpl->GetSubgraphCount();
106 return pTfLiteParserImpl->GetSubgraphInputTensorNames(subgraphId);
111 return pTfLiteParserImpl->GetSubgraphOutputTensorNames(subgraphId);
117const 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())
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;
298std::vector<unsigned int> GetUIntBuffer(armnn::TensorInfo
info,
304 if (!bufferPtr || bufferPtr->data.empty())
306 throw ParseException(
"UInt buffer is null or empty.");
309 const size_t numElements =
info.GetNumElements();
310 std::vector<unsigned int> buffer(
info.GetNumElements());
311 buffer.reserve(numElements);
313 if (
info.GetDataType() == DataType::Signed32)
315 size_t requiredBytes = numElements *
sizeof(int32_t);
316 if (bufferPtr->data.size() < requiredBytes)
318 throw ParseException(
"UInt buffer too small for Signed32 tensor.");
321 ::memcpy(buffer.data(), bufferPtr->data.data(), requiredBytes);
323 else if (
info.GetDataType() == DataType::Signed64)
325 size_t requiredBytes = numElements *
sizeof(int64_t);
326 if (bufferPtr->data.size() < requiredBytes)
328 throw ParseException(
"UInt buffer too small for Signed64 tensor.");
331 std::vector<uint64_t> uint64Buffer(numElements);
332 ::memcpy(uint64Buffer.data(), bufferPtr->data.data(), requiredBytes);
333 buffer.assign(std::begin(uint64Buffer), std::end(uint64Buffer));
338 throw ParseException(
339 fmt::format(
"Unsupported data type for uint buffer {}, only Signed 32 or Signed 64 are supported. {}",
346#define CHECK_BUFFER_SIZE(BUFFER_PTR, TENSOR_INFO, BUFFER_ID) \
347 CheckBufferSize(BUFFER_PTR, TENSOR_INFO, BUFFER_ID, CHECK_LOCATION())
349bool IsActivationSupported(tflite::ActivationFunctionType activationType)
351 switch(activationType)
353 case tflite::ActivationFunctionType_NONE:
354 case tflite::ActivationFunctionType_RELU:
355 case tflite::ActivationFunctionType_RELU6:
356 case tflite::ActivationFunctionType_TANH:
367#define CHECK_SUPPORTED_FUSED_ACTIVATION(OPTION, SUBGRAPH_INDEX, OPERATOR_INDEX) \
369 if (IsActivationSupported(OPTION->fused_activation_function) == false) \
371 throw ParseException( \
372 fmt::format("TfLite parser doesn't support fused activation: " \
373 "{}/{} in {} subgraph:{} operator:{} at {}", \
374 OPTION->fused_activation_function, \
375 tflite::EnumNameActivationFunctionType(\
376 OPTION->fused_activation_function), \
380 CHECK_LOCATION().FileLine())); \
385std::vector<unsigned int> AsUnsignedVector(
const std::vector<int32_t>& in)
387 std::vector<unsigned int> result;
388 result.reserve(in.size());
401bool IsOptionalOperandPresent(
int input)
406void CalcPadding(uint32_t inputSize,
410 uint32_t& paddingFront,
411 uint32_t& paddingBack,
412 tflite::Padding padding)
416 if (padding == tflite::Padding_SAME)
418 uint32_t outputSize = (inputSize + stride - 1) / stride;
419 uint32_t dilatedSize = filterSize + (dilation - 1) * (filterSize - 1);
420 uint32_t temp = (outputSize - 1) * stride + dilatedSize;
421 if (temp > inputSize)
423 paddingFront = (temp - inputSize) / 2;
424 paddingBack = (temp - inputSize) - paddingFront;
432void CalcPadding(uint32_t inputSize,
436 uint32_t& paddingFront,
437 uint32_t& paddingBack,
438 tflite::Padding padding,
444 if (padding == tflite::Padding_SAME)
446 uint32_t totalPadding = (inputSize - 1) * stride + filterSize - outputSize;
447 paddingFront = totalPadding / 2;
448 paddingBack = totalPadding - paddingFront;
453 const std::vector<unsigned int>& shape,
454 const bool outputTensor =
false)
459 switch (tensorPtr->type)
461 case tflite::TensorType_UINT8:
464 case tflite::TensorType_FLOAT32:
467 case tflite::TensorType_FLOAT16:
470 case tflite::TensorType_INT8:
471 if (tensorPtr->quantization->zero_point.size() == 1)
482 case tflite::TensorType_INT16:
485 case tflite::TensorType_INT32:
488 case tflite::TensorType_INT64:
491 case tflite::TensorType_BOOL:
497 throw ParseException(
498 fmt::format(
"Unsupported data type {} = {} for tensor: {}. {}",
500 tflite::EnumNameTensorType(tensorPtr->type),
505 TensorShape tensorShape;
507 std::vector<unsigned int> safeShape = shape;
508 if (shape.size() == 0)
510 safeShape.push_back(1);
519 size_t shapeSignatureSize = tensorPtr->shape_signature.size();
522 if (shapeSignatureSize != 0)
525 if (shapeSignatureSize != shape.size())
529 for (
unsigned int i = 0; i < shapeSignatureSize; ++i)
531 unsigned int dim = tensorPtr->shape_signature[i] > -1 ?
532 static_cast<unsigned int>(tensorPtr->shape_signature[i]) : 0;
533 safeShape.push_back(dim);
537 std::unique_ptr<bool[]> dimMask = std::make_unique<bool[]>(tensorPtr->shape_signature.size());
538 bool batchOnly =
true;
539 for (
unsigned int i = 0; i < tensorPtr->shape_signature.size(); ++i)
541 dimMask[i] = tensorPtr->shape_signature[i] != -1;
543 if (i > 0 && !dimMask[i])
552 tensorShape = TensorShape(
static_cast<unsigned int>(safeShape.size()), safeShape.data(), dimMask.get());
555 else if (shape.size() == 0)
557 tensorShape = TensorShape(1,
false);
565 float quantizationScale = 1.0f;
566 int32_t quantizationOffset = 0;
568 if (tensorPtr->quantization.get())
570 if (tensorPtr->quantization->scale.size() <= 1)
575 if (tensorPtr->quantization->scale.size() == 1)
577 quantizationScale = tensorPtr->quantization->scale[0];
579 if (tensorPtr->quantization->zero_point.size() == 1)
586 armnn::TensorInfo result(tensorShape,
594 std::vector<float> quantizationScales;
595 std::vector<int32_t> quantizationOffsets;
598 std::copy(tensorPtr->quantization->scale.begin(),
599 tensorPtr->quantization->scale.end(),
600 std::back_inserter(quantizationScales));
603 armnn::TensorInfo result(tensorShape,
612 armnn::TensorInfo result(tensorShape,
621 const bool outputTensor =
false)
623 auto const& dimensions = AsUnsignedVector(tensorPtr->shape);
624 return ToTensorInfo(tensorPtr, dimensions, outputTensor);
628std::pair<armnn::ConstTensor, std::unique_ptr<T[]>>
631 armnn::TensorInfo& tensorInfo,
632 armnn::Optional<armnn::PermutationVector&> permutationVector)
638 throw armnn::ParseException(fmt::format(
"Tensor pointer is null {}",
CHECK_LOCATION().AsString()));
643 throw armnn::ParseException(fmt::format(
"Buffer for buffer:{} is null", tensorPtr->buffer).c_str());
647 if (bufferPtr->data.size() < requiredBytes)
649 throw ParseException(fmt::format(
"Buffer for buffer:{} too small. Expected at least {} bytes, got {}.",
650 tensorPtr->buffer, requiredBytes, bufferPtr->data.size()));
655 if (permutationVector.
has_value() && permutationVector.
value().GetSize() > 0)
659 reinterpret_cast<const T*
>(bufferPtr->data.data()), data.get(),
sizeof(T));
663 ::memcpy(data.get(), bufferPtr->data.data(), tensorInfo.
GetNumBytes());
669 return std::make_pair(ConstTensor(tensorInfo, data.get()), std::move(data));
679bool CheckShape(
const armnn::TensorShape& actual,
const std::vector<int32_t>& expected)
682 if (actualSize != expected.size())
687 for (
unsigned int i = 0u; i < actualSize; i++)
689 if (expected[i] < 0 ||
690 actual[i] !=
static_cast<unsigned int>(expected[i]))
699bool CheckShape(
const armnn::TensorShape& actual,
const armnn::TensorShape& expected)
701 std::vector<int32_t> expectedVec;
704 expectedVec.push_back(expected[i]);
709void CheckMatchingQuantization(
const TensorInfo& first,
710 const TensorInfo& second,
711 const std::string& descName,
712 std::string
const& firstName,
713 std::string
const& secondName)
725 if (firstDataType != secondDataType)
727 throw InvalidArgumentException(descName +
": " + firstName +
" and " + secondName +
728 " must be of the same quantized type, " +
735 throw InvalidArgumentException(descName +
": " + firstName +
" and " + secondName +
736 " must have the same quantization space, " +
746 auto shape = tensorPtr->shape;
752 auto shapeSig = tensorPtr->shape_signature;
754 if (shapeSig.empty())
759 for (
unsigned int i = 0; i < shapeSig.size() ; ++i)
761 if (shapeSig[i] == -1)
773, m_Network(nullptr, nullptr)
777 m_ParserFunctions[tflite::BuiltinOperator_ABS] = &TfLiteParserImpl::ParseAbs;
778 m_ParserFunctions[tflite::BuiltinOperator_ADD] = &TfLiteParserImpl::ParseAdd;
779 m_ParserFunctions[tflite::BuiltinOperator_ARG_MIN] = &TfLiteParserImpl::ParseArgMin;
780 m_ParserFunctions[tflite::BuiltinOperator_ARG_MAX] = &TfLiteParserImpl::ParseArgMax;
781 m_ParserFunctions[tflite::BuiltinOperator_AVERAGE_POOL_2D] = &TfLiteParserImpl::ParseAveragePool2D;
782 m_ParserFunctions[tflite::BuiltinOperator_BATCH_TO_SPACE_ND] = &TfLiteParserImpl::ParseBatchToSpaceND;
783 m_ParserFunctions[tflite::BuiltinOperator_BATCH_MATMUL] = &TfLiteParserImpl::ParseBatchMatMul;
784 m_ParserFunctions[tflite::BuiltinOperator_BROADCAST_TO] = &TfLiteParserImpl::ParseBroadcastTo;
785 m_ParserFunctions[tflite::BuiltinOperator_CEIL] = &TfLiteParserImpl::ParseCeil;
786 m_ParserFunctions[tflite::BuiltinOperator_CAST] = &TfLiteParserImpl::ParseCast;
787 m_ParserFunctions[tflite::BuiltinOperator_CONCATENATION] = &TfLiteParserImpl::ParseConcatenation;
788 m_ParserFunctions[tflite::BuiltinOperator_CONV_2D] = &TfLiteParserImpl::ParseConv2D;
790 #if defined(ARMNN_POST_TFLITE_2_4)
791 m_ParserFunctions[tflite::BuiltinOperator_CONV_3D] = &TfLiteParserImpl::ParseConv3D;
793 m_ParserFunctions[tflite::BuiltinOperator_CUSTOM] = &TfLiteParserImpl::ParseCustomOperator;
794 m_ParserFunctions[tflite::BuiltinOperator_DEPTH_TO_SPACE] = &TfLiteParserImpl::ParseDepthToSpace;
795 m_ParserFunctions[tflite::BuiltinOperator_DEPTHWISE_CONV_2D] = &TfLiteParserImpl::ParseDepthwiseConv2D;
796 m_ParserFunctions[tflite::BuiltinOperator_DEQUANTIZE] = &TfLiteParserImpl::ParseDequantize;
797 m_ParserFunctions[tflite::BuiltinOperator_DIV] = &TfLiteParserImpl::ParseDiv;
798 m_ParserFunctions[tflite::BuiltinOperator_ELU] = &TfLiteParserImpl::ParseElu;
799 m_ParserFunctions[tflite::BuiltinOperator_EQUAL] = &TfLiteParserImpl::ParseEqual;
800 m_ParserFunctions[tflite::BuiltinOperator_EXP] = &TfLiteParserImpl::ParseExp;
801 m_ParserFunctions[tflite::BuiltinOperator_EXPAND_DIMS] = &TfLiteParserImpl::ParseExpandDims;
802 m_ParserFunctions[tflite::BuiltinOperator_FLOOR_DIV] = &TfLiteParserImpl::ParseFloorDiv;
803 m_ParserFunctions[tflite::BuiltinOperator_FULLY_CONNECTED] = &TfLiteParserImpl::ParseFullyConnected;
804 m_ParserFunctions[tflite::BuiltinOperator_GATHER] = &TfLiteParserImpl::ParseGather;
805 m_ParserFunctions[tflite::BuiltinOperator_GELU] = &TfLiteParserImpl::ParseGelu;
806 m_ParserFunctions[tflite::BuiltinOperator_GATHER_ND] = &TfLiteParserImpl::ParseGatherNd;
807 m_ParserFunctions[tflite::BuiltinOperator_GREATER] = &TfLiteParserImpl::ParseGreater;
808 m_ParserFunctions[tflite::BuiltinOperator_GREATER_EQUAL] = &TfLiteParserImpl::ParseGreaterOrEqual;
809 m_ParserFunctions[tflite::BuiltinOperator_HARD_SWISH] = &TfLiteParserImpl::ParseHardSwish;
810 m_ParserFunctions[tflite::BuiltinOperator_LEAKY_RELU] = &TfLiteParserImpl::ParseLeakyRelu;
811 m_ParserFunctions[tflite::BuiltinOperator_LESS] = &TfLiteParserImpl::ParseLess;
812 m_ParserFunctions[tflite::BuiltinOperator_LESS_EQUAL] = &TfLiteParserImpl::ParseLessOrEqual;
813 m_ParserFunctions[tflite::BuiltinOperator_LOCAL_RESPONSE_NORMALIZATION]
814 = &TfLiteParserImpl::ParseLocalResponseNormalization;
815 m_ParserFunctions[tflite::BuiltinOperator_LOG] = &TfLiteParserImpl::ParseLog;
816 m_ParserFunctions[tflite::BuiltinOperator_LOGICAL_NOT] = &TfLiteParserImpl::ParseLogicalNot;
817 m_ParserFunctions[tflite::BuiltinOperator_LOGISTIC] = &TfLiteParserImpl::ParseLogistic;
818 m_ParserFunctions[tflite::BuiltinOperator_LOG_SOFTMAX] = &TfLiteParserImpl::ParseLogSoftmax;
819 m_ParserFunctions[tflite::BuiltinOperator_L2_NORMALIZATION] = &TfLiteParserImpl::ParseL2Normalization;
820 m_ParserFunctions[tflite::BuiltinOperator_MAX_POOL_2D] = &TfLiteParserImpl::ParseMaxPool2D;
821 m_ParserFunctions[tflite::BuiltinOperator_MAXIMUM] = &TfLiteParserImpl::ParseMaximum;
822 m_ParserFunctions[tflite::BuiltinOperator_MEAN] = &TfLiteParserImpl::ParseMean;
823 m_ParserFunctions[tflite::BuiltinOperator_MINIMUM] = &TfLiteParserImpl::ParseMinimum;
824 m_ParserFunctions[tflite::BuiltinOperator_MIRROR_PAD] = &TfLiteParserImpl::ParseMirrorPad;
825 m_ParserFunctions[tflite::BuiltinOperator_MUL] = &TfLiteParserImpl::ParseMul;
826 m_ParserFunctions[tflite::BuiltinOperator_NEG] = &TfLiteParserImpl::ParseNeg;
827 m_ParserFunctions[tflite::BuiltinOperator_NOT_EQUAL] = &TfLiteParserImpl::ParseNotEqual;
828 m_ParserFunctions[tflite::BuiltinOperator_PACK] = &TfLiteParserImpl::ParsePack;
829 m_ParserFunctions[tflite::BuiltinOperator_PAD] = &TfLiteParserImpl::ParsePad;
830 m_ParserFunctions[tflite::BuiltinOperator_PADV2] = &TfLiteParserImpl::ParsePad;
831 m_ParserFunctions[tflite::BuiltinOperator_POW] = &TfLiteParserImpl::ParsePower;
832 m_ParserFunctions[tflite::BuiltinOperator_PRELU] = &TfLiteParserImpl::ParsePrelu;
833 m_ParserFunctions[tflite::BuiltinOperator_QUANTIZE] = &TfLiteParserImpl::ParseQuantize;
834 m_ParserFunctions[tflite::BuiltinOperator_RELU] = &TfLiteParserImpl::ParseRelu;
835 m_ParserFunctions[tflite::BuiltinOperator_RELU6] = &TfLiteParserImpl::ParseRelu6;
836 m_ParserFunctions[tflite::BuiltinOperator_REDUCE_MAX] = &TfLiteParserImpl::ParseReduceMax;
837 m_ParserFunctions[tflite::BuiltinOperator_REDUCE_MIN] = &TfLiteParserImpl::ParseReduceMin;
838 m_ParserFunctions[tflite::BuiltinOperator_REDUCE_PROD] = &TfLiteParserImpl::ParseReduceProd;
839 m_ParserFunctions[tflite::BuiltinOperator_RESHAPE] = &TfLiteParserImpl::ParseReshape;
840 m_ParserFunctions[tflite::BuiltinOperator_RESIZE_BILINEAR] = &TfLiteParserImpl::ParseResizeBilinear;
841 m_ParserFunctions[tflite::BuiltinOperator_RESIZE_NEAREST_NEIGHBOR] = &TfLiteParserImpl::ParseResizeNearestNeighbor;
842 m_ParserFunctions[tflite::BuiltinOperator_REVERSE_V2] = &TfLiteParserImpl::ParseReverseV2;
843 m_ParserFunctions[tflite::BuiltinOperator_RSQRT] = &TfLiteParserImpl::ParseRsqrt;
844 m_ParserFunctions[tflite::BuiltinOperator_SCATTER_ND] = &TfLiteParserImpl::ParseScatterNd;
845 m_ParserFunctions[tflite::BuiltinOperator_SQRT] = &TfLiteParserImpl::ParseSqrt;
846 m_ParserFunctions[tflite::BuiltinOperator_SHAPE] = &TfLiteParserImpl::ParseShape;
847 m_ParserFunctions[tflite::BuiltinOperator_SIN] = &TfLiteParserImpl::ParseSin;
848 m_ParserFunctions[tflite::BuiltinOperator_SLICE] = &TfLiteParserImpl::ParseSlice;
849 m_ParserFunctions[tflite::BuiltinOperator_SOFTMAX] = &TfLiteParserImpl::ParseSoftmax;
850 m_ParserFunctions[tflite::BuiltinOperator_SPACE_TO_BATCH_ND] = &TfLiteParserImpl::ParseSpaceToBatchND;
851 m_ParserFunctions[tflite::BuiltinOperator_SPACE_TO_DEPTH] = &TfLiteParserImpl::ParseSpaceToDepth;
852 m_ParserFunctions[tflite::BuiltinOperator_SPLIT] = &TfLiteParserImpl::ParseSplit;
853 m_ParserFunctions[tflite::BuiltinOperator_SPLIT_V] = &TfLiteParserImpl::ParseSplitV;
854 m_ParserFunctions[tflite::BuiltinOperator_SQUEEZE] = &TfLiteParserImpl::ParseSqueeze;
855 m_ParserFunctions[tflite::BuiltinOperator_SQUARE] = &TfLiteParserImpl::ParseSquare;
856 m_ParserFunctions[tflite::BuiltinOperator_SQUARED_DIFFERENCE] = &TfLiteParserImpl::ParseSquaredDifference;
857 m_ParserFunctions[tflite::BuiltinOperator_STRIDED_SLICE] = &TfLiteParserImpl::ParseStridedSlice;
858 m_ParserFunctions[tflite::BuiltinOperator_SUB] = &TfLiteParserImpl::ParseSub;
859 m_ParserFunctions[tflite::BuiltinOperator_SUM] = &TfLiteParserImpl::ParseSum;
860 m_ParserFunctions[tflite::BuiltinOperator_TANH] = &TfLiteParserImpl::ParseTanH;
861 m_ParserFunctions[tflite::BuiltinOperator_TILE] = &TfLiteParserImpl::ParseTile;
862 m_ParserFunctions[tflite::BuiltinOperator_TRANSPOSE] = &TfLiteParserImpl::ParseTranspose;
863 m_ParserFunctions[tflite::BuiltinOperator_TRANSPOSE_CONV] = &TfLiteParserImpl::ParseTransposeConv;
864 m_ParserFunctions[tflite::BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM]
865 = &TfLiteParserImpl::ParseUnidirectionalSequenceLSTM;
866 m_ParserFunctions[tflite::BuiltinOperator_UNPACK] = &TfLiteParserImpl::ParseUnpack;
869 m_CustomParserFunctions[
"TFLite_Detection_PostProcess"] = &TfLiteParserImpl::ParseDetectionPostProcess;
873 size_t operatorIndex,
876 const auto& subgraphPtr = m_Model->subgraphs[subgraphIndex];
877 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
880 auto search = armnnTfLiteParser::TfLiteParserImpl::m_TensorInfos.find(inputId);
882 if (search != m_TensorInfos.end())
884 return m_TensorInfos[inputId];
888 auto tensorInfo = ::armnnTfLiteParser::ToTensorInfo(subgraphPtr->tensors[inputId].get());
889 m_TensorInfos.insert({ inputId, tensorInfo });
894armnn::TensorInfo TfLiteParserImpl::OutputTensorInfoFromInputs(
size_t subgraphIndex,
895 size_t operatorIndex,
896 armnn::IConnectableLayer* layer,
898 std::vector<int> inputs)
900 const auto& subgraphPtr = m_Model->subgraphs[subgraphIndex];
901 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
905 auto outputSearch = armnnTfLiteParser::TfLiteParserImpl::m_TensorInfos.find(outputId);
907 if (outputSearch != m_TensorInfos.end())
909 return m_TensorInfos[outputId];
912 const auto& outputTensorPtr = subgraphPtr->tensors[outputId].get();
913 TensorInfo tensor = ::armnnTfLiteParser::ToTensorInfo(outputTensorPtr,
true);
915 if (IsDynamic(outputTensorPtr))
921 inputs.emplace_back(i);
925 std::vector<armnn::TensorShape> inputShapes;
927 for (
unsigned int i = 0; i < inputs.size(); ++i)
930 auto search = armnnTfLiteParser::TfLiteParserImpl::m_TensorInfos.find(inputId);
932 if (search != m_TensorInfos.end())
934 auto &inputTensorInfo = m_TensorInfos[inputId];
935 inputShapes.push_back(inputTensorInfo.GetShape());
939 auto inputTensorInfo = ::armnnTfLiteParser::ToTensorInfo(subgraphPtr->tensors[inputId].get());
940 m_TensorInfos.insert({ inputId, inputTensorInfo});
941 inputShapes.push_back(inputTensorInfo.GetShape());
947 m_TensorInfos.insert({ outputId, tensor});
951armnn::TensorInfo TfLiteParserImpl::OutputTensorInfoFromShapes(
size_t subgraphIndex,
952 size_t operatorIndex,
953 armnn::IConnectableLayer* layer,
955 std::vector<armnn::TensorShape> inputShapes)
957 const auto& subgraphPtr = m_Model->subgraphs[subgraphIndex];
958 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
961 const auto& outputTensorPtr = subgraphPtr->tensors[outputId].get();
962 TensorInfo tensor = ::armnnTfLiteParser::ToTensorInfo(outputTensorPtr,
true);
964 if (IsDynamic(outputTensorPtr))
969 m_TensorInfos.insert({ outputId, tensor});
973void TfLiteParserImpl::ResetParser()
977 m_SubgraphConnections.clear();
978 m_OverriddenOutputShapes.clear();
979 m_ConstantsToDequantize.clear();
980 m_ConstantsToBeCreated.clear();
981 m_TensorInfos.clear();
988 return CreateNetworkFromModel();
995 return CreateNetworkFromModel();
1002 m_Model = std::move(model);
1004 return CreateNetworkFromModel();
1007INetworkPtr TfLiteParserImpl::CreateNetworkFromModel()
1014 if (m_Options.value().m_InferAndValidate)
1016 BackendOptions shapeInferenceMethodOption(
"ShapeInferenceMethod",
1018 {
"InferAndValidate",
true }
1021 networkOptions.push_back(shapeInferenceMethodOption);
1023 if (m_Options.value().m_AllowExpandedDims)
1025 BackendOptions shapeInferenceMethodOption(
"AllowExpandedDims",
1027 {
"AllowExpandedDims",
true }
1030 networkOptions.push_back(shapeInferenceMethodOption);
1035 if (m_Model.get() ==
nullptr)
1037 throw ParseException(fmt::format(
"Tflite Model pointer is null {}",
CHECK_LOCATION().AsString()));
1043 size_t subgraphIndex = 0;
1044 uint8_t usableSubgraphs = 0;
1045 for (
size_t i = 0; i < m_Model->subgraphs.size(); i++)
1047 if (m_Model->subgraphs[i]->name.rfind(
"VALIDATION:", 0) != 0)
1054 if (usableSubgraphs > 1)
1056 throw ParseException(
1057 fmt::format(
"Current TfLite parser only supports 1 non validation subgraph. This model has: {} {}",
1061 size_t operatorIndex = 0;
1064 const SubgraphPtr& subgraph = m_Model->subgraphs[subgraphIndex];
1065 SetupInputLayerTensorInfos(subgraphIndex);
1066 SetupConstantLayerTensorInfos(subgraphIndex);
1068 m_SubgraphConnections.emplace_back(subgraph->tensors.size());
1071 const auto& opCodePtr = m_Model->operator_codes[op->opcode_index];
1074#if defined(ARMNN_POST_TFLITE_2_3)
1075 auto builtinCode = std::max(opCodePtr->builtin_code,
1076 static_cast<tflite::BuiltinOperator
>(opCodePtr->deprecated_builtin_code));
1078 auto builtinCode = opCodePtr->builtin_code;
1081 if (builtinCode > tflite::BuiltinOperator_MAX)
1083 throw ParseException(fmt::format(
"Operator code {} is out of range 0-{}. "
1084 "subgraph:{} operator idx:{}. {}",
1085 builtinCode, tflite::BuiltinOperator_MAX, subgraphIndex,
1090 auto& parserFunction = m_ParserFunctions[builtinCode];
1091 (this->*parserFunction)(subgraphIndex, operatorIndex);
1095 SetupInputLayers(subgraphIndex);
1096 SetupOutputLayers(subgraphIndex);
1097 SetupConstantLayers(subgraphIndex);
1099 catch (
const ParseException& e)
1101 std::stringstream errorString;
1102 errorString <<
"Failed to parse operator #" << operatorIndex <<
" within subgraph #"
1103 << subgraphIndex <<
" error: " << e.
what();
1105 std::stringstream errors;
1106 errors << errorString.str() <<
"\n";
1107 throw ParseException(errors.str());
1111 for (subgraphIndex = 0; subgraphIndex < m_SubgraphConnections.size(); ++subgraphIndex)
1113 for (
size_t tensorIndex = 0; tensorIndex < m_SubgraphConnections[subgraphIndex].size(); ++tensorIndex)
1115 if (m_SubgraphConnections[subgraphIndex][tensorIndex].outputSlot !=
nullptr)
1117 for (
size_t inputSlotIdx = 0;
1118 inputSlotIdx < m_SubgraphConnections[subgraphIndex][tensorIndex].inputSlots.size();
1121 m_SubgraphConnections[subgraphIndex][tensorIndex].outputSlot->Connect(
1122 *(m_SubgraphConnections[subgraphIndex][tensorIndex].inputSlots[inputSlotIdx]));
1127 return std::move(m_Network);
1134 return (TfLiteParserImpl::IsConstTensor(tensorPtr) && inputDataType == DataType::Float32 &&
1135 (tensorDataType == DataType::QAsymmU8 ||
1136 tensorDataType == DataType::QAsymmS8 ||
1137 tensorDataType == DataType::QSymmS8 ||
1138 tensorDataType == DataType::Signed32 ||
1139 tensorDataType == DataType::Signed64));
1142void TfLiteParserImpl::RegisterProducerOfTensor(
size_t subgraphIndex,
1144 armnn::IOutputSlot* slot)
1148 TensorSlots & tensorSlots = m_SubgraphConnections[subgraphIndex][tensorIndex];
1154 if (tensorSlots.outputSlot !=
nullptr)
1156 throw ParseException(fmt::format(
"Another layer has already registered itself as the producer of "
1157 "subgraph:{} tensor:{} {}",
1163 tensorSlots.outputSlot = slot;
1166void TfLiteParserImpl::RegisterConsumerOfTensor(
size_t subgraphIndex,
1168 armnn::IInputSlot* slot)
1172 TensorSlots& tensorSlots = m_SubgraphConnections[subgraphIndex][tensorIndex];
1173 tensorSlots.inputSlots.push_back(slot);
1176void TfLiteParserImpl::ParseCustomOperator(
size_t subgraphIndex,
size_t operatorIndex)
1178 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1181 auto customParserFunction = &TfLiteParserImpl::ParseUnsupportedOperator;
1184 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1185 const auto& customCode = m_Model->operator_codes[operatorPtr->opcode_index]->custom_code;
1188 auto iterator = m_CustomParserFunctions.find(customCode);
1189 if (iterator != m_CustomParserFunctions.end())
1191 customParserFunction = iterator->second;
1195 (this->*customParserFunction)(subgraphIndex, operatorIndex);
1198void TfLiteParserImpl::ParseUnsupportedOperator(
size_t subgraphIndex,
size_t operatorIndex)
1200 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1202 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1204 auto opcodeIndex = operatorPtr->opcode_index;
1207#if defined(ARMNN_POST_TFLITE_2_3)
1208 auto opcode = std::max(m_Model->operator_codes[opcodeIndex]->builtin_code,
1209 static_cast<tflite::BuiltinOperator
>(m_Model->operator_codes[opcodeIndex]->deprecated_builtin_code));
1211 auto opcode = m_Model->operator_codes[opcodeIndex]->builtin_code;
1214 if (!m_Options || !m_Options.value().m_StandInLayerForUnsupported)
1217 throw ParseException(
1218 fmt::format(
"Operator not supported. "
1219 "subgraph:{} operator:{} "
1220 "opcode_index:{} opcode:{} / {} {}",
1225 tflite::EnumNameBuiltinOperator(opcode),
1229 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1230 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1235 StandInDescriptor descriptor(numInputs, numOutputs);
1236 auto layerName = fmt::format(
"StandIn:{}:{}:{}", subgraphIndex, operatorIndex, opcode);
1239 IConnectableLayer* layer = m_Network->AddStandInLayer(descriptor, layerName.c_str());
1243 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
1247 for (
unsigned int i = 0u; i < numOutputs; ++i)
1252 auto inputTensorIds = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1253 auto outputTensorIds = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1255 RegisterInputSlots(subgraphIndex, operatorIndex, layer, inputTensorIds);
1256 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIds);
1259void TfLiteParserImpl::ParseCast(
size_t subgraphIndex,
size_t operatorIndex)
1261 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1263 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1265 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1268 auto layerName = fmt::format(
"Cast:{}:{}", subgraphIndex, operatorIndex);
1270 IConnectableLayer* layer = m_Network->AddCastLayer(layerName.c_str());
1274 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
1278 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
1281 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1282 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1284 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1285 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
1288void TfLiteParserImpl::ParseConv2D(
size_t subgraphIndex,
size_t operatorIndex)
1290 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1292 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1293 const auto* options = operatorPtr->builtin_options.AsConv2DOptions();
1297 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1298 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1301 Convolution2dDescriptor desc;
1302 inputs.size() == 3 ?
1310 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
1311 armnn::TensorInfo filterTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
1314 unsigned int inputHeight = inputTensorInfo.
GetShape()[1];
1315 unsigned int inputWidth = inputTensorInfo.
GetShape()[2];
1319 unsigned int filterHeight = filterTensorInfo.
GetShape()[1];
1320 unsigned int filterWidth = filterTensorInfo.
GetShape()[2];
1322 CalcPadding(inputHeight, filterHeight, desc.
m_StrideY,
1324 CalcPadding(inputWidth, filterWidth, desc.
m_StrideX,
1329 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1330 std::vector<unsigned int> tensorIndexesToRegister = { inputTensorIndexes[0], inputTensorIndexes[1] };
1332 auto layerName = fmt::format(
"Conv2D:{}:{}", subgraphIndex, operatorIndex);
1333 armnn::IConnectableLayer* layer = m_Network->AddConvolution2dLayer(desc, layerName.c_str());
1335 if (ShouldConstantTensorBeConverted(inputs[1], inputTensorInfo.
GetDataType(), filterTensorInfo.
GetDataType()))
1337 m_ConstantsToDequantize.emplace_back(inputs[1]->buffer);
1342 armnn::TensorInfo biasTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
1345 tensorIndexesToRegister.emplace_back(inputTensorIndexes[2]);
1347 if (ShouldConstantTensorBeConverted(inputs[2], inputTensorInfo.
GetDataType(), biasTensorInfo.
GetDataType()))
1349 m_ConstantsToDequantize.emplace_back(inputs[2]->buffer);
1355 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
1359 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
1364 RegisterInputSlots(subgraphIndex, operatorIndex, layer, tensorIndexesToRegister);
1366 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
1368 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1369 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, { outputTensorIndexes[0] });
1373#if defined(ARMNN_POST_TFLITE_2_4)
1374void TfLiteParserImpl::ParseConv3D(
size_t subgraphIndex,
size_t operatorIndex)
1376 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1378 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1379 const auto* options = operatorPtr->builtin_options.AsConv3DOptions();
1383 Convolution3dDescriptor desc;
1393 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1396 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1399 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
1400 armnn::TensorInfo filterTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
1403 unsigned int inputDepth = inputTensorInfo.
GetShape()[1];
1404 unsigned int inputHeight = inputTensorInfo.
GetShape()[2];
1405 unsigned int inputWidth = inputTensorInfo.
GetShape()[3];
1408 unsigned int filterDepth = filterTensorInfo.
GetShape()[0];
1409 unsigned int filterHeight = filterTensorInfo.
GetShape()[1];
1410 unsigned int filterWidth = filterTensorInfo.
GetShape()[2];
1412 CalcPadding(inputDepth, filterDepth, desc.
m_StrideZ,
1414 CalcPadding(inputHeight, filterHeight, desc.
m_StrideY,
1416 CalcPadding(inputWidth, filterWidth, desc.
m_StrideX,
1419 auto filterTensorAndData = CreateConstTensorNonPermuted(inputs[1], filterTensorInfo, inputTensorInfo.
GetDataType());
1421 auto layerName = fmt::format(
"Conv3D:{}:{}", subgraphIndex, operatorIndex);
1423 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1426 std::vector<unsigned int> tensorIndexesToRegister = {inputTensorIndexes[0], inputTensorIndexes[1]};
1428 if (inputs.size() == 3)
1433 tensorIndexesToRegister.emplace_back(inputTensorIndexes[2]);
1436 armnn::IConnectableLayer* layer = m_Network->AddConvolution3dLayer(desc, layerName.c_str());
1440 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
1444 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
1448 RegisterInputSlots(subgraphIndex, operatorIndex, layer, tensorIndexesToRegister);
1450 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
1452 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1453 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1457void TfLiteParserImpl::ParseDepthwiseConv2D(
size_t subgraphIndex,
size_t operatorIndex)
1459 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1461 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1462 const auto* options = operatorPtr->builtin_options.AsDepthwiseConv2DOptions();
1466 DepthwiseConvolution2dDescriptor desc;
1472 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1474 if (inputs.size() == 3)
1479 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1484 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
1485 armnn::TensorInfo filterTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
1488 unsigned int inputHeight = inputTensorInfo.
GetShape()[1];
1489 unsigned int inputWidth = inputTensorInfo.
GetShape()[2];
1492 unsigned int filterHeight = filterTensorInfo.
GetShape()[1];
1493 unsigned int filterWidth = filterTensorInfo.
GetShape()[2];
1495 CalcPadding(inputHeight, filterHeight, desc.
m_StrideY,
1497 CalcPadding(inputWidth, filterWidth, desc.
m_StrideX,
1501 auto layerName = fmt::format(
"DepthwiseConv2D:{}:{}", subgraphIndex, operatorIndex);
1503 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1506 std::vector<unsigned int> tensorIndexesToRegister = {inputTensorIndexes[0], inputTensorIndexes[1]};
1508 armnn::IConnectableLayer* layer = m_Network->AddDepthwiseConvolution2dLayer(desc, layerName.c_str());
1513 TensorInfo biasTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
1516 tensorIndexesToRegister.emplace_back(inputTensorIndexes[2]);
1521 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
1525 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
1530 RegisterInputSlots(subgraphIndex, operatorIndex, layer, tensorIndexesToRegister);
1532 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
1534 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1535 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1538void TfLiteParserImpl::ParseDequantize(
size_t subgraphIndex,
size_t operatorIndex)
1540 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1542 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1545 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1548 auto layerName = fmt::format(
"Dequantize:{}:{}", subgraphIndex, operatorIndex);
1550 IConnectableLayer* layer = m_Network->AddDequantizeLayer(layerName.c_str());
1554 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
1558 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
1561 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1562 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1564 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1565 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
1568void TfLiteParserImpl::ParseExpandDims(
size_t subgraphIndex,
size_t operatorIndex)
1570 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1572 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1575 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1578 auto layerName = fmt::format(
"ExpandDims:{}:{}", subgraphIndex, operatorIndex);
1580 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
1581 armnn::TensorInfo outputTensorInfo =
ToTensorInfo(outputs[0],
true);
1582 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1584 armnn::TensorInfo axisTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
1587 ValidateBuffer(axisBufferPtr, axisTensorInfo,
"axis");
1589 if (axisBufferPtr ==
nullptr)
1591 throw ParseException(fmt::format(
"{}: Operation has invalid inputs. Failed to read axis.",
1596 ::memcpy(axisData.data(), axisBufferPtr->data.data(), axisTensorInfo.
GetNumBytes());
1597 int32_t axis = axisData[0];
1599 auto inputRank =
static_cast<int32_t
>(inputTensorInfo.
GetShape().GetNumDimensions());
1600 auto outputRank = inputRank + 1;
1601 if((axis < -1 * outputRank) || (outputRank <= axis))
1603 throw ParseException(fmt::format(
"{}: Axis {} is not within [-{}, {}) range.",
1607 axis = axis < 0 ? (axis + outputRank) : axis;
1609 std::vector<unsigned int> shape(
static_cast<unsigned int>(outputRank));
1610 unsigned int inputShapeIndex = 0;
1611 for (
unsigned int i = 0; i < static_cast<unsigned int>(outputRank); ++i)
1613 if (i ==
static_cast<unsigned int>(axis))
1619 shape[i] = inputTensorInfo.
GetShape()[inputShapeIndex];
1624 ReshapeDescriptor reshapeDesc;
1625 reshapeDesc.
m_TargetShape = TensorShape(
static_cast<unsigned int>(outputRank), shape.data());
1628 IConnectableLayer* layer = m_Network->AddReshapeLayer(reshapeDesc, layerName.c_str());
1632 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
1637 m_TensorInfos[outputTensorIds[0]] = outputTensorInfo;
1639 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1640 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1642 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1643 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1646void TfLiteParserImpl::ParseTranspose(
size_t subgraphIndex,
size_t operatorIndex)
1648 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1650 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1653 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1656 auto layerName = fmt::format(
"Transpose:{}:{}", subgraphIndex, operatorIndex);
1657 TransposeDescriptor desc;
1659 if (inputs.size() == 2)
1661 armnn::TensorInfo permuteTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
1663 ValidateBuffer(permuteBufferPtr, permuteTensorInfo,
"permute");
1666 std::vector<unsigned int> permuteShape(numPermVecElements);
1667 ::memcpy(permuteShape.data(), permuteBufferPtr->data.data(), permuteTensorInfo.
GetNumBytes());
1668 PermutationVector permutationVector(permuteShape.data(), permuteTensorInfo.
GetNumElements());
1670 desc = TransposeDescriptor(permutationVector);
1672 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
1674 IConnectableLayer* layer = m_Network->AddTransposeLayer(desc, layerName.c_str());
1678 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
1682 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
1683 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1686 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1687 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1689 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1690 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1693void TfLiteParserImpl::ParseTransposeConv(
size_t subgraphIndex,
size_t operatorIndex)
1695 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1697 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1698 const auto* options = operatorPtr->builtin_options.AsTransposeConvOptions();
1700 TransposeConvolution2dDescriptor desc;
1706 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1707 if (inputs.size() == 4)
1716 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1720 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
1721 armnn::TensorInfo filterTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
1724 const unsigned int inputHeight = inputTensorInfo.
GetShape()[1];
1725 const unsigned int inputWidth = inputTensorInfo.
GetShape()[2];
1727 const unsigned int filterHeight = filterTensorInfo.
GetShape()[1];
1728 const unsigned int filterWidth = filterTensorInfo.
GetShape()[2];
1734 if (inputs[0] && IsConstTensor(inputs[0]))
1736 armnn::TensorInfo tensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
1740 ValidateBuffer(outputBufferPtr, tensorInfo,
"output");
1742 if (tensorInfo.
GetDataType() == DataType::Signed32)
1744 ::memcpy(output_shape.data(), outputBufferPtr->data.data(), tensorInfo.
GetNumBytes());
1746 if (tensorInfo.
GetDataType() == DataType::QAsymmU8)
1750 output_shape[i] =
GetBuffer(m_Model, inputs[0]->buffer)->data.data()[i];
1754 for (
int dimension : output_shape)
1756 desc.
m_OutputShape.push_back(
static_cast<unsigned int>(dimension));
1764 CalcPadding(inputHeight,
1773 CalcPadding(inputWidth,
1784 CalcPadding(inputHeight,
1792 CalcPadding(inputWidth,
1801 auto filterTensorAndData = CreateConstTensorNonPermuted(inputs[1], filterTensorInfo, inputTensorInfo.
GetDataType());
1803 armnn::IConnectableLayer* layer =
nullptr;
1804 auto layerName = fmt::format(
"TransposeConv:{}:{}", subgraphIndex, operatorIndex);
1808 auto biasTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 3);
1809 auto biasConstTensor = CreateConstTensorNonPermuted(inputs[3], biasTensorInfo, inputTensorInfo.
GetDataType());
1810 layer = m_Network->AddTransposeConvolution2dLayer(desc,
1811 filterTensorAndData.first,
1812 biasConstTensor.first,
1817 layer = m_Network->AddTransposeConvolution2dLayer(desc,
1818 filterTensorAndData.first,
1825 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
1829 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0 , { 2, 1 });
1833 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1834 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[2]});
1836 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1837 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1840void TfLiteParserImpl::ParseAveragePool2D(
size_t subgraphIndex,
size_t operatorIndex)
1842 ParsePool(subgraphIndex, operatorIndex, PoolingAlgorithm::Average);
1845void TfLiteParserImpl::ParseBatchMatMul(
size_t subgraphIndex,
size_t operatorIndex)
1847 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1849 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1852 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1855 auto layerName = fmt::format(
"BatchMatMul:{}:{}", subgraphIndex, operatorIndex);
1857 TensorInfo inputXTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
1858 TensorInfo inputYTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
1860 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
1861 const auto* options = operatorPtr->builtin_options.AsBatchMatMulOptions();
1864 BatchMatMulDescriptor descriptor(options->adj_x,
1870 IConnectableLayer* layer = m_Network->AddBatchMatMulLayer(descriptor, layerName.c_str());
1874 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
1878 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
1881 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1882 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
1884 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1885 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1888void TfLiteParserImpl::ParseBatchToSpaceND(
size_t subgraphIndex,
size_t operatorIndex)
1890 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1892 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1895 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1898 armnn::TensorInfo blockShapeTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
1900 ValidateBuffer(blockShapeBufferPtr, blockShapeTensorInfo,
"blockShape");
1902 armnn::TensorInfo cropsTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
1904 ValidateBuffer(cropsBufferPtr, cropsTensorInfo,
"crops");
1906 std::vector<unsigned int> blockShape(blockShapeTensorInfo.
GetNumElements());
1907 ::memcpy(blockShape.data(), blockShapeBufferPtr->data.data(), blockShapeTensorInfo.
GetNumBytes());
1909 std::vector<unsigned int> cropsVector(cropsTensorInfo.
GetNumElements());
1910 ::memcpy(cropsVector.data(), cropsBufferPtr->data.data(), cropsTensorInfo.
GetNumBytes());
1913 std::vector<std::pair<unsigned int, unsigned int>> crops;
1914 for (
unsigned int i = 0; i < cropsTensorInfo.
GetNumElements() / step; ++i)
1916 crops.emplace_back(cropsVector[i * step], cropsVector[i * step + 1]);
1919 armnn::BatchToSpaceNdDescriptor desc;
1924 auto layerName = fmt::format(
"BatchToSpaceND:{}:{}", subgraphIndex, operatorIndex);
1926 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
1928 IConnectableLayer* layer = m_Network->AddBatchToSpaceNdLayer(desc, layerName.c_str());
1932 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
1936 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
1937 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
1940 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
1941 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
1943 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
1944 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
1947void TfLiteParserImpl::ParseBroadcastTo(
size_t subgraphIndex,
size_t operatorIndex)
1949 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
1951 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
1954 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
1959 TensorInfo outputTensorInfo =
ToTensorInfo(outputs[0]);
1961 auto layerName = fmt::format(
"Broadcast_to:{}:{}", subgraphIndex, operatorIndex);
1963 BroadcastToDescriptor descriptor;
1965 auto shapeBufferPtr =
GetBuffer(m_Model, inputs[1]->buffer);
1966 if (shapeBufferPtr !=
nullptr)
1968 std::vector<unsigned int> targetShape;
1970 auto shapeData =
reinterpret_cast<const int32_t*
>(shapeBufferPtr->data.data());
1973 for (
unsigned int i = 0; i < numElement; ++i)
1985 "data and output shape are not found in the buffer.");
1995 IConnectableLayer* layer = m_Network->AddBroadcastToLayer(descriptor, layerName.c_str());
2000 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2001 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2003 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2004 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2007void TfLiteParserImpl::ParseL2Normalization(
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 L2NormalizationDescriptor desc;
2019 auto layerName = fmt::format(
"L2Normalization:{}:{}", subgraphIndex, operatorIndex);
2020 IConnectableLayer* layer = m_Network->AddL2NormalizationLayer(desc, layerName.c_str());
2024 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
2028 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
2031 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2032 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2034 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2035 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2038void TfLiteParserImpl::ParseMaxPool2D(
size_t subgraphIndex,
size_t operatorIndex)
2040 ParsePool(subgraphIndex, operatorIndex, PoolingAlgorithm::Max);
2043void TfLiteParserImpl::ParseMaximum(
size_t subgraphIndex,
size_t operatorIndex)
2045 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2047 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2050 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2053 auto layerName = fmt::format(
"Maximum:{}:{}", subgraphIndex, operatorIndex);
2055 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2056 TensorInfo input1TensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2057 CheckMatchingQuantization(inputTensorInfo, input1TensorInfo, layerName,
"Input 0",
"Input 1");
2059 IConnectableLayer* layer = m_Network->AddElementwiseBinaryLayer(BinaryOperation::Maximum, layerName.c_str());
2063 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
2067 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
2068 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
2071 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2072 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
2074 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2075 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2078void TfLiteParserImpl::ParseMinimum(
size_t subgraphIndex,
size_t operatorIndex)
2080 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2082 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2085 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2088 auto layerName = fmt::format(
"Minimum:{}:{}", subgraphIndex, operatorIndex);
2090 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2091 TensorInfo input1TensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2092 CheckMatchingQuantization(inputTensorInfo, input1TensorInfo, layerName,
"Input 0",
"Input 1");
2094 IConnectableLayer* layer = m_Network->AddElementwiseBinaryLayer(BinaryOperation::Minimum, layerName.c_str());
2098 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
2102 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
2103 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
2106 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2107 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
2109 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2110 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2113void TfLiteParserImpl::ParsePool(
size_t subgraphIndex,
2114 size_t operatorIndex,
2117 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2119 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2120 const auto* options = operatorPtr->builtin_options.AsPool2DOptions();
2124 std::string layerName;
2128 case PoolingAlgorithm::Average:
2130 fmt::format(
"AveragePool2D:{}:{}", subgraphIndex, operatorIndex);
2132 case PoolingAlgorithm::Max:
2134 fmt::format(
"MaxPool2D:{}:{}", subgraphIndex, operatorIndex);
2137 throw ParseException(fmt::format(
"Unsupported Pooling Algorithm {}",
CHECK_LOCATION().AsString()));
2151 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2153 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2156 unsigned int inputHeight = inputTensorInfo.
GetShape()[1];
2157 unsigned int inputWidth = inputTensorInfo.
GetShape()[2];
2164 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2167 IConnectableLayer* layer = m_Network->AddPooling2dLayer(desc, layerName.c_str());
2171 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
2175 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
2176 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
2181 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2182 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2184 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
2186 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2187 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2190void TfLiteParserImpl::ParseSlice(
size_t subgraphIndex,
size_t operatorIndex)
2192 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2194 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2196 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2199 SliceDescriptor desc;
2202 armnn::TensorInfo beginTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2204 ValidateBuffer(beginBufferPtr, beginTensorInfo,
"begin");
2206 std::vector<unsigned int> begin(beginTensorInfo.
GetNumElements());
2207 ::memcpy(begin.data(), beginBufferPtr->data.data(), beginTensorInfo.
GetNumBytes());
2210 armnn::TensorInfo sizeTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
2212 ValidateBuffer(sizeBufferPtr, sizeTensorInfo,
"size");
2217 if (sizeBufferPtr->data.data())
2219 ::memcpy(signedSize.data(), sizeBufferPtr->data.data(), sizeTensorInfo.
GetNumBytes());
2223 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2225 for (
unsigned int i = 0; i < signedSize.size(); ++i)
2227 int signedValue = signedSize[i];
2229 if (signedValue < -1 || signedValue >
static_cast<int>(inputTensorInfo.
GetShape()[i] - begin[i]))
2231 throw ParseException(fmt::format(
"Invalid value for size {} size must be in range "
2232 "[-1, inputDimSize - begin] [-1, {}] inclusive {}",
2234 inputTensorInfo.
GetShape()[i] - begin[i],
2238 if (signedValue == -1)
2240 size[i] = inputTensorInfo.
GetShape()[i] - begin[i];
2244 size[i] =
static_cast<unsigned int>(signedValue);
2248 desc = SliceDescriptor(begin, size);
2250 auto layerName = fmt::format(
"Slice:{}:{}", subgraphIndex, operatorIndex);
2252 IConnectableLayer*
const layer = m_Network->AddSliceLayer(desc, layerName.c_str());
2254 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
2255 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
2260 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2261 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2264 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2265 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2268void TfLiteParserImpl::ParseSoftmax(
size_t subgraphIndex,
size_t operatorIndex)
2270 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2271 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2272 const auto* options = operatorPtr->builtin_options.AsSoftmaxOptions();
2274 SoftmaxDescriptor desc;
2275 desc.
m_Beta = options->beta;
2277 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2279 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2282 auto layerName = fmt::format(
"Softmax:{}:{}", subgraphIndex, operatorIndex);
2283 IConnectableLayer*
const layer = m_Network->AddSoftmaxLayer(desc, layerName.c_str());
2285 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
2290 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2291 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2294 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2295 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2298void TfLiteParserImpl::ParseLogSoftmax(
size_t subgraphIndex,
size_t operatorIndex)
2300 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2304 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2306 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2309 auto layerName = fmt::format(
"LogSoftmax:{}:{}", subgraphIndex, operatorIndex);
2310 IConnectableLayer*
const layer = m_Network->AddLogSoftmaxLayer(desc, layerName.c_str());
2312 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
2317 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2318 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2321 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2322 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2325void TfLiteParserImpl::ParseScatterNd(
size_t subgraphIndex,
size_t operatorIndex)
2327 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2334 armnn::TensorInfo indicesTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2335 armnn::TensorInfo updatesTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2336 armnn::TensorInfo shapeTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
2337 armnn::TensorInfo outputTensorInfo =
ToTensorInfo(outputs[0]);
2342 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2343 const auto* options = operatorPtr->builtin_options.AsScatterNdOptions();
2346 auto layerName = fmt::format(
"ScatterND:{}:{}", subgraphIndex, operatorIndex);
2348 IConnectableLayer* layer = m_Network->AddScatterNdLayer(descriptor, layerName.c_str());
2352 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
2356 outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1, 2});
2359 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2360 RegisterInputSlots(subgraphIndex,
2363 {inputTensorIndexes[2], inputTensorIndexes[0], inputTensorIndexes[1]});
2365 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2366 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2369void TfLiteParserImpl::ParseSpaceToBatchND(
size_t subgraphIndex,
size_t operatorIndex)
2371 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2373 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2376 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2379 armnn::TensorInfo blockShapeTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2381 ValidateBuffer(blockShapeBufferPtr, blockShapeTensorInfo,
"block");
2383 armnn::TensorInfo padListTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
2385 ValidateBuffer(padListBufferPtr, padListTensorInfo,
"padList");
2391 throw ParseException(
2392 fmt::format(
"In SpaceToBatchND block_shape and paddings can only be of type INT32. {}",
2396 std::vector<unsigned int> blockShape(blockShapeTensorInfo.
GetNumElements());
2397 ::memcpy(blockShape.data(), blockShapeBufferPtr->data.data(), blockShapeTensorInfo.
GetNumBytes());
2399 std::vector<unsigned int> padListVector(padListTensorInfo.
GetNumElements());
2400 ::memcpy(padListVector.data(), padListBufferPtr->data.data(), padListTensorInfo.
GetNumBytes());
2403 std::vector<std::pair<unsigned int, unsigned int>> padList;
2404 for (
unsigned int i = 0; i < padListTensorInfo.
GetNumElements() / step; ++i)
2406 padList.emplace_back(padListVector[i * step], padListVector[i * step + 1]);
2409 armnn::SpaceToBatchNdDescriptor desc;
2414 auto layerName = fmt::format(
"SpaceToBatchND:{}:{}", subgraphIndex, operatorIndex);
2416 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2418 IConnectableLayer* layer = m_Network->AddSpaceToBatchNdLayer(desc, layerName.c_str());
2422 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
2426 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
2427 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
2430 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2431 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2433 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2434 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2437void TfLiteParserImpl::ParseSpaceToDepth(
size_t subgraphIndex,
size_t operatorIndex)
2439 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2446 armnn::SpaceToDepthDescriptor descriptor;
2448 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2449 const auto* options = operatorPtr->builtin_options.AsSpaceToDepthOptions();
2450 auto blockSize = options->block_size;
2453 throw ParseException(
2454 fmt::format(
"Operation has invalid block size: {} Block size should be >= 2 {}",
2460 auto layerName = fmt::format(
"SpaceToDepth:{}:{}", subgraphIndex, operatorIndex);
2461 IConnectableLayer* layer = m_Network->AddSpaceToDepthLayer(descriptor, layerName.c_str());
2465 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
2469 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
2472 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2473 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2475 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2476 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2483 static const uint32_t dimensionSequence[] = { 0, 1, 2, 3 };
2487 std::stringstream ss;
2488 ss <<
"Input tensor has unexpected number of dimensions:" << inputTensorInfo.
GetNumDimensions()
2489 <<
" shape:" << inputTensorInfo.
GetShape() <<
" "
2494 if (squeezeDims.empty())
2496 squeezeDims.assign(dimensionSequence,
2500 std::vector<uint32_t> outputDims;
2503 bool skipSqueeze = (std::find(squeezeDims.begin(), squeezeDims.end(), i) == squeezeDims.end());
2504 auto currentDimension = inputTensorInfo.
GetShape()[i];
2505 if (skipSqueeze || currentDimension != 1)
2507 outputDims.push_back(currentDimension);
2511 if (outputDims.size() > 4)
2513 std::stringstream ss;
2514 ss <<
"Output tensor has unexpected number of dimensions:" << inputTensorInfo.
GetNumDimensions()
2515 <<
" shape:" << inputTensorInfo.
GetShape() <<
" "
2527 return outTensorInfo;
2530void TfLiteParserImpl::ParseShape(
size_t subgraphIndex,
size_t operatorIndex)
2532 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2534 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2536 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2539 auto layerName = fmt::format(
"Shape:{}:{}", subgraphIndex, operatorIndex);
2549 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
2556 throw ParseException(
2558 "Output tensor data type is not supported. (Supported types: Signed32 & Signed64) {}",
2562 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2563 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2565 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2566 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
2569void TfLiteParserImpl::ParseSqueeze(
size_t subgraphIndex,
size_t operatorIndex)
2571 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2573 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2576 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2579 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2580 const auto * options = operatorPtr->builtin_options.AsSqueezeOptions();
2581 auto layerName = fmt::format(
"Squeeze:{}:{}", subgraphIndex, operatorIndex);
2583 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2585 std::vector<uint32_t> squeezeDim;
2588 if (options->squeeze_dims.size() == 1 && options->squeeze_dims[0] < 0)
2590 int32_t dim =
static_cast<int32_t
>(inputTensorInfo.
GetShape().GetNumDimensions()) + options->squeeze_dims[0];
2591 squeezeDim.push_back(
static_cast<uint32_t
>(dim));
2595 squeezeDim = AsUnsignedVector(options->squeeze_dims);
2600 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
2602 ReshapeDescriptor reshapeDesc;
2606 m_TensorInfos[outputTensorIds[0]] = outputTensorInfo;
2608 IConnectableLayer* layer = m_Network->AddReshapeLayer(reshapeDesc, layerName.c_str());
2612 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
2618 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2619 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2621 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2622 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2625void TfLiteParserImpl::ParseStridedSlice(
size_t subgraphIndex,
size_t operatorIndex)
2627 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2629 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2632 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2635 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2636 const auto* options = operatorPtr->builtin_options.AsStridedSliceOptions();
2638 StridedSliceDescriptor desc;
2646 armnn::TensorInfo beginTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2648 ValidateBuffer(beginBufferPtr, beginTensorInfo,
"begin");
2651 if (beginBufferPtr->data.data() !=
nullptr)
2653 ::memcpy(begin.data(), beginBufferPtr->data.data(), beginTensorInfo.
GetNumBytes());
2657 throw ParseException(
"ParseStridedSlice: Invalid input - the begin vector is null");
2660 armnn::TensorInfo endTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
2662 ValidateBuffer(endBufferPtr, endTensorInfo,
"end");
2665 if (endBufferPtr->data.data() !=
nullptr)
2667 ::memcpy(end.data(), endBufferPtr->data.data(), endTensorInfo.
GetNumBytes());
2671 throw ParseException(
"ParseStridedSlice: Invalid input - the end vector is null");
2674 armnn::TensorInfo strideTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 3);
2676 ValidateBuffer(strideBufferPtr, strideTensorInfo,
"stride");
2680 if (strideBufferPtr->data.data() !=
nullptr)
2682 ::memcpy(stride.data(), strideBufferPtr->data.data(), strideTensorInfo.
GetNumBytes());
2686 throw ParseException(
"ParseStridedSlice: Invalid input - the stride vector is null");
2693 auto layerName = fmt::format(
"StridedSlice:{}:{}", subgraphIndex, operatorIndex);
2694 IConnectableLayer* layer = m_Network->AddStridedSliceLayer(desc, layerName.c_str());
2698 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
2702 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
2705 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2706 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2708 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2709 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2712void TfLiteParserImpl::ParseSub(
size_t subgraphIndex,
size_t operatorIndex)
2714 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2716 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2717 const auto* options = operatorPtr->builtin_options.AsSubOptions();
2719 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2722 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2725 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2726 armnn::TensorInfo input1TensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2728 auto layerName = fmt::format(
"Sub:{}:{}", subgraphIndex, operatorIndex);
2729 IConnectableLayer* layer = m_Network->AddElementwiseBinaryLayer(BinaryOperation::Sub, layerName.c_str());
2733 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
2737 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
2740 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2741 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
2744 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
2747 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2748 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2751void TfLiteParserImpl::ParseDiv(
size_t subgraphIndex,
size_t operatorIndex)
2753 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2755 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2756 const auto* options = operatorPtr->builtin_options.AsDivOptions();
2758 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2761 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2764 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2765 armnn::TensorInfo input1TensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2767 auto layerName = fmt::format(
"Div:{}:{}", subgraphIndex, operatorIndex);
2768 IConnectableLayer* layer = m_Network->AddElementwiseBinaryLayer(BinaryOperation::Div, layerName.c_str());
2772 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
2776 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
2779 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2780 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
2783 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
2786 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2787 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2790void TfLiteParserImpl::ParseFloorDiv(
size_t subgraphIndex,
size_t operatorIndex)
2792 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2794 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2797 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2800 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2801 armnn::TensorInfo input1TensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2803 auto layerName = fmt::format(
"FloorDiv:{}:{}", subgraphIndex, operatorIndex);
2804 IConnectableLayer* layer = m_Network->AddElementwiseBinaryLayer(BinaryOperation::FloorDiv, layerName.c_str());
2808 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
2812 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
2815 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2816 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
2817 layer = AddFusedFloorLayer(layer, 0);
2819 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2820 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2823void TfLiteParserImpl::ParseAdd(
size_t subgraphIndex,
size_t operatorIndex)
2825 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2827 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2828 const auto* options = operatorPtr->builtin_options.AsAddOptions();
2830 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2833 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2836 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2837 armnn::TensorInfo input1TensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2839 auto layerName = fmt::format(
"Add:{}:{}", subgraphIndex, operatorIndex);
2840 IConnectableLayer* layer = m_Network->AddElementwiseBinaryLayer(BinaryOperation::Add, layerName.c_str());
2844 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
2848 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
2851 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2852 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
2855 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
2858 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2859 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2862void TfLiteParserImpl::ParseMul(
size_t subgraphIndex,
size_t operatorIndex)
2864 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2866 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
2867 const auto* options = operatorPtr->builtin_options.AsMulOptions();
2869 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2872 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2875 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2876 armnn::TensorInfo input1TensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2878 auto layerName = fmt::format(
"Mul:{}:{}", subgraphIndex, operatorIndex);
2879 IConnectableLayer* layer = m_Network->AddElementwiseBinaryLayer(BinaryOperation::Mul, layerName.c_str());
2883 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
2887 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
2890 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2891 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
2894 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
2897 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2898 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2901void TfLiteParserImpl::ParseMean(
size_t subgraphIndex,
size_t operatorIndex)
2903 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2905 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
2907 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
2910 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2911 TensorInfo dimTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2913 armnn::MeanDescriptor desc;
2917 if (axisBufferPtr !=
nullptr && !axisBufferPtr->data.empty())
2919 ValidateBuffer(axisBufferPtr, dimTensorInfo,
"axis");
2921 ::memcpy(axisData.data(), axisBufferPtr->data.data(), dimTensorInfo.
GetNumBytes());
2925 std::set<unsigned int> uniqueAxis;
2926 std::transform(axisData.begin(),
2928 std::inserter(uniqueAxis, uniqueAxis.begin()),
2929 [rank](
int i)->unsigned
int{
2930 return static_cast<uint32_t>(((i + rank) % rank)); });
2931 desc.
m_Axis.assign(uniqueAxis.begin(), uniqueAxis.end());
2937 desc.
m_Axis.push_back(i);
2941 armnn::TensorInfo outputTensorInfo =
ToTensorInfo(outputs[0],
true);
2945 auto layerName = fmt::format(
"Mean:{}:{}", subgraphIndex, operatorIndex);
2946 IConnectableLayer* layer = m_Network->AddMeanLayer(desc, layerName.c_str());
2950 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
2954 outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
2957 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
2958 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
2960 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
2961 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
2964void TfLiteParserImpl::ParsePad(
size_t subgraphIndex,
size_t operatorIndex)
2966 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
2973 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
2974 armnn::TensorInfo padTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
2976 std::vector<unsigned int> padBuffer = GetUIntBuffer(padTensorInfo, m_Model, inputs[1]->buffer);
2979 armnn::PadDescriptor desc;
2980 auto opcode = GetOpCode(m_Model, subgraphIndex, operatorIndex);
2982 if (opcode == tflite::BuiltinOperator_PAD)
2991 else if (opcode == tflite::BuiltinOperator_PADV2)
2995 armnn::TensorInfo padValueTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
3004 if (!padValueBufferPtr->data.empty())
3010 std::vector<float> padValueBuffer(padValueTensorInfo.
GetNumElements());
3012 const size_t requiredBytes = padValueTensorInfo.
GetNumElements() *
sizeof(float);
3013 if (padValueBufferPtr->data.size() < requiredBytes)
3015 throw ParseException(
"Pad value buffer is too small for expected data.");
3018 ::memcpy(padValueBuffer.data(), padValueBufferPtr->data.data(), padValueBufferPtr->data.size());
3024 std::vector<uint8_t> padValueBuffer(padValueTensorInfo.
GetNumElements());
3026 const size_t requiredBytes = padValueTensorInfo.
GetNumElements() *
sizeof(uint8_t);
3027 if (padValueBufferPtr->data.size() < requiredBytes)
3029 throw ParseException(
"Pad value buffer is too small for expected data.");
3032 ::memcpy(padValueBuffer.data(), padValueBufferPtr->data.data(), padValueBufferPtr->data.size());
3041 std::vector<int8_t> padValueBuffer(padValueTensorInfo.
GetNumElements());
3043 const size_t requiredBytes = padValueTensorInfo.
GetNumElements() *
sizeof(int8_t);
3044 if (padValueBufferPtr->data.size() < requiredBytes)
3046 throw ParseException(
"Pad value buffer is too small for expected data.");
3049 ::memcpy(padValueBuffer.data(), padValueBufferPtr->data.data(), padValueBufferPtr->data.size());
3064 for (
unsigned int i = 0; i < padTensorInfo.
GetNumElements() / step; ++i)
3066 desc.
m_PadList.emplace_back(padBuffer[i * step], padBuffer[i * step + 1]);
3069 auto layerName = (opcode == tflite::BuiltinOperator_PAD) ? fmt::format(
"Pad:{}:{}", subgraphIndex, operatorIndex)
3070 : fmt::format(
"PadV2:{}:{}", subgraphIndex, operatorIndex);
3072 IConnectableLayer* layer = m_Network->AddPadLayer(desc, layerName.c_str());
3076 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
3080 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
3083 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3084 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
3086 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3087 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
3090void TfLiteParserImpl::ParseMirrorPad(
size_t subgraphIndex,
size_t operatorIndex)
3092 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3100 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
3102 armnn::TensorInfo padTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
3105 std::vector<unsigned int> padBuffer(padTensorInfo.
GetNumElements());
3106 ValidateBuffer(bufferPtr, padTensorInfo,
"axis");
3107 ::memcpy(padBuffer.data(), bufferPtr->data.data(), padTensorInfo.
GetNumBytes());
3110 armnn::PadDescriptor desc;
3111 for (
unsigned int i = 0; i < padTensorInfo.
GetNumElements() / step; ++i)
3113 desc.
m_PadList.emplace_back(padBuffer[i * step], padBuffer[i * step + 1]);
3116 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
3117 const auto* options = operatorPtr->builtin_options.AsMirrorPadOptions();
3119 if (options->mode == tflite::MirrorPadMode_REFLECT)
3123 else if (options->mode == tflite::MirrorPadMode_SYMMETRIC)
3134 auto inputShape = inputTensorInfo.
GetShape();
3137 const unsigned int isReflect =
static_cast<unsigned int>(desc.
m_PaddingMode == PaddingMode::Reflect);
3138 for(
unsigned int i = 0; i < padList.size(); ++i)
3140 if(padList.at(i).first > (inputShape[i] - isReflect) ||
3141 padList.at(i).second > (inputShape[i] - isReflect))
3144 "equal (Symmetric) to the dimension size.");
3148 auto layerName = fmt::format(
"MirrorPad:{}:{}", subgraphIndex, operatorIndex);
3150 IConnectableLayer* layer = m_Network->AddPadLayer(desc, layerName.c_str());
3154 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
3158 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
3161 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3162 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
3164 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3165 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
3168void TfLiteParserImpl::ParsePrelu(
size_t subgraphIndex,
size_t operatorIndex)
3170 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3172 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
3175 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
3178 auto layerName = fmt::format(
"Prelu:{}:{}", subgraphIndex, operatorIndex);
3180 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
3181 armnn::TensorInfo alphaTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
3183 IConnectableLayer* layer = m_Network->AddPreluLayer(layerName.c_str());
3187 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
3191 if (IsConstTensor(inputs[1]))
3193 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3195 RegisterConsumerOfTensor(subgraphIndex, inputTensorIndexes[0], slot);
3197 auto alphaTensorAndData = CreateConstTensorNonPermuted(inputs[1], alphaTensorInfo,
3199 std::string constLayerName = fmt::format(
"Constant:{}", inputs[1]->name);
3200 IConnectableLayer* constLayer =
3201 m_Network->AddConstantLayer(alphaTensorAndData.first, constLayerName.c_str());
3205 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
3211 RegisterOutputSlots(subgraphIndex,
3212 VIRTUAL_OPERATOR_ID,
3214 { inputTensorIndexes[1] });
3218 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3219 RegisterInputSlots(subgraphIndex, operatorIndex, layer, inputTensorIndexes);
3222 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
3225 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3226 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
3229void TfLiteParserImpl::ParseQuantize(
size_t subgraphIndex,
size_t operatorIndex)
3231 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3233 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
3236 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
3239 auto layerName = fmt::format(
"Quantize:{}:{}", subgraphIndex, operatorIndex);
3241 IConnectableLayer* layer = m_Network->AddQuantizeLayer(layerName.c_str());
3245 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
3249 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
3252 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3253 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
3255 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3256 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
3259void TfLiteParserImpl::ParseRelu(
size_t subgraphIndex,
size_t operatorIndex)
3261 ParseActivation(subgraphIndex,operatorIndex, ActivationFunction::ReLu);
3264void TfLiteParserImpl::ParseRelu6(
size_t subgraphIndex,
size_t operatorIndex)
3266 ParseActivation(subgraphIndex,operatorIndex, ActivationFunction::BoundedReLu);
3269void TfLiteParserImpl::ParseLeakyRelu(
size_t subgraphIndex,
size_t operatorIndex)
3271 ParseActivation(subgraphIndex, operatorIndex, ActivationFunction::LeakyReLu);
3274void TfLiteParserImpl::ParseLogistic(
size_t subgraphIndex,
size_t operatorIndex)
3276 ParseActivation(subgraphIndex,operatorIndex,ActivationFunction::Sigmoid);
3279void TfLiteParserImpl::ParseTanH(
size_t subgraphIndex,
size_t operatorIndex)
3281 ParseActivation(subgraphIndex,operatorIndex,ActivationFunction::TanH);
3284void TfLiteParserImpl::ParseElu(
size_t subgraphIndex,
size_t operatorIndex)
3286 ParseActivation(subgraphIndex, operatorIndex, ActivationFunction::Elu);
3289void TfLiteParserImpl::ParseHardSwish(
size_t subgraphIndex,
size_t operatorIndex)
3291 ParseActivation(subgraphIndex, operatorIndex, ActivationFunction::HardSwish);
3294void TfLiteParserImpl::ParseGelu(
size_t subgraphIndex,
size_t operatorIndex)
3296 ParseActivation(subgraphIndex,operatorIndex,ActivationFunction::Gelu);
3299void TfLiteParserImpl::ParseActivation(
size_t subgraphIndex,
size_t operatorIndex,
ActivationFunction activationType)
3301 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3302 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
3305 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
3308 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
3311 auto layerName = fmt::format(
"Activation:");
3312 ActivationDescriptor activationDesc;
3315 switch (activationType)
3317 case ActivationFunction::ReLu:
3319 layerName += fmt::format(
"RELU:{}:{}", subgraphIndex, operatorIndex);
3322 case ActivationFunction::BoundedReLu:
3324 layerName += fmt::format(
"RELU6:{}:{}", subgraphIndex, operatorIndex);
3325 activationDesc.
m_A = 6.0f;
3326 activationDesc.
m_B = 0.0f;
3329 case ActivationFunction::Sigmoid:
3331 layerName += fmt::format(
"SIGMOID:{}:{}", subgraphIndex, operatorIndex);
3334 case ActivationFunction::TanH:
3336 layerName += fmt::format(
"TANH:{}:{}", subgraphIndex, operatorIndex);
3337 activationDesc.
m_A = 1.0f;
3338 activationDesc.
m_B = 1.0f;
3341 case ActivationFunction::LeakyReLu:
3343 layerName += fmt::format(
"LEAKYRELU:{}:{}", subgraphIndex, operatorIndex);
3344 const auto* options = operatorPtr->builtin_options.AsLeakyReluOptions();
3345 activationDesc.
m_A = options->alpha;
3348 case ActivationFunction::Elu:
3350 layerName += fmt::format(
"ELU:{}:{}", subgraphIndex, operatorIndex);
3351 activationDesc.
m_A = 1.0f;
3354 case ActivationFunction::HardSwish:
3356 layerName += fmt::format(
"HARDSWISH:{}:{}", subgraphIndex, operatorIndex);
3359 case ActivationFunction::Gelu:
3361 layerName += fmt::format(
"GELU:{}:{}", subgraphIndex, operatorIndex);
3366 throw ParseException(
3367 fmt::format(
"Unexpected ActivationFunction[{}] when creating layerName {} ",
3372 IConnectableLayer*
const layer = m_Network->AddActivationLayer(activationDesc, layerName.c_str());
3374 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
3379 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3380 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
3383 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3384 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
3388 const std::vector<int32_t>& targetDimsIn)
3390 std::vector<unsigned int> outputDims(targetDimsIn.begin(), targetDimsIn.end());
3391 const auto stretchDim = std::find(targetDimsIn.begin(), targetDimsIn.end(), -1);
3393 if (stretchDim != targetDimsIn.end())
3395 if (std::find(std::next(stretchDim), targetDimsIn.end(), -1) != targetDimsIn.end())
3398 fmt::format(
"At most one component of shape can be -1 {}",
CHECK_LOCATION().AsString()));
3401 auto targetNumElements =
3403 std::accumulate(targetDimsIn.begin(), targetDimsIn.end(), -1, std::multiplies<int32_t>()));
3405 auto stretchIndex =
static_cast<size_t>(std::distance(targetDimsIn.begin(), stretchDim));
3407 if (targetNumElements == 0)
3411 outputDims[stretchIndex] = 0;
3416 fmt::format(
"Input to reshape is a tensor with elements, but the requested shape has 0. {}",
3422 outputDims[stretchIndex] = inputTensorInfo.
GetNumElements() / targetNumElements;
3434void TfLiteParserImpl::ParseReshape(
size_t subgraphIndex,
size_t operatorIndex)
3436 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3438 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
3440 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
3443 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
3444 const auto* options = operatorPtr->builtin_options.AsReshapeOptions();
3445 auto layerName = fmt::format(
"Reshape:{}:{}", subgraphIndex, operatorIndex);
3447 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
3449 CheckMatchingQuantization(inputTensorInfo, actualOutputTensorInfo, layerName,
"Input 0",
"Output 0");
3455 std::vector<int32_t> targetShape;
3456 bool targetShapeFound =
false;
3458 if (options !=
nullptr)
3461 if (options->new_shape.empty() ==
false)
3463 targetShape = options->new_shape;
3464 targetShapeFound =
true;
3469 if (!targetShapeFound)
3472 if (inputs.size() > 1 && inputs[1] !=
nullptr)
3474 if (inputs[1]->is_variable)
3479 if (inputs[1]->shape.size() != 1)
3484 if (inputs[1]->type != tflite::TensorType_INT32)
3490 auto bufferPtr =
GetBuffer(m_Model, inputs[1]->buffer);
3491 auto values =
reinterpret_cast<const int32_t*
>(bufferPtr->data.data());
3494 for (
int i = 0; i < inputs[1]->shape[0]; ++i)
3496 targetShape.push_back(values[i]);
3508 for (
unsigned int i = 0; i < actualOutputTensorInfo.
GetShape().GetNumDimensions(); ++i)
3510 targetShape.push_back(actualOutputTensorInfo.
GetShape()[i]);
3514 else if (reshapeShapes[0] > 2)
3516 throw ParseException(fmt::format(
"Invalid input shape '{}' in Reshape layer '{}' {}. "
3517 "When inferring during runtime, the parser only supports "
3518 "shape (batch, -1) or (-1) for target shape input.",
3525 const int32_t numInputElements = inputTensorInfo.
GetNumElements();
3526 const int32_t inputTensorShape = inputTensorInfo.
GetShape()[0];
3527 if (reshapeShapes[0] == 1)
3529 targetShape = {numInputElements};
3531 else if (reshapeShapes[0] == 2)
3533 targetShape = {inputTensorShape, numInputElements / inputTensorShape};
3537 catch (
const std::exception& exc)
3540 "Reshape operation. Reshape operator target shape input buffer data "
3541 "is null. " << exc.what());
3548 "At least one method required");
3559 const armnn::TensorShape& reshapeOutputTensorShape = reshapeOutputTensorInfo.
GetShape();
3560 if (inputs.size() > 1 && !
CheckShape(reshapeOutputTensorShape, outputs[0]->shape)
3561 && !outputs[0]->shape_signature.empty())
3565 std::vector<int32_t> secondaryOutputTargetShape = outputs[0]->shape_signature;
3569 armnn::TensorInfo secondaryReshapeOutputTensorInfo =
3572 if (!
CheckShape(reshapeOutputTensorShape, secondaryReshapeOutputTensorInfo.
GetShape()))
3574 std::stringstream ss;
3575 ss <<
"New shape defined in reshape parameters "
3576 << reshapeOutputTensorShape
3577 <<
" does not equal output shape "
3578 << actualOutputTensorInfo.
GetShape()
3581 throw ParseException(ss.str());
3586 ReshapeDescriptor reshapeDesc;
3588 m_TensorInfos[outputTensorIds[0]] = reshapeOutputTensorInfo;
3590 IConnectableLayer* layer = m_Network->AddReshapeLayer(reshapeDesc, layerName.c_str());
3594 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
3600 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3601 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
3603 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3604 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
3607void TfLiteParserImpl::ParseResizeBilinear(
size_t subgraphIndex,
size_t operatorIndex)
3609 ParseResize(subgraphIndex, operatorIndex, ResizeMethod::Bilinear);
3612void TfLiteParserImpl::ParseResizeNearestNeighbor(
size_t subgraphIndex,
size_t operatorIndex)
3614 ParseResize(subgraphIndex, operatorIndex, ResizeMethod::NearestNeighbor);
3617void TfLiteParserImpl::ParseResize(
size_t subgraphIndex,
size_t operatorIndex,
ResizeMethod resizeMethod)
3619 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3621 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
3624 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
3627 armnn::TensorInfo sizeTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
3630 std::vector<int32_t> sizeTensorData(sizeTensorInfo.
GetNumElements());
3633 ValidateBuffer(sizeBufferPtr, sizeTensorInfo,
"size");
3634 ::memcpy(sizeTensorData.data(), sizeBufferPtr->data.data(), sizeTensorInfo.
GetNumBytes());
3636 ResizeDescriptor desc;
3639 desc.
m_TargetWidth =
static_cast<uint32_t
> (sizeTensorData[1]);
3642 auto layerName = fmt::format(
"Resize:");
3644 switch (resizeMethod)
3646 case ResizeMethod::Bilinear:
3648 layerName += fmt::format(
"BILINEAR:{}:{}", subgraphIndex, operatorIndex);
3650 const auto & operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
3651 const auto * options = operatorPtr->builtin_options.AsResizeBilinearOptions();
3657 case ResizeMethod::NearestNeighbor:
3659 layerName += fmt::format(
"NEARESTNEIGHBOR:{}:{}", subgraphIndex, operatorIndex);
3664 throw ParseException(
3665 fmt::format(
"Unexpected ResizeMethod[{}] when creating layerName {} ",
3670 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
3672 IConnectableLayer* layer = m_Network->AddResizeLayer(desc, layerName.c_str());
3676 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
3680 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
3681 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
3684 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3685 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
3687 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3688 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
3691void TfLiteParserImpl::ParseReverseV2(
size_t subgraphIndex,
size_t operatorIndex)
3693 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3695 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
3698 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
3701 auto layerName = fmt::format(
"ReverseV2:{}:{}", subgraphIndex, operatorIndex);
3705 TensorInfo outputTensorInfo =
ToTensorInfo(outputs[0]);
3707 IConnectableLayer* layer = m_Network->AddReverseV2Layer(layerName.c_str());
3712 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3713 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
3715 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3716 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
3719void TfLiteParserImpl::ParseTile(
size_t subgraphIndex,
size_t operatorIndex)
3721 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3723 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
3726 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
3730 TensorInfo multiplesTensorInfo =
ToTensorInfo(inputs[1]);
3731 TensorInfo outputTensorInfo =
ToTensorInfo(outputs[0]);
3733 auto layerName = fmt::format(
"Tile:{}:{}", subgraphIndex, operatorIndex);
3735 TileDescriptor descriptor;
3738 if (multiplesBufferPtr !=
nullptr)
3740 std::vector<int32_t> multiplesData(multiplesTensorInfo.
GetNumElements());
3741 ValidateBuffer(multiplesBufferPtr, multiplesTensorInfo,
"multiples");
3742 ::memcpy(multiplesData.data(), multiplesBufferPtr->data.data(), multiplesTensorInfo.
GetNumBytes());
3743 descriptor.
m_Multiples.assign(multiplesData.begin(), multiplesData.end());
3750 IConnectableLayer* layer = m_Network->AddTileLayer(descriptor, layerName.c_str());
3755 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3756 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
3758 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3759 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
3762void TfLiteParserImpl::ParseConcatenation(
size_t subgraphIndex,
size_t operatorIndex)
3764 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3766 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
3767 const auto* options = operatorPtr->builtin_options.AsConcatenationOptions();
3771 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
3772 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
3777 unsigned int numConcatView =
static_cast<unsigned int>(inputs.size());
3778 uint32_t inputRank = InputTensorInfo(subgraphIndex, operatorIndex, 0).GetNumDimensions();
3780 const unsigned int concatDimInput =
static_cast<unsigned int>(
3781 (
static_cast<int>(inputRank) + options->axis) %
static_cast<int>(inputRank));
3783 OriginsDescriptor concatDescriptor(
static_cast<uint32_t
>(numConcatView), inputRank);
3784 concatDescriptor.SetConcatAxis(concatDimInput);
3785 unsigned int mergeDimOrigin = 0;
3787 for (
unsigned int viewIndex = 0; viewIndex < numConcatView; ++viewIndex)
3789 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, viewIndex);
3793 inputTensorInfo, concatDescriptor, concatDimInput, viewIndex, mergeDimOrigin);
3796 auto layerName = fmt::format(
"Concatenation:{}:{}", subgraphIndex, operatorIndex);
3798 IConnectableLayer* layer = m_Network->AddConcatLayer(concatDescriptor, layerName.c_str());
3802 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
3806 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {});
3809 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3810 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes});
3813 layer = AddFusedActivationLayer(layer, 0, options->fused_activation_function);
3815 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3816 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
3819void TfLiteParserImpl::ParseFullyConnected(
size_t subgraphIndex,
size_t operatorIndex)
3821 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3823 const auto& operatorRfr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
3824 const auto options = operatorRfr->builtin_options.AsFullyConnectedOptions();
3828 FullyConnectedDescriptor desc;
3832 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
3833 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
3836 armnn::TensorInfo filterTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
3839 int32_t weightsDimension =
static_cast<int32_t
>(filterTensorInfo.
GetNumDimensions());
3840 if (weightsDimension != 2)
3842 throw ParseException(
3843 fmt::format(
"Dimension {} for Fully Connected weights is not supported by Armnn. "
3849 armnn::IConnectableLayer* layer =
nullptr;
3850 auto layerName = fmt::format(
"FullyConnected:{}:{}", subgraphIndex, operatorIndex);
3852 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
3854 std::vector<unsigned int> tensorIndexesToRegister = {inputTensorIndexes[0]};
3855 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
3860 tensorIndexesToRegister.emplace_back(inputTensorIndexes[1]);
3862 if (ShouldConstantTensorBeConverted(inputs[1], inputTensorInfo.
GetDataType(), filterTensorInfo.
GetDataType()))
3864 m_ConstantsToDequantize.emplace_back(inputs[1]->buffer);
3867 if (inputs.size() == 3)
3870 armnn::TensorInfo biasTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
3873 tensorIndexesToRegister.emplace_back(inputTensorIndexes[2]);
3875 if (ShouldConstantTensorBeConverted(inputs[2], inputTensorInfo.
GetDataType(), biasTensorInfo.
GetDataType()))
3877 m_ConstantsToDequantize.emplace_back(inputs[2]->buffer);
3882 layer = m_Network->AddFullyConnectedLayer(desc, layerName.c_str());
3886 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
3890 unsigned int startingSlotIndex = 0;
3897 std::vector<unsigned int> reshapedDimensions(2);
3898 reshapedDimensions[1] = filterTensorInfo.
GetShape()[1];
3899 reshapedDimensions[0] = inputTensorInfo.
GetNumElements() / reshapedDimensions[1];
3901 if (inputTensorInfo.
GetNumElements() % reshapedDimensions[1] != 0)
3903 throw ParseException(
3904 fmt::format(
"Failed to deduce input tensor shape from filter size {} {}",
3905 reshapedDimensions[1],
3909 armnn::TensorInfo reshapedTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
3910 reshapedTensorInfo.
SetShape(armnn::TensorShape{ 2, reshapedDimensions.data() });
3911 inputTensorInfo = reshapedTensorInfo;
3913 std::string reshapeLayerName = fmt::format(
"Reshape_for:{}", layer->
GetName());
3914 armnn::ReshapeDescriptor reshapeDescriptor;
3916 armnn::IConnectableLayer* reshapeLayer = m_Network->AddReshapeLayer(reshapeDescriptor,
3917 reshapeLayerName.c_str());
3922 RegisterInputSlots(subgraphIndex, operatorIndex, reshapeLayer, {inputTensorIndexes[0]});
3924 tensorIndexesToRegister.erase(tensorIndexesToRegister.begin());
3925 startingSlotIndex = 1;
3928 RegisterInputSlots(subgraphIndex, operatorIndex, layer, tensorIndexesToRegister, startingSlotIndex);
3930 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromShapes(subgraphIndex, operatorIndex, layer, 0,
3939 std::vector<unsigned int> reshapedDimensions(2);
3940 reshapedDimensions[1] = filterTensorInfo.
GetShape()[0];
3941 reshapedDimensions[0] = outputTensorInfo.
GetNumElements() / reshapedDimensions[1];
3942 armnn::TensorInfo reshapedOutputTensorInfo = outputTensorInfo;
3943 if (outputTensorInfo.
GetNumElements() % reshapedDimensions[1] != 0)
3945 throw ParseException(
3946 fmt::format(
"Failed to deduce output tensor shape from filter size {} {}",
3947 reshapedDimensions[1],
3950 reshapedOutputTensorInfo.
SetShape(armnn::TensorShape{ 2, reshapedDimensions.data() });
3953 std::string reshapeLayerName = fmt::format(
"ExpandDims:{}:{}", subgraphIndex, operatorIndex);
3954 layer = AddReshapeLayer(layer, 0, reshapeLayerName, outputTensorInfo);
3958 armnn::IConnectableLayer* fusedActivationLayer = AddFusedActivationLayer(layer, 0,
3959 options->fused_activation_function);
3962 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
3963 RegisterOutputSlots(subgraphIndex, operatorIndex, fusedActivationLayer, {outputTensorIndexes[0]});
3968void TfLiteParserImpl::ParseDetectionPostProcess(
size_t subgraphIndex,
size_t operatorIndex)
3970 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
3972 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
3974 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
3975 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
3979 auto custom_options = operatorPtr->custom_options;
3980 const flexbuffers::Map& m = flexbuffers::GetRoot(custom_options.data(), custom_options.size()).AsMap();
3983 DetectionPostProcessDescriptor desc;
3989 desc.
m_ScaleH = m[
"h_scale"].AsFloat();
3990 desc.
m_ScaleW = m[
"w_scale"].AsFloat();
3991 desc.
m_ScaleX = m[
"x_scale"].AsFloat();
3992 desc.
m_ScaleY = m[
"y_scale"].AsFloat();
3994 if (!(m[
"use_regular_nms"].IsNull()))
3998 if (!(m[
"detections_per_class"].IsNull()))
4005 throw InvalidArgumentException(
"DetectionPostProcessTFLiteParser: Intersection over union threshold "
4006 "must be positive and less than or equal to 1.");
4009 armnn::TensorInfo anchorTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 2);
4010 auto anchorTensorAndData = CreateConstTensorNonPermuted(inputs[2], anchorTensorInfo);
4012 auto layerName = fmt::format(
"DetectionPostProcess:{}:{}", subgraphIndex, operatorIndex);
4013 IConnectableLayer* layer = m_Network->AddDetectionPostProcessLayer(desc, anchorTensorAndData,
4018 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
4025 m_OverriddenOutputShapes.push_back({ 1, numDetectedBox, 4 });
4026 m_OverriddenOutputShapes.push_back({ 1, numDetectedBox });
4027 m_OverriddenOutputShapes.push_back({ 1, numDetectedBox });
4028 m_OverriddenOutputShapes.push_back({ 1 });
4030 for (
unsigned int i = 0 ; i < outputs.size() ; ++i)
4032 armnn::TensorInfo detectionBoxOutputTensorInfo =
ToTensorInfo(outputs[i], m_OverriddenOutputShapes[i]);
4038 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
4039 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
4042 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
4043 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0],
4044 outputTensorIndexes[1],
4045 outputTensorIndexes[2],
4046 outputTensorIndexes[3]});
4050void TfLiteParserImpl::ParsePack(
size_t subgraphIndex,
size_t operatorIndex)
4052 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
4054 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
4055 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
4058 if (inputs.size() < 1)
4060 throw ParseException(
"Pack must have at least one input.");
4063 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
4064 const auto* options = operatorPtr->builtin_options.AsPackOptions();
4066 StackDescriptor desc;
4067 desc.
m_Axis =
static_cast<uint32_t
>(options->axis);
4068 desc.
m_NumInputs =
static_cast<uint32_t
>(inputs.size());
4071 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
4074 auto layerName = fmt::format(
"Pack:{}:{}", subgraphIndex, operatorIndex);
4075 IConnectableLayer* layer = m_Network->AddStackLayer(desc, layerName.c_str());
4079 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
4083 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {});
4086 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
4087 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes});
4089 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
4090 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
4093void TfLiteParserImpl::ParseUnidirectionalSequenceLSTM(
size_t subgraphIndex,
size_t operatorIndex)
4095 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
4097 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
4098 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
4100 if (inputs.size() < 2)
4102 throw ParseException(
"UnidirectionalSequenceLSTM must have at least 2 input.");
4105 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
4106 const auto& subgraphPtr = m_Model->subgraphs[subgraphIndex];
4107 const auto nodeParams = operatorPtr->builtin_options.AsUnidirectionalSequenceLSTMOptions();
4109 auto inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
4115 armnn::LstmInputParams params;
4117 if (IsOptionalOperandPresent(operatorPtr->inputs[1]))
4119 params.
m_InputToInputWeights = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[1]].get(),
4120 inputTensorInfo).first;
4124 inputTensorInfo).first;
4125 params.
m_InputToCellWeights = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[3]].get(),
4126 inputTensorInfo).first;
4128 inputTensorInfo).first;
4131 if (IsOptionalOperandPresent(operatorPtr->inputs[5]))
4134 inputTensorInfo).first;
4138 inputTensorInfo).first;
4140 inputTensorInfo).first;
4142 inputTensorInfo).first;
4145 if (IsOptionalOperandPresent(operatorPtr->inputs[9]))
4147 params.
m_CellToInputWeights = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[9]].get(),
4148 inputTensorInfo).first;
4151 if (IsOptionalOperandPresent(operatorPtr->inputs[10]))
4153 params.
m_CellToForgetWeights = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[10]].get(),
4154 inputTensorInfo).first;
4157 if (IsOptionalOperandPresent(operatorPtr->inputs[11]))
4159 params.
m_CellToOutputWeights = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[11]].get(),
4160 inputTensorInfo).first;
4164 if (IsOptionalOperandPresent(operatorPtr->inputs[12]))
4166 params.
m_InputGateBias = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[12]].get(),
4167 inputTensorInfo).first;
4170 params.
m_ForgetGateBias = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[13]].get(),
4171 inputTensorInfo).first;
4172 params.
m_CellBias = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[14]].get(),
4173 inputTensorInfo).first;
4174 params.
m_OutputGateBias = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[15]].get(),
4175 inputTensorInfo).first;
4178 if (IsOptionalOperandPresent(operatorPtr->inputs[16]))
4180 params.
m_ProjectionWeights = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[16]].get(),
4181 inputTensorInfo).first;
4184 if (IsOptionalOperandPresent(operatorPtr->inputs[17]))
4186 params.
m_ProjectionBias = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[17]].get(),
4187 inputTensorInfo).first;
4191 armnn::TensorInfo outputStateInInfo =
ToTensorInfo(subgraphPtr->tensors[operatorPtr->inputs[18]].get());
4192 m_ConstantsToBeCreated.push_back(operatorPtr->inputs[18]);
4193 armnn::TensorInfo cellStateInInfo =
ToTensorInfo(subgraphPtr->tensors[operatorPtr->inputs[19]].get());
4194 m_ConstantsToBeCreated.push_back(operatorPtr->inputs[19]);
4197 if (inputs.size() >= 21 && IsOptionalOperandPresent(operatorPtr->inputs[20]))
4200 inputTensorInfo).first;
4203 if (inputs.size() >= 22 && IsOptionalOperandPresent(operatorPtr->inputs[21]))
4206 inputTensorInfo).first;
4209 if (inputs.size() >= 23 && IsOptionalOperandPresent(operatorPtr->inputs[22]))
4211 params.
m_CellLayerNormWeights = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->inputs[22]].get(),
4212 inputTensorInfo).first;
4215 if (inputs.size() >= 24 && IsOptionalOperandPresent(operatorPtr->inputs[23]))
4218 inputTensorInfo).first;
4239 auto inputIntermediate = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->intermediates[0]].get(),
4240 inputTensorInfo).first;
4241 auto inputIntermediateTensorInfo = inputIntermediate->GetInfo();
4244 auto forgetIntermediate = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->intermediates[1]].get(),
4245 inputTensorInfo).first;
4246 auto forgetIntermediateTensorInfo = forgetIntermediate->GetInfo();
4249 auto cellIntermediate = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->intermediates[2]].get(),
4250 inputTensorInfo).first;
4251 auto cellIntermediateTensorInfo = cellIntermediate->GetInfo();
4254 auto outputIntermediate = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->intermediates[3]].get(),
4255 inputTensorInfo).first;
4256 auto outputIntermediateTensorInfo = outputIntermediate->GetInfo();
4261 float defaultIntermediate = std::pow(2, -12);
4268 if (operatorPtr->intermediates.size() > 4)
4270 auto hiddentensor = CreateConstTensorPtr(subgraphPtr->tensors[operatorPtr->intermediates[4]].get(),
4271 inputTensorInfo).first;
4277 unsigned int outputSize = outputTensorInfo.
GetShape()[2];
4278 unsigned int numUnits = cellStateInInfo.
GetShape()[1];
4284 armnn::TensorInfo scratchBufferTensorInfo({batchSize, numUnits * 3}, dataType, qScale, qOffset);
4287 scratchBufferTensorInfo = armnn::TensorInfo({batchSize, numUnits * 4}, dataType, qScale, qOffset);
4289 armnn::TensorInfo cellStateOutTensorInfo({batchSize, numUnits},
4293 armnn::TensorInfo outputStateOutTensorInfo({batchSize, outputSize}, dataType, qScale, qOffset);
4295 armnn::LstmInputParamsInfo paramsInfo;
4343 auto layerName = fmt::format(
"UnidirectionalSequenceLSTM:{}:{}", subgraphIndex, operatorIndex);
4344 armnn::IConnectableLayer* layer = m_Network->AddUnidirectionalSequenceLstmLayer(desc, params);
4348 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
4354 auto inputTensorIndexes = AsUnsignedVector({operatorPtr->inputs[0],
4355 operatorPtr->inputs[18],
4356 operatorPtr->inputs[19]});
4357 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0],
4358 inputTensorIndexes[1],
4359 inputTensorIndexes[2]});
4361 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
4367 unsigned int tensorIndex = outputTensorIndexes[0];
4369 RegisterProducerOfTensor(subgraphIndex, tensorIndex, slot);
4372void TfLiteParserImpl::ParseUnpack(
size_t subgraphIndex,
size_t operatorIndex)
4374 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
4376 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
4377 const auto* options = operatorPtr->builtin_options.AsUnpackOptions();
4382 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
4385 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
4389 throw ParseException(
4390 fmt::format(
"The unpack axis: {} cannot be greater than or equal to "
4391 "the number of input dimension {} {}",
4401 unpackNum = inputTensorInfo.
GetShape()[unpackAxis];
4407 throw ParseException(
"Number to unpack must greater than zero.");
4410 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
4414 std::vector<unsigned int> unpackDimSizes(inputDimSize);
4417 for (
unsigned int i = 0; i < inputDimSize; ++i)
4419 unpackDimSizes[i] = inputTensorInfo.
GetShape()[i];
4422 if (unpackDimSizes[unpackAxis] != unpackNum)
4424 throw ParseException(
"Number to unpack must be the same as length of the dimension to "
4428 unpackDimSizes[unpackAxis] /= unpackNum;
4430 SplitterDescriptor splitDesc(unpackNum,
static_cast<unsigned int>(unpackDimSizes.size()));
4431 for (
unsigned int j = 0; j < unpackNum; ++j)
4434 for (
unsigned int dimIdx = 0; dimIdx < unpackDimSizes.size(); ++dimIdx)
4436 splitDesc.SetViewSize(j, dimIdx, unpackDimSizes[dimIdx]);
4438 splitDesc.SetViewOriginCoord(j, unpackAxis, unpackDimSizes[unpackAxis] * j);
4440 splitDesc.SetAxis(unpackAxis);
4441 auto layerName = fmt::format(
"Unpack:{}:{}", subgraphIndex, operatorIndex);
4442 IConnectableLayer* layer = m_Network->AddSplitterLayer(splitDesc, layerName.c_str());
4446 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
4450 TensorShape splitOutShape = TensorShape(
static_cast<unsigned int>(unpackDimSizes.size()),
4451 unpackDimSizes.data());
4453 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
4454 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
4456 std::vector<unsigned int> reshapeDims;
4457 for (
unsigned int axis = 0; axis < splitOutShape.
GetNumDimensions(); ++axis)
4459 if (axis != unpackAxis)
4461 reshapeDims.push_back(splitOutShape[axis]);
4465 TensorShape reshapeOutputShape(splitOutShape.
GetNumDimensions() -1, reshapeDims.data());
4470 armnn::TensorInfo outputTensorInfo =
ToTensorInfo(outputs[k],
true);
4471 std::string reshapeLayerName = fmt::format(
"Reshape_for:{}", layer->
GetName());
4472 armnn::ReshapeDescriptor desc;
4474 armnn::IConnectableLayer* reshapeLayer = m_Network->AddReshapeLayer(desc, layerName.c_str());
4485 armnn::IOutputSlot* slot = &(reshapeLayer->
GetOutputSlot(0));
4486 RegisterProducerOfTensor(subgraphIndex, reshapedOutputId, slot);
4490void TfLiteParserImpl::ParseSplit(
size_t subgraphIndex,
size_t operatorIndex)
4492 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
4494 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
4495 const auto* options = operatorPtr->builtin_options.AsSplitOptions();
4502 throw ParseException(
"Number to splits must greater than zero.");
4505 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
4507 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
4510 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
4511 armnn::TensorInfo axisTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
4515 throw ParseException(fmt::format(
"Axis tensor can only have 1 element {}",
4520 if (axisBufferPtr ==
nullptr)
4522 throw ParseException(
4523 fmt::format(
"Operation has invalid inputs. Failed to read axis. {}",
4528 ValidateBuffer(axisBufferPtr, axisTensorInfo,
"axis");
4529 ::memcpy(axisData.data(), axisBufferPtr->data.data(), axisTensorInfo.
GetNumBytes());
4530 int32_t axis = axisData[0];
4532 auto inputDimensions =
static_cast<int32_t
>(inputTensorInfo.
GetNumDimensions());
4533 if (((axis < -inputDimensions) && (axis < 0)) || ((axis >= inputDimensions) && (axis > 0)))
4538 throw ParseException(
4539 fmt::format(
"Operation has invalid axis: {}. Axis must be in range [-n, n) {}",
4549 throw ParseException(
4550 fmt::format(
"The number of dimensions: {} for input tensors of the split op cannot be greater than {} {}",
4556 std::vector<unsigned int> splitterDimSizes(inputDimSize);
4559 for (
unsigned int i = 0; i < inputDimSize; ++i)
4561 splitterDimSizes[i] = inputTensorInfo.
GetShape()[i];
4564 if (splitterDimSizes[splitDim] % numSplits != 0)
4566 throw ParseException(
"Number of splits must evenly divide the dimension");
4568 splitterDimSizes[splitDim] /= numSplits;
4571 for (
unsigned int j = 0; j < numSplits; ++j)
4574 for (
unsigned int dimIdx = 0; dimIdx < splitterDimSizes.size(); ++dimIdx)
4576 splitDesc.SetViewSize(j, dimIdx, splitterDimSizes[dimIdx]);
4578 splitDesc.SetViewOriginCoord(j, splitDim, splitterDimSizes[splitDim] * j);
4582 splitDesc.SetAxis(axis);
4584 auto layerName = fmt::format(
"Split:{}:{}", subgraphIndex, operatorIndex);
4585 IConnectableLayer* layer = m_Network->AddSplitterLayer(splitDesc, layerName.c_str());
4589 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
4593 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
4594 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[1]});
4598 armnn::TensorInfo tensorInfo =
ToTensorInfo(outputs[k],
true);
4602 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
4603 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
4609 int v = idx < 0 ? numDims + idx : idx;
4611 if (v < 0 || v > numDims)
4616 return static_cast<unsigned int>(v);
4619void TfLiteParserImpl::ParseSplitV(
size_t subgraphIndex,
size_t operatorIndex)
4621 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
4623 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
4624 const auto* options = operatorPtr->builtin_options.AsSplitVOptions();
4626 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
4629 auto& inputTensor = inputs[0];
4630 auto& splitsTensor = inputs[1];
4631 auto& axisTensor = inputs[2];
4639 throw ParseException(fmt::format(
"Axis tensor can only have 1 element {}",
4647 throw ParseException(
4648 fmt::format(
"The number of dimensions: {} for input tensors of the "
4649 "SplitV op cannot be greater than {} {}",
4657 if (axisBufferPtr ==
nullptr)
4659 throw ParseException(
4660 fmt::format(
"Operation has invalid inputs. Failed to read axis. {}",
4665 ValidateBuffer(axisBufferPtr, axisTensorInfo,
"axis");
4666 ::memcpy(axisData.data(), axisBufferPtr->data.data(), axisTensorInfo.
GetNumBytes());
4667 int32_t axis = axisData[0];
4669 auto inputDimensions =
static_cast<int32_t
>(inputTensorInfo.
GetNumDimensions());
4670 if (((axis < -inputDimensions) && (axis < 0)) || ((axis >= inputDimensions) && (axis > 0)))
4675 throw ParseException(
4676 fmt::format(
"Operation has invalid axis: {}. Axis must be in range [-n, n) {}",
4684 unsigned int numSplits{0};
4697 throw ParseException(
"SplitV has invalid number of splits");
4700 std::vector<int> splitsData(numSplits);
4702 ValidateBuffer(splitsBufferPtr, splitsInfo,
"splits");
4703 ::memcpy(splitsData.data(), splitsBufferPtr->data.data(), splitsInfo.
GetNumBytes());
4705 unsigned int idx = 0;
4707 unsigned int inferIdx{0};
4709 for (
auto split : splitsData)
4723 if (numInferred == 0)
4727 throw ParseException(
"SplitV split_sizes does not sum to the dimension of value along split_dim.");
4730 else if (numInferred == 1)
4736 throw ParseException(
"Cannot infer split size for more than one split");
4740 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
4745 unsigned int accumSplit = 0;
4746 for (
unsigned int j = 0; j < numSplits; ++j)
4751 for (
unsigned int dimIdx = 0; dimIdx < inputTensorInfo.
GetNumDimensions(); ++dimIdx)
4753 unsigned int dimSize = inputTensorInfo.
GetShape()[dimIdx];
4754 if (dimIdx == splitDim)
4756 dimSize = splitSize;
4758 splitDesc.SetViewSize(j, dimIdx, dimSize);
4761 splitDesc.SetViewOriginCoord(j, splitDim, accumSplit);
4762 accumSplit += splitSize;
4764 splitDesc.SetAxis(axis);
4766 auto layerName = fmt::format(
"SplitV:{}:{}", subgraphIndex, operatorIndex);
4767 IConnectableLayer* layer = m_Network->AddSplitterLayer(splitDesc, layerName.c_str());
4771 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
4775 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
4776 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
4780 armnn::TensorInfo tensorInfo =
ToTensorInfo(outputs[k],
true);
4784 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
4785 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
4788void TfLiteParserImpl::ParseArgMin(
size_t subgraphIndex,
size_t operatorIndex)
4793void TfLiteParserImpl::ParseArgMax(
size_t subgraphIndex,
size_t operatorIndex)
4798void TfLiteParserImpl::ParseArgMinMax(
size_t subgraphIndex,
size_t operatorIndex,
ArgMinMaxFunction argMinMaxFunction)
4800 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
4801 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
4804 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
4807 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
4808 armnn::TensorInfo axisTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
4809 armnn::TensorInfo outputTensorInfo =
ToTensorInfo(outputs[0]);
4813 throw ParseException(fmt::format(
"Axis tensor can only have 1 element {}",
4821 throw ParseException(
4823 "Output tensor data type is not supported. (Supported types: Signed32 & Signed64) {}",
4829 if (axisBufferPtr ==
nullptr)
4831 throw ParseException(
4832 fmt::format(
"Operation has invalid inputs. Failed to read axis. {}",
4837 ValidateBuffer(axisBufferPtr, axisTensorInfo,
"axis");
4839 ::memcpy(axisData.data(), axisBufferPtr->data.data(), axisTensorInfo.
GetNumBytes());
4840 int32_t axis = axisData.front();
4842 auto inputDimensions =
static_cast<int32_t
>(inputTensorInfo.
GetNumDimensions());
4843 if (((axis < -inputDimensions) && (axis < 0)) || ((axis >= inputDimensions) && (axis > 0)))
4848 throw ParseException(
4849 fmt::format(
"Operation has invalid axis: {}. Axis must be in range [-n, n) {}",
4854 ArgMinMaxDescriptor desc;
4859 auto layerName = argMinMaxFunction == ArgMinMaxFunction::Max ?
"ArgMax:{}:{}" :
"ArgMin:{}:{}";
4860 auto layerNameFormatted = fmt::format(layerName, subgraphIndex, operatorIndex);
4861 IConnectableLayer *layer = m_Network->AddArgMinMaxLayer(desc, layerNameFormatted.c_str());
4865 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
4869 outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
4873 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
4874 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
4877 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
4878 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
4881void TfLiteParserImpl::ParseGather(
size_t subgraphIndex,
size_t operatorIndex)
4883 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
4890 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
4891 armnn::TensorInfo indicesTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
4892 armnn::TensorInfo outputTensorInfo =
ToTensorInfo(outputs[0]);
4894 armnn::GatherDescriptor gatherDescriptor;
4896 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
4897 const auto* options = operatorPtr->builtin_options.AsGatherOptions();
4898 auto axis = options->axis;
4900 auto layerName = fmt::format(
"Gather:{}:{}", subgraphIndex, operatorIndex);
4902 auto inputDimensions =
static_cast<int32_t
>(inputTensorInfo.
GetNumDimensions());
4905 if (((axis < -inputDimensions) && (axis < 0)) || ((axis >= inputDimensions) && (axis > 0)))
4907 throw ParseException(
4908 fmt::format(
"Operation has invalid axis: {} It is out of bounds [ -{}, {} ) {}",
4910 inputDimensions, inputDimensions,
4913 if (outputDimensions !=
static_cast<unsigned int>(inputDimensions) + indicesDimensions - 1)
4915 throw ParseException(
4916 fmt::format(
"Operation has invalid output dimensions: {} Output must be an ({} + {} - 1) -D tensor {}",
4918 inputDimensions, indicesDimensions,
4922 gatherDescriptor.
m_Axis = axis;
4924 IConnectableLayer* layer = m_Network->AddGatherLayer(gatherDescriptor, layerName.c_str());
4928 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
4932 outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
4935 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
4936 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
4938 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
4939 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
4942void TfLiteParserImpl::ParseGatherNd(
size_t subgraphIndex,
size_t operatorIndex)
4944 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
4951 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
4952 armnn::TensorInfo indicesTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
4954 auto layerName = fmt::format(
"GatherNd:{}:{}", subgraphIndex, operatorIndex);
4955 IConnectableLayer* layer = m_Network->AddGatherNdLayer(layerName.c_str());
4959 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
4963 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
4966 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
4967 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
4969 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
4970 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
4973void TfLiteParserImpl::ParseDepthToSpace(
size_t subgraphIndex,
size_t operatorIndex)
4975 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
4984 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
4985 const auto* options = operatorPtr->builtin_options.AsDepthToSpaceOptions();
4986 auto blockSize = options->block_size;
4989 throw ParseException(
4990 fmt::format(
"Operation has invalid block size: {} Block size should be >= 2 {}",
4996 auto layerName = fmt::format(
"DepthToSpace:{}:{}", subgraphIndex, operatorIndex);
4997 IConnectableLayer* layer = m_Network->AddDepthToSpaceLayer(descriptor, layerName.c_str());
5001 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
5005 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
5008 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
5009 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
5011 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
5012 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
5015void TfLiteParserImpl::ParseSum(
size_t subgraphIndex,
size_t operatorIndex)
5020void TfLiteParserImpl::ParseReduceProd(
size_t subgraphIndex,
size_t operatorIndex)
5025void TfLiteParserImpl::ParseReduceMax(
size_t subgraphIndex,
size_t operatorIndex)
5030void TfLiteParserImpl::ParseReduceMin(
size_t subgraphIndex,
size_t operatorIndex)
5035void TfLiteParserImpl::ParseReduce(
size_t subgraphIndex,
size_t operatorIndex,
ReduceOperation reduceOperation)
5037 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
5039 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
5040 const auto* options = operatorPtr->builtin_options.AsReducerOptions();
5042 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
5045 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
5048 auto layerName = fmt::format(
"Reduce:{}:{}", subgraphIndex, operatorIndex);
5050 armnn::TensorInfo inputTensorInfo0 = InputTensorInfo(subgraphIndex, operatorIndex, 0);
5051 armnn::TensorInfo inputTensorInfo1 = InputTensorInfo(subgraphIndex, operatorIndex, 1);
5053 ReduceDescriptor desc;
5056 if (axisBufferPtr !=
nullptr)
5058 std::vector<int32_t> axisData(inputTensorInfo1.
GetNumElements());
5059 ValidateBuffer(axisBufferPtr, inputTensorInfo1,
"axis");
5060 ::memcpy(axisData.data(), axisBufferPtr->data.data(), inputTensorInfo1.
GetNumBytes());
5064 std::set<unsigned int> uniqueAxis;
5065 std::transform(axisData.begin(),
5067 std::inserter(uniqueAxis, uniqueAxis.begin()),
5068 [rank](
int i)->unsigned
int{
5069 return static_cast<uint32_t>(((i + rank) % rank)); });
5070 desc.
m_vAxis.assign(uniqueAxis.begin(), uniqueAxis.end());
5084 IConnectableLayer* layer = m_Network->AddReduceLayer(desc, layerName.c_str());
5086 armnn::TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
5090 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
5091 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
5094 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
5095 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
5098void TfLiteParserImpl::ParseLocalResponseNormalization(
size_t subgraphIndex,
size_t operatorIndex)
5100 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
5102 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
5105 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
5108 auto layerName = fmt::format(
"LRN:{}:{}", subgraphIndex, operatorIndex);
5109 std::string layerNameFormatted = fmt::format(layerName, subgraphIndex, operatorIndex);
5111 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
5113 const auto& operatorPtr = m_Model->subgraphs[subgraphIndex]->operators[operatorIndex];
5114 const auto* options = operatorPtr->builtin_options.AsLocalResponseNormalizationOptions();
5116 armnn::NormalizationDescriptor descriptor;
5120 descriptor.
m_NormSize =
static_cast<uint32_t
>(options->radius);
5121 descriptor.
m_K = options->bias;
5122 descriptor.
m_Alpha = options->alpha;
5123 descriptor.
m_Beta = options->beta;
5129 IConnectableLayer* layer = m_Network->AddNormalizationLayer(descriptor, layerNameFormatted.c_str());
5133 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
5137 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
5140 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
5141 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
5143 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
5144 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
5147void TfLiteParserImpl::ParseAbs(
size_t subgraphIndex,
size_t operatorIndex)
5152void TfLiteParserImpl::ParseCeil(
size_t subgraphIndex,
size_t operatorIndex)
5157void TfLiteParserImpl::ParseExp(
size_t subgraphIndex,
size_t operatorIndex)
5162void TfLiteParserImpl::ParseLog(
size_t subgraphIndex,
size_t operatorIndex)
5167void TfLiteParserImpl::ParseLogicalNot(
size_t subgraphIndex,
size_t operatorIndex)
5172void TfLiteParserImpl::ParseNeg(
size_t subgraphIndex,
size_t operatorIndex)
5177void TfLiteParserImpl::ParsePower(
size_t subgraphIndex,
size_t operatorIndex)
5179 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
5181 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
5184 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
5187 auto layerName = fmt::format(
"Power:{}:{}", subgraphIndex, operatorIndex);
5189 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
5190 TensorInfo input1TensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
5191 CheckMatchingQuantization(inputTensorInfo, input1TensorInfo, layerName,
"Input 0",
"Input 1");
5193 IConnectableLayer* layer = m_Network->AddElementwiseBinaryLayer(BinaryOperation::Power, layerName.c_str());
5197 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
5201 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
5202 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
5205 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
5206 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
5208 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
5209 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
5212void TfLiteParserImpl::ParseRsqrt(
size_t subgraphIndex,
size_t operatorIndex)
5217void TfLiteParserImpl::ParseSin(
size_t subgraphIndex,
size_t operatorIndex)
5222void TfLiteParserImpl::ParseSqrt(
size_t subgraphIndex,
size_t operatorIndex)
5227void TfLiteParserImpl::ParseSquare(
size_t subgraphIndex,
size_t operatorIndex)
5229 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
5231 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
5234 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
5237 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
5239 auto layerName = fmt::format(
"Square:{}:{}", subgraphIndex, operatorIndex);
5240 IConnectableLayer* layer = m_Network->AddElementwiseBinaryLayer(BinaryOperation::Mul, layerName.c_str());
5243 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 0});
5244 CheckMatchingQuantization(inputTensorInfo, outputTensorInfo, layerName,
"Input 0",
"Output 0");
5247 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
5248 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[0]});
5250 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
5251 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
5254void TfLiteParserImpl::ParseSquaredDifference(
size_t subgraphIndex,
size_t operatorIndex)
5256 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
5258 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
5261 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
5264 auto layerName = fmt::format(
"SquaredDifference:{}:{}", subgraphIndex, operatorIndex);
5266 TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
5267 TensorInfo input1TensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
5269 IConnectableLayer* layer = m_Network->AddElementwiseBinaryLayer(BinaryOperation::SqDiff, layerName.c_str());
5273 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
5277 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
5280 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
5281 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
5283 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
5284 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
5287void TfLiteParserImpl::ParseElementwiseUnary(
size_t subgraphIndex,
size_t operatorIndex,
UnaryOperation unaryOperation)
5289 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
5291 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
5294 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
5298 std::string layerNameFormatted = fmt::format(layerName, subgraphIndex, operatorIndex);
5300 ElementwiseUnaryDescriptor desc;
5302 IConnectableLayer* layer = m_Network->AddElementwiseUnaryLayer(desc, layerNameFormatted.c_str());
5306 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
5310 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0});
5313 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
5314 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
5316 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
5317 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, outputTensorIndexes);
5320void TfLiteParserImpl::ParseEqual(
size_t subgraphIndex,
size_t operatorIndex)
5325void TfLiteParserImpl::ParseNotEqual(
size_t subgraphIndex,
size_t operatorIndex)
5330void TfLiteParserImpl::ParseGreater(
size_t subgraphIndex,
size_t operatorIndex)
5335void TfLiteParserImpl::ParseGreaterOrEqual(
size_t subgraphIndex,
size_t operatorIndex)
5340void TfLiteParserImpl::ParseLess(
size_t subgraphIndex,
size_t operatorIndex)
5345void TfLiteParserImpl::ParseLessOrEqual(
size_t subgraphIndex,
size_t operatorIndex)
5350void TfLiteParserImpl::ParseComparison(
size_t subgraphIndex,
size_t operatorIndex,
5353 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
5355 auto inputs =
GetInputs(m_Model, subgraphIndex, operatorIndex);
5358 auto outputs =
GetOutputs(m_Model, subgraphIndex, operatorIndex);
5362 std::string layerNameFormatted = fmt::format(layerName, subgraphIndex, operatorIndex);
5364 armnn::TensorInfo inputTensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 0);
5365 armnn::TensorInfo input1TensorInfo = InputTensorInfo(subgraphIndex, operatorIndex, 1);
5366 CheckMatchingQuantization(inputTensorInfo, input1TensorInfo, layerNameFormatted,
"Input 0",
"Input 1");
5368 ComparisonDescriptor desc;
5370 IConnectableLayer* layer = m_Network->AddComparisonLayer(desc, layerNameFormatted.c_str());
5374 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
5378 TensorInfo outputTensorInfo = OutputTensorInfoFromInputs(subgraphIndex, operatorIndex, layer, 0, {0, 1});
5381 auto inputTensorIndexes = AsUnsignedVector(
GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
5382 RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0], inputTensorIndexes[1]});
5384 auto outputTensorIndexes = AsUnsignedVector(
GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
5385 RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
5388armnn::IConnectableLayer* TfLiteParserImpl::AddReshapeLayer(armnn::IConnectableLayer* layer,
5389 unsigned int outputSlot,
5390 std::string reshapeLayerName,
5391 armnn::TensorInfo outputShape)
5393 ReshapeDescriptor desc;
5396 IConnectableLayer* reshapeLayer =
5397 m_Network->AddReshapeLayer(desc, reshapeLayerName.c_str());
5402 return reshapeLayer;
5405armnn::IConnectableLayer* TfLiteParserImpl::AddFusedActivationLayer(armnn::IConnectableLayer* prevLayer,
5406 unsigned int outputSlot,
5407 tflite::ActivationFunctionType activationType)
5409 ActivationDescriptor activationDesc;
5410 std::string layerName = prevLayer->
GetName();
5412 switch(activationType)
5414 case tflite::ActivationFunctionType_NONE:
5419 case tflite::ActivationFunctionType_RELU:
5421 activationDesc.
m_Function = ActivationFunction::ReLu;
5422 layerName +=
":RELU";
5425 case tflite::ActivationFunctionType_RELU6:
5427 activationDesc.
m_Function = ActivationFunction::BoundedReLu;
5428 activationDesc.
m_A = 6.0f;
5429 activationDesc.
m_B = 0.0f;
5430 layerName +=
":RELU6";
5433 case tflite::ActivationFunctionType_TANH:
5435 activationDesc.
m_Function = ActivationFunction::TanH;
5436 activationDesc.
m_A = 1.0f;
5437 activationDesc.
m_B = 1.0f;
5438 layerName +=
":TANH";
5443 case tflite::ActivationFunctionType_RELU_N1_TO_1:
5444 case tflite::ActivationFunctionType_SIGN_BIT:
5447 throw ParseException(
5448 fmt::format(
"TfLite parser doesn't support fused activation: "
5451 tflite::EnumNameActivationFunctionType(activationType),
5457 IConnectableLayer* activationLayer =
5458 m_Network->AddActivationLayer(activationDesc, layerName.c_str());
5460 auto & prevOutputSlot = prevLayer->
GetOutputSlot(outputSlot);
5463 return activationLayer;
5466armnn::IConnectableLayer* TfLiteParserImpl::AddFusedFloorLayer(armnn::IConnectableLayer* prevLayer,
5467 unsigned int outputSlot)
5470 auto& prevOutputSlot = prevLayer->
GetOutputSlot(outputSlot);
5473 if (dataType == DataType::Signed32)
5478 std::string layerName = prevLayer->
GetName();
5479 IConnectableLayer* floorLayer = m_Network->AddFloorLayer(layerName.c_str());
5489 if (fileName ==
nullptr)
5494 std::error_code errorCode;
5495 fs::path pathToFile(fileName);
5496 if (!fs::exists(pathToFile, errorCode))
5499 std::stringstream msg;
5500 msg <<
"Cannot find the file (" << fileName <<
") errorCode: " << errorCode
5504 if (!fs::is_regular_file(pathToFile))
5508 pathToFile.c_str()));
5511 std::ifstream file(fileName, std::ios::binary);
5512 std::string fileContent((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
5514 fileContent.size());
5519 if (binaryContent ==
nullptr)
5524 flatbuffers::Verifier verifier(binaryContent, len);
5525 if (verifier.VerifyBuffer<tflite::Model>() ==
false)
5528 fmt::format(
"Buffer doesn't conform to the expected Tensorflow Lite "
5529 "flatbuffers format. size:{} {}",
5533 return tflite::UnPackModel(binaryContent);
5537 size_t subgraphIndex,
5538 size_t operatorIndex)
5542 const auto& subgraphPtr = model->subgraphs[subgraphIndex];
5543 const auto& operatorPtr = subgraphPtr->operators[operatorIndex];
5545 size_t inputCount = operatorPtr->inputs.size();
5547 for (
size_t i = 0; i < inputCount; ++i)
5550 if (operatorPtr->inputs[i] == -1)
5557 result.push_back(subgraphPtr->tensors[inputId].get());
5564 size_t subgraphIndex,
5565 size_t operatorIndex)
5569 const auto& subgraphPtr = model->subgraphs[subgraphIndex];
5570 const auto& operatorPtr = subgraphPtr->operators[operatorIndex];
5572 size_t outputCount = operatorPtr->outputs.size();
5574 for (
size_t i = 0; i < outputCount; ++i)
5578 result[i] = subgraphPtr->tensors[outputId].get();
5584 size_t subgraphIndex)
5587 const auto& subgraphPtr = model->subgraphs[subgraphIndex];
5589 size_t inputCount = subgraphPtr->inputs.size();
5591 for (
size_t i = 0; i < inputCount; ++i)
5595 result[i] = std::make_pair(inputId, subgraphPtr->tensors[inputId].get());
5601 size_t subgraphIndex)
5604 const auto& subgraphPtr = model->subgraphs[subgraphIndex];
5606 size_t outputCount = subgraphPtr->outputs.size();
5608 for (
size_t i = 0; i < outputCount; ++i)
5611 result[i] = std::make_pair(outputId, subgraphPtr->tensors[outputId].get());
5617 size_t subgraphIndex,
5618 size_t operatorIndex)
5621 const auto& subgraphPtr = model->subgraphs[subgraphIndex];
5622 const auto& operatorPtr = subgraphPtr->operators[operatorIndex];
5623 return operatorPtr->inputs;
5627 size_t subgraphIndex,
5628 size_t operatorIndex)
5631 const auto& subgraphPtr = model->subgraphs[subgraphIndex];
5632 const auto& operatorPtr = subgraphPtr->operators[operatorIndex];
5633 return operatorPtr->outputs;
5636void TfLiteParserImpl::RegisterInputSlots(
size_t subgraphIndex,
5637 size_t operatorIndex,
5639 const std::vector<unsigned int>& tensorIndexes,
5640 unsigned int startingSlotIndex)
5642 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
5653 fmt::format(
"The number of tensor inputs ({}) does not match the number expected ({})"
5654 " for subgraph:{} operator index:{} {}",
5655 tensorIndexes.size(),
5662 for (
unsigned int index = 0; index < tensorIndexes.size() ; ++index)
5664 unsigned int tensorIndex = tensorIndexes[index];
5665 armnn::IInputSlot* slot = &(layer->
GetInputSlot(startingSlotIndex + index));
5666 RegisterConsumerOfTensor(subgraphIndex, tensorIndex, slot);
5670void TfLiteParserImpl::RegisterOutputSlots(
size_t subgraphIndex,
5671 size_t operatorIndex,
5672 IConnectableLayer* layer,
5673 const std::vector<unsigned int>& tensorIndexes)
5675 CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
5679 throw NullPointerException(fmt::format(
"Layer {} pointer is null {}",
5685 throw ParseException(
5686 fmt::format(
"The number of tensor outputs ({}) does not match the number expected ({})"
5687 " for subgraph:{} operator index:{} {}",
5688 tensorIndexes.size(),
5695 for (
unsigned int slotIndex = 0; slotIndex < layer->
GetNumOutputSlots(); ++slotIndex)
5697 unsigned int tensorIndex = tensorIndexes[slotIndex];
5698 armnn::IOutputSlot* slot = &(layer->
GetOutputSlot(slotIndex));
5699 RegisterProducerOfTensor(subgraphIndex, tensorIndex, slot);
5703void TfLiteParserImpl::SetupInputLayerTensorInfos(
size_t subgraphIndex)
5708 for (
auto const& tensorIdAndPtr : inputs)
5711 m_TensorInfos.insert({tensorIdAndPtr.first, tensorInfo});
5715void TfLiteParserImpl::SetupInputLayers(
size_t subgraphIndex)
5720 for (
auto const& tensorIdAndPtr : inputs)
5722 auto bindingId = GenerateLayerBindingId(subgraphIndex, tensorIdAndPtr.first);
5723 IConnectableLayer* layer =
5724 m_Network->AddInputLayer(bindingId, tensorIdAndPtr.second->name.c_str());
5729 RegisterOutputSlots(subgraphIndex,
5730 VIRTUAL_OPERATOR_ID,
5732 {
static_cast<uint32_t
>(tensorIdAndPtr.first) });
5736void TfLiteParserImpl::SetupOutputLayers(
size_t subgraphIndex)
5741 for (
auto const& tensorIdAndPtr : outputs)
5743 auto bindingId = GenerateLayerBindingId(subgraphIndex, tensorIdAndPtr.first);
5744 IConnectableLayer* layer =
5745 m_Network->AddOutputLayer(bindingId, tensorIdAndPtr.second->name.c_str());
5747 RegisterInputSlots(subgraphIndex,
5748 VIRTUAL_OPERATOR_ID,
5750 {
static_cast<uint32_t
>(tensorIdAndPtr.first) });
5754void TfLiteParserImpl::SetupConstantLayerTensorInfos(
size_t subgraph)
5758 const auto & subgraphPtr = m_Model->subgraphs[subgraph];
5759 for (
unsigned int subgraphIndex = 0; subgraphIndex < m_SubgraphConnections.size(); ++subgraphIndex)
5761 for (
unsigned int tensorIndex = 0; tensorIndex < m_SubgraphConnections[subgraphIndex].size(); ++tensorIndex)
5763 if (m_SubgraphConnections[subgraphIndex][tensorIndex].outputSlot ==
nullptr &&
5764 m_SubgraphConnections[subgraphIndex][tensorIndex].inputSlots.size() > 0)
5766 TensorRawPtr tensorPtr = subgraphPtr->tensors[tensorIndex].get();
5768 armnn::TensorInfo tensorInfo =
ToTensorInfo(tensorPtr);
5770 m_TensorInfos.insert({tensorIndex, tensorInfo});
5776void TfLiteParserImpl::SetupConstantLayers(
size_t subgraph)
5780 const auto & subgraphPtr = m_Model->subgraphs[subgraph];
5781 for (
unsigned int subgraphIndex = 0; subgraphIndex < m_SubgraphConnections.size(); ++subgraphIndex)
5783 for (
unsigned int tensorIndex = 0; tensorIndex < m_SubgraphConnections[subgraphIndex].size(); ++tensorIndex)
5785 if (m_SubgraphConnections[subgraphIndex][tensorIndex].outputSlot ==
nullptr &&
5786 m_SubgraphConnections[subgraphIndex][tensorIndex].inputSlots.size() > 0)
5788 TensorRawPtr tensorPtr = subgraphPtr->tensors[tensorIndex].get();
5790 if (IsConstTensor(tensorPtr))
5792 armnn::TensorInfo tensorInfo =
ToTensorInfo(tensorPtr);
5795 if (std::find(m_ConstantsToDequantize.begin(), m_ConstantsToDequantize.end(), tensorPtr->buffer)
5796 != m_ConstantsToDequantize.end())
5798 dataType = DataType::Float32;
5800 auto tensorAndData = CreateConstTensorNonPermuted(tensorPtr, tensorInfo, dataType);
5802 std::string layerName = fmt::format(
"Constant:{}", tensorPtr->name);
5803 IConnectableLayer *layer = m_Network->AddConstantLayer(tensorAndData.first, layerName.c_str());
5806 RegisterOutputSlots(subgraphIndex,
5807 VIRTUAL_OPERATOR_ID,
5811 else if (ShouldConstantTensorBeCreated(tensorIndex))
5813 armnn::TensorInfo tensorInfo =
ToTensorInfo(tensorPtr);
5816 if (std::find(m_ConstantsToDequantize.begin(), m_ConstantsToDequantize.end(), tensorPtr->buffer)
5817 != m_ConstantsToDequantize.end())
5819 dataType = DataType::Float32;
5825 auto tensorAndData = ConstTensor(tensorInfo, std::vector<uint8_t>(tensorInfo.
GetNumBytes()));
5827 std::string layerName = fmt::format(
"Constant:{}", tensorPtr->name);
5828 IConnectableLayer* layer = m_Network->AddConstantLayer(tensorAndData, layerName.c_str());
5831 RegisterOutputSlots(subgraphIndex,
5832 VIRTUAL_OPERATOR_ID,
5838 throw ParseException(
5839 fmt::format(
"Invalid Tensor: Tensor should be constant. {}",
5851 return model->buffers[bufferIndex].get();
5855std::pair<armnn::ConstTensor, TfLiteParserImpl::SupportedDataStorage>
5864 auto constData = CreateConstTensorImpl<T>(bufferPtr,
5868 TfLiteParserImpl::SupportedDataStorage storage(std::move(constData.second));
5869 return std::make_pair(constData.first, std::move(storage));
5872bool TfLiteParserImpl::ShouldConstantTensorBeCreated(
unsigned int tensorIndex)
5875 return (std::find(m_ConstantsToBeCreated.begin(), m_ConstantsToBeCreated.end(), tensorIndex)
5876 != m_ConstantsToBeCreated.end());
5879bool TfLiteParserImpl::IsConstTensor(TensorRawPtr tensorPtr)
5882 bool isConst =
true;
5884 auto buffer =
GetBuffer(m_Model, tensorPtr->buffer);
5885 if (buffer->data.size() == 0)
5893std::pair<armnn::ConstTensor, TfLiteParserImpl::SupportedDataStorage>
5894TfLiteParserImpl::CreateConstTensorPermuted(TensorRawPtr tensorPtr,
5895 armnn::TensorInfo& tensorInfo,
5896 armnn::Optional<armnn::PermutationVector&> permutationVector)
5899 auto bufferPtr =
GetBuffer(m_Model, tensorPtr->buffer);
5908 return CreateConstTensorAndStoreData<float>(bufferPtr,
5913 return CreateConstTensorAndStoreData<uint8_t>(bufferPtr,
5918 return CreateConstTensorAndStoreData<int8_t>(bufferPtr,
5923 return CreateConstTensorAndStoreData<int8_t>(bufferPtr,
5928 return CreateConstTensorAndStoreData<int32_t>(bufferPtr,
5934 std::stringstream errString;
5935 errString <<
"Unexpected datatype when creating const tensor: "
5937 <<
" shape:" << tensorInfo.
GetShape()
5939 throw ParseException(errString.str());
5944armnn::ConstTensor TfLiteParserImpl::CreateConstTensorNonPermuted(TensorRawPtr tensorPtr,
5945 armnn::TensorInfo& tensorInfo)
5948 auto bufferPtr =
GetBuffer(m_Model, tensorPtr->buffer);
5954 return ConstTensor(tensorInfo, bufferPtr->data.data());
5957std::pair<armnn::ConstTensor, std::unique_ptr<float[]>>
5958TfLiteParserImpl::CreateConstTensorNonPermuted(TensorRawPtr tensorPtr,
5959 armnn::TensorInfo& tensorInfo,
5963 auto bufferPtr =
GetBuffer(m_Model, tensorPtr->buffer);
5969 if (inputDataType == DataType::Float32 && tensorInfo.
GetDataType() != DataType::Float32)
5973 TensorInfo constTensorInfo(tensorInfo.
GetShape(), DataType::Float32, 0.0f, 0,
true);
5975 return std::make_pair(ConstTensor(constTensorInfo, data.get()), std::move(data));
5977 catch (InvalidArgumentException&)
5979 throw ParseException(
5980 fmt::format(
"Unsupported input/weights combination: Input {} not supported with Weights {}",
5988 return std::make_pair(ConstTensor(tensorInfo, bufferPtr->data.data()), std::unique_ptr<
float[]>());
5992std::pair<armnn::ConstTensor*, std::unique_ptr<float[]>>
5993TfLiteParserImpl::CreateConstTensorPtr(TensorRawPtr tensorPtr, armnn::TensorInfo& inputTensorInfo)
5996 armnn::TensorInfo tensorInfo =
ToTensorInfo(tensorPtr);
5997 auto bufferPtr =
GetBuffer(m_Model, tensorPtr->buffer);
6007 TensorInfo constTensorInfo(tensorInfo.
GetShape(), DataType::Float32, 0.0f, 0,
true);
6009 return std::make_pair(
new ConstTensor(constTensorInfo, data.get()), std::move(data));
6011 catch (InvalidArgumentException&)
6013 throw ParseException(
6014 fmt::format(
"Unsupported input/weights combination: Input {} not supported with Weights {}",
6022 return std::make_pair(
new ConstTensor(tensorInfo, bufferPtr->data.data()), std::unique_ptr<
float[]>());
6027 const std::string& name)
const
6031 for (
auto const& input : inputs)
6033 if (input.second->name == name)
6035 auto bindingId = GenerateLayerBindingId(subgraphId, input.first);
6036 auto inputTensorInfo = ToTensorInfo(input.second);
6039 return std::make_pair(bindingId, inputTensorInfo);
6043 std::stringstream bindings;
6044 for (
auto const& input : inputs)
6046 bindings <<
"'" << input.second->name <<
"' ";
6050 fmt::format(
"No input binding found for subgraph:{} and name:{}. "
6051 "Possible inputs are: [{}] {}",
6059 const std::string& name)
const
6063 for (
unsigned int i = 0; i < outputs.size(); ++i)
6065 auto const output = outputs[i];
6066 if (output.second->name == name)
6068 auto bindingId = GenerateLayerBindingId(subgraphId, output.first);
6069 std::vector<unsigned int> shape = m_OverriddenOutputShapes.size() > 0 ?
6070 m_OverriddenOutputShapes[i] : AsUnsignedVector(output.second->shape);
6071 return std::make_pair(bindingId, ToTensorInfo(output.second, shape));
6075 std::stringstream bindings;
6076 for (
auto const& output : outputs)
6078 bindings <<
"'" << output.second->name <<
"' ";
6082 fmt::format(
"No output binding found for subgraph:{} and name:{}. "
6083 "Possible outputs are: [{}] {}",
6092 return m_Model->subgraphs.size();
6099 std::vector<std::string> result;
6100 result.reserve(inputs.size());
6101 for (
auto const& input : inputs)
6103 result.push_back(input.second->name);
6112 std::vector<std::string> result;
6113 result.reserve(outputs.size());
6114 for (
auto const& output : outputs)
6116 result.push_back(output.second->name);
6126TfLiteParserImpl::SupportedDataStorage::SupportedDataStorage(std::unique_ptr<
float[]>&& data)
6127: m_FloatData(
std::move(data))
6128, m_Uint8Data(nullptr)
6129, m_Int8Data(nullptr)
6130, m_Int32Data(nullptr)
6134TfLiteParserImpl::SupportedDataStorage::SupportedDataStorage(std::unique_ptr<uint8_t[]>&& data)
6135: m_FloatData(nullptr)
6136, m_Uint8Data(
std::move(data))
6137, m_Int8Data(nullptr)
6138, m_Int32Data(nullptr)
6142TfLiteParserImpl::SupportedDataStorage::SupportedDataStorage(std::unique_ptr<int8_t[]>&& data)
6143: m_FloatData(nullptr)
6144, m_Uint8Data(nullptr)
6145, m_Int8Data(std::move(data))
6146, m_Int32Data(nullptr)
6150TfLiteParserImpl::SupportedDataStorage::SupportedDataStorage(std::unique_ptr<int32_t[]>&& data)
6151: m_FloatData(nullptr)
6152, m_Uint8Data(nullptr)
6153, m_Int8Data(nullptr)
6154, m_Int32Data(std::move(data))
6158void TfLiteParserImpl::ValidateBuffer(BufferRawPtr bufferPtr,
6159 const armnn::TensorInfo& tensorInfo,
6160 const std::string& bufferName)
6162 if (bufferPtr ==
nullptr)
6164 throw ParseException(bufferName +
" buffer pointer is null.");
6167 if (bufferPtr->data.empty())
6169 throw ParseException(bufferName +
" buffer data is empty.");
6173 if (bufferPtr->data.size() < requiredBytes)
6175 throw ParseException(fmt::format(bufferName +
" buffer too small. Expected at least {} bytes, got {}.",
6176 requiredBytes, bufferPtr->data.size()));
#define ARMNN_ASSERT(COND)
#define CHECK_TENSOR_PTR(TENSOR_PTR)
#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_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
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 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 GetNumInputSlots() const =0
Returns the number of connectable input slots.
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.
static INetworkPtr Create(const NetworkOptions &networkOptions={})
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
virtual int Connect(IInputSlot &destination)=0
virtual const IConnectableLayer & GetOwningIConnectableLayer() const =0
virtual const TensorInfo & GetTensorInfo() const =0
bool has_value() const noexcept
float GetQuantizationScale() const
const TensorShape & GetShape() 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
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.
size_t GetSubgraphCount() const
Return the number of subgraphs in the parsed model.
static void Destroy(ITfLiteParser *parser)
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...
armnn::INetworkPtr CreateNetworkFromBinaryFile(const char *graphFile)
Create the network from a flatbuffers binary file on disk.
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.
static ITfLiteParserPtr Create(const armnn::Optional< TfLiteParserOptions > &options=armnn::EmptyOptional())
armnn::INetworkPtr CreateNetworkFromBinary(const std::vector< uint8_t > &binaryContent)
Create the network from a flatbuffers binary.
static ITfLiteParser * CreateRaw(const armnn::Optional< TfLiteParserOptions > &options=armnn::EmptyOptional())
std::vector< std::string > GetSubgraphInputTensorNames(size_t subgraphId) const
Return the input tensor names for a given subgraph.
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
TfLiteParserImpl(const armnn::Optional< ITfLiteParser::TfLiteParserOptions > &options=armnn::EmptyOptional())
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::Pooling2dDescriptor * Pooling2dDescriptor
bool CheckShape(const armnn::TensorShape &actual, const std::vector< uint32_t > &expected)
armnn::TensorInfo ToTensorInfo(TensorRawPtr tensorPtr)
Copyright (c) 2021 ARM Limited and Contributors.
constexpr char const * GetComparisonOperationAsCString(ComparisonOperation operation)
constexpr char const * GetUnaryOperationAsCString(UnaryOperation operation)
constexpr const char * GetDataTypeName(DataType dataType)
std::vector< BackendOptions > NetworkOptions
ViewsDescriptor SplitterDescriptor
SpaceToDepthDescriptor DepthToSpaceDescriptor
A DepthToSpaceDescriptor for the DepthToSpaceLayer.
std::enable_if_t< std::is_unsigned< Source >::value &&std::is_unsigned< Dest >::value, Dest > numeric_cast(Source source)
int LayerBindingId
Type of identifiers for bindable layers (inputs, outputs).
constexpr unsigned int MaxNumOfTensorDimensions
SoftmaxDescriptor LogSoftmaxDescriptor
A LogSoftmaxDescriptor for the LogSoftmaxLayer.
LstmDescriptor UnidirectionalSequenceLstmDescriptor
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
@ LocalBrightness
Krichevsky 2012: Local Brightness Normalization.
void IgnoreUnused(Ts &&...)
std::pair< armnn::ConstTensor, std::unique_ptr< T[]> > CreateConstTensorImpl(const T *bufferPtr, armnn::TensorInfo &tensorInfo, const armnn::Optional< armnn::PermutationVector & > permutationVector)
armnn::BindingPointInfo BindingPointInfo
unsigned int ComputeWrappedIndex(int idx, unsigned int numDimsIn)
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)
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,...
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.
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
ComparisonOperation m_Operation
Specifies the comparison operation to execute.
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.
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.
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.
UnaryOperation m_Operation
Specifies the elementwiseUnary operation to execute.
bool m_TransposeWeightMatrix
Enable/disable transpose weight matrix.
bool m_ConstantWeights
Enable/disable constant weights and biases.
bool m_BiasEnabled
Enable/disable bias.
int32_t m_Axis
The axis in params to gather indices from.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
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.
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.
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).
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.
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).
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.
TensorShape m_TargetShape
Target shape value.
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.
float m_Beta
Exponentiation value.
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,...
unsigned int m_BlockSize
Scalar specifying the input block size. It must be >= 1.
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.
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.
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.