blob: 639e514a780009a6ecd106943fb6ef56532727f8 [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;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000356 armnn::Status loadingStatus;
357 if (delegate->m_Options.GetOptimizerOptions().m_ImportEnabled)
358 {
359 armnn::INetworkProperties networkProperties(true, true);
360 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
361 std::move(optNet),
362 errorMessage,
363 networkProperties);
364 }
365 else
366 {
367 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
368 std::move(optNet),
369 errorMessage);
370 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100371 if (loadingStatus != armnn::Status::Success)
372 {
373 // Optimize failed
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000374 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded:" + errorMessage);
Sadik Armagan62483be2020-10-23 17:14:43 +0100375 }
376 }
377 catch (std::exception& ex)
378 {
379 std::stringstream exMessage;
380 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
381 throw armnn::Exception(exMessage.str());
382 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100383
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000384 // Register debug callback function
385 if (delegate->m_Options.GetDebugCallbackFunction().has_value())
386 {
387 delegate->m_Runtime->RegisterDebugCallback(networkId, delegate->m_Options.GetDebugCallbackFunction().value());
388 }
389
Sadik Armagan3c24f432020-10-19 17:35:30 +0100390 // Create a new SubGraph with networkId and runtime
Sadik Armagan62483be2020-10-23 17:14:43 +0100391 return new ArmnnSubgraph(networkId, delegate->m_Runtime.get(), inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100392}
393
394TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
395{
Finn Williams6f9f9902020-11-13 13:23:15 +0000396 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100397 return kTfLiteOk;
398}
399
Sadik Armagan62483be2020-10-23 17:14:43 +0100400TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100401{
Sadik Armagan62483be2020-10-23 17:14:43 +0100402 // Prepare inputs
403 armnn::InputTensors inputTensors;
404 size_t inputIndex = 0;
405 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
406 {
407 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
408 if (tensor->allocation_type != kTfLiteMmapRo)
409 {
410 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
411 const armnn::ConstTensor inputTensor(inputBinding.second, tensor->data.data);
412 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100413
Sadik Armagan62483be2020-10-23 17:14:43 +0100414 ++inputIndex;
415 }
416 }
417
418 // Prepare outputs
419 armnn::OutputTensors outputTensors;
420 size_t outputIndex = 0;
421 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
422 {
423 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
424 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
425 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
426 outputTensors.emplace_back(outputIdx, outputTensor);
427
428 ++outputIndex;
429 }
430
431 // Run graph
432 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
433 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100434}
435
Sadik Armagan62483be2020-10-23 17:14:43 +0100436TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100437 TfLiteContext* tfLiteContext,
438 TfLiteRegistration* tfLiteRegistration,
439 TfLiteNode* tfLiteNode,
440 int nodeIndex)
441{
Sadik Armagan62483be2020-10-23 17:14:43 +0100442 switch (tfLiteRegistration->builtin_code)
443 {
444 case kTfLiteBuiltinAbs:
445 return VisitElementwiseUnaryOperator(delegateData,
446 tfLiteContext,
447 tfLiteNode,
448 nodeIndex,
449 armnn::UnaryOperation::Abs);
450 case kTfLiteBuiltinAdd:
451 return VisitElementwiseBinaryOperator(delegateData,
452 tfLiteContext,
453 tfLiteNode,
454 nodeIndex,
455 kTfLiteBuiltinAdd);
456 case kTfLiteBuiltinArgMax:
457 return VisitArgMinMaxOperator(delegateData,
458 tfLiteContext,
459 tfLiteNode,
460 nodeIndex,
461 kTfLiteBuiltinArgMax);
462 case kTfLiteBuiltinArgMin:
463 return VisitArgMinMaxOperator(delegateData,
464 tfLiteContext,
465 tfLiteNode,
466 nodeIndex,
467 kTfLiteBuiltinArgMin);
468 case kTfLiteBuiltinAveragePool2d:
469 return VisitPoolingOperator(delegateData,
470 tfLiteContext,
471 tfLiteNode,
472 nodeIndex,
473 kTfLiteBuiltinAveragePool2d);
474 case kTfLiteBuiltinBatchToSpaceNd:
475 return VisitBatchToSpaceNdOperator(delegateData,
476 tfLiteContext,
477 tfLiteNode,
478 nodeIndex,
479 kTfLiteBuiltinBatchToSpaceNd);
480 case kTfLiteBuiltinConcatenation:
481 return VisitControlOperator(delegateData,
482 tfLiteContext,
483 tfLiteNode,
484 nodeIndex,
485 kTfLiteBuiltinConcatenation);
486 case kTfLiteBuiltinConv2d:
487 return VisitConvolutionOperator(delegateData,
488 tfLiteContext,
489 tfLiteNode,
490 nodeIndex,
491 kTfLiteBuiltinConv2d);
492 case kTfLiteBuiltinDepthToSpace:
493 return VisitDepthToSpaceOperator(delegateData,
494 tfLiteContext,
495 tfLiteNode,
496 nodeIndex,
497 kTfLiteBuiltinDepthToSpace);
498 case kTfLiteBuiltinDepthwiseConv2d:
499 return VisitConvolutionOperator(delegateData,
500 tfLiteContext,
501 tfLiteNode,
502 nodeIndex,
503 kTfLiteBuiltinDepthwiseConv2d);
504 case kTfLiteBuiltinDequantize:
505 return VisitDequantizeOperator(delegateData,
506 tfLiteContext,
507 tfLiteNode,
508 nodeIndex,
509 kTfLiteBuiltinDequantize);
510 case kTfLiteBuiltinDiv:
511 return VisitElementwiseBinaryOperator(delegateData,
512 tfLiteContext,
513 tfLiteNode,
514 nodeIndex,
515 kTfLiteBuiltinDiv);
516 case kTfLiteBuiltinElu:
517 return VisitActivationOperator(delegateData,
518 tfLiteContext,
519 tfLiteNode,
520 nodeIndex,
521 kTfLiteBuiltinElu);
522 case kTfLiteBuiltinEqual:
523 return VisitComparisonOperator(delegateData,
524 tfLiteContext,
525 tfLiteNode,
526 nodeIndex,
527 kTfLiteBuiltinEqual);
528 case kTfLiteBuiltinExp:
529 return VisitElementwiseUnaryOperator(delegateData,
530 tfLiteContext,
531 tfLiteNode,
532 nodeIndex,
533 armnn::UnaryOperation::Exp);
534 case kTfLiteBuiltinExpandDims:
535 return VisitExpandDimsOperator(delegateData,
536 tfLiteContext,
537 tfLiteNode,
538 nodeIndex,
539 kTfLiteBuiltinExpandDims);
540 case kTfLiteBuiltinFill:
541 return VisitFillOperator(delegateData,
542 tfLiteContext,
543 tfLiteNode,
544 nodeIndex,
545 kTfLiteBuiltinFill);
546 case kTfLiteBuiltinFloor:
547 return VisitFloorOperator(delegateData,
548 tfLiteContext,
549 tfLiteNode,
550 nodeIndex,
551 kTfLiteBuiltinFloor);
552 case kTfLiteBuiltinFullyConnected:
553 return VisitFullyConnectedOperator(delegateData,
554 tfLiteContext,
555 tfLiteNode,
556 nodeIndex,
557 kTfLiteBuiltinFullyConnected);
558 case kTfLiteBuiltinGather:
559 return VisitGatherOperator(delegateData,
560 tfLiteContext,
561 tfLiteNode,
562 nodeIndex,
563 kTfLiteBuiltinGather);
564 case kTfLiteBuiltinGatherNd:
565 return VisitGatherOperator(delegateData,
566 tfLiteContext,
567 tfLiteNode,
568 nodeIndex,
569 kTfLiteBuiltinGatherNd);
570 case kTfLiteBuiltinGreater:
571 return VisitComparisonOperator(delegateData,
572 tfLiteContext,
573 tfLiteNode,
574 nodeIndex,
575 kTfLiteBuiltinGreater);
576 case kTfLiteBuiltinGreaterEqual:
577 return VisitComparisonOperator(delegateData,
578 tfLiteContext,
579 tfLiteNode,
580 nodeIndex,
581 kTfLiteBuiltinGreaterEqual);
582 case kTfLiteBuiltinHardSwish:
583 return VisitActivationOperator(delegateData,
584 tfLiteContext,
585 tfLiteNode,
586 nodeIndex,
587 kTfLiteBuiltinHardSwish);
588 case kTfLiteBuiltinL2Normalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000589 return VisitL2NormalizationOperator(delegateData,
590 tfLiteContext,
591 tfLiteNode,
592 nodeIndex,
593 kTfLiteBuiltinL2Normalization);
Sadik Armagan62483be2020-10-23 17:14:43 +0100594 case kTfLiteBuiltinL2Pool2d:
595 return VisitPoolingOperator(delegateData,
596 tfLiteContext,
597 tfLiteNode,
598 nodeIndex,
599 kTfLiteBuiltinL2Pool2d);
600 case kTfLiteBuiltinLess:
601 return VisitComparisonOperator(delegateData,
602 tfLiteContext,
603 tfLiteNode,
604 nodeIndex,
605 kTfLiteBuiltinLess);
606 case kTfLiteBuiltinLessEqual:
607 return VisitComparisonOperator(delegateData,
608 tfLiteContext,
609 tfLiteNode,
610 nodeIndex,
611 kTfLiteBuiltinLessEqual);
612 case kTfLiteBuiltinLocalResponseNormalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000613 return VisitLocalResponseNormalizationOperator(delegateData,
614 tfLiteContext,
615 tfLiteNode,
616 nodeIndex,
617 kTfLiteBuiltinLocalResponseNormalization);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000618 case kTfLiteBuiltinLogicalAnd:
619 return VisitLogicalBinaryOperator(delegateData,
620 tfLiteContext,
621 tfLiteNode,
622 nodeIndex,
623 kTfLiteBuiltinLogicalAnd,
624 armnn::LogicalBinaryOperation::LogicalAnd);
625 case kTfLiteBuiltinLogicalNot:
626 return VisitElementwiseUnaryOperator(delegateData,
627 tfLiteContext,
628 tfLiteNode,
629 nodeIndex,
630 armnn::UnaryOperation::LogicalNot);
631 case kTfLiteBuiltinLogicalOr:
632 return VisitLogicalBinaryOperator(delegateData,
633 tfLiteContext,
634 tfLiteNode,
635 nodeIndex,
636 kTfLiteBuiltinLogicalOr,
637 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100638 case kTfLiteBuiltinLogistic:
639 return VisitActivationOperator(delegateData,
640 tfLiteContext,
641 tfLiteNode,
642 nodeIndex,
643 kTfLiteBuiltinLogistic);
644 case kTfLiteBuiltinLogSoftmax:
645 return VisitSoftmaxOperator(delegateData,
646 tfLiteContext,
647 tfLiteNode,
648 nodeIndex,
649 kTfLiteBuiltinLogSoftmax);
650 case kTfLiteBuiltinLstm:
651 return VisitLstmOperator(delegateData,
652 tfLiteContext,
653 tfLiteNode,
654 nodeIndex,
655 kTfLiteBuiltinLstm);
656 case kTfLiteBuiltinMaxPool2d:
657 return VisitPoolingOperator(delegateData,
658 tfLiteContext,
659 tfLiteNode,
660 nodeIndex,
661 kTfLiteBuiltinMaxPool2d);
662 case kTfLiteBuiltinMaximum:
663 return VisitElementwiseBinaryOperator(delegateData,
664 tfLiteContext,
665 tfLiteNode,
666 nodeIndex,
667 kTfLiteBuiltinMaximum);
668 case kTfLiteBuiltinMean:
669 return VisitControlOperator(delegateData,
670 tfLiteContext,
671 tfLiteNode,
672 nodeIndex,
673 kTfLiteBuiltinMean);
674 case kTfLiteBuiltinMinimum:
675 return VisitElementwiseBinaryOperator(delegateData,
676 tfLiteContext,
677 tfLiteNode,
678 nodeIndex,
679 kTfLiteBuiltinMinimum);
680 case kTfLiteBuiltinMul:
681 return VisitElementwiseBinaryOperator(delegateData,
682 tfLiteContext,
683 tfLiteNode,
684 nodeIndex,
685 kTfLiteBuiltinMul);
686 case kTfLiteBuiltinNeg:
687 return VisitElementwiseUnaryOperator(delegateData,
688 tfLiteContext,
689 tfLiteNode,
690 nodeIndex,
691 armnn::UnaryOperation::Neg);
692 case kTfLiteBuiltinNotEqual:
693 return VisitComparisonOperator(delegateData,
694 tfLiteContext,
695 tfLiteNode,
696 nodeIndex,
697 kTfLiteBuiltinNotEqual);
698 case kTfLiteBuiltinPad:
699 return VisitPadOperator(delegateData,
700 tfLiteContext,
701 tfLiteNode,
702 nodeIndex,
703 kTfLiteBuiltinPad);
704 case kTfLiteBuiltinPadv2:
705 return VisitPadOperator(delegateData,
706 tfLiteContext,
707 tfLiteNode,
708 nodeIndex,
709 kTfLiteBuiltinPadv2);
710 case kTfLiteBuiltinPrelu:
711 return VisitActivationOperator(delegateData,
712 tfLiteContext,
713 tfLiteNode,
714 nodeIndex,
715 kTfLiteBuiltinPrelu);
716 case kTfLiteBuiltinQuantize:
717 return VisitQuantizeOperator(delegateData,
718 tfLiteContext,
719 tfLiteNode,
720 nodeIndex,
721 kTfLiteBuiltinQuantize);
722 case kTfLiteBuiltinRank:
723 return VisitControlOperator(delegateData,
724 tfLiteContext,
725 tfLiteNode,
726 nodeIndex,
727 kTfLiteBuiltinRank);
728 case kTfLiteBuiltinRelu:
729 return VisitActivationOperator(delegateData,
730 tfLiteContext,
731 tfLiteNode,
732 nodeIndex,
733 kTfLiteBuiltinRelu);
734 case kTfLiteBuiltinReluN1To1:
735 return VisitActivationOperator(delegateData,
736 tfLiteContext,
737 tfLiteNode,
738 nodeIndex,
739 kTfLiteBuiltinReluN1To1);
740 case kTfLiteBuiltinRelu6:
741 return VisitActivationOperator(delegateData,
742 tfLiteContext,
743 tfLiteNode,
744 nodeIndex,
745 kTfLiteBuiltinRelu6);
746 case kTfLiteBuiltinReshape:
747 return VisitReshapeOperator(delegateData,
748 tfLiteContext,
749 tfLiteNode,
750 nodeIndex,
751 kTfLiteBuiltinReshape);
752 case kTfLiteBuiltinResizeBilinear:
753 return VisitResizeOperator(delegateData,
754 tfLiteContext,
755 tfLiteNode,
756 nodeIndex,
757 kTfLiteBuiltinResizeBilinear);
758 case kTfLiteBuiltinResizeNearestNeighbor:
759 return VisitResizeOperator(delegateData,
760 tfLiteContext,
761 tfLiteNode,
762 nodeIndex,
763 kTfLiteBuiltinResizeNearestNeighbor);
764 case kTfLiteBuiltinRsqrt:
765 return VisitElementwiseUnaryOperator(delegateData,
766 tfLiteContext,
767 tfLiteNode,
768 nodeIndex,
769 armnn::UnaryOperation::Rsqrt);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +0000770 case kTfLiteBuiltinSplit:
771 return VisitSplitOperator(delegateData,
772 tfLiteContext,
773 tfLiteNode,
774 nodeIndex,
775 kTfLiteBuiltinSplit);
776 case kTfLiteBuiltinSplitV:
777 return VisitSplitVOperator(delegateData,
778 tfLiteContext,
779 tfLiteNode,
780 nodeIndex,
781 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +0100782 case kTfLiteBuiltinSqrt:
783 return VisitElementwiseUnaryOperator(delegateData,
784 tfLiteContext,
785 tfLiteNode,
786 nodeIndex,
787 armnn::UnaryOperation::Sqrt);
788 case kTfLiteBuiltinSqueeze:
789 return VisitSqueezeOperator(delegateData,
790 tfLiteContext,
791 tfLiteNode,
792 nodeIndex,
793 kTfLiteBuiltinSqueeze);
794 case kTfLiteBuiltinStridedSlice:
795 return VisitSliceOperator(delegateData,
796 tfLiteContext,
797 tfLiteNode,
798 nodeIndex,
799 kTfLiteBuiltinStridedSlice);
800 case kTfLiteBuiltinTranspose:
801 return VisitTransposeOperator(delegateData,
802 tfLiteContext,
803 tfLiteNode,
804 nodeIndex,
805 kTfLiteBuiltinTranspose);
806 case kTfLiteBuiltinTransposeConv:
807 return VisitConvolutionOperator(delegateData,
808 tfLiteContext,
809 tfLiteNode,
810 nodeIndex,
811 kTfLiteBuiltinTransposeConv);
812 case kTfLiteBuiltinSoftmax:
813 return VisitSoftmaxOperator(delegateData,
814 tfLiteContext,
815 tfLiteNode,
816 nodeIndex,
817 kTfLiteBuiltinSoftmax);
818 case kTfLiteBuiltinSpaceToBatchNd:
819 return VisitSpaceToBatchNdOperator(delegateData,
820 tfLiteContext,
821 tfLiteNode,
822 nodeIndex,
823 kTfLiteBuiltinSpaceToBatchNd);
824 case kTfLiteBuiltinSpaceToDepth:
825 return VisitSpaceToDepthOperator(delegateData,
826 tfLiteContext,
827 tfLiteNode,
828 nodeIndex,
829 kTfLiteBuiltinSpaceToDepth);
830 case kTfLiteBuiltinSub:
831 return VisitElementwiseBinaryOperator(delegateData,
832 tfLiteContext,
833 tfLiteNode,
834 nodeIndex,
835 kTfLiteBuiltinSub);
836 case kTfLiteBuiltinTanh:
837 return VisitActivationOperator(delegateData,
838 tfLiteContext,
839 tfLiteNode,
840 nodeIndex,
841 kTfLiteBuiltinTanh);
842 default:
843 return kTfLiteError;
844 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100845}
846
847} // armnnDelegate namespace