blob: df848469b17fda23386ad97396df42a0d4278602 [file] [log] [blame]
Francis Murtaghc4fb0dd2023-03-16 17:01:56 +00001//
2// Copyright © 2023 Arm Ltd and Contributors. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
Teresa Charlinf69ae562023-04-27 14:42:23 +01005
6#pragma once
7
8#include "OpaqueDelegateUtils.hpp"
9
10namespace armnnOpaqueDelegate
11{
12
13std::string GetLayerName(armnn::UnaryOperation unaryOperation)
14{
15 std::string layerName = "ELEMENTWISE_UNARY";
16 switch (unaryOperation)
17 {
18 case armnn::UnaryOperation::Abs:
19 layerName += " ABS";
20 break;
21 case armnn::UnaryOperation::Ceil:
22 layerName += " CEIL";
23 break;
24 case armnn::UnaryOperation::Exp:
25 layerName += " EXP";
26 break;
27 case armnn::UnaryOperation::Log:
28 layerName += " LOG";
29 break;
30 case armnn::UnaryOperation::LogicalNot:
31 layerName += " LOGICALNOT";
32 break;
33 case armnn::UnaryOperation::Neg:
34 layerName += " NEG";
35 break;
36 case armnn::UnaryOperation::Rsqrt:
37 layerName += " RSQRT";
38 break;
39 case armnn::UnaryOperation::Sin:
40 layerName += " SIN";
41 break;
42 case armnn::UnaryOperation::Sqrt:
43 layerName += " SQRT";
44 break;
45 default:
46 layerName += " UNKNOWN";
47 }
48 return layerName;
49}
50
51TfLiteStatus VisitElementwiseUnaryOperator(DelegateData& delegateData,
52 TfLiteOpaqueContext* tfLiteContext,
53 TfLiteOpaqueNode* tfLiteNode,
54 int nodeIndex,
55 int32_t tfLiteElementWiseUnaryOperatorCode,
56 armnn::UnaryOperation unaryOperation)
57{
58 TF_LITE_ENSURE_STATUS(ValidateNumInputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
59 TF_LITE_ENSURE_STATUS(ValidateNumOutputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
60
61 // Gather input indices and use to get input tensor.
62 int numInputs = 0;
63 const int* inputTensors;
64 if (TfLiteOpaqueNodeInputs(tfLiteNode, &inputTensors, &numInputs) != kTfLiteOk)
65 {
66 TF_LITE_OPAQUE_MAYBE_KERNEL_LOG(
67 tfLiteContext,
68 "TfLiteArmnnOpaqueDelegate: Unable to gather input tensor indices from node #%d: ",
69 nodeIndex);
70 return kTfLiteError;
71 }
72 // Use input indices to get input tensor.
73 const TfLiteOpaqueTensor* tfLiteInputTensor = TfLiteOpaqueContextGetOpaqueTensor(tfLiteContext, inputTensors[0]);
74 if (!IsValid(tfLiteContext, tfLiteInputTensor, tfLiteElementWiseUnaryOperatorCode, nodeIndex))
75 {
76 return kTfLiteError;
77 }
78
79 // Gather output indices and use to get output tensor.
80 int numOutputs = 0;
81 const int* outputTensors;
82 if (TfLiteOpaqueNodeOutputs(tfLiteNode, &outputTensors, &numOutputs) != kTfLiteOk)
83 {
84 TF_LITE_OPAQUE_MAYBE_KERNEL_LOG(
85 tfLiteContext,
86 "TfLiteArmnnOpaqueDelegate: Unable to gather output tensor indices from node #%d: ",
87 nodeIndex);
88 return kTfLiteError;
89 }
90 // Use output indices to get output tensor.
91 const TfLiteOpaqueTensor* tfLiteOutputTensor = TfLiteOpaqueContextGetOpaqueTensor(tfLiteContext, outputTensors[0]);
92 if (!IsValid(tfLiteContext, tfLiteOutputTensor, tfLiteElementWiseUnaryOperatorCode, nodeIndex))
93 {
94 return kTfLiteError;
95 }
96
97 const armnn::TensorInfo& inputTensorInfo = GetTensorInfoForTfLiteOpaqueTensor(tfLiteInputTensor);
98 const armnn::TensorInfo& outputTensorInfo = GetTensorInfoForTfLiteOpaqueTensor(tfLiteOutputTensor, true);
99
100 armnn::ElementwiseUnaryDescriptor descriptor(unaryOperation);
101 bool isSupported = false;
102 armnn::BackendId setBackend;
103 auto validateFunc = [&](const armnn::TensorInfo& outputTensorInfo, bool& isSupported, std::string layerName)
104 {
105 FORWARD_LAYER_OPAQUE_SUPPORT_FUNC(layerName.c_str(),
106 tfLiteContext,
107 IsElementwiseUnarySupported,
108 delegateData.m_Backends,
109 isSupported,
110 setBackend,
111 inputTensorInfo,
112 outputTensorInfo,
113 descriptor);
114 };
115
116 if (!delegateData.m_Network)
117 {
118 validateFunc(outputTensorInfo, isSupported, GetLayerName(unaryOperation));
119 return isSupported ? kTfLiteOk : kTfLiteError;
120 }
121
122 armnn::IConnectableLayer* layer = delegateData.m_Network->AddElementwiseUnaryLayer(descriptor);
123 layer->SetBackendId(setBackend);
124 ARMNN_ASSERT(layer != nullptr);
125
126 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
127 outputSlot.SetTensorInfo(outputTensorInfo);
128
129 // try to connect the Constant Inputs if there are any
130 if(ProcessInputs(layer, delegateData, tfLiteContext, tfLiteNode) != kTfLiteOk )
131 {
132 return kTfLiteError;
133 }
134
135 // Connect
136 return Connect(layer, tfLiteContext, tfLiteNode, delegateData);
137}
138
139} // namespace armnnOpaqueDelegate