blob: 8055a6958c9ddcc9c9da8c14bdd9c46cf26f0439 [file] [log] [blame]
Sadik Armagan62483be2020-10-23 17:14:43 +01001//
Ryan OShea3ad2e142023-01-13 10: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
Matthew Sloyan11572322023-03-16 10:17:51 +00008#include <ClassicDelegateUtils.hpp>
Jim Flynn4b2f3472021-10-13 21:20:07 +01009#include "MultiLayerFacade.hpp"
10#include "SharedFunctions.hpp"
Sadik Armagan67e95f22020-10-29 16:14:54 +000011
Sadik Armagan62483be2020-10-23 17:14:43 +010012#include <tensorflow/lite/builtin_ops.h>
13#include <tensorflow/lite/c/builtin_op_data.h>
14#include <tensorflow/lite/c/common.h>
15#include <tensorflow/lite/minimal_logging.h>
Sadik Armagan05e9fd22020-11-17 12:01:47 +000016#include "tensorflow/lite/delegates/utils.h"
Sadik Armagan62483be2020-10-23 17:14:43 +010017
18namespace armnnDelegate
19{
20
Sadik Armagan67e95f22020-10-29 16:14:54 +000021TfLiteStatus ValidateAddOperator(DelegateData& delegateData,
22 TfLiteContext* tfLiteContext,
23 const armnn::TensorInfo& inputInfo1,
24 const armnn::TensorInfo& inputInfo2,
25 const armnn::TensorInfo& outputInfo)
26{
27 bool isSupported = false;
28 auto validateFunc = [&](const armnn::TensorInfo& outputTensorInfo, bool& isSupported)
29 {
Mike Kelly3ec30772023-03-08 13:47:17 +000030 std::vector<armnn::TensorInfo> infos { inputInfo1, inputInfo2, outputInfo };
Sadik Armaganbfa767c2022-02-09 14:58:03 +000031 FORWARD_LAYER_SUPPORT_FUNC("ADD",
Sadik Armagan67e95f22020-10-29 16:14:54 +000032 tfLiteContext,
Mike Kelly3ec30772023-03-08 13:47:17 +000033 IsElementwiseBinarySupported,
Sadik Armagan67e95f22020-10-29 16:14:54 +000034 delegateData.m_Backends,
35 isSupported,
Cathal Corbett53837672022-09-01 11:34:37 +010036 armnn::BackendId(),
Sadik Armagan67e95f22020-10-29 16:14:54 +000037 inputInfo1,
38 inputInfo2,
Mike Kelly3ec30772023-03-08 13:47:17 +000039 outputInfo,
40 armnn::BinaryOperation::Add);
Sadik Armagan67e95f22020-10-29 16:14:54 +000041 };
42
43 validateFunc(outputInfo, isSupported);
44 return isSupported ? kTfLiteOk : kTfLiteError;
45}
46
Jim Flynn4b2f3472021-10-13 21:20:07 +010047
Sadik Armagan21a94ff2020-11-09 08:38:30 +000048TfLiteStatus ValidateDivOperator(DelegateData& delegateData,
49 TfLiteContext* tfLiteContext,
50 const armnn::TensorInfo& inputInfo1,
51 const armnn::TensorInfo& inputInfo2,
52 const armnn::TensorInfo& outputInfo)
Sadik Armagan67e95f22020-10-29 16:14:54 +000053{
Sadik Armagan21a94ff2020-11-09 08:38:30 +000054 bool isSupported = false;
55 auto validateFunc = [&](const armnn::TensorInfo& outputTensorInfo, bool& isSupported)
Sadik Armagan67e95f22020-10-29 16:14:54 +000056 {
Sadik Armaganbfa767c2022-02-09 14:58:03 +000057 FORWARD_LAYER_SUPPORT_FUNC("DIV",
Sadik Armagan21a94ff2020-11-09 08:38:30 +000058 tfLiteContext,
Mike Kelly3ec30772023-03-08 13:47:17 +000059 IsElementwiseBinarySupported,
Sadik Armagan21a94ff2020-11-09 08:38:30 +000060 delegateData.m_Backends,
61 isSupported,
Cathal Corbett53837672022-09-01 11:34:37 +010062 armnn::BackendId(),
Sadik Armagan21a94ff2020-11-09 08:38:30 +000063 inputInfo1,
64 inputInfo2,
Mike Kelly3ec30772023-03-08 13:47:17 +000065 outputTensorInfo,
66 armnn::BinaryOperation::Div);
Sadik Armagan21a94ff2020-11-09 08:38:30 +000067 };
Sadik Armagan67e95f22020-10-29 16:14:54 +000068
Sadik Armagan21a94ff2020-11-09 08:38:30 +000069 validateFunc(outputInfo, isSupported);
70 return isSupported ? kTfLiteOk : kTfLiteError;
71}
72
Jim Flynn4b2f3472021-10-13 21:20:07 +010073TfLiteStatus ValidateFloorDivOperator(DelegateData& delegateData,
74 TfLiteContext* tfLiteContext,
75 const armnn::TensorInfo& inputInfo1,
76 const armnn::TensorInfo& inputInfo2,
77 const armnn::TensorInfo& outputInfo)
78{
79 // need first to validate that the div operator is supported
80 // then that the floor operator is supported
81 TfLiteStatus status = ValidateDivOperator(delegateData, tfLiteContext, inputInfo1, inputInfo2, outputInfo);
82 if (status != kTfLiteOk)
83 {
84 return status;
85 }
86 // if the inputs and output of the div are all Signed32 we don't need to add the floor operator afterward.
87 if (AreAllSigned32(inputInfo1, inputInfo2, outputInfo))
88 {
89 return status;
90 }
91 // in case broadcasting is being done from one of the inputs to the div
92 // choose the full sized input tensor to pass to the floor validation routine
93 armnn::TensorInfo floorInputInfo = inputInfo1;
94 if (inputInfo1.GetNumDimensions() < inputInfo2.GetNumDimensions())
95 {
96 floorInputInfo = inputInfo2;
97 }
98 status = ValidateFloorOperator(delegateData, tfLiteContext, floorInputInfo, outputInfo);
99 return status;
100}
101
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000102TfLiteStatus ValidateMaximumOperator(DelegateData& delegateData,
103 TfLiteContext* tfLiteContext,
104 const armnn::TensorInfo& inputInfo1,
105 const armnn::TensorInfo& inputInfo2,
106 const armnn::TensorInfo& outputInfo)
107{
108 bool isSupported = false;
109 auto validateFunc = [&](const armnn::TensorInfo& outputTensorInfo, bool& isSupported)
110 {
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000111 FORWARD_LAYER_SUPPORT_FUNC("MAXIMUM",
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000112 tfLiteContext,
Mike Kelly3ec30772023-03-08 13:47:17 +0000113 IsElementwiseBinarySupported,
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000114 delegateData.m_Backends,
115 isSupported,
Cathal Corbett53837672022-09-01 11:34:37 +0100116 armnn::BackendId(),
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000117 inputInfo1,
118 inputInfo2,
Mike Kelly3ec30772023-03-08 13:47:17 +0000119 outputTensorInfo,
120 armnn::BinaryOperation::Maximum);
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000121 };
122
123 validateFunc(outputInfo, isSupported);
124 return isSupported ? kTfLiteOk : kTfLiteError;
125}
126
127TfLiteStatus ValidateMinimumOperator(DelegateData& delegateData,
128 TfLiteContext* tfLiteContext,
129 const armnn::TensorInfo& inputInfo1,
130 const armnn::TensorInfo& inputInfo2,
131 const armnn::TensorInfo& outputInfo)
132{
133 bool isSupported = false;
134 auto validateFunc = [&](const armnn::TensorInfo& outputTensorInfo, bool& isSupported)
135 {
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000136 FORWARD_LAYER_SUPPORT_FUNC("MINIMUM",
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000137 tfLiteContext,
Mike Kelly3ec30772023-03-08 13:47:17 +0000138 IsElementwiseBinarySupported,
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000139 delegateData.m_Backends,
140 isSupported,
Cathal Corbett53837672022-09-01 11:34:37 +0100141 armnn::BackendId(),
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000142 inputInfo1,
143 inputInfo2,
Mike Kelly3ec30772023-03-08 13:47:17 +0000144 outputTensorInfo,
145 armnn::BinaryOperation::Minimum);
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000146 };
147
148 validateFunc(outputInfo, isSupported);
149 return isSupported ? kTfLiteOk : kTfLiteError;
150}
151
152TfLiteStatus ValidateMulOperator(DelegateData& delegateData,
153 TfLiteContext* tfLiteContext,
154 const armnn::TensorInfo& inputInfo1,
155 const armnn::TensorInfo& inputInfo2,
156 const armnn::TensorInfo& outputInfo)
157{
158 bool isSupported = false;
159 auto validateFunc = [&](const armnn::TensorInfo& outputTensorInfo, bool& isSupported)
160 {
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000161 FORWARD_LAYER_SUPPORT_FUNC("MUL",
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000162 tfLiteContext,
Mike Kelly3ec30772023-03-08 13:47:17 +0000163 IsElementwiseBinarySupported,
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000164 delegateData.m_Backends,
165 isSupported,
Cathal Corbett53837672022-09-01 11:34:37 +0100166 armnn::BackendId(),
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000167 inputInfo1,
168 inputInfo2,
Mike Kelly3ec30772023-03-08 13:47:17 +0000169 outputTensorInfo,
170 armnn::BinaryOperation::Mul);
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000171 };
172
173 validateFunc(outputInfo, isSupported);
174 return isSupported ? kTfLiteOk : kTfLiteError;
175}
176
John Mcloughlin0ec00872023-05-15 17:03:49 +0100177TfLiteStatus ValidatePowerOperator(DelegateData& delegateData,
178 TfLiteContext* tfLiteContext,
179 const armnn::TensorInfo& inputInfo1,
180 const armnn::TensorInfo& inputInfo2,
181 const armnn::TensorInfo& outputInfo)
182{
183 bool isSupported = false;
184 auto validateFunc = [&](const armnn::TensorInfo& outputTensorInfo, bool& isSupported)
185 {
186 FORWARD_LAYER_SUPPORT_FUNC("POWER",
187 tfLiteContext,
188 IsElementwiseBinarySupported,
189 delegateData.m_Backends,
190 isSupported,
191 armnn::BackendId(),
192 inputInfo1,
193 inputInfo2,
194 outputTensorInfo,
195 armnn::BinaryOperation::Power);
196 };
197
198 validateFunc(outputInfo, isSupported);
199 return isSupported ? kTfLiteOk : kTfLiteError;
200}
201
202TfLiteStatus ValidateSquaredDifferenceOperator(DelegateData& delegateData,
203 TfLiteContext* tfLiteContext,
204 const armnn::TensorInfo& inputInfo1,
205 const armnn::TensorInfo& inputInfo2,
206 const armnn::TensorInfo& outputInfo)
207{
208 bool isSupported = false;
209 auto validateFunc = [&](const armnn::TensorInfo& outputTensorInfo, bool& isSupported)
210 {
211 FORWARD_LAYER_SUPPORT_FUNC("SQUAREDDIFFERENCE",
212 tfLiteContext,
213 IsElementwiseBinarySupported,
214 delegateData.m_Backends,
215 isSupported,
216 armnn::BackendId(),
217 inputInfo1,
218 inputInfo2,
219 outputTensorInfo,
220 armnn::BinaryOperation::SqDiff);
221 };
222
223 validateFunc(outputInfo, isSupported);
224 return isSupported ? kTfLiteOk : kTfLiteError;
225}
226
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000227TfLiteStatus ValidateSubOperator(DelegateData& delegateData,
228 TfLiteContext* tfLiteContext,
229 const armnn::TensorInfo& inputInfo1,
230 const armnn::TensorInfo& inputInfo2,
231 const armnn::TensorInfo& outputInfo)
232{
233 bool isSupported = false;
234 auto validateFunc = [&](const armnn::TensorInfo& outputTensorInfo, bool& isSupported)
235 {
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000236 FORWARD_LAYER_SUPPORT_FUNC("SUB",
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000237 tfLiteContext,
Mike Kelly3ec30772023-03-08 13:47:17 +0000238 IsElementwiseBinarySupported,
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000239 delegateData.m_Backends,
240 isSupported,
Cathal Corbett53837672022-09-01 11:34:37 +0100241 armnn::BackendId(),
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000242 inputInfo1,
243 inputInfo2,
Mike Kelly3ec30772023-03-08 13:47:17 +0000244 outputTensorInfo,
245 armnn::BinaryOperation::Sub);
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000246 };
247
248 validateFunc(outputInfo, isSupported);
249 return isSupported ? kTfLiteOk : kTfLiteError;
Sadik Armagan67e95f22020-10-29 16:14:54 +0000250}
251
Jim Flynn4b2f3472021-10-13 21:20:07 +0100252std::pair<armnn::IConnectableLayer*, armnn::IConnectableLayer*> AddFloorDivLayer(
253 DelegateData& delegateData,
254 const armnn::TensorInfo& outputTensorInfo)
255{
Mike Kelly3ec30772023-03-08 13:47:17 +0000256 armnn::IConnectableLayer* divisionLayer = delegateData.m_Network->AddElementwiseBinaryLayer(
257 armnn::BinaryOperation::Div);
Jim Flynn4b2f3472021-10-13 21:20:07 +0100258 // if the output of the div is Signed32 the Floor layer is not required
259 if (armnn::DataType::Signed32 == outputTensorInfo.GetDataType())
260 {
261 return std::make_pair(divisionLayer, divisionLayer);
262 }
263 armnn::IOutputSlot& outputSlot = divisionLayer->GetOutputSlot(0);
264 outputSlot.SetTensorInfo(outputTensorInfo);
265 armnn::IConnectableLayer* floorLayer = delegateData.m_Network->AddFloorLayer();
266 outputSlot.Connect(floorLayer->GetInputSlot(0));
267 return std::make_pair(divisionLayer, floorLayer);
268}
269
Sadik Armagan62483be2020-10-23 17:14:43 +0100270TfLiteStatus VisitElementwiseBinaryOperator(DelegateData& delegateData,
271 TfLiteContext* tfLiteContext,
272 TfLiteNode* tfLiteNode,
273 int nodeIndex,
274 int32_t elementwiseBinaryOperatorCode)
275{
Sadik Armagan67e95f22020-10-29 16:14:54 +0000276 TF_LITE_ENSURE_STATUS(ValidateNumInputs(tfLiteContext, tfLiteNode, 2, nodeIndex));
277 TF_LITE_ENSURE_STATUS(ValidateNumOutputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
278
279 const TfLiteTensor* tfLiteTensors = tfLiteContext->tensors;
280 const TfLiteTensor& tfLiteInputTensor0 = tfLiteTensors[tfLiteNode->inputs->data[0]];
281 if (IsDynamicTensor(tfLiteInputTensor0))
282 {
283 TF_LITE_MAYBE_KERNEL_LOG(
284 tfLiteContext,
285 "TfLiteArmnnDelegate: Dynamic input tensors are not supported in operator #%d node #%d: ",
286 elementwiseBinaryOperatorCode, nodeIndex);
287 return kTfLiteError;
288 }
289
290 const TfLiteTensor& tfLiteInputTensor1 = tfLiteTensors[tfLiteNode->inputs->data[1]];
291 if (IsDynamicTensor(tfLiteInputTensor1))
292 {
293 TF_LITE_MAYBE_KERNEL_LOG(
294 tfLiteContext,
295 "TfLiteArmnnDelegate: Dynamic input tensors are not supported in operator #%d node #%d: ",
296 elementwiseBinaryOperatorCode, nodeIndex);
297 return kTfLiteError;
298 }
299
300 const TfLiteTensor& tfLiteOutputTensor = tfLiteTensors[tfLiteNode->outputs->data[0]];
301 if (IsDynamicTensor(tfLiteOutputTensor))
302 {
303 TF_LITE_MAYBE_KERNEL_LOG(
304 tfLiteContext,
305 "TfLiteArmnnDelegate: Dynamic output tensors are not supported in operator #%d node #%d: ",
306 elementwiseBinaryOperatorCode, nodeIndex);
307 return kTfLiteError;
308 }
309
Sadik Armagan05e9fd22020-11-17 12:01:47 +0000310 armnn::TensorInfo inputTensorInfo0 = GetTensorInfoForTfLiteTensor(tfLiteInputTensor0);
311 armnn::TensorInfo inputTensorInfo1 = GetTensorInfoForTfLiteTensor(tfLiteInputTensor1);
312
Sadik Armagan90a119b2022-08-05 16:12:49 +0100313 const armnn::TensorInfo& outputTensorInfo = GetTensorInfoForTfLiteTensor(tfLiteOutputTensor, true);
Sadik Armagan67e95f22020-10-29 16:14:54 +0000314
Ryan OSheaa544f0f2023-01-25 18:10:20 +0000315 // Check if we need to expand the dims of the input tensor infos.
316 // This is required for a few of the backends.
317 if(inputTensorInfo0.GetNumDimensions() != inputTensorInfo1.GetNumDimensions())
318 {
319 ExpandTensorRankToEqual(inputTensorInfo0, inputTensorInfo1);
320 }
321
Ryan OShea3ad2e142023-01-13 10:19:20 +0000322 auto* tfLiteNodeParameters = reinterpret_cast<TfLiteAddParams*>(tfLiteNode->builtin_data);
Ryan OShea475c7a82023-01-30 14:24:15 +0000323 TfLiteFusedActivation activationType = kTfLiteActNone;
Ryan OShea3ad2e142023-01-13 10:19:20 +0000324 if (tfLiteNodeParameters)
325 {
326 activationType = tfLiteNodeParameters->activation;
Ryan OShea3ad2e142023-01-13 10:19:20 +0000327 TfLiteStatus activationStatus = ValidateFusedActivationOperator(delegateData, tfLiteContext, outputTensorInfo,
328 outputTensorInfo, activationType);
329 if(activationStatus != kTfLiteOk)
330 {
331 return kTfLiteError;
332 }
333 }
334
Sadik Armagan67e95f22020-10-29 16:14:54 +0000335 if (!delegateData.m_Network)
336 {
337 switch(elementwiseBinaryOperatorCode)
338 {
339 case kTfLiteBuiltinAdd:
340 return ValidateAddOperator(delegateData,
341 tfLiteContext,
342 inputTensorInfo0,
343 inputTensorInfo1,
344 outputTensorInfo);
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000345 case kTfLiteBuiltinDiv:
346 return ValidateDivOperator(delegateData,
347 tfLiteContext,
348 inputTensorInfo0,
349 inputTensorInfo1,
350 outputTensorInfo);
Jim Flynn4b2f3472021-10-13 21:20:07 +0100351 case kTfLiteBuiltinFloorDiv:
352 return ValidateFloorDivOperator(delegateData,
353 tfLiteContext,
354 inputTensorInfo0,
355 inputTensorInfo1,
356 outputTensorInfo);
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000357 case kTfLiteBuiltinMaximum:
358 return ValidateMaximumOperator(delegateData,
359 tfLiteContext,
360 inputTensorInfo0,
361 inputTensorInfo1,
362 outputTensorInfo);
363 case kTfLiteBuiltinMinimum:
364 return ValidateMinimumOperator(delegateData,
365 tfLiteContext,
366 inputTensorInfo0,
367 inputTensorInfo1,
368 outputTensorInfo);
369 case kTfLiteBuiltinMul:
Sadik Armagan15f7fae2020-11-18 09:37:03 +0000370 return ValidateMulOperator(delegateData,
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000371 tfLiteContext,
372 inputTensorInfo0,
373 inputTensorInfo1,
374 outputTensorInfo);
John Mcloughlin0ec00872023-05-15 17:03:49 +0100375 case kTfLiteBuiltinPow:
376 return ValidatePowerOperator(delegateData,
377 tfLiteContext,
378 inputTensorInfo0,
379 inputTensorInfo1,
380 outputTensorInfo);
381 case kTfLiteBuiltinSquaredDifference:
382 return ValidateSquaredDifferenceOperator(delegateData,
383 tfLiteContext,
384 inputTensorInfo0,
385 inputTensorInfo1,
386 outputTensorInfo);
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000387 case kTfLiteBuiltinSub:
Sadik Armagan15f7fae2020-11-18 09:37:03 +0000388 return ValidateSubOperator(delegateData,
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000389 tfLiteContext,
390 inputTensorInfo0,
391 inputTensorInfo1,
392 outputTensorInfo);
Sadik Armagan67e95f22020-10-29 16:14:54 +0000393 default:
394 return kTfLiteError;
395 }
396 }
397
398 armnn::IConnectableLayer* elementwiseBinaryLayer = nullptr;
Jim Flynn4b2f3472021-10-13 21:20:07 +0100399 MultiLayerFacade multiLayer;
Sadik Armagan67e95f22020-10-29 16:14:54 +0000400 switch(elementwiseBinaryOperatorCode)
401 {
402 case kTfLiteBuiltinAdd:
Mike Kelly3ec30772023-03-08 13:47:17 +0000403 elementwiseBinaryLayer = delegateData.m_Network->AddElementwiseBinaryLayer(
404 armnn::BinaryOperation::Add);
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000405 break;
406 case kTfLiteBuiltinDiv:
Mike Kelly3ec30772023-03-08 13:47:17 +0000407 elementwiseBinaryLayer = delegateData.m_Network->AddElementwiseBinaryLayer(
408 armnn::BinaryOperation::Div);
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000409 break;
Jim Flynn4b2f3472021-10-13 21:20:07 +0100410 case kTfLiteBuiltinFloorDiv:
411 {
412 auto layers = AddFloorDivLayer(delegateData, outputTensorInfo);
413 multiLayer.AssignValues(layers.first, layers.second);
414 elementwiseBinaryLayer = &multiLayer;
415 }
416 break;
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000417 case kTfLiteBuiltinMaximum:
Mike Kelly3ec30772023-03-08 13:47:17 +0000418 elementwiseBinaryLayer = delegateData.m_Network->AddElementwiseBinaryLayer(
419 armnn::BinaryOperation::Maximum);
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000420 break;
421 case kTfLiteBuiltinMinimum:
Mike Kelly3ec30772023-03-08 13:47:17 +0000422 elementwiseBinaryLayer = delegateData.m_Network->AddElementwiseBinaryLayer(
423 armnn::BinaryOperation::Minimum);
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000424 break;
425 case kTfLiteBuiltinMul:
Mike Kelly3ec30772023-03-08 13:47:17 +0000426 elementwiseBinaryLayer = delegateData.m_Network->AddElementwiseBinaryLayer(
427 armnn::BinaryOperation::Mul);
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000428 break;
John Mcloughlin0ec00872023-05-15 17:03:49 +0100429 case kTfLiteBuiltinPow:
430 elementwiseBinaryLayer = delegateData.m_Network->AddElementwiseBinaryLayer(
431 armnn::BinaryOperation::Power);
432 break;
433 case kTfLiteBuiltinSquaredDifference:
434 elementwiseBinaryLayer = delegateData.m_Network->AddElementwiseBinaryLayer(
435 armnn::BinaryOperation::SqDiff);
436 break;
Sadik Armagan21a94ff2020-11-09 08:38:30 +0000437 case kTfLiteBuiltinSub:
Mike Kelly3ec30772023-03-08 13:47:17 +0000438 elementwiseBinaryLayer = delegateData.m_Network->AddElementwiseBinaryLayer(
439 armnn::BinaryOperation::Sub);
Sadik Armagan67e95f22020-10-29 16:14:54 +0000440 break;
441 default:
442 return kTfLiteError;
443 }
444 ARMNN_ASSERT(elementwiseBinaryLayer != nullptr);
Sadik Armagan67e95f22020-10-29 16:14:54 +0000445 armnn::IOutputSlot& outputSlot = elementwiseBinaryLayer->GetOutputSlot(0);
446 outputSlot.SetTensorInfo(outputTensorInfo);
447
Sadik Armaganf7ac72c2021-05-05 15:03:50 +0100448 auto inputsTensorsProcess = ProcessInputs(elementwiseBinaryLayer,
449 delegateData,
450 tfLiteContext,
451 tfLiteNode);
452 if (inputsTensorsProcess == kTfLiteError)
Sadik Armagan05e9fd22020-11-17 12:01:47 +0000453 {
Sadik Armaganf7ac72c2021-05-05 15:03:50 +0100454 return inputsTensorsProcess;
Sadik Armagan05e9fd22020-11-17 12:01:47 +0000455 }
456
Ryan OSheaa544f0f2023-01-25 18:10:20 +0000457 if(Connect(elementwiseBinaryLayer, tfLiteNode, delegateData) != kTfLiteOk)
Sadik Armagan67e95f22020-10-29 16:14:54 +0000458 {
459 return kTfLiteError;
460 }
461
Sadik Armagan67e95f22020-10-29 16:14:54 +0000462 if (!tfLiteNodeParameters)
463 {
464 // No Activation
465 return kTfLiteOk;
466 }
Ryan OShea3ad2e142023-01-13 10:19:20 +0000467 // Check and Create Activation
Sadik Armagan05e9fd22020-11-17 12:01:47 +0000468 return FusedActivation(tfLiteContext, tfLiteNode, activationType, elementwiseBinaryLayer, 0, delegateData);
Sadik Armagan62483be2020-10-23 17:14:43 +0100469}
470
471} // namespace armnnDelegate