blob: b494a367693cf4a898e895ed588377cc86cf6ee1 [file] [log] [blame]
Sadik Armagan3c24f432020-10-19 17:35:30 +01001//
Mike Kelly5446a4d2023-01-20 15:51:05 +00002// Copyright © 2020-2023 Arm Ltd and Contributors. All rights reserved.
Sadik Armagan3c24f432020-10-19 17:35:30 +01003// SPDX-License-Identifier: MIT
4//
5
6#include <armnn_delegate.hpp>
Sadik Armagan62483be2020-10-23 17:14:43 +01007
Matthew Sloyanac001ee2021-02-03 10:43:04 +00008#include "Version.hpp"
9
Sadik Armagan62483be2020-10-23 17:14:43 +010010#include "Activation.hpp"
11#include "ArgMinMax.hpp"
Ryan OShea49ed0df2022-09-21 16:09:41 +010012#include "BatchMatMul.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010013#include "BatchSpace.hpp"
14#include "Comparison.hpp"
15#include "Convolution.hpp"
16#include "Control.hpp"
17#include "ElementwiseBinary.hpp"
18#include "ElementwiseUnary.hpp"
19#include "Fill.hpp"
20#include "FullyConnected.hpp"
21#include "Gather.hpp"
Teresa Charlind5c0ed22022-04-25 18:23:41 +010022#include "GatherNd.hpp"
Matthew Sloyanc8eb9552020-11-26 10:54:22 +000023#include "LogicalBinary.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010024#include "Lstm.hpp"
25#include "Normalization.hpp"
Matthew Sloyana7a12f52021-05-06 10:05:28 +010026#include "Pack.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010027#include "Pad.hpp"
28#include "Pooling.hpp"
James Conroy39825482021-05-27 17:44:50 +010029#include "Prelu.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010030#include "Quantization.hpp"
31#include "Redefine.hpp"
Sadik Armagana2747482021-02-09 10:28:54 +000032#include "Reduce.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010033#include "Resize.hpp"
34#include "Round.hpp"
Keith Davis0176fd82021-06-01 17:36:32 +010035#include "Shape.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010036#include "Slice.hpp"
Cathal Corbett839b9322022-11-18 08:52:18 +000037#include "StridedSlice.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010038#include "Softmax.hpp"
39#include "SpaceDepth.hpp"
Sadik Armagan34fa1bd2020-11-27 12:40:52 +000040#include "Split.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010041#include "Transpose.hpp"
Narumol Prangnawarat7684b182021-08-12 14:48:15 +010042#include "UnidirectionalSequenceLstm.hpp"
Kevin May8ab2d7a2021-05-07 09:32:51 +010043#include "Unpack.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010044
Colm Donelan3e32a872021-10-04 22:55:37 +010045#include <armnnUtils/Filesystem.hpp>
Jan Eilers17d34da2021-12-08 16:15:12 +000046#include <armnn/utility/Timer.hpp>
Sadik Armagan62483be2020-10-23 17:14:43 +010047#include <flatbuffers/flatbuffers.h>
48#include <tensorflow/lite/context_util.h>
Jim Flynn4b2f3472021-10-13 21:20:07 +010049#include <tensorflow/lite/schema/schema_generated.h>
Sadik Armagan62483be2020-10-23 17:14:43 +010050
Sadik Armagan3c24f432020-10-19 17:35:30 +010051#include <algorithm>
Matthew Sloyanac001ee2021-02-03 10:43:04 +000052#include <iostream>
Sadik Armagan62483be2020-10-23 17:14:43 +010053#include <sstream>
Sadik Armagan3c24f432020-10-19 17:35:30 +010054
55namespace armnnDelegate
56{
57
Sadik Armagan62483be2020-10-23 17:14:43 +010058DelegateOptions TfLiteArmnnDelegateOptionsDefault()
59{
60 DelegateOptions options(armnn::Compute::CpuRef);
61 return options;
62}
63
64TfLiteDelegate* TfLiteArmnnDelegateCreate(armnnDelegate::DelegateOptions options)
65{
66 auto* armnnDelegate = new ::armnnDelegate::Delegate(options);
67 return armnnDelegate->GetDelegate();
68}
69
70void TfLiteArmnnDelegateDelete(TfLiteDelegate* tfLiteDelegate)
71{
72 if (tfLiteDelegate != nullptr)
73 {
74 delete static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_);
75 }
76}
77
78TfLiteStatus DoPrepare(TfLiteContext* tfLiteContext, TfLiteDelegate* tfLiteDelegate)
79{
80 TfLiteIntArray* supportedOperators =
81 static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_)->IdentifyOperatorsToDelegate(tfLiteContext);
82
83 // ArmNN Delegate Registration
84 static const TfLiteRegistration kArmnnSubgraphRegistration = {
85 // ArmnnSubgraph Init
86 .init = [](TfLiteContext* tfLiteContext, const char* buffer, size_t length) -> void* {
Finn Williams6f9f9902020-11-13 13:23:15 +000087 armnn::IgnoreUnused(length);
Sadik Armagan62483be2020-10-23 17:14:43 +010088 const TfLiteDelegateParams* parameters = reinterpret_cast<const TfLiteDelegateParams*>(buffer);
89
90 return static_cast<void*>(ArmnnSubgraph::Create(
91 tfLiteContext, parameters, static_cast<::armnnDelegate::Delegate*>(parameters->delegate->data_)));
92 },
93 // ArmnnSubgraph Free
94 .free = [](TfLiteContext* tfLiteContext, void* buffer) -> void {
Finn Williams6f9f9902020-11-13 13:23:15 +000095 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan62483be2020-10-23 17:14:43 +010096 if (buffer != nullptr)
97 {
98 delete static_cast<ArmnnSubgraph*>(buffer);
99 }
100 },
101 // ArmnnSubgraph Prepare
102 .prepare = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
103 if (tfLiteNode->user_data == nullptr)
104 {
105 return kTfLiteError;
106 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100107 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Prepare(tfLiteContext);
108 },
109 // ArmnnSubgraph Invoke
110 .invoke = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
111 if (tfLiteNode->user_data == nullptr)
112 {
113 return kTfLiteError;
114 }
115
116 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Invoke(tfLiteContext, tfLiteNode);
117 },
118
119 .profiling_string = nullptr,
120 .builtin_code = kTfLiteBuiltinDelegate,
121 .custom_name = "TfLiteArmNnDelegate",
122 .version = 1,
Colm Donelan718966f2022-10-10 10:06:12 +0100123 .registration_external = nullptr,
Sadik Armagan62483be2020-10-23 17:14:43 +0100124 };
125
126 const TfLiteStatus status =
127 tfLiteContext->ReplaceNodeSubsetsWithDelegateKernels(
128 tfLiteContext, kArmnnSubgraphRegistration, supportedOperators, tfLiteDelegate);
129
130 TfLiteIntArrayFree(supportedOperators);
131 return status;
132
133}
134
Sadik Armagan3c24f432020-10-19 17:35:30 +0100135Delegate::Delegate(armnnDelegate::DelegateOptions options)
Mike Kelly5446a4d2023-01-20 15:51:05 +0000136 : m_Options(std::move(options))
Sadik Armagan3c24f432020-10-19 17:35:30 +0100137{
Jan Eilers2cd18472020-12-15 10:42:38 +0000138 // Configures logging for ARMNN
Colm Donelanda7f2f92022-12-20 16:21:35 +0000139 if (m_Options.IsLoggingEnabled())
Jan Eilers2cd18472020-12-15 10:42:38 +0000140 {
Colm Donelanda7f2f92022-12-20 16:21:35 +0000141 armnn::ConfigureLogging(true, true, m_Options.GetLoggingSeverity());
Jan Eilers2cd18472020-12-15 10:42:38 +0000142 }
Mike Kelly5446a4d2023-01-20 15:51:05 +0000143 // Create/Get the static ArmNN Runtime. Note that the m_Runtime will be shared by all armnn_delegate
144 // instances so the RuntimeOptions cannot be altered for different armnn_delegate instances.
145 m_Runtime = GetRuntime(m_Options.GetRuntimeOptions());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100146 std::vector<armnn::BackendId> backends;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100147 if (m_Runtime)
148 {
149 const armnn::BackendIdSet supportedDevices = m_Runtime->GetDeviceSpec().GetSupportedBackends();
150 for (auto& backend : m_Options.GetBackends())
151 {
152 if (std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) == supportedDevices.cend())
153 {
Sadik Armagan0534e032020-10-27 17:30:18 +0000154 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100155 "TfLiteArmnnDelegate: Requested unknown backend %s", backend.Get().c_str());
156 }
157 else
158 {
159 backends.push_back(backend);
160 }
161 }
162 }
163
164 if (backends.empty())
165 {
166 // No known backend specified
167 throw armnn::InvalidArgumentException("TfLiteArmnnDelegate: No known backend specified.");
168 }
169 m_Options.SetBackends(backends);
170
171 TFLITE_LOG_PROD_ONCE(tflite::TFLITE_LOG_INFO, "TfLiteArmnnDelegate: Created TfLite ArmNN delegate.");
172}
173
Sadik Armagan62483be2020-10-23 17:14:43 +0100174TfLiteIntArray* Delegate::IdentifyOperatorsToDelegate(TfLiteContext* tfLiteContext)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100175{
176 TfLiteIntArray* executionPlan = nullptr;
177 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
178 {
179 TF_LITE_KERNEL_LOG(tfLiteContext, "TfLiteArmnnDelegate: Unable to get graph execution plan.");
180 return nullptr;
181 }
182
Sadik Armagan62483be2020-10-23 17:14:43 +0100183 // Delegate data with null network
184 DelegateData delegateData(m_Options.GetBackends());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100185
186 TfLiteIntArray* nodesToDelegate = TfLiteIntArrayCreate(executionPlan->size);
187 nodesToDelegate->size = 0;
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000188
189 std::set<int32_t> unsupportedOperators;
190
Sadik Armagan3c24f432020-10-19 17:35:30 +0100191 for (int i = 0; i < executionPlan->size; ++i)
192 {
193 const int nodeIndex = executionPlan->data[i];
194
195 // If TfLite nodes can be delegated to ArmNN
196 TfLiteNode* tfLiteNode = nullptr;
197 TfLiteRegistration* tfLiteRegistration = nullptr;
198 if (tfLiteContext->GetNodeAndRegistration(
199 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
200 {
201 TF_LITE_KERNEL_LOG(tfLiteContext,
202 "TfLiteArmnnDelegate: Unable to get node and registration for node %d.",
203 nodeIndex);
204 continue;
205 }
206
Ryan OShea05b6a3e2023-01-11 15:27:50 +0000207 TfLiteStatus visitStatus;
208
209 try
210 {
211 visitStatus = ArmnnSubgraph::VisitNode(
212 delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex);
213 }
214 catch(std::exception& ex)
215 {
216 ARMNN_LOG(error) << "ArmNN Failed to visit node with error: " << ex.what();
217 visitStatus = kTfLiteError;
218 }
219
220 if ( visitStatus != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100221 {
222 // node is not supported by ArmNN
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000223 unsupportedOperators.insert(tfLiteRegistration->builtin_code);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100224 continue;
225 }
226
227 nodesToDelegate->data[nodesToDelegate->size++] = nodeIndex;
228 }
229
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000230 for (std::set<int32_t>::iterator it=unsupportedOperators.begin(); it!=unsupportedOperators.end(); ++it)
231 {
232 TF_LITE_KERNEL_LOG(tfLiteContext,
233 "Operator %s [%d] is not supported by armnn_delegate.",
234 tflite::EnumNameBuiltinOperator(tflite::BuiltinOperator(*it)),
235 *it);
236 }
237
Sadik Armaganca565c12022-08-16 12:17:24 +0100238 if (!unsupportedOperators.empty() && m_Options.TfLiteRuntimeFallbackDisabled())
239 {
240 std::stringstream exMessage;
241 exMessage << "TfLiteArmnnDelegate: There are unsupported operators in the model. ";
242 exMessage << "Not falling back to TfLite Runtime as fallback is disabled. ";
243 exMessage << "This should only be disabled under test conditions.";
244 throw armnn::Exception(exMessage.str());
245 }
Colm Donelan3811a972023-01-25 21:19:49 +0000246 if (nodesToDelegate->size == 0)
247 {
248 ARMNN_LOG(info) << "No operators in this model are supported by the Arm NN TfLite delegate." <<
249 " The model will be executed entirely by TfLite runtime.";
250 }
Sadik Armaganca565c12022-08-16 12:17:24 +0100251
Sadik Armagan62483be2020-10-23 17:14:43 +0100252 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100253 return nodesToDelegate;
254}
255
256TfLiteDelegate* Delegate::GetDelegate()
257{
258 return &m_Delegate;
259}
260
Matthew Sloyanac001ee2021-02-03 10:43:04 +0000261const std::string Delegate::GetVersion()
262{
263 return DELEGATE_VERSION;
264}
265
Sadik Armagan62483be2020-10-23 17:14:43 +0100266TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
267 TfLiteContext* tfLiteContext,
268 const TfLiteIntArray* inputs,
269 std::vector<armnn::BindingPointInfo>& inputBindings)
270{
Finn Williams6f9f9902020-11-13 13:23:15 +0000271 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100272 for (unsigned int i = 0; i < numInputs; ++i)
273 {
274 const int32_t tensorId = inputs->data[i];
275 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000276 // Do not create bindings for constant inputs
277 if (tensor.allocation_type == kTfLiteMmapRo)
278 {
279 continue;
280 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100281
282 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
283 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
284
285 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
286 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
287 outputSlot.SetTensorInfo(tensorInfo);
288
289 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000290 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100291
Sadik Armagan6e36a642020-11-10 21:18:41 +0000292 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100293 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000294
Sadik Armagan62483be2020-10-23 17:14:43 +0100295 return kTfLiteOk;
296}
297
298TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
299 TfLiteContext* tfLiteContext,
300 const TfLiteIntArray* outputs,
301 std::vector<armnn::BindingPointInfo>& outputBindings)
302{
Finn Williams6f9f9902020-11-13 13:23:15 +0000303 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100304 for (unsigned int i = 0; i < numOutputs; ++i)
305 {
306 const int32_t tensorId = outputs->data[i];
307 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
308
309 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
310 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
311
312 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Finn Williams6f9f9902020-11-13 13:23:15 +0000313 ARMNN_ASSERT(delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] != nullptr);
314 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100315 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
316 }
317
318 return kTfLiteOk;
319}
320
Sadik Armagan3c24f432020-10-19 17:35:30 +0100321ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
322 const TfLiteDelegateParams* parameters,
323 const Delegate* delegate)
324{
Jan Eilers17d34da2021-12-08 16:15:12 +0000325 const auto startTime = armnn::GetTimeNow();
326 ARMNN_LOG(info) << "ArmnnSubgraph creation";
327
Sadik Armagan3c24f432020-10-19 17:35:30 +0100328 TfLiteIntArray* executionPlan;
329 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
330 {
331 return nullptr;
332 }
333
Sadik Armagan62483be2020-10-23 17:14:43 +0100334 // Initialize DelegateData holds network and output slots information
335 DelegateData delegateData(delegate->m_Options.GetBackends());
336
337 // Build ArmNN Network
John Mcloughlinc5ee0d72023-03-24 12:07:25 +0000338 armnn::NetworkOptions networkOptions = delegate->m_Options.GetOptimizerOptions().GetModelOptions();
Sadik Armagan3c24f432020-10-19 17:35:30 +0100339 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100340 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100341
Sadik Armagan6e36a642020-11-10 21:18:41 +0000342 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
343
Sadik Armagan62483be2020-10-23 17:14:43 +0100344 std::vector<armnn::BindingPointInfo> inputBindings;
345 std::vector<armnn::BindingPointInfo> outputBindings;
346
347 // Add input layer
348 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
349 if (status != kTfLiteOk)
350 {
351 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
352 }
353
354 // Parse TfLite delegate nodes to ArmNN
Jan Eilers17d34da2021-12-08 16:15:12 +0000355 const auto parseStartTime = armnn::GetTimeNow();
Sadik Armagan3c24f432020-10-19 17:35:30 +0100356 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
357 {
358 const int nodeIndex = parameters->nodes_to_replace->data[i];
359
360 TfLiteNode* tfLiteNode = nullptr;
361 TfLiteRegistration* tfLiteRegistration = nullptr;
362 if (tfLiteContext->GetNodeAndRegistration(
363 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
364 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000365 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100366 }
367
Sadik Armagan62483be2020-10-23 17:14:43 +0100368 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100369 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000370 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100371 }
372 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000373 ARMNN_LOG(info) << "Parse nodes to ArmNN time: " << std::setprecision(2)
374 << std::fixed << armnn::GetTimeDuration(parseStartTime).count() << " ms";
Sadik Armagan3c24f432020-10-19 17:35:30 +0100375
Sadik Armagan62483be2020-10-23 17:14:43 +0100376 // Add Output layer
377 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
378 if (status != kTfLiteOk)
379 {
380 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
381 }
382
383 // Optimize ArmNN network
384 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
385 try
386 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000387 const auto optimizeStartTime = armnn::GetTimeNow();
Sadik Armagan6e36a642020-11-10 21:18:41 +0000388 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100389 delegate->m_Options.GetBackends(),
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000390 delegate->m_Runtime->GetDeviceSpec(),
391 delegate->m_Options.GetOptimizerOptions());
Jan Eilers17d34da2021-12-08 16:15:12 +0000392 ARMNN_LOG(info) << "Optimize ArmnnSubgraph time: " << std::setprecision(2)
393 << std::fixed << armnn::GetTimeDuration(optimizeStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100394 }
Ryan OShea05b6a3e2023-01-11 15:27:50 +0000395 catch (std::exception& ex)
Sadik Armagan62483be2020-10-23 17:14:43 +0100396 {
397 std::stringstream exMessage;
398 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
399 throw armnn::Exception(exMessage.str());
400 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100401 if (!optNet)
402 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100403 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100404 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
405 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100406
Colm Donelan3e32a872021-10-04 22:55:37 +0100407 // If set, we will serialize the optimized model into a dot file.
408 const std::string serializeToDotFile = delegate->m_Options.GetSerializeToDot();
409 if (!serializeToDotFile.empty())
410 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000411 ARMNN_LOG(info) << "Writing graph to dot file: " << serializeToDotFile;
Colm Donelan3e32a872021-10-04 22:55:37 +0100412 fs::path filename = serializeToDotFile;
413 std::fstream file(filename.c_str(), std::ios_base::out);
414 optNet->SerializeToDot(file);
415 }
416
Sadik Armagan62483be2020-10-23 17:14:43 +0100417 try
418 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000419 const auto loadStartTime = armnn::GetTimeNow();
420
Sadik Armagan62483be2020-10-23 17:14:43 +0100421 // Load graph into runtime
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000422 std::string errorMessage;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000423 armnn::Status loadingStatus;
Francis Murtagh626bd902022-06-21 13:16:23 +0000424 armnn::MemorySource inputSource = armnn::MemorySource::Undefined;
425 armnn::MemorySource outputSource = armnn::MemorySource::Undefined;
426 // There's a bit of an assumption here that the delegate will only support Malloc memory source.
John Mcloughlinc5ee0d72023-03-24 12:07:25 +0000427 if (delegate->m_Options.GetOptimizerOptions().GetImportEnabled())
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000428 {
Francis Murtagh626bd902022-06-21 13:16:23 +0000429 inputSource = armnn::MemorySource::Malloc;
430 }
John Mcloughlinc5ee0d72023-03-24 12:07:25 +0000431 if (delegate->m_Options.GetOptimizerOptions().GetExportEnabled())
Francis Murtagh626bd902022-06-21 13:16:23 +0000432 {
433 outputSource = armnn::MemorySource::Malloc;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000434 }
Colm Donelan3e32a872021-10-04 22:55:37 +0100435 armnn::INetworkProperties networkProperties(false,
Francis Murtagh626bd902022-06-21 13:16:23 +0000436 inputSource,
437 outputSource,
Colm Donelan3e32a872021-10-04 22:55:37 +0100438 delegate->m_Options.GetInternalProfilingState(),
439 delegate->m_Options.GetInternalProfilingDetail());
440 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
441 std::move(optNet),
442 errorMessage,
443 networkProperties);
Sadik Armagan62483be2020-10-23 17:14:43 +0100444 if (loadingStatus != armnn::Status::Success)
445 {
Colm Donelan45142282021-10-21 23:39:52 +0100446 // Network load failed.
Colm Donelan194086f2022-11-14 17:23:07 +0000447 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded: " + errorMessage);
Sadik Armagan62483be2020-10-23 17:14:43 +0100448 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000449
450 ARMNN_LOG(info) << "Load ArmnnSubgraph time: " << std::setprecision(2)
451 << std::fixed << armnn::GetTimeDuration(loadStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100452 }
453 catch (std::exception& ex)
454 {
455 std::stringstream exMessage;
456 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
457 throw armnn::Exception(exMessage.str());
458 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100459
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000460 // Register debug callback function
461 if (delegate->m_Options.GetDebugCallbackFunction().has_value())
462 {
463 delegate->m_Runtime->RegisterDebugCallback(networkId, delegate->m_Options.GetDebugCallbackFunction().value());
464 }
465
Jan Eilers17d34da2021-12-08 16:15:12 +0000466 ARMNN_LOG(info) << "Overall ArmnnSubgraph creation time: " << std::setprecision(2)
467 << std::fixed << armnn::GetTimeDuration(startTime).count() << " ms\n";
468
Sadik Armagan3c24f432020-10-19 17:35:30 +0100469 // Create a new SubGraph with networkId and runtime
Mike Kelly5446a4d2023-01-20 15:51:05 +0000470 return new ArmnnSubgraph(networkId, delegate->m_Runtime, inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100471}
472
473TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
474{
Finn Williams6f9f9902020-11-13 13:23:15 +0000475 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100476 return kTfLiteOk;
477}
478
Sadik Armagan62483be2020-10-23 17:14:43 +0100479TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100480{
Sadik Armagan62483be2020-10-23 17:14:43 +0100481 // Prepare inputs
482 armnn::InputTensors inputTensors;
483 size_t inputIndex = 0;
484 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
485 {
486 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
487 if (tensor->allocation_type != kTfLiteMmapRo)
488 {
489 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100490 armnn::TensorInfo inputTensorInfo = inputBinding.second;
491 inputTensorInfo.SetConstant(true);
492 const armnn::ConstTensor inputTensor(inputTensorInfo, tensor->data.data);
Sadik Armagan62483be2020-10-23 17:14:43 +0100493 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100494
Sadik Armagan62483be2020-10-23 17:14:43 +0100495 ++inputIndex;
496 }
497 }
498
499 // Prepare outputs
500 armnn::OutputTensors outputTensors;
501 size_t outputIndex = 0;
502 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
503 {
504 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
505 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
506 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
507 outputTensors.emplace_back(outputIdx, outputTensor);
508
509 ++outputIndex;
510 }
511
512 // Run graph
513 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
Colm Donelan45142282021-10-21 23:39:52 +0100514 // The delegate holds its own Arm NN runtime so this is our last chance to print internal profiling data.
515 std::shared_ptr<armnn::IProfiler> profiler = m_Runtime->GetProfiler(m_NetworkId);
516 if (profiler && profiler->IsProfilingEnabled())
517 {
518 profiler->Print(std::cout);
519 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100520 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100521}
522
Sadik Armagan62483be2020-10-23 17:14:43 +0100523TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100524 TfLiteContext* tfLiteContext,
525 TfLiteRegistration* tfLiteRegistration,
526 TfLiteNode* tfLiteNode,
527 int nodeIndex)
528{
Sadik Armagan62483be2020-10-23 17:14:43 +0100529 switch (tfLiteRegistration->builtin_code)
530 {
Ryan OShead21abaf2022-06-10 14:49:11 +0100531 case kTfLiteBuiltinCustom:
532 {
533#if defined(ARMNN_POST_TFLITE_2_5)
534 // Custom operators are defined by the name rather than the builtin code.
535 // Parse the custom_name param in the registration to point to the correct visitor function.
536 std::string customOperatorName = tfLiteRegistration->custom_name;
537 if ( customOperatorName == "AveragePool3D" )
538 {
539 return VisitPooling3dOperator(delegateData,
540 tfLiteContext,
541 tfLiteNode,
542 nodeIndex,
543 customOperatorName);
544 }
545 else if (customOperatorName == "MaxPool3D")
546 {
547 return VisitPooling3dOperator(delegateData,
548 tfLiteContext,
549 tfLiteNode,
550 nodeIndex,
551 customOperatorName);
552 }
553#endif
554 // Invalid or unsupported custom operator
555 return kTfLiteError;
556 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100557 case kTfLiteBuiltinAbs:
558 return VisitElementwiseUnaryOperator(delegateData,
559 tfLiteContext,
560 tfLiteNode,
561 nodeIndex,
562 armnn::UnaryOperation::Abs);
563 case kTfLiteBuiltinAdd:
564 return VisitElementwiseBinaryOperator(delegateData,
565 tfLiteContext,
566 tfLiteNode,
567 nodeIndex,
568 kTfLiteBuiltinAdd);
569 case kTfLiteBuiltinArgMax:
570 return VisitArgMinMaxOperator(delegateData,
571 tfLiteContext,
572 tfLiteNode,
573 nodeIndex,
574 kTfLiteBuiltinArgMax);
575 case kTfLiteBuiltinArgMin:
576 return VisitArgMinMaxOperator(delegateData,
577 tfLiteContext,
578 tfLiteNode,
579 nodeIndex,
580 kTfLiteBuiltinArgMin);
581 case kTfLiteBuiltinAveragePool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100582 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100583 tfLiteContext,
584 tfLiteNode,
585 nodeIndex,
586 kTfLiteBuiltinAveragePool2d);
Ryan OShea49ed0df2022-09-21 16:09:41 +0100587 case kTfLiteBuiltinBatchMatmul:
588 return VisitBatchMatMulOperator(delegateData,
589 tfLiteContext,
590 tfLiteNode,
591 nodeIndex,
592 kTfLiteBuiltinBatchMatmul);
Sadik Armagan62483be2020-10-23 17:14:43 +0100593 case kTfLiteBuiltinBatchToSpaceNd:
594 return VisitBatchToSpaceNdOperator(delegateData,
595 tfLiteContext,
596 tfLiteNode,
597 nodeIndex,
598 kTfLiteBuiltinBatchToSpaceNd);
Sadik Armagan937565b2021-04-21 14:03:28 +0100599 case kTfLiteBuiltinCast:
600 return VisitCastOperator(delegateData,
601 tfLiteContext,
602 tfLiteNode,
603 nodeIndex,
604 kTfLiteBuiltinCast);
Sadik Armagan62483be2020-10-23 17:14:43 +0100605 case kTfLiteBuiltinConcatenation:
606 return VisitControlOperator(delegateData,
607 tfLiteContext,
608 tfLiteNode,
609 nodeIndex,
610 kTfLiteBuiltinConcatenation);
611 case kTfLiteBuiltinConv2d:
612 return VisitConvolutionOperator(delegateData,
613 tfLiteContext,
614 tfLiteNode,
615 nodeIndex,
616 kTfLiteBuiltinConv2d);
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100617// Conv3d is only correctly supported for external delegates from TF Lite v2.6, as there was a breaking bug in v2.5.
618#if defined(ARMNN_POST_TFLITE_2_5)
619 case kTfLiteBuiltinConv3d:
620 return VisitConvolutionOperator(delegateData,
621 tfLiteContext,
622 tfLiteNode,
623 nodeIndex,
624 kTfLiteBuiltinConv3d);
625#endif
Sadik Armagan62483be2020-10-23 17:14:43 +0100626 case kTfLiteBuiltinDepthToSpace:
627 return VisitDepthToSpaceOperator(delegateData,
628 tfLiteContext,
629 tfLiteNode,
630 nodeIndex,
631 kTfLiteBuiltinDepthToSpace);
632 case kTfLiteBuiltinDepthwiseConv2d:
633 return VisitConvolutionOperator(delegateData,
634 tfLiteContext,
635 tfLiteNode,
636 nodeIndex,
637 kTfLiteBuiltinDepthwiseConv2d);
638 case kTfLiteBuiltinDequantize:
639 return VisitDequantizeOperator(delegateData,
640 tfLiteContext,
641 tfLiteNode,
642 nodeIndex,
643 kTfLiteBuiltinDequantize);
644 case kTfLiteBuiltinDiv:
645 return VisitElementwiseBinaryOperator(delegateData,
646 tfLiteContext,
647 tfLiteNode,
648 nodeIndex,
649 kTfLiteBuiltinDiv);
650 case kTfLiteBuiltinElu:
651 return VisitActivationOperator(delegateData,
652 tfLiteContext,
653 tfLiteNode,
654 nodeIndex,
655 kTfLiteBuiltinElu);
656 case kTfLiteBuiltinEqual:
657 return VisitComparisonOperator(delegateData,
658 tfLiteContext,
659 tfLiteNode,
660 nodeIndex,
661 kTfLiteBuiltinEqual);
662 case kTfLiteBuiltinExp:
663 return VisitElementwiseUnaryOperator(delegateData,
664 tfLiteContext,
665 tfLiteNode,
666 nodeIndex,
667 armnn::UnaryOperation::Exp);
668 case kTfLiteBuiltinExpandDims:
669 return VisitExpandDimsOperator(delegateData,
670 tfLiteContext,
671 tfLiteNode,
672 nodeIndex,
673 kTfLiteBuiltinExpandDims);
674 case kTfLiteBuiltinFill:
675 return VisitFillOperator(delegateData,
676 tfLiteContext,
677 tfLiteNode,
678 nodeIndex,
679 kTfLiteBuiltinFill);
680 case kTfLiteBuiltinFloor:
681 return VisitFloorOperator(delegateData,
682 tfLiteContext,
683 tfLiteNode,
684 nodeIndex,
685 kTfLiteBuiltinFloor);
Jim Flynn4b2f3472021-10-13 21:20:07 +0100686 case kTfLiteBuiltinFloorDiv:
687 return VisitElementwiseBinaryOperator(delegateData,
688 tfLiteContext,
689 tfLiteNode,
690 nodeIndex,
691 kTfLiteBuiltinFloorDiv);
Sadik Armagan62483be2020-10-23 17:14:43 +0100692 case kTfLiteBuiltinFullyConnected:
693 return VisitFullyConnectedOperator(delegateData,
694 tfLiteContext,
695 tfLiteNode,
696 nodeIndex,
697 kTfLiteBuiltinFullyConnected);
698 case kTfLiteBuiltinGather:
699 return VisitGatherOperator(delegateData,
700 tfLiteContext,
701 tfLiteNode,
702 nodeIndex,
703 kTfLiteBuiltinGather);
Teresa Charlind5c0ed22022-04-25 18:23:41 +0100704 case kTfLiteBuiltinGatherNd:
705 return VisitGatherNdOperator(delegateData,
706 tfLiteContext,
707 tfLiteNode,
708 nodeIndex,
709 kTfLiteBuiltinGatherNd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100710 case kTfLiteBuiltinGreater:
711 return VisitComparisonOperator(delegateData,
712 tfLiteContext,
713 tfLiteNode,
714 nodeIndex,
715 kTfLiteBuiltinGreater);
716 case kTfLiteBuiltinGreaterEqual:
717 return VisitComparisonOperator(delegateData,
718 tfLiteContext,
719 tfLiteNode,
720 nodeIndex,
721 kTfLiteBuiltinGreaterEqual);
722 case kTfLiteBuiltinHardSwish:
723 return VisitActivationOperator(delegateData,
724 tfLiteContext,
725 tfLiteNode,
726 nodeIndex,
727 kTfLiteBuiltinHardSwish);
728 case kTfLiteBuiltinL2Normalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000729 return VisitL2NormalizationOperator(delegateData,
730 tfLiteContext,
731 tfLiteNode,
732 nodeIndex,
733 kTfLiteBuiltinL2Normalization);
Sadik Armagan62483be2020-10-23 17:14:43 +0100734 case kTfLiteBuiltinL2Pool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100735 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100736 tfLiteContext,
737 tfLiteNode,
738 nodeIndex,
739 kTfLiteBuiltinL2Pool2d);
740 case kTfLiteBuiltinLess:
741 return VisitComparisonOperator(delegateData,
742 tfLiteContext,
743 tfLiteNode,
744 nodeIndex,
745 kTfLiteBuiltinLess);
746 case kTfLiteBuiltinLessEqual:
747 return VisitComparisonOperator(delegateData,
748 tfLiteContext,
749 tfLiteNode,
750 nodeIndex,
751 kTfLiteBuiltinLessEqual);
752 case kTfLiteBuiltinLocalResponseNormalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000753 return VisitLocalResponseNormalizationOperator(delegateData,
754 tfLiteContext,
755 tfLiteNode,
756 nodeIndex,
757 kTfLiteBuiltinLocalResponseNormalization);
Teresa Charlinb1f5f702022-07-12 14:16:24 +0100758 case kTfLiteBuiltinLog:
759 return VisitElementwiseUnaryOperator(delegateData,
760 tfLiteContext,
761 tfLiteNode,
762 nodeIndex,
763 armnn::UnaryOperation::Log);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000764 case kTfLiteBuiltinLogicalAnd:
765 return VisitLogicalBinaryOperator(delegateData,
766 tfLiteContext,
767 tfLiteNode,
768 nodeIndex,
769 kTfLiteBuiltinLogicalAnd,
770 armnn::LogicalBinaryOperation::LogicalAnd);
771 case kTfLiteBuiltinLogicalNot:
772 return VisitElementwiseUnaryOperator(delegateData,
773 tfLiteContext,
774 tfLiteNode,
775 nodeIndex,
776 armnn::UnaryOperation::LogicalNot);
777 case kTfLiteBuiltinLogicalOr:
778 return VisitLogicalBinaryOperator(delegateData,
779 tfLiteContext,
780 tfLiteNode,
781 nodeIndex,
782 kTfLiteBuiltinLogicalOr,
783 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100784 case kTfLiteBuiltinLogistic:
785 return VisitActivationOperator(delegateData,
786 tfLiteContext,
787 tfLiteNode,
788 nodeIndex,
789 kTfLiteBuiltinLogistic);
790 case kTfLiteBuiltinLogSoftmax:
791 return VisitSoftmaxOperator(delegateData,
792 tfLiteContext,
793 tfLiteNode,
794 nodeIndex,
795 kTfLiteBuiltinLogSoftmax);
796 case kTfLiteBuiltinLstm:
797 return VisitLstmOperator(delegateData,
798 tfLiteContext,
799 tfLiteNode,
800 nodeIndex,
801 kTfLiteBuiltinLstm);
802 case kTfLiteBuiltinMaxPool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100803 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100804 tfLiteContext,
805 tfLiteNode,
806 nodeIndex,
807 kTfLiteBuiltinMaxPool2d);
808 case kTfLiteBuiltinMaximum:
809 return VisitElementwiseBinaryOperator(delegateData,
810 tfLiteContext,
811 tfLiteNode,
812 nodeIndex,
813 kTfLiteBuiltinMaximum);
814 case kTfLiteBuiltinMean:
815 return VisitControlOperator(delegateData,
816 tfLiteContext,
817 tfLiteNode,
818 nodeIndex,
819 kTfLiteBuiltinMean);
820 case kTfLiteBuiltinMinimum:
821 return VisitElementwiseBinaryOperator(delegateData,
822 tfLiteContext,
823 tfLiteNode,
824 nodeIndex,
825 kTfLiteBuiltinMinimum);
Matthew Sloyanaf3a4ef2021-10-22 15:48:12 +0100826 case kTfLiteBuiltinMirrorPad:
827 return VisitPadOperator(delegateData,
828 tfLiteContext,
829 tfLiteNode,
830 nodeIndex,
831 kTfLiteBuiltinMirrorPad);
Sadik Armagan62483be2020-10-23 17:14:43 +0100832 case kTfLiteBuiltinMul:
833 return VisitElementwiseBinaryOperator(delegateData,
834 tfLiteContext,
835 tfLiteNode,
836 nodeIndex,
837 kTfLiteBuiltinMul);
838 case kTfLiteBuiltinNeg:
839 return VisitElementwiseUnaryOperator(delegateData,
840 tfLiteContext,
841 tfLiteNode,
842 nodeIndex,
843 armnn::UnaryOperation::Neg);
844 case kTfLiteBuiltinNotEqual:
845 return VisitComparisonOperator(delegateData,
846 tfLiteContext,
847 tfLiteNode,
848 nodeIndex,
849 kTfLiteBuiltinNotEqual);
Matthew Sloyana7a12f52021-05-06 10:05:28 +0100850 case kTfLiteBuiltinPack:
851 return VisitPackOperator(delegateData,
852 tfLiteContext,
853 tfLiteNode,
854 nodeIndex,
855 kTfLiteBuiltinPack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100856 case kTfLiteBuiltinPad:
857 return VisitPadOperator(delegateData,
858 tfLiteContext,
859 tfLiteNode,
860 nodeIndex,
861 kTfLiteBuiltinPad);
862 case kTfLiteBuiltinPadv2:
863 return VisitPadOperator(delegateData,
864 tfLiteContext,
865 tfLiteNode,
866 nodeIndex,
867 kTfLiteBuiltinPadv2);
868 case kTfLiteBuiltinPrelu:
James Conroy39825482021-05-27 17:44:50 +0100869 return VisitPreluOperator(delegateData,
870 tfLiteContext,
871 tfLiteNode,
872 nodeIndex,
873 kTfLiteBuiltinPrelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100874 case kTfLiteBuiltinQuantize:
875 return VisitQuantizeOperator(delegateData,
876 tfLiteContext,
877 tfLiteNode,
878 nodeIndex,
879 kTfLiteBuiltinQuantize);
880 case kTfLiteBuiltinRank:
881 return VisitControlOperator(delegateData,
882 tfLiteContext,
883 tfLiteNode,
884 nodeIndex,
885 kTfLiteBuiltinRank);
Sadik Armagana2747482021-02-09 10:28:54 +0000886 case kTfLiteBuiltinReduceMax:
887 return VisitReduceOperator(delegateData,
888 tfLiteContext,
889 tfLiteNode,
890 nodeIndex,
891 kTfLiteBuiltinReduceMax);
892 case kTfLiteBuiltinReduceMin:
893 return VisitReduceOperator(delegateData,
894 tfLiteContext,
895 tfLiteNode,
896 nodeIndex,
897 kTfLiteBuiltinReduceMin);
Teresa Charlin4e3e8312021-08-05 12:34:37 +0100898 case kTfLiteBuiltinReduceProd:
899 return VisitReduceOperator(delegateData,
900 tfLiteContext,
901 tfLiteNode,
902 nodeIndex,
903 kTfLiteBuiltinReduceProd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100904 case kTfLiteBuiltinRelu:
905 return VisitActivationOperator(delegateData,
906 tfLiteContext,
907 tfLiteNode,
908 nodeIndex,
909 kTfLiteBuiltinRelu);
910 case kTfLiteBuiltinReluN1To1:
911 return VisitActivationOperator(delegateData,
912 tfLiteContext,
913 tfLiteNode,
914 nodeIndex,
915 kTfLiteBuiltinReluN1To1);
916 case kTfLiteBuiltinRelu6:
917 return VisitActivationOperator(delegateData,
918 tfLiteContext,
919 tfLiteNode,
920 nodeIndex,
921 kTfLiteBuiltinRelu6);
922 case kTfLiteBuiltinReshape:
923 return VisitReshapeOperator(delegateData,
924 tfLiteContext,
925 tfLiteNode,
926 nodeIndex,
927 kTfLiteBuiltinReshape);
928 case kTfLiteBuiltinResizeBilinear:
929 return VisitResizeOperator(delegateData,
930 tfLiteContext,
931 tfLiteNode,
932 nodeIndex,
933 kTfLiteBuiltinResizeBilinear);
934 case kTfLiteBuiltinResizeNearestNeighbor:
935 return VisitResizeOperator(delegateData,
936 tfLiteContext,
937 tfLiteNode,
938 nodeIndex,
939 kTfLiteBuiltinResizeNearestNeighbor);
940 case kTfLiteBuiltinRsqrt:
941 return VisitElementwiseUnaryOperator(delegateData,
942 tfLiteContext,
943 tfLiteNode,
944 nodeIndex,
945 armnn::UnaryOperation::Rsqrt);
Keith Davis0176fd82021-06-01 17:36:32 +0100946 case kTfLiteBuiltinShape:
947 return VisitShapeOperator(delegateData,
948 tfLiteContext,
949 tfLiteNode,
950 nodeIndex,
951 kTfLiteBuiltinShape);
Teresa Charlinb1f5f702022-07-12 14:16:24 +0100952 case kTfLiteBuiltinSin:
953 return VisitElementwiseUnaryOperator(delegateData,
954 tfLiteContext,
955 tfLiteNode,
956 nodeIndex,
957 armnn::UnaryOperation::Sin);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +0000958 case kTfLiteBuiltinSplit:
959 return VisitSplitOperator(delegateData,
960 tfLiteContext,
961 tfLiteNode,
962 nodeIndex,
963 kTfLiteBuiltinSplit);
964 case kTfLiteBuiltinSplitV:
965 return VisitSplitVOperator(delegateData,
966 tfLiteContext,
967 tfLiteNode,
968 nodeIndex,
969 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +0100970 case kTfLiteBuiltinSqrt:
971 return VisitElementwiseUnaryOperator(delegateData,
972 tfLiteContext,
973 tfLiteNode,
974 nodeIndex,
975 armnn::UnaryOperation::Sqrt);
976 case kTfLiteBuiltinSqueeze:
977 return VisitSqueezeOperator(delegateData,
978 tfLiteContext,
979 tfLiteNode,
980 nodeIndex,
981 kTfLiteBuiltinSqueeze);
Cathal Corbett839b9322022-11-18 08:52:18 +0000982 case kTfLiteBuiltinSlice:
Sadik Armagan62483be2020-10-23 17:14:43 +0100983 return VisitSliceOperator(delegateData,
984 tfLiteContext,
985 tfLiteNode,
986 nodeIndex,
Cathal Corbett839b9322022-11-18 08:52:18 +0000987 kTfLiteBuiltinSlice);
988 case kTfLiteBuiltinStridedSlice:
989 return VisitStridedSliceOperator(delegateData,
990 tfLiteContext,
991 tfLiteNode,
992 nodeIndex,
993 kTfLiteBuiltinStridedSlice);
Sadik Armagana2747482021-02-09 10:28:54 +0000994 case kTfLiteBuiltinSum:
995 return VisitReduceOperator(delegateData,
996 tfLiteContext,
997 tfLiteNode,
998 nodeIndex,
999 kTfLiteBuiltinSum);
Sadik Armagan62483be2020-10-23 17:14:43 +01001000 case kTfLiteBuiltinTranspose:
1001 return VisitTransposeOperator(delegateData,
1002 tfLiteContext,
1003 tfLiteNode,
1004 nodeIndex,
1005 kTfLiteBuiltinTranspose);
1006 case kTfLiteBuiltinTransposeConv:
1007 return VisitConvolutionOperator(delegateData,
1008 tfLiteContext,
1009 tfLiteNode,
1010 nodeIndex,
1011 kTfLiteBuiltinTransposeConv);
1012 case kTfLiteBuiltinSoftmax:
1013 return VisitSoftmaxOperator(delegateData,
1014 tfLiteContext,
1015 tfLiteNode,
1016 nodeIndex,
1017 kTfLiteBuiltinSoftmax);
1018 case kTfLiteBuiltinSpaceToBatchNd:
1019 return VisitSpaceToBatchNdOperator(delegateData,
1020 tfLiteContext,
1021 tfLiteNode,
1022 nodeIndex,
1023 kTfLiteBuiltinSpaceToBatchNd);
1024 case kTfLiteBuiltinSpaceToDepth:
1025 return VisitSpaceToDepthOperator(delegateData,
1026 tfLiteContext,
1027 tfLiteNode,
1028 nodeIndex,
1029 kTfLiteBuiltinSpaceToDepth);
1030 case kTfLiteBuiltinSub:
1031 return VisitElementwiseBinaryOperator(delegateData,
1032 tfLiteContext,
1033 tfLiteNode,
1034 nodeIndex,
1035 kTfLiteBuiltinSub);
1036 case kTfLiteBuiltinTanh:
1037 return VisitActivationOperator(delegateData,
1038 tfLiteContext,
1039 tfLiteNode,
1040 nodeIndex,
1041 kTfLiteBuiltinTanh);
Narumol Prangnawarat7684b182021-08-12 14:48:15 +01001042 case kTfLiteBuiltinUnidirectionalSequenceLstm:
1043 return VisitUnidirectionalSequenceLstmOperator(delegateData,
1044 tfLiteContext,
1045 tfLiteNode,
1046 nodeIndex,
1047 kTfLiteBuiltinUnidirectionalSequenceLstm);
Kevin May8ab2d7a2021-05-07 09:32:51 +01001048 case kTfLiteBuiltinUnpack:
1049 return VisitUnpackOperator(delegateData,
1050 tfLiteContext,
1051 tfLiteNode,
1052 nodeIndex,
1053 kTfLiteBuiltinUnpack);
Sadik Armagan62483be2020-10-23 17:14:43 +01001054 default:
1055 return kTfLiteError;
1056 }
Sadik Armagan3c24f432020-10-19 17:35:30 +01001057}
1058
1059} // armnnDelegate namespace