blob: befadddd77c8de274a1b49e99100d4b6dec94f20 [file] [log] [blame]
Sadik Armagan62483be2020-10-23 17:14:43 +01001//
Ryan OShea4c231de2023-01-17 15:19:20 +00002// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
Sadik Armagan62483be2020-10-23 17:14:43 +01003// SPDX-License-Identifier: MIT
4//
5
6#pragma once
7
8#include <tensorflow/lite/builtin_ops.h>
9#include <tensorflow/lite/c/builtin_op_data.h>
10#include <tensorflow/lite/c/common.h>
11#include <tensorflow/lite/minimal_logging.h>
12
13namespace armnnDelegate
14{
15
Sadik Armagan4b227bb2021-01-22 10:53:38 +000016TfLiteStatus VisitL2NormalizationOperator(DelegateData& delegateData,
17 TfLiteContext* tfLiteContext,
18 TfLiteNode* tfLiteNode,
19 int nodeIndex,
20 int32_t operatorCode)
Sadik Armagan62483be2020-10-23 17:14:43 +010021{
Sadik Armagan4b227bb2021-01-22 10:53:38 +000022 TF_LITE_ENSURE_STATUS(ValidateNumInputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
23 TF_LITE_ENSURE_STATUS(ValidateNumOutputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
Finn Williams6f9f9902020-11-13 13:23:15 +000024
Sadik Armagan4b227bb2021-01-22 10:53:38 +000025 const TfLiteTensor* tfLiteTensors = tfLiteContext->tensors;
26 const TfLiteTensor& tfLiteInputTensor = tfLiteTensors[tfLiteNode->inputs->data[0]];
27 if (!IsValid(tfLiteContext, tfLiteInputTensor, operatorCode, nodeIndex))
28 {
29 return kTfLiteError;
30 }
31
32 const TfLiteTensor& tfLiteOutputTensor = tfLiteTensors[tfLiteNode->outputs->data[0]];
33 if (!IsValid(tfLiteContext, tfLiteOutputTensor, operatorCode, nodeIndex))
34 {
35 return kTfLiteError;
36 }
37
38 const armnn::TensorInfo& inputTensorInfo = GetTensorInfoForTfLiteTensor(tfLiteInputTensor);
Sadik Armagan90a119b2022-08-05 16:12:49 +010039 const armnn::TensorInfo& outputTensorInfo = GetTensorInfoForTfLiteTensor(tfLiteOutputTensor, true);
Sadik Armagan4b227bb2021-01-22 10:53:38 +000040
41 armnn::L2NormalizationDescriptor descriptor;
42 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
43
44 bool isSupported = false;
Cathal Corbett53837672022-09-01 11:34:37 +010045 armnn::BackendId setBackend;
Sadik Armagan4b227bb2021-01-22 10:53:38 +000046 auto validateFunc = [&](const armnn::TensorInfo& outInfo, bool& isSupported)
47 {
Sadik Armaganbfa767c2022-02-09 14:58:03 +000048 FORWARD_LAYER_SUPPORT_FUNC("L2_NORMALIZATION",
Sadik Armagan4b227bb2021-01-22 10:53:38 +000049 tfLiteContext,
50 IsL2NormalizationSupported,
51 delegateData.m_Backends,
52 isSupported,
Cathal Corbett53837672022-09-01 11:34:37 +010053 setBackend,
Sadik Armagan4b227bb2021-01-22 10:53:38 +000054 inputTensorInfo,
55 outInfo,
56 descriptor);
57 };
58
59 if (!delegateData.m_Network)
60 {
61 validateFunc(outputTensorInfo, isSupported);
62 return isSupported ? kTfLiteOk : kTfLiteError;
63 }
64
65 // Add a L2Normalization layer
Mike Kelly07169c82023-08-02 13:23:09 +010066 auto layerName = GetLayerName(armnn::LayerType::L2Normalization, nodeIndex);
67 armnn::IConnectableLayer* layer = delegateData.m_Network->AddL2NormalizationLayer(descriptor, layerName.c_str());
Cathal Corbett53837672022-09-01 11:34:37 +010068 layer->SetBackendId(setBackend);
Sadik Armagan4b227bb2021-01-22 10:53:38 +000069 ARMNN_ASSERT(layer != nullptr);
70
71 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
72 outputSlot.SetTensorInfo(outputTensorInfo);
73
Ryan OShea4c231de2023-01-17 15:19:20 +000074 // try to connect the Constant Inputs if there are any
Mike Kelly07169c82023-08-02 13:23:09 +010075 if (ProcessInputs(layer, delegateData, tfLiteContext, tfLiteNode, nodeIndex) != kTfLiteOk)
Ryan OShea4c231de2023-01-17 15:19:20 +000076 {
77 return kTfLiteError;
78 }
79
Sadik Armagan4b227bb2021-01-22 10:53:38 +000080 // Connect
81 return Connect(layer, tfLiteNode, delegateData);
82}
83
84
85TfLiteStatus VisitLocalResponseNormalizationOperator(DelegateData& delegateData,
86 TfLiteContext* tfLiteContext,
87 TfLiteNode* tfLiteNode,
88 int nodeIndex,
89 int32_t normalizationOperatorCode)
90{
91 TF_LITE_ENSURE_STATUS(ValidateNumInputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
92 TF_LITE_ENSURE_STATUS(ValidateNumOutputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
93
94 const TfLiteTensor* tfLiteTensors = tfLiteContext->tensors;
95 const TfLiteTensor& tfLiteInputTensor = tfLiteTensors[tfLiteNode->inputs->data[0]];
96 if (!IsValid(tfLiteContext, tfLiteInputTensor, normalizationOperatorCode, nodeIndex))
97 {
98 return kTfLiteError;
99 }
100
101 const TfLiteTensor& tfLiteOutputTensor = tfLiteTensors[tfLiteNode->outputs->data[0]];
102 if (!IsValid(tfLiteContext, tfLiteOutputTensor, normalizationOperatorCode, nodeIndex))
103 {
104 return kTfLiteError;
105 }
106
107 const armnn::TensorInfo& inputTensorInfo = GetTensorInfoForTfLiteTensor(tfLiteInputTensor);
Sadik Armagan90a119b2022-08-05 16:12:49 +0100108 const armnn::TensorInfo& outputTensorInfo = GetTensorInfoForTfLiteTensor(tfLiteOutputTensor, true);
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000109
110 armnn::NormalizationDescriptor descriptor;
111 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
112 descriptor.m_NormChannelType = armnn::NormalizationAlgorithmChannel::Across;
113 descriptor.m_NormMethodType = armnn::NormalizationAlgorithmMethod::LocalBrightness;
114
115 auto* params = reinterpret_cast<TfLiteLocalResponseNormParams*>(tfLiteNode->builtin_data);
116 descriptor.m_NormSize = params->radius;
117 descriptor.m_K = params->bias;
118 descriptor.m_Alpha = params->alpha;
119 descriptor.m_Beta = params->beta;
120
121 // ArmNN expects normSize to be the full size of the normalization window
122 descriptor.m_NormSize = 1 + (2 * descriptor.m_NormSize);
123
124 bool isSupported = false;
Cathal Corbett53837672022-09-01 11:34:37 +0100125 armnn::BackendId setBackend;
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000126 auto validateFunc = [&](const armnn::TensorInfo& outInfo, bool& isSupported)
127 {
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000128 FORWARD_LAYER_SUPPORT_FUNC("NORMALIZATION",
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000129 tfLiteContext,
130 IsNormalizationSupported,
131 delegateData.m_Backends,
132 isSupported,
Cathal Corbett53837672022-09-01 11:34:37 +0100133 setBackend,
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000134 inputTensorInfo,
135 outInfo,
136 descriptor);
137 };
138
139 if (!delegateData.m_Network)
140 {
141 validateFunc(outputTensorInfo, isSupported);
142 return isSupported ? kTfLiteOk : kTfLiteError;
143 }
144
145 // Add a Normalization layer
Mike Kelly07169c82023-08-02 13:23:09 +0100146 auto layerName = GetLayerName(armnn::LayerType::Normalization, nodeIndex);
147 armnn::IConnectableLayer* layer = delegateData.m_Network->AddNormalizationLayer(descriptor, layerName.c_str());
Cathal Corbett53837672022-09-01 11:34:37 +0100148 layer->SetBackendId(setBackend);
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000149 ARMNN_ASSERT(layer != nullptr);
150
151 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
152 outputSlot.SetTensorInfo(outputTensorInfo);
153
Ryan OShea4c231de2023-01-17 15:19:20 +0000154 // try to connect the Constant Inputs if there are any
Mike Kelly07169c82023-08-02 13:23:09 +0100155 if (ProcessInputs(layer, delegateData, tfLiteContext, tfLiteNode, nodeIndex) != kTfLiteOk)
Ryan OShea4c231de2023-01-17 15:19:20 +0000156 {
157 return kTfLiteError;
158 }
159
Sadik Armagan4b227bb2021-01-22 10:53:38 +0000160 // Connect
161 return Connect(layer, tfLiteNode, delegateData);
Sadik Armagan62483be2020-10-23 17:14:43 +0100162}
163
164} // namespace armnnDelegate