blob: 94e3fe15f7a54520b631910eef56e88d6a2650bf [file] [log] [blame]
Georgios Pinitas407c3e62017-10-25 18:26:46 +01001/*
Giorgio Arena11674872018-02-07 15:38:12 +00002 * Copyright (c) 2017-2018 ARM Limited.
Georgios Pinitas407c3e62017-10-25 18:26:46 +01003 *
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
Giorgio Arena11674872018-02-07 15:38:12 +000082 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 const auto act_info = ctx.parameter<ActivationLayerInfo>("act_info");
Georgios Pinitas407c3e62017-10-25 18:26:46 +010090
91 // Create and configure function
92 auto batch_norm = arm_compute::support::cpp14::make_unique<arm_compute::CLBatchNormalizationLayer>();
Giorgio Arena11674872018-02-07 15:38:12 +000093 batch_norm->configure(in, out, mean, var, beta, gamma, epsilon, act_info);
Georgios Pinitas407c3e62017-10-25 18:26:46 +010094
95 // Log info
96 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLBatchNormalizationLayer"
97 << " Data Type: " << in->info()->data_type()
98 << " Input shape: " << in->info()->tensor_shape()
99 << " Output shape: " << out->info()->tensor_shape()
100 << " Mean shape: " << mean->info()->tensor_shape()
101 << " Var shape: " << var->info()->tensor_shape()
102 << " Beta shape: " << beta->info()->tensor_shape()
103 << " Gamma shape: " << gamma->info()->tensor_shape()
104 << " Epsilon: " << epsilon
Giorgio Arena11674872018-02-07 15:38:12 +0000105 << " Activation function: " << act_info.activation()
106 << " a: " << act_info.a()
107 << " b: " << act_info.b()
Georgios Pinitas407c3e62017-10-25 18:26:46 +0100108 << std::endl);
109
110 return std::move(batch_norm);
111}
112
Giorgio Arena04a8f8c2017-11-23 11:45:24 +0000113/* DepthConvertLayer Layer */
Michalis Spyrou27c9efb2017-10-09 15:46:30 +0100114REGISTER_SIMPLE_OPERATION(CLDepthConvertLayerOperation, OPENCL, OperationType::DepthConvertLayer)
115{
116 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 1);
117 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
118 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
119 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
120
121 // Extract IO and info
122 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
123 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
124 const auto conv_policy = ctx.parameter<ConvertPolicy>("ConvertPolicy");
125 const auto shift = ctx.parameter<uint32_t>("shift");
126
127 // Create and configure function
Giorgio Arena04a8f8c2017-11-23 11:45:24 +0000128 auto depthconvert = arm_compute::support::cpp14::make_unique<arm_compute::CLDepthConvertLayer>();
Michalis Spyrou27c9efb2017-10-09 15:46:30 +0100129 depthconvert->configure(in, out, conv_policy, shift);
130
131 // Log info
132 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLDepthConvertLayer"
133 << " Data Type: " << in->info()->data_type()
134 << " Input shape: " << in->info()->tensor_shape()
135 << " Output shape: " << out->info()->tensor_shape()
136 << " shift: " << shift
137 << std::endl);
138
139 return std::move(depthconvert);
140}
141
Michalis Spyrou7bfe4c52017-11-24 09:54:20 +0000142/* DepthwiseConvolutionLayer Layer */
143REGISTER_SIMPLE_OPERATION(CLDepthwiseConvolutionOperation, OPENCL, OperationType::DepthwiseConvolutionLayer)
144{
Georgios Pinitas236bfe72017-11-23 15:59:55 +0000145 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 2 && ctx.num_inputs() != 3);
Michalis Spyrou7bfe4c52017-11-24 09:54:20 +0000146 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
147 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
148 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
149
150 // Extract IO and info
151 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
152 auto *weights = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(1));
153 auto *biases = ctx.num_inputs() == 3 ? dynamic_cast<arm_compute::ICLTensor *>(ctx.input(2)) : nullptr;
154 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
155 const auto conv_info = ctx.parameter<PadStrideInfo>("ConvolutionInfo");
156 const auto opt3x3 = ctx.parameter<bool>("Optimized3x3");
157
158 // Create and configure function
159 std::unique_ptr<arm_compute::IFunction> func;
160 bool run_3x3_opt = opt3x3 && weights->info()->dimension(0) == 3;
161 if(run_3x3_opt)
162 {
Georgios Pinitas1250a5a2018-01-02 13:27:37 +0000163 auto depwthwise_conv = arm_compute::support::cpp14::make_unique<arm_compute::CLDepthwiseConvolutionLayer3x3>();
Michalis Spyrou7bfe4c52017-11-24 09:54:20 +0000164 depwthwise_conv->configure(in, weights, biases, out, conv_info);
165 func = std::move(depwthwise_conv);
166 }
167 else
168 {
Georgios Pinitas1250a5a2018-01-02 13:27:37 +0000169 auto depwthwise_conv = arm_compute::support::cpp14::make_unique<arm_compute::CLDepthwiseConvolutionLayer>();
Michalis Spyrou7bfe4c52017-11-24 09:54:20 +0000170 depwthwise_conv->configure(in, weights, biases, out, conv_info);
171 func = std::move(depwthwise_conv);
172 }
173
174 // Log info
175 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLDepthwiseConvolutionLayer"
176 << " Data Type: " << in->info()->data_type()
177 << " Input shape: " << in->info()->tensor_shape()
178 << " Weights shape: " << weights->info()->tensor_shape()
179 << " Output shape: " << out->info()->tensor_shape());
180 if(biases == nullptr)
181 {
182 ARM_COMPUTE_LOG_GRAPH_INFO(" Biases shape: No biases provided" << std::endl);
183 }
184 else
185 {
186 ARM_COMPUTE_LOG_GRAPH_INFO(" Biases shape: " << biases->info()->tensor_shape() << std::endl);
187 }
188
189 return func;
190}
191
Michalis Spyrou27c9efb2017-10-09 15:46:30 +0100192/* DeQuantizationLayer Layer */
193REGISTER_SIMPLE_OPERATION(CLDequantizationLayerOperation, OPENCL, OperationType::DequantizationLayer)
194{
195 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 1);
196 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 2);
197 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
198 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
199 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(1)) == nullptr);
200
201 // Extract IO and info
202 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
203 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
204 auto *min_max = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(1));
205
206 // Create and configure function
207 auto dequantization = arm_compute::support::cpp14::make_unique<arm_compute::CLDequantizationLayer>();
208 dequantization->configure(in, out, min_max);
209
210 // Log info
211 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLDequantizationLayer"
212 << " Data Type: " << in->info()->data_type()
213 << " Input shape: " << in->info()->tensor_shape()
214 << " Output shape: " << out->info()->tensor_shape()
215 << " Min max shape: " << min_max->info()->tensor_shape()
216 << std::endl);
217
218 return std::move(dequantization);
219}
220
221/* Flatten Layer */
222REGISTER_SIMPLE_OPERATION(CLFlattenLayerOperation, OPENCL, OperationType::FlattenLayer)
223{
224 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 1);
225 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
226 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
227 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
228
229 // Extract IO and info
230 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
231 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
232
233 // Create and configure function
234 auto flatten = arm_compute::support::cpp14::make_unique<arm_compute::CLFlattenLayer>();
235 flatten->configure(in, out);
236
237 // Log info
Isabella Gottardid0f70992017-11-03 14:48:14 +0000238 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLFlattenLayer"
Michalis Spyrou27c9efb2017-10-09 15:46:30 +0100239 << " Data Type: " << in->info()->data_type()
240 << " Input shape: " << in->info()->tensor_shape()
241 << " Output shape: " << out->info()->tensor_shape()
242 << std::endl);
243
244 return std::move(flatten);
245}
246
Georgios Pinitas407c3e62017-10-25 18:26:46 +0100247/* Floor Layer */
248REGISTER_SIMPLE_OPERATION(CLFloorLayerOperation, OPENCL, OperationType::FloorLayer)
249{
250 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 1);
251 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
252 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
253 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
254
255 // Extract IO and info
256 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
257 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
258
259 // Create and configure function
260 auto floor = arm_compute::support::cpp14::make_unique<arm_compute::CLFloor>();
261 floor->configure(in, out);
262
263 // Log info
264 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLFloorLayer"
265 << " Data Type: " << in->info()->data_type()
266 << " Input shape: " << in->info()->tensor_shape()
267 << " Output shape: " << out->info()->tensor_shape()
268 << std::endl);
269
270 return std::move(floor);
271}
272
273/* Fully Connected Layer */
274REGISTER_SIMPLE_OPERATION(CLFullyConnectedLayer, OPENCL, OperationType::FullyConnectedLayer)
275{
276 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 3);
277 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
278 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
279 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(1)) == nullptr);
280 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(2)) == nullptr);
281 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
282
283 // Extract IO and info
284 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
285 auto *weights = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(1));
286 auto *biases = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(2));
287 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
288
289 // Create and configure function
290 auto fc = arm_compute::support::cpp14::make_unique<arm_compute::CLFullyConnectedLayer>();
291 fc->configure(in, weights, biases, out);
292
293 // Log info
Isabella Gottardid0f70992017-11-03 14:48:14 +0000294 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLFullyConnectedLayer"
Georgios Pinitas407c3e62017-10-25 18:26:46 +0100295 << " Data Type: " << in->info()->data_type()
296 << " Input shape: " << in->info()->tensor_shape()
297 << " Weights shape: " << weights->info()->tensor_shape()
298 << " Biases Shape: " << biases->info()->tensor_shape()
299 << " Output shape: " << out->info()->tensor_shape()
300 << std::endl);
301
302 return std::move(fc);
303}
304
305/* L2 Normalize Layer */
306REGISTER_SIMPLE_OPERATION(CLL2NormalizeLayerOperation, OPENCL, OperationType::L2NormalizeLayer)
307{
308 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 1);
309 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
310 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
311 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
312
313 // Extract IO and info
314 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
315 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
316 const auto axis = ctx.parameter<unsigned int>("axis");
317 const auto epsilon = ctx.parameter<float>("epsilon");
318
319 // Create and configure function
Giorgio Arena04a8f8c2017-11-23 11:45:24 +0000320 auto l2_norm = arm_compute::support::cpp14::make_unique<arm_compute::CLL2NormalizeLayer>();
Georgios Pinitas407c3e62017-10-25 18:26:46 +0100321 l2_norm->configure(in, out, axis, epsilon);
322
323 // Log info
324 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLL2NormalizeLayer"
325 << " Data Type: " << in->info()->data_type()
326 << " Input shape: " << in->info()->tensor_shape()
327 << " Output shape: " << out->info()->tensor_shape()
328 << " Axis: " << axis
329 << " Epsilon: " << epsilon
330 << std::endl);
331
332 return std::move(l2_norm);
333}
334
335/* Normalization Layer */
336REGISTER_SIMPLE_OPERATION(CLNormalizationLayerOperation, OPENCL, OperationType::NormalizationLayer)
337{
338 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 1);
339 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
340 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
341 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
342
343 // Extract IO and info
344 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
345 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
346 const auto norm_info = ctx.parameter<NormalizationLayerInfo>("NormalizationLayerInfo");
347
348 // Create and configure function
349 auto norm = arm_compute::support::cpp14::make_unique<arm_compute::CLNormalizationLayer>();
350 norm->configure(in, out, norm_info);
351
352 // Log info
353 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLNormalizationLayer"
354 << " Data Type: " << in->info()->data_type()
355 << " Input shape: " << in->info()->tensor_shape()
356 << " Output shape: " << out->info()->tensor_shape()
357 << " Normalization info: " << norm_info
358 << std::endl);
359
360 return std::move(norm);
361}
362
363/* Pooling Layer */
364REGISTER_SIMPLE_OPERATION(CLPoolingLayerOperation, OPENCL, OperationType::PoolingLayer)
365{
366 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 1);
367 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
368 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
369 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
370
371 // Extract IO and info
372 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
373 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
374 const auto pool_info = ctx.parameter<PoolingLayerInfo>("PoolingLayerInfo");
375
376 // Create and configure function
377 auto pool = arm_compute::support::cpp14::make_unique<arm_compute::CLPoolingLayer>();
378 pool->configure(in, out, pool_info);
379
380 // Log info
381 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLPoolingLayer"
382 << " Data Type: " << in->info()->data_type()
383 << " Input shape: " << in->info()->tensor_shape()
384 << " Output shape: " << out->info()->tensor_shape()
385 << " Pooling info: " << pool_info
386 << std::endl);
387
388 return std::move(pool);
389}
390
Michalis Spyrou27c9efb2017-10-09 15:46:30 +0100391/* Quantization Layer */
392REGISTER_SIMPLE_OPERATION(CLQuantizationLayerOperation, OPENCL, OperationType::QuantizationLayer)
393{
394 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 1);
395 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
396 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
397 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
398
399 // Extract IO and info
400 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
401 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
402
403 // Create and configure function
404 auto quantization = arm_compute::support::cpp14::make_unique<arm_compute::CLQuantizationLayer>();
405 quantization->configure(in, out);
406
407 // Log info
Isabella Gottardid0f70992017-11-03 14:48:14 +0000408 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLQuantizationLayer"
Michalis Spyrou27c9efb2017-10-09 15:46:30 +0100409 << " Data Type: " << in->info()->data_type()
410 << " Input shape: " << in->info()->tensor_shape()
411 << " Output shape: " << out->info()->tensor_shape()
412 << std::endl);
413
414 return std::move(quantization);
415}
416
417/* Reshape Layer */
418REGISTER_SIMPLE_OPERATION(CLReshapeLayerOperation, OPENCL, OperationType::ReshapeLayer)
419{
420 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 1);
421 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
422 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
423 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
424
425 // Extract IO and info
426 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
427 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
428
429 // Create and configure function
430 auto reshape = arm_compute::support::cpp14::make_unique<arm_compute::CLReshapeLayer>();
431 reshape->configure(in, out);
432
433 // Log info
Isabella Gottardid0f70992017-11-03 14:48:14 +0000434 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLReshapeLayer"
Michalis Spyrou27c9efb2017-10-09 15:46:30 +0100435 << " Data Type: " << in->info()->data_type()
436 << " Input shape: " << in->info()->tensor_shape()
437 << " Output shape: " << out->info()->tensor_shape()
438 << std::endl);
439
440 return std::move(reshape);
441}
442
Georgios Pinitas407c3e62017-10-25 18:26:46 +0100443/* Softmax Layer */
444REGISTER_SIMPLE_OPERATION(CLSoftmaxLayerOperation, OPENCL, OperationType::SoftmaxLayer)
445{
446 ARM_COMPUTE_ERROR_ON(ctx.num_inputs() != 1);
447 ARM_COMPUTE_ERROR_ON(ctx.num_outputs() != 1);
448 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0)) == nullptr);
449 ARM_COMPUTE_ERROR_ON(dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0)) == nullptr);
450
451 // Extract IO and info
452 auto *in = dynamic_cast<arm_compute::ICLTensor *>(ctx.input(0));
453 auto *out = dynamic_cast<arm_compute::ICLTensor *>(ctx.output(0));
454
455 // Create and configure function
456 auto smx = arm_compute::support::cpp14::make_unique<arm_compute::CLSoftmaxLayer>();
457 smx->configure(in, out);
458
459 // Log info
460 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiating CLSoftmaxLayer"
461 << " Data Type: " << in->info()->data_type()
462 << " Input shape: " << in->info()->tensor_shape()
463 << " Output shape: " << out->info()->tensor_shape()
464 << std::endl);
465
466 return std::move(smx);
467}