blob: 0069b4fe0ee5d7d6d665038961f52e273e30d821 [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];
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100425 armnn::TensorInfo inputTensorInfo = inputBinding.second;
426 inputTensorInfo.SetConstant(true);
427 const armnn::ConstTensor inputTensor(inputTensorInfo, tensor->data.data);
Sadik Armagan62483be2020-10-23 17:14:43 +0100428 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100429
Sadik Armagan62483be2020-10-23 17:14:43 +0100430 ++inputIndex;
431 }
432 }
433
434 // Prepare outputs
435 armnn::OutputTensors outputTensors;
436 size_t outputIndex = 0;
437 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
438 {
439 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
440 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
441 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
442 outputTensors.emplace_back(outputIdx, outputTensor);
443
444 ++outputIndex;
445 }
446
447 // Run graph
448 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
Colm Donelan45142282021-10-21 23:39:52 +0100449 // The delegate holds its own Arm NN runtime so this is our last chance to print internal profiling data.
450 std::shared_ptr<armnn::IProfiler> profiler = m_Runtime->GetProfiler(m_NetworkId);
451 if (profiler && profiler->IsProfilingEnabled())
452 {
453 profiler->Print(std::cout);
454 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100455 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100456}
457
Sadik Armagan62483be2020-10-23 17:14:43 +0100458TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100459 TfLiteContext* tfLiteContext,
460 TfLiteRegistration* tfLiteRegistration,
461 TfLiteNode* tfLiteNode,
462 int nodeIndex)
463{
Sadik Armagan62483be2020-10-23 17:14:43 +0100464 switch (tfLiteRegistration->builtin_code)
465 {
466 case kTfLiteBuiltinAbs:
467 return VisitElementwiseUnaryOperator(delegateData,
468 tfLiteContext,
469 tfLiteNode,
470 nodeIndex,
471 armnn::UnaryOperation::Abs);
472 case kTfLiteBuiltinAdd:
473 return VisitElementwiseBinaryOperator(delegateData,
474 tfLiteContext,
475 tfLiteNode,
476 nodeIndex,
477 kTfLiteBuiltinAdd);
478 case kTfLiteBuiltinArgMax:
479 return VisitArgMinMaxOperator(delegateData,
480 tfLiteContext,
481 tfLiteNode,
482 nodeIndex,
483 kTfLiteBuiltinArgMax);
484 case kTfLiteBuiltinArgMin:
485 return VisitArgMinMaxOperator(delegateData,
486 tfLiteContext,
487 tfLiteNode,
488 nodeIndex,
489 kTfLiteBuiltinArgMin);
490 case kTfLiteBuiltinAveragePool2d:
491 return VisitPoolingOperator(delegateData,
492 tfLiteContext,
493 tfLiteNode,
494 nodeIndex,
495 kTfLiteBuiltinAveragePool2d);
496 case kTfLiteBuiltinBatchToSpaceNd:
497 return VisitBatchToSpaceNdOperator(delegateData,
498 tfLiteContext,
499 tfLiteNode,
500 nodeIndex,
501 kTfLiteBuiltinBatchToSpaceNd);
Sadik Armagan937565b2021-04-21 14:03:28 +0100502 case kTfLiteBuiltinCast:
503 return VisitCastOperator(delegateData,
504 tfLiteContext,
505 tfLiteNode,
506 nodeIndex,
507 kTfLiteBuiltinCast);
Sadik Armagan62483be2020-10-23 17:14:43 +0100508 case kTfLiteBuiltinConcatenation:
509 return VisitControlOperator(delegateData,
510 tfLiteContext,
511 tfLiteNode,
512 nodeIndex,
513 kTfLiteBuiltinConcatenation);
514 case kTfLiteBuiltinConv2d:
515 return VisitConvolutionOperator(delegateData,
516 tfLiteContext,
517 tfLiteNode,
518 nodeIndex,
519 kTfLiteBuiltinConv2d);
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100520// Conv3d is only correctly supported for external delegates from TF Lite v2.6, as there was a breaking bug in v2.5.
521#if defined(ARMNN_POST_TFLITE_2_5)
522 case kTfLiteBuiltinConv3d:
523 return VisitConvolutionOperator(delegateData,
524 tfLiteContext,
525 tfLiteNode,
526 nodeIndex,
527 kTfLiteBuiltinConv3d);
528#endif
Sadik Armagan62483be2020-10-23 17:14:43 +0100529 case kTfLiteBuiltinDepthToSpace:
530 return VisitDepthToSpaceOperator(delegateData,
531 tfLiteContext,
532 tfLiteNode,
533 nodeIndex,
534 kTfLiteBuiltinDepthToSpace);
535 case kTfLiteBuiltinDepthwiseConv2d:
536 return VisitConvolutionOperator(delegateData,
537 tfLiteContext,
538 tfLiteNode,
539 nodeIndex,
540 kTfLiteBuiltinDepthwiseConv2d);
541 case kTfLiteBuiltinDequantize:
542 return VisitDequantizeOperator(delegateData,
543 tfLiteContext,
544 tfLiteNode,
545 nodeIndex,
546 kTfLiteBuiltinDequantize);
547 case kTfLiteBuiltinDiv:
548 return VisitElementwiseBinaryOperator(delegateData,
549 tfLiteContext,
550 tfLiteNode,
551 nodeIndex,
552 kTfLiteBuiltinDiv);
553 case kTfLiteBuiltinElu:
554 return VisitActivationOperator(delegateData,
555 tfLiteContext,
556 tfLiteNode,
557 nodeIndex,
558 kTfLiteBuiltinElu);
559 case kTfLiteBuiltinEqual:
560 return VisitComparisonOperator(delegateData,
561 tfLiteContext,
562 tfLiteNode,
563 nodeIndex,
564 kTfLiteBuiltinEqual);
565 case kTfLiteBuiltinExp:
566 return VisitElementwiseUnaryOperator(delegateData,
567 tfLiteContext,
568 tfLiteNode,
569 nodeIndex,
570 armnn::UnaryOperation::Exp);
571 case kTfLiteBuiltinExpandDims:
572 return VisitExpandDimsOperator(delegateData,
573 tfLiteContext,
574 tfLiteNode,
575 nodeIndex,
576 kTfLiteBuiltinExpandDims);
577 case kTfLiteBuiltinFill:
578 return VisitFillOperator(delegateData,
579 tfLiteContext,
580 tfLiteNode,
581 nodeIndex,
582 kTfLiteBuiltinFill);
583 case kTfLiteBuiltinFloor:
584 return VisitFloorOperator(delegateData,
585 tfLiteContext,
586 tfLiteNode,
587 nodeIndex,
588 kTfLiteBuiltinFloor);
Jim Flynn4b2f3472021-10-13 21:20:07 +0100589 case kTfLiteBuiltinFloorDiv:
590 return VisitElementwiseBinaryOperator(delegateData,
591 tfLiteContext,
592 tfLiteNode,
593 nodeIndex,
594 kTfLiteBuiltinFloorDiv);
Sadik Armagan62483be2020-10-23 17:14:43 +0100595 case kTfLiteBuiltinFullyConnected:
596 return VisitFullyConnectedOperator(delegateData,
597 tfLiteContext,
598 tfLiteNode,
599 nodeIndex,
600 kTfLiteBuiltinFullyConnected);
601 case kTfLiteBuiltinGather:
602 return VisitGatherOperator(delegateData,
603 tfLiteContext,
604 tfLiteNode,
605 nodeIndex,
606 kTfLiteBuiltinGather);
607 case kTfLiteBuiltinGatherNd:
608 return VisitGatherOperator(delegateData,
609 tfLiteContext,
610 tfLiteNode,
611 nodeIndex,
612 kTfLiteBuiltinGatherNd);
613 case kTfLiteBuiltinGreater:
614 return VisitComparisonOperator(delegateData,
615 tfLiteContext,
616 tfLiteNode,
617 nodeIndex,
618 kTfLiteBuiltinGreater);
619 case kTfLiteBuiltinGreaterEqual:
620 return VisitComparisonOperator(delegateData,
621 tfLiteContext,
622 tfLiteNode,
623 nodeIndex,
624 kTfLiteBuiltinGreaterEqual);
625 case kTfLiteBuiltinHardSwish:
626 return VisitActivationOperator(delegateData,
627 tfLiteContext,
628 tfLiteNode,
629 nodeIndex,
630 kTfLiteBuiltinHardSwish);
631 case kTfLiteBuiltinL2Normalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000632 return VisitL2NormalizationOperator(delegateData,
633 tfLiteContext,
634 tfLiteNode,
635 nodeIndex,
636 kTfLiteBuiltinL2Normalization);
Sadik Armagan62483be2020-10-23 17:14:43 +0100637 case kTfLiteBuiltinL2Pool2d:
638 return VisitPoolingOperator(delegateData,
639 tfLiteContext,
640 tfLiteNode,
641 nodeIndex,
642 kTfLiteBuiltinL2Pool2d);
643 case kTfLiteBuiltinLess:
644 return VisitComparisonOperator(delegateData,
645 tfLiteContext,
646 tfLiteNode,
647 nodeIndex,
648 kTfLiteBuiltinLess);
649 case kTfLiteBuiltinLessEqual:
650 return VisitComparisonOperator(delegateData,
651 tfLiteContext,
652 tfLiteNode,
653 nodeIndex,
654 kTfLiteBuiltinLessEqual);
655 case kTfLiteBuiltinLocalResponseNormalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000656 return VisitLocalResponseNormalizationOperator(delegateData,
657 tfLiteContext,
658 tfLiteNode,
659 nodeIndex,
660 kTfLiteBuiltinLocalResponseNormalization);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000661 case kTfLiteBuiltinLogicalAnd:
662 return VisitLogicalBinaryOperator(delegateData,
663 tfLiteContext,
664 tfLiteNode,
665 nodeIndex,
666 kTfLiteBuiltinLogicalAnd,
667 armnn::LogicalBinaryOperation::LogicalAnd);
668 case kTfLiteBuiltinLogicalNot:
669 return VisitElementwiseUnaryOperator(delegateData,
670 tfLiteContext,
671 tfLiteNode,
672 nodeIndex,
673 armnn::UnaryOperation::LogicalNot);
674 case kTfLiteBuiltinLogicalOr:
675 return VisitLogicalBinaryOperator(delegateData,
676 tfLiteContext,
677 tfLiteNode,
678 nodeIndex,
679 kTfLiteBuiltinLogicalOr,
680 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100681 case kTfLiteBuiltinLogistic:
682 return VisitActivationOperator(delegateData,
683 tfLiteContext,
684 tfLiteNode,
685 nodeIndex,
686 kTfLiteBuiltinLogistic);
687 case kTfLiteBuiltinLogSoftmax:
688 return VisitSoftmaxOperator(delegateData,
689 tfLiteContext,
690 tfLiteNode,
691 nodeIndex,
692 kTfLiteBuiltinLogSoftmax);
693 case kTfLiteBuiltinLstm:
694 return VisitLstmOperator(delegateData,
695 tfLiteContext,
696 tfLiteNode,
697 nodeIndex,
698 kTfLiteBuiltinLstm);
699 case kTfLiteBuiltinMaxPool2d:
700 return VisitPoolingOperator(delegateData,
701 tfLiteContext,
702 tfLiteNode,
703 nodeIndex,
704 kTfLiteBuiltinMaxPool2d);
705 case kTfLiteBuiltinMaximum:
706 return VisitElementwiseBinaryOperator(delegateData,
707 tfLiteContext,
708 tfLiteNode,
709 nodeIndex,
710 kTfLiteBuiltinMaximum);
711 case kTfLiteBuiltinMean:
712 return VisitControlOperator(delegateData,
713 tfLiteContext,
714 tfLiteNode,
715 nodeIndex,
716 kTfLiteBuiltinMean);
717 case kTfLiteBuiltinMinimum:
718 return VisitElementwiseBinaryOperator(delegateData,
719 tfLiteContext,
720 tfLiteNode,
721 nodeIndex,
722 kTfLiteBuiltinMinimum);
Matthew Sloyanaf3a4ef2021-10-22 15:48:12 +0100723 case kTfLiteBuiltinMirrorPad:
724 return VisitPadOperator(delegateData,
725 tfLiteContext,
726 tfLiteNode,
727 nodeIndex,
728 kTfLiteBuiltinMirrorPad);
Sadik Armagan62483be2020-10-23 17:14:43 +0100729 case kTfLiteBuiltinMul:
730 return VisitElementwiseBinaryOperator(delegateData,
731 tfLiteContext,
732 tfLiteNode,
733 nodeIndex,
734 kTfLiteBuiltinMul);
735 case kTfLiteBuiltinNeg:
736 return VisitElementwiseUnaryOperator(delegateData,
737 tfLiteContext,
738 tfLiteNode,
739 nodeIndex,
740 armnn::UnaryOperation::Neg);
741 case kTfLiteBuiltinNotEqual:
742 return VisitComparisonOperator(delegateData,
743 tfLiteContext,
744 tfLiteNode,
745 nodeIndex,
746 kTfLiteBuiltinNotEqual);
Matthew Sloyana7a12f52021-05-06 10:05:28 +0100747 case kTfLiteBuiltinPack:
748 return VisitPackOperator(delegateData,
749 tfLiteContext,
750 tfLiteNode,
751 nodeIndex,
752 kTfLiteBuiltinPack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100753 case kTfLiteBuiltinPad:
754 return VisitPadOperator(delegateData,
755 tfLiteContext,
756 tfLiteNode,
757 nodeIndex,
758 kTfLiteBuiltinPad);
759 case kTfLiteBuiltinPadv2:
760 return VisitPadOperator(delegateData,
761 tfLiteContext,
762 tfLiteNode,
763 nodeIndex,
764 kTfLiteBuiltinPadv2);
765 case kTfLiteBuiltinPrelu:
James Conroy39825482021-05-27 17:44:50 +0100766 return VisitPreluOperator(delegateData,
767 tfLiteContext,
768 tfLiteNode,
769 nodeIndex,
770 kTfLiteBuiltinPrelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100771 case kTfLiteBuiltinQuantize:
772 return VisitQuantizeOperator(delegateData,
773 tfLiteContext,
774 tfLiteNode,
775 nodeIndex,
776 kTfLiteBuiltinQuantize);
777 case kTfLiteBuiltinRank:
778 return VisitControlOperator(delegateData,
779 tfLiteContext,
780 tfLiteNode,
781 nodeIndex,
782 kTfLiteBuiltinRank);
Sadik Armagana2747482021-02-09 10:28:54 +0000783 case kTfLiteBuiltinReduceMax:
784 return VisitReduceOperator(delegateData,
785 tfLiteContext,
786 tfLiteNode,
787 nodeIndex,
788 kTfLiteBuiltinReduceMax);
789 case kTfLiteBuiltinReduceMin:
790 return VisitReduceOperator(delegateData,
791 tfLiteContext,
792 tfLiteNode,
793 nodeIndex,
794 kTfLiteBuiltinReduceMin);
Teresa Charlin4e3e8312021-08-05 12:34:37 +0100795 case kTfLiteBuiltinReduceProd:
796 return VisitReduceOperator(delegateData,
797 tfLiteContext,
798 tfLiteNode,
799 nodeIndex,
800 kTfLiteBuiltinReduceProd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100801 case kTfLiteBuiltinRelu:
802 return VisitActivationOperator(delegateData,
803 tfLiteContext,
804 tfLiteNode,
805 nodeIndex,
806 kTfLiteBuiltinRelu);
807 case kTfLiteBuiltinReluN1To1:
808 return VisitActivationOperator(delegateData,
809 tfLiteContext,
810 tfLiteNode,
811 nodeIndex,
812 kTfLiteBuiltinReluN1To1);
813 case kTfLiteBuiltinRelu6:
814 return VisitActivationOperator(delegateData,
815 tfLiteContext,
816 tfLiteNode,
817 nodeIndex,
818 kTfLiteBuiltinRelu6);
819 case kTfLiteBuiltinReshape:
820 return VisitReshapeOperator(delegateData,
821 tfLiteContext,
822 tfLiteNode,
823 nodeIndex,
824 kTfLiteBuiltinReshape);
825 case kTfLiteBuiltinResizeBilinear:
826 return VisitResizeOperator(delegateData,
827 tfLiteContext,
828 tfLiteNode,
829 nodeIndex,
830 kTfLiteBuiltinResizeBilinear);
831 case kTfLiteBuiltinResizeNearestNeighbor:
832 return VisitResizeOperator(delegateData,
833 tfLiteContext,
834 tfLiteNode,
835 nodeIndex,
836 kTfLiteBuiltinResizeNearestNeighbor);
837 case kTfLiteBuiltinRsqrt:
838 return VisitElementwiseUnaryOperator(delegateData,
839 tfLiteContext,
840 tfLiteNode,
841 nodeIndex,
842 armnn::UnaryOperation::Rsqrt);
Keith Davis0176fd82021-06-01 17:36:32 +0100843 case kTfLiteBuiltinShape:
844 return VisitShapeOperator(delegateData,
845 tfLiteContext,
846 tfLiteNode,
847 nodeIndex,
848 kTfLiteBuiltinShape);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +0000849 case kTfLiteBuiltinSplit:
850 return VisitSplitOperator(delegateData,
851 tfLiteContext,
852 tfLiteNode,
853 nodeIndex,
854 kTfLiteBuiltinSplit);
855 case kTfLiteBuiltinSplitV:
856 return VisitSplitVOperator(delegateData,
857 tfLiteContext,
858 tfLiteNode,
859 nodeIndex,
860 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +0100861 case kTfLiteBuiltinSqrt:
862 return VisitElementwiseUnaryOperator(delegateData,
863 tfLiteContext,
864 tfLiteNode,
865 nodeIndex,
866 armnn::UnaryOperation::Sqrt);
867 case kTfLiteBuiltinSqueeze:
868 return VisitSqueezeOperator(delegateData,
869 tfLiteContext,
870 tfLiteNode,
871 nodeIndex,
872 kTfLiteBuiltinSqueeze);
873 case kTfLiteBuiltinStridedSlice:
874 return VisitSliceOperator(delegateData,
875 tfLiteContext,
876 tfLiteNode,
877 nodeIndex,
878 kTfLiteBuiltinStridedSlice);
Sadik Armagana2747482021-02-09 10:28:54 +0000879 case kTfLiteBuiltinSum:
880 return VisitReduceOperator(delegateData,
881 tfLiteContext,
882 tfLiteNode,
883 nodeIndex,
884 kTfLiteBuiltinSum);
Sadik Armagan62483be2020-10-23 17:14:43 +0100885 case kTfLiteBuiltinTranspose:
886 return VisitTransposeOperator(delegateData,
887 tfLiteContext,
888 tfLiteNode,
889 nodeIndex,
890 kTfLiteBuiltinTranspose);
891 case kTfLiteBuiltinTransposeConv:
892 return VisitConvolutionOperator(delegateData,
893 tfLiteContext,
894 tfLiteNode,
895 nodeIndex,
896 kTfLiteBuiltinTransposeConv);
897 case kTfLiteBuiltinSoftmax:
898 return VisitSoftmaxOperator(delegateData,
899 tfLiteContext,
900 tfLiteNode,
901 nodeIndex,
902 kTfLiteBuiltinSoftmax);
903 case kTfLiteBuiltinSpaceToBatchNd:
904 return VisitSpaceToBatchNdOperator(delegateData,
905 tfLiteContext,
906 tfLiteNode,
907 nodeIndex,
908 kTfLiteBuiltinSpaceToBatchNd);
909 case kTfLiteBuiltinSpaceToDepth:
910 return VisitSpaceToDepthOperator(delegateData,
911 tfLiteContext,
912 tfLiteNode,
913 nodeIndex,
914 kTfLiteBuiltinSpaceToDepth);
915 case kTfLiteBuiltinSub:
916 return VisitElementwiseBinaryOperator(delegateData,
917 tfLiteContext,
918 tfLiteNode,
919 nodeIndex,
920 kTfLiteBuiltinSub);
921 case kTfLiteBuiltinTanh:
922 return VisitActivationOperator(delegateData,
923 tfLiteContext,
924 tfLiteNode,
925 nodeIndex,
926 kTfLiteBuiltinTanh);
Narumol Prangnawarat7684b182021-08-12 14:48:15 +0100927 case kTfLiteBuiltinUnidirectionalSequenceLstm:
928 return VisitUnidirectionalSequenceLstmOperator(delegateData,
929 tfLiteContext,
930 tfLiteNode,
931 nodeIndex,
932 kTfLiteBuiltinUnidirectionalSequenceLstm);
Kevin May8ab2d7a2021-05-07 09:32:51 +0100933 case kTfLiteBuiltinUnpack:
934 return VisitUnpackOperator(delegateData,
935 tfLiteContext,
936 tfLiteNode,
937 nodeIndex,
938 kTfLiteBuiltinUnpack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100939 default:
940 return kTfLiteError;
941 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100942}
943
944} // armnnDelegate namespace