blob: 120997a8b4b984fc1b7bcad4e9dca53c0eb5b9e5 [file] [log] [blame]
Georgios Pinitasd8734b52017-12-22 15:27:52 +00001/*
Giuseppe Rossinibb365de2019-02-15 10:24:47 +00002 * Copyright (c) 2018-2019 ARM Limited.
Georgios Pinitasd8734b52017-12-22 15:27:52 +00003 *
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 */
Georgios Pinitasd9eb2752018-04-03 13:44:29 +010024#ifndef __ARM_COMPUTE_GRAPH_LAYERS_H__
25#define __ARM_COMPUTE_GRAPH_LAYERS_H__
Georgios Pinitasd8734b52017-12-22 15:27:52 +000026
Georgios Pinitasd9eb2752018-04-03 13:44:29 +010027#include "arm_compute/graph/GraphBuilder.h"
28#include "arm_compute/graph/Types.h"
29#include "arm_compute/graph/frontend/ILayer.h"
30#include "arm_compute/graph/frontend/IStream.h"
31#include "arm_compute/graph/frontend/SubStream.h"
Georgios Pinitasd8734b52017-12-22 15:27:52 +000032
33#include "arm_compute/core/utils/misc/Utility.h"
34
35#include <memory>
36#include <string>
37
38namespace arm_compute
39{
Georgios Pinitasd9eb2752018-04-03 13:44:29 +010040namespace graph
Georgios Pinitasd8734b52017-12-22 15:27:52 +000041{
42namespace frontend
43{
44/** Input Layer */
45class InputLayer final : public ILayer
46{
47public:
Alex Gildayc357c472018-03-21 13:54:09 +000048 /** Construct an input layer.
49 *
50 * @param[in] desc Description of input tensor.
51 * @param[in] accessor Accessor to get input tensor data from.
52 */
Georgios Pinitasd8734b52017-12-22 15:27:52 +000053 InputLayer(TensorDescriptor desc, ITensorAccessorUPtr accessor)
54 : _desc(desc), _accessor(std::move(accessor))
55 {
56 }
57
58 NodeID create_layer(IStream &s) override
59 {
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +010060 NodeParams common_params = { name(), s.hints().target_hint };
Georgios Pinitasd8734b52017-12-22 15:27:52 +000061 return GraphBuilder::add_input_node(s.graph(), common_params, _desc, std::move(_accessor));
62 }
63
64private:
65 TensorDescriptor _desc;
66 ITensorAccessorUPtr _accessor;
67};
68
Michalis Spyrou1a569a32019-09-10 17:20:34 +010069/** Constant Layer */
70class ConstantLayer final : public ILayer
71{
72public:
73 /** Construct a constant layer.
74 *
75 * @param[in] desc Description of input tensor.
76 * @param[in] accessor Accessor to get input tensor data from.
77 */
78 ConstantLayer(TensorDescriptor desc, ITensorAccessorUPtr accessor)
79 : _desc(desc), _accessor(std::move(accessor))
80 {
81 }
82
83 NodeID create_layer(IStream &s) override
84 {
85 NodeParams common_params = { name(), s.hints().target_hint };
86 return GraphBuilder::add_const_node(s.graph(), common_params, _desc, std::move(_accessor));
87 }
88
89private:
90 TensorDescriptor _desc;
91 ITensorAccessorUPtr _accessor;
92};
93
Georgios Pinitasd8734b52017-12-22 15:27:52 +000094/** Output Layer */
95class OutputLayer final : public ILayer
96{
97public:
Alex Gildayc357c472018-03-21 13:54:09 +000098 /** Construct an output layer.
99 *
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000100 * @param[in] accessor Accessor to give output tensor data to.
101 * @param[in] connection_idx (Optional) Input connection index
Alex Gildayc357c472018-03-21 13:54:09 +0000102 */
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000103 OutputLayer(ITensorAccessorUPtr accessor, unsigned int connection_idx = 0)
104 : _accessor(std::move(accessor)), _connection_idx(connection_idx)
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000105 {
106 }
107
108 NodeID create_layer(IStream &s) override
109 {
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +0100110 NodeParams common_params = { name(), s.hints().target_hint };
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000111 NodeIdxPair input = { s.tail_node(), _connection_idx };
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000112 return GraphBuilder::add_output_node(s.graph(), common_params, input, std::move(_accessor));
113 }
114
115private:
116 ITensorAccessorUPtr _accessor;
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000117 unsigned int _connection_idx;
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000118};
119
120/** Activation Layer */
121class ActivationLayer final : public ILayer
122{
123public:
Alex Gildayc357c472018-03-21 13:54:09 +0000124 /** Construct an activation layer.
125 *
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000126 * @param[in] act_info Activation information
127 * @param[in] out_quant_info (Optional) Output quantization info
Alex Gildayc357c472018-03-21 13:54:09 +0000128 */
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000129 ActivationLayer(ActivationLayerInfo act_info,
130 const QuantizationInfo out_quant_info = QuantizationInfo())
131 : _act_info(act_info),
132 _out_quant_info(std::move(out_quant_info))
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000133 {
134 }
135
136 NodeID create_layer(IStream &s) override
137 {
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +0100138 NodeParams common_params = { name(), s.hints().target_hint };
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000139 NodeIdxPair input = { s.tail_node(), 0 };
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000140 return GraphBuilder::add_activation_node(s.graph(), common_params, input, _act_info, std::move(_out_quant_info));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000141 }
142
143private:
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000144 ActivationLayerInfo _act_info;
145 const QuantizationInfo _out_quant_info;
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000146};
147
148/** Batchnormalization Layer */
149class BatchNormalizationLayer final : public ILayer
150{
151public:
Alex Gildayc357c472018-03-21 13:54:09 +0000152 /** Construct a batch normalization layer.
153 *
154 * @param[in] mean Accessor to get mean tensor data from.
155 * @param[in] var Accessor to get var tensor data from.
156 * @param[in] gamma (Optional) Accessor to get gamma tensor data from. Default: nullptr.
157 * @param[in] beta (Optional) Accessor to get beta tensor data from. Default: nullptr.
158 * @param[in] epsilon (Optional) Epsilon value. Default: 0.001.
159 */
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000160 BatchNormalizationLayer(ITensorAccessorUPtr mean,
161 ITensorAccessorUPtr var,
162 ITensorAccessorUPtr gamma = nullptr,
163 ITensorAccessorUPtr beta = nullptr,
164 float epsilon = 0.001f)
165 : _mean(std::move(mean)), _var(std::move(var)), _gamma(std::move(gamma)), _beta(std::move(beta)), _epsilon(epsilon)
166 {
167 }
168
169 NodeID create_layer(IStream &s) override
170 {
171 ARM_COMPUTE_ERROR_ON(_mean == nullptr);
172 ARM_COMPUTE_ERROR_ON(_var == nullptr);
173
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +0100174 NodeParams common_params = { name(), s.hints().target_hint };
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000175 NodeIdxPair input = { s.tail_node(), 0 };
176 return GraphBuilder::add_batch_normalization_node(s.graph(), common_params, input, _epsilon,
177 std::move(_mean), std::move(_var), std::move(_beta), std::move(_gamma));
178 }
179
180private:
181 ITensorAccessorUPtr _mean;
182 ITensorAccessorUPtr _var;
183 ITensorAccessorUPtr _gamma;
184 ITensorAccessorUPtr _beta;
185 float _epsilon;
186};
187
Manuel Bottinid2048ce2018-10-23 17:00:42 +0100188/** Bounding Box Transform Layer */
189class BoundingBoxTransformLayer final : public ILayer
190{
191public:
192 /** Construct a bounding box transform layer.
193 *
194 * @param[in] sub_stream_input Graph sub-stream for the input
195 * @param[in] sub_stream_deltas Graph sub-stream for the deltas
196 * @param[in] info Contains BoundingBox operation information described in @ref BoundingBoxTransformInfo.
197 */
198 BoundingBoxTransformLayer(SubStream &&sub_stream_input, SubStream &&sub_stream_deltas, BoundingBoxTransformInfo info)
199 : _ss_input(sub_stream_input), _ss_deltas(sub_stream_deltas), _bbox_info(info)
200 {
201 }
202
203 /** Create layer and add to the given stream.
204 *
205 * @param[in] s Stream to add layer to.
206 *
207 * @return ID of the created node.
208 */
209 NodeID create_layer(IStream &s) override
210 {
211 NodeParams common_params = { name(), s.hints().target_hint };
212 NodeIdxPair input = { _ss_input.tail_node(), 0 };
213 NodeIdxPair deltas = { _ss_deltas.tail_node(), 0 };
214 return GraphBuilder::add_bounding_box_transform_node(s.graph(), common_params, input, deltas, _bbox_info);
215 }
216
217private:
218 SubStream _ss_input;
219 SubStream _ss_deltas;
220 BoundingBoxTransformInfo _bbox_info;
221};
222
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100223/** Channel Shuffle Layer */
224class ChannelShuffleLayer final : public ILayer
225{
226public:
227 /** Construct a Channel Shuffle layer.
228 *
229 * @param[in] num_groups Number of groups
230 */
231 ChannelShuffleLayer(unsigned int num_groups)
232 : _num_groups(num_groups)
233 {
234 }
235
236 NodeID create_layer(IStream &s) override
237 {
238 NodeParams common_params = { name(), s.hints().target_hint };
239 NodeIdxPair input = { s.tail_node(), 0 };
240 return GraphBuilder::add_channel_shuffle_node(s.graph(), common_params, input, _num_groups);
241 }
242
243private:
244 unsigned int _num_groups;
245};
246
Georgios Pinitas427bbbf2018-08-28 13:32:02 +0100247/** Concat Layer */
248class ConcatLayer final : public ILayer
249{
250public:
251 /** Construct a concatenation layer
252 *
253 * @param[in] sub_stream1 First graph branch
254 * @param[in] sub_stream2 Second graph branch
255 * @param[in] rest_sub_streams Rest sub-graph branches
256 */
257 template <typename... Ts>
258 ConcatLayer(SubStream &&sub_stream1, SubStream &&sub_stream2, Ts &&... rest_sub_streams)
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000259 : _sub_streams(), _concat_descriptor(DataLayoutDimension::CHANNEL)
Pablo Tello32521432018-11-15 14:43:10 +0000260 {
261 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream1)));
262 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream2)));
263
264 utility::for_each([&](SubStream && sub_stream)
265 {
266 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream)));
267 },
268 std::move(rest_sub_streams)...);
269 }
270 /** Construct a concatenation layer
271 *
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000272 * @param[in] concat_descriptor Concat layer descriptor
273 * @param[in] sub_stream1 First graph branch
274 * @param[in] sub_stream2 Second graph branch
275 * @param[in] rest_sub_streams Rest sub-graph branches
Pablo Tello32521432018-11-15 14:43:10 +0000276 */
277 template <typename... Ts>
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000278 ConcatLayer(descriptors::ConcatLayerDescriptor concat_descriptor, SubStream &&sub_stream1, SubStream &&sub_stream2, Ts &&... rest_sub_streams)
279 : _sub_streams(), _concat_descriptor(concat_descriptor)
Georgios Pinitas427bbbf2018-08-28 13:32:02 +0100280 {
281 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream1)));
282 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream2)));
283
284 utility::for_each([&](SubStream && sub_stream)
285 {
286 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream)));
287 },
288 std::move(rest_sub_streams)...);
289 }
290 /** Construct a concat layer
291 *
292 * @param[in] sub_stream Sub-stream
293 */
294 template <typename... Ts>
295 ConcatLayer(SubStream &&sub_stream)
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000296 : _sub_streams(), _concat_descriptor(DataLayoutDimension::CHANNEL)
Georgios Pinitas427bbbf2018-08-28 13:32:02 +0100297 {
298 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream)));
299 }
300 NodeID create_layer(IStream &s) override
301 {
302 NodeID nid = EmptyNodeID;
303 NodeParams common_params = { name(), s.hints().target_hint };
304 if(_sub_streams.size() == 1 && _sub_streams.at(0) != nullptr)
305 {
306 nid = _sub_streams[0]->tail_node();
307 }
308 else
309 {
310 // Collect tail nodes and concatenate
311 std::vector<NodeIdxPair> nodes;
312 for(auto &ss : _sub_streams)
313 {
314 if(ss && (ss->tail_node() != EmptyNodeID))
315 {
316 const auto tail_node = s.graph().node(ss->tail_node());
317 if(tail_node != nullptr && tail_node->type() != NodeType::Output)
318 {
319 nodes.push_back({ ss->tail_node(), 0 });
320 }
321 }
322 }
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000323 nid = GraphBuilder::add_concatenate_node(s.graph(), common_params, nodes, _concat_descriptor);
Georgios Pinitas427bbbf2018-08-28 13:32:02 +0100324 }
325 return nid;
326 }
327
328private:
329 std::vector<std::unique_ptr<SubStream>> _sub_streams;
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000330 descriptors::ConcatLayerDescriptor _concat_descriptor;
Georgios Pinitas427bbbf2018-08-28 13:32:02 +0100331};
332
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000333/** Convolution Layer */
334class ConvolutionLayer final : public ILayer
335{
336public:
Alex Gildayc357c472018-03-21 13:54:09 +0000337 /** Construct a convolution layer.
338 *
Giorgio Arenabb54e4e2018-04-05 17:20:34 +0100339 * @param[in] conv_width Convolution width.
340 * @param[in] conv_height Convolution height.
341 * @param[in] ofm Output feature map.
342 * @param[in] weights Accessor to get kernel weights from.
343 * @param[in] bias Accessor to get kernel bias from.
344 * @param[in] conv_info Padding and stride information.
345 * @param[in] num_groups (Optional) Number of groups. Default: 1.
346 * @param[in] weights_quant_info (Optional) Weights quantization information
347 * @param[in] out_quant_info (Optional) Output quantization info
Alex Gildayc357c472018-03-21 13:54:09 +0000348 */
Giorgio Arenabb54e4e2018-04-05 17:20:34 +0100349 ConvolutionLayer(unsigned int conv_width,
350 unsigned int conv_height,
351 unsigned int ofm,
352 ITensorAccessorUPtr weights,
353 ITensorAccessorUPtr bias,
354 PadStrideInfo conv_info,
355 unsigned int num_groups = 1,
356 const QuantizationInfo weights_quant_info = QuantizationInfo(),
357 const QuantizationInfo out_quant_info = QuantizationInfo())
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000358 : _conv_width(conv_width),
359 _conv_height(conv_height),
360 _ofm(ofm),
361 _conv_info(std::move(conv_info)),
362 _num_groups(num_groups),
363 _weights(std::move(weights)),
Giorgio Arenabb54e4e2018-04-05 17:20:34 +0100364 _bias(std::move(bias)),
365 _weights_quant_info(std::move(weights_quant_info)),
366 _out_quant_info(std::move(out_quant_info))
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000367 {
368 }
369
370 NodeID create_layer(IStream &s) override
371 {
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000372 NodeIdxPair input = { s.tail_node(), 0 };
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +0100373 NodeParams common_params = { name(), s.hints().target_hint };
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000374 return GraphBuilder::add_convolution_node(s.graph(), common_params, input,
Georgios Pinitasee33ea52018-03-08 16:01:29 +0000375 Size2D(_conv_width, _conv_height), _ofm, _conv_info, _num_groups,
Giorgio Arena59631a12018-05-02 13:59:04 +0100376 s.hints().convolution_method_hint, s.hints().fast_math_hint,
Giorgio Arenabb54e4e2018-04-05 17:20:34 +0100377 std::move(_weights), std::move(_bias), std::move(_weights_quant_info), std::move(_out_quant_info));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000378 }
379
380private:
Giorgio Arenabb54e4e2018-04-05 17:20:34 +0100381 unsigned int _conv_width;
382 unsigned int _conv_height;
383 unsigned int _ofm;
384 const PadStrideInfo _conv_info;
385 unsigned int _num_groups;
386 ITensorAccessorUPtr _weights;
387 ITensorAccessorUPtr _bias;
388 const QuantizationInfo _weights_quant_info;
389 const QuantizationInfo _out_quant_info;
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000390};
391
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100392/** Deconvolution Layer */
393class DeconvolutionLayer final : public ILayer
394{
395public:
396 /** Construct a convolution layer.
397 *
Manuel Bottinic1b76fa2019-06-17 12:04:40 +0100398 * @param[in] conv_width Convolution width.
399 * @param[in] conv_height Convolution height.
400 * @param[in] ofm Output feature map.
401 * @param[in] weights Accessor to get kernel weights from.
402 * @param[in] bias Accessor to get kernel bias from.
403 * @param[in] deconv_info Padding and stride information.
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100404 */
405 DeconvolutionLayer(unsigned int conv_width,
406 unsigned int conv_height,
407 unsigned int ofm,
408 ITensorAccessorUPtr weights,
409 ITensorAccessorUPtr bias,
Manuel Bottinic1b76fa2019-06-17 12:04:40 +0100410 PadStrideInfo deconv_info)
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100411 : _conv_width(conv_width),
412 _conv_height(conv_height),
413 _ofm(ofm),
414 _deconv_info(std::move(deconv_info)),
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100415 _weights(std::move(weights)),
416 _bias(std::move(bias))
417 {
418 }
419
420 NodeID create_layer(IStream &s) override
421 {
422 NodeIdxPair input = { s.tail_node(), 0 };
423 NodeParams common_params = { name(), s.hints().target_hint };
424 return GraphBuilder::add_deconvolution_node(s.graph(), common_params, input,
Manuel Bottinic1b76fa2019-06-17 12:04:40 +0100425 Size2D(_conv_width, _conv_height), _ofm, _deconv_info,
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100426 std::move(_weights), std::move(_bias));
427 }
428
429private:
430 unsigned int _conv_width;
431 unsigned int _conv_height;
432 unsigned int _ofm;
433 const PadStrideInfo _deconv_info;
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100434 ITensorAccessorUPtr _weights;
435 ITensorAccessorUPtr _bias;
436};
437
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000438/** Depthwise Convolution Layer */
439class DepthwiseConvolutionLayer final : public ILayer
440{
441public:
Alex Gildayc357c472018-03-21 13:54:09 +0000442 /** Construct a depthwise convolution layer.
443 *
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000444 * @param[in] conv_width Convolution width.
445 * @param[in] conv_height Convolution height.
446 * @param[in] weights Accessor to get kernel weights from.
447 * @param[in] bias Accessor to get kernel bias from.
448 * @param[in] conv_info Padding and stride information.
449 * @param[in] depth_multiplier (Optional) Depth multiplier parameter.
450 * @param[in] weights_quant_info (Optional) Quantization info used for weights
451 * @param[in] out_quant_info (Optional) Output quantization info
Alex Gildayc357c472018-03-21 13:54:09 +0000452 */
Giorgio Arenabb54e4e2018-04-05 17:20:34 +0100453 DepthwiseConvolutionLayer(unsigned int conv_width,
454 unsigned int conv_height,
455 ITensorAccessorUPtr weights,
456 ITensorAccessorUPtr bias,
457 PadStrideInfo conv_info,
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000458 int depth_multiplier = 1,
459 const QuantizationInfo weights_quant_info = QuantizationInfo(),
460 const QuantizationInfo out_quant_info = QuantizationInfo())
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000461 : _conv_width(conv_width),
462 _conv_height(conv_height),
463 _conv_info(std::move(conv_info)),
464 _weights(std::move(weights)),
Giorgio Arenabb54e4e2018-04-05 17:20:34 +0100465 _bias(std::move(bias)),
Georgios Pinitas05045c12018-12-07 18:31:47 +0000466 _depth_multiplier(depth_multiplier),
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000467 _weights_quant_info(std::move(weights_quant_info)),
468 _out_quant_info(std::move(out_quant_info))
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000469 {
470 }
471
472 NodeID create_layer(IStream &s) override
473 {
474 NodeIdxPair input = { s.tail_node(), 0 };
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +0100475 NodeParams common_params = { name(), s.hints().target_hint };
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000476 return GraphBuilder::add_depthwise_convolution_node(s.graph(), common_params,
Georgios Pinitas05045c12018-12-07 18:31:47 +0000477 input, Size2D(_conv_width, _conv_height), _conv_info, _depth_multiplier,
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000478 s.hints().depthwise_convolution_method_hint,
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000479 std::move(_weights), std::move(_bias), std::move(_weights_quant_info), std::move(_out_quant_info));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000480 }
481
482private:
Giorgio Arenabb54e4e2018-04-05 17:20:34 +0100483 unsigned int _conv_width;
484 unsigned int _conv_height;
485 const PadStrideInfo _conv_info;
486 ITensorAccessorUPtr _weights;
487 ITensorAccessorUPtr _bias;
Georgios Pinitas05045c12018-12-07 18:31:47 +0000488 int _depth_multiplier;
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000489 const QuantizationInfo _weights_quant_info;
490 const QuantizationInfo _out_quant_info;
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000491};
Isabella Gottardi7234ed82018-11-27 08:51:10 +0000492/** DetectionOutput Layer */
493class DetectionOutputLayer final : public ILayer
494{
495public:
496 /** Construct a detection output layer.
497 *
498 * @param[in] sub_stream_conf Confidence graph sub-stream.
499 * @param[in] sub_stream_prior PriorBox graph sub-stream.
500 * @param[in] detect_info DetectionOutput parameters.
501 */
Georgios Pinitasf52cd782019-03-25 14:06:14 +0000502 DetectionOutputLayer(SubStream &&sub_stream_conf, SubStream &&sub_stream_prior, const DetectionOutputLayerInfo &detect_info)
Isabella Gottardi7234ed82018-11-27 08:51:10 +0000503 : _ss_conf(std::move(sub_stream_conf)), _ss_prior(std::move(sub_stream_prior)), _detect_info(detect_info)
504 {
505 }
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000506
Isabella Gottardi7234ed82018-11-27 08:51:10 +0000507 NodeID create_layer(IStream &s) override
508 {
509 NodeParams common_params = { name(), s.hints().target_hint };
510 NodeIdxPair input_loc = { s.tail_node(), 0 };
511 NodeIdxPair input_conf = { _ss_conf.tail_node(), 0 };
512 NodeIdxPair input_priorbox = { _ss_prior.tail_node(), 0 };
513 return GraphBuilder::add_detection_output_node(s.graph(), common_params, input_loc, input_conf, input_priorbox, _detect_info);
514 }
515
516private:
517 SubStream _ss_conf;
518 SubStream _ss_prior;
519 DetectionOutputLayerInfo _detect_info;
520};
Isabella Gottardia7acb3c2019-01-08 13:48:44 +0000521/** DetectionOutputPostProcess Layer */
522class DetectionPostProcessLayer final : public ILayer
523{
524public:
525 /** Construct a detection output layer.
526 *
527 * @param[in] sub_stream_class_prediction Class prediction graph sub-stream.
528 * @param[in] detect_info DetectionOutput parameters.
529 * @param[in] anchors Accessor to get anchors tensor data from.
530 * @param[in] out_quant_info (Optional) Output quantization info
531 */
532 DetectionPostProcessLayer(SubStream &&sub_stream_class_prediction, DetectionPostProcessLayerInfo detect_info, ITensorAccessorUPtr anchors,
533 const QuantizationInfo out_quant_info = QuantizationInfo())
534 : _sub_stream_class_prediction(std::move(sub_stream_class_prediction)), _detect_info(detect_info), _anchors(std::move(anchors)), _out_quant_info(std::move(out_quant_info))
535 {
536 }
537
538 NodeID create_layer(IStream &s) override
539 {
540 ARM_COMPUTE_ERROR_ON(_anchors == nullptr);
541
542 NodeParams common_params = { name(), s.hints().target_hint };
543 NodeIdxPair input_box_encoding = { s.tail_node(), 0 };
544 NodeIdxPair input_class_prediction = { _sub_stream_class_prediction.tail_node(), 0 };
545 return GraphBuilder::add_detection_post_process_node(s.graph(), common_params, input_box_encoding, input_class_prediction, _detect_info, std::move(_anchors), std::move(_out_quant_info));
546 }
547
548private:
549 SubStream _sub_stream_class_prediction;
550 DetectionPostProcessLayerInfo _detect_info;
551 ITensorAccessorUPtr _anchors;
552 const QuantizationInfo _out_quant_info;
553};
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100554/** Dummy Layer */
555class DummyLayer final : public ILayer
556{
557public:
558 /** Construct an input layer.
559 *
560 * @param[in] shape Output shape
561 */
562 DummyLayer(TensorShape shape)
563 : _shape(shape)
564 {
565 }
566
567 NodeID create_layer(IStream &s) override
568 {
569 NodeParams common_params = { name(), s.hints().target_hint };
570 NodeIdxPair input = { s.tail_node(), 0 };
571 return GraphBuilder::add_dummy_node(s.graph(), common_params, input, _shape);
572 }
573
574private:
575 TensorShape _shape;
576};
577
Georgios Pinitas427bbbf2018-08-28 13:32:02 +0100578class EltwiseLayer final : public ILayer
579{
580public:
581 /** Construct an element-wise operation layer
582 *
583 * @param[in] sub_stream0 First graph sub-stream
584 * @param[in] sub_stream1 First graph sub-stream
585 * @param[in] op Element-wise operation to perform
586 */
587 EltwiseLayer(SubStream &&sub_stream0, SubStream &&sub_stream1, EltwiseOperation op)
588 : _ss0(std::move(sub_stream0)), _ss1(std::move(sub_stream1)), _op(op)
589 {
590 }
591
592 NodeID create_layer(IStream &s) override
593 {
594 NodeParams common_params = { name(), s.hints().target_hint };
595 NodeIdxPair input0 = { _ss0.tail_node(), 0 };
596 NodeIdxPair input1 = { _ss1.tail_node(), 0 };
597
598 return GraphBuilder::add_elementwise_node(s.graph(), common_params, input0, input1, _op);
599 }
600
601private:
602 SubStream _ss0;
603 SubStream _ss1;
604 EltwiseOperation _op;
605};
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000606/** Flatten Layer */
607class FlattenLayer final : public ILayer
608{
609public:
Alex Gildayc357c472018-03-21 13:54:09 +0000610 /** Construct a flatten layer. */
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000611 FlattenLayer()
612 {
613 }
614
615 NodeID create_layer(IStream &s) override
616 {
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +0100617 NodeParams common_params = { name(), s.hints().target_hint };
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000618 NodeIdxPair input = { s.tail_node(), 0 };
619 return GraphBuilder::add_flatten_node(s.graph(), common_params, input);
620 }
621};
622
623/** Fully Connected Layer */
624class FullyConnectedLayer final : public ILayer
625{
626public:
Alex Gildayc357c472018-03-21 13:54:09 +0000627 /** Construct a fully connected layer.
628 *
Georgios Pinitas2f1366a2018-07-31 16:33:06 +0100629 * @param[in] num_outputs Number of outputs.
630 * @param[in] weights Accessor to get weights from.
631 * @param[in] bias Accessor to get bias from.
Georgios Pinitasc55cef12018-08-01 15:24:18 +0100632 * @param[in] fc_info (Optional) Fully connected layer metadata
Georgios Pinitas2f1366a2018-07-31 16:33:06 +0100633 * @param[in] weights_quant_info (Optional) Weights quantization information
634 * @param[in] out_quant_info (Optional) Output quantization info
Alex Gildayc357c472018-03-21 13:54:09 +0000635 */
Georgios Pinitasc55cef12018-08-01 15:24:18 +0100636 FullyConnectedLayer(unsigned int num_outputs,
637 ITensorAccessorUPtr weights,
638 ITensorAccessorUPtr bias,
639 const FullyConnectedLayerInfo fc_info = FullyConnectedLayerInfo(),
640 const QuantizationInfo weights_quant_info = QuantizationInfo(),
641 const QuantizationInfo out_quant_info = QuantizationInfo())
Georgios Pinitas2f1366a2018-07-31 16:33:06 +0100642 : _num_outputs(num_outputs),
643 _weights(std::move(weights)),
644 _bias(std::move(bias)),
Michele Di Giorgioa42f55f2019-03-08 14:52:17 +0000645 _weights_ss(nullptr),
646 _bias_ss(nullptr),
647 _fc_info(fc_info),
648 _weights_quant_info(std::move(weights_quant_info)),
649 _out_quant_info(std::move(out_quant_info))
650 {
651 }
652
653 /** Construct a fully connected layer.
654 *
655 * @param[in] num_outputs Number of outputs.
656 * @param[in] sub_stream_weights Graph sub-stream for the weights.
657 * @param[in] sub_stream_bias Graph sub-stream for the bias.
658 * @param[in] fc_info (Optional) Fully connected layer metadata
659 * @param[in] weights_quant_info (Optional) Weights quantization information
660 * @param[in] out_quant_info (Optional) Output quantization info
661 */
662 FullyConnectedLayer(unsigned int num_outputs,
Michalis Spyrou1a569a32019-09-10 17:20:34 +0100663 SubStream sub_stream_weights,
664 SubStream sub_stream_bias,
Michele Di Giorgioa42f55f2019-03-08 14:52:17 +0000665 const FullyConnectedLayerInfo fc_info = FullyConnectedLayerInfo(),
666 const QuantizationInfo weights_quant_info = QuantizationInfo(),
667 const QuantizationInfo out_quant_info = QuantizationInfo())
668 : _num_outputs(num_outputs),
669 _weights(nullptr),
670 _bias(nullptr),
671 _weights_ss(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream_weights))),
672 _bias_ss(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream_bias))),
Georgios Pinitasc55cef12018-08-01 15:24:18 +0100673 _fc_info(fc_info),
Georgios Pinitas2f1366a2018-07-31 16:33:06 +0100674 _weights_quant_info(std::move(weights_quant_info)),
675 _out_quant_info(std::move(out_quant_info))
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000676 {
677 }
678
Michele Di Giorgio47e6fed2018-11-13 12:04:25 +0000679 /** Create layer and add to the given stream.
680 *
681 * @param[in] s Stream to add layer to.
682 *
683 * @return ID of the created node.
684 */
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000685 NodeID create_layer(IStream &s) override
686 {
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +0100687 NodeParams common_params = { name(), s.hints().target_hint };
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000688 NodeIdxPair input = { s.tail_node(), 0 };
Michele Di Giorgioa42f55f2019-03-08 14:52:17 +0000689 if(_weights != nullptr)
690 {
691 return GraphBuilder::add_fully_connected_layer(s.graph(), common_params, input, _num_outputs,
692 std::move(_weights), std::move(_bias), _fc_info,
693 std::move(_weights_quant_info), std::move(_out_quant_info));
694 }
695 else
696 {
697 ARM_COMPUTE_ERROR_ON(_weights_ss == nullptr);
698
699 NodeID bias_nid = (_bias_ss == nullptr) ? EmptyNodeID : _bias_ss->tail_node();
700 return GraphBuilder::add_fully_connected_layer(s.graph(), common_params, input, _num_outputs,
701 _weights_ss->tail_node(), bias_nid, _fc_info,
702 std::move(_out_quant_info));
703 }
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000704 }
705
706private:
Georgios Pinitasc55cef12018-08-01 15:24:18 +0100707 unsigned int _num_outputs;
708 ITensorAccessorUPtr _weights;
709 ITensorAccessorUPtr _bias;
Michele Di Giorgioa42f55f2019-03-08 14:52:17 +0000710 std::unique_ptr<SubStream> _weights_ss;
711 std::unique_ptr<SubStream> _bias_ss;
Georgios Pinitasc55cef12018-08-01 15:24:18 +0100712 const FullyConnectedLayerInfo _fc_info;
713 const QuantizationInfo _weights_quant_info;
714 const QuantizationInfo _out_quant_info;
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000715};
716
Manuel Bottini5209be52019-02-13 16:34:56 +0000717/** Generate Proposals Layer */
718class GenerateProposalsLayer final : public ILayer
719{
720public:
721 /** Construct a generate proposals layer.
722 *
723 * @param[in] ss_scores Graph sub-stream for the scores.
724 * @param[in] ss_deltas Graph sub-stream for the deltas.
725 * @param[in] ss_anchors Graph sub-stream for the anchors.
726 * @param[in] info Generate Proposals operation information.
727 */
728 GenerateProposalsLayer(SubStream &&ss_scores, SubStream &&ss_deltas, SubStream &&ss_anchors, GenerateProposalsInfo info)
729 : _ss_scores(std::move(ss_scores)), _ss_deltas(std::move(ss_deltas)), _ss_anchors(std::move(ss_anchors)), _info(info)
730 {
731 }
732
733 /** Create layer and add to the given stream.
734 *
735 * @param[in] s Stream to add layer to.
736 *
737 * @return ID of the created node.
738 */
739 NodeID create_layer(IStream &s) override
740 {
741 NodeParams common_params = { name(), s.hints().target_hint };
742 NodeIdxPair scores = { _ss_scores.tail_node(), 0 };
743 NodeIdxPair deltas = { _ss_deltas.tail_node(), 0 };
744 NodeIdxPair anchors = { _ss_anchors.tail_node(), 0 };
745 return GraphBuilder::add_generate_proposals_node(s.graph(), common_params, scores, deltas, anchors, _info);
746 }
747
748private:
749 SubStream _ss_scores;
750 SubStream _ss_deltas;
751 SubStream _ss_anchors;
752 GenerateProposalsInfo _info;
753};
754
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000755/** Normalization Layer */
756class NormalizationLayer final : public ILayer
757{
758public:
Alex Gildayc357c472018-03-21 13:54:09 +0000759 /** Construct a normalization layer.
760 *
761 * @param[in] norm_info Normalization information.
762 */
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000763 NormalizationLayer(NormalizationLayerInfo norm_info)
764 : _norm_info(norm_info)
765 {
766 }
767
768 NodeID create_layer(IStream &s) override
769 {
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +0100770 NodeParams common_params = { name(), s.hints().target_hint };
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000771 NodeIdxPair input = { s.tail_node(), 0 };
772 return GraphBuilder::add_normalization_node(s.graph(), common_params, input, _norm_info);
773 }
774
775private:
776 NormalizationLayerInfo _norm_info;
777};
778
Michele Di Giorgio555d1102018-09-12 13:51:59 +0100779/** Normalize planar YUV Layer */
780class NormalizePlanarYUVLayer final : public ILayer
781{
782public:
783 /** Construct a normalize planar YUV layer.
784 *
785 * @param[in] mean Accessor to get mean tensor data from.
786 * @param[in] std Accessor to get std tensor data from.
787 */
788 NormalizePlanarYUVLayer(ITensorAccessorUPtr mean,
789 ITensorAccessorUPtr std)
790 : _mean(std::move(mean)), _std(std::move(std))
791 {
792 }
793
794 NodeID create_layer(IStream &s) override
795 {
796 ARM_COMPUTE_ERROR_ON(_mean == nullptr);
797 ARM_COMPUTE_ERROR_ON(_std == nullptr);
798
799 NodeParams common_params = { name(), s.hints().target_hint };
800 NodeIdxPair input = { s.tail_node(), 0 };
801 return GraphBuilder::add_normalize_planar_yuv_node(s.graph(), common_params, input,
802 std::move(_mean), std::move(_std));
803 }
804
805private:
806 ITensorAccessorUPtr _mean;
807 ITensorAccessorUPtr _std;
808};
809
Michele Di Giorgio4bb17332018-09-26 13:56:51 +0100810/** Pad Layer */
811class PadLayer final : public ILayer
812{
813public:
814 /** Construct a pad layer.
815 *
816 * @param[in] padding The padding for each spatial dimension of the input tensor. The pair padding[i]
817 * specifies the front and the end padding in the i-th dimension.
818 */
819 PadLayer(PaddingList padding)
820 : _padding(padding)
821 {
822 }
823
824 NodeID create_layer(IStream &s) override
825 {
826 NodeParams common_params = { name(), s.hints().target_hint };
827 NodeIdxPair input = { s.tail_node(), 0 };
828 return GraphBuilder::add_pad_node(s.graph(), common_params, input, _padding);
829 }
830
831private:
832 PaddingList _padding;
833};
834
Georgios Pinitas57c48242018-08-02 13:41:49 +0100835/** Permute Layer */
836class PermuteLayer final : public ILayer
837{
838public:
839 /** Construct a permute layer.
840 *
841 * @param[in] perm Permutation vector.
842 * @param[in] layout (Optional) Data layout to assign to permuted tensor.
843 * If UNKNOWN then the input's layout will be used.
844 */
845 PermuteLayer(PermutationVector perm, DataLayout layout = DataLayout::UNKNOWN)
846 : _perm(perm), _layout(layout)
847 {
848 }
849
850 NodeID create_layer(IStream &s) override
851 {
852 NodeParams common_params = { name(), s.hints().target_hint };
853 NodeIdxPair input = { s.tail_node(), 0 };
854 return GraphBuilder::add_permute_node(s.graph(), common_params, input, _perm, _layout);
855 }
856
857private:
858 PermutationVector _perm;
859 DataLayout _layout;
860};
861
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000862/** Pooling Layer */
863class PoolingLayer final : public ILayer
864{
865public:
Alex Gildayc357c472018-03-21 13:54:09 +0000866 /** Construct a pooling layer.
867 *
868 * @param[in] pool_info Pooling information.
869 */
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000870 PoolingLayer(PoolingLayerInfo pool_info)
871 : _pool_info(pool_info)
872 {
873 }
874
875 NodeID create_layer(IStream &s) override
876 {
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +0100877 NodeParams common_params = { name(), s.hints().target_hint };
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000878 NodeIdxPair input = { s.tail_node(), 0 };
879 return GraphBuilder::add_pooling_node(s.graph(), common_params, input, _pool_info);
880 }
881
882private:
883 PoolingLayerInfo _pool_info;
884};
885
Pablo Tello32521432018-11-15 14:43:10 +0000886/** PriorBox Layer */
887class PriorBoxLayer final : public ILayer
888{
889public:
890 /** Construct a priorbox layer.
891 *
892 * @param[in] sub_stream First graph sub-stream
893 * @param[in] prior_info PriorBox parameters.
894 */
Georgios Pinitasf52cd782019-03-25 14:06:14 +0000895 PriorBoxLayer(SubStream &&sub_stream, const PriorBoxLayerInfo &prior_info)
Pablo Tello32521432018-11-15 14:43:10 +0000896 : _ss(std::move(sub_stream)), _prior_info(prior_info)
897 {
898 }
899
900 NodeID create_layer(IStream &s) override
901 {
902 NodeParams common_params = { name(), s.hints().target_hint };
903 NodeIdxPair input0 = { s.tail_node(), 0 };
904 NodeIdxPair input1 = { _ss.tail_node(), 0 };
905 return GraphBuilder::add_priorbox_node(s.graph(), common_params, input0, input1, _prior_info);
906 }
907
908private:
909 SubStream _ss;
910 PriorBoxLayerInfo _prior_info;
911};
912
Isabella Gottardi3db1ba92019-05-17 12:35:20 +0100913/** Quantization Layer */
914class QuantizationLayer final : public ILayer
915{
916public:
917 /** Construct a quantization layer.
918 *
919 * @param[in] out_quant_info Output tensor quantization info
920 */
921 QuantizationLayer(QuantizationInfo out_quant_info)
922 : _out_quant_info(out_quant_info)
923 {
924 }
925
926 NodeID create_layer(IStream &s) override
927 {
928 NodeParams common_params = { name(), s.hints().target_hint };
929 NodeIdxPair input = { s.tail_node(), 0 };
930 return GraphBuilder::add_quantization_node(s.graph(), common_params, input, _out_quant_info);
931 }
932
933private:
934 QuantizationInfo _out_quant_info;
935};
936
Gian Marco Iodice23e24792018-09-07 15:32:14 +0100937/** Reorg Layer */
938class ReorgLayer final : public ILayer
939{
940public:
941 /** Construct a reorg layer.
942 *
943 * @param[in] stride Stride value to use for reorganizing the values in the output tensor.
944 * It defines the spatial distance between 2 consecutive pixels in the x and y direction
945 */
946 ReorgLayer(int stride)
947 : _stride(stride)
948 {
949 }
950
951 NodeID create_layer(IStream &s) override
952 {
953 NodeParams common_params = { name(), s.hints().target_hint };
954 NodeIdxPair input = { s.tail_node(), 0 };
955 return GraphBuilder::add_reorg_node(s.graph(), common_params, input, _stride);
956 }
957
958private:
959 int _stride;
960};
961
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000962/** Reshape Layer */
963class ReshapeLayer final : public ILayer
964{
965public:
Alex Gildayc357c472018-03-21 13:54:09 +0000966 /** Construct a reshape layer.
967 *
968 * @param[in] shape Target shape.
969 */
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000970 ReshapeLayer(TensorShape shape)
971 : _shape(shape)
972 {
973 }
974
975 NodeID create_layer(IStream &s) override
976 {
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +0100977 NodeParams common_params = { name(), s.hints().target_hint };
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000978 NodeIdxPair input = { s.tail_node(), 0 };
979 return GraphBuilder::add_reshape_node(s.graph(), common_params, input, _shape);
980 }
981
982private:
983 TensorShape _shape;
984};
985
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100986/** Resize Layer */
987class ResizeLayer final : public ILayer
988{
989public:
990 ResizeLayer(InterpolationPolicy policy, float width_scale, float height_scale)
991 : _policy(policy), _width_scale(width_scale), _height_scale(height_scale)
992 {
993 }
994
995 NodeID create_layer(IStream &s) override
996 {
997 NodeParams common_params = { name(), s.hints().target_hint };
998 NodeIdxPair input = { s.tail_node(), 0 };
999 return GraphBuilder::add_resize_node(s.graph(), common_params, input, _policy, _width_scale, _height_scale);
1000 }
1001
1002private:
1003 InterpolationPolicy _policy;
1004 float _width_scale;
1005 float _height_scale;
1006};
1007
Manuel Bottini3f9d4d72018-10-19 14:04:42 +01001008/** ROIAlign Layer */
1009class ROIAlignLayer final : public ILayer
1010{
1011public:
1012 /** Construct a RoiAlign layer.
1013 *
1014 * @param[in] sub_stream_input Graph sub-stream for the input
1015 * @param[in] sub_stream_rois Graph sub-stream for the rois
1016 * @param[in] pool_info Pooling information.
1017 */
1018 ROIAlignLayer(SubStream &&sub_stream_input, SubStream &&sub_stream_rois, ROIPoolingLayerInfo pool_info)
1019 : _ss_input(sub_stream_input), _ss_rois(sub_stream_rois), _pool_info(pool_info)
1020 {
1021 }
1022
1023 /** Prevent instances of this class from being copy constructed */
1024 ROIAlignLayer(const ROIAlignLayer &) = delete;
1025 /** Prevent instances of this class from being copied */
1026 ROIAlignLayer &operator=(const ROIAlignLayer &) = delete;
1027
1028 NodeID create_layer(IStream &s) override
1029 {
1030 NodeParams common_params = { name(), s.hints().target_hint };
1031 NodeIdxPair input = { _ss_input.tail_node(), 0 };
1032 NodeIdxPair rois = { _ss_rois.tail_node(), 0 };
1033 return GraphBuilder::add_roi_align_node(s.graph(), common_params, input, rois, _pool_info);
1034 }
1035
1036private:
1037 SubStream _ss_input;
1038 SubStream _ss_rois;
1039 ROIPoolingLayerInfo _pool_info;
1040};
1041
Isabella Gottardi88d5b222018-04-06 12:24:55 +01001042/** Scale Layer */
1043class ScaleLayer final : public ILayer
1044{
1045public:
1046 /** Construct a scale layer.
1047 *
1048 * @param[in] mul_w Accessor to get mul weight from.
1049 * @param[in] add_w Accessor to get add weight from.
1050 */
1051 ScaleLayer(ITensorAccessorUPtr mul_w,
1052 ITensorAccessorUPtr add_w)
1053 : _mul_w(std::move(mul_w)), _add_w(std::move(add_w))
1054 {
1055 }
1056
1057 NodeID create_layer(IStream &s) override
1058 {
1059 NodeParams common_params = { name(), s.hints().target_hint };
1060 NodeIdxPair input = { s.tail_node(), 0 };
1061 return GraphBuilder::add_scale_layer(s.graph(), common_params, input, std::move(_mul_w), std::move(_add_w));
1062 }
1063
1064private:
1065 ITensorAccessorUPtr _mul_w;
1066 ITensorAccessorUPtr _add_w;
1067};
1068
Michele Di Giorgioc30b6682018-09-12 17:44:08 +01001069/** Slice Layer */
1070class SliceLayer final : public ILayer
1071{
1072public:
1073 /** Construct a slice layer.
1074 *
1075 * @param[in] starts The starts of the dimensions of the input tensor to be sliced. The length must be of rank(input).
1076 * @param[in] ends The ends of the dimensions of the input tensor to be sliced. The length must be of rank(input).
1077 */
1078 SliceLayer(Coordinates &starts, Coordinates &ends)
1079 : _starts(starts), _ends(ends)
1080 {
1081 }
1082
1083 NodeID create_layer(IStream &s) override
1084 {
1085 NodeParams common_params = { name(), s.hints().target_hint };
1086 NodeIdxPair input = { s.tail_node(), 0 };
1087 return GraphBuilder::add_slice_node(s.graph(), common_params, input, _starts, _ends);
1088 }
1089
1090private:
1091 Coordinates _starts;
1092 Coordinates _ends;
1093};
1094
Georgios Pinitasd8734b52017-12-22 15:27:52 +00001095/** Softmax Layer */
1096class SoftmaxLayer final : public ILayer
1097{
1098public:
Alex Gildayc357c472018-03-21 13:54:09 +00001099 /** Construct a softmax layer.
1100 *
1101 * @param[in] beta (Optional) Beta value. Default 1.0.
1102 */
Georgios Pinitasd8734b52017-12-22 15:27:52 +00001103 SoftmaxLayer(float beta = 1.0f)
1104 : _beta(beta)
1105 {
1106 }
1107
1108 NodeID create_layer(IStream &s) override
1109 {
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +01001110 NodeParams common_params = { name(), s.hints().target_hint };
Georgios Pinitasd8734b52017-12-22 15:27:52 +00001111 NodeIdxPair input = { s.tail_node(), 0 };
1112 return GraphBuilder::add_softmax_node(s.graph(), common_params, input, _beta);
1113 }
1114
1115private:
1116 float _beta;
1117};
Michalis Spyrou96f67692018-09-13 11:39:28 +01001118
Michele Di Giorgioec699752019-03-22 15:25:32 +00001119/** Stack Layer */
1120class StackLayer final : public ILayer
1121{
1122public:
1123 /** Construct a concatenation layer
1124 *
1125 * @param[in] sub_stream1 First graph branch
1126 * @param[in] sub_stream2 Second graph branch
1127 * @param[in] rest_sub_streams Rest sub-graph branches
1128 */
1129 template <typename... Ts>
1130 StackLayer(SubStream &&sub_stream1, SubStream &&sub_stream2, Ts &&... rest_sub_streams)
1131 : _sub_streams(), _axis(0)
1132 {
1133 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream1)));
1134 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream2)));
1135
1136 utility::for_each([&](SubStream && sub_stream)
1137 {
1138 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream)));
1139 },
1140 std::move(rest_sub_streams)...);
1141 }
1142 /** Construct a concatenation layer
1143 *
1144 * @param[in] axis Stack layer axis along which to stack the inputs
1145 * @param[in] sub_stream1 First graph branch
1146 * @param[in] sub_stream2 Second graph branch
1147 * @param[in] rest_sub_streams Rest sub-graph branches
1148 */
1149 template <typename... Ts>
1150 StackLayer(int axis, SubStream &&sub_stream1, SubStream &&sub_stream2, Ts &&... rest_sub_streams)
1151 : _sub_streams(), _axis(axis)
1152 {
1153 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream1)));
1154 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream2)));
1155
1156 utility::for_each([&](SubStream && sub_stream)
1157 {
1158 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream)));
1159 },
1160 std::move(rest_sub_streams)...);
1161 }
1162 /** Construct a concat layer
1163 *
1164 * @param[in] sub_stream Sub-stream
1165 */
1166 template <typename... Ts>
1167 StackLayer(SubStream &&sub_stream)
1168 : _sub_streams(), _axis(0)
1169 {
1170 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream)));
1171 }
1172 NodeID create_layer(IStream &s) override
1173 {
1174 NodeID nid = EmptyNodeID;
1175 NodeParams common_params = { name(), s.hints().target_hint };
1176 if(_sub_streams.size() == 1 && _sub_streams.at(0) != nullptr)
1177 {
1178 nid = _sub_streams[0]->tail_node();
1179 }
1180 else
1181 {
1182 // Collect tail nodes and stack
1183 std::vector<NodeIdxPair> nodes;
1184 for(auto &ss : _sub_streams)
1185 {
1186 if(ss && (ss->tail_node() != EmptyNodeID))
1187 {
1188 const auto tail_node = s.graph().node(ss->tail_node());
1189 if(tail_node != nullptr && tail_node->type() != NodeType::Output)
1190 {
1191 nodes.push_back({ ss->tail_node(), 0 });
1192 }
1193 }
1194 }
1195 nid = GraphBuilder::add_stack_node(s.graph(), common_params, nodes, _axis);
1196 }
1197 return nid;
1198 }
1199
1200private:
1201 std::vector<std::unique_ptr<SubStream>> _sub_streams;
1202 int _axis;
1203};
1204
Michalis Spyrou4e1c3f32018-09-20 17:14:03 +01001205/** Upsample Layer */
1206class UpsampleLayer final : public ILayer
1207{
1208public:
1209 /** Construct a Upsample layer.
1210 *
1211 * @param[in] info Stride info
1212 * @param[in] upsampling_policy Upsampling policy
1213 */
1214 UpsampleLayer(Size2D info, InterpolationPolicy upsampling_policy)
1215 : _info(info), _upsampling_policy(upsampling_policy)
1216 {
1217 }
1218
1219 NodeID create_layer(IStream &s) override
1220 {
1221 NodeParams common_params = { name(), s.hints().target_hint };
1222 NodeIdxPair input = { s.tail_node(), 0 };
1223 return GraphBuilder::add_upsample_node(s.graph(), common_params, input, _info, _upsampling_policy);
1224 }
1225
1226private:
1227 Size2D _info;
1228 InterpolationPolicy _upsampling_policy;
1229};
1230
Michalis Spyrou96f67692018-09-13 11:39:28 +01001231/** YOLO Layer */
1232class YOLOLayer final : public ILayer
1233{
1234public:
1235 /** Construct a YOLO layer.
1236 *
1237 * @param[in] act_info Activation info
1238 * @param[in] num_classes Number of classes to activate
1239 */
1240 YOLOLayer(ActivationLayerInfo act_info, int32_t num_classes)
1241 : _act_info(act_info), _num_classes(num_classes)
1242 {
1243 }
1244
1245 NodeID create_layer(IStream &s) override
1246 {
1247 NodeParams common_params = { name(), s.hints().target_hint };
1248 NodeIdxPair input = { s.tail_node(), 0 };
1249 return GraphBuilder::add_yolo_node(s.graph(), common_params, input, _act_info, _num_classes);
1250 }
1251
1252private:
1253 ActivationLayerInfo _act_info;
1254 int32_t _num_classes;
1255};
Georgios Pinitasd8734b52017-12-22 15:27:52 +00001256} // namespace frontend
Georgios Pinitasd9eb2752018-04-03 13:44:29 +01001257} // namespace graph
Georgios Pinitasd8734b52017-12-22 15:27:52 +00001258} // namespace arm_compute
Georgios Pinitasd9eb2752018-04-03 13:44:29 +01001259#endif /* __ARM_COMPUTE_GRAPH_LAYERS_H__ */