blob: 909721124151ae9df0d7fab7f1d47d484dd67254 [file] [log] [blame]
Sadik Armagan3c24f432020-10-19 17:35:30 +01001//
2// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include <armnn_delegate.hpp>
Sadik Armagan62483be2020-10-23 17:14:43 +01007
8#include "Activation.hpp"
9#include "ArgMinMax.hpp"
10#include "BatchSpace.hpp"
11#include "Comparison.hpp"
12#include "Convolution.hpp"
13#include "Control.hpp"
14#include "ElementwiseBinary.hpp"
15#include "ElementwiseUnary.hpp"
16#include "Fill.hpp"
17#include "FullyConnected.hpp"
18#include "Gather.hpp"
19#include "Lstm.hpp"
20#include "Normalization.hpp"
21#include "Pad.hpp"
22#include "Pooling.hpp"
23#include "Quantization.hpp"
24#include "Redefine.hpp"
25#include "Resize.hpp"
26#include "Round.hpp"
27#include "Slice.hpp"
28#include "Softmax.hpp"
29#include "SpaceDepth.hpp"
Sadik Armagan34fa1bd2020-11-27 12:40:52 +000030#include "Split.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010031#include "Transpose.hpp"
32
33#include <flatbuffers/flatbuffers.h>
34#include <tensorflow/lite/context_util.h>
35
Sadik Armagan3c24f432020-10-19 17:35:30 +010036#include <algorithm>
Sadik Armagan62483be2020-10-23 17:14:43 +010037#include <sstream>
Sadik Armagan3c24f432020-10-19 17:35:30 +010038
39namespace armnnDelegate
40{
41
Sadik Armagan62483be2020-10-23 17:14:43 +010042DelegateOptions TfLiteArmnnDelegateOptionsDefault()
43{
44 DelegateOptions options(armnn::Compute::CpuRef);
45 return options;
46}
47
48TfLiteDelegate* TfLiteArmnnDelegateCreate(armnnDelegate::DelegateOptions options)
49{
50 auto* armnnDelegate = new ::armnnDelegate::Delegate(options);
51 return armnnDelegate->GetDelegate();
52}
53
54void TfLiteArmnnDelegateDelete(TfLiteDelegate* tfLiteDelegate)
55{
56 if (tfLiteDelegate != nullptr)
57 {
58 delete static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_);
59 }
60}
61
62TfLiteStatus DoPrepare(TfLiteContext* tfLiteContext, TfLiteDelegate* tfLiteDelegate)
63{
64 TfLiteIntArray* supportedOperators =
65 static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_)->IdentifyOperatorsToDelegate(tfLiteContext);
66
67 // ArmNN Delegate Registration
68 static const TfLiteRegistration kArmnnSubgraphRegistration = {
69 // ArmnnSubgraph Init
70 .init = [](TfLiteContext* tfLiteContext, const char* buffer, size_t length) -> void* {
Finn Williams6f9f9902020-11-13 13:23:15 +000071 armnn::IgnoreUnused(length);
Sadik Armagan62483be2020-10-23 17:14:43 +010072 const TfLiteDelegateParams* parameters = reinterpret_cast<const TfLiteDelegateParams*>(buffer);
73
74 return static_cast<void*>(ArmnnSubgraph::Create(
75 tfLiteContext, parameters, static_cast<::armnnDelegate::Delegate*>(parameters->delegate->data_)));
76 },
77 // ArmnnSubgraph Free
78 .free = [](TfLiteContext* tfLiteContext, void* buffer) -> void {
Finn Williams6f9f9902020-11-13 13:23:15 +000079 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan62483be2020-10-23 17:14:43 +010080 if (buffer != nullptr)
81 {
82 delete static_cast<ArmnnSubgraph*>(buffer);
83 }
84 },
85 // ArmnnSubgraph Prepare
86 .prepare = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
87 if (tfLiteNode->user_data == nullptr)
88 {
89 return kTfLiteError;
90 }
Sadik Armagan62483be2020-10-23 17:14:43 +010091 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Prepare(tfLiteContext);
92 },
93 // ArmnnSubgraph Invoke
94 .invoke = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
95 if (tfLiteNode->user_data == nullptr)
96 {
97 return kTfLiteError;
98 }
99
100 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Invoke(tfLiteContext, tfLiteNode);
101 },
102
103 .profiling_string = nullptr,
104 .builtin_code = kTfLiteBuiltinDelegate,
105 .custom_name = "TfLiteArmNnDelegate",
106 .version = 1,
107 };
108
109 const TfLiteStatus status =
110 tfLiteContext->ReplaceNodeSubsetsWithDelegateKernels(
111 tfLiteContext, kArmnnSubgraphRegistration, supportedOperators, tfLiteDelegate);
112
113 TfLiteIntArrayFree(supportedOperators);
114 return status;
115
116}
117
Sadik Armagan3c24f432020-10-19 17:35:30 +0100118Delegate::Delegate(armnnDelegate::DelegateOptions options)
119 : m_Runtime(nullptr, nullptr),
120 m_Options(std::move(options))
121{
122 // Create ArmNN Runtime
123 armnn::IRuntime::CreationOptions runtimeOptions;
Sadik Armagan4189cc52020-11-11 18:01:48 +0000124
125 auto backendOptions = m_Options.GetBackendOptions();
126 if (!backendOptions.empty())
127 {
128 runtimeOptions.m_BackendOptions = backendOptions;
129 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100130 m_Runtime = armnn::IRuntime::Create(runtimeOptions);
131
132 std::vector<armnn::BackendId> backends;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100133 if (m_Runtime)
134 {
135 const armnn::BackendIdSet supportedDevices = m_Runtime->GetDeviceSpec().GetSupportedBackends();
136 for (auto& backend : m_Options.GetBackends())
137 {
138 if (std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) == supportedDevices.cend())
139 {
Sadik Armagan0534e032020-10-27 17:30:18 +0000140 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100141 "TfLiteArmnnDelegate: Requested unknown backend %s", backend.Get().c_str());
142 }
143 else
144 {
145 backends.push_back(backend);
146 }
147 }
148 }
149
150 if (backends.empty())
151 {
152 // No known backend specified
153 throw armnn::InvalidArgumentException("TfLiteArmnnDelegate: No known backend specified.");
154 }
155 m_Options.SetBackends(backends);
156
157 TFLITE_LOG_PROD_ONCE(tflite::TFLITE_LOG_INFO, "TfLiteArmnnDelegate: Created TfLite ArmNN delegate.");
158}
159
Sadik Armagan62483be2020-10-23 17:14:43 +0100160TfLiteIntArray* Delegate::IdentifyOperatorsToDelegate(TfLiteContext* tfLiteContext)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100161{
162 TfLiteIntArray* executionPlan = nullptr;
163 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
164 {
165 TF_LITE_KERNEL_LOG(tfLiteContext, "TfLiteArmnnDelegate: Unable to get graph execution plan.");
166 return nullptr;
167 }
168
Sadik Armagan62483be2020-10-23 17:14:43 +0100169 // Delegate data with null network
170 DelegateData delegateData(m_Options.GetBackends());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100171
172 TfLiteIntArray* nodesToDelegate = TfLiteIntArrayCreate(executionPlan->size);
173 nodesToDelegate->size = 0;
174 for (int i = 0; i < executionPlan->size; ++i)
175 {
176 const int nodeIndex = executionPlan->data[i];
177
178 // If TfLite nodes can be delegated to ArmNN
179 TfLiteNode* tfLiteNode = nullptr;
180 TfLiteRegistration* tfLiteRegistration = nullptr;
181 if (tfLiteContext->GetNodeAndRegistration(
182 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
183 {
184 TF_LITE_KERNEL_LOG(tfLiteContext,
185 "TfLiteArmnnDelegate: Unable to get node and registration for node %d.",
186 nodeIndex);
187 continue;
188 }
189
190 if (ArmnnSubgraph::VisitNode(
Sadik Armagan62483be2020-10-23 17:14:43 +0100191 delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100192 {
193 // node is not supported by ArmNN
194 continue;
195 }
196
197 nodesToDelegate->data[nodesToDelegate->size++] = nodeIndex;
198 }
199
Sadik Armagan62483be2020-10-23 17:14:43 +0100200 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100201 return nodesToDelegate;
202}
203
204TfLiteDelegate* Delegate::GetDelegate()
205{
206 return &m_Delegate;
207}
208
Sadik Armagan62483be2020-10-23 17:14:43 +0100209TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
210 TfLiteContext* tfLiteContext,
211 const TfLiteIntArray* inputs,
212 std::vector<armnn::BindingPointInfo>& inputBindings)
213{
Finn Williams6f9f9902020-11-13 13:23:15 +0000214 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100215 for (unsigned int i = 0; i < numInputs; ++i)
216 {
217 const int32_t tensorId = inputs->data[i];
218 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000219 // Do not create bindings for constant inputs
220 if (tensor.allocation_type == kTfLiteMmapRo)
221 {
222 continue;
223 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100224
225 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
226 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
227
228 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
229 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
230 outputSlot.SetTensorInfo(tensorInfo);
231
232 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000233 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100234
Sadik Armagan6e36a642020-11-10 21:18:41 +0000235 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100236 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000237
Sadik Armagan62483be2020-10-23 17:14:43 +0100238 return kTfLiteOk;
239}
240
241TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
242 TfLiteContext* tfLiteContext,
243 const TfLiteIntArray* outputs,
244 std::vector<armnn::BindingPointInfo>& outputBindings)
245{
Finn Williams6f9f9902020-11-13 13:23:15 +0000246 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100247 for (unsigned int i = 0; i < numOutputs; ++i)
248 {
249 const int32_t tensorId = outputs->data[i];
250 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
251
252 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
253 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
254
255 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Finn Williams6f9f9902020-11-13 13:23:15 +0000256 ARMNN_ASSERT(delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] != nullptr);
257 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100258 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
259 }
260
261 return kTfLiteOk;
262}
263
Sadik Armagan3c24f432020-10-19 17:35:30 +0100264ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
265 const TfLiteDelegateParams* parameters,
266 const Delegate* delegate)
267{
268 TfLiteIntArray* executionPlan;
269 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
270 {
271 return nullptr;
272 }
273
Sadik Armagan62483be2020-10-23 17:14:43 +0100274 // Initialize DelegateData holds network and output slots information
275 DelegateData delegateData(delegate->m_Options.GetBackends());
276
277 // Build ArmNN Network
Sadik Armagan3c24f432020-10-19 17:35:30 +0100278 armnn::NetworkOptions networkOptions = {};
279 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100280 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100281
Sadik Armagan6e36a642020-11-10 21:18:41 +0000282 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
283
Sadik Armagan62483be2020-10-23 17:14:43 +0100284
285 std::vector<armnn::BindingPointInfo> inputBindings;
286 std::vector<armnn::BindingPointInfo> outputBindings;
287
288 // Add input layer
289 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
290 if (status != kTfLiteOk)
291 {
292 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
293 }
294
295 // Parse TfLite delegate nodes to ArmNN
Sadik Armagan3c24f432020-10-19 17:35:30 +0100296 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
297 {
298 const int nodeIndex = parameters->nodes_to_replace->data[i];
299
300 TfLiteNode* tfLiteNode = nullptr;
301 TfLiteRegistration* tfLiteRegistration = nullptr;
302 if (tfLiteContext->GetNodeAndRegistration(
303 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
304 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000305 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100306 }
307
Sadik Armagan62483be2020-10-23 17:14:43 +0100308 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100309 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000310 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100311 }
312 }
313
Sadik Armagan62483be2020-10-23 17:14:43 +0100314 // Add Output layer
315 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
316 if (status != kTfLiteOk)
317 {
318 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
319 }
320
321 // Optimize ArmNN network
322 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
323 try
324 {
Sadik Armagan6e36a642020-11-10 21:18:41 +0000325 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100326 delegate->m_Options.GetBackends(),
327 delegate->m_Runtime->GetDeviceSpec());
328 }
329 catch (std::exception &ex)
330 {
331 std::stringstream exMessage;
332 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
333 throw armnn::Exception(exMessage.str());
334 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100335 if (!optNet)
336 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100337 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100338 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
339 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100340
341 try
342 {
343 // Load graph into runtime
344 auto loadingStatus = delegate->m_Runtime->LoadNetwork(networkId, std::move(optNet));
345 if (loadingStatus != armnn::Status::Success)
346 {
347 // Optimize failed
348 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded!");;
349 }
350 }
351 catch (std::exception& ex)
352 {
353 std::stringstream exMessage;
354 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
355 throw armnn::Exception(exMessage.str());
356 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100357
358 // Create a new SubGraph with networkId and runtime
Sadik Armagan62483be2020-10-23 17:14:43 +0100359 return new ArmnnSubgraph(networkId, delegate->m_Runtime.get(), inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100360}
361
362TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
363{
Finn Williams6f9f9902020-11-13 13:23:15 +0000364 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100365 return kTfLiteOk;
366}
367
Sadik Armagan62483be2020-10-23 17:14:43 +0100368TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100369{
Sadik Armagan62483be2020-10-23 17:14:43 +0100370 // Prepare inputs
371 armnn::InputTensors inputTensors;
372 size_t inputIndex = 0;
373 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
374 {
375 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
376 if (tensor->allocation_type != kTfLiteMmapRo)
377 {
378 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
379 const armnn::ConstTensor inputTensor(inputBinding.second, tensor->data.data);
380 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100381
Sadik Armagan62483be2020-10-23 17:14:43 +0100382 ++inputIndex;
383 }
384 }
385
386 // Prepare outputs
387 armnn::OutputTensors outputTensors;
388 size_t outputIndex = 0;
389 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
390 {
391 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
392 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
393 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
394 outputTensors.emplace_back(outputIdx, outputTensor);
395
396 ++outputIndex;
397 }
398
399 // Run graph
400 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
401 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100402}
403
Sadik Armagan62483be2020-10-23 17:14:43 +0100404TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100405 TfLiteContext* tfLiteContext,
406 TfLiteRegistration* tfLiteRegistration,
407 TfLiteNode* tfLiteNode,
408 int nodeIndex)
409{
Sadik Armagan62483be2020-10-23 17:14:43 +0100410 switch (tfLiteRegistration->builtin_code)
411 {
412 case kTfLiteBuiltinAbs:
413 return VisitElementwiseUnaryOperator(delegateData,
414 tfLiteContext,
415 tfLiteNode,
416 nodeIndex,
417 armnn::UnaryOperation::Abs);
418 case kTfLiteBuiltinAdd:
419 return VisitElementwiseBinaryOperator(delegateData,
420 tfLiteContext,
421 tfLiteNode,
422 nodeIndex,
423 kTfLiteBuiltinAdd);
424 case kTfLiteBuiltinArgMax:
425 return VisitArgMinMaxOperator(delegateData,
426 tfLiteContext,
427 tfLiteNode,
428 nodeIndex,
429 kTfLiteBuiltinArgMax);
430 case kTfLiteBuiltinArgMin:
431 return VisitArgMinMaxOperator(delegateData,
432 tfLiteContext,
433 tfLiteNode,
434 nodeIndex,
435 kTfLiteBuiltinArgMin);
436 case kTfLiteBuiltinAveragePool2d:
437 return VisitPoolingOperator(delegateData,
438 tfLiteContext,
439 tfLiteNode,
440 nodeIndex,
441 kTfLiteBuiltinAveragePool2d);
442 case kTfLiteBuiltinBatchToSpaceNd:
443 return VisitBatchToSpaceNdOperator(delegateData,
444 tfLiteContext,
445 tfLiteNode,
446 nodeIndex,
447 kTfLiteBuiltinBatchToSpaceNd);
448 case kTfLiteBuiltinConcatenation:
449 return VisitControlOperator(delegateData,
450 tfLiteContext,
451 tfLiteNode,
452 nodeIndex,
453 kTfLiteBuiltinConcatenation);
454 case kTfLiteBuiltinConv2d:
455 return VisitConvolutionOperator(delegateData,
456 tfLiteContext,
457 tfLiteNode,
458 nodeIndex,
459 kTfLiteBuiltinConv2d);
460 case kTfLiteBuiltinDepthToSpace:
461 return VisitDepthToSpaceOperator(delegateData,
462 tfLiteContext,
463 tfLiteNode,
464 nodeIndex,
465 kTfLiteBuiltinDepthToSpace);
466 case kTfLiteBuiltinDepthwiseConv2d:
467 return VisitConvolutionOperator(delegateData,
468 tfLiteContext,
469 tfLiteNode,
470 nodeIndex,
471 kTfLiteBuiltinDepthwiseConv2d);
472 case kTfLiteBuiltinDequantize:
473 return VisitDequantizeOperator(delegateData,
474 tfLiteContext,
475 tfLiteNode,
476 nodeIndex,
477 kTfLiteBuiltinDequantize);
478 case kTfLiteBuiltinDiv:
479 return VisitElementwiseBinaryOperator(delegateData,
480 tfLiteContext,
481 tfLiteNode,
482 nodeIndex,
483 kTfLiteBuiltinDiv);
484 case kTfLiteBuiltinElu:
485 return VisitActivationOperator(delegateData,
486 tfLiteContext,
487 tfLiteNode,
488 nodeIndex,
489 kTfLiteBuiltinElu);
490 case kTfLiteBuiltinEqual:
491 return VisitComparisonOperator(delegateData,
492 tfLiteContext,
493 tfLiteNode,
494 nodeIndex,
495 kTfLiteBuiltinEqual);
496 case kTfLiteBuiltinExp:
497 return VisitElementwiseUnaryOperator(delegateData,
498 tfLiteContext,
499 tfLiteNode,
500 nodeIndex,
501 armnn::UnaryOperation::Exp);
502 case kTfLiteBuiltinExpandDims:
503 return VisitExpandDimsOperator(delegateData,
504 tfLiteContext,
505 tfLiteNode,
506 nodeIndex,
507 kTfLiteBuiltinExpandDims);
508 case kTfLiteBuiltinFill:
509 return VisitFillOperator(delegateData,
510 tfLiteContext,
511 tfLiteNode,
512 nodeIndex,
513 kTfLiteBuiltinFill);
514 case kTfLiteBuiltinFloor:
515 return VisitFloorOperator(delegateData,
516 tfLiteContext,
517 tfLiteNode,
518 nodeIndex,
519 kTfLiteBuiltinFloor);
520 case kTfLiteBuiltinFullyConnected:
521 return VisitFullyConnectedOperator(delegateData,
522 tfLiteContext,
523 tfLiteNode,
524 nodeIndex,
525 kTfLiteBuiltinFullyConnected);
526 case kTfLiteBuiltinGather:
527 return VisitGatherOperator(delegateData,
528 tfLiteContext,
529 tfLiteNode,
530 nodeIndex,
531 kTfLiteBuiltinGather);
532 case kTfLiteBuiltinGatherNd:
533 return VisitGatherOperator(delegateData,
534 tfLiteContext,
535 tfLiteNode,
536 nodeIndex,
537 kTfLiteBuiltinGatherNd);
538 case kTfLiteBuiltinGreater:
539 return VisitComparisonOperator(delegateData,
540 tfLiteContext,
541 tfLiteNode,
542 nodeIndex,
543 kTfLiteBuiltinGreater);
544 case kTfLiteBuiltinGreaterEqual:
545 return VisitComparisonOperator(delegateData,
546 tfLiteContext,
547 tfLiteNode,
548 nodeIndex,
549 kTfLiteBuiltinGreaterEqual);
550 case kTfLiteBuiltinHardSwish:
551 return VisitActivationOperator(delegateData,
552 tfLiteContext,
553 tfLiteNode,
554 nodeIndex,
555 kTfLiteBuiltinHardSwish);
556 case kTfLiteBuiltinL2Normalization:
557 return VisitNormalizationOperator(delegateData,
558 tfLiteContext,
559 tfLiteNode,
560 nodeIndex,
561 kTfLiteBuiltinL2Normalization);
562 case kTfLiteBuiltinL2Pool2d:
563 return VisitPoolingOperator(delegateData,
564 tfLiteContext,
565 tfLiteNode,
566 nodeIndex,
567 kTfLiteBuiltinL2Pool2d);
568 case kTfLiteBuiltinLess:
569 return VisitComparisonOperator(delegateData,
570 tfLiteContext,
571 tfLiteNode,
572 nodeIndex,
573 kTfLiteBuiltinLess);
574 case kTfLiteBuiltinLessEqual:
575 return VisitComparisonOperator(delegateData,
576 tfLiteContext,
577 tfLiteNode,
578 nodeIndex,
579 kTfLiteBuiltinLessEqual);
580 case kTfLiteBuiltinLocalResponseNormalization:
581 return VisitNormalizationOperator(delegateData,
582 tfLiteContext,
583 tfLiteNode,
584 nodeIndex,
585 kTfLiteBuiltinLocalResponseNormalization);
586 case kTfLiteBuiltinLogistic:
587 return VisitActivationOperator(delegateData,
588 tfLiteContext,
589 tfLiteNode,
590 nodeIndex,
591 kTfLiteBuiltinLogistic);
592 case kTfLiteBuiltinLogSoftmax:
593 return VisitSoftmaxOperator(delegateData,
594 tfLiteContext,
595 tfLiteNode,
596 nodeIndex,
597 kTfLiteBuiltinLogSoftmax);
598 case kTfLiteBuiltinLstm:
599 return VisitLstmOperator(delegateData,
600 tfLiteContext,
601 tfLiteNode,
602 nodeIndex,
603 kTfLiteBuiltinLstm);
604 case kTfLiteBuiltinMaxPool2d:
605 return VisitPoolingOperator(delegateData,
606 tfLiteContext,
607 tfLiteNode,
608 nodeIndex,
609 kTfLiteBuiltinMaxPool2d);
610 case kTfLiteBuiltinMaximum:
611 return VisitElementwiseBinaryOperator(delegateData,
612 tfLiteContext,
613 tfLiteNode,
614 nodeIndex,
615 kTfLiteBuiltinMaximum);
616 case kTfLiteBuiltinMean:
617 return VisitControlOperator(delegateData,
618 tfLiteContext,
619 tfLiteNode,
620 nodeIndex,
621 kTfLiteBuiltinMean);
622 case kTfLiteBuiltinMinimum:
623 return VisitElementwiseBinaryOperator(delegateData,
624 tfLiteContext,
625 tfLiteNode,
626 nodeIndex,
627 kTfLiteBuiltinMinimum);
628 case kTfLiteBuiltinMul:
629 return VisitElementwiseBinaryOperator(delegateData,
630 tfLiteContext,
631 tfLiteNode,
632 nodeIndex,
633 kTfLiteBuiltinMul);
634 case kTfLiteBuiltinNeg:
635 return VisitElementwiseUnaryOperator(delegateData,
636 tfLiteContext,
637 tfLiteNode,
638 nodeIndex,
639 armnn::UnaryOperation::Neg);
640 case kTfLiteBuiltinNotEqual:
641 return VisitComparisonOperator(delegateData,
642 tfLiteContext,
643 tfLiteNode,
644 nodeIndex,
645 kTfLiteBuiltinNotEqual);
646 case kTfLiteBuiltinPad:
647 return VisitPadOperator(delegateData,
648 tfLiteContext,
649 tfLiteNode,
650 nodeIndex,
651 kTfLiteBuiltinPad);
652 case kTfLiteBuiltinPadv2:
653 return VisitPadOperator(delegateData,
654 tfLiteContext,
655 tfLiteNode,
656 nodeIndex,
657 kTfLiteBuiltinPadv2);
658 case kTfLiteBuiltinPrelu:
659 return VisitActivationOperator(delegateData,
660 tfLiteContext,
661 tfLiteNode,
662 nodeIndex,
663 kTfLiteBuiltinPrelu);
664 case kTfLiteBuiltinQuantize:
665 return VisitQuantizeOperator(delegateData,
666 tfLiteContext,
667 tfLiteNode,
668 nodeIndex,
669 kTfLiteBuiltinQuantize);
670 case kTfLiteBuiltinRank:
671 return VisitControlOperator(delegateData,
672 tfLiteContext,
673 tfLiteNode,
674 nodeIndex,
675 kTfLiteBuiltinRank);
676 case kTfLiteBuiltinRelu:
677 return VisitActivationOperator(delegateData,
678 tfLiteContext,
679 tfLiteNode,
680 nodeIndex,
681 kTfLiteBuiltinRelu);
682 case kTfLiteBuiltinReluN1To1:
683 return VisitActivationOperator(delegateData,
684 tfLiteContext,
685 tfLiteNode,
686 nodeIndex,
687 kTfLiteBuiltinReluN1To1);
688 case kTfLiteBuiltinRelu6:
689 return VisitActivationOperator(delegateData,
690 tfLiteContext,
691 tfLiteNode,
692 nodeIndex,
693 kTfLiteBuiltinRelu6);
694 case kTfLiteBuiltinReshape:
695 return VisitReshapeOperator(delegateData,
696 tfLiteContext,
697 tfLiteNode,
698 nodeIndex,
699 kTfLiteBuiltinReshape);
700 case kTfLiteBuiltinResizeBilinear:
701 return VisitResizeOperator(delegateData,
702 tfLiteContext,
703 tfLiteNode,
704 nodeIndex,
705 kTfLiteBuiltinResizeBilinear);
706 case kTfLiteBuiltinResizeNearestNeighbor:
707 return VisitResizeOperator(delegateData,
708 tfLiteContext,
709 tfLiteNode,
710 nodeIndex,
711 kTfLiteBuiltinResizeNearestNeighbor);
712 case kTfLiteBuiltinRsqrt:
713 return VisitElementwiseUnaryOperator(delegateData,
714 tfLiteContext,
715 tfLiteNode,
716 nodeIndex,
717 armnn::UnaryOperation::Rsqrt);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +0000718 case kTfLiteBuiltinSplit:
719 return VisitSplitOperator(delegateData,
720 tfLiteContext,
721 tfLiteNode,
722 nodeIndex,
723 kTfLiteBuiltinSplit);
724 case kTfLiteBuiltinSplitV:
725 return VisitSplitVOperator(delegateData,
726 tfLiteContext,
727 tfLiteNode,
728 nodeIndex,
729 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +0100730 case kTfLiteBuiltinSqrt:
731 return VisitElementwiseUnaryOperator(delegateData,
732 tfLiteContext,
733 tfLiteNode,
734 nodeIndex,
735 armnn::UnaryOperation::Sqrt);
736 case kTfLiteBuiltinSqueeze:
737 return VisitSqueezeOperator(delegateData,
738 tfLiteContext,
739 tfLiteNode,
740 nodeIndex,
741 kTfLiteBuiltinSqueeze);
742 case kTfLiteBuiltinStridedSlice:
743 return VisitSliceOperator(delegateData,
744 tfLiteContext,
745 tfLiteNode,
746 nodeIndex,
747 kTfLiteBuiltinStridedSlice);
748 case kTfLiteBuiltinTranspose:
749 return VisitTransposeOperator(delegateData,
750 tfLiteContext,
751 tfLiteNode,
752 nodeIndex,
753 kTfLiteBuiltinTranspose);
754 case kTfLiteBuiltinTransposeConv:
755 return VisitConvolutionOperator(delegateData,
756 tfLiteContext,
757 tfLiteNode,
758 nodeIndex,
759 kTfLiteBuiltinTransposeConv);
760 case kTfLiteBuiltinSoftmax:
761 return VisitSoftmaxOperator(delegateData,
762 tfLiteContext,
763 tfLiteNode,
764 nodeIndex,
765 kTfLiteBuiltinSoftmax);
766 case kTfLiteBuiltinSpaceToBatchNd:
767 return VisitSpaceToBatchNdOperator(delegateData,
768 tfLiteContext,
769 tfLiteNode,
770 nodeIndex,
771 kTfLiteBuiltinSpaceToBatchNd);
772 case kTfLiteBuiltinSpaceToDepth:
773 return VisitSpaceToDepthOperator(delegateData,
774 tfLiteContext,
775 tfLiteNode,
776 nodeIndex,
777 kTfLiteBuiltinSpaceToDepth);
778 case kTfLiteBuiltinSub:
779 return VisitElementwiseBinaryOperator(delegateData,
780 tfLiteContext,
781 tfLiteNode,
782 nodeIndex,
783 kTfLiteBuiltinSub);
784 case kTfLiteBuiltinTanh:
785 return VisitActivationOperator(delegateData,
786 tfLiteContext,
787 tfLiteNode,
788 nodeIndex,
789 kTfLiteBuiltinTanh);
790 default:
791 return kTfLiteError;
792 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100793}
794
795} // armnnDelegate namespace