95 const float hiresInputScale = (1.0f / 128.0f) * inputScale;
96 const float outputMultiplier = hiresInputScale / outputScale;
97 int outputMultiplierExponent;
98 int16_t outputMultiplierFixedpointInt16;
99 int32_t outputMultiplierFixedpointInt32;
101 quantizeMultiplier(outputMultiplier, &outputMultiplierFixedpointInt32, &outputMultiplierExponent);
102 downScaleInt32ToInt16Multiplier(outputMultiplierFixedpointInt32, &outputMultiplierFixedpointInt16);
106 const float reluishScale = 3.0f / 32768.0f;
107 const float reluishMultiplier = hiresInputScale / reluishScale;
108 int reluishMultiplierExponent;
109 int16_t reluishMultiplierFixedpointInt16;
110 int32_t reluishMultiplierFixedpointInt32;
112 quantizeMultiplier(reluishMultiplier, &reluishMultiplierFixedpointInt32, &reluishMultiplierExponent);
113 downScaleInt32ToInt16Multiplier(reluishMultiplierFixedpointInt32, &reluishMultiplierFixedpointInt16);
115 std::vector<int16_t> table;
117 for (int32_t i = -128; i < 128; i++)
119 const int16_t inputValue =
static_cast<int16_t
>(i - inputZp);
120 const int16_t inputValueHiresInputScale =
static_cast<int16_t
>(inputValue * (1 << 7));
122 int16_t reluishValue = inputValueHiresInputScale;
123 if (reluishMultiplierExponent > 0)
125 reluishValue = gemmlowp::ShiftLeft(reluishValue, reluishMultiplierExponent - 1);
128 reluishValue = gemmlowp::SaturatingRoundingDoublingHighMul(reluishValue, reluishMultiplierFixedpointInt16);
130 if (reluishMultiplierExponent > 0)
132 reluishValue = gemmlowp::ShiftLeft(reluishValue, 1);
134 else if (reluishMultiplierExponent < 0)
136 reluishValue = gemmlowp::RoundingDivideByPOT(reluishValue, -reluishMultiplierExponent);
139 reluishValue =
static_cast<int16_t
>((reluishValue + (1 << 15)) >> 1);
141 const int16_t inputValPreshiftOutputScale =
142 gemmlowp::SaturatingRoundingDoublingHighMul(inputValueHiresInputScale, outputMultiplierFixedpointInt16);
144 const int16_t preshiftOutputValue = saturatingDoublingHighMul(reluishValue, inputValPreshiftOutputScale);
146 int16_t outputValue = gemmlowp::RoundingDivideByPOT(preshiftOutputValue, -outputMultiplierExponent);
148 outputValue =
static_cast<int16_t
>(outputValue + outputZp);
149 outputValue = std::min<int16_t>(outputValue, std::numeric_limits<int8_t>::max());
150 outputValue = std::max<int16_t>(outputValue, std::numeric_limits<int8_t>::min());
152 table.push_back(outputValue);
161 const std::vector<const TensorInfo*>& inputs,
162 const std::vector<const TensorInfo*>& outputs,
165 if (inputs.size() != 1)
167 throw armnn::Exception(
"ConvertHardSwishToTosaOperator: 1 input tensors required.");
170 if (outputs.size() != 1)
172 throw armnn::Exception(
"ConvertHardSwishToTosaOperator: 1 output tensor required.");
175 if (desc->
m_Function != ActivationFunction::HardSwish)
177 throw armnn::Exception(
"ConvertHardSwishToTosaOperator ActivationDescriptor only supports function HardSwish.");
180 std::string inputName = std::string(
"input_");
181 std::string outputName = std::string(
"output0_");
186 if (layer !=
nullptr)
192 std::vector<TosaSerializationTensor*> tensors;
193 std::vector<TosaSerializationOperator*> operators;
195 DataType inputDType = inputs[0]->GetDataType();
197 bool isInt8 = (inputDType == DataType::QAsymmS8 || inputDType == DataType::QSymmS8);
200 float inputScale = inputs[0]->GetQuantizationScale();
201 float outputScale = outputs[0]->GetQuantizationScale();
202 int32_t inputZp = inputs[0]->GetQuantizationOffset();
203 int32_t outputZp = outputs[0]->GetQuantizationOffset();
205 TosaTableAttribute attribute(
207 operators.push_back(
new TosaSerializationOperator(tosa::Op_TABLE,
208 Attribute_TableAttribute,
215 throw Exception(
"ConvertHardSwishToTosaOperator() type currently unimplemented.");
221 std::vector<int32_t> inputShape0;
222 DType inputDType0 =
ArmNNToDType(inputs[0]->GetDataType());
223 if(inputName.find(
"input_") != std::string::npos)
226 tensors.push_back(
new TosaSerializationTensor(inputName, inputShape0, inputDType0, {}));
230 DType outputDType0 =
ArmNNToDType(outputs[0]->GetDataType());
231 tensors.push_back(
new TosaSerializationTensor(outputName, outputShape0, outputDType0, {}));
235 return new TosaSerializationBasicBlock(blockName,