blob: c041dd1714bcd333397513e99f36151b47b87d86 [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"
12#include "BatchSpace.hpp"
13#include "Comparison.hpp"
14#include "Convolution.hpp"
15#include "Control.hpp"
16#include "ElementwiseBinary.hpp"
17#include "ElementwiseUnary.hpp"
18#include "Fill.hpp"
19#include "FullyConnected.hpp"
20#include "Gather.hpp"
Teresa Charlind5c0ed22022-04-25 18:23:41 +010021#include "GatherNd.hpp"
Matthew Sloyanc8eb9552020-11-26 10:54:22 +000022#include "LogicalBinary.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010023#include "Lstm.hpp"
24#include "Normalization.hpp"
Matthew Sloyana7a12f52021-05-06 10:05:28 +010025#include "Pack.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010026#include "Pad.hpp"
27#include "Pooling.hpp"
James Conroy39825482021-05-27 17:44:50 +010028#include "Prelu.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010029#include "Quantization.hpp"
30#include "Redefine.hpp"
Sadik Armagana2747482021-02-09 10:28:54 +000031#include "Reduce.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010032#include "Resize.hpp"
33#include "Round.hpp"
Keith Davis0176fd82021-06-01 17:36:32 +010034#include "Shape.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010035#include "Slice.hpp"
36#include "Softmax.hpp"
37#include "SpaceDepth.hpp"
Sadik Armagan34fa1bd2020-11-27 12:40:52 +000038#include "Split.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010039#include "Transpose.hpp"
Narumol Prangnawarat7684b182021-08-12 14:48:15 +010040#include "UnidirectionalSequenceLstm.hpp"
Kevin May8ab2d7a2021-05-07 09:32:51 +010041#include "Unpack.hpp"
Sadik Armagan62483be2020-10-23 17:14:43 +010042
Colm Donelan3e32a872021-10-04 22:55:37 +010043#include <armnnUtils/Filesystem.hpp>
Jan Eilers17d34da2021-12-08 16:15:12 +000044#include <armnn/utility/Timer.hpp>
Sadik Armagan62483be2020-10-23 17:14:43 +010045#include <flatbuffers/flatbuffers.h>
46#include <tensorflow/lite/context_util.h>
Jim Flynn4b2f3472021-10-13 21:20:07 +010047#include <tensorflow/lite/schema/schema_generated.h>
Sadik Armagan62483be2020-10-23 17:14:43 +010048
Sadik Armagan3c24f432020-10-19 17:35:30 +010049#include <algorithm>
Matthew Sloyanac001ee2021-02-03 10:43:04 +000050#include <iostream>
Sadik Armagan62483be2020-10-23 17:14:43 +010051#include <sstream>
Sadik Armagan3c24f432020-10-19 17:35:30 +010052
53namespace armnnDelegate
54{
55
Sadik Armagan62483be2020-10-23 17:14:43 +010056DelegateOptions TfLiteArmnnDelegateOptionsDefault()
57{
58 DelegateOptions options(armnn::Compute::CpuRef);
59 return options;
60}
61
62TfLiteDelegate* TfLiteArmnnDelegateCreate(armnnDelegate::DelegateOptions options)
63{
64 auto* armnnDelegate = new ::armnnDelegate::Delegate(options);
65 return armnnDelegate->GetDelegate();
66}
67
68void TfLiteArmnnDelegateDelete(TfLiteDelegate* tfLiteDelegate)
69{
70 if (tfLiteDelegate != nullptr)
71 {
72 delete static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_);
73 }
74}
75
76TfLiteStatus DoPrepare(TfLiteContext* tfLiteContext, TfLiteDelegate* tfLiteDelegate)
77{
78 TfLiteIntArray* supportedOperators =
79 static_cast<::armnnDelegate::Delegate*>(tfLiteDelegate->data_)->IdentifyOperatorsToDelegate(tfLiteContext);
80
81 // ArmNN Delegate Registration
82 static const TfLiteRegistration kArmnnSubgraphRegistration = {
83 // ArmnnSubgraph Init
84 .init = [](TfLiteContext* tfLiteContext, const char* buffer, size_t length) -> void* {
Finn Williams6f9f9902020-11-13 13:23:15 +000085 armnn::IgnoreUnused(length);
Sadik Armagan62483be2020-10-23 17:14:43 +010086 const TfLiteDelegateParams* parameters = reinterpret_cast<const TfLiteDelegateParams*>(buffer);
87
88 return static_cast<void*>(ArmnnSubgraph::Create(
89 tfLiteContext, parameters, static_cast<::armnnDelegate::Delegate*>(parameters->delegate->data_)));
90 },
91 // ArmnnSubgraph Free
92 .free = [](TfLiteContext* tfLiteContext, void* buffer) -> void {
Finn Williams6f9f9902020-11-13 13:23:15 +000093 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan62483be2020-10-23 17:14:43 +010094 if (buffer != nullptr)
95 {
96 delete static_cast<ArmnnSubgraph*>(buffer);
97 }
98 },
99 // ArmnnSubgraph Prepare
100 .prepare = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
101 if (tfLiteNode->user_data == nullptr)
102 {
103 return kTfLiteError;
104 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100105 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Prepare(tfLiteContext);
106 },
107 // ArmnnSubgraph Invoke
108 .invoke = [](TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode) -> TfLiteStatus {
109 if (tfLiteNode->user_data == nullptr)
110 {
111 return kTfLiteError;
112 }
113
114 return static_cast<ArmnnSubgraph*>(tfLiteNode->user_data)->Invoke(tfLiteContext, tfLiteNode);
115 },
116
117 .profiling_string = nullptr,
118 .builtin_code = kTfLiteBuiltinDelegate,
119 .custom_name = "TfLiteArmNnDelegate",
120 .version = 1,
121 };
122
123 const TfLiteStatus status =
124 tfLiteContext->ReplaceNodeSubsetsWithDelegateKernels(
125 tfLiteContext, kArmnnSubgraphRegistration, supportedOperators, tfLiteDelegate);
126
127 TfLiteIntArrayFree(supportedOperators);
128 return status;
129
130}
131
Sadik Armagan3c24f432020-10-19 17:35:30 +0100132Delegate::Delegate(armnnDelegate::DelegateOptions options)
133 : m_Runtime(nullptr, nullptr),
134 m_Options(std::move(options))
135{
Jan Eilers2cd18472020-12-15 10:42:38 +0000136 // Configures logging for ARMNN
137 if (options.IsLoggingEnabled())
138 {
139 armnn::ConfigureLogging(true, true, options.GetLoggingSeverity());
140 }
141
Sadik Armagan3c24f432020-10-19 17:35:30 +0100142 // Create ArmNN Runtime
Jan Eilersb1c62f12021-10-26 14:56:47 +0100143 m_Runtime = armnn::IRuntime::Create(options.GetRuntimeOptions());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100144
145 std::vector<armnn::BackendId> backends;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100146 if (m_Runtime)
147 {
148 const armnn::BackendIdSet supportedDevices = m_Runtime->GetDeviceSpec().GetSupportedBackends();
149 for (auto& backend : m_Options.GetBackends())
150 {
151 if (std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) == supportedDevices.cend())
152 {
Sadik Armagan0534e032020-10-27 17:30:18 +0000153 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100154 "TfLiteArmnnDelegate: Requested unknown backend %s", backend.Get().c_str());
155 }
156 else
157 {
158 backends.push_back(backend);
159 }
160 }
161 }
162
163 if (backends.empty())
164 {
165 // No known backend specified
166 throw armnn::InvalidArgumentException("TfLiteArmnnDelegate: No known backend specified.");
167 }
168 m_Options.SetBackends(backends);
169
170 TFLITE_LOG_PROD_ONCE(tflite::TFLITE_LOG_INFO, "TfLiteArmnnDelegate: Created TfLite ArmNN delegate.");
171}
172
Sadik Armagan62483be2020-10-23 17:14:43 +0100173TfLiteIntArray* Delegate::IdentifyOperatorsToDelegate(TfLiteContext* tfLiteContext)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100174{
175 TfLiteIntArray* executionPlan = nullptr;
176 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
177 {
178 TF_LITE_KERNEL_LOG(tfLiteContext, "TfLiteArmnnDelegate: Unable to get graph execution plan.");
179 return nullptr;
180 }
181
Sadik Armagan62483be2020-10-23 17:14:43 +0100182 // Delegate data with null network
183 DelegateData delegateData(m_Options.GetBackends());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100184
185 TfLiteIntArray* nodesToDelegate = TfLiteIntArrayCreate(executionPlan->size);
186 nodesToDelegate->size = 0;
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000187
188 std::set<int32_t> unsupportedOperators;
189
Sadik Armagan3c24f432020-10-19 17:35:30 +0100190 for (int i = 0; i < executionPlan->size; ++i)
191 {
192 const int nodeIndex = executionPlan->data[i];
193
194 // If TfLite nodes can be delegated to ArmNN
195 TfLiteNode* tfLiteNode = nullptr;
196 TfLiteRegistration* tfLiteRegistration = nullptr;
197 if (tfLiteContext->GetNodeAndRegistration(
198 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
199 {
200 TF_LITE_KERNEL_LOG(tfLiteContext,
201 "TfLiteArmnnDelegate: Unable to get node and registration for node %d.",
202 nodeIndex);
203 continue;
204 }
205
206 if (ArmnnSubgraph::VisitNode(
Sadik Armagan62483be2020-10-23 17:14:43 +0100207 delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100208 {
209 // node is not supported by ArmNN
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000210 unsupportedOperators.insert(tfLiteRegistration->builtin_code);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100211 continue;
212 }
213
214 nodesToDelegate->data[nodesToDelegate->size++] = nodeIndex;
215 }
216
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000217 for (std::set<int32_t>::iterator it=unsupportedOperators.begin(); it!=unsupportedOperators.end(); ++it)
218 {
219 TF_LITE_KERNEL_LOG(tfLiteContext,
220 "Operator %s [%d] is not supported by armnn_delegate.",
221 tflite::EnumNameBuiltinOperator(tflite::BuiltinOperator(*it)),
222 *it);
223 }
224
Sadik Armaganca565c12022-08-16 12:17:24 +0100225 if (!unsupportedOperators.empty() && m_Options.TfLiteRuntimeFallbackDisabled())
226 {
227 std::stringstream exMessage;
228 exMessage << "TfLiteArmnnDelegate: There are unsupported operators in the model. ";
229 exMessage << "Not falling back to TfLite Runtime as fallback is disabled. ";
230 exMessage << "This should only be disabled under test conditions.";
231 throw armnn::Exception(exMessage.str());
232 }
233
Sadik Armagan62483be2020-10-23 17:14:43 +0100234 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100235 return nodesToDelegate;
236}
237
238TfLiteDelegate* Delegate::GetDelegate()
239{
240 return &m_Delegate;
241}
242
Matthew Sloyanac001ee2021-02-03 10:43:04 +0000243const std::string Delegate::GetVersion()
244{
245 return DELEGATE_VERSION;
246}
247
Sadik Armagan62483be2020-10-23 17:14:43 +0100248TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
249 TfLiteContext* tfLiteContext,
250 const TfLiteIntArray* inputs,
251 std::vector<armnn::BindingPointInfo>& inputBindings)
252{
Finn Williams6f9f9902020-11-13 13:23:15 +0000253 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100254 for (unsigned int i = 0; i < numInputs; ++i)
255 {
256 const int32_t tensorId = inputs->data[i];
257 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000258 // Do not create bindings for constant inputs
259 if (tensor.allocation_type == kTfLiteMmapRo)
260 {
261 continue;
262 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100263
264 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
265 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
266
267 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
268 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
269 outputSlot.SetTensorInfo(tensorInfo);
270
271 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000272 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100273
Sadik Armagan6e36a642020-11-10 21:18:41 +0000274 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100275 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000276
Sadik Armagan62483be2020-10-23 17:14:43 +0100277 return kTfLiteOk;
278}
279
280TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
281 TfLiteContext* tfLiteContext,
282 const TfLiteIntArray* outputs,
283 std::vector<armnn::BindingPointInfo>& outputBindings)
284{
Finn Williams6f9f9902020-11-13 13:23:15 +0000285 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100286 for (unsigned int i = 0; i < numOutputs; ++i)
287 {
288 const int32_t tensorId = outputs->data[i];
289 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
290
291 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
292 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
293
294 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Finn Williams6f9f9902020-11-13 13:23:15 +0000295 ARMNN_ASSERT(delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] != nullptr);
296 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100297 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
298 }
299
300 return kTfLiteOk;
301}
302
Sadik Armagan3c24f432020-10-19 17:35:30 +0100303ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
304 const TfLiteDelegateParams* parameters,
305 const Delegate* delegate)
306{
Jan Eilers17d34da2021-12-08 16:15:12 +0000307 const auto startTime = armnn::GetTimeNow();
308 ARMNN_LOG(info) << "ArmnnSubgraph creation";
309
Sadik Armagan3c24f432020-10-19 17:35:30 +0100310 TfLiteIntArray* executionPlan;
311 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
312 {
313 return nullptr;
314 }
315
Sadik Armagan62483be2020-10-23 17:14:43 +0100316 // Initialize DelegateData holds network and output slots information
317 DelegateData delegateData(delegate->m_Options.GetBackends());
318
319 // Build ArmNN Network
Mike Kelly80512b02022-05-16 23:10:42 +0100320 armnn::NetworkOptions networkOptions = delegate->m_Options.GetOptimizerOptions().m_ModelOptions;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100321 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100322 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100323
Sadik Armagan6e36a642020-11-10 21:18:41 +0000324 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
325
Sadik Armagan62483be2020-10-23 17:14:43 +0100326 std::vector<armnn::BindingPointInfo> inputBindings;
327 std::vector<armnn::BindingPointInfo> outputBindings;
328
329 // Add input layer
330 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
331 if (status != kTfLiteOk)
332 {
333 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
334 }
335
336 // Parse TfLite delegate nodes to ArmNN
Jan Eilers17d34da2021-12-08 16:15:12 +0000337 const auto parseStartTime = armnn::GetTimeNow();
Sadik Armagan3c24f432020-10-19 17:35:30 +0100338 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
339 {
340 const int nodeIndex = parameters->nodes_to_replace->data[i];
341
342 TfLiteNode* tfLiteNode = nullptr;
343 TfLiteRegistration* tfLiteRegistration = nullptr;
344 if (tfLiteContext->GetNodeAndRegistration(
345 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
346 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000347 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100348 }
349
Sadik Armagan62483be2020-10-23 17:14:43 +0100350 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100351 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000352 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100353 }
354 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000355 ARMNN_LOG(info) << "Parse nodes to ArmNN time: " << std::setprecision(2)
356 << std::fixed << armnn::GetTimeDuration(parseStartTime).count() << " ms";
Sadik Armagan3c24f432020-10-19 17:35:30 +0100357
Sadik Armagan62483be2020-10-23 17:14:43 +0100358 // Add Output layer
359 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
360 if (status != kTfLiteOk)
361 {
362 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
363 }
364
365 // Optimize ArmNN network
366 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
367 try
368 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000369 const auto optimizeStartTime = armnn::GetTimeNow();
Sadik Armagan6e36a642020-11-10 21:18:41 +0000370 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100371 delegate->m_Options.GetBackends(),
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000372 delegate->m_Runtime->GetDeviceSpec(),
373 delegate->m_Options.GetOptimizerOptions());
Jan Eilers17d34da2021-12-08 16:15:12 +0000374 ARMNN_LOG(info) << "Optimize ArmnnSubgraph time: " << std::setprecision(2)
375 << std::fixed << armnn::GetTimeDuration(optimizeStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100376 }
377 catch (std::exception &ex)
378 {
379 std::stringstream exMessage;
380 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
381 throw armnn::Exception(exMessage.str());
382 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100383 if (!optNet)
384 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100385 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100386 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
387 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100388
Colm Donelan3e32a872021-10-04 22:55:37 +0100389 // If set, we will serialize the optimized model into a dot file.
390 const std::string serializeToDotFile = delegate->m_Options.GetSerializeToDot();
391 if (!serializeToDotFile.empty())
392 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000393 ARMNN_LOG(info) << "Writing graph to dot file: " << serializeToDotFile;
Colm Donelan3e32a872021-10-04 22:55:37 +0100394 fs::path filename = serializeToDotFile;
395 std::fstream file(filename.c_str(), std::ios_base::out);
396 optNet->SerializeToDot(file);
397 }
398
Sadik Armagan62483be2020-10-23 17:14:43 +0100399 try
400 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000401 const auto loadStartTime = armnn::GetTimeNow();
402
Sadik Armagan62483be2020-10-23 17:14:43 +0100403 // Load graph into runtime
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000404 std::string errorMessage;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000405 armnn::Status loadingStatus;
Francis Murtagh626bd902022-06-21 13:16:23 +0000406 armnn::MemorySource inputSource = armnn::MemorySource::Undefined;
407 armnn::MemorySource outputSource = armnn::MemorySource::Undefined;
408 // There's a bit of an assumption here that the delegate will only support Malloc memory source.
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000409 if (delegate->m_Options.GetOptimizerOptions().m_ImportEnabled)
410 {
Francis Murtagh626bd902022-06-21 13:16:23 +0000411 inputSource = armnn::MemorySource::Malloc;
412 }
413 if (delegate->m_Options.GetOptimizerOptions().m_ExportEnabled)
414 {
415 outputSource = armnn::MemorySource::Malloc;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000416 }
Colm Donelan3e32a872021-10-04 22:55:37 +0100417 armnn::INetworkProperties networkProperties(false,
Francis Murtagh626bd902022-06-21 13:16:23 +0000418 inputSource,
419 outputSource,
Colm Donelan3e32a872021-10-04 22:55:37 +0100420 delegate->m_Options.GetInternalProfilingState(),
421 delegate->m_Options.GetInternalProfilingDetail());
422 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
423 std::move(optNet),
424 errorMessage,
425 networkProperties);
Sadik Armagan62483be2020-10-23 17:14:43 +0100426 if (loadingStatus != armnn::Status::Success)
427 {
Colm Donelan45142282021-10-21 23:39:52 +0100428 // Network load failed.
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000429 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded:" + errorMessage);
Sadik Armagan62483be2020-10-23 17:14:43 +0100430 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000431
432 ARMNN_LOG(info) << "Load ArmnnSubgraph time: " << std::setprecision(2)
433 << std::fixed << armnn::GetTimeDuration(loadStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100434 }
435 catch (std::exception& ex)
436 {
437 std::stringstream exMessage;
438 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
439 throw armnn::Exception(exMessage.str());
440 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100441
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000442 // Register debug callback function
443 if (delegate->m_Options.GetDebugCallbackFunction().has_value())
444 {
445 delegate->m_Runtime->RegisterDebugCallback(networkId, delegate->m_Options.GetDebugCallbackFunction().value());
446 }
447
Jan Eilers17d34da2021-12-08 16:15:12 +0000448 ARMNN_LOG(info) << "Overall ArmnnSubgraph creation time: " << std::setprecision(2)
449 << std::fixed << armnn::GetTimeDuration(startTime).count() << " ms\n";
450
Sadik Armagan3c24f432020-10-19 17:35:30 +0100451 // Create a new SubGraph with networkId and runtime
Sadik Armagan62483be2020-10-23 17:14:43 +0100452 return new ArmnnSubgraph(networkId, delegate->m_Runtime.get(), inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100453}
454
455TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
456{
Finn Williams6f9f9902020-11-13 13:23:15 +0000457 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100458 return kTfLiteOk;
459}
460
Sadik Armagan62483be2020-10-23 17:14:43 +0100461TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100462{
Sadik Armagan62483be2020-10-23 17:14:43 +0100463 // Prepare inputs
464 armnn::InputTensors inputTensors;
465 size_t inputIndex = 0;
466 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
467 {
468 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
469 if (tensor->allocation_type != kTfLiteMmapRo)
470 {
471 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100472 armnn::TensorInfo inputTensorInfo = inputBinding.second;
473 inputTensorInfo.SetConstant(true);
474 const armnn::ConstTensor inputTensor(inputTensorInfo, tensor->data.data);
Sadik Armagan62483be2020-10-23 17:14:43 +0100475 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100476
Sadik Armagan62483be2020-10-23 17:14:43 +0100477 ++inputIndex;
478 }
479 }
480
481 // Prepare outputs
482 armnn::OutputTensors outputTensors;
483 size_t outputIndex = 0;
484 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
485 {
486 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
487 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
488 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
489 outputTensors.emplace_back(outputIdx, outputTensor);
490
491 ++outputIndex;
492 }
493
494 // Run graph
495 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
Colm Donelan45142282021-10-21 23:39:52 +0100496 // The delegate holds its own Arm NN runtime so this is our last chance to print internal profiling data.
497 std::shared_ptr<armnn::IProfiler> profiler = m_Runtime->GetProfiler(m_NetworkId);
498 if (profiler && profiler->IsProfilingEnabled())
499 {
500 profiler->Print(std::cout);
501 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100502 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100503}
504
Sadik Armagan62483be2020-10-23 17:14:43 +0100505TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100506 TfLiteContext* tfLiteContext,
507 TfLiteRegistration* tfLiteRegistration,
508 TfLiteNode* tfLiteNode,
509 int nodeIndex)
510{
Sadik Armagan62483be2020-10-23 17:14:43 +0100511 switch (tfLiteRegistration->builtin_code)
512 {
Ryan OShead21abaf2022-06-10 14:49:11 +0100513 case kTfLiteBuiltinCustom:
514 {
515#if defined(ARMNN_POST_TFLITE_2_5)
516 // Custom operators are defined by the name rather than the builtin code.
517 // Parse the custom_name param in the registration to point to the correct visitor function.
518 std::string customOperatorName = tfLiteRegistration->custom_name;
519 if ( customOperatorName == "AveragePool3D" )
520 {
521 return VisitPooling3dOperator(delegateData,
522 tfLiteContext,
523 tfLiteNode,
524 nodeIndex,
525 customOperatorName);
526 }
527 else if (customOperatorName == "MaxPool3D")
528 {
529 return VisitPooling3dOperator(delegateData,
530 tfLiteContext,
531 tfLiteNode,
532 nodeIndex,
533 customOperatorName);
534 }
535#endif
536 // Invalid or unsupported custom operator
537 return kTfLiteError;
538 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100539 case kTfLiteBuiltinAbs:
540 return VisitElementwiseUnaryOperator(delegateData,
541 tfLiteContext,
542 tfLiteNode,
543 nodeIndex,
544 armnn::UnaryOperation::Abs);
545 case kTfLiteBuiltinAdd:
546 return VisitElementwiseBinaryOperator(delegateData,
547 tfLiteContext,
548 tfLiteNode,
549 nodeIndex,
550 kTfLiteBuiltinAdd);
551 case kTfLiteBuiltinArgMax:
552 return VisitArgMinMaxOperator(delegateData,
553 tfLiteContext,
554 tfLiteNode,
555 nodeIndex,
556 kTfLiteBuiltinArgMax);
557 case kTfLiteBuiltinArgMin:
558 return VisitArgMinMaxOperator(delegateData,
559 tfLiteContext,
560 tfLiteNode,
561 nodeIndex,
562 kTfLiteBuiltinArgMin);
563 case kTfLiteBuiltinAveragePool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100564 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100565 tfLiteContext,
566 tfLiteNode,
567 nodeIndex,
568 kTfLiteBuiltinAveragePool2d);
569 case kTfLiteBuiltinBatchToSpaceNd:
570 return VisitBatchToSpaceNdOperator(delegateData,
571 tfLiteContext,
572 tfLiteNode,
573 nodeIndex,
574 kTfLiteBuiltinBatchToSpaceNd);
Sadik Armagan937565b2021-04-21 14:03:28 +0100575 case kTfLiteBuiltinCast:
576 return VisitCastOperator(delegateData,
577 tfLiteContext,
578 tfLiteNode,
579 nodeIndex,
580 kTfLiteBuiltinCast);
Sadik Armagan62483be2020-10-23 17:14:43 +0100581 case kTfLiteBuiltinConcatenation:
582 return VisitControlOperator(delegateData,
583 tfLiteContext,
584 tfLiteNode,
585 nodeIndex,
586 kTfLiteBuiltinConcatenation);
587 case kTfLiteBuiltinConv2d:
588 return VisitConvolutionOperator(delegateData,
589 tfLiteContext,
590 tfLiteNode,
591 nodeIndex,
592 kTfLiteBuiltinConv2d);
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100593// Conv3d is only correctly supported for external delegates from TF Lite v2.6, as there was a breaking bug in v2.5.
594#if defined(ARMNN_POST_TFLITE_2_5)
595 case kTfLiteBuiltinConv3d:
596 return VisitConvolutionOperator(delegateData,
597 tfLiteContext,
598 tfLiteNode,
599 nodeIndex,
600 kTfLiteBuiltinConv3d);
601#endif
Sadik Armagan62483be2020-10-23 17:14:43 +0100602 case kTfLiteBuiltinDepthToSpace:
603 return VisitDepthToSpaceOperator(delegateData,
604 tfLiteContext,
605 tfLiteNode,
606 nodeIndex,
607 kTfLiteBuiltinDepthToSpace);
608 case kTfLiteBuiltinDepthwiseConv2d:
609 return VisitConvolutionOperator(delegateData,
610 tfLiteContext,
611 tfLiteNode,
612 nodeIndex,
613 kTfLiteBuiltinDepthwiseConv2d);
614 case kTfLiteBuiltinDequantize:
615 return VisitDequantizeOperator(delegateData,
616 tfLiteContext,
617 tfLiteNode,
618 nodeIndex,
619 kTfLiteBuiltinDequantize);
620 case kTfLiteBuiltinDiv:
621 return VisitElementwiseBinaryOperator(delegateData,
622 tfLiteContext,
623 tfLiteNode,
624 nodeIndex,
625 kTfLiteBuiltinDiv);
626 case kTfLiteBuiltinElu:
627 return VisitActivationOperator(delegateData,
628 tfLiteContext,
629 tfLiteNode,
630 nodeIndex,
631 kTfLiteBuiltinElu);
632 case kTfLiteBuiltinEqual:
633 return VisitComparisonOperator(delegateData,
634 tfLiteContext,
635 tfLiteNode,
636 nodeIndex,
637 kTfLiteBuiltinEqual);
638 case kTfLiteBuiltinExp:
639 return VisitElementwiseUnaryOperator(delegateData,
640 tfLiteContext,
641 tfLiteNode,
642 nodeIndex,
643 armnn::UnaryOperation::Exp);
644 case kTfLiteBuiltinExpandDims:
645 return VisitExpandDimsOperator(delegateData,
646 tfLiteContext,
647 tfLiteNode,
648 nodeIndex,
649 kTfLiteBuiltinExpandDims);
650 case kTfLiteBuiltinFill:
651 return VisitFillOperator(delegateData,
652 tfLiteContext,
653 tfLiteNode,
654 nodeIndex,
655 kTfLiteBuiltinFill);
656 case kTfLiteBuiltinFloor:
657 return VisitFloorOperator(delegateData,
658 tfLiteContext,
659 tfLiteNode,
660 nodeIndex,
661 kTfLiteBuiltinFloor);
Jim Flynn4b2f3472021-10-13 21:20:07 +0100662 case kTfLiteBuiltinFloorDiv:
663 return VisitElementwiseBinaryOperator(delegateData,
664 tfLiteContext,
665 tfLiteNode,
666 nodeIndex,
667 kTfLiteBuiltinFloorDiv);
Sadik Armagan62483be2020-10-23 17:14:43 +0100668 case kTfLiteBuiltinFullyConnected:
669 return VisitFullyConnectedOperator(delegateData,
670 tfLiteContext,
671 tfLiteNode,
672 nodeIndex,
673 kTfLiteBuiltinFullyConnected);
674 case kTfLiteBuiltinGather:
675 return VisitGatherOperator(delegateData,
676 tfLiteContext,
677 tfLiteNode,
678 nodeIndex,
679 kTfLiteBuiltinGather);
Teresa Charlind5c0ed22022-04-25 18:23:41 +0100680 case kTfLiteBuiltinGatherNd:
681 return VisitGatherNdOperator(delegateData,
682 tfLiteContext,
683 tfLiteNode,
684 nodeIndex,
685 kTfLiteBuiltinGatherNd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100686 case kTfLiteBuiltinGreater:
687 return VisitComparisonOperator(delegateData,
688 tfLiteContext,
689 tfLiteNode,
690 nodeIndex,
691 kTfLiteBuiltinGreater);
692 case kTfLiteBuiltinGreaterEqual:
693 return VisitComparisonOperator(delegateData,
694 tfLiteContext,
695 tfLiteNode,
696 nodeIndex,
697 kTfLiteBuiltinGreaterEqual);
698 case kTfLiteBuiltinHardSwish:
699 return VisitActivationOperator(delegateData,
700 tfLiteContext,
701 tfLiteNode,
702 nodeIndex,
703 kTfLiteBuiltinHardSwish);
704 case kTfLiteBuiltinL2Normalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000705 return VisitL2NormalizationOperator(delegateData,
706 tfLiteContext,
707 tfLiteNode,
708 nodeIndex,
709 kTfLiteBuiltinL2Normalization);
Sadik Armagan62483be2020-10-23 17:14:43 +0100710 case kTfLiteBuiltinL2Pool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100711 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100712 tfLiteContext,
713 tfLiteNode,
714 nodeIndex,
715 kTfLiteBuiltinL2Pool2d);
716 case kTfLiteBuiltinLess:
717 return VisitComparisonOperator(delegateData,
718 tfLiteContext,
719 tfLiteNode,
720 nodeIndex,
721 kTfLiteBuiltinLess);
722 case kTfLiteBuiltinLessEqual:
723 return VisitComparisonOperator(delegateData,
724 tfLiteContext,
725 tfLiteNode,
726 nodeIndex,
727 kTfLiteBuiltinLessEqual);
728 case kTfLiteBuiltinLocalResponseNormalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000729 return VisitLocalResponseNormalizationOperator(delegateData,
730 tfLiteContext,
731 tfLiteNode,
732 nodeIndex,
733 kTfLiteBuiltinLocalResponseNormalization);
Teresa Charlinb1f5f702022-07-12 14:16:24 +0100734 case kTfLiteBuiltinLog:
735 return VisitElementwiseUnaryOperator(delegateData,
736 tfLiteContext,
737 tfLiteNode,
738 nodeIndex,
739 armnn::UnaryOperation::Log);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000740 case kTfLiteBuiltinLogicalAnd:
741 return VisitLogicalBinaryOperator(delegateData,
742 tfLiteContext,
743 tfLiteNode,
744 nodeIndex,
745 kTfLiteBuiltinLogicalAnd,
746 armnn::LogicalBinaryOperation::LogicalAnd);
747 case kTfLiteBuiltinLogicalNot:
748 return VisitElementwiseUnaryOperator(delegateData,
749 tfLiteContext,
750 tfLiteNode,
751 nodeIndex,
752 armnn::UnaryOperation::LogicalNot);
753 case kTfLiteBuiltinLogicalOr:
754 return VisitLogicalBinaryOperator(delegateData,
755 tfLiteContext,
756 tfLiteNode,
757 nodeIndex,
758 kTfLiteBuiltinLogicalOr,
759 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100760 case kTfLiteBuiltinLogistic:
761 return VisitActivationOperator(delegateData,
762 tfLiteContext,
763 tfLiteNode,
764 nodeIndex,
765 kTfLiteBuiltinLogistic);
766 case kTfLiteBuiltinLogSoftmax:
767 return VisitSoftmaxOperator(delegateData,
768 tfLiteContext,
769 tfLiteNode,
770 nodeIndex,
771 kTfLiteBuiltinLogSoftmax);
772 case kTfLiteBuiltinLstm:
773 return VisitLstmOperator(delegateData,
774 tfLiteContext,
775 tfLiteNode,
776 nodeIndex,
777 kTfLiteBuiltinLstm);
778 case kTfLiteBuiltinMaxPool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100779 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100780 tfLiteContext,
781 tfLiteNode,
782 nodeIndex,
783 kTfLiteBuiltinMaxPool2d);
784 case kTfLiteBuiltinMaximum:
785 return VisitElementwiseBinaryOperator(delegateData,
786 tfLiteContext,
787 tfLiteNode,
788 nodeIndex,
789 kTfLiteBuiltinMaximum);
790 case kTfLiteBuiltinMean:
791 return VisitControlOperator(delegateData,
792 tfLiteContext,
793 tfLiteNode,
794 nodeIndex,
795 kTfLiteBuiltinMean);
796 case kTfLiteBuiltinMinimum:
797 return VisitElementwiseBinaryOperator(delegateData,
798 tfLiteContext,
799 tfLiteNode,
800 nodeIndex,
801 kTfLiteBuiltinMinimum);
Matthew Sloyanaf3a4ef2021-10-22 15:48:12 +0100802 case kTfLiteBuiltinMirrorPad:
803 return VisitPadOperator(delegateData,
804 tfLiteContext,
805 tfLiteNode,
806 nodeIndex,
807 kTfLiteBuiltinMirrorPad);
Sadik Armagan62483be2020-10-23 17:14:43 +0100808 case kTfLiteBuiltinMul:
809 return VisitElementwiseBinaryOperator(delegateData,
810 tfLiteContext,
811 tfLiteNode,
812 nodeIndex,
813 kTfLiteBuiltinMul);
814 case kTfLiteBuiltinNeg:
815 return VisitElementwiseUnaryOperator(delegateData,
816 tfLiteContext,
817 tfLiteNode,
818 nodeIndex,
819 armnn::UnaryOperation::Neg);
820 case kTfLiteBuiltinNotEqual:
821 return VisitComparisonOperator(delegateData,
822 tfLiteContext,
823 tfLiteNode,
824 nodeIndex,
825 kTfLiteBuiltinNotEqual);
Matthew Sloyana7a12f52021-05-06 10:05:28 +0100826 case kTfLiteBuiltinPack:
827 return VisitPackOperator(delegateData,
828 tfLiteContext,
829 tfLiteNode,
830 nodeIndex,
831 kTfLiteBuiltinPack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100832 case kTfLiteBuiltinPad:
833 return VisitPadOperator(delegateData,
834 tfLiteContext,
835 tfLiteNode,
836 nodeIndex,
837 kTfLiteBuiltinPad);
838 case kTfLiteBuiltinPadv2:
839 return VisitPadOperator(delegateData,
840 tfLiteContext,
841 tfLiteNode,
842 nodeIndex,
843 kTfLiteBuiltinPadv2);
844 case kTfLiteBuiltinPrelu:
James Conroy39825482021-05-27 17:44:50 +0100845 return VisitPreluOperator(delegateData,
846 tfLiteContext,
847 tfLiteNode,
848 nodeIndex,
849 kTfLiteBuiltinPrelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100850 case kTfLiteBuiltinQuantize:
851 return VisitQuantizeOperator(delegateData,
852 tfLiteContext,
853 tfLiteNode,
854 nodeIndex,
855 kTfLiteBuiltinQuantize);
856 case kTfLiteBuiltinRank:
857 return VisitControlOperator(delegateData,
858 tfLiteContext,
859 tfLiteNode,
860 nodeIndex,
861 kTfLiteBuiltinRank);
Sadik Armagana2747482021-02-09 10:28:54 +0000862 case kTfLiteBuiltinReduceMax:
863 return VisitReduceOperator(delegateData,
864 tfLiteContext,
865 tfLiteNode,
866 nodeIndex,
867 kTfLiteBuiltinReduceMax);
868 case kTfLiteBuiltinReduceMin:
869 return VisitReduceOperator(delegateData,
870 tfLiteContext,
871 tfLiteNode,
872 nodeIndex,
873 kTfLiteBuiltinReduceMin);
Teresa Charlin4e3e8312021-08-05 12:34:37 +0100874 case kTfLiteBuiltinReduceProd:
875 return VisitReduceOperator(delegateData,
876 tfLiteContext,
877 tfLiteNode,
878 nodeIndex,
879 kTfLiteBuiltinReduceProd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100880 case kTfLiteBuiltinRelu:
881 return VisitActivationOperator(delegateData,
882 tfLiteContext,
883 tfLiteNode,
884 nodeIndex,
885 kTfLiteBuiltinRelu);
886 case kTfLiteBuiltinReluN1To1:
887 return VisitActivationOperator(delegateData,
888 tfLiteContext,
889 tfLiteNode,
890 nodeIndex,
891 kTfLiteBuiltinReluN1To1);
892 case kTfLiteBuiltinRelu6:
893 return VisitActivationOperator(delegateData,
894 tfLiteContext,
895 tfLiteNode,
896 nodeIndex,
897 kTfLiteBuiltinRelu6);
898 case kTfLiteBuiltinReshape:
899 return VisitReshapeOperator(delegateData,
900 tfLiteContext,
901 tfLiteNode,
902 nodeIndex,
903 kTfLiteBuiltinReshape);
904 case kTfLiteBuiltinResizeBilinear:
905 return VisitResizeOperator(delegateData,
906 tfLiteContext,
907 tfLiteNode,
908 nodeIndex,
909 kTfLiteBuiltinResizeBilinear);
910 case kTfLiteBuiltinResizeNearestNeighbor:
911 return VisitResizeOperator(delegateData,
912 tfLiteContext,
913 tfLiteNode,
914 nodeIndex,
915 kTfLiteBuiltinResizeNearestNeighbor);
916 case kTfLiteBuiltinRsqrt:
917 return VisitElementwiseUnaryOperator(delegateData,
918 tfLiteContext,
919 tfLiteNode,
920 nodeIndex,
921 armnn::UnaryOperation::Rsqrt);
Keith Davis0176fd82021-06-01 17:36:32 +0100922 case kTfLiteBuiltinShape:
923 return VisitShapeOperator(delegateData,
924 tfLiteContext,
925 tfLiteNode,
926 nodeIndex,
927 kTfLiteBuiltinShape);
Teresa Charlinb1f5f702022-07-12 14:16:24 +0100928 case kTfLiteBuiltinSin:
929 return VisitElementwiseUnaryOperator(delegateData,
930 tfLiteContext,
931 tfLiteNode,
932 nodeIndex,
933 armnn::UnaryOperation::Sin);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +0000934 case kTfLiteBuiltinSplit:
935 return VisitSplitOperator(delegateData,
936 tfLiteContext,
937 tfLiteNode,
938 nodeIndex,
939 kTfLiteBuiltinSplit);
940 case kTfLiteBuiltinSplitV:
941 return VisitSplitVOperator(delegateData,
942 tfLiteContext,
943 tfLiteNode,
944 nodeIndex,
945 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +0100946 case kTfLiteBuiltinSqrt:
947 return VisitElementwiseUnaryOperator(delegateData,
948 tfLiteContext,
949 tfLiteNode,
950 nodeIndex,
951 armnn::UnaryOperation::Sqrt);
952 case kTfLiteBuiltinSqueeze:
953 return VisitSqueezeOperator(delegateData,
954 tfLiteContext,
955 tfLiteNode,
956 nodeIndex,
957 kTfLiteBuiltinSqueeze);
958 case kTfLiteBuiltinStridedSlice:
959 return VisitSliceOperator(delegateData,
960 tfLiteContext,
961 tfLiteNode,
962 nodeIndex,
963 kTfLiteBuiltinStridedSlice);
Sadik Armagana2747482021-02-09 10:28:54 +0000964 case kTfLiteBuiltinSum:
965 return VisitReduceOperator(delegateData,
966 tfLiteContext,
967 tfLiteNode,
968 nodeIndex,
969 kTfLiteBuiltinSum);
Sadik Armagan62483be2020-10-23 17:14:43 +0100970 case kTfLiteBuiltinTranspose:
971 return VisitTransposeOperator(delegateData,
972 tfLiteContext,
973 tfLiteNode,
974 nodeIndex,
975 kTfLiteBuiltinTranspose);
976 case kTfLiteBuiltinTransposeConv:
977 return VisitConvolutionOperator(delegateData,
978 tfLiteContext,
979 tfLiteNode,
980 nodeIndex,
981 kTfLiteBuiltinTransposeConv);
982 case kTfLiteBuiltinSoftmax:
983 return VisitSoftmaxOperator(delegateData,
984 tfLiteContext,
985 tfLiteNode,
986 nodeIndex,
987 kTfLiteBuiltinSoftmax);
988 case kTfLiteBuiltinSpaceToBatchNd:
989 return VisitSpaceToBatchNdOperator(delegateData,
990 tfLiteContext,
991 tfLiteNode,
992 nodeIndex,
993 kTfLiteBuiltinSpaceToBatchNd);
994 case kTfLiteBuiltinSpaceToDepth:
995 return VisitSpaceToDepthOperator(delegateData,
996 tfLiteContext,
997 tfLiteNode,
998 nodeIndex,
999 kTfLiteBuiltinSpaceToDepth);
1000 case kTfLiteBuiltinSub:
1001 return VisitElementwiseBinaryOperator(delegateData,
1002 tfLiteContext,
1003 tfLiteNode,
1004 nodeIndex,
1005 kTfLiteBuiltinSub);
1006 case kTfLiteBuiltinTanh:
1007 return VisitActivationOperator(delegateData,
1008 tfLiteContext,
1009 tfLiteNode,
1010 nodeIndex,
1011 kTfLiteBuiltinTanh);
Narumol Prangnawarat7684b182021-08-12 14:48:15 +01001012 case kTfLiteBuiltinUnidirectionalSequenceLstm:
1013 return VisitUnidirectionalSequenceLstmOperator(delegateData,
1014 tfLiteContext,
1015 tfLiteNode,
1016 nodeIndex,
1017 kTfLiteBuiltinUnidirectionalSequenceLstm);
Kevin May8ab2d7a2021-05-07 09:32:51 +01001018 case kTfLiteBuiltinUnpack:
1019 return VisitUnpackOperator(delegateData,
1020 tfLiteContext,
1021 tfLiteNode,
1022 nodeIndex,
1023 kTfLiteBuiltinUnpack);
Sadik Armagan62483be2020-10-23 17:14:43 +01001024 default:
1025 return kTfLiteError;
1026 }
Sadik Armagan3c24f432020-10-19 17:35:30 +01001027}
1028
1029} // armnnDelegate namespace