blob: 52621ee6c106b6f8876207e6731d7d5273399fed [file] [log] [blame]
Sadik Armagan3c24f432020-10-19 17:35:30 +01001//
Colm Donelan253d1bb2024-03-04 22:19:26 +00002// Copyright © 2020-2024 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"
Idriss Chaouchcbf79292023-09-08 11:18:16 +010014#include "BroadcastTo.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010015#include "Comparison.hpp"
16#include "Convolution.hpp"
17#include "Control.hpp"
18#include "ElementwiseBinary.hpp"
19#include "ElementwiseUnary.hpp"
20#include "Fill.hpp"
21#include "FullyConnected.hpp"
22#include "Gather.hpp"
Teresa Charlind5c0ed22022-04-25 18:23:41 +010023#include "GatherNd.hpp"
Matthew Sloyanc8eb9552020-11-26 10:54:22 +000024#include "LogicalBinary.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010025#include "Lstm.hpp"
26#include "Normalization.hpp"
Matthew Sloyana7a12f52021-05-06 10:05:28 +010027#include "Pack.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010028#include "Pad.hpp"
29#include "Pooling.hpp"
James Conroy39825482021-05-27 17:44:50 +010030#include "Prelu.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010031#include "Quantization.hpp"
32#include "Redefine.hpp"
Sadik Armagana2747482021-02-09 10:28:54 +000033#include "Reduce.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010034#include "Resize.hpp"
Tracy Narine7306bbe2023-07-17 16:06:26 +010035#include "ReverseV2.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010036#include "Round.hpp"
Kevin May93bbf002024-03-11 09:31:10 +000037#include "ScatterNd.hpp"
Keith Davis0176fd82021-06-01 17:36:32 +010038#include "Shape.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010039#include "Slice.hpp"
Cathal Corbett839b9322022-11-18 08:52:18 +000040#include "StridedSlice.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010041#include "Softmax.hpp"
42#include "SpaceDepth.hpp"
Sadik Armagan34fa1bd2020-11-27 12:40:52 +000043#include "Split.hpp"
Tianle Cheng92ce35c2023-07-25 16:41:00 +010044#include "Tile.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010045#include "Transpose.hpp"
Narumol Prangnawarat7684b182021-08-12 14:48:15 +010046#include "UnidirectionalSequenceLstm.hpp"
Kevin May8ab2d7a2021-05-07 09:32:51 +010047#include "Unpack.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010048
Colm Donelan3e32a872021-10-04 22:55:37 +010049#include <armnnUtils/Filesystem.hpp>
Jan Eilers17d34da2021-12-08 16:15:12 +000050#include <armnn/utility/Timer.hpp>
Sadik Armagan62483be2020-10-23 17:14:43 +010051#include <flatbuffers/flatbuffers.h>
52#include <tensorflow/lite/context_util.h>
Jim Flynn4b2f3472021-10-13 21:20:07 +010053#include <tensorflow/lite/schema/schema_generated.h>
Sadik Armagan62483be2020-10-23 17:14:43 +010054
Sadik Armagan3c24f432020-10-19 17:35:30 +010055#include <algorithm>
Matthew Sloyanac001ee2021-02-03 10:43:04 +000056#include <iostream>
Sadik Armagan62483be2020-10-23 17:14:43 +010057#include <sstream>
Sadik Armagan3c24f432020-10-19 17:35:30 +010058
59namespace armnnDelegate
60{
61
Sadik Armagan62483be2020-10-23 17:14:43 +010062DelegateOptions TfLiteArmnnDelegateOptionsDefault()
63{
64 DelegateOptions options(armnn::Compute::CpuRef);
65 return options;
66}
67
68TfLiteDelegate* TfLiteArmnnDelegateCreate(armnnDelegate::DelegateOptions options)
69{
70 auto* armnnDelegate = new ::armnnDelegate::Delegate(options);
71 return armnnDelegate->GetDelegate();
72}
73
74void TfLiteArmnnDelegateDelete(TfLiteDelegate* tfLiteDelegate)
75{
76 if (tfLiteDelegate != nullptr)
77 {
78 delete static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_);
79 }
80}
81
82TfLiteStatus DoPrepare(TfLiteContext* tfLiteContext, TfLiteDelegate* tfLiteDelegate)
83{
84 TfLiteIntArray* supportedOperators =
85 static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_)->IdentifyOperatorsToDelegate(tfLiteContext);
86
87 // ArmNN Delegate Registration
88 static const TfLiteRegistration kArmnnSubgraphRegistration = {
89 // ArmnnSubgraph Init
90 .init = [](TfLiteContext* tfLiteContext, const char* buffer, size_t length) -> void* {
Finn Williams6f9f9902020-11-13 13:23:15 +000091 armnn::IgnoreUnused(length);
Sadik Armagan62483be2020-10-23 17:14:43 +010092 const TfLiteDelegateParams* parameters = reinterpret_cast<const TfLiteDelegateParams*>(buffer);
93
94 return static_cast<void*>(ArmnnSubgraph::Create(
95 tfLiteContext, parameters, static_cast<::armnnDelegate::Delegate*>(parameters->delegate->data_)));
96 },
97 // ArmnnSubgraph Free
98 .free = [](TfLiteContext* tfLiteContext, void* buffer) -> void {
Finn Williams6f9f9902020-11-13 13:23:15 +000099 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan62483be2020-10-23 17:14:43 +0100100 if (buffer != nullptr)
101 {
102 delete static_cast<ArmnnSubgraph*>(buffer);
103 }
104 },
105 // ArmnnSubgraph Prepare
106 .prepare = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
107 if (tfLiteNode->user_data == nullptr)
108 {
109 return kTfLiteError;
110 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100111 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Prepare(tfLiteContext);
112 },
113 // ArmnnSubgraph Invoke
114 .invoke = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
115 if (tfLiteNode->user_data == nullptr)
116 {
117 return kTfLiteError;
118 }
119
120 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Invoke(tfLiteContext, tfLiteNode);
121 },
122
123 .profiling_string = nullptr,
124 .builtin_code = kTfLiteBuiltinDelegate,
125 .custom_name = "TfLiteArmNnDelegate",
126 .version = 1,
Colm Donelan718966f2022-10-10 10:06:12 +0100127 .registration_external = nullptr,
Matthew Sloyan76d0c4c2023-09-07 14:48:56 +0100128 .async_kernel = nullptr,
129 .inplace_operator = 0
Sadik Armagan62483be2020-10-23 17:14:43 +0100130 };
131
132 const TfLiteStatus status =
133 tfLiteContext->ReplaceNodeSubsetsWithDelegateKernels(
134 tfLiteContext, kArmnnSubgraphRegistration, supportedOperators, tfLiteDelegate);
135
136 TfLiteIntArrayFree(supportedOperators);
137 return status;
138
139}
140
Sadik Armagan3c24f432020-10-19 17:35:30 +0100141Delegate::Delegate(armnnDelegate::DelegateOptions options)
Mike Kelly5446a4d2023-01-20 15:51:05 +0000142 : m_Options(std::move(options))
Sadik Armagan3c24f432020-10-19 17:35:30 +0100143{
Jan Eilers2cd18472020-12-15 10:42:38 +0000144 // Configures logging for ARMNN
Colm Donelanda7f2f92022-12-20 16:21:35 +0000145 if (m_Options.IsLoggingEnabled())
Jan Eilers2cd18472020-12-15 10:42:38 +0000146 {
Colm Donelanda7f2f92022-12-20 16:21:35 +0000147 armnn::ConfigureLogging(true, true, m_Options.GetLoggingSeverity());
Jan Eilers2cd18472020-12-15 10:42:38 +0000148 }
Mike Kelly5446a4d2023-01-20 15:51:05 +0000149 // Create/Get the static ArmNN Runtime. Note that the m_Runtime will be shared by all armnn_delegate
150 // instances so the RuntimeOptions cannot be altered for different armnn_delegate instances.
151 m_Runtime = GetRuntime(m_Options.GetRuntimeOptions());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100152 std::vector<armnn::BackendId> backends;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100153 if (m_Runtime)
154 {
155 const armnn::BackendIdSet supportedDevices = m_Runtime->GetDeviceSpec().GetSupportedBackends();
156 for (auto& backend : m_Options.GetBackends())
157 {
158 if (std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) == supportedDevices.cend())
159 {
Sadik Armagan0534e032020-10-27 17:30:18 +0000160 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100161 "TfLiteArmnnDelegate: Requested unknown backend %s", backend.Get().c_str());
162 }
163 else
164 {
165 backends.push_back(backend);
Kevin May0425a372023-11-03 12:06:04 +0000166 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
167 "TfLiteArmnnDelegate: Added backend %s", backend.Get().c_str());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100168 }
169 }
170 }
171
172 if (backends.empty())
173 {
174 // No known backend specified
175 throw armnn::InvalidArgumentException("TfLiteArmnnDelegate: No known backend specified.");
176 }
177 m_Options.SetBackends(backends);
178
179 TFLITE_LOG_PROD_ONCE(tflite::TFLITE_LOG_INFO, "TfLiteArmnnDelegate: Created TfLite ArmNN delegate.");
180}
181
Sadik Armagan62483be2020-10-23 17:14:43 +0100182TfLiteIntArray* Delegate::IdentifyOperatorsToDelegate(TfLiteContext* tfLiteContext)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100183{
184 TfLiteIntArray* executionPlan = nullptr;
185 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
186 {
187 TF_LITE_KERNEL_LOG(tfLiteContext, "TfLiteArmnnDelegate: Unable to get graph execution plan.");
188 return nullptr;
189 }
190
Sadik Armagan62483be2020-10-23 17:14:43 +0100191 // Delegate data with null network
192 DelegateData delegateData(m_Options.GetBackends());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100193
194 TfLiteIntArray* nodesToDelegate = TfLiteIntArrayCreate(executionPlan->size);
195 nodesToDelegate->size = 0;
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000196
197 std::set<int32_t> unsupportedOperators;
198
Sadik Armagan3c24f432020-10-19 17:35:30 +0100199 for (int i = 0; i < executionPlan->size; ++i)
200 {
201 const int nodeIndex = executionPlan->data[i];
202
203 // If TfLite nodes can be delegated to ArmNN
204 TfLiteNode* tfLiteNode = nullptr;
205 TfLiteRegistration* tfLiteRegistration = nullptr;
206 if (tfLiteContext->GetNodeAndRegistration(
207 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
208 {
209 TF_LITE_KERNEL_LOG(tfLiteContext,
210 "TfLiteArmnnDelegate: Unable to get node and registration for node %d.",
211 nodeIndex);
212 continue;
213 }
214
Ryan OShea05b6a3e2023-01-11 15:27:50 +0000215 TfLiteStatus visitStatus;
216
217 try
218 {
219 visitStatus = ArmnnSubgraph::VisitNode(
220 delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex);
221 }
222 catch(std::exception& ex)
223 {
224 ARMNN_LOG(error) << "ArmNN Failed to visit node with error: " << ex.what();
225 visitStatus = kTfLiteError;
Ciara Sookarry39436152023-10-31 15:44:41 +0000226 TF_LITE_KERNEL_LOG(tfLiteContext,
227 "Exception text: %s",
228 ex.what());
Ryan OShea05b6a3e2023-01-11 15:27:50 +0000229 }
230
231 if ( visitStatus != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100232 {
233 // node is not supported by ArmNN
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000234 unsupportedOperators.insert(tfLiteRegistration->builtin_code);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100235 continue;
236 }
237
238 nodesToDelegate->data[nodesToDelegate->size++] = nodeIndex;
239 }
240
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000241 for (std::set<int32_t>::iterator it=unsupportedOperators.begin(); it!=unsupportedOperators.end(); ++it)
242 {
243 TF_LITE_KERNEL_LOG(tfLiteContext,
244 "Operator %s [%d] is not supported by armnn_delegate.",
245 tflite::EnumNameBuiltinOperator(tflite::BuiltinOperator(*it)),
246 *it);
247 }
248
Sadik Armaganca565c12022-08-16 12:17:24 +0100249 if (!unsupportedOperators.empty() && m_Options.TfLiteRuntimeFallbackDisabled())
250 {
251 std::stringstream exMessage;
252 exMessage << "TfLiteArmnnDelegate: There are unsupported operators in the model. ";
253 exMessage << "Not falling back to TfLite Runtime as fallback is disabled. ";
254 exMessage << "This should only be disabled under test conditions.";
255 throw armnn::Exception(exMessage.str());
256 }
Colm Donelan3811a972023-01-25 21:19:49 +0000257 if (nodesToDelegate->size == 0)
258 {
259 ARMNN_LOG(info) << "No operators in this model are supported by the Arm NN TfLite delegate." <<
260 " The model will be executed entirely by TfLite runtime.";
261 }
Sadik Armaganca565c12022-08-16 12:17:24 +0100262
Sadik Armagan62483be2020-10-23 17:14:43 +0100263 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100264 return nodesToDelegate;
265}
266
267TfLiteDelegate* Delegate::GetDelegate()
268{
269 return &m_Delegate;
270}
271
Matthew Sloyanac001ee2021-02-03 10:43:04 +0000272const std::string Delegate::GetVersion()
273{
274 return DELEGATE_VERSION;
275}
276
Colm Donelan253d1bb2024-03-04 22:19:26 +0000277ArmnnSubgraph::~ArmnnSubgraph()
278{
279 // The delegate holds its own Arm NN runtime so this is our last chance to print internal profiling data.
280 std::shared_ptr<armnn::IProfiler> profiler = m_Runtime->GetProfiler(m_NetworkId);
281 if (profiler && profiler->IsProfilingEnabled())
282 {
283 profiler->Print(std::cout);
284 }
285}
286
Sadik Armagan62483be2020-10-23 17:14:43 +0100287TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
288 TfLiteContext* tfLiteContext,
289 const TfLiteIntArray* inputs,
290 std::vector<armnn::BindingPointInfo>& inputBindings)
291{
Finn Williams6f9f9902020-11-13 13:23:15 +0000292 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100293 for (unsigned int i = 0; i < numInputs; ++i)
294 {
295 const int32_t tensorId = inputs->data[i];
296 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000297 // Do not create bindings for constant inputs
298 if (tensor.allocation_type == kTfLiteMmapRo)
299 {
300 continue;
301 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100302
303 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
304 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
305
306 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
307 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
308 outputSlot.SetTensorInfo(tensorInfo);
309
310 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000311 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100312
Sadik Armagan6e36a642020-11-10 21:18:41 +0000313 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100314 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000315
Sadik Armagan62483be2020-10-23 17:14:43 +0100316 return kTfLiteOk;
317}
318
319TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
320 TfLiteContext* tfLiteContext,
321 const TfLiteIntArray* outputs,
322 std::vector<armnn::BindingPointInfo>& outputBindings)
323{
Finn Williams6f9f9902020-11-13 13:23:15 +0000324 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100325 for (unsigned int i = 0; i < numOutputs; ++i)
326 {
327 const int32_t tensorId = outputs->data[i];
328 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
329
330 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
331 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
332
333 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Ryan OSheac229b3f2023-06-27 22:34:54 +0100334
335 if (delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] == nullptr)
336 {
337 return kTfLiteError;
338 }
339
Finn Williams6f9f9902020-11-13 13:23:15 +0000340 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100341 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
342 }
343
344 return kTfLiteOk;
345}
346
Sadik Armagan3c24f432020-10-19 17:35:30 +0100347ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
348 const TfLiteDelegateParams* parameters,
349 const Delegate* delegate)
350{
Jan Eilers17d34da2021-12-08 16:15:12 +0000351 const auto startTime = armnn::GetTimeNow();
352 ARMNN_LOG(info) << "ArmnnSubgraph creation";
353
Sadik Armagan3c24f432020-10-19 17:35:30 +0100354 TfLiteIntArray* executionPlan;
355 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
356 {
357 return nullptr;
358 }
359
Sadik Armagan62483be2020-10-23 17:14:43 +0100360 // Initialize DelegateData holds network and output slots information
361 DelegateData delegateData(delegate->m_Options.GetBackends());
362
363 // Build ArmNN Network
John Mcloughlinc5ee0d72023-03-24 12:07:25 +0000364 armnn::NetworkOptions networkOptions = delegate->m_Options.GetOptimizerOptions().GetModelOptions();
Sadik Armagan3c24f432020-10-19 17:35:30 +0100365 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100366 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100367
Sadik Armagan6e36a642020-11-10 21:18:41 +0000368 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
369
Sadik Armagan62483be2020-10-23 17:14:43 +0100370 std::vector<armnn::BindingPointInfo> inputBindings;
371 std::vector<armnn::BindingPointInfo> outputBindings;
372
373 // Add input layer
374 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
375 if (status != kTfLiteOk)
376 {
377 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
378 }
379
380 // Parse TfLite delegate nodes to ArmNN
Jan Eilers17d34da2021-12-08 16:15:12 +0000381 const auto parseStartTime = armnn::GetTimeNow();
Sadik Armagan3c24f432020-10-19 17:35:30 +0100382 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
383 {
384 const int nodeIndex = parameters->nodes_to_replace->data[i];
385
386 TfLiteNode* tfLiteNode = nullptr;
387 TfLiteRegistration* tfLiteRegistration = nullptr;
388 if (tfLiteContext->GetNodeAndRegistration(
389 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
390 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000391 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100392 }
393
Sadik Armagan62483be2020-10-23 17:14:43 +0100394 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100395 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000396 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100397 }
398 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000399 ARMNN_LOG(info) << "Parse nodes to ArmNN time: " << std::setprecision(2)
400 << std::fixed << armnn::GetTimeDuration(parseStartTime).count() << " ms";
Sadik Armagan3c24f432020-10-19 17:35:30 +0100401
Sadik Armagan62483be2020-10-23 17:14:43 +0100402 // Add Output layer
403 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
404 if (status != kTfLiteOk)
405 {
406 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
407 }
408
409 // Optimize ArmNN network
410 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
411 try
412 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000413 const auto optimizeStartTime = armnn::GetTimeNow();
Sadik Armagan6e36a642020-11-10 21:18:41 +0000414 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100415 delegate->m_Options.GetBackends(),
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000416 delegate->m_Runtime->GetDeviceSpec(),
417 delegate->m_Options.GetOptimizerOptions());
Jan Eilers17d34da2021-12-08 16:15:12 +0000418 ARMNN_LOG(info) << "Optimize ArmnnSubgraph time: " << std::setprecision(2)
419 << std::fixed << armnn::GetTimeDuration(optimizeStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100420 }
Ryan OShea05b6a3e2023-01-11 15:27:50 +0000421 catch (std::exception& ex)
Sadik Armagan62483be2020-10-23 17:14:43 +0100422 {
423 std::stringstream exMessage;
424 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
425 throw armnn::Exception(exMessage.str());
426 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100427 if (!optNet)
428 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100429 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100430 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
431 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100432
Colm Donelan3e32a872021-10-04 22:55:37 +0100433 // If set, we will serialize the optimized model into a dot file.
434 const std::string serializeToDotFile = delegate->m_Options.GetSerializeToDot();
435 if (!serializeToDotFile.empty())
436 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000437 ARMNN_LOG(info) << "Writing graph to dot file: " << serializeToDotFile;
Colm Donelan3e32a872021-10-04 22:55:37 +0100438 fs::path filename = serializeToDotFile;
439 std::fstream file(filename.c_str(), std::ios_base::out);
440 optNet->SerializeToDot(file);
441 }
442
Sadik Armagan62483be2020-10-23 17:14:43 +0100443 try
444 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000445 const auto loadStartTime = armnn::GetTimeNow();
446
Sadik Armagan62483be2020-10-23 17:14:43 +0100447 // Load graph into runtime
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000448 std::string errorMessage;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000449 armnn::Status loadingStatus;
Francis Murtagh626bd902022-06-21 13:16:23 +0000450 armnn::MemorySource inputSource = armnn::MemorySource::Undefined;
451 armnn::MemorySource outputSource = armnn::MemorySource::Undefined;
452 // There's a bit of an assumption here that the delegate will only support Malloc memory source.
John Mcloughlinc5ee0d72023-03-24 12:07:25 +0000453 if (delegate->m_Options.GetOptimizerOptions().GetImportEnabled())
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000454 {
Francis Murtagh626bd902022-06-21 13:16:23 +0000455 inputSource = armnn::MemorySource::Malloc;
456 }
John Mcloughlinc5ee0d72023-03-24 12:07:25 +0000457 if (delegate->m_Options.GetOptimizerOptions().GetExportEnabled())
Francis Murtagh626bd902022-06-21 13:16:23 +0000458 {
459 outputSource = armnn::MemorySource::Malloc;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000460 }
Colm Donelan3e32a872021-10-04 22:55:37 +0100461 armnn::INetworkProperties networkProperties(false,
Francis Murtagh626bd902022-06-21 13:16:23 +0000462 inputSource,
463 outputSource,
Colm Donelan3e32a872021-10-04 22:55:37 +0100464 delegate->m_Options.GetInternalProfilingState(),
465 delegate->m_Options.GetInternalProfilingDetail());
466 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
467 std::move(optNet),
468 errorMessage,
469 networkProperties);
Sadik Armagan62483be2020-10-23 17:14:43 +0100470 if (loadingStatus != armnn::Status::Success)
471 {
Colm Donelan45142282021-10-21 23:39:52 +0100472 // Network load failed.
Colm Donelan194086f2022-11-14 17:23:07 +0000473 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded: " + errorMessage);
Sadik Armagan62483be2020-10-23 17:14:43 +0100474 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000475
476 ARMNN_LOG(info) << "Load ArmnnSubgraph time: " << std::setprecision(2)
477 << std::fixed << armnn::GetTimeDuration(loadStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100478 }
479 catch (std::exception& ex)
480 {
481 std::stringstream exMessage;
482 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
483 throw armnn::Exception(exMessage.str());
484 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100485
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000486 // Register debug callback function
487 if (delegate->m_Options.GetDebugCallbackFunction().has_value())
488 {
489 delegate->m_Runtime->RegisterDebugCallback(networkId, delegate->m_Options.GetDebugCallbackFunction().value());
490 }
491
Jan Eilers17d34da2021-12-08 16:15:12 +0000492 ARMNN_LOG(info) << "Overall ArmnnSubgraph creation time: " << std::setprecision(2)
493 << std::fixed << armnn::GetTimeDuration(startTime).count() << " ms\n";
494
Sadik Armagan3c24f432020-10-19 17:35:30 +0100495 // Create a new SubGraph with networkId and runtime
Mike Kelly5446a4d2023-01-20 15:51:05 +0000496 return new ArmnnSubgraph(networkId, delegate->m_Runtime, inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100497}
498
499TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
500{
Finn Williams6f9f9902020-11-13 13:23:15 +0000501 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100502 return kTfLiteOk;
503}
504
Sadik Armagan62483be2020-10-23 17:14:43 +0100505TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100506{
Sadik Armagan62483be2020-10-23 17:14:43 +0100507 // Prepare inputs
508 armnn::InputTensors inputTensors;
509 size_t inputIndex = 0;
510 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
511 {
512 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
513 if (tensor->allocation_type != kTfLiteMmapRo)
514 {
515 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100516 armnn::TensorInfo inputTensorInfo = inputBinding.second;
517 inputTensorInfo.SetConstant(true);
518 const armnn::ConstTensor inputTensor(inputTensorInfo, tensor->data.data);
Sadik Armagan62483be2020-10-23 17:14:43 +0100519 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100520
Sadik Armagan62483be2020-10-23 17:14:43 +0100521 ++inputIndex;
522 }
523 }
524
525 // Prepare outputs
526 armnn::OutputTensors outputTensors;
527 size_t outputIndex = 0;
528 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
529 {
530 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
531 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
532 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
533 outputTensors.emplace_back(outputIdx, outputTensor);
534
535 ++outputIndex;
536 }
537
538 // Run graph
539 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
540 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100541}
542
Sadik Armagan62483be2020-10-23 17:14:43 +0100543TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100544 TfLiteContext* tfLiteContext,
545 TfLiteRegistration* tfLiteRegistration,
546 TfLiteNode* tfLiteNode,
547 int nodeIndex)
548{
Sadik Armagan62483be2020-10-23 17:14:43 +0100549 switch (tfLiteRegistration->builtin_code)
550 {
Ryan OShead21abaf2022-06-10 14:49:11 +0100551 case kTfLiteBuiltinCustom:
552 {
553#if defined(ARMNN_POST_TFLITE_2_5)
554 // Custom operators are defined by the name rather than the builtin code.
555 // Parse the custom_name param in the registration to point to the correct visitor function.
556 std::string customOperatorName = tfLiteRegistration->custom_name;
557 if ( customOperatorName == "AveragePool3D" )
558 {
559 return VisitPooling3dOperator(delegateData,
560 tfLiteContext,
561 tfLiteNode,
562 nodeIndex,
563 customOperatorName);
564 }
565 else if (customOperatorName == "MaxPool3D")
566 {
567 return VisitPooling3dOperator(delegateData,
568 tfLiteContext,
569 tfLiteNode,
570 nodeIndex,
571 customOperatorName);
572 }
573#endif
574 // Invalid or unsupported custom operator
575 return kTfLiteError;
576 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100577 case kTfLiteBuiltinAbs:
578 return VisitElementwiseUnaryOperator(delegateData,
579 tfLiteContext,
580 tfLiteNode,
581 nodeIndex,
582 armnn::UnaryOperation::Abs);
583 case kTfLiteBuiltinAdd:
584 return VisitElementwiseBinaryOperator(delegateData,
585 tfLiteContext,
586 tfLiteNode,
587 nodeIndex,
588 kTfLiteBuiltinAdd);
589 case kTfLiteBuiltinArgMax:
590 return VisitArgMinMaxOperator(delegateData,
591 tfLiteContext,
592 tfLiteNode,
593 nodeIndex,
594 kTfLiteBuiltinArgMax);
595 case kTfLiteBuiltinArgMin:
596 return VisitArgMinMaxOperator(delegateData,
597 tfLiteContext,
598 tfLiteNode,
599 nodeIndex,
600 kTfLiteBuiltinArgMin);
601 case kTfLiteBuiltinAveragePool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100602 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100603 tfLiteContext,
604 tfLiteNode,
605 nodeIndex,
606 kTfLiteBuiltinAveragePool2d);
Ryan OShea49ed0df2022-09-21 16:09:41 +0100607 case kTfLiteBuiltinBatchMatmul:
608 return VisitBatchMatMulOperator(delegateData,
609 tfLiteContext,
610 tfLiteNode,
611 nodeIndex,
612 kTfLiteBuiltinBatchMatmul);
Sadik Armagan62483be2020-10-23 17:14:43 +0100613 case kTfLiteBuiltinBatchToSpaceNd:
614 return VisitBatchToSpaceNdOperator(delegateData,
615 tfLiteContext,
616 tfLiteNode,
617 nodeIndex,
618 kTfLiteBuiltinBatchToSpaceNd);
Idriss Chaouchcbf79292023-09-08 11:18:16 +0100619 case kTfLiteBuiltinBroadcastTo:
620 return VisitBroadcastToOperator(delegateData,
621 tfLiteContext,
622 tfLiteNode,
623 nodeIndex,
624 kTfLiteBuiltinBroadcastTo);
Sadik Armagan937565b2021-04-21 14:03:28 +0100625 case kTfLiteBuiltinCast:
626 return VisitCastOperator(delegateData,
627 tfLiteContext,
628 tfLiteNode,
629 nodeIndex,
630 kTfLiteBuiltinCast);
Teresa Charlin93f0ad02023-03-23 15:28:02 +0000631 case kTfLiteBuiltinCeil:
632 return VisitElementwiseUnaryOperator(delegateData,
633 tfLiteContext,
634 tfLiteNode,
635 nodeIndex,
636 armnn::UnaryOperation::Ceil);
Sadik Armagan62483be2020-10-23 17:14:43 +0100637 case kTfLiteBuiltinConcatenation:
638 return VisitControlOperator(delegateData,
639 tfLiteContext,
640 tfLiteNode,
641 nodeIndex,
642 kTfLiteBuiltinConcatenation);
643 case kTfLiteBuiltinConv2d:
644 return VisitConvolutionOperator(delegateData,
645 tfLiteContext,
646 tfLiteNode,
647 nodeIndex,
648 kTfLiteBuiltinConv2d);
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100649// Conv3d is only correctly supported for external delegates from TF Lite v2.6, as there was a breaking bug in v2.5.
650#if defined(ARMNN_POST_TFLITE_2_5)
651 case kTfLiteBuiltinConv3d:
652 return VisitConvolutionOperator(delegateData,
653 tfLiteContext,
654 tfLiteNode,
655 nodeIndex,
656 kTfLiteBuiltinConv3d);
657#endif
Sadik Armagan62483be2020-10-23 17:14:43 +0100658 case kTfLiteBuiltinDepthToSpace:
659 return VisitDepthToSpaceOperator(delegateData,
660 tfLiteContext,
661 tfLiteNode,
662 nodeIndex,
663 kTfLiteBuiltinDepthToSpace);
664 case kTfLiteBuiltinDepthwiseConv2d:
665 return VisitConvolutionOperator(delegateData,
666 tfLiteContext,
667 tfLiteNode,
668 nodeIndex,
669 kTfLiteBuiltinDepthwiseConv2d);
670 case kTfLiteBuiltinDequantize:
671 return VisitDequantizeOperator(delegateData,
672 tfLiteContext,
673 tfLiteNode,
674 nodeIndex,
675 kTfLiteBuiltinDequantize);
676 case kTfLiteBuiltinDiv:
677 return VisitElementwiseBinaryOperator(delegateData,
678 tfLiteContext,
679 tfLiteNode,
680 nodeIndex,
681 kTfLiteBuiltinDiv);
682 case kTfLiteBuiltinElu:
683 return VisitActivationOperator(delegateData,
684 tfLiteContext,
685 tfLiteNode,
686 nodeIndex,
687 kTfLiteBuiltinElu);
688 case kTfLiteBuiltinEqual:
689 return VisitComparisonOperator(delegateData,
690 tfLiteContext,
691 tfLiteNode,
692 nodeIndex,
693 kTfLiteBuiltinEqual);
694 case kTfLiteBuiltinExp:
695 return VisitElementwiseUnaryOperator(delegateData,
696 tfLiteContext,
697 tfLiteNode,
698 nodeIndex,
699 armnn::UnaryOperation::Exp);
700 case kTfLiteBuiltinExpandDims:
701 return VisitExpandDimsOperator(delegateData,
702 tfLiteContext,
703 tfLiteNode,
704 nodeIndex,
705 kTfLiteBuiltinExpandDims);
706 case kTfLiteBuiltinFill:
707 return VisitFillOperator(delegateData,
708 tfLiteContext,
709 tfLiteNode,
710 nodeIndex,
711 kTfLiteBuiltinFill);
712 case kTfLiteBuiltinFloor:
713 return VisitFloorOperator(delegateData,
714 tfLiteContext,
715 tfLiteNode,
716 nodeIndex,
717 kTfLiteBuiltinFloor);
Jim Flynn4b2f3472021-10-13 21:20:07 +0100718 case kTfLiteBuiltinFloorDiv:
719 return VisitElementwiseBinaryOperator(delegateData,
720 tfLiteContext,
721 tfLiteNode,
722 nodeIndex,
723 kTfLiteBuiltinFloorDiv);
Sadik Armagan62483be2020-10-23 17:14:43 +0100724 case kTfLiteBuiltinFullyConnected:
725 return VisitFullyConnectedOperator(delegateData,
726 tfLiteContext,
727 tfLiteNode,
728 nodeIndex,
729 kTfLiteBuiltinFullyConnected);
730 case kTfLiteBuiltinGather:
731 return VisitGatherOperator(delegateData,
732 tfLiteContext,
733 tfLiteNode,
734 nodeIndex,
735 kTfLiteBuiltinGather);
Teresa Charlind5c0ed22022-04-25 18:23:41 +0100736 case kTfLiteBuiltinGatherNd:
737 return VisitGatherNdOperator(delegateData,
738 tfLiteContext,
739 tfLiteNode,
740 nodeIndex,
741 kTfLiteBuiltinGatherNd);
Teresa Charlin077cddb2023-09-15 15:19:21 +0100742 case kTfLiteBuiltinGelu:
743 return VisitActivationOperator(delegateData,
744 tfLiteContext,
745 tfLiteNode,
746 nodeIndex,
747 kTfLiteBuiltinGelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100748 case kTfLiteBuiltinGreater:
749 return VisitComparisonOperator(delegateData,
750 tfLiteContext,
751 tfLiteNode,
752 nodeIndex,
753 kTfLiteBuiltinGreater);
754 case kTfLiteBuiltinGreaterEqual:
755 return VisitComparisonOperator(delegateData,
756 tfLiteContext,
757 tfLiteNode,
758 nodeIndex,
759 kTfLiteBuiltinGreaterEqual);
760 case kTfLiteBuiltinHardSwish:
761 return VisitActivationOperator(delegateData,
762 tfLiteContext,
763 tfLiteNode,
764 nodeIndex,
765 kTfLiteBuiltinHardSwish);
766 case kTfLiteBuiltinL2Normalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000767 return VisitL2NormalizationOperator(delegateData,
768 tfLiteContext,
769 tfLiteNode,
770 nodeIndex,
771 kTfLiteBuiltinL2Normalization);
Sadik Armagan62483be2020-10-23 17:14:43 +0100772 case kTfLiteBuiltinL2Pool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100773 return VisitPooling2dOperator(delegateData,
Tianle Chengae931732023-07-28 11:53:04 +0100774 tfLiteContext,
775 tfLiteNode,
776 nodeIndex,
777 kTfLiteBuiltinL2Pool2d);
778 case kTfLiteBuiltinLeakyRelu:
779 return VisitActivationOperator(delegateData,
780 tfLiteContext,
781 tfLiteNode,
782 nodeIndex,
783 kTfLiteBuiltinLeakyRelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100784 case kTfLiteBuiltinLess:
785 return VisitComparisonOperator(delegateData,
786 tfLiteContext,
787 tfLiteNode,
788 nodeIndex,
789 kTfLiteBuiltinLess);
790 case kTfLiteBuiltinLessEqual:
791 return VisitComparisonOperator(delegateData,
792 tfLiteContext,
793 tfLiteNode,
794 nodeIndex,
795 kTfLiteBuiltinLessEqual);
796 case kTfLiteBuiltinLocalResponseNormalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000797 return VisitLocalResponseNormalizationOperator(delegateData,
798 tfLiteContext,
799 tfLiteNode,
800 nodeIndex,
801 kTfLiteBuiltinLocalResponseNormalization);
Teresa Charlinb1f5f702022-07-12 14:16:24 +0100802 case kTfLiteBuiltinLog:
803 return VisitElementwiseUnaryOperator(delegateData,
804 tfLiteContext,
805 tfLiteNode,
806 nodeIndex,
807 armnn::UnaryOperation::Log);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000808 case kTfLiteBuiltinLogicalAnd:
809 return VisitLogicalBinaryOperator(delegateData,
810 tfLiteContext,
811 tfLiteNode,
812 nodeIndex,
813 kTfLiteBuiltinLogicalAnd,
814 armnn::LogicalBinaryOperation::LogicalAnd);
815 case kTfLiteBuiltinLogicalNot:
816 return VisitElementwiseUnaryOperator(delegateData,
817 tfLiteContext,
818 tfLiteNode,
819 nodeIndex,
820 armnn::UnaryOperation::LogicalNot);
821 case kTfLiteBuiltinLogicalOr:
822 return VisitLogicalBinaryOperator(delegateData,
823 tfLiteContext,
824 tfLiteNode,
825 nodeIndex,
826 kTfLiteBuiltinLogicalOr,
827 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100828 case kTfLiteBuiltinLogistic:
829 return VisitActivationOperator(delegateData,
830 tfLiteContext,
831 tfLiteNode,
832 nodeIndex,
833 kTfLiteBuiltinLogistic);
834 case kTfLiteBuiltinLogSoftmax:
835 return VisitSoftmaxOperator(delegateData,
836 tfLiteContext,
837 tfLiteNode,
838 nodeIndex,
839 kTfLiteBuiltinLogSoftmax);
840 case kTfLiteBuiltinLstm:
841 return VisitLstmOperator(delegateData,
842 tfLiteContext,
843 tfLiteNode,
844 nodeIndex,
845 kTfLiteBuiltinLstm);
846 case kTfLiteBuiltinMaxPool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100847 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100848 tfLiteContext,
849 tfLiteNode,
850 nodeIndex,
851 kTfLiteBuiltinMaxPool2d);
852 case kTfLiteBuiltinMaximum:
853 return VisitElementwiseBinaryOperator(delegateData,
854 tfLiteContext,
855 tfLiteNode,
856 nodeIndex,
857 kTfLiteBuiltinMaximum);
858 case kTfLiteBuiltinMean:
859 return VisitControlOperator(delegateData,
860 tfLiteContext,
861 tfLiteNode,
862 nodeIndex,
863 kTfLiteBuiltinMean);
864 case kTfLiteBuiltinMinimum:
865 return VisitElementwiseBinaryOperator(delegateData,
866 tfLiteContext,
867 tfLiteNode,
868 nodeIndex,
869 kTfLiteBuiltinMinimum);
Matthew Sloyanaf3a4ef2021-10-22 15:48:12 +0100870 case kTfLiteBuiltinMirrorPad:
871 return VisitPadOperator(delegateData,
872 tfLiteContext,
873 tfLiteNode,
874 nodeIndex,
875 kTfLiteBuiltinMirrorPad);
Sadik Armagan62483be2020-10-23 17:14:43 +0100876 case kTfLiteBuiltinMul:
877 return VisitElementwiseBinaryOperator(delegateData,
878 tfLiteContext,
879 tfLiteNode,
880 nodeIndex,
881 kTfLiteBuiltinMul);
882 case kTfLiteBuiltinNeg:
883 return VisitElementwiseUnaryOperator(delegateData,
884 tfLiteContext,
885 tfLiteNode,
886 nodeIndex,
887 armnn::UnaryOperation::Neg);
888 case kTfLiteBuiltinNotEqual:
889 return VisitComparisonOperator(delegateData,
890 tfLiteContext,
891 tfLiteNode,
892 nodeIndex,
893 kTfLiteBuiltinNotEqual);
Matthew Sloyana7a12f52021-05-06 10:05:28 +0100894 case kTfLiteBuiltinPack:
895 return VisitPackOperator(delegateData,
896 tfLiteContext,
897 tfLiteNode,
898 nodeIndex,
899 kTfLiteBuiltinPack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100900 case kTfLiteBuiltinPad:
901 return VisitPadOperator(delegateData,
902 tfLiteContext,
903 tfLiteNode,
904 nodeIndex,
905 kTfLiteBuiltinPad);
906 case kTfLiteBuiltinPadv2:
907 return VisitPadOperator(delegateData,
908 tfLiteContext,
909 tfLiteNode,
910 nodeIndex,
911 kTfLiteBuiltinPadv2);
John Mcloughlin0ec00872023-05-15 17:03:49 +0100912 case kTfLiteBuiltinPow:
913 return VisitElementwiseBinaryOperator(delegateData,
914 tfLiteContext,
915 tfLiteNode,
916 nodeIndex,
917 kTfLiteBuiltinPow);
Sadik Armagan62483be2020-10-23 17:14:43 +0100918 case kTfLiteBuiltinPrelu:
James Conroy39825482021-05-27 17:44:50 +0100919 return VisitPreluOperator(delegateData,
920 tfLiteContext,
921 tfLiteNode,
922 nodeIndex,
923 kTfLiteBuiltinPrelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100924 case kTfLiteBuiltinQuantize:
925 return VisitQuantizeOperator(delegateData,
926 tfLiteContext,
927 tfLiteNode,
928 nodeIndex,
929 kTfLiteBuiltinQuantize);
930 case kTfLiteBuiltinRank:
931 return VisitControlOperator(delegateData,
932 tfLiteContext,
933 tfLiteNode,
934 nodeIndex,
935 kTfLiteBuiltinRank);
Sadik Armagana2747482021-02-09 10:28:54 +0000936 case kTfLiteBuiltinReduceMax:
937 return VisitReduceOperator(delegateData,
938 tfLiteContext,
939 tfLiteNode,
940 nodeIndex,
941 kTfLiteBuiltinReduceMax);
942 case kTfLiteBuiltinReduceMin:
943 return VisitReduceOperator(delegateData,
944 tfLiteContext,
945 tfLiteNode,
946 nodeIndex,
947 kTfLiteBuiltinReduceMin);
Teresa Charlin4e3e8312021-08-05 12:34:37 +0100948 case kTfLiteBuiltinReduceProd:
949 return VisitReduceOperator(delegateData,
950 tfLiteContext,
951 tfLiteNode,
952 nodeIndex,
953 kTfLiteBuiltinReduceProd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100954 case kTfLiteBuiltinRelu:
955 return VisitActivationOperator(delegateData,
956 tfLiteContext,
957 tfLiteNode,
958 nodeIndex,
959 kTfLiteBuiltinRelu);
960 case kTfLiteBuiltinReluN1To1:
961 return VisitActivationOperator(delegateData,
962 tfLiteContext,
963 tfLiteNode,
964 nodeIndex,
965 kTfLiteBuiltinReluN1To1);
966 case kTfLiteBuiltinRelu6:
967 return VisitActivationOperator(delegateData,
968 tfLiteContext,
969 tfLiteNode,
970 nodeIndex,
971 kTfLiteBuiltinRelu6);
972 case kTfLiteBuiltinReshape:
973 return VisitReshapeOperator(delegateData,
974 tfLiteContext,
975 tfLiteNode,
976 nodeIndex,
977 kTfLiteBuiltinReshape);
978 case kTfLiteBuiltinResizeBilinear:
979 return VisitResizeOperator(delegateData,
980 tfLiteContext,
981 tfLiteNode,
982 nodeIndex,
983 kTfLiteBuiltinResizeBilinear);
984 case kTfLiteBuiltinResizeNearestNeighbor:
985 return VisitResizeOperator(delegateData,
986 tfLiteContext,
987 tfLiteNode,
988 nodeIndex,
989 kTfLiteBuiltinResizeNearestNeighbor);
Tracy Narine7306bbe2023-07-17 16:06:26 +0100990 case kTfLiteBuiltinReverseV2:
991 return VisitReverseV2Operator(delegateData,
992 tfLiteContext,
993 tfLiteNode,
994 nodeIndex,
995 kTfLiteBuiltinReverseV2);
Sadik Armagan62483be2020-10-23 17:14:43 +0100996 case kTfLiteBuiltinRsqrt:
997 return VisitElementwiseUnaryOperator(delegateData,
998 tfLiteContext,
999 tfLiteNode,
1000 nodeIndex,
1001 armnn::UnaryOperation::Rsqrt);
Keith Davis0176fd82021-06-01 17:36:32 +01001002 case kTfLiteBuiltinShape:
1003 return VisitShapeOperator(delegateData,
1004 tfLiteContext,
1005 tfLiteNode,
1006 nodeIndex,
1007 kTfLiteBuiltinShape);
Teresa Charlinb1f5f702022-07-12 14:16:24 +01001008 case kTfLiteBuiltinSin:
1009 return VisitElementwiseUnaryOperator(delegateData,
1010 tfLiteContext,
1011 tfLiteNode,
1012 nodeIndex,
1013 armnn::UnaryOperation::Sin);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +00001014 case kTfLiteBuiltinSplit:
1015 return VisitSplitOperator(delegateData,
1016 tfLiteContext,
1017 tfLiteNode,
1018 nodeIndex,
1019 kTfLiteBuiltinSplit);
1020 case kTfLiteBuiltinSplitV:
1021 return VisitSplitVOperator(delegateData,
1022 tfLiteContext,
1023 tfLiteNode,
1024 nodeIndex,
1025 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +01001026 case kTfLiteBuiltinSqrt:
1027 return VisitElementwiseUnaryOperator(delegateData,
1028 tfLiteContext,
1029 tfLiteNode,
1030 nodeIndex,
1031 armnn::UnaryOperation::Sqrt);
John Mcloughlin0ec00872023-05-15 17:03:49 +01001032 case kTfLiteBuiltinSquaredDifference:
1033 return VisitElementwiseBinaryOperator(delegateData,
1034 tfLiteContext,
1035 tfLiteNode,
1036 nodeIndex,
1037 kTfLiteBuiltinSquaredDifference);
Sadik Armagan62483be2020-10-23 17:14:43 +01001038 case kTfLiteBuiltinSqueeze:
1039 return VisitSqueezeOperator(delegateData,
1040 tfLiteContext,
1041 tfLiteNode,
1042 nodeIndex,
1043 kTfLiteBuiltinSqueeze);
Cathal Corbett839b9322022-11-18 08:52:18 +00001044 case kTfLiteBuiltinSlice:
Sadik Armagan62483be2020-10-23 17:14:43 +01001045 return VisitSliceOperator(delegateData,
1046 tfLiteContext,
1047 tfLiteNode,
1048 nodeIndex,
Cathal Corbett839b9322022-11-18 08:52:18 +00001049 kTfLiteBuiltinSlice);
1050 case kTfLiteBuiltinStridedSlice:
1051 return VisitStridedSliceOperator(delegateData,
1052 tfLiteContext,
1053 tfLiteNode,
1054 nodeIndex,
1055 kTfLiteBuiltinStridedSlice);
Sadik Armagana2747482021-02-09 10:28:54 +00001056 case kTfLiteBuiltinSum:
1057 return VisitReduceOperator(delegateData,
1058 tfLiteContext,
1059 tfLiteNode,
1060 nodeIndex,
1061 kTfLiteBuiltinSum);
Sadik Armagan62483be2020-10-23 17:14:43 +01001062 case kTfLiteBuiltinTranspose:
1063 return VisitTransposeOperator(delegateData,
1064 tfLiteContext,
1065 tfLiteNode,
1066 nodeIndex,
1067 kTfLiteBuiltinTranspose);
1068 case kTfLiteBuiltinTransposeConv:
1069 return VisitConvolutionOperator(delegateData,
1070 tfLiteContext,
1071 tfLiteNode,
1072 nodeIndex,
1073 kTfLiteBuiltinTransposeConv);
Kevin May93bbf002024-03-11 09:31:10 +00001074 case kTfLiteBuiltinScatterNd:
1075 return VisitScatterNdOperator(delegateData,
1076 tfLiteContext,
1077 tfLiteNode,
1078 nodeIndex,
1079 kTfLiteBuiltinScatterNd);
Sadik Armagan62483be2020-10-23 17:14:43 +01001080 case kTfLiteBuiltinSoftmax:
1081 return VisitSoftmaxOperator(delegateData,
1082 tfLiteContext,
1083 tfLiteNode,
1084 nodeIndex,
1085 kTfLiteBuiltinSoftmax);
1086 case kTfLiteBuiltinSpaceToBatchNd:
1087 return VisitSpaceToBatchNdOperator(delegateData,
1088 tfLiteContext,
1089 tfLiteNode,
1090 nodeIndex,
1091 kTfLiteBuiltinSpaceToBatchNd);
1092 case kTfLiteBuiltinSpaceToDepth:
1093 return VisitSpaceToDepthOperator(delegateData,
1094 tfLiteContext,
1095 tfLiteNode,
1096 nodeIndex,
1097 kTfLiteBuiltinSpaceToDepth);
1098 case kTfLiteBuiltinSub:
1099 return VisitElementwiseBinaryOperator(delegateData,
1100 tfLiteContext,
1101 tfLiteNode,
1102 nodeIndex,
1103 kTfLiteBuiltinSub);
1104 case kTfLiteBuiltinTanh:
1105 return VisitActivationOperator(delegateData,
1106 tfLiteContext,
1107 tfLiteNode,
1108 nodeIndex,
1109 kTfLiteBuiltinTanh);
Tianle Cheng92ce35c2023-07-25 16:41:00 +01001110 case kTfLiteBuiltinTile:
1111 return VisitTileOperator(delegateData,
1112 tfLiteContext,
1113 tfLiteNode,
1114 nodeIndex,
1115 kTfLiteBuiltinTile);
Narumol Prangnawarat7684b182021-08-12 14:48:15 +01001116 case kTfLiteBuiltinUnidirectionalSequenceLstm:
1117 return VisitUnidirectionalSequenceLstmOperator(delegateData,
1118 tfLiteContext,
1119 tfLiteNode,
1120 nodeIndex,
1121 kTfLiteBuiltinUnidirectionalSequenceLstm);
Kevin May8ab2d7a2021-05-07 09:32:51 +01001122 case kTfLiteBuiltinUnpack:
1123 return VisitUnpackOperator(delegateData,
1124 tfLiteContext,
1125 tfLiteNode,
1126 nodeIndex,
1127 kTfLiteBuiltinUnpack);
Sadik Armagan62483be2020-10-23 17:14:43 +01001128 default:
1129 return kTfLiteError;
1130 }
Sadik Armagan3c24f432020-10-19 17:35:30 +01001131}
1132
1133} // armnnDelegate namespace