blob: 0c984ecc82f4f8bbbeb97ee42d97b50ad128b79a [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"
33#include "Slice.hpp"
34#include "Softmax.hpp"
35#include "SpaceDepth.hpp"
Sadik Armagan34fa1bd2020-11-27 12:40:52 +000036#include "Split.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010037#include "Transpose.hpp"
Kevin May8ab2d7a2021-05-07 09:32:51 +010038#include "Unpack.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010039
40#include <flatbuffers/flatbuffers.h>
41#include <tensorflow/lite/context_util.h>
42
Sadik Armagan3c24f432020-10-19 17:35:30 +010043#include <algorithm>
Matthew Sloyanac001ee2021-02-03 10:43:04 +000044#include <iostream>
Sadik Armagan62483be2020-10-23 17:14:43 +010045#include <sstream>
Sadik Armagan3c24f432020-10-19 17:35:30 +010046
47namespace armnnDelegate
48{
49
Sadik Armagan62483be2020-10-23 17:14:43 +010050DelegateOptions TfLiteArmnnDelegateOptionsDefault()
51{
52 DelegateOptions options(armnn::Compute::CpuRef);
53 return options;
54}
55
56TfLiteDelegate* TfLiteArmnnDelegateCreate(armnnDelegate::DelegateOptions options)
57{
58 auto* armnnDelegate = new ::armnnDelegate::Delegate(options);
59 return armnnDelegate->GetDelegate();
60}
61
62void TfLiteArmnnDelegateDelete(TfLiteDelegate* tfLiteDelegate)
63{
64 if (tfLiteDelegate != nullptr)
65 {
66 delete static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_);
67 }
68}
69
70TfLiteStatus DoPrepare(TfLiteContext* tfLiteContext, TfLiteDelegate* tfLiteDelegate)
71{
72 TfLiteIntArray* supportedOperators =
73 static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_)->IdentifyOperatorsToDelegate(tfLiteContext);
74
75 // ArmNN Delegate Registration
76 static const TfLiteRegistration kArmnnSubgraphRegistration = {
77 // ArmnnSubgraph Init
78 .init = [](TfLiteContext* tfLiteContext, const char* buffer, size_t length) -> void* {
Finn Williams6f9f9902020-11-13 13:23:15 +000079 armnn::IgnoreUnused(length);
Sadik Armagan62483be2020-10-23 17:14:43 +010080 const TfLiteDelegateParams* parameters = reinterpret_cast<const TfLiteDelegateParams*>(buffer);
81
82 return static_cast<void*>(ArmnnSubgraph::Create(
83 tfLiteContext, parameters, static_cast<::armnnDelegate::Delegate*>(parameters->delegate->data_)));
84 },
85 // ArmnnSubgraph Free
86 .free = [](TfLiteContext* tfLiteContext, void* buffer) -> void {
Finn Williams6f9f9902020-11-13 13:23:15 +000087 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan62483be2020-10-23 17:14:43 +010088 if (buffer != nullptr)
89 {
90 delete static_cast<ArmnnSubgraph*>(buffer);
91 }
92 },
93 // ArmnnSubgraph Prepare
94 .prepare = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
95 if (tfLiteNode->user_data == nullptr)
96 {
97 return kTfLiteError;
98 }
Sadik Armagan62483be2020-10-23 17:14:43 +010099 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Prepare(tfLiteContext);
100 },
101 // ArmnnSubgraph Invoke
102 .invoke = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
103 if (tfLiteNode->user_data == nullptr)
104 {
105 return kTfLiteError;
106 }
107
108 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Invoke(tfLiteContext, tfLiteNode);
109 },
110
111 .profiling_string = nullptr,
112 .builtin_code = kTfLiteBuiltinDelegate,
113 .custom_name = "TfLiteArmNnDelegate",
114 .version = 1,
115 };
116
117 const TfLiteStatus status =
118 tfLiteContext->ReplaceNodeSubsetsWithDelegateKernels(
119 tfLiteContext, kArmnnSubgraphRegistration, supportedOperators, tfLiteDelegate);
120
121 TfLiteIntArrayFree(supportedOperators);
122 return status;
123
124}
125
Sadik Armagan3c24f432020-10-19 17:35:30 +0100126Delegate::Delegate(armnnDelegate::DelegateOptions options)
127 : m_Runtime(nullptr, nullptr),
128 m_Options(std::move(options))
129{
Jan Eilers2cd18472020-12-15 10:42:38 +0000130 // Configures logging for ARMNN
131 if (options.IsLoggingEnabled())
132 {
133 armnn::ConfigureLogging(true, true, options.GetLoggingSeverity());
134 }
135
Sadik Armagan3c24f432020-10-19 17:35:30 +0100136 // Create ArmNN Runtime
137 armnn::IRuntime::CreationOptions runtimeOptions;
Sadik Armagan4189cc52020-11-11 18:01:48 +0000138
139 auto backendOptions = m_Options.GetBackendOptions();
140 if (!backendOptions.empty())
141 {
142 runtimeOptions.m_BackendOptions = backendOptions;
143 }
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000144 else if (!m_Options.GetOptimizerOptions().m_ModelOptions.empty())
145 {
146 runtimeOptions.m_BackendOptions = m_Options.GetOptimizerOptions().m_ModelOptions;
147 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100148 m_Runtime = armnn::IRuntime::Create(runtimeOptions);
149
150 std::vector<armnn::BackendId> backends;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100151 if (m_Runtime)
152 {
153 const armnn::BackendIdSet supportedDevices = m_Runtime->GetDeviceSpec().GetSupportedBackends();
154 for (auto& backend : m_Options.GetBackends())
155 {
156 if (std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) == supportedDevices.cend())
157 {
Sadik Armagan0534e032020-10-27 17:30:18 +0000158 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100159 "TfLiteArmnnDelegate: Requested unknown backend %s", backend.Get().c_str());
160 }
161 else
162 {
163 backends.push_back(backend);
164 }
165 }
166 }
167
168 if (backends.empty())
169 {
170 // No known backend specified
171 throw armnn::InvalidArgumentException("TfLiteArmnnDelegate: No known backend specified.");
172 }
173 m_Options.SetBackends(backends);
174
175 TFLITE_LOG_PROD_ONCE(tflite::TFLITE_LOG_INFO, "TfLiteArmnnDelegate: Created TfLite ArmNN delegate.");
176}
177
Sadik Armagan62483be2020-10-23 17:14:43 +0100178TfLiteIntArray* Delegate::IdentifyOperatorsToDelegate(TfLiteContext* tfLiteContext)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100179{
180 TfLiteIntArray* executionPlan = nullptr;
181 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
182 {
183 TF_LITE_KERNEL_LOG(tfLiteContext, "TfLiteArmnnDelegate: Unable to get graph execution plan.");
184 return nullptr;
185 }
186
Sadik Armagan62483be2020-10-23 17:14:43 +0100187 // Delegate data with null network
188 DelegateData delegateData(m_Options.GetBackends());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100189
190 TfLiteIntArray* nodesToDelegate = TfLiteIntArrayCreate(executionPlan->size);
191 nodesToDelegate->size = 0;
192 for (int i = 0; i < executionPlan->size; ++i)
193 {
194 const int nodeIndex = executionPlan->data[i];
195
196 // If TfLite nodes can be delegated to ArmNN
197 TfLiteNode* tfLiteNode = nullptr;
198 TfLiteRegistration* tfLiteRegistration = nullptr;
199 if (tfLiteContext->GetNodeAndRegistration(
200 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
201 {
202 TF_LITE_KERNEL_LOG(tfLiteContext,
203 "TfLiteArmnnDelegate: Unable to get node and registration for node %d.",
204 nodeIndex);
205 continue;
206 }
207
208 if (ArmnnSubgraph::VisitNode(
Sadik Armagan62483be2020-10-23 17:14:43 +0100209 delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100210 {
211 // node is not supported by ArmNN
212 continue;
213 }
214
215 nodesToDelegate->data[nodesToDelegate->size++] = nodeIndex;
216 }
217
Sadik Armagan62483be2020-10-23 17:14:43 +0100218 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100219 return nodesToDelegate;
220}
221
222TfLiteDelegate* Delegate::GetDelegate()
223{
224 return &m_Delegate;
225}
226
Matthew Sloyanac001ee2021-02-03 10:43:04 +0000227const std::string Delegate::GetVersion()
228{
229 return DELEGATE_VERSION;
230}
231
Sadik Armagan62483be2020-10-23 17:14:43 +0100232TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
233 TfLiteContext* tfLiteContext,
234 const TfLiteIntArray* inputs,
235 std::vector<armnn::BindingPointInfo>& inputBindings)
236{
Finn Williams6f9f9902020-11-13 13:23:15 +0000237 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100238 for (unsigned int i = 0; i < numInputs; ++i)
239 {
240 const int32_t tensorId = inputs->data[i];
241 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000242 // Do not create bindings for constant inputs
243 if (tensor.allocation_type == kTfLiteMmapRo)
244 {
245 continue;
246 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100247
248 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
249 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
250
251 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
252 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
253 outputSlot.SetTensorInfo(tensorInfo);
254
255 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000256 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100257
Sadik Armagan6e36a642020-11-10 21:18:41 +0000258 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100259 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000260
Sadik Armagan62483be2020-10-23 17:14:43 +0100261 return kTfLiteOk;
262}
263
264TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
265 TfLiteContext* tfLiteContext,
266 const TfLiteIntArray* outputs,
267 std::vector<armnn::BindingPointInfo>& outputBindings)
268{
Finn Williams6f9f9902020-11-13 13:23:15 +0000269 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100270 for (unsigned int i = 0; i < numOutputs; ++i)
271 {
272 const int32_t tensorId = outputs->data[i];
273 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
274
275 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
276 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
277
278 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Finn Williams6f9f9902020-11-13 13:23:15 +0000279 ARMNN_ASSERT(delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] != nullptr);
280 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100281 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
282 }
283
284 return kTfLiteOk;
285}
286
Sadik Armagan3c24f432020-10-19 17:35:30 +0100287ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
288 const TfLiteDelegateParams* parameters,
289 const Delegate* delegate)
290{
291 TfLiteIntArray* executionPlan;
292 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
293 {
294 return nullptr;
295 }
296
Sadik Armagan62483be2020-10-23 17:14:43 +0100297 // Initialize DelegateData holds network and output slots information
298 DelegateData delegateData(delegate->m_Options.GetBackends());
299
300 // Build ArmNN Network
Sadik Armagan3c24f432020-10-19 17:35:30 +0100301 armnn::NetworkOptions networkOptions = {};
302 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100303 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100304
Sadik Armagan6e36a642020-11-10 21:18:41 +0000305 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
306
Sadik Armagan62483be2020-10-23 17:14:43 +0100307 std::vector<armnn::BindingPointInfo> inputBindings;
308 std::vector<armnn::BindingPointInfo> outputBindings;
309
310 // Add input layer
311 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
312 if (status != kTfLiteOk)
313 {
314 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
315 }
316
317 // Parse TfLite delegate nodes to ArmNN
Sadik Armagan3c24f432020-10-19 17:35:30 +0100318 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
319 {
320 const int nodeIndex = parameters->nodes_to_replace->data[i];
321
322 TfLiteNode* tfLiteNode = nullptr;
323 TfLiteRegistration* tfLiteRegistration = nullptr;
324 if (tfLiteContext->GetNodeAndRegistration(
325 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
326 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000327 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100328 }
329
Sadik Armagan62483be2020-10-23 17:14:43 +0100330 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100331 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000332 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100333 }
334 }
335
Sadik Armagan62483be2020-10-23 17:14:43 +0100336 // Add Output layer
337 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
338 if (status != kTfLiteOk)
339 {
340 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
341 }
342
343 // Optimize ArmNN network
344 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
345 try
346 {
Sadik Armagan6e36a642020-11-10 21:18:41 +0000347 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100348 delegate->m_Options.GetBackends(),
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000349 delegate->m_Runtime->GetDeviceSpec(),
350 delegate->m_Options.GetOptimizerOptions());
Sadik Armagan62483be2020-10-23 17:14:43 +0100351 }
352 catch (std::exception &ex)
353 {
354 std::stringstream exMessage;
355 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
356 throw armnn::Exception(exMessage.str());
357 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100358 if (!optNet)
359 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100360 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100361 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
362 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100363
364 try
365 {
366 // Load graph into runtime
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000367 std::string errorMessage;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000368 armnn::Status loadingStatus;
369 if (delegate->m_Options.GetOptimizerOptions().m_ImportEnabled)
370 {
Francis Murtagh73d3e2e2021-04-29 14:23:04 +0100371 armnn::INetworkProperties networkProperties(false,
372 armnn::MemorySource::Malloc,
373 armnn::MemorySource::Malloc);
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000374 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
375 std::move(optNet),
376 errorMessage,
377 networkProperties);
378 }
379 else
380 {
381 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
382 std::move(optNet),
383 errorMessage);
384 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100385 if (loadingStatus != armnn::Status::Success)
386 {
387 // Optimize failed
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000388 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded:" + errorMessage);
Sadik Armagan62483be2020-10-23 17:14:43 +0100389 }
390 }
391 catch (std::exception& ex)
392 {
393 std::stringstream exMessage;
394 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
395 throw armnn::Exception(exMessage.str());
396 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100397
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000398 // Register debug callback function
399 if (delegate->m_Options.GetDebugCallbackFunction().has_value())
400 {
401 delegate->m_Runtime->RegisterDebugCallback(networkId, delegate->m_Options.GetDebugCallbackFunction().value());
402 }
403
Sadik Armagan3c24f432020-10-19 17:35:30 +0100404 // Create a new SubGraph with networkId and runtime
Sadik Armagan62483be2020-10-23 17:14:43 +0100405 return new ArmnnSubgraph(networkId, delegate->m_Runtime.get(), inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100406}
407
408TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
409{
Finn Williams6f9f9902020-11-13 13:23:15 +0000410 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100411 return kTfLiteOk;
412}
413
Sadik Armagan62483be2020-10-23 17:14:43 +0100414TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100415{
Sadik Armagan62483be2020-10-23 17:14:43 +0100416 // Prepare inputs
417 armnn::InputTensors inputTensors;
418 size_t inputIndex = 0;
419 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
420 {
421 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
422 if (tensor->allocation_type != kTfLiteMmapRo)
423 {
424 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
425 const armnn::ConstTensor inputTensor(inputBinding.second, tensor->data.data);
426 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100427
Sadik Armagan62483be2020-10-23 17:14:43 +0100428 ++inputIndex;
429 }
430 }
431
432 // Prepare outputs
433 armnn::OutputTensors outputTensors;
434 size_t outputIndex = 0;
435 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
436 {
437 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
438 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
439 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
440 outputTensors.emplace_back(outputIdx, outputTensor);
441
442 ++outputIndex;
443 }
444
445 // Run graph
446 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
447 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100448}
449
Sadik Armagan62483be2020-10-23 17:14:43 +0100450TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100451 TfLiteContext* tfLiteContext,
452 TfLiteRegistration* tfLiteRegistration,
453 TfLiteNode* tfLiteNode,
454 int nodeIndex)
455{
Sadik Armagan62483be2020-10-23 17:14:43 +0100456 switch (tfLiteRegistration->builtin_code)
457 {
458 case kTfLiteBuiltinAbs:
459 return VisitElementwiseUnaryOperator(delegateData,
460 tfLiteContext,
461 tfLiteNode,
462 nodeIndex,
463 armnn::UnaryOperation::Abs);
464 case kTfLiteBuiltinAdd:
465 return VisitElementwiseBinaryOperator(delegateData,
466 tfLiteContext,
467 tfLiteNode,
468 nodeIndex,
469 kTfLiteBuiltinAdd);
470 case kTfLiteBuiltinArgMax:
471 return VisitArgMinMaxOperator(delegateData,
472 tfLiteContext,
473 tfLiteNode,
474 nodeIndex,
475 kTfLiteBuiltinArgMax);
476 case kTfLiteBuiltinArgMin:
477 return VisitArgMinMaxOperator(delegateData,
478 tfLiteContext,
479 tfLiteNode,
480 nodeIndex,
481 kTfLiteBuiltinArgMin);
482 case kTfLiteBuiltinAveragePool2d:
483 return VisitPoolingOperator(delegateData,
484 tfLiteContext,
485 tfLiteNode,
486 nodeIndex,
487 kTfLiteBuiltinAveragePool2d);
488 case kTfLiteBuiltinBatchToSpaceNd:
489 return VisitBatchToSpaceNdOperator(delegateData,
490 tfLiteContext,
491 tfLiteNode,
492 nodeIndex,
493 kTfLiteBuiltinBatchToSpaceNd);
Sadik Armagan937565b2021-04-21 14:03:28 +0100494 case kTfLiteBuiltinCast:
495 return VisitCastOperator(delegateData,
496 tfLiteContext,
497 tfLiteNode,
498 nodeIndex,
499 kTfLiteBuiltinCast);
Sadik Armagan62483be2020-10-23 17:14:43 +0100500 case kTfLiteBuiltinConcatenation:
501 return VisitControlOperator(delegateData,
502 tfLiteContext,
503 tfLiteNode,
504 nodeIndex,
505 kTfLiteBuiltinConcatenation);
506 case kTfLiteBuiltinConv2d:
507 return VisitConvolutionOperator(delegateData,
508 tfLiteContext,
509 tfLiteNode,
510 nodeIndex,
511 kTfLiteBuiltinConv2d);
512 case kTfLiteBuiltinDepthToSpace:
513 return VisitDepthToSpaceOperator(delegateData,
514 tfLiteContext,
515 tfLiteNode,
516 nodeIndex,
517 kTfLiteBuiltinDepthToSpace);
518 case kTfLiteBuiltinDepthwiseConv2d:
519 return VisitConvolutionOperator(delegateData,
520 tfLiteContext,
521 tfLiteNode,
522 nodeIndex,
523 kTfLiteBuiltinDepthwiseConv2d);
524 case kTfLiteBuiltinDequantize:
525 return VisitDequantizeOperator(delegateData,
526 tfLiteContext,
527 tfLiteNode,
528 nodeIndex,
529 kTfLiteBuiltinDequantize);
530 case kTfLiteBuiltinDiv:
531 return VisitElementwiseBinaryOperator(delegateData,
532 tfLiteContext,
533 tfLiteNode,
534 nodeIndex,
535 kTfLiteBuiltinDiv);
536 case kTfLiteBuiltinElu:
537 return VisitActivationOperator(delegateData,
538 tfLiteContext,
539 tfLiteNode,
540 nodeIndex,
541 kTfLiteBuiltinElu);
542 case kTfLiteBuiltinEqual:
543 return VisitComparisonOperator(delegateData,
544 tfLiteContext,
545 tfLiteNode,
546 nodeIndex,
547 kTfLiteBuiltinEqual);
548 case kTfLiteBuiltinExp:
549 return VisitElementwiseUnaryOperator(delegateData,
550 tfLiteContext,
551 tfLiteNode,
552 nodeIndex,
553 armnn::UnaryOperation::Exp);
554 case kTfLiteBuiltinExpandDims:
555 return VisitExpandDimsOperator(delegateData,
556 tfLiteContext,
557 tfLiteNode,
558 nodeIndex,
559 kTfLiteBuiltinExpandDims);
560 case kTfLiteBuiltinFill:
561 return VisitFillOperator(delegateData,
562 tfLiteContext,
563 tfLiteNode,
564 nodeIndex,
565 kTfLiteBuiltinFill);
566 case kTfLiteBuiltinFloor:
567 return VisitFloorOperator(delegateData,
568 tfLiteContext,
569 tfLiteNode,
570 nodeIndex,
571 kTfLiteBuiltinFloor);
572 case kTfLiteBuiltinFullyConnected:
573 return VisitFullyConnectedOperator(delegateData,
574 tfLiteContext,
575 tfLiteNode,
576 nodeIndex,
577 kTfLiteBuiltinFullyConnected);
578 case kTfLiteBuiltinGather:
579 return VisitGatherOperator(delegateData,
580 tfLiteContext,
581 tfLiteNode,
582 nodeIndex,
583 kTfLiteBuiltinGather);
584 case kTfLiteBuiltinGatherNd:
585 return VisitGatherOperator(delegateData,
586 tfLiteContext,
587 tfLiteNode,
588 nodeIndex,
589 kTfLiteBuiltinGatherNd);
590 case kTfLiteBuiltinGreater:
591 return VisitComparisonOperator(delegateData,
592 tfLiteContext,
593 tfLiteNode,
594 nodeIndex,
595 kTfLiteBuiltinGreater);
596 case kTfLiteBuiltinGreaterEqual:
597 return VisitComparisonOperator(delegateData,
598 tfLiteContext,
599 tfLiteNode,
600 nodeIndex,
601 kTfLiteBuiltinGreaterEqual);
602 case kTfLiteBuiltinHardSwish:
603 return VisitActivationOperator(delegateData,
604 tfLiteContext,
605 tfLiteNode,
606 nodeIndex,
607 kTfLiteBuiltinHardSwish);
608 case kTfLiteBuiltinL2Normalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000609 return VisitL2NormalizationOperator(delegateData,
610 tfLiteContext,
611 tfLiteNode,
612 nodeIndex,
613 kTfLiteBuiltinL2Normalization);
Sadik Armagan62483be2020-10-23 17:14:43 +0100614 case kTfLiteBuiltinL2Pool2d:
615 return VisitPoolingOperator(delegateData,
616 tfLiteContext,
617 tfLiteNode,
618 nodeIndex,
619 kTfLiteBuiltinL2Pool2d);
620 case kTfLiteBuiltinLess:
621 return VisitComparisonOperator(delegateData,
622 tfLiteContext,
623 tfLiteNode,
624 nodeIndex,
625 kTfLiteBuiltinLess);
626 case kTfLiteBuiltinLessEqual:
627 return VisitComparisonOperator(delegateData,
628 tfLiteContext,
629 tfLiteNode,
630 nodeIndex,
631 kTfLiteBuiltinLessEqual);
632 case kTfLiteBuiltinLocalResponseNormalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000633 return VisitLocalResponseNormalizationOperator(delegateData,
634 tfLiteContext,
635 tfLiteNode,
636 nodeIndex,
637 kTfLiteBuiltinLocalResponseNormalization);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000638 case kTfLiteBuiltinLogicalAnd:
639 return VisitLogicalBinaryOperator(delegateData,
640 tfLiteContext,
641 tfLiteNode,
642 nodeIndex,
643 kTfLiteBuiltinLogicalAnd,
644 armnn::LogicalBinaryOperation::LogicalAnd);
645 case kTfLiteBuiltinLogicalNot:
646 return VisitElementwiseUnaryOperator(delegateData,
647 tfLiteContext,
648 tfLiteNode,
649 nodeIndex,
650 armnn::UnaryOperation::LogicalNot);
651 case kTfLiteBuiltinLogicalOr:
652 return VisitLogicalBinaryOperator(delegateData,
653 tfLiteContext,
654 tfLiteNode,
655 nodeIndex,
656 kTfLiteBuiltinLogicalOr,
657 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100658 case kTfLiteBuiltinLogistic:
659 return VisitActivationOperator(delegateData,
660 tfLiteContext,
661 tfLiteNode,
662 nodeIndex,
663 kTfLiteBuiltinLogistic);
664 case kTfLiteBuiltinLogSoftmax:
665 return VisitSoftmaxOperator(delegateData,
666 tfLiteContext,
667 tfLiteNode,
668 nodeIndex,
669 kTfLiteBuiltinLogSoftmax);
670 case kTfLiteBuiltinLstm:
671 return VisitLstmOperator(delegateData,
672 tfLiteContext,
673 tfLiteNode,
674 nodeIndex,
675 kTfLiteBuiltinLstm);
676 case kTfLiteBuiltinMaxPool2d:
677 return VisitPoolingOperator(delegateData,
678 tfLiteContext,
679 tfLiteNode,
680 nodeIndex,
681 kTfLiteBuiltinMaxPool2d);
682 case kTfLiteBuiltinMaximum:
683 return VisitElementwiseBinaryOperator(delegateData,
684 tfLiteContext,
685 tfLiteNode,
686 nodeIndex,
687 kTfLiteBuiltinMaximum);
688 case kTfLiteBuiltinMean:
689 return VisitControlOperator(delegateData,
690 tfLiteContext,
691 tfLiteNode,
692 nodeIndex,
693 kTfLiteBuiltinMean);
694 case kTfLiteBuiltinMinimum:
695 return VisitElementwiseBinaryOperator(delegateData,
696 tfLiteContext,
697 tfLiteNode,
698 nodeIndex,
699 kTfLiteBuiltinMinimum);
700 case kTfLiteBuiltinMul:
701 return VisitElementwiseBinaryOperator(delegateData,
702 tfLiteContext,
703 tfLiteNode,
704 nodeIndex,
705 kTfLiteBuiltinMul);
706 case kTfLiteBuiltinNeg:
707 return VisitElementwiseUnaryOperator(delegateData,
708 tfLiteContext,
709 tfLiteNode,
710 nodeIndex,
711 armnn::UnaryOperation::Neg);
712 case kTfLiteBuiltinNotEqual:
713 return VisitComparisonOperator(delegateData,
714 tfLiteContext,
715 tfLiteNode,
716 nodeIndex,
717 kTfLiteBuiltinNotEqual);
Matthew Sloyana7a12f52021-05-06 10:05:28 +0100718 case kTfLiteBuiltinPack:
719 return VisitPackOperator(delegateData,
720 tfLiteContext,
721 tfLiteNode,
722 nodeIndex,
723 kTfLiteBuiltinPack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100724 case kTfLiteBuiltinPad:
725 return VisitPadOperator(delegateData,
726 tfLiteContext,
727 tfLiteNode,
728 nodeIndex,
729 kTfLiteBuiltinPad);
730 case kTfLiteBuiltinPadv2:
731 return VisitPadOperator(delegateData,
732 tfLiteContext,
733 tfLiteNode,
734 nodeIndex,
735 kTfLiteBuiltinPadv2);
736 case kTfLiteBuiltinPrelu:
James Conroy39825482021-05-27 17:44:50 +0100737 return VisitPreluOperator(delegateData,
738 tfLiteContext,
739 tfLiteNode,
740 nodeIndex,
741 kTfLiteBuiltinPrelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100742 case kTfLiteBuiltinQuantize:
743 return VisitQuantizeOperator(delegateData,
744 tfLiteContext,
745 tfLiteNode,
746 nodeIndex,
747 kTfLiteBuiltinQuantize);
748 case kTfLiteBuiltinRank:
749 return VisitControlOperator(delegateData,
750 tfLiteContext,
751 tfLiteNode,
752 nodeIndex,
753 kTfLiteBuiltinRank);
Sadik Armagana2747482021-02-09 10:28:54 +0000754 case kTfLiteBuiltinReduceMax:
755 return VisitReduceOperator(delegateData,
756 tfLiteContext,
757 tfLiteNode,
758 nodeIndex,
759 kTfLiteBuiltinReduceMax);
760 case kTfLiteBuiltinReduceMin:
761 return VisitReduceOperator(delegateData,
762 tfLiteContext,
763 tfLiteNode,
764 nodeIndex,
765 kTfLiteBuiltinReduceMin);
Sadik Armagan62483be2020-10-23 17:14:43 +0100766 case kTfLiteBuiltinRelu:
767 return VisitActivationOperator(delegateData,
768 tfLiteContext,
769 tfLiteNode,
770 nodeIndex,
771 kTfLiteBuiltinRelu);
772 case kTfLiteBuiltinReluN1To1:
773 return VisitActivationOperator(delegateData,
774 tfLiteContext,
775 tfLiteNode,
776 nodeIndex,
777 kTfLiteBuiltinReluN1To1);
778 case kTfLiteBuiltinRelu6:
779 return VisitActivationOperator(delegateData,
780 tfLiteContext,
781 tfLiteNode,
782 nodeIndex,
783 kTfLiteBuiltinRelu6);
784 case kTfLiteBuiltinReshape:
785 return VisitReshapeOperator(delegateData,
786 tfLiteContext,
787 tfLiteNode,
788 nodeIndex,
789 kTfLiteBuiltinReshape);
790 case kTfLiteBuiltinResizeBilinear:
791 return VisitResizeOperator(delegateData,
792 tfLiteContext,
793 tfLiteNode,
794 nodeIndex,
795 kTfLiteBuiltinResizeBilinear);
796 case kTfLiteBuiltinResizeNearestNeighbor:
797 return VisitResizeOperator(delegateData,
798 tfLiteContext,
799 tfLiteNode,
800 nodeIndex,
801 kTfLiteBuiltinResizeNearestNeighbor);
802 case kTfLiteBuiltinRsqrt:
803 return VisitElementwiseUnaryOperator(delegateData,
804 tfLiteContext,
805 tfLiteNode,
806 nodeIndex,
807 armnn::UnaryOperation::Rsqrt);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +0000808 case kTfLiteBuiltinSplit:
809 return VisitSplitOperator(delegateData,
810 tfLiteContext,
811 tfLiteNode,
812 nodeIndex,
813 kTfLiteBuiltinSplit);
814 case kTfLiteBuiltinSplitV:
815 return VisitSplitVOperator(delegateData,
816 tfLiteContext,
817 tfLiteNode,
818 nodeIndex,
819 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +0100820 case kTfLiteBuiltinSqrt:
821 return VisitElementwiseUnaryOperator(delegateData,
822 tfLiteContext,
823 tfLiteNode,
824 nodeIndex,
825 armnn::UnaryOperation::Sqrt);
826 case kTfLiteBuiltinSqueeze:
827 return VisitSqueezeOperator(delegateData,
828 tfLiteContext,
829 tfLiteNode,
830 nodeIndex,
831 kTfLiteBuiltinSqueeze);
832 case kTfLiteBuiltinStridedSlice:
833 return VisitSliceOperator(delegateData,
834 tfLiteContext,
835 tfLiteNode,
836 nodeIndex,
837 kTfLiteBuiltinStridedSlice);
Sadik Armagana2747482021-02-09 10:28:54 +0000838 case kTfLiteBuiltinSum:
839 return VisitReduceOperator(delegateData,
840 tfLiteContext,
841 tfLiteNode,
842 nodeIndex,
843 kTfLiteBuiltinSum);
Sadik Armagan62483be2020-10-23 17:14:43 +0100844 case kTfLiteBuiltinTranspose:
845 return VisitTransposeOperator(delegateData,
846 tfLiteContext,
847 tfLiteNode,
848 nodeIndex,
849 kTfLiteBuiltinTranspose);
850 case kTfLiteBuiltinTransposeConv:
851 return VisitConvolutionOperator(delegateData,
852 tfLiteContext,
853 tfLiteNode,
854 nodeIndex,
855 kTfLiteBuiltinTransposeConv);
856 case kTfLiteBuiltinSoftmax:
857 return VisitSoftmaxOperator(delegateData,
858 tfLiteContext,
859 tfLiteNode,
860 nodeIndex,
861 kTfLiteBuiltinSoftmax);
862 case kTfLiteBuiltinSpaceToBatchNd:
863 return VisitSpaceToBatchNdOperator(delegateData,
864 tfLiteContext,
865 tfLiteNode,
866 nodeIndex,
867 kTfLiteBuiltinSpaceToBatchNd);
868 case kTfLiteBuiltinSpaceToDepth:
869 return VisitSpaceToDepthOperator(delegateData,
870 tfLiteContext,
871 tfLiteNode,
872 nodeIndex,
873 kTfLiteBuiltinSpaceToDepth);
874 case kTfLiteBuiltinSub:
875 return VisitElementwiseBinaryOperator(delegateData,
876 tfLiteContext,
877 tfLiteNode,
878 nodeIndex,
879 kTfLiteBuiltinSub);
880 case kTfLiteBuiltinTanh:
881 return VisitActivationOperator(delegateData,
882 tfLiteContext,
883 tfLiteNode,
884 nodeIndex,
885 kTfLiteBuiltinTanh);
Kevin May8ab2d7a2021-05-07 09:32:51 +0100886 case kTfLiteBuiltinUnpack:
887 return VisitUnpackOperator(delegateData,
888 tfLiteContext,
889 tfLiteNode,
890 nodeIndex,
891 kTfLiteBuiltinUnpack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100892 default:
893 return kTfLiteError;
894 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100895}
896
897} // armnnDelegate namespace