blob: 6dba890509125c077e51e4cfd29f4f2b1dd80b20 [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 }
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000137 else if (!m_Options.GetOptimizerOptions().m_ModelOptions.empty())
138 {
139 runtimeOptions.m_BackendOptions = m_Options.GetOptimizerOptions().m_ModelOptions;
140 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100141 m_Runtime = armnn::IRuntime::Create(runtimeOptions);
142
143 std::vector<armnn::BackendId> backends;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100144 if (m_Runtime)
145 {
146 const armnn::BackendIdSet supportedDevices = m_Runtime->GetDeviceSpec().GetSupportedBackends();
147 for (auto& backend : m_Options.GetBackends())
148 {
149 if (std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) == supportedDevices.cend())
150 {
Sadik Armagan0534e032020-10-27 17:30:18 +0000151 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100152 "TfLiteArmnnDelegate: Requested unknown backend %s", backend.Get().c_str());
153 }
154 else
155 {
156 backends.push_back(backend);
157 }
158 }
159 }
160
161 if (backends.empty())
162 {
163 // No known backend specified
164 throw armnn::InvalidArgumentException("TfLiteArmnnDelegate: No known backend specified.");
165 }
166 m_Options.SetBackends(backends);
167
168 TFLITE_LOG_PROD_ONCE(tflite::TFLITE_LOG_INFO, "TfLiteArmnnDelegate: Created TfLite ArmNN delegate.");
169}
170
Sadik Armagan62483be2020-10-23 17:14:43 +0100171TfLiteIntArray* Delegate::IdentifyOperatorsToDelegate(TfLiteContext* tfLiteContext)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100172{
173 TfLiteIntArray* executionPlan = nullptr;
174 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
175 {
176 TF_LITE_KERNEL_LOG(tfLiteContext, "TfLiteArmnnDelegate: Unable to get graph execution plan.");
177 return nullptr;
178 }
179
Sadik Armagan62483be2020-10-23 17:14:43 +0100180 // Delegate data with null network
181 DelegateData delegateData(m_Options.GetBackends());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100182
183 TfLiteIntArray* nodesToDelegate = TfLiteIntArrayCreate(executionPlan->size);
184 nodesToDelegate->size = 0;
185 for (int i = 0; i < executionPlan->size; ++i)
186 {
187 const int nodeIndex = executionPlan->data[i];
188
189 // If TfLite nodes can be delegated to ArmNN
190 TfLiteNode* tfLiteNode = nullptr;
191 TfLiteRegistration* tfLiteRegistration = nullptr;
192 if (tfLiteContext->GetNodeAndRegistration(
193 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
194 {
195 TF_LITE_KERNEL_LOG(tfLiteContext,
196 "TfLiteArmnnDelegate: Unable to get node and registration for node %d.",
197 nodeIndex);
198 continue;
199 }
200
201 if (ArmnnSubgraph::VisitNode(
Sadik Armagan62483be2020-10-23 17:14:43 +0100202 delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100203 {
204 // node is not supported by ArmNN
205 continue;
206 }
207
208 nodesToDelegate->data[nodesToDelegate->size++] = nodeIndex;
209 }
210
Sadik Armagan62483be2020-10-23 17:14:43 +0100211 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100212 return nodesToDelegate;
213}
214
215TfLiteDelegate* Delegate::GetDelegate()
216{
217 return &m_Delegate;
218}
219
Sadik Armagan62483be2020-10-23 17:14:43 +0100220TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
221 TfLiteContext* tfLiteContext,
222 const TfLiteIntArray* inputs,
223 std::vector<armnn::BindingPointInfo>& inputBindings)
224{
Finn Williams6f9f9902020-11-13 13:23:15 +0000225 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100226 for (unsigned int i = 0; i < numInputs; ++i)
227 {
228 const int32_t tensorId = inputs->data[i];
229 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000230 // Do not create bindings for constant inputs
231 if (tensor.allocation_type == kTfLiteMmapRo)
232 {
233 continue;
234 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100235
236 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
237 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
238
239 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
240 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
241 outputSlot.SetTensorInfo(tensorInfo);
242
243 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000244 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100245
Sadik Armagan6e36a642020-11-10 21:18:41 +0000246 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100247 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000248
Sadik Armagan62483be2020-10-23 17:14:43 +0100249 return kTfLiteOk;
250}
251
252TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
253 TfLiteContext* tfLiteContext,
254 const TfLiteIntArray* outputs,
255 std::vector<armnn::BindingPointInfo>& outputBindings)
256{
Finn Williams6f9f9902020-11-13 13:23:15 +0000257 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100258 for (unsigned int i = 0; i < numOutputs; ++i)
259 {
260 const int32_t tensorId = outputs->data[i];
261 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
262
263 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
264 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
265
266 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Finn Williams6f9f9902020-11-13 13:23:15 +0000267 ARMNN_ASSERT(delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] != nullptr);
268 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100269 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
270 }
271
272 return kTfLiteOk;
273}
274
Sadik Armagan3c24f432020-10-19 17:35:30 +0100275ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
276 const TfLiteDelegateParams* parameters,
277 const Delegate* delegate)
278{
279 TfLiteIntArray* executionPlan;
280 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
281 {
282 return nullptr;
283 }
284
Sadik Armagan62483be2020-10-23 17:14:43 +0100285 // Initialize DelegateData holds network and output slots information
286 DelegateData delegateData(delegate->m_Options.GetBackends());
287
288 // Build ArmNN Network
Sadik Armagan3c24f432020-10-19 17:35:30 +0100289 armnn::NetworkOptions networkOptions = {};
290 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100291 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100292
Sadik Armagan6e36a642020-11-10 21:18:41 +0000293 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
294
Sadik Armagan62483be2020-10-23 17:14:43 +0100295 std::vector<armnn::BindingPointInfo> inputBindings;
296 std::vector<armnn::BindingPointInfo> outputBindings;
297
298 // Add input layer
299 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
300 if (status != kTfLiteOk)
301 {
302 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
303 }
304
305 // Parse TfLite delegate nodes to ArmNN
Sadik Armagan3c24f432020-10-19 17:35:30 +0100306 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
307 {
308 const int nodeIndex = parameters->nodes_to_replace->data[i];
309
310 TfLiteNode* tfLiteNode = nullptr;
311 TfLiteRegistration* tfLiteRegistration = nullptr;
312 if (tfLiteContext->GetNodeAndRegistration(
313 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
314 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000315 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100316 }
317
Sadik Armagan62483be2020-10-23 17:14:43 +0100318 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100319 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000320 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100321 }
322 }
323
Sadik Armagan62483be2020-10-23 17:14:43 +0100324 // Add Output layer
325 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
326 if (status != kTfLiteOk)
327 {
328 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
329 }
330
331 // Optimize ArmNN network
332 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
333 try
334 {
Sadik Armagan6e36a642020-11-10 21:18:41 +0000335 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100336 delegate->m_Options.GetBackends(),
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000337 delegate->m_Runtime->GetDeviceSpec(),
338 delegate->m_Options.GetOptimizerOptions());
Sadik Armagan62483be2020-10-23 17:14:43 +0100339 }
340 catch (std::exception &ex)
341 {
342 std::stringstream exMessage;
343 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
344 throw armnn::Exception(exMessage.str());
345 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100346 if (!optNet)
347 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100348 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100349 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
350 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100351
352 try
353 {
354 // Load graph into runtime
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000355 std::string errorMessage;
356 auto loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
357 std::move(optNet),
358 errorMessage,
359 delegate->m_Options.GetNetworkProperties());
Sadik Armagan62483be2020-10-23 17:14:43 +0100360 if (loadingStatus != armnn::Status::Success)
361 {
362 // Optimize failed
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000363 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded:" + errorMessage);
Sadik Armagan62483be2020-10-23 17:14:43 +0100364 }
365 }
366 catch (std::exception& ex)
367 {
368 std::stringstream exMessage;
369 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
370 throw armnn::Exception(exMessage.str());
371 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100372
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000373 // Register debug callback function
374 if (delegate->m_Options.GetDebugCallbackFunction().has_value())
375 {
376 delegate->m_Runtime->RegisterDebugCallback(networkId, delegate->m_Options.GetDebugCallbackFunction().value());
377 }
378
Sadik Armagan3c24f432020-10-19 17:35:30 +0100379 // Create a new SubGraph with networkId and runtime
Sadik Armagan62483be2020-10-23 17:14:43 +0100380 return new ArmnnSubgraph(networkId, delegate->m_Runtime.get(), inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100381}
382
383TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
384{
Finn Williams6f9f9902020-11-13 13:23:15 +0000385 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100386 return kTfLiteOk;
387}
388
Sadik Armagan62483be2020-10-23 17:14:43 +0100389TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100390{
Sadik Armagan62483be2020-10-23 17:14:43 +0100391 // Prepare inputs
392 armnn::InputTensors inputTensors;
393 size_t inputIndex = 0;
394 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
395 {
396 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
397 if (tensor->allocation_type != kTfLiteMmapRo)
398 {
399 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
400 const armnn::ConstTensor inputTensor(inputBinding.second, tensor->data.data);
401 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100402
Sadik Armagan62483be2020-10-23 17:14:43 +0100403 ++inputIndex;
404 }
405 }
406
407 // Prepare outputs
408 armnn::OutputTensors outputTensors;
409 size_t outputIndex = 0;
410 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
411 {
412 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
413 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
414 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
415 outputTensors.emplace_back(outputIdx, outputTensor);
416
417 ++outputIndex;
418 }
419
420 // Run graph
421 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
422 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100423}
424
Sadik Armagan62483be2020-10-23 17:14:43 +0100425TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100426 TfLiteContext* tfLiteContext,
427 TfLiteRegistration* tfLiteRegistration,
428 TfLiteNode* tfLiteNode,
429 int nodeIndex)
430{
Sadik Armagan62483be2020-10-23 17:14:43 +0100431 switch (tfLiteRegistration->builtin_code)
432 {
433 case kTfLiteBuiltinAbs:
434 return VisitElementwiseUnaryOperator(delegateData,
435 tfLiteContext,
436 tfLiteNode,
437 nodeIndex,
438 armnn::UnaryOperation::Abs);
439 case kTfLiteBuiltinAdd:
440 return VisitElementwiseBinaryOperator(delegateData,
441 tfLiteContext,
442 tfLiteNode,
443 nodeIndex,
444 kTfLiteBuiltinAdd);
445 case kTfLiteBuiltinArgMax:
446 return VisitArgMinMaxOperator(delegateData,
447 tfLiteContext,
448 tfLiteNode,
449 nodeIndex,
450 kTfLiteBuiltinArgMax);
451 case kTfLiteBuiltinArgMin:
452 return VisitArgMinMaxOperator(delegateData,
453 tfLiteContext,
454 tfLiteNode,
455 nodeIndex,
456 kTfLiteBuiltinArgMin);
457 case kTfLiteBuiltinAveragePool2d:
458 return VisitPoolingOperator(delegateData,
459 tfLiteContext,
460 tfLiteNode,
461 nodeIndex,
462 kTfLiteBuiltinAveragePool2d);
463 case kTfLiteBuiltinBatchToSpaceNd:
464 return VisitBatchToSpaceNdOperator(delegateData,
465 tfLiteContext,
466 tfLiteNode,
467 nodeIndex,
468 kTfLiteBuiltinBatchToSpaceNd);
469 case kTfLiteBuiltinConcatenation:
470 return VisitControlOperator(delegateData,
471 tfLiteContext,
472 tfLiteNode,
473 nodeIndex,
474 kTfLiteBuiltinConcatenation);
475 case kTfLiteBuiltinConv2d:
476 return VisitConvolutionOperator(delegateData,
477 tfLiteContext,
478 tfLiteNode,
479 nodeIndex,
480 kTfLiteBuiltinConv2d);
481 case kTfLiteBuiltinDepthToSpace:
482 return VisitDepthToSpaceOperator(delegateData,
483 tfLiteContext,
484 tfLiteNode,
485 nodeIndex,
486 kTfLiteBuiltinDepthToSpace);
487 case kTfLiteBuiltinDepthwiseConv2d:
488 return VisitConvolutionOperator(delegateData,
489 tfLiteContext,
490 tfLiteNode,
491 nodeIndex,
492 kTfLiteBuiltinDepthwiseConv2d);
493 case kTfLiteBuiltinDequantize:
494 return VisitDequantizeOperator(delegateData,
495 tfLiteContext,
496 tfLiteNode,
497 nodeIndex,
498 kTfLiteBuiltinDequantize);
499 case kTfLiteBuiltinDiv:
500 return VisitElementwiseBinaryOperator(delegateData,
501 tfLiteContext,
502 tfLiteNode,
503 nodeIndex,
504 kTfLiteBuiltinDiv);
505 case kTfLiteBuiltinElu:
506 return VisitActivationOperator(delegateData,
507 tfLiteContext,
508 tfLiteNode,
509 nodeIndex,
510 kTfLiteBuiltinElu);
511 case kTfLiteBuiltinEqual:
512 return VisitComparisonOperator(delegateData,
513 tfLiteContext,
514 tfLiteNode,
515 nodeIndex,
516 kTfLiteBuiltinEqual);
517 case kTfLiteBuiltinExp:
518 return VisitElementwiseUnaryOperator(delegateData,
519 tfLiteContext,
520 tfLiteNode,
521 nodeIndex,
522 armnn::UnaryOperation::Exp);
523 case kTfLiteBuiltinExpandDims:
524 return VisitExpandDimsOperator(delegateData,
525 tfLiteContext,
526 tfLiteNode,
527 nodeIndex,
528 kTfLiteBuiltinExpandDims);
529 case kTfLiteBuiltinFill:
530 return VisitFillOperator(delegateData,
531 tfLiteContext,
532 tfLiteNode,
533 nodeIndex,
534 kTfLiteBuiltinFill);
535 case kTfLiteBuiltinFloor:
536 return VisitFloorOperator(delegateData,
537 tfLiteContext,
538 tfLiteNode,
539 nodeIndex,
540 kTfLiteBuiltinFloor);
541 case kTfLiteBuiltinFullyConnected:
542 return VisitFullyConnectedOperator(delegateData,
543 tfLiteContext,
544 tfLiteNode,
545 nodeIndex,
546 kTfLiteBuiltinFullyConnected);
547 case kTfLiteBuiltinGather:
548 return VisitGatherOperator(delegateData,
549 tfLiteContext,
550 tfLiteNode,
551 nodeIndex,
552 kTfLiteBuiltinGather);
553 case kTfLiteBuiltinGatherNd:
554 return VisitGatherOperator(delegateData,
555 tfLiteContext,
556 tfLiteNode,
557 nodeIndex,
558 kTfLiteBuiltinGatherNd);
559 case kTfLiteBuiltinGreater:
560 return VisitComparisonOperator(delegateData,
561 tfLiteContext,
562 tfLiteNode,
563 nodeIndex,
564 kTfLiteBuiltinGreater);
565 case kTfLiteBuiltinGreaterEqual:
566 return VisitComparisonOperator(delegateData,
567 tfLiteContext,
568 tfLiteNode,
569 nodeIndex,
570 kTfLiteBuiltinGreaterEqual);
571 case kTfLiteBuiltinHardSwish:
572 return VisitActivationOperator(delegateData,
573 tfLiteContext,
574 tfLiteNode,
575 nodeIndex,
576 kTfLiteBuiltinHardSwish);
577 case kTfLiteBuiltinL2Normalization:
578 return VisitNormalizationOperator(delegateData,
579 tfLiteContext,
580 tfLiteNode,
581 nodeIndex,
582 kTfLiteBuiltinL2Normalization);
583 case kTfLiteBuiltinL2Pool2d:
584 return VisitPoolingOperator(delegateData,
585 tfLiteContext,
586 tfLiteNode,
587 nodeIndex,
588 kTfLiteBuiltinL2Pool2d);
589 case kTfLiteBuiltinLess:
590 return VisitComparisonOperator(delegateData,
591 tfLiteContext,
592 tfLiteNode,
593 nodeIndex,
594 kTfLiteBuiltinLess);
595 case kTfLiteBuiltinLessEqual:
596 return VisitComparisonOperator(delegateData,
597 tfLiteContext,
598 tfLiteNode,
599 nodeIndex,
600 kTfLiteBuiltinLessEqual);
601 case kTfLiteBuiltinLocalResponseNormalization:
602 return VisitNormalizationOperator(delegateData,
603 tfLiteContext,
604 tfLiteNode,
605 nodeIndex,
606 kTfLiteBuiltinLocalResponseNormalization);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000607 case kTfLiteBuiltinLogicalAnd:
608 return VisitLogicalBinaryOperator(delegateData,
609 tfLiteContext,
610 tfLiteNode,
611 nodeIndex,
612 kTfLiteBuiltinLogicalAnd,
613 armnn::LogicalBinaryOperation::LogicalAnd);
614 case kTfLiteBuiltinLogicalNot:
615 return VisitElementwiseUnaryOperator(delegateData,
616 tfLiteContext,
617 tfLiteNode,
618 nodeIndex,
619 armnn::UnaryOperation::LogicalNot);
620 case kTfLiteBuiltinLogicalOr:
621 return VisitLogicalBinaryOperator(delegateData,
622 tfLiteContext,
623 tfLiteNode,
624 nodeIndex,
625 kTfLiteBuiltinLogicalOr,
626 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100627 case kTfLiteBuiltinLogistic:
628 return VisitActivationOperator(delegateData,
629 tfLiteContext,
630 tfLiteNode,
631 nodeIndex,
632 kTfLiteBuiltinLogistic);
633 case kTfLiteBuiltinLogSoftmax:
634 return VisitSoftmaxOperator(delegateData,
635 tfLiteContext,
636 tfLiteNode,
637 nodeIndex,
638 kTfLiteBuiltinLogSoftmax);
639 case kTfLiteBuiltinLstm:
640 return VisitLstmOperator(delegateData,
641 tfLiteContext,
642 tfLiteNode,
643 nodeIndex,
644 kTfLiteBuiltinLstm);
645 case kTfLiteBuiltinMaxPool2d:
646 return VisitPoolingOperator(delegateData,
647 tfLiteContext,
648 tfLiteNode,
649 nodeIndex,
650 kTfLiteBuiltinMaxPool2d);
651 case kTfLiteBuiltinMaximum:
652 return VisitElementwiseBinaryOperator(delegateData,
653 tfLiteContext,
654 tfLiteNode,
655 nodeIndex,
656 kTfLiteBuiltinMaximum);
657 case kTfLiteBuiltinMean:
658 return VisitControlOperator(delegateData,
659 tfLiteContext,
660 tfLiteNode,
661 nodeIndex,
662 kTfLiteBuiltinMean);
663 case kTfLiteBuiltinMinimum:
664 return VisitElementwiseBinaryOperator(delegateData,
665 tfLiteContext,
666 tfLiteNode,
667 nodeIndex,
668 kTfLiteBuiltinMinimum);
669 case kTfLiteBuiltinMul:
670 return VisitElementwiseBinaryOperator(delegateData,
671 tfLiteContext,
672 tfLiteNode,
673 nodeIndex,
674 kTfLiteBuiltinMul);
675 case kTfLiteBuiltinNeg:
676 return VisitElementwiseUnaryOperator(delegateData,
677 tfLiteContext,
678 tfLiteNode,
679 nodeIndex,
680 armnn::UnaryOperation::Neg);
681 case kTfLiteBuiltinNotEqual:
682 return VisitComparisonOperator(delegateData,
683 tfLiteContext,
684 tfLiteNode,
685 nodeIndex,
686 kTfLiteBuiltinNotEqual);
687 case kTfLiteBuiltinPad:
688 return VisitPadOperator(delegateData,
689 tfLiteContext,
690 tfLiteNode,
691 nodeIndex,
692 kTfLiteBuiltinPad);
693 case kTfLiteBuiltinPadv2:
694 return VisitPadOperator(delegateData,
695 tfLiteContext,
696 tfLiteNode,
697 nodeIndex,
698 kTfLiteBuiltinPadv2);
699 case kTfLiteBuiltinPrelu:
700 return VisitActivationOperator(delegateData,
701 tfLiteContext,
702 tfLiteNode,
703 nodeIndex,
704 kTfLiteBuiltinPrelu);
705 case kTfLiteBuiltinQuantize:
706 return VisitQuantizeOperator(delegateData,
707 tfLiteContext,
708 tfLiteNode,
709 nodeIndex,
710 kTfLiteBuiltinQuantize);
711 case kTfLiteBuiltinRank:
712 return VisitControlOperator(delegateData,
713 tfLiteContext,
714 tfLiteNode,
715 nodeIndex,
716 kTfLiteBuiltinRank);
717 case kTfLiteBuiltinRelu:
718 return VisitActivationOperator(delegateData,
719 tfLiteContext,
720 tfLiteNode,
721 nodeIndex,
722 kTfLiteBuiltinRelu);
723 case kTfLiteBuiltinReluN1To1:
724 return VisitActivationOperator(delegateData,
725 tfLiteContext,
726 tfLiteNode,
727 nodeIndex,
728 kTfLiteBuiltinReluN1To1);
729 case kTfLiteBuiltinRelu6:
730 return VisitActivationOperator(delegateData,
731 tfLiteContext,
732 tfLiteNode,
733 nodeIndex,
734 kTfLiteBuiltinRelu6);
735 case kTfLiteBuiltinReshape:
736 return VisitReshapeOperator(delegateData,
737 tfLiteContext,
738 tfLiteNode,
739 nodeIndex,
740 kTfLiteBuiltinReshape);
741 case kTfLiteBuiltinResizeBilinear:
742 return VisitResizeOperator(delegateData,
743 tfLiteContext,
744 tfLiteNode,
745 nodeIndex,
746 kTfLiteBuiltinResizeBilinear);
747 case kTfLiteBuiltinResizeNearestNeighbor:
748 return VisitResizeOperator(delegateData,
749 tfLiteContext,
750 tfLiteNode,
751 nodeIndex,
752 kTfLiteBuiltinResizeNearestNeighbor);
753 case kTfLiteBuiltinRsqrt:
754 return VisitElementwiseUnaryOperator(delegateData,
755 tfLiteContext,
756 tfLiteNode,
757 nodeIndex,
758 armnn::UnaryOperation::Rsqrt);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +0000759 case kTfLiteBuiltinSplit:
760 return VisitSplitOperator(delegateData,
761 tfLiteContext,
762 tfLiteNode,
763 nodeIndex,
764 kTfLiteBuiltinSplit);
765 case kTfLiteBuiltinSplitV:
766 return VisitSplitVOperator(delegateData,
767 tfLiteContext,
768 tfLiteNode,
769 nodeIndex,
770 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +0100771 case kTfLiteBuiltinSqrt:
772 return VisitElementwiseUnaryOperator(delegateData,
773 tfLiteContext,
774 tfLiteNode,
775 nodeIndex,
776 armnn::UnaryOperation::Sqrt);
777 case kTfLiteBuiltinSqueeze:
778 return VisitSqueezeOperator(delegateData,
779 tfLiteContext,
780 tfLiteNode,
781 nodeIndex,
782 kTfLiteBuiltinSqueeze);
783 case kTfLiteBuiltinStridedSlice:
784 return VisitSliceOperator(delegateData,
785 tfLiteContext,
786 tfLiteNode,
787 nodeIndex,
788 kTfLiteBuiltinStridedSlice);
789 case kTfLiteBuiltinTranspose:
790 return VisitTransposeOperator(delegateData,
791 tfLiteContext,
792 tfLiteNode,
793 nodeIndex,
794 kTfLiteBuiltinTranspose);
795 case kTfLiteBuiltinTransposeConv:
796 return VisitConvolutionOperator(delegateData,
797 tfLiteContext,
798 tfLiteNode,
799 nodeIndex,
800 kTfLiteBuiltinTransposeConv);
801 case kTfLiteBuiltinSoftmax:
802 return VisitSoftmaxOperator(delegateData,
803 tfLiteContext,
804 tfLiteNode,
805 nodeIndex,
806 kTfLiteBuiltinSoftmax);
807 case kTfLiteBuiltinSpaceToBatchNd:
808 return VisitSpaceToBatchNdOperator(delegateData,
809 tfLiteContext,
810 tfLiteNode,
811 nodeIndex,
812 kTfLiteBuiltinSpaceToBatchNd);
813 case kTfLiteBuiltinSpaceToDepth:
814 return VisitSpaceToDepthOperator(delegateData,
815 tfLiteContext,
816 tfLiteNode,
817 nodeIndex,
818 kTfLiteBuiltinSpaceToDepth);
819 case kTfLiteBuiltinSub:
820 return VisitElementwiseBinaryOperator(delegateData,
821 tfLiteContext,
822 tfLiteNode,
823 nodeIndex,
824 kTfLiteBuiltinSub);
825 case kTfLiteBuiltinTanh:
826 return VisitActivationOperator(delegateData,
827 tfLiteContext,
828 tfLiteNode,
829 nodeIndex,
830 kTfLiteBuiltinTanh);
831 default:
832 return kTfLiteError;
833 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100834}
835
836} // armnnDelegate namespace