aboutsummaryrefslogtreecommitdiff
path: root/src/backends/tosaCommon/operatorMappings/TosaRescaleOperatorUtils.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/backends/tosaCommon/operatorMappings/TosaRescaleOperatorUtils.hpp')
-rw-r--r--src/backends/tosaCommon/operatorMappings/TosaRescaleOperatorUtils.hpp130
1 files changed, 130 insertions, 0 deletions
diff --git a/src/backends/tosaCommon/operatorMappings/TosaRescaleOperatorUtils.hpp b/src/backends/tosaCommon/operatorMappings/TosaRescaleOperatorUtils.hpp
new file mode 100644
index 0000000000..a0432846f5
--- /dev/null
+++ b/src/backends/tosaCommon/operatorMappings/TosaRescaleOperatorUtils.hpp
@@ -0,0 +1,130 @@
+//
+// Copyright © 2024 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include <armnn/Exceptions.hpp>
+
+#pragma once
+
+inline void CreateRescaleTosaOperator(const std::string& inputName,
+ const std::string& outputName,
+ DType output_type,
+ const std::vector<int32_t>& shape,
+ int32_t scale_multiplier,
+ int32_t scale_shift,
+ int32_t input_zp,
+ int32_t output_zp,
+ bool double_round,
+ bool scale32,
+ TosaSerializationOperator** op,
+ TosaSerializationTensor** tensor)
+{
+ if (!op)
+ {
+ throw armnn::Exception("CreateRescaleTosaOperator: nullptr op");
+ }
+
+ std::vector<int32_t> multipliers{scale_multiplier};
+ std::vector<int32_t> shifts{scale_shift};
+ TosaRescaleAttribute attribute(input_zp,
+ output_zp,
+ multipliers,
+ shifts,
+ scale32,
+ double_round,
+ false);
+
+ // op
+ *op = new TosaSerializationOperator(Op_RESCALE, Attribute_RescaleAttribute, &attribute, {inputName}, {outputName});
+ if (!(*op))
+ {
+ throw armnn::Exception("CreateRescaleTosaOperator: failed to created operator");
+ }
+ if (tensor != nullptr)
+ {
+ // tensor
+ *tensor = new TosaSerializationTensor(outputName, shape, output_type, {});
+ if (! (*tensor))
+ {
+ throw armnn::Exception("CreateRescaleTosaOperator: failed to created tensor");
+ }
+ }
+}
+
+inline void CreateRescaleTosaOperator(const std::string& inputName,
+ const std::string& outputName,
+ DType output_type,
+ const std::vector<int32_t>& shape,
+ double scale,
+ int32_t input_zp,
+ int32_t output_zp,
+ bool double_round,
+ bool scale32,
+ TosaSerializationOperator** op,
+ TosaSerializationTensor** tensor)
+{
+ // The code that follows is based on the behaviour specified in
+ // https://www.mlplatform.org/tosa/tosa_spec.html#_precision_scaling
+
+ auto GetScaleParams = [](double scale, double& m, int32_t& n)
+ {
+ m = 0;
+ n = 0;
+
+ double lastErr = 1e06;
+
+ const int32_t numExponents = 62;
+ const double start = 1.0;
+ const double end = 2.0;
+
+ // Slow iterative approach but running in Reference only
+ for (int32_t i = 0; i < numExponents; ++i)
+ {
+ double exp = 1.0 / (1 << i);
+ double currentM = scale / exp; // Find current m given value = currentM * exp
+ if ((currentM >= start) && (currentM < end))
+ {
+ double value = currentM * exp;
+ double err = std::abs(scale - value);
+ if (err < lastErr)
+ {
+ // Take the m, n that minimize the error
+ n = i;
+ m = currentM;
+ lastErr = err;
+ }
+ }
+ }
+ };
+
+ auto GetMultiplierShiftByScale = [GetScaleParams](bool scale32, double scale, int32_t& multiplier, int32_t& shift)
+ {
+ double m = 0;
+ int32_t n = 0;
+
+ GetScaleParams(scale, m, n);
+
+ multiplier = (scale32) ? (1 << 30) * static_cast<int32_t>(m) : (1 << 14) * static_cast<int32_t>(m);
+ shift = (scale32) ? (30 + n) : (14 + n);
+ };
+
+ int32_t multiplier;
+ int32_t shift;
+ GetMultiplierShiftByScale(scale32, scale, multiplier, shift);
+ CreateRescaleTosaOperator(inputName, outputName, output_type, shape, multiplier, shift,
+ input_zp, output_zp, double_round, scale32, op, tensor);
+}
+
+inline void CreateFromInt32RescaleTosaOperator(const std::string& inputName,
+ const std::string& outputName,
+ DType output_type,
+ const std::vector<int32_t>& shape,
+ double output_scale,
+ int32_t output_zp,
+ TosaSerializationOperator** op,
+ TosaSerializationTensor** tensor)
+{
+ CreateRescaleTosaOperator(inputName, outputName, output_type, shape,
+ output_scale, 0, output_zp, true, true, op, tensor);
+}