blob: 05bf9b2ee7f6e755029d756933a576acc677c02d [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"
Keith Davis0176fd82021-06-01 17:36:32 +010037#include "Shape.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010038#include "Slice.hpp"
Cathal Corbett839b9322022-11-18 08:52:18 +000039#include "StridedSlice.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010040#include "Softmax.hpp"
41#include "SpaceDepth.hpp"
Sadik Armagan34fa1bd2020-11-27 12:40:52 +000042#include "Split.hpp"
Tianle Cheng92ce35c2023-07-25 16:41:00 +010043#include "Tile.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010044#include "Transpose.hpp"
Narumol Prangnawarat7684b182021-08-12 14:48:15 +010045#include "UnidirectionalSequenceLstm.hpp"
Kevin May8ab2d7a2021-05-07 09:32:51 +010046#include "Unpack.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010047
Colm Donelan3e32a872021-10-04 22:55:37 +010048#include <armnnUtils/Filesystem.hpp>
Jan Eilers17d34da2021-12-08 16:15:12 +000049#include <armnn/utility/Timer.hpp>
Sadik Armagan62483be2020-10-23 17:14:43 +010050#include <flatbuffers/flatbuffers.h>
51#include <tensorflow/lite/context_util.h>
Jim Flynn4b2f3472021-10-13 21:20:07 +010052#include <tensorflow/lite/schema/schema_generated.h>
Sadik Armagan62483be2020-10-23 17:14:43 +010053
Sadik Armagan3c24f432020-10-19 17:35:30 +010054#include <algorithm>
Matthew Sloyanac001ee2021-02-03 10:43:04 +000055#include <iostream>
Sadik Armagan62483be2020-10-23 17:14:43 +010056#include <sstream>
Sadik Armagan3c24f432020-10-19 17:35:30 +010057
58namespace armnnDelegate
59{
60
Sadik Armagan62483be2020-10-23 17:14:43 +010061DelegateOptions TfLiteArmnnDelegateOptionsDefault()
62{
63 DelegateOptions options(armnn::Compute::CpuRef);
64 return options;
65}
66
67TfLiteDelegate* TfLiteArmnnDelegateCreate(armnnDelegate::DelegateOptions options)
68{
69 auto* armnnDelegate = new ::armnnDelegate::Delegate(options);
70 return armnnDelegate->GetDelegate();
71}
72
73void TfLiteArmnnDelegateDelete(TfLiteDelegate* tfLiteDelegate)
74{
75 if (tfLiteDelegate != nullptr)
76 {
77 delete static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_);
78 }
79}
80
81TfLiteStatus DoPrepare(TfLiteContext* tfLiteContext, TfLiteDelegate* tfLiteDelegate)
82{
83 TfLiteIntArray* supportedOperators =
84 static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_)->IdentifyOperatorsToDelegate(tfLiteContext);
85
86 // ArmNN Delegate Registration
87 static const TfLiteRegistration kArmnnSubgraphRegistration = {
88 // ArmnnSubgraph Init
89 .init = [](TfLiteContext* tfLiteContext, const char* buffer, size_t length) -> void* {
Finn Williams6f9f9902020-11-13 13:23:15 +000090 armnn::IgnoreUnused(length);
Sadik Armagan62483be2020-10-23 17:14:43 +010091 const TfLiteDelegateParams* parameters = reinterpret_cast<const TfLiteDelegateParams*>(buffer);
92
93 return static_cast<void*>(ArmnnSubgraph::Create(
94 tfLiteContext, parameters, static_cast<::armnnDelegate::Delegate*>(parameters->delegate->data_)));
95 },
96 // ArmnnSubgraph Free
97 .free = [](TfLiteContext* tfLiteContext, void* buffer) -> void {
Finn Williams6f9f9902020-11-13 13:23:15 +000098 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan62483be2020-10-23 17:14:43 +010099 if (buffer != nullptr)
100 {
101 delete static_cast<ArmnnSubgraph*>(buffer);
102 }
103 },
104 // ArmnnSubgraph Prepare
105 .prepare = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
106 if (tfLiteNode->user_data == nullptr)
107 {
108 return kTfLiteError;
109 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100110 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Prepare(tfLiteContext);
111 },
112 // ArmnnSubgraph Invoke
113 .invoke = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
114 if (tfLiteNode->user_data == nullptr)
115 {
116 return kTfLiteError;
117 }
118
119 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Invoke(tfLiteContext, tfLiteNode);
120 },
121
122 .profiling_string = nullptr,
123 .builtin_code = kTfLiteBuiltinDelegate,
124 .custom_name = "TfLiteArmNnDelegate",
125 .version = 1,
Colm Donelan718966f2022-10-10 10:06:12 +0100126 .registration_external = nullptr,
Matthew Sloyan76d0c4c2023-09-07 14:48:56 +0100127 .async_kernel = nullptr,
128 .inplace_operator = 0
Sadik Armagan62483be2020-10-23 17:14:43 +0100129 };
130
131 const TfLiteStatus status =
132 tfLiteContext->ReplaceNodeSubsetsWithDelegateKernels(
133 tfLiteContext, kArmnnSubgraphRegistration, supportedOperators, tfLiteDelegate);
134
135 TfLiteIntArrayFree(supportedOperators);
136 return status;
137
138}
139
Sadik Armagan3c24f432020-10-19 17:35:30 +0100140Delegate::Delegate(armnnDelegate::DelegateOptions options)
Mike Kelly5446a4d2023-01-20 15:51:05 +0000141 : m_Options(std::move(options))
Sadik Armagan3c24f432020-10-19 17:35:30 +0100142{
Jan Eilers2cd18472020-12-15 10:42:38 +0000143 // Configures logging for ARMNN
Colm Donelanda7f2f92022-12-20 16:21:35 +0000144 if (m_Options.IsLoggingEnabled())
Jan Eilers2cd18472020-12-15 10:42:38 +0000145 {
Colm Donelanda7f2f92022-12-20 16:21:35 +0000146 armnn::ConfigureLogging(true, true, m_Options.GetLoggingSeverity());
Jan Eilers2cd18472020-12-15 10:42:38 +0000147 }
Mike Kelly5446a4d2023-01-20 15:51:05 +0000148 // Create/Get the static ArmNN Runtime. Note that the m_Runtime will be shared by all armnn_delegate
149 // instances so the RuntimeOptions cannot be altered for different armnn_delegate instances.
150 m_Runtime = GetRuntime(m_Options.GetRuntimeOptions());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100151 std::vector<armnn::BackendId> backends;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100152 if (m_Runtime)
153 {
154 const armnn::BackendIdSet supportedDevices = m_Runtime->GetDeviceSpec().GetSupportedBackends();
155 for (auto& backend : m_Options.GetBackends())
156 {
157 if (std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) == supportedDevices.cend())
158 {
Sadik Armagan0534e032020-10-27 17:30:18 +0000159 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100160 "TfLiteArmnnDelegate: Requested unknown backend %s", backend.Get().c_str());
161 }
162 else
163 {
164 backends.push_back(backend);
Kevin May0425a372023-11-03 12:06:04 +0000165 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
166 "TfLiteArmnnDelegate: Added backend %s", backend.Get().c_str());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100167 }
168 }
169 }
170
171 if (backends.empty())
172 {
173 // No known backend specified
174 throw armnn::InvalidArgumentException("TfLiteArmnnDelegate: No known backend specified.");
175 }
176 m_Options.SetBackends(backends);
177
178 TFLITE_LOG_PROD_ONCE(tflite::TFLITE_LOG_INFO, "TfLiteArmnnDelegate: Created TfLite ArmNN delegate.");
179}
180
Sadik Armagan62483be2020-10-23 17:14:43 +0100181TfLiteIntArray* Delegate::IdentifyOperatorsToDelegate(TfLiteContext* tfLiteContext)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100182{
183 TfLiteIntArray* executionPlan = nullptr;
184 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
185 {
186 TF_LITE_KERNEL_LOG(tfLiteContext, "TfLiteArmnnDelegate: Unable to get graph execution plan.");
187 return nullptr;
188 }
189
Sadik Armagan62483be2020-10-23 17:14:43 +0100190 // Delegate data with null network
191 DelegateData delegateData(m_Options.GetBackends());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100192
193 TfLiteIntArray* nodesToDelegate = TfLiteIntArrayCreate(executionPlan->size);
194 nodesToDelegate->size = 0;
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000195
196 std::set<int32_t> unsupportedOperators;
197
Sadik Armagan3c24f432020-10-19 17:35:30 +0100198 for (int i = 0; i < executionPlan->size; ++i)
199 {
200 const int nodeIndex = executionPlan->data[i];
201
202 // If TfLite nodes can be delegated to ArmNN
203 TfLiteNode* tfLiteNode = nullptr;
204 TfLiteRegistration* tfLiteRegistration = nullptr;
205 if (tfLiteContext->GetNodeAndRegistration(
206 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
207 {
208 TF_LITE_KERNEL_LOG(tfLiteContext,
209 "TfLiteArmnnDelegate: Unable to get node and registration for node %d.",
210 nodeIndex);
211 continue;
212 }
213
Ryan OShea05b6a3e2023-01-11 15:27:50 +0000214 TfLiteStatus visitStatus;
215
216 try
217 {
218 visitStatus = ArmnnSubgraph::VisitNode(
219 delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex);
220 }
221 catch(std::exception& ex)
222 {
223 ARMNN_LOG(error) << "ArmNN Failed to visit node with error: " << ex.what();
224 visitStatus = kTfLiteError;
Ciara Sookarry39436152023-10-31 15:44:41 +0000225 TF_LITE_KERNEL_LOG(tfLiteContext,
226 "Exception text: %s",
227 ex.what());
Ryan OShea05b6a3e2023-01-11 15:27:50 +0000228 }
229
230 if ( visitStatus != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100231 {
232 // node is not supported by ArmNN
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000233 unsupportedOperators.insert(tfLiteRegistration->builtin_code);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100234 continue;
235 }
236
237 nodesToDelegate->data[nodesToDelegate->size++] = nodeIndex;
238 }
239
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000240 for (std::set<int32_t>::iterator it=unsupportedOperators.begin(); it!=unsupportedOperators.end(); ++it)
241 {
242 TF_LITE_KERNEL_LOG(tfLiteContext,
243 "Operator %s [%d] is not supported by armnn_delegate.",
244 tflite::EnumNameBuiltinOperator(tflite::BuiltinOperator(*it)),
245 *it);
246 }
247
Sadik Armaganca565c12022-08-16 12:17:24 +0100248 if (!unsupportedOperators.empty() && m_Options.TfLiteRuntimeFallbackDisabled())
249 {
250 std::stringstream exMessage;
251 exMessage << "TfLiteArmnnDelegate: There are unsupported operators in the model. ";
252 exMessage << "Not falling back to TfLite Runtime as fallback is disabled. ";
253 exMessage << "This should only be disabled under test conditions.";
254 throw armnn::Exception(exMessage.str());
255 }
Colm Donelan3811a972023-01-25 21:19:49 +0000256 if (nodesToDelegate->size == 0)
257 {
258 ARMNN_LOG(info) << "No operators in this model are supported by the Arm NN TfLite delegate." <<
259 " The model will be executed entirely by TfLite runtime.";
260 }
Sadik Armaganca565c12022-08-16 12:17:24 +0100261
Sadik Armagan62483be2020-10-23 17:14:43 +0100262 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100263 return nodesToDelegate;
264}
265
266TfLiteDelegate* Delegate::GetDelegate()
267{
268 return &m_Delegate;
269}
270
Matthew Sloyanac001ee2021-02-03 10:43:04 +0000271const std::string Delegate::GetVersion()
272{
273 return DELEGATE_VERSION;
274}
275
Colm Donelan253d1bb2024-03-04 22:19:26 +0000276ArmnnSubgraph::~ArmnnSubgraph()
277{
278 // The delegate holds its own Arm NN runtime so this is our last chance to print internal profiling data.
279 std::shared_ptr<armnn::IProfiler> profiler = m_Runtime->GetProfiler(m_NetworkId);
280 if (profiler && profiler->IsProfilingEnabled())
281 {
282 profiler->Print(std::cout);
283 }
284}
285
Sadik Armagan62483be2020-10-23 17:14:43 +0100286TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
287 TfLiteContext* tfLiteContext,
288 const TfLiteIntArray* inputs,
289 std::vector<armnn::BindingPointInfo>& inputBindings)
290{
Finn Williams6f9f9902020-11-13 13:23:15 +0000291 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100292 for (unsigned int i = 0; i < numInputs; ++i)
293 {
294 const int32_t tensorId = inputs->data[i];
295 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000296 // Do not create bindings for constant inputs
297 if (tensor.allocation_type == kTfLiteMmapRo)
298 {
299 continue;
300 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100301
302 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
303 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
304
305 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
306 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
307 outputSlot.SetTensorInfo(tensorInfo);
308
309 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000310 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100311
Sadik Armagan6e36a642020-11-10 21:18:41 +0000312 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100313 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000314
Sadik Armagan62483be2020-10-23 17:14:43 +0100315 return kTfLiteOk;
316}
317
318TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
319 TfLiteContext* tfLiteContext,
320 const TfLiteIntArray* outputs,
321 std::vector<armnn::BindingPointInfo>& outputBindings)
322{
Finn Williams6f9f9902020-11-13 13:23:15 +0000323 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100324 for (unsigned int i = 0; i < numOutputs; ++i)
325 {
326 const int32_t tensorId = outputs->data[i];
327 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
328
329 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
330 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
331
332 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Ryan OSheac229b3f2023-06-27 22:34:54 +0100333
334 if (delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] == nullptr)
335 {
336 return kTfLiteError;
337 }
338
Finn Williams6f9f9902020-11-13 13:23:15 +0000339 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100340 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
341 }
342
343 return kTfLiteOk;
344}
345
Sadik Armagan3c24f432020-10-19 17:35:30 +0100346ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
347 const TfLiteDelegateParams* parameters,
348 const Delegate* delegate)
349{
Jan Eilers17d34da2021-12-08 16:15:12 +0000350 const auto startTime = armnn::GetTimeNow();
351 ARMNN_LOG(info) << "ArmnnSubgraph creation";
352
Sadik Armagan3c24f432020-10-19 17:35:30 +0100353 TfLiteIntArray* executionPlan;
354 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
355 {
356 return nullptr;
357 }
358
Sadik Armagan62483be2020-10-23 17:14:43 +0100359 // Initialize DelegateData holds network and output slots information
360 DelegateData delegateData(delegate->m_Options.GetBackends());
361
362 // Build ArmNN Network
John Mcloughlinc5ee0d72023-03-24 12:07:25 +0000363 armnn::NetworkOptions networkOptions = delegate->m_Options.GetOptimizerOptions().GetModelOptions();
Sadik Armagan3c24f432020-10-19 17:35:30 +0100364 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100365 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100366
Sadik Armagan6e36a642020-11-10 21:18:41 +0000367 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
368
Sadik Armagan62483be2020-10-23 17:14:43 +0100369 std::vector<armnn::BindingPointInfo> inputBindings;
370 std::vector<armnn::BindingPointInfo> outputBindings;
371
372 // Add input layer
373 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
374 if (status != kTfLiteOk)
375 {
376 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
377 }
378
379 // Parse TfLite delegate nodes to ArmNN
Jan Eilers17d34da2021-12-08 16:15:12 +0000380 const auto parseStartTime = armnn::GetTimeNow();
Sadik Armagan3c24f432020-10-19 17:35:30 +0100381 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
382 {
383 const int nodeIndex = parameters->nodes_to_replace->data[i];
384
385 TfLiteNode* tfLiteNode = nullptr;
386 TfLiteRegistration* tfLiteRegistration = nullptr;
387 if (tfLiteContext->GetNodeAndRegistration(
388 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
389 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000390 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100391 }
392
Sadik Armagan62483be2020-10-23 17:14:43 +0100393 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100394 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000395 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100396 }
397 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000398 ARMNN_LOG(info) << "Parse nodes to ArmNN time: " << std::setprecision(2)
399 << std::fixed << armnn::GetTimeDuration(parseStartTime).count() << " ms";
Sadik Armagan3c24f432020-10-19 17:35:30 +0100400
Sadik Armagan62483be2020-10-23 17:14:43 +0100401 // Add Output layer
402 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
403 if (status != kTfLiteOk)
404 {
405 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
406 }
407
408 // Optimize ArmNN network
409 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
410 try
411 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000412 const auto optimizeStartTime = armnn::GetTimeNow();
Sadik Armagan6e36a642020-11-10 21:18:41 +0000413 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100414 delegate->m_Options.GetBackends(),
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000415 delegate->m_Runtime->GetDeviceSpec(),
416 delegate->m_Options.GetOptimizerOptions());
Jan Eilers17d34da2021-12-08 16:15:12 +0000417 ARMNN_LOG(info) << "Optimize ArmnnSubgraph time: " << std::setprecision(2)
418 << std::fixed << armnn::GetTimeDuration(optimizeStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100419 }
Ryan OShea05b6a3e2023-01-11 15:27:50 +0000420 catch (std::exception& ex)
Sadik Armagan62483be2020-10-23 17:14:43 +0100421 {
422 std::stringstream exMessage;
423 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
424 throw armnn::Exception(exMessage.str());
425 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100426 if (!optNet)
427 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100428 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100429 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
430 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100431
Colm Donelan3e32a872021-10-04 22:55:37 +0100432 // If set, we will serialize the optimized model into a dot file.
433 const std::string serializeToDotFile = delegate->m_Options.GetSerializeToDot();
434 if (!serializeToDotFile.empty())
435 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000436 ARMNN_LOG(info) << "Writing graph to dot file: " << serializeToDotFile;
Colm Donelan3e32a872021-10-04 22:55:37 +0100437 fs::path filename = serializeToDotFile;
438 std::fstream file(filename.c_str(), std::ios_base::out);
439 optNet->SerializeToDot(file);
440 }
441
Sadik Armagan62483be2020-10-23 17:14:43 +0100442 try
443 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000444 const auto loadStartTime = armnn::GetTimeNow();
445
Sadik Armagan62483be2020-10-23 17:14:43 +0100446 // Load graph into runtime
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000447 std::string errorMessage;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000448 armnn::Status loadingStatus;
Francis Murtagh626bd902022-06-21 13:16:23 +0000449 armnn::MemorySource inputSource = armnn::MemorySource::Undefined;
450 armnn::MemorySource outputSource = armnn::MemorySource::Undefined;
451 // There's a bit of an assumption here that the delegate will only support Malloc memory source.
John Mcloughlinc5ee0d72023-03-24 12:07:25 +0000452 if (delegate->m_Options.GetOptimizerOptions().GetImportEnabled())
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000453 {
Francis Murtagh626bd902022-06-21 13:16:23 +0000454 inputSource = armnn::MemorySource::Malloc;
455 }
John Mcloughlinc5ee0d72023-03-24 12:07:25 +0000456 if (delegate->m_Options.GetOptimizerOptions().GetExportEnabled())
Francis Murtagh626bd902022-06-21 13:16:23 +0000457 {
458 outputSource = armnn::MemorySource::Malloc;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000459 }
Colm Donelan3e32a872021-10-04 22:55:37 +0100460 armnn::INetworkProperties networkProperties(false,
Francis Murtagh626bd902022-06-21 13:16:23 +0000461 inputSource,
462 outputSource,
Colm Donelan3e32a872021-10-04 22:55:37 +0100463 delegate->m_Options.GetInternalProfilingState(),
464 delegate->m_Options.GetInternalProfilingDetail());
465 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
466 std::move(optNet),
467 errorMessage,
468 networkProperties);
Sadik Armagan62483be2020-10-23 17:14:43 +0100469 if (loadingStatus != armnn::Status::Success)
470 {
Colm Donelan45142282021-10-21 23:39:52 +0100471 // Network load failed.
Colm Donelan194086f2022-11-14 17:23:07 +0000472 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded: " + errorMessage);
Sadik Armagan62483be2020-10-23 17:14:43 +0100473 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000474
475 ARMNN_LOG(info) << "Load ArmnnSubgraph time: " << std::setprecision(2)
476 << std::fixed << armnn::GetTimeDuration(loadStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100477 }
478 catch (std::exception& ex)
479 {
480 std::stringstream exMessage;
481 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
482 throw armnn::Exception(exMessage.str());
483 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100484
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000485 // Register debug callback function
486 if (delegate->m_Options.GetDebugCallbackFunction().has_value())
487 {
488 delegate->m_Runtime->RegisterDebugCallback(networkId, delegate->m_Options.GetDebugCallbackFunction().value());
489 }
490
Jan Eilers17d34da2021-12-08 16:15:12 +0000491 ARMNN_LOG(info) << "Overall ArmnnSubgraph creation time: " << std::setprecision(2)
492 << std::fixed << armnn::GetTimeDuration(startTime).count() << " ms\n";
493
Sadik Armagan3c24f432020-10-19 17:35:30 +0100494 // Create a new SubGraph with networkId and runtime
Mike Kelly5446a4d2023-01-20 15:51:05 +0000495 return new ArmnnSubgraph(networkId, delegate->m_Runtime, inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100496}
497
498TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
499{
Finn Williams6f9f9902020-11-13 13:23:15 +0000500 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100501 return kTfLiteOk;
502}
503
Sadik Armagan62483be2020-10-23 17:14:43 +0100504TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100505{
Sadik Armagan62483be2020-10-23 17:14:43 +0100506 // Prepare inputs
507 armnn::InputTensors inputTensors;
508 size_t inputIndex = 0;
509 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
510 {
511 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
512 if (tensor->allocation_type != kTfLiteMmapRo)
513 {
514 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100515 armnn::TensorInfo inputTensorInfo = inputBinding.second;
516 inputTensorInfo.SetConstant(true);
517 const armnn::ConstTensor inputTensor(inputTensorInfo, tensor->data.data);
Sadik Armagan62483be2020-10-23 17:14:43 +0100518 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100519
Sadik Armagan62483be2020-10-23 17:14:43 +0100520 ++inputIndex;
521 }
522 }
523
524 // Prepare outputs
525 armnn::OutputTensors outputTensors;
526 size_t outputIndex = 0;
527 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
528 {
529 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
530 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
531 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
532 outputTensors.emplace_back(outputIdx, outputTensor);
533
534 ++outputIndex;
535 }
536
537 // Run graph
538 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
539 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100540}
541
Sadik Armagan62483be2020-10-23 17:14:43 +0100542TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100543 TfLiteContext* tfLiteContext,
544 TfLiteRegistration* tfLiteRegistration,
545 TfLiteNode* tfLiteNode,
546 int nodeIndex)
547{
Sadik Armagan62483be2020-10-23 17:14:43 +0100548 switch (tfLiteRegistration->builtin_code)
549 {
Ryan OShead21abaf2022-06-10 14:49:11 +0100550 case kTfLiteBuiltinCustom:
551 {
552#if defined(ARMNN_POST_TFLITE_2_5)
553 // Custom operators are defined by the name rather than the builtin code.
554 // Parse the custom_name param in the registration to point to the correct visitor function.
555 std::string customOperatorName = tfLiteRegistration->custom_name;
556 if ( customOperatorName == "AveragePool3D" )
557 {
558 return VisitPooling3dOperator(delegateData,
559 tfLiteContext,
560 tfLiteNode,
561 nodeIndex,
562 customOperatorName);
563 }
564 else if (customOperatorName == "MaxPool3D")
565 {
566 return VisitPooling3dOperator(delegateData,
567 tfLiteContext,
568 tfLiteNode,
569 nodeIndex,
570 customOperatorName);
571 }
572#endif
573 // Invalid or unsupported custom operator
574 return kTfLiteError;
575 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100576 case kTfLiteBuiltinAbs:
577 return VisitElementwiseUnaryOperator(delegateData,
578 tfLiteContext,
579 tfLiteNode,
580 nodeIndex,
581 armnn::UnaryOperation::Abs);
582 case kTfLiteBuiltinAdd:
583 return VisitElementwiseBinaryOperator(delegateData,
584 tfLiteContext,
585 tfLiteNode,
586 nodeIndex,
587 kTfLiteBuiltinAdd);
588 case kTfLiteBuiltinArgMax:
589 return VisitArgMinMaxOperator(delegateData,
590 tfLiteContext,
591 tfLiteNode,
592 nodeIndex,
593 kTfLiteBuiltinArgMax);
594 case kTfLiteBuiltinArgMin:
595 return VisitArgMinMaxOperator(delegateData,
596 tfLiteContext,
597 tfLiteNode,
598 nodeIndex,
599 kTfLiteBuiltinArgMin);
600 case kTfLiteBuiltinAveragePool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100601 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100602 tfLiteContext,
603 tfLiteNode,
604 nodeIndex,
605 kTfLiteBuiltinAveragePool2d);
Ryan OShea49ed0df2022-09-21 16:09:41 +0100606 case kTfLiteBuiltinBatchMatmul:
607 return VisitBatchMatMulOperator(delegateData,
608 tfLiteContext,
609 tfLiteNode,
610 nodeIndex,
611 kTfLiteBuiltinBatchMatmul);
Sadik Armagan62483be2020-10-23 17:14:43 +0100612 case kTfLiteBuiltinBatchToSpaceNd:
613 return VisitBatchToSpaceNdOperator(delegateData,
614 tfLiteContext,
615 tfLiteNode,
616 nodeIndex,
617 kTfLiteBuiltinBatchToSpaceNd);
Idriss Chaouchcbf79292023-09-08 11:18:16 +0100618 case kTfLiteBuiltinBroadcastTo:
619 return VisitBroadcastToOperator(delegateData,
620 tfLiteContext,
621 tfLiteNode,
622 nodeIndex,
623 kTfLiteBuiltinBroadcastTo);
Sadik Armagan937565b2021-04-21 14:03:28 +0100624 case kTfLiteBuiltinCast:
625 return VisitCastOperator(delegateData,
626 tfLiteContext,
627 tfLiteNode,
628 nodeIndex,
629 kTfLiteBuiltinCast);
Teresa Charlin93f0ad02023-03-23 15:28:02 +0000630 case kTfLiteBuiltinCeil:
631 return VisitElementwiseUnaryOperator(delegateData,
632 tfLiteContext,
633 tfLiteNode,
634 nodeIndex,
635 armnn::UnaryOperation::Ceil);
Sadik Armagan62483be2020-10-23 17:14:43 +0100636 case kTfLiteBuiltinConcatenation:
637 return VisitControlOperator(delegateData,
638 tfLiteContext,
639 tfLiteNode,
640 nodeIndex,
641 kTfLiteBuiltinConcatenation);
642 case kTfLiteBuiltinConv2d:
643 return VisitConvolutionOperator(delegateData,
644 tfLiteContext,
645 tfLiteNode,
646 nodeIndex,
647 kTfLiteBuiltinConv2d);
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100648// Conv3d is only correctly supported for external delegates from TF Lite v2.6, as there was a breaking bug in v2.5.
649#if defined(ARMNN_POST_TFLITE_2_5)
650 case kTfLiteBuiltinConv3d:
651 return VisitConvolutionOperator(delegateData,
652 tfLiteContext,
653 tfLiteNode,
654 nodeIndex,
655 kTfLiteBuiltinConv3d);
656#endif
Sadik Armagan62483be2020-10-23 17:14:43 +0100657 case kTfLiteBuiltinDepthToSpace:
658 return VisitDepthToSpaceOperator(delegateData,
659 tfLiteContext,
660 tfLiteNode,
661 nodeIndex,
662 kTfLiteBuiltinDepthToSpace);
663 case kTfLiteBuiltinDepthwiseConv2d:
664 return VisitConvolutionOperator(delegateData,
665 tfLiteContext,
666 tfLiteNode,
667 nodeIndex,
668 kTfLiteBuiltinDepthwiseConv2d);
669 case kTfLiteBuiltinDequantize:
670 return VisitDequantizeOperator(delegateData,
671 tfLiteContext,
672 tfLiteNode,
673 nodeIndex,
674 kTfLiteBuiltinDequantize);
675 case kTfLiteBuiltinDiv:
676 return VisitElementwiseBinaryOperator(delegateData,
677 tfLiteContext,
678 tfLiteNode,
679 nodeIndex,
680 kTfLiteBuiltinDiv);
681 case kTfLiteBuiltinElu:
682 return VisitActivationOperator(delegateData,
683 tfLiteContext,
684 tfLiteNode,
685 nodeIndex,
686 kTfLiteBuiltinElu);
687 case kTfLiteBuiltinEqual:
688 return VisitComparisonOperator(delegateData,
689 tfLiteContext,
690 tfLiteNode,
691 nodeIndex,
692 kTfLiteBuiltinEqual);
693 case kTfLiteBuiltinExp:
694 return VisitElementwiseUnaryOperator(delegateData,
695 tfLiteContext,
696 tfLiteNode,
697 nodeIndex,
698 armnn::UnaryOperation::Exp);
699 case kTfLiteBuiltinExpandDims:
700 return VisitExpandDimsOperator(delegateData,
701 tfLiteContext,
702 tfLiteNode,
703 nodeIndex,
704 kTfLiteBuiltinExpandDims);
705 case kTfLiteBuiltinFill:
706 return VisitFillOperator(delegateData,
707 tfLiteContext,
708 tfLiteNode,
709 nodeIndex,
710 kTfLiteBuiltinFill);
711 case kTfLiteBuiltinFloor:
712 return VisitFloorOperator(delegateData,
713 tfLiteContext,
714 tfLiteNode,
715 nodeIndex,
716 kTfLiteBuiltinFloor);
Jim Flynn4b2f3472021-10-13 21:20:07 +0100717 case kTfLiteBuiltinFloorDiv:
718 return VisitElementwiseBinaryOperator(delegateData,
719 tfLiteContext,
720 tfLiteNode,
721 nodeIndex,
722 kTfLiteBuiltinFloorDiv);
Sadik Armagan62483be2020-10-23 17:14:43 +0100723 case kTfLiteBuiltinFullyConnected:
724 return VisitFullyConnectedOperator(delegateData,
725 tfLiteContext,
726 tfLiteNode,
727 nodeIndex,
728 kTfLiteBuiltinFullyConnected);
729 case kTfLiteBuiltinGather:
730 return VisitGatherOperator(delegateData,
731 tfLiteContext,
732 tfLiteNode,
733 nodeIndex,
734 kTfLiteBuiltinGather);
Teresa Charlind5c0ed22022-04-25 18:23:41 +0100735 case kTfLiteBuiltinGatherNd:
736 return VisitGatherNdOperator(delegateData,
737 tfLiteContext,
738 tfLiteNode,
739 nodeIndex,
740 kTfLiteBuiltinGatherNd);
Teresa Charlin077cddb2023-09-15 15:19:21 +0100741 case kTfLiteBuiltinGelu:
742 return VisitActivationOperator(delegateData,
743 tfLiteContext,
744 tfLiteNode,
745 nodeIndex,
746 kTfLiteBuiltinGelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100747 case kTfLiteBuiltinGreater:
748 return VisitComparisonOperator(delegateData,
749 tfLiteContext,
750 tfLiteNode,
751 nodeIndex,
752 kTfLiteBuiltinGreater);
753 case kTfLiteBuiltinGreaterEqual:
754 return VisitComparisonOperator(delegateData,
755 tfLiteContext,
756 tfLiteNode,
757 nodeIndex,
758 kTfLiteBuiltinGreaterEqual);
759 case kTfLiteBuiltinHardSwish:
760 return VisitActivationOperator(delegateData,
761 tfLiteContext,
762 tfLiteNode,
763 nodeIndex,
764 kTfLiteBuiltinHardSwish);
765 case kTfLiteBuiltinL2Normalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000766 return VisitL2NormalizationOperator(delegateData,
767 tfLiteContext,
768 tfLiteNode,
769 nodeIndex,
770 kTfLiteBuiltinL2Normalization);
Sadik Armagan62483be2020-10-23 17:14:43 +0100771 case kTfLiteBuiltinL2Pool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100772 return VisitPooling2dOperator(delegateData,
Tianle Chengae931732023-07-28 11:53:04 +0100773 tfLiteContext,
774 tfLiteNode,
775 nodeIndex,
776 kTfLiteBuiltinL2Pool2d);
777 case kTfLiteBuiltinLeakyRelu:
778 return VisitActivationOperator(delegateData,
779 tfLiteContext,
780 tfLiteNode,
781 nodeIndex,
782 kTfLiteBuiltinLeakyRelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100783 case kTfLiteBuiltinLess:
784 return VisitComparisonOperator(delegateData,
785 tfLiteContext,
786 tfLiteNode,
787 nodeIndex,
788 kTfLiteBuiltinLess);
789 case kTfLiteBuiltinLessEqual:
790 return VisitComparisonOperator(delegateData,
791 tfLiteContext,
792 tfLiteNode,
793 nodeIndex,
794 kTfLiteBuiltinLessEqual);
795 case kTfLiteBuiltinLocalResponseNormalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000796 return VisitLocalResponseNormalizationOperator(delegateData,
797 tfLiteContext,
798 tfLiteNode,
799 nodeIndex,
800 kTfLiteBuiltinLocalResponseNormalization);
Teresa Charlinb1f5f702022-07-12 14:16:24 +0100801 case kTfLiteBuiltinLog:
802 return VisitElementwiseUnaryOperator(delegateData,
803 tfLiteContext,
804 tfLiteNode,
805 nodeIndex,
806 armnn::UnaryOperation::Log);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000807 case kTfLiteBuiltinLogicalAnd:
808 return VisitLogicalBinaryOperator(delegateData,
809 tfLiteContext,
810 tfLiteNode,
811 nodeIndex,
812 kTfLiteBuiltinLogicalAnd,
813 armnn::LogicalBinaryOperation::LogicalAnd);
814 case kTfLiteBuiltinLogicalNot:
815 return VisitElementwiseUnaryOperator(delegateData,
816 tfLiteContext,
817 tfLiteNode,
818 nodeIndex,
819 armnn::UnaryOperation::LogicalNot);
820 case kTfLiteBuiltinLogicalOr:
821 return VisitLogicalBinaryOperator(delegateData,
822 tfLiteContext,
823 tfLiteNode,
824 nodeIndex,
825 kTfLiteBuiltinLogicalOr,
826 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100827 case kTfLiteBuiltinLogistic:
828 return VisitActivationOperator(delegateData,
829 tfLiteContext,
830 tfLiteNode,
831 nodeIndex,
832 kTfLiteBuiltinLogistic);
833 case kTfLiteBuiltinLogSoftmax:
834 return VisitSoftmaxOperator(delegateData,
835 tfLiteContext,
836 tfLiteNode,
837 nodeIndex,
838 kTfLiteBuiltinLogSoftmax);
839 case kTfLiteBuiltinLstm:
840 return VisitLstmOperator(delegateData,
841 tfLiteContext,
842 tfLiteNode,
843 nodeIndex,
844 kTfLiteBuiltinLstm);
845 case kTfLiteBuiltinMaxPool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100846 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100847 tfLiteContext,
848 tfLiteNode,
849 nodeIndex,
850 kTfLiteBuiltinMaxPool2d);
851 case kTfLiteBuiltinMaximum:
852 return VisitElementwiseBinaryOperator(delegateData,
853 tfLiteContext,
854 tfLiteNode,
855 nodeIndex,
856 kTfLiteBuiltinMaximum);
857 case kTfLiteBuiltinMean:
858 return VisitControlOperator(delegateData,
859 tfLiteContext,
860 tfLiteNode,
861 nodeIndex,
862 kTfLiteBuiltinMean);
863 case kTfLiteBuiltinMinimum:
864 return VisitElementwiseBinaryOperator(delegateData,
865 tfLiteContext,
866 tfLiteNode,
867 nodeIndex,
868 kTfLiteBuiltinMinimum);
Matthew Sloyanaf3a4ef2021-10-22 15:48:12 +0100869 case kTfLiteBuiltinMirrorPad:
870 return VisitPadOperator(delegateData,
871 tfLiteContext,
872 tfLiteNode,
873 nodeIndex,
874 kTfLiteBuiltinMirrorPad);
Sadik Armagan62483be2020-10-23 17:14:43 +0100875 case kTfLiteBuiltinMul:
876 return VisitElementwiseBinaryOperator(delegateData,
877 tfLiteContext,
878 tfLiteNode,
879 nodeIndex,
880 kTfLiteBuiltinMul);
881 case kTfLiteBuiltinNeg:
882 return VisitElementwiseUnaryOperator(delegateData,
883 tfLiteContext,
884 tfLiteNode,
885 nodeIndex,
886 armnn::UnaryOperation::Neg);
887 case kTfLiteBuiltinNotEqual:
888 return VisitComparisonOperator(delegateData,
889 tfLiteContext,
890 tfLiteNode,
891 nodeIndex,
892 kTfLiteBuiltinNotEqual);
Matthew Sloyana7a12f52021-05-06 10:05:28 +0100893 case kTfLiteBuiltinPack:
894 return VisitPackOperator(delegateData,
895 tfLiteContext,
896 tfLiteNode,
897 nodeIndex,
898 kTfLiteBuiltinPack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100899 case kTfLiteBuiltinPad:
900 return VisitPadOperator(delegateData,
901 tfLiteContext,
902 tfLiteNode,
903 nodeIndex,
904 kTfLiteBuiltinPad);
905 case kTfLiteBuiltinPadv2:
906 return VisitPadOperator(delegateData,
907 tfLiteContext,
908 tfLiteNode,
909 nodeIndex,
910 kTfLiteBuiltinPadv2);
John Mcloughlin0ec00872023-05-15 17:03:49 +0100911 case kTfLiteBuiltinPow:
912 return VisitElementwiseBinaryOperator(delegateData,
913 tfLiteContext,
914 tfLiteNode,
915 nodeIndex,
916 kTfLiteBuiltinPow);
Sadik Armagan62483be2020-10-23 17:14:43 +0100917 case kTfLiteBuiltinPrelu:
James Conroy39825482021-05-27 17:44:50 +0100918 return VisitPreluOperator(delegateData,
919 tfLiteContext,
920 tfLiteNode,
921 nodeIndex,
922 kTfLiteBuiltinPrelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100923 case kTfLiteBuiltinQuantize:
924 return VisitQuantizeOperator(delegateData,
925 tfLiteContext,
926 tfLiteNode,
927 nodeIndex,
928 kTfLiteBuiltinQuantize);
929 case kTfLiteBuiltinRank:
930 return VisitControlOperator(delegateData,
931 tfLiteContext,
932 tfLiteNode,
933 nodeIndex,
934 kTfLiteBuiltinRank);
Sadik Armagana2747482021-02-09 10:28:54 +0000935 case kTfLiteBuiltinReduceMax:
936 return VisitReduceOperator(delegateData,
937 tfLiteContext,
938 tfLiteNode,
939 nodeIndex,
940 kTfLiteBuiltinReduceMax);
941 case kTfLiteBuiltinReduceMin:
942 return VisitReduceOperator(delegateData,
943 tfLiteContext,
944 tfLiteNode,
945 nodeIndex,
946 kTfLiteBuiltinReduceMin);
Teresa Charlin4e3e8312021-08-05 12:34:37 +0100947 case kTfLiteBuiltinReduceProd:
948 return VisitReduceOperator(delegateData,
949 tfLiteContext,
950 tfLiteNode,
951 nodeIndex,
952 kTfLiteBuiltinReduceProd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100953 case kTfLiteBuiltinRelu:
954 return VisitActivationOperator(delegateData,
955 tfLiteContext,
956 tfLiteNode,
957 nodeIndex,
958 kTfLiteBuiltinRelu);
959 case kTfLiteBuiltinReluN1To1:
960 return VisitActivationOperator(delegateData,
961 tfLiteContext,
962 tfLiteNode,
963 nodeIndex,
964 kTfLiteBuiltinReluN1To1);
965 case kTfLiteBuiltinRelu6:
966 return VisitActivationOperator(delegateData,
967 tfLiteContext,
968 tfLiteNode,
969 nodeIndex,
970 kTfLiteBuiltinRelu6);
971 case kTfLiteBuiltinReshape:
972 return VisitReshapeOperator(delegateData,
973 tfLiteContext,
974 tfLiteNode,
975 nodeIndex,
976 kTfLiteBuiltinReshape);
977 case kTfLiteBuiltinResizeBilinear:
978 return VisitResizeOperator(delegateData,
979 tfLiteContext,
980 tfLiteNode,
981 nodeIndex,
982 kTfLiteBuiltinResizeBilinear);
983 case kTfLiteBuiltinResizeNearestNeighbor:
984 return VisitResizeOperator(delegateData,
985 tfLiteContext,
986 tfLiteNode,
987 nodeIndex,
988 kTfLiteBuiltinResizeNearestNeighbor);
Tracy Narine7306bbe2023-07-17 16:06:26 +0100989 case kTfLiteBuiltinReverseV2:
990 return VisitReverseV2Operator(delegateData,
991 tfLiteContext,
992 tfLiteNode,
993 nodeIndex,
994 kTfLiteBuiltinReverseV2);
Sadik Armagan62483be2020-10-23 17:14:43 +0100995 case kTfLiteBuiltinRsqrt:
996 return VisitElementwiseUnaryOperator(delegateData,
997 tfLiteContext,
998 tfLiteNode,
999 nodeIndex,
1000 armnn::UnaryOperation::Rsqrt);
Keith Davis0176fd82021-06-01 17:36:32 +01001001 case kTfLiteBuiltinShape:
1002 return VisitShapeOperator(delegateData,
1003 tfLiteContext,
1004 tfLiteNode,
1005 nodeIndex,
1006 kTfLiteBuiltinShape);
Teresa Charlinb1f5f702022-07-12 14:16:24 +01001007 case kTfLiteBuiltinSin:
1008 return VisitElementwiseUnaryOperator(delegateData,
1009 tfLiteContext,
1010 tfLiteNode,
1011 nodeIndex,
1012 armnn::UnaryOperation::Sin);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +00001013 case kTfLiteBuiltinSplit:
1014 return VisitSplitOperator(delegateData,
1015 tfLiteContext,
1016 tfLiteNode,
1017 nodeIndex,
1018 kTfLiteBuiltinSplit);
1019 case kTfLiteBuiltinSplitV:
1020 return VisitSplitVOperator(delegateData,
1021 tfLiteContext,
1022 tfLiteNode,
1023 nodeIndex,
1024 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +01001025 case kTfLiteBuiltinSqrt:
1026 return VisitElementwiseUnaryOperator(delegateData,
1027 tfLiteContext,
1028 tfLiteNode,
1029 nodeIndex,
1030 armnn::UnaryOperation::Sqrt);
John Mcloughlin0ec00872023-05-15 17:03:49 +01001031 case kTfLiteBuiltinSquaredDifference:
1032 return VisitElementwiseBinaryOperator(delegateData,
1033 tfLiteContext,
1034 tfLiteNode,
1035 nodeIndex,
1036 kTfLiteBuiltinSquaredDifference);
Sadik Armagan62483be2020-10-23 17:14:43 +01001037 case kTfLiteBuiltinSqueeze:
1038 return VisitSqueezeOperator(delegateData,
1039 tfLiteContext,
1040 tfLiteNode,
1041 nodeIndex,
1042 kTfLiteBuiltinSqueeze);
Cathal Corbett839b9322022-11-18 08:52:18 +00001043 case kTfLiteBuiltinSlice:
Sadik Armagan62483be2020-10-23 17:14:43 +01001044 return VisitSliceOperator(delegateData,
1045 tfLiteContext,
1046 tfLiteNode,
1047 nodeIndex,
Cathal Corbett839b9322022-11-18 08:52:18 +00001048 kTfLiteBuiltinSlice);
1049 case kTfLiteBuiltinStridedSlice:
1050 return VisitStridedSliceOperator(delegateData,
1051 tfLiteContext,
1052 tfLiteNode,
1053 nodeIndex,
1054 kTfLiteBuiltinStridedSlice);
Sadik Armagana2747482021-02-09 10:28:54 +00001055 case kTfLiteBuiltinSum:
1056 return VisitReduceOperator(delegateData,
1057 tfLiteContext,
1058 tfLiteNode,
1059 nodeIndex,
1060 kTfLiteBuiltinSum);
Sadik Armagan62483be2020-10-23 17:14:43 +01001061 case kTfLiteBuiltinTranspose:
1062 return VisitTransposeOperator(delegateData,
1063 tfLiteContext,
1064 tfLiteNode,
1065 nodeIndex,
1066 kTfLiteBuiltinTranspose);
1067 case kTfLiteBuiltinTransposeConv:
1068 return VisitConvolutionOperator(delegateData,
1069 tfLiteContext,
1070 tfLiteNode,
1071 nodeIndex,
1072 kTfLiteBuiltinTransposeConv);
1073 case kTfLiteBuiltinSoftmax:
1074 return VisitSoftmaxOperator(delegateData,
1075 tfLiteContext,
1076 tfLiteNode,
1077 nodeIndex,
1078 kTfLiteBuiltinSoftmax);
1079 case kTfLiteBuiltinSpaceToBatchNd:
1080 return VisitSpaceToBatchNdOperator(delegateData,
1081 tfLiteContext,
1082 tfLiteNode,
1083 nodeIndex,
1084 kTfLiteBuiltinSpaceToBatchNd);
1085 case kTfLiteBuiltinSpaceToDepth:
1086 return VisitSpaceToDepthOperator(delegateData,
1087 tfLiteContext,
1088 tfLiteNode,
1089 nodeIndex,
1090 kTfLiteBuiltinSpaceToDepth);
1091 case kTfLiteBuiltinSub:
1092 return VisitElementwiseBinaryOperator(delegateData,
1093 tfLiteContext,
1094 tfLiteNode,
1095 nodeIndex,
1096 kTfLiteBuiltinSub);
1097 case kTfLiteBuiltinTanh:
1098 return VisitActivationOperator(delegateData,
1099 tfLiteContext,
1100 tfLiteNode,
1101 nodeIndex,
1102 kTfLiteBuiltinTanh);
Tianle Cheng92ce35c2023-07-25 16:41:00 +01001103 case kTfLiteBuiltinTile:
1104 return VisitTileOperator(delegateData,
1105 tfLiteContext,
1106 tfLiteNode,
1107 nodeIndex,
1108 kTfLiteBuiltinTile);
Narumol Prangnawarat7684b182021-08-12 14:48:15 +01001109 case kTfLiteBuiltinUnidirectionalSequenceLstm:
1110 return VisitUnidirectionalSequenceLstmOperator(delegateData,
1111 tfLiteContext,
1112 tfLiteNode,
1113 nodeIndex,
1114 kTfLiteBuiltinUnidirectionalSequenceLstm);
Kevin May8ab2d7a2021-05-07 09:32:51 +01001115 case kTfLiteBuiltinUnpack:
1116 return VisitUnpackOperator(delegateData,
1117 tfLiteContext,
1118 tfLiteNode,
1119 nodeIndex,
1120 kTfLiteBuiltinUnpack);
Sadik Armagan62483be2020-10-23 17:14:43 +01001121 default:
1122 return kTfLiteError;
1123 }
Sadik Armagan3c24f432020-10-19 17:35:30 +01001124}
1125
1126} // armnnDelegate namespace