ArmNN
 24.08
SoftmaxOperator.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2024 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 //
6 // Copyright © 2020 The TensorFlow Authors. All Rights Reserved.
7 // SPDX-License-Identifier: Apache-2.0
8 //
9 
10 #include "SoftmaxOperator.hpp"
11 
14 
15 // This function is paraphrased from:
16 // tensorflow/compiler/mlir/tosa/transforms/legalize_common.cc from function convertSoftmaxOp
17 TosaSerializationBasicBlock* ConvertSoftmaxToTosaOperator(const Layer* layer,
18  const std::vector<const TensorInfo*>& inputs,
19  const std::vector<const TensorInfo*>& outputs,
20  const SoftmaxDescriptor* softmaxDescriptor)
21 
22 {
24  "ConvertSoftmaxToTosaOperator: Softmax currently only supports Int8 Quantized inputs");
25 
26  ARMNN_THROW_INVALIDARG_MSG_IF_FALSE(inputs.size() == 1,
27  "ConvertSoftmaxToTosaOperator: Softmax must have only one input");
28 
29  ARMNN_THROW_INVALIDARG_MSG_IF_FALSE(outputs.size() >= 1,
30  "ConvertSoftmaxToTosaOperator: Softmax must have at least one output");
31 
32  std::string inputName = std::string("input_");
33  std::string outputName = std::string("output0_");
34  std::string blockName = std::string("Op_SOFTMAX_block_") + GetUniqueTosaMappingID();
35 
36  std::string inputNameConst1 = std::string("intermediate_constant1_") + GetUniqueTosaMappingID();
37  std::string inputNameConst2 = std::string("intermediate_constant2_") + GetUniqueTosaMappingID();
38  std::string inputNameConst3 = std::string("intermediate_constant3_") + GetUniqueTosaMappingID();
39  std::string inputNameConst3a = std::string("intermediate_constant3a_") + GetUniqueTosaMappingID();
40  std::string inputNameConst4 = std::string("intermediate_constant4_") + GetUniqueTosaMappingID();
41  std::string inputNameConst5 = std::string("intermediate_constant5_") + GetUniqueTosaMappingID();
42  std::string inputNameConst6 = std::string("intermediate_constant6_") + GetUniqueTosaMappingID();
43  std::string inputNameConst7 = std::string("intermediate_constant7_") + GetUniqueTosaMappingID();
44  std::string inputNameConst8 = std::string("intermediate_constant8_") + GetUniqueTosaMappingID();
45  std::string inputNameConst8a = std::string("intermediate_constant8a_") + GetUniqueTosaMappingID();
46  std::string inputNameConst8b = std::string("intermediate_constant8b_") + GetUniqueTosaMappingID();
47  std::string inputNameConst9 = std::string("intermediate_constant9_") + GetUniqueTosaMappingID();
48  std::string inputNameConst9a = std::string("intermediate_constant9a_") + GetUniqueTosaMappingID();
49  std::string inputNameConst9b = std::string("intermediate_constant9b_") + GetUniqueTosaMappingID();
50  std::string inputNameConst10 = std::string("intermediate_constant10_") + GetUniqueTosaMappingID();
51 
52  std::string outputNameRescale1 = std::string("intermediate0_") + GetUniqueTosaMappingID();
53  std::string outputNameReduceMax1 = std::string("intermediate1_") + GetUniqueTosaMappingID();
54  std::string outputNameSub1 = std::string("intermediate2_") + GetUniqueTosaMappingID();
55  std::string outputNameRescale2 = std::string("intermediate3_") + GetUniqueTosaMappingID();
56  std::string outputNameTable1 = std::string("intermediate4_") + GetUniqueTosaMappingID();
57  std::string outputNameTable2 = std::string("intermediate5_") + GetUniqueTosaMappingID();
58  std::string outputNameTable3 = std::string("intermediate6_") + GetUniqueTosaMappingID();
59  std::string outputNameTable4 = std::string("intermediate7_") + GetUniqueTosaMappingID();
60  std::string outputNameLogicalL1 = std::string("intermediate8_") + GetUniqueTosaMappingID();
61  std::string outputNameLogicalL2 = std::string("intermediate9_") + GetUniqueTosaMappingID();
62  std::string outputNameLogicalL3 = std::string("intermediate10_") + GetUniqueTosaMappingID();
63  std::string outputNameArithmeticR1 = std::string("intermediate11_") + GetUniqueTosaMappingID();
64  std::string outputNameAdd1 = std::string("intermediate12_") + GetUniqueTosaMappingID();
65  std::string outputNameAdd2 = std::string("intermediate13_") + GetUniqueTosaMappingID();
66  std::string outputNameAdd3 = std::string("intermediate14_") + GetUniqueTosaMappingID();
67  std::string outputNameArithmeticR2 = std::string("intermediate15_") + GetUniqueTosaMappingID();
68  std::string outputNameReduceSum1 = std::string("intermediate16_") + GetUniqueTosaMappingID();
69  std::string outputNameCLZ1 = std::string("intermediate17_") + GetUniqueTosaMappingID();
70  std::string outputNameSub2 = std::string("intermediate18_") + GetUniqueTosaMappingID();
71  std::string outputNameLogicalL4 = std::string("intermediate19_") + GetUniqueTosaMappingID();
72  std::string outputNameMul1 = std::string("intermediate20_") + GetUniqueTosaMappingID();
73  std::string outputNameAdd4 = std::string("intermediate21_") + GetUniqueTosaMappingID();
74  std::string outputNameMul2 = std::string("intermediate22_") + GetUniqueTosaMappingID();
75  std::string outputNameSub3 = std::string("intermediate23_") + GetUniqueTosaMappingID();
76  std::string outputNameMul3 = std::string("intermediate24_") + GetUniqueTosaMappingID();
77  std::string outputNameMul4 = std::string("intermediate25_") + GetUniqueTosaMappingID();
78  std::string outputNameAdd5 = std::string("intermediate26_") + GetUniqueTosaMappingID();
79  std::string outputNameMul5 = std::string("intermediate27_") + GetUniqueTosaMappingID();
80  std::string outputNameSub4 = std::string("intermediate28_") + GetUniqueTosaMappingID();
81  std::string outputNameMul6 = std::string("intermediate29_") + GetUniqueTosaMappingID();
82  std::string outputNameMul7 = std::string("intermediate30_") + GetUniqueTosaMappingID();
83  std::string outputNameAdd6 = std::string("intermediate31_") + GetUniqueTosaMappingID();
84  std::string outputNameMul8 = std::string("intermediate32_") + GetUniqueTosaMappingID();
85  std::string outputNameSub5 = std::string("intermediate33_") + GetUniqueTosaMappingID();
86  std::string outputNameMul9 = std::string("intermediate34_") + GetUniqueTosaMappingID();
87  std::string outputNameMul10 = std::string("intermediate35_") + GetUniqueTosaMappingID();
88  std::string outputNameAdd7 = std::string("intermediate36_") + GetUniqueTosaMappingID();
89  std::string outputNameMul11 = std::string("intermediate37_") + GetUniqueTosaMappingID();
90  std::string outputNameSub6 = std::string("intermediate38_") + GetUniqueTosaMappingID();
91  std::string outputNameArithmeticR3 = std::string("intermediate39_") + GetUniqueTosaMappingID();
92 
93  // If a layer is present then the block will be used for execution, so input and output names need to be determined
94  // using the previous and following layers so the graph is connected correctly. For validation this doesn't matter.
95  if (layer != nullptr)
96  {
97  inputName = GenerateUniqueInputName(layer->GetInputSlot(0));
98  outputName = GenerateUniqueOutputName(*layer);
99  }
100 
101  const TensorInfo& inputInfo = *inputs[0];
102  const TensorInfo& outputInfo = *outputs[0];
103 
104  std::vector<TosaSerializationTensor *> tensors;
105  std::vector<TosaSerializationOperator *> operators;
106 
107  std::vector<int32_t> inputShape0 = GetTosaTensorShape(inputInfo.GetShape());
108  std::vector<int32_t> outputShape0 = GetTosaTensorShape(outputInfo.GetShape());
109 
110  DType inputDType0 = ArmNNToDType(inputInfo.GetDataType());
111  DType outputDType0 = ArmNNToDType(outputInfo.GetDataType());
112 
113  // Only add input tensors if connected layer is an input layer.
114  // As intermediate or constant tensors will be created separately.
115  // There also can't be duplicate tensor.
116  if (inputName.find("input_") != std::string::npos)
117  {
118  tensors.push_back(new TosaSerializationTensor(inputName, inputShape0, inputDType0, {}));
119  }
120 
121  float inScale = inputInfo.GetQuantizationScale();
122 
123  int32_t input_zp = inputInfo.GetQuantizationOffset();
124  int32_t output_zp = outputInfo.GetQuantizationOffset();
125 
126  std::vector<uint8_t> uint8Data;
127 
128  unsigned int rank = inputInfo.GetNumDimensions();
129  const std::vector<int32_t> singleValueShape(rank,1);
130  auto axis = static_cast<int32_t>(rank - 1);
131  TosaAxisAttribute tosaAxisAttribute(axis);
132 
133  // softmax calculations done using only the last tensor dimension
134  std::vector<int32_t> reduceShape = inputShape0;
135  reduceShape[static_cast<unsigned long>(axis)] = 1;
136 
137  TosaSerializationOperator *rescaleOp1 = nullptr;
138  CreateRescaleTosaOperator(inputName, outputNameRescale1, 1.0f, input_zp, 0, false, true, &rescaleOp1);
139 
140  tensors.push_back(new TosaSerializationTensor(outputNameRescale1, inputShape0, DType_INT32, {}));
141  operators.push_back(rescaleOp1);
142 
143  auto *reduceMaxOp1 = new TosaSerializationOperator(Op_REDUCE_MAX,
144  Attribute_AxisAttribute,
145  &tosaAxisAttribute,
146  {outputNameRescale1},
147  {outputNameReduceMax1});
148  tensors.push_back(new TosaSerializationTensor(outputNameReduceMax1, reduceShape, DType_INT32, {}));
149  operators.push_back(reduceMaxOp1);
150 
151  auto *subOp1 = new TosaSerializationOperator(Op_SUB,
152  Attribute_NONE,
153  nullptr,
154  {outputNameRescale1, outputNameReduceMax1},
155  {outputNameSub1});
156  tensors.push_back(new TosaSerializationTensor(outputNameSub1, inputShape0, DType_INT32, {}));
157  operators.push_back(subOp1);
158 
159  TosaSerializationOperator *rescaleOp2 = nullptr;
160  CreateRescaleTosaOperator(outputNameSub1, outputNameRescale2, 128.0f, 0, 0, false, true, &rescaleOp2);
161  tensors.push_back(new TosaSerializationTensor(outputNameRescale2, inputShape0, DType_INT16, {}));
162  operators.push_back(rescaleOp2);
163 
164  std::array<std::vector <int16_t>, 4> lookupTables;
165  CalculateSoftmaxTableValues(softmaxDescriptor->m_Beta, inScale, lookupTables);
166 
167  const std::vector<int16_t> first = lookupTables[0];
168  const std::vector<int16_t> table1(&first[0],&first[0]+513);
169  const std::vector<int16_t> second = lookupTables[1];
170  const std::vector<int16_t> table2(&second[0],&second[0]+513);
171  const std::vector<int16_t> third = lookupTables[2];
172  const std::vector<int16_t> table3(&third[0],&third[0]+513);
173  const std::vector<int16_t> fourth = lookupTables[3];
174  const std::vector<int16_t> table4(&fourth[0],&fourth[0]+513);
175 
176  TosaTableAttribute tosaTableAttribute1(table1);
177  TosaTableAttribute tosaTableAttribute2(table2);
178  TosaTableAttribute tosaTableAttribute3(table3);
179  TosaTableAttribute tosaTableAttribute4(table4);
180 
181  auto* tableOp1 = new TosaSerializationOperator(Op_TABLE,
182  Attribute_TableAttribute,
183  &tosaTableAttribute1,
184  {outputNameRescale2},
185  {outputNameTable1});
186  tensors.push_back(new TosaSerializationTensor(outputNameTable1, inputShape0, DType_INT32, {}));
187  operators.push_back(tableOp1);
188 
189  auto* tableOp2 = new TosaSerializationOperator(Op_TABLE,
190  Attribute_TableAttribute,
191  &tosaTableAttribute2,
192  {outputNameRescale2},
193  {outputNameTable2});
194  tensors.push_back(new TosaSerializationTensor(outputNameTable2, inputShape0, DType_INT32, {}));
195  operators.push_back(tableOp2);
196 
197  auto* tableOp3 = new TosaSerializationOperator(Op_TABLE,
198  Attribute_TableAttribute,
199  &tosaTableAttribute3,
200  {outputNameRescale2},
201  {outputNameTable3});
202  tensors.push_back(new TosaSerializationTensor(outputNameTable3, inputShape0, DType_INT32, {}));
203  operators.push_back(tableOp3);
204 
205  auto* tableOp4 = new TosaSerializationOperator(Op_TABLE,
206  Attribute_TableAttribute,
207  &tosaTableAttribute4,
208  {outputNameRescale2},
209  {outputNameTable4});
210  tensors.push_back(new TosaSerializationTensor(outputNameTable4, inputShape0, DType_INT32, {}));
211  operators.push_back(tableOp4);
212 
213  TosaSerializationHandler::ConvertI32toU8({17}, uint8Data);
214  tensors.push_back(new TosaSerializationTensor(inputNameConst1,singleValueShape, DType_INT32,uint8Data));
215  operators.push_back(new TosaSerializationOperator(Op_CONST, Attribute_NONE, nullptr, {}, {inputNameConst1}));
216 
217  auto* logicalLOp1 = new TosaSerializationOperator(Op_LOGICAL_LEFT_SHIFT,
218  Attribute_NONE,
219  nullptr,
220  {outputNameTable1, inputNameConst1},
221  {outputNameLogicalL1});
222  tensors.push_back(new TosaSerializationTensor(outputNameLogicalL1, inputShape0, DType_INT32, {}));
223  operators.push_back(logicalLOp1);
224 
225  TosaSerializationHandler::ConvertI32toU8({9}, uint8Data);
226  tensors.push_back(new TosaSerializationTensor(inputNameConst2, singleValueShape, DType_INT32,uint8Data));
227  operators.push_back(new TosaSerializationOperator(Op_CONST, Attribute_NONE, nullptr, {}, {inputNameConst2}));
228 
229  auto* logicalLOp2 = new TosaSerializationOperator(Op_LOGICAL_LEFT_SHIFT,
230  Attribute_NONE,
231  nullptr,
232  {outputNameTable2, inputNameConst2},
233  {outputNameLogicalL2});
234  tensors.push_back(new TosaSerializationTensor(outputNameLogicalL2, inputShape0, DType_INT32, {}));
235  operators.push_back(logicalLOp2);
236 
237  TosaSerializationHandler::ConvertI32toU8({1}, uint8Data);
238  tensors.push_back(new TosaSerializationTensor(inputNameConst3, singleValueShape, DType_INT32,uint8Data));
239  operators.push_back(new TosaSerializationOperator(Op_CONST, Attribute_NONE, nullptr, {}, {inputNameConst3}));
240 
241  auto* logicalLOp3 = new TosaSerializationOperator(Op_LOGICAL_LEFT_SHIFT,
242  Attribute_NONE,
243  nullptr,
244  {outputNameTable3, inputNameConst3},
245  {outputNameLogicalL3});
246  tensors.push_back(new TosaSerializationTensor(outputNameLogicalL3, inputShape0, DType_INT32, {}));
247  operators.push_back(logicalLOp3);
248 
249  bool rounding = true;
250  TosaArithmeticRightShiftAttribute shiftRAttribute(rounding);
251 
252  TosaSerializationHandler::ConvertI32toU8({7}, uint8Data);
253  tensors.push_back(new TosaSerializationTensor(inputNameConst4, singleValueShape, DType_INT32,uint8Data));
254  operators.push_back(new TosaSerializationOperator(Op_CONST, Attribute_NONE, nullptr, {}, {inputNameConst4}));
255 
256  auto* arithmeticROp1 = new TosaSerializationOperator(Op_ARITHMETIC_RIGHT_SHIFT,
257  Attribute_ArithmeticRightShiftAttribute,
258  &shiftRAttribute,
259  {outputNameTable4, inputNameConst4},
260  {outputNameArithmeticR1});
261  tensors.push_back(new TosaSerializationTensor(outputNameArithmeticR1, inputShape0, DType_INT32, {}));
262  operators.push_back(arithmeticROp1);
263 
264  auto* addOp1 = new TosaSerializationOperator(Op_ADD,
265  Attribute_NONE,
266  nullptr,
267  {outputNameLogicalL1, outputNameLogicalL2},
268  {outputNameAdd1});
269  tensors.push_back(new TosaSerializationTensor(outputNameAdd1, inputShape0, DType_INT32, {}));
270  operators.push_back(addOp1);
271 
272  auto* addOp2 = new TosaSerializationOperator(Op_ADD,
273  Attribute_NONE,
274  nullptr,
275  {outputNameAdd1, outputNameLogicalL3},
276  {outputNameAdd2});
277  tensors.push_back(new TosaSerializationTensor(outputNameAdd2, inputShape0, DType_INT32, {}));
278  operators.push_back(addOp2);
279 
280  auto* addOp3 = new TosaSerializationOperator(Op_ADD,
281  Attribute_NONE,
282  nullptr,
283  {outputNameAdd2, outputNameArithmeticR1},
284  {outputNameAdd3});
285  tensors.push_back(new TosaSerializationTensor(outputNameAdd3, inputShape0, DType_INT32, {}));
286  operators.push_back(addOp3);
287 
288  TosaSerializationHandler::ConvertI32toU8({12}, uint8Data);
289  tensors.push_back(new TosaSerializationTensor(inputNameConst5, singleValueShape, DType_INT32,uint8Data));
290  operators.push_back(new TosaSerializationOperator(Op_CONST, Attribute_NONE, nullptr, {}, {inputNameConst5}));
291 
292  auto* arithmeticROp2 = new TosaSerializationOperator(Op_ARITHMETIC_RIGHT_SHIFT,
293  Attribute_ArithmeticRightShiftAttribute,
294  &shiftRAttribute,
295  {outputNameAdd3, inputNameConst5},
296  {outputNameArithmeticR2});
297  tensors.push_back(new TosaSerializationTensor(outputNameArithmeticR2, inputShape0, DType_INT32, {}));
298  operators.push_back(arithmeticROp2);
299 
300  auto* reduceSumOp1 = new TosaSerializationOperator(Op_REDUCE_SUM,
301  Attribute_AxisAttribute,
302  &tosaAxisAttribute,
303  {outputNameArithmeticR2},
304  {outputNameReduceSum1});
305  tensors.push_back(new TosaSerializationTensor(outputNameReduceSum1, reduceShape, DType_INT32, {}));
306  operators.push_back(reduceSumOp1);
307 
308  auto* countLeadingZeroOp1 = new TosaSerializationOperator(Op_CLZ,
309  Attribute_NONE,
310  nullptr,
311  {outputNameReduceSum1},
312  {outputNameCLZ1});
313  tensors.push_back(new TosaSerializationTensor(outputNameCLZ1, reduceShape, DType_INT32, {}));
314  operators.push_back(countLeadingZeroOp1);
315 
316  TosaSerializationHandler::ConvertI32toU8({1}, uint8Data);
317  tensors.push_back(new TosaSerializationTensor(inputNameConst3a, singleValueShape, DType_INT32, uint8Data));
318  operators.push_back(new TosaSerializationOperator(Op_CONST, Attribute_NONE, nullptr, {}, {inputNameConst3a}));
319 
320  auto* subOp2 = new TosaSerializationOperator(Op_SUB,
321  Attribute_NONE,
322  nullptr,
323  {outputNameCLZ1, inputNameConst3a},
324  {outputNameSub2});
325  tensors.push_back(new TosaSerializationTensor(outputNameSub2, reduceShape, DType_INT32, {}));
326  operators.push_back(subOp2);
327 
328  // half_denominator
329  auto* logicalLOp4 = new TosaSerializationOperator(Op_LOGICAL_LEFT_SHIFT,
330  Attribute_NONE,
331  nullptr,
332  {outputNameReduceSum1, outputNameSub2},
333  {outputNameLogicalL4});
334  tensors.push_back(new TosaSerializationTensor(outputNameLogicalL4, reduceShape, DType_INT32, {}));
335  operators.push_back(logicalLOp4);
336 
337  TosaMulAttribute mulAttribute1(31);
338 
339  TosaSerializationHandler::ConvertI32toU8({-1010580540}, uint8Data); // constant_neg_32_over_17
340  tensors.push_back(new TosaSerializationTensor(inputNameConst6, singleValueShape, DType_INT32,uint8Data));
341  operators.push_back(new TosaSerializationOperator(Op_CONST, Attribute_NONE, nullptr, {}, {inputNameConst6}));
342 
343  // mul_half_denominator
344  auto* mulOp1 = new TosaSerializationOperator(Op_MUL,
345  Attribute_MulAttribute,
346  &mulAttribute1,
347  {outputNameLogicalL4, inputNameConst6},
348  {outputNameMul1});
349  tensors.push_back(new TosaSerializationTensor(outputNameMul1, reduceShape, DType_INT32, {}));
350  operators.push_back(mulOp1);
351 
352  TosaSerializationHandler::ConvertI32toU8({1515870810}, uint8Data); // constant_48_over_17
353  tensors.push_back(new TosaSerializationTensor(inputNameConst7, singleValueShape, DType_INT32,uint8Data));
354  operators.push_back(new TosaSerializationOperator(Op_CONST, Attribute_NONE, nullptr, {}, {inputNameConst7}));
355 
356  // nr_x
357  auto* addOp4 = new TosaSerializationOperator(Op_ADD,
358  Attribute_NONE,
359  nullptr,
360  {outputNameMul1, inputNameConst7},
361  {outputNameAdd4});
362  tensors.push_back(new TosaSerializationTensor(outputNameAdd4, reduceShape, DType_INT32, {}));
363  operators.push_back(addOp4);
364 
365  // Newton-Raphson 3 iterations of MUL SUB MUL MUL ADD sequence
366  auto* mulOp2 = new TosaSerializationOperator(Op_MUL,
367  Attribute_MulAttribute,
368  &mulAttribute1,
369  {outputNameAdd4, outputNameLogicalL4},
370  {outputNameMul2});
371  tensors.push_back(new TosaSerializationTensor(outputNameMul2, reduceShape, DType_INT32, {}));
372  operators.push_back(mulOp2);
373 
374  TosaSerializationHandler::ConvertI32toU8({536870912}, uint8Data); // F2_one constant
375  tensors.push_back(new TosaSerializationTensor(inputNameConst8, singleValueShape, DType_INT32,uint8Data));
376  operators.push_back(new TosaSerializationOperator(Op_CONST, Attribute_NONE, nullptr, {}, {inputNameConst8}));
377 
378  auto* subOp3 = new TosaSerializationOperator(Op_SUB,
379  Attribute_NONE,
380  nullptr,
381  {inputNameConst8, outputNameMul2},
382  {outputNameSub3});
383  tensors.push_back(new TosaSerializationTensor(outputNameSub3, reduceShape, DType_INT32, {}));
384  operators.push_back(subOp3);
385 
386  auto* mulOp3 = new TosaSerializationOperator(Op_MUL,
387  Attribute_MulAttribute,
388  &mulAttribute1,
389  {outputNameAdd4, outputNameSub3},
390  {outputNameMul3});
391  tensors.push_back(new TosaSerializationTensor(outputNameMul3, reduceShape, DType_INT32, {}));
392  operators.push_back(mulOp3);
393 
394  TosaMulAttribute mulAttribute2(0);
395 
396  TosaSerializationHandler::ConvertI32toU8({4}, uint8Data);
397  tensors.push_back(new TosaSerializationTensor(inputNameConst9, singleValueShape, DType_INT32,uint8Data));
398  operators.push_back(new TosaSerializationOperator(Op_CONST, Attribute_NONE, nullptr, {}, {inputNameConst9}));
399 
400  auto* mulOp4 = new TosaSerializationOperator(Op_MUL,
401  Attribute_MulAttribute,
402  &mulAttribute2,
403  {outputNameMul3, inputNameConst9},
404  {outputNameMul4});
405  tensors.push_back(new TosaSerializationTensor(outputNameMul4, reduceShape, DType_INT32, {}));
406  operators.push_back(mulOp4);
407 
408  auto* addOp5 = new TosaSerializationOperator(Op_ADD,
409  Attribute_NONE,
410  nullptr,
411  {outputNameAdd4, outputNameMul4},
412  {outputNameAdd5});
413  tensors.push_back(new TosaSerializationTensor(outputNameAdd5, reduceShape, DType_INT32, {}));
414  operators.push_back(addOp5);
415 
416  // Newton-Raphson 2nd iteration... nr_x = op25_add_x_op24.getResult();
417  auto* mulOp5 = new TosaSerializationOperator(Op_MUL,
418  Attribute_MulAttribute,
419  &mulAttribute1,
420  {outputNameAdd5, outputNameLogicalL4},
421  {outputNameMul5});
422  tensors.push_back(new TosaSerializationTensor(outputNameMul5, reduceShape, DType_INT32, {}));
423  operators.push_back(mulOp5);
424 
425  TosaSerializationHandler::ConvertI32toU8({536870912}, uint8Data);
426  tensors.push_back(new TosaSerializationTensor(inputNameConst8a, singleValueShape, DType_INT32,uint8Data));
427  operators.push_back(new TosaSerializationOperator(Op_CONST, Attribute_NONE, nullptr, {}, {inputNameConst8a}));
428 
429  auto* subOp4 = new TosaSerializationOperator(Op_SUB,
430  Attribute_NONE,
431  nullptr,
432  {inputNameConst8a, outputNameMul5},
433  {outputNameSub4});
434  tensors.push_back(new TosaSerializationTensor(outputNameSub4, reduceShape, DType_INT32, {}));
435  operators.push_back(subOp4);
436 
437  auto* mulOp6 = new TosaSerializationOperator(Op_MUL,
438  Attribute_MulAttribute,
439  &mulAttribute1,
440  {outputNameAdd5, outputNameSub4},
441  {outputNameMul6});
442  tensors.push_back(new TosaSerializationTensor(outputNameMul6, reduceShape, DType_INT32, {}));
443  operators.push_back(mulOp6);
444 
445  TosaSerializationHandler::ConvertI32toU8({4}, uint8Data);
446  tensors.push_back(new TosaSerializationTensor(inputNameConst9a, singleValueShape, DType_INT32,uint8Data));
447  operators.push_back(new TosaSerializationOperator(Op_CONST, Attribute_NONE, nullptr, {}, {inputNameConst9a}));
448 
449  auto* mulOp7 = new TosaSerializationOperator(Op_MUL,
450  Attribute_MulAttribute,
451  &mulAttribute2,
452  {outputNameMul6, inputNameConst9a},
453  {outputNameMul7});
454  tensors.push_back(new TosaSerializationTensor(outputNameMul7, reduceShape, DType_INT32, {}));
455  operators.push_back(mulOp7);
456 
457  auto* addOp6 = new TosaSerializationOperator(Op_ADD,
458  Attribute_NONE,
459  nullptr,
460  {outputNameAdd5, outputNameMul7},
461  {outputNameAdd6});
462  tensors.push_back(new TosaSerializationTensor(outputNameAdd6, reduceShape, DType_INT32, {}));
463  operators.push_back(addOp6);
464 
465  // Newton-Raphson 3rd iteration... nr_x = op25_add_x_op24.getResult();
466  auto* mulOp8 = new TosaSerializationOperator(Op_MUL,
467  Attribute_MulAttribute,
468  &mulAttribute1,
469  {outputNameAdd6, outputNameLogicalL4},
470  {outputNameMul8});
471  tensors.push_back(new TosaSerializationTensor(outputNameMul8, reduceShape, DType_INT32, {}));
472  operators.push_back(mulOp8);
473 
474  TosaSerializationHandler::ConvertI32toU8({536870912}, uint8Data);
475  tensors.push_back(new TosaSerializationTensor(inputNameConst8b, singleValueShape, DType_INT32,uint8Data));
476  operators.push_back(new TosaSerializationOperator(Op_CONST, Attribute_NONE, nullptr, {}, {inputNameConst8b}));
477 
478  auto* subOp5 = new TosaSerializationOperator(Op_SUB,
479  Attribute_NONE,
480  nullptr,
481  {inputNameConst8b, outputNameMul8},
482  {outputNameSub5});
483  tensors.push_back(new TosaSerializationTensor(outputNameSub5, reduceShape, DType_INT32, {}));
484  operators.push_back(subOp5);
485 
486  auto* mulOp9 = new TosaSerializationOperator(Op_MUL,
487  Attribute_MulAttribute,
488  &mulAttribute1,
489  {outputNameAdd6, outputNameSub5},
490  {outputNameMul9});
491  tensors.push_back(new TosaSerializationTensor(outputNameMul9, reduceShape, DType_INT32, {}));
492  operators.push_back(mulOp9);
493 
494  TosaSerializationHandler::ConvertI32toU8({4}, uint8Data);
495  tensors.push_back(new TosaSerializationTensor(inputNameConst9b, singleValueShape, DType_INT32,uint8Data));
496  operators.push_back(new TosaSerializationOperator(Op_CONST, Attribute_NONE, nullptr, {}, {inputNameConst9b}));
497 
498  auto* mulOp10 = new TosaSerializationOperator(Op_MUL,
499  Attribute_MulAttribute,
500  &mulAttribute2,
501  {outputNameMul9, inputNameConst9b},
502  {outputNameMul10});
503  tensors.push_back(new TosaSerializationTensor(outputNameMul10, reduceShape, DType_INT32, {}));
504  operators.push_back(mulOp10);
505 
506  auto* addOp7 = new TosaSerializationOperator(Op_ADD,
507  Attribute_NONE,
508  nullptr,
509  {outputNameAdd6, outputNameMul10},
510  {outputNameAdd7});
511  tensors.push_back(new TosaSerializationTensor(outputNameAdd7, reduceShape, DType_INT32, {}));
512  operators.push_back(addOp7);
513 
514  TosaMulAttribute mulAttribute3(30);
515 
516  auto* mulOp11 = new TosaSerializationOperator(Op_MUL,
517  Attribute_MulAttribute,
518  &mulAttribute3,
519  {outputNameAdd3, outputNameAdd7},
520  {outputNameMul11});
521  tensors.push_back(new TosaSerializationTensor(outputNameMul11, outputShape0, DType_INT32, {}));
522  operators.push_back(mulOp11);
523 
524  TosaSerializationHandler::ConvertI32toU8({35}, uint8Data);
525  tensors.push_back(new TosaSerializationTensor(inputNameConst10, singleValueShape, DType_INT32,uint8Data));
526  operators.push_back(new TosaSerializationOperator(Op_CONST, Attribute_NONE, nullptr, {}, {inputNameConst10}));
527 
528  auto* subOp6 = new TosaSerializationOperator(Op_SUB,
529  Attribute_NONE,
530  nullptr,
531  {inputNameConst10, outputNameCLZ1},
532  {outputNameSub6});
533  tensors.push_back(new TosaSerializationTensor(outputNameSub6, reduceShape, DType_INT32, {}));
534  operators.push_back(subOp6);
535 
536  auto* arithmeticROp3 = new TosaSerializationOperator(Op_ARITHMETIC_RIGHT_SHIFT,
537  Attribute_ArithmeticRightShiftAttribute,
538  &shiftRAttribute,
539  {outputNameMul11, outputNameSub6},
540  {outputNameArithmeticR3});
541  tensors.push_back(new TosaSerializationTensor(outputNameArithmeticR3, outputShape0, DType_INT32, {}));
542  operators.push_back(arithmeticROp3);
543 
544  TosaSerializationOperator* rescaleOp3 = nullptr;
545  CreateRescaleTosaOperator(outputNameArithmeticR3, outputName, 1.0f, 0, output_zp, false, true, &rescaleOp3);
546 
547  tensors.push_back(new TosaSerializationTensor(outputName, outputShape0, outputDType0, {}));
548  operators.push_back(rescaleOp3);
549 
550  return new TosaSerializationBasicBlock(blockName,
551  mainName,
552  {operators},
553  tensors,
554  {inputName},
555  {outputName});
556 }
armnn::IsQuantized8BitType
constexpr bool IsQuantized8BitType(DataType dataType)
Definition: TypesUtils.hpp:316
armnn::SoftmaxDescriptor::m_Beta
float m_Beta
Exponentiation value.
Definition: Descriptors.hpp:190
armnn::TensorInfo::GetQuantizationScale
float GetQuantizationScale() const
Definition: Tensor.cpp:461
armnn::TensorInfo
Definition: Tensor.hpp:152
armnn::TensorInfo::GetNumDimensions
unsigned int GetNumDimensions() const
Definition: Tensor.hpp:197
TosaRescaleOperatorUtils.hpp
GenerateUniqueOutputName
std::string GenerateUniqueOutputName(const Layer &layer, uint32_t layerSlot=0)
Definition: TosaOperatorUtils.hpp:120
armnn::Layer::GetInputSlot
const InputSlot & GetInputSlot(unsigned int index) const override
Get a const input slot handle by slot index.
Definition: Layer.hpp:337
armnn::Layer
Definition: Layer.hpp:230
mainName
const std::string mainName
Definition: TosaOperatorUtils.hpp:19
ArmNNToDType
DType ArmNNToDType(const DataType &type)
Definition: TosaOperatorUtils.hpp:22
TosaSoftmaxOperatorUtils.hpp
armnn::TensorInfo::GetDataType
DataType GetDataType() const
Definition: Tensor.hpp:200
SoftmaxOperator.hpp
armnn::TensorInfo::GetShape
const TensorShape & GetShape() const
Definition: Tensor.hpp:193
GetTosaTensorShape
std::vector< int32_t > GetTosaTensorShape(const TensorShape &shape)
Definition: TosaOperatorUtils.hpp:79
ConvertSoftmaxToTosaOperator
TosaSerializationBasicBlock * ConvertSoftmaxToTosaOperator(const Layer *layer, const std::vector< const TensorInfo * > &inputs, const std::vector< const TensorInfo * > &outputs, const SoftmaxDescriptor *softmaxDescriptor)
Definition: SoftmaxOperator.cpp:17
CalculateSoftmaxTableValues
void CalculateSoftmaxTableValues(double softmaxBeta, double scale, std::array< std::vector< int16_t >, 4 > &tables)
Definition: TosaSoftmaxOperatorUtils.hpp:60
CreateRescaleTosaOperator
void CreateRescaleTosaOperator(const std::string &inputName, const std::string &outputName, const std::vector< int32_t > &multipliers, const std::vector< int32_t > &shifts, int32_t input_zp, int32_t output_zp, bool double_round, bool scale32, bool per_channel, TosaSerializationOperator **op)
Definition: TosaRescaleOperatorUtils.hpp:10
armnn::TensorInfo::GetQuantizationOffset
int32_t GetQuantizationOffset() const
Definition: Tensor.cpp:482
GenerateUniqueInputName
std::string GenerateUniqueInputName(const armnn::InputSlot &slot)
Definition: TosaOperatorUtils.hpp:109
armnn::SoftmaxDescriptor
A SoftmaxDescriptor for the SoftmaxLayer.
Definition: Descriptors.hpp:177
GetUniqueTosaMappingID
std::string GetUniqueTosaMappingID()
Definition: TosaOperatorUtils.hpp:138
ARMNN_THROW_INVALIDARG_MSG_IF_FALSE
#define ARMNN_THROW_INVALIDARG_MSG_IF_FALSE(_cond, _str)
Definition: Exceptions.hpp:210