blob: 4adbd1161675da3113142c548e1e76d167717cac [file] [log] [blame]
Sadik Armagan62483be2020-10-23 17:14:43 +01001//
2// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
3// 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 Armagan62483be2020-10-23 17:14:43 +010016TfLiteStatus VisitDequantizeOperator(DelegateData& delegateData,
17 TfLiteContext* tfLiteContext,
18 TfLiteNode* tfLiteNode,
19 int nodeIndex,
Matthew Sloyan0d35a932020-11-09 12:25:05 +000020 int32_t tfLiteDequantizeOperatorCode)
Sadik Armagan62483be2020-10-23 17:14:43 +010021{
Matthew Sloyan0d35a932020-11-09 12:25:05 +000022 TF_LITE_ENSURE_STATUS(ValidateNumInputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
23 TF_LITE_ENSURE_STATUS(ValidateNumOutputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
24
25 const TfLiteTensor* tfLiteTensors = tfLiteContext->tensors;
26 const TfLiteTensor& tfLiteInputTensor = tfLiteTensors[tfLiteNode->inputs->data[0]];
27 if (IsDynamicTensor(tfLiteInputTensor))
28 {
29 TF_LITE_MAYBE_KERNEL_LOG(
30 tfLiteContext,
31 "TfLiteArmnnDelegate: Dynamic input tensors are not supported in operator #%d node #%d: ",
32 tfLiteDequantizeOperatorCode, nodeIndex);
33 return kTfLiteError;
34 }
35
36 const TfLiteTensor& tfLiteOutputTensor = tfLiteTensors[tfLiteNode->outputs->data[0]];
37 if (IsDynamicTensor(tfLiteOutputTensor))
38 {
39 TF_LITE_MAYBE_KERNEL_LOG(
40 tfLiteContext,
41 "TfLiteArmnnDelegate: Dynamic output tensors are not supported in operator #%d node #%d: ",
42 tfLiteDequantizeOperatorCode, nodeIndex);
43 return kTfLiteError;
44 }
45
46 const armnn::TensorInfo& inputTensorInfo = GetTensorInfoForTfLiteTensor(tfLiteInputTensor);
47 const armnn::TensorInfo& outputTensorInfo = GetTensorInfoForTfLiteTensor(tfLiteOutputTensor);
48
49 bool isSupported = false;
50 auto validateFunc = [&](const armnn::TensorInfo& outputTensorInfo, bool& isSupported)
51 {
52 FORWARD_LAYER_SUPPORT_FUNC(__func__,
53 tfLiteContext,
54 IsDequantizeSupported,
55 delegateData.m_Backends,
56 isSupported,
57 inputTensorInfo,
58 outputTensorInfo);
59 };
60
61 if (!delegateData.m_Network)
62 {
63 validateFunc(outputTensorInfo, isSupported);
64 return isSupported ? kTfLiteOk : kTfLiteError;
65 }
66
67 armnn::IConnectableLayer* dequantizeLayer = delegateData.m_Network->AddDequantizeLayer();
68 ARMNN_ASSERT(dequantizeLayer != nullptr);
69
70 armnn::IOutputSlot& outputSlot = dequantizeLayer->GetOutputSlot(0);
71 outputSlot.SetTensorInfo(outputTensorInfo);
72
73 return Connect(dequantizeLayer, tfLiteNode, delegateData);
74}
75
76TfLiteStatus VisitQuantizeOperator(DelegateData& delegateData,
77 TfLiteContext* tfLiteContext,
78 TfLiteNode* tfLiteNode,
79 int nodeIndex,
80 int32_t tfLiteQuantizeOperatorCode)
81{
82 TF_LITE_ENSURE_STATUS(ValidateNumInputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
83 TF_LITE_ENSURE_STATUS(ValidateNumOutputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
84
85 const TfLiteTensor* tfLiteTensors = tfLiteContext->tensors;
86 const TfLiteTensor& tfLiteInputTensor = tfLiteTensors[tfLiteNode->inputs->data[0]];
87 if (IsDynamicTensor(tfLiteInputTensor))
88 {
89 TF_LITE_MAYBE_KERNEL_LOG(
90 tfLiteContext,
91 "TfLiteArmnnDelegate: Dynamic input tensors are not supported in operator #%d node #%d: ",
92 tfLiteQuantizeOperatorCode, nodeIndex);
93 return kTfLiteError;
94 }
95
96 const TfLiteTensor& tfLiteOutputTensor = tfLiteTensors[tfLiteNode->outputs->data[0]];
97 if (IsDynamicTensor(tfLiteOutputTensor))
98 {
99 TF_LITE_MAYBE_KERNEL_LOG(
100 tfLiteContext,
101 "TfLiteArmnnDelegate: Dynamic output tensors are not supported in operator #%d node #%d: ",
102 tfLiteQuantizeOperatorCode, nodeIndex);
103 return kTfLiteError;
104 }
105
106 // Only affine per-layer quantization is supported.
107 if (!IsAffineQuantization(tfLiteOutputTensor))
108 {
109 TF_LITE_MAYBE_KERNEL_LOG(
110 tfLiteContext,
111 "TfLiteArmnnDelegate: Only affine per-layer quantization is supported in operator #%d node #%d: ",
112 tfLiteQuantizeOperatorCode, nodeIndex);
113 return kTfLiteError;
114 }
115
116 const armnn::TensorInfo& inputTensorInfo = GetTensorInfoForTfLiteTensor(tfLiteInputTensor);
117 const armnn::TensorInfo& outputTensorInfo = GetTensorInfoForTfLiteTensor(tfLiteOutputTensor);
118
119 bool isSupported = false;
120 auto validateFunc = [&](const armnn::TensorInfo& outputTensorInfo, bool& isSupported)
121 {
122 FORWARD_LAYER_SUPPORT_FUNC(__func__,
123 tfLiteContext,
124 IsQuantizeSupported,
125 delegateData.m_Backends,
126 isSupported,
127 inputTensorInfo,
128 outputTensorInfo);
129 };
130
131 if (!delegateData.m_Network)
132 {
133 validateFunc(outputTensorInfo, isSupported);
134 return isSupported ? kTfLiteOk : kTfLiteError;
135 }
136
137 armnn::IConnectableLayer* quantizeLayer = delegateData.m_Network->AddQuantizeLayer();
138 ARMNN_ASSERT(quantizeLayer != nullptr);
139
140 armnn::IOutputSlot& outputSlot = quantizeLayer->GetOutputSlot(0);
141 outputSlot.SetTensorInfo(outputTensorInfo);
142
143 return Connect(quantizeLayer, tfLiteNode, delegateData);
Sadik Armagan62483be2020-10-23 17:14:43 +0100144}
145
146} // namespace armnnDelegate