blob: 1b6d68eb7a17ce14a6e9eaef04ed2631e74ef5ac [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 Armagan62483be2020-10-23 17:14:43 +0100225 std::sort(&nodesToDelegate->data[0], &nodesToDelegate->data[nodesToDelegate->size]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100226 return nodesToDelegate;
227}
228
229TfLiteDelegate* Delegate::GetDelegate()
230{
231 return &m_Delegate;
232}
233
Matthew Sloyanac001ee2021-02-03 10:43:04 +0000234const std::string Delegate::GetVersion()
235{
236 return DELEGATE_VERSION;
237}
238
Sadik Armagan62483be2020-10-23 17:14:43 +0100239TfLiteStatus ArmnnSubgraph::AddInputLayer(DelegateData& delegateData,
240 TfLiteContext* tfLiteContext,
241 const TfLiteIntArray* inputs,
242 std::vector<armnn::BindingPointInfo>& inputBindings)
243{
Finn Williams6f9f9902020-11-13 13:23:15 +0000244 const size_t numInputs = static_cast<size_t>(inputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100245 for (unsigned int i = 0; i < numInputs; ++i)
246 {
247 const int32_t tensorId = inputs->data[i];
248 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
Sadik Armagan6e36a642020-11-10 21:18:41 +0000249 // Do not create bindings for constant inputs
250 if (tensor.allocation_type == kTfLiteMmapRo)
251 {
252 continue;
253 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100254
255 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
256 armnn::IConnectableLayer* layer = delegateData.m_Network->AddInputLayer(bindingId);
257
258 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
259 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
260 outputSlot.SetTensorInfo(tensorInfo);
261
262 // Store for creating connections
Finn Williams6f9f9902020-11-13 13:23:15 +0000263 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] = &outputSlot;
Sadik Armagan62483be2020-10-23 17:14:43 +0100264
Sadik Armagan6e36a642020-11-10 21:18:41 +0000265 inputBindings.push_back(std::make_pair(bindingId, tensorInfo));
Sadik Armagan62483be2020-10-23 17:14:43 +0100266 }
Sadik Armagan6e36a642020-11-10 21:18:41 +0000267
Sadik Armagan62483be2020-10-23 17:14:43 +0100268 return kTfLiteOk;
269}
270
271TfLiteStatus ArmnnSubgraph::AddOutputLayer(DelegateData& delegateData,
272 TfLiteContext* tfLiteContext,
273 const TfLiteIntArray* outputs,
274 std::vector<armnn::BindingPointInfo>& outputBindings)
275{
Finn Williams6f9f9902020-11-13 13:23:15 +0000276 const size_t numOutputs = static_cast<size_t>(outputs->size);
Sadik Armagan62483be2020-10-23 17:14:43 +0100277 for (unsigned int i = 0; i < numOutputs; ++i)
278 {
279 const int32_t tensorId = outputs->data[i];
280 const TfLiteTensor tensor = tfLiteContext->tensors[tensorId];
281
282 auto bindingId = static_cast<armnn::LayerBindingId>((tensorId));
283 armnn::IConnectableLayer* layer = delegateData.m_Network->AddOutputLayer(bindingId);
284
285 auto tensorInfo = GetTensorInfoForTfLiteTensor(tensor);
Finn Williams6f9f9902020-11-13 13:23:15 +0000286 ARMNN_ASSERT(delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)] != nullptr);
287 delegateData.m_OutputSlotForNode[static_cast<unsigned long>(tensorId)]->Connect(layer->GetInputSlot(0));
Sadik Armagan62483be2020-10-23 17:14:43 +0100288 outputBindings.push_back(std::make_pair(bindingId, tensorInfo));
289 }
290
291 return kTfLiteOk;
292}
293
Sadik Armagan3c24f432020-10-19 17:35:30 +0100294ArmnnSubgraph* ArmnnSubgraph::Create(TfLiteContext* tfLiteContext,
295 const TfLiteDelegateParams* parameters,
296 const Delegate* delegate)
297{
Jan Eilers17d34da2021-12-08 16:15:12 +0000298 const auto startTime = armnn::GetTimeNow();
299 ARMNN_LOG(info) << "ArmnnSubgraph creation";
300
Sadik Armagan3c24f432020-10-19 17:35:30 +0100301 TfLiteIntArray* executionPlan;
302 if (tfLiteContext->GetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk)
303 {
304 return nullptr;
305 }
306
Sadik Armagan62483be2020-10-23 17:14:43 +0100307 // Initialize DelegateData holds network and output slots information
308 DelegateData delegateData(delegate->m_Options.GetBackends());
309
310 // Build ArmNN Network
Mike Kelly80512b02022-05-16 23:10:42 +0100311 armnn::NetworkOptions networkOptions = delegate->m_Options.GetOptimizerOptions().m_ModelOptions;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100312 armnn::NetworkId networkId;
Sadik Armagan62483be2020-10-23 17:14:43 +0100313 delegateData.m_Network = armnn::INetwork::Create(networkOptions);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100314
Sadik Armagan6e36a642020-11-10 21:18:41 +0000315 delegateData.m_OutputSlotForNode = std::vector<armnn::IOutputSlot*>(tfLiteContext->tensors_size, nullptr);
316
Sadik Armagan62483be2020-10-23 17:14:43 +0100317 std::vector<armnn::BindingPointInfo> inputBindings;
318 std::vector<armnn::BindingPointInfo> outputBindings;
319
320 // Add input layer
321 auto status = AddInputLayer(delegateData, tfLiteContext, parameters->input_tensors, inputBindings);
322 if (status != kTfLiteOk)
323 {
324 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Inputs to the network!");
325 }
326
327 // Parse TfLite delegate nodes to ArmNN
Jan Eilers17d34da2021-12-08 16:15:12 +0000328 const auto parseStartTime = armnn::GetTimeNow();
Sadik Armagan3c24f432020-10-19 17:35:30 +0100329 for (int i = 0; i < parameters->nodes_to_replace->size; ++i)
330 {
331 const int nodeIndex = parameters->nodes_to_replace->data[i];
332
333 TfLiteNode* tfLiteNode = nullptr;
334 TfLiteRegistration* tfLiteRegistration = nullptr;
335 if (tfLiteContext->GetNodeAndRegistration(
336 tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk)
337 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000338 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to get node registration: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100339 }
340
Sadik Armagan62483be2020-10-23 17:14:43 +0100341 if (VisitNode(delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex) != kTfLiteOk)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100342 {
Finn Williams6f9f9902020-11-13 13:23:15 +0000343 throw armnn::Exception(&"TfLiteArmnnDelegate: Unable to parse node: " [ nodeIndex]);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100344 }
345 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000346 ARMNN_LOG(info) << "Parse nodes to ArmNN time: " << std::setprecision(2)
347 << std::fixed << armnn::GetTimeDuration(parseStartTime).count() << " ms";
Sadik Armagan3c24f432020-10-19 17:35:30 +0100348
Sadik Armagan62483be2020-10-23 17:14:43 +0100349 // Add Output layer
350 status = AddOutputLayer(delegateData, tfLiteContext, parameters->output_tensors, outputBindings);
351 if (status != kTfLiteOk)
352 {
353 throw armnn::Exception("TfLiteArmnnDelegate: Unable to add Outputs to the network!");
354 }
355
356 // Optimize ArmNN network
357 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
358 try
359 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000360 const auto optimizeStartTime = armnn::GetTimeNow();
Sadik Armagan6e36a642020-11-10 21:18:41 +0000361 optNet = armnn::Optimize(*(delegateData.m_Network.get()),
Sadik Armagan62483be2020-10-23 17:14:43 +0100362 delegate->m_Options.GetBackends(),
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000363 delegate->m_Runtime->GetDeviceSpec(),
364 delegate->m_Options.GetOptimizerOptions());
Jan Eilers17d34da2021-12-08 16:15:12 +0000365 ARMNN_LOG(info) << "Optimize ArmnnSubgraph time: " << std::setprecision(2)
366 << std::fixed << armnn::GetTimeDuration(optimizeStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100367 }
368 catch (std::exception &ex)
369 {
370 std::stringstream exMessage;
371 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from optimize.";
372 throw armnn::Exception(exMessage.str());
373 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100374 if (!optNet)
375 {
Sadik Armagan62483be2020-10-23 17:14:43 +0100376 // Optimize failed
Sadik Armagan3c24f432020-10-19 17:35:30 +0100377 throw armnn::Exception("TfLiteArmnnDelegate: Unable to optimize the network!");
378 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100379
Colm Donelan3e32a872021-10-04 22:55:37 +0100380 // If set, we will serialize the optimized model into a dot file.
381 const std::string serializeToDotFile = delegate->m_Options.GetSerializeToDot();
382 if (!serializeToDotFile.empty())
383 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000384 ARMNN_LOG(info) << "Writing graph to dot file: " << serializeToDotFile;
Colm Donelan3e32a872021-10-04 22:55:37 +0100385 fs::path filename = serializeToDotFile;
386 std::fstream file(filename.c_str(), std::ios_base::out);
387 optNet->SerializeToDot(file);
388 }
389
Sadik Armagan62483be2020-10-23 17:14:43 +0100390 try
391 {
Jan Eilers17d34da2021-12-08 16:15:12 +0000392 const auto loadStartTime = armnn::GetTimeNow();
393
Sadik Armagan62483be2020-10-23 17:14:43 +0100394 // Load graph into runtime
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000395 std::string errorMessage;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000396 armnn::Status loadingStatus;
Colm Donelan03bf98a2022-05-30 15:20:36 +0100397 armnn::MemorySource inputSource = armnn::MemorySource::Undefined;
398 armnn::MemorySource outputSource = armnn::MemorySource::Undefined;
399 // There's a bit of an assumption here that the delegate will only support Malloc memory source.
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000400 if (delegate->m_Options.GetOptimizerOptions().m_ImportEnabled)
401 {
Colm Donelan03bf98a2022-05-30 15:20:36 +0100402 inputSource = armnn::MemorySource::Malloc;
403 }
404 if (delegate->m_Options.GetOptimizerOptions().m_ExportEnabled)
405 {
406 outputSource = armnn::MemorySource::Malloc;
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000407 }
Colm Donelan3e32a872021-10-04 22:55:37 +0100408 armnn::INetworkProperties networkProperties(false,
Colm Donelan03bf98a2022-05-30 15:20:36 +0100409 inputSource,
410 outputSource,
Colm Donelan3e32a872021-10-04 22:55:37 +0100411 delegate->m_Options.GetInternalProfilingState(),
412 delegate->m_Options.GetInternalProfilingDetail());
413 loadingStatus = delegate->m_Runtime->LoadNetwork(networkId,
414 std::move(optNet),
415 errorMessage,
416 networkProperties);
Sadik Armagan62483be2020-10-23 17:14:43 +0100417 if (loadingStatus != armnn::Status::Success)
418 {
Colm Donelan45142282021-10-21 23:39:52 +0100419 // Network load failed.
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000420 throw armnn::Exception("TfLiteArmnnDelegate: Network could not be loaded:" + errorMessage);
Sadik Armagan62483be2020-10-23 17:14:43 +0100421 }
Jan Eilers17d34da2021-12-08 16:15:12 +0000422
423 ARMNN_LOG(info) << "Load ArmnnSubgraph time: " << std::setprecision(2)
424 << std::fixed << armnn::GetTimeDuration(loadStartTime).count() << " ms";
Sadik Armagan62483be2020-10-23 17:14:43 +0100425 }
426 catch (std::exception& ex)
427 {
428 std::stringstream exMessage;
429 exMessage << "TfLiteArmnnDelegate: Exception (" << ex.what() << ") caught from LoadNetwork.";
430 throw armnn::Exception(exMessage.str());
431 }
Sadik Armagan3c24f432020-10-19 17:35:30 +0100432
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000433 // Register debug callback function
434 if (delegate->m_Options.GetDebugCallbackFunction().has_value())
435 {
436 delegate->m_Runtime->RegisterDebugCallback(networkId, delegate->m_Options.GetDebugCallbackFunction().value());
437 }
438
Jan Eilers17d34da2021-12-08 16:15:12 +0000439 ARMNN_LOG(info) << "Overall ArmnnSubgraph creation time: " << std::setprecision(2)
440 << std::fixed << armnn::GetTimeDuration(startTime).count() << " ms\n";
441
Sadik Armagan3c24f432020-10-19 17:35:30 +0100442 // Create a new SubGraph with networkId and runtime
Sadik Armagan62483be2020-10-23 17:14:43 +0100443 return new ArmnnSubgraph(networkId, delegate->m_Runtime.get(), inputBindings, outputBindings);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100444}
445
446TfLiteStatus ArmnnSubgraph::Prepare(TfLiteContext* tfLiteContext)
447{
Finn Williams6f9f9902020-11-13 13:23:15 +0000448 armnn::IgnoreUnused(tfLiteContext);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100449 return kTfLiteOk;
450}
451
Sadik Armagan62483be2020-10-23 17:14:43 +0100452TfLiteStatus ArmnnSubgraph::Invoke(TfLiteContext* tfLiteContext, TfLiteNode* tfLiteNode)
Sadik Armagan3c24f432020-10-19 17:35:30 +0100453{
Sadik Armagan62483be2020-10-23 17:14:43 +0100454 // Prepare inputs
455 armnn::InputTensors inputTensors;
456 size_t inputIndex = 0;
457 for (auto inputIdx : tflite::TfLiteIntArrayView(tfLiteNode->inputs))
458 {
459 TfLiteTensor* tensor = &tfLiteContext->tensors[inputIdx];
460 if (tensor->allocation_type != kTfLiteMmapRo)
461 {
462 const armnn::BindingPointInfo& inputBinding = m_InputBindings[inputIndex];
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100463 armnn::TensorInfo inputTensorInfo = inputBinding.second;
464 inputTensorInfo.SetConstant(true);
465 const armnn::ConstTensor inputTensor(inputTensorInfo, tensor->data.data);
Sadik Armagan62483be2020-10-23 17:14:43 +0100466 inputTensors.emplace_back(inputIdx, inputTensor);
Sadik Armagan3c24f432020-10-19 17:35:30 +0100467
Sadik Armagan62483be2020-10-23 17:14:43 +0100468 ++inputIndex;
469 }
470 }
471
472 // Prepare outputs
473 armnn::OutputTensors outputTensors;
474 size_t outputIndex = 0;
475 for (auto outputIdx : tflite::TfLiteIntArrayView(tfLiteNode->outputs))
476 {
477 const armnn::BindingPointInfo& outputBinding = m_OutputBindings[outputIndex];
478 TfLiteTensor* tensor = &tfLiteContext->tensors[outputIdx];
479 const armnn::Tensor outputTensor(outputBinding.second, tensor->data.data);
480 outputTensors.emplace_back(outputIdx, outputTensor);
481
482 ++outputIndex;
483 }
484
485 // Run graph
486 auto status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
Colm Donelan45142282021-10-21 23:39:52 +0100487 // The delegate holds its own Arm NN runtime so this is our last chance to print internal profiling data.
488 std::shared_ptr<armnn::IProfiler> profiler = m_Runtime->GetProfiler(m_NetworkId);
489 if (profiler && profiler->IsProfilingEnabled())
490 {
491 profiler->Print(std::cout);
492 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100493 return (status == armnn::Status::Success) ? kTfLiteOk : kTfLiteError;
Sadik Armagan3c24f432020-10-19 17:35:30 +0100494}
495
Sadik Armagan62483be2020-10-23 17:14:43 +0100496TfLiteStatus ArmnnSubgraph::VisitNode(DelegateData& delegateData,
Sadik Armagan3c24f432020-10-19 17:35:30 +0100497 TfLiteContext* tfLiteContext,
498 TfLiteRegistration* tfLiteRegistration,
499 TfLiteNode* tfLiteNode,
500 int nodeIndex)
501{
Sadik Armagan62483be2020-10-23 17:14:43 +0100502 switch (tfLiteRegistration->builtin_code)
503 {
Ryan OShead21abaf2022-06-10 14:49:11 +0100504 case kTfLiteBuiltinCustom:
505 {
506#if defined(ARMNN_POST_TFLITE_2_5)
507 // Custom operators are defined by the name rather than the builtin code.
508 // Parse the custom_name param in the registration to point to the correct visitor function.
509 std::string customOperatorName = tfLiteRegistration->custom_name;
510 if ( customOperatorName == "AveragePool3D" )
511 {
512 return VisitPooling3dOperator(delegateData,
513 tfLiteContext,
514 tfLiteNode,
515 nodeIndex,
516 customOperatorName);
517 }
518 else if (customOperatorName == "MaxPool3D")
519 {
520 return VisitPooling3dOperator(delegateData,
521 tfLiteContext,
522 tfLiteNode,
523 nodeIndex,
524 customOperatorName);
525 }
526#endif
527 // Invalid or unsupported custom operator
528 return kTfLiteError;
529 }
Sadik Armagan62483be2020-10-23 17:14:43 +0100530 case kTfLiteBuiltinAbs:
531 return VisitElementwiseUnaryOperator(delegateData,
532 tfLiteContext,
533 tfLiteNode,
534 nodeIndex,
535 armnn::UnaryOperation::Abs);
536 case kTfLiteBuiltinAdd:
537 return VisitElementwiseBinaryOperator(delegateData,
538 tfLiteContext,
539 tfLiteNode,
540 nodeIndex,
541 kTfLiteBuiltinAdd);
542 case kTfLiteBuiltinArgMax:
543 return VisitArgMinMaxOperator(delegateData,
544 tfLiteContext,
545 tfLiteNode,
546 nodeIndex,
547 kTfLiteBuiltinArgMax);
548 case kTfLiteBuiltinArgMin:
549 return VisitArgMinMaxOperator(delegateData,
550 tfLiteContext,
551 tfLiteNode,
552 nodeIndex,
553 kTfLiteBuiltinArgMin);
554 case kTfLiteBuiltinAveragePool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100555 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100556 tfLiteContext,
557 tfLiteNode,
558 nodeIndex,
559 kTfLiteBuiltinAveragePool2d);
560 case kTfLiteBuiltinBatchToSpaceNd:
561 return VisitBatchToSpaceNdOperator(delegateData,
562 tfLiteContext,
563 tfLiteNode,
564 nodeIndex,
565 kTfLiteBuiltinBatchToSpaceNd);
Sadik Armagan937565b2021-04-21 14:03:28 +0100566 case kTfLiteBuiltinCast:
567 return VisitCastOperator(delegateData,
568 tfLiteContext,
569 tfLiteNode,
570 nodeIndex,
571 kTfLiteBuiltinCast);
Sadik Armagan62483be2020-10-23 17:14:43 +0100572 case kTfLiteBuiltinConcatenation:
573 return VisitControlOperator(delegateData,
574 tfLiteContext,
575 tfLiteNode,
576 nodeIndex,
577 kTfLiteBuiltinConcatenation);
578 case kTfLiteBuiltinConv2d:
579 return VisitConvolutionOperator(delegateData,
580 tfLiteContext,
581 tfLiteNode,
582 nodeIndex,
583 kTfLiteBuiltinConv2d);
Matthew Sloyan81ec9942021-10-12 10:26:30 +0100584// Conv3d is only correctly supported for external delegates from TF Lite v2.6, as there was a breaking bug in v2.5.
585#if defined(ARMNN_POST_TFLITE_2_5)
586 case kTfLiteBuiltinConv3d:
587 return VisitConvolutionOperator(delegateData,
588 tfLiteContext,
589 tfLiteNode,
590 nodeIndex,
591 kTfLiteBuiltinConv3d);
592#endif
Sadik Armagan62483be2020-10-23 17:14:43 +0100593 case kTfLiteBuiltinDepthToSpace:
594 return VisitDepthToSpaceOperator(delegateData,
595 tfLiteContext,
596 tfLiteNode,
597 nodeIndex,
598 kTfLiteBuiltinDepthToSpace);
599 case kTfLiteBuiltinDepthwiseConv2d:
600 return VisitConvolutionOperator(delegateData,
601 tfLiteContext,
602 tfLiteNode,
603 nodeIndex,
604 kTfLiteBuiltinDepthwiseConv2d);
605 case kTfLiteBuiltinDequantize:
606 return VisitDequantizeOperator(delegateData,
607 tfLiteContext,
608 tfLiteNode,
609 nodeIndex,
610 kTfLiteBuiltinDequantize);
611 case kTfLiteBuiltinDiv:
612 return VisitElementwiseBinaryOperator(delegateData,
613 tfLiteContext,
614 tfLiteNode,
615 nodeIndex,
616 kTfLiteBuiltinDiv);
617 case kTfLiteBuiltinElu:
618 return VisitActivationOperator(delegateData,
619 tfLiteContext,
620 tfLiteNode,
621 nodeIndex,
622 kTfLiteBuiltinElu);
623 case kTfLiteBuiltinEqual:
624 return VisitComparisonOperator(delegateData,
625 tfLiteContext,
626 tfLiteNode,
627 nodeIndex,
628 kTfLiteBuiltinEqual);
629 case kTfLiteBuiltinExp:
630 return VisitElementwiseUnaryOperator(delegateData,
631 tfLiteContext,
632 tfLiteNode,
633 nodeIndex,
634 armnn::UnaryOperation::Exp);
635 case kTfLiteBuiltinExpandDims:
636 return VisitExpandDimsOperator(delegateData,
637 tfLiteContext,
638 tfLiteNode,
639 nodeIndex,
640 kTfLiteBuiltinExpandDims);
641 case kTfLiteBuiltinFill:
642 return VisitFillOperator(delegateData,
643 tfLiteContext,
644 tfLiteNode,
645 nodeIndex,
646 kTfLiteBuiltinFill);
647 case kTfLiteBuiltinFloor:
648 return VisitFloorOperator(delegateData,
649 tfLiteContext,
650 tfLiteNode,
651 nodeIndex,
652 kTfLiteBuiltinFloor);
Jim Flynn4b2f3472021-10-13 21:20:07 +0100653 case kTfLiteBuiltinFloorDiv:
654 return VisitElementwiseBinaryOperator(delegateData,
655 tfLiteContext,
656 tfLiteNode,
657 nodeIndex,
658 kTfLiteBuiltinFloorDiv);
Sadik Armagan62483be2020-10-23 17:14:43 +0100659 case kTfLiteBuiltinFullyConnected:
660 return VisitFullyConnectedOperator(delegateData,
661 tfLiteContext,
662 tfLiteNode,
663 nodeIndex,
664 kTfLiteBuiltinFullyConnected);
665 case kTfLiteBuiltinGather:
666 return VisitGatherOperator(delegateData,
667 tfLiteContext,
668 tfLiteNode,
669 nodeIndex,
670 kTfLiteBuiltinGather);
Teresa Charlind5c0ed22022-04-25 18:23:41 +0100671 case kTfLiteBuiltinGatherNd:
672 return VisitGatherNdOperator(delegateData,
673 tfLiteContext,
674 tfLiteNode,
675 nodeIndex,
676 kTfLiteBuiltinGatherNd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100677 case kTfLiteBuiltinGreater:
678 return VisitComparisonOperator(delegateData,
679 tfLiteContext,
680 tfLiteNode,
681 nodeIndex,
682 kTfLiteBuiltinGreater);
683 case kTfLiteBuiltinGreaterEqual:
684 return VisitComparisonOperator(delegateData,
685 tfLiteContext,
686 tfLiteNode,
687 nodeIndex,
688 kTfLiteBuiltinGreaterEqual);
689 case kTfLiteBuiltinHardSwish:
690 return VisitActivationOperator(delegateData,
691 tfLiteContext,
692 tfLiteNode,
693 nodeIndex,
694 kTfLiteBuiltinHardSwish);
695 case kTfLiteBuiltinL2Normalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000696 return VisitL2NormalizationOperator(delegateData,
697 tfLiteContext,
698 tfLiteNode,
699 nodeIndex,
700 kTfLiteBuiltinL2Normalization);
Sadik Armagan62483be2020-10-23 17:14:43 +0100701 case kTfLiteBuiltinL2Pool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100702 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100703 tfLiteContext,
704 tfLiteNode,
705 nodeIndex,
706 kTfLiteBuiltinL2Pool2d);
707 case kTfLiteBuiltinLess:
708 return VisitComparisonOperator(delegateData,
709 tfLiteContext,
710 tfLiteNode,
711 nodeIndex,
712 kTfLiteBuiltinLess);
713 case kTfLiteBuiltinLessEqual:
714 return VisitComparisonOperator(delegateData,
715 tfLiteContext,
716 tfLiteNode,
717 nodeIndex,
718 kTfLiteBuiltinLessEqual);
719 case kTfLiteBuiltinLocalResponseNormalization:
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000720 return VisitLocalResponseNormalizationOperator(delegateData,
721 tfLiteContext,
722 tfLiteNode,
723 nodeIndex,
724 kTfLiteBuiltinLocalResponseNormalization);
Matthew Sloyanc8eb9552020-11-26 10:54:22 +0000725 case kTfLiteBuiltinLogicalAnd:
726 return VisitLogicalBinaryOperator(delegateData,
727 tfLiteContext,
728 tfLiteNode,
729 nodeIndex,
730 kTfLiteBuiltinLogicalAnd,
731 armnn::LogicalBinaryOperation::LogicalAnd);
732 case kTfLiteBuiltinLogicalNot:
733 return VisitElementwiseUnaryOperator(delegateData,
734 tfLiteContext,
735 tfLiteNode,
736 nodeIndex,
737 armnn::UnaryOperation::LogicalNot);
738 case kTfLiteBuiltinLogicalOr:
739 return VisitLogicalBinaryOperator(delegateData,
740 tfLiteContext,
741 tfLiteNode,
742 nodeIndex,
743 kTfLiteBuiltinLogicalOr,
744 armnn::LogicalBinaryOperation::LogicalOr);
Sadik Armagan62483be2020-10-23 17:14:43 +0100745 case kTfLiteBuiltinLogistic:
746 return VisitActivationOperator(delegateData,
747 tfLiteContext,
748 tfLiteNode,
749 nodeIndex,
750 kTfLiteBuiltinLogistic);
751 case kTfLiteBuiltinLogSoftmax:
752 return VisitSoftmaxOperator(delegateData,
753 tfLiteContext,
754 tfLiteNode,
755 nodeIndex,
756 kTfLiteBuiltinLogSoftmax);
757 case kTfLiteBuiltinLstm:
758 return VisitLstmOperator(delegateData,
759 tfLiteContext,
760 tfLiteNode,
761 nodeIndex,
762 kTfLiteBuiltinLstm);
763 case kTfLiteBuiltinMaxPool2d:
Ryan OShead21abaf2022-06-10 14:49:11 +0100764 return VisitPooling2dOperator(delegateData,
Sadik Armagan62483be2020-10-23 17:14:43 +0100765 tfLiteContext,
766 tfLiteNode,
767 nodeIndex,
768 kTfLiteBuiltinMaxPool2d);
769 case kTfLiteBuiltinMaximum:
770 return VisitElementwiseBinaryOperator(delegateData,
771 tfLiteContext,
772 tfLiteNode,
773 nodeIndex,
774 kTfLiteBuiltinMaximum);
775 case kTfLiteBuiltinMean:
776 return VisitControlOperator(delegateData,
777 tfLiteContext,
778 tfLiteNode,
779 nodeIndex,
780 kTfLiteBuiltinMean);
781 case kTfLiteBuiltinMinimum:
782 return VisitElementwiseBinaryOperator(delegateData,
783 tfLiteContext,
784 tfLiteNode,
785 nodeIndex,
786 kTfLiteBuiltinMinimum);
Matthew Sloyanaf3a4ef2021-10-22 15:48:12 +0100787 case kTfLiteBuiltinMirrorPad:
788 return VisitPadOperator(delegateData,
789 tfLiteContext,
790 tfLiteNode,
791 nodeIndex,
792 kTfLiteBuiltinMirrorPad);
Sadik Armagan62483be2020-10-23 17:14:43 +0100793 case kTfLiteBuiltinMul:
794 return VisitElementwiseBinaryOperator(delegateData,
795 tfLiteContext,
796 tfLiteNode,
797 nodeIndex,
798 kTfLiteBuiltinMul);
799 case kTfLiteBuiltinNeg:
800 return VisitElementwiseUnaryOperator(delegateData,
801 tfLiteContext,
802 tfLiteNode,
803 nodeIndex,
804 armnn::UnaryOperation::Neg);
805 case kTfLiteBuiltinNotEqual:
806 return VisitComparisonOperator(delegateData,
807 tfLiteContext,
808 tfLiteNode,
809 nodeIndex,
810 kTfLiteBuiltinNotEqual);
Matthew Sloyana7a12f52021-05-06 10:05:28 +0100811 case kTfLiteBuiltinPack:
812 return VisitPackOperator(delegateData,
813 tfLiteContext,
814 tfLiteNode,
815 nodeIndex,
816 kTfLiteBuiltinPack);
Sadik Armagan62483be2020-10-23 17:14:43 +0100817 case kTfLiteBuiltinPad:
818 return VisitPadOperator(delegateData,
819 tfLiteContext,
820 tfLiteNode,
821 nodeIndex,
822 kTfLiteBuiltinPad);
823 case kTfLiteBuiltinPadv2:
824 return VisitPadOperator(delegateData,
825 tfLiteContext,
826 tfLiteNode,
827 nodeIndex,
828 kTfLiteBuiltinPadv2);
829 case kTfLiteBuiltinPrelu:
James Conroy39825482021-05-27 17:44:50 +0100830 return VisitPreluOperator(delegateData,
831 tfLiteContext,
832 tfLiteNode,
833 nodeIndex,
834 kTfLiteBuiltinPrelu);
Sadik Armagan62483be2020-10-23 17:14:43 +0100835 case kTfLiteBuiltinQuantize:
836 return VisitQuantizeOperator(delegateData,
837 tfLiteContext,
838 tfLiteNode,
839 nodeIndex,
840 kTfLiteBuiltinQuantize);
841 case kTfLiteBuiltinRank:
842 return VisitControlOperator(delegateData,
843 tfLiteContext,
844 tfLiteNode,
845 nodeIndex,
846 kTfLiteBuiltinRank);
Sadik Armagana2747482021-02-09 10:28:54 +0000847 case kTfLiteBuiltinReduceMax:
848 return VisitReduceOperator(delegateData,
849 tfLiteContext,
850 tfLiteNode,
851 nodeIndex,
852 kTfLiteBuiltinReduceMax);
853 case kTfLiteBuiltinReduceMin:
854 return VisitReduceOperator(delegateData,
855 tfLiteContext,
856 tfLiteNode,
857 nodeIndex,
858 kTfLiteBuiltinReduceMin);
Teresa Charlin4e3e8312021-08-05 12:34:37 +0100859 case kTfLiteBuiltinReduceProd:
860 return VisitReduceOperator(delegateData,
861 tfLiteContext,
862 tfLiteNode,
863 nodeIndex,
864 kTfLiteBuiltinReduceProd);
Sadik Armagan62483be2020-10-23 17:14:43 +0100865 case kTfLiteBuiltinRelu:
866 return VisitActivationOperator(delegateData,
867 tfLiteContext,
868 tfLiteNode,
869 nodeIndex,
870 kTfLiteBuiltinRelu);
871 case kTfLiteBuiltinReluN1To1:
872 return VisitActivationOperator(delegateData,
873 tfLiteContext,
874 tfLiteNode,
875 nodeIndex,
876 kTfLiteBuiltinReluN1To1);
877 case kTfLiteBuiltinRelu6:
878 return VisitActivationOperator(delegateData,
879 tfLiteContext,
880 tfLiteNode,
881 nodeIndex,
882 kTfLiteBuiltinRelu6);
883 case kTfLiteBuiltinReshape:
884 return VisitReshapeOperator(delegateData,
885 tfLiteContext,
886 tfLiteNode,
887 nodeIndex,
888 kTfLiteBuiltinReshape);
889 case kTfLiteBuiltinResizeBilinear:
890 return VisitResizeOperator(delegateData,
891 tfLiteContext,
892 tfLiteNode,
893 nodeIndex,
894 kTfLiteBuiltinResizeBilinear);
895 case kTfLiteBuiltinResizeNearestNeighbor:
896 return VisitResizeOperator(delegateData,
897 tfLiteContext,
898 tfLiteNode,
899 nodeIndex,
900 kTfLiteBuiltinResizeNearestNeighbor);
901 case kTfLiteBuiltinRsqrt:
902 return VisitElementwiseUnaryOperator(delegateData,
903 tfLiteContext,
904 tfLiteNode,
905 nodeIndex,
906 armnn::UnaryOperation::Rsqrt);
Keith Davis0176fd82021-06-01 17:36:32 +0100907 case kTfLiteBuiltinShape:
908 return VisitShapeOperator(delegateData,
909 tfLiteContext,
910 tfLiteNode,
911 nodeIndex,
912 kTfLiteBuiltinShape);
Sadik Armagan34fa1bd2020-11-27 12:40:52 +0000913 case kTfLiteBuiltinSplit:
914 return VisitSplitOperator(delegateData,
915 tfLiteContext,
916 tfLiteNode,
917 nodeIndex,
918 kTfLiteBuiltinSplit);
919 case kTfLiteBuiltinSplitV:
920 return VisitSplitVOperator(delegateData,
921 tfLiteContext,
922 tfLiteNode,
923 nodeIndex,
924 kTfLiteBuiltinSplitV);
Sadik Armagan62483be2020-10-23 17:14:43 +0100925 case kTfLiteBuiltinSqrt:
926 return VisitElementwiseUnaryOperator(delegateData,
927 tfLiteContext,
928 tfLiteNode,
929 nodeIndex,
930 armnn::UnaryOperation::Sqrt);
931 case kTfLiteBuiltinSqueeze:
932 return VisitSqueezeOperator(delegateData,
933 tfLiteContext,
934 tfLiteNode,
935 nodeIndex,
936 kTfLiteBuiltinSqueeze);
937 case kTfLiteBuiltinStridedSlice:
938 return VisitSliceOperator(delegateData,
939 tfLiteContext,
940 tfLiteNode,
941 nodeIndex,
942 kTfLiteBuiltinStridedSlice);
Sadik Armagana2747482021-02-09 10:28:54 +0000943 case kTfLiteBuiltinSum:
944 return VisitReduceOperator(delegateData,
945 tfLiteContext,
946 tfLiteNode,
947 nodeIndex,
948 kTfLiteBuiltinSum);
Sadik Armagan62483be2020-10-23 17:14:43 +0100949 case kTfLiteBuiltinTranspose:
950 return VisitTransposeOperator(delegateData,
951 tfLiteContext,
952 tfLiteNode,
953 nodeIndex,
954 kTfLiteBuiltinTranspose);
955 case kTfLiteBuiltinTransposeConv:
956 return VisitConvolutionOperator(delegateData,
957 tfLiteContext,
958 tfLiteNode,
959 nodeIndex,
960 kTfLiteBuiltinTransposeConv);
961 case kTfLiteBuiltinSoftmax:
962 return VisitSoftmaxOperator(delegateData,
963 tfLiteContext,
964 tfLiteNode,
965 nodeIndex,
966 kTfLiteBuiltinSoftmax);
967 case kTfLiteBuiltinSpaceToBatchNd:
968 return VisitSpaceToBatchNdOperator(delegateData,
969 tfLiteContext,
970 tfLiteNode,
971 nodeIndex,
972 kTfLiteBuiltinSpaceToBatchNd);
973 case kTfLiteBuiltinSpaceToDepth:
974 return VisitSpaceToDepthOperator(delegateData,
975 tfLiteContext,
976 tfLiteNode,
977 nodeIndex,
978 kTfLiteBuiltinSpaceToDepth);
979 case kTfLiteBuiltinSub:
980 return VisitElementwiseBinaryOperator(delegateData,
981 tfLiteContext,
982 tfLiteNode,
983 nodeIndex,
984 kTfLiteBuiltinSub);
985 case kTfLiteBuiltinTanh:
986 return VisitActivationOperator(delegateData,
987 tfLiteContext,
988 tfLiteNode,
989 nodeIndex,
990 kTfLiteBuiltinTanh);
Narumol Prangnawarat7684b182021-08-12 14:48:15 +0100991 case kTfLiteBuiltinUnidirectionalSequenceLstm:
992 return VisitUnidirectionalSequenceLstmOperator(delegateData,
993 tfLiteContext,
994 tfLiteNode,
995 nodeIndex,
996 kTfLiteBuiltinUnidirectionalSequenceLstm);
Kevin May8ab2d7a2021-05-07 09:32:51 +0100997 case kTfLiteBuiltinUnpack:
998 return VisitUnpackOperator(delegateData,
999 tfLiteContext,
1000 tfLiteNode,
1001 nodeIndex,
1002 kTfLiteBuiltinUnpack);
Sadik Armagan62483be2020-10-23 17:14:43 +01001003 default:
1004 return kTfLiteError;
1005 }
Sadik Armagan3c24f432020-10-19 17:35:30 +01001006}
1007
1008} // armnnDelegate namespace