20{
23 "ConvertPReluToTosaOperator: Prelu currently only supports Int8 Quantized inputs");
24 if (inputs.size() != 2) {
25 throw armnn::Exception(
"ConvertPReluToTosaOperator: 2 input tensors required.");
26 }
27
28 if (outputs.size() != 1) {
29 throw armnn::Exception(
"ConvertPReluToTosaOperator: 1 output tensor required.");
30 }
31
32 std::string inputName0 = std::string("input_0");
33 std::string inputName1 = std::string("input_1");
43 std::string outputName = std::string("output0_");
45
46 double scale_alpha = inputs[0]->GetQuantizationScale() * inputs[1]->GetQuantizationScale() /
47 outputs[0]->GetQuantizationScale();
48 double scale_identity = inputs[0]->GetQuantizationScale() / outputs[0]->GetQuantizationScale();
49 int32_t input0_zp = inputs[0]->GetQuantizationOffset();
50 int32_t input1_zp = inputs[1]->GetQuantizationOffset();
51 int32_t output_zp = outputs[0]->GetQuantizationOffset();
52
53
54
55 if (layer != nullptr) {
59 }
60
61 std::vector<TosaSerializationTensor *> tensors;
62 std::vector<TosaSerializationOperator *> operators;
63
64
65
66
67 std::vector<int32_t> inputShape0;
69 DType inputDType0 =
ArmNNToDType(inputs[0]->GetDataType());
70 if (inputName0.find("input_") != std::string::npos) {
71 tensors.push_back(new TosaSerializationTensor(inputName0, inputShape0, inputDType0, {}));
72 }
73
74 std::vector<int32_t> inputShape1;
76 if (inputName1.find("input_") != std::string::npos) {
77 tensors.push_back(new TosaSerializationTensor(inputName1, inputShape1, inputDType0, {}));
78 }
79
81 DType outputDType0 =
ArmNNToDType(outputs[0]->GetDataType());
82
83
84
85
86
87
88
89
90
91
92 TosaSerializationOperator* op_rescale_in = nullptr;
94 outputNameRescaleTo32,
95 1.0f,
96 input0_zp,
97 0,
98 false,
99 false,
100 true,
101 true,
102 &op_rescale_in);
103 operators.emplace_back(op_rescale_in);
104 tensors.emplace_back(new TosaSerializationTensor(outputNameRescaleTo32,
105 inputShape0,
106 DType_INT32,
107 {}));
108
109 int32_t clamp_min = 0;
110 int32_t clamp_max = std::numeric_limits<int8_t>::max();
111 float float_max = std::numeric_limits<float>::max();
112
113
114
115 TosaClampAttribute attribute(clamp_min, clamp_max, 0, float_max);
116 auto* clamp_op = new TosaSerializationOperator(Op_CLAMP,
117 Attribute_ClampAttribute,
118 &attribute,
119 {inputName0},
120 {outputNameClamp});
121 operators.push_back(clamp_op);
122 tensors.push_back(new TosaSerializationTensor(outputNameClamp, inputShape0, inputDType0, {}));
123
124
125 TosaSerializationOperator* op_clamp = nullptr;
127 outputNameClampTo32,
128 1.0f,
129 input0_zp,
130 0,
131 false,
132 false,
133 true,
134 true,
135 &op_clamp);
136 operators.emplace_back(op_clamp);
137 tensors.emplace_back(new TosaSerializationTensor(outputNameClampTo32,
138 inputShape0,
139 DType_INT32,
140 {}));
141
142 TosaSerializationOperator *op_ge = new TosaSerializationOperator(Op_EQUAL,
143 Attribute_NONE,
144 nullptr,
145 {outputNameRescaleTo32, outputNameClampTo32},
146 {outputNameClampEq});
147 operators.push_back(op_ge);
148 tensors.push_back(new TosaSerializationTensor(outputNameClampEq, inputShape0, DType_BOOL, {}));
149
150
151 TosaSerializationOperator* op_rescale_slope_in = nullptr;
153 outputNameRescaleSlope,
154 1.0f,
155 input1_zp,
156 0,
157 false,
158 false,
159 true,
160 true,
161 &op_rescale_slope_in);
162 operators.emplace_back(op_rescale_slope_in);
163 tensors.emplace_back(new TosaSerializationTensor(outputNameRescaleSlope,
164 inputShape1,
165 DType_INT32,
166 {}));
167
168 int32_t shift = 0;
169 TosaMulAttribute mulAttribute(shift);
170 TosaSerializationOperator *mulOp = new TosaSerializationOperator(Op_MUL,
171 Attribute_MulAttribute,
172 &mulAttribute,
173 {outputNameRescaleTo32,
174 outputNameRescaleSlope},
175 {outputNameMul});
176 operators.push_back(mulOp);
177 tensors.push_back(new TosaSerializationTensor(outputNameMul, outputShape0, DType_INT32, {}));
178
179 TosaSerializationOperator *op_rescale_slope_in2 = nullptr;
181 outputNameRescaleSlope2,
182 scale_alpha,
183 0,
184 output_zp,
185 false,
186 false,
187 true,
188 true,
189 &op_rescale_slope_in2);
190 operators.push_back(op_rescale_slope_in2);
191 tensors.push_back(new TosaSerializationTensor(outputNameRescaleSlope2,
192 outputShape0,
193 outputDType0, {}));
194
195 TosaSerializationOperator *op_rescale_identity_in = nullptr;
197 outputNameRescaleIdentity,
198 scale_identity,
199 input0_zp,
200 output_zp,
201 false,
202 false,
203 true,
204 true,
205 &op_rescale_identity_in);
206 operators.push_back(op_rescale_identity_in);
207 tensors.push_back(new TosaSerializationTensor(outputNameRescaleIdentity,
208 outputShape0,
209 outputDType0, {}));
210
211 TosaSerializationOperator *selectOp = new TosaSerializationOperator(Op_SELECT,
212 Attribute_NONE,
213 nullptr,
214 {outputNameClampEq,
215 outputNameRescaleIdentity,
216 outputNameRescaleSlope2},
217 {outputName});
218 operators.push_back(selectOp);
219 tensors.push_back(new TosaSerializationTensor(outputName, outputShape0, outputDType0, {}));
220
221
222
223 return new TosaSerializationBasicBlock(blockName,
225 operators,
226 tensors,
227 {inputName0,inputName1},
228 {outputName});
229
230}
#define ARMNN_THROW_INVALIDARG_MSG_IF_FALSE(_cond, _str)
std::string GenerateUniqueOutputName(const Layer &layer, uint32_t layerSlot=0)
const std::string mainName
DType ArmNNToDType(const DataType &type)
std::string GenerateUniqueInputName(const armnn::InputSlot &slot)
std::string GetUniqueTosaMappingID()
std::vector< int32_t > GetTosaTensorShape(const TensorShape &shape)
void CreateRescaleTosaOperator(const std::string &inputName, const std::string &outputName, double scale, int32_t input_zp, int32_t output_zp, bool input_unsigned, bool output_unsigned, bool double_round, bool scale32, TosaSerializationOperator **op)
Creates a Tosa rescale operator.
Base class for all ArmNN exceptions so that users can filter to just those.
const InputSlot & GetInputSlot(unsigned int index) const override
Get a const input slot handle by slot index.
constexpr bool IsQuantized8BitType(DataType dataType)