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
broadcastOpConstructor(Type dataType,uint32_t rank,RandomOperation * op)23 static void broadcastOpConstructor(Type dataType, uint32_t rank, RandomOperation* op) {
24 // TODO: All inputs of the broadcast op have the same rank 4 for now.
25 op->inputs[0]->dimensions.resize(rank);
26 op->inputs[1]->dimensions.resize(rank);
27 op->outputs[0]->dimensions.resize(rank);
28 for (uint32_t i = 0; i < rank; i++) {
29 if (getBernoulli(0.9f)) {
30 op->inputs[0]->dimensions[i] = RandomVariableType::FREE;
31 } else {
32 op->inputs[0]->dimensions[i] = 1;
33 }
34 if (getBernoulli(0.9f)) {
35 op->inputs[1]->dimensions[i] = op->inputs[0]->dimensions[i];
36 } else {
37 op->inputs[1]->dimensions[i] = 1;
38 }
39 op->outputs[0]->dimensions[i] =
40 max(op->inputs[0]->dimensions[i], op->inputs[1]->dimensions[i]);
41 }
42
43 // MUL requires output.scale > input0.scale * input1.scale.
44 if (dataType == Type::TENSOR_QUANT8_ASYMM && op->opType == ANEURALNETWORKS_MUL) {
45 float minScale = op->inputs[0]->scale * op->inputs[1]->scale;
46 op->outputs[0]->scale = getUniform(minScale, minScale * 5);
47 }
48
49 // DIV and POW may produce Inf output values. We should not connect this output tensor to the
50 // input of another operation.
51 if (op->opType == ANEURALNETWORKS_DIV || op->opType == ANEURALNETWORKS_POW) {
52 op->outputs[0]->doNotConnect = true;
53 }
54 }
55
56 // For broadcast operations with fused activation.
57 #define DEFINE_BROADCAST_WITH_ACT_SIGNATURE(op, ver, ...) \
58 DEFINE_OPERATION_SIGNATURE(op##_##ver){ \
59 .opType = ANEURALNETWORKS_##op, \
60 .supportedDataTypes = {__VA_ARGS__}, \
61 .supportedRanks = {1, 2, 3, 4}, \
62 .version = HalVersion::ver, \
63 .inputs = {INPUT_DEFAULT, INPUT_DEFAULT, PARAMETER_CHOICE(Type::INT32, 0, 1, 2, 3)}, \
64 .outputs = {OUTPUT_DEFAULT}, \
65 .constructor = broadcastOpConstructor};
66
67 // Arithmetic with activation.
68 DEFINE_BROADCAST_WITH_ACT_SIGNATURE(ADD, V1_0, Type::TENSOR_FLOAT32, Type::TENSOR_QUANT8_ASYMM);
69 DEFINE_BROADCAST_WITH_ACT_SIGNATURE(MUL, V1_0, Type::TENSOR_FLOAT32, Type::TENSOR_QUANT8_ASYMM);
70 DEFINE_BROADCAST_WITH_ACT_SIGNATURE(SUB, V1_1, Type::TENSOR_FLOAT32);
71 DEFINE_BROADCAST_WITH_ACT_SIGNATURE(DIV, V1_1, Type::TENSOR_FLOAT32);
72 DEFINE_BROADCAST_WITH_ACT_SIGNATURE(ADD, V1_2, Type::TENSOR_FLOAT16);
73 DEFINE_BROADCAST_WITH_ACT_SIGNATURE(MUL, V1_2, Type::TENSOR_FLOAT16);
74 DEFINE_BROADCAST_WITH_ACT_SIGNATURE(SUB, V1_2, Type::TENSOR_FLOAT16, Type::TENSOR_QUANT8_ASYMM);
75 DEFINE_BROADCAST_WITH_ACT_SIGNATURE(DIV, V1_2, Type::TENSOR_FLOAT16);
76
77 // For broadcast ops with output of the same data type as inputs.
78 #define DEFINE_BROADCAST_SIGNATURE(op, ver, ...) \
79 DEFINE_OPERATION_SIGNATURE(op##_##ver){.opType = ANEURALNETWORKS_##op, \
80 .supportedDataTypes = {__VA_ARGS__}, \
81 .supportedRanks = {1, 2, 3, 4, 5}, \
82 .version = HalVersion::ver, \
83 .inputs = {INPUT_DEFAULT, INPUT_DEFAULT}, \
84 .outputs = {OUTPUT_DEFAULT}, \
85 .constructor = broadcastOpConstructor};
86
87 // Arithmetic without activation.
88 DEFINE_BROADCAST_SIGNATURE(POW, V1_2, Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16);
89 DEFINE_BROADCAST_SIGNATURE(PRELU, V1_2, Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16,
90 Type::TENSOR_QUANT8_ASYMM);
91 DEFINE_BROADCAST_SIGNATURE(MAXIMUM, V1_2, Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16,
92 Type::TENSOR_QUANT8_ASYMM, Type::TENSOR_INT32);
93 DEFINE_BROADCAST_SIGNATURE(MINIMUM, V1_2, Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16,
94 Type::TENSOR_QUANT8_ASYMM, Type::TENSOR_INT32);
95
96 // Logical
97 DEFINE_BROADCAST_SIGNATURE(LOGICAL_AND, V1_2, Type::TENSOR_BOOL8);
98 DEFINE_BROADCAST_SIGNATURE(LOGICAL_OR, V1_2, Type::TENSOR_BOOL8);
99
100 // Comparisons
101 #define DEFINE_COMPARISON_SIGNATURE(op, ver, ...) \
102 DEFINE_OPERATION_SIGNATURE(op##_##ver){.opType = ANEURALNETWORKS_##op, \
103 .supportedDataTypes = {__VA_ARGS__}, \
104 .supportedRanks = {1, 2, 3, 4}, \
105 .version = HalVersion::ver, \
106 .inputs = {INPUT_DEFAULT, INPUT_DEFAULT}, \
107 .outputs = {OUTPUT_TYPED(Type::TENSOR_BOOL8)}, \
108 .constructor = broadcastOpConstructor};
109
110 DEFINE_COMPARISON_SIGNATURE(EQUAL, V1_2, Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16,
111 Type::TENSOR_INT32, Type::TENSOR_QUANT8_ASYMM, Type::TENSOR_BOOL8);
112 DEFINE_COMPARISON_SIGNATURE(GREATER, V1_2, Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16,
113 Type::TENSOR_INT32, Type::TENSOR_QUANT8_ASYMM);
114 DEFINE_COMPARISON_SIGNATURE(GREATER_EQUAL, V1_2, Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16,
115 Type::TENSOR_INT32, Type::TENSOR_QUANT8_ASYMM);
116 DEFINE_COMPARISON_SIGNATURE(LESS, V1_2, Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16,
117 Type::TENSOR_INT32, Type::TENSOR_QUANT8_ASYMM);
118 DEFINE_COMPARISON_SIGNATURE(LESS_EQUAL, V1_2, Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16,
119 Type::TENSOR_INT32, Type::TENSOR_QUANT8_ASYMM);
120 DEFINE_COMPARISON_SIGNATURE(NOT_EQUAL, V1_2, Type::TENSOR_FLOAT32, Type::TENSOR_FLOAT16,
121 Type::TENSOR_INT32, Type::TENSOR_QUANT8_ASYMM, Type::TENSOR_BOOL8);
122
123 } // namespace fuzzing_test
124 } // namespace nn
125 } // namespace android
126