blob: b2ad16051ffb9b618acd73318bf73b54e5e8f1fb [file] [log] [blame]
Sadik Armagan3c24f432020-10-19 17:35:30 +01001//
Ryan OShead21abaf2022-06-10 14:49:11 +01002// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
Sadik Armagan3c24f432020-10-19 17:35:30 +01003// 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"
Ryan OShea49ed0df2022-09-21 16:09:41 +010012#include "BatchMatMul.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010013#include "BatchSpace.hpp"
14#include "Comparison.hpp"
15#include "Convolution.hpp"
16#include "Control.hpp"
17#include "ElementwiseBinary.hpp"
18#include "ElementwiseUnary.hpp"
19#include "Fill.hpp"
20#include "FullyConnected.hpp"
21#include "Gather.hpp"
Teresa Charlind5c0ed22022-04-25 18:23:41 +010022#include "GatherNd.hpp"
Matthew Sloyanc8eb9552020-11-26 10:54:22 +000023#include "LogicalBinary.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010024#include "Lstm.hpp"
25#include "Normalization.hpp"
Matthew Sloyana7a12f52021-05-06 10:05:28 +010026#include "Pack.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010027#include "Pad.hpp"
28#include "Pooling.hpp"
James Conroy39825482021-05-27 17:44:50 +010029#include "Prelu.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010030#include "Quantization.hpp"
31#include "Redefine.hpp"
Sadik Armagana2747482021-02-09 10:28:54 +000032#include "Reduce.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010033#include "Resize.hpp"
34#include "Round.hpp"
Keith Davis0176fd82021-06-01 17:36:32 +010035#include "Shape.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010036#include "Slice.hpp"
37#include "Softmax.hpp"
38#include "SpaceDepth.hpp"
Sadik Armagan34fa1bd2020-11-27 12:40:52 +000039#include "Split.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010040#include "Transpose.hpp"
Narumol Prangnawarat7684b182021-08-12 14:48:15 +010041#include "UnidirectionalSequenceLstm.hpp"
Kevin May8ab2d7a2021-05-07 09:32:51 +010042#include "Unpack.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010043
Colm Donelan3e32a872021-10-04 22:55:37 +010044#include <armnnUtils/Filesystem.hpp>
Jan Eilers17d34da2021-12-08 16:15:12 +000045#include <armnn/utility/Timer.hpp>
Sadik Armagan62483be2020-10-23 17:14:43 +010046#include <flatbuffers/flatbuffers.h>
47#include <tensorflow/lite/context_util.h>
Jim Flynn4b2f3472021-10-13 21:20:07 +010048#include <tensorflow/lite/schema/schema_generated.h>
Sadik Armagan62483be2020-10-23 17:14:43 +010049
Sadik Armagan3c24f432020-10-19 17:35:30 +010050#include <algorithm>
Matthew Sloyanac001ee2021-02-03 10:43:04 +000051#include <iostream>
Sadik Armagan62483be2020-10-23 17:14:43 +010052#include <sstream>
Sadik Armagan3c24f432020-10-19 17:35:30 +010053
54namespace armnnDelegate
55{
56
Sadik Armagan62483be2020-10-23 17:14:43 +010057DelegateOptions TfLiteArmnnDelegateOptionsDefault()
58{
59 DelegateOptions options(armnn::Compute::CpuRef);
60 return options;
61}
62
63TfLiteDelegate* TfLiteArmnnDelegateCreate(armnnDelegate::DelegateOptions options)
64{
65 auto* armnnDelegate = new ::armnnDelegate::Delegate(options);
66 return armnnDelegate->GetDelegate();
67}
68
69void TfLiteArmnnDelegateDelete(TfLiteDelegate* tfLiteDelegate)
70{
71 if (tfLiteDelegate != nullptr)
72 {
73 delete static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_);
74 }
75}
76
77TfLiteStatus DoPrepare(TfLiteContext* tfLiteContext, TfLiteDelegate* tfLiteDelegate)
78{
79 TfLiteIntArray* supportedOperators =
80 static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_)->IdentifyOperatorsToDelegate(tfLiteContext);
81
82 // ArmNN Delegate Registration
83 static const TfLiteRegistration kArmnnSubgraphRegistration = {
84 // ArmnnSubgraph Init
85 .init = [](TfLiteContext* tfLiteContext, const char* buffer, size_t length) -> void* {
Finn Williams6f9f9902020-11-13 13:23:15 +000086 armnn::IgnoreUnused(length);
Sadik Armagan62483be2020-10-23 17:14:43 +010087 const TfLiteDelegateParams* parameters = reinterpret_cast<const TfLiteDelegateParams*>(buffer);
88
89 return static_cast<void*>(ArmnnSubgraph::Create(
90 tfLiteContext, parameters, static_cast<::armnnDelegate::Delegate*>(parameters->delegate->data_)));
91 },
92 // ArmnnSubgraph Free
93 .free = [](TfLiteContext* tfLiteContext, void* buffer) -> void {
Finn Williams6f9f9902020-11-13 13:23:15 +000094 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan62483be2020-10-23 17:14:43 +010095 if (buffer != nullptr)
96 {
97 delete static_cast<ArmnnSubgraph*>(buffer);
98 }
99 },
100 // ArmnnSubgraph Prepare
101 .prepare = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
102 if (tfLiteNode->user_data == nullptr)
103 {
104 return kTfLiteError;
105 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100106 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Prepare(tfLiteContext);
107 },
108 // ArmnnSubgraph Invoke
109 .invoke = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
110 if (tfLiteNode->user_data == nullptr)
111 {
112 return kTfLiteError;
113 }
114
115 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Invoke(tfLiteContext, tfLiteNode);
116 },
117
118 .profiling_string = nullptr,
119 .builtin_code = kTfLiteBuiltinDelegate,
120 .custom_name = "TfLiteArmNnDelegate",
121 .version = 1,
Colm Donelan718966f2022-10-10 10:06:12 +0100122 .registration_external = nullptr,
Sadik Armagan62483be2020-10-23 17:14:43 +0100123 };
124
125 const TfLiteStatus status =
126 tfLiteContext->ReplaceNodeSubsetsWithDelegateKernels(
127 tfLiteContext, kArmnnSubgraphRegistration, supportedOperators, tfLiteDelegate);
128
129 TfLiteIntArrayFree(supportedOperators);
130 return status;
131
132}
133
Sadik Armagan3c24f432020-10-19 17:35:30 +0100134Delegate::Delegate(armnnDelegate::DelegateOptions options)
135 : m_Runtime(nullptr, nullptr),
136 m_Options(std::move(options))
137{
Jan Eilers2cd18472020-12-15 10:42:38 +0000138 // Configures logging for ARMNN
139 if (options.IsLoggingEnabled())
140 {
141 armnn::ConfigureLogging(true, true, options.GetLoggingSeverity());
142 }
143
Sadik Armagan3c24f432020-10-19 17:35:30 +0100144 // Create ArmNN Runtime
Jan Eilersb1c62f12021-10-26 14:56:47 +0100145 m_Runtime = armnn::IRuntime::Create(options.GetRuntimeOptions());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100146
147 std::vector<armnn::BackendId> backends;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100148 if (m_Runtime)
149 {
150 const armnn::BackendIdSet supportedDevices = m_Runtime->GetDeviceSpec().GetSupportedBackends();
151 for (auto& backend : m_Options.GetBackends())
152 {
153 if (std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) == supportedDevices.cend())
154 {
Sadik Armagan0534e032020-10-27 17:30:18 +0000155 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100156 "TfLiteArmnnDelegate: Requested unknown backend %s", backend.Get().c_str());
157 }
158 else
159 {
160 backends.push_back(backend);
161 }
162 }
163 }
164
165 if (backends.empty())
166 {
167 // No known backend specified
168 throw armnn::InvalidArgumentException("TfLiteArmnnDelegate: No known backend specified.");
169 }
170 m_Options.SetBackends(backends);
171
172 TFLITE_LOG_PROD_ONCE(tflite::TFLITE_LOG_INFO, "TfLiteArmnnDelegate: Created TfLite ArmNN delegate.");
173}
174
Sadik Armagan62483be2020-10-23 17:14:43 +0100175TfLiteIntArray* Delegate::IdentifyOperatorsToDelegate(TfLiteContext* tfLiteContext)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100176{
177 TfLiteIntArray* executionPlan = nullptr;
178 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
179 {
180 TF_LITE_KERNEL_LOG(tfLiteContext, "TfLiteArmnnDelegate: Unable to get graph execution plan.");
181 return nullptr;
182 }
183
Sadik Armagan62483be2020-10-23 17:14:43 +0100184 // Delegate data with null network
185 DelegateData delegateData(m_Options.GetBackends());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100186
187 TfLiteIntArray* nodesToDelegate = TfLiteIntArrayCreate(executionPlan->size);
188 nodesToDelegate->size = 0;
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000189
190 std::set<int32_t> unsupportedOperators;
191
Sadik Armagan3c24f432020-10-19 17:35:30 +0100192 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
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000212 unsupportedOperators.insert(tfLiteRegistration->builtin_code);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100213 continue;
214 }
215
216 nodesToDelegate->data[nodesToDelegate->size++] = nodeIndex;
217 }
218
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000219 for (std::set<int32_t>::iterator it=unsupportedOperators.begin(); it!=unsupportedOperators.end(); ++it)
220 {
221 TF_LITE_KERNEL_LOG(tfLiteContext,
222 "Operator %s [%d] is not supported by armnn_delegate.",
223 tflite::EnumNameBuiltinOperator(tflite::BuiltinOperator(*it)),
224 *it);
225 }
226
Sadik Armaganca565c12022-08-16 12:17:24 +0100227 if (!unsupportedOperators.empty() && m_Options.TfLiteRuntimeFallbackDisabled())
228 {
229 std::stringstream exMessage;
230 exMessage << "TfLiteArmnnDelegate: There are unsupported operators in the model. ";
231 exMessage << "Not falling back to TfLite Runtime as fallback is disabled. ";
232 exMessage << "This should only be disabled under test conditions.";
233 throw armnn::Exception(exMessage.str());
234 }
235
Sadik Armagan62483be2020-10-23 17:14:43 +0100236 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100237 return nodesToDelegate;
238}
239
240TfLiteDelegate* Delegate::GetDelegate()
241{
242 return &m_Delegate;
243}
244
Matthew Sloyanac001ee2021-02-03 10:43:04 +0000245const std::string Delegate::GetVersion()
246{
247 return DELEGATE_VERSION;
248}
249
Sadik Armagan62483be2020-10-23 17:14:43 +0100250TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
251 TfLiteContext* tfLiteContext,
252 const TfLiteIntArray* inputs,
253 std::vector<armnn::BindingPointInfo>& inputBindings)
254{
Finn Williams6f9f9902020-11-13 13:23:15 +0000255 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100256 for (unsigned int i = 0; i < numInputs; ++i)
257 {
258 const int32_t tensorId = inputs->data[i];
259 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000260 // Do not create bindings for constant inputs
261 if (tensor.allocation_type == kTfLiteMmapRo)
262 {
263 continue;
264 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100265
266 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
267 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
268
269 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
270 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
271 outputSlot.SetTensorInfo(tensorInfo);
272
273 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000274 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100275
Sadik Armagan6e36a642020-11-10 21:18:41 +0000276 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100277 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000278
Sadik Armagan62483be2020-10-23 17:14:43 +0100279 return kTfLiteOk;
280}
281
282TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
283 TfLiteContext* tfLiteContext,
284 const TfLiteIntArray* outputs,
285 std::vector<armnn::BindingPointInfo>& outputBindings)
286{
Finn Williams6f9f9902020-11-13 13:23:15 +0000287 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100288 for (unsigned int i = 0; i < numOutputs; ++i)
289 {
290 const int32_t tensorId = outputs->data[i];
291 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
292
293 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
294 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
295
296 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Finn Williams6f9f9902020-11-13 13:23:15 +0000297 ARMNN_ASSERT(delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] != nullptr);
298 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100299 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
300 }
301
302 return kTfLiteOk;
303}
304
Sadik Armagan3c24f432020-10-19 17:35:30 +0100305ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
306 const TfLiteDelegateParams* parameters,
307 const Delegate* delegate)
308{
Jan Eilers17d34da2021-12-08 16:15:12 +0000309 const auto startTime = armnn::GetTimeNow();
310 ARMNN_LOG(info) << "ArmnnSubgraph creation";
311
Sadik Armagan3c24f432020-10-19 17:35:30 +0100312 TfLiteIntArray* executionPlan;
313 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
314 {
315 return nullptr;
316 }
317
Sadik Armagan62483be2020-10-23 17:14:43 +0100318 // Initialize DelegateData holds network and output slots information
319 DelegateData delegateData(delegate->m_Options.GetBackends());
320
321 // Build ArmNN Network
Mike Kelly80512b02022-05-16 23:10:42 +0100322 armnn::NetworkOptions networkOptions = delegate->m_Options.GetOptimizerOptions().m_ModelOptions;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100323 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100324 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100325
Sadik Armagan6e36a642020-11-10 21:18:41 +0000326 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
327
Sadik Armagan62483be2020-10-23 17:14:43 +0100328 std::vector<armnn::BindingPointInfo> inputBindings;
329 std::vector<armnn::BindingPointInfo> outputBindings;
330
331 // Add input layer
332 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
333 if (status != kTfLiteOk)
334 {
335 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
336 }
337
338 // Parse TfLite delegate nodes to ArmNN
Jan Eilers17d34da2021-12-08 16:15:12 +0000339 const auto parseStartTime = armnn::GetTimeNow();
Sadik Armagan3c24f432020-10-19 17:35:30 +0100340 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
341 {
342 const int nodeIndex = parameters->nodes_to_replace->data[i];
343
344 TfLiteNode* tfLiteNode = nullptr;
345 TfLiteRegistration* tfLiteRegistration = nullptr;
346 if (tfLiteContext->GetNodeAndRegistration(
347 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
348 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000349 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100350 }
351
Sadik Armagan62483be2020-10-23 17:14:43 +0100352 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100353 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000354 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100355 }
356 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000357 ARMNN_LOG(info) << "Parse nodes to ArmNN time: " << std::setprecision(2)
358 << std::fixed << armnn::GetTimeDuration(parseStartTime).count() << " ms";
Sadik Armagan3c24f432020-10-19 17:35:30 +0100359
Sadik Armagan62483be2020-10-23 17:14:43 +0100360 // Add Output layer
361 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
362 if (status != kTfLiteOk)
363 {
364 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
365 }
366
367 // Optimize ArmNN network
368 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
369 try
370 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000371 const auto optimizeStartTime = armnn::GetTimeNow();
Sadik Armagan6e36a642020-11-10 21:18:41 +0000372 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100373 delegate->m_Options.GetBackends(),
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000374 delegate->m_Runtime->GetDeviceSpec(),
375 delegate->m_Options.GetOptimizerOptions());
Jan Eilers17d34da2021-12-08 16:15:12 +0000376 ARMNN_LOG(info) << "Optimize ArmnnSubgraph time: " << std::setprecision(2)
377 << std::fixed << armnn::GetTimeDuration(optimizeStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100378 }
379 catch (std::exception &ex)
380 {
381 std::stringstream exMessage;
382 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
383 throw armnn::Exception(exMessage.str());
384 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100385 if (!optNet)
386 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100387 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100388 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
389 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100390
Colm Donelan3e32a872021-10-04 22:55:37 +0100391 // If set, we will serialize the optimized model into a dot file.
392 const std::string serializeToDotFile = delegate->m_Options.GetSerializeToDot();
393 if (!serializeToDotFile.empty())
394 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000395 ARMNN_LOG(info) << "Writing graph to dot file: " << serializeToDotFile;
Colm Donelan3e32a872021-10-04 22:55:37 +0100396 fs::path filename = serializeToDotFile;
397 std::fstream file(filename.c_str(), std::ios_base::out);
398 optNet->SerializeToDot(file);
399 }
400
Sadik Armagan62483be2020-10-23 17:14:43 +0100401 try
402 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000403 const auto loadStartTime = armnn::GetTimeNow();
404
Sadik Armagan62483be2020-10-23 17:14:43 +0100405 // Load graph into runtime
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000406 std::string errorMessage;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000407 armnn::Status loadingStatus;
Francis Murtagh626bd902022-06-21 13:16:23 +0000408 armnn::MemorySource inputSource = armnn::MemorySource::Undefined;
409 armnn::MemorySource outputSource = armnn::MemorySource::Undefined;
410 // There's a bit of an assumption here that the delegate will only support Malloc memory source.
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000411 if (delegate->m_Options.GetOptimizerOptions().m_ImportEnabled)
412 {
Francis Murtagh626bd902022-06-21 13:16:23 +0000413 inputSource = armnn::MemorySource::Malloc;
414 }
415 if (delegate->m_Options.GetOptimizerOptions().m_ExportEnabled)
416 {
417 outputSource = armnn::MemorySource::Malloc;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000418 }
Colm Donelan3e32a872021-10-04 22:55:37 +0100419 armnn::INetworkProperties networkProperties(false,
Francis Murtagh626bd902022-06-21 13:16:23 +0000420 inputSource,
421 outputSource,
Colm Donelan3e32a872021-10-04 22:55:37 +0100422 delegate->m_Options.GetInternalProfilingState(),
423 delegate->m_Options.GetInternalProfilingDetail());
424 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
425 std::move(optNet),
426 errorMessage,
427 networkProperties);
Sadik Armagan62483be2020-10-23 17:14:43 +0100428 if (loadingStatus != armnn::Status::Success)
429 {
Colm Donelan45142282021-10-21 23:39:52 +0100430 // Network load failed.
Colm Donelan194086f2022-11-14 17:23:07 +0000431 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded: " + errorMessage);
Sadik Armagan62483be2020-10-23 17:14:43 +0100432 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000433
434 ARMNN_LOG(info) << "Load ArmnnSubgraph time: " << std::setprecision(2)
435 << std::fixed << armnn::GetTimeDuration(loadStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100436 }
437 catch (std::exception& ex)
438 {
439 std::stringstream exMessage;
440 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
441 throw armnn::Exception(exMessage.str());
442 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100443
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000444 // Register debug callback function
445 if (delegate->m_Options.GetDebugCallbackFunction().has_value())
446 {
447 delegate->m_Runtime->RegisterDebugCallback(networkId, delegate->m_Options.GetDebugCallbackFunction().value());
448 }
449
Jan Eilers17d34da2021-12-08 16:15:12 +0000450 ARMNN_LOG(info) << "Overall ArmnnSubgraph creation time: " << std::setprecision(2)
451 << std::fixed << armnn::GetTimeDuration(startTime).count() << " ms\n";
452
Sadik Armagan3c24f432020-10-19 17:35:30 +0100453 // Create a new SubGraph with networkId and runtime
Sadik Armagan62483be2020-10-23 17:14:43 +0100454 return new ArmnnSubgraph(networkId, delegate->m_Runtime.get(), inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100455}
456
457TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
458{
Finn Williams6f9f9902020-11-13 13:23:15 +0000459 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100460 return kTfLiteOk;
461}
462
Sadik Armagan62483be2020-10-23 17:14:43 +0100463TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100464{
Sadik Armagan62483be2020-10-23 17:14:43 +0100465 // Prepare inputs
466 armnn::InputTensors inputTensors;
467 size_t inputIndex = 0;
468 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
469 {
470 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
471 if (tensor->allocation_type != kTfLiteMmapRo)
472 {
473 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100474 armnn::TensorInfo inputTensorInfo = inputBinding.second;
475 inputTensorInfo.SetConstant(true);
476 const armnn::ConstTensor inputTensor(inputTensorInfo, tensor->data.data);
Sadik Armagan62483be2020-10-23 17:14:43 +0100477 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100478
Sadik Armagan62483be2020-10-23 17:14:43 +0100479 ++inputIndex;
480 }
481 }
482
483 // Prepare outputs
484 armnn::OutputTensors outputTensors;
485 size_t outputIndex = 0;
486 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
487 {
488 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
489 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
490 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
491 outputTensors.emplace_back(outputIdx, outputTensor);
492
493 ++outputIndex;
494 }
495
496 // Run graph
497 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
Colm Donelan45142282021-10-21 23:39:52 +0100498 // The delegate holds its own Arm NN runtime so this is our last chance to print internal profiling data.
499 std::shared_ptr<armnn::IProfiler> profiler = m_Runtime->GetProfiler(m_NetworkId);
500 if (profiler && profiler->IsProfilingEnabled())
501 {
502 profiler->Print(std::cout);
503 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100504 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100505}
506
Sadik Armagan62483be2020-10-23 17:14:43 +0100507TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100508 TfLiteContext* tfLiteContext,
509 TfLiteRegistration* tfLiteRegistration,
510 TfLiteNode* tfLiteNode,
511 int nodeIndex)
512{
Sadik Armagan62483be2020-10-23 17:14:43 +0100513 switch (tfLiteRegistration->builtin_code)
514 {
Ryan OShead21abaf2022-06-10 14:49:11 +0100515 case kTfLiteBuiltinCustom:
516 {
517#if defined(ARMNN_POST_TFLITE_2_5)
518 // Custom operators are defined by the name rather than the builtin code.
519 // Parse the custom_name param in the registration to point to the correct visitor function.
520 std::string customOperatorName = tfLiteRegistration->custom_name;
521 if ( customOperatorName == "AveragePool3D" )
522 {
523 return VisitPooling3dOperator(delegateData,
524 tfLiteContext,
525 tfLiteNode,
526 nodeIndex,
527 customOperatorName);
528 }
529 else if (customOperatorName == "MaxPool3D")
530 {
531 return VisitPooling3dOperator(delegateData,
532 tfLiteContext,
533 tfLiteNode,
534 nodeIndex,
535 customOperatorName);
536 }
537#endif
538 // Invalid or unsupported custom operator
539 return kTfLiteError;
540 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100541 case kTfLiteBuiltinAbs:
542 return VisitElementwiseUnaryOperator(delegateData,
543 tfLiteContext,
544 tfLiteNode,
545 nodeIndex,
546 armnn::UnaryOperation::Abs);
547 case kTfLiteBuiltinAdd:
548 return VisitElementwiseBinaryOperator(delegateData,
549 tfLiteContext,
550 tfLiteNode,
551 nodeIndex,
552 kTfLiteBuiltinAdd);
553 case kTfLiteBuiltinArgMax:
554 return VisitArgMinMaxOperator(delegateData,
555 tfLiteContext,
556 tfLiteNode,
557 nodeIndex,
558 kTfLiteBuiltinArgMax);
559 case kTfLiteBuiltinArgMin:
560 return VisitArgMinMaxOperator(delegateData,
561 tfLiteContext,
562 tfLiteNode,
563 nodeIndex,
564 kTfLiteBuiltinArgMin);
565 case kTfLiteBuiltinAveragePool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100566 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100567 tfLiteContext,
568 tfLiteNode,
569 nodeIndex,
570 kTfLiteBuiltinAveragePool2d);
Ryan OShea49ed0df2022-09-21 16:09:41 +0100571 case kTfLiteBuiltinBatchMatmul:
572 return VisitBatchMatMulOperator(delegateData,
573 tfLiteContext,
574 tfLiteNode,
575 nodeIndex,
576 kTfLiteBuiltinBatchMatmul);
Sadik Armagan62483be2020-10-23 17:14:43 +0100577 case kTfLiteBuiltinBatchToSpaceNd:
578 return VisitBatchToSpaceNdOperator(delegateData,
579 tfLiteContext,
580 tfLiteNode,
581 nodeIndex,
582 kTfLiteBuiltinBatchToSpaceNd);
Sadik Armagan937565b2021-04-21 14:03:28 +0100583 case kTfLiteBuiltinCast:
584 return VisitCastOperator(delegateData,
585 tfLiteContext,
586 tfLiteNode,
587 nodeIndex,
588 kTfLiteBuiltinCast);
Sadik Armagan62483be2020-10-23 17:14:43 +0100589 case kTfLiteBuiltinConcatenation:
590 return VisitControlOperator(delegateData,
591 tfLiteContext,
592 tfLiteNode,
593 nodeIndex,
594 kTfLiteBuiltinConcatenation);
595 case kTfLiteBuiltinConv2d:
596 return VisitConvolutionOperator(delegateData,
597 tfLiteContext,
598 tfLiteNode,
599 nodeIndex,
600 kTfLiteBuiltinConv2d);
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100601// Conv3d is only correctly supported for external delegates from TF Lite v2.6, as there was a breaking bug in v2.5.
602#if defined(ARMNN_POST_TFLITE_2_5)
603 case kTfLiteBuiltinConv3d:
604 return VisitConvolutionOperator(delegateData,
605 tfLiteContext,
606 tfLiteNode,
607 nodeIndex,
608 kTfLiteBuiltinConv3d);
609#endif
Sadik Armagan62483be2020-10-23 17:14:43 +0100610 case kTfLiteBuiltinDepthToSpace:
611 return VisitDepthToSpaceOperator(delegateData,
612 tfLiteContext,
613 tfLiteNode,
614 nodeIndex,
615 kTfLiteBuiltinDepthToSpace);
616 case kTfLiteBuiltinDepthwiseConv2d:
617 return VisitConvolutionOperator(delegateData,
618 tfLiteContext,
619 tfLiteNode,
620 nodeIndex,
621 kTfLiteBuiltinDepthwiseConv2d);
622 case kTfLiteBuiltinDequantize:
623 return VisitDequantizeOperator(delegateData,
624 tfLiteContext,
625 tfLiteNode,
626 nodeIndex,
627 kTfLiteBuiltinDequantize);
628 case kTfLiteBuiltinDiv:
629 return VisitElementwiseBinaryOperator(delegateData,
630 tfLiteContext,
631 tfLiteNode,
632 nodeIndex,
633 kTfLiteBuiltinDiv);
634 case kTfLiteBuiltinElu:
635 return VisitActivationOperator(delegateData,
636 tfLiteContext,
637 tfLiteNode,
638 nodeIndex,
639 kTfLiteBuiltinElu);
640 case kTfLiteBuiltinEqual:
641 return VisitComparisonOperator(delegateData,
642 tfLiteContext,
643 tfLiteNode,
644 nodeIndex,
645 kTfLiteBuiltinEqual);
646 case kTfLiteBuiltinExp:
647 return VisitElementwiseUnaryOperator(delegateData,
648 tfLiteContext,
649 tfLiteNode,
650 nodeIndex,
651 armnn::UnaryOperation::Exp);
652 case kTfLiteBuiltinExpandDims:
653 return VisitExpandDimsOperator(delegateData,
654 tfLiteContext,
655 tfLiteNode,
656 nodeIndex,
657 kTfLiteBuiltinExpandDims);
658 case kTfLiteBuiltinFill:
659 return VisitFillOperator(delegateData,
660 tfLiteContext,
661 tfLiteNode,
662 nodeIndex,
663 kTfLiteBuiltinFill);
664 case kTfLiteBuiltinFloor:
665 return VisitFloorOperator(delegateData,
666 tfLiteContext,
667 tfLiteNode,
668 nodeIndex,
669 kTfLiteBuiltinFloor);
Jim Flynn4b2f3472021-10-13 21:20:07 +0100670 case kTfLiteBuiltinFloorDiv:
671 return VisitElementwiseBinaryOperator(delegateData,
672 tfLiteContext,
673 tfLiteNode,
674 nodeIndex,
675 kTfLiteBuiltinFloorDiv);
Sadik Armagan62483be2020-10-23 17:14:43 +0100676 case kTfLiteBuiltinFullyConnected:
677 return VisitFullyConnectedOperator(delegateData,
678 tfLiteContext,
679 tfLiteNode,
680 nodeIndex,
681 kTfLiteBuiltinFullyConnected);
682 case kTfLiteBuiltinGather:
683 return VisitGatherOperator(delegateData,
684 tfLiteContext,
685 tfLiteNode,
686 nodeIndex,
687 kTfLiteBuiltinGather);
Teresa Charlind5c0ed22022-04-25 18:23:41 +0100688 case kTfLiteBuiltinGatherNd:
689 return VisitGatherNdOperator(delegateData,
690 tfLiteContext,
691 tfLiteNode,
692 nodeIndex,
693 kTfLiteBuiltinGatherNd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100694 case kTfLiteBuiltinGreater:
695 return VisitComparisonOperator(delegateData,
696 tfLiteContext,
697 tfLiteNode,
698 nodeIndex,
699 kTfLiteBuiltinGreater);
700 case kTfLiteBuiltinGreaterEqual:
701 return VisitComparisonOperator(delegateData,
702 tfLiteContext,
703 tfLiteNode,
704 nodeIndex,
705 kTfLiteBuiltinGreaterEqual);
706 case kTfLiteBuiltinHardSwish:
707 return VisitActivationOperator(delegateData,
708 tfLiteContext,
709 tfLiteNode,
710 nodeIndex,
711 kTfLiteBuiltinHardSwish);
712 case kTfLiteBuiltinL2Normalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000713 return VisitL2NormalizationOperator(delegateData,
714 tfLiteContext,
715 tfLiteNode,
716 nodeIndex,
717 kTfLiteBuiltinL2Normalization);
Sadik Armagan62483be2020-10-23 17:14:43 +0100718 case kTfLiteBuiltinL2Pool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100719 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100720 tfLiteContext,
721 tfLiteNode,
722 nodeIndex,
723 kTfLiteBuiltinL2Pool2d);
724 case kTfLiteBuiltinLess:
725 return VisitComparisonOperator(delegateData,
726 tfLiteContext,
727 tfLiteNode,
728 nodeIndex,
729 kTfLiteBuiltinLess);
730 case kTfLiteBuiltinLessEqual:
731 return VisitComparisonOperator(delegateData,
732 tfLiteContext,
733 tfLiteNode,
734 nodeIndex,
735 kTfLiteBuiltinLessEqual);
736 case kTfLiteBuiltinLocalResponseNormalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000737 return VisitLocalResponseNormalizationOperator(delegateData,
738 tfLiteContext,
739 tfLiteNode,
740 nodeIndex,
741 kTfLiteBuiltinLocalResponseNormalization);
Teresa Charlinb1f5f702022-07-12 14:16:24 +0100742 case kTfLiteBuiltinLog:
743 return VisitElementwiseUnaryOperator(delegateData,
744 tfLiteContext,
745 tfLiteNode,
746 nodeIndex,
747 armnn::UnaryOperation::Log);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000748 case kTfLiteBuiltinLogicalAnd:
749 return VisitLogicalBinaryOperator(delegateData,
750 tfLiteContext,
751 tfLiteNode,
752 nodeIndex,
753 kTfLiteBuiltinLogicalAnd,
754 armnn::LogicalBinaryOperation::LogicalAnd);
755 case kTfLiteBuiltinLogicalNot:
756 return VisitElementwiseUnaryOperator(delegateData,
757 tfLiteContext,
758 tfLiteNode,
759 nodeIndex,
760 armnn::UnaryOperation::LogicalNot);
761 case kTfLiteBuiltinLogicalOr:
762 return VisitLogicalBinaryOperator(delegateData,
763 tfLiteContext,
764 tfLiteNode,
765 nodeIndex,
766 kTfLiteBuiltinLogicalOr,
767 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100768 case kTfLiteBuiltinLogistic:
769 return VisitActivationOperator(delegateData,
770 tfLiteContext,
771 tfLiteNode,
772 nodeIndex,
773 kTfLiteBuiltinLogistic);
774 case kTfLiteBuiltinLogSoftmax:
775 return VisitSoftmaxOperator(delegateData,
776 tfLiteContext,
777 tfLiteNode,
778 nodeIndex,
779 kTfLiteBuiltinLogSoftmax);
780 case kTfLiteBuiltinLstm:
781 return VisitLstmOperator(delegateData,
782 tfLiteContext,
783 tfLiteNode,
784 nodeIndex,
785 kTfLiteBuiltinLstm);
786 case kTfLiteBuiltinMaxPool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100787 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100788 tfLiteContext,
789 tfLiteNode,
790 nodeIndex,
791 kTfLiteBuiltinMaxPool2d);
792 case kTfLiteBuiltinMaximum:
793 return VisitElementwiseBinaryOperator(delegateData,
794 tfLiteContext,
795 tfLiteNode,
796 nodeIndex,
797 kTfLiteBuiltinMaximum);
798 case kTfLiteBuiltinMean:
799 return VisitControlOperator(delegateData,
800 tfLiteContext,
801 tfLiteNode,
802 nodeIndex,
803 kTfLiteBuiltinMean);
804 case kTfLiteBuiltinMinimum:
805 return VisitElementwiseBinaryOperator(delegateData,
806 tfLiteContext,
807 tfLiteNode,
808 nodeIndex,
809 kTfLiteBuiltinMinimum);
Matthew Sloyanaf3a4ef2021-10-22 15:48:12 +0100810 case kTfLiteBuiltinMirrorPad:
811 return VisitPadOperator(delegateData,
812 tfLiteContext,
813 tfLiteNode,
814 nodeIndex,
815 kTfLiteBuiltinMirrorPad);
Sadik Armagan62483be2020-10-23 17:14:43 +0100816 case kTfLiteBuiltinMul:
817 return VisitElementwiseBinaryOperator(delegateData,
818 tfLiteContext,
819 tfLiteNode,
820 nodeIndex,
821 kTfLiteBuiltinMul);
822 case kTfLiteBuiltinNeg:
823 return VisitElementwiseUnaryOperator(delegateData,
824 tfLiteContext,
825 tfLiteNode,
826 nodeIndex,
827 armnn::UnaryOperation::Neg);
828 case kTfLiteBuiltinNotEqual:
829 return VisitComparisonOperator(delegateData,
830 tfLiteContext,
831 tfLiteNode,
832 nodeIndex,
833 kTfLiteBuiltinNotEqual);
Matthew Sloyana7a12f52021-05-06 10:05:28 +0100834 case kTfLiteBuiltinPack:
835 return VisitPackOperator(delegateData,
836 tfLiteContext,
837 tfLiteNode,
838 nodeIndex,
839 kTfLiteBuiltinPack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100840 case kTfLiteBuiltinPad:
841 return VisitPadOperator(delegateData,
842 tfLiteContext,
843 tfLiteNode,
844 nodeIndex,
845 kTfLiteBuiltinPad);
846 case kTfLiteBuiltinPadv2:
847 return VisitPadOperator(delegateData,
848 tfLiteContext,
849 tfLiteNode,
850 nodeIndex,
851 kTfLiteBuiltinPadv2);
852 case kTfLiteBuiltinPrelu:
James Conroy39825482021-05-27 17:44:50 +0100853 return VisitPreluOperator(delegateData,
854 tfLiteContext,
855 tfLiteNode,
856 nodeIndex,
857 kTfLiteBuiltinPrelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100858 case kTfLiteBuiltinQuantize:
859 return VisitQuantizeOperator(delegateData,
860 tfLiteContext,
861 tfLiteNode,
862 nodeIndex,
863 kTfLiteBuiltinQuantize);
864 case kTfLiteBuiltinRank:
865 return VisitControlOperator(delegateData,
866 tfLiteContext,
867 tfLiteNode,
868 nodeIndex,
869 kTfLiteBuiltinRank);
Sadik Armagana2747482021-02-09 10:28:54 +0000870 case kTfLiteBuiltinReduceMax:
871 return VisitReduceOperator(delegateData,
872 tfLiteContext,
873 tfLiteNode,
874 nodeIndex,
875 kTfLiteBuiltinReduceMax);
876 case kTfLiteBuiltinReduceMin:
877 return VisitReduceOperator(delegateData,
878 tfLiteContext,
879 tfLiteNode,
880 nodeIndex,
881 kTfLiteBuiltinReduceMin);
Teresa Charlin4e3e8312021-08-05 12:34:37 +0100882 case kTfLiteBuiltinReduceProd:
883 return VisitReduceOperator(delegateData,
884 tfLiteContext,
885 tfLiteNode,
886 nodeIndex,
887 kTfLiteBuiltinReduceProd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100888 case kTfLiteBuiltinRelu:
889 return VisitActivationOperator(delegateData,
890 tfLiteContext,
891 tfLiteNode,
892 nodeIndex,
893 kTfLiteBuiltinRelu);
894 case kTfLiteBuiltinReluN1To1:
895 return VisitActivationOperator(delegateData,
896 tfLiteContext,
897 tfLiteNode,
898 nodeIndex,
899 kTfLiteBuiltinReluN1To1);
900 case kTfLiteBuiltinRelu6:
901 return VisitActivationOperator(delegateData,
902 tfLiteContext,
903 tfLiteNode,
904 nodeIndex,
905 kTfLiteBuiltinRelu6);
906 case kTfLiteBuiltinReshape:
907 return VisitReshapeOperator(delegateData,
908 tfLiteContext,
909 tfLiteNode,
910 nodeIndex,
911 kTfLiteBuiltinReshape);
912 case kTfLiteBuiltinResizeBilinear:
913 return VisitResizeOperator(delegateData,
914 tfLiteContext,
915 tfLiteNode,
916 nodeIndex,
917 kTfLiteBuiltinResizeBilinear);
918 case kTfLiteBuiltinResizeNearestNeighbor:
919 return VisitResizeOperator(delegateData,
920 tfLiteContext,
921 tfLiteNode,
922 nodeIndex,
923 kTfLiteBuiltinResizeNearestNeighbor);
924 case kTfLiteBuiltinRsqrt:
925 return VisitElementwiseUnaryOperator(delegateData,
926 tfLiteContext,
927 tfLiteNode,
928 nodeIndex,
929 armnn::UnaryOperation::Rsqrt);
Keith Davis0176fd82021-06-01 17:36:32 +0100930 case kTfLiteBuiltinShape:
931 return VisitShapeOperator(delegateData,
932 tfLiteContext,
933 tfLiteNode,
934 nodeIndex,
935 kTfLiteBuiltinShape);
Teresa Charlinb1f5f702022-07-12 14:16:24 +0100936 case kTfLiteBuiltinSin:
937 return VisitElementwiseUnaryOperator(delegateData,
938 tfLiteContext,
939 tfLiteNode,
940 nodeIndex,
941 armnn::UnaryOperation::Sin);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +0000942 case kTfLiteBuiltinSplit:
943 return VisitSplitOperator(delegateData,
944 tfLiteContext,
945 tfLiteNode,
946 nodeIndex,
947 kTfLiteBuiltinSplit);
948 case kTfLiteBuiltinSplitV:
949 return VisitSplitVOperator(delegateData,
950 tfLiteContext,
951 tfLiteNode,
952 nodeIndex,
953 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +0100954 case kTfLiteBuiltinSqrt:
955 return VisitElementwiseUnaryOperator(delegateData,
956 tfLiteContext,
957 tfLiteNode,
958 nodeIndex,
959 armnn::UnaryOperation::Sqrt);
960 case kTfLiteBuiltinSqueeze:
961 return VisitSqueezeOperator(delegateData,
962 tfLiteContext,
963 tfLiteNode,
964 nodeIndex,
965 kTfLiteBuiltinSqueeze);
966 case kTfLiteBuiltinStridedSlice:
967 return VisitSliceOperator(delegateData,
968 tfLiteContext,
969 tfLiteNode,
970 nodeIndex,
971 kTfLiteBuiltinStridedSlice);
Sadik Armagana2747482021-02-09 10:28:54 +0000972 case kTfLiteBuiltinSum:
973 return VisitReduceOperator(delegateData,
974 tfLiteContext,
975 tfLiteNode,
976 nodeIndex,
977 kTfLiteBuiltinSum);
Sadik Armagan62483be2020-10-23 17:14:43 +0100978 case kTfLiteBuiltinTranspose:
979 return VisitTransposeOperator(delegateData,
980 tfLiteContext,
981 tfLiteNode,
982 nodeIndex,
983 kTfLiteBuiltinTranspose);
984 case kTfLiteBuiltinTransposeConv:
985 return VisitConvolutionOperator(delegateData,
986 tfLiteContext,
987 tfLiteNode,
988 nodeIndex,
989 kTfLiteBuiltinTransposeConv);
990 case kTfLiteBuiltinSoftmax:
991 return VisitSoftmaxOperator(delegateData,
992 tfLiteContext,
993 tfLiteNode,
994 nodeIndex,
995 kTfLiteBuiltinSoftmax);
996 case kTfLiteBuiltinSpaceToBatchNd:
997 return VisitSpaceToBatchNdOperator(delegateData,
998 tfLiteContext,
999 tfLiteNode,
1000 nodeIndex,
1001 kTfLiteBuiltinSpaceToBatchNd);
1002 case kTfLiteBuiltinSpaceToDepth:
1003 return VisitSpaceToDepthOperator(delegateData,
1004 tfLiteContext,
1005 tfLiteNode,
1006 nodeIndex,
1007 kTfLiteBuiltinSpaceToDepth);
1008 case kTfLiteBuiltinSub:
1009 return VisitElementwiseBinaryOperator(delegateData,
1010 tfLiteContext,
1011 tfLiteNode,
1012 nodeIndex,
1013 kTfLiteBuiltinSub);
1014 case kTfLiteBuiltinTanh:
1015 return VisitActivationOperator(delegateData,
1016 tfLiteContext,
1017 tfLiteNode,
1018 nodeIndex,
1019 kTfLiteBuiltinTanh);
Narumol Prangnawarat7684b182021-08-12 14:48:15 +01001020 case kTfLiteBuiltinUnidirectionalSequenceLstm:
1021 return VisitUnidirectionalSequenceLstmOperator(delegateData,
1022 tfLiteContext,
1023 tfLiteNode,
1024 nodeIndex,
1025 kTfLiteBuiltinUnidirectionalSequenceLstm);
Kevin May8ab2d7a2021-05-07 09:32:51 +01001026 case kTfLiteBuiltinUnpack:
1027 return VisitUnpackOperator(delegateData,
1028 tfLiteContext,
1029 tfLiteNode,
1030 nodeIndex,
1031 kTfLiteBuiltinUnpack);
Sadik Armagan62483be2020-10-23 17:14:43 +01001032 default:
1033 return kTfLiteError;
1034 }
Sadik Armagan3c24f432020-10-19 17:35:30 +01001035}
1036
1037} // armnnDelegate namespace