1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "fuzzing/operation_signatures/OperationSignatureUtils.h"
18
19 namespace android {
20 namespace nn {
21 namespace fuzzing_test {
22
elementwiseOpConstructor(TestOperandType dataType,uint32_t rank,RandomOperation * op)23 static void elementwiseOpConstructor(TestOperandType dataType, uint32_t rank, RandomOperation* op) {
24 sameShapeOpConstructor(dataType, rank, op);
25
26 switch (op->opType) {
27 case TestOperationType::RELU:
28 case TestOperationType::RELU6:
29 op->outputs[0]->valueProperties = RandomOperand::NON_NEGATIVE;
30 break;
31 case TestOperationType::LOGISTIC:
32 op->outputs[0]->valueProperties = RandomOperand::NON_ZERO | RandomOperand::NON_NEGATIVE;
33 break;
34 case TestOperationType::ABS:
35 op->outputs[0]->valueProperties = RandomOperand::NON_NEGATIVE;
36 break;
37 case TestOperationType::EXP:
38 op->outputs[0]->valueProperties = RandomOperand::NON_ZERO | RandomOperand::NON_NEGATIVE;
39 break;
40 case TestOperationType::LOG:
41 op->inputs[0]->valueProperties = RandomOperand::NON_ZERO | RandomOperand::NON_NEGATIVE;
42 break;
43 case TestOperationType::RSQRT:
44 op->inputs[0]->valueProperties = RandomOperand::NON_ZERO | RandomOperand::NON_NEGATIVE;
45 op->outputs[0]->valueProperties = RandomOperand::NON_ZERO | RandomOperand::NON_NEGATIVE;
46 break;
47 case TestOperationType::SQRT:
48 op->inputs[0]->valueProperties = RandomOperand::NON_NEGATIVE;
49 op->outputs[0]->valueProperties = RandomOperand::NON_NEGATIVE;
50 break;
51 default:
52 break;
53 }
54 }
55
56 #define DEFINE_ELEMENTWISE_SIGNATURE(op, ver, ...) \
57 DEFINE_OPERATION_SIGNATURE(op##_##ver){.opType = TestOperationType::op, \
58 .supportedDataTypes = {__VA_ARGS__}, \
59 .supportedRanks = {1, 2, 3, 4}, \
60 .version = TestHalVersion::ver, \
61 .inputs = {INPUT_DEFAULT}, \
62 .outputs = {OUTPUT_DEFAULT}, \
63 .constructor = elementwiseOpConstructor};
64
65 DEFINE_ELEMENTWISE_SIGNATURE(FLOOR, V1_0, TestOperandType::TENSOR_FLOAT32);
66 DEFINE_ELEMENTWISE_SIGNATURE(RELU, V1_0, TestOperandType::TENSOR_FLOAT32,
67 TestOperandType::TENSOR_QUANT8_ASYMM);
68 DEFINE_ELEMENTWISE_SIGNATURE(RELU1, V1_0, TestOperandType::TENSOR_FLOAT32,
69 TestOperandType::TENSOR_QUANT8_ASYMM);
70 DEFINE_ELEMENTWISE_SIGNATURE(RELU6, V1_0, TestOperandType::TENSOR_FLOAT32,
71 TestOperandType::TENSOR_QUANT8_ASYMM);
72 DEFINE_ELEMENTWISE_SIGNATURE(TANH, V1_0, TestOperandType::TENSOR_FLOAT32);
73 DEFINE_ELEMENTWISE_SIGNATURE(FLOOR, V1_2, TestOperandType::TENSOR_FLOAT16);
74 DEFINE_ELEMENTWISE_SIGNATURE(LOGISTIC, V1_2, TestOperandType::TENSOR_FLOAT16);
75 DEFINE_ELEMENTWISE_SIGNATURE(RELU, V1_2, TestOperandType::TENSOR_FLOAT16);
76 DEFINE_ELEMENTWISE_SIGNATURE(RELU1, V1_2, TestOperandType::TENSOR_FLOAT16);
77 DEFINE_ELEMENTWISE_SIGNATURE(RELU6, V1_2, TestOperandType::TENSOR_FLOAT16);
78 DEFINE_ELEMENTWISE_SIGNATURE(RELU, V1_3, TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED);
79 DEFINE_ELEMENTWISE_SIGNATURE(RELU1, V1_3, TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED);
80 DEFINE_ELEMENTWISE_SIGNATURE(RELU6, V1_3, TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED);
81 DEFINE_ELEMENTWISE_SIGNATURE(HARD_SWISH, V1_3, TestOperandType::TENSOR_FLOAT32,
82 TestOperandType::TENSOR_FLOAT16, TestOperandType::TENSOR_QUANT8_ASYMM);
83
84 #define DEFINE_ELEMENTWISE_SIGNATURE_WITH_RANK5(op, ver, ...) \
85 DEFINE_OPERATION_SIGNATURE(op##_##ver){.opType = TestOperationType::op, \
86 .supportedDataTypes = {__VA_ARGS__}, \
87 .supportedRanks = {1, 2, 3, 4, 5}, \
88 .version = TestHalVersion::ver, \
89 .inputs = {INPUT_DEFAULT}, \
90 .outputs = {OUTPUT_DEFAULT}, \
91 .constructor = elementwiseOpConstructor};
92
93 DEFINE_ELEMENTWISE_SIGNATURE_WITH_RANK5(ABS, V1_2, TestOperandType::TENSOR_FLOAT32,
94 TestOperandType::TENSOR_FLOAT16);
95 DEFINE_ELEMENTWISE_SIGNATURE_WITH_RANK5(EXP, V1_2, TestOperandType::TENSOR_FLOAT32,
96 TestOperandType::TENSOR_FLOAT16);
97 DEFINE_ELEMENTWISE_SIGNATURE_WITH_RANK5(NEG, V1_2, TestOperandType::TENSOR_FLOAT32,
98 TestOperandType::TENSOR_FLOAT16,
99 TestOperandType::TENSOR_INT32);
100 DEFINE_ELEMENTWISE_SIGNATURE_WITH_RANK5(SIN, V1_2, TestOperandType::TENSOR_FLOAT32,
101 TestOperandType::TENSOR_FLOAT16);
102 DEFINE_ELEMENTWISE_SIGNATURE_WITH_RANK5(LOGICAL_NOT, V1_2, TestOperandType::TENSOR_BOOL8);
103 DEFINE_ELEMENTWISE_SIGNATURE_WITH_RANK5(ABS, V1_3, TestOperandType::TENSOR_INT32);
104
105 DEFINE_ELEMENTWISE_SIGNATURE_WITH_RANK5(LOG, V1_2, TestOperandType::TENSOR_FLOAT32,
106 TestOperandType::TENSOR_FLOAT16);
107 DEFINE_ELEMENTWISE_SIGNATURE_WITH_RANK5(RSQRT, V1_2, TestOperandType::TENSOR_FLOAT32,
108 TestOperandType::TENSOR_FLOAT16);
109 DEFINE_ELEMENTWISE_SIGNATURE_WITH_RANK5(SQRT, V1_2, TestOperandType::TENSOR_FLOAT32,
110 TestOperandType::TENSOR_FLOAT16);
111
112 // Quantized operations with special output quantization parameters.
113 #define DEFINE_ELEMENTWISE_WITH_QUANT_OUTPUT_SIGNATURE(op, ver, s, z, ...) \
114 DEFINE_OPERATION_SIGNATURE(op##_##ver){.opType = TestOperationType::op, \
115 .supportedDataTypes = {__VA_ARGS__}, \
116 .supportedRanks = {1, 2, 3, 4}, \
117 .version = TestHalVersion::ver, \
118 .inputs = {INPUT_DEFAULT}, \
119 .outputs = {OUTPUT_QUANT((s), (z))}, \
120 .constructor = sameDimensionOpConstructor};
121
122 DEFINE_ELEMENTWISE_WITH_QUANT_OUTPUT_SIGNATURE(LOGISTIC, V1_0, /*scale=*/1.f / 256, /*zeroPoint=*/0,
123 TestOperandType::TENSOR_FLOAT32,
124 TestOperandType::TENSOR_QUANT8_ASYMM);
125 DEFINE_ELEMENTWISE_WITH_QUANT_OUTPUT_SIGNATURE(TANH, V1_2, /*scale=*/1.f / 128, /*zeroPoint=*/128,
126 TestOperandType::TENSOR_FLOAT16,
127 TestOperandType::TENSOR_QUANT8_ASYMM);
128 DEFINE_ELEMENTWISE_WITH_QUANT_OUTPUT_SIGNATURE(LOGISTIC, V1_3, /*scale=*/1.f / 256,
129 /*zeroPoint=*/-128,
130 TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED);
131 DEFINE_ELEMENTWISE_WITH_QUANT_OUTPUT_SIGNATURE(TANH, V1_3, /*scale=*/1.f / 128, /*zeroPoint=*/0,
132 TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED);
133
castingOpConstructor(TestOperandType dataType,uint32_t rank,RandomOperation * op)134 static void castingOpConstructor(TestOperandType dataType, uint32_t rank, RandomOperation* op) {
135 sameDimensionOpConstructor(dataType, rank, op);
136
137 // If it is casting to/from a FP16 data type, the source/destination should have a scale
138 // representable in FP16 to avoid precision loss.
139 if (op->inputs[0]->dataType == TestOperandType::TENSOR_FLOAT16) {
140 op->outputs[0]->scale = static_cast<_Float16>(op->outputs[0]->scale);
141 } else if (op->outputs[0]->dataType == TestOperandType::TENSOR_FLOAT16) {
142 op->inputs[0]->scale = static_cast<_Float16>(op->inputs[0]->scale);
143 }
144 }
145
146 // Operations with output data type different from input.
147 #define DEFINE_QUANTIZATION_OP_SIGNATURE(op, ver, outType, ...) \
148 DEFINE_OPERATION_SIGNATURE(op##_##outType##_##ver){ \
149 .opType = TestOperationType::op, \
150 .supportedDataTypes = {__VA_ARGS__}, \
151 .supportedRanks = {1, 2, 3, 4}, \
152 .version = TestHalVersion::ver, \
153 .inputs = {INPUT_DEFAULT}, \
154 .outputs = {OUTPUT_TYPED(TestOperandType::outType)}, \
155 .constructor = castingOpConstructor};
156
157 DEFINE_QUANTIZATION_OP_SIGNATURE(DEQUANTIZE, V1_0, /*outType=*/TENSOR_FLOAT32,
158 TestOperandType::TENSOR_QUANT8_ASYMM);
159
160 DEFINE_QUANTIZATION_OP_SIGNATURE(DEQUANTIZE, V1_2, /*outType=*/TENSOR_FLOAT32,
161 TestOperandType::TENSOR_QUANT8_SYMM);
162
163 DEFINE_QUANTIZATION_OP_SIGNATURE(DEQUANTIZE, V1_2, /*outType=*/TENSOR_FLOAT16,
164 TestOperandType::TENSOR_QUANT8_ASYMM,
165 TestOperandType::TENSOR_QUANT8_SYMM);
166
167 DEFINE_QUANTIZATION_OP_SIGNATURE(DEQUANTIZE, V1_3, /*outType=*/TENSOR_FLOAT32,
168 TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED);
169
170 DEFINE_QUANTIZATION_OP_SIGNATURE(DEQUANTIZE, V1_3, /*outType=*/TENSOR_FLOAT16,
171 TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED);
172
173 DEFINE_QUANTIZATION_OP_SIGNATURE(QUANTIZE, V1_2, /*outType=*/TENSOR_QUANT8_ASYMM,
174 TestOperandType::TENSOR_FLOAT32, TestOperandType::TENSOR_FLOAT16);
175
176 DEFINE_QUANTIZATION_OP_SIGNATURE(QUANTIZE, V1_3,
177 /*outType=*/TENSOR_QUANT8_ASYMM_SIGNED,
178 TestOperandType::TENSOR_FLOAT32, TestOperandType::TENSOR_FLOAT16);
179
180 #define DEFINE_CAST_SIGNATURE(ver, outType, ...) \
181 DEFINE_OPERATION_SIGNATURE(CAST_##outType##_##ver){ \
182 .opType = TestOperationType::CAST, \
183 .supportedDataTypes = {__VA_ARGS__}, \
184 .supportedRanks = {1, 2, 3, 4, 5}, \
185 .version = TestHalVersion::ver, \
186 .inputs = {INPUT_DEFAULT}, \
187 .outputs = {OUTPUT_TYPED(TestOperandType::outType)}, \
188 .constructor = castingOpConstructor};
189
190 DEFINE_CAST_SIGNATURE(V1_2, /*outType=*/TENSOR_FLOAT32, TestOperandType::TENSOR_FLOAT32,
191 TestOperandType::TENSOR_FLOAT16, TestOperandType::TENSOR_QUANT8_ASYMM,
192 TestOperandType::TENSOR_INT32);
193
194 DEFINE_CAST_SIGNATURE(V1_2, /*outType=*/TENSOR_FLOAT16, TestOperandType::TENSOR_FLOAT32,
195 TestOperandType::TENSOR_FLOAT16, TestOperandType::TENSOR_QUANT8_ASYMM,
196 TestOperandType::TENSOR_INT32);
197
198 DEFINE_CAST_SIGNATURE(V1_2, /*outType=*/TENSOR_QUANT8_ASYMM, TestOperandType::TENSOR_FLOAT32,
199 TestOperandType::TENSOR_FLOAT16, TestOperandType::TENSOR_QUANT8_ASYMM,
200 TestOperandType::TENSOR_INT32);
201
202 DEFINE_CAST_SIGNATURE(V1_2, /*outType=*/TENSOR_INT32, TestOperandType::TENSOR_FLOAT32,
203 TestOperandType::TENSOR_FLOAT16, TestOperandType::TENSOR_QUANT8_ASYMM,
204 TestOperandType::TENSOR_INT32);
205
206 DEFINE_CAST_SIGNATURE(V1_3, /*outType=*/TENSOR_BOOL8, TestOperandType::TENSOR_BOOL8);
207 DEFINE_CAST_SIGNATURE(V1_3, /*outType=*/TENSOR_INT32, TestOperandType::TENSOR_INT32);
208 DEFINE_CAST_SIGNATURE(V1_3, /*outType=*/TENSOR_QUANT16_ASYMM,
209 TestOperandType::TENSOR_QUANT16_ASYMM);
210 DEFINE_CAST_SIGNATURE(V1_3, /*outType=*/TENSOR_QUANT16_SYMM, TestOperandType::TENSOR_QUANT16_SYMM);
211 DEFINE_CAST_SIGNATURE(V1_3, /*outType=*/TENSOR_QUANT8_ASYMM_SIGNED,
212 TestOperandType::TENSOR_QUANT8_ASYMM_SIGNED);
213 DEFINE_CAST_SIGNATURE(V1_3, /*outType=*/TENSOR_QUANT8_SYMM, TestOperandType::TENSOR_QUANT8_SYMM);
214
DEFINE_OPERATION_SIGNATURE(ELU_V1_3)215 DEFINE_OPERATION_SIGNATURE(ELU_V1_3){
216 .opType = TestOperationType::ELU,
217 .supportedDataTypes = {TestOperandType::TENSOR_FLOAT32, TestOperandType::TENSOR_FLOAT16},
218 .supportedRanks = {1, 2, 3, 4, 5},
219 .version = TestHalVersion::V1_3,
220 .inputs = {INPUT_DEFAULT, PARAMETER_FLOAT_RANGE(0.0f, 10.0f)},
221 .outputs = {OUTPUT_DEFAULT},
222 .constructor = sameDimensionOpConstructor};
223
224 } // namespace fuzzing_test
225 } // namespace nn
226 } // namespace android
227