blob: 3ebc0cc6b53098ace0dc3cfc2db3995355b34595 [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
Matthew Sloyanac001ee2021-02-03 10:43:04 +00008#include "Version.hpp"
9
Sadik Armagan62483be2020-10-23 17:14:43 +010010#include "Activation.hpp"
11#include "ArgMinMax.hpp"
12#include "BatchSpace.hpp"
13#include "Comparison.hpp"
14#include "Convolution.hpp"
15#include "Control.hpp"
16#include "ElementwiseBinary.hpp"
17#include "ElementwiseUnary.hpp"
18#include "Fill.hpp"
19#include "FullyConnected.hpp"
20#include "Gather.hpp"
Matthew Sloyanc8eb9552020-11-26 10:54:22 +000021#include "LogicalBinary.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010022#include "Lstm.hpp"
23#include "Normalization.hpp"
24#include "Pad.hpp"
25#include "Pooling.hpp"
26#include "Quantization.hpp"
27#include "Redefine.hpp"
28#include "Resize.hpp"
29#include "Round.hpp"
30#include "Slice.hpp"
31#include "Softmax.hpp"
32#include "SpaceDepth.hpp"
Sadik Armagan34fa1bd2020-11-27 12:40:52 +000033#include "Split.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010034#include "Transpose.hpp"
35
36#include <flatbuffers/flatbuffers.h>
37#include <tensorflow/lite/context_util.h>
38
Sadik Armagan3c24f432020-10-19 17:35:30 +010039#include <algorithm>
Matthew Sloyanac001ee2021-02-03 10:43:04 +000040#include <iostream>
Sadik Armagan62483be2020-10-23 17:14:43 +010041#include <sstream>
Sadik Armagan3c24f432020-10-19 17:35:30 +010042
43namespace armnnDelegate
44{
45
Sadik Armagan62483be2020-10-23 17:14:43 +010046DelegateOptions TfLiteArmnnDelegateOptionsDefault()
47{
48 DelegateOptions options(armnn::Compute::CpuRef);
49 return options;
50}
51
52TfLiteDelegate* TfLiteArmnnDelegateCreate(armnnDelegate::DelegateOptions options)
53{
54 auto* armnnDelegate = new ::armnnDelegate::Delegate(options);
55 return armnnDelegate->GetDelegate();
56}
57
58void TfLiteArmnnDelegateDelete(TfLiteDelegate* tfLiteDelegate)
59{
60 if (tfLiteDelegate != nullptr)
61 {
62 delete static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_);
63 }
64}
65
66TfLiteStatus DoPrepare(TfLiteContext* tfLiteContext, TfLiteDelegate* tfLiteDelegate)
67{
68 TfLiteIntArray* supportedOperators =
69 static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_)->IdentifyOperatorsToDelegate(tfLiteContext);
70
71 // ArmNN Delegate Registration
72 static const TfLiteRegistration kArmnnSubgraphRegistration = {
73 // ArmnnSubgraph Init
74 .init = [](TfLiteContext* tfLiteContext, const char* buffer, size_t length) -> void* {
Finn Williams6f9f9902020-11-13 13:23:15 +000075 armnn::IgnoreUnused(length);
Sadik Armagan62483be2020-10-23 17:14:43 +010076 const TfLiteDelegateParams* parameters = reinterpret_cast<const TfLiteDelegateParams*>(buffer);
77
78 return static_cast<void*>(ArmnnSubgraph::Create(
79 tfLiteContext, parameters, static_cast<::armnnDelegate::Delegate*>(parameters->delegate->data_)));
80 },
81 // ArmnnSubgraph Free
82 .free = [](TfLiteContext* tfLiteContext, void* buffer) -> void {
Finn Williams6f9f9902020-11-13 13:23:15 +000083 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan62483be2020-10-23 17:14:43 +010084 if (buffer != nullptr)
85 {
86 delete static_cast<ArmnnSubgraph*>(buffer);
87 }
88 },
89 // ArmnnSubgraph Prepare
90 .prepare = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
91 if (tfLiteNode->user_data == nullptr)
92 {
93 return kTfLiteError;
94 }
Sadik Armagan62483be2020-10-23 17:14:43 +010095 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Prepare(tfLiteContext);
96 },
97 // ArmnnSubgraph Invoke
98 .invoke = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
99 if (tfLiteNode->user_data == nullptr)
100 {
101 return kTfLiteError;
102 }
103
104 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Invoke(tfLiteContext, tfLiteNode);
105 },
106
107 .profiling_string = nullptr,
108 .builtin_code = kTfLiteBuiltinDelegate,
109 .custom_name = "TfLiteArmNnDelegate",
110 .version = 1,
111 };
112
113 const TfLiteStatus status =
114 tfLiteContext->ReplaceNodeSubsetsWithDelegateKernels(
115 tfLiteContext, kArmnnSubgraphRegistration, supportedOperators, tfLiteDelegate);
116
117 TfLiteIntArrayFree(supportedOperators);
118 return status;
119
120}
121
Sadik Armagan3c24f432020-10-19 17:35:30 +0100122Delegate::Delegate(armnnDelegate::DelegateOptions options)
123 : m_Runtime(nullptr, nullptr),
124 m_Options(std::move(options))
125{
Jan Eilers2cd18472020-12-15 10:42:38 +0000126 // Configures logging for ARMNN
127 if (options.IsLoggingEnabled())
128 {
129 armnn::ConfigureLogging(true, true, options.GetLoggingSeverity());
130 }
131
Sadik Armagan3c24f432020-10-19 17:35:30 +0100132 // Create ArmNN Runtime
133 armnn::IRuntime::CreationOptions runtimeOptions;
Sadik Armagan4189cc52020-11-11 18:01:48 +0000134
135 auto backendOptions = m_Options.GetBackendOptions();
136 if (!backendOptions.empty())
137 {
138 runtimeOptions.m_BackendOptions = backendOptions;
139 }
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000140 else if (!m_Options.GetOptimizerOptions().m_ModelOptions.empty())
141 {
142 runtimeOptions.m_BackendOptions = m_Options.GetOptimizerOptions().m_ModelOptions;
143 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100144 m_Runtime = armnn::IRuntime::Create(runtimeOptions);
145
146 std::vector<armnn::BackendId> backends;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100147 if (m_Runtime)
148 {
149 const armnn::BackendIdSet supportedDevices = m_Runtime->GetDeviceSpec().GetSupportedBackends();
150 for (auto& backend : m_Options.GetBackends())
151 {
152 if (std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) == supportedDevices.cend())
153 {
Sadik Armagan0534e032020-10-27 17:30:18 +0000154 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100155 "TfLiteArmnnDelegate: Requested unknown backend %s", backend.Get().c_str());
156 }
157 else
158 {
159 backends.push_back(backend);
160 }
161 }
162 }
163
164 if (backends.empty())
165 {
166 // No known backend specified
167 throw armnn::InvalidArgumentException("TfLiteArmnnDelegate: No known backend specified.");
168 }
169 m_Options.SetBackends(backends);
170
171 TFLITE_LOG_PROD_ONCE(tflite::TFLITE_LOG_INFO, "TfLiteArmnnDelegate: Created TfLite ArmNN delegate.");
172}
173
Sadik Armagan62483be2020-10-23 17:14:43 +0100174TfLiteIntArray* Delegate::IdentifyOperatorsToDelegate(TfLiteContext* tfLiteContext)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100175{
176 TfLiteIntArray* executionPlan = nullptr;
177 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
178 {
179 TF_LITE_KERNEL_LOG(tfLiteContext, "TfLiteArmnnDelegate: Unable to get graph execution plan.");
180 return nullptr;
181 }
182
Sadik Armagan62483be2020-10-23 17:14:43 +0100183 // Delegate data with null network
184 DelegateData delegateData(m_Options.GetBackends());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100185
186 TfLiteIntArray* nodesToDelegate = TfLiteIntArrayCreate(executionPlan->size);
187 nodesToDelegate->size = 0;
188 for (int i = 0; i < executionPlan->size; ++i)
189 {
190 const int nodeIndex = executionPlan->data[i];
191
192 // If TfLite nodes can be delegated to ArmNN
193 TfLiteNode* tfLiteNode = nullptr;
194 TfLiteRegistration* tfLiteRegistration = nullptr;
195 if (tfLiteContext->GetNodeAndRegistration(
196 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
197 {
198 TF_LITE_KERNEL_LOG(tfLiteContext,
199 "TfLiteArmnnDelegate: Unable to get node and registration for node %d.",
200 nodeIndex);
201 continue;
202 }
203
204 if (ArmnnSubgraph::VisitNode(
Sadik Armagan62483be2020-10-23 17:14:43 +0100205 delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100206 {
207 // node is not supported by ArmNN
208 continue;
209 }
210
211 nodesToDelegate->data[nodesToDelegate->size++] = nodeIndex;
212 }
213
Sadik Armagan62483be2020-10-23 17:14:43 +0100214 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100215 return nodesToDelegate;
216}
217
218TfLiteDelegate* Delegate::GetDelegate()
219{
220 return &m_Delegate;
221}
222
Matthew Sloyanac001ee2021-02-03 10:43:04 +0000223const std::string Delegate::GetVersion()
224{
225 return DELEGATE_VERSION;
226}
227
Sadik Armagan62483be2020-10-23 17:14:43 +0100228TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
229 TfLiteContext* tfLiteContext,
230 const TfLiteIntArray* inputs,
231 std::vector<armnn::BindingPointInfo>& inputBindings)
232{
Finn Williams6f9f9902020-11-13 13:23:15 +0000233 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100234 for (unsigned int i = 0; i < numInputs; ++i)
235 {
236 const int32_t tensorId = inputs->data[i];
237 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000238 // Do not create bindings for constant inputs
239 if (tensor.allocation_type == kTfLiteMmapRo)
240 {
241 continue;
242 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100243
244 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
245 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
246
247 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
248 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
249 outputSlot.SetTensorInfo(tensorInfo);
250
251 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000252 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100253
Sadik Armagan6e36a642020-11-10 21:18:41 +0000254 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100255 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000256
Sadik Armagan62483be2020-10-23 17:14:43 +0100257 return kTfLiteOk;
258}
259
260TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
261 TfLiteContext* tfLiteContext,
262 const TfLiteIntArray* outputs,
263 std::vector<armnn::BindingPointInfo>& outputBindings)
264{
Finn Williams6f9f9902020-11-13 13:23:15 +0000265 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100266 for (unsigned int i = 0; i < numOutputs; ++i)
267 {
268 const int32_t tensorId = outputs->data[i];
269 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
270
271 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
272 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
273
274 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Finn Williams6f9f9902020-11-13 13:23:15 +0000275 ARMNN_ASSERT(delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] != nullptr);
276 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100277 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
278 }
279
280 return kTfLiteOk;
281}
282
Sadik Armagan3c24f432020-10-19 17:35:30 +0100283ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
284 const TfLiteDelegateParams* parameters,
285 const Delegate* delegate)
286{
287 TfLiteIntArray* executionPlan;
288 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
289 {
290 return nullptr;
291 }
292
Sadik Armagan62483be2020-10-23 17:14:43 +0100293 // Initialize DelegateData holds network and output slots information
294 DelegateData delegateData(delegate->m_Options.GetBackends());
295
296 // Build ArmNN Network
Sadik Armagan3c24f432020-10-19 17:35:30 +0100297 armnn::NetworkOptions networkOptions = {};
298 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100299 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100300
Sadik Armagan6e36a642020-11-10 21:18:41 +0000301 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
302
Sadik Armagan62483be2020-10-23 17:14:43 +0100303 std::vector<armnn::BindingPointInfo> inputBindings;
304 std::vector<armnn::BindingPointInfo> outputBindings;
305
306 // Add input layer
307 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
308 if (status != kTfLiteOk)
309 {
310 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
311 }
312
313 // Parse TfLite delegate nodes to ArmNN
Sadik Armagan3c24f432020-10-19 17:35:30 +0100314 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
315 {
316 const int nodeIndex = parameters->nodes_to_replace->data[i];
317
318 TfLiteNode* tfLiteNode = nullptr;
319 TfLiteRegistration* tfLiteRegistration = nullptr;
320 if (tfLiteContext->GetNodeAndRegistration(
321 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
322 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000323 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100324 }
325
Sadik Armagan62483be2020-10-23 17:14:43 +0100326 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100327 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000328 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100329 }
330 }
331
Sadik Armagan62483be2020-10-23 17:14:43 +0100332 // Add Output layer
333 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
334 if (status != kTfLiteOk)
335 {
336 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
337 }
338
339 // Optimize ArmNN network
340 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
341 try
342 {
Sadik Armagan6e36a642020-11-10 21:18:41 +0000343 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100344 delegate->m_Options.GetBackends(),
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000345 delegate->m_Runtime->GetDeviceSpec(),
346 delegate->m_Options.GetOptimizerOptions());
Sadik Armagan62483be2020-10-23 17:14:43 +0100347 }
348 catch (std::exception &ex)
349 {
350 std::stringstream exMessage;
351 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
352 throw armnn::Exception(exMessage.str());
353 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100354 if (!optNet)
355 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100356 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100357 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
358 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100359
360 try
361 {
362 // Load graph into runtime
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000363 std::string errorMessage;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000364 armnn::Status loadingStatus;
365 if (delegate->m_Options.GetOptimizerOptions().m_ImportEnabled)
366 {
367 armnn::INetworkProperties networkProperties(true, true);
368 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
369 std::move(optNet),
370 errorMessage,
371 networkProperties);
372 }
373 else
374 {
375 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
376 std::move(optNet),
377 errorMessage);
378 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100379 if (loadingStatus != armnn::Status::Success)
380 {
381 // Optimize failed
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000382 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded:" + errorMessage);
Sadik Armagan62483be2020-10-23 17:14:43 +0100383 }
384 }
385 catch (std::exception& ex)
386 {
387 std::stringstream exMessage;
388 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
389 throw armnn::Exception(exMessage.str());
390 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100391
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000392 // Register debug callback function
393 if (delegate->m_Options.GetDebugCallbackFunction().has_value())
394 {
395 delegate->m_Runtime->RegisterDebugCallback(networkId, delegate->m_Options.GetDebugCallbackFunction().value());
396 }
397
Sadik Armagan3c24f432020-10-19 17:35:30 +0100398 // Create a new SubGraph with networkId and runtime
Sadik Armagan62483be2020-10-23 17:14:43 +0100399 return new ArmnnSubgraph(networkId, delegate->m_Runtime.get(), inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100400}
401
402TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
403{
Finn Williams6f9f9902020-11-13 13:23:15 +0000404 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100405 return kTfLiteOk;
406}
407
Sadik Armagan62483be2020-10-23 17:14:43 +0100408TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100409{
Sadik Armagan62483be2020-10-23 17:14:43 +0100410 // Prepare inputs
411 armnn::InputTensors inputTensors;
412 size_t inputIndex = 0;
413 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
414 {
415 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
416 if (tensor->allocation_type != kTfLiteMmapRo)
417 {
418 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
419 const armnn::ConstTensor inputTensor(inputBinding.second, tensor->data.data);
420 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100421
Sadik Armagan62483be2020-10-23 17:14:43 +0100422 ++inputIndex;
423 }
424 }
425
426 // Prepare outputs
427 armnn::OutputTensors outputTensors;
428 size_t outputIndex = 0;
429 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
430 {
431 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
432 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
433 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
434 outputTensors.emplace_back(outputIdx, outputTensor);
435
436 ++outputIndex;
437 }
438
439 // Run graph
440 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
441 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100442}
443
Sadik Armagan62483be2020-10-23 17:14:43 +0100444TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100445 TfLiteContext* tfLiteContext,
446 TfLiteRegistration* tfLiteRegistration,
447 TfLiteNode* tfLiteNode,
448 int nodeIndex)
449{
Sadik Armagan62483be2020-10-23 17:14:43 +0100450 switch (tfLiteRegistration->builtin_code)
451 {
452 case kTfLiteBuiltinAbs:
453 return VisitElementwiseUnaryOperator(delegateData,
454 tfLiteContext,
455 tfLiteNode,
456 nodeIndex,
457 armnn::UnaryOperation::Abs);
458 case kTfLiteBuiltinAdd:
459 return VisitElementwiseBinaryOperator(delegateData,
460 tfLiteContext,
461 tfLiteNode,
462 nodeIndex,
463 kTfLiteBuiltinAdd);
464 case kTfLiteBuiltinArgMax:
465 return VisitArgMinMaxOperator(delegateData,
466 tfLiteContext,
467 tfLiteNode,
468 nodeIndex,
469 kTfLiteBuiltinArgMax);
470 case kTfLiteBuiltinArgMin:
471 return VisitArgMinMaxOperator(delegateData,
472 tfLiteContext,
473 tfLiteNode,
474 nodeIndex,
475 kTfLiteBuiltinArgMin);
476 case kTfLiteBuiltinAveragePool2d:
477 return VisitPoolingOperator(delegateData,
478 tfLiteContext,
479 tfLiteNode,
480 nodeIndex,
481 kTfLiteBuiltinAveragePool2d);
482 case kTfLiteBuiltinBatchToSpaceNd:
483 return VisitBatchToSpaceNdOperator(delegateData,
484 tfLiteContext,
485 tfLiteNode,
486 nodeIndex,
487 kTfLiteBuiltinBatchToSpaceNd);
488 case kTfLiteBuiltinConcatenation:
489 return VisitControlOperator(delegateData,
490 tfLiteContext,
491 tfLiteNode,
492 nodeIndex,
493 kTfLiteBuiltinConcatenation);
494 case kTfLiteBuiltinConv2d:
495 return VisitConvolutionOperator(delegateData,
496 tfLiteContext,
497 tfLiteNode,
498 nodeIndex,
499 kTfLiteBuiltinConv2d);
500 case kTfLiteBuiltinDepthToSpace:
501 return VisitDepthToSpaceOperator(delegateData,
502 tfLiteContext,
503 tfLiteNode,
504 nodeIndex,
505 kTfLiteBuiltinDepthToSpace);
506 case kTfLiteBuiltinDepthwiseConv2d:
507 return VisitConvolutionOperator(delegateData,
508 tfLiteContext,
509 tfLiteNode,
510 nodeIndex,
511 kTfLiteBuiltinDepthwiseConv2d);
512 case kTfLiteBuiltinDequantize:
513 return VisitDequantizeOperator(delegateData,
514 tfLiteContext,
515 tfLiteNode,
516 nodeIndex,
517 kTfLiteBuiltinDequantize);
518 case kTfLiteBuiltinDiv:
519 return VisitElementwiseBinaryOperator(delegateData,
520 tfLiteContext,
521 tfLiteNode,
522 nodeIndex,
523 kTfLiteBuiltinDiv);
524 case kTfLiteBuiltinElu:
525 return VisitActivationOperator(delegateData,
526 tfLiteContext,
527 tfLiteNode,
528 nodeIndex,
529 kTfLiteBuiltinElu);
530 case kTfLiteBuiltinEqual:
531 return VisitComparisonOperator(delegateData,
532 tfLiteContext,
533 tfLiteNode,
534 nodeIndex,
535 kTfLiteBuiltinEqual);
536 case kTfLiteBuiltinExp:
537 return VisitElementwiseUnaryOperator(delegateData,
538 tfLiteContext,
539 tfLiteNode,
540 nodeIndex,
541 armnn::UnaryOperation::Exp);
542 case kTfLiteBuiltinExpandDims:
543 return VisitExpandDimsOperator(delegateData,
544 tfLiteContext,
545 tfLiteNode,
546 nodeIndex,
547 kTfLiteBuiltinExpandDims);
548 case kTfLiteBuiltinFill:
549 return VisitFillOperator(delegateData,
550 tfLiteContext,
551 tfLiteNode,
552 nodeIndex,
553 kTfLiteBuiltinFill);
554 case kTfLiteBuiltinFloor:
555 return VisitFloorOperator(delegateData,
556 tfLiteContext,
557 tfLiteNode,
558 nodeIndex,
559 kTfLiteBuiltinFloor);
560 case kTfLiteBuiltinFullyConnected:
561 return VisitFullyConnectedOperator(delegateData,
562 tfLiteContext,
563 tfLiteNode,
564 nodeIndex,
565 kTfLiteBuiltinFullyConnected);
566 case kTfLiteBuiltinGather:
567 return VisitGatherOperator(delegateData,
568 tfLiteContext,
569 tfLiteNode,
570 nodeIndex,
571 kTfLiteBuiltinGather);
572 case kTfLiteBuiltinGatherNd:
573 return VisitGatherOperator(delegateData,
574 tfLiteContext,
575 tfLiteNode,
576 nodeIndex,
577 kTfLiteBuiltinGatherNd);
578 case kTfLiteBuiltinGreater:
579 return VisitComparisonOperator(delegateData,
580 tfLiteContext,
581 tfLiteNode,
582 nodeIndex,
583 kTfLiteBuiltinGreater);
584 case kTfLiteBuiltinGreaterEqual:
585 return VisitComparisonOperator(delegateData,
586 tfLiteContext,
587 tfLiteNode,
588 nodeIndex,
589 kTfLiteBuiltinGreaterEqual);
590 case kTfLiteBuiltinHardSwish:
591 return VisitActivationOperator(delegateData,
592 tfLiteContext,
593 tfLiteNode,
594 nodeIndex,
595 kTfLiteBuiltinHardSwish);
596 case kTfLiteBuiltinL2Normalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000597 return VisitL2NormalizationOperator(delegateData,
598 tfLiteContext,
599 tfLiteNode,
600 nodeIndex,
601 kTfLiteBuiltinL2Normalization);
Sadik Armagan62483be2020-10-23 17:14:43 +0100602 case kTfLiteBuiltinL2Pool2d:
603 return VisitPoolingOperator(delegateData,
604 tfLiteContext,
605 tfLiteNode,
606 nodeIndex,
607 kTfLiteBuiltinL2Pool2d);
608 case kTfLiteBuiltinLess:
609 return VisitComparisonOperator(delegateData,
610 tfLiteContext,
611 tfLiteNode,
612 nodeIndex,
613 kTfLiteBuiltinLess);
614 case kTfLiteBuiltinLessEqual:
615 return VisitComparisonOperator(delegateData,
616 tfLiteContext,
617 tfLiteNode,
618 nodeIndex,
619 kTfLiteBuiltinLessEqual);
620 case kTfLiteBuiltinLocalResponseNormalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000621 return VisitLocalResponseNormalizationOperator(delegateData,
622 tfLiteContext,
623 tfLiteNode,
624 nodeIndex,
625 kTfLiteBuiltinLocalResponseNormalization);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000626 case kTfLiteBuiltinLogicalAnd:
627 return VisitLogicalBinaryOperator(delegateData,
628 tfLiteContext,
629 tfLiteNode,
630 nodeIndex,
631 kTfLiteBuiltinLogicalAnd,
632 armnn::LogicalBinaryOperation::LogicalAnd);
633 case kTfLiteBuiltinLogicalNot:
634 return VisitElementwiseUnaryOperator(delegateData,
635 tfLiteContext,
636 tfLiteNode,
637 nodeIndex,
638 armnn::UnaryOperation::LogicalNot);
639 case kTfLiteBuiltinLogicalOr:
640 return VisitLogicalBinaryOperator(delegateData,
641 tfLiteContext,
642 tfLiteNode,
643 nodeIndex,
644 kTfLiteBuiltinLogicalOr,
645 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100646 case kTfLiteBuiltinLogistic:
647 return VisitActivationOperator(delegateData,
648 tfLiteContext,
649 tfLiteNode,
650 nodeIndex,
651 kTfLiteBuiltinLogistic);
652 case kTfLiteBuiltinLogSoftmax:
653 return VisitSoftmaxOperator(delegateData,
654 tfLiteContext,
655 tfLiteNode,
656 nodeIndex,
657 kTfLiteBuiltinLogSoftmax);
658 case kTfLiteBuiltinLstm:
659 return VisitLstmOperator(delegateData,
660 tfLiteContext,
661 tfLiteNode,
662 nodeIndex,
663 kTfLiteBuiltinLstm);
664 case kTfLiteBuiltinMaxPool2d:
665 return VisitPoolingOperator(delegateData,
666 tfLiteContext,
667 tfLiteNode,
668 nodeIndex,
669 kTfLiteBuiltinMaxPool2d);
670 case kTfLiteBuiltinMaximum:
671 return VisitElementwiseBinaryOperator(delegateData,
672 tfLiteContext,
673 tfLiteNode,
674 nodeIndex,
675 kTfLiteBuiltinMaximum);
676 case kTfLiteBuiltinMean:
677 return VisitControlOperator(delegateData,
678 tfLiteContext,
679 tfLiteNode,
680 nodeIndex,
681 kTfLiteBuiltinMean);
682 case kTfLiteBuiltinMinimum:
683 return VisitElementwiseBinaryOperator(delegateData,
684 tfLiteContext,
685 tfLiteNode,
686 nodeIndex,
687 kTfLiteBuiltinMinimum);
688 case kTfLiteBuiltinMul:
689 return VisitElementwiseBinaryOperator(delegateData,
690 tfLiteContext,
691 tfLiteNode,
692 nodeIndex,
693 kTfLiteBuiltinMul);
694 case kTfLiteBuiltinNeg:
695 return VisitElementwiseUnaryOperator(delegateData,
696 tfLiteContext,
697 tfLiteNode,
698 nodeIndex,
699 armnn::UnaryOperation::Neg);
700 case kTfLiteBuiltinNotEqual:
701 return VisitComparisonOperator(delegateData,
702 tfLiteContext,
703 tfLiteNode,
704 nodeIndex,
705 kTfLiteBuiltinNotEqual);
706 case kTfLiteBuiltinPad:
707 return VisitPadOperator(delegateData,
708 tfLiteContext,
709 tfLiteNode,
710 nodeIndex,
711 kTfLiteBuiltinPad);
712 case kTfLiteBuiltinPadv2:
713 return VisitPadOperator(delegateData,
714 tfLiteContext,
715 tfLiteNode,
716 nodeIndex,
717 kTfLiteBuiltinPadv2);
718 case kTfLiteBuiltinPrelu:
719 return VisitActivationOperator(delegateData,
720 tfLiteContext,
721 tfLiteNode,
722 nodeIndex,
723 kTfLiteBuiltinPrelu);
724 case kTfLiteBuiltinQuantize:
725 return VisitQuantizeOperator(delegateData,
726 tfLiteContext,
727 tfLiteNode,
728 nodeIndex,
729 kTfLiteBuiltinQuantize);
730 case kTfLiteBuiltinRank:
731 return VisitControlOperator(delegateData,
732 tfLiteContext,
733 tfLiteNode,
734 nodeIndex,
735 kTfLiteBuiltinRank);
736 case kTfLiteBuiltinRelu:
737 return VisitActivationOperator(delegateData,
738 tfLiteContext,
739 tfLiteNode,
740 nodeIndex,
741 kTfLiteBuiltinRelu);
742 case kTfLiteBuiltinReluN1To1:
743 return VisitActivationOperator(delegateData,
744 tfLiteContext,
745 tfLiteNode,
746 nodeIndex,
747 kTfLiteBuiltinReluN1To1);
748 case kTfLiteBuiltinRelu6:
749 return VisitActivationOperator(delegateData,
750 tfLiteContext,
751 tfLiteNode,
752 nodeIndex,
753 kTfLiteBuiltinRelu6);
754 case kTfLiteBuiltinReshape:
755 return VisitReshapeOperator(delegateData,
756 tfLiteContext,
757 tfLiteNode,
758 nodeIndex,
759 kTfLiteBuiltinReshape);
760 case kTfLiteBuiltinResizeBilinear:
761 return VisitResizeOperator(delegateData,
762 tfLiteContext,
763 tfLiteNode,
764 nodeIndex,
765 kTfLiteBuiltinResizeBilinear);
766 case kTfLiteBuiltinResizeNearestNeighbor:
767 return VisitResizeOperator(delegateData,
768 tfLiteContext,
769 tfLiteNode,
770 nodeIndex,
771 kTfLiteBuiltinResizeNearestNeighbor);
772 case kTfLiteBuiltinRsqrt:
773 return VisitElementwiseUnaryOperator(delegateData,
774 tfLiteContext,
775 tfLiteNode,
776 nodeIndex,
777 armnn::UnaryOperation::Rsqrt);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +0000778 case kTfLiteBuiltinSplit:
779 return VisitSplitOperator(delegateData,
780 tfLiteContext,
781 tfLiteNode,
782 nodeIndex,
783 kTfLiteBuiltinSplit);
784 case kTfLiteBuiltinSplitV:
785 return VisitSplitVOperator(delegateData,
786 tfLiteContext,
787 tfLiteNode,
788 nodeIndex,
789 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +0100790 case kTfLiteBuiltinSqrt:
791 return VisitElementwiseUnaryOperator(delegateData,
792 tfLiteContext,
793 tfLiteNode,
794 nodeIndex,
795 armnn::UnaryOperation::Sqrt);
796 case kTfLiteBuiltinSqueeze:
797 return VisitSqueezeOperator(delegateData,
798 tfLiteContext,
799 tfLiteNode,
800 nodeIndex,
801 kTfLiteBuiltinSqueeze);
802 case kTfLiteBuiltinStridedSlice:
803 return VisitSliceOperator(delegateData,
804 tfLiteContext,
805 tfLiteNode,
806 nodeIndex,
807 kTfLiteBuiltinStridedSlice);
808 case kTfLiteBuiltinTranspose:
809 return VisitTransposeOperator(delegateData,
810 tfLiteContext,
811 tfLiteNode,
812 nodeIndex,
813 kTfLiteBuiltinTranspose);
814 case kTfLiteBuiltinTransposeConv:
815 return VisitConvolutionOperator(delegateData,
816 tfLiteContext,
817 tfLiteNode,
818 nodeIndex,
819 kTfLiteBuiltinTransposeConv);
820 case kTfLiteBuiltinSoftmax:
821 return VisitSoftmaxOperator(delegateData,
822 tfLiteContext,
823 tfLiteNode,
824 nodeIndex,
825 kTfLiteBuiltinSoftmax);
826 case kTfLiteBuiltinSpaceToBatchNd:
827 return VisitSpaceToBatchNdOperator(delegateData,
828 tfLiteContext,
829 tfLiteNode,
830 nodeIndex,
831 kTfLiteBuiltinSpaceToBatchNd);
832 case kTfLiteBuiltinSpaceToDepth:
833 return VisitSpaceToDepthOperator(delegateData,
834 tfLiteContext,
835 tfLiteNode,
836 nodeIndex,
837 kTfLiteBuiltinSpaceToDepth);
838 case kTfLiteBuiltinSub:
839 return VisitElementwiseBinaryOperator(delegateData,
840 tfLiteContext,
841 tfLiteNode,
842 nodeIndex,
843 kTfLiteBuiltinSub);
844 case kTfLiteBuiltinTanh:
845 return VisitActivationOperator(delegateData,
846 tfLiteContext,
847 tfLiteNode,
848 nodeIndex,
849 kTfLiteBuiltinTanh);
850 default:
851 return kTfLiteError;
852 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100853}
854
855} // armnnDelegate namespace