1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 /*!
21  * \file tvm/relay/qnn/attrs.h
22  * \brief Auxiliary attributes for qnn operators.
23  */
24 #ifndef TVM_RELAY_QNN_ATTRS_H_
25 #define TVM_RELAY_QNN_ATTRS_H_
26 
27 #include <tvm/attrs.h>
28 #include <string>
29 
30 namespace tvm {
31 namespace relay {
32 namespace qnn {
33 
34 /*! \brief Attribute for requantize operator */
35 struct RequantizeAttrs : public tvm::AttrsNode<RequantizeAttrs> {
36   double input_scale;
37   int32_t input_zero_point;
38   double output_scale;
39   int32_t output_zero_point;
40   std::string rounding;
41   DataType out_dtype;
42 
43   TVM_DECLARE_ATTRS(RequantizeAttrs, "relay.attrs.RequantizeAttrs") {
44     TVM_ATTR_FIELD(input_scale)
45         .describe("The scale of the input tensor.");
46     TVM_ATTR_FIELD(input_zero_point)
47         .describe("The zero point of the input tensor.");
48     TVM_ATTR_FIELD(output_scale)
49         .describe("The scale of the output tensor.");
50     TVM_ATTR_FIELD(output_zero_point)
51         .describe("The zero point of the output tensor.");
52     TVM_ATTR_FIELD(rounding).set_default("UPWARD")
53         .describe("Defines the rounding direction when the value is midway between"
54                   "two representable values. There are two supported modes - UPWARD"
55                   "or TONEAREST. Both modes behave exactly same except at the"
56                   "midpoints between the two representable values. At the midpoint,"
57                   "UPWARD rounds towards positive infinity (for example -1.5 will be"
58                   "rounded to -1). TONEAREST is the standard rounding where the"
59                   "value is rounded away from zero at midpoints (for example, -1.5"
60                   "rounds to -2). More context can be found at following gblic manual"
61                   "https://www.gnu.org/software/libc/manual/html_node/Rounding.html.");
62     TVM_ATTR_FIELD(out_dtype)
63         .set_default(NullValue<DataType>())
64         .describe("Output data type, set to explicit type under mixed precision setting");
65   }
66 };
67 
68 /*! \brief Attribute for quantize operator */
69 struct QuantizeAttrs : public tvm::AttrsNode<QuantizeAttrs> {
70   int32_t output_zero_point;
71   double output_scale;
72   DataType out_dtype;
73 
74   TVM_DECLARE_ATTRS(QuantizeAttrs, "relay.attrs.QuantizeAttrs") {
75     TVM_ATTR_FIELD(out_dtype)
76       .describe("Output data type, can be one of [int8 or uint8].");
77     TVM_ATTR_FIELD(output_zero_point)
78       .describe("The zero_point for the activation of this op.");
79     TVM_ATTR_FIELD(output_scale)
80       .describe("The scale for the activation of this op.");
81   }
82 };
83 
84 /*! \brief Attribute for dequantize operator */
85 struct DequantizeAttrs : public tvm::AttrsNode<DequantizeAttrs> {
86   int32_t input_zero_point;
87   double input_scale;
88 
89   TVM_DECLARE_ATTRS(DequantizeAttrs, "relay.attrs.DequantizeAttrs") {
90     TVM_ATTR_FIELD(input_zero_point)
91       .describe("The zero_point for the input tensor of this op.");
92     TVM_ATTR_FIELD(input_scale)
93       .describe("The scale for the input tensor of this op.");
94   }
95 };
96 
97 /*! \brief Attributes used in QNN concatenate operator */
98 struct QnnConcatenateAttrs : public tvm::AttrsNode<QnnConcatenateAttrs> {
99   Array<tvm::Expr> input_scales;
100   Array<tvm::Expr> input_zero_points;
101   double output_scale;
102   int32_t output_zero_point;
103   int axis;
104 
105   TVM_DECLARE_ATTRS(QnnConcatenateAttrs, "relay.attrs.QnnConcatenateAttrs") {
106     TVM_ATTR_FIELD(input_scales)
107         .describe("The list of scales of input quantized tensors.");
108     TVM_ATTR_FIELD(input_zero_points)
109         .describe("The list of zero points of input quantized tensors.");
110     TVM_ATTR_FIELD(output_zero_point)
111       .describe("The zero_point for the output tensor.");
112     TVM_ATTR_FIELD(output_scale)
113       .describe("The scale for the output tensor.");
114     TVM_ATTR_FIELD(axis)
115         .describe("The axis at which the input arrays are concatenated."
116                   "Should lie in range `[-ndim, ndim)`.")
117         .set_default(0);
118   }
119 };  // struct QnnConcatenateAttrs
120 
121 /*! \brief Attribute for QNN Conv2d operator */
122 struct QnnConv2DAttrs : public tvm::AttrsNode<QnnConv2DAttrs> {
123   // Traditional conv2d attributes.
124   Array<IndexExpr> strides;
125   Array<IndexExpr> padding;
126   Array<IndexExpr> dilation;
127   int groups;
128   IndexExpr channels;
129   Array<IndexExpr> kernel_size;
130   std::string data_layout;
131   std::string kernel_layout;
132   std::string out_layout;
133   DataType out_dtype;
134 
135   // Quantization related attributes.
136   int32_t input_zero_point;
137   int32_t kernel_zero_point;
138   // The input tensor scale and kernel tensor scales are stored
139   // for easy access to this information.
140   double input_scale;
141   double kernel_scale;
142 
143   TVM_DECLARE_ATTRS(QnnConv2DAttrs, "relay.attrs.QnnConv2DAttrs") {
144     TVM_ATTR_FIELD(strides).set_default(Array<IndexExpr>({1, 1}))
145         .describe("Specifies the strides of the convolution.");
146     TVM_ATTR_FIELD(padding).set_default(Array<IndexExpr>({0, 0}))
147         .describe("If padding is non-zero, then the input is implicitly zero-padded"
148                   "on both sides for padding number of points");
149     TVM_ATTR_FIELD(dilation).set_default(Array<IndexExpr>({1, 1}))
150         .describe("Specifies the dilation rate to use for dilated convolution.");
151     TVM_ATTR_FIELD(groups).set_default(1)
152         .describe("Controls the connections between inputs and outputs."
153                   "At groups=1, all inputs are convolved to all outputs."
154                   "At groups=2, the operation becomes equivalent to having two convolution"
155                   "layers side by side, each seeing half the input channels, and producing"
156                   "half the output channels, and both subsequently concatenated.");
157     TVM_ATTR_FIELD(channels)
158         .describe("The number of output channels in the convolution."
159                   " If it is not set, inferred by shape of the weight.")
160         .set_default(NullValue<IndexExpr>());
161     TVM_ATTR_FIELD(kernel_size)
162         .describe("Specifies the dimensions of the convolution window.")
163         .set_default(NullValue<Array<IndexExpr> >());
164     TVM_ATTR_FIELD(data_layout).set_default("NCHW")
165         .describe("Dimension ordering of input data. Can be 'NCHW', 'NHWC', etc."
166                   "'N', 'C', 'H', 'W' stands for batch, channel, height, and width"
167                   "dimensions respectively. Convolution is applied on the 'H' and"
168                   "'W' dimensions.");
169     TVM_ATTR_FIELD(kernel_layout).set_default("OIHW")
170         .describe("Dimension ordering of weight. Can be 'OIHW', 'OIHW16o16i', etc."
171                   "'O', 'I', 'H', 'W' stands for num_filter, input_channel, height, and width"
172                   "dimensions respectively.");
173     TVM_ATTR_FIELD(out_layout).set_default("")
174         .describe("Dimension ordering of output. Can be 'NCHW', 'NHWC', etc."
175                   "'N', 'C', 'H', 'W' stands for batch, channel, height, and width"
176                   "dimensions respectively. Default to be same as input layout.");
177     TVM_ATTR_FIELD(out_dtype)
178         .set_default(NullValue<DataType>())
179         .describe("Output data type, set to explicit type under mixed precision setting");
180     TVM_ATTR_FIELD(input_zero_point)
181         .describe("The zero point of the input tensor.");
182     TVM_ATTR_FIELD(kernel_zero_point)
183         .describe("The zero point of the kernel tensor.");
184     TVM_ATTR_FIELD(input_scale)
185       .describe("The quantization scale for the input tensor.");
186     TVM_ATTR_FIELD(kernel_scale)
187       .describe("The quantization scale for the weight tensor.");
188   }
189 };
190 
191 /*! \brief Attribute for QNN binary operator */
192 struct QnnBinaryOpAttrs : public tvm::AttrsNode<QnnBinaryOpAttrs> {
193   int32_t lhs_zero_point;
194   double lhs_scale;
195   int32_t rhs_zero_point;
196   double rhs_scale;
197   int32_t output_zero_point;
198   double output_scale;
199 
200   TVM_DECLARE_ATTRS(QnnBinaryOpAttrs, "relay.attrs.QnnBinaryOpAttrs") {
201     TVM_ATTR_FIELD(lhs_zero_point)
202       .describe("The zero_point for the lhs input tensor of this op.");
203     TVM_ATTR_FIELD(lhs_scale)
204       .describe("The scale for the lhs input tensor of this op.");
205     TVM_ATTR_FIELD(rhs_zero_point)
206       .describe("The zero_point for the rhs input tensor of this op.");
207     TVM_ATTR_FIELD(rhs_scale)
208       .describe("The scale for the rhs input tensor of this op.");
209     TVM_ATTR_FIELD(output_zero_point)
210       .describe("The zero_point for the activation of this op.");
211     TVM_ATTR_FIELD(output_scale)
212       .describe("The scale for the activation of this op.");
213   }
214 };
215 
216 /*! \brief Attributes for qnn dense operator */
217 struct QnnDenseAttrs : public tvm::AttrsNode<QnnDenseAttrs> {
218   IndexExpr units;
219   DataType out_dtype;
220   // Quantization related attributes.
221   int32_t input_zero_point;
222   int32_t kernel_zero_point;
223   double input_scale;
224   double kernel_scale;
225 
226   TVM_DECLARE_ATTRS(QnnDenseAttrs, "relay.attrs.QnnDenseAttrs") {
227     TVM_ATTR_FIELD(units)
228       .describe("Number of hidden units of the dense transformation.");
229     TVM_ATTR_FIELD(out_dtype)
230       .describe("Output data type, set to explicit type under mixed precision setting");
231     TVM_ATTR_FIELD(input_zero_point)
232       .describe("The zero point of the input tensor.");
233     TVM_ATTR_FIELD(kernel_zero_point)
234       .describe("The zero point of the kernel tensor.");
235     TVM_ATTR_FIELD(input_scale)
236       .describe("The input tensor scale.");
237     TVM_ATTR_FIELD(kernel_scale)
238       .describe("The kernel tensor scale.");
239   }
240 };
241 
242 }  // namespace qnn
243 }  // namespace relay
244 }  // namespace tvm
245 #endif  // TVM_RELAY_QNN_ATTRS_H_
246