| 11 | { |
| 12 | |
| 13 | TfLiteStatus VisitStridedSliceOperator(DelegateData& delegateData, |
| 14 | TfLiteOpaqueContext* tfLiteContext, |
| 15 | TfLiteOpaqueNode* tfLiteNode, |
| 16 | int nodeIndex, |
| 17 | int32_t tfLiteStridedSliceOperatorCode) |
| 18 | { |
| 19 | TF_LITE_ENSURE_STATUS(ValidateNumInputs(tfLiteContext, tfLiteNode, 4, nodeIndex)); |
| 20 | TF_LITE_ENSURE_STATUS(ValidateNumOutputs(tfLiteContext, tfLiteNode, 1, nodeIndex)); |
| 21 | |
| 22 | // Read inputs [input, begin, end, strides] |
| 23 | // Gather input indices and use to get input tensor. |
| 24 | const int* inputTensors; |
| 25 | int numInputs; |
| 26 | if (TfLiteOpaqueNodeInputs(tfLiteNode, &inputTensors, &numInputs) != kTfLiteOk) |
| 27 | { |
| 28 | TF_LITE_OPAQUE_MAYBE_KERNEL_LOG( |
| 29 | tfLiteContext, |
| 30 | "TfLiteArmnnOpaqueDelegate: Unable to gather input tensor indices from node #%d: ", |
| 31 | nodeIndex); |
| 32 | return kTfLiteError; |
| 33 | } |
| 34 | |
| 35 | std::vector<const TfLiteOpaqueTensor*> tfLiteInputTensors; |
| 36 | tfLiteInputTensors.reserve(numInputs); |
| 37 | for (int i = 0; i < numInputs; i++) |
| 38 | { |
| 39 | const TfLiteOpaqueTensor* inputTensor = TfLiteOpaqueContextGetOpaqueTensor(tfLiteContext, inputTensors[i]); |
| 40 | tfLiteInputTensors.push_back(inputTensor); |
| 41 | if (!IsValid(tfLiteContext, inputTensor, tfLiteStridedSliceOperatorCode, nodeIndex)) |
| 42 | { |
| 43 | return kTfLiteError; |
| 44 | } |
| 45 | // Checking for unsupported non-const non-network input tensors |
| 46 | // Index 0 is the input, index 1-3 should be constant |
| 47 | if(i > 0 && TfLiteOpaqueTensorGetAllocationType(inputTensor) != kTfLiteMmapRo) |
| 48 | { |
| 49 | TF_LITE_OPAQUE_MAYBE_KERNEL_LOG( |
| 50 | tfLiteContext, |
| 51 | "TfLiteArmnnOpaqueDelegate: Unsupported constant data input through non-const tensor " |
| 52 | "in operator #%d node #%d", |
| 53 | tfLiteStridedSliceOperatorCode, nodeIndex); |
| 54 | return kTfLiteError; |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | const armnn::TensorInfo& inputTensorInfo = GetTensorInfoForTfLiteOpaqueTensor(tfLiteInputTensors[0]); |
| 59 | |
| 60 | // We save the begin, end and strides tensors in our descriptor. Therefore we have to read those values from inputs |
| 61 | unsigned int inputRank = inputTensorInfo.GetNumDimensions(); |
| 62 | |
| 63 | // Input tensors of rank greater than 4 are unsupported - delegate back to TFLite runtime |
| 64 | if(inputRank > 4) |
| 65 | { |
| 66 | TF_LITE_OPAQUE_MAYBE_KERNEL_LOG( |
| 67 | tfLiteContext, |
| 68 | "TfLitearmnnOpaqueDelegate: Tensors of rank greater than 4 are unsupported" |
| 69 | " in the StridedSlice operator. Operator: #%d node #%d: ", |
| 70 | tfLiteStridedSliceOperatorCode, nodeIndex); |
no test coverage detected