21{
22 if (inputs.size() != 1)
23 {
24 throw armnn::Exception(
"ConvertLeakyReluToTosaOperator: 1 input tensors required.");
25 }
26
27 if (outputs.size() != 1)
28 {
29 throw armnn::Exception(
"ConvertLeakyReluToTosaOperator: 1 output tensor required.");
30 }
31
32 std::string inputName = std::string("input_");
35 std::string outputName = std::string("output0_");
37
38
39
40 if (layer != nullptr)
41 {
44 }
45
46 std::vector<TosaSerializationTensor*> tensors;
47
48
49
50
51 std::vector<int32_t> inputShape0;
52 DType inputDType0 =
ArmNNToDType(inputs[0]->GetDataType());
53 if(inputName.find("input_") != std::string::npos)
54 {
56 tensors.push_back(new TosaSerializationTensor(inputName, inputShape0, inputDType0, {}));
57 }
58
60 DType outputDType0 =
ArmNNToDType(outputs[0]->GetDataType());
61 tensors.push_back(new TosaSerializationTensor(outputName, outputShape0, outputDType0, {}));
62
63 if (inputDType0 == DType::DType_FP32 ||
64 inputDType0 == DType::DType_FP16)
65 {
66
67 TosaSerializationOperator* alphaOp = nullptr;
68 TosaSerializationTensor* alphaTensor = nullptr;
70 activationDescriptor->
m_A,
71 inputDType0,
72 inputShape0,
73 alphaOp,
74 alphaTensor);
75 tensors.push_back(alphaTensor);
76
77
78 int32_t shift = 0;
79 TosaMulAttribute mulAttribute(shift);
80 TosaSerializationOperator* mulOp = new TosaSerializationOperator(Op_MUL,
81 Attribute_MulAttribute,
82 &mulAttribute,
83 {inputName, outputNameAlpha},
84 {outputNameMul});
85 tensors.push_back(new TosaSerializationTensor(outputNameMul, inputShape0, inputDType0, {}));
86
87 TosaSerializationOperator* op = nullptr;
88 if (activationDescriptor->
m_A <= 1.0)
89 {
90 op = new TosaSerializationOperator(Op_MAXIMUM,
91 Attribute_NONE,
92 nullptr,
93 {inputName, outputNameMul},
94 {outputName});
95 }
96 else
97 {
98 op = new TosaSerializationOperator(Op_MINIMUM,
99 Attribute_NONE,
100 nullptr,
101 {inputName, outputNameMul},
102 {outputName});
103
104 }
105
106
107
108 return new TosaSerializationBasicBlock(blockName,
110 {alphaOp, mulOp, op},
111 tensors,
112 {inputName},
113 {outputName});
114 }
115 else
116 {
120
121 DType rescale_type = DType::DType_INT32;
122 float alpha = activationDescriptor->
m_A;
123 double scale_alpha = inputs[0]->GetQuantizationScale() * alpha / outputs[0]->GetQuantizationScale();
124 double scale_identity = inputs[0]->GetQuantizationScale() / outputs[0]->GetQuantizationScale();
125 int32_t input_zp = inputs[0]->GetQuantizationOffset();
126 int32_t output_zp = outputs[0]->GetQuantizationOffset();
127
128
129
130
131 TosaSerializationOperator* rescaleAlphaOp = nullptr;
133 outputNameRescaleAlpha,
134 scale_alpha,
135 input_zp,
136 0,
137 false,
138 false,
139 true,
140 true,
141 &rescaleAlphaOp);
142 tensors.push_back(new TosaSerializationTensor(outputNameRescaleAlpha,
144 rescale_type, {}));
145
146
147
148 TosaSerializationOperator* rescaleIdentityOp = nullptr;
150 outputNameRescaleIdentity,
151 scale_identity,
152 input_zp,
153 0,
154 false,
155 false,
156 true,
157 true,
158 &rescaleIdentityOp);
159 tensors.push_back(new TosaSerializationTensor(outputNameRescaleIdentity,
161 rescale_type, {}));
162
163
164
165
166
167
168
169
170
171
172
173
174 TosaSerializationOperator* op = nullptr;
175 if (alpha <= 1.0)
176 {
177 op = new TosaSerializationOperator(Op_MAXIMUM,
178 Attribute_NONE,
179 nullptr,
180 {outputNameRescaleAlpha, outputNameRescaleIdentity},
181 {outputNameRescaleMaxMin});
182 }
183 else
184 {
185 op = new TosaSerializationOperator(Op_MINIMUM,
186 Attribute_NONE,
187 nullptr,
188 {outputNameRescaleAlpha, outputNameRescaleIdentity},
189 {outputNameRescaleMaxMin});
190
191 }
192 tensors.push_back(new TosaSerializationTensor(outputNameRescaleMaxMin,
194 rescale_type, {}));
195
196
197
198 TosaSerializationOperator* rescaleOutputOp = nullptr;
200 outputName,
201 1.0,
202 0,
203 output_zp,
204 false,
205 false,
206 true,
207 true,
208 &rescaleOutputOp);
209
210
211
212 return new TosaSerializationBasicBlock(blockName,
214 {rescaleAlphaOp, rescaleIdentityOp, op, rescaleOutputOp},
215 tensors,
216 {inputName},
217 {outputName});
218 }
219}
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 CreateConstTosaOperator(const std::string &outputName, const T value, DType dtype, const std::vector< int32_t > &shape, TosaSerializationOperator *&op, TosaSerializationTensor *&tensor)
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.
float m_A
Alpha upper bound value used by the activation functions. (BoundedReLu, Linear, TanH,...