blob: d2b179670821eb9c1fc0a2e6b2961e968ab82fee [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"
30#include "Transpose.hpp"
31
32#include <flatbuffers/flatbuffers.h>
33#include <tensorflow/lite/context_util.h>
34
Sadik Armagan3c24f432020-10-19 17:35:30 +010035#include <algorithm>
Sadik Armagan62483be2020-10-23 17:14:43 +010036#include <sstream>
Sadik Armagan3c24f432020-10-19 17:35:30 +010037
38namespace armnnDelegate
39{
40
Sadik Armagan62483be2020-10-23 17:14:43 +010041DelegateOptions TfLiteArmnnDelegateOptionsDefault()
42{
43 DelegateOptions options(armnn::Compute::CpuRef);
44 return options;
45}
46
47TfLiteDelegate* TfLiteArmnnDelegateCreate(armnnDelegate::DelegateOptions options)
48{
49 auto* armnnDelegate = new ::armnnDelegate::Delegate(options);
50 return armnnDelegate->GetDelegate();
51}
52
53void TfLiteArmnnDelegateDelete(TfLiteDelegate* tfLiteDelegate)
54{
55 if (tfLiteDelegate != nullptr)
56 {
57 delete static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_);
58 }
59}
60
61TfLiteStatus DoPrepare(TfLiteContext* tfLiteContext, TfLiteDelegate* tfLiteDelegate)
62{
63 TfLiteIntArray* supportedOperators =
64 static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_)->IdentifyOperatorsToDelegate(tfLiteContext);
65
66 // ArmNN Delegate Registration
67 static const TfLiteRegistration kArmnnSubgraphRegistration = {
68 // ArmnnSubgraph Init
69 .init = [](TfLiteContext* tfLiteContext, const char* buffer, size_t length) -> void* {
Finn Williams6f9f9902020-11-13 13:23:15 +000070 armnn::IgnoreUnused(length);
Sadik Armagan62483be2020-10-23 17:14:43 +010071 const TfLiteDelegateParams* parameters = reinterpret_cast<const TfLiteDelegateParams*>(buffer);
72
73 return static_cast<void*>(ArmnnSubgraph::Create(
74 tfLiteContext, parameters, static_cast<::armnnDelegate::Delegate*>(parameters->delegate->data_)));
75 },
76 // ArmnnSubgraph Free
77 .free = [](TfLiteContext* tfLiteContext, void* buffer) -> void {
Finn Williams6f9f9902020-11-13 13:23:15 +000078 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan62483be2020-10-23 17:14:43 +010079 if (buffer != nullptr)
80 {
81 delete static_cast<ArmnnSubgraph*>(buffer);
82 }
83 },
84 // ArmnnSubgraph Prepare
85 .prepare = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
86 if (tfLiteNode->user_data == nullptr)
87 {
88 return kTfLiteError;
89 }
Sadik Armagan62483be2020-10-23 17:14:43 +010090 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Prepare(tfLiteContext);
91 },
92 // ArmnnSubgraph Invoke
93 .invoke = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
94 if (tfLiteNode->user_data == nullptr)
95 {
96 return kTfLiteError;
97 }
98
99 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Invoke(tfLiteContext, tfLiteNode);
100 },
101
102 .profiling_string = nullptr,
103 .builtin_code = kTfLiteBuiltinDelegate,
104 .custom_name = "TfLiteArmNnDelegate",
105 .version = 1,
106 };
107
108 const TfLiteStatus status =
109 tfLiteContext->ReplaceNodeSubsetsWithDelegateKernels(
110 tfLiteContext, kArmnnSubgraphRegistration, supportedOperators, tfLiteDelegate);
111
112 TfLiteIntArrayFree(supportedOperators);
113 return status;
114
115}
116
Sadik Armagan3c24f432020-10-19 17:35:30 +0100117Delegate::Delegate(armnnDelegate::DelegateOptions options)
118 : m_Runtime(nullptr, nullptr),
119 m_Options(std::move(options))
120{
121 // Create ArmNN Runtime
122 armnn::IRuntime::CreationOptions runtimeOptions;
Sadik Armagan4189cc52020-11-11 18:01:48 +0000123
124 auto backendOptions = m_Options.GetBackendOptions();
125 if (!backendOptions.empty())
126 {
127 runtimeOptions.m_BackendOptions = backendOptions;
128 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100129 m_Runtime = armnn::IRuntime::Create(runtimeOptions);
130
131 std::vector<armnn::BackendId> backends;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100132 if (m_Runtime)
133 {
134 const armnn::BackendIdSet supportedDevices = m_Runtime->GetDeviceSpec().GetSupportedBackends();
135 for (auto& backend : m_Options.GetBackends())
136 {
137 if (std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) == supportedDevices.cend())
138 {
Sadik Armagan0534e032020-10-27 17:30:18 +0000139 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100140 "TfLiteArmnnDelegate: Requested unknown backend %s", backend.Get().c_str());
141 }
142 else
143 {
144 backends.push_back(backend);
145 }
146 }
147 }
148
149 if (backends.empty())
150 {
151 // No known backend specified
152 throw armnn::InvalidArgumentException("TfLiteArmnnDelegate: No known backend specified.");
153 }
154 m_Options.SetBackends(backends);
155
156 TFLITE_LOG_PROD_ONCE(tflite::TFLITE_LOG_INFO, "TfLiteArmnnDelegate: Created TfLite ArmNN delegate.");
157}
158
Sadik Armagan62483be2020-10-23 17:14:43 +0100159TfLiteIntArray* Delegate::IdentifyOperatorsToDelegate(TfLiteContext* tfLiteContext)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100160{
161 TfLiteIntArray* executionPlan = nullptr;
162 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
163 {
164 TF_LITE_KERNEL_LOG(tfLiteContext, "TfLiteArmnnDelegate: Unable to get graph execution plan.");
165 return nullptr;
166 }
167
Sadik Armagan62483be2020-10-23 17:14:43 +0100168 // Delegate data with null network
169 DelegateData delegateData(m_Options.GetBackends());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100170
171 TfLiteIntArray* nodesToDelegate = TfLiteIntArrayCreate(executionPlan->size);
172 nodesToDelegate->size = 0;
173 for (int i = 0; i < executionPlan->size; ++i)
174 {
175 const int nodeIndex = executionPlan->data[i];
176
177 // If TfLite nodes can be delegated to ArmNN
178 TfLiteNode* tfLiteNode = nullptr;
179 TfLiteRegistration* tfLiteRegistration = nullptr;
180 if (tfLiteContext->GetNodeAndRegistration(
181 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
182 {
183 TF_LITE_KERNEL_LOG(tfLiteContext,
184 "TfLiteArmnnDelegate: Unable to get node and registration for node %d.",
185 nodeIndex);
186 continue;
187 }
188
189 if (ArmnnSubgraph::VisitNode(
Sadik Armagan62483be2020-10-23 17:14:43 +0100190 delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100191 {
192 // node is not supported by ArmNN
193 continue;
194 }
195
196 nodesToDelegate->data[nodesToDelegate->size++] = nodeIndex;
197 }
198
Sadik Armagan62483be2020-10-23 17:14:43 +0100199 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100200 return nodesToDelegate;
201}
202
203TfLiteDelegate* Delegate::GetDelegate()
204{
205 return &m_Delegate;
206}
207
Sadik Armagan62483be2020-10-23 17:14:43 +0100208TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
209 TfLiteContext* tfLiteContext,
210 const TfLiteIntArray* inputs,
211 std::vector<armnn::BindingPointInfo>& inputBindings)
212{
Finn Williams6f9f9902020-11-13 13:23:15 +0000213 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100214 for (unsigned int i = 0; i < numInputs; ++i)
215 {
216 const int32_t tensorId = inputs->data[i];
217 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000218 // Do not create bindings for constant inputs
219 if (tensor.allocation_type == kTfLiteMmapRo)
220 {
221 continue;
222 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100223
224 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
225 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
226
227 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
228 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
229 outputSlot.SetTensorInfo(tensorInfo);
230
231 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000232 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100233
Sadik Armagan6e36a642020-11-10 21:18:41 +0000234 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100235 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000236
Sadik Armagan62483be2020-10-23 17:14:43 +0100237 return kTfLiteOk;
238}
239
240TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
241 TfLiteContext* tfLiteContext,
242 const TfLiteIntArray* outputs,
243 std::vector<armnn::BindingPointInfo>& outputBindings)
244{
Finn Williams6f9f9902020-11-13 13:23:15 +0000245 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100246 for (unsigned int i = 0; i < numOutputs; ++i)
247 {
248 const int32_t tensorId = outputs->data[i];
249 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
250
251 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
252 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
253
254 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Finn Williams6f9f9902020-11-13 13:23:15 +0000255 ARMNN_ASSERT(delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] != nullptr);
256 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100257 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
258 }
259
260 return kTfLiteOk;
261}
262
Sadik Armagan3c24f432020-10-19 17:35:30 +0100263ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
264 const TfLiteDelegateParams* parameters,
265 const Delegate* delegate)
266{
267 TfLiteIntArray* executionPlan;
268 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
269 {
270 return nullptr;
271 }
272
Sadik Armagan62483be2020-10-23 17:14:43 +0100273 // Initialize DelegateData holds network and output slots information
274 DelegateData delegateData(delegate->m_Options.GetBackends());
275
276 // Build ArmNN Network
Sadik Armagan3c24f432020-10-19 17:35:30 +0100277 armnn::NetworkOptions networkOptions = {};
278 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100279 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100280
Sadik Armagan6e36a642020-11-10 21:18:41 +0000281 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
282
Sadik Armagan62483be2020-10-23 17:14:43 +0100283
284 std::vector<armnn::BindingPointInfo> inputBindings;
285 std::vector<armnn::BindingPointInfo> outputBindings;
286
287 // Add input layer
288 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
289 if (status != kTfLiteOk)
290 {
291 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
292 }
293
294 // Parse TfLite delegate nodes to ArmNN
Sadik Armagan3c24f432020-10-19 17:35:30 +0100295 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
296 {
297 const int nodeIndex = parameters->nodes_to_replace->data[i];
298
299 TfLiteNode* tfLiteNode = nullptr;
300 TfLiteRegistration* tfLiteRegistration = nullptr;
301 if (tfLiteContext->GetNodeAndRegistration(
302 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
303 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000304 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100305 }
306
Sadik Armagan62483be2020-10-23 17:14:43 +0100307 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100308 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000309 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100310 }
311 }
312
Sadik Armagan62483be2020-10-23 17:14:43 +0100313 // Add Output layer
314 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
315 if (status != kTfLiteOk)
316 {
317 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
318 }
319
320 // Optimize ArmNN network
321 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
322 try
323 {
Sadik Armagan6e36a642020-11-10 21:18:41 +0000324 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100325 delegate->m_Options.GetBackends(),
326 delegate->m_Runtime->GetDeviceSpec());
327 }
328 catch (std::exception &ex)
329 {
330 std::stringstream exMessage;
331 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
332 throw armnn::Exception(exMessage.str());
333 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100334 if (!optNet)
335 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100336 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100337 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
338 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100339
340 try
341 {
342 // Load graph into runtime
343 auto loadingStatus = delegate->m_Runtime->LoadNetwork(networkId, std::move(optNet));
344 if (loadingStatus != armnn::Status::Success)
345 {
346 // Optimize failed
347 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded!");;
348 }
349 }
350 catch (std::exception& ex)
351 {
352 std::stringstream exMessage;
353 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
354 throw armnn::Exception(exMessage.str());
355 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100356
357 // Create a new SubGraph with networkId and runtime
Sadik Armagan62483be2020-10-23 17:14:43 +0100358 return new ArmnnSubgraph(networkId, delegate->m_Runtime.get(), inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100359}
360
361TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
362{
Finn Williams6f9f9902020-11-13 13:23:15 +0000363 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100364 return kTfLiteOk;
365}
366
Sadik Armagan62483be2020-10-23 17:14:43 +0100367TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100368{
Sadik Armagan62483be2020-10-23 17:14:43 +0100369 // Prepare inputs
370 armnn::InputTensors inputTensors;
371 size_t inputIndex = 0;
372 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
373 {
374 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
375 if (tensor->allocation_type != kTfLiteMmapRo)
376 {
377 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
378 const armnn::ConstTensor inputTensor(inputBinding.second, tensor->data.data);
379 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100380
Sadik Armagan62483be2020-10-23 17:14:43 +0100381 ++inputIndex;
382 }
383 }
384
385 // Prepare outputs
386 armnn::OutputTensors outputTensors;
387 size_t outputIndex = 0;
388 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
389 {
390 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
391 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
392 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
393 outputTensors.emplace_back(outputIdx, outputTensor);
394
395 ++outputIndex;
396 }
397
398 // Run graph
399 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
400 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100401}
402
Sadik Armagan62483be2020-10-23 17:14:43 +0100403TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100404 TfLiteContext* tfLiteContext,
405 TfLiteRegistration* tfLiteRegistration,
406 TfLiteNode* tfLiteNode,
407 int nodeIndex)
408{
Sadik Armagan62483be2020-10-23 17:14:43 +0100409 switch (tfLiteRegistration->builtin_code)
410 {
411 case kTfLiteBuiltinAbs:
412 return VisitElementwiseUnaryOperator(delegateData,
413 tfLiteContext,
414 tfLiteNode,
415 nodeIndex,
416 armnn::UnaryOperation::Abs);
417 case kTfLiteBuiltinAdd:
418 return VisitElementwiseBinaryOperator(delegateData,
419 tfLiteContext,
420 tfLiteNode,
421 nodeIndex,
422 kTfLiteBuiltinAdd);
423 case kTfLiteBuiltinArgMax:
424 return VisitArgMinMaxOperator(delegateData,
425 tfLiteContext,
426 tfLiteNode,
427 nodeIndex,
428 kTfLiteBuiltinArgMax);
429 case kTfLiteBuiltinArgMin:
430 return VisitArgMinMaxOperator(delegateData,
431 tfLiteContext,
432 tfLiteNode,
433 nodeIndex,
434 kTfLiteBuiltinArgMin);
435 case kTfLiteBuiltinAveragePool2d:
436 return VisitPoolingOperator(delegateData,
437 tfLiteContext,
438 tfLiteNode,
439 nodeIndex,
440 kTfLiteBuiltinAveragePool2d);
441 case kTfLiteBuiltinBatchToSpaceNd:
442 return VisitBatchToSpaceNdOperator(delegateData,
443 tfLiteContext,
444 tfLiteNode,
445 nodeIndex,
446 kTfLiteBuiltinBatchToSpaceNd);
447 case kTfLiteBuiltinConcatenation:
448 return VisitControlOperator(delegateData,
449 tfLiteContext,
450 tfLiteNode,
451 nodeIndex,
452 kTfLiteBuiltinConcatenation);
453 case kTfLiteBuiltinConv2d:
454 return VisitConvolutionOperator(delegateData,
455 tfLiteContext,
456 tfLiteNode,
457 nodeIndex,
458 kTfLiteBuiltinConv2d);
459 case kTfLiteBuiltinDepthToSpace:
460 return VisitDepthToSpaceOperator(delegateData,
461 tfLiteContext,
462 tfLiteNode,
463 nodeIndex,
464 kTfLiteBuiltinDepthToSpace);
465 case kTfLiteBuiltinDepthwiseConv2d:
466 return VisitConvolutionOperator(delegateData,
467 tfLiteContext,
468 tfLiteNode,
469 nodeIndex,
470 kTfLiteBuiltinDepthwiseConv2d);
471 case kTfLiteBuiltinDequantize:
472 return VisitDequantizeOperator(delegateData,
473 tfLiteContext,
474 tfLiteNode,
475 nodeIndex,
476 kTfLiteBuiltinDequantize);
477 case kTfLiteBuiltinDiv:
478 return VisitElementwiseBinaryOperator(delegateData,
479 tfLiteContext,
480 tfLiteNode,
481 nodeIndex,
482 kTfLiteBuiltinDiv);
483 case kTfLiteBuiltinElu:
484 return VisitActivationOperator(delegateData,
485 tfLiteContext,
486 tfLiteNode,
487 nodeIndex,
488 kTfLiteBuiltinElu);
489 case kTfLiteBuiltinEqual:
490 return VisitComparisonOperator(delegateData,
491 tfLiteContext,
492 tfLiteNode,
493 nodeIndex,
494 kTfLiteBuiltinEqual);
495 case kTfLiteBuiltinExp:
496 return VisitElementwiseUnaryOperator(delegateData,
497 tfLiteContext,
498 tfLiteNode,
499 nodeIndex,
500 armnn::UnaryOperation::Exp);
501 case kTfLiteBuiltinExpandDims:
502 return VisitExpandDimsOperator(delegateData,
503 tfLiteContext,
504 tfLiteNode,
505 nodeIndex,
506 kTfLiteBuiltinExpandDims);
507 case kTfLiteBuiltinFill:
508 return VisitFillOperator(delegateData,
509 tfLiteContext,
510 tfLiteNode,
511 nodeIndex,
512 kTfLiteBuiltinFill);
513 case kTfLiteBuiltinFloor:
514 return VisitFloorOperator(delegateData,
515 tfLiteContext,
516 tfLiteNode,
517 nodeIndex,
518 kTfLiteBuiltinFloor);
519 case kTfLiteBuiltinFullyConnected:
520 return VisitFullyConnectedOperator(delegateData,
521 tfLiteContext,
522 tfLiteNode,
523 nodeIndex,
524 kTfLiteBuiltinFullyConnected);
525 case kTfLiteBuiltinGather:
526 return VisitGatherOperator(delegateData,
527 tfLiteContext,
528 tfLiteNode,
529 nodeIndex,
530 kTfLiteBuiltinGather);
531 case kTfLiteBuiltinGatherNd:
532 return VisitGatherOperator(delegateData,
533 tfLiteContext,
534 tfLiteNode,
535 nodeIndex,
536 kTfLiteBuiltinGatherNd);
537 case kTfLiteBuiltinGreater:
538 return VisitComparisonOperator(delegateData,
539 tfLiteContext,
540 tfLiteNode,
541 nodeIndex,
542 kTfLiteBuiltinGreater);
543 case kTfLiteBuiltinGreaterEqual:
544 return VisitComparisonOperator(delegateData,
545 tfLiteContext,
546 tfLiteNode,
547 nodeIndex,
548 kTfLiteBuiltinGreaterEqual);
549 case kTfLiteBuiltinHardSwish:
550 return VisitActivationOperator(delegateData,
551 tfLiteContext,
552 tfLiteNode,
553 nodeIndex,
554 kTfLiteBuiltinHardSwish);
555 case kTfLiteBuiltinL2Normalization:
556 return VisitNormalizationOperator(delegateData,
557 tfLiteContext,
558 tfLiteNode,
559 nodeIndex,
560 kTfLiteBuiltinL2Normalization);
561 case kTfLiteBuiltinL2Pool2d:
562 return VisitPoolingOperator(delegateData,
563 tfLiteContext,
564 tfLiteNode,
565 nodeIndex,
566 kTfLiteBuiltinL2Pool2d);
567 case kTfLiteBuiltinLess:
568 return VisitComparisonOperator(delegateData,
569 tfLiteContext,
570 tfLiteNode,
571 nodeIndex,
572 kTfLiteBuiltinLess);
573 case kTfLiteBuiltinLessEqual:
574 return VisitComparisonOperator(delegateData,
575 tfLiteContext,
576 tfLiteNode,
577 nodeIndex,
578 kTfLiteBuiltinLessEqual);
579 case kTfLiteBuiltinLocalResponseNormalization:
580 return VisitNormalizationOperator(delegateData,
581 tfLiteContext,
582 tfLiteNode,
583 nodeIndex,
584 kTfLiteBuiltinLocalResponseNormalization);
585 case kTfLiteBuiltinLogistic:
586 return VisitActivationOperator(delegateData,
587 tfLiteContext,
588 tfLiteNode,
589 nodeIndex,
590 kTfLiteBuiltinLogistic);
591 case kTfLiteBuiltinLogSoftmax:
592 return VisitSoftmaxOperator(delegateData,
593 tfLiteContext,
594 tfLiteNode,
595 nodeIndex,
596 kTfLiteBuiltinLogSoftmax);
597 case kTfLiteBuiltinLstm:
598 return VisitLstmOperator(delegateData,
599 tfLiteContext,
600 tfLiteNode,
601 nodeIndex,
602 kTfLiteBuiltinLstm);
603 case kTfLiteBuiltinMaxPool2d:
604 return VisitPoolingOperator(delegateData,
605 tfLiteContext,
606 tfLiteNode,
607 nodeIndex,
608 kTfLiteBuiltinMaxPool2d);
609 case kTfLiteBuiltinMaximum:
610 return VisitElementwiseBinaryOperator(delegateData,
611 tfLiteContext,
612 tfLiteNode,
613 nodeIndex,
614 kTfLiteBuiltinMaximum);
615 case kTfLiteBuiltinMean:
616 return VisitControlOperator(delegateData,
617 tfLiteContext,
618 tfLiteNode,
619 nodeIndex,
620 kTfLiteBuiltinMean);
621 case kTfLiteBuiltinMinimum:
622 return VisitElementwiseBinaryOperator(delegateData,
623 tfLiteContext,
624 tfLiteNode,
625 nodeIndex,
626 kTfLiteBuiltinMinimum);
627 case kTfLiteBuiltinMul:
628 return VisitElementwiseBinaryOperator(delegateData,
629 tfLiteContext,
630 tfLiteNode,
631 nodeIndex,
632 kTfLiteBuiltinMul);
633 case kTfLiteBuiltinNeg:
634 return VisitElementwiseUnaryOperator(delegateData,
635 tfLiteContext,
636 tfLiteNode,
637 nodeIndex,
638 armnn::UnaryOperation::Neg);
639 case kTfLiteBuiltinNotEqual:
640 return VisitComparisonOperator(delegateData,
641 tfLiteContext,
642 tfLiteNode,
643 nodeIndex,
644 kTfLiteBuiltinNotEqual);
645 case kTfLiteBuiltinPad:
646 return VisitPadOperator(delegateData,
647 tfLiteContext,
648 tfLiteNode,
649 nodeIndex,
650 kTfLiteBuiltinPad);
651 case kTfLiteBuiltinPadv2:
652 return VisitPadOperator(delegateData,
653 tfLiteContext,
654 tfLiteNode,
655 nodeIndex,
656 kTfLiteBuiltinPadv2);
657 case kTfLiteBuiltinPrelu:
658 return VisitActivationOperator(delegateData,
659 tfLiteContext,
660 tfLiteNode,
661 nodeIndex,
662 kTfLiteBuiltinPrelu);
663 case kTfLiteBuiltinQuantize:
664 return VisitQuantizeOperator(delegateData,
665 tfLiteContext,
666 tfLiteNode,
667 nodeIndex,
668 kTfLiteBuiltinQuantize);
669 case kTfLiteBuiltinRank:
670 return VisitControlOperator(delegateData,
671 tfLiteContext,
672 tfLiteNode,
673 nodeIndex,
674 kTfLiteBuiltinRank);
675 case kTfLiteBuiltinRelu:
676 return VisitActivationOperator(delegateData,
677 tfLiteContext,
678 tfLiteNode,
679 nodeIndex,
680 kTfLiteBuiltinRelu);
681 case kTfLiteBuiltinReluN1To1:
682 return VisitActivationOperator(delegateData,
683 tfLiteContext,
684 tfLiteNode,
685 nodeIndex,
686 kTfLiteBuiltinReluN1To1);
687 case kTfLiteBuiltinRelu6:
688 return VisitActivationOperator(delegateData,
689 tfLiteContext,
690 tfLiteNode,
691 nodeIndex,
692 kTfLiteBuiltinRelu6);
693 case kTfLiteBuiltinReshape:
694 return VisitReshapeOperator(delegateData,
695 tfLiteContext,
696 tfLiteNode,
697 nodeIndex,
698 kTfLiteBuiltinReshape);
699 case kTfLiteBuiltinResizeBilinear:
700 return VisitResizeOperator(delegateData,
701 tfLiteContext,
702 tfLiteNode,
703 nodeIndex,
704 kTfLiteBuiltinResizeBilinear);
705 case kTfLiteBuiltinResizeNearestNeighbor:
706 return VisitResizeOperator(delegateData,
707 tfLiteContext,
708 tfLiteNode,
709 nodeIndex,
710 kTfLiteBuiltinResizeNearestNeighbor);
711 case kTfLiteBuiltinRsqrt:
712 return VisitElementwiseUnaryOperator(delegateData,
713 tfLiteContext,
714 tfLiteNode,
715 nodeIndex,
716 armnn::UnaryOperation::Rsqrt);
717 case kTfLiteBuiltinSqrt:
718 return VisitElementwiseUnaryOperator(delegateData,
719 tfLiteContext,
720 tfLiteNode,
721 nodeIndex,
722 armnn::UnaryOperation::Sqrt);
723 case kTfLiteBuiltinSqueeze:
724 return VisitSqueezeOperator(delegateData,
725 tfLiteContext,
726 tfLiteNode,
727 nodeIndex,
728 kTfLiteBuiltinSqueeze);
729 case kTfLiteBuiltinStridedSlice:
730 return VisitSliceOperator(delegateData,
731 tfLiteContext,
732 tfLiteNode,
733 nodeIndex,
734 kTfLiteBuiltinStridedSlice);
735 case kTfLiteBuiltinTranspose:
736 return VisitTransposeOperator(delegateData,
737 tfLiteContext,
738 tfLiteNode,
739 nodeIndex,
740 kTfLiteBuiltinTranspose);
741 case kTfLiteBuiltinTransposeConv:
742 return VisitConvolutionOperator(delegateData,
743 tfLiteContext,
744 tfLiteNode,
745 nodeIndex,
746 kTfLiteBuiltinTransposeConv);
747 case kTfLiteBuiltinSoftmax:
748 return VisitSoftmaxOperator(delegateData,
749 tfLiteContext,
750 tfLiteNode,
751 nodeIndex,
752 kTfLiteBuiltinSoftmax);
753 case kTfLiteBuiltinSpaceToBatchNd:
754 return VisitSpaceToBatchNdOperator(delegateData,
755 tfLiteContext,
756 tfLiteNode,
757 nodeIndex,
758 kTfLiteBuiltinSpaceToBatchNd);
759 case kTfLiteBuiltinSpaceToDepth:
760 return VisitSpaceToDepthOperator(delegateData,
761 tfLiteContext,
762 tfLiteNode,
763 nodeIndex,
764 kTfLiteBuiltinSpaceToDepth);
765 case kTfLiteBuiltinSub:
766 return VisitElementwiseBinaryOperator(delegateData,
767 tfLiteContext,
768 tfLiteNode,
769 nodeIndex,
770 kTfLiteBuiltinSub);
771 case kTfLiteBuiltinTanh:
772 return VisitActivationOperator(delegateData,
773 tfLiteContext,
774 tfLiteNode,
775 nodeIndex,
776 kTfLiteBuiltinTanh);
777 default:
778 return kTfLiteError;
779 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100780}
781
782} // armnnDelegate namespace