blob: 21c66fe706b0e2bbd134388c1ef1e77781f0595e [file] [log] [blame]
Sadik Armagan3c24f432020-10-19 17:35:30 +01001//
Ryan OShead21abaf2022-06-10 14:49:11 +01002// Copyright © 2022 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"
37#include "Softmax.hpp"
38#include "SpaceDepth.hpp"
Sadik Armagan34fa1bd2020-11-27 12:40:52 +000039#include "Split.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010040#include "Transpose.hpp"
Narumol Prangnawarat7684b182021-08-12 14:48:15 +010041#include "UnidirectionalSequenceLstm.hpp"
Kevin May8ab2d7a2021-05-07 09:32:51 +010042#include "Unpack.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010043
Colm Donelan3e32a872021-10-04 22:55:37 +010044#include <armnnUtils/Filesystem.hpp>
Jan Eilers17d34da2021-12-08 16:15:12 +000045#include <armnn/utility/Timer.hpp>
Sadik Armagan62483be2020-10-23 17:14:43 +010046#include <flatbuffers/flatbuffers.h>
47#include <tensorflow/lite/context_util.h>
Jim Flynn4b2f3472021-10-13 21:20:07 +010048#include <tensorflow/lite/schema/schema_generated.h>
Sadik Armagan62483be2020-10-23 17:14:43 +010049
Sadik Armagan3c24f432020-10-19 17:35:30 +010050#include <algorithm>
Matthew Sloyanac001ee2021-02-03 10:43:04 +000051#include <iostream>
Sadik Armagan62483be2020-10-23 17:14:43 +010052#include <sstream>
Sadik Armagan3c24f432020-10-19 17:35:30 +010053
54namespace armnnDelegate
55{
56
Sadik Armagan62483be2020-10-23 17:14:43 +010057DelegateOptions TfLiteArmnnDelegateOptionsDefault()
58{
59 DelegateOptions options(armnn::Compute::CpuRef);
60 return options;
61}
62
63TfLiteDelegate* TfLiteArmnnDelegateCreate(armnnDelegate::DelegateOptions options)
64{
65 auto* armnnDelegate = new ::armnnDelegate::Delegate(options);
66 return armnnDelegate->GetDelegate();
67}
68
69void TfLiteArmnnDelegateDelete(TfLiteDelegate* tfLiteDelegate)
70{
71 if (tfLiteDelegate != nullptr)
72 {
73 delete static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_);
74 }
75}
76
77TfLiteStatus DoPrepare(TfLiteContext* tfLiteContext, TfLiteDelegate* tfLiteDelegate)
78{
79 TfLiteIntArray* supportedOperators =
80 static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_)->IdentifyOperatorsToDelegate(tfLiteContext);
81
82 // ArmNN Delegate Registration
83 static const TfLiteRegistration kArmnnSubgraphRegistration = {
84 // ArmnnSubgraph Init
85 .init = [](TfLiteContext* tfLiteContext, const char* buffer, size_t length) -> void* {
Finn Williams6f9f9902020-11-13 13:23:15 +000086 armnn::IgnoreUnused(length);
Sadik Armagan62483be2020-10-23 17:14:43 +010087 const TfLiteDelegateParams* parameters = reinterpret_cast<const TfLiteDelegateParams*>(buffer);
88
89 return static_cast<void*>(ArmnnSubgraph::Create(
90 tfLiteContext, parameters, static_cast<::armnnDelegate::Delegate*>(parameters->delegate->data_)));
91 },
92 // ArmnnSubgraph Free
93 .free = [](TfLiteContext* tfLiteContext, void* buffer) -> void {
Finn Williams6f9f9902020-11-13 13:23:15 +000094 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan62483be2020-10-23 17:14:43 +010095 if (buffer != nullptr)
96 {
97 delete static_cast<ArmnnSubgraph*>(buffer);
98 }
99 },
100 // ArmnnSubgraph Prepare
101 .prepare = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
102 if (tfLiteNode->user_data == nullptr)
103 {
104 return kTfLiteError;
105 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100106 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Prepare(tfLiteContext);
107 },
108 // ArmnnSubgraph Invoke
109 .invoke = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
110 if (tfLiteNode->user_data == nullptr)
111 {
112 return kTfLiteError;
113 }
114
115 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Invoke(tfLiteContext, tfLiteNode);
116 },
117
118 .profiling_string = nullptr,
119 .builtin_code = kTfLiteBuiltinDelegate,
120 .custom_name = "TfLiteArmNnDelegate",
121 .version = 1,
122 };
123
124 const TfLiteStatus status =
125 tfLiteContext->ReplaceNodeSubsetsWithDelegateKernels(
126 tfLiteContext, kArmnnSubgraphRegistration, supportedOperators, tfLiteDelegate);
127
128 TfLiteIntArrayFree(supportedOperators);
129 return status;
130
131}
132
Sadik Armagan3c24f432020-10-19 17:35:30 +0100133Delegate::Delegate(armnnDelegate::DelegateOptions options)
134 : m_Runtime(nullptr, nullptr),
135 m_Options(std::move(options))
136{
Jan Eilers2cd18472020-12-15 10:42:38 +0000137 // Configures logging for ARMNN
138 if (options.IsLoggingEnabled())
139 {
140 armnn::ConfigureLogging(true, true, options.GetLoggingSeverity());
141 }
142
Sadik Armagan3c24f432020-10-19 17:35:30 +0100143 // Create ArmNN Runtime
Jan Eilersb1c62f12021-10-26 14:56:47 +0100144 m_Runtime = armnn::IRuntime::Create(options.GetRuntimeOptions());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100145
146 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
207 if (ArmnnSubgraph::VisitNode(
Sadik Armagan62483be2020-10-23 17:14:43 +0100208 delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100209 {
210 // node is not supported by ArmNN
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000211 unsupportedOperators.insert(tfLiteRegistration->builtin_code);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100212 continue;
213 }
214
215 nodesToDelegate->data[nodesToDelegate->size++] = nodeIndex;
216 }
217
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000218 for (std::set<int32_t>::iterator it=unsupportedOperators.begin(); it!=unsupportedOperators.end(); ++it)
219 {
220 TF_LITE_KERNEL_LOG(tfLiteContext,
221 "Operator %s [%d] is not supported by armnn_delegate.",
222 tflite::EnumNameBuiltinOperator(tflite::BuiltinOperator(*it)),
223 *it);
224 }
225
Sadik Armaganca565c12022-08-16 12:17:24 +0100226 if (!unsupportedOperators.empty() && m_Options.TfLiteRuntimeFallbackDisabled())
227 {
228 std::stringstream exMessage;
229 exMessage << "TfLiteArmnnDelegate: There are unsupported operators in the model. ";
230 exMessage << "Not falling back to TfLite Runtime as fallback is disabled. ";
231 exMessage << "This should only be disabled under test conditions.";
232 throw armnn::Exception(exMessage.str());
233 }
234
Sadik Armagan62483be2020-10-23 17:14:43 +0100235 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100236 return nodesToDelegate;
237}
238
239TfLiteDelegate* Delegate::GetDelegate()
240{
241 return &m_Delegate;
242}
243
Matthew Sloyanac001ee2021-02-03 10:43:04 +0000244const std::string Delegate::GetVersion()
245{
246 return DELEGATE_VERSION;
247}
248
Sadik Armagan62483be2020-10-23 17:14:43 +0100249TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
250 TfLiteContext* tfLiteContext,
251 const TfLiteIntArray* inputs,
252 std::vector<armnn::BindingPointInfo>& inputBindings)
253{
Finn Williams6f9f9902020-11-13 13:23:15 +0000254 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100255 for (unsigned int i = 0; i < numInputs; ++i)
256 {
257 const int32_t tensorId = inputs->data[i];
258 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000259 // Do not create bindings for constant inputs
260 if (tensor.allocation_type == kTfLiteMmapRo)
261 {
262 continue;
263 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100264
265 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
266 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
267
268 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
269 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
270 outputSlot.SetTensorInfo(tensorInfo);
271
272 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000273 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100274
Sadik Armagan6e36a642020-11-10 21:18:41 +0000275 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100276 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000277
Sadik Armagan62483be2020-10-23 17:14:43 +0100278 return kTfLiteOk;
279}
280
281TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
282 TfLiteContext* tfLiteContext,
283 const TfLiteIntArray* outputs,
284 std::vector<armnn::BindingPointInfo>& outputBindings)
285{
Finn Williams6f9f9902020-11-13 13:23:15 +0000286 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100287 for (unsigned int i = 0; i < numOutputs; ++i)
288 {
289 const int32_t tensorId = outputs->data[i];
290 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
291
292 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
293 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
294
295 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Finn Williams6f9f9902020-11-13 13:23:15 +0000296 ARMNN_ASSERT(delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] != nullptr);
297 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100298 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
299 }
300
301 return kTfLiteOk;
302}
303
Sadik Armagan3c24f432020-10-19 17:35:30 +0100304ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
305 const TfLiteDelegateParams* parameters,
306 const Delegate* delegate)
307{
Jan Eilers17d34da2021-12-08 16:15:12 +0000308 const auto startTime = armnn::GetTimeNow();
309 ARMNN_LOG(info) << "ArmnnSubgraph creation";
310
Sadik Armagan3c24f432020-10-19 17:35:30 +0100311 TfLiteIntArray* executionPlan;
312 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
313 {
314 return nullptr;
315 }
316
Sadik Armagan62483be2020-10-23 17:14:43 +0100317 // Initialize DelegateData holds network and output slots information
318 DelegateData delegateData(delegate->m_Options.GetBackends());
319
320 // Build ArmNN Network
Mike Kelly80512b02022-05-16 23:10:42 +0100321 armnn::NetworkOptions networkOptions = delegate->m_Options.GetOptimizerOptions().m_ModelOptions;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100322 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100323 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100324
Sadik Armagan6e36a642020-11-10 21:18:41 +0000325 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
326
Sadik Armagan62483be2020-10-23 17:14:43 +0100327 std::vector<armnn::BindingPointInfo> inputBindings;
328 std::vector<armnn::BindingPointInfo> outputBindings;
329
330 // Add input layer
331 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
332 if (status != kTfLiteOk)
333 {
334 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
335 }
336
337 // Parse TfLite delegate nodes to ArmNN
Jan Eilers17d34da2021-12-08 16:15:12 +0000338 const auto parseStartTime = armnn::GetTimeNow();
Sadik Armagan3c24f432020-10-19 17:35:30 +0100339 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
340 {
341 const int nodeIndex = parameters->nodes_to_replace->data[i];
342
343 TfLiteNode* tfLiteNode = nullptr;
344 TfLiteRegistration* tfLiteRegistration = nullptr;
345 if (tfLiteContext->GetNodeAndRegistration(
346 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
347 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000348 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100349 }
350
Sadik Armagan62483be2020-10-23 17:14:43 +0100351 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100352 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000353 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100354 }
355 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000356 ARMNN_LOG(info) << "Parse nodes to ArmNN time: " << std::setprecision(2)
357 << std::fixed << armnn::GetTimeDuration(parseStartTime).count() << " ms";
Sadik Armagan3c24f432020-10-19 17:35:30 +0100358
Sadik Armagan62483be2020-10-23 17:14:43 +0100359 // Add Output layer
360 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
361 if (status != kTfLiteOk)
362 {
363 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
364 }
365
366 // Optimize ArmNN network
367 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
368 try
369 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000370 const auto optimizeStartTime = armnn::GetTimeNow();
Sadik Armagan6e36a642020-11-10 21:18:41 +0000371 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100372 delegate->m_Options.GetBackends(),
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000373 delegate->m_Runtime->GetDeviceSpec(),
374 delegate->m_Options.GetOptimizerOptions());
Jan Eilers17d34da2021-12-08 16:15:12 +0000375 ARMNN_LOG(info) << "Optimize ArmnnSubgraph time: " << std::setprecision(2)
376 << std::fixed << armnn::GetTimeDuration(optimizeStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100377 }
378 catch (std::exception &ex)
379 {
380 std::stringstream exMessage;
381 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
382 throw armnn::Exception(exMessage.str());
383 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100384 if (!optNet)
385 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100386 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100387 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
388 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100389
Colm Donelan3e32a872021-10-04 22:55:37 +0100390 // If set, we will serialize the optimized model into a dot file.
391 const std::string serializeToDotFile = delegate->m_Options.GetSerializeToDot();
392 if (!serializeToDotFile.empty())
393 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000394 ARMNN_LOG(info) << "Writing graph to dot file: " << serializeToDotFile;
Colm Donelan3e32a872021-10-04 22:55:37 +0100395 fs::path filename = serializeToDotFile;
396 std::fstream file(filename.c_str(), std::ios_base::out);
397 optNet->SerializeToDot(file);
398 }
399
Sadik Armagan62483be2020-10-23 17:14:43 +0100400 try
401 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000402 const auto loadStartTime = armnn::GetTimeNow();
403
Sadik Armagan62483be2020-10-23 17:14:43 +0100404 // Load graph into runtime
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000405 std::string errorMessage;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000406 armnn::Status loadingStatus;
Francis Murtagh626bd902022-06-21 13:16:23 +0000407 armnn::MemorySource inputSource = armnn::MemorySource::Undefined;
408 armnn::MemorySource outputSource = armnn::MemorySource::Undefined;
409 // There's a bit of an assumption here that the delegate will only support Malloc memory source.
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000410 if (delegate->m_Options.GetOptimizerOptions().m_ImportEnabled)
411 {
Francis Murtagh626bd902022-06-21 13:16:23 +0000412 inputSource = armnn::MemorySource::Malloc;
413 }
414 if (delegate->m_Options.GetOptimizerOptions().m_ExportEnabled)
415 {
416 outputSource = armnn::MemorySource::Malloc;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000417 }
Colm Donelan3e32a872021-10-04 22:55:37 +0100418 armnn::INetworkProperties networkProperties(false,
Francis Murtagh626bd902022-06-21 13:16:23 +0000419 inputSource,
420 outputSource,
Colm Donelan3e32a872021-10-04 22:55:37 +0100421 delegate->m_Options.GetInternalProfilingState(),
422 delegate->m_Options.GetInternalProfilingDetail());
423 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
424 std::move(optNet),
425 errorMessage,
426 networkProperties);
Sadik Armagan62483be2020-10-23 17:14:43 +0100427 if (loadingStatus != armnn::Status::Success)
428 {
Colm Donelan45142282021-10-21 23:39:52 +0100429 // Network load failed.
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000430 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded:" + errorMessage);
Sadik Armagan62483be2020-10-23 17:14:43 +0100431 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000432
433 ARMNN_LOG(info) << "Load ArmnnSubgraph time: " << std::setprecision(2)
434 << std::fixed << armnn::GetTimeDuration(loadStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100435 }
436 catch (std::exception& ex)
437 {
438 std::stringstream exMessage;
439 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
440 throw armnn::Exception(exMessage.str());
441 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100442
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000443 // Register debug callback function
444 if (delegate->m_Options.GetDebugCallbackFunction().has_value())
445 {
446 delegate->m_Runtime->RegisterDebugCallback(networkId, delegate->m_Options.GetDebugCallbackFunction().value());
447 }
448
Jan Eilers17d34da2021-12-08 16:15:12 +0000449 ARMNN_LOG(info) << "Overall ArmnnSubgraph creation time: " << std::setprecision(2)
450 << std::fixed << armnn::GetTimeDuration(startTime).count() << " ms\n";
451
Sadik Armagan3c24f432020-10-19 17:35:30 +0100452 // Create a new SubGraph with networkId and runtime
Sadik Armagan62483be2020-10-23 17:14:43 +0100453 return new ArmnnSubgraph(networkId, delegate->m_Runtime.get(), inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100454}
455
456TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
457{
Finn Williams6f9f9902020-11-13 13:23:15 +0000458 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100459 return kTfLiteOk;
460}
461
Sadik Armagan62483be2020-10-23 17:14:43 +0100462TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100463{
Sadik Armagan62483be2020-10-23 17:14:43 +0100464 // Prepare inputs
465 armnn::InputTensors inputTensors;
466 size_t inputIndex = 0;
467 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
468 {
469 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
470 if (tensor->allocation_type != kTfLiteMmapRo)
471 {
472 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100473 armnn::TensorInfo inputTensorInfo = inputBinding.second;
474 inputTensorInfo.SetConstant(true);
475 const armnn::ConstTensor inputTensor(inputTensorInfo, tensor->data.data);
Sadik Armagan62483be2020-10-23 17:14:43 +0100476 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100477
Sadik Armagan62483be2020-10-23 17:14:43 +0100478 ++inputIndex;
479 }
480 }
481
482 // Prepare outputs
483 armnn::OutputTensors outputTensors;
484 size_t outputIndex = 0;
485 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
486 {
487 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
488 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
489 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
490 outputTensors.emplace_back(outputIdx, outputTensor);
491
492 ++outputIndex;
493 }
494
495 // Run graph
496 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
Colm Donelan45142282021-10-21 23:39:52 +0100497 // The delegate holds its own Arm NN runtime so this is our last chance to print internal profiling data.
498 std::shared_ptr<armnn::IProfiler> profiler = m_Runtime->GetProfiler(m_NetworkId);
499 if (profiler && profiler->IsProfilingEnabled())
500 {
501 profiler->Print(std::cout);
502 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100503 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100504}
505
Sadik Armagan62483be2020-10-23 17:14:43 +0100506TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100507 TfLiteContext* tfLiteContext,
508 TfLiteRegistration* tfLiteRegistration,
509 TfLiteNode* tfLiteNode,
510 int nodeIndex)
511{
Sadik Armagan62483be2020-10-23 17:14:43 +0100512 switch (tfLiteRegistration->builtin_code)
513 {
Ryan OShead21abaf2022-06-10 14:49:11 +0100514 case kTfLiteBuiltinCustom:
515 {
516#if defined(ARMNN_POST_TFLITE_2_5)
517 // Custom operators are defined by the name rather than the builtin code.
518 // Parse the custom_name param in the registration to point to the correct visitor function.
519 std::string customOperatorName = tfLiteRegistration->custom_name;
520 if ( customOperatorName == "AveragePool3D" )
521 {
522 return VisitPooling3dOperator(delegateData,
523 tfLiteContext,
524 tfLiteNode,
525 nodeIndex,
526 customOperatorName);
527 }
528 else if (customOperatorName == "MaxPool3D")
529 {
530 return VisitPooling3dOperator(delegateData,
531 tfLiteContext,
532 tfLiteNode,
533 nodeIndex,
534 customOperatorName);
535 }
536#endif
537 // Invalid or unsupported custom operator
538 return kTfLiteError;
539 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100540 case kTfLiteBuiltinAbs:
541 return VisitElementwiseUnaryOperator(delegateData,
542 tfLiteContext,
543 tfLiteNode,
544 nodeIndex,
545 armnn::UnaryOperation::Abs);
546 case kTfLiteBuiltinAdd:
547 return VisitElementwiseBinaryOperator(delegateData,
548 tfLiteContext,
549 tfLiteNode,
550 nodeIndex,
551 kTfLiteBuiltinAdd);
552 case kTfLiteBuiltinArgMax:
553 return VisitArgMinMaxOperator(delegateData,
554 tfLiteContext,
555 tfLiteNode,
556 nodeIndex,
557 kTfLiteBuiltinArgMax);
558 case kTfLiteBuiltinArgMin:
559 return VisitArgMinMaxOperator(delegateData,
560 tfLiteContext,
561 tfLiteNode,
562 nodeIndex,
563 kTfLiteBuiltinArgMin);
564 case kTfLiteBuiltinAveragePool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100565 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100566 tfLiteContext,
567 tfLiteNode,
568 nodeIndex,
569 kTfLiteBuiltinAveragePool2d);
Ryan OShea49ed0df2022-09-21 16:09:41 +0100570 case kTfLiteBuiltinBatchMatmul:
571 return VisitBatchMatMulOperator(delegateData,
572 tfLiteContext,
573 tfLiteNode,
574 nodeIndex,
575 kTfLiteBuiltinBatchMatmul);
Sadik Armagan62483be2020-10-23 17:14:43 +0100576 case kTfLiteBuiltinBatchToSpaceNd:
577 return VisitBatchToSpaceNdOperator(delegateData,
578 tfLiteContext,
579 tfLiteNode,
580 nodeIndex,
581 kTfLiteBuiltinBatchToSpaceNd);
Sadik Armagan937565b2021-04-21 14:03:28 +0100582 case kTfLiteBuiltinCast:
583 return VisitCastOperator(delegateData,
584 tfLiteContext,
585 tfLiteNode,
586 nodeIndex,
587 kTfLiteBuiltinCast);
Sadik Armagan62483be2020-10-23 17:14:43 +0100588 case kTfLiteBuiltinConcatenation:
589 return VisitControlOperator(delegateData,
590 tfLiteContext,
591 tfLiteNode,
592 nodeIndex,
593 kTfLiteBuiltinConcatenation);
594 case kTfLiteBuiltinConv2d:
595 return VisitConvolutionOperator(delegateData,
596 tfLiteContext,
597 tfLiteNode,
598 nodeIndex,
599 kTfLiteBuiltinConv2d);
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100600// Conv3d is only correctly supported for external delegates from TF Lite v2.6, as there was a breaking bug in v2.5.
601#if defined(ARMNN_POST_TFLITE_2_5)
602 case kTfLiteBuiltinConv3d:
603 return VisitConvolutionOperator(delegateData,
604 tfLiteContext,
605 tfLiteNode,
606 nodeIndex,
607 kTfLiteBuiltinConv3d);
608#endif
Sadik Armagan62483be2020-10-23 17:14:43 +0100609 case kTfLiteBuiltinDepthToSpace:
610 return VisitDepthToSpaceOperator(delegateData,
611 tfLiteContext,
612 tfLiteNode,
613 nodeIndex,
614 kTfLiteBuiltinDepthToSpace);
615 case kTfLiteBuiltinDepthwiseConv2d:
616 return VisitConvolutionOperator(delegateData,
617 tfLiteContext,
618 tfLiteNode,
619 nodeIndex,
620 kTfLiteBuiltinDepthwiseConv2d);
621 case kTfLiteBuiltinDequantize:
622 return VisitDequantizeOperator(delegateData,
623 tfLiteContext,
624 tfLiteNode,
625 nodeIndex,
626 kTfLiteBuiltinDequantize);
627 case kTfLiteBuiltinDiv:
628 return VisitElementwiseBinaryOperator(delegateData,
629 tfLiteContext,
630 tfLiteNode,
631 nodeIndex,
632 kTfLiteBuiltinDiv);
633 case kTfLiteBuiltinElu:
634 return VisitActivationOperator(delegateData,
635 tfLiteContext,
636 tfLiteNode,
637 nodeIndex,
638 kTfLiteBuiltinElu);
639 case kTfLiteBuiltinEqual:
640 return VisitComparisonOperator(delegateData,
641 tfLiteContext,
642 tfLiteNode,
643 nodeIndex,
644 kTfLiteBuiltinEqual);
645 case kTfLiteBuiltinExp:
646 return VisitElementwiseUnaryOperator(delegateData,
647 tfLiteContext,
648 tfLiteNode,
649 nodeIndex,
650 armnn::UnaryOperation::Exp);
651 case kTfLiteBuiltinExpandDims:
652 return VisitExpandDimsOperator(delegateData,
653 tfLiteContext,
654 tfLiteNode,
655 nodeIndex,
656 kTfLiteBuiltinExpandDims);
657 case kTfLiteBuiltinFill:
658 return VisitFillOperator(delegateData,
659 tfLiteContext,
660 tfLiteNode,
661 nodeIndex,
662 kTfLiteBuiltinFill);
663 case kTfLiteBuiltinFloor:
664 return VisitFloorOperator(delegateData,
665 tfLiteContext,
666 tfLiteNode,
667 nodeIndex,
668 kTfLiteBuiltinFloor);
Jim Flynn4b2f3472021-10-13 21:20:07 +0100669 case kTfLiteBuiltinFloorDiv:
670 return VisitElementwiseBinaryOperator(delegateData,
671 tfLiteContext,
672 tfLiteNode,
673 nodeIndex,
674 kTfLiteBuiltinFloorDiv);
Sadik Armagan62483be2020-10-23 17:14:43 +0100675 case kTfLiteBuiltinFullyConnected:
676 return VisitFullyConnectedOperator(delegateData,
677 tfLiteContext,
678 tfLiteNode,
679 nodeIndex,
680 kTfLiteBuiltinFullyConnected);
681 case kTfLiteBuiltinGather:
682 return VisitGatherOperator(delegateData,
683 tfLiteContext,
684 tfLiteNode,
685 nodeIndex,
686 kTfLiteBuiltinGather);
Teresa Charlind5c0ed22022-04-25 18:23:41 +0100687 case kTfLiteBuiltinGatherNd:
688 return VisitGatherNdOperator(delegateData,
689 tfLiteContext,
690 tfLiteNode,
691 nodeIndex,
692 kTfLiteBuiltinGatherNd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100693 case kTfLiteBuiltinGreater:
694 return VisitComparisonOperator(delegateData,
695 tfLiteContext,
696 tfLiteNode,
697 nodeIndex,
698 kTfLiteBuiltinGreater);
699 case kTfLiteBuiltinGreaterEqual:
700 return VisitComparisonOperator(delegateData,
701 tfLiteContext,
702 tfLiteNode,
703 nodeIndex,
704 kTfLiteBuiltinGreaterEqual);
705 case kTfLiteBuiltinHardSwish:
706 return VisitActivationOperator(delegateData,
707 tfLiteContext,
708 tfLiteNode,
709 nodeIndex,
710 kTfLiteBuiltinHardSwish);
711 case kTfLiteBuiltinL2Normalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000712 return VisitL2NormalizationOperator(delegateData,
713 tfLiteContext,
714 tfLiteNode,
715 nodeIndex,
716 kTfLiteBuiltinL2Normalization);
Sadik Armagan62483be2020-10-23 17:14:43 +0100717 case kTfLiteBuiltinL2Pool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100718 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100719 tfLiteContext,
720 tfLiteNode,
721 nodeIndex,
722 kTfLiteBuiltinL2Pool2d);
723 case kTfLiteBuiltinLess:
724 return VisitComparisonOperator(delegateData,
725 tfLiteContext,
726 tfLiteNode,
727 nodeIndex,
728 kTfLiteBuiltinLess);
729 case kTfLiteBuiltinLessEqual:
730 return VisitComparisonOperator(delegateData,
731 tfLiteContext,
732 tfLiteNode,
733 nodeIndex,
734 kTfLiteBuiltinLessEqual);
735 case kTfLiteBuiltinLocalResponseNormalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000736 return VisitLocalResponseNormalizationOperator(delegateData,
737 tfLiteContext,
738 tfLiteNode,
739 nodeIndex,
740 kTfLiteBuiltinLocalResponseNormalization);
Teresa Charlinb1f5f702022-07-12 14:16:24 +0100741 case kTfLiteBuiltinLog:
742 return VisitElementwiseUnaryOperator(delegateData,
743 tfLiteContext,
744 tfLiteNode,
745 nodeIndex,
746 armnn::UnaryOperation::Log);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000747 case kTfLiteBuiltinLogicalAnd:
748 return VisitLogicalBinaryOperator(delegateData,
749 tfLiteContext,
750 tfLiteNode,
751 nodeIndex,
752 kTfLiteBuiltinLogicalAnd,
753 armnn::LogicalBinaryOperation::LogicalAnd);
754 case kTfLiteBuiltinLogicalNot:
755 return VisitElementwiseUnaryOperator(delegateData,
756 tfLiteContext,
757 tfLiteNode,
758 nodeIndex,
759 armnn::UnaryOperation::LogicalNot);
760 case kTfLiteBuiltinLogicalOr:
761 return VisitLogicalBinaryOperator(delegateData,
762 tfLiteContext,
763 tfLiteNode,
764 nodeIndex,
765 kTfLiteBuiltinLogicalOr,
766 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100767 case kTfLiteBuiltinLogistic:
768 return VisitActivationOperator(delegateData,
769 tfLiteContext,
770 tfLiteNode,
771 nodeIndex,
772 kTfLiteBuiltinLogistic);
773 case kTfLiteBuiltinLogSoftmax:
774 return VisitSoftmaxOperator(delegateData,
775 tfLiteContext,
776 tfLiteNode,
777 nodeIndex,
778 kTfLiteBuiltinLogSoftmax);
779 case kTfLiteBuiltinLstm:
780 return VisitLstmOperator(delegateData,
781 tfLiteContext,
782 tfLiteNode,
783 nodeIndex,
784 kTfLiteBuiltinLstm);
785 case kTfLiteBuiltinMaxPool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100786 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100787 tfLiteContext,
788 tfLiteNode,
789 nodeIndex,
790 kTfLiteBuiltinMaxPool2d);
791 case kTfLiteBuiltinMaximum:
792 return VisitElementwiseBinaryOperator(delegateData,
793 tfLiteContext,
794 tfLiteNode,
795 nodeIndex,
796 kTfLiteBuiltinMaximum);
797 case kTfLiteBuiltinMean:
798 return VisitControlOperator(delegateData,
799 tfLiteContext,
800 tfLiteNode,
801 nodeIndex,
802 kTfLiteBuiltinMean);
803 case kTfLiteBuiltinMinimum:
804 return VisitElementwiseBinaryOperator(delegateData,
805 tfLiteContext,
806 tfLiteNode,
807 nodeIndex,
808 kTfLiteBuiltinMinimum);
Matthew Sloyanaf3a4ef2021-10-22 15:48:12 +0100809 case kTfLiteBuiltinMirrorPad:
810 return VisitPadOperator(delegateData,
811 tfLiteContext,
812 tfLiteNode,
813 nodeIndex,
814 kTfLiteBuiltinMirrorPad);
Sadik Armagan62483be2020-10-23 17:14:43 +0100815 case kTfLiteBuiltinMul:
816 return VisitElementwiseBinaryOperator(delegateData,
817 tfLiteContext,
818 tfLiteNode,
819 nodeIndex,
820 kTfLiteBuiltinMul);
821 case kTfLiteBuiltinNeg:
822 return VisitElementwiseUnaryOperator(delegateData,
823 tfLiteContext,
824 tfLiteNode,
825 nodeIndex,
826 armnn::UnaryOperation::Neg);
827 case kTfLiteBuiltinNotEqual:
828 return VisitComparisonOperator(delegateData,
829 tfLiteContext,
830 tfLiteNode,
831 nodeIndex,
832 kTfLiteBuiltinNotEqual);
Matthew Sloyana7a12f52021-05-06 10:05:28 +0100833 case kTfLiteBuiltinPack:
834 return VisitPackOperator(delegateData,
835 tfLiteContext,
836 tfLiteNode,
837 nodeIndex,
838 kTfLiteBuiltinPack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100839 case kTfLiteBuiltinPad:
840 return VisitPadOperator(delegateData,
841 tfLiteContext,
842 tfLiteNode,
843 nodeIndex,
844 kTfLiteBuiltinPad);
845 case kTfLiteBuiltinPadv2:
846 return VisitPadOperator(delegateData,
847 tfLiteContext,
848 tfLiteNode,
849 nodeIndex,
850 kTfLiteBuiltinPadv2);
851 case kTfLiteBuiltinPrelu:
James Conroy39825482021-05-27 17:44:50 +0100852 return VisitPreluOperator(delegateData,
853 tfLiteContext,
854 tfLiteNode,
855 nodeIndex,
856 kTfLiteBuiltinPrelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100857 case kTfLiteBuiltinQuantize:
858 return VisitQuantizeOperator(delegateData,
859 tfLiteContext,
860 tfLiteNode,
861 nodeIndex,
862 kTfLiteBuiltinQuantize);
863 case kTfLiteBuiltinRank:
864 return VisitControlOperator(delegateData,
865 tfLiteContext,
866 tfLiteNode,
867 nodeIndex,
868 kTfLiteBuiltinRank);
Sadik Armagana2747482021-02-09 10:28:54 +0000869 case kTfLiteBuiltinReduceMax:
870 return VisitReduceOperator(delegateData,
871 tfLiteContext,
872 tfLiteNode,
873 nodeIndex,
874 kTfLiteBuiltinReduceMax);
875 case kTfLiteBuiltinReduceMin:
876 return VisitReduceOperator(delegateData,
877 tfLiteContext,
878 tfLiteNode,
879 nodeIndex,
880 kTfLiteBuiltinReduceMin);
Teresa Charlin4e3e8312021-08-05 12:34:37 +0100881 case kTfLiteBuiltinReduceProd:
882 return VisitReduceOperator(delegateData,
883 tfLiteContext,
884 tfLiteNode,
885 nodeIndex,
886 kTfLiteBuiltinReduceProd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100887 case kTfLiteBuiltinRelu:
888 return VisitActivationOperator(delegateData,
889 tfLiteContext,
890 tfLiteNode,
891 nodeIndex,
892 kTfLiteBuiltinRelu);
893 case kTfLiteBuiltinReluN1To1:
894 return VisitActivationOperator(delegateData,
895 tfLiteContext,
896 tfLiteNode,
897 nodeIndex,
898 kTfLiteBuiltinReluN1To1);
899 case kTfLiteBuiltinRelu6:
900 return VisitActivationOperator(delegateData,
901 tfLiteContext,
902 tfLiteNode,
903 nodeIndex,
904 kTfLiteBuiltinRelu6);
905 case kTfLiteBuiltinReshape:
906 return VisitReshapeOperator(delegateData,
907 tfLiteContext,
908 tfLiteNode,
909 nodeIndex,
910 kTfLiteBuiltinReshape);
911 case kTfLiteBuiltinResizeBilinear:
912 return VisitResizeOperator(delegateData,
913 tfLiteContext,
914 tfLiteNode,
915 nodeIndex,
916 kTfLiteBuiltinResizeBilinear);
917 case kTfLiteBuiltinResizeNearestNeighbor:
918 return VisitResizeOperator(delegateData,
919 tfLiteContext,
920 tfLiteNode,
921 nodeIndex,
922 kTfLiteBuiltinResizeNearestNeighbor);
923 case kTfLiteBuiltinRsqrt:
924 return VisitElementwiseUnaryOperator(delegateData,
925 tfLiteContext,
926 tfLiteNode,
927 nodeIndex,
928 armnn::UnaryOperation::Rsqrt);
Keith Davis0176fd82021-06-01 17:36:32 +0100929 case kTfLiteBuiltinShape:
930 return VisitShapeOperator(delegateData,
931 tfLiteContext,
932 tfLiteNode,
933 nodeIndex,
934 kTfLiteBuiltinShape);
Teresa Charlinb1f5f702022-07-12 14:16:24 +0100935 case kTfLiteBuiltinSin:
936 return VisitElementwiseUnaryOperator(delegateData,
937 tfLiteContext,
938 tfLiteNode,
939 nodeIndex,
940 armnn::UnaryOperation::Sin);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +0000941 case kTfLiteBuiltinSplit:
942 return VisitSplitOperator(delegateData,
943 tfLiteContext,
944 tfLiteNode,
945 nodeIndex,
946 kTfLiteBuiltinSplit);
947 case kTfLiteBuiltinSplitV:
948 return VisitSplitVOperator(delegateData,
949 tfLiteContext,
950 tfLiteNode,
951 nodeIndex,
952 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +0100953 case kTfLiteBuiltinSqrt:
954 return VisitElementwiseUnaryOperator(delegateData,
955 tfLiteContext,
956 tfLiteNode,
957 nodeIndex,
958 armnn::UnaryOperation::Sqrt);
959 case kTfLiteBuiltinSqueeze:
960 return VisitSqueezeOperator(delegateData,
961 tfLiteContext,
962 tfLiteNode,
963 nodeIndex,
964 kTfLiteBuiltinSqueeze);
965 case kTfLiteBuiltinStridedSlice:
966 return VisitSliceOperator(delegateData,
967 tfLiteContext,
968 tfLiteNode,
969 nodeIndex,
970 kTfLiteBuiltinStridedSlice);
Sadik Armagana2747482021-02-09 10:28:54 +0000971 case kTfLiteBuiltinSum:
972 return VisitReduceOperator(delegateData,
973 tfLiteContext,
974 tfLiteNode,
975 nodeIndex,
976 kTfLiteBuiltinSum);
Sadik Armagan62483be2020-10-23 17:14:43 +0100977 case kTfLiteBuiltinTranspose:
978 return VisitTransposeOperator(delegateData,
979 tfLiteContext,
980 tfLiteNode,
981 nodeIndex,
982 kTfLiteBuiltinTranspose);
983 case kTfLiteBuiltinTransposeConv:
984 return VisitConvolutionOperator(delegateData,
985 tfLiteContext,
986 tfLiteNode,
987 nodeIndex,
988 kTfLiteBuiltinTransposeConv);
989 case kTfLiteBuiltinSoftmax:
990 return VisitSoftmaxOperator(delegateData,
991 tfLiteContext,
992 tfLiteNode,
993 nodeIndex,
994 kTfLiteBuiltinSoftmax);
995 case kTfLiteBuiltinSpaceToBatchNd:
996 return VisitSpaceToBatchNdOperator(delegateData,
997 tfLiteContext,
998 tfLiteNode,
999 nodeIndex,
1000 kTfLiteBuiltinSpaceToBatchNd);
1001 case kTfLiteBuiltinSpaceToDepth:
1002 return VisitSpaceToDepthOperator(delegateData,
1003 tfLiteContext,
1004 tfLiteNode,
1005 nodeIndex,
1006 kTfLiteBuiltinSpaceToDepth);
1007 case kTfLiteBuiltinSub:
1008 return VisitElementwiseBinaryOperator(delegateData,
1009 tfLiteContext,
1010 tfLiteNode,
1011 nodeIndex,
1012 kTfLiteBuiltinSub);
1013 case kTfLiteBuiltinTanh:
1014 return VisitActivationOperator(delegateData,
1015 tfLiteContext,
1016 tfLiteNode,
1017 nodeIndex,
1018 kTfLiteBuiltinTanh);
Narumol Prangnawarat7684b182021-08-12 14:48:15 +01001019 case kTfLiteBuiltinUnidirectionalSequenceLstm:
1020 return VisitUnidirectionalSequenceLstmOperator(delegateData,
1021 tfLiteContext,
1022 tfLiteNode,
1023 nodeIndex,
1024 kTfLiteBuiltinUnidirectionalSequenceLstm);
Kevin May8ab2d7a2021-05-07 09:32:51 +01001025 case kTfLiteBuiltinUnpack:
1026 return VisitUnpackOperator(delegateData,
1027 tfLiteContext,
1028 tfLiteNode,
1029 nodeIndex,
1030 kTfLiteBuiltinUnpack);
Sadik Armagan62483be2020-10-23 17:14:43 +01001031 default:
1032 return kTfLiteError;
1033 }
Sadik Armagan3c24f432020-10-19 17:35:30 +01001034}
1035
1036} // armnnDelegate namespace