blob: 4c1bc57fc2c883e348d621ce63ad4221f671c928 [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"
Narumol Prangnawarat7684b182021-08-12 14:48:15 +010039#include "UnidirectionalSequenceLstm.hpp"
Kevin May8ab2d7a2021-05-07 09:32:51 +010040#include "Unpack.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010041
Colm Donelan3e32a872021-10-04 22:55:37 +010042#include <armnnUtils/Filesystem.hpp>
Sadik Armagan62483be2020-10-23 17:14:43 +010043#include <flatbuffers/flatbuffers.h>
44#include <tensorflow/lite/context_util.h>
Jim Flynn4b2f3472021-10-13 21:20:07 +010045#include <tensorflow/lite/schema/schema_generated.h>
Sadik Armagan62483be2020-10-23 17:14:43 +010046
Sadik Armagan3c24f432020-10-19 17:35:30 +010047#include <algorithm>
Matthew Sloyanac001ee2021-02-03 10:43:04 +000048#include <iostream>
Sadik Armagan62483be2020-10-23 17:14:43 +010049#include <sstream>
Sadik Armagan3c24f432020-10-19 17:35:30 +010050
51namespace armnnDelegate
52{
53
Sadik Armagan62483be2020-10-23 17:14:43 +010054DelegateOptions TfLiteArmnnDelegateOptionsDefault()
55{
56 DelegateOptions options(armnn::Compute::CpuRef);
57 return options;
58}
59
60TfLiteDelegate* TfLiteArmnnDelegateCreate(armnnDelegate::DelegateOptions options)
61{
62 auto* armnnDelegate = new ::armnnDelegate::Delegate(options);
63 return armnnDelegate->GetDelegate();
64}
65
66void TfLiteArmnnDelegateDelete(TfLiteDelegate* tfLiteDelegate)
67{
68 if (tfLiteDelegate != nullptr)
69 {
70 delete static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_);
71 }
72}
73
74TfLiteStatus DoPrepare(TfLiteContext* tfLiteContext, TfLiteDelegate* tfLiteDelegate)
75{
76 TfLiteIntArray* supportedOperators =
77 static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_)->IdentifyOperatorsToDelegate(tfLiteContext);
78
79 // ArmNN Delegate Registration
80 static const TfLiteRegistration kArmnnSubgraphRegistration = {
81 // ArmnnSubgraph Init
82 .init = [](TfLiteContext* tfLiteContext, const char* buffer, size_t length) -> void* {
Finn Williams6f9f9902020-11-13 13:23:15 +000083 armnn::IgnoreUnused(length);
Sadik Armagan62483be2020-10-23 17:14:43 +010084 const TfLiteDelegateParams* parameters = reinterpret_cast<const TfLiteDelegateParams*>(buffer);
85
86 return static_cast<void*>(ArmnnSubgraph::Create(
87 tfLiteContext, parameters, static_cast<::armnnDelegate::Delegate*>(parameters->delegate->data_)));
88 },
89 // ArmnnSubgraph Free
90 .free = [](TfLiteContext* tfLiteContext, void* buffer) -> void {
Finn Williams6f9f9902020-11-13 13:23:15 +000091 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan62483be2020-10-23 17:14:43 +010092 if (buffer != nullptr)
93 {
94 delete static_cast<ArmnnSubgraph*>(buffer);
95 }
96 },
97 // ArmnnSubgraph Prepare
98 .prepare = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
99 if (tfLiteNode->user_data == nullptr)
100 {
101 return kTfLiteError;
102 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100103 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Prepare(tfLiteContext);
104 },
105 // ArmnnSubgraph Invoke
106 .invoke = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
107 if (tfLiteNode->user_data == nullptr)
108 {
109 return kTfLiteError;
110 }
111
112 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Invoke(tfLiteContext, tfLiteNode);
113 },
114
115 .profiling_string = nullptr,
116 .builtin_code = kTfLiteBuiltinDelegate,
117 .custom_name = "TfLiteArmNnDelegate",
118 .version = 1,
119 };
120
121 const TfLiteStatus status =
122 tfLiteContext->ReplaceNodeSubsetsWithDelegateKernels(
123 tfLiteContext, kArmnnSubgraphRegistration, supportedOperators, tfLiteDelegate);
124
125 TfLiteIntArrayFree(supportedOperators);
126 return status;
127
128}
129
Sadik Armagan3c24f432020-10-19 17:35:30 +0100130Delegate::Delegate(armnnDelegate::DelegateOptions options)
131 : m_Runtime(nullptr, nullptr),
132 m_Options(std::move(options))
133{
Jan Eilers2cd18472020-12-15 10:42:38 +0000134 // Configures logging for ARMNN
135 if (options.IsLoggingEnabled())
136 {
137 armnn::ConfigureLogging(true, true, options.GetLoggingSeverity());
138 }
139
Sadik Armagan3c24f432020-10-19 17:35:30 +0100140 // Create ArmNN Runtime
Jan Eilersb1c62f12021-10-26 14:56:47 +0100141 m_Runtime = armnn::IRuntime::Create(options.GetRuntimeOptions());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100142
143 std::vector<armnn::BackendId> backends;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100144 if (m_Runtime)
145 {
146 const armnn::BackendIdSet supportedDevices = m_Runtime->GetDeviceSpec().GetSupportedBackends();
147 for (auto& backend : m_Options.GetBackends())
148 {
149 if (std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) == supportedDevices.cend())
150 {
Sadik Armagan0534e032020-10-27 17:30:18 +0000151 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100152 "TfLiteArmnnDelegate: Requested unknown backend %s", backend.Get().c_str());
153 }
154 else
155 {
156 backends.push_back(backend);
157 }
158 }
159 }
160
161 if (backends.empty())
162 {
163 // No known backend specified
164 throw armnn::InvalidArgumentException("TfLiteArmnnDelegate: No known backend specified.");
165 }
166 m_Options.SetBackends(backends);
167
168 TFLITE_LOG_PROD_ONCE(tflite::TFLITE_LOG_INFO, "TfLiteArmnnDelegate: Created TfLite ArmNN delegate.");
169}
170
Sadik Armagan62483be2020-10-23 17:14:43 +0100171TfLiteIntArray* Delegate::IdentifyOperatorsToDelegate(TfLiteContext* tfLiteContext)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100172{
173 TfLiteIntArray* executionPlan = nullptr;
174 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
175 {
176 TF_LITE_KERNEL_LOG(tfLiteContext, "TfLiteArmnnDelegate: Unable to get graph execution plan.");
177 return nullptr;
178 }
179
Sadik Armagan62483be2020-10-23 17:14:43 +0100180 // Delegate data with null network
181 DelegateData delegateData(m_Options.GetBackends());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100182
183 TfLiteIntArray* nodesToDelegate = TfLiteIntArrayCreate(executionPlan->size);
184 nodesToDelegate->size = 0;
185 for (int i = 0; i < executionPlan->size; ++i)
186 {
187 const int nodeIndex = executionPlan->data[i];
188
189 // If TfLite nodes can be delegated to ArmNN
190 TfLiteNode* tfLiteNode = nullptr;
191 TfLiteRegistration* tfLiteRegistration = nullptr;
192 if (tfLiteContext->GetNodeAndRegistration(
193 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
194 {
195 TF_LITE_KERNEL_LOG(tfLiteContext,
196 "TfLiteArmnnDelegate: Unable to get node and registration for node %d.",
197 nodeIndex);
198 continue;
199 }
200
201 if (ArmnnSubgraph::VisitNode(
Sadik Armagan62483be2020-10-23 17:14:43 +0100202 delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100203 {
204 // node is not supported by ArmNN
205 continue;
206 }
207
208 nodesToDelegate->data[nodesToDelegate->size++] = nodeIndex;
209 }
210
Sadik Armagan62483be2020-10-23 17:14:43 +0100211 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100212 return nodesToDelegate;
213}
214
215TfLiteDelegate* Delegate::GetDelegate()
216{
217 return &m_Delegate;
218}
219
Matthew Sloyanac001ee2021-02-03 10:43:04 +0000220const std::string Delegate::GetVersion()
221{
222 return DELEGATE_VERSION;
223}
224
Sadik Armagan62483be2020-10-23 17:14:43 +0100225TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
226 TfLiteContext* tfLiteContext,
227 const TfLiteIntArray* inputs,
228 std::vector<armnn::BindingPointInfo>& inputBindings)
229{
Finn Williams6f9f9902020-11-13 13:23:15 +0000230 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100231 for (unsigned int i = 0; i < numInputs; ++i)
232 {
233 const int32_t tensorId = inputs->data[i];
234 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000235 // Do not create bindings for constant inputs
236 if (tensor.allocation_type == kTfLiteMmapRo)
237 {
238 continue;
239 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100240
241 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
242 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
243
244 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
245 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
246 outputSlot.SetTensorInfo(tensorInfo);
247
248 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000249 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100250
Sadik Armagan6e36a642020-11-10 21:18:41 +0000251 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100252 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000253
Sadik Armagan62483be2020-10-23 17:14:43 +0100254 return kTfLiteOk;
255}
256
257TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
258 TfLiteContext* tfLiteContext,
259 const TfLiteIntArray* outputs,
260 std::vector<armnn::BindingPointInfo>& outputBindings)
261{
Finn Williams6f9f9902020-11-13 13:23:15 +0000262 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100263 for (unsigned int i = 0; i < numOutputs; ++i)
264 {
265 const int32_t tensorId = outputs->data[i];
266 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
267
268 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
269 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
270
271 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Finn Williams6f9f9902020-11-13 13:23:15 +0000272 ARMNN_ASSERT(delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] != nullptr);
273 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100274 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
275 }
276
277 return kTfLiteOk;
278}
279
Sadik Armagan3c24f432020-10-19 17:35:30 +0100280ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
281 const TfLiteDelegateParams* parameters,
282 const Delegate* delegate)
283{
284 TfLiteIntArray* executionPlan;
285 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
286 {
287 return nullptr;
288 }
289
Sadik Armagan62483be2020-10-23 17:14:43 +0100290 // Initialize DelegateData holds network and output slots information
291 DelegateData delegateData(delegate->m_Options.GetBackends());
292
293 // Build ArmNN Network
Sadik Armagan3c24f432020-10-19 17:35:30 +0100294 armnn::NetworkOptions networkOptions = {};
295 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100296 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100297
Sadik Armagan6e36a642020-11-10 21:18:41 +0000298 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
299
Sadik Armagan62483be2020-10-23 17:14:43 +0100300 std::vector<armnn::BindingPointInfo> inputBindings;
301 std::vector<armnn::BindingPointInfo> outputBindings;
302
303 // Add input layer
304 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
305 if (status != kTfLiteOk)
306 {
307 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
308 }
309
310 // Parse TfLite delegate nodes to ArmNN
Sadik Armagan3c24f432020-10-19 17:35:30 +0100311 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
312 {
313 const int nodeIndex = parameters->nodes_to_replace->data[i];
314
315 TfLiteNode* tfLiteNode = nullptr;
316 TfLiteRegistration* tfLiteRegistration = nullptr;
317 if (tfLiteContext->GetNodeAndRegistration(
318 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
319 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000320 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100321 }
322
Sadik Armagan62483be2020-10-23 17:14:43 +0100323 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100324 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000325 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100326 }
327 }
328
Sadik Armagan62483be2020-10-23 17:14:43 +0100329 // Add Output layer
330 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
331 if (status != kTfLiteOk)
332 {
333 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
334 }
335
336 // Optimize ArmNN network
337 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
338 try
339 {
Sadik Armagan6e36a642020-11-10 21:18:41 +0000340 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100341 delegate->m_Options.GetBackends(),
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000342 delegate->m_Runtime->GetDeviceSpec(),
343 delegate->m_Options.GetOptimizerOptions());
Sadik Armagan62483be2020-10-23 17:14:43 +0100344 }
345 catch (std::exception &ex)
346 {
347 std::stringstream exMessage;
348 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
349 throw armnn::Exception(exMessage.str());
350 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100351 if (!optNet)
352 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100353 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100354 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
355 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100356
Colm Donelan3e32a872021-10-04 22:55:37 +0100357 // If set, we will serialize the optimized model into a dot file.
358 const std::string serializeToDotFile = delegate->m_Options.GetSerializeToDot();
359 if (!serializeToDotFile.empty())
360 {
361 fs::path filename = serializeToDotFile;
362 std::fstream file(filename.c_str(), std::ios_base::out);
363 optNet->SerializeToDot(file);
364 }
365
Sadik Armagan62483be2020-10-23 17:14:43 +0100366 try
367 {
368 // Load graph into runtime
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000369 std::string errorMessage;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000370 armnn::Status loadingStatus;
Colm Donelan3e32a872021-10-04 22:55:37 +0100371 armnn::MemorySource memorySource = armnn::MemorySource::Undefined;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000372 if (delegate->m_Options.GetOptimizerOptions().m_ImportEnabled)
373 {
Colm Donelan3e32a872021-10-04 22:55:37 +0100374 memorySource = armnn::MemorySource::Malloc;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000375 }
Colm Donelan3e32a872021-10-04 22:55:37 +0100376 armnn::INetworkProperties networkProperties(false,
377 memorySource,
378 memorySource,
379 delegate->m_Options.GetInternalProfilingState(),
380 delegate->m_Options.GetInternalProfilingDetail());
381 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
382 std::move(optNet),
383 errorMessage,
384 networkProperties);
Sadik Armagan62483be2020-10-23 17:14:43 +0100385 if (loadingStatus != armnn::Status::Success)
386 {
Colm Donelan45142282021-10-21 23:39:52 +0100387 // Network load 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);
Colm Donelan45142282021-10-21 23:39:52 +0100447 // The delegate holds its own Arm NN runtime so this is our last chance to print internal profiling data.
448 std::shared_ptr<armnn::IProfiler> profiler = m_Runtime->GetProfiler(m_NetworkId);
449 if (profiler && profiler->IsProfilingEnabled())
450 {
451 profiler->Print(std::cout);
452 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100453 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100454}
455
Sadik Armagan62483be2020-10-23 17:14:43 +0100456TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100457 TfLiteContext* tfLiteContext,
458 TfLiteRegistration* tfLiteRegistration,
459 TfLiteNode* tfLiteNode,
460 int nodeIndex)
461{
Sadik Armagan62483be2020-10-23 17:14:43 +0100462 switch (tfLiteRegistration->builtin_code)
463 {
464 case kTfLiteBuiltinAbs:
465 return VisitElementwiseUnaryOperator(delegateData,
466 tfLiteContext,
467 tfLiteNode,
468 nodeIndex,
469 armnn::UnaryOperation::Abs);
470 case kTfLiteBuiltinAdd:
471 return VisitElementwiseBinaryOperator(delegateData,
472 tfLiteContext,
473 tfLiteNode,
474 nodeIndex,
475 kTfLiteBuiltinAdd);
476 case kTfLiteBuiltinArgMax:
477 return VisitArgMinMaxOperator(delegateData,
478 tfLiteContext,
479 tfLiteNode,
480 nodeIndex,
481 kTfLiteBuiltinArgMax);
482 case kTfLiteBuiltinArgMin:
483 return VisitArgMinMaxOperator(delegateData,
484 tfLiteContext,
485 tfLiteNode,
486 nodeIndex,
487 kTfLiteBuiltinArgMin);
488 case kTfLiteBuiltinAveragePool2d:
489 return VisitPoolingOperator(delegateData,
490 tfLiteContext,
491 tfLiteNode,
492 nodeIndex,
493 kTfLiteBuiltinAveragePool2d);
494 case kTfLiteBuiltinBatchToSpaceNd:
495 return VisitBatchToSpaceNdOperator(delegateData,
496 tfLiteContext,
497 tfLiteNode,
498 nodeIndex,
499 kTfLiteBuiltinBatchToSpaceNd);
Sadik Armagan937565b2021-04-21 14:03:28 +0100500 case kTfLiteBuiltinCast:
501 return VisitCastOperator(delegateData,
502 tfLiteContext,
503 tfLiteNode,
504 nodeIndex,
505 kTfLiteBuiltinCast);
Sadik Armagan62483be2020-10-23 17:14:43 +0100506 case kTfLiteBuiltinConcatenation:
507 return VisitControlOperator(delegateData,
508 tfLiteContext,
509 tfLiteNode,
510 nodeIndex,
511 kTfLiteBuiltinConcatenation);
512 case kTfLiteBuiltinConv2d:
513 return VisitConvolutionOperator(delegateData,
514 tfLiteContext,
515 tfLiteNode,
516 nodeIndex,
517 kTfLiteBuiltinConv2d);
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100518// Conv3d is only correctly supported for external delegates from TF Lite v2.6, as there was a breaking bug in v2.5.
519#if defined(ARMNN_POST_TFLITE_2_5)
520 case kTfLiteBuiltinConv3d:
521 return VisitConvolutionOperator(delegateData,
522 tfLiteContext,
523 tfLiteNode,
524 nodeIndex,
525 kTfLiteBuiltinConv3d);
526#endif
Sadik Armagan62483be2020-10-23 17:14:43 +0100527 case kTfLiteBuiltinDepthToSpace:
528 return VisitDepthToSpaceOperator(delegateData,
529 tfLiteContext,
530 tfLiteNode,
531 nodeIndex,
532 kTfLiteBuiltinDepthToSpace);
533 case kTfLiteBuiltinDepthwiseConv2d:
534 return VisitConvolutionOperator(delegateData,
535 tfLiteContext,
536 tfLiteNode,
537 nodeIndex,
538 kTfLiteBuiltinDepthwiseConv2d);
539 case kTfLiteBuiltinDequantize:
540 return VisitDequantizeOperator(delegateData,
541 tfLiteContext,
542 tfLiteNode,
543 nodeIndex,
544 kTfLiteBuiltinDequantize);
545 case kTfLiteBuiltinDiv:
546 return VisitElementwiseBinaryOperator(delegateData,
547 tfLiteContext,
548 tfLiteNode,
549 nodeIndex,
550 kTfLiteBuiltinDiv);
551 case kTfLiteBuiltinElu:
552 return VisitActivationOperator(delegateData,
553 tfLiteContext,
554 tfLiteNode,
555 nodeIndex,
556 kTfLiteBuiltinElu);
557 case kTfLiteBuiltinEqual:
558 return VisitComparisonOperator(delegateData,
559 tfLiteContext,
560 tfLiteNode,
561 nodeIndex,
562 kTfLiteBuiltinEqual);
563 case kTfLiteBuiltinExp:
564 return VisitElementwiseUnaryOperator(delegateData,
565 tfLiteContext,
566 tfLiteNode,
567 nodeIndex,
568 armnn::UnaryOperation::Exp);
569 case kTfLiteBuiltinExpandDims:
570 return VisitExpandDimsOperator(delegateData,
571 tfLiteContext,
572 tfLiteNode,
573 nodeIndex,
574 kTfLiteBuiltinExpandDims);
575 case kTfLiteBuiltinFill:
576 return VisitFillOperator(delegateData,
577 tfLiteContext,
578 tfLiteNode,
579 nodeIndex,
580 kTfLiteBuiltinFill);
581 case kTfLiteBuiltinFloor:
582 return VisitFloorOperator(delegateData,
583 tfLiteContext,
584 tfLiteNode,
585 nodeIndex,
586 kTfLiteBuiltinFloor);
Jim Flynn4b2f3472021-10-13 21:20:07 +0100587 case kTfLiteBuiltinFloorDiv:
588 return VisitElementwiseBinaryOperator(delegateData,
589 tfLiteContext,
590 tfLiteNode,
591 nodeIndex,
592 kTfLiteBuiltinFloorDiv);
Sadik Armagan62483be2020-10-23 17:14:43 +0100593 case kTfLiteBuiltinFullyConnected:
594 return VisitFullyConnectedOperator(delegateData,
595 tfLiteContext,
596 tfLiteNode,
597 nodeIndex,
598 kTfLiteBuiltinFullyConnected);
599 case kTfLiteBuiltinGather:
600 return VisitGatherOperator(delegateData,
601 tfLiteContext,
602 tfLiteNode,
603 nodeIndex,
604 kTfLiteBuiltinGather);
605 case kTfLiteBuiltinGatherNd:
606 return VisitGatherOperator(delegateData,
607 tfLiteContext,
608 tfLiteNode,
609 nodeIndex,
610 kTfLiteBuiltinGatherNd);
611 case kTfLiteBuiltinGreater:
612 return VisitComparisonOperator(delegateData,
613 tfLiteContext,
614 tfLiteNode,
615 nodeIndex,
616 kTfLiteBuiltinGreater);
617 case kTfLiteBuiltinGreaterEqual:
618 return VisitComparisonOperator(delegateData,
619 tfLiteContext,
620 tfLiteNode,
621 nodeIndex,
622 kTfLiteBuiltinGreaterEqual);
623 case kTfLiteBuiltinHardSwish:
624 return VisitActivationOperator(delegateData,
625 tfLiteContext,
626 tfLiteNode,
627 nodeIndex,
628 kTfLiteBuiltinHardSwish);
629 case kTfLiteBuiltinL2Normalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000630 return VisitL2NormalizationOperator(delegateData,
631 tfLiteContext,
632 tfLiteNode,
633 nodeIndex,
634 kTfLiteBuiltinL2Normalization);
Sadik Armagan62483be2020-10-23 17:14:43 +0100635 case kTfLiteBuiltinL2Pool2d:
636 return VisitPoolingOperator(delegateData,
637 tfLiteContext,
638 tfLiteNode,
639 nodeIndex,
640 kTfLiteBuiltinL2Pool2d);
641 case kTfLiteBuiltinLess:
642 return VisitComparisonOperator(delegateData,
643 tfLiteContext,
644 tfLiteNode,
645 nodeIndex,
646 kTfLiteBuiltinLess);
647 case kTfLiteBuiltinLessEqual:
648 return VisitComparisonOperator(delegateData,
649 tfLiteContext,
650 tfLiteNode,
651 nodeIndex,
652 kTfLiteBuiltinLessEqual);
653 case kTfLiteBuiltinLocalResponseNormalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000654 return VisitLocalResponseNormalizationOperator(delegateData,
655 tfLiteContext,
656 tfLiteNode,
657 nodeIndex,
658 kTfLiteBuiltinLocalResponseNormalization);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000659 case kTfLiteBuiltinLogicalAnd:
660 return VisitLogicalBinaryOperator(delegateData,
661 tfLiteContext,
662 tfLiteNode,
663 nodeIndex,
664 kTfLiteBuiltinLogicalAnd,
665 armnn::LogicalBinaryOperation::LogicalAnd);
666 case kTfLiteBuiltinLogicalNot:
667 return VisitElementwiseUnaryOperator(delegateData,
668 tfLiteContext,
669 tfLiteNode,
670 nodeIndex,
671 armnn::UnaryOperation::LogicalNot);
672 case kTfLiteBuiltinLogicalOr:
673 return VisitLogicalBinaryOperator(delegateData,
674 tfLiteContext,
675 tfLiteNode,
676 nodeIndex,
677 kTfLiteBuiltinLogicalOr,
678 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100679 case kTfLiteBuiltinLogistic:
680 return VisitActivationOperator(delegateData,
681 tfLiteContext,
682 tfLiteNode,
683 nodeIndex,
684 kTfLiteBuiltinLogistic);
685 case kTfLiteBuiltinLogSoftmax:
686 return VisitSoftmaxOperator(delegateData,
687 tfLiteContext,
688 tfLiteNode,
689 nodeIndex,
690 kTfLiteBuiltinLogSoftmax);
691 case kTfLiteBuiltinLstm:
692 return VisitLstmOperator(delegateData,
693 tfLiteContext,
694 tfLiteNode,
695 nodeIndex,
696 kTfLiteBuiltinLstm);
697 case kTfLiteBuiltinMaxPool2d:
698 return VisitPoolingOperator(delegateData,
699 tfLiteContext,
700 tfLiteNode,
701 nodeIndex,
702 kTfLiteBuiltinMaxPool2d);
703 case kTfLiteBuiltinMaximum:
704 return VisitElementwiseBinaryOperator(delegateData,
705 tfLiteContext,
706 tfLiteNode,
707 nodeIndex,
708 kTfLiteBuiltinMaximum);
709 case kTfLiteBuiltinMean:
710 return VisitControlOperator(delegateData,
711 tfLiteContext,
712 tfLiteNode,
713 nodeIndex,
714 kTfLiteBuiltinMean);
715 case kTfLiteBuiltinMinimum:
716 return VisitElementwiseBinaryOperator(delegateData,
717 tfLiteContext,
718 tfLiteNode,
719 nodeIndex,
720 kTfLiteBuiltinMinimum);
Matthew Sloyanaf3a4ef2021-10-22 15:48:12 +0100721 case kTfLiteBuiltinMirrorPad:
722 return VisitPadOperator(delegateData,
723 tfLiteContext,
724 tfLiteNode,
725 nodeIndex,
726 kTfLiteBuiltinMirrorPad);
Sadik Armagan62483be2020-10-23 17:14:43 +0100727 case kTfLiteBuiltinMul:
728 return VisitElementwiseBinaryOperator(delegateData,
729 tfLiteContext,
730 tfLiteNode,
731 nodeIndex,
732 kTfLiteBuiltinMul);
733 case kTfLiteBuiltinNeg:
734 return VisitElementwiseUnaryOperator(delegateData,
735 tfLiteContext,
736 tfLiteNode,
737 nodeIndex,
738 armnn::UnaryOperation::Neg);
739 case kTfLiteBuiltinNotEqual:
740 return VisitComparisonOperator(delegateData,
741 tfLiteContext,
742 tfLiteNode,
743 nodeIndex,
744 kTfLiteBuiltinNotEqual);
Matthew Sloyana7a12f52021-05-06 10:05:28 +0100745 case kTfLiteBuiltinPack:
746 return VisitPackOperator(delegateData,
747 tfLiteContext,
748 tfLiteNode,
749 nodeIndex,
750 kTfLiteBuiltinPack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100751 case kTfLiteBuiltinPad:
752 return VisitPadOperator(delegateData,
753 tfLiteContext,
754 tfLiteNode,
755 nodeIndex,
756 kTfLiteBuiltinPad);
757 case kTfLiteBuiltinPadv2:
758 return VisitPadOperator(delegateData,
759 tfLiteContext,
760 tfLiteNode,
761 nodeIndex,
762 kTfLiteBuiltinPadv2);
763 case kTfLiteBuiltinPrelu:
James Conroy39825482021-05-27 17:44:50 +0100764 return VisitPreluOperator(delegateData,
765 tfLiteContext,
766 tfLiteNode,
767 nodeIndex,
768 kTfLiteBuiltinPrelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100769 case kTfLiteBuiltinQuantize:
770 return VisitQuantizeOperator(delegateData,
771 tfLiteContext,
772 tfLiteNode,
773 nodeIndex,
774 kTfLiteBuiltinQuantize);
775 case kTfLiteBuiltinRank:
776 return VisitControlOperator(delegateData,
777 tfLiteContext,
778 tfLiteNode,
779 nodeIndex,
780 kTfLiteBuiltinRank);
Sadik Armagana2747482021-02-09 10:28:54 +0000781 case kTfLiteBuiltinReduceMax:
782 return VisitReduceOperator(delegateData,
783 tfLiteContext,
784 tfLiteNode,
785 nodeIndex,
786 kTfLiteBuiltinReduceMax);
787 case kTfLiteBuiltinReduceMin:
788 return VisitReduceOperator(delegateData,
789 tfLiteContext,
790 tfLiteNode,
791 nodeIndex,
792 kTfLiteBuiltinReduceMin);
Teresa Charlin4e3e8312021-08-05 12:34:37 +0100793 case kTfLiteBuiltinReduceProd:
794 return VisitReduceOperator(delegateData,
795 tfLiteContext,
796 tfLiteNode,
797 nodeIndex,
798 kTfLiteBuiltinReduceProd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100799 case kTfLiteBuiltinRelu:
800 return VisitActivationOperator(delegateData,
801 tfLiteContext,
802 tfLiteNode,
803 nodeIndex,
804 kTfLiteBuiltinRelu);
805 case kTfLiteBuiltinReluN1To1:
806 return VisitActivationOperator(delegateData,
807 tfLiteContext,
808 tfLiteNode,
809 nodeIndex,
810 kTfLiteBuiltinReluN1To1);
811 case kTfLiteBuiltinRelu6:
812 return VisitActivationOperator(delegateData,
813 tfLiteContext,
814 tfLiteNode,
815 nodeIndex,
816 kTfLiteBuiltinRelu6);
817 case kTfLiteBuiltinReshape:
818 return VisitReshapeOperator(delegateData,
819 tfLiteContext,
820 tfLiteNode,
821 nodeIndex,
822 kTfLiteBuiltinReshape);
823 case kTfLiteBuiltinResizeBilinear:
824 return VisitResizeOperator(delegateData,
825 tfLiteContext,
826 tfLiteNode,
827 nodeIndex,
828 kTfLiteBuiltinResizeBilinear);
829 case kTfLiteBuiltinResizeNearestNeighbor:
830 return VisitResizeOperator(delegateData,
831 tfLiteContext,
832 tfLiteNode,
833 nodeIndex,
834 kTfLiteBuiltinResizeNearestNeighbor);
835 case kTfLiteBuiltinRsqrt:
836 return VisitElementwiseUnaryOperator(delegateData,
837 tfLiteContext,
838 tfLiteNode,
839 nodeIndex,
840 armnn::UnaryOperation::Rsqrt);
Keith Davis0176fd82021-06-01 17:36:32 +0100841 case kTfLiteBuiltinShape:
842 return VisitShapeOperator(delegateData,
843 tfLiteContext,
844 tfLiteNode,
845 nodeIndex,
846 kTfLiteBuiltinShape);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +0000847 case kTfLiteBuiltinSplit:
848 return VisitSplitOperator(delegateData,
849 tfLiteContext,
850 tfLiteNode,
851 nodeIndex,
852 kTfLiteBuiltinSplit);
853 case kTfLiteBuiltinSplitV:
854 return VisitSplitVOperator(delegateData,
855 tfLiteContext,
856 tfLiteNode,
857 nodeIndex,
858 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +0100859 case kTfLiteBuiltinSqrt:
860 return VisitElementwiseUnaryOperator(delegateData,
861 tfLiteContext,
862 tfLiteNode,
863 nodeIndex,
864 armnn::UnaryOperation::Sqrt);
865 case kTfLiteBuiltinSqueeze:
866 return VisitSqueezeOperator(delegateData,
867 tfLiteContext,
868 tfLiteNode,
869 nodeIndex,
870 kTfLiteBuiltinSqueeze);
871 case kTfLiteBuiltinStridedSlice:
872 return VisitSliceOperator(delegateData,
873 tfLiteContext,
874 tfLiteNode,
875 nodeIndex,
876 kTfLiteBuiltinStridedSlice);
Sadik Armagana2747482021-02-09 10:28:54 +0000877 case kTfLiteBuiltinSum:
878 return VisitReduceOperator(delegateData,
879 tfLiteContext,
880 tfLiteNode,
881 nodeIndex,
882 kTfLiteBuiltinSum);
Sadik Armagan62483be2020-10-23 17:14:43 +0100883 case kTfLiteBuiltinTranspose:
884 return VisitTransposeOperator(delegateData,
885 tfLiteContext,
886 tfLiteNode,
887 nodeIndex,
888 kTfLiteBuiltinTranspose);
889 case kTfLiteBuiltinTransposeConv:
890 return VisitConvolutionOperator(delegateData,
891 tfLiteContext,
892 tfLiteNode,
893 nodeIndex,
894 kTfLiteBuiltinTransposeConv);
895 case kTfLiteBuiltinSoftmax:
896 return VisitSoftmaxOperator(delegateData,
897 tfLiteContext,
898 tfLiteNode,
899 nodeIndex,
900 kTfLiteBuiltinSoftmax);
901 case kTfLiteBuiltinSpaceToBatchNd:
902 return VisitSpaceToBatchNdOperator(delegateData,
903 tfLiteContext,
904 tfLiteNode,
905 nodeIndex,
906 kTfLiteBuiltinSpaceToBatchNd);
907 case kTfLiteBuiltinSpaceToDepth:
908 return VisitSpaceToDepthOperator(delegateData,
909 tfLiteContext,
910 tfLiteNode,
911 nodeIndex,
912 kTfLiteBuiltinSpaceToDepth);
913 case kTfLiteBuiltinSub:
914 return VisitElementwiseBinaryOperator(delegateData,
915 tfLiteContext,
916 tfLiteNode,
917 nodeIndex,
918 kTfLiteBuiltinSub);
919 case kTfLiteBuiltinTanh:
920 return VisitActivationOperator(delegateData,
921 tfLiteContext,
922 tfLiteNode,
923 nodeIndex,
924 kTfLiteBuiltinTanh);
Narumol Prangnawarat7684b182021-08-12 14:48:15 +0100925 case kTfLiteBuiltinUnidirectionalSequenceLstm:
926 return VisitUnidirectionalSequenceLstmOperator(delegateData,
927 tfLiteContext,
928 tfLiteNode,
929 nodeIndex,
930 kTfLiteBuiltinUnidirectionalSequenceLstm);
Kevin May8ab2d7a2021-05-07 09:32:51 +0100931 case kTfLiteBuiltinUnpack:
932 return VisitUnpackOperator(delegateData,
933 tfLiteContext,
934 tfLiteNode,
935 nodeIndex,
936 kTfLiteBuiltinUnpack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100937 default:
938 return kTfLiteError;
939 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100940}
941
942} // armnnDelegate namespace