22 if (inputs.size() != 1)
24 throw armnn::Exception(
"ConvertReluToTosaOperator: 1 input tensors required.");
27 if (outputs.size() != 1)
29 throw armnn::Exception(
"ConvertReluToTosaOperator: 1 output tensor required.");
32 std::string inputName = std::string(
"input_");
33 std::string outputName = std::string(
"output0_");
44 std::vector<TosaSerializationTensor*> tensors;
45 std::vector<TosaSerializationOperator*> operators;
51 DType inputDType0 =
ArmNNToDType(inputs[0]->GetDataType());
52 if(inputName.find(
"input_") != std::string::npos)
54 tensors.push_back(
new TosaSerializationTensor(inputName, inputShape0, inputDType0, {}));
58 DType outputDType0 =
ArmNNToDType(outputs[0]->GetDataType());
59 tensors.push_back(
new TosaSerializationTensor(outputName, outputShape0, outputDType0, {}));
61 int32_t clamp_min = 0;
62 int32_t clamp_max = 0;
63 float float_max = 0.0f;
64 switch (desc->m_Function)
66 case ActivationFunction::ReLu:
68 clamp_max = std::numeric_limits<int32_t>::max();
69 float_max = std::numeric_limits<float>::max();
72 case ActivationFunction::BoundedReLu:
74 clamp_max =
static_cast<int32_t
>(desc->m_A);
75 float_max = desc->m_A;
78 case ActivationFunction::LeakyReLu:
80 throw Exception(
"LeakyRelu TOSA mappings are performed in ConvertLeakyReluToTosaOperator().");
84 throw Exception(
"Activation function is not supported in ConvertReluToTosaOperator().");
88 std::string clampInputNameStr = inputName;
89 if (inputDType0 == tosa::DType::DType_INT8 || inputDType0 == tosa::DType::DType_INT16)
92 clampInputNameStr = outputNameRescale;
94 double scale = inputs[0]->GetQuantizationScale() / outputs[0]->GetQuantizationScale();
95 int32_t input_zp = inputs[0]->GetQuantizationOffset();
96 int32_t output_zp = outputs[0]->GetQuantizationOffset();
98 clamp_min = output_zp;
100 if (desc->m_Function == ActivationFunction::BoundedReLu)
102 clamp_max =
static_cast<int32_t
>(std::round(desc->m_A / outputs[0]->GetQuantizationScale())) + output_zp;
105 if (inputDType0 == tosa::DType::DType_INT8)
108 clamp_min < std::numeric_limits<int8_t>::min() ? std::numeric_limits<int8_t>::min() : clamp_min;
110 clamp_max > std::numeric_limits<int8_t>::max() ? std::numeric_limits<int8_t>::max() : clamp_max;
115 clamp_min < std::numeric_limits<int16_t>::min() ? std::numeric_limits<int16_t>::min() : clamp_min;
117 clamp_max > std::numeric_limits<int16_t>::max() ? std::numeric_limits<int16_t>::max() : clamp_max;
120 TosaSerializationOperator* rescaleOp =
nullptr;
131 operators.push_back(rescaleOp);
132 tensors.push_back(
new TosaSerializationTensor(outputNameRescale,
138 TosaClampAttribute attribute(clamp_min, clamp_max, 0, float_max);
139 auto* clamp_op =
new TosaSerializationOperator(Op_CLAMP,
140 Attribute_ClampAttribute,
144 operators.push_back(clamp_op);
148 return new TosaSerializationBasicBlock(blockName,
std::string GenerateUniqueOutputName(const Layer &layer, uint32_t layerSlot=0)
const std::string mainName
DType ArmNNToDType(const DataType &type)
std::vector< int32_t > GetTosaTensorShape(const TensorShape &shape)
std::string GenerateUniqueInputName(const armnn::InputSlot &slot)
std::string GetUniqueTosaMappingID()
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)
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.