blob: aa6c1be37dc094e6691e42b4cfe9cb07ba1e8462 [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"
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)
136 : m_Runtime(nullptr, nullptr),
137 m_Options(std::move(options))
138{
Jan Eilers2cd18472020-12-15 10:42:38 +0000139 // Configures logging for ARMNN
Colm Donelanda7f2f92022-12-20 16:21:35 +0000140 if (m_Options.IsLoggingEnabled())
Jan Eilers2cd18472020-12-15 10:42:38 +0000141 {
Colm Donelanda7f2f92022-12-20 16:21:35 +0000142 armnn::ConfigureLogging(true, true, m_Options.GetLoggingSeverity());
Jan Eilers2cd18472020-12-15 10:42:38 +0000143 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100144 // Create ArmNN Runtime
Colm Donelanda7f2f92022-12-20 16:21:35 +0000145 m_Runtime = armnn::IRuntime::Create(m_Options.GetRuntimeOptions());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100146
147 std::vector<armnn::BackendId> backends;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100148 if (m_Runtime)
149 {
150 const armnn::BackendIdSet supportedDevices = m_Runtime->GetDeviceSpec().GetSupportedBackends();
151 for (auto& backend : m_Options.GetBackends())
152 {
153 if (std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) == supportedDevices.cend())
154 {
Sadik Armagan0534e032020-10-27 17:30:18 +0000155 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100156 "TfLiteArmnnDelegate: Requested unknown backend %s", backend.Get().c_str());
157 }
158 else
159 {
160 backends.push_back(backend);
161 }
162 }
163 }
164
165 if (backends.empty())
166 {
167 // No known backend specified
168 throw armnn::InvalidArgumentException("TfLiteArmnnDelegate: No known backend specified.");
169 }
170 m_Options.SetBackends(backends);
171
172 TFLITE_LOG_PROD_ONCE(tflite::TFLITE_LOG_INFO, "TfLiteArmnnDelegate: Created TfLite ArmNN delegate.");
173}
174
Sadik Armagan62483be2020-10-23 17:14:43 +0100175TfLiteIntArray* Delegate::IdentifyOperatorsToDelegate(TfLiteContext* tfLiteContext)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100176{
177 TfLiteIntArray* executionPlan = nullptr;
178 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
179 {
180 TF_LITE_KERNEL_LOG(tfLiteContext, "TfLiteArmnnDelegate: Unable to get graph execution plan.");
181 return nullptr;
182 }
183
Sadik Armagan62483be2020-10-23 17:14:43 +0100184 // Delegate data with null network
185 DelegateData delegateData(m_Options.GetBackends());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100186
187 TfLiteIntArray* nodesToDelegate = TfLiteIntArrayCreate(executionPlan->size);
188 nodesToDelegate->size = 0;
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000189
190 std::set<int32_t> unsupportedOperators;
191
Sadik Armagan3c24f432020-10-19 17:35:30 +0100192 for (int i = 0; i < executionPlan->size; ++i)
193 {
194 const int nodeIndex = executionPlan->data[i];
195
196 // If TfLite nodes can be delegated to ArmNN
197 TfLiteNode* tfLiteNode = nullptr;
198 TfLiteRegistration* tfLiteRegistration = nullptr;
199 if (tfLiteContext->GetNodeAndRegistration(
200 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
201 {
202 TF_LITE_KERNEL_LOG(tfLiteContext,
203 "TfLiteArmnnDelegate: Unable to get node and registration for node %d.",
204 nodeIndex);
205 continue;
206 }
207
Ryan OShea05b6a3e2023-01-11 15:27:50 +0000208 TfLiteStatus visitStatus;
209
210 try
211 {
212 visitStatus = ArmnnSubgraph::VisitNode(
213 delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex);
214 }
215 catch(std::exception& ex)
216 {
217 ARMNN_LOG(error) << "ArmNN Failed to visit node with error: " << ex.what();
218 visitStatus = kTfLiteError;
219 }
220
221 if ( visitStatus != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100222 {
223 // node is not supported by ArmNN
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000224 unsupportedOperators.insert(tfLiteRegistration->builtin_code);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100225 continue;
226 }
227
228 nodesToDelegate->data[nodesToDelegate->size++] = nodeIndex;
229 }
230
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000231 for (std::set<int32_t>::iterator it=unsupportedOperators.begin(); it!=unsupportedOperators.end(); ++it)
232 {
233 TF_LITE_KERNEL_LOG(tfLiteContext,
234 "Operator %s [%d] is not supported by armnn_delegate.",
235 tflite::EnumNameBuiltinOperator(tflite::BuiltinOperator(*it)),
236 *it);
237 }
238
Sadik Armaganca565c12022-08-16 12:17:24 +0100239 if (!unsupportedOperators.empty() && m_Options.TfLiteRuntimeFallbackDisabled())
240 {
241 std::stringstream exMessage;
242 exMessage << "TfLiteArmnnDelegate: There are unsupported operators in the model. ";
243 exMessage << "Not falling back to TfLite Runtime as fallback is disabled. ";
244 exMessage << "This should only be disabled under test conditions.";
245 throw armnn::Exception(exMessage.str());
246 }
247
Sadik Armagan62483be2020-10-23 17:14:43 +0100248 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100249 return nodesToDelegate;
250}
251
252TfLiteDelegate* Delegate::GetDelegate()
253{
254 return &m_Delegate;
255}
256
Matthew Sloyanac001ee2021-02-03 10:43:04 +0000257const std::string Delegate::GetVersion()
258{
259 return DELEGATE_VERSION;
260}
261
Sadik Armagan62483be2020-10-23 17:14:43 +0100262TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
263 TfLiteContext* tfLiteContext,
264 const TfLiteIntArray* inputs,
265 std::vector<armnn::BindingPointInfo>& inputBindings)
266{
Finn Williams6f9f9902020-11-13 13:23:15 +0000267 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100268 for (unsigned int i = 0; i < numInputs; ++i)
269 {
270 const int32_t tensorId = inputs->data[i];
271 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000272 // Do not create bindings for constant inputs
273 if (tensor.allocation_type == kTfLiteMmapRo)
274 {
275 continue;
276 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100277
278 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
279 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
280
281 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
282 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
283 outputSlot.SetTensorInfo(tensorInfo);
284
285 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000286 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100287
Sadik Armagan6e36a642020-11-10 21:18:41 +0000288 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100289 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000290
Sadik Armagan62483be2020-10-23 17:14:43 +0100291 return kTfLiteOk;
292}
293
294TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
295 TfLiteContext* tfLiteContext,
296 const TfLiteIntArray* outputs,
297 std::vector<armnn::BindingPointInfo>& outputBindings)
298{
Finn Williams6f9f9902020-11-13 13:23:15 +0000299 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100300 for (unsigned int i = 0; i < numOutputs; ++i)
301 {
302 const int32_t tensorId = outputs->data[i];
303 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
304
305 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
306 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
307
308 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Finn Williams6f9f9902020-11-13 13:23:15 +0000309 ARMNN_ASSERT(delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] != nullptr);
310 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100311 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
312 }
313
314 return kTfLiteOk;
315}
316
Sadik Armagan3c24f432020-10-19 17:35:30 +0100317ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
318 const TfLiteDelegateParams* parameters,
319 const Delegate* delegate)
320{
Jan Eilers17d34da2021-12-08 16:15:12 +0000321 const auto startTime = armnn::GetTimeNow();
322 ARMNN_LOG(info) << "ArmnnSubgraph creation";
323
Sadik Armagan3c24f432020-10-19 17:35:30 +0100324 TfLiteIntArray* executionPlan;
325 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
326 {
327 return nullptr;
328 }
329
Sadik Armagan62483be2020-10-23 17:14:43 +0100330 // Initialize DelegateData holds network and output slots information
331 DelegateData delegateData(delegate->m_Options.GetBackends());
332
333 // Build ArmNN Network
Mike Kelly80512b02022-05-16 23:10:42 +0100334 armnn::NetworkOptions networkOptions = delegate->m_Options.GetOptimizerOptions().m_ModelOptions;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100335 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100336 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100337
Sadik Armagan6e36a642020-11-10 21:18:41 +0000338 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
339
Sadik Armagan62483be2020-10-23 17:14:43 +0100340 std::vector<armnn::BindingPointInfo> inputBindings;
341 std::vector<armnn::BindingPointInfo> outputBindings;
342
343 // Add input layer
344 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
345 if (status != kTfLiteOk)
346 {
347 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
348 }
349
350 // Parse TfLite delegate nodes to ArmNN
Jan Eilers17d34da2021-12-08 16:15:12 +0000351 const auto parseStartTime = armnn::GetTimeNow();
Sadik Armagan3c24f432020-10-19 17:35:30 +0100352 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
353 {
354 const int nodeIndex = parameters->nodes_to_replace->data[i];
355
356 TfLiteNode* tfLiteNode = nullptr;
357 TfLiteRegistration* tfLiteRegistration = nullptr;
358 if (tfLiteContext->GetNodeAndRegistration(
359 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
360 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000361 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100362 }
363
Sadik Armagan62483be2020-10-23 17:14:43 +0100364 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100365 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000366 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100367 }
368 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000369 ARMNN_LOG(info) << "Parse nodes to ArmNN time: " << std::setprecision(2)
370 << std::fixed << armnn::GetTimeDuration(parseStartTime).count() << " ms";
Sadik Armagan3c24f432020-10-19 17:35:30 +0100371
Sadik Armagan62483be2020-10-23 17:14:43 +0100372 // Add Output layer
373 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
374 if (status != kTfLiteOk)
375 {
376 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
377 }
378
379 // Optimize ArmNN network
380 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
381 try
382 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000383 const auto optimizeStartTime = armnn::GetTimeNow();
Sadik Armagan6e36a642020-11-10 21:18:41 +0000384 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100385 delegate->m_Options.GetBackends(),
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000386 delegate->m_Runtime->GetDeviceSpec(),
387 delegate->m_Options.GetOptimizerOptions());
Jan Eilers17d34da2021-12-08 16:15:12 +0000388 ARMNN_LOG(info) << "Optimize ArmnnSubgraph time: " << std::setprecision(2)
389 << std::fixed << armnn::GetTimeDuration(optimizeStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100390 }
Ryan OShea05b6a3e2023-01-11 15:27:50 +0000391 catch (std::exception& ex)
Sadik Armagan62483be2020-10-23 17:14:43 +0100392 {
393 std::stringstream exMessage;
394 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
395 throw armnn::Exception(exMessage.str());
396 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100397 if (!optNet)
398 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100399 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100400 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
401 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100402
Colm Donelan3e32a872021-10-04 22:55:37 +0100403 // If set, we will serialize the optimized model into a dot file.
404 const std::string serializeToDotFile = delegate->m_Options.GetSerializeToDot();
405 if (!serializeToDotFile.empty())
406 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000407 ARMNN_LOG(info) << "Writing graph to dot file: " << serializeToDotFile;
Colm Donelan3e32a872021-10-04 22:55:37 +0100408 fs::path filename = serializeToDotFile;
409 std::fstream file(filename.c_str(), std::ios_base::out);
410 optNet->SerializeToDot(file);
411 }
412
Sadik Armagan62483be2020-10-23 17:14:43 +0100413 try
414 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000415 const auto loadStartTime = armnn::GetTimeNow();
416
Sadik Armagan62483be2020-10-23 17:14:43 +0100417 // Load graph into runtime
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000418 std::string errorMessage;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000419 armnn::Status loadingStatus;
Francis Murtagh626bd902022-06-21 13:16:23 +0000420 armnn::MemorySource inputSource = armnn::MemorySource::Undefined;
421 armnn::MemorySource outputSource = armnn::MemorySource::Undefined;
422 // There's a bit of an assumption here that the delegate will only support Malloc memory source.
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000423 if (delegate->m_Options.GetOptimizerOptions().m_ImportEnabled)
424 {
Francis Murtagh626bd902022-06-21 13:16:23 +0000425 inputSource = armnn::MemorySource::Malloc;
426 }
427 if (delegate->m_Options.GetOptimizerOptions().m_ExportEnabled)
428 {
429 outputSource = armnn::MemorySource::Malloc;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000430 }
Colm Donelan3e32a872021-10-04 22:55:37 +0100431 armnn::INetworkProperties networkProperties(false,
Francis Murtagh626bd902022-06-21 13:16:23 +0000432 inputSource,
433 outputSource,
Colm Donelan3e32a872021-10-04 22:55:37 +0100434 delegate->m_Options.GetInternalProfilingState(),
435 delegate->m_Options.GetInternalProfilingDetail());
436 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
437 std::move(optNet),
438 errorMessage,
439 networkProperties);
Sadik Armagan62483be2020-10-23 17:14:43 +0100440 if (loadingStatus != armnn::Status::Success)
441 {
Colm Donelan45142282021-10-21 23:39:52 +0100442 // Network load failed.
Colm Donelan194086f2022-11-14 17:23:07 +0000443 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded: " + errorMessage);
Sadik Armagan62483be2020-10-23 17:14:43 +0100444 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000445
446 ARMNN_LOG(info) << "Load ArmnnSubgraph time: " << std::setprecision(2)
447 << std::fixed << armnn::GetTimeDuration(loadStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100448 }
449 catch (std::exception& ex)
450 {
451 std::stringstream exMessage;
452 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
453 throw armnn::Exception(exMessage.str());
454 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100455
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000456 // Register debug callback function
457 if (delegate->m_Options.GetDebugCallbackFunction().has_value())
458 {
459 delegate->m_Runtime->RegisterDebugCallback(networkId, delegate->m_Options.GetDebugCallbackFunction().value());
460 }
461
Jan Eilers17d34da2021-12-08 16:15:12 +0000462 ARMNN_LOG(info) << "Overall ArmnnSubgraph creation time: " << std::setprecision(2)
463 << std::fixed << armnn::GetTimeDuration(startTime).count() << " ms\n";
464
Sadik Armagan3c24f432020-10-19 17:35:30 +0100465 // Create a new SubGraph with networkId and runtime
Sadik Armagan62483be2020-10-23 17:14:43 +0100466 return new ArmnnSubgraph(networkId, delegate->m_Runtime.get(), inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100467}
468
469TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
470{
Finn Williams6f9f9902020-11-13 13:23:15 +0000471 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100472 return kTfLiteOk;
473}
474
Sadik Armagan62483be2020-10-23 17:14:43 +0100475TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100476{
Sadik Armagan62483be2020-10-23 17:14:43 +0100477 // Prepare inputs
478 armnn::InputTensors inputTensors;
479 size_t inputIndex = 0;
480 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
481 {
482 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
483 if (tensor->allocation_type != kTfLiteMmapRo)
484 {
485 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100486 armnn::TensorInfo inputTensorInfo = inputBinding.second;
487 inputTensorInfo.SetConstant(true);
488 const armnn::ConstTensor inputTensor(inputTensorInfo, tensor->data.data);
Sadik Armagan62483be2020-10-23 17:14:43 +0100489 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100490
Sadik Armagan62483be2020-10-23 17:14:43 +0100491 ++inputIndex;
492 }
493 }
494
495 // Prepare outputs
496 armnn::OutputTensors outputTensors;
497 size_t outputIndex = 0;
498 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
499 {
500 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
501 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
502 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
503 outputTensors.emplace_back(outputIdx, outputTensor);
504
505 ++outputIndex;
506 }
507
508 // Run graph
509 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
Colm Donelan45142282021-10-21 23:39:52 +0100510 // The delegate holds its own Arm NN runtime so this is our last chance to print internal profiling data.
511 std::shared_ptr<armnn::IProfiler> profiler = m_Runtime->GetProfiler(m_NetworkId);
512 if (profiler && profiler->IsProfilingEnabled())
513 {
514 profiler->Print(std::cout);
515 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100516 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100517}
518
Sadik Armagan62483be2020-10-23 17:14:43 +0100519TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100520 TfLiteContext* tfLiteContext,
521 TfLiteRegistration* tfLiteRegistration,
522 TfLiteNode* tfLiteNode,
523 int nodeIndex)
524{
Sadik Armagan62483be2020-10-23 17:14:43 +0100525 switch (tfLiteRegistration->builtin_code)
526 {
Ryan OShead21abaf2022-06-10 14:49:11 +0100527 case kTfLiteBuiltinCustom:
528 {
529#if defined(ARMNN_POST_TFLITE_2_5)
530 // Custom operators are defined by the name rather than the builtin code.
531 // Parse the custom_name param in the registration to point to the correct visitor function.
532 std::string customOperatorName = tfLiteRegistration->custom_name;
533 if ( customOperatorName == "AveragePool3D" )
534 {
535 return VisitPooling3dOperator(delegateData,
536 tfLiteContext,
537 tfLiteNode,
538 nodeIndex,
539 customOperatorName);
540 }
541 else if (customOperatorName == "MaxPool3D")
542 {
543 return VisitPooling3dOperator(delegateData,
544 tfLiteContext,
545 tfLiteNode,
546 nodeIndex,
547 customOperatorName);
548 }
549#endif
550 // Invalid or unsupported custom operator
551 return kTfLiteError;
552 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100553 case kTfLiteBuiltinAbs:
554 return VisitElementwiseUnaryOperator(delegateData,
555 tfLiteContext,
556 tfLiteNode,
557 nodeIndex,
558 armnn::UnaryOperation::Abs);
559 case kTfLiteBuiltinAdd:
560 return VisitElementwiseBinaryOperator(delegateData,
561 tfLiteContext,
562 tfLiteNode,
563 nodeIndex,
564 kTfLiteBuiltinAdd);
565 case kTfLiteBuiltinArgMax:
566 return VisitArgMinMaxOperator(delegateData,
567 tfLiteContext,
568 tfLiteNode,
569 nodeIndex,
570 kTfLiteBuiltinArgMax);
571 case kTfLiteBuiltinArgMin:
572 return VisitArgMinMaxOperator(delegateData,
573 tfLiteContext,
574 tfLiteNode,
575 nodeIndex,
576 kTfLiteBuiltinArgMin);
577 case kTfLiteBuiltinAveragePool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100578 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100579 tfLiteContext,
580 tfLiteNode,
581 nodeIndex,
582 kTfLiteBuiltinAveragePool2d);
Ryan OShea49ed0df2022-09-21 16:09:41 +0100583 case kTfLiteBuiltinBatchMatmul:
584 return VisitBatchMatMulOperator(delegateData,
585 tfLiteContext,
586 tfLiteNode,
587 nodeIndex,
588 kTfLiteBuiltinBatchMatmul);
Sadik Armagan62483be2020-10-23 17:14:43 +0100589 case kTfLiteBuiltinBatchToSpaceNd:
590 return VisitBatchToSpaceNdOperator(delegateData,
591 tfLiteContext,
592 tfLiteNode,
593 nodeIndex,
594 kTfLiteBuiltinBatchToSpaceNd);
Sadik Armagan937565b2021-04-21 14:03:28 +0100595 case kTfLiteBuiltinCast:
596 return VisitCastOperator(delegateData,
597 tfLiteContext,
598 tfLiteNode,
599 nodeIndex,
600 kTfLiteBuiltinCast);
Sadik Armagan62483be2020-10-23 17:14:43 +0100601 case kTfLiteBuiltinConcatenation:
602 return VisitControlOperator(delegateData,
603 tfLiteContext,
604 tfLiteNode,
605 nodeIndex,
606 kTfLiteBuiltinConcatenation);
607 case kTfLiteBuiltinConv2d:
608 return VisitConvolutionOperator(delegateData,
609 tfLiteContext,
610 tfLiteNode,
611 nodeIndex,
612 kTfLiteBuiltinConv2d);
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100613// Conv3d is only correctly supported for external delegates from TF Lite v2.6, as there was a breaking bug in v2.5.
614#if defined(ARMNN_POST_TFLITE_2_5)
615 case kTfLiteBuiltinConv3d:
616 return VisitConvolutionOperator(delegateData,
617 tfLiteContext,
618 tfLiteNode,
619 nodeIndex,
620 kTfLiteBuiltinConv3d);
621#endif
Sadik Armagan62483be2020-10-23 17:14:43 +0100622 case kTfLiteBuiltinDepthToSpace:
623 return VisitDepthToSpaceOperator(delegateData,
624 tfLiteContext,
625 tfLiteNode,
626 nodeIndex,
627 kTfLiteBuiltinDepthToSpace);
628 case kTfLiteBuiltinDepthwiseConv2d:
629 return VisitConvolutionOperator(delegateData,
630 tfLiteContext,
631 tfLiteNode,
632 nodeIndex,
633 kTfLiteBuiltinDepthwiseConv2d);
634 case kTfLiteBuiltinDequantize:
635 return VisitDequantizeOperator(delegateData,
636 tfLiteContext,
637 tfLiteNode,
638 nodeIndex,
639 kTfLiteBuiltinDequantize);
640 case kTfLiteBuiltinDiv:
641 return VisitElementwiseBinaryOperator(delegateData,
642 tfLiteContext,
643 tfLiteNode,
644 nodeIndex,
645 kTfLiteBuiltinDiv);
646 case kTfLiteBuiltinElu:
647 return VisitActivationOperator(delegateData,
648 tfLiteContext,
649 tfLiteNode,
650 nodeIndex,
651 kTfLiteBuiltinElu);
652 case kTfLiteBuiltinEqual:
653 return VisitComparisonOperator(delegateData,
654 tfLiteContext,
655 tfLiteNode,
656 nodeIndex,
657 kTfLiteBuiltinEqual);
658 case kTfLiteBuiltinExp:
659 return VisitElementwiseUnaryOperator(delegateData,
660 tfLiteContext,
661 tfLiteNode,
662 nodeIndex,
663 armnn::UnaryOperation::Exp);
664 case kTfLiteBuiltinExpandDims:
665 return VisitExpandDimsOperator(delegateData,
666 tfLiteContext,
667 tfLiteNode,
668 nodeIndex,
669 kTfLiteBuiltinExpandDims);
670 case kTfLiteBuiltinFill:
671 return VisitFillOperator(delegateData,
672 tfLiteContext,
673 tfLiteNode,
674 nodeIndex,
675 kTfLiteBuiltinFill);
676 case kTfLiteBuiltinFloor:
677 return VisitFloorOperator(delegateData,
678 tfLiteContext,
679 tfLiteNode,
680 nodeIndex,
681 kTfLiteBuiltinFloor);
Jim Flynn4b2f3472021-10-13 21:20:07 +0100682 case kTfLiteBuiltinFloorDiv:
683 return VisitElementwiseBinaryOperator(delegateData,
684 tfLiteContext,
685 tfLiteNode,
686 nodeIndex,
687 kTfLiteBuiltinFloorDiv);
Sadik Armagan62483be2020-10-23 17:14:43 +0100688 case kTfLiteBuiltinFullyConnected:
689 return VisitFullyConnectedOperator(delegateData,
690 tfLiteContext,
691 tfLiteNode,
692 nodeIndex,
693 kTfLiteBuiltinFullyConnected);
694 case kTfLiteBuiltinGather:
695 return VisitGatherOperator(delegateData,
696 tfLiteContext,
697 tfLiteNode,
698 nodeIndex,
699 kTfLiteBuiltinGather);
Teresa Charlind5c0ed22022-04-25 18:23:41 +0100700 case kTfLiteBuiltinGatherNd:
701 return VisitGatherNdOperator(delegateData,
702 tfLiteContext,
703 tfLiteNode,
704 nodeIndex,
705 kTfLiteBuiltinGatherNd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100706 case kTfLiteBuiltinGreater:
707 return VisitComparisonOperator(delegateData,
708 tfLiteContext,
709 tfLiteNode,
710 nodeIndex,
711 kTfLiteBuiltinGreater);
712 case kTfLiteBuiltinGreaterEqual:
713 return VisitComparisonOperator(delegateData,
714 tfLiteContext,
715 tfLiteNode,
716 nodeIndex,
717 kTfLiteBuiltinGreaterEqual);
718 case kTfLiteBuiltinHardSwish:
719 return VisitActivationOperator(delegateData,
720 tfLiteContext,
721 tfLiteNode,
722 nodeIndex,
723 kTfLiteBuiltinHardSwish);
724 case kTfLiteBuiltinL2Normalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000725 return VisitL2NormalizationOperator(delegateData,
726 tfLiteContext,
727 tfLiteNode,
728 nodeIndex,
729 kTfLiteBuiltinL2Normalization);
Sadik Armagan62483be2020-10-23 17:14:43 +0100730 case kTfLiteBuiltinL2Pool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100731 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100732 tfLiteContext,
733 tfLiteNode,
734 nodeIndex,
735 kTfLiteBuiltinL2Pool2d);
736 case kTfLiteBuiltinLess:
737 return VisitComparisonOperator(delegateData,
738 tfLiteContext,
739 tfLiteNode,
740 nodeIndex,
741 kTfLiteBuiltinLess);
742 case kTfLiteBuiltinLessEqual:
743 return VisitComparisonOperator(delegateData,
744 tfLiteContext,
745 tfLiteNode,
746 nodeIndex,
747 kTfLiteBuiltinLessEqual);
748 case kTfLiteBuiltinLocalResponseNormalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000749 return VisitLocalResponseNormalizationOperator(delegateData,
750 tfLiteContext,
751 tfLiteNode,
752 nodeIndex,
753 kTfLiteBuiltinLocalResponseNormalization);
Teresa Charlinb1f5f702022-07-12 14:16:24 +0100754 case kTfLiteBuiltinLog:
755 return VisitElementwiseUnaryOperator(delegateData,
756 tfLiteContext,
757 tfLiteNode,
758 nodeIndex,
759 armnn::UnaryOperation::Log);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000760 case kTfLiteBuiltinLogicalAnd:
761 return VisitLogicalBinaryOperator(delegateData,
762 tfLiteContext,
763 tfLiteNode,
764 nodeIndex,
765 kTfLiteBuiltinLogicalAnd,
766 armnn::LogicalBinaryOperation::LogicalAnd);
767 case kTfLiteBuiltinLogicalNot:
768 return VisitElementwiseUnaryOperator(delegateData,
769 tfLiteContext,
770 tfLiteNode,
771 nodeIndex,
772 armnn::UnaryOperation::LogicalNot);
773 case kTfLiteBuiltinLogicalOr:
774 return VisitLogicalBinaryOperator(delegateData,
775 tfLiteContext,
776 tfLiteNode,
777 nodeIndex,
778 kTfLiteBuiltinLogicalOr,
779 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100780 case kTfLiteBuiltinLogistic:
781 return VisitActivationOperator(delegateData,
782 tfLiteContext,
783 tfLiteNode,
784 nodeIndex,
785 kTfLiteBuiltinLogistic);
786 case kTfLiteBuiltinLogSoftmax:
787 return VisitSoftmaxOperator(delegateData,
788 tfLiteContext,
789 tfLiteNode,
790 nodeIndex,
791 kTfLiteBuiltinLogSoftmax);
792 case kTfLiteBuiltinLstm:
793 return VisitLstmOperator(delegateData,
794 tfLiteContext,
795 tfLiteNode,
796 nodeIndex,
797 kTfLiteBuiltinLstm);
798 case kTfLiteBuiltinMaxPool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100799 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100800 tfLiteContext,
801 tfLiteNode,
802 nodeIndex,
803 kTfLiteBuiltinMaxPool2d);
804 case kTfLiteBuiltinMaximum:
805 return VisitElementwiseBinaryOperator(delegateData,
806 tfLiteContext,
807 tfLiteNode,
808 nodeIndex,
809 kTfLiteBuiltinMaximum);
810 case kTfLiteBuiltinMean:
811 return VisitControlOperator(delegateData,
812 tfLiteContext,
813 tfLiteNode,
814 nodeIndex,
815 kTfLiteBuiltinMean);
816 case kTfLiteBuiltinMinimum:
817 return VisitElementwiseBinaryOperator(delegateData,
818 tfLiteContext,
819 tfLiteNode,
820 nodeIndex,
821 kTfLiteBuiltinMinimum);
Matthew Sloyanaf3a4ef2021-10-22 15:48:12 +0100822 case kTfLiteBuiltinMirrorPad:
823 return VisitPadOperator(delegateData,
824 tfLiteContext,
825 tfLiteNode,
826 nodeIndex,
827 kTfLiteBuiltinMirrorPad);
Sadik Armagan62483be2020-10-23 17:14:43 +0100828 case kTfLiteBuiltinMul:
829 return VisitElementwiseBinaryOperator(delegateData,
830 tfLiteContext,
831 tfLiteNode,
832 nodeIndex,
833 kTfLiteBuiltinMul);
834 case kTfLiteBuiltinNeg:
835 return VisitElementwiseUnaryOperator(delegateData,
836 tfLiteContext,
837 tfLiteNode,
838 nodeIndex,
839 armnn::UnaryOperation::Neg);
840 case kTfLiteBuiltinNotEqual:
841 return VisitComparisonOperator(delegateData,
842 tfLiteContext,
843 tfLiteNode,
844 nodeIndex,
845 kTfLiteBuiltinNotEqual);
Matthew Sloyana7a12f52021-05-06 10:05:28 +0100846 case kTfLiteBuiltinPack:
847 return VisitPackOperator(delegateData,
848 tfLiteContext,
849 tfLiteNode,
850 nodeIndex,
851 kTfLiteBuiltinPack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100852 case kTfLiteBuiltinPad:
853 return VisitPadOperator(delegateData,
854 tfLiteContext,
855 tfLiteNode,
856 nodeIndex,
857 kTfLiteBuiltinPad);
858 case kTfLiteBuiltinPadv2:
859 return VisitPadOperator(delegateData,
860 tfLiteContext,
861 tfLiteNode,
862 nodeIndex,
863 kTfLiteBuiltinPadv2);
864 case kTfLiteBuiltinPrelu:
James Conroy39825482021-05-27 17:44:50 +0100865 return VisitPreluOperator(delegateData,
866 tfLiteContext,
867 tfLiteNode,
868 nodeIndex,
869 kTfLiteBuiltinPrelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100870 case kTfLiteBuiltinQuantize:
871 return VisitQuantizeOperator(delegateData,
872 tfLiteContext,
873 tfLiteNode,
874 nodeIndex,
875 kTfLiteBuiltinQuantize);
876 case kTfLiteBuiltinRank:
877 return VisitControlOperator(delegateData,
878 tfLiteContext,
879 tfLiteNode,
880 nodeIndex,
881 kTfLiteBuiltinRank);
Sadik Armagana2747482021-02-09 10:28:54 +0000882 case kTfLiteBuiltinReduceMax:
883 return VisitReduceOperator(delegateData,
884 tfLiteContext,
885 tfLiteNode,
886 nodeIndex,
887 kTfLiteBuiltinReduceMax);
888 case kTfLiteBuiltinReduceMin:
889 return VisitReduceOperator(delegateData,
890 tfLiteContext,
891 tfLiteNode,
892 nodeIndex,
893 kTfLiteBuiltinReduceMin);
Teresa Charlin4e3e8312021-08-05 12:34:37 +0100894 case kTfLiteBuiltinReduceProd:
895 return VisitReduceOperator(delegateData,
896 tfLiteContext,
897 tfLiteNode,
898 nodeIndex,
899 kTfLiteBuiltinReduceProd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100900 case kTfLiteBuiltinRelu:
901 return VisitActivationOperator(delegateData,
902 tfLiteContext,
903 tfLiteNode,
904 nodeIndex,
905 kTfLiteBuiltinRelu);
906 case kTfLiteBuiltinReluN1To1:
907 return VisitActivationOperator(delegateData,
908 tfLiteContext,
909 tfLiteNode,
910 nodeIndex,
911 kTfLiteBuiltinReluN1To1);
912 case kTfLiteBuiltinRelu6:
913 return VisitActivationOperator(delegateData,
914 tfLiteContext,
915 tfLiteNode,
916 nodeIndex,
917 kTfLiteBuiltinRelu6);
918 case kTfLiteBuiltinReshape:
919 return VisitReshapeOperator(delegateData,
920 tfLiteContext,
921 tfLiteNode,
922 nodeIndex,
923 kTfLiteBuiltinReshape);
924 case kTfLiteBuiltinResizeBilinear:
925 return VisitResizeOperator(delegateData,
926 tfLiteContext,
927 tfLiteNode,
928 nodeIndex,
929 kTfLiteBuiltinResizeBilinear);
930 case kTfLiteBuiltinResizeNearestNeighbor:
931 return VisitResizeOperator(delegateData,
932 tfLiteContext,
933 tfLiteNode,
934 nodeIndex,
935 kTfLiteBuiltinResizeNearestNeighbor);
936 case kTfLiteBuiltinRsqrt:
937 return VisitElementwiseUnaryOperator(delegateData,
938 tfLiteContext,
939 tfLiteNode,
940 nodeIndex,
941 armnn::UnaryOperation::Rsqrt);
Keith Davis0176fd82021-06-01 17:36:32 +0100942 case kTfLiteBuiltinShape:
943 return VisitShapeOperator(delegateData,
944 tfLiteContext,
945 tfLiteNode,
946 nodeIndex,
947 kTfLiteBuiltinShape);
Teresa Charlinb1f5f702022-07-12 14:16:24 +0100948 case kTfLiteBuiltinSin:
949 return VisitElementwiseUnaryOperator(delegateData,
950 tfLiteContext,
951 tfLiteNode,
952 nodeIndex,
953 armnn::UnaryOperation::Sin);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +0000954 case kTfLiteBuiltinSplit:
955 return VisitSplitOperator(delegateData,
956 tfLiteContext,
957 tfLiteNode,
958 nodeIndex,
959 kTfLiteBuiltinSplit);
960 case kTfLiteBuiltinSplitV:
961 return VisitSplitVOperator(delegateData,
962 tfLiteContext,
963 tfLiteNode,
964 nodeIndex,
965 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +0100966 case kTfLiteBuiltinSqrt:
967 return VisitElementwiseUnaryOperator(delegateData,
968 tfLiteContext,
969 tfLiteNode,
970 nodeIndex,
971 armnn::UnaryOperation::Sqrt);
972 case kTfLiteBuiltinSqueeze:
973 return VisitSqueezeOperator(delegateData,
974 tfLiteContext,
975 tfLiteNode,
976 nodeIndex,
977 kTfLiteBuiltinSqueeze);
Cathal Corbett839b9322022-11-18 08:52:18 +0000978 case kTfLiteBuiltinSlice:
Sadik Armagan62483be2020-10-23 17:14:43 +0100979 return VisitSliceOperator(delegateData,
980 tfLiteContext,
981 tfLiteNode,
982 nodeIndex,
Cathal Corbett839b9322022-11-18 08:52:18 +0000983 kTfLiteBuiltinSlice);
984 case kTfLiteBuiltinStridedSlice:
985 return VisitStridedSliceOperator(delegateData,
986 tfLiteContext,
987 tfLiteNode,
988 nodeIndex,
989 kTfLiteBuiltinStridedSlice);
Sadik Armagana2747482021-02-09 10:28:54 +0000990 case kTfLiteBuiltinSum:
991 return VisitReduceOperator(delegateData,
992 tfLiteContext,
993 tfLiteNode,
994 nodeIndex,
995 kTfLiteBuiltinSum);
Sadik Armagan62483be2020-10-23 17:14:43 +0100996 case kTfLiteBuiltinTranspose:
997 return VisitTransposeOperator(delegateData,
998 tfLiteContext,
999 tfLiteNode,
1000 nodeIndex,
1001 kTfLiteBuiltinTranspose);
1002 case kTfLiteBuiltinTransposeConv:
1003 return VisitConvolutionOperator(delegateData,
1004 tfLiteContext,
1005 tfLiteNode,
1006 nodeIndex,
1007 kTfLiteBuiltinTransposeConv);
1008 case kTfLiteBuiltinSoftmax:
1009 return VisitSoftmaxOperator(delegateData,
1010 tfLiteContext,
1011 tfLiteNode,
1012 nodeIndex,
1013 kTfLiteBuiltinSoftmax);
1014 case kTfLiteBuiltinSpaceToBatchNd:
1015 return VisitSpaceToBatchNdOperator(delegateData,
1016 tfLiteContext,
1017 tfLiteNode,
1018 nodeIndex,
1019 kTfLiteBuiltinSpaceToBatchNd);
1020 case kTfLiteBuiltinSpaceToDepth:
1021 return VisitSpaceToDepthOperator(delegateData,
1022 tfLiteContext,
1023 tfLiteNode,
1024 nodeIndex,
1025 kTfLiteBuiltinSpaceToDepth);
1026 case kTfLiteBuiltinSub:
1027 return VisitElementwiseBinaryOperator(delegateData,
1028 tfLiteContext,
1029 tfLiteNode,
1030 nodeIndex,
1031 kTfLiteBuiltinSub);
1032 case kTfLiteBuiltinTanh:
1033 return VisitActivationOperator(delegateData,
1034 tfLiteContext,
1035 tfLiteNode,
1036 nodeIndex,
1037 kTfLiteBuiltinTanh);
Narumol Prangnawarat7684b182021-08-12 14:48:15 +01001038 case kTfLiteBuiltinUnidirectionalSequenceLstm:
1039 return VisitUnidirectionalSequenceLstmOperator(delegateData,
1040 tfLiteContext,
1041 tfLiteNode,
1042 nodeIndex,
1043 kTfLiteBuiltinUnidirectionalSequenceLstm);
Kevin May8ab2d7a2021-05-07 09:32:51 +01001044 case kTfLiteBuiltinUnpack:
1045 return VisitUnpackOperator(delegateData,
1046 tfLiteContext,
1047 tfLiteNode,
1048 nodeIndex,
1049 kTfLiteBuiltinUnpack);
Sadik Armagan62483be2020-10-23 17:14:43 +01001050 default:
1051 return kTfLiteError;
1052 }
Sadik Armagan3c24f432020-10-19 17:35:30 +01001053}
1054
1055} // armnnDelegate namespace