blob: 7e4f5b5602390dcf72e56733d4f27787dcddf30a [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"
Kevin May8ab2d7a2021-05-07 09:32:51 +010037#include "Unpack.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010038
39#include <flatbuffers/flatbuffers.h>
40#include <tensorflow/lite/context_util.h>
41
Sadik Armagan3c24f432020-10-19 17:35:30 +010042#include <algorithm>
Matthew Sloyanac001ee2021-02-03 10:43:04 +000043#include <iostream>
Sadik Armagan62483be2020-10-23 17:14:43 +010044#include <sstream>
Sadik Armagan3c24f432020-10-19 17:35:30 +010045
46namespace armnnDelegate
47{
48
Sadik Armagan62483be2020-10-23 17:14:43 +010049DelegateOptions TfLiteArmnnDelegateOptionsDefault()
50{
51 DelegateOptions options(armnn::Compute::CpuRef);
52 return options;
53}
54
55TfLiteDelegate* TfLiteArmnnDelegateCreate(armnnDelegate::DelegateOptions options)
56{
57 auto* armnnDelegate = new ::armnnDelegate::Delegate(options);
58 return armnnDelegate->GetDelegate();
59}
60
61void TfLiteArmnnDelegateDelete(TfLiteDelegate* tfLiteDelegate)
62{
63 if (tfLiteDelegate != nullptr)
64 {
65 delete static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_);
66 }
67}
68
69TfLiteStatus DoPrepare(TfLiteContext* tfLiteContext, TfLiteDelegate* tfLiteDelegate)
70{
71 TfLiteIntArray* supportedOperators =
72 static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_)->IdentifyOperatorsToDelegate(tfLiteContext);
73
74 // ArmNN Delegate Registration
75 static const TfLiteRegistration kArmnnSubgraphRegistration = {
76 // ArmnnSubgraph Init
77 .init = [](TfLiteContext* tfLiteContext, const char* buffer, size_t length) -> void* {
Finn Williams6f9f9902020-11-13 13:23:15 +000078 armnn::IgnoreUnused(length);
Sadik Armagan62483be2020-10-23 17:14:43 +010079 const TfLiteDelegateParams* parameters = reinterpret_cast<const TfLiteDelegateParams*>(buffer);
80
81 return static_cast<void*>(ArmnnSubgraph::Create(
82 tfLiteContext, parameters, static_cast<::armnnDelegate::Delegate*>(parameters->delegate->data_)));
83 },
84 // ArmnnSubgraph Free
85 .free = [](TfLiteContext* tfLiteContext, void* buffer) -> void {
Finn Williams6f9f9902020-11-13 13:23:15 +000086 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan62483be2020-10-23 17:14:43 +010087 if (buffer != nullptr)
88 {
89 delete static_cast<ArmnnSubgraph*>(buffer);
90 }
91 },
92 // ArmnnSubgraph Prepare
93 .prepare = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
94 if (tfLiteNode->user_data == nullptr)
95 {
96 return kTfLiteError;
97 }
Sadik Armagan62483be2020-10-23 17:14:43 +010098 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Prepare(tfLiteContext);
99 },
100 // ArmnnSubgraph Invoke
101 .invoke = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
102 if (tfLiteNode->user_data == nullptr)
103 {
104 return kTfLiteError;
105 }
106
107 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Invoke(tfLiteContext, tfLiteNode);
108 },
109
110 .profiling_string = nullptr,
111 .builtin_code = kTfLiteBuiltinDelegate,
112 .custom_name = "TfLiteArmNnDelegate",
113 .version = 1,
114 };
115
116 const TfLiteStatus status =
117 tfLiteContext->ReplaceNodeSubsetsWithDelegateKernels(
118 tfLiteContext, kArmnnSubgraphRegistration, supportedOperators, tfLiteDelegate);
119
120 TfLiteIntArrayFree(supportedOperators);
121 return status;
122
123}
124
Sadik Armagan3c24f432020-10-19 17:35:30 +0100125Delegate::Delegate(armnnDelegate::DelegateOptions options)
126 : m_Runtime(nullptr, nullptr),
127 m_Options(std::move(options))
128{
Jan Eilers2cd18472020-12-15 10:42:38 +0000129 // Configures logging for ARMNN
130 if (options.IsLoggingEnabled())
131 {
132 armnn::ConfigureLogging(true, true, options.GetLoggingSeverity());
133 }
134
Sadik Armagan3c24f432020-10-19 17:35:30 +0100135 // Create ArmNN Runtime
136 armnn::IRuntime::CreationOptions runtimeOptions;
Sadik Armagan4189cc52020-11-11 18:01:48 +0000137
138 auto backendOptions = m_Options.GetBackendOptions();
139 if (!backendOptions.empty())
140 {
141 runtimeOptions.m_BackendOptions = backendOptions;
142 }
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000143 else if (!m_Options.GetOptimizerOptions().m_ModelOptions.empty())
144 {
145 runtimeOptions.m_BackendOptions = m_Options.GetOptimizerOptions().m_ModelOptions;
146 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100147 m_Runtime = armnn::IRuntime::Create(runtimeOptions);
148
149 std::vector<armnn::BackendId> backends;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100150 if (m_Runtime)
151 {
152 const armnn::BackendIdSet supportedDevices = m_Runtime->GetDeviceSpec().GetSupportedBackends();
153 for (auto& backend : m_Options.GetBackends())
154 {
155 if (std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) == supportedDevices.cend())
156 {
Sadik Armagan0534e032020-10-27 17:30:18 +0000157 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100158 "TfLiteArmnnDelegate: Requested unknown backend %s", backend.Get().c_str());
159 }
160 else
161 {
162 backends.push_back(backend);
163 }
164 }
165 }
166
167 if (backends.empty())
168 {
169 // No known backend specified
170 throw armnn::InvalidArgumentException("TfLiteArmnnDelegate: No known backend specified.");
171 }
172 m_Options.SetBackends(backends);
173
174 TFLITE_LOG_PROD_ONCE(tflite::TFLITE_LOG_INFO, "TfLiteArmnnDelegate: Created TfLite ArmNN delegate.");
175}
176
Sadik Armagan62483be2020-10-23 17:14:43 +0100177TfLiteIntArray* Delegate::IdentifyOperatorsToDelegate(TfLiteContext* tfLiteContext)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100178{
179 TfLiteIntArray* executionPlan = nullptr;
180 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
181 {
182 TF_LITE_KERNEL_LOG(tfLiteContext, "TfLiteArmnnDelegate: Unable to get graph execution plan.");
183 return nullptr;
184 }
185
Sadik Armagan62483be2020-10-23 17:14:43 +0100186 // Delegate data with null network
187 DelegateData delegateData(m_Options.GetBackends());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100188
189 TfLiteIntArray* nodesToDelegate = TfLiteIntArrayCreate(executionPlan->size);
190 nodesToDelegate->size = 0;
191 for (int i = 0; i < executionPlan->size; ++i)
192 {
193 const int nodeIndex = executionPlan->data[i];
194
195 // If TfLite nodes can be delegated to ArmNN
196 TfLiteNode* tfLiteNode = nullptr;
197 TfLiteRegistration* tfLiteRegistration = nullptr;
198 if (tfLiteContext->GetNodeAndRegistration(
199 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
200 {
201 TF_LITE_KERNEL_LOG(tfLiteContext,
202 "TfLiteArmnnDelegate: Unable to get node and registration for node %d.",
203 nodeIndex);
204 continue;
205 }
206
207 if (ArmnnSubgraph::VisitNode(
Sadik Armagan62483be2020-10-23 17:14:43 +0100208 delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100209 {
210 // node is not supported by ArmNN
211 continue;
212 }
213
214 nodesToDelegate->data[nodesToDelegate->size++] = nodeIndex;
215 }
216
Sadik Armagan62483be2020-10-23 17:14:43 +0100217 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100218 return nodesToDelegate;
219}
220
221TfLiteDelegate* Delegate::GetDelegate()
222{
223 return &m_Delegate;
224}
225
Matthew Sloyanac001ee2021-02-03 10:43:04 +0000226const std::string Delegate::GetVersion()
227{
228 return DELEGATE_VERSION;
229}
230
Sadik Armagan62483be2020-10-23 17:14:43 +0100231TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
232 TfLiteContext* tfLiteContext,
233 const TfLiteIntArray* inputs,
234 std::vector<armnn::BindingPointInfo>& inputBindings)
235{
Finn Williams6f9f9902020-11-13 13:23:15 +0000236 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100237 for (unsigned int i = 0; i < numInputs; ++i)
238 {
239 const int32_t tensorId = inputs->data[i];
240 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000241 // Do not create bindings for constant inputs
242 if (tensor.allocation_type == kTfLiteMmapRo)
243 {
244 continue;
245 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100246
247 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
248 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
249
250 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
251 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
252 outputSlot.SetTensorInfo(tensorInfo);
253
254 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000255 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100256
Sadik Armagan6e36a642020-11-10 21:18:41 +0000257 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100258 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000259
Sadik Armagan62483be2020-10-23 17:14:43 +0100260 return kTfLiteOk;
261}
262
263TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
264 TfLiteContext* tfLiteContext,
265 const TfLiteIntArray* outputs,
266 std::vector<armnn::BindingPointInfo>& outputBindings)
267{
Finn Williams6f9f9902020-11-13 13:23:15 +0000268 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100269 for (unsigned int i = 0; i < numOutputs; ++i)
270 {
271 const int32_t tensorId = outputs->data[i];
272 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
273
274 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
275 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
276
277 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Finn Williams6f9f9902020-11-13 13:23:15 +0000278 ARMNN_ASSERT(delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] != nullptr);
279 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100280 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
281 }
282
283 return kTfLiteOk;
284}
285
Sadik Armagan3c24f432020-10-19 17:35:30 +0100286ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
287 const TfLiteDelegateParams* parameters,
288 const Delegate* delegate)
289{
290 TfLiteIntArray* executionPlan;
291 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
292 {
293 return nullptr;
294 }
295
Sadik Armagan62483be2020-10-23 17:14:43 +0100296 // Initialize DelegateData holds network and output slots information
297 DelegateData delegateData(delegate->m_Options.GetBackends());
298
299 // Build ArmNN Network
Sadik Armagan3c24f432020-10-19 17:35:30 +0100300 armnn::NetworkOptions networkOptions = {};
301 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100302 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100303
Sadik Armagan6e36a642020-11-10 21:18:41 +0000304 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
305
Sadik Armagan62483be2020-10-23 17:14:43 +0100306 std::vector<armnn::BindingPointInfo> inputBindings;
307 std::vector<armnn::BindingPointInfo> outputBindings;
308
309 // Add input layer
310 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
311 if (status != kTfLiteOk)
312 {
313 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
314 }
315
316 // Parse TfLite delegate nodes to ArmNN
Sadik Armagan3c24f432020-10-19 17:35:30 +0100317 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
318 {
319 const int nodeIndex = parameters->nodes_to_replace->data[i];
320
321 TfLiteNode* tfLiteNode = nullptr;
322 TfLiteRegistration* tfLiteRegistration = nullptr;
323 if (tfLiteContext->GetNodeAndRegistration(
324 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
325 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000326 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100327 }
328
Sadik Armagan62483be2020-10-23 17:14:43 +0100329 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100330 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000331 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100332 }
333 }
334
Sadik Armagan62483be2020-10-23 17:14:43 +0100335 // Add Output layer
336 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
337 if (status != kTfLiteOk)
338 {
339 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
340 }
341
342 // Optimize ArmNN network
343 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
344 try
345 {
Sadik Armagan6e36a642020-11-10 21:18:41 +0000346 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100347 delegate->m_Options.GetBackends(),
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000348 delegate->m_Runtime->GetDeviceSpec(),
349 delegate->m_Options.GetOptimizerOptions());
Sadik Armagan62483be2020-10-23 17:14:43 +0100350 }
351 catch (std::exception &ex)
352 {
353 std::stringstream exMessage;
354 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
355 throw armnn::Exception(exMessage.str());
356 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100357 if (!optNet)
358 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100359 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100360 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
361 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100362
363 try
364 {
365 // Load graph into runtime
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000366 std::string errorMessage;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000367 armnn::Status loadingStatus;
368 if (delegate->m_Options.GetOptimizerOptions().m_ImportEnabled)
369 {
Francis Murtagh73d3e2e2021-04-29 14:23:04 +0100370 armnn::INetworkProperties networkProperties(false,
371 armnn::MemorySource::Malloc,
372 armnn::MemorySource::Malloc);
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000373 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
374 std::move(optNet),
375 errorMessage,
376 networkProperties);
377 }
378 else
379 {
380 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
381 std::move(optNet),
382 errorMessage);
383 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100384 if (loadingStatus != armnn::Status::Success)
385 {
386 // Optimize failed
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000387 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded:" + errorMessage);
Sadik Armagan62483be2020-10-23 17:14:43 +0100388 }
389 }
390 catch (std::exception& ex)
391 {
392 std::stringstream exMessage;
393 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
394 throw armnn::Exception(exMessage.str());
395 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100396
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000397 // Register debug callback function
398 if (delegate->m_Options.GetDebugCallbackFunction().has_value())
399 {
400 delegate->m_Runtime->RegisterDebugCallback(networkId, delegate->m_Options.GetDebugCallbackFunction().value());
401 }
402
Sadik Armagan3c24f432020-10-19 17:35:30 +0100403 // Create a new SubGraph with networkId and runtime
Sadik Armagan62483be2020-10-23 17:14:43 +0100404 return new ArmnnSubgraph(networkId, delegate->m_Runtime.get(), inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100405}
406
407TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
408{
Finn Williams6f9f9902020-11-13 13:23:15 +0000409 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100410 return kTfLiteOk;
411}
412
Sadik Armagan62483be2020-10-23 17:14:43 +0100413TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100414{
Sadik Armagan62483be2020-10-23 17:14:43 +0100415 // Prepare inputs
416 armnn::InputTensors inputTensors;
417 size_t inputIndex = 0;
418 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
419 {
420 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
421 if (tensor->allocation_type != kTfLiteMmapRo)
422 {
423 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
424 const armnn::ConstTensor inputTensor(inputBinding.second, tensor->data.data);
425 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100426
Sadik Armagan62483be2020-10-23 17:14:43 +0100427 ++inputIndex;
428 }
429 }
430
431 // Prepare outputs
432 armnn::OutputTensors outputTensors;
433 size_t outputIndex = 0;
434 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
435 {
436 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
437 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
438 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
439 outputTensors.emplace_back(outputIdx, outputTensor);
440
441 ++outputIndex;
442 }
443
444 // Run graph
445 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
446 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100447}
448
Sadik Armagan62483be2020-10-23 17:14:43 +0100449TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100450 TfLiteContext* tfLiteContext,
451 TfLiteRegistration* tfLiteRegistration,
452 TfLiteNode* tfLiteNode,
453 int nodeIndex)
454{
Sadik Armagan62483be2020-10-23 17:14:43 +0100455 switch (tfLiteRegistration->builtin_code)
456 {
457 case kTfLiteBuiltinAbs:
458 return VisitElementwiseUnaryOperator(delegateData,
459 tfLiteContext,
460 tfLiteNode,
461 nodeIndex,
462 armnn::UnaryOperation::Abs);
463 case kTfLiteBuiltinAdd:
464 return VisitElementwiseBinaryOperator(delegateData,
465 tfLiteContext,
466 tfLiteNode,
467 nodeIndex,
468 kTfLiteBuiltinAdd);
469 case kTfLiteBuiltinArgMax:
470 return VisitArgMinMaxOperator(delegateData,
471 tfLiteContext,
472 tfLiteNode,
473 nodeIndex,
474 kTfLiteBuiltinArgMax);
475 case kTfLiteBuiltinArgMin:
476 return VisitArgMinMaxOperator(delegateData,
477 tfLiteContext,
478 tfLiteNode,
479 nodeIndex,
480 kTfLiteBuiltinArgMin);
481 case kTfLiteBuiltinAveragePool2d:
482 return VisitPoolingOperator(delegateData,
483 tfLiteContext,
484 tfLiteNode,
485 nodeIndex,
486 kTfLiteBuiltinAveragePool2d);
487 case kTfLiteBuiltinBatchToSpaceNd:
488 return VisitBatchToSpaceNdOperator(delegateData,
489 tfLiteContext,
490 tfLiteNode,
491 nodeIndex,
492 kTfLiteBuiltinBatchToSpaceNd);
Sadik Armagan937565b2021-04-21 14:03:28 +0100493 case kTfLiteBuiltinCast:
494 return VisitCastOperator(delegateData,
495 tfLiteContext,
496 tfLiteNode,
497 nodeIndex,
498 kTfLiteBuiltinCast);
Sadik Armagan62483be2020-10-23 17:14:43 +0100499 case kTfLiteBuiltinConcatenation:
500 return VisitControlOperator(delegateData,
501 tfLiteContext,
502 tfLiteNode,
503 nodeIndex,
504 kTfLiteBuiltinConcatenation);
505 case kTfLiteBuiltinConv2d:
506 return VisitConvolutionOperator(delegateData,
507 tfLiteContext,
508 tfLiteNode,
509 nodeIndex,
510 kTfLiteBuiltinConv2d);
511 case kTfLiteBuiltinDepthToSpace:
512 return VisitDepthToSpaceOperator(delegateData,
513 tfLiteContext,
514 tfLiteNode,
515 nodeIndex,
516 kTfLiteBuiltinDepthToSpace);
517 case kTfLiteBuiltinDepthwiseConv2d:
518 return VisitConvolutionOperator(delegateData,
519 tfLiteContext,
520 tfLiteNode,
521 nodeIndex,
522 kTfLiteBuiltinDepthwiseConv2d);
523 case kTfLiteBuiltinDequantize:
524 return VisitDequantizeOperator(delegateData,
525 tfLiteContext,
526 tfLiteNode,
527 nodeIndex,
528 kTfLiteBuiltinDequantize);
529 case kTfLiteBuiltinDiv:
530 return VisitElementwiseBinaryOperator(delegateData,
531 tfLiteContext,
532 tfLiteNode,
533 nodeIndex,
534 kTfLiteBuiltinDiv);
535 case kTfLiteBuiltinElu:
536 return VisitActivationOperator(delegateData,
537 tfLiteContext,
538 tfLiteNode,
539 nodeIndex,
540 kTfLiteBuiltinElu);
541 case kTfLiteBuiltinEqual:
542 return VisitComparisonOperator(delegateData,
543 tfLiteContext,
544 tfLiteNode,
545 nodeIndex,
546 kTfLiteBuiltinEqual);
547 case kTfLiteBuiltinExp:
548 return VisitElementwiseUnaryOperator(delegateData,
549 tfLiteContext,
550 tfLiteNode,
551 nodeIndex,
552 armnn::UnaryOperation::Exp);
553 case kTfLiteBuiltinExpandDims:
554 return VisitExpandDimsOperator(delegateData,
555 tfLiteContext,
556 tfLiteNode,
557 nodeIndex,
558 kTfLiteBuiltinExpandDims);
559 case kTfLiteBuiltinFill:
560 return VisitFillOperator(delegateData,
561 tfLiteContext,
562 tfLiteNode,
563 nodeIndex,
564 kTfLiteBuiltinFill);
565 case kTfLiteBuiltinFloor:
566 return VisitFloorOperator(delegateData,
567 tfLiteContext,
568 tfLiteNode,
569 nodeIndex,
570 kTfLiteBuiltinFloor);
571 case kTfLiteBuiltinFullyConnected:
572 return VisitFullyConnectedOperator(delegateData,
573 tfLiteContext,
574 tfLiteNode,
575 nodeIndex,
576 kTfLiteBuiltinFullyConnected);
577 case kTfLiteBuiltinGather:
578 return VisitGatherOperator(delegateData,
579 tfLiteContext,
580 tfLiteNode,
581 nodeIndex,
582 kTfLiteBuiltinGather);
583 case kTfLiteBuiltinGatherNd:
584 return VisitGatherOperator(delegateData,
585 tfLiteContext,
586 tfLiteNode,
587 nodeIndex,
588 kTfLiteBuiltinGatherNd);
589 case kTfLiteBuiltinGreater:
590 return VisitComparisonOperator(delegateData,
591 tfLiteContext,
592 tfLiteNode,
593 nodeIndex,
594 kTfLiteBuiltinGreater);
595 case kTfLiteBuiltinGreaterEqual:
596 return VisitComparisonOperator(delegateData,
597 tfLiteContext,
598 tfLiteNode,
599 nodeIndex,
600 kTfLiteBuiltinGreaterEqual);
601 case kTfLiteBuiltinHardSwish:
602 return VisitActivationOperator(delegateData,
603 tfLiteContext,
604 tfLiteNode,
605 nodeIndex,
606 kTfLiteBuiltinHardSwish);
607 case kTfLiteBuiltinL2Normalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000608 return VisitL2NormalizationOperator(delegateData,
609 tfLiteContext,
610 tfLiteNode,
611 nodeIndex,
612 kTfLiteBuiltinL2Normalization);
Sadik Armagan62483be2020-10-23 17:14:43 +0100613 case kTfLiteBuiltinL2Pool2d:
614 return VisitPoolingOperator(delegateData,
615 tfLiteContext,
616 tfLiteNode,
617 nodeIndex,
618 kTfLiteBuiltinL2Pool2d);
619 case kTfLiteBuiltinLess:
620 return VisitComparisonOperator(delegateData,
621 tfLiteContext,
622 tfLiteNode,
623 nodeIndex,
624 kTfLiteBuiltinLess);
625 case kTfLiteBuiltinLessEqual:
626 return VisitComparisonOperator(delegateData,
627 tfLiteContext,
628 tfLiteNode,
629 nodeIndex,
630 kTfLiteBuiltinLessEqual);
631 case kTfLiteBuiltinLocalResponseNormalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000632 return VisitLocalResponseNormalizationOperator(delegateData,
633 tfLiteContext,
634 tfLiteNode,
635 nodeIndex,
636 kTfLiteBuiltinLocalResponseNormalization);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000637 case kTfLiteBuiltinLogicalAnd:
638 return VisitLogicalBinaryOperator(delegateData,
639 tfLiteContext,
640 tfLiteNode,
641 nodeIndex,
642 kTfLiteBuiltinLogicalAnd,
643 armnn::LogicalBinaryOperation::LogicalAnd);
644 case kTfLiteBuiltinLogicalNot:
645 return VisitElementwiseUnaryOperator(delegateData,
646 tfLiteContext,
647 tfLiteNode,
648 nodeIndex,
649 armnn::UnaryOperation::LogicalNot);
650 case kTfLiteBuiltinLogicalOr:
651 return VisitLogicalBinaryOperator(delegateData,
652 tfLiteContext,
653 tfLiteNode,
654 nodeIndex,
655 kTfLiteBuiltinLogicalOr,
656 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100657 case kTfLiteBuiltinLogistic:
658 return VisitActivationOperator(delegateData,
659 tfLiteContext,
660 tfLiteNode,
661 nodeIndex,
662 kTfLiteBuiltinLogistic);
663 case kTfLiteBuiltinLogSoftmax:
664 return VisitSoftmaxOperator(delegateData,
665 tfLiteContext,
666 tfLiteNode,
667 nodeIndex,
668 kTfLiteBuiltinLogSoftmax);
669 case kTfLiteBuiltinLstm:
670 return VisitLstmOperator(delegateData,
671 tfLiteContext,
672 tfLiteNode,
673 nodeIndex,
674 kTfLiteBuiltinLstm);
675 case kTfLiteBuiltinMaxPool2d:
676 return VisitPoolingOperator(delegateData,
677 tfLiteContext,
678 tfLiteNode,
679 nodeIndex,
680 kTfLiteBuiltinMaxPool2d);
681 case kTfLiteBuiltinMaximum:
682 return VisitElementwiseBinaryOperator(delegateData,
683 tfLiteContext,
684 tfLiteNode,
685 nodeIndex,
686 kTfLiteBuiltinMaximum);
687 case kTfLiteBuiltinMean:
688 return VisitControlOperator(delegateData,
689 tfLiteContext,
690 tfLiteNode,
691 nodeIndex,
692 kTfLiteBuiltinMean);
693 case kTfLiteBuiltinMinimum:
694 return VisitElementwiseBinaryOperator(delegateData,
695 tfLiteContext,
696 tfLiteNode,
697 nodeIndex,
698 kTfLiteBuiltinMinimum);
699 case kTfLiteBuiltinMul:
700 return VisitElementwiseBinaryOperator(delegateData,
701 tfLiteContext,
702 tfLiteNode,
703 nodeIndex,
704 kTfLiteBuiltinMul);
705 case kTfLiteBuiltinNeg:
706 return VisitElementwiseUnaryOperator(delegateData,
707 tfLiteContext,
708 tfLiteNode,
709 nodeIndex,
710 armnn::UnaryOperation::Neg);
711 case kTfLiteBuiltinNotEqual:
712 return VisitComparisonOperator(delegateData,
713 tfLiteContext,
714 tfLiteNode,
715 nodeIndex,
716 kTfLiteBuiltinNotEqual);
Matthew Sloyana7a12f52021-05-06 10:05:28 +0100717 case kTfLiteBuiltinPack:
718 return VisitPackOperator(delegateData,
719 tfLiteContext,
720 tfLiteNode,
721 nodeIndex,
722 kTfLiteBuiltinPack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100723 case kTfLiteBuiltinPad:
724 return VisitPadOperator(delegateData,
725 tfLiteContext,
726 tfLiteNode,
727 nodeIndex,
728 kTfLiteBuiltinPad);
729 case kTfLiteBuiltinPadv2:
730 return VisitPadOperator(delegateData,
731 tfLiteContext,
732 tfLiteNode,
733 nodeIndex,
734 kTfLiteBuiltinPadv2);
735 case kTfLiteBuiltinPrelu:
736 return VisitActivationOperator(delegateData,
737 tfLiteContext,
738 tfLiteNode,
739 nodeIndex,
740 kTfLiteBuiltinPrelu);
741 case kTfLiteBuiltinQuantize:
742 return VisitQuantizeOperator(delegateData,
743 tfLiteContext,
744 tfLiteNode,
745 nodeIndex,
746 kTfLiteBuiltinQuantize);
747 case kTfLiteBuiltinRank:
748 return VisitControlOperator(delegateData,
749 tfLiteContext,
750 tfLiteNode,
751 nodeIndex,
752 kTfLiteBuiltinRank);
Sadik Armagana2747482021-02-09 10:28:54 +0000753 case kTfLiteBuiltinReduceMax:
754 return VisitReduceOperator(delegateData,
755 tfLiteContext,
756 tfLiteNode,
757 nodeIndex,
758 kTfLiteBuiltinReduceMax);
759 case kTfLiteBuiltinReduceMin:
760 return VisitReduceOperator(delegateData,
761 tfLiteContext,
762 tfLiteNode,
763 nodeIndex,
764 kTfLiteBuiltinReduceMin);
Sadik Armagan62483be2020-10-23 17:14:43 +0100765 case kTfLiteBuiltinRelu:
766 return VisitActivationOperator(delegateData,
767 tfLiteContext,
768 tfLiteNode,
769 nodeIndex,
770 kTfLiteBuiltinRelu);
771 case kTfLiteBuiltinReluN1To1:
772 return VisitActivationOperator(delegateData,
773 tfLiteContext,
774 tfLiteNode,
775 nodeIndex,
776 kTfLiteBuiltinReluN1To1);
777 case kTfLiteBuiltinRelu6:
778 return VisitActivationOperator(delegateData,
779 tfLiteContext,
780 tfLiteNode,
781 nodeIndex,
782 kTfLiteBuiltinRelu6);
783 case kTfLiteBuiltinReshape:
784 return VisitReshapeOperator(delegateData,
785 tfLiteContext,
786 tfLiteNode,
787 nodeIndex,
788 kTfLiteBuiltinReshape);
789 case kTfLiteBuiltinResizeBilinear:
790 return VisitResizeOperator(delegateData,
791 tfLiteContext,
792 tfLiteNode,
793 nodeIndex,
794 kTfLiteBuiltinResizeBilinear);
795 case kTfLiteBuiltinResizeNearestNeighbor:
796 return VisitResizeOperator(delegateData,
797 tfLiteContext,
798 tfLiteNode,
799 nodeIndex,
800 kTfLiteBuiltinResizeNearestNeighbor);
801 case kTfLiteBuiltinRsqrt:
802 return VisitElementwiseUnaryOperator(delegateData,
803 tfLiteContext,
804 tfLiteNode,
805 nodeIndex,
806 armnn::UnaryOperation::Rsqrt);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +0000807 case kTfLiteBuiltinSplit:
808 return VisitSplitOperator(delegateData,
809 tfLiteContext,
810 tfLiteNode,
811 nodeIndex,
812 kTfLiteBuiltinSplit);
813 case kTfLiteBuiltinSplitV:
814 return VisitSplitVOperator(delegateData,
815 tfLiteContext,
816 tfLiteNode,
817 nodeIndex,
818 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +0100819 case kTfLiteBuiltinSqrt:
820 return VisitElementwiseUnaryOperator(delegateData,
821 tfLiteContext,
822 tfLiteNode,
823 nodeIndex,
824 armnn::UnaryOperation::Sqrt);
825 case kTfLiteBuiltinSqueeze:
826 return VisitSqueezeOperator(delegateData,
827 tfLiteContext,
828 tfLiteNode,
829 nodeIndex,
830 kTfLiteBuiltinSqueeze);
831 case kTfLiteBuiltinStridedSlice:
832 return VisitSliceOperator(delegateData,
833 tfLiteContext,
834 tfLiteNode,
835 nodeIndex,
836 kTfLiteBuiltinStridedSlice);
Sadik Armagana2747482021-02-09 10:28:54 +0000837 case kTfLiteBuiltinSum:
838 return VisitReduceOperator(delegateData,
839 tfLiteContext,
840 tfLiteNode,
841 nodeIndex,
842 kTfLiteBuiltinSum);
Sadik Armagan62483be2020-10-23 17:14:43 +0100843 case kTfLiteBuiltinTranspose:
844 return VisitTransposeOperator(delegateData,
845 tfLiteContext,
846 tfLiteNode,
847 nodeIndex,
848 kTfLiteBuiltinTranspose);
849 case kTfLiteBuiltinTransposeConv:
850 return VisitConvolutionOperator(delegateData,
851 tfLiteContext,
852 tfLiteNode,
853 nodeIndex,
854 kTfLiteBuiltinTransposeConv);
855 case kTfLiteBuiltinSoftmax:
856 return VisitSoftmaxOperator(delegateData,
857 tfLiteContext,
858 tfLiteNode,
859 nodeIndex,
860 kTfLiteBuiltinSoftmax);
861 case kTfLiteBuiltinSpaceToBatchNd:
862 return VisitSpaceToBatchNdOperator(delegateData,
863 tfLiteContext,
864 tfLiteNode,
865 nodeIndex,
866 kTfLiteBuiltinSpaceToBatchNd);
867 case kTfLiteBuiltinSpaceToDepth:
868 return VisitSpaceToDepthOperator(delegateData,
869 tfLiteContext,
870 tfLiteNode,
871 nodeIndex,
872 kTfLiteBuiltinSpaceToDepth);
873 case kTfLiteBuiltinSub:
874 return VisitElementwiseBinaryOperator(delegateData,
875 tfLiteContext,
876 tfLiteNode,
877 nodeIndex,
878 kTfLiteBuiltinSub);
879 case kTfLiteBuiltinTanh:
880 return VisitActivationOperator(delegateData,
881 tfLiteContext,
882 tfLiteNode,
883 nodeIndex,
884 kTfLiteBuiltinTanh);
Kevin May8ab2d7a2021-05-07 09:32:51 +0100885 case kTfLiteBuiltinUnpack:
886 return VisitUnpackOperator(delegateData,
887 tfLiteContext,
888 tfLiteNode,
889 nodeIndex,
890 kTfLiteBuiltinUnpack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100891 default:
892 return kTfLiteError;
893 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100894}
895
896} // armnnDelegate namespace