blob: e637ca6ebf93a1b5093a12dc3835fefd8245a00e [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"
Sadik Armagana2747482021-02-09 10:28:54 +000028#include "Reduce.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010029#include "Resize.hpp"
30#include "Round.hpp"
31#include "Slice.hpp"
32#include "Softmax.hpp"
33#include "SpaceDepth.hpp"
Sadik Armagan34fa1bd2020-11-27 12:40:52 +000034#include "Split.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010035#include "Transpose.hpp"
36
37#include <flatbuffers/flatbuffers.h>
38#include <tensorflow/lite/context_util.h>
39
Sadik Armagan3c24f432020-10-19 17:35:30 +010040#include <algorithm>
Matthew Sloyanac001ee2021-02-03 10:43:04 +000041#include <iostream>
Sadik Armagan62483be2020-10-23 17:14:43 +010042#include <sstream>
Sadik Armagan3c24f432020-10-19 17:35:30 +010043
44namespace armnnDelegate
45{
46
Sadik Armagan62483be2020-10-23 17:14:43 +010047DelegateOptions TfLiteArmnnDelegateOptionsDefault()
48{
49 DelegateOptions options(armnn::Compute::CpuRef);
50 return options;
51}
52
53TfLiteDelegate* TfLiteArmnnDelegateCreate(armnnDelegate::DelegateOptions options)
54{
55 auto* armnnDelegate = new ::armnnDelegate::Delegate(options);
56 return armnnDelegate->GetDelegate();
57}
58
59void TfLiteArmnnDelegateDelete(TfLiteDelegate* tfLiteDelegate)
60{
61 if (tfLiteDelegate != nullptr)
62 {
63 delete static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_);
64 }
65}
66
67TfLiteStatus DoPrepare(TfLiteContext* tfLiteContext, TfLiteDelegate* tfLiteDelegate)
68{
69 TfLiteIntArray* supportedOperators =
70 static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_)->IdentifyOperatorsToDelegate(tfLiteContext);
71
72 // ArmNN Delegate Registration
73 static const TfLiteRegistration kArmnnSubgraphRegistration = {
74 // ArmnnSubgraph Init
75 .init = [](TfLiteContext* tfLiteContext, const char* buffer, size_t length) -> void* {
Finn Williams6f9f9902020-11-13 13:23:15 +000076 armnn::IgnoreUnused(length);
Sadik Armagan62483be2020-10-23 17:14:43 +010077 const TfLiteDelegateParams* parameters = reinterpret_cast<const TfLiteDelegateParams*>(buffer);
78
79 return static_cast<void*>(ArmnnSubgraph::Create(
80 tfLiteContext, parameters, static_cast<::armnnDelegate::Delegate*>(parameters->delegate->data_)));
81 },
82 // ArmnnSubgraph Free
83 .free = [](TfLiteContext* tfLiteContext, void* buffer) -> void {
Finn Williams6f9f9902020-11-13 13:23:15 +000084 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan62483be2020-10-23 17:14:43 +010085 if (buffer != nullptr)
86 {
87 delete static_cast<ArmnnSubgraph*>(buffer);
88 }
89 },
90 // ArmnnSubgraph Prepare
91 .prepare = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
92 if (tfLiteNode->user_data == nullptr)
93 {
94 return kTfLiteError;
95 }
Sadik Armagan62483be2020-10-23 17:14:43 +010096 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Prepare(tfLiteContext);
97 },
98 // ArmnnSubgraph Invoke
99 .invoke = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
100 if (tfLiteNode->user_data == nullptr)
101 {
102 return kTfLiteError;
103 }
104
105 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Invoke(tfLiteContext, tfLiteNode);
106 },
107
108 .profiling_string = nullptr,
109 .builtin_code = kTfLiteBuiltinDelegate,
110 .custom_name = "TfLiteArmNnDelegate",
111 .version = 1,
112 };
113
114 const TfLiteStatus status =
115 tfLiteContext->ReplaceNodeSubsetsWithDelegateKernels(
116 tfLiteContext, kArmnnSubgraphRegistration, supportedOperators, tfLiteDelegate);
117
118 TfLiteIntArrayFree(supportedOperators);
119 return status;
120
121}
122
Sadik Armagan3c24f432020-10-19 17:35:30 +0100123Delegate::Delegate(armnnDelegate::DelegateOptions options)
124 : m_Runtime(nullptr, nullptr),
125 m_Options(std::move(options))
126{
Jan Eilers2cd18472020-12-15 10:42:38 +0000127 // Configures logging for ARMNN
128 if (options.IsLoggingEnabled())
129 {
130 armnn::ConfigureLogging(true, true, options.GetLoggingSeverity());
131 }
132
Sadik Armagan3c24f432020-10-19 17:35:30 +0100133 // Create ArmNN Runtime
134 armnn::IRuntime::CreationOptions runtimeOptions;
Sadik Armagan4189cc52020-11-11 18:01:48 +0000135
136 auto backendOptions = m_Options.GetBackendOptions();
137 if (!backendOptions.empty())
138 {
139 runtimeOptions.m_BackendOptions = backendOptions;
140 }
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000141 else if (!m_Options.GetOptimizerOptions().m_ModelOptions.empty())
142 {
143 runtimeOptions.m_BackendOptions = m_Options.GetOptimizerOptions().m_ModelOptions;
144 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100145 m_Runtime = armnn::IRuntime::Create(runtimeOptions);
146
147 std::vector<armnn::BackendId> backends;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100148 if (m_Runtime)
149 {
150 const armnn::BackendIdSet supportedDevices = m_Runtime->GetDeviceSpec().GetSupportedBackends();
151 for (auto& backend : m_Options.GetBackends())
152 {
153 if (std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) == supportedDevices.cend())
154 {
Sadik Armagan0534e032020-10-27 17:30:18 +0000155 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100156 "TfLiteArmnnDelegate: Requested unknown backend %s", backend.Get().c_str());
157 }
158 else
159 {
160 backends.push_back(backend);
161 }
162 }
163 }
164
165 if (backends.empty())
166 {
167 // No known backend specified
168 throw armnn::InvalidArgumentException("TfLiteArmnnDelegate: No known backend specified.");
169 }
170 m_Options.SetBackends(backends);
171
172 TFLITE_LOG_PROD_ONCE(tflite::TFLITE_LOG_INFO, "TfLiteArmnnDelegate: Created TfLite ArmNN delegate.");
173}
174
Sadik Armagan62483be2020-10-23 17:14:43 +0100175TfLiteIntArray* Delegate::IdentifyOperatorsToDelegate(TfLiteContext* tfLiteContext)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100176{
177 TfLiteIntArray* executionPlan = nullptr;
178 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
179 {
180 TF_LITE_KERNEL_LOG(tfLiteContext, "TfLiteArmnnDelegate: Unable to get graph execution plan.");
181 return nullptr;
182 }
183
Sadik Armagan62483be2020-10-23 17:14:43 +0100184 // Delegate data with null network
185 DelegateData delegateData(m_Options.GetBackends());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100186
187 TfLiteIntArray* nodesToDelegate = TfLiteIntArrayCreate(executionPlan->size);
188 nodesToDelegate->size = 0;
189 for (int i = 0; i < executionPlan->size; ++i)
190 {
191 const int nodeIndex = executionPlan->data[i];
192
193 // If TfLite nodes can be delegated to ArmNN
194 TfLiteNode* tfLiteNode = nullptr;
195 TfLiteRegistration* tfLiteRegistration = nullptr;
196 if (tfLiteContext->GetNodeAndRegistration(
197 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
198 {
199 TF_LITE_KERNEL_LOG(tfLiteContext,
200 "TfLiteArmnnDelegate: Unable to get node and registration for node %d.",
201 nodeIndex);
202 continue;
203 }
204
205 if (ArmnnSubgraph::VisitNode(
Sadik Armagan62483be2020-10-23 17:14:43 +0100206 delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100207 {
208 // node is not supported by ArmNN
209 continue;
210 }
211
212 nodesToDelegate->data[nodesToDelegate->size++] = nodeIndex;
213 }
214
Sadik Armagan62483be2020-10-23 17:14:43 +0100215 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100216 return nodesToDelegate;
217}
218
219TfLiteDelegate* Delegate::GetDelegate()
220{
221 return &m_Delegate;
222}
223
Matthew Sloyanac001ee2021-02-03 10:43:04 +0000224const std::string Delegate::GetVersion()
225{
226 return DELEGATE_VERSION;
227}
228
Sadik Armagan62483be2020-10-23 17:14:43 +0100229TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
230 TfLiteContext* tfLiteContext,
231 const TfLiteIntArray* inputs,
232 std::vector<armnn::BindingPointInfo>& inputBindings)
233{
Finn Williams6f9f9902020-11-13 13:23:15 +0000234 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100235 for (unsigned int i = 0; i < numInputs; ++i)
236 {
237 const int32_t tensorId = inputs->data[i];
238 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000239 // Do not create bindings for constant inputs
240 if (tensor.allocation_type == kTfLiteMmapRo)
241 {
242 continue;
243 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100244
245 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
246 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
247
248 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
249 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
250 outputSlot.SetTensorInfo(tensorInfo);
251
252 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000253 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100254
Sadik Armagan6e36a642020-11-10 21:18:41 +0000255 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100256 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000257
Sadik Armagan62483be2020-10-23 17:14:43 +0100258 return kTfLiteOk;
259}
260
261TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
262 TfLiteContext* tfLiteContext,
263 const TfLiteIntArray* outputs,
264 std::vector<armnn::BindingPointInfo>& outputBindings)
265{
Finn Williams6f9f9902020-11-13 13:23:15 +0000266 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100267 for (unsigned int i = 0; i < numOutputs; ++i)
268 {
269 const int32_t tensorId = outputs->data[i];
270 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
271
272 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
273 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
274
275 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Finn Williams6f9f9902020-11-13 13:23:15 +0000276 ARMNN_ASSERT(delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] != nullptr);
277 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100278 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
279 }
280
281 return kTfLiteOk;
282}
283
Sadik Armagan3c24f432020-10-19 17:35:30 +0100284ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
285 const TfLiteDelegateParams* parameters,
286 const Delegate* delegate)
287{
288 TfLiteIntArray* executionPlan;
289 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
290 {
291 return nullptr;
292 }
293
Sadik Armagan62483be2020-10-23 17:14:43 +0100294 // Initialize DelegateData holds network and output slots information
295 DelegateData delegateData(delegate->m_Options.GetBackends());
296
297 // Build ArmNN Network
Sadik Armagan3c24f432020-10-19 17:35:30 +0100298 armnn::NetworkOptions networkOptions = {};
299 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100300 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100301
Sadik Armagan6e36a642020-11-10 21:18:41 +0000302 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
303
Sadik Armagan62483be2020-10-23 17:14:43 +0100304 std::vector<armnn::BindingPointInfo> inputBindings;
305 std::vector<armnn::BindingPointInfo> outputBindings;
306
307 // Add input layer
308 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
309 if (status != kTfLiteOk)
310 {
311 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
312 }
313
314 // Parse TfLite delegate nodes to ArmNN
Sadik Armagan3c24f432020-10-19 17:35:30 +0100315 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
316 {
317 const int nodeIndex = parameters->nodes_to_replace->data[i];
318
319 TfLiteNode* tfLiteNode = nullptr;
320 TfLiteRegistration* tfLiteRegistration = nullptr;
321 if (tfLiteContext->GetNodeAndRegistration(
322 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
323 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000324 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100325 }
326
Sadik Armagan62483be2020-10-23 17:14:43 +0100327 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100328 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000329 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100330 }
331 }
332
Sadik Armagan62483be2020-10-23 17:14:43 +0100333 // Add Output layer
334 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
335 if (status != kTfLiteOk)
336 {
337 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
338 }
339
340 // Optimize ArmNN network
341 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
342 try
343 {
Sadik Armagan6e36a642020-11-10 21:18:41 +0000344 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100345 delegate->m_Options.GetBackends(),
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000346 delegate->m_Runtime->GetDeviceSpec(),
347 delegate->m_Options.GetOptimizerOptions());
Sadik Armagan62483be2020-10-23 17:14:43 +0100348 }
349 catch (std::exception &ex)
350 {
351 std::stringstream exMessage;
352 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
353 throw armnn::Exception(exMessage.str());
354 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100355 if (!optNet)
356 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100357 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100358 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
359 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100360
361 try
362 {
363 // Load graph into runtime
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000364 std::string errorMessage;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000365 armnn::Status loadingStatus;
366 if (delegate->m_Options.GetOptimizerOptions().m_ImportEnabled)
367 {
Francis Murtagh73d3e2e2021-04-29 14:23:04 +0100368 armnn::INetworkProperties networkProperties(false,
369 armnn::MemorySource::Malloc,
370 armnn::MemorySource::Malloc);
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000371 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
372 std::move(optNet),
373 errorMessage,
374 networkProperties);
375 }
376 else
377 {
378 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
379 std::move(optNet),
380 errorMessage);
381 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100382 if (loadingStatus != armnn::Status::Success)
383 {
384 // Optimize failed
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000385 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded:" + errorMessage);
Sadik Armagan62483be2020-10-23 17:14:43 +0100386 }
387 }
388 catch (std::exception& ex)
389 {
390 std::stringstream exMessage;
391 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
392 throw armnn::Exception(exMessage.str());
393 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100394
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000395 // Register debug callback function
396 if (delegate->m_Options.GetDebugCallbackFunction().has_value())
397 {
398 delegate->m_Runtime->RegisterDebugCallback(networkId, delegate->m_Options.GetDebugCallbackFunction().value());
399 }
400
Sadik Armagan3c24f432020-10-19 17:35:30 +0100401 // Create a new SubGraph with networkId and runtime
Sadik Armagan62483be2020-10-23 17:14:43 +0100402 return new ArmnnSubgraph(networkId, delegate->m_Runtime.get(), inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100403}
404
405TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
406{
Finn Williams6f9f9902020-11-13 13:23:15 +0000407 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100408 return kTfLiteOk;
409}
410
Sadik Armagan62483be2020-10-23 17:14:43 +0100411TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100412{
Sadik Armagan62483be2020-10-23 17:14:43 +0100413 // Prepare inputs
414 armnn::InputTensors inputTensors;
415 size_t inputIndex = 0;
416 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
417 {
418 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
419 if (tensor->allocation_type != kTfLiteMmapRo)
420 {
421 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
422 const armnn::ConstTensor inputTensor(inputBinding.second, tensor->data.data);
423 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100424
Sadik Armagan62483be2020-10-23 17:14:43 +0100425 ++inputIndex;
426 }
427 }
428
429 // Prepare outputs
430 armnn::OutputTensors outputTensors;
431 size_t outputIndex = 0;
432 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
433 {
434 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
435 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
436 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
437 outputTensors.emplace_back(outputIdx, outputTensor);
438
439 ++outputIndex;
440 }
441
442 // Run graph
443 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
444 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100445}
446
Sadik Armagan62483be2020-10-23 17:14:43 +0100447TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100448 TfLiteContext* tfLiteContext,
449 TfLiteRegistration* tfLiteRegistration,
450 TfLiteNode* tfLiteNode,
451 int nodeIndex)
452{
Sadik Armagan62483be2020-10-23 17:14:43 +0100453 switch (tfLiteRegistration->builtin_code)
454 {
455 case kTfLiteBuiltinAbs:
456 return VisitElementwiseUnaryOperator(delegateData,
457 tfLiteContext,
458 tfLiteNode,
459 nodeIndex,
460 armnn::UnaryOperation::Abs);
461 case kTfLiteBuiltinAdd:
462 return VisitElementwiseBinaryOperator(delegateData,
463 tfLiteContext,
464 tfLiteNode,
465 nodeIndex,
466 kTfLiteBuiltinAdd);
467 case kTfLiteBuiltinArgMax:
468 return VisitArgMinMaxOperator(delegateData,
469 tfLiteContext,
470 tfLiteNode,
471 nodeIndex,
472 kTfLiteBuiltinArgMax);
473 case kTfLiteBuiltinArgMin:
474 return VisitArgMinMaxOperator(delegateData,
475 tfLiteContext,
476 tfLiteNode,
477 nodeIndex,
478 kTfLiteBuiltinArgMin);
479 case kTfLiteBuiltinAveragePool2d:
480 return VisitPoolingOperator(delegateData,
481 tfLiteContext,
482 tfLiteNode,
483 nodeIndex,
484 kTfLiteBuiltinAveragePool2d);
485 case kTfLiteBuiltinBatchToSpaceNd:
486 return VisitBatchToSpaceNdOperator(delegateData,
487 tfLiteContext,
488 tfLiteNode,
489 nodeIndex,
490 kTfLiteBuiltinBatchToSpaceNd);
Sadik Armagan937565b2021-04-21 14:03:28 +0100491 case kTfLiteBuiltinCast:
492 return VisitCastOperator(delegateData,
493 tfLiteContext,
494 tfLiteNode,
495 nodeIndex,
496 kTfLiteBuiltinCast);
Sadik Armagan62483be2020-10-23 17:14:43 +0100497 case kTfLiteBuiltinConcatenation:
498 return VisitControlOperator(delegateData,
499 tfLiteContext,
500 tfLiteNode,
501 nodeIndex,
502 kTfLiteBuiltinConcatenation);
503 case kTfLiteBuiltinConv2d:
504 return VisitConvolutionOperator(delegateData,
505 tfLiteContext,
506 tfLiteNode,
507 nodeIndex,
508 kTfLiteBuiltinConv2d);
509 case kTfLiteBuiltinDepthToSpace:
510 return VisitDepthToSpaceOperator(delegateData,
511 tfLiteContext,
512 tfLiteNode,
513 nodeIndex,
514 kTfLiteBuiltinDepthToSpace);
515 case kTfLiteBuiltinDepthwiseConv2d:
516 return VisitConvolutionOperator(delegateData,
517 tfLiteContext,
518 tfLiteNode,
519 nodeIndex,
520 kTfLiteBuiltinDepthwiseConv2d);
521 case kTfLiteBuiltinDequantize:
522 return VisitDequantizeOperator(delegateData,
523 tfLiteContext,
524 tfLiteNode,
525 nodeIndex,
526 kTfLiteBuiltinDequantize);
527 case kTfLiteBuiltinDiv:
528 return VisitElementwiseBinaryOperator(delegateData,
529 tfLiteContext,
530 tfLiteNode,
531 nodeIndex,
532 kTfLiteBuiltinDiv);
533 case kTfLiteBuiltinElu:
534 return VisitActivationOperator(delegateData,
535 tfLiteContext,
536 tfLiteNode,
537 nodeIndex,
538 kTfLiteBuiltinElu);
539 case kTfLiteBuiltinEqual:
540 return VisitComparisonOperator(delegateData,
541 tfLiteContext,
542 tfLiteNode,
543 nodeIndex,
544 kTfLiteBuiltinEqual);
545 case kTfLiteBuiltinExp:
546 return VisitElementwiseUnaryOperator(delegateData,
547 tfLiteContext,
548 tfLiteNode,
549 nodeIndex,
550 armnn::UnaryOperation::Exp);
551 case kTfLiteBuiltinExpandDims:
552 return VisitExpandDimsOperator(delegateData,
553 tfLiteContext,
554 tfLiteNode,
555 nodeIndex,
556 kTfLiteBuiltinExpandDims);
557 case kTfLiteBuiltinFill:
558 return VisitFillOperator(delegateData,
559 tfLiteContext,
560 tfLiteNode,
561 nodeIndex,
562 kTfLiteBuiltinFill);
563 case kTfLiteBuiltinFloor:
564 return VisitFloorOperator(delegateData,
565 tfLiteContext,
566 tfLiteNode,
567 nodeIndex,
568 kTfLiteBuiltinFloor);
569 case kTfLiteBuiltinFullyConnected:
570 return VisitFullyConnectedOperator(delegateData,
571 tfLiteContext,
572 tfLiteNode,
573 nodeIndex,
574 kTfLiteBuiltinFullyConnected);
575 case kTfLiteBuiltinGather:
576 return VisitGatherOperator(delegateData,
577 tfLiteContext,
578 tfLiteNode,
579 nodeIndex,
580 kTfLiteBuiltinGather);
581 case kTfLiteBuiltinGatherNd:
582 return VisitGatherOperator(delegateData,
583 tfLiteContext,
584 tfLiteNode,
585 nodeIndex,
586 kTfLiteBuiltinGatherNd);
587 case kTfLiteBuiltinGreater:
588 return VisitComparisonOperator(delegateData,
589 tfLiteContext,
590 tfLiteNode,
591 nodeIndex,
592 kTfLiteBuiltinGreater);
593 case kTfLiteBuiltinGreaterEqual:
594 return VisitComparisonOperator(delegateData,
595 tfLiteContext,
596 tfLiteNode,
597 nodeIndex,
598 kTfLiteBuiltinGreaterEqual);
599 case kTfLiteBuiltinHardSwish:
600 return VisitActivationOperator(delegateData,
601 tfLiteContext,
602 tfLiteNode,
603 nodeIndex,
604 kTfLiteBuiltinHardSwish);
605 case kTfLiteBuiltinL2Normalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000606 return VisitL2NormalizationOperator(delegateData,
607 tfLiteContext,
608 tfLiteNode,
609 nodeIndex,
610 kTfLiteBuiltinL2Normalization);
Sadik Armagan62483be2020-10-23 17:14:43 +0100611 case kTfLiteBuiltinL2Pool2d:
612 return VisitPoolingOperator(delegateData,
613 tfLiteContext,
614 tfLiteNode,
615 nodeIndex,
616 kTfLiteBuiltinL2Pool2d);
617 case kTfLiteBuiltinLess:
618 return VisitComparisonOperator(delegateData,
619 tfLiteContext,
620 tfLiteNode,
621 nodeIndex,
622 kTfLiteBuiltinLess);
623 case kTfLiteBuiltinLessEqual:
624 return VisitComparisonOperator(delegateData,
625 tfLiteContext,
626 tfLiteNode,
627 nodeIndex,
628 kTfLiteBuiltinLessEqual);
629 case kTfLiteBuiltinLocalResponseNormalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000630 return VisitLocalResponseNormalizationOperator(delegateData,
631 tfLiteContext,
632 tfLiteNode,
633 nodeIndex,
634 kTfLiteBuiltinLocalResponseNormalization);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000635 case kTfLiteBuiltinLogicalAnd:
636 return VisitLogicalBinaryOperator(delegateData,
637 tfLiteContext,
638 tfLiteNode,
639 nodeIndex,
640 kTfLiteBuiltinLogicalAnd,
641 armnn::LogicalBinaryOperation::LogicalAnd);
642 case kTfLiteBuiltinLogicalNot:
643 return VisitElementwiseUnaryOperator(delegateData,
644 tfLiteContext,
645 tfLiteNode,
646 nodeIndex,
647 armnn::UnaryOperation::LogicalNot);
648 case kTfLiteBuiltinLogicalOr:
649 return VisitLogicalBinaryOperator(delegateData,
650 tfLiteContext,
651 tfLiteNode,
652 nodeIndex,
653 kTfLiteBuiltinLogicalOr,
654 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100655 case kTfLiteBuiltinLogistic:
656 return VisitActivationOperator(delegateData,
657 tfLiteContext,
658 tfLiteNode,
659 nodeIndex,
660 kTfLiteBuiltinLogistic);
661 case kTfLiteBuiltinLogSoftmax:
662 return VisitSoftmaxOperator(delegateData,
663 tfLiteContext,
664 tfLiteNode,
665 nodeIndex,
666 kTfLiteBuiltinLogSoftmax);
667 case kTfLiteBuiltinLstm:
668 return VisitLstmOperator(delegateData,
669 tfLiteContext,
670 tfLiteNode,
671 nodeIndex,
672 kTfLiteBuiltinLstm);
673 case kTfLiteBuiltinMaxPool2d:
674 return VisitPoolingOperator(delegateData,
675 tfLiteContext,
676 tfLiteNode,
677 nodeIndex,
678 kTfLiteBuiltinMaxPool2d);
679 case kTfLiteBuiltinMaximum:
680 return VisitElementwiseBinaryOperator(delegateData,
681 tfLiteContext,
682 tfLiteNode,
683 nodeIndex,
684 kTfLiteBuiltinMaximum);
685 case kTfLiteBuiltinMean:
686 return VisitControlOperator(delegateData,
687 tfLiteContext,
688 tfLiteNode,
689 nodeIndex,
690 kTfLiteBuiltinMean);
691 case kTfLiteBuiltinMinimum:
692 return VisitElementwiseBinaryOperator(delegateData,
693 tfLiteContext,
694 tfLiteNode,
695 nodeIndex,
696 kTfLiteBuiltinMinimum);
697 case kTfLiteBuiltinMul:
698 return VisitElementwiseBinaryOperator(delegateData,
699 tfLiteContext,
700 tfLiteNode,
701 nodeIndex,
702 kTfLiteBuiltinMul);
703 case kTfLiteBuiltinNeg:
704 return VisitElementwiseUnaryOperator(delegateData,
705 tfLiteContext,
706 tfLiteNode,
707 nodeIndex,
708 armnn::UnaryOperation::Neg);
709 case kTfLiteBuiltinNotEqual:
710 return VisitComparisonOperator(delegateData,
711 tfLiteContext,
712 tfLiteNode,
713 nodeIndex,
714 kTfLiteBuiltinNotEqual);
715 case kTfLiteBuiltinPad:
716 return VisitPadOperator(delegateData,
717 tfLiteContext,
718 tfLiteNode,
719 nodeIndex,
720 kTfLiteBuiltinPad);
721 case kTfLiteBuiltinPadv2:
722 return VisitPadOperator(delegateData,
723 tfLiteContext,
724 tfLiteNode,
725 nodeIndex,
726 kTfLiteBuiltinPadv2);
727 case kTfLiteBuiltinPrelu:
728 return VisitActivationOperator(delegateData,
729 tfLiteContext,
730 tfLiteNode,
731 nodeIndex,
732 kTfLiteBuiltinPrelu);
733 case kTfLiteBuiltinQuantize:
734 return VisitQuantizeOperator(delegateData,
735 tfLiteContext,
736 tfLiteNode,
737 nodeIndex,
738 kTfLiteBuiltinQuantize);
739 case kTfLiteBuiltinRank:
740 return VisitControlOperator(delegateData,
741 tfLiteContext,
742 tfLiteNode,
743 nodeIndex,
744 kTfLiteBuiltinRank);
Sadik Armagana2747482021-02-09 10:28:54 +0000745 case kTfLiteBuiltinReduceMax:
746 return VisitReduceOperator(delegateData,
747 tfLiteContext,
748 tfLiteNode,
749 nodeIndex,
750 kTfLiteBuiltinReduceMax);
751 case kTfLiteBuiltinReduceMin:
752 return VisitReduceOperator(delegateData,
753 tfLiteContext,
754 tfLiteNode,
755 nodeIndex,
756 kTfLiteBuiltinReduceMin);
Sadik Armagan62483be2020-10-23 17:14:43 +0100757 case kTfLiteBuiltinRelu:
758 return VisitActivationOperator(delegateData,
759 tfLiteContext,
760 tfLiteNode,
761 nodeIndex,
762 kTfLiteBuiltinRelu);
763 case kTfLiteBuiltinReluN1To1:
764 return VisitActivationOperator(delegateData,
765 tfLiteContext,
766 tfLiteNode,
767 nodeIndex,
768 kTfLiteBuiltinReluN1To1);
769 case kTfLiteBuiltinRelu6:
770 return VisitActivationOperator(delegateData,
771 tfLiteContext,
772 tfLiteNode,
773 nodeIndex,
774 kTfLiteBuiltinRelu6);
775 case kTfLiteBuiltinReshape:
776 return VisitReshapeOperator(delegateData,
777 tfLiteContext,
778 tfLiteNode,
779 nodeIndex,
780 kTfLiteBuiltinReshape);
781 case kTfLiteBuiltinResizeBilinear:
782 return VisitResizeOperator(delegateData,
783 tfLiteContext,
784 tfLiteNode,
785 nodeIndex,
786 kTfLiteBuiltinResizeBilinear);
787 case kTfLiteBuiltinResizeNearestNeighbor:
788 return VisitResizeOperator(delegateData,
789 tfLiteContext,
790 tfLiteNode,
791 nodeIndex,
792 kTfLiteBuiltinResizeNearestNeighbor);
793 case kTfLiteBuiltinRsqrt:
794 return VisitElementwiseUnaryOperator(delegateData,
795 tfLiteContext,
796 tfLiteNode,
797 nodeIndex,
798 armnn::UnaryOperation::Rsqrt);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +0000799 case kTfLiteBuiltinSplit:
800 return VisitSplitOperator(delegateData,
801 tfLiteContext,
802 tfLiteNode,
803 nodeIndex,
804 kTfLiteBuiltinSplit);
805 case kTfLiteBuiltinSplitV:
806 return VisitSplitVOperator(delegateData,
807 tfLiteContext,
808 tfLiteNode,
809 nodeIndex,
810 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +0100811 case kTfLiteBuiltinSqrt:
812 return VisitElementwiseUnaryOperator(delegateData,
813 tfLiteContext,
814 tfLiteNode,
815 nodeIndex,
816 armnn::UnaryOperation::Sqrt);
817 case kTfLiteBuiltinSqueeze:
818 return VisitSqueezeOperator(delegateData,
819 tfLiteContext,
820 tfLiteNode,
821 nodeIndex,
822 kTfLiteBuiltinSqueeze);
823 case kTfLiteBuiltinStridedSlice:
824 return VisitSliceOperator(delegateData,
825 tfLiteContext,
826 tfLiteNode,
827 nodeIndex,
828 kTfLiteBuiltinStridedSlice);
Sadik Armagana2747482021-02-09 10:28:54 +0000829 case kTfLiteBuiltinSum:
830 return VisitReduceOperator(delegateData,
831 tfLiteContext,
832 tfLiteNode,
833 nodeIndex,
834 kTfLiteBuiltinSum);
Sadik Armagan62483be2020-10-23 17:14:43 +0100835 case kTfLiteBuiltinTranspose:
836 return VisitTransposeOperator(delegateData,
837 tfLiteContext,
838 tfLiteNode,
839 nodeIndex,
840 kTfLiteBuiltinTranspose);
841 case kTfLiteBuiltinTransposeConv:
842 return VisitConvolutionOperator(delegateData,
843 tfLiteContext,
844 tfLiteNode,
845 nodeIndex,
846 kTfLiteBuiltinTransposeConv);
847 case kTfLiteBuiltinSoftmax:
848 return VisitSoftmaxOperator(delegateData,
849 tfLiteContext,
850 tfLiteNode,
851 nodeIndex,
852 kTfLiteBuiltinSoftmax);
853 case kTfLiteBuiltinSpaceToBatchNd:
854 return VisitSpaceToBatchNdOperator(delegateData,
855 tfLiteContext,
856 tfLiteNode,
857 nodeIndex,
858 kTfLiteBuiltinSpaceToBatchNd);
859 case kTfLiteBuiltinSpaceToDepth:
860 return VisitSpaceToDepthOperator(delegateData,
861 tfLiteContext,
862 tfLiteNode,
863 nodeIndex,
864 kTfLiteBuiltinSpaceToDepth);
865 case kTfLiteBuiltinSub:
866 return VisitElementwiseBinaryOperator(delegateData,
867 tfLiteContext,
868 tfLiteNode,
869 nodeIndex,
870 kTfLiteBuiltinSub);
871 case kTfLiteBuiltinTanh:
872 return VisitActivationOperator(delegateData,
873 tfLiteContext,
874 tfLiteNode,
875 nodeIndex,
876 kTfLiteBuiltinTanh);
877 default:
878 return kTfLiteError;
879 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100880}
881
882} // armnnDelegate namespace