aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Johnson <jeremy.johnson@arm.com>2021-09-07 13:59:47 +0100
committerJeremy Johnson <jeremy.johnson@arm.com>2021-09-15 17:26:44 +0100
commitef509a45670c206416ddad7b3eed5eb880c5bca8 (patch)
tree2bbe6291b3669173ce8708d59d6e8c04caf7d858
parentb227ae5ff22411c3f7c82e2b4b5a4618008e897a (diff)
downloadreference_model-ef509a45670c206416ddad7b3eed5eb880c5bca8.tar.gz
Fix for ADD/SUB saturation in tests
Change-Id: I4f05b256f4f439f72e5ee8bce60e4e92b6aaa6e7 Signed-off-by: Jeremy Johnson <jeremy.johnson@arm.com>
-rw-r--r--verif/tosa_test_gen.py62
1 files changed, 60 insertions, 2 deletions
diff --git a/verif/tosa_test_gen.py b/verif/tosa_test_gen.py
index 942f75c..3e14c5b 100644
--- a/verif/tosa_test_gen.py
+++ b/verif/tosa_test_gen.py
@@ -1969,8 +1969,66 @@ class TosaTestGen:
# Build the random tensor operands and the test
tens = []
- # If test is ArithmeticRightShift, force value of operand[1] to be within [0, num_bits]
- if op["op"] == Op.ARITHMETIC_RIGHT_SHIFT:
+ if (op["op"] == Op.ADD or op["op"] == Op.SUB) and dtypeList[0] == DType.INT32:
+ # Make sure the operation does not cause value saturation - where
+ # the number wraps due to limited number of bits to store the answer
+ assert (
+ pCount == 2 and cCount == 0
+ ), "Op.ADD / Op.SUB must have 2 placeholders, 0 consts"
+
+ placeholders = []
+ add = (op["op"] == Op.ADD)
+ a_arr = self.getRandTensor(shapeList[0], dtypeList[0])
+ b_arr = self.getRandTensor(shapeList[1], dtypeList[1])
+ if add:
+ res_arr = np.add(a_arr, b_arr, dtype=np.int64)
+ else:
+ res_arr = np.subtract(a_arr, b_arr, dtype=np.int64)
+
+ # Work out the saturation limits
+ max_i32 = (1 << 31)-1
+ min_i32 = -(1 << 31)
+ max_arr = np.full(shapeList[1], max_i32)
+ min_arr = np.full(shapeList[1], min_i32)
+
+ # Find how much values exceed the maximum/minimums
+ sat_max_arr = np.maximum(res_arr - max_arr, 0)
+ sat_min_arr = np.minimum(res_arr - min_arr, 0)
+
+ if not add:
+ # Swap saturation values and negate values as we need to perform opposite operations
+ sat_max_arr, sat_min_arr = -sat_min_arr, -sat_max_arr
+
+ # Create new array of unsaturated values by clipping values as needed
+ b_unsat_arr = b_arr
+ if (sat_max_arr != 0).any():
+ # Clip values that cause saturation
+ b_unsat_arr = np.subtract(b_unsat_arr, sat_max_arr, dtype=np.int32)
+ # Reduce axes in unsaturated tensor to match original tensor
+ for axis, dim in enumerate(b_arr.shape):
+ if dim != b_unsat_arr.shape[axis]:
+ assert ( dim == 1 ), "Op.ADD / SUB dimension must be 1 or matching to be broadcastable"
+ b_unsat_arr = np.amin(b_unsat_arr, axis=axis, keepdims=True)
+
+ if (sat_min_arr != 0).any():
+ # Clip values that cause saturation
+ b_unsat_arr = np.subtract(b_unsat_arr, sat_min_arr, dtype=np.int32)
+ # Reduce axes in unsaturated tensor to match original tensor
+ for axis, dim in enumerate(b_arr.shape):
+ if dim != b_unsat_arr.shape[axis]:
+ assert ( dim == 1 ), "Op.ADD / SUB dimension must be 1 or matching to be broadcastable"
+ b_unsat_arr = np.amax(b_unsat_arr, axis=axis, keepdims=True)
+
+ placeholders.append(
+ self.ser.addPlaceholder(shapeList[0], dtypeList[0], a_arr)
+ )
+ placeholders.append(
+ self.ser.addPlaceholder(shapeList[1], dtypeList[1], b_unsat_arr)
+ )
+
+ tens.extend(placeholders)
+ elif op["op"] == Op.ARITHMETIC_RIGHT_SHIFT:
+ # Force value of operand[1] to be within [0, num_bits]
assert (
pCount == 2 and cCount == 0
), "Op.ArithmeticRightShift must have 2 placeholders, 0 consts"