blob: 647f88f0e29950988757d9219f618a217c5c0e25 [file] [log] [blame]
Georgios Pinitas407c3e62017-10-25 18:26:46 +01001/*
2 * Copyright (c) 2017 ARM Limited.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#include "arm_compute/core/CL/ICLTensor.h"
25#include "arm_compute/core/Error.h"
26#include "arm_compute/graph/IOperation.h"
27#include "arm_compute/graph/NodeContext.h"
28#include "arm_compute/graph/OperationRegistrar.h"
29#include "arm_compute/graph/Types.h"
30#include "arm_compute/runtime/CL/CLFunctions.h"
31#include "support/ToolchainSupport.h"
32#include "utils/GraphTypePrinter.h"
33#include "utils/TypePrinter.h"
34
35#include <memory>
36
37using namespace arm_compute::graph;
38
39/* Activation Layer */
40REGISTER_SIMPLE_OPERATION(CLActivationLayerOperation, OPENCL, OperationType::ActivationLayer)
41{
42 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 1);
43 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
44 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
45 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
46
47 // Extract IO and info
48 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
49 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
50 const auto act_info = ctx.parameter<ActivationLayerInfo>("ActivationLayerInfo");
51
52 // Create and configure function
53 auto activation = arm_compute::support::cpp14::make_unique<arm_compute::CLActivationLayer>();
54 activation->configure(in, out, act_info);
55
56 // Log info
57 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLActivationLayer"
58 << " Data Type: " << in->info()->data_type()
59 << " Input shape: " << in->info()->tensor_shape()
60 << " Output shape: " << out->info()->tensor_shape()
61 << " Activation function: " << act_info.activation()
62 << " a: " << act_info.a()
63 << " b: " << act_info.b()
64 << std::endl);
65
66 return std::move(activation);
67}
68
69/* Batch Normalization Layer */
70REGISTER_SIMPLE_OPERATION(CLBatchNormalizationLayerOperation, OPENCL, OperationType::BatchNormalizationLayer)
71{
72 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 5);
73 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
74 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
75 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(1)) == nullptr);
76 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(2)) == nullptr);
77 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(3)) == nullptr);
78 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(4)) == nullptr);
79 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
80
81 // Extract IO and info
82 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
83 auto *mean = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(1));
84 auto *var = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(2));
85 auto *beta = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(3));
86 auto *gamma = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(4));
87 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
88 const auto epsilon = ctx.parameter<float>("epsilon");
89
90 // Create and configure function
91 auto batch_norm = arm_compute::support::cpp14::make_unique<arm_compute::CLBatchNormalizationLayer>();
92 batch_norm->configure(in, out, mean, var, beta, gamma, epsilon);
93
94 // Log info
95 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLBatchNormalizationLayer"
96 << " Data Type: " << in->info()->data_type()
97 << " Input shape: " << in->info()->tensor_shape()
98 << " Output shape: " << out->info()->tensor_shape()
99 << " Mean shape: " << mean->info()->tensor_shape()
100 << " Var shape: " << var->info()->tensor_shape()
101 << " Beta shape: " << beta->info()->tensor_shape()
102 << " Gamma shape: " << gamma->info()->tensor_shape()
103 << " Epsilon: " << epsilon
104 << std::endl);
105
106 return std::move(batch_norm);
107}
108
Michalis Spyrou27c9efb2017-10-09 15:46:30 +0100109/* DepthConvert Layer */
110REGISTER_SIMPLE_OPERATION(CLDepthConvertLayerOperation, OPENCL, OperationType::DepthConvertLayer)
111{
112 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 1);
113 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
114 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
115 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
116
117 // Extract IO and info
118 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
119 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
120 const auto conv_policy = ctx.parameter<ConvertPolicy>("ConvertPolicy");
121 const auto shift = ctx.parameter<uint32_t>("shift");
122
123 // Create and configure function
124 auto depthconvert = arm_compute::support::cpp14::make_unique<arm_compute::CLDepthConvert>();
125 depthconvert->configure(in, out, conv_policy, shift);
126
127 // Log info
128 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLDepthConvertLayer"
129 << " Data Type: " << in->info()->data_type()
130 << " Input shape: " << in->info()->tensor_shape()
131 << " Output shape: " << out->info()->tensor_shape()
132 << " shift: " << shift
133 << std::endl);
134
135 return std::move(depthconvert);
136}
137
Michalis Spyrou7bfe4c52017-11-24 09:54:20 +0000138/* DepthwiseConvolutionLayer Layer */
139REGISTER_SIMPLE_OPERATION(CLDepthwiseConvolutionOperation, OPENCL, OperationType::DepthwiseConvolutionLayer)
140{
Georgios Pinitas236bfe72017-11-23 15:59:55 +0000141 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 2 && ctx.num_inputs() != 3);
Michalis Spyrou7bfe4c52017-11-24 09:54:20 +0000142 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
143 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
144 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
145
146 // Extract IO and info
147 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
148 auto *weights = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(1));
149 auto *biases = ctx.num_inputs() == 3 ? dynamic_cast<arm_compute::ICLTensor *>(ctx.input(2)) : nullptr;
150 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
151 const auto conv_info = ctx.parameter<PadStrideInfo>("ConvolutionInfo");
152 const auto opt3x3 = ctx.parameter<bool>("Optimized3x3");
153
154 // Create and configure function
155 std::unique_ptr<arm_compute::IFunction> func;
156 bool run_3x3_opt = opt3x3 && weights->info()->dimension(0) == 3;
157 if(run_3x3_opt)
158 {
159 auto depwthwise_conv = arm_compute::support::cpp14::make_unique<arm_compute::CLDepthwiseConvolution>();
160 depwthwise_conv->configure(in, weights, biases, out, conv_info);
161 func = std::move(depwthwise_conv);
162 }
163 else
164 {
165 auto depwthwise_conv = arm_compute::support::cpp14::make_unique<arm_compute::CLDepthwiseConvolution3x3>();
166 depwthwise_conv->configure(in, weights, biases, out, conv_info);
167 func = std::move(depwthwise_conv);
168 }
169
170 // Log info
171 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLDepthwiseConvolutionLayer"
172 << " Data Type: " << in->info()->data_type()
173 << " Input shape: " << in->info()->tensor_shape()
174 << " Weights shape: " << weights->info()->tensor_shape()
175 << " Output shape: " << out->info()->tensor_shape());
176 if(biases == nullptr)
177 {
178 ARM_COMPUTE_LOG_GRAPH_INFO(" Biases shape: No biases provided" << std::endl);
179 }
180 else
181 {
182 ARM_COMPUTE_LOG_GRAPH_INFO(" Biases shape: " << biases->info()->tensor_shape() << std::endl);
183 }
184
185 return func;
186}
187
Michalis Spyrou27c9efb2017-10-09 15:46:30 +0100188/* DeQuantizationLayer Layer */
189REGISTER_SIMPLE_OPERATION(CLDequantizationLayerOperation, OPENCL, OperationType::DequantizationLayer)
190{
191 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 1);
192 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 2);
193 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
194 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
195 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(1)) == nullptr);
196
197 // Extract IO and info
198 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
199 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
200 auto *min_max = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(1));
201
202 // Create and configure function
203 auto dequantization = arm_compute::support::cpp14::make_unique<arm_compute::CLDequantizationLayer>();
204 dequantization->configure(in, out, min_max);
205
206 // Log info
207 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLDequantizationLayer"
208 << " Data Type: " << in->info()->data_type()
209 << " Input shape: " << in->info()->tensor_shape()
210 << " Output shape: " << out->info()->tensor_shape()
211 << " Min max shape: " << min_max->info()->tensor_shape()
212 << std::endl);
213
214 return std::move(dequantization);
215}
216
217/* Flatten Layer */
218REGISTER_SIMPLE_OPERATION(CLFlattenLayerOperation, OPENCL, OperationType::FlattenLayer)
219{
220 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 1);
221 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
222 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
223 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
224
225 // Extract IO and info
226 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
227 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
228
229 // Create and configure function
230 auto flatten = arm_compute::support::cpp14::make_unique<arm_compute::CLFlattenLayer>();
231 flatten->configure(in, out);
232
233 // Log info
Isabella Gottardid0f70992017-11-03 14:48:14 +0000234 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLFlattenLayer"
Michalis Spyrou27c9efb2017-10-09 15:46:30 +0100235 << " Data Type: " << in->info()->data_type()
236 << " Input shape: " << in->info()->tensor_shape()
237 << " Output shape: " << out->info()->tensor_shape()
238 << std::endl);
239
240 return std::move(flatten);
241}
242
Georgios Pinitas407c3e62017-10-25 18:26:46 +0100243/* Floor Layer */
244REGISTER_SIMPLE_OPERATION(CLFloorLayerOperation, OPENCL, OperationType::FloorLayer)
245{
246 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 1);
247 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
248 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
249 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
250
251 // Extract IO and info
252 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
253 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
254
255 // Create and configure function
256 auto floor = arm_compute::support::cpp14::make_unique<arm_compute::CLFloor>();
257 floor->configure(in, out);
258
259 // Log info
260 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLFloorLayer"
261 << " Data Type: " << in->info()->data_type()
262 << " Input shape: " << in->info()->tensor_shape()
263 << " Output shape: " << out->info()->tensor_shape()
264 << std::endl);
265
266 return std::move(floor);
267}
268
269/* Fully Connected Layer */
270REGISTER_SIMPLE_OPERATION(CLFullyConnectedLayer, OPENCL, OperationType::FullyConnectedLayer)
271{
272 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 3);
273 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
274 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
275 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(1)) == nullptr);
276 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(2)) == nullptr);
277 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
278
279 // Extract IO and info
280 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
281 auto *weights = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(1));
282 auto *biases = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(2));
283 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
284
285 // Create and configure function
286 auto fc = arm_compute::support::cpp14::make_unique<arm_compute::CLFullyConnectedLayer>();
287 fc->configure(in, weights, biases, out);
288
289 // Log info
Isabella Gottardid0f70992017-11-03 14:48:14 +0000290 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLFullyConnectedLayer"
Georgios Pinitas407c3e62017-10-25 18:26:46 +0100291 << " Data Type: " << in->info()->data_type()
292 << " Input shape: " << in->info()->tensor_shape()
293 << " Weights shape: " << weights->info()->tensor_shape()
294 << " Biases Shape: " << biases->info()->tensor_shape()
295 << " Output shape: " << out->info()->tensor_shape()
296 << std::endl);
297
298 return std::move(fc);
299}
300
301/* L2 Normalize Layer */
302REGISTER_SIMPLE_OPERATION(CLL2NormalizeLayerOperation, OPENCL, OperationType::L2NormalizeLayer)
303{
304 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 1);
305 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
306 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
307 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
308
309 // Extract IO and info
310 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
311 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
312 const auto axis = ctx.parameter<unsigned int>("axis");
313 const auto epsilon = ctx.parameter<float>("epsilon");
314
315 // Create and configure function
316 auto l2_norm = arm_compute::support::cpp14::make_unique<arm_compute::CLL2Normalize>();
317 l2_norm->configure(in, out, axis, epsilon);
318
319 // Log info
320 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLL2NormalizeLayer"
321 << " Data Type: " << in->info()->data_type()
322 << " Input shape: " << in->info()->tensor_shape()
323 << " Output shape: " << out->info()->tensor_shape()
324 << " Axis: " << axis
325 << " Epsilon: " << epsilon
326 << std::endl);
327
328 return std::move(l2_norm);
329}
330
331/* Normalization Layer */
332REGISTER_SIMPLE_OPERATION(CLNormalizationLayerOperation, OPENCL, OperationType::NormalizationLayer)
333{
334 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 1);
335 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
336 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
337 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
338
339 // Extract IO and info
340 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
341 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
342 const auto norm_info = ctx.parameter<NormalizationLayerInfo>("NormalizationLayerInfo");
343
344 // Create and configure function
345 auto norm = arm_compute::support::cpp14::make_unique<arm_compute::CLNormalizationLayer>();
346 norm->configure(in, out, norm_info);
347
348 // Log info
349 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLNormalizationLayer"
350 << " Data Type: " << in->info()->data_type()
351 << " Input shape: " << in->info()->tensor_shape()
352 << " Output shape: " << out->info()->tensor_shape()
353 << " Normalization info: " << norm_info
354 << std::endl);
355
356 return std::move(norm);
357}
358
359/* Pooling Layer */
360REGISTER_SIMPLE_OPERATION(CLPoolingLayerOperation, OPENCL, OperationType::PoolingLayer)
361{
362 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 1);
363 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
364 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
365 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
366
367 // Extract IO and info
368 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
369 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
370 const auto pool_info = ctx.parameter<PoolingLayerInfo>("PoolingLayerInfo");
371
372 // Create and configure function
373 auto pool = arm_compute::support::cpp14::make_unique<arm_compute::CLPoolingLayer>();
374 pool->configure(in, out, pool_info);
375
376 // Log info
377 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLPoolingLayer"
378 << " Data Type: " << in->info()->data_type()
379 << " Input shape: " << in->info()->tensor_shape()
380 << " Output shape: " << out->info()->tensor_shape()
381 << " Pooling info: " << pool_info
382 << std::endl);
383
384 return std::move(pool);
385}
386
Michalis Spyrou27c9efb2017-10-09 15:46:30 +0100387/* Quantization Layer */
388REGISTER_SIMPLE_OPERATION(CLQuantizationLayerOperation, OPENCL, OperationType::QuantizationLayer)
389{
390 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 1);
391 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
392 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
393 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
394
395 // Extract IO and info
396 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
397 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
398
399 // Create and configure function
400 auto quantization = arm_compute::support::cpp14::make_unique<arm_compute::CLQuantizationLayer>();
401 quantization->configure(in, out);
402
403 // Log info
Isabella Gottardid0f70992017-11-03 14:48:14 +0000404 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLQuantizationLayer"
Michalis Spyrou27c9efb2017-10-09 15:46:30 +0100405 << " Data Type: " << in->info()->data_type()
406 << " Input shape: " << in->info()->tensor_shape()
407 << " Output shape: " << out->info()->tensor_shape()
408 << std::endl);
409
410 return std::move(quantization);
411}
412
413/* Reshape Layer */
414REGISTER_SIMPLE_OPERATION(CLReshapeLayerOperation, OPENCL, OperationType::ReshapeLayer)
415{
416 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 1);
417 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
418 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
419 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
420
421 // Extract IO and info
422 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
423 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
424
425 // Create and configure function
426 auto reshape = arm_compute::support::cpp14::make_unique<arm_compute::CLReshapeLayer>();
427 reshape->configure(in, out);
428
429 // Log info
Isabella Gottardid0f70992017-11-03 14:48:14 +0000430 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLReshapeLayer"
Michalis Spyrou27c9efb2017-10-09 15:46:30 +0100431 << " Data Type: " << in->info()->data_type()
432 << " Input shape: " << in->info()->tensor_shape()
433 << " Output shape: " << out->info()->tensor_shape()
434 << std::endl);
435
436 return std::move(reshape);
437}
438
Georgios Pinitas407c3e62017-10-25 18:26:46 +0100439/* Softmax Layer */
440REGISTER_SIMPLE_OPERATION(CLSoftmaxLayerOperation, OPENCL, OperationType::SoftmaxLayer)
441{
442 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 1);
443 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
444 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
445 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
446
447 // Extract IO and info
448 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
449 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
450
451 // Create and configure function
452 auto smx = arm_compute::support::cpp14::make_unique<arm_compute::CLSoftmaxLayer>();
453 smx->configure(in, out);
454
455 // Log info
456 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLSoftmaxLayer"
457 << " Data Type: " << in->info()->data_type()
458 << " Input shape: " << in->info()->tensor_shape()
459 << " Output shape: " << out->info()->tensor_shape()
460 << std::endl);
461
462 return std::move(smx);
463}