blob: d777eff27c6f4ec4c15670a3f397f5fe81139b89 [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"
Matthew Sloyana7a12f52021-05-06 10:05:28 +010024#include "Pack.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010025#include "Pad.hpp"
26#include "Pooling.hpp"
27#include "Quantization.hpp"
28#include "Redefine.hpp"
Sadik Armagana2747482021-02-09 10:28:54 +000029#include "Reduce.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010030#include "Resize.hpp"
31#include "Round.hpp"
32#include "Slice.hpp"
33#include "Softmax.hpp"
34#include "SpaceDepth.hpp"
Sadik Armagan34fa1bd2020-11-27 12:40:52 +000035#include "Split.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010036#include "Transpose.hpp"
37
38#include <flatbuffers/flatbuffers.h>
39#include <tensorflow/lite/context_util.h>
40
Sadik Armagan3c24f432020-10-19 17:35:30 +010041#include <algorithm>
Matthew Sloyanac001ee2021-02-03 10:43:04 +000042#include <iostream>
Sadik Armagan62483be2020-10-23 17:14:43 +010043#include <sstream>
Sadik Armagan3c24f432020-10-19 17:35:30 +010044
45namespace armnnDelegate
46{
47
Sadik Armagan62483be2020-10-23 17:14:43 +010048DelegateOptions TfLiteArmnnDelegateOptionsDefault()
49{
50 DelegateOptions options(armnn::Compute::CpuRef);
51 return options;
52}
53
54TfLiteDelegate* TfLiteArmnnDelegateCreate(armnnDelegate::DelegateOptions options)
55{
56 auto* armnnDelegate = new ::armnnDelegate::Delegate(options);
57 return armnnDelegate->GetDelegate();
58}
59
60void TfLiteArmnnDelegateDelete(TfLiteDelegate* tfLiteDelegate)
61{
62 if (tfLiteDelegate != nullptr)
63 {
64 delete static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_);
65 }
66}
67
68TfLiteStatus DoPrepare(TfLiteContext* tfLiteContext, TfLiteDelegate* tfLiteDelegate)
69{
70 TfLiteIntArray* supportedOperators =
71 static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_)->IdentifyOperatorsToDelegate(tfLiteContext);
72
73 // ArmNN Delegate Registration
74 static const TfLiteRegistration kArmnnSubgraphRegistration = {
75 // ArmnnSubgraph Init
76 .init = [](TfLiteContext* tfLiteContext, const char* buffer, size_t length) -> void* {
Finn Williams6f9f9902020-11-13 13:23:15 +000077 armnn::IgnoreUnused(length);
Sadik Armagan62483be2020-10-23 17:14:43 +010078 const TfLiteDelegateParams* parameters = reinterpret_cast<const TfLiteDelegateParams*>(buffer);
79
80 return static_cast<void*>(ArmnnSubgraph::Create(
81 tfLiteContext, parameters, static_cast<::armnnDelegate::Delegate*>(parameters->delegate->data_)));
82 },
83 // ArmnnSubgraph Free
84 .free = [](TfLiteContext* tfLiteContext, void* buffer) -> void {
Finn Williams6f9f9902020-11-13 13:23:15 +000085 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan62483be2020-10-23 17:14:43 +010086 if (buffer != nullptr)
87 {
88 delete static_cast<ArmnnSubgraph*>(buffer);
89 }
90 },
91 // ArmnnSubgraph Prepare
92 .prepare = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
93 if (tfLiteNode->user_data == nullptr)
94 {
95 return kTfLiteError;
96 }
Sadik Armagan62483be2020-10-23 17:14:43 +010097 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Prepare(tfLiteContext);
98 },
99 // ArmnnSubgraph Invoke
100 .invoke = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
101 if (tfLiteNode->user_data == nullptr)
102 {
103 return kTfLiteError;
104 }
105
106 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Invoke(tfLiteContext, tfLiteNode);
107 },
108
109 .profiling_string = nullptr,
110 .builtin_code = kTfLiteBuiltinDelegate,
111 .custom_name = "TfLiteArmNnDelegate",
112 .version = 1,
113 };
114
115 const TfLiteStatus status =
116 tfLiteContext->ReplaceNodeSubsetsWithDelegateKernels(
117 tfLiteContext, kArmnnSubgraphRegistration, supportedOperators, tfLiteDelegate);
118
119 TfLiteIntArrayFree(supportedOperators);
120 return status;
121
122}
123
Sadik Armagan3c24f432020-10-19 17:35:30 +0100124Delegate::Delegate(armnnDelegate::DelegateOptions options)
125 : m_Runtime(nullptr, nullptr),
126 m_Options(std::move(options))
127{
Jan Eilers2cd18472020-12-15 10:42:38 +0000128 // Configures logging for ARMNN
129 if (options.IsLoggingEnabled())
130 {
131 armnn::ConfigureLogging(true, true, options.GetLoggingSeverity());
132 }
133
Sadik Armagan3c24f432020-10-19 17:35:30 +0100134 // Create ArmNN Runtime
135 armnn::IRuntime::CreationOptions runtimeOptions;
Sadik Armagan4189cc52020-11-11 18:01:48 +0000136
137 auto backendOptions = m_Options.GetBackendOptions();
138 if (!backendOptions.empty())
139 {
140 runtimeOptions.m_BackendOptions = backendOptions;
141 }
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000142 else if (!m_Options.GetOptimizerOptions().m_ModelOptions.empty())
143 {
144 runtimeOptions.m_BackendOptions = m_Options.GetOptimizerOptions().m_ModelOptions;
145 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100146 m_Runtime = armnn::IRuntime::Create(runtimeOptions);
147
148 std::vector<armnn::BackendId> backends;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100149 if (m_Runtime)
150 {
151 const armnn::BackendIdSet supportedDevices = m_Runtime->GetDeviceSpec().GetSupportedBackends();
152 for (auto& backend : m_Options.GetBackends())
153 {
154 if (std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) == supportedDevices.cend())
155 {
Sadik Armagan0534e032020-10-27 17:30:18 +0000156 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100157 "TfLiteArmnnDelegate: Requested unknown backend %s", backend.Get().c_str());
158 }
159 else
160 {
161 backends.push_back(backend);
162 }
163 }
164 }
165
166 if (backends.empty())
167 {
168 // No known backend specified
169 throw armnn::InvalidArgumentException("TfLiteArmnnDelegate: No known backend specified.");
170 }
171 m_Options.SetBackends(backends);
172
173 TFLITE_LOG_PROD_ONCE(tflite::TFLITE_LOG_INFO, "TfLiteArmnnDelegate: Created TfLite ArmNN delegate.");
174}
175
Sadik Armagan62483be2020-10-23 17:14:43 +0100176TfLiteIntArray* Delegate::IdentifyOperatorsToDelegate(TfLiteContext* tfLiteContext)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100177{
178 TfLiteIntArray* executionPlan = nullptr;
179 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
180 {
181 TF_LITE_KERNEL_LOG(tfLiteContext, "TfLiteArmnnDelegate: Unable to get graph execution plan.");
182 return nullptr;
183 }
184
Sadik Armagan62483be2020-10-23 17:14:43 +0100185 // Delegate data with null network
186 DelegateData delegateData(m_Options.GetBackends());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100187
188 TfLiteIntArray* nodesToDelegate = TfLiteIntArrayCreate(executionPlan->size);
189 nodesToDelegate->size = 0;
190 for (int i = 0; i < executionPlan->size; ++i)
191 {
192 const int nodeIndex = executionPlan->data[i];
193
194 // If TfLite nodes can be delegated to ArmNN
195 TfLiteNode* tfLiteNode = nullptr;
196 TfLiteRegistration* tfLiteRegistration = nullptr;
197 if (tfLiteContext->GetNodeAndRegistration(
198 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
199 {
200 TF_LITE_KERNEL_LOG(tfLiteContext,
201 "TfLiteArmnnDelegate: Unable to get node and registration for node %d.",
202 nodeIndex);
203 continue;
204 }
205
206 if (ArmnnSubgraph::VisitNode(
Sadik Armagan62483be2020-10-23 17:14:43 +0100207 delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100208 {
209 // node is not supported by ArmNN
210 continue;
211 }
212
213 nodesToDelegate->data[nodesToDelegate->size++] = nodeIndex;
214 }
215
Sadik Armagan62483be2020-10-23 17:14:43 +0100216 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100217 return nodesToDelegate;
218}
219
220TfLiteDelegate* Delegate::GetDelegate()
221{
222 return &m_Delegate;
223}
224
Matthew Sloyanac001ee2021-02-03 10:43:04 +0000225const std::string Delegate::GetVersion()
226{
227 return DELEGATE_VERSION;
228}
229
Sadik Armagan62483be2020-10-23 17:14:43 +0100230TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
231 TfLiteContext* tfLiteContext,
232 const TfLiteIntArray* inputs,
233 std::vector<armnn::BindingPointInfo>& inputBindings)
234{
Finn Williams6f9f9902020-11-13 13:23:15 +0000235 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100236 for (unsigned int i = 0; i < numInputs; ++i)
237 {
238 const int32_t tensorId = inputs->data[i];
239 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000240 // Do not create bindings for constant inputs
241 if (tensor.allocation_type == kTfLiteMmapRo)
242 {
243 continue;
244 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100245
246 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
247 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
248
249 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
250 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
251 outputSlot.SetTensorInfo(tensorInfo);
252
253 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000254 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100255
Sadik Armagan6e36a642020-11-10 21:18:41 +0000256 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100257 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000258
Sadik Armagan62483be2020-10-23 17:14:43 +0100259 return kTfLiteOk;
260}
261
262TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
263 TfLiteContext* tfLiteContext,
264 const TfLiteIntArray* outputs,
265 std::vector<armnn::BindingPointInfo>& outputBindings)
266{
Finn Williams6f9f9902020-11-13 13:23:15 +0000267 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100268 for (unsigned int i = 0; i < numOutputs; ++i)
269 {
270 const int32_t tensorId = outputs->data[i];
271 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
272
273 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
274 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
275
276 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Finn Williams6f9f9902020-11-13 13:23:15 +0000277 ARMNN_ASSERT(delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] != nullptr);
278 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100279 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
280 }
281
282 return kTfLiteOk;
283}
284
Sadik Armagan3c24f432020-10-19 17:35:30 +0100285ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
286 const TfLiteDelegateParams* parameters,
287 const Delegate* delegate)
288{
289 TfLiteIntArray* executionPlan;
290 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
291 {
292 return nullptr;
293 }
294
Sadik Armagan62483be2020-10-23 17:14:43 +0100295 // Initialize DelegateData holds network and output slots information
296 DelegateData delegateData(delegate->m_Options.GetBackends());
297
298 // Build ArmNN Network
Sadik Armagan3c24f432020-10-19 17:35:30 +0100299 armnn::NetworkOptions networkOptions = {};
300 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100301 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100302
Sadik Armagan6e36a642020-11-10 21:18:41 +0000303 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
304
Sadik Armagan62483be2020-10-23 17:14:43 +0100305 std::vector<armnn::BindingPointInfo> inputBindings;
306 std::vector<armnn::BindingPointInfo> outputBindings;
307
308 // Add input layer
309 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
310 if (status != kTfLiteOk)
311 {
312 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
313 }
314
315 // Parse TfLite delegate nodes to ArmNN
Sadik Armagan3c24f432020-10-19 17:35:30 +0100316 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
317 {
318 const int nodeIndex = parameters->nodes_to_replace->data[i];
319
320 TfLiteNode* tfLiteNode = nullptr;
321 TfLiteRegistration* tfLiteRegistration = nullptr;
322 if (tfLiteContext->GetNodeAndRegistration(
323 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
324 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000325 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100326 }
327
Sadik Armagan62483be2020-10-23 17:14:43 +0100328 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100329 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000330 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100331 }
332 }
333
Sadik Armagan62483be2020-10-23 17:14:43 +0100334 // Add Output layer
335 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
336 if (status != kTfLiteOk)
337 {
338 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
339 }
340
341 // Optimize ArmNN network
342 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
343 try
344 {
Sadik Armagan6e36a642020-11-10 21:18:41 +0000345 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100346 delegate->m_Options.GetBackends(),
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000347 delegate->m_Runtime->GetDeviceSpec(),
348 delegate->m_Options.GetOptimizerOptions());
Sadik Armagan62483be2020-10-23 17:14:43 +0100349 }
350 catch (std::exception &ex)
351 {
352 std::stringstream exMessage;
353 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
354 throw armnn::Exception(exMessage.str());
355 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100356 if (!optNet)
357 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100358 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100359 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
360 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100361
362 try
363 {
364 // Load graph into runtime
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000365 std::string errorMessage;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000366 armnn::Status loadingStatus;
367 if (delegate->m_Options.GetOptimizerOptions().m_ImportEnabled)
368 {
Francis Murtagh73d3e2e2021-04-29 14:23:04 +0100369 armnn::INetworkProperties networkProperties(false,
370 armnn::MemorySource::Malloc,
371 armnn::MemorySource::Malloc);
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000372 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
373 std::move(optNet),
374 errorMessage,
375 networkProperties);
376 }
377 else
378 {
379 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
380 std::move(optNet),
381 errorMessage);
382 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100383 if (loadingStatus != armnn::Status::Success)
384 {
385 // Optimize failed
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000386 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded:" + errorMessage);
Sadik Armagan62483be2020-10-23 17:14:43 +0100387 }
388 }
389 catch (std::exception& ex)
390 {
391 std::stringstream exMessage;
392 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
393 throw armnn::Exception(exMessage.str());
394 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100395
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000396 // Register debug callback function
397 if (delegate->m_Options.GetDebugCallbackFunction().has_value())
398 {
399 delegate->m_Runtime->RegisterDebugCallback(networkId, delegate->m_Options.GetDebugCallbackFunction().value());
400 }
401
Sadik Armagan3c24f432020-10-19 17:35:30 +0100402 // Create a new SubGraph with networkId and runtime
Sadik Armagan62483be2020-10-23 17:14:43 +0100403 return new ArmnnSubgraph(networkId, delegate->m_Runtime.get(), inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100404}
405
406TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
407{
Finn Williams6f9f9902020-11-13 13:23:15 +0000408 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100409 return kTfLiteOk;
410}
411
Sadik Armagan62483be2020-10-23 17:14:43 +0100412TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100413{
Sadik Armagan62483be2020-10-23 17:14:43 +0100414 // Prepare inputs
415 armnn::InputTensors inputTensors;
416 size_t inputIndex = 0;
417 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
418 {
419 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
420 if (tensor->allocation_type != kTfLiteMmapRo)
421 {
422 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
423 const armnn::ConstTensor inputTensor(inputBinding.second, tensor->data.data);
424 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100425
Sadik Armagan62483be2020-10-23 17:14:43 +0100426 ++inputIndex;
427 }
428 }
429
430 // Prepare outputs
431 armnn::OutputTensors outputTensors;
432 size_t outputIndex = 0;
433 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
434 {
435 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
436 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
437 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
438 outputTensors.emplace_back(outputIdx, outputTensor);
439
440 ++outputIndex;
441 }
442
443 // Run graph
444 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
445 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100446}
447
Sadik Armagan62483be2020-10-23 17:14:43 +0100448TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100449 TfLiteContext* tfLiteContext,
450 TfLiteRegistration* tfLiteRegistration,
451 TfLiteNode* tfLiteNode,
452 int nodeIndex)
453{
Sadik Armagan62483be2020-10-23 17:14:43 +0100454 switch (tfLiteRegistration->builtin_code)
455 {
456 case kTfLiteBuiltinAbs:
457 return VisitElementwiseUnaryOperator(delegateData,
458 tfLiteContext,
459 tfLiteNode,
460 nodeIndex,
461 armnn::UnaryOperation::Abs);
462 case kTfLiteBuiltinAdd:
463 return VisitElementwiseBinaryOperator(delegateData,
464 tfLiteContext,
465 tfLiteNode,
466 nodeIndex,
467 kTfLiteBuiltinAdd);
468 case kTfLiteBuiltinArgMax:
469 return VisitArgMinMaxOperator(delegateData,
470 tfLiteContext,
471 tfLiteNode,
472 nodeIndex,
473 kTfLiteBuiltinArgMax);
474 case kTfLiteBuiltinArgMin:
475 return VisitArgMinMaxOperator(delegateData,
476 tfLiteContext,
477 tfLiteNode,
478 nodeIndex,
479 kTfLiteBuiltinArgMin);
480 case kTfLiteBuiltinAveragePool2d:
481 return VisitPoolingOperator(delegateData,
482 tfLiteContext,
483 tfLiteNode,
484 nodeIndex,
485 kTfLiteBuiltinAveragePool2d);
486 case kTfLiteBuiltinBatchToSpaceNd:
487 return VisitBatchToSpaceNdOperator(delegateData,
488 tfLiteContext,
489 tfLiteNode,
490 nodeIndex,
491 kTfLiteBuiltinBatchToSpaceNd);
Sadik Armagan937565b2021-04-21 14:03:28 +0100492 case kTfLiteBuiltinCast:
493 return VisitCastOperator(delegateData,
494 tfLiteContext,
495 tfLiteNode,
496 nodeIndex,
497 kTfLiteBuiltinCast);
Sadik Armagan62483be2020-10-23 17:14:43 +0100498 case kTfLiteBuiltinConcatenation:
499 return VisitControlOperator(delegateData,
500 tfLiteContext,
501 tfLiteNode,
502 nodeIndex,
503 kTfLiteBuiltinConcatenation);
504 case kTfLiteBuiltinConv2d:
505 return VisitConvolutionOperator(delegateData,
506 tfLiteContext,
507 tfLiteNode,
508 nodeIndex,
509 kTfLiteBuiltinConv2d);
510 case kTfLiteBuiltinDepthToSpace:
511 return VisitDepthToSpaceOperator(delegateData,
512 tfLiteContext,
513 tfLiteNode,
514 nodeIndex,
515 kTfLiteBuiltinDepthToSpace);
516 case kTfLiteBuiltinDepthwiseConv2d:
517 return VisitConvolutionOperator(delegateData,
518 tfLiteContext,
519 tfLiteNode,
520 nodeIndex,
521 kTfLiteBuiltinDepthwiseConv2d);
522 case kTfLiteBuiltinDequantize:
523 return VisitDequantizeOperator(delegateData,
524 tfLiteContext,
525 tfLiteNode,
526 nodeIndex,
527 kTfLiteBuiltinDequantize);
528 case kTfLiteBuiltinDiv:
529 return VisitElementwiseBinaryOperator(delegateData,
530 tfLiteContext,
531 tfLiteNode,
532 nodeIndex,
533 kTfLiteBuiltinDiv);
534 case kTfLiteBuiltinElu:
535 return VisitActivationOperator(delegateData,
536 tfLiteContext,
537 tfLiteNode,
538 nodeIndex,
539 kTfLiteBuiltinElu);
540 case kTfLiteBuiltinEqual:
541 return VisitComparisonOperator(delegateData,
542 tfLiteContext,
543 tfLiteNode,
544 nodeIndex,
545 kTfLiteBuiltinEqual);
546 case kTfLiteBuiltinExp:
547 return VisitElementwiseUnaryOperator(delegateData,
548 tfLiteContext,
549 tfLiteNode,
550 nodeIndex,
551 armnn::UnaryOperation::Exp);
552 case kTfLiteBuiltinExpandDims:
553 return VisitExpandDimsOperator(delegateData,
554 tfLiteContext,
555 tfLiteNode,
556 nodeIndex,
557 kTfLiteBuiltinExpandDims);
558 case kTfLiteBuiltinFill:
559 return VisitFillOperator(delegateData,
560 tfLiteContext,
561 tfLiteNode,
562 nodeIndex,
563 kTfLiteBuiltinFill);
564 case kTfLiteBuiltinFloor:
565 return VisitFloorOperator(delegateData,
566 tfLiteContext,
567 tfLiteNode,
568 nodeIndex,
569 kTfLiteBuiltinFloor);
570 case kTfLiteBuiltinFullyConnected:
571 return VisitFullyConnectedOperator(delegateData,
572 tfLiteContext,
573 tfLiteNode,
574 nodeIndex,
575 kTfLiteBuiltinFullyConnected);
576 case kTfLiteBuiltinGather:
577 return VisitGatherOperator(delegateData,
578 tfLiteContext,
579 tfLiteNode,
580 nodeIndex,
581 kTfLiteBuiltinGather);
582 case kTfLiteBuiltinGatherNd:
583 return VisitGatherOperator(delegateData,
584 tfLiteContext,
585 tfLiteNode,
586 nodeIndex,
587 kTfLiteBuiltinGatherNd);
588 case kTfLiteBuiltinGreater:
589 return VisitComparisonOperator(delegateData,
590 tfLiteContext,
591 tfLiteNode,
592 nodeIndex,
593 kTfLiteBuiltinGreater);
594 case kTfLiteBuiltinGreaterEqual:
595 return VisitComparisonOperator(delegateData,
596 tfLiteContext,
597 tfLiteNode,
598 nodeIndex,
599 kTfLiteBuiltinGreaterEqual);
600 case kTfLiteBuiltinHardSwish:
601 return VisitActivationOperator(delegateData,
602 tfLiteContext,
603 tfLiteNode,
604 nodeIndex,
605 kTfLiteBuiltinHardSwish);
606 case kTfLiteBuiltinL2Normalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000607 return VisitL2NormalizationOperator(delegateData,
608 tfLiteContext,
609 tfLiteNode,
610 nodeIndex,
611 kTfLiteBuiltinL2Normalization);
Sadik Armagan62483be2020-10-23 17:14:43 +0100612 case kTfLiteBuiltinL2Pool2d:
613 return VisitPoolingOperator(delegateData,
614 tfLiteContext,
615 tfLiteNode,
616 nodeIndex,
617 kTfLiteBuiltinL2Pool2d);
618 case kTfLiteBuiltinLess:
619 return VisitComparisonOperator(delegateData,
620 tfLiteContext,
621 tfLiteNode,
622 nodeIndex,
623 kTfLiteBuiltinLess);
624 case kTfLiteBuiltinLessEqual:
625 return VisitComparisonOperator(delegateData,
626 tfLiteContext,
627 tfLiteNode,
628 nodeIndex,
629 kTfLiteBuiltinLessEqual);
630 case kTfLiteBuiltinLocalResponseNormalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000631 return VisitLocalResponseNormalizationOperator(delegateData,
632 tfLiteContext,
633 tfLiteNode,
634 nodeIndex,
635 kTfLiteBuiltinLocalResponseNormalization);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000636 case kTfLiteBuiltinLogicalAnd:
637 return VisitLogicalBinaryOperator(delegateData,
638 tfLiteContext,
639 tfLiteNode,
640 nodeIndex,
641 kTfLiteBuiltinLogicalAnd,
642 armnn::LogicalBinaryOperation::LogicalAnd);
643 case kTfLiteBuiltinLogicalNot:
644 return VisitElementwiseUnaryOperator(delegateData,
645 tfLiteContext,
646 tfLiteNode,
647 nodeIndex,
648 armnn::UnaryOperation::LogicalNot);
649 case kTfLiteBuiltinLogicalOr:
650 return VisitLogicalBinaryOperator(delegateData,
651 tfLiteContext,
652 tfLiteNode,
653 nodeIndex,
654 kTfLiteBuiltinLogicalOr,
655 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100656 case kTfLiteBuiltinLogistic:
657 return VisitActivationOperator(delegateData,
658 tfLiteContext,
659 tfLiteNode,
660 nodeIndex,
661 kTfLiteBuiltinLogistic);
662 case kTfLiteBuiltinLogSoftmax:
663 return VisitSoftmaxOperator(delegateData,
664 tfLiteContext,
665 tfLiteNode,
666 nodeIndex,
667 kTfLiteBuiltinLogSoftmax);
668 case kTfLiteBuiltinLstm:
669 return VisitLstmOperator(delegateData,
670 tfLiteContext,
671 tfLiteNode,
672 nodeIndex,
673 kTfLiteBuiltinLstm);
674 case kTfLiteBuiltinMaxPool2d:
675 return VisitPoolingOperator(delegateData,
676 tfLiteContext,
677 tfLiteNode,
678 nodeIndex,
679 kTfLiteBuiltinMaxPool2d);
680 case kTfLiteBuiltinMaximum:
681 return VisitElementwiseBinaryOperator(delegateData,
682 tfLiteContext,
683 tfLiteNode,
684 nodeIndex,
685 kTfLiteBuiltinMaximum);
686 case kTfLiteBuiltinMean:
687 return VisitControlOperator(delegateData,
688 tfLiteContext,
689 tfLiteNode,
690 nodeIndex,
691 kTfLiteBuiltinMean);
692 case kTfLiteBuiltinMinimum:
693 return VisitElementwiseBinaryOperator(delegateData,
694 tfLiteContext,
695 tfLiteNode,
696 nodeIndex,
697 kTfLiteBuiltinMinimum);
698 case kTfLiteBuiltinMul:
699 return VisitElementwiseBinaryOperator(delegateData,
700 tfLiteContext,
701 tfLiteNode,
702 nodeIndex,
703 kTfLiteBuiltinMul);
704 case kTfLiteBuiltinNeg:
705 return VisitElementwiseUnaryOperator(delegateData,
706 tfLiteContext,
707 tfLiteNode,
708 nodeIndex,
709 armnn::UnaryOperation::Neg);
710 case kTfLiteBuiltinNotEqual:
711 return VisitComparisonOperator(delegateData,
712 tfLiteContext,
713 tfLiteNode,
714 nodeIndex,
715 kTfLiteBuiltinNotEqual);
Matthew Sloyana7a12f52021-05-06 10:05:28 +0100716 case kTfLiteBuiltinPack:
717 return VisitPackOperator(delegateData,
718 tfLiteContext,
719 tfLiteNode,
720 nodeIndex,
721 kTfLiteBuiltinPack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100722 case kTfLiteBuiltinPad:
723 return VisitPadOperator(delegateData,
724 tfLiteContext,
725 tfLiteNode,
726 nodeIndex,
727 kTfLiteBuiltinPad);
728 case kTfLiteBuiltinPadv2:
729 return VisitPadOperator(delegateData,
730 tfLiteContext,
731 tfLiteNode,
732 nodeIndex,
733 kTfLiteBuiltinPadv2);
734 case kTfLiteBuiltinPrelu:
735 return VisitActivationOperator(delegateData,
736 tfLiteContext,
737 tfLiteNode,
738 nodeIndex,
739 kTfLiteBuiltinPrelu);
740 case kTfLiteBuiltinQuantize:
741 return VisitQuantizeOperator(delegateData,
742 tfLiteContext,
743 tfLiteNode,
744 nodeIndex,
745 kTfLiteBuiltinQuantize);
746 case kTfLiteBuiltinRank:
747 return VisitControlOperator(delegateData,
748 tfLiteContext,
749 tfLiteNode,
750 nodeIndex,
751 kTfLiteBuiltinRank);
Sadik Armagana2747482021-02-09 10:28:54 +0000752 case kTfLiteBuiltinReduceMax:
753 return VisitReduceOperator(delegateData,
754 tfLiteContext,
755 tfLiteNode,
756 nodeIndex,
757 kTfLiteBuiltinReduceMax);
758 case kTfLiteBuiltinReduceMin:
759 return VisitReduceOperator(delegateData,
760 tfLiteContext,
761 tfLiteNode,
762 nodeIndex,
763 kTfLiteBuiltinReduceMin);
Sadik Armagan62483be2020-10-23 17:14:43 +0100764 case kTfLiteBuiltinRelu:
765 return VisitActivationOperator(delegateData,
766 tfLiteContext,
767 tfLiteNode,
768 nodeIndex,
769 kTfLiteBuiltinRelu);
770 case kTfLiteBuiltinReluN1To1:
771 return VisitActivationOperator(delegateData,
772 tfLiteContext,
773 tfLiteNode,
774 nodeIndex,
775 kTfLiteBuiltinReluN1To1);
776 case kTfLiteBuiltinRelu6:
777 return VisitActivationOperator(delegateData,
778 tfLiteContext,
779 tfLiteNode,
780 nodeIndex,
781 kTfLiteBuiltinRelu6);
782 case kTfLiteBuiltinReshape:
783 return VisitReshapeOperator(delegateData,
784 tfLiteContext,
785 tfLiteNode,
786 nodeIndex,
787 kTfLiteBuiltinReshape);
788 case kTfLiteBuiltinResizeBilinear:
789 return VisitResizeOperator(delegateData,
790 tfLiteContext,
791 tfLiteNode,
792 nodeIndex,
793 kTfLiteBuiltinResizeBilinear);
794 case kTfLiteBuiltinResizeNearestNeighbor:
795 return VisitResizeOperator(delegateData,
796 tfLiteContext,
797 tfLiteNode,
798 nodeIndex,
799 kTfLiteBuiltinResizeNearestNeighbor);
800 case kTfLiteBuiltinRsqrt:
801 return VisitElementwiseUnaryOperator(delegateData,
802 tfLiteContext,
803 tfLiteNode,
804 nodeIndex,
805 armnn::UnaryOperation::Rsqrt);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +0000806 case kTfLiteBuiltinSplit:
807 return VisitSplitOperator(delegateData,
808 tfLiteContext,
809 tfLiteNode,
810 nodeIndex,
811 kTfLiteBuiltinSplit);
812 case kTfLiteBuiltinSplitV:
813 return VisitSplitVOperator(delegateData,
814 tfLiteContext,
815 tfLiteNode,
816 nodeIndex,
817 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +0100818 case kTfLiteBuiltinSqrt:
819 return VisitElementwiseUnaryOperator(delegateData,
820 tfLiteContext,
821 tfLiteNode,
822 nodeIndex,
823 armnn::UnaryOperation::Sqrt);
824 case kTfLiteBuiltinSqueeze:
825 return VisitSqueezeOperator(delegateData,
826 tfLiteContext,
827 tfLiteNode,
828 nodeIndex,
829 kTfLiteBuiltinSqueeze);
830 case kTfLiteBuiltinStridedSlice:
831 return VisitSliceOperator(delegateData,
832 tfLiteContext,
833 tfLiteNode,
834 nodeIndex,
835 kTfLiteBuiltinStridedSlice);
Sadik Armagana2747482021-02-09 10:28:54 +0000836 case kTfLiteBuiltinSum:
837 return VisitReduceOperator(delegateData,
838 tfLiteContext,
839 tfLiteNode,
840 nodeIndex,
841 kTfLiteBuiltinSum);
Sadik Armagan62483be2020-10-23 17:14:43 +0100842 case kTfLiteBuiltinTranspose:
843 return VisitTransposeOperator(delegateData,
844 tfLiteContext,
845 tfLiteNode,
846 nodeIndex,
847 kTfLiteBuiltinTranspose);
848 case kTfLiteBuiltinTransposeConv:
849 return VisitConvolutionOperator(delegateData,
850 tfLiteContext,
851 tfLiteNode,
852 nodeIndex,
853 kTfLiteBuiltinTransposeConv);
854 case kTfLiteBuiltinSoftmax:
855 return VisitSoftmaxOperator(delegateData,
856 tfLiteContext,
857 tfLiteNode,
858 nodeIndex,
859 kTfLiteBuiltinSoftmax);
860 case kTfLiteBuiltinSpaceToBatchNd:
861 return VisitSpaceToBatchNdOperator(delegateData,
862 tfLiteContext,
863 tfLiteNode,
864 nodeIndex,
865 kTfLiteBuiltinSpaceToBatchNd);
866 case kTfLiteBuiltinSpaceToDepth:
867 return VisitSpaceToDepthOperator(delegateData,
868 tfLiteContext,
869 tfLiteNode,
870 nodeIndex,
871 kTfLiteBuiltinSpaceToDepth);
872 case kTfLiteBuiltinSub:
873 return VisitElementwiseBinaryOperator(delegateData,
874 tfLiteContext,
875 tfLiteNode,
876 nodeIndex,
877 kTfLiteBuiltinSub);
878 case kTfLiteBuiltinTanh:
879 return VisitActivationOperator(delegateData,
880 tfLiteContext,
881 tfLiteNode,
882 nodeIndex,
883 kTfLiteBuiltinTanh);
884 default:
885 return kTfLiteError;
886 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100887}
888
889} // armnnDelegate namespace