blob: d5712aefad06660868118b75139816b4315230fe [file] [log] [blame]
Sadik Armagan62483be2020-10-23 17:14:43 +01001//
Cathal Corbett839b9322022-11-18 08:52:18 +00002// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
Sadik Armagan62483be2020-10-23 17:14:43 +01003// SPDX-License-Identifier: MIT
4//
5
6#pragma once
7
Finn Williams6f9f9902020-11-13 13:23:15 +00008#include <armnn/utility/IgnoreUnused.hpp>
9
Sadik Armagan62483be2020-10-23 17:14:43 +010010#include <tensorflow/lite/builtin_ops.h>
11#include <tensorflow/lite/c/builtin_op_data.h>
12#include <tensorflow/lite/c/common.h>
13#include <tensorflow/lite/minimal_logging.h>
14
15namespace armnnDelegate
16{
17
18TfLiteStatus VisitSliceOperator(DelegateData& delegateData,
19 TfLiteContext* tfLiteContext,
20 TfLiteNode* tfLiteNode,
21 int nodeIndex,
22 int32_t sliceOperatorCode)
23{
Cathal Corbett839b9322022-11-18 08:52:18 +000024 TF_LITE_ENSURE_STATUS(ValidateNumInputs(tfLiteContext, tfLiteNode, 3, nodeIndex));
Jan Eilers2ffddda2021-02-03 09:14:30 +000025 TF_LITE_ENSURE_STATUS(ValidateNumOutputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
Finn Williams6f9f9902020-11-13 13:23:15 +000026
Cathal Corbett839b9322022-11-18 08:52:18 +000027 // Read inputs [input, begin, size]
Jan Eilers2ffddda2021-02-03 09:14:30 +000028 int numInputs = tfLiteNode->inputs->size;
29 std::vector<const TfLiteTensor*> tfLiteInputs;
30 tfLiteInputs.reserve(numInputs);
31 const TfLiteTensor* tfLiteTensors = tfLiteContext->tensors;
32 for (int i = 0; i < numInputs; i++)
33 {
34 const TfLiteTensor* inputTensor = &tfLiteTensors[tfLiteNode->inputs->data[i]];
35 tfLiteInputs.push_back(inputTensor);
36 if (!IsValid(tfLiteContext, *inputTensor, sliceOperatorCode, nodeIndex))
37 {
38 return kTfLiteError;
39 }
40 }
41
Cathal Corbett839b9322022-11-18 08:52:18 +000042 // We save the begin and size tensors in our descriptor. Therefore we have to read those values from inputs
Jan Eilers2ffddda2021-02-03 09:14:30 +000043 int inputRank = tfLiteInputs[0]->dims->size;
Cathal Corbett839b9322022-11-18 08:52:18 +000044 auto ReadInt32Input = [&](int inputIndex, std::vector<uint32_t>& outputData) -> TfLiteStatus
Jan Eilers2ffddda2021-02-03 09:14:30 +000045 {
46 if (tfLiteInputs[inputIndex]->type != kTfLiteInt32)
47 {
48 TF_LITE_MAYBE_KERNEL_LOG(
49 tfLiteContext,
Cathal Corbett839b9322022-11-18 08:52:18 +000050 "TfLiteArmnnDelegate: The Begin- and Size-Tensors of the Slice operation need to "
Jan Eilers2ffddda2021-02-03 09:14:30 +000051 "be of type int32. Operator: #%d node #%d: ",
52 sliceOperatorCode, nodeIndex);
53 return kTfLiteError;
54 }
55 int rank = tfLiteInputs[inputIndex]->dims->size;
56 if (rank != 1)
57 {
58 TF_LITE_MAYBE_KERNEL_LOG(
59 tfLiteContext,
Cathal Corbett839b9322022-11-18 08:52:18 +000060 "TfLiteArmnnDelegate: The Begin- and Size-Tensors of the Slice operation need to "
Jan Eilers2ffddda2021-02-03 09:14:30 +000061 "be a 1D-Tensor. Operator: #%d node #%d: ",
62 sliceOperatorCode, nodeIndex);
63 return kTfLiteError;
64 }
65 int numValues = tfLiteInputs[inputIndex]->dims->data[0];
66 if (numValues != inputRank)
67 {
68 TF_LITE_MAYBE_KERNEL_LOG(
69 tfLiteContext,
Cathal Corbett839b9322022-11-18 08:52:18 +000070 "TfLiteArmnnDelegate: The number of values in the Begin- and Size-Tensors of the "
71 "Slice operation need to be equal to the rank of the Input-Tensor. Operator: #%d node #%d: ",
Jan Eilers2ffddda2021-02-03 09:14:30 +000072 sliceOperatorCode, nodeIndex);
73 return kTfLiteError;
74 }
75 // return tensor data
Cathal Corbett839b9322022-11-18 08:52:18 +000076 auto* tensorDataPtr = tflite::GetTensorData<uint32_t>(tfLiteInputs[inputIndex]);
Jan Eilers2ffddda2021-02-03 09:14:30 +000077 outputData.assign(tensorDataPtr, tensorDataPtr+numValues);
78 return kTfLiteOk;
79 };
80
Cathal Corbett839b9322022-11-18 08:52:18 +000081 std::vector<uint32_t> begin;
82 if (ReadInt32Input(1, begin) != kTfLiteOk)
Jan Eilers2ffddda2021-02-03 09:14:30 +000083 return kTfLiteError;
Cathal Corbett839b9322022-11-18 08:52:18 +000084 std::vector<uint32_t> size;
85 if (ReadInt32Input(2, size) != kTfLiteOk)
Jan Eilers2ffddda2021-02-03 09:14:30 +000086 return kTfLiteError;
Jan Eilers2ffddda2021-02-03 09:14:30 +000087
88 // Write all data to the descriptor
Cathal Corbett839b9322022-11-18 08:52:18 +000089 armnn::SliceDescriptor descriptor(begin, size);
Jan Eilers2ffddda2021-02-03 09:14:30 +000090
91 // Validate output
92 const TfLiteTensor& tfLiteOutputTensor = tfLiteTensors[tfLiteNode->outputs->data[0]];
93 if (!IsValid(tfLiteContext, tfLiteOutputTensor, sliceOperatorCode, nodeIndex))
94 {
95 return kTfLiteError;
96 }
97
98 const armnn::TensorInfo& inputTensorInfo = GetTensorInfoForTfLiteTensor(*tfLiteInputs[0]);
Sadik Armagan90a119b2022-08-05 16:12:49 +010099 const armnn::TensorInfo& outputTensorInfo = GetTensorInfoForTfLiteTensor(tfLiteOutputTensor, true);
Jan Eilers2ffddda2021-02-03 09:14:30 +0000100
101 bool isSupported = false;
Cathal Corbett53837672022-09-01 11:34:37 +0100102 armnn::BackendId setBackend;
Jan Eilers2ffddda2021-02-03 09:14:30 +0000103 auto validateFunc = [&](const armnn::TensorInfo& outInfo, bool& isSupported)
104 {
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000105 FORWARD_LAYER_SUPPORT_FUNC("SLICE",
Jan Eilers2ffddda2021-02-03 09:14:30 +0000106 tfLiteContext,
Cathal Corbett839b9322022-11-18 08:52:18 +0000107 IsSliceSupported,
Jan Eilers2ffddda2021-02-03 09:14:30 +0000108 delegateData.m_Backends,
109 isSupported,
Cathal Corbett53837672022-09-01 11:34:37 +0100110 setBackend,
Jan Eilers2ffddda2021-02-03 09:14:30 +0000111 inputTensorInfo,
112 outInfo,
113 descriptor);
114 };
115
116 if (!delegateData.m_Network)
117 {
118 validateFunc(outputTensorInfo, isSupported);
119 return isSupported ? kTfLiteOk : kTfLiteError;
120 }
121
Cathal Corbett53837672022-09-01 11:34:37 +0100122 // Add a Slice layer
Cathal Corbett839b9322022-11-18 08:52:18 +0000123 armnn::IConnectableLayer* layer = delegateData.m_Network->AddSliceLayer(descriptor);
Cathal Corbett53837672022-09-01 11:34:37 +0100124 layer->SetBackendId(setBackend);
Jan Eilers2ffddda2021-02-03 09:14:30 +0000125 ARMNN_ASSERT(layer != nullptr);
126
127 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
128 outputSlot.SetTensorInfo(outputTensorInfo);
129
130 // Connect
131 return Connect(layer, tfLiteNode, delegateData);
Sadik Armagan62483be2020-10-23 17:14:43 +0100132}
133
134} // namespace armnnDelegate
Cathal Corbett53837672022-09-01 11:34:37 +0100135