blob: 9aa316d8c3e5db26dce96cd97c253f1c5d76be7e [file] [log] [blame]
Sadik Armagan62483be2020-10-23 17:14:43 +01001//
Ryan OShea4c231de2023-01-17 15:19:20 +00002// Copyright © 2022-2023 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>
James Wardf89964e2020-11-09 11:57:47 +000014#include <tensorflow/lite/kernels/internal/tensor_ctypes.h>
Sadik Armagan62483be2020-10-23 17:14:43 +010015
16namespace armnnDelegate
17{
18
19TfLiteStatus VisitTransposeOperator(DelegateData& delegateData,
20 TfLiteContext* tfLiteContext,
21 TfLiteNode* tfLiteNode,
22 int nodeIndex,
James Wardf89964e2020-11-09 11:57:47 +000023 int32_t tfliteTransposeOperatorCode)
Sadik Armagan62483be2020-10-23 17:14:43 +010024{
James Wardf89964e2020-11-09 11:57:47 +000025 TF_LITE_ENSURE_STATUS(ValidateNumInputs(tfLiteContext, tfLiteNode, 2, nodeIndex));
26 TF_LITE_ENSURE_STATUS(ValidateNumOutputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
Sadik Armagan62483be2020-10-23 17:14:43 +010027
James Wardf89964e2020-11-09 11:57:47 +000028 const TfLiteTensor *tfLiteTensors = tfLiteContext->tensors;
29 const TfLiteTensor& tfLiteInputTensor0 = tfLiteTensors[tfLiteNode->inputs->data[0]];
30 if (IsDynamicTensor(tfLiteInputTensor0))
31 {
32 TF_LITE_MAYBE_KERNEL_LOG(tfLiteContext,
33 "TfLiteArmnnDelegate: Dynamic input tensors are not supported in "
34 "operator #%d node #%d: ",
35 tfliteTransposeOperatorCode, nodeIndex);
Finn Williams6f9f9902020-11-13 13:23:15 +000036
James Wardf89964e2020-11-09 11:57:47 +000037 return kTfLiteError;
38 }
39
40 const TfLiteTensor& tfLiteInputTensor1 = tfLiteTensors[tfLiteNode->inputs->data[1]];
41 if (IsDynamicTensor(tfLiteInputTensor1))
42 {
43 TF_LITE_MAYBE_KERNEL_LOG(tfLiteContext,
44 "TfLiteArmnnDelegate: Dynamic input tensors are not supported in "
45 "operator #%d node #%d: ",
46 tfliteTransposeOperatorCode, nodeIndex);
47 return kTfLiteError;
48 }
49
50 const TfLiteTensor& tfLiteOutputTensor = tfLiteTensors[tfLiteNode->outputs->data[0]];
51 if (IsDynamicTensor(tfLiteOutputTensor))
52 {
53 TF_LITE_MAYBE_KERNEL_LOG(tfLiteContext,
54 "TfLiteArmnnDelegate: Dynamic output tensors are not supported in "
55 "operator #%d node #%d: ",
56 tfliteTransposeOperatorCode, nodeIndex);
57 return kTfLiteError;
58 }
59
60 const armnn::TensorInfo& inputTensorInfo0 = GetTensorInfoForTfLiteTensor(tfLiteInputTensor0);
Sadik Armagan90a119b2022-08-05 16:12:49 +010061 const armnn::TensorInfo& outputTensorInfo = GetTensorInfoForTfLiteTensor(tfLiteOutputTensor, true);
James Wardf89964e2020-11-09 11:57:47 +000062
63 auto* permTensorDataPtr = tflite::GetTensorData<int32_t>(&tfLiteInputTensor1);
James Ward7c0e3fd2020-11-16 18:46:12 +000064 unsigned int numEl = tfLiteInputTensor1.dims->data[0];
James Wardf89964e2020-11-09 11:57:47 +000065
Ryan OSheac229b3f2023-06-27 22:34:54 +010066 if (numEl > static_cast<int>(armnn::MaxNumOfTensorDimensions))
67 {
68 return kTfLiteError;
69 }
70
71 if (tfLiteInputTensor1.dims->size != 1)
72 {
73 return kTfLiteError;
74 }
James Wardf89964e2020-11-09 11:57:47 +000075
76 armnn::TransposeDescriptor descriptor(armnn::PermutationVector(
77 reinterpret_cast<const armnn::PermutationVector::ValueType *> (permTensorDataPtr),
Finn Williams6f9f9902020-11-13 13:23:15 +000078 static_cast<armnn::PermutationVector::SizeType>(numEl)));
James Wardf89964e2020-11-09 11:57:47 +000079
80 bool isSupported = false;
Cathal Corbett53837672022-09-01 11:34:37 +010081 armnn::BackendId setBackend;
James Wardf89964e2020-11-09 11:57:47 +000082 auto validateFunc = [&](const armnn::TensorInfo& outputTensorInfo, bool& isSupported)
83 {
Sadik Armaganbfa767c2022-02-09 14:58:03 +000084 FORWARD_LAYER_SUPPORT_FUNC("TRANSPOSE",
James Wardf89964e2020-11-09 11:57:47 +000085 tfLiteContext,
86 IsTransposeSupported,
87 delegateData.m_Backends,
88 isSupported,
Cathal Corbett53837672022-09-01 11:34:37 +010089 setBackend,
James Wardf89964e2020-11-09 11:57:47 +000090 inputTensorInfo0,
91 outputTensorInfo,
92 descriptor);
93 };
94
95 if (!delegateData.m_Network)
96 {
97 validateFunc(outputTensorInfo, isSupported);
98 return isSupported ? kTfLiteOk : kTfLiteError;
99 }
100
Mike Kelly07169c82023-08-02 13:23:09 +0100101 auto layerName = GetLayerName(armnn::LayerType::Transpose, nodeIndex);
102 armnn::IConnectableLayer* transposeLayer = delegateData.m_Network->AddTransposeLayer(descriptor, layerName.c_str());
Cathal Corbett53837672022-09-01 11:34:37 +0100103 transposeLayer->SetBackendId(setBackend);
James Wardf89964e2020-11-09 11:57:47 +0000104 ARMNN_ASSERT(transposeLayer != nullptr);
Ryan OSheac229b3f2023-06-27 22:34:54 +0100105
106 // permutation vector given to descriptor object
107 if (transposeLayer->GetNumInputSlots() != 1)
108 {
109 return kTfLiteError;
110 }
James Wardf89964e2020-11-09 11:57:47 +0000111
112 armnn::IOutputSlot& outputSlot = transposeLayer->GetOutputSlot(0);
113 outputSlot.SetTensorInfo(outputTensorInfo);
114
Ryan OShea4c231de2023-01-17 15:19:20 +0000115 // try to connect the Constant Inputs if there are any
Mike Kelly07169c82023-08-02 13:23:09 +0100116 if (ProcessInputs(transposeLayer, delegateData, tfLiteContext, tfLiteNode, nodeIndex) != kTfLiteOk)
Ryan OShea4c231de2023-01-17 15:19:20 +0000117 {
118 return kTfLiteError;
119 }
120
James Wardf89964e2020-11-09 11:57:47 +0000121 return Connect(transposeLayer, tfLiteNode, delegateData);
122}
Sadik Armagan62483be2020-10-23 17:14:43 +0100123} // namespace armnnDelegate