blob: 6250a5f6388e06e668a74cddf92751ef8c780469 [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"
Matthew Sloyanc8eb9552020-11-26 10:54:22 +000019#include "LogicalBinary.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010020#include "Lstm.hpp"
21#include "Normalization.hpp"
22#include "Pad.hpp"
23#include "Pooling.hpp"
24#include "Quantization.hpp"
25#include "Redefine.hpp"
26#include "Resize.hpp"
27#include "Round.hpp"
28#include "Slice.hpp"
29#include "Softmax.hpp"
30#include "SpaceDepth.hpp"
Sadik Armagan34fa1bd2020-11-27 12:40:52 +000031#include "Split.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010032#include "Transpose.hpp"
33
34#include <flatbuffers/flatbuffers.h>
35#include <tensorflow/lite/context_util.h>
36
Sadik Armagan3c24f432020-10-19 17:35:30 +010037#include <algorithm>
Sadik Armagan62483be2020-10-23 17:14:43 +010038#include <sstream>
Sadik Armagan3c24f432020-10-19 17:35:30 +010039
40namespace armnnDelegate
41{
42
Sadik Armagan62483be2020-10-23 17:14:43 +010043DelegateOptions TfLiteArmnnDelegateOptionsDefault()
44{
45 DelegateOptions options(armnn::Compute::CpuRef);
46 return options;
47}
48
49TfLiteDelegate* TfLiteArmnnDelegateCreate(armnnDelegate::DelegateOptions options)
50{
51 auto* armnnDelegate = new ::armnnDelegate::Delegate(options);
52 return armnnDelegate->GetDelegate();
53}
54
55void TfLiteArmnnDelegateDelete(TfLiteDelegate* tfLiteDelegate)
56{
57 if (tfLiteDelegate != nullptr)
58 {
59 delete static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_);
60 }
61}
62
63TfLiteStatus DoPrepare(TfLiteContext* tfLiteContext, TfLiteDelegate* tfLiteDelegate)
64{
65 TfLiteIntArray* supportedOperators =
66 static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_)->IdentifyOperatorsToDelegate(tfLiteContext);
67
68 // ArmNN Delegate Registration
69 static const TfLiteRegistration kArmnnSubgraphRegistration = {
70 // ArmnnSubgraph Init
71 .init = [](TfLiteContext* tfLiteContext, const char* buffer, size_t length) -> void* {
Finn Williams6f9f9902020-11-13 13:23:15 +000072 armnn::IgnoreUnused(length);
Sadik Armagan62483be2020-10-23 17:14:43 +010073 const TfLiteDelegateParams* parameters = reinterpret_cast<const TfLiteDelegateParams*>(buffer);
74
75 return static_cast<void*>(ArmnnSubgraph::Create(
76 tfLiteContext, parameters, static_cast<::armnnDelegate::Delegate*>(parameters->delegate->data_)));
77 },
78 // ArmnnSubgraph Free
79 .free = [](TfLiteContext* tfLiteContext, void* buffer) -> void {
Finn Williams6f9f9902020-11-13 13:23:15 +000080 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan62483be2020-10-23 17:14:43 +010081 if (buffer != nullptr)
82 {
83 delete static_cast<ArmnnSubgraph*>(buffer);
84 }
85 },
86 // ArmnnSubgraph Prepare
87 .prepare = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
88 if (tfLiteNode->user_data == nullptr)
89 {
90 return kTfLiteError;
91 }
Sadik Armagan62483be2020-10-23 17:14:43 +010092 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Prepare(tfLiteContext);
93 },
94 // ArmnnSubgraph Invoke
95 .invoke = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
96 if (tfLiteNode->user_data == nullptr)
97 {
98 return kTfLiteError;
99 }
100
101 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Invoke(tfLiteContext, tfLiteNode);
102 },
103
104 .profiling_string = nullptr,
105 .builtin_code = kTfLiteBuiltinDelegate,
106 .custom_name = "TfLiteArmNnDelegate",
107 .version = 1,
108 };
109
110 const TfLiteStatus status =
111 tfLiteContext->ReplaceNodeSubsetsWithDelegateKernels(
112 tfLiteContext, kArmnnSubgraphRegistration, supportedOperators, tfLiteDelegate);
113
114 TfLiteIntArrayFree(supportedOperators);
115 return status;
116
117}
118
Sadik Armagan3c24f432020-10-19 17:35:30 +0100119Delegate::Delegate(armnnDelegate::DelegateOptions options)
120 : m_Runtime(nullptr, nullptr),
121 m_Options(std::move(options))
122{
Jan Eilers2cd18472020-12-15 10:42:38 +0000123 // Configures logging for ARMNN
124 if (options.IsLoggingEnabled())
125 {
126 armnn::ConfigureLogging(true, true, options.GetLoggingSeverity());
127 }
128
Sadik Armagan3c24f432020-10-19 17:35:30 +0100129 // Create ArmNN Runtime
130 armnn::IRuntime::CreationOptions runtimeOptions;
Sadik Armagan4189cc52020-11-11 18:01:48 +0000131
132 auto backendOptions = m_Options.GetBackendOptions();
133 if (!backendOptions.empty())
134 {
135 runtimeOptions.m_BackendOptions = backendOptions;
136 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100137 m_Runtime = armnn::IRuntime::Create(runtimeOptions);
138
139 std::vector<armnn::BackendId> backends;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100140 if (m_Runtime)
141 {
142 const armnn::BackendIdSet supportedDevices = m_Runtime->GetDeviceSpec().GetSupportedBackends();
143 for (auto& backend : m_Options.GetBackends())
144 {
145 if (std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) == supportedDevices.cend())
146 {
Sadik Armagan0534e032020-10-27 17:30:18 +0000147 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100148 "TfLiteArmnnDelegate: Requested unknown backend %s", backend.Get().c_str());
149 }
150 else
151 {
152 backends.push_back(backend);
153 }
154 }
155 }
156
157 if (backends.empty())
158 {
159 // No known backend specified
160 throw armnn::InvalidArgumentException("TfLiteArmnnDelegate: No known backend specified.");
161 }
162 m_Options.SetBackends(backends);
163
164 TFLITE_LOG_PROD_ONCE(tflite::TFLITE_LOG_INFO, "TfLiteArmnnDelegate: Created TfLite ArmNN delegate.");
165}
166
Sadik Armagan62483be2020-10-23 17:14:43 +0100167TfLiteIntArray* Delegate::IdentifyOperatorsToDelegate(TfLiteContext* tfLiteContext)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100168{
169 TfLiteIntArray* executionPlan = nullptr;
170 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
171 {
172 TF_LITE_KERNEL_LOG(tfLiteContext, "TfLiteArmnnDelegate: Unable to get graph execution plan.");
173 return nullptr;
174 }
175
Sadik Armagan62483be2020-10-23 17:14:43 +0100176 // Delegate data with null network
177 DelegateData delegateData(m_Options.GetBackends());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100178
179 TfLiteIntArray* nodesToDelegate = TfLiteIntArrayCreate(executionPlan->size);
180 nodesToDelegate->size = 0;
181 for (int i = 0; i < executionPlan->size; ++i)
182 {
183 const int nodeIndex = executionPlan->data[i];
184
185 // If TfLite nodes can be delegated to ArmNN
186 TfLiteNode* tfLiteNode = nullptr;
187 TfLiteRegistration* tfLiteRegistration = nullptr;
188 if (tfLiteContext->GetNodeAndRegistration(
189 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
190 {
191 TF_LITE_KERNEL_LOG(tfLiteContext,
192 "TfLiteArmnnDelegate: Unable to get node and registration for node %d.",
193 nodeIndex);
194 continue;
195 }
196
197 if (ArmnnSubgraph::VisitNode(
Sadik Armagan62483be2020-10-23 17:14:43 +0100198 delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100199 {
200 // node is not supported by ArmNN
201 continue;
202 }
203
204 nodesToDelegate->data[nodesToDelegate->size++] = nodeIndex;
205 }
206
Sadik Armagan62483be2020-10-23 17:14:43 +0100207 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100208 return nodesToDelegate;
209}
210
211TfLiteDelegate* Delegate::GetDelegate()
212{
213 return &m_Delegate;
214}
215
Sadik Armagan62483be2020-10-23 17:14:43 +0100216TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
217 TfLiteContext* tfLiteContext,
218 const TfLiteIntArray* inputs,
219 std::vector<armnn::BindingPointInfo>& inputBindings)
220{
Finn Williams6f9f9902020-11-13 13:23:15 +0000221 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100222 for (unsigned int i = 0; i < numInputs; ++i)
223 {
224 const int32_t tensorId = inputs->data[i];
225 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000226 // Do not create bindings for constant inputs
227 if (tensor.allocation_type == kTfLiteMmapRo)
228 {
229 continue;
230 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100231
232 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
233 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
234
235 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
236 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
237 outputSlot.SetTensorInfo(tensorInfo);
238
239 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000240 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100241
Sadik Armagan6e36a642020-11-10 21:18:41 +0000242 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100243 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000244
Sadik Armagan62483be2020-10-23 17:14:43 +0100245 return kTfLiteOk;
246}
247
248TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
249 TfLiteContext* tfLiteContext,
250 const TfLiteIntArray* outputs,
251 std::vector<armnn::BindingPointInfo>& outputBindings)
252{
Finn Williams6f9f9902020-11-13 13:23:15 +0000253 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100254 for (unsigned int i = 0; i < numOutputs; ++i)
255 {
256 const int32_t tensorId = outputs->data[i];
257 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
258
259 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
260 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
261
262 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Finn Williams6f9f9902020-11-13 13:23:15 +0000263 ARMNN_ASSERT(delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] != nullptr);
264 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100265 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
266 }
267
268 return kTfLiteOk;
269}
270
Sadik Armagan3c24f432020-10-19 17:35:30 +0100271ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
272 const TfLiteDelegateParams* parameters,
273 const Delegate* delegate)
274{
275 TfLiteIntArray* executionPlan;
276 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
277 {
278 return nullptr;
279 }
280
Sadik Armagan62483be2020-10-23 17:14:43 +0100281 // Initialize DelegateData holds network and output slots information
282 DelegateData delegateData(delegate->m_Options.GetBackends());
283
284 // Build ArmNN Network
Sadik Armagan3c24f432020-10-19 17:35:30 +0100285 armnn::NetworkOptions networkOptions = {};
286 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100287 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100288
Sadik Armagan6e36a642020-11-10 21:18:41 +0000289 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
290
Sadik Armagan62483be2020-10-23 17:14:43 +0100291
292 std::vector<armnn::BindingPointInfo> inputBindings;
293 std::vector<armnn::BindingPointInfo> outputBindings;
294
295 // Add input layer
296 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
297 if (status != kTfLiteOk)
298 {
299 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
300 }
301
302 // Parse TfLite delegate nodes to ArmNN
Sadik Armagan3c24f432020-10-19 17:35:30 +0100303 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
304 {
305 const int nodeIndex = parameters->nodes_to_replace->data[i];
306
307 TfLiteNode* tfLiteNode = nullptr;
308 TfLiteRegistration* tfLiteRegistration = nullptr;
309 if (tfLiteContext->GetNodeAndRegistration(
310 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
311 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000312 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100313 }
314
Sadik Armagan62483be2020-10-23 17:14:43 +0100315 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100316 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000317 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100318 }
319 }
320
Sadik Armagan62483be2020-10-23 17:14:43 +0100321 // Add Output layer
322 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
323 if (status != kTfLiteOk)
324 {
325 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
326 }
327
328 // Optimize ArmNN network
329 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
330 try
331 {
Sadik Armagan6e36a642020-11-10 21:18:41 +0000332 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100333 delegate->m_Options.GetBackends(),
334 delegate->m_Runtime->GetDeviceSpec());
335 }
336 catch (std::exception &ex)
337 {
338 std::stringstream exMessage;
339 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
340 throw armnn::Exception(exMessage.str());
341 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100342 if (!optNet)
343 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100344 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100345 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
346 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100347
348 try
349 {
350 // Load graph into runtime
351 auto loadingStatus = delegate->m_Runtime->LoadNetwork(networkId, std::move(optNet));
352 if (loadingStatus != armnn::Status::Success)
353 {
354 // Optimize failed
355 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded!");;
356 }
357 }
358 catch (std::exception& ex)
359 {
360 std::stringstream exMessage;
361 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
362 throw armnn::Exception(exMessage.str());
363 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100364
365 // Create a new SubGraph with networkId and runtime
Sadik Armagan62483be2020-10-23 17:14:43 +0100366 return new ArmnnSubgraph(networkId, delegate->m_Runtime.get(), inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100367}
368
369TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
370{
Finn Williams6f9f9902020-11-13 13:23:15 +0000371 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100372 return kTfLiteOk;
373}
374
Sadik Armagan62483be2020-10-23 17:14:43 +0100375TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100376{
Sadik Armagan62483be2020-10-23 17:14:43 +0100377 // Prepare inputs
378 armnn::InputTensors inputTensors;
379 size_t inputIndex = 0;
380 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
381 {
382 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
383 if (tensor->allocation_type != kTfLiteMmapRo)
384 {
385 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
386 const armnn::ConstTensor inputTensor(inputBinding.second, tensor->data.data);
387 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100388
Sadik Armagan62483be2020-10-23 17:14:43 +0100389 ++inputIndex;
390 }
391 }
392
393 // Prepare outputs
394 armnn::OutputTensors outputTensors;
395 size_t outputIndex = 0;
396 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
397 {
398 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
399 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
400 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
401 outputTensors.emplace_back(outputIdx, outputTensor);
402
403 ++outputIndex;
404 }
405
406 // Run graph
407 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
408 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100409}
410
Sadik Armagan62483be2020-10-23 17:14:43 +0100411TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100412 TfLiteContext* tfLiteContext,
413 TfLiteRegistration* tfLiteRegistration,
414 TfLiteNode* tfLiteNode,
415 int nodeIndex)
416{
Sadik Armagan62483be2020-10-23 17:14:43 +0100417 switch (tfLiteRegistration->builtin_code)
418 {
419 case kTfLiteBuiltinAbs:
420 return VisitElementwiseUnaryOperator(delegateData,
421 tfLiteContext,
422 tfLiteNode,
423 nodeIndex,
424 armnn::UnaryOperation::Abs);
425 case kTfLiteBuiltinAdd:
426 return VisitElementwiseBinaryOperator(delegateData,
427 tfLiteContext,
428 tfLiteNode,
429 nodeIndex,
430 kTfLiteBuiltinAdd);
431 case kTfLiteBuiltinArgMax:
432 return VisitArgMinMaxOperator(delegateData,
433 tfLiteContext,
434 tfLiteNode,
435 nodeIndex,
436 kTfLiteBuiltinArgMax);
437 case kTfLiteBuiltinArgMin:
438 return VisitArgMinMaxOperator(delegateData,
439 tfLiteContext,
440 tfLiteNode,
441 nodeIndex,
442 kTfLiteBuiltinArgMin);
443 case kTfLiteBuiltinAveragePool2d:
444 return VisitPoolingOperator(delegateData,
445 tfLiteContext,
446 tfLiteNode,
447 nodeIndex,
448 kTfLiteBuiltinAveragePool2d);
449 case kTfLiteBuiltinBatchToSpaceNd:
450 return VisitBatchToSpaceNdOperator(delegateData,
451 tfLiteContext,
452 tfLiteNode,
453 nodeIndex,
454 kTfLiteBuiltinBatchToSpaceNd);
455 case kTfLiteBuiltinConcatenation:
456 return VisitControlOperator(delegateData,
457 tfLiteContext,
458 tfLiteNode,
459 nodeIndex,
460 kTfLiteBuiltinConcatenation);
461 case kTfLiteBuiltinConv2d:
462 return VisitConvolutionOperator(delegateData,
463 tfLiteContext,
464 tfLiteNode,
465 nodeIndex,
466 kTfLiteBuiltinConv2d);
467 case kTfLiteBuiltinDepthToSpace:
468 return VisitDepthToSpaceOperator(delegateData,
469 tfLiteContext,
470 tfLiteNode,
471 nodeIndex,
472 kTfLiteBuiltinDepthToSpace);
473 case kTfLiteBuiltinDepthwiseConv2d:
474 return VisitConvolutionOperator(delegateData,
475 tfLiteContext,
476 tfLiteNode,
477 nodeIndex,
478 kTfLiteBuiltinDepthwiseConv2d);
479 case kTfLiteBuiltinDequantize:
480 return VisitDequantizeOperator(delegateData,
481 tfLiteContext,
482 tfLiteNode,
483 nodeIndex,
484 kTfLiteBuiltinDequantize);
485 case kTfLiteBuiltinDiv:
486 return VisitElementwiseBinaryOperator(delegateData,
487 tfLiteContext,
488 tfLiteNode,
489 nodeIndex,
490 kTfLiteBuiltinDiv);
491 case kTfLiteBuiltinElu:
492 return VisitActivationOperator(delegateData,
493 tfLiteContext,
494 tfLiteNode,
495 nodeIndex,
496 kTfLiteBuiltinElu);
497 case kTfLiteBuiltinEqual:
498 return VisitComparisonOperator(delegateData,
499 tfLiteContext,
500 tfLiteNode,
501 nodeIndex,
502 kTfLiteBuiltinEqual);
503 case kTfLiteBuiltinExp:
504 return VisitElementwiseUnaryOperator(delegateData,
505 tfLiteContext,
506 tfLiteNode,
507 nodeIndex,
508 armnn::UnaryOperation::Exp);
509 case kTfLiteBuiltinExpandDims:
510 return VisitExpandDimsOperator(delegateData,
511 tfLiteContext,
512 tfLiteNode,
513 nodeIndex,
514 kTfLiteBuiltinExpandDims);
515 case kTfLiteBuiltinFill:
516 return VisitFillOperator(delegateData,
517 tfLiteContext,
518 tfLiteNode,
519 nodeIndex,
520 kTfLiteBuiltinFill);
521 case kTfLiteBuiltinFloor:
522 return VisitFloorOperator(delegateData,
523 tfLiteContext,
524 tfLiteNode,
525 nodeIndex,
526 kTfLiteBuiltinFloor);
527 case kTfLiteBuiltinFullyConnected:
528 return VisitFullyConnectedOperator(delegateData,
529 tfLiteContext,
530 tfLiteNode,
531 nodeIndex,
532 kTfLiteBuiltinFullyConnected);
533 case kTfLiteBuiltinGather:
534 return VisitGatherOperator(delegateData,
535 tfLiteContext,
536 tfLiteNode,
537 nodeIndex,
538 kTfLiteBuiltinGather);
539 case kTfLiteBuiltinGatherNd:
540 return VisitGatherOperator(delegateData,
541 tfLiteContext,
542 tfLiteNode,
543 nodeIndex,
544 kTfLiteBuiltinGatherNd);
545 case kTfLiteBuiltinGreater:
546 return VisitComparisonOperator(delegateData,
547 tfLiteContext,
548 tfLiteNode,
549 nodeIndex,
550 kTfLiteBuiltinGreater);
551 case kTfLiteBuiltinGreaterEqual:
552 return VisitComparisonOperator(delegateData,
553 tfLiteContext,
554 tfLiteNode,
555 nodeIndex,
556 kTfLiteBuiltinGreaterEqual);
557 case kTfLiteBuiltinHardSwish:
558 return VisitActivationOperator(delegateData,
559 tfLiteContext,
560 tfLiteNode,
561 nodeIndex,
562 kTfLiteBuiltinHardSwish);
563 case kTfLiteBuiltinL2Normalization:
564 return VisitNormalizationOperator(delegateData,
565 tfLiteContext,
566 tfLiteNode,
567 nodeIndex,
568 kTfLiteBuiltinL2Normalization);
569 case kTfLiteBuiltinL2Pool2d:
570 return VisitPoolingOperator(delegateData,
571 tfLiteContext,
572 tfLiteNode,
573 nodeIndex,
574 kTfLiteBuiltinL2Pool2d);
575 case kTfLiteBuiltinLess:
576 return VisitComparisonOperator(delegateData,
577 tfLiteContext,
578 tfLiteNode,
579 nodeIndex,
580 kTfLiteBuiltinLess);
581 case kTfLiteBuiltinLessEqual:
582 return VisitComparisonOperator(delegateData,
583 tfLiteContext,
584 tfLiteNode,
585 nodeIndex,
586 kTfLiteBuiltinLessEqual);
587 case kTfLiteBuiltinLocalResponseNormalization:
588 return VisitNormalizationOperator(delegateData,
589 tfLiteContext,
590 tfLiteNode,
591 nodeIndex,
592 kTfLiteBuiltinLocalResponseNormalization);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000593 case kTfLiteBuiltinLogicalAnd:
594 return VisitLogicalBinaryOperator(delegateData,
595 tfLiteContext,
596 tfLiteNode,
597 nodeIndex,
598 kTfLiteBuiltinLogicalAnd,
599 armnn::LogicalBinaryOperation::LogicalAnd);
600 case kTfLiteBuiltinLogicalNot:
601 return VisitElementwiseUnaryOperator(delegateData,
602 tfLiteContext,
603 tfLiteNode,
604 nodeIndex,
605 armnn::UnaryOperation::LogicalNot);
606 case kTfLiteBuiltinLogicalOr:
607 return VisitLogicalBinaryOperator(delegateData,
608 tfLiteContext,
609 tfLiteNode,
610 nodeIndex,
611 kTfLiteBuiltinLogicalOr,
612 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100613 case kTfLiteBuiltinLogistic:
614 return VisitActivationOperator(delegateData,
615 tfLiteContext,
616 tfLiteNode,
617 nodeIndex,
618 kTfLiteBuiltinLogistic);
619 case kTfLiteBuiltinLogSoftmax:
620 return VisitSoftmaxOperator(delegateData,
621 tfLiteContext,
622 tfLiteNode,
623 nodeIndex,
624 kTfLiteBuiltinLogSoftmax);
625 case kTfLiteBuiltinLstm:
626 return VisitLstmOperator(delegateData,
627 tfLiteContext,
628 tfLiteNode,
629 nodeIndex,
630 kTfLiteBuiltinLstm);
631 case kTfLiteBuiltinMaxPool2d:
632 return VisitPoolingOperator(delegateData,
633 tfLiteContext,
634 tfLiteNode,
635 nodeIndex,
636 kTfLiteBuiltinMaxPool2d);
637 case kTfLiteBuiltinMaximum:
638 return VisitElementwiseBinaryOperator(delegateData,
639 tfLiteContext,
640 tfLiteNode,
641 nodeIndex,
642 kTfLiteBuiltinMaximum);
643 case kTfLiteBuiltinMean:
644 return VisitControlOperator(delegateData,
645 tfLiteContext,
646 tfLiteNode,
647 nodeIndex,
648 kTfLiteBuiltinMean);
649 case kTfLiteBuiltinMinimum:
650 return VisitElementwiseBinaryOperator(delegateData,
651 tfLiteContext,
652 tfLiteNode,
653 nodeIndex,
654 kTfLiteBuiltinMinimum);
655 case kTfLiteBuiltinMul:
656 return VisitElementwiseBinaryOperator(delegateData,
657 tfLiteContext,
658 tfLiteNode,
659 nodeIndex,
660 kTfLiteBuiltinMul);
661 case kTfLiteBuiltinNeg:
662 return VisitElementwiseUnaryOperator(delegateData,
663 tfLiteContext,
664 tfLiteNode,
665 nodeIndex,
666 armnn::UnaryOperation::Neg);
667 case kTfLiteBuiltinNotEqual:
668 return VisitComparisonOperator(delegateData,
669 tfLiteContext,
670 tfLiteNode,
671 nodeIndex,
672 kTfLiteBuiltinNotEqual);
673 case kTfLiteBuiltinPad:
674 return VisitPadOperator(delegateData,
675 tfLiteContext,
676 tfLiteNode,
677 nodeIndex,
678 kTfLiteBuiltinPad);
679 case kTfLiteBuiltinPadv2:
680 return VisitPadOperator(delegateData,
681 tfLiteContext,
682 tfLiteNode,
683 nodeIndex,
684 kTfLiteBuiltinPadv2);
685 case kTfLiteBuiltinPrelu:
686 return VisitActivationOperator(delegateData,
687 tfLiteContext,
688 tfLiteNode,
689 nodeIndex,
690 kTfLiteBuiltinPrelu);
691 case kTfLiteBuiltinQuantize:
692 return VisitQuantizeOperator(delegateData,
693 tfLiteContext,
694 tfLiteNode,
695 nodeIndex,
696 kTfLiteBuiltinQuantize);
697 case kTfLiteBuiltinRank:
698 return VisitControlOperator(delegateData,
699 tfLiteContext,
700 tfLiteNode,
701 nodeIndex,
702 kTfLiteBuiltinRank);
703 case kTfLiteBuiltinRelu:
704 return VisitActivationOperator(delegateData,
705 tfLiteContext,
706 tfLiteNode,
707 nodeIndex,
708 kTfLiteBuiltinRelu);
709 case kTfLiteBuiltinReluN1To1:
710 return VisitActivationOperator(delegateData,
711 tfLiteContext,
712 tfLiteNode,
713 nodeIndex,
714 kTfLiteBuiltinReluN1To1);
715 case kTfLiteBuiltinRelu6:
716 return VisitActivationOperator(delegateData,
717 tfLiteContext,
718 tfLiteNode,
719 nodeIndex,
720 kTfLiteBuiltinRelu6);
721 case kTfLiteBuiltinReshape:
722 return VisitReshapeOperator(delegateData,
723 tfLiteContext,
724 tfLiteNode,
725 nodeIndex,
726 kTfLiteBuiltinReshape);
727 case kTfLiteBuiltinResizeBilinear:
728 return VisitResizeOperator(delegateData,
729 tfLiteContext,
730 tfLiteNode,
731 nodeIndex,
732 kTfLiteBuiltinResizeBilinear);
733 case kTfLiteBuiltinResizeNearestNeighbor:
734 return VisitResizeOperator(delegateData,
735 tfLiteContext,
736 tfLiteNode,
737 nodeIndex,
738 kTfLiteBuiltinResizeNearestNeighbor);
739 case kTfLiteBuiltinRsqrt:
740 return VisitElementwiseUnaryOperator(delegateData,
741 tfLiteContext,
742 tfLiteNode,
743 nodeIndex,
744 armnn::UnaryOperation::Rsqrt);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +0000745 case kTfLiteBuiltinSplit:
746 return VisitSplitOperator(delegateData,
747 tfLiteContext,
748 tfLiteNode,
749 nodeIndex,
750 kTfLiteBuiltinSplit);
751 case kTfLiteBuiltinSplitV:
752 return VisitSplitVOperator(delegateData,
753 tfLiteContext,
754 tfLiteNode,
755 nodeIndex,
756 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +0100757 case kTfLiteBuiltinSqrt:
758 return VisitElementwiseUnaryOperator(delegateData,
759 tfLiteContext,
760 tfLiteNode,
761 nodeIndex,
762 armnn::UnaryOperation::Sqrt);
763 case kTfLiteBuiltinSqueeze:
764 return VisitSqueezeOperator(delegateData,
765 tfLiteContext,
766 tfLiteNode,
767 nodeIndex,
768 kTfLiteBuiltinSqueeze);
769 case kTfLiteBuiltinStridedSlice:
770 return VisitSliceOperator(delegateData,
771 tfLiteContext,
772 tfLiteNode,
773 nodeIndex,
774 kTfLiteBuiltinStridedSlice);
775 case kTfLiteBuiltinTranspose:
776 return VisitTransposeOperator(delegateData,
777 tfLiteContext,
778 tfLiteNode,
779 nodeIndex,
780 kTfLiteBuiltinTranspose);
781 case kTfLiteBuiltinTransposeConv:
782 return VisitConvolutionOperator(delegateData,
783 tfLiteContext,
784 tfLiteNode,
785 nodeIndex,
786 kTfLiteBuiltinTransposeConv);
787 case kTfLiteBuiltinSoftmax:
788 return VisitSoftmaxOperator(delegateData,
789 tfLiteContext,
790 tfLiteNode,
791 nodeIndex,
792 kTfLiteBuiltinSoftmax);
793 case kTfLiteBuiltinSpaceToBatchNd:
794 return VisitSpaceToBatchNdOperator(delegateData,
795 tfLiteContext,
796 tfLiteNode,
797 nodeIndex,
798 kTfLiteBuiltinSpaceToBatchNd);
799 case kTfLiteBuiltinSpaceToDepth:
800 return VisitSpaceToDepthOperator(delegateData,
801 tfLiteContext,
802 tfLiteNode,
803 nodeIndex,
804 kTfLiteBuiltinSpaceToDepth);
805 case kTfLiteBuiltinSub:
806 return VisitElementwiseBinaryOperator(delegateData,
807 tfLiteContext,
808 tfLiteNode,
809 nodeIndex,
810 kTfLiteBuiltinSub);
811 case kTfLiteBuiltinTanh:
812 return VisitActivationOperator(delegateData,
813 tfLiteContext,
814 tfLiteNode,
815 nodeIndex,
816 kTfLiteBuiltinTanh);
817 default:
818 return kTfLiteError;
819 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100820}
821
822} // armnnDelegate namespace