blob: 4d95522dbdb18255780efb9bc6491640a43da60d [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
140 if (options.IsLoggingEnabled())
141 {
142 armnn::ConfigureLogging(true, true, options.GetLoggingSeverity());
143 }
144
Sadik Armagan3c24f432020-10-19 17:35:30 +0100145 // Create ArmNN Runtime
Jan Eilersb1c62f12021-10-26 14:56:47 +0100146 m_Runtime = armnn::IRuntime::Create(options.GetRuntimeOptions());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100147
148 std::vector<armnn::BackendId> backends;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100149 if (m_Runtime)
150 {
151 const armnn::BackendIdSet supportedDevices = m_Runtime->GetDeviceSpec().GetSupportedBackends();
152 for (auto& backend : m_Options.GetBackends())
153 {
154 if (std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) == supportedDevices.cend())
155 {
Sadik Armagan0534e032020-10-27 17:30:18 +0000156 TFLITE_LOG_PROD(tflite::TFLITE_LOG_INFO,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100157 "TfLiteArmnnDelegate: Requested unknown backend %s", backend.Get().c_str());
158 }
159 else
160 {
161 backends.push_back(backend);
162 }
163 }
164 }
165
166 if (backends.empty())
167 {
168 // No known backend specified
169 throw armnn::InvalidArgumentException("TfLiteArmnnDelegate: No known backend specified.");
170 }
171 m_Options.SetBackends(backends);
172
173 TFLITE_LOG_PROD_ONCE(tflite::TFLITE_LOG_INFO, "TfLiteArmnnDelegate: Created TfLite ArmNN delegate.");
174}
175
Sadik Armagan62483be2020-10-23 17:14:43 +0100176TfLiteIntArray* Delegate::IdentifyOperatorsToDelegate(TfLiteContext* tfLiteContext)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100177{
178 TfLiteIntArray* executionPlan = nullptr;
179 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
180 {
181 TF_LITE_KERNEL_LOG(tfLiteContext, "TfLiteArmnnDelegate: Unable to get graph execution plan.");
182 return nullptr;
183 }
184
Sadik Armagan62483be2020-10-23 17:14:43 +0100185 // Delegate data with null network
186 DelegateData delegateData(m_Options.GetBackends());
Sadik Armagan3c24f432020-10-19 17:35:30 +0100187
188 TfLiteIntArray* nodesToDelegate = TfLiteIntArrayCreate(executionPlan->size);
189 nodesToDelegate->size = 0;
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000190
191 std::set<int32_t> unsupportedOperators;
192
Sadik Armagan3c24f432020-10-19 17:35:30 +0100193 for (int i = 0; i < executionPlan->size; ++i)
194 {
195 const int nodeIndex = executionPlan->data[i];
196
197 // If TfLite nodes can be delegated to ArmNN
198 TfLiteNode* tfLiteNode = nullptr;
199 TfLiteRegistration* tfLiteRegistration = nullptr;
200 if (tfLiteContext->GetNodeAndRegistration(
201 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
202 {
203 TF_LITE_KERNEL_LOG(tfLiteContext,
204 "TfLiteArmnnDelegate: Unable to get node and registration for node %d.",
205 nodeIndex);
206 continue;
207 }
208
209 if (ArmnnSubgraph::VisitNode(
Sadik Armagan62483be2020-10-23 17:14:43 +0100210 delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100211 {
212 // node is not supported by ArmNN
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000213 unsupportedOperators.insert(tfLiteRegistration->builtin_code);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100214 continue;
215 }
216
217 nodesToDelegate->data[nodesToDelegate->size++] = nodeIndex;
218 }
219
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000220 for (std::set<int32_t>::iterator it=unsupportedOperators.begin(); it!=unsupportedOperators.end(); ++it)
221 {
222 TF_LITE_KERNEL_LOG(tfLiteContext,
223 "Operator %s [%d] is not supported by armnn_delegate.",
224 tflite::EnumNameBuiltinOperator(tflite::BuiltinOperator(*it)),
225 *it);
226 }
227
Sadik Armaganca565c12022-08-16 12:17:24 +0100228 if (!unsupportedOperators.empty() && m_Options.TfLiteRuntimeFallbackDisabled())
229 {
230 std::stringstream exMessage;
231 exMessage << "TfLiteArmnnDelegate: There are unsupported operators in the model. ";
232 exMessage << "Not falling back to TfLite Runtime as fallback is disabled. ";
233 exMessage << "This should only be disabled under test conditions.";
234 throw armnn::Exception(exMessage.str());
235 }
236
Sadik Armagan62483be2020-10-23 17:14:43 +0100237 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100238 return nodesToDelegate;
239}
240
241TfLiteDelegate* Delegate::GetDelegate()
242{
243 return &m_Delegate;
244}
245
Matthew Sloyanac001ee2021-02-03 10:43:04 +0000246const std::string Delegate::GetVersion()
247{
248 return DELEGATE_VERSION;
249}
250
Sadik Armagan62483be2020-10-23 17:14:43 +0100251TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
252 TfLiteContext* tfLiteContext,
253 const TfLiteIntArray* inputs,
254 std::vector<armnn::BindingPointInfo>& inputBindings)
255{
Finn Williams6f9f9902020-11-13 13:23:15 +0000256 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100257 for (unsigned int i = 0; i < numInputs; ++i)
258 {
259 const int32_t tensorId = inputs->data[i];
260 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000261 // Do not create bindings for constant inputs
262 if (tensor.allocation_type == kTfLiteMmapRo)
263 {
264 continue;
265 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100266
267 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
268 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
269
270 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
271 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
272 outputSlot.SetTensorInfo(tensorInfo);
273
274 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000275 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100276
Sadik Armagan6e36a642020-11-10 21:18:41 +0000277 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100278 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000279
Sadik Armagan62483be2020-10-23 17:14:43 +0100280 return kTfLiteOk;
281}
282
283TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
284 TfLiteContext* tfLiteContext,
285 const TfLiteIntArray* outputs,
286 std::vector<armnn::BindingPointInfo>& outputBindings)
287{
Finn Williams6f9f9902020-11-13 13:23:15 +0000288 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100289 for (unsigned int i = 0; i < numOutputs; ++i)
290 {
291 const int32_t tensorId = outputs->data[i];
292 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
293
294 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
295 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
296
297 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Finn Williams6f9f9902020-11-13 13:23:15 +0000298 ARMNN_ASSERT(delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] != nullptr);
299 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100300 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
301 }
302
303 return kTfLiteOk;
304}
305
Sadik Armagan3c24f432020-10-19 17:35:30 +0100306ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
307 const TfLiteDelegateParams* parameters,
308 const Delegate* delegate)
309{
Jan Eilers17d34da2021-12-08 16:15:12 +0000310 const auto startTime = armnn::GetTimeNow();
311 ARMNN_LOG(info) << "ArmnnSubgraph creation";
312
Sadik Armagan3c24f432020-10-19 17:35:30 +0100313 TfLiteIntArray* executionPlan;
314 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
315 {
316 return nullptr;
317 }
318
Sadik Armagan62483be2020-10-23 17:14:43 +0100319 // Initialize DelegateData holds network and output slots information
320 DelegateData delegateData(delegate->m_Options.GetBackends());
321
322 // Build ArmNN Network
Mike Kelly80512b02022-05-16 23:10:42 +0100323 armnn::NetworkOptions networkOptions = delegate->m_Options.GetOptimizerOptions().m_ModelOptions;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100324 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100325 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100326
Sadik Armagan6e36a642020-11-10 21:18:41 +0000327 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
328
Sadik Armagan62483be2020-10-23 17:14:43 +0100329 std::vector<armnn::BindingPointInfo> inputBindings;
330 std::vector<armnn::BindingPointInfo> outputBindings;
331
332 // Add input layer
333 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
334 if (status != kTfLiteOk)
335 {
336 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
337 }
338
339 // Parse TfLite delegate nodes to ArmNN
Jan Eilers17d34da2021-12-08 16:15:12 +0000340 const auto parseStartTime = armnn::GetTimeNow();
Sadik Armagan3c24f432020-10-19 17:35:30 +0100341 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
342 {
343 const int nodeIndex = parameters->nodes_to_replace->data[i];
344
345 TfLiteNode* tfLiteNode = nullptr;
346 TfLiteRegistration* tfLiteRegistration = nullptr;
347 if (tfLiteContext->GetNodeAndRegistration(
348 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
349 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000350 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100351 }
352
Sadik Armagan62483be2020-10-23 17:14:43 +0100353 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100354 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000355 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100356 }
357 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000358 ARMNN_LOG(info) << "Parse nodes to ArmNN time: " << std::setprecision(2)
359 << std::fixed << armnn::GetTimeDuration(parseStartTime).count() << " ms";
Sadik Armagan3c24f432020-10-19 17:35:30 +0100360
Sadik Armagan62483be2020-10-23 17:14:43 +0100361 // Add Output layer
362 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
363 if (status != kTfLiteOk)
364 {
365 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
366 }
367
368 // Optimize ArmNN network
369 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
370 try
371 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000372 const auto optimizeStartTime = armnn::GetTimeNow();
Sadik Armagan6e36a642020-11-10 21:18:41 +0000373 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100374 delegate->m_Options.GetBackends(),
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000375 delegate->m_Runtime->GetDeviceSpec(),
376 delegate->m_Options.GetOptimizerOptions());
Jan Eilers17d34da2021-12-08 16:15:12 +0000377 ARMNN_LOG(info) << "Optimize ArmnnSubgraph time: " << std::setprecision(2)
378 << std::fixed << armnn::GetTimeDuration(optimizeStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100379 }
380 catch (std::exception &ex)
381 {
382 std::stringstream exMessage;
383 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
384 throw armnn::Exception(exMessage.str());
385 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100386 if (!optNet)
387 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100388 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100389 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
390 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100391
Colm Donelan3e32a872021-10-04 22:55:37 +0100392 // If set, we will serialize the optimized model into a dot file.
393 const std::string serializeToDotFile = delegate->m_Options.GetSerializeToDot();
394 if (!serializeToDotFile.empty())
395 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000396 ARMNN_LOG(info) << "Writing graph to dot file: " << serializeToDotFile;
Colm Donelan3e32a872021-10-04 22:55:37 +0100397 fs::path filename = serializeToDotFile;
398 std::fstream file(filename.c_str(), std::ios_base::out);
399 optNet->SerializeToDot(file);
400 }
401
Sadik Armagan62483be2020-10-23 17:14:43 +0100402 try
403 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000404 const auto loadStartTime = armnn::GetTimeNow();
405
Sadik Armagan62483be2020-10-23 17:14:43 +0100406 // Load graph into runtime
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000407 std::string errorMessage;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000408 armnn::Status loadingStatus;
Francis Murtagh626bd902022-06-21 13:16:23 +0000409 armnn::MemorySource inputSource = armnn::MemorySource::Undefined;
410 armnn::MemorySource outputSource = armnn::MemorySource::Undefined;
411 // There's a bit of an assumption here that the delegate will only support Malloc memory source.
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000412 if (delegate->m_Options.GetOptimizerOptions().m_ImportEnabled)
413 {
Francis Murtagh626bd902022-06-21 13:16:23 +0000414 inputSource = armnn::MemorySource::Malloc;
415 }
416 if (delegate->m_Options.GetOptimizerOptions().m_ExportEnabled)
417 {
418 outputSource = armnn::MemorySource::Malloc;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000419 }
Colm Donelan3e32a872021-10-04 22:55:37 +0100420 armnn::INetworkProperties networkProperties(false,
Francis Murtagh626bd902022-06-21 13:16:23 +0000421 inputSource,
422 outputSource,
Colm Donelan3e32a872021-10-04 22:55:37 +0100423 delegate->m_Options.GetInternalProfilingState(),
424 delegate->m_Options.GetInternalProfilingDetail());
425 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
426 std::move(optNet),
427 errorMessage,
428 networkProperties);
Sadik Armagan62483be2020-10-23 17:14:43 +0100429 if (loadingStatus != armnn::Status::Success)
430 {
Colm Donelan45142282021-10-21 23:39:52 +0100431 // Network load failed.
Colm Donelan194086f2022-11-14 17:23:07 +0000432 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded: " + errorMessage);
Sadik Armagan62483be2020-10-23 17:14:43 +0100433 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000434
435 ARMNN_LOG(info) << "Load ArmnnSubgraph time: " << std::setprecision(2)
436 << std::fixed << armnn::GetTimeDuration(loadStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100437 }
438 catch (std::exception& ex)
439 {
440 std::stringstream exMessage;
441 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
442 throw armnn::Exception(exMessage.str());
443 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100444
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000445 // Register debug callback function
446 if (delegate->m_Options.GetDebugCallbackFunction().has_value())
447 {
448 delegate->m_Runtime->RegisterDebugCallback(networkId, delegate->m_Options.GetDebugCallbackFunction().value());
449 }
450
Jan Eilers17d34da2021-12-08 16:15:12 +0000451 ARMNN_LOG(info) << "Overall ArmnnSubgraph creation time: " << std::setprecision(2)
452 << std::fixed << armnn::GetTimeDuration(startTime).count() << " ms\n";
453
Sadik Armagan3c24f432020-10-19 17:35:30 +0100454 // Create a new SubGraph with networkId and runtime
Sadik Armagan62483be2020-10-23 17:14:43 +0100455 return new ArmnnSubgraph(networkId, delegate->m_Runtime.get(), inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100456}
457
458TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
459{
Finn Williams6f9f9902020-11-13 13:23:15 +0000460 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100461 return kTfLiteOk;
462}
463
Sadik Armagan62483be2020-10-23 17:14:43 +0100464TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100465{
Sadik Armagan62483be2020-10-23 17:14:43 +0100466 // Prepare inputs
467 armnn::InputTensors inputTensors;
468 size_t inputIndex = 0;
469 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
470 {
471 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
472 if (tensor->allocation_type != kTfLiteMmapRo)
473 {
474 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100475 armnn::TensorInfo inputTensorInfo = inputBinding.second;
476 inputTensorInfo.SetConstant(true);
477 const armnn::ConstTensor inputTensor(inputTensorInfo, tensor->data.data);
Sadik Armagan62483be2020-10-23 17:14:43 +0100478 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100479
Sadik Armagan62483be2020-10-23 17:14:43 +0100480 ++inputIndex;
481 }
482 }
483
484 // Prepare outputs
485 armnn::OutputTensors outputTensors;
486 size_t outputIndex = 0;
487 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
488 {
489 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
490 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
491 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
492 outputTensors.emplace_back(outputIdx, outputTensor);
493
494 ++outputIndex;
495 }
496
497 // Run graph
498 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
Colm Donelan45142282021-10-21 23:39:52 +0100499 // The delegate holds its own Arm NN runtime so this is our last chance to print internal profiling data.
500 std::shared_ptr<armnn::IProfiler> profiler = m_Runtime->GetProfiler(m_NetworkId);
501 if (profiler && profiler->IsProfilingEnabled())
502 {
503 profiler->Print(std::cout);
504 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100505 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100506}
507
Sadik Armagan62483be2020-10-23 17:14:43 +0100508TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100509 TfLiteContext* tfLiteContext,
510 TfLiteRegistration* tfLiteRegistration,
511 TfLiteNode* tfLiteNode,
512 int nodeIndex)
513{
Sadik Armagan62483be2020-10-23 17:14:43 +0100514 switch (tfLiteRegistration->builtin_code)
515 {
Ryan OShead21abaf2022-06-10 14:49:11 +0100516 case kTfLiteBuiltinCustom:
517 {
518#if defined(ARMNN_POST_TFLITE_2_5)
519 // Custom operators are defined by the name rather than the builtin code.
520 // Parse the custom_name param in the registration to point to the correct visitor function.
521 std::string customOperatorName = tfLiteRegistration->custom_name;
522 if ( customOperatorName == "AveragePool3D" )
523 {
524 return VisitPooling3dOperator(delegateData,
525 tfLiteContext,
526 tfLiteNode,
527 nodeIndex,
528 customOperatorName);
529 }
530 else if (customOperatorName == "MaxPool3D")
531 {
532 return VisitPooling3dOperator(delegateData,
533 tfLiteContext,
534 tfLiteNode,
535 nodeIndex,
536 customOperatorName);
537 }
538#endif
539 // Invalid or unsupported custom operator
540 return kTfLiteError;
541 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100542 case kTfLiteBuiltinAbs:
543 return VisitElementwiseUnaryOperator(delegateData,
544 tfLiteContext,
545 tfLiteNode,
546 nodeIndex,
547 armnn::UnaryOperation::Abs);
548 case kTfLiteBuiltinAdd:
549 return VisitElementwiseBinaryOperator(delegateData,
550 tfLiteContext,
551 tfLiteNode,
552 nodeIndex,
553 kTfLiteBuiltinAdd);
554 case kTfLiteBuiltinArgMax:
555 return VisitArgMinMaxOperator(delegateData,
556 tfLiteContext,
557 tfLiteNode,
558 nodeIndex,
559 kTfLiteBuiltinArgMax);
560 case kTfLiteBuiltinArgMin:
561 return VisitArgMinMaxOperator(delegateData,
562 tfLiteContext,
563 tfLiteNode,
564 nodeIndex,
565 kTfLiteBuiltinArgMin);
566 case kTfLiteBuiltinAveragePool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100567 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100568 tfLiteContext,
569 tfLiteNode,
570 nodeIndex,
571 kTfLiteBuiltinAveragePool2d);
Ryan OShea49ed0df2022-09-21 16:09:41 +0100572 case kTfLiteBuiltinBatchMatmul:
573 return VisitBatchMatMulOperator(delegateData,
574 tfLiteContext,
575 tfLiteNode,
576 nodeIndex,
577 kTfLiteBuiltinBatchMatmul);
Sadik Armagan62483be2020-10-23 17:14:43 +0100578 case kTfLiteBuiltinBatchToSpaceNd:
579 return VisitBatchToSpaceNdOperator(delegateData,
580 tfLiteContext,
581 tfLiteNode,
582 nodeIndex,
583 kTfLiteBuiltinBatchToSpaceNd);
Sadik Armagan937565b2021-04-21 14:03:28 +0100584 case kTfLiteBuiltinCast:
585 return VisitCastOperator(delegateData,
586 tfLiteContext,
587 tfLiteNode,
588 nodeIndex,
589 kTfLiteBuiltinCast);
Sadik Armagan62483be2020-10-23 17:14:43 +0100590 case kTfLiteBuiltinConcatenation:
591 return VisitControlOperator(delegateData,
592 tfLiteContext,
593 tfLiteNode,
594 nodeIndex,
595 kTfLiteBuiltinConcatenation);
596 case kTfLiteBuiltinConv2d:
597 return VisitConvolutionOperator(delegateData,
598 tfLiteContext,
599 tfLiteNode,
600 nodeIndex,
601 kTfLiteBuiltinConv2d);
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100602// Conv3d is only correctly supported for external delegates from TF Lite v2.6, as there was a breaking bug in v2.5.
603#if defined(ARMNN_POST_TFLITE_2_5)
604 case kTfLiteBuiltinConv3d:
605 return VisitConvolutionOperator(delegateData,
606 tfLiteContext,
607 tfLiteNode,
608 nodeIndex,
609 kTfLiteBuiltinConv3d);
610#endif
Sadik Armagan62483be2020-10-23 17:14:43 +0100611 case kTfLiteBuiltinDepthToSpace:
612 return VisitDepthToSpaceOperator(delegateData,
613 tfLiteContext,
614 tfLiteNode,
615 nodeIndex,
616 kTfLiteBuiltinDepthToSpace);
617 case kTfLiteBuiltinDepthwiseConv2d:
618 return VisitConvolutionOperator(delegateData,
619 tfLiteContext,
620 tfLiteNode,
621 nodeIndex,
622 kTfLiteBuiltinDepthwiseConv2d);
623 case kTfLiteBuiltinDequantize:
624 return VisitDequantizeOperator(delegateData,
625 tfLiteContext,
626 tfLiteNode,
627 nodeIndex,
628 kTfLiteBuiltinDequantize);
629 case kTfLiteBuiltinDiv:
630 return VisitElementwiseBinaryOperator(delegateData,
631 tfLiteContext,
632 tfLiteNode,
633 nodeIndex,
634 kTfLiteBuiltinDiv);
635 case kTfLiteBuiltinElu:
636 return VisitActivationOperator(delegateData,
637 tfLiteContext,
638 tfLiteNode,
639 nodeIndex,
640 kTfLiteBuiltinElu);
641 case kTfLiteBuiltinEqual:
642 return VisitComparisonOperator(delegateData,
643 tfLiteContext,
644 tfLiteNode,
645 nodeIndex,
646 kTfLiteBuiltinEqual);
647 case kTfLiteBuiltinExp:
648 return VisitElementwiseUnaryOperator(delegateData,
649 tfLiteContext,
650 tfLiteNode,
651 nodeIndex,
652 armnn::UnaryOperation::Exp);
653 case kTfLiteBuiltinExpandDims:
654 return VisitExpandDimsOperator(delegateData,
655 tfLiteContext,
656 tfLiteNode,
657 nodeIndex,
658 kTfLiteBuiltinExpandDims);
659 case kTfLiteBuiltinFill:
660 return VisitFillOperator(delegateData,
661 tfLiteContext,
662 tfLiteNode,
663 nodeIndex,
664 kTfLiteBuiltinFill);
665 case kTfLiteBuiltinFloor:
666 return VisitFloorOperator(delegateData,
667 tfLiteContext,
668 tfLiteNode,
669 nodeIndex,
670 kTfLiteBuiltinFloor);
Jim Flynn4b2f3472021-10-13 21:20:07 +0100671 case kTfLiteBuiltinFloorDiv:
672 return VisitElementwiseBinaryOperator(delegateData,
673 tfLiteContext,
674 tfLiteNode,
675 nodeIndex,
676 kTfLiteBuiltinFloorDiv);
Sadik Armagan62483be2020-10-23 17:14:43 +0100677 case kTfLiteBuiltinFullyConnected:
678 return VisitFullyConnectedOperator(delegateData,
679 tfLiteContext,
680 tfLiteNode,
681 nodeIndex,
682 kTfLiteBuiltinFullyConnected);
683 case kTfLiteBuiltinGather:
684 return VisitGatherOperator(delegateData,
685 tfLiteContext,
686 tfLiteNode,
687 nodeIndex,
688 kTfLiteBuiltinGather);
Teresa Charlind5c0ed22022-04-25 18:23:41 +0100689 case kTfLiteBuiltinGatherNd:
690 return VisitGatherNdOperator(delegateData,
691 tfLiteContext,
692 tfLiteNode,
693 nodeIndex,
694 kTfLiteBuiltinGatherNd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100695 case kTfLiteBuiltinGreater:
696 return VisitComparisonOperator(delegateData,
697 tfLiteContext,
698 tfLiteNode,
699 nodeIndex,
700 kTfLiteBuiltinGreater);
701 case kTfLiteBuiltinGreaterEqual:
702 return VisitComparisonOperator(delegateData,
703 tfLiteContext,
704 tfLiteNode,
705 nodeIndex,
706 kTfLiteBuiltinGreaterEqual);
707 case kTfLiteBuiltinHardSwish:
708 return VisitActivationOperator(delegateData,
709 tfLiteContext,
710 tfLiteNode,
711 nodeIndex,
712 kTfLiteBuiltinHardSwish);
713 case kTfLiteBuiltinL2Normalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000714 return VisitL2NormalizationOperator(delegateData,
715 tfLiteContext,
716 tfLiteNode,
717 nodeIndex,
718 kTfLiteBuiltinL2Normalization);
Sadik Armagan62483be2020-10-23 17:14:43 +0100719 case kTfLiteBuiltinL2Pool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100720 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100721 tfLiteContext,
722 tfLiteNode,
723 nodeIndex,
724 kTfLiteBuiltinL2Pool2d);
725 case kTfLiteBuiltinLess:
726 return VisitComparisonOperator(delegateData,
727 tfLiteContext,
728 tfLiteNode,
729 nodeIndex,
730 kTfLiteBuiltinLess);
731 case kTfLiteBuiltinLessEqual:
732 return VisitComparisonOperator(delegateData,
733 tfLiteContext,
734 tfLiteNode,
735 nodeIndex,
736 kTfLiteBuiltinLessEqual);
737 case kTfLiteBuiltinLocalResponseNormalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000738 return VisitLocalResponseNormalizationOperator(delegateData,
739 tfLiteContext,
740 tfLiteNode,
741 nodeIndex,
742 kTfLiteBuiltinLocalResponseNormalization);
Teresa Charlinb1f5f702022-07-12 14:16:24 +0100743 case kTfLiteBuiltinLog:
744 return VisitElementwiseUnaryOperator(delegateData,
745 tfLiteContext,
746 tfLiteNode,
747 nodeIndex,
748 armnn::UnaryOperation::Log);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000749 case kTfLiteBuiltinLogicalAnd:
750 return VisitLogicalBinaryOperator(delegateData,
751 tfLiteContext,
752 tfLiteNode,
753 nodeIndex,
754 kTfLiteBuiltinLogicalAnd,
755 armnn::LogicalBinaryOperation::LogicalAnd);
756 case kTfLiteBuiltinLogicalNot:
757 return VisitElementwiseUnaryOperator(delegateData,
758 tfLiteContext,
759 tfLiteNode,
760 nodeIndex,
761 armnn::UnaryOperation::LogicalNot);
762 case kTfLiteBuiltinLogicalOr:
763 return VisitLogicalBinaryOperator(delegateData,
764 tfLiteContext,
765 tfLiteNode,
766 nodeIndex,
767 kTfLiteBuiltinLogicalOr,
768 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100769 case kTfLiteBuiltinLogistic:
770 return VisitActivationOperator(delegateData,
771 tfLiteContext,
772 tfLiteNode,
773 nodeIndex,
774 kTfLiteBuiltinLogistic);
775 case kTfLiteBuiltinLogSoftmax:
776 return VisitSoftmaxOperator(delegateData,
777 tfLiteContext,
778 tfLiteNode,
779 nodeIndex,
780 kTfLiteBuiltinLogSoftmax);
781 case kTfLiteBuiltinLstm:
782 return VisitLstmOperator(delegateData,
783 tfLiteContext,
784 tfLiteNode,
785 nodeIndex,
786 kTfLiteBuiltinLstm);
787 case kTfLiteBuiltinMaxPool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100788 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100789 tfLiteContext,
790 tfLiteNode,
791 nodeIndex,
792 kTfLiteBuiltinMaxPool2d);
793 case kTfLiteBuiltinMaximum:
794 return VisitElementwiseBinaryOperator(delegateData,
795 tfLiteContext,
796 tfLiteNode,
797 nodeIndex,
798 kTfLiteBuiltinMaximum);
799 case kTfLiteBuiltinMean:
800 return VisitControlOperator(delegateData,
801 tfLiteContext,
802 tfLiteNode,
803 nodeIndex,
804 kTfLiteBuiltinMean);
805 case kTfLiteBuiltinMinimum:
806 return VisitElementwiseBinaryOperator(delegateData,
807 tfLiteContext,
808 tfLiteNode,
809 nodeIndex,
810 kTfLiteBuiltinMinimum);
Matthew Sloyanaf3a4ef2021-10-22 15:48:12 +0100811 case kTfLiteBuiltinMirrorPad:
812 return VisitPadOperator(delegateData,
813 tfLiteContext,
814 tfLiteNode,
815 nodeIndex,
816 kTfLiteBuiltinMirrorPad);
Sadik Armagan62483be2020-10-23 17:14:43 +0100817 case kTfLiteBuiltinMul:
818 return VisitElementwiseBinaryOperator(delegateData,
819 tfLiteContext,
820 tfLiteNode,
821 nodeIndex,
822 kTfLiteBuiltinMul);
823 case kTfLiteBuiltinNeg:
824 return VisitElementwiseUnaryOperator(delegateData,
825 tfLiteContext,
826 tfLiteNode,
827 nodeIndex,
828 armnn::UnaryOperation::Neg);
829 case kTfLiteBuiltinNotEqual:
830 return VisitComparisonOperator(delegateData,
831 tfLiteContext,
832 tfLiteNode,
833 nodeIndex,
834 kTfLiteBuiltinNotEqual);
Matthew Sloyana7a12f52021-05-06 10:05:28 +0100835 case kTfLiteBuiltinPack:
836 return VisitPackOperator(delegateData,
837 tfLiteContext,
838 tfLiteNode,
839 nodeIndex,
840 kTfLiteBuiltinPack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100841 case kTfLiteBuiltinPad:
842 return VisitPadOperator(delegateData,
843 tfLiteContext,
844 tfLiteNode,
845 nodeIndex,
846 kTfLiteBuiltinPad);
847 case kTfLiteBuiltinPadv2:
848 return VisitPadOperator(delegateData,
849 tfLiteContext,
850 tfLiteNode,
851 nodeIndex,
852 kTfLiteBuiltinPadv2);
853 case kTfLiteBuiltinPrelu:
James Conroy39825482021-05-27 17:44:50 +0100854 return VisitPreluOperator(delegateData,
855 tfLiteContext,
856 tfLiteNode,
857 nodeIndex,
858 kTfLiteBuiltinPrelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100859 case kTfLiteBuiltinQuantize:
860 return VisitQuantizeOperator(delegateData,
861 tfLiteContext,
862 tfLiteNode,
863 nodeIndex,
864 kTfLiteBuiltinQuantize);
865 case kTfLiteBuiltinRank:
866 return VisitControlOperator(delegateData,
867 tfLiteContext,
868 tfLiteNode,
869 nodeIndex,
870 kTfLiteBuiltinRank);
Sadik Armagana2747482021-02-09 10:28:54 +0000871 case kTfLiteBuiltinReduceMax:
872 return VisitReduceOperator(delegateData,
873 tfLiteContext,
874 tfLiteNode,
875 nodeIndex,
876 kTfLiteBuiltinReduceMax);
877 case kTfLiteBuiltinReduceMin:
878 return VisitReduceOperator(delegateData,
879 tfLiteContext,
880 tfLiteNode,
881 nodeIndex,
882 kTfLiteBuiltinReduceMin);
Teresa Charlin4e3e8312021-08-05 12:34:37 +0100883 case kTfLiteBuiltinReduceProd:
884 return VisitReduceOperator(delegateData,
885 tfLiteContext,
886 tfLiteNode,
887 nodeIndex,
888 kTfLiteBuiltinReduceProd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100889 case kTfLiteBuiltinRelu:
890 return VisitActivationOperator(delegateData,
891 tfLiteContext,
892 tfLiteNode,
893 nodeIndex,
894 kTfLiteBuiltinRelu);
895 case kTfLiteBuiltinReluN1To1:
896 return VisitActivationOperator(delegateData,
897 tfLiteContext,
898 tfLiteNode,
899 nodeIndex,
900 kTfLiteBuiltinReluN1To1);
901 case kTfLiteBuiltinRelu6:
902 return VisitActivationOperator(delegateData,
903 tfLiteContext,
904 tfLiteNode,
905 nodeIndex,
906 kTfLiteBuiltinRelu6);
907 case kTfLiteBuiltinReshape:
908 return VisitReshapeOperator(delegateData,
909 tfLiteContext,
910 tfLiteNode,
911 nodeIndex,
912 kTfLiteBuiltinReshape);
913 case kTfLiteBuiltinResizeBilinear:
914 return VisitResizeOperator(delegateData,
915 tfLiteContext,
916 tfLiteNode,
917 nodeIndex,
918 kTfLiteBuiltinResizeBilinear);
919 case kTfLiteBuiltinResizeNearestNeighbor:
920 return VisitResizeOperator(delegateData,
921 tfLiteContext,
922 tfLiteNode,
923 nodeIndex,
924 kTfLiteBuiltinResizeNearestNeighbor);
925 case kTfLiteBuiltinRsqrt:
926 return VisitElementwiseUnaryOperator(delegateData,
927 tfLiteContext,
928 tfLiteNode,
929 nodeIndex,
930 armnn::UnaryOperation::Rsqrt);
Keith Davis0176fd82021-06-01 17:36:32 +0100931 case kTfLiteBuiltinShape:
932 return VisitShapeOperator(delegateData,
933 tfLiteContext,
934 tfLiteNode,
935 nodeIndex,
936 kTfLiteBuiltinShape);
Teresa Charlinb1f5f702022-07-12 14:16:24 +0100937 case kTfLiteBuiltinSin:
938 return VisitElementwiseUnaryOperator(delegateData,
939 tfLiteContext,
940 tfLiteNode,
941 nodeIndex,
942 armnn::UnaryOperation::Sin);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +0000943 case kTfLiteBuiltinSplit:
944 return VisitSplitOperator(delegateData,
945 tfLiteContext,
946 tfLiteNode,
947 nodeIndex,
948 kTfLiteBuiltinSplit);
949 case kTfLiteBuiltinSplitV:
950 return VisitSplitVOperator(delegateData,
951 tfLiteContext,
952 tfLiteNode,
953 nodeIndex,
954 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +0100955 case kTfLiteBuiltinSqrt:
956 return VisitElementwiseUnaryOperator(delegateData,
957 tfLiteContext,
958 tfLiteNode,
959 nodeIndex,
960 armnn::UnaryOperation::Sqrt);
961 case kTfLiteBuiltinSqueeze:
962 return VisitSqueezeOperator(delegateData,
963 tfLiteContext,
964 tfLiteNode,
965 nodeIndex,
966 kTfLiteBuiltinSqueeze);
Cathal Corbett839b9322022-11-18 08:52:18 +0000967 case kTfLiteBuiltinSlice:
Sadik Armagan62483be2020-10-23 17:14:43 +0100968 return VisitSliceOperator(delegateData,
969 tfLiteContext,
970 tfLiteNode,
971 nodeIndex,
Cathal Corbett839b9322022-11-18 08:52:18 +0000972 kTfLiteBuiltinSlice);
973 case kTfLiteBuiltinStridedSlice:
974 return VisitStridedSliceOperator(delegateData,
975 tfLiteContext,
976 tfLiteNode,
977 nodeIndex,
978 kTfLiteBuiltinStridedSlice);
Sadik Armagana2747482021-02-09 10:28:54 +0000979 case kTfLiteBuiltinSum:
980 return VisitReduceOperator(delegateData,
981 tfLiteContext,
982 tfLiteNode,
983 nodeIndex,
984 kTfLiteBuiltinSum);
Sadik Armagan62483be2020-10-23 17:14:43 +0100985 case kTfLiteBuiltinTranspose:
986 return VisitTransposeOperator(delegateData,
987 tfLiteContext,
988 tfLiteNode,
989 nodeIndex,
990 kTfLiteBuiltinTranspose);
991 case kTfLiteBuiltinTransposeConv:
992 return VisitConvolutionOperator(delegateData,
993 tfLiteContext,
994 tfLiteNode,
995 nodeIndex,
996 kTfLiteBuiltinTransposeConv);
997 case kTfLiteBuiltinSoftmax:
998 return VisitSoftmaxOperator(delegateData,
999 tfLiteContext,
1000 tfLiteNode,
1001 nodeIndex,
1002 kTfLiteBuiltinSoftmax);
1003 case kTfLiteBuiltinSpaceToBatchNd:
1004 return VisitSpaceToBatchNdOperator(delegateData,
1005 tfLiteContext,
1006 tfLiteNode,
1007 nodeIndex,
1008 kTfLiteBuiltinSpaceToBatchNd);
1009 case kTfLiteBuiltinSpaceToDepth:
1010 return VisitSpaceToDepthOperator(delegateData,
1011 tfLiteContext,
1012 tfLiteNode,
1013 nodeIndex,
1014 kTfLiteBuiltinSpaceToDepth);
1015 case kTfLiteBuiltinSub:
1016 return VisitElementwiseBinaryOperator(delegateData,
1017 tfLiteContext,
1018 tfLiteNode,
1019 nodeIndex,
1020 kTfLiteBuiltinSub);
1021 case kTfLiteBuiltinTanh:
1022 return VisitActivationOperator(delegateData,
1023 tfLiteContext,
1024 tfLiteNode,
1025 nodeIndex,
1026 kTfLiteBuiltinTanh);
Narumol Prangnawarat7684b182021-08-12 14:48:15 +01001027 case kTfLiteBuiltinUnidirectionalSequenceLstm:
1028 return VisitUnidirectionalSequenceLstmOperator(delegateData,
1029 tfLiteContext,
1030 tfLiteNode,
1031 nodeIndex,
1032 kTfLiteBuiltinUnidirectionalSequenceLstm);
Kevin May8ab2d7a2021-05-07 09:32:51 +01001033 case kTfLiteBuiltinUnpack:
1034 return VisitUnpackOperator(delegateData,
1035 tfLiteContext,
1036 tfLiteNode,
1037 nodeIndex,
1038 kTfLiteBuiltinUnpack);
Sadik Armagan62483be2020-10-23 17:14:43 +01001039 default:
1040 return kTfLiteError;
1041 }
Sadik Armagan3c24f432020-10-19 17:35:30 +01001042}
1043
1044} // armnnDelegate namespace