a5bbe1691a5f35ca8472f4f9e4dd32fa1c78b9cb
[platform/core/ml/nnfw.git] / runtime / onert / backend / acl_common / Convert.cc
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
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 "Convert.h"
18
19 #include "Swizzle.h"
20 #include "ir/DataType.h"
21 #include <memory>
22
23 namespace
24 {
25
26 ::arm_compute::DataLayout asDataLayout(onert::ir::Layout layout)
27 {
28   switch (layout)
29   {
30     case onert::ir::Layout::NHWC:
31       return ::arm_compute::DataLayout::NHWC;
32     case onert::ir::Layout::NCHW:
33       return ::arm_compute::DataLayout::NCHW;
34     default:
35       return ::arm_compute::DataLayout::UNKNOWN;
36   }
37 }
38
39 } // namespace
40
41 namespace onert
42 {
43 namespace backend
44 {
45 namespace acl_common
46 {
47
48 ::arm_compute::TensorShape asTensorShape(const ir::Shape &shape, ir::Layout frontend_layout,
49                                          ir::Layout backend_layout, bool apply_dim_correction)
50 {
51   // If shape's rank is 0, the tensor is a scalar
52   // Sometimes, some ACL kernel can use a scalar as tensor. But ACL does not allocate buffer for
53   // tensor having rank as 0.
54   const auto tensor_shape = shape.rank() == 0 ? ir::Shape{1} : shape;
55
56   const uint32_t rank = tensor_shape.rank();
57
58   ::arm_compute::TensorShape res{};
59
60   res.set_num_dimensions(rank);
61
62   for (uint32_t axis = 0; axis < rank; ++axis)
63   {
64     // NOTE In some cases, in incorrect dimensions is required.
65     // For example, intput_size is 1 in LSTM. The input-to-input weights([num_units, input_size]) of
66     // LSTM is used as the weight of the FullyConnected.
67     // The FullyConnected's weight must be greater or equal than 2-dimensions.
68     // However, if the dimension correction is applied to input_to_input_weights with input_size
69     // equal to 1, it will be changed to 1-D.
70     // So input_to_input_weights is not used by the weight of FullyConnected.
71     res.set(ToARMComputeAxis(rank, axis, frontend_layout, backend_layout).value(),
72             tensor_shape.dim(axis), apply_dim_correction);
73   }
74
75   return res;
76 }
77
78 ::arm_compute::Coordinates asTensorCoordinate(const ir::Coordinates &coord,
79                                               ir::Layout frontend_layout, ir::Layout backend_layout)
80 {
81   const uint32_t rank = coord.size();
82
83   ::arm_compute::Coordinates res{};
84
85   res.set_num_dimensions(rank);
86
87   for (uint32_t axis = 0; axis < rank; ++axis)
88   {
89     res.set(ToARMComputeAxis(rank, axis, frontend_layout, backend_layout).value(), coord[axis]);
90   }
91
92   return res;
93 }
94
95 ::arm_compute::DataType asDataType(const ir::DataType type)
96 {
97   switch (type)
98   {
99     case ir::DataType::FLOAT32:
100       return ::arm_compute::DataType::F32;
101     case ir::DataType::INT32:
102       return ::arm_compute::DataType::S32;
103     case ir::DataType::UINT32:
104       return ::arm_compute::DataType::U32;
105     case ir::DataType::QUANT_UINT8_ASYMM:
106       return ::arm_compute::DataType::QASYMM8;
107     case ir::DataType::BOOL8:
108     case ir::DataType::UINT8:
109       return ::arm_compute::DataType::U8;
110     case ir::DataType::QUANT_INT8_SYMM:
111       return ::arm_compute::DataType::S8;
112     case ir::DataType::FLOAT16:
113       return ::arm_compute::DataType::F16;
114     default:
115       throw std::runtime_error("Not supported, yet");
116       break;
117   }
118 }
119
120 ::arm_compute::QuantizationInfo asQuantizationInfo(const float scale, const int32_t offset)
121 {
122   return ::arm_compute::QuantizationInfo(scale, offset);
123 }
124
125 ::arm_compute::TensorInfo asTensorInfo(const ir::Shape &shape, const ir::TypeInfo &typeInfo,
126                                        ir::Layout frontend_layout, ir::Layout backend_layout,
127                                        bool apply_dim_correction)
128 {
129   ::arm_compute::TensorInfo info(
130       asTensorShape(shape, frontend_layout, backend_layout, apply_dim_correction), 1,
131       asDataType(typeInfo.type()), asQuantizationInfo(typeInfo.scale(), typeInfo.offset()));
132   info.set_data_layout(asDataLayout(backend_layout));
133   return info;
134 }
135
136 ::arm_compute::PadStrideInfo asPadStrideInfo(const ir::ExplicitPadding &padding,
137                                              const ir::Stride &stride)
138 {
139   return ::arm_compute::PadStrideInfo{stride.horizontal,
140                                       stride.vertical,
141                                       padding.left,
142                                       padding.right,
143                                       padding.top,
144                                       padding.bottom,
145                                       ::arm_compute::DimensionRoundingType::FLOOR};
146 }
147
148 ::arm_compute::ActivationLayerInfo asActivationLayerInfo(const ir::Activation act_code)
149 {
150   switch (act_code)
151   {
152     case ir::Activation::NONE:
153       return ::arm_compute::ActivationLayerInfo{};
154     case ir::Activation::RELU:
155       return ::arm_compute::ActivationLayerInfo{
156           ::arm_compute::ActivationLayerInfo::ActivationFunction::RELU};
157     case ir::Activation::RELU1:
158       return ::arm_compute::ActivationLayerInfo{
159           ::arm_compute::ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, 1.0f, -1.0f};
160     case ir::Activation::RELU6:
161       return ::arm_compute::ActivationLayerInfo{
162           ::arm_compute::ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, 6.0f, 0.0f};
163     // Cases for activation of LSTM.
164     case ir::Activation::TANH:
165       return ::arm_compute::ActivationLayerInfo{
166           ::arm_compute::ActivationLayerInfo::ActivationFunction::TANH, 1.0f, 1.0f};
167     case ir::Activation::SIGMOID:
168       // NOTE The sigmoid function is a special case of the Logistic function when L=1, k=1, x0=0.
169       // TODO In ACL and nnapi sepc, currently, Logistic's L always is 1, k always is 1, x0 always
170       // 0(always sigmoid) regardless of values of the parameter.
171       //      If ACL support non-sigmoid logistic, should fix param values.
172       return ::arm_compute::ActivationLayerInfo{
173           ::arm_compute::ActivationLayerInfo::ActivationFunction::LOGISTIC, 0.0f, 0.0f};
174     default:
175       throw std::runtime_error{"Not supported, yet"};
176       break;
177   }
178 }
179
180 arm_compute::Coordinates asCoordinates(const ir::Operand &operand, int32_t rank,
181                                        ir::Layout frontend_layout, ir::Layout backend_layout)
182 {
183   std::set<uint32_t> axes = asSet(operand, rank, frontend_layout, backend_layout);
184
185   arm_compute::Coordinates reduce_axes;
186   for (const int32_t axis : axes)
187   {
188     reduce_axes.set(reduce_axes.num_dimensions(), axis);
189   }
190
191   return reduce_axes;
192 }
193
194 std::set<uint32_t> asSet(const ir::Operand &operand, int32_t rank, ir::Layout frontend_layout,
195                          ir::Layout backend_layout)
196 {
197   std::set<std::uint32_t> axes;
198
199   for (size_t i = 0; i < operand.shape().num_elements(); ++i)
200   {
201     int32_t axis = 0;
202     switch (operand.typeInfo().type())
203     {
204       case ir::DataType::INT32:
205         axis = reinterpret_cast<const int32_t *>(operand.data()->base())[i];
206         break;
207       case ir::DataType::INT64:
208         axis = reinterpret_cast<const int64_t *>(operand.data()->base())[i];
209         break;
210       default:
211         throw std::runtime_error("acl_common::asSet: Not supported data type");
212     }
213     if (axis < 0)
214       axis += rank;
215     axes.insert(ToARMComputeAxis(rank, axis, frontend_layout, backend_layout).value());
216   }
217
218   return axes;
219 }
220
221 std::unique_ptr<AclFunction> asAclFunction(std::unique_ptr<::arm_compute::IFunction> &&layer)
222 {
223   return std::make_unique<AclFunction>(std::move(layer));
224 }
225
226 std::unique_ptr<AclClFunction> asAclClFunction(std::unique_ptr<::arm_compute::IFunction> &&layer)
227 {
228   return std::make_unique<AclClFunction>(std::move(layer));
229 }
230
231 ir::Layout asRuntimeLayout(::arm_compute::DataLayout data_layout)
232 {
233   switch (data_layout)
234   {
235     case ::arm_compute::DataLayout::NHWC:
236       return ir::Layout::NHWC;
237     case ::arm_compute::DataLayout::NCHW:
238       return ir::Layout::NCHW;
239     default:
240       return ir::Layout::UNKNOWN;
241   }
242 }
243
244 ir::DataType asRuntimeDataType(::arm_compute::DataType data_type)
245 {
246   switch (data_type)
247   {
248     case ::arm_compute::DataType::F32:
249       return ir::DataType::FLOAT32;
250     case ::arm_compute::DataType::S32:
251       return ir::DataType::INT32;
252     case ::arm_compute::DataType::U32:
253       return ir::DataType::UINT32;
254     case ::arm_compute::DataType::QASYMM8:
255       return ir::DataType::QUANT_UINT8_ASYMM;
256     case ::arm_compute::DataType::U8:
257       return ir::DataType::UINT8;
258     case ::arm_compute::DataType::QSYMM8:
259       return ir::DataType::QUANT_INT8_SYMM;
260     case ::arm_compute::DataType::F16:
261       return ir::DataType::FLOAT16;
262     default:
263       throw std::runtime_error{"Not supported, yet"};
264       break;
265   }
266 }
267
268 arm_compute::ReduceOperation convertReduceType(ir::operation::Reduce::ReduceType reduce_type_ir)
269 {
270   switch (reduce_type_ir)
271   {
272     case ir::operation::Reduce::ReduceType::MAX:
273       return arm_compute::ReduceOperation::MAX;
274     case ir::operation::Reduce::ReduceType::MIN:
275       return arm_compute::ReduceOperation::MIN;
276     case ir::operation::Reduce::ReduceType::SUM:
277       return arm_compute::ReduceOperation::SUM;
278     default:
279       throw std::runtime_error("convertReduceType: Not supported operation yet");
280   }
281 }
282
283 } // namespace acl_common
284 } // namespace backend
285 } // namespace onert