blob: 57488fc3de89706d6a230b16908ed78199fd527d [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"
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
Sadik Armagan62483be2020-10-23 17:14:43 +0100276TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
277 TfLiteContext* tfLiteContext,
278 const TfLiteIntArray* inputs,
279 std::vector<armnn::BindingPointInfo>& inputBindings)
280{
Finn Williams6f9f9902020-11-13 13:23:15 +0000281 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100282 for (unsigned int i = 0; i < numInputs; ++i)
283 {
284 const int32_t tensorId = inputs->data[i];
285 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000286 // Do not create bindings for constant inputs
287 if (tensor.allocation_type == kTfLiteMmapRo)
288 {
289 continue;
290 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100291
292 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
293 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
294
295 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
296 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
297 outputSlot.SetTensorInfo(tensorInfo);
298
299 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000300 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100301
Sadik Armagan6e36a642020-11-10 21:18:41 +0000302 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100303 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000304
Sadik Armagan62483be2020-10-23 17:14:43 +0100305 return kTfLiteOk;
306}
307
308TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
309 TfLiteContext* tfLiteContext,
310 const TfLiteIntArray* outputs,
311 std::vector<armnn::BindingPointInfo>& outputBindings)
312{
Finn Williams6f9f9902020-11-13 13:23:15 +0000313 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100314 for (unsigned int i = 0; i < numOutputs; ++i)
315 {
316 const int32_t tensorId = outputs->data[i];
317 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
318
319 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
320 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
321
322 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Ryan OSheac229b3f2023-06-27 22:34:54 +0100323
324 if (delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] == nullptr)
325 {
326 return kTfLiteError;
327 }
328
Finn Williams6f9f9902020-11-13 13:23:15 +0000329 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100330 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
331 }
332
333 return kTfLiteOk;
334}
335
Sadik Armagan3c24f432020-10-19 17:35:30 +0100336ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
337 const TfLiteDelegateParams* parameters,
338 const Delegate* delegate)
339{
Jan Eilers17d34da2021-12-08 16:15:12 +0000340 const auto startTime = armnn::GetTimeNow();
341 ARMNN_LOG(info) << "ArmnnSubgraph creation";
342
Sadik Armagan3c24f432020-10-19 17:35:30 +0100343 TfLiteIntArray* executionPlan;
344 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
345 {
346 return nullptr;
347 }
348
Sadik Armagan62483be2020-10-23 17:14:43 +0100349 // Initialize DelegateData holds network and output slots information
350 DelegateData delegateData(delegate->m_Options.GetBackends());
351
352 // Build ArmNN Network
John Mcloughlinc5ee0d72023-03-24 12:07:25 +0000353 armnn::NetworkOptions networkOptions = delegate->m_Options.GetOptimizerOptions().GetModelOptions();
Sadik Armagan3c24f432020-10-19 17:35:30 +0100354 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100355 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100356
Sadik Armagan6e36a642020-11-10 21:18:41 +0000357 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
358
Sadik Armagan62483be2020-10-23 17:14:43 +0100359 std::vector<armnn::BindingPointInfo> inputBindings;
360 std::vector<armnn::BindingPointInfo> outputBindings;
361
362 // Add input layer
363 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
364 if (status != kTfLiteOk)
365 {
366 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
367 }
368
369 // Parse TfLite delegate nodes to ArmNN
Jan Eilers17d34da2021-12-08 16:15:12 +0000370 const auto parseStartTime = armnn::GetTimeNow();
Sadik Armagan3c24f432020-10-19 17:35:30 +0100371 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
372 {
373 const int nodeIndex = parameters->nodes_to_replace->data[i];
374
375 TfLiteNode* tfLiteNode = nullptr;
376 TfLiteRegistration* tfLiteRegistration = nullptr;
377 if (tfLiteContext->GetNodeAndRegistration(
378 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
379 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000380 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100381 }
382
Sadik Armagan62483be2020-10-23 17:14:43 +0100383 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100384 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000385 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100386 }
387 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000388 ARMNN_LOG(info) << "Parse nodes to ArmNN time: " << std::setprecision(2)
389 << std::fixed << armnn::GetTimeDuration(parseStartTime).count() << " ms";
Sadik Armagan3c24f432020-10-19 17:35:30 +0100390
Sadik Armagan62483be2020-10-23 17:14:43 +0100391 // Add Output layer
392 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
393 if (status != kTfLiteOk)
394 {
395 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
396 }
397
398 // Optimize ArmNN network
399 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
400 try
401 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000402 const auto optimizeStartTime = armnn::GetTimeNow();
Sadik Armagan6e36a642020-11-10 21:18:41 +0000403 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100404 delegate->m_Options.GetBackends(),
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000405 delegate->m_Runtime->GetDeviceSpec(),
406 delegate->m_Options.GetOptimizerOptions());
Jan Eilers17d34da2021-12-08 16:15:12 +0000407 ARMNN_LOG(info) << "Optimize ArmnnSubgraph time: " << std::setprecision(2)
408 << std::fixed << armnn::GetTimeDuration(optimizeStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100409 }
Ryan OShea05b6a3e2023-01-11 15:27:50 +0000410 catch (std::exception& ex)
Sadik Armagan62483be2020-10-23 17:14:43 +0100411 {
412 std::stringstream exMessage;
413 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
414 throw armnn::Exception(exMessage.str());
415 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100416 if (!optNet)
417 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100418 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100419 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
420 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100421
Colm Donelan3e32a872021-10-04 22:55:37 +0100422 // If set, we will serialize the optimized model into a dot file.
423 const std::string serializeToDotFile = delegate->m_Options.GetSerializeToDot();
424 if (!serializeToDotFile.empty())
425 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000426 ARMNN_LOG(info) << "Writing graph to dot file: " << serializeToDotFile;
Colm Donelan3e32a872021-10-04 22:55:37 +0100427 fs::path filename = serializeToDotFile;
428 std::fstream file(filename.c_str(), std::ios_base::out);
429 optNet->SerializeToDot(file);
430 }
431
Sadik Armagan62483be2020-10-23 17:14:43 +0100432 try
433 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000434 const auto loadStartTime = armnn::GetTimeNow();
435
Sadik Armagan62483be2020-10-23 17:14:43 +0100436 // Load graph into runtime
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000437 std::string errorMessage;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000438 armnn::Status loadingStatus;
Francis Murtagh626bd902022-06-21 13:16:23 +0000439 armnn::MemorySource inputSource = armnn::MemorySource::Undefined;
440 armnn::MemorySource outputSource = armnn::MemorySource::Undefined;
441 // There's a bit of an assumption here that the delegate will only support Malloc memory source.
John Mcloughlinc5ee0d72023-03-24 12:07:25 +0000442 if (delegate->m_Options.GetOptimizerOptions().GetImportEnabled())
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000443 {
Francis Murtagh626bd902022-06-21 13:16:23 +0000444 inputSource = armnn::MemorySource::Malloc;
445 }
John Mcloughlinc5ee0d72023-03-24 12:07:25 +0000446 if (delegate->m_Options.GetOptimizerOptions().GetExportEnabled())
Francis Murtagh626bd902022-06-21 13:16:23 +0000447 {
448 outputSource = armnn::MemorySource::Malloc;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000449 }
Colm Donelan3e32a872021-10-04 22:55:37 +0100450 armnn::INetworkProperties networkProperties(false,
Francis Murtagh626bd902022-06-21 13:16:23 +0000451 inputSource,
452 outputSource,
Colm Donelan3e32a872021-10-04 22:55:37 +0100453 delegate->m_Options.GetInternalProfilingState(),
454 delegate->m_Options.GetInternalProfilingDetail());
455 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
456 std::move(optNet),
457 errorMessage,
458 networkProperties);
Sadik Armagan62483be2020-10-23 17:14:43 +0100459 if (loadingStatus != armnn::Status::Success)
460 {
Colm Donelan45142282021-10-21 23:39:52 +0100461 // Network load failed.
Colm Donelan194086f2022-11-14 17:23:07 +0000462 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded: " + errorMessage);
Sadik Armagan62483be2020-10-23 17:14:43 +0100463 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000464
465 ARMNN_LOG(info) << "Load ArmnnSubgraph time: " << std::setprecision(2)
466 << std::fixed << armnn::GetTimeDuration(loadStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100467 }
468 catch (std::exception& ex)
469 {
470 std::stringstream exMessage;
471 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
472 throw armnn::Exception(exMessage.str());
473 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100474
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000475 // Register debug callback function
476 if (delegate->m_Options.GetDebugCallbackFunction().has_value())
477 {
478 delegate->m_Runtime->RegisterDebugCallback(networkId, delegate->m_Options.GetDebugCallbackFunction().value());
479 }
480
Jan Eilers17d34da2021-12-08 16:15:12 +0000481 ARMNN_LOG(info) << "Overall ArmnnSubgraph creation time: " << std::setprecision(2)
482 << std::fixed << armnn::GetTimeDuration(startTime).count() << " ms\n";
483
Sadik Armagan3c24f432020-10-19 17:35:30 +0100484 // Create a new SubGraph with networkId and runtime
Mike Kelly5446a4d2023-01-20 15:51:05 +0000485 return new ArmnnSubgraph(networkId, delegate->m_Runtime, inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100486}
487
488TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
489{
Finn Williams6f9f9902020-11-13 13:23:15 +0000490 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100491 return kTfLiteOk;
492}
493
Sadik Armagan62483be2020-10-23 17:14:43 +0100494TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100495{
Sadik Armagan62483be2020-10-23 17:14:43 +0100496 // Prepare inputs
497 armnn::InputTensors inputTensors;
498 size_t inputIndex = 0;
499 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
500 {
501 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
502 if (tensor->allocation_type != kTfLiteMmapRo)
503 {
504 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100505 armnn::TensorInfo inputTensorInfo = inputBinding.second;
506 inputTensorInfo.SetConstant(true);
507 const armnn::ConstTensor inputTensor(inputTensorInfo, tensor->data.data);
Sadik Armagan62483be2020-10-23 17:14:43 +0100508 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100509
Sadik Armagan62483be2020-10-23 17:14:43 +0100510 ++inputIndex;
511 }
512 }
513
514 // Prepare outputs
515 armnn::OutputTensors outputTensors;
516 size_t outputIndex = 0;
517 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
518 {
519 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
520 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
521 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
522 outputTensors.emplace_back(outputIdx, outputTensor);
523
524 ++outputIndex;
525 }
526
527 // Run graph
528 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
Colm Donelan45142282021-10-21 23:39:52 +0100529 // The delegate holds its own Arm NN runtime so this is our last chance to print internal profiling data.
530 std::shared_ptr<armnn::IProfiler> profiler = m_Runtime->GetProfiler(m_NetworkId);
531 if (profiler && profiler->IsProfilingEnabled())
532 {
533 profiler->Print(std::cout);
534 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100535 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100536}
537
Sadik Armagan62483be2020-10-23 17:14:43 +0100538TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100539 TfLiteContext* tfLiteContext,
540 TfLiteRegistration* tfLiteRegistration,
541 TfLiteNode* tfLiteNode,
542 int nodeIndex)
543{
Sadik Armagan62483be2020-10-23 17:14:43 +0100544 switch (tfLiteRegistration->builtin_code)
545 {
Ryan OShead21abaf2022-06-10 14:49:11 +0100546 case kTfLiteBuiltinCustom:
547 {
548#if defined(ARMNN_POST_TFLITE_2_5)
549 // Custom operators are defined by the name rather than the builtin code.
550 // Parse the custom_name param in the registration to point to the correct visitor function.
551 std::string customOperatorName = tfLiteRegistration->custom_name;
552 if ( customOperatorName == "AveragePool3D" )
553 {
554 return VisitPooling3dOperator(delegateData,
555 tfLiteContext,
556 tfLiteNode,
557 nodeIndex,
558 customOperatorName);
559 }
560 else if (customOperatorName == "MaxPool3D")
561 {
562 return VisitPooling3dOperator(delegateData,
563 tfLiteContext,
564 tfLiteNode,
565 nodeIndex,
566 customOperatorName);
567 }
568#endif
569 // Invalid or unsupported custom operator
570 return kTfLiteError;
571 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100572 case kTfLiteBuiltinAbs:
573 return VisitElementwiseUnaryOperator(delegateData,
574 tfLiteContext,
575 tfLiteNode,
576 nodeIndex,
577 armnn::UnaryOperation::Abs);
578 case kTfLiteBuiltinAdd:
579 return VisitElementwiseBinaryOperator(delegateData,
580 tfLiteContext,
581 tfLiteNode,
582 nodeIndex,
583 kTfLiteBuiltinAdd);
584 case kTfLiteBuiltinArgMax:
585 return VisitArgMinMaxOperator(delegateData,
586 tfLiteContext,
587 tfLiteNode,
588 nodeIndex,
589 kTfLiteBuiltinArgMax);
590 case kTfLiteBuiltinArgMin:
591 return VisitArgMinMaxOperator(delegateData,
592 tfLiteContext,
593 tfLiteNode,
594 nodeIndex,
595 kTfLiteBuiltinArgMin);
596 case kTfLiteBuiltinAveragePool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100597 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100598 tfLiteContext,
599 tfLiteNode,
600 nodeIndex,
601 kTfLiteBuiltinAveragePool2d);
Ryan OShea49ed0df2022-09-21 16:09:41 +0100602 case kTfLiteBuiltinBatchMatmul:
603 return VisitBatchMatMulOperator(delegateData,
604 tfLiteContext,
605 tfLiteNode,
606 nodeIndex,
607 kTfLiteBuiltinBatchMatmul);
Sadik Armagan62483be2020-10-23 17:14:43 +0100608 case kTfLiteBuiltinBatchToSpaceNd:
609 return VisitBatchToSpaceNdOperator(delegateData,
610 tfLiteContext,
611 tfLiteNode,
612 nodeIndex,
613 kTfLiteBuiltinBatchToSpaceNd);
Idriss Chaouchcbf79292023-09-08 11:18:16 +0100614 case kTfLiteBuiltinBroadcastTo:
615 return VisitBroadcastToOperator(delegateData,
616 tfLiteContext,
617 tfLiteNode,
618 nodeIndex,
619 kTfLiteBuiltinBroadcastTo);
Sadik Armagan937565b2021-04-21 14:03:28 +0100620 case kTfLiteBuiltinCast:
621 return VisitCastOperator(delegateData,
622 tfLiteContext,
623 tfLiteNode,
624 nodeIndex,
625 kTfLiteBuiltinCast);
Teresa Charlin93f0ad02023-03-23 15:28:02 +0000626 case kTfLiteBuiltinCeil:
627 return VisitElementwiseUnaryOperator(delegateData,
628 tfLiteContext,
629 tfLiteNode,
630 nodeIndex,
631 armnn::UnaryOperation::Ceil);
Sadik Armagan62483be2020-10-23 17:14:43 +0100632 case kTfLiteBuiltinConcatenation:
633 return VisitControlOperator(delegateData,
634 tfLiteContext,
635 tfLiteNode,
636 nodeIndex,
637 kTfLiteBuiltinConcatenation);
638 case kTfLiteBuiltinConv2d:
639 return VisitConvolutionOperator(delegateData,
640 tfLiteContext,
641 tfLiteNode,
642 nodeIndex,
643 kTfLiteBuiltinConv2d);
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100644// Conv3d is only correctly supported for external delegates from TF Lite v2.6, as there was a breaking bug in v2.5.
645#if defined(ARMNN_POST_TFLITE_2_5)
646 case kTfLiteBuiltinConv3d:
647 return VisitConvolutionOperator(delegateData,
648 tfLiteContext,
649 tfLiteNode,
650 nodeIndex,
651 kTfLiteBuiltinConv3d);
652#endif
Sadik Armagan62483be2020-10-23 17:14:43 +0100653 case kTfLiteBuiltinDepthToSpace:
654 return VisitDepthToSpaceOperator(delegateData,
655 tfLiteContext,
656 tfLiteNode,
657 nodeIndex,
658 kTfLiteBuiltinDepthToSpace);
659 case kTfLiteBuiltinDepthwiseConv2d:
660 return VisitConvolutionOperator(delegateData,
661 tfLiteContext,
662 tfLiteNode,
663 nodeIndex,
664 kTfLiteBuiltinDepthwiseConv2d);
665 case kTfLiteBuiltinDequantize:
666 return VisitDequantizeOperator(delegateData,
667 tfLiteContext,
668 tfLiteNode,
669 nodeIndex,
670 kTfLiteBuiltinDequantize);
671 case kTfLiteBuiltinDiv:
672 return VisitElementwiseBinaryOperator(delegateData,
673 tfLiteContext,
674 tfLiteNode,
675 nodeIndex,
676 kTfLiteBuiltinDiv);
677 case kTfLiteBuiltinElu:
678 return VisitActivationOperator(delegateData,
679 tfLiteContext,
680 tfLiteNode,
681 nodeIndex,
682 kTfLiteBuiltinElu);
683 case kTfLiteBuiltinEqual:
684 return VisitComparisonOperator(delegateData,
685 tfLiteContext,
686 tfLiteNode,
687 nodeIndex,
688 kTfLiteBuiltinEqual);
689 case kTfLiteBuiltinExp:
690 return VisitElementwiseUnaryOperator(delegateData,
691 tfLiteContext,
692 tfLiteNode,
693 nodeIndex,
694 armnn::UnaryOperation::Exp);
695 case kTfLiteBuiltinExpandDims:
696 return VisitExpandDimsOperator(delegateData,
697 tfLiteContext,
698 tfLiteNode,
699 nodeIndex,
700 kTfLiteBuiltinExpandDims);
701 case kTfLiteBuiltinFill:
702 return VisitFillOperator(delegateData,
703 tfLiteContext,
704 tfLiteNode,
705 nodeIndex,
706 kTfLiteBuiltinFill);
707 case kTfLiteBuiltinFloor:
708 return VisitFloorOperator(delegateData,
709 tfLiteContext,
710 tfLiteNode,
711 nodeIndex,
712 kTfLiteBuiltinFloor);
Jim Flynn4b2f3472021-10-13 21:20:07 +0100713 case kTfLiteBuiltinFloorDiv:
714 return VisitElementwiseBinaryOperator(delegateData,
715 tfLiteContext,
716 tfLiteNode,
717 nodeIndex,
718 kTfLiteBuiltinFloorDiv);
Sadik Armagan62483be2020-10-23 17:14:43 +0100719 case kTfLiteBuiltinFullyConnected:
720 return VisitFullyConnectedOperator(delegateData,
721 tfLiteContext,
722 tfLiteNode,
723 nodeIndex,
724 kTfLiteBuiltinFullyConnected);
725 case kTfLiteBuiltinGather:
726 return VisitGatherOperator(delegateData,
727 tfLiteContext,
728 tfLiteNode,
729 nodeIndex,
730 kTfLiteBuiltinGather);
Teresa Charlind5c0ed22022-04-25 18:23:41 +0100731 case kTfLiteBuiltinGatherNd:
732 return VisitGatherNdOperator(delegateData,
733 tfLiteContext,
734 tfLiteNode,
735 nodeIndex,
736 kTfLiteBuiltinGatherNd);
Teresa Charlin077cddb2023-09-15 15:19:21 +0100737 case kTfLiteBuiltinGelu:
738 return VisitActivationOperator(delegateData,
739 tfLiteContext,
740 tfLiteNode,
741 nodeIndex,
742 kTfLiteBuiltinGelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100743 case kTfLiteBuiltinGreater:
744 return VisitComparisonOperator(delegateData,
745 tfLiteContext,
746 tfLiteNode,
747 nodeIndex,
748 kTfLiteBuiltinGreater);
749 case kTfLiteBuiltinGreaterEqual:
750 return VisitComparisonOperator(delegateData,
751 tfLiteContext,
752 tfLiteNode,
753 nodeIndex,
754 kTfLiteBuiltinGreaterEqual);
755 case kTfLiteBuiltinHardSwish:
756 return VisitActivationOperator(delegateData,
757 tfLiteContext,
758 tfLiteNode,
759 nodeIndex,
760 kTfLiteBuiltinHardSwish);
761 case kTfLiteBuiltinL2Normalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000762 return VisitL2NormalizationOperator(delegateData,
763 tfLiteContext,
764 tfLiteNode,
765 nodeIndex,
766 kTfLiteBuiltinL2Normalization);
Sadik Armagan62483be2020-10-23 17:14:43 +0100767 case kTfLiteBuiltinL2Pool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100768 return VisitPooling2dOperator(delegateData,
Tianle Chengae931732023-07-28 11:53:04 +0100769 tfLiteContext,
770 tfLiteNode,
771 nodeIndex,
772 kTfLiteBuiltinL2Pool2d);
773 case kTfLiteBuiltinLeakyRelu:
774 return VisitActivationOperator(delegateData,
775 tfLiteContext,
776 tfLiteNode,
777 nodeIndex,
778 kTfLiteBuiltinLeakyRelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100779 case kTfLiteBuiltinLess:
780 return VisitComparisonOperator(delegateData,
781 tfLiteContext,
782 tfLiteNode,
783 nodeIndex,
784 kTfLiteBuiltinLess);
785 case kTfLiteBuiltinLessEqual:
786 return VisitComparisonOperator(delegateData,
787 tfLiteContext,
788 tfLiteNode,
789 nodeIndex,
790 kTfLiteBuiltinLessEqual);
791 case kTfLiteBuiltinLocalResponseNormalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000792 return VisitLocalResponseNormalizationOperator(delegateData,
793 tfLiteContext,
794 tfLiteNode,
795 nodeIndex,
796 kTfLiteBuiltinLocalResponseNormalization);
Teresa Charlinb1f5f702022-07-12 14:16:24 +0100797 case kTfLiteBuiltinLog:
798 return VisitElementwiseUnaryOperator(delegateData,
799 tfLiteContext,
800 tfLiteNode,
801 nodeIndex,
802 armnn::UnaryOperation::Log);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000803 case kTfLiteBuiltinLogicalAnd:
804 return VisitLogicalBinaryOperator(delegateData,
805 tfLiteContext,
806 tfLiteNode,
807 nodeIndex,
808 kTfLiteBuiltinLogicalAnd,
809 armnn::LogicalBinaryOperation::LogicalAnd);
810 case kTfLiteBuiltinLogicalNot:
811 return VisitElementwiseUnaryOperator(delegateData,
812 tfLiteContext,
813 tfLiteNode,
814 nodeIndex,
815 armnn::UnaryOperation::LogicalNot);
816 case kTfLiteBuiltinLogicalOr:
817 return VisitLogicalBinaryOperator(delegateData,
818 tfLiteContext,
819 tfLiteNode,
820 nodeIndex,
821 kTfLiteBuiltinLogicalOr,
822 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100823 case kTfLiteBuiltinLogistic:
824 return VisitActivationOperator(delegateData,
825 tfLiteContext,
826 tfLiteNode,
827 nodeIndex,
828 kTfLiteBuiltinLogistic);
829 case kTfLiteBuiltinLogSoftmax:
830 return VisitSoftmaxOperator(delegateData,
831 tfLiteContext,
832 tfLiteNode,
833 nodeIndex,
834 kTfLiteBuiltinLogSoftmax);
835 case kTfLiteBuiltinLstm:
836 return VisitLstmOperator(delegateData,
837 tfLiteContext,
838 tfLiteNode,
839 nodeIndex,
840 kTfLiteBuiltinLstm);
841 case kTfLiteBuiltinMaxPool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100842 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100843 tfLiteContext,
844 tfLiteNode,
845 nodeIndex,
846 kTfLiteBuiltinMaxPool2d);
847 case kTfLiteBuiltinMaximum:
848 return VisitElementwiseBinaryOperator(delegateData,
849 tfLiteContext,
850 tfLiteNode,
851 nodeIndex,
852 kTfLiteBuiltinMaximum);
853 case kTfLiteBuiltinMean:
854 return VisitControlOperator(delegateData,
855 tfLiteContext,
856 tfLiteNode,
857 nodeIndex,
858 kTfLiteBuiltinMean);
859 case kTfLiteBuiltinMinimum:
860 return VisitElementwiseBinaryOperator(delegateData,
861 tfLiteContext,
862 tfLiteNode,
863 nodeIndex,
864 kTfLiteBuiltinMinimum);
Matthew Sloyanaf3a4ef2021-10-22 15:48:12 +0100865 case kTfLiteBuiltinMirrorPad:
866 return VisitPadOperator(delegateData,
867 tfLiteContext,
868 tfLiteNode,
869 nodeIndex,
870 kTfLiteBuiltinMirrorPad);
Sadik Armagan62483be2020-10-23 17:14:43 +0100871 case kTfLiteBuiltinMul:
872 return VisitElementwiseBinaryOperator(delegateData,
873 tfLiteContext,
874 tfLiteNode,
875 nodeIndex,
876 kTfLiteBuiltinMul);
877 case kTfLiteBuiltinNeg:
878 return VisitElementwiseUnaryOperator(delegateData,
879 tfLiteContext,
880 tfLiteNode,
881 nodeIndex,
882 armnn::UnaryOperation::Neg);
883 case kTfLiteBuiltinNotEqual:
884 return VisitComparisonOperator(delegateData,
885 tfLiteContext,
886 tfLiteNode,
887 nodeIndex,
888 kTfLiteBuiltinNotEqual);
Matthew Sloyana7a12f52021-05-06 10:05:28 +0100889 case kTfLiteBuiltinPack:
890 return VisitPackOperator(delegateData,
891 tfLiteContext,
892 tfLiteNode,
893 nodeIndex,
894 kTfLiteBuiltinPack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100895 case kTfLiteBuiltinPad:
896 return VisitPadOperator(delegateData,
897 tfLiteContext,
898 tfLiteNode,
899 nodeIndex,
900 kTfLiteBuiltinPad);
901 case kTfLiteBuiltinPadv2:
902 return VisitPadOperator(delegateData,
903 tfLiteContext,
904 tfLiteNode,
905 nodeIndex,
906 kTfLiteBuiltinPadv2);
John Mcloughlin0ec00872023-05-15 17:03:49 +0100907 case kTfLiteBuiltinPow:
908 return VisitElementwiseBinaryOperator(delegateData,
909 tfLiteContext,
910 tfLiteNode,
911 nodeIndex,
912 kTfLiteBuiltinPow);
Sadik Armagan62483be2020-10-23 17:14:43 +0100913 case kTfLiteBuiltinPrelu:
James Conroy39825482021-05-27 17:44:50 +0100914 return VisitPreluOperator(delegateData,
915 tfLiteContext,
916 tfLiteNode,
917 nodeIndex,
918 kTfLiteBuiltinPrelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100919 case kTfLiteBuiltinQuantize:
920 return VisitQuantizeOperator(delegateData,
921 tfLiteContext,
922 tfLiteNode,
923 nodeIndex,
924 kTfLiteBuiltinQuantize);
925 case kTfLiteBuiltinRank:
926 return VisitControlOperator(delegateData,
927 tfLiteContext,
928 tfLiteNode,
929 nodeIndex,
930 kTfLiteBuiltinRank);
Sadik Armagana2747482021-02-09 10:28:54 +0000931 case kTfLiteBuiltinReduceMax:
932 return VisitReduceOperator(delegateData,
933 tfLiteContext,
934 tfLiteNode,
935 nodeIndex,
936 kTfLiteBuiltinReduceMax);
937 case kTfLiteBuiltinReduceMin:
938 return VisitReduceOperator(delegateData,
939 tfLiteContext,
940 tfLiteNode,
941 nodeIndex,
942 kTfLiteBuiltinReduceMin);
Teresa Charlin4e3e8312021-08-05 12:34:37 +0100943 case kTfLiteBuiltinReduceProd:
944 return VisitReduceOperator(delegateData,
945 tfLiteContext,
946 tfLiteNode,
947 nodeIndex,
948 kTfLiteBuiltinReduceProd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100949 case kTfLiteBuiltinRelu:
950 return VisitActivationOperator(delegateData,
951 tfLiteContext,
952 tfLiteNode,
953 nodeIndex,
954 kTfLiteBuiltinRelu);
955 case kTfLiteBuiltinReluN1To1:
956 return VisitActivationOperator(delegateData,
957 tfLiteContext,
958 tfLiteNode,
959 nodeIndex,
960 kTfLiteBuiltinReluN1To1);
961 case kTfLiteBuiltinRelu6:
962 return VisitActivationOperator(delegateData,
963 tfLiteContext,
964 tfLiteNode,
965 nodeIndex,
966 kTfLiteBuiltinRelu6);
967 case kTfLiteBuiltinReshape:
968 return VisitReshapeOperator(delegateData,
969 tfLiteContext,
970 tfLiteNode,
971 nodeIndex,
972 kTfLiteBuiltinReshape);
973 case kTfLiteBuiltinResizeBilinear:
974 return VisitResizeOperator(delegateData,
975 tfLiteContext,
976 tfLiteNode,
977 nodeIndex,
978 kTfLiteBuiltinResizeBilinear);
979 case kTfLiteBuiltinResizeNearestNeighbor:
980 return VisitResizeOperator(delegateData,
981 tfLiteContext,
982 tfLiteNode,
983 nodeIndex,
984 kTfLiteBuiltinResizeNearestNeighbor);
Tracy Narine7306bbe2023-07-17 16:06:26 +0100985 case kTfLiteBuiltinReverseV2:
986 return VisitReverseV2Operator(delegateData,
987 tfLiteContext,
988 tfLiteNode,
989 nodeIndex,
990 kTfLiteBuiltinReverseV2);
Sadik Armagan62483be2020-10-23 17:14:43 +0100991 case kTfLiteBuiltinRsqrt:
992 return VisitElementwiseUnaryOperator(delegateData,
993 tfLiteContext,
994 tfLiteNode,
995 nodeIndex,
996 armnn::UnaryOperation::Rsqrt);
Keith Davis0176fd82021-06-01 17:36:32 +0100997 case kTfLiteBuiltinShape:
998 return VisitShapeOperator(delegateData,
999 tfLiteContext,
1000 tfLiteNode,
1001 nodeIndex,
1002 kTfLiteBuiltinShape);
Teresa Charlinb1f5f702022-07-12 14:16:24 +01001003 case kTfLiteBuiltinSin:
1004 return VisitElementwiseUnaryOperator(delegateData,
1005 tfLiteContext,
1006 tfLiteNode,
1007 nodeIndex,
1008 armnn::UnaryOperation::Sin);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +00001009 case kTfLiteBuiltinSplit:
1010 return VisitSplitOperator(delegateData,
1011 tfLiteContext,
1012 tfLiteNode,
1013 nodeIndex,
1014 kTfLiteBuiltinSplit);
1015 case kTfLiteBuiltinSplitV:
1016 return VisitSplitVOperator(delegateData,
1017 tfLiteContext,
1018 tfLiteNode,
1019 nodeIndex,
1020 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +01001021 case kTfLiteBuiltinSqrt:
1022 return VisitElementwiseUnaryOperator(delegateData,
1023 tfLiteContext,
1024 tfLiteNode,
1025 nodeIndex,
1026 armnn::UnaryOperation::Sqrt);
John Mcloughlin0ec00872023-05-15 17:03:49 +01001027 case kTfLiteBuiltinSquaredDifference:
1028 return VisitElementwiseBinaryOperator(delegateData,
1029 tfLiteContext,
1030 tfLiteNode,
1031 nodeIndex,
1032 kTfLiteBuiltinSquaredDifference);
Sadik Armagan62483be2020-10-23 17:14:43 +01001033 case kTfLiteBuiltinSqueeze:
1034 return VisitSqueezeOperator(delegateData,
1035 tfLiteContext,
1036 tfLiteNode,
1037 nodeIndex,
1038 kTfLiteBuiltinSqueeze);
Cathal Corbett839b9322022-11-18 08:52:18 +00001039 case kTfLiteBuiltinSlice:
Sadik Armagan62483be2020-10-23 17:14:43 +01001040 return VisitSliceOperator(delegateData,
1041 tfLiteContext,
1042 tfLiteNode,
1043 nodeIndex,
Cathal Corbett839b9322022-11-18 08:52:18 +00001044 kTfLiteBuiltinSlice);
1045 case kTfLiteBuiltinStridedSlice:
1046 return VisitStridedSliceOperator(delegateData,
1047 tfLiteContext,
1048 tfLiteNode,
1049 nodeIndex,
1050 kTfLiteBuiltinStridedSlice);
Sadik Armagana2747482021-02-09 10:28:54 +00001051 case kTfLiteBuiltinSum:
1052 return VisitReduceOperator(delegateData,
1053 tfLiteContext,
1054 tfLiteNode,
1055 nodeIndex,
1056 kTfLiteBuiltinSum);
Sadik Armagan62483be2020-10-23 17:14:43 +01001057 case kTfLiteBuiltinTranspose:
1058 return VisitTransposeOperator(delegateData,
1059 tfLiteContext,
1060 tfLiteNode,
1061 nodeIndex,
1062 kTfLiteBuiltinTranspose);
1063 case kTfLiteBuiltinTransposeConv:
1064 return VisitConvolutionOperator(delegateData,
1065 tfLiteContext,
1066 tfLiteNode,
1067 nodeIndex,
1068 kTfLiteBuiltinTransposeConv);
1069 case kTfLiteBuiltinSoftmax:
1070 return VisitSoftmaxOperator(delegateData,
1071 tfLiteContext,
1072 tfLiteNode,
1073 nodeIndex,
1074 kTfLiteBuiltinSoftmax);
1075 case kTfLiteBuiltinSpaceToBatchNd:
1076 return VisitSpaceToBatchNdOperator(delegateData,
1077 tfLiteContext,
1078 tfLiteNode,
1079 nodeIndex,
1080 kTfLiteBuiltinSpaceToBatchNd);
1081 case kTfLiteBuiltinSpaceToDepth:
1082 return VisitSpaceToDepthOperator(delegateData,
1083 tfLiteContext,
1084 tfLiteNode,
1085 nodeIndex,
1086 kTfLiteBuiltinSpaceToDepth);
1087 case kTfLiteBuiltinSub:
1088 return VisitElementwiseBinaryOperator(delegateData,
1089 tfLiteContext,
1090 tfLiteNode,
1091 nodeIndex,
1092 kTfLiteBuiltinSub);
1093 case kTfLiteBuiltinTanh:
1094 return VisitActivationOperator(delegateData,
1095 tfLiteContext,
1096 tfLiteNode,
1097 nodeIndex,
1098 kTfLiteBuiltinTanh);
Tianle Cheng92ce35c2023-07-25 16:41:00 +01001099 case kTfLiteBuiltinTile:
1100 return VisitTileOperator(delegateData,
1101 tfLiteContext,
1102 tfLiteNode,
1103 nodeIndex,
1104 kTfLiteBuiltinTile);
Narumol Prangnawarat7684b182021-08-12 14:48:15 +01001105 case kTfLiteBuiltinUnidirectionalSequenceLstm:
1106 return VisitUnidirectionalSequenceLstmOperator(delegateData,
1107 tfLiteContext,
1108 tfLiteNode,
1109 nodeIndex,
1110 kTfLiteBuiltinUnidirectionalSequenceLstm);
Kevin May8ab2d7a2021-05-07 09:32:51 +01001111 case kTfLiteBuiltinUnpack:
1112 return VisitUnpackOperator(delegateData,
1113 tfLiteContext,
1114 tfLiteNode,
1115 nodeIndex,
1116 kTfLiteBuiltinUnpack);
Sadik Armagan62483be2020-10-23 17:14:43 +01001117 default:
1118 return kTfLiteError;
1119 }
Sadik Armagan3c24f432020-10-19 17:35:30 +01001120}
1121
1122} // armnnDelegate namespace