blob: 0ac33808b02a36ae74daf0bf1e98c09d2649e4c1 [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"
James Conroy39825482021-05-27 17:44:50 +010027#include "Prelu.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010028#include "Quantization.hpp"
29#include "Redefine.hpp"
Sadik Armagana2747482021-02-09 10:28:54 +000030#include "Reduce.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010031#include "Resize.hpp"
32#include "Round.hpp"
Keith Davis0176fd82021-06-01 17:36:32 +010033#include "Shape.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010034#include "Slice.hpp"
35#include "Softmax.hpp"
36#include "SpaceDepth.hpp"
Sadik Armagan34fa1bd2020-11-27 12:40:52 +000037#include "Split.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010038#include "Transpose.hpp"
Kevin May8ab2d7a2021-05-07 09:32:51 +010039#include "Unpack.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010040
41#include <flatbuffers/flatbuffers.h>
42#include <tensorflow/lite/context_util.h>
43
Sadik Armagan3c24f432020-10-19 17:35:30 +010044#include <algorithm>
Matthew Sloyanac001ee2021-02-03 10:43:04 +000045#include <iostream>
Sadik Armagan62483be2020-10-23 17:14:43 +010046#include <sstream>
Sadik Armagan3c24f432020-10-19 17:35:30 +010047
48namespace armnnDelegate
49{
50
Sadik Armagan62483be2020-10-23 17:14:43 +010051DelegateOptions TfLiteArmnnDelegateOptionsDefault()
52{
53 DelegateOptions options(armnn::Compute::CpuRef);
54 return options;
55}
56
57TfLiteDelegate* TfLiteArmnnDelegateCreate(armnnDelegate::DelegateOptions options)
58{
59 auto* armnnDelegate = new ::armnnDelegate::Delegate(options);
60 return armnnDelegate->GetDelegate();
61}
62
63void TfLiteArmnnDelegateDelete(TfLiteDelegate* tfLiteDelegate)
64{
65 if (tfLiteDelegate != nullptr)
66 {
67 delete static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_);
68 }
69}
70
71TfLiteStatus DoPrepare(TfLiteContext* tfLiteContext, TfLiteDelegate* tfLiteDelegate)
72{
73 TfLiteIntArray* supportedOperators =
74 static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_)->IdentifyOperatorsToDelegate(tfLiteContext);
75
76 // ArmNN Delegate Registration
77 static const TfLiteRegistration kArmnnSubgraphRegistration = {
78 // ArmnnSubgraph Init
79 .init = [](TfLiteContext* tfLiteContext, const char* buffer, size_t length) -> void* {
Finn Williams6f9f9902020-11-13 13:23:15 +000080 armnn::IgnoreUnused(length);
Sadik Armagan62483be2020-10-23 17:14:43 +010081 const TfLiteDelegateParams* parameters = reinterpret_cast<const TfLiteDelegateParams*>(buffer);
82
83 return static_cast<void*>(ArmnnSubgraph::Create(
84 tfLiteContext, parameters, static_cast<::armnnDelegate::Delegate*>(parameters->delegate->data_)));
85 },
86 // ArmnnSubgraph Free
87 .free = [](TfLiteContext* tfLiteContext, void* buffer) -> void {
Finn Williams6f9f9902020-11-13 13:23:15 +000088 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan62483be2020-10-23 17:14:43 +010089 if (buffer != nullptr)
90 {
91 delete static_cast<ArmnnSubgraph*>(buffer);
92 }
93 },
94 // ArmnnSubgraph Prepare
95 .prepare = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
96 if (tfLiteNode->user_data == nullptr)
97 {
98 return kTfLiteError;
99 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100100 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Prepare(tfLiteContext);
101 },
102 // ArmnnSubgraph Invoke
103 .invoke = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
104 if (tfLiteNode->user_data == nullptr)
105 {
106 return kTfLiteError;
107 }
108
109 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Invoke(tfLiteContext, tfLiteNode);
110 },
111
112 .profiling_string = nullptr,
113 .builtin_code = kTfLiteBuiltinDelegate,
114 .custom_name = "TfLiteArmNnDelegate",
115 .version = 1,
116 };
117
118 const TfLiteStatus status =
119 tfLiteContext->ReplaceNodeSubsetsWithDelegateKernels(
120 tfLiteContext, kArmnnSubgraphRegistration, supportedOperators, tfLiteDelegate);
121
122 TfLiteIntArrayFree(supportedOperators);
123 return status;
124
125}
126
Sadik Armagan3c24f432020-10-19 17:35:30 +0100127Delegate::Delegate(armnnDelegate::DelegateOptions options)
128 : m_Runtime(nullptr, nullptr),
129 m_Options(std::move(options))
130{
Jan Eilers2cd18472020-12-15 10:42:38 +0000131 // Configures logging for ARMNN
132 if (options.IsLoggingEnabled())
133 {
134 armnn::ConfigureLogging(true, true, options.GetLoggingSeverity());
135 }
136
Sadik Armagan3c24f432020-10-19 17:35:30 +0100137 // Create ArmNN Runtime
138 armnn::IRuntime::CreationOptions runtimeOptions;
Sadik Armagan4189cc52020-11-11 18:01:48 +0000139
140 auto backendOptions = m_Options.GetBackendOptions();
141 if (!backendOptions.empty())
142 {
143 runtimeOptions.m_BackendOptions = backendOptions;
144 }
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000145 else if (!m_Options.GetOptimizerOptions().m_ModelOptions.empty())
146 {
147 runtimeOptions.m_BackendOptions = m_Options.GetOptimizerOptions().m_ModelOptions;
148 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100149 m_Runtime = armnn::IRuntime::Create(runtimeOptions);
150
151 std::vector<armnn::BackendId> backends;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100152 if (m_Runtime)
153 {
154 const armnn::BackendIdSet supportedDevices = m_Runtime->GetDeviceSpec().GetSupportedBackends();
155 for (auto& backend : m_Options.GetBackends())
156 {
157 if (std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) == supportedDevices.cend())
158 {
Sadik Armagan0534e032020-10-27 17:30:18 +0000159 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100160 "TfLiteArmnnDelegate: Requested unknown backend %s", backend.Get().c_str());
161 }
162 else
163 {
164 backends.push_back(backend);
165 }
166 }
167 }
168
169 if (backends.empty())
170 {
171 // No known backend specified
172 throw armnn::InvalidArgumentException("TfLiteArmnnDelegate: No known backend specified.");
173 }
174 m_Options.SetBackends(backends);
175
176 TFLITE_LOG_PROD_ONCE(tflite::TFLITE_LOG_INFO, "TfLiteArmnnDelegate: Created TfLite ArmNN delegate.");
177}
178
Sadik Armagan62483be2020-10-23 17:14:43 +0100179TfLiteIntArray* Delegate::IdentifyOperatorsToDelegate(TfLiteContext* tfLiteContext)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100180{
181 TfLiteIntArray* executionPlan = nullptr;
182 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
183 {
184 TF_LITE_KERNEL_LOG(tfLiteContext, "TfLiteArmnnDelegate: Unable to get graph execution plan.");
185 return nullptr;
186 }
187
Sadik Armagan62483be2020-10-23 17:14:43 +0100188 // Delegate data with null network
189 DelegateData delegateData(m_Options.GetBackends());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100190
191 TfLiteIntArray* nodesToDelegate = TfLiteIntArrayCreate(executionPlan->size);
192 nodesToDelegate->size = 0;
193 for (int i = 0; i < executionPlan->size; ++i)
194 {
195 const int nodeIndex = executionPlan->data[i];
196
197 // If TfLite nodes can be delegated to ArmNN
198 TfLiteNode* tfLiteNode = nullptr;
199 TfLiteRegistration* tfLiteRegistration = nullptr;
200 if (tfLiteContext->GetNodeAndRegistration(
201 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
202 {
203 TF_LITE_KERNEL_LOG(tfLiteContext,
204 "TfLiteArmnnDelegate: Unable to get node and registration for node %d.",
205 nodeIndex);
206 continue;
207 }
208
209 if (ArmnnSubgraph::VisitNode(
Sadik Armagan62483be2020-10-23 17:14:43 +0100210 delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100211 {
212 // node is not supported by ArmNN
213 continue;
214 }
215
216 nodesToDelegate->data[nodesToDelegate->size++] = nodeIndex;
217 }
218
Sadik Armagan62483be2020-10-23 17:14:43 +0100219 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100220 return nodesToDelegate;
221}
222
223TfLiteDelegate* Delegate::GetDelegate()
224{
225 return &m_Delegate;
226}
227
Matthew Sloyanac001ee2021-02-03 10:43:04 +0000228const std::string Delegate::GetVersion()
229{
230 return DELEGATE_VERSION;
231}
232
Sadik Armagan62483be2020-10-23 17:14:43 +0100233TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
234 TfLiteContext* tfLiteContext,
235 const TfLiteIntArray* inputs,
236 std::vector<armnn::BindingPointInfo>& inputBindings)
237{
Finn Williams6f9f9902020-11-13 13:23:15 +0000238 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100239 for (unsigned int i = 0; i < numInputs; ++i)
240 {
241 const int32_t tensorId = inputs->data[i];
242 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000243 // Do not create bindings for constant inputs
244 if (tensor.allocation_type == kTfLiteMmapRo)
245 {
246 continue;
247 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100248
249 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
250 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
251
252 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
253 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
254 outputSlot.SetTensorInfo(tensorInfo);
255
256 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000257 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100258
Sadik Armagan6e36a642020-11-10 21:18:41 +0000259 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100260 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000261
Sadik Armagan62483be2020-10-23 17:14:43 +0100262 return kTfLiteOk;
263}
264
265TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
266 TfLiteContext* tfLiteContext,
267 const TfLiteIntArray* outputs,
268 std::vector<armnn::BindingPointInfo>& outputBindings)
269{
Finn Williams6f9f9902020-11-13 13:23:15 +0000270 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100271 for (unsigned int i = 0; i < numOutputs; ++i)
272 {
273 const int32_t tensorId = outputs->data[i];
274 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
275
276 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
277 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
278
279 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Finn Williams6f9f9902020-11-13 13:23:15 +0000280 ARMNN_ASSERT(delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] != nullptr);
281 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100282 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
283 }
284
285 return kTfLiteOk;
286}
287
Sadik Armagan3c24f432020-10-19 17:35:30 +0100288ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
289 const TfLiteDelegateParams* parameters,
290 const Delegate* delegate)
291{
292 TfLiteIntArray* executionPlan;
293 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
294 {
295 return nullptr;
296 }
297
Sadik Armagan62483be2020-10-23 17:14:43 +0100298 // Initialize DelegateData holds network and output slots information
299 DelegateData delegateData(delegate->m_Options.GetBackends());
300
301 // Build ArmNN Network
Sadik Armagan3c24f432020-10-19 17:35:30 +0100302 armnn::NetworkOptions networkOptions = {};
303 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100304 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100305
Sadik Armagan6e36a642020-11-10 21:18:41 +0000306 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
307
Sadik Armagan62483be2020-10-23 17:14:43 +0100308 std::vector<armnn::BindingPointInfo> inputBindings;
309 std::vector<armnn::BindingPointInfo> outputBindings;
310
311 // Add input layer
312 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
313 if (status != kTfLiteOk)
314 {
315 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
316 }
317
318 // Parse TfLite delegate nodes to ArmNN
Sadik Armagan3c24f432020-10-19 17:35:30 +0100319 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
320 {
321 const int nodeIndex = parameters->nodes_to_replace->data[i];
322
323 TfLiteNode* tfLiteNode = nullptr;
324 TfLiteRegistration* tfLiteRegistration = nullptr;
325 if (tfLiteContext->GetNodeAndRegistration(
326 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
327 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000328 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100329 }
330
Sadik Armagan62483be2020-10-23 17:14:43 +0100331 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100332 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000333 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100334 }
335 }
336
Sadik Armagan62483be2020-10-23 17:14:43 +0100337 // Add Output layer
338 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
339 if (status != kTfLiteOk)
340 {
341 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
342 }
343
344 // Optimize ArmNN network
345 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
346 try
347 {
Sadik Armagan6e36a642020-11-10 21:18:41 +0000348 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100349 delegate->m_Options.GetBackends(),
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000350 delegate->m_Runtime->GetDeviceSpec(),
351 delegate->m_Options.GetOptimizerOptions());
Sadik Armagan62483be2020-10-23 17:14:43 +0100352 }
353 catch (std::exception &ex)
354 {
355 std::stringstream exMessage;
356 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
357 throw armnn::Exception(exMessage.str());
358 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100359 if (!optNet)
360 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100361 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100362 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
363 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100364
365 try
366 {
367 // Load graph into runtime
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000368 std::string errorMessage;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000369 armnn::Status loadingStatus;
370 if (delegate->m_Options.GetOptimizerOptions().m_ImportEnabled)
371 {
Francis Murtagh73d3e2e2021-04-29 14:23:04 +0100372 armnn::INetworkProperties networkProperties(false,
373 armnn::MemorySource::Malloc,
374 armnn::MemorySource::Malloc);
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000375 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
376 std::move(optNet),
377 errorMessage,
378 networkProperties);
379 }
380 else
381 {
382 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
383 std::move(optNet),
384 errorMessage);
385 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100386 if (loadingStatus != armnn::Status::Success)
387 {
388 // Optimize failed
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000389 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded:" + errorMessage);
Sadik Armagan62483be2020-10-23 17:14:43 +0100390 }
391 }
392 catch (std::exception& ex)
393 {
394 std::stringstream exMessage;
395 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
396 throw armnn::Exception(exMessage.str());
397 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100398
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000399 // Register debug callback function
400 if (delegate->m_Options.GetDebugCallbackFunction().has_value())
401 {
402 delegate->m_Runtime->RegisterDebugCallback(networkId, delegate->m_Options.GetDebugCallbackFunction().value());
403 }
404
Sadik Armagan3c24f432020-10-19 17:35:30 +0100405 // Create a new SubGraph with networkId and runtime
Sadik Armagan62483be2020-10-23 17:14:43 +0100406 return new ArmnnSubgraph(networkId, delegate->m_Runtime.get(), inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100407}
408
409TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
410{
Finn Williams6f9f9902020-11-13 13:23:15 +0000411 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100412 return kTfLiteOk;
413}
414
Sadik Armagan62483be2020-10-23 17:14:43 +0100415TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100416{
Sadik Armagan62483be2020-10-23 17:14:43 +0100417 // Prepare inputs
418 armnn::InputTensors inputTensors;
419 size_t inputIndex = 0;
420 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
421 {
422 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
423 if (tensor->allocation_type != kTfLiteMmapRo)
424 {
425 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
426 const armnn::ConstTensor inputTensor(inputBinding.second, tensor->data.data);
427 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100428
Sadik Armagan62483be2020-10-23 17:14:43 +0100429 ++inputIndex;
430 }
431 }
432
433 // Prepare outputs
434 armnn::OutputTensors outputTensors;
435 size_t outputIndex = 0;
436 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
437 {
438 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
439 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
440 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
441 outputTensors.emplace_back(outputIdx, outputTensor);
442
443 ++outputIndex;
444 }
445
446 // Run graph
447 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
448 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100449}
450
Sadik Armagan62483be2020-10-23 17:14:43 +0100451TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100452 TfLiteContext* tfLiteContext,
453 TfLiteRegistration* tfLiteRegistration,
454 TfLiteNode* tfLiteNode,
455 int nodeIndex)
456{
Sadik Armagan62483be2020-10-23 17:14:43 +0100457 switch (tfLiteRegistration->builtin_code)
458 {
459 case kTfLiteBuiltinAbs:
460 return VisitElementwiseUnaryOperator(delegateData,
461 tfLiteContext,
462 tfLiteNode,
463 nodeIndex,
464 armnn::UnaryOperation::Abs);
465 case kTfLiteBuiltinAdd:
466 return VisitElementwiseBinaryOperator(delegateData,
467 tfLiteContext,
468 tfLiteNode,
469 nodeIndex,
470 kTfLiteBuiltinAdd);
471 case kTfLiteBuiltinArgMax:
472 return VisitArgMinMaxOperator(delegateData,
473 tfLiteContext,
474 tfLiteNode,
475 nodeIndex,
476 kTfLiteBuiltinArgMax);
477 case kTfLiteBuiltinArgMin:
478 return VisitArgMinMaxOperator(delegateData,
479 tfLiteContext,
480 tfLiteNode,
481 nodeIndex,
482 kTfLiteBuiltinArgMin);
483 case kTfLiteBuiltinAveragePool2d:
484 return VisitPoolingOperator(delegateData,
485 tfLiteContext,
486 tfLiteNode,
487 nodeIndex,
488 kTfLiteBuiltinAveragePool2d);
489 case kTfLiteBuiltinBatchToSpaceNd:
490 return VisitBatchToSpaceNdOperator(delegateData,
491 tfLiteContext,
492 tfLiteNode,
493 nodeIndex,
494 kTfLiteBuiltinBatchToSpaceNd);
Sadik Armagan937565b2021-04-21 14:03:28 +0100495 case kTfLiteBuiltinCast:
496 return VisitCastOperator(delegateData,
497 tfLiteContext,
498 tfLiteNode,
499 nodeIndex,
500 kTfLiteBuiltinCast);
Sadik Armagan62483be2020-10-23 17:14:43 +0100501 case kTfLiteBuiltinConcatenation:
502 return VisitControlOperator(delegateData,
503 tfLiteContext,
504 tfLiteNode,
505 nodeIndex,
506 kTfLiteBuiltinConcatenation);
507 case kTfLiteBuiltinConv2d:
508 return VisitConvolutionOperator(delegateData,
509 tfLiteContext,
510 tfLiteNode,
511 nodeIndex,
512 kTfLiteBuiltinConv2d);
513 case kTfLiteBuiltinDepthToSpace:
514 return VisitDepthToSpaceOperator(delegateData,
515 tfLiteContext,
516 tfLiteNode,
517 nodeIndex,
518 kTfLiteBuiltinDepthToSpace);
519 case kTfLiteBuiltinDepthwiseConv2d:
520 return VisitConvolutionOperator(delegateData,
521 tfLiteContext,
522 tfLiteNode,
523 nodeIndex,
524 kTfLiteBuiltinDepthwiseConv2d);
525 case kTfLiteBuiltinDequantize:
526 return VisitDequantizeOperator(delegateData,
527 tfLiteContext,
528 tfLiteNode,
529 nodeIndex,
530 kTfLiteBuiltinDequantize);
531 case kTfLiteBuiltinDiv:
532 return VisitElementwiseBinaryOperator(delegateData,
533 tfLiteContext,
534 tfLiteNode,
535 nodeIndex,
536 kTfLiteBuiltinDiv);
537 case kTfLiteBuiltinElu:
538 return VisitActivationOperator(delegateData,
539 tfLiteContext,
540 tfLiteNode,
541 nodeIndex,
542 kTfLiteBuiltinElu);
543 case kTfLiteBuiltinEqual:
544 return VisitComparisonOperator(delegateData,
545 tfLiteContext,
546 tfLiteNode,
547 nodeIndex,
548 kTfLiteBuiltinEqual);
549 case kTfLiteBuiltinExp:
550 return VisitElementwiseUnaryOperator(delegateData,
551 tfLiteContext,
552 tfLiteNode,
553 nodeIndex,
554 armnn::UnaryOperation::Exp);
555 case kTfLiteBuiltinExpandDims:
556 return VisitExpandDimsOperator(delegateData,
557 tfLiteContext,
558 tfLiteNode,
559 nodeIndex,
560 kTfLiteBuiltinExpandDims);
561 case kTfLiteBuiltinFill:
562 return VisitFillOperator(delegateData,
563 tfLiteContext,
564 tfLiteNode,
565 nodeIndex,
566 kTfLiteBuiltinFill);
567 case kTfLiteBuiltinFloor:
568 return VisitFloorOperator(delegateData,
569 tfLiteContext,
570 tfLiteNode,
571 nodeIndex,
572 kTfLiteBuiltinFloor);
573 case kTfLiteBuiltinFullyConnected:
574 return VisitFullyConnectedOperator(delegateData,
575 tfLiteContext,
576 tfLiteNode,
577 nodeIndex,
578 kTfLiteBuiltinFullyConnected);
579 case kTfLiteBuiltinGather:
580 return VisitGatherOperator(delegateData,
581 tfLiteContext,
582 tfLiteNode,
583 nodeIndex,
584 kTfLiteBuiltinGather);
585 case kTfLiteBuiltinGatherNd:
586 return VisitGatherOperator(delegateData,
587 tfLiteContext,
588 tfLiteNode,
589 nodeIndex,
590 kTfLiteBuiltinGatherNd);
591 case kTfLiteBuiltinGreater:
592 return VisitComparisonOperator(delegateData,
593 tfLiteContext,
594 tfLiteNode,
595 nodeIndex,
596 kTfLiteBuiltinGreater);
597 case kTfLiteBuiltinGreaterEqual:
598 return VisitComparisonOperator(delegateData,
599 tfLiteContext,
600 tfLiteNode,
601 nodeIndex,
602 kTfLiteBuiltinGreaterEqual);
603 case kTfLiteBuiltinHardSwish:
604 return VisitActivationOperator(delegateData,
605 tfLiteContext,
606 tfLiteNode,
607 nodeIndex,
608 kTfLiteBuiltinHardSwish);
609 case kTfLiteBuiltinL2Normalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000610 return VisitL2NormalizationOperator(delegateData,
611 tfLiteContext,
612 tfLiteNode,
613 nodeIndex,
614 kTfLiteBuiltinL2Normalization);
Sadik Armagan62483be2020-10-23 17:14:43 +0100615 case kTfLiteBuiltinL2Pool2d:
616 return VisitPoolingOperator(delegateData,
617 tfLiteContext,
618 tfLiteNode,
619 nodeIndex,
620 kTfLiteBuiltinL2Pool2d);
621 case kTfLiteBuiltinLess:
622 return VisitComparisonOperator(delegateData,
623 tfLiteContext,
624 tfLiteNode,
625 nodeIndex,
626 kTfLiteBuiltinLess);
627 case kTfLiteBuiltinLessEqual:
628 return VisitComparisonOperator(delegateData,
629 tfLiteContext,
630 tfLiteNode,
631 nodeIndex,
632 kTfLiteBuiltinLessEqual);
633 case kTfLiteBuiltinLocalResponseNormalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000634 return VisitLocalResponseNormalizationOperator(delegateData,
635 tfLiteContext,
636 tfLiteNode,
637 nodeIndex,
638 kTfLiteBuiltinLocalResponseNormalization);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000639 case kTfLiteBuiltinLogicalAnd:
640 return VisitLogicalBinaryOperator(delegateData,
641 tfLiteContext,
642 tfLiteNode,
643 nodeIndex,
644 kTfLiteBuiltinLogicalAnd,
645 armnn::LogicalBinaryOperation::LogicalAnd);
646 case kTfLiteBuiltinLogicalNot:
647 return VisitElementwiseUnaryOperator(delegateData,
648 tfLiteContext,
649 tfLiteNode,
650 nodeIndex,
651 armnn::UnaryOperation::LogicalNot);
652 case kTfLiteBuiltinLogicalOr:
653 return VisitLogicalBinaryOperator(delegateData,
654 tfLiteContext,
655 tfLiteNode,
656 nodeIndex,
657 kTfLiteBuiltinLogicalOr,
658 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100659 case kTfLiteBuiltinLogistic:
660 return VisitActivationOperator(delegateData,
661 tfLiteContext,
662 tfLiteNode,
663 nodeIndex,
664 kTfLiteBuiltinLogistic);
665 case kTfLiteBuiltinLogSoftmax:
666 return VisitSoftmaxOperator(delegateData,
667 tfLiteContext,
668 tfLiteNode,
669 nodeIndex,
670 kTfLiteBuiltinLogSoftmax);
671 case kTfLiteBuiltinLstm:
672 return VisitLstmOperator(delegateData,
673 tfLiteContext,
674 tfLiteNode,
675 nodeIndex,
676 kTfLiteBuiltinLstm);
677 case kTfLiteBuiltinMaxPool2d:
678 return VisitPoolingOperator(delegateData,
679 tfLiteContext,
680 tfLiteNode,
681 nodeIndex,
682 kTfLiteBuiltinMaxPool2d);
683 case kTfLiteBuiltinMaximum:
684 return VisitElementwiseBinaryOperator(delegateData,
685 tfLiteContext,
686 tfLiteNode,
687 nodeIndex,
688 kTfLiteBuiltinMaximum);
689 case kTfLiteBuiltinMean:
690 return VisitControlOperator(delegateData,
691 tfLiteContext,
692 tfLiteNode,
693 nodeIndex,
694 kTfLiteBuiltinMean);
695 case kTfLiteBuiltinMinimum:
696 return VisitElementwiseBinaryOperator(delegateData,
697 tfLiteContext,
698 tfLiteNode,
699 nodeIndex,
700 kTfLiteBuiltinMinimum);
701 case kTfLiteBuiltinMul:
702 return VisitElementwiseBinaryOperator(delegateData,
703 tfLiteContext,
704 tfLiteNode,
705 nodeIndex,
706 kTfLiteBuiltinMul);
707 case kTfLiteBuiltinNeg:
708 return VisitElementwiseUnaryOperator(delegateData,
709 tfLiteContext,
710 tfLiteNode,
711 nodeIndex,
712 armnn::UnaryOperation::Neg);
713 case kTfLiteBuiltinNotEqual:
714 return VisitComparisonOperator(delegateData,
715 tfLiteContext,
716 tfLiteNode,
717 nodeIndex,
718 kTfLiteBuiltinNotEqual);
Matthew Sloyana7a12f52021-05-06 10:05:28 +0100719 case kTfLiteBuiltinPack:
720 return VisitPackOperator(delegateData,
721 tfLiteContext,
722 tfLiteNode,
723 nodeIndex,
724 kTfLiteBuiltinPack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100725 case kTfLiteBuiltinPad:
726 return VisitPadOperator(delegateData,
727 tfLiteContext,
728 tfLiteNode,
729 nodeIndex,
730 kTfLiteBuiltinPad);
731 case kTfLiteBuiltinPadv2:
732 return VisitPadOperator(delegateData,
733 tfLiteContext,
734 tfLiteNode,
735 nodeIndex,
736 kTfLiteBuiltinPadv2);
737 case kTfLiteBuiltinPrelu:
James Conroy39825482021-05-27 17:44:50 +0100738 return VisitPreluOperator(delegateData,
739 tfLiteContext,
740 tfLiteNode,
741 nodeIndex,
742 kTfLiteBuiltinPrelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100743 case kTfLiteBuiltinQuantize:
744 return VisitQuantizeOperator(delegateData,
745 tfLiteContext,
746 tfLiteNode,
747 nodeIndex,
748 kTfLiteBuiltinQuantize);
749 case kTfLiteBuiltinRank:
750 return VisitControlOperator(delegateData,
751 tfLiteContext,
752 tfLiteNode,
753 nodeIndex,
754 kTfLiteBuiltinRank);
Sadik Armagana2747482021-02-09 10:28:54 +0000755 case kTfLiteBuiltinReduceMax:
756 return VisitReduceOperator(delegateData,
757 tfLiteContext,
758 tfLiteNode,
759 nodeIndex,
760 kTfLiteBuiltinReduceMax);
761 case kTfLiteBuiltinReduceMin:
762 return VisitReduceOperator(delegateData,
763 tfLiteContext,
764 tfLiteNode,
765 nodeIndex,
766 kTfLiteBuiltinReduceMin);
Sadik Armagan62483be2020-10-23 17:14:43 +0100767 case kTfLiteBuiltinRelu:
768 return VisitActivationOperator(delegateData,
769 tfLiteContext,
770 tfLiteNode,
771 nodeIndex,
772 kTfLiteBuiltinRelu);
773 case kTfLiteBuiltinReluN1To1:
774 return VisitActivationOperator(delegateData,
775 tfLiteContext,
776 tfLiteNode,
777 nodeIndex,
778 kTfLiteBuiltinReluN1To1);
779 case kTfLiteBuiltinRelu6:
780 return VisitActivationOperator(delegateData,
781 tfLiteContext,
782 tfLiteNode,
783 nodeIndex,
784 kTfLiteBuiltinRelu6);
785 case kTfLiteBuiltinReshape:
786 return VisitReshapeOperator(delegateData,
787 tfLiteContext,
788 tfLiteNode,
789 nodeIndex,
790 kTfLiteBuiltinReshape);
791 case kTfLiteBuiltinResizeBilinear:
792 return VisitResizeOperator(delegateData,
793 tfLiteContext,
794 tfLiteNode,
795 nodeIndex,
796 kTfLiteBuiltinResizeBilinear);
797 case kTfLiteBuiltinResizeNearestNeighbor:
798 return VisitResizeOperator(delegateData,
799 tfLiteContext,
800 tfLiteNode,
801 nodeIndex,
802 kTfLiteBuiltinResizeNearestNeighbor);
803 case kTfLiteBuiltinRsqrt:
804 return VisitElementwiseUnaryOperator(delegateData,
805 tfLiteContext,
806 tfLiteNode,
807 nodeIndex,
808 armnn::UnaryOperation::Rsqrt);
Keith Davis0176fd82021-06-01 17:36:32 +0100809 case kTfLiteBuiltinShape:
810 return VisitShapeOperator(delegateData,
811 tfLiteContext,
812 tfLiteNode,
813 nodeIndex,
814 kTfLiteBuiltinShape);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +0000815 case kTfLiteBuiltinSplit:
816 return VisitSplitOperator(delegateData,
817 tfLiteContext,
818 tfLiteNode,
819 nodeIndex,
820 kTfLiteBuiltinSplit);
821 case kTfLiteBuiltinSplitV:
822 return VisitSplitVOperator(delegateData,
823 tfLiteContext,
824 tfLiteNode,
825 nodeIndex,
826 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +0100827 case kTfLiteBuiltinSqrt:
828 return VisitElementwiseUnaryOperator(delegateData,
829 tfLiteContext,
830 tfLiteNode,
831 nodeIndex,
832 armnn::UnaryOperation::Sqrt);
833 case kTfLiteBuiltinSqueeze:
834 return VisitSqueezeOperator(delegateData,
835 tfLiteContext,
836 tfLiteNode,
837 nodeIndex,
838 kTfLiteBuiltinSqueeze);
839 case kTfLiteBuiltinStridedSlice:
840 return VisitSliceOperator(delegateData,
841 tfLiteContext,
842 tfLiteNode,
843 nodeIndex,
844 kTfLiteBuiltinStridedSlice);
Sadik Armagana2747482021-02-09 10:28:54 +0000845 case kTfLiteBuiltinSum:
846 return VisitReduceOperator(delegateData,
847 tfLiteContext,
848 tfLiteNode,
849 nodeIndex,
850 kTfLiteBuiltinSum);
Sadik Armagan62483be2020-10-23 17:14:43 +0100851 case kTfLiteBuiltinTranspose:
852 return VisitTransposeOperator(delegateData,
853 tfLiteContext,
854 tfLiteNode,
855 nodeIndex,
856 kTfLiteBuiltinTranspose);
857 case kTfLiteBuiltinTransposeConv:
858 return VisitConvolutionOperator(delegateData,
859 tfLiteContext,
860 tfLiteNode,
861 nodeIndex,
862 kTfLiteBuiltinTransposeConv);
863 case kTfLiteBuiltinSoftmax:
864 return VisitSoftmaxOperator(delegateData,
865 tfLiteContext,
866 tfLiteNode,
867 nodeIndex,
868 kTfLiteBuiltinSoftmax);
869 case kTfLiteBuiltinSpaceToBatchNd:
870 return VisitSpaceToBatchNdOperator(delegateData,
871 tfLiteContext,
872 tfLiteNode,
873 nodeIndex,
874 kTfLiteBuiltinSpaceToBatchNd);
875 case kTfLiteBuiltinSpaceToDepth:
876 return VisitSpaceToDepthOperator(delegateData,
877 tfLiteContext,
878 tfLiteNode,
879 nodeIndex,
880 kTfLiteBuiltinSpaceToDepth);
881 case kTfLiteBuiltinSub:
882 return VisitElementwiseBinaryOperator(delegateData,
883 tfLiteContext,
884 tfLiteNode,
885 nodeIndex,
886 kTfLiteBuiltinSub);
887 case kTfLiteBuiltinTanh:
888 return VisitActivationOperator(delegateData,
889 tfLiteContext,
890 tfLiteNode,
891 nodeIndex,
892 kTfLiteBuiltinTanh);
Kevin May8ab2d7a2021-05-07 09:32:51 +0100893 case kTfLiteBuiltinUnpack:
894 return VisitUnpackOperator(delegateData,
895 tfLiteContext,
896 tfLiteNode,
897 nodeIndex,
898 kTfLiteBuiltinUnpack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100899 default:
900 return kTfLiteError;
901 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100902}
903
904} // armnnDelegate namespace