Main Compliance testing support for LOG and ACTIVATIONs
Increase exp2 allowed range to account for denormals.
Minor adjustments to verify to match spec updates for pseudo code.
Set ranges of activation function inputs to match spec.
Signed-off-by: Jeremy Johnson <jeremy.johnson@arm.com>
Change-Id: I6fcf665932ac2c9080e284b865da8f7746801f59
diff --git a/reference_model/src/generate/generate_utils.cc b/reference_model/src/generate/generate_utils.cc
index 5546269..d2168c9 100644
--- a/reference_model/src/generate/generate_utils.cc
+++ b/reference_model/src/generate/generate_utils.cc
@@ -43,11 +43,14 @@
{ Op::Op_ARGMAX, "ARGMAX" },
{ Op::Op_AVG_POOL2D, "AVG_POOL2D" },
{ Op::Op_CEIL, "CEIL" },
+ { Op::Op_CLAMP, "CLAMP" },
{ Op::Op_CONV2D, "CONV2D" },
+ { Op::Op_ERF, "ERF" },
{ Op::Op_EXP, "EXP" },
{ Op::Op_FLOOR, "FLOOR" },
{ Op::Op_FULLY_CONNECTED, "FULLY_CONNECTED" },
{ Op::Op_IDENTITY, "IDENTITY" },
+ { Op::Op_LOG, "LOG" },
{ Op::Op_MATMUL, "MATMUL" },
{ Op::Op_MAXIMUM, "MAXIMUM" },
{ Op::Op_MAX_POOL2D, "MAX_POOL2D" },
@@ -61,7 +64,9 @@
{ Op::Op_REDUCE_MAX, "REDUCE_MAX" },
{ Op::Op_REDUCE_MIN, "REDUCE_MIN" },
{ Op::Op_REDUCE_SUM, "REDUCE_SUM" },
+ { Op::Op_SIGMOID, "SIGMOID" },
{ Op::Op_SUB, "SUB" },
+ { Op::Op_TANH, "TANH" },
})
} // namespace tosa
diff --git a/reference_model/src/verify/verify_abs_error.cc b/reference_model/src/verify/verify_abs_error.cc
index 1afa7fd..b43da08 100644
--- a/reference_model/src/verify/verify_abs_error.cc
+++ b/reference_model/src/verify/verify_abs_error.cc
@@ -32,7 +32,7 @@
for (size_t i = 0; i < T; ++i)
{
- double errBound = ref[i] * exp2(-AccPrecision<float>::normal_frac) * bnd[i];
+ double errBound = std::abs(ref[i]) * exp2(-AccPrecision<float>::normal_frac) * bnd[i];
bool valid = tosaCheckFloatBound(imp[i], ref[i], errBound);
if (!valid)
{
diff --git a/reference_model/src/verify/verify_ulp.cc b/reference_model/src/verify/verify_ulp.cc
index b333810..6e78b96 100644
--- a/reference_model/src/verify/verify_ulp.cc
+++ b/reference_model/src/verify/verify_ulp.cc
@@ -30,15 +30,8 @@
double errorBound = 0.0;
if (std::isfinite(referenceValue) && std::abs(referenceValue) != 0.0)
{
- // Make the sign of the reference value positive
- // and adjust the test value appropriately.
- if (referenceValue < 0)
- {
- referenceValue = -referenceValue;
- testValue = -testValue;
- }
// Find the exponent of the reference value.
- int32_t referenceExponent = ilog2(referenceValue);
+ int32_t referenceExponent = ilog2(std::abs(referenceValue));
// Work out the values magnitude - by raising 2 to the power of the
// exponent and taking the normalized minimum for denormal values
diff --git a/reference_model/src/verify/verify_utils.cc b/reference_model/src/verify/verify_utils.cc
index 414f7d7..9aa6ba2 100644
--- a/reference_model/src/verify/verify_utils.cc
+++ b/reference_model/src/verify/verify_utils.cc
@@ -170,7 +170,11 @@
// Like const_exp2 but for use during runtime
double exp2(int32_t n)
{
- TOSA_REF_REQUIRE(-1022 <= n && n <= 1023, " Invalid exponent value (%d) in exp2", n);
+ if (n < -1075)
+ {
+ return 0.0; // smaller than smallest denormal
+ }
+ TOSA_REF_REQUIRE(n <= 1023, " Invalid exponent value (%d) in exp2", n);
return const_exp2(n);
}
@@ -212,6 +216,9 @@
return false;
}
+ // Check the errorBound
+ TOSA_REF_REQUIRE(errorBound >= 0.f, " Invalid error bound (%g)", errorBound);
+
// Make the sign of the reference value positive
// and adjust the test value appropriately.
if (referenceValue < 0)
@@ -219,10 +226,6 @@
referenceValue = -referenceValue;
testValue = -testValue;
}
- if (errorBound < 0)
- {
- errorBound = -errorBound;
- }
// At this point we are ready to calculate the ULP bounds for the reference value.
double referenceMin, referenceMax;
diff --git a/verif/conformance/tosa_main_profile_ops_info.json b/verif/conformance/tosa_main_profile_ops_info.json
index 87b14c2..35d72e8 100644
--- a/verif/conformance/tosa_main_profile_ops_info.json
+++ b/verif/conformance/tosa_main_profile_ops_info.json
@@ -403,6 +403,7 @@
"profile": [
"tosa-mi"
],
+ "support_for": [ "lazy_data_gen" ],
"generation": {
"standard": {
"generator_args": [
@@ -414,7 +415,7 @@
"--target-dtype",
"bf16",
"--fp-values-range",
- "-2.0,2.0",
+ "-max,max",
"--tensor-dim-range",
"20,64",
"--target-rank",
@@ -432,7 +433,7 @@
"--target-dtype",
"bf16",
"--fp-values-range",
- "-2.0,2.0",
+ "-max,max",
"--tensor-dim-range",
"1,20",
"--target-rank",
@@ -444,7 +445,7 @@
"--target-dtype",
"fp32",
"--fp-values-range",
- "-2.0,2.0",
+ "-max,max",
"--target-shape",
"1,2,1,65536",
"--target-shape",
@@ -1369,6 +1370,7 @@
"profile": [
"tosa-mi"
],
+ "support_for": [ "lazy_data_gen" ],
"generation": {
"standard": {
"generator_args": [
@@ -1382,7 +1384,7 @@
"--target-dtype",
"bf16",
"--fp-values-range",
- "-2.0,2.0",
+ "-max,max",
"--tensor-dim-range",
"15,64",
"--target-rank",
@@ -1398,7 +1400,7 @@
"--target-dtype",
"fp32",
"--fp-values-range",
- "-2.0,2.0",
+ "-max,max",
"--tensor-dim-range",
"1,15",
"--target-rank",
@@ -1412,7 +1414,7 @@
"--target-dtype",
"fp16",
"--fp-values-range",
- "-2.0,2.0",
+ "-max,max",
"--target-shape",
"1,65530,1,2",
"--target-shape",
@@ -2748,6 +2750,7 @@
"profile": [
"tosa-mi"
],
+ "support_for": [ "lazy_data_gen" ],
"generation": {
"standard": {
"generator_args": [
@@ -2759,7 +2762,7 @@
"--target-dtype",
"bf16",
"--fp-values-range",
- "-2.0,2.0",
+ "-16.0,16.0",
"--tensor-dim-range",
"16,64",
"--target-rank",
@@ -2777,7 +2780,7 @@
"--target-dtype",
"bf16",
"--fp-values-range",
- "-2.0,2.0",
+ "-16.0,16.0",
"--tensor-dim-range",
"1,19",
"--target-rank",
@@ -2789,7 +2792,7 @@
"--target-dtype",
"fp32",
"--fp-values-range",
- "-2.0,2.0",
+ "-16.0,16.0",
"--target-shape",
"1,2,65538,2,1",
"--target-shape",
@@ -2946,6 +2949,7 @@
"profile": [
"tosa-mi"
],
+ "support_for": [ "lazy_data_gen" ],
"generation": {
"standard": {
"generator_args": [
@@ -2957,7 +2961,7 @@
"--target-dtype",
"bf16",
"--fp-values-range",
- "-2.0,2.0",
+ "-8.0,8.0",
"--tensor-dim-range",
"18,60",
"--target-rank",
@@ -2975,7 +2979,7 @@
"--target-dtype",
"bf16",
"--fp-values-range",
- "-2.0,2.0",
+ "-8.0,8.0",
"--tensor-dim-range",
"1,24",
"--target-rank",
@@ -2987,7 +2991,7 @@
"--target-dtype",
"fp32",
"--fp-values-range",
- "-2.0,2.0",
+ "-8.0,8.0",
"--target-shape",
"1,65535,2,1,1",
"--target-shape",
@@ -3011,6 +3015,7 @@
"profile": [
"tosa-mi"
],
+ "support_for": [ "lazy_data_gen" ],
"generation": {
"standard": {
"generator_args": [
@@ -3022,7 +3027,7 @@
"--target-dtype",
"bf16",
"--fp-values-range",
- "-2.0,2.0",
+ "-4.0,4.0",
"--tensor-dim-range",
"18,60",
"--target-rank",
@@ -3040,7 +3045,7 @@
"--target-dtype",
"bf16",
"--fp-values-range",
- "-2.0,2.0",
+ "-4.0,4.0",
"--tensor-dim-range",
"1,24",
"--target-rank",
@@ -3052,7 +3057,7 @@
"--target-dtype",
"fp32",
"--fp-values-range",
- "-2.0,2.0",
+ "-4.0,4.0",
"--target-shape",
"1,65535,2,1,1",
"--target-shape",
diff --git a/verif/generator/tosa_test_gen.py b/verif/generator/tosa_test_gen.py
index 9f65fd4..04093b8 100644
--- a/verif/generator/tosa_test_gen.py
+++ b/verif/generator/tosa_test_gen.py
@@ -405,13 +405,9 @@
self.ser.addOperator(op["op"], input_list, output_list, attr)
- if op["op"] in (Op.LOG,):
- # TODO - add compliance support LOG
- compliance = None
- else:
- compliance = self.tensorComplianceMetaData(
- op, a.dtype, args_dict, result_tensor, error_name
- )
+ compliance = self.tensorComplianceMetaData(
+ op, a.dtype, args_dict, result_tensor, error_name
+ )
return TosaTestGen.BuildInfo(result_tensor, compliance)
def build_binary_broadcast(
@@ -1241,8 +1237,13 @@
return TosaTestGen.BuildInfo(result_tensor, compliance)
- def build_clamp(self, op, a, validator_fcns=None, error_name=None):
- result_tens = OutputShaper.unaryOp(self.ser, self.rng, a, error_name)
+ def build_clamp(
+ self, op, inputs, args_dict, validator_fcns=None, error_name=None, qinfo=None
+ ):
+ assert len(inputs) == 1
+ a = inputs[0]
+
+ result_tensor = OutputShaper.unaryOp(self.ser, self.rng, a, error_name)
v = [self.getRandNumberDType(a.dtype), self.getRandNumberDType(a.dtype)]
@@ -1258,7 +1259,7 @@
# Invalidate Input/Output list for error if checks.
input_list = [a.name]
- output_list = [result_tens.name]
+ output_list = [result_tensor.name]
pCount, cCount = op["operands"]
num_operands = pCount + cCount
input_list, output_list = TosaErrorIfArgGen.eiInvalidateInputOutputList(
@@ -1273,10 +1274,10 @@
max_val=max_val,
min_val=min_val,
input_shape=a.shape,
- output_shape=result_tens.shape,
+ output_shape=result_tensor.shape,
input_dtype=a.dtype,
- output_dtype=result_tens.dtype,
- result_tensors=[result_tens],
+ output_dtype=result_tensor.dtype,
+ result_tensors=[result_tensor],
input_list=input_list,
output_list=output_list,
num_operands=num_operands,
@@ -1295,7 +1296,12 @@
attr.ClampAttribute(self.ser.builder, min_val, max_val, 0, 0)
self.ser.addOperator(op["op"], input_list, output_list, attr)
- return result_tens
+
+ compliance = self.tensorComplianceMetaData(
+ op, a.dtype, args_dict, result_tensor, error_name
+ )
+
+ return TosaTestGen.BuildInfo(result_tensor, compliance)
def build_leaky_relu(self, op, a, validator_fcns=None, error_name=None):
result_tens = OutputShaper.unaryOp(self.ser, self.rng, a, error_name)
@@ -1313,12 +1319,17 @@
self.ser.addOperator(op["op"], [a.name], [result_tens.name])
return result_tens
- def build_sigmoid(self, op, a, validator_fcns=None, error_name=None):
- result_tens = OutputShaper.unaryOp(self.ser, self.rng, a, error_name)
+ def build_activation(
+ self, op, inputs, args_dict, validator_fcns=None, error_name=None, qinfo=None
+ ):
+ assert len(inputs) == 1
+ a = inputs[0]
+
+ result_tensor = OutputShaper.unaryOp(self.ser, self.rng, a, error_name)
# Invalidate Input/Output list for error if checks.
input_list = [a.name]
- output_list = [result_tens.name]
+ output_list = [result_tensor.name]
pCount, cCount = op["operands"]
num_operands = pCount + cCount
input_list, output_list = TosaErrorIfArgGen.eiInvalidateInputOutputList(
@@ -1331,10 +1342,10 @@
error_name,
op=op,
input_shape=a.shape,
- output_shape=result_tens.shape,
+ output_shape=result_tensor.shape,
input_dtype=a.dtype,
- output_dtype=result_tens.dtype,
- result_tensors=[result_tens],
+ output_dtype=result_tensor.dtype,
+ result_tensors=[result_tensor],
input_list=input_list,
output_list=output_list,
num_operands=num_operands,
@@ -1342,69 +1353,12 @@
return None
self.ser.addOperator(op["op"], input_list, output_list)
- return result_tens
- def build_tanh(self, op, a, validator_fcns=None, error_name=None):
- result_tens = OutputShaper.unaryOp(self.ser, self.rng, a, error_name)
-
- # Invalidate Input/Output list for error if checks.
- input_list = [a.name]
- output_list = [result_tens.name]
- pCount, cCount = op["operands"]
- num_operands = pCount + cCount
- input_list, output_list = TosaErrorIfArgGen.eiInvalidateInputOutputList(
- self, error_name, input_list, output_list
+ compliance = self.tensorComplianceMetaData(
+ op, a.dtype, args_dict, result_tensor, error_name
)
- if not TosaErrorValidator.evValidateErrorIfs(
- self.ser,
- validator_fcns,
- error_name,
- op=op,
- input_shape=a.shape,
- output_shape=result_tens.shape,
- input_dtype=a.dtype,
- output_dtype=result_tens.dtype,
- result_tensors=[result_tens],
- input_list=input_list,
- output_list=output_list,
- num_operands=num_operands,
- ):
- return None
-
- self.ser.addOperator(op["op"], input_list, output_list)
- return result_tens
-
- def build_erf(self, op, a, validator_fcns=None, error_name=None):
- result_tens = OutputShaper.unaryOp(self.ser, self.rng, a, error_name)
-
- # Invalidate Input/Output list for error if checks.
- input_list = [a.name]
- output_list = [result_tens.name]
- pCount, cCount = op["operands"]
- num_operands = pCount + cCount
- input_list, output_list = TosaErrorIfArgGen.eiInvalidateInputOutputList(
- self, error_name, input_list, output_list
- )
-
- if not TosaErrorValidator.evValidateErrorIfs(
- self.ser,
- validator_fcns,
- error_name,
- op=op,
- input_shape=a.shape,
- output_shape=result_tens.shape,
- input_dtype=a.dtype,
- output_dtype=result_tens.dtype,
- result_tensors=[result_tens],
- input_list=input_list,
- output_list=output_list,
- num_operands=num_operands,
- ):
- return None
-
- self.ser.addOperator(op["op"], input_list, output_list)
- return result_tens
+ return TosaTestGen.BuildInfo(result_tensor, compliance)
def build_concat(
self, op, inputs, args_dict, validator_fcns=None, error_name=None, qinfo=None
@@ -3220,8 +3174,8 @@
"build_fcn": (
build_clamp,
TosaTensorGen.tgBasic,
- TosaTensorValuesGen.tvgDefault,
- None,
+ TosaTensorValuesGen.tvgLazyGenDefault,
+ TosaArgGen.agNone,
),
"types": TYPE_NARROW_INT_FP,
"error_if_validators": (
@@ -3231,15 +3185,18 @@
TosaErrorValidator.evWrongInputList,
TosaErrorValidator.evWrongOutputList,
),
+ "data_gen": {
+ "fp": (gtu.DataGenType.PSEUDO_RANDOM,),
+ },
},
"sigmoid": {
"op": Op.SIGMOID,
"operands": (1, 0),
"build_fcn": (
- build_sigmoid,
+ build_activation,
TosaTensorGen.tgBasic,
- TosaTensorValuesGen.tvgDefault,
- None,
+ TosaTensorValuesGen.tvgLazyGenDefault,
+ TosaArgGen.agNone,
),
"types": TYPE_FP,
"error_if_validators": (
@@ -3248,15 +3205,19 @@
TosaErrorValidator.evWrongInputList,
TosaErrorValidator.evWrongOutputList,
),
+ "data_gen": {
+ "fp": (gtu.DataGenType.PSEUDO_RANDOM,),
+ },
+ "compliance": {"ulp": 5},
},
"tanh": {
"op": Op.TANH,
"operands": (1, 0),
"build_fcn": (
- build_tanh,
+ build_activation,
TosaTensorGen.tgBasic,
- TosaTensorValuesGen.tvgDefault,
- None,
+ TosaTensorValuesGen.tvgLazyGenDefault,
+ TosaArgGen.agNone,
),
"types": TYPE_FP,
"error_if_validators": (
@@ -3265,15 +3226,19 @@
TosaErrorValidator.evWrongInputList,
TosaErrorValidator.evWrongOutputList,
),
+ "data_gen": {
+ "fp": (gtu.DataGenType.PSEUDO_RANDOM,),
+ },
+ "compliance": {"ulp": 5},
},
"erf": {
"op": Op.ERF,
"operands": (1, 0),
"build_fcn": (
- build_erf,
+ build_activation,
TosaTensorGen.tgBasic,
- TosaTensorValuesGen.tvgDefault,
- None,
+ TosaTensorValuesGen.tvgLazyGenDefault,
+ TosaArgGen.agNone,
),
"types": TYPE_FP,
"error_if_validators": (
@@ -3282,6 +3247,10 @@
TosaErrorValidator.evWrongInputList,
TosaErrorValidator.evWrongOutputList,
),
+ "data_gen": {
+ "fp": (gtu.DataGenType.PSEUDO_RANDOM,),
+ },
+ "compliance": {"ulp": 5},
},
# Elementwise Binary Operators
"add": {
@@ -3778,6 +3747,10 @@
TosaErrorValidator.evWrongInputList,
TosaErrorValidator.evWrongOutputList,
),
+ "data_gen": {
+ "fp": (gtu.DataGenType.PSEUDO_RANDOM,),
+ },
+ "compliance": {"ulp": 5},
},
"logical_not": {
"op": Op.LOGICAL_NOT,