blob: de2aa0c6325c546a5ccc270192096d3d87c9d23b [file] [log] [blame]
Sadik Armagan3c24f432020-10-19 17:35:30 +01001//
Mike Kelly5446a4d2023-01-20 15:51:05 +00002// Copyright © 2020-2023 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"
Tracy Narine7306bbe2023-07-17 16:06:26 +010034#include "ReverseV2.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010035#include "Round.hpp"
Keith Davis0176fd82021-06-01 17:36:32 +010036#include "Shape.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010037#include "Slice.hpp"
Cathal Corbett839b9322022-11-18 08:52:18 +000038#include "StridedSlice.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010039#include "Softmax.hpp"
40#include "SpaceDepth.hpp"
Sadik Armagan34fa1bd2020-11-27 12:40:52 +000041#include "Split.hpp"
Tianle Cheng92ce35c2023-07-25 16:41:00 +010042#include "Tile.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010043#include "Transpose.hpp"
Narumol Prangnawarat7684b182021-08-12 14:48:15 +010044#include "UnidirectionalSequenceLstm.hpp"
Kevin May8ab2d7a2021-05-07 09:32:51 +010045#include "Unpack.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010046
Colm Donelan3e32a872021-10-04 22:55:37 +010047#include <armnnUtils/Filesystem.hpp>
Jan Eilers17d34da2021-12-08 16:15:12 +000048#include <armnn/utility/Timer.hpp>
Sadik Armagan62483be2020-10-23 17:14:43 +010049#include <flatbuffers/flatbuffers.h>
50#include <tensorflow/lite/context_util.h>
Jim Flynn4b2f3472021-10-13 21:20:07 +010051#include <tensorflow/lite/schema/schema_generated.h>
Sadik Armagan62483be2020-10-23 17:14:43 +010052
Sadik Armagan3c24f432020-10-19 17:35:30 +010053#include <algorithm>
Matthew Sloyanac001ee2021-02-03 10:43:04 +000054#include <iostream>
Sadik Armagan62483be2020-10-23 17:14:43 +010055#include <sstream>
Sadik Armagan3c24f432020-10-19 17:35:30 +010056
57namespace armnnDelegate
58{
59
Sadik Armagan62483be2020-10-23 17:14:43 +010060DelegateOptions TfLiteArmnnDelegateOptionsDefault()
61{
62 DelegateOptions options(armnn::Compute::CpuRef);
63 return options;
64}
65
66TfLiteDelegate* TfLiteArmnnDelegateCreate(armnnDelegate::DelegateOptions options)
67{
68 auto* armnnDelegate = new ::armnnDelegate::Delegate(options);
69 return armnnDelegate->GetDelegate();
70}
71
72void TfLiteArmnnDelegateDelete(TfLiteDelegate* tfLiteDelegate)
73{
74 if (tfLiteDelegate != nullptr)
75 {
76 delete static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_);
77 }
78}
79
80TfLiteStatus DoPrepare(TfLiteContext* tfLiteContext, TfLiteDelegate* tfLiteDelegate)
81{
82 TfLiteIntArray* supportedOperators =
83 static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_)->IdentifyOperatorsToDelegate(tfLiteContext);
84
85 // ArmNN Delegate Registration
86 static const TfLiteRegistration kArmnnSubgraphRegistration = {
87 // ArmnnSubgraph Init
88 .init = [](TfLiteContext* tfLiteContext, const char* buffer, size_t length) -> void* {
Finn Williams6f9f9902020-11-13 13:23:15 +000089 armnn::IgnoreUnused(length);
Sadik Armagan62483be2020-10-23 17:14:43 +010090 const TfLiteDelegateParams* parameters = reinterpret_cast<const TfLiteDelegateParams*>(buffer);
91
92 return static_cast<void*>(ArmnnSubgraph::Create(
93 tfLiteContext, parameters, static_cast<::armnnDelegate::Delegate*>(parameters->delegate->data_)));
94 },
95 // ArmnnSubgraph Free
96 .free = [](TfLiteContext* tfLiteContext, void* buffer) -> void {
Finn Williams6f9f9902020-11-13 13:23:15 +000097 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan62483be2020-10-23 17:14:43 +010098 if (buffer != nullptr)
99 {
100 delete static_cast<ArmnnSubgraph*>(buffer);
101 }
102 },
103 // ArmnnSubgraph Prepare
104 .prepare = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
105 if (tfLiteNode->user_data == nullptr)
106 {
107 return kTfLiteError;
108 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100109 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Prepare(tfLiteContext);
110 },
111 // ArmnnSubgraph Invoke
112 .invoke = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
113 if (tfLiteNode->user_data == nullptr)
114 {
115 return kTfLiteError;
116 }
117
118 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Invoke(tfLiteContext, tfLiteNode);
119 },
120
121 .profiling_string = nullptr,
122 .builtin_code = kTfLiteBuiltinDelegate,
123 .custom_name = "TfLiteArmNnDelegate",
124 .version = 1,
Colm Donelan718966f2022-10-10 10:06:12 +0100125 .registration_external = nullptr,
Sadik Armagan62483be2020-10-23 17:14:43 +0100126 };
127
128 const TfLiteStatus status =
129 tfLiteContext->ReplaceNodeSubsetsWithDelegateKernels(
130 tfLiteContext, kArmnnSubgraphRegistration, supportedOperators, tfLiteDelegate);
131
132 TfLiteIntArrayFree(supportedOperators);
133 return status;
134
135}
136
Sadik Armagan3c24f432020-10-19 17:35:30 +0100137Delegate::Delegate(armnnDelegate::DelegateOptions options)
Mike Kelly5446a4d2023-01-20 15:51:05 +0000138 : m_Options(std::move(options))
Sadik Armagan3c24f432020-10-19 17:35:30 +0100139{
Jan Eilers2cd18472020-12-15 10:42:38 +0000140 // Configures logging for ARMNN
Colm Donelanda7f2f92022-12-20 16:21:35 +0000141 if (m_Options.IsLoggingEnabled())
Jan Eilers2cd18472020-12-15 10:42:38 +0000142 {
Colm Donelanda7f2f92022-12-20 16:21:35 +0000143 armnn::ConfigureLogging(true, true, m_Options.GetLoggingSeverity());
Jan Eilers2cd18472020-12-15 10:42:38 +0000144 }
Mike Kelly5446a4d2023-01-20 15:51:05 +0000145 // Create/Get the static ArmNN Runtime. Note that the m_Runtime will be shared by all armnn_delegate
146 // instances so the RuntimeOptions cannot be altered for different armnn_delegate instances.
147 m_Runtime = GetRuntime(m_Options.GetRuntimeOptions());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100148 std::vector<armnn::BackendId> backends;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100149 if (m_Runtime)
150 {
151 const armnn::BackendIdSet supportedDevices = m_Runtime->GetDeviceSpec().GetSupportedBackends();
152 for (auto& backend : m_Options.GetBackends())
153 {
154 if (std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) == supportedDevices.cend())
155 {
Sadik Armagan0534e032020-10-27 17:30:18 +0000156 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100157 "TfLiteArmnnDelegate: Requested unknown backend %s", backend.Get().c_str());
158 }
159 else
160 {
161 backends.push_back(backend);
162 }
163 }
164 }
165
166 if (backends.empty())
167 {
168 // No known backend specified
169 throw armnn::InvalidArgumentException("TfLiteArmnnDelegate: No known backend specified.");
170 }
171 m_Options.SetBackends(backends);
172
173 TFLITE_LOG_PROD_ONCE(tflite::TFLITE_LOG_INFO, "TfLiteArmnnDelegate: Created TfLite ArmNN delegate.");
174}
175
Sadik Armagan62483be2020-10-23 17:14:43 +0100176TfLiteIntArray* Delegate::IdentifyOperatorsToDelegate(TfLiteContext* tfLiteContext)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100177{
178 TfLiteIntArray* executionPlan = nullptr;
179 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
180 {
181 TF_LITE_KERNEL_LOG(tfLiteContext, "TfLiteArmnnDelegate: Unable to get graph execution plan.");
182 return nullptr;
183 }
184
Sadik Armagan62483be2020-10-23 17:14:43 +0100185 // Delegate data with null network
186 DelegateData delegateData(m_Options.GetBackends());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100187
188 TfLiteIntArray* nodesToDelegate = TfLiteIntArrayCreate(executionPlan->size);
189 nodesToDelegate->size = 0;
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000190
191 std::set<int32_t> unsupportedOperators;
192
Sadik Armagan3c24f432020-10-19 17:35:30 +0100193 for (int i = 0; i < executionPlan->size; ++i)
194 {
195 const int nodeIndex = executionPlan->data[i];
196
197 // If TfLite nodes can be delegated to ArmNN
198 TfLiteNode* tfLiteNode = nullptr;
199 TfLiteRegistration* tfLiteRegistration = nullptr;
200 if (tfLiteContext->GetNodeAndRegistration(
201 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
202 {
203 TF_LITE_KERNEL_LOG(tfLiteContext,
204 "TfLiteArmnnDelegate: Unable to get node and registration for node %d.",
205 nodeIndex);
206 continue;
207 }
208
Ryan OShea05b6a3e2023-01-11 15:27:50 +0000209 TfLiteStatus visitStatus;
210
211 try
212 {
213 visitStatus = ArmnnSubgraph::VisitNode(
214 delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex);
215 }
216 catch(std::exception& ex)
217 {
218 ARMNN_LOG(error) << "ArmNN Failed to visit node with error: " << ex.what();
219 visitStatus = kTfLiteError;
220 }
221
222 if ( visitStatus != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100223 {
224 // node is not supported by ArmNN
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000225 unsupportedOperators.insert(tfLiteRegistration->builtin_code);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100226 continue;
227 }
228
229 nodesToDelegate->data[nodesToDelegate->size++] = nodeIndex;
230 }
231
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000232 for (std::set<int32_t>::iterator it=unsupportedOperators.begin(); it!=unsupportedOperators.end(); ++it)
233 {
234 TF_LITE_KERNEL_LOG(tfLiteContext,
235 "Operator %s [%d] is not supported by armnn_delegate.",
236 tflite::EnumNameBuiltinOperator(tflite::BuiltinOperator(*it)),
237 *it);
238 }
239
Sadik Armaganca565c12022-08-16 12:17:24 +0100240 if (!unsupportedOperators.empty() && m_Options.TfLiteRuntimeFallbackDisabled())
241 {
242 std::stringstream exMessage;
243 exMessage << "TfLiteArmnnDelegate: There are unsupported operators in the model. ";
244 exMessage << "Not falling back to TfLite Runtime as fallback is disabled. ";
245 exMessage << "This should only be disabled under test conditions.";
246 throw armnn::Exception(exMessage.str());
247 }
Colm Donelan3811a972023-01-25 21:19:49 +0000248 if (nodesToDelegate->size == 0)
249 {
250 ARMNN_LOG(info) << "No operators in this model are supported by the Arm NN TfLite delegate." <<
251 " The model will be executed entirely by TfLite runtime.";
252 }
Sadik Armaganca565c12022-08-16 12:17:24 +0100253
Sadik Armagan62483be2020-10-23 17:14:43 +0100254 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100255 return nodesToDelegate;
256}
257
258TfLiteDelegate* Delegate::GetDelegate()
259{
260 return &m_Delegate;
261}
262
Matthew Sloyanac001ee2021-02-03 10:43:04 +0000263const std::string Delegate::GetVersion()
264{
265 return DELEGATE_VERSION;
266}
267
Sadik Armagan62483be2020-10-23 17:14:43 +0100268TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
269 TfLiteContext* tfLiteContext,
270 const TfLiteIntArray* inputs,
271 std::vector<armnn::BindingPointInfo>& inputBindings)
272{
Finn Williams6f9f9902020-11-13 13:23:15 +0000273 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100274 for (unsigned int i = 0; i < numInputs; ++i)
275 {
276 const int32_t tensorId = inputs->data[i];
277 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000278 // Do not create bindings for constant inputs
279 if (tensor.allocation_type == kTfLiteMmapRo)
280 {
281 continue;
282 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100283
284 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
285 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
286
287 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
288 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
289 outputSlot.SetTensorInfo(tensorInfo);
290
291 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000292 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100293
Sadik Armagan6e36a642020-11-10 21:18:41 +0000294 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100295 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000296
Sadik Armagan62483be2020-10-23 17:14:43 +0100297 return kTfLiteOk;
298}
299
300TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
301 TfLiteContext* tfLiteContext,
302 const TfLiteIntArray* outputs,
303 std::vector<armnn::BindingPointInfo>& outputBindings)
304{
Finn Williams6f9f9902020-11-13 13:23:15 +0000305 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100306 for (unsigned int i = 0; i < numOutputs; ++i)
307 {
308 const int32_t tensorId = outputs->data[i];
309 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
310
311 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
312 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
313
314 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Ryan OSheac229b3f2023-06-27 22:34:54 +0100315
316 if (delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] == nullptr)
317 {
318 return kTfLiteError;
319 }
320
Finn Williams6f9f9902020-11-13 13:23:15 +0000321 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100322 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
323 }
324
325 return kTfLiteOk;
326}
327
Sadik Armagan3c24f432020-10-19 17:35:30 +0100328ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
329 const TfLiteDelegateParams* parameters,
330 const Delegate* delegate)
331{
Jan Eilers17d34da2021-12-08 16:15:12 +0000332 const auto startTime = armnn::GetTimeNow();
333 ARMNN_LOG(info) << "ArmnnSubgraph creation";
334
Sadik Armagan3c24f432020-10-19 17:35:30 +0100335 TfLiteIntArray* executionPlan;
336 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
337 {
338 return nullptr;
339 }
340
Sadik Armagan62483be2020-10-23 17:14:43 +0100341 // Initialize DelegateData holds network and output slots information
342 DelegateData delegateData(delegate->m_Options.GetBackends());
343
344 // Build ArmNN Network
John Mcloughlinc5ee0d72023-03-24 12:07:25 +0000345 armnn::NetworkOptions networkOptions = delegate->m_Options.GetOptimizerOptions().GetModelOptions();
Sadik Armagan3c24f432020-10-19 17:35:30 +0100346 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100347 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100348
Sadik Armagan6e36a642020-11-10 21:18:41 +0000349 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
350
Sadik Armagan62483be2020-10-23 17:14:43 +0100351 std::vector<armnn::BindingPointInfo> inputBindings;
352 std::vector<armnn::BindingPointInfo> outputBindings;
353
354 // Add input layer
355 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
356 if (status != kTfLiteOk)
357 {
358 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
359 }
360
361 // Parse TfLite delegate nodes to ArmNN
Jan Eilers17d34da2021-12-08 16:15:12 +0000362 const auto parseStartTime = armnn::GetTimeNow();
Sadik Armagan3c24f432020-10-19 17:35:30 +0100363 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
364 {
365 const int nodeIndex = parameters->nodes_to_replace->data[i];
366
367 TfLiteNode* tfLiteNode = nullptr;
368 TfLiteRegistration* tfLiteRegistration = nullptr;
369 if (tfLiteContext->GetNodeAndRegistration(
370 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
371 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000372 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100373 }
374
Sadik Armagan62483be2020-10-23 17:14:43 +0100375 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100376 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000377 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100378 }
379 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000380 ARMNN_LOG(info) << "Parse nodes to ArmNN time: " << std::setprecision(2)
381 << std::fixed << armnn::GetTimeDuration(parseStartTime).count() << " ms";
Sadik Armagan3c24f432020-10-19 17:35:30 +0100382
Sadik Armagan62483be2020-10-23 17:14:43 +0100383 // Add Output layer
384 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
385 if (status != kTfLiteOk)
386 {
387 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
388 }
389
390 // Optimize ArmNN network
391 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
392 try
393 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000394 const auto optimizeStartTime = armnn::GetTimeNow();
Sadik Armagan6e36a642020-11-10 21:18:41 +0000395 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100396 delegate->m_Options.GetBackends(),
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000397 delegate->m_Runtime->GetDeviceSpec(),
398 delegate->m_Options.GetOptimizerOptions());
Jan Eilers17d34da2021-12-08 16:15:12 +0000399 ARMNN_LOG(info) << "Optimize ArmnnSubgraph time: " << std::setprecision(2)
400 << std::fixed << armnn::GetTimeDuration(optimizeStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100401 }
Ryan OShea05b6a3e2023-01-11 15:27:50 +0000402 catch (std::exception& ex)
Sadik Armagan62483be2020-10-23 17:14:43 +0100403 {
404 std::stringstream exMessage;
405 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
406 throw armnn::Exception(exMessage.str());
407 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100408 if (!optNet)
409 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100410 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100411 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
412 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100413
Colm Donelan3e32a872021-10-04 22:55:37 +0100414 // If set, we will serialize the optimized model into a dot file.
415 const std::string serializeToDotFile = delegate->m_Options.GetSerializeToDot();
416 if (!serializeToDotFile.empty())
417 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000418 ARMNN_LOG(info) << "Writing graph to dot file: " << serializeToDotFile;
Colm Donelan3e32a872021-10-04 22:55:37 +0100419 fs::path filename = serializeToDotFile;
420 std::fstream file(filename.c_str(), std::ios_base::out);
421 optNet->SerializeToDot(file);
422 }
423
Sadik Armagan62483be2020-10-23 17:14:43 +0100424 try
425 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000426 const auto loadStartTime = armnn::GetTimeNow();
427
Sadik Armagan62483be2020-10-23 17:14:43 +0100428 // Load graph into runtime
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000429 std::string errorMessage;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000430 armnn::Status loadingStatus;
Francis Murtagh626bd902022-06-21 13:16:23 +0000431 armnn::MemorySource inputSource = armnn::MemorySource::Undefined;
432 armnn::MemorySource outputSource = armnn::MemorySource::Undefined;
433 // There's a bit of an assumption here that the delegate will only support Malloc memory source.
John Mcloughlinc5ee0d72023-03-24 12:07:25 +0000434 if (delegate->m_Options.GetOptimizerOptions().GetImportEnabled())
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000435 {
Francis Murtagh626bd902022-06-21 13:16:23 +0000436 inputSource = armnn::MemorySource::Malloc;
437 }
John Mcloughlinc5ee0d72023-03-24 12:07:25 +0000438 if (delegate->m_Options.GetOptimizerOptions().GetExportEnabled())
Francis Murtagh626bd902022-06-21 13:16:23 +0000439 {
440 outputSource = armnn::MemorySource::Malloc;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000441 }
Colm Donelan3e32a872021-10-04 22:55:37 +0100442 armnn::INetworkProperties networkProperties(false,
Francis Murtagh626bd902022-06-21 13:16:23 +0000443 inputSource,
444 outputSource,
Colm Donelan3e32a872021-10-04 22:55:37 +0100445 delegate->m_Options.GetInternalProfilingState(),
446 delegate->m_Options.GetInternalProfilingDetail());
447 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
448 std::move(optNet),
449 errorMessage,
450 networkProperties);
Sadik Armagan62483be2020-10-23 17:14:43 +0100451 if (loadingStatus != armnn::Status::Success)
452 {
Colm Donelan45142282021-10-21 23:39:52 +0100453 // Network load failed.
Colm Donelan194086f2022-11-14 17:23:07 +0000454 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded: " + errorMessage);
Sadik Armagan62483be2020-10-23 17:14:43 +0100455 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000456
457 ARMNN_LOG(info) << "Load ArmnnSubgraph time: " << std::setprecision(2)
458 << std::fixed << armnn::GetTimeDuration(loadStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100459 }
460 catch (std::exception& ex)
461 {
462 std::stringstream exMessage;
463 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
464 throw armnn::Exception(exMessage.str());
465 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100466
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000467 // Register debug callback function
468 if (delegate->m_Options.GetDebugCallbackFunction().has_value())
469 {
470 delegate->m_Runtime->RegisterDebugCallback(networkId, delegate->m_Options.GetDebugCallbackFunction().value());
471 }
472
Jan Eilers17d34da2021-12-08 16:15:12 +0000473 ARMNN_LOG(info) << "Overall ArmnnSubgraph creation time: " << std::setprecision(2)
474 << std::fixed << armnn::GetTimeDuration(startTime).count() << " ms\n";
475
Sadik Armagan3c24f432020-10-19 17:35:30 +0100476 // Create a new SubGraph with networkId and runtime
Mike Kelly5446a4d2023-01-20 15:51:05 +0000477 return new ArmnnSubgraph(networkId, delegate->m_Runtime, inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100478}
479
480TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
481{
Finn Williams6f9f9902020-11-13 13:23:15 +0000482 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100483 return kTfLiteOk;
484}
485
Sadik Armagan62483be2020-10-23 17:14:43 +0100486TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100487{
Sadik Armagan62483be2020-10-23 17:14:43 +0100488 // Prepare inputs
489 armnn::InputTensors inputTensors;
490 size_t inputIndex = 0;
491 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
492 {
493 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
494 if (tensor->allocation_type != kTfLiteMmapRo)
495 {
496 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100497 armnn::TensorInfo inputTensorInfo = inputBinding.second;
498 inputTensorInfo.SetConstant(true);
499 const armnn::ConstTensor inputTensor(inputTensorInfo, tensor->data.data);
Sadik Armagan62483be2020-10-23 17:14:43 +0100500 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100501
Sadik Armagan62483be2020-10-23 17:14:43 +0100502 ++inputIndex;
503 }
504 }
505
506 // Prepare outputs
507 armnn::OutputTensors outputTensors;
508 size_t outputIndex = 0;
509 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
510 {
511 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
512 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
513 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
514 outputTensors.emplace_back(outputIdx, outputTensor);
515
516 ++outputIndex;
517 }
518
519 // Run graph
520 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
Colm Donelan45142282021-10-21 23:39:52 +0100521 // The delegate holds its own Arm NN runtime so this is our last chance to print internal profiling data.
522 std::shared_ptr<armnn::IProfiler> profiler = m_Runtime->GetProfiler(m_NetworkId);
523 if (profiler && profiler->IsProfilingEnabled())
524 {
525 profiler->Print(std::cout);
526 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100527 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100528}
529
Sadik Armagan62483be2020-10-23 17:14:43 +0100530TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100531 TfLiteContext* tfLiteContext,
532 TfLiteRegistration* tfLiteRegistration,
533 TfLiteNode* tfLiteNode,
534 int nodeIndex)
535{
Sadik Armagan62483be2020-10-23 17:14:43 +0100536 switch (tfLiteRegistration->builtin_code)
537 {
Ryan OShead21abaf2022-06-10 14:49:11 +0100538 case kTfLiteBuiltinCustom:
539 {
540#if defined(ARMNN_POST_TFLITE_2_5)
541 // Custom operators are defined by the name rather than the builtin code.
542 // Parse the custom_name param in the registration to point to the correct visitor function.
543 std::string customOperatorName = tfLiteRegistration->custom_name;
544 if ( customOperatorName == "AveragePool3D" )
545 {
546 return VisitPooling3dOperator(delegateData,
547 tfLiteContext,
548 tfLiteNode,
549 nodeIndex,
550 customOperatorName);
551 }
552 else if (customOperatorName == "MaxPool3D")
553 {
554 return VisitPooling3dOperator(delegateData,
555 tfLiteContext,
556 tfLiteNode,
557 nodeIndex,
558 customOperatorName);
559 }
560#endif
561 // Invalid or unsupported custom operator
562 return kTfLiteError;
563 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100564 case kTfLiteBuiltinAbs:
565 return VisitElementwiseUnaryOperator(delegateData,
566 tfLiteContext,
567 tfLiteNode,
568 nodeIndex,
569 armnn::UnaryOperation::Abs);
570 case kTfLiteBuiltinAdd:
571 return VisitElementwiseBinaryOperator(delegateData,
572 tfLiteContext,
573 tfLiteNode,
574 nodeIndex,
575 kTfLiteBuiltinAdd);
576 case kTfLiteBuiltinArgMax:
577 return VisitArgMinMaxOperator(delegateData,
578 tfLiteContext,
579 tfLiteNode,
580 nodeIndex,
581 kTfLiteBuiltinArgMax);
582 case kTfLiteBuiltinArgMin:
583 return VisitArgMinMaxOperator(delegateData,
584 tfLiteContext,
585 tfLiteNode,
586 nodeIndex,
587 kTfLiteBuiltinArgMin);
588 case kTfLiteBuiltinAveragePool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100589 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100590 tfLiteContext,
591 tfLiteNode,
592 nodeIndex,
593 kTfLiteBuiltinAveragePool2d);
Ryan OShea49ed0df2022-09-21 16:09:41 +0100594 case kTfLiteBuiltinBatchMatmul:
595 return VisitBatchMatMulOperator(delegateData,
596 tfLiteContext,
597 tfLiteNode,
598 nodeIndex,
599 kTfLiteBuiltinBatchMatmul);
Sadik Armagan62483be2020-10-23 17:14:43 +0100600 case kTfLiteBuiltinBatchToSpaceNd:
601 return VisitBatchToSpaceNdOperator(delegateData,
602 tfLiteContext,
603 tfLiteNode,
604 nodeIndex,
605 kTfLiteBuiltinBatchToSpaceNd);
Sadik Armagan937565b2021-04-21 14:03:28 +0100606 case kTfLiteBuiltinCast:
607 return VisitCastOperator(delegateData,
608 tfLiteContext,
609 tfLiteNode,
610 nodeIndex,
611 kTfLiteBuiltinCast);
Teresa Charlin93f0ad02023-03-23 15:28:02 +0000612 case kTfLiteBuiltinCeil:
613 return VisitElementwiseUnaryOperator(delegateData,
614 tfLiteContext,
615 tfLiteNode,
616 nodeIndex,
617 armnn::UnaryOperation::Ceil);
Sadik Armagan62483be2020-10-23 17:14:43 +0100618 case kTfLiteBuiltinConcatenation:
619 return VisitControlOperator(delegateData,
620 tfLiteContext,
621 tfLiteNode,
622 nodeIndex,
623 kTfLiteBuiltinConcatenation);
624 case kTfLiteBuiltinConv2d:
625 return VisitConvolutionOperator(delegateData,
626 tfLiteContext,
627 tfLiteNode,
628 nodeIndex,
629 kTfLiteBuiltinConv2d);
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100630// Conv3d is only correctly supported for external delegates from TF Lite v2.6, as there was a breaking bug in v2.5.
631#if defined(ARMNN_POST_TFLITE_2_5)
632 case kTfLiteBuiltinConv3d:
633 return VisitConvolutionOperator(delegateData,
634 tfLiteContext,
635 tfLiteNode,
636 nodeIndex,
637 kTfLiteBuiltinConv3d);
638#endif
Sadik Armagan62483be2020-10-23 17:14:43 +0100639 case kTfLiteBuiltinDepthToSpace:
640 return VisitDepthToSpaceOperator(delegateData,
641 tfLiteContext,
642 tfLiteNode,
643 nodeIndex,
644 kTfLiteBuiltinDepthToSpace);
645 case kTfLiteBuiltinDepthwiseConv2d:
646 return VisitConvolutionOperator(delegateData,
647 tfLiteContext,
648 tfLiteNode,
649 nodeIndex,
650 kTfLiteBuiltinDepthwiseConv2d);
651 case kTfLiteBuiltinDequantize:
652 return VisitDequantizeOperator(delegateData,
653 tfLiteContext,
654 tfLiteNode,
655 nodeIndex,
656 kTfLiteBuiltinDequantize);
657 case kTfLiteBuiltinDiv:
658 return VisitElementwiseBinaryOperator(delegateData,
659 tfLiteContext,
660 tfLiteNode,
661 nodeIndex,
662 kTfLiteBuiltinDiv);
663 case kTfLiteBuiltinElu:
664 return VisitActivationOperator(delegateData,
665 tfLiteContext,
666 tfLiteNode,
667 nodeIndex,
668 kTfLiteBuiltinElu);
669 case kTfLiteBuiltinEqual:
670 return VisitComparisonOperator(delegateData,
671 tfLiteContext,
672 tfLiteNode,
673 nodeIndex,
674 kTfLiteBuiltinEqual);
675 case kTfLiteBuiltinExp:
676 return VisitElementwiseUnaryOperator(delegateData,
677 tfLiteContext,
678 tfLiteNode,
679 nodeIndex,
680 armnn::UnaryOperation::Exp);
681 case kTfLiteBuiltinExpandDims:
682 return VisitExpandDimsOperator(delegateData,
683 tfLiteContext,
684 tfLiteNode,
685 nodeIndex,
686 kTfLiteBuiltinExpandDims);
687 case kTfLiteBuiltinFill:
688 return VisitFillOperator(delegateData,
689 tfLiteContext,
690 tfLiteNode,
691 nodeIndex,
692 kTfLiteBuiltinFill);
693 case kTfLiteBuiltinFloor:
694 return VisitFloorOperator(delegateData,
695 tfLiteContext,
696 tfLiteNode,
697 nodeIndex,
698 kTfLiteBuiltinFloor);
Jim Flynn4b2f3472021-10-13 21:20:07 +0100699 case kTfLiteBuiltinFloorDiv:
700 return VisitElementwiseBinaryOperator(delegateData,
701 tfLiteContext,
702 tfLiteNode,
703 nodeIndex,
704 kTfLiteBuiltinFloorDiv);
Sadik Armagan62483be2020-10-23 17:14:43 +0100705 case kTfLiteBuiltinFullyConnected:
706 return VisitFullyConnectedOperator(delegateData,
707 tfLiteContext,
708 tfLiteNode,
709 nodeIndex,
710 kTfLiteBuiltinFullyConnected);
711 case kTfLiteBuiltinGather:
712 return VisitGatherOperator(delegateData,
713 tfLiteContext,
714 tfLiteNode,
715 nodeIndex,
716 kTfLiteBuiltinGather);
Teresa Charlind5c0ed22022-04-25 18:23:41 +0100717 case kTfLiteBuiltinGatherNd:
718 return VisitGatherNdOperator(delegateData,
719 tfLiteContext,
720 tfLiteNode,
721 nodeIndex,
722 kTfLiteBuiltinGatherNd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100723 case kTfLiteBuiltinGreater:
724 return VisitComparisonOperator(delegateData,
725 tfLiteContext,
726 tfLiteNode,
727 nodeIndex,
728 kTfLiteBuiltinGreater);
729 case kTfLiteBuiltinGreaterEqual:
730 return VisitComparisonOperator(delegateData,
731 tfLiteContext,
732 tfLiteNode,
733 nodeIndex,
734 kTfLiteBuiltinGreaterEqual);
735 case kTfLiteBuiltinHardSwish:
736 return VisitActivationOperator(delegateData,
737 tfLiteContext,
738 tfLiteNode,
739 nodeIndex,
740 kTfLiteBuiltinHardSwish);
741 case kTfLiteBuiltinL2Normalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000742 return VisitL2NormalizationOperator(delegateData,
743 tfLiteContext,
744 tfLiteNode,
745 nodeIndex,
746 kTfLiteBuiltinL2Normalization);
Sadik Armagan62483be2020-10-23 17:14:43 +0100747 case kTfLiteBuiltinL2Pool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100748 return VisitPooling2dOperator(delegateData,
Tianle Chengae931732023-07-28 11:53:04 +0100749 tfLiteContext,
750 tfLiteNode,
751 nodeIndex,
752 kTfLiteBuiltinL2Pool2d);
753 case kTfLiteBuiltinLeakyRelu:
754 return VisitActivationOperator(delegateData,
755 tfLiteContext,
756 tfLiteNode,
757 nodeIndex,
758 kTfLiteBuiltinLeakyRelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100759 case kTfLiteBuiltinLess:
760 return VisitComparisonOperator(delegateData,
761 tfLiteContext,
762 tfLiteNode,
763 nodeIndex,
764 kTfLiteBuiltinLess);
765 case kTfLiteBuiltinLessEqual:
766 return VisitComparisonOperator(delegateData,
767 tfLiteContext,
768 tfLiteNode,
769 nodeIndex,
770 kTfLiteBuiltinLessEqual);
771 case kTfLiteBuiltinLocalResponseNormalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000772 return VisitLocalResponseNormalizationOperator(delegateData,
773 tfLiteContext,
774 tfLiteNode,
775 nodeIndex,
776 kTfLiteBuiltinLocalResponseNormalization);
Teresa Charlinb1f5f702022-07-12 14:16:24 +0100777 case kTfLiteBuiltinLog:
778 return VisitElementwiseUnaryOperator(delegateData,
779 tfLiteContext,
780 tfLiteNode,
781 nodeIndex,
782 armnn::UnaryOperation::Log);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000783 case kTfLiteBuiltinLogicalAnd:
784 return VisitLogicalBinaryOperator(delegateData,
785 tfLiteContext,
786 tfLiteNode,
787 nodeIndex,
788 kTfLiteBuiltinLogicalAnd,
789 armnn::LogicalBinaryOperation::LogicalAnd);
790 case kTfLiteBuiltinLogicalNot:
791 return VisitElementwiseUnaryOperator(delegateData,
792 tfLiteContext,
793 tfLiteNode,
794 nodeIndex,
795 armnn::UnaryOperation::LogicalNot);
796 case kTfLiteBuiltinLogicalOr:
797 return VisitLogicalBinaryOperator(delegateData,
798 tfLiteContext,
799 tfLiteNode,
800 nodeIndex,
801 kTfLiteBuiltinLogicalOr,
802 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100803 case kTfLiteBuiltinLogistic:
804 return VisitActivationOperator(delegateData,
805 tfLiteContext,
806 tfLiteNode,
807 nodeIndex,
808 kTfLiteBuiltinLogistic);
809 case kTfLiteBuiltinLogSoftmax:
810 return VisitSoftmaxOperator(delegateData,
811 tfLiteContext,
812 tfLiteNode,
813 nodeIndex,
814 kTfLiteBuiltinLogSoftmax);
815 case kTfLiteBuiltinLstm:
816 return VisitLstmOperator(delegateData,
817 tfLiteContext,
818 tfLiteNode,
819 nodeIndex,
820 kTfLiteBuiltinLstm);
821 case kTfLiteBuiltinMaxPool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100822 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100823 tfLiteContext,
824 tfLiteNode,
825 nodeIndex,
826 kTfLiteBuiltinMaxPool2d);
827 case kTfLiteBuiltinMaximum:
828 return VisitElementwiseBinaryOperator(delegateData,
829 tfLiteContext,
830 tfLiteNode,
831 nodeIndex,
832 kTfLiteBuiltinMaximum);
833 case kTfLiteBuiltinMean:
834 return VisitControlOperator(delegateData,
835 tfLiteContext,
836 tfLiteNode,
837 nodeIndex,
838 kTfLiteBuiltinMean);
839 case kTfLiteBuiltinMinimum:
840 return VisitElementwiseBinaryOperator(delegateData,
841 tfLiteContext,
842 tfLiteNode,
843 nodeIndex,
844 kTfLiteBuiltinMinimum);
Matthew Sloyanaf3a4ef2021-10-22 15:48:12 +0100845 case kTfLiteBuiltinMirrorPad:
846 return VisitPadOperator(delegateData,
847 tfLiteContext,
848 tfLiteNode,
849 nodeIndex,
850 kTfLiteBuiltinMirrorPad);
Sadik Armagan62483be2020-10-23 17:14:43 +0100851 case kTfLiteBuiltinMul:
852 return VisitElementwiseBinaryOperator(delegateData,
853 tfLiteContext,
854 tfLiteNode,
855 nodeIndex,
856 kTfLiteBuiltinMul);
857 case kTfLiteBuiltinNeg:
858 return VisitElementwiseUnaryOperator(delegateData,
859 tfLiteContext,
860 tfLiteNode,
861 nodeIndex,
862 armnn::UnaryOperation::Neg);
863 case kTfLiteBuiltinNotEqual:
864 return VisitComparisonOperator(delegateData,
865 tfLiteContext,
866 tfLiteNode,
867 nodeIndex,
868 kTfLiteBuiltinNotEqual);
Matthew Sloyana7a12f52021-05-06 10:05:28 +0100869 case kTfLiteBuiltinPack:
870 return VisitPackOperator(delegateData,
871 tfLiteContext,
872 tfLiteNode,
873 nodeIndex,
874 kTfLiteBuiltinPack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100875 case kTfLiteBuiltinPad:
876 return VisitPadOperator(delegateData,
877 tfLiteContext,
878 tfLiteNode,
879 nodeIndex,
880 kTfLiteBuiltinPad);
881 case kTfLiteBuiltinPadv2:
882 return VisitPadOperator(delegateData,
883 tfLiteContext,
884 tfLiteNode,
885 nodeIndex,
886 kTfLiteBuiltinPadv2);
John Mcloughlin0ec00872023-05-15 17:03:49 +0100887 case kTfLiteBuiltinPow:
888 return VisitElementwiseBinaryOperator(delegateData,
889 tfLiteContext,
890 tfLiteNode,
891 nodeIndex,
892 kTfLiteBuiltinPow);
Sadik Armagan62483be2020-10-23 17:14:43 +0100893 case kTfLiteBuiltinPrelu:
James Conroy39825482021-05-27 17:44:50 +0100894 return VisitPreluOperator(delegateData,
895 tfLiteContext,
896 tfLiteNode,
897 nodeIndex,
898 kTfLiteBuiltinPrelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100899 case kTfLiteBuiltinQuantize:
900 return VisitQuantizeOperator(delegateData,
901 tfLiteContext,
902 tfLiteNode,
903 nodeIndex,
904 kTfLiteBuiltinQuantize);
905 case kTfLiteBuiltinRank:
906 return VisitControlOperator(delegateData,
907 tfLiteContext,
908 tfLiteNode,
909 nodeIndex,
910 kTfLiteBuiltinRank);
Sadik Armagana2747482021-02-09 10:28:54 +0000911 case kTfLiteBuiltinReduceMax:
912 return VisitReduceOperator(delegateData,
913 tfLiteContext,
914 tfLiteNode,
915 nodeIndex,
916 kTfLiteBuiltinReduceMax);
917 case kTfLiteBuiltinReduceMin:
918 return VisitReduceOperator(delegateData,
919 tfLiteContext,
920 tfLiteNode,
921 nodeIndex,
922 kTfLiteBuiltinReduceMin);
Teresa Charlin4e3e8312021-08-05 12:34:37 +0100923 case kTfLiteBuiltinReduceProd:
924 return VisitReduceOperator(delegateData,
925 tfLiteContext,
926 tfLiteNode,
927 nodeIndex,
928 kTfLiteBuiltinReduceProd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100929 case kTfLiteBuiltinRelu:
930 return VisitActivationOperator(delegateData,
931 tfLiteContext,
932 tfLiteNode,
933 nodeIndex,
934 kTfLiteBuiltinRelu);
935 case kTfLiteBuiltinReluN1To1:
936 return VisitActivationOperator(delegateData,
937 tfLiteContext,
938 tfLiteNode,
939 nodeIndex,
940 kTfLiteBuiltinReluN1To1);
941 case kTfLiteBuiltinRelu6:
942 return VisitActivationOperator(delegateData,
943 tfLiteContext,
944 tfLiteNode,
945 nodeIndex,
946 kTfLiteBuiltinRelu6);
947 case kTfLiteBuiltinReshape:
948 return VisitReshapeOperator(delegateData,
949 tfLiteContext,
950 tfLiteNode,
951 nodeIndex,
952 kTfLiteBuiltinReshape);
953 case kTfLiteBuiltinResizeBilinear:
954 return VisitResizeOperator(delegateData,
955 tfLiteContext,
956 tfLiteNode,
957 nodeIndex,
958 kTfLiteBuiltinResizeBilinear);
959 case kTfLiteBuiltinResizeNearestNeighbor:
960 return VisitResizeOperator(delegateData,
961 tfLiteContext,
962 tfLiteNode,
963 nodeIndex,
964 kTfLiteBuiltinResizeNearestNeighbor);
Tracy Narine7306bbe2023-07-17 16:06:26 +0100965 case kTfLiteBuiltinReverseV2:
966 return VisitReverseV2Operator(delegateData,
967 tfLiteContext,
968 tfLiteNode,
969 nodeIndex,
970 kTfLiteBuiltinReverseV2);
Sadik Armagan62483be2020-10-23 17:14:43 +0100971 case kTfLiteBuiltinRsqrt:
972 return VisitElementwiseUnaryOperator(delegateData,
973 tfLiteContext,
974 tfLiteNode,
975 nodeIndex,
976 armnn::UnaryOperation::Rsqrt);
Keith Davis0176fd82021-06-01 17:36:32 +0100977 case kTfLiteBuiltinShape:
978 return VisitShapeOperator(delegateData,
979 tfLiteContext,
980 tfLiteNode,
981 nodeIndex,
982 kTfLiteBuiltinShape);
Teresa Charlinb1f5f702022-07-12 14:16:24 +0100983 case kTfLiteBuiltinSin:
984 return VisitElementwiseUnaryOperator(delegateData,
985 tfLiteContext,
986 tfLiteNode,
987 nodeIndex,
988 armnn::UnaryOperation::Sin);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +0000989 case kTfLiteBuiltinSplit:
990 return VisitSplitOperator(delegateData,
991 tfLiteContext,
992 tfLiteNode,
993 nodeIndex,
994 kTfLiteBuiltinSplit);
995 case kTfLiteBuiltinSplitV:
996 return VisitSplitVOperator(delegateData,
997 tfLiteContext,
998 tfLiteNode,
999 nodeIndex,
1000 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +01001001 case kTfLiteBuiltinSqrt:
1002 return VisitElementwiseUnaryOperator(delegateData,
1003 tfLiteContext,
1004 tfLiteNode,
1005 nodeIndex,
1006 armnn::UnaryOperation::Sqrt);
John Mcloughlin0ec00872023-05-15 17:03:49 +01001007 case kTfLiteBuiltinSquaredDifference:
1008 return VisitElementwiseBinaryOperator(delegateData,
1009 tfLiteContext,
1010 tfLiteNode,
1011 nodeIndex,
1012 kTfLiteBuiltinSquaredDifference);
Sadik Armagan62483be2020-10-23 17:14:43 +01001013 case kTfLiteBuiltinSqueeze:
1014 return VisitSqueezeOperator(delegateData,
1015 tfLiteContext,
1016 tfLiteNode,
1017 nodeIndex,
1018 kTfLiteBuiltinSqueeze);
Cathal Corbett839b9322022-11-18 08:52:18 +00001019 case kTfLiteBuiltinSlice:
Sadik Armagan62483be2020-10-23 17:14:43 +01001020 return VisitSliceOperator(delegateData,
1021 tfLiteContext,
1022 tfLiteNode,
1023 nodeIndex,
Cathal Corbett839b9322022-11-18 08:52:18 +00001024 kTfLiteBuiltinSlice);
1025 case kTfLiteBuiltinStridedSlice:
1026 return VisitStridedSliceOperator(delegateData,
1027 tfLiteContext,
1028 tfLiteNode,
1029 nodeIndex,
1030 kTfLiteBuiltinStridedSlice);
Sadik Armagana2747482021-02-09 10:28:54 +00001031 case kTfLiteBuiltinSum:
1032 return VisitReduceOperator(delegateData,
1033 tfLiteContext,
1034 tfLiteNode,
1035 nodeIndex,
1036 kTfLiteBuiltinSum);
Sadik Armagan62483be2020-10-23 17:14:43 +01001037 case kTfLiteBuiltinTranspose:
1038 return VisitTransposeOperator(delegateData,
1039 tfLiteContext,
1040 tfLiteNode,
1041 nodeIndex,
1042 kTfLiteBuiltinTranspose);
1043 case kTfLiteBuiltinTransposeConv:
1044 return VisitConvolutionOperator(delegateData,
1045 tfLiteContext,
1046 tfLiteNode,
1047 nodeIndex,
1048 kTfLiteBuiltinTransposeConv);
1049 case kTfLiteBuiltinSoftmax:
1050 return VisitSoftmaxOperator(delegateData,
1051 tfLiteContext,
1052 tfLiteNode,
1053 nodeIndex,
1054 kTfLiteBuiltinSoftmax);
1055 case kTfLiteBuiltinSpaceToBatchNd:
1056 return VisitSpaceToBatchNdOperator(delegateData,
1057 tfLiteContext,
1058 tfLiteNode,
1059 nodeIndex,
1060 kTfLiteBuiltinSpaceToBatchNd);
1061 case kTfLiteBuiltinSpaceToDepth:
1062 return VisitSpaceToDepthOperator(delegateData,
1063 tfLiteContext,
1064 tfLiteNode,
1065 nodeIndex,
1066 kTfLiteBuiltinSpaceToDepth);
1067 case kTfLiteBuiltinSub:
1068 return VisitElementwiseBinaryOperator(delegateData,
1069 tfLiteContext,
1070 tfLiteNode,
1071 nodeIndex,
1072 kTfLiteBuiltinSub);
1073 case kTfLiteBuiltinTanh:
1074 return VisitActivationOperator(delegateData,
1075 tfLiteContext,
1076 tfLiteNode,
1077 nodeIndex,
1078 kTfLiteBuiltinTanh);
Tianle Cheng92ce35c2023-07-25 16:41:00 +01001079 case kTfLiteBuiltinTile:
1080 return VisitTileOperator(delegateData,
1081 tfLiteContext,
1082 tfLiteNode,
1083 nodeIndex,
1084 kTfLiteBuiltinTile);
Narumol Prangnawarat7684b182021-08-12 14:48:15 +01001085 case kTfLiteBuiltinUnidirectionalSequenceLstm:
1086 return VisitUnidirectionalSequenceLstmOperator(delegateData,
1087 tfLiteContext,
1088 tfLiteNode,
1089 nodeIndex,
1090 kTfLiteBuiltinUnidirectionalSequenceLstm);
Kevin May8ab2d7a2021-05-07 09:32:51 +01001091 case kTfLiteBuiltinUnpack:
1092 return VisitUnpackOperator(delegateData,
1093 tfLiteContext,
1094 tfLiteNode,
1095 nodeIndex,
1096 kTfLiteBuiltinUnpack);
Sadik Armagan62483be2020-10-23 17:14:43 +01001097 default:
1098 return kTfLiteError;
1099 }
Sadik Armagan3c24f432020-10-19 17:35:30 +01001100}
1101
1102} // armnnDelegate namespace