blob: 3fc4af46d5b3e79996165c509e4978e75e7f5fc9 [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
69/** Output Layer */
70class OutputLayer final : public ILayer
71{
72public:
Alex Gildayc357c472018-03-21 13:54:09 +000073 /** Construct an output layer.
74 *
Isabella Gottardi0ae5de92019-03-14 10:32:11 +000075 * @param[in] accessor Accessor to give output tensor data to.
76 * @param[in] connection_idx (Optional) Input connection index
Alex Gildayc357c472018-03-21 13:54:09 +000077 */
Isabella Gottardi0ae5de92019-03-14 10:32:11 +000078 OutputLayer(ITensorAccessorUPtr accessor, unsigned int connection_idx = 0)
79 : _accessor(std::move(accessor)), _connection_idx(connection_idx)
Georgios Pinitasd8734b52017-12-22 15:27:52 +000080 {
81 }
82
83 NodeID create_layer(IStream &s) override
84 {
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +010085 NodeParams common_params = { name(), s.hints().target_hint };
Isabella Gottardi0ae5de92019-03-14 10:32:11 +000086 NodeIdxPair input = { s.tail_node(), _connection_idx };
Georgios Pinitasd8734b52017-12-22 15:27:52 +000087 return GraphBuilder::add_output_node(s.graph(), common_params, input, std::move(_accessor));
88 }
89
90private:
91 ITensorAccessorUPtr _accessor;
Isabella Gottardi0ae5de92019-03-14 10:32:11 +000092 unsigned int _connection_idx;
Georgios Pinitasd8734b52017-12-22 15:27:52 +000093};
94
95/** Activation Layer */
96class ActivationLayer final : public ILayer
97{
98public:
Alex Gildayc357c472018-03-21 13:54:09 +000099 /** Construct an activation layer.
100 *
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000101 * @param[in] act_info Activation information
102 * @param[in] out_quant_info (Optional) Output quantization info
Alex Gildayc357c472018-03-21 13:54:09 +0000103 */
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000104 ActivationLayer(ActivationLayerInfo act_info,
105 const QuantizationInfo out_quant_info = QuantizationInfo())
106 : _act_info(act_info),
107 _out_quant_info(std::move(out_quant_info))
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000108 {
109 }
110
111 NodeID create_layer(IStream &s) override
112 {
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +0100113 NodeParams common_params = { name(), s.hints().target_hint };
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000114 NodeIdxPair input = { s.tail_node(), 0 };
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000115 return GraphBuilder::add_activation_node(s.graph(), common_params, input, _act_info, std::move(_out_quant_info));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000116 }
117
118private:
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000119 ActivationLayerInfo _act_info;
120 const QuantizationInfo _out_quant_info;
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000121};
122
123/** Batchnormalization Layer */
124class BatchNormalizationLayer final : public ILayer
125{
126public:
Alex Gildayc357c472018-03-21 13:54:09 +0000127 /** Construct a batch normalization layer.
128 *
129 * @param[in] mean Accessor to get mean tensor data from.
130 * @param[in] var Accessor to get var tensor data from.
131 * @param[in] gamma (Optional) Accessor to get gamma tensor data from. Default: nullptr.
132 * @param[in] beta (Optional) Accessor to get beta tensor data from. Default: nullptr.
133 * @param[in] epsilon (Optional) Epsilon value. Default: 0.001.
134 */
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000135 BatchNormalizationLayer(ITensorAccessorUPtr mean,
136 ITensorAccessorUPtr var,
137 ITensorAccessorUPtr gamma = nullptr,
138 ITensorAccessorUPtr beta = nullptr,
139 float epsilon = 0.001f)
140 : _mean(std::move(mean)), _var(std::move(var)), _gamma(std::move(gamma)), _beta(std::move(beta)), _epsilon(epsilon)
141 {
142 }
143
144 NodeID create_layer(IStream &s) override
145 {
146 ARM_COMPUTE_ERROR_ON(_mean == nullptr);
147 ARM_COMPUTE_ERROR_ON(_var == nullptr);
148
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +0100149 NodeParams common_params = { name(), s.hints().target_hint };
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000150 NodeIdxPair input = { s.tail_node(), 0 };
151 return GraphBuilder::add_batch_normalization_node(s.graph(), common_params, input, _epsilon,
152 std::move(_mean), std::move(_var), std::move(_beta), std::move(_gamma));
153 }
154
155private:
156 ITensorAccessorUPtr _mean;
157 ITensorAccessorUPtr _var;
158 ITensorAccessorUPtr _gamma;
159 ITensorAccessorUPtr _beta;
160 float _epsilon;
161};
162
Manuel Bottinid2048ce2018-10-23 17:00:42 +0100163/** Bounding Box Transform Layer */
164class BoundingBoxTransformLayer final : public ILayer
165{
166public:
167 /** Construct a bounding box transform layer.
168 *
169 * @param[in] sub_stream_input Graph sub-stream for the input
170 * @param[in] sub_stream_deltas Graph sub-stream for the deltas
171 * @param[in] info Contains BoundingBox operation information described in @ref BoundingBoxTransformInfo.
172 */
173 BoundingBoxTransformLayer(SubStream &&sub_stream_input, SubStream &&sub_stream_deltas, BoundingBoxTransformInfo info)
174 : _ss_input(sub_stream_input), _ss_deltas(sub_stream_deltas), _bbox_info(info)
175 {
176 }
177
178 /** Create layer and add to the given stream.
179 *
180 * @param[in] s Stream to add layer to.
181 *
182 * @return ID of the created node.
183 */
184 NodeID create_layer(IStream &s) override
185 {
186 NodeParams common_params = { name(), s.hints().target_hint };
187 NodeIdxPair input = { _ss_input.tail_node(), 0 };
188 NodeIdxPair deltas = { _ss_deltas.tail_node(), 0 };
189 return GraphBuilder::add_bounding_box_transform_node(s.graph(), common_params, input, deltas, _bbox_info);
190 }
191
192private:
193 SubStream _ss_input;
194 SubStream _ss_deltas;
195 BoundingBoxTransformInfo _bbox_info;
196};
197
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100198/** Channel Shuffle Layer */
199class ChannelShuffleLayer final : public ILayer
200{
201public:
202 /** Construct a Channel Shuffle layer.
203 *
204 * @param[in] num_groups Number of groups
205 */
206 ChannelShuffleLayer(unsigned int num_groups)
207 : _num_groups(num_groups)
208 {
209 }
210
211 NodeID create_layer(IStream &s) override
212 {
213 NodeParams common_params = { name(), s.hints().target_hint };
214 NodeIdxPair input = { s.tail_node(), 0 };
215 return GraphBuilder::add_channel_shuffle_node(s.graph(), common_params, input, _num_groups);
216 }
217
218private:
219 unsigned int _num_groups;
220};
221
Georgios Pinitas427bbbf2018-08-28 13:32:02 +0100222/** Concat Layer */
223class ConcatLayer final : public ILayer
224{
225public:
226 /** Construct a concatenation layer
227 *
228 * @param[in] sub_stream1 First graph branch
229 * @param[in] sub_stream2 Second graph branch
230 * @param[in] rest_sub_streams Rest sub-graph branches
231 */
232 template <typename... Ts>
233 ConcatLayer(SubStream &&sub_stream1, SubStream &&sub_stream2, Ts &&... rest_sub_streams)
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000234 : _sub_streams(), _concat_descriptor(DataLayoutDimension::CHANNEL)
Pablo Tello32521432018-11-15 14:43:10 +0000235 {
236 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream1)));
237 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream2)));
238
239 utility::for_each([&](SubStream && sub_stream)
240 {
241 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream)));
242 },
243 std::move(rest_sub_streams)...);
244 }
245 /** Construct a concatenation layer
246 *
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000247 * @param[in] concat_descriptor Concat layer descriptor
248 * @param[in] sub_stream1 First graph branch
249 * @param[in] sub_stream2 Second graph branch
250 * @param[in] rest_sub_streams Rest sub-graph branches
Pablo Tello32521432018-11-15 14:43:10 +0000251 */
252 template <typename... Ts>
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000253 ConcatLayer(descriptors::ConcatLayerDescriptor concat_descriptor, SubStream &&sub_stream1, SubStream &&sub_stream2, Ts &&... rest_sub_streams)
254 : _sub_streams(), _concat_descriptor(concat_descriptor)
Georgios Pinitas427bbbf2018-08-28 13:32:02 +0100255 {
256 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream1)));
257 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream2)));
258
259 utility::for_each([&](SubStream && sub_stream)
260 {
261 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream)));
262 },
263 std::move(rest_sub_streams)...);
264 }
265 /** Construct a concat layer
266 *
267 * @param[in] sub_stream Sub-stream
268 */
269 template <typename... Ts>
270 ConcatLayer(SubStream &&sub_stream)
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000271 : _sub_streams(), _concat_descriptor(DataLayoutDimension::CHANNEL)
Georgios Pinitas427bbbf2018-08-28 13:32:02 +0100272 {
273 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream)));
274 }
275 NodeID create_layer(IStream &s) override
276 {
277 NodeID nid = EmptyNodeID;
278 NodeParams common_params = { name(), s.hints().target_hint };
279 if(_sub_streams.size() == 1 && _sub_streams.at(0) != nullptr)
280 {
281 nid = _sub_streams[0]->tail_node();
282 }
283 else
284 {
285 // Collect tail nodes and concatenate
286 std::vector<NodeIdxPair> nodes;
287 for(auto &ss : _sub_streams)
288 {
289 if(ss && (ss->tail_node() != EmptyNodeID))
290 {
291 const auto tail_node = s.graph().node(ss->tail_node());
292 if(tail_node != nullptr && tail_node->type() != NodeType::Output)
293 {
294 nodes.push_back({ ss->tail_node(), 0 });
295 }
296 }
297 }
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000298 nid = GraphBuilder::add_concatenate_node(s.graph(), common_params, nodes, _concat_descriptor);
Georgios Pinitas427bbbf2018-08-28 13:32:02 +0100299 }
300 return nid;
301 }
302
303private:
304 std::vector<std::unique_ptr<SubStream>> _sub_streams;
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000305 descriptors::ConcatLayerDescriptor _concat_descriptor;
Georgios Pinitas427bbbf2018-08-28 13:32:02 +0100306};
307
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000308/** Convolution Layer */
309class ConvolutionLayer final : public ILayer
310{
311public:
Alex Gildayc357c472018-03-21 13:54:09 +0000312 /** Construct a convolution layer.
313 *
Giorgio Arenabb54e4e2018-04-05 17:20:34 +0100314 * @param[in] conv_width Convolution width.
315 * @param[in] conv_height Convolution height.
316 * @param[in] ofm Output feature map.
317 * @param[in] weights Accessor to get kernel weights from.
318 * @param[in] bias Accessor to get kernel bias from.
319 * @param[in] conv_info Padding and stride information.
320 * @param[in] num_groups (Optional) Number of groups. Default: 1.
321 * @param[in] weights_quant_info (Optional) Weights quantization information
322 * @param[in] out_quant_info (Optional) Output quantization info
Alex Gildayc357c472018-03-21 13:54:09 +0000323 */
Giorgio Arenabb54e4e2018-04-05 17:20:34 +0100324 ConvolutionLayer(unsigned int conv_width,
325 unsigned int conv_height,
326 unsigned int ofm,
327 ITensorAccessorUPtr weights,
328 ITensorAccessorUPtr bias,
329 PadStrideInfo conv_info,
330 unsigned int num_groups = 1,
331 const QuantizationInfo weights_quant_info = QuantizationInfo(),
332 const QuantizationInfo out_quant_info = QuantizationInfo())
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000333 : _conv_width(conv_width),
334 _conv_height(conv_height),
335 _ofm(ofm),
336 _conv_info(std::move(conv_info)),
337 _num_groups(num_groups),
338 _weights(std::move(weights)),
Giorgio Arenabb54e4e2018-04-05 17:20:34 +0100339 _bias(std::move(bias)),
340 _weights_quant_info(std::move(weights_quant_info)),
341 _out_quant_info(std::move(out_quant_info))
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000342 {
343 }
344
345 NodeID create_layer(IStream &s) override
346 {
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000347 NodeIdxPair input = { s.tail_node(), 0 };
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +0100348 NodeParams common_params = { name(), s.hints().target_hint };
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000349 return GraphBuilder::add_convolution_node(s.graph(), common_params, input,
Georgios Pinitasee33ea52018-03-08 16:01:29 +0000350 Size2D(_conv_width, _conv_height), _ofm, _conv_info, _num_groups,
Giorgio Arena59631a12018-05-02 13:59:04 +0100351 s.hints().convolution_method_hint, s.hints().fast_math_hint,
Giorgio Arenabb54e4e2018-04-05 17:20:34 +0100352 std::move(_weights), std::move(_bias), std::move(_weights_quant_info), std::move(_out_quant_info));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000353 }
354
355private:
Giorgio Arenabb54e4e2018-04-05 17:20:34 +0100356 unsigned int _conv_width;
357 unsigned int _conv_height;
358 unsigned int _ofm;
359 const PadStrideInfo _conv_info;
360 unsigned int _num_groups;
361 ITensorAccessorUPtr _weights;
362 ITensorAccessorUPtr _bias;
363 const QuantizationInfo _weights_quant_info;
364 const QuantizationInfo _out_quant_info;
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000365};
366
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100367/** Deconvolution Layer */
368class DeconvolutionLayer final : public ILayer
369{
370public:
371 /** Construct a convolution layer.
372 *
Manuel Bottinic1b76fa2019-06-17 12:04:40 +0100373 * @param[in] conv_width Convolution width.
374 * @param[in] conv_height Convolution height.
375 * @param[in] ofm Output feature map.
376 * @param[in] weights Accessor to get kernel weights from.
377 * @param[in] bias Accessor to get kernel bias from.
378 * @param[in] deconv_info Padding and stride information.
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100379 */
380 DeconvolutionLayer(unsigned int conv_width,
381 unsigned int conv_height,
382 unsigned int ofm,
383 ITensorAccessorUPtr weights,
384 ITensorAccessorUPtr bias,
Manuel Bottinic1b76fa2019-06-17 12:04:40 +0100385 PadStrideInfo deconv_info)
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100386 : _conv_width(conv_width),
387 _conv_height(conv_height),
388 _ofm(ofm),
389 _deconv_info(std::move(deconv_info)),
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100390 _weights(std::move(weights)),
391 _bias(std::move(bias))
392 {
393 }
394
395 NodeID create_layer(IStream &s) override
396 {
397 NodeIdxPair input = { s.tail_node(), 0 };
398 NodeParams common_params = { name(), s.hints().target_hint };
399 return GraphBuilder::add_deconvolution_node(s.graph(), common_params, input,
Manuel Bottinic1b76fa2019-06-17 12:04:40 +0100400 Size2D(_conv_width, _conv_height), _ofm, _deconv_info,
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100401 std::move(_weights), std::move(_bias));
402 }
403
404private:
405 unsigned int _conv_width;
406 unsigned int _conv_height;
407 unsigned int _ofm;
408 const PadStrideInfo _deconv_info;
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100409 ITensorAccessorUPtr _weights;
410 ITensorAccessorUPtr _bias;
411};
412
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000413/** Depthwise Convolution Layer */
414class DepthwiseConvolutionLayer final : public ILayer
415{
416public:
Alex Gildayc357c472018-03-21 13:54:09 +0000417 /** Construct a depthwise convolution layer.
418 *
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000419 * @param[in] conv_width Convolution width.
420 * @param[in] conv_height Convolution height.
421 * @param[in] weights Accessor to get kernel weights from.
422 * @param[in] bias Accessor to get kernel bias from.
423 * @param[in] conv_info Padding and stride information.
424 * @param[in] depth_multiplier (Optional) Depth multiplier parameter.
425 * @param[in] weights_quant_info (Optional) Quantization info used for weights
426 * @param[in] out_quant_info (Optional) Output quantization info
Alex Gildayc357c472018-03-21 13:54:09 +0000427 */
Giorgio Arenabb54e4e2018-04-05 17:20:34 +0100428 DepthwiseConvolutionLayer(unsigned int conv_width,
429 unsigned int conv_height,
430 ITensorAccessorUPtr weights,
431 ITensorAccessorUPtr bias,
432 PadStrideInfo conv_info,
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000433 int depth_multiplier = 1,
434 const QuantizationInfo weights_quant_info = QuantizationInfo(),
435 const QuantizationInfo out_quant_info = QuantizationInfo())
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000436 : _conv_width(conv_width),
437 _conv_height(conv_height),
438 _conv_info(std::move(conv_info)),
439 _weights(std::move(weights)),
Giorgio Arenabb54e4e2018-04-05 17:20:34 +0100440 _bias(std::move(bias)),
Georgios Pinitas05045c12018-12-07 18:31:47 +0000441 _depth_multiplier(depth_multiplier),
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000442 _weights_quant_info(std::move(weights_quant_info)),
443 _out_quant_info(std::move(out_quant_info))
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000444 {
445 }
446
447 NodeID create_layer(IStream &s) override
448 {
449 NodeIdxPair input = { s.tail_node(), 0 };
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +0100450 NodeParams common_params = { name(), s.hints().target_hint };
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000451 return GraphBuilder::add_depthwise_convolution_node(s.graph(), common_params,
Georgios Pinitas05045c12018-12-07 18:31:47 +0000452 input, Size2D(_conv_width, _conv_height), _conv_info, _depth_multiplier,
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000453 s.hints().depthwise_convolution_method_hint,
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000454 std::move(_weights), std::move(_bias), std::move(_weights_quant_info), std::move(_out_quant_info));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000455 }
456
457private:
Giorgio Arenabb54e4e2018-04-05 17:20:34 +0100458 unsigned int _conv_width;
459 unsigned int _conv_height;
460 const PadStrideInfo _conv_info;
461 ITensorAccessorUPtr _weights;
462 ITensorAccessorUPtr _bias;
Georgios Pinitas05045c12018-12-07 18:31:47 +0000463 int _depth_multiplier;
Isabella Gottardi0ae5de92019-03-14 10:32:11 +0000464 const QuantizationInfo _weights_quant_info;
465 const QuantizationInfo _out_quant_info;
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000466};
Isabella Gottardi7234ed82018-11-27 08:51:10 +0000467/** DetectionOutput Layer */
468class DetectionOutputLayer final : public ILayer
469{
470public:
471 /** Construct a detection output layer.
472 *
473 * @param[in] sub_stream_conf Confidence graph sub-stream.
474 * @param[in] sub_stream_prior PriorBox graph sub-stream.
475 * @param[in] detect_info DetectionOutput parameters.
476 */
Georgios Pinitasf52cd782019-03-25 14:06:14 +0000477 DetectionOutputLayer(SubStream &&sub_stream_conf, SubStream &&sub_stream_prior, const DetectionOutputLayerInfo &detect_info)
Isabella Gottardi7234ed82018-11-27 08:51:10 +0000478 : _ss_conf(std::move(sub_stream_conf)), _ss_prior(std::move(sub_stream_prior)), _detect_info(detect_info)
479 {
480 }
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000481
Isabella Gottardi7234ed82018-11-27 08:51:10 +0000482 NodeID create_layer(IStream &s) override
483 {
484 NodeParams common_params = { name(), s.hints().target_hint };
485 NodeIdxPair input_loc = { s.tail_node(), 0 };
486 NodeIdxPair input_conf = { _ss_conf.tail_node(), 0 };
487 NodeIdxPair input_priorbox = { _ss_prior.tail_node(), 0 };
488 return GraphBuilder::add_detection_output_node(s.graph(), common_params, input_loc, input_conf, input_priorbox, _detect_info);
489 }
490
491private:
492 SubStream _ss_conf;
493 SubStream _ss_prior;
494 DetectionOutputLayerInfo _detect_info;
495};
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100496/** Dummy Layer */
497class DummyLayer final : public ILayer
498{
499public:
500 /** Construct an input layer.
501 *
502 * @param[in] shape Output shape
503 */
504 DummyLayer(TensorShape shape)
505 : _shape(shape)
506 {
507 }
508
509 NodeID create_layer(IStream &s) override
510 {
511 NodeParams common_params = { name(), s.hints().target_hint };
512 NodeIdxPair input = { s.tail_node(), 0 };
513 return GraphBuilder::add_dummy_node(s.graph(), common_params, input, _shape);
514 }
515
516private:
517 TensorShape _shape;
518};
519
Georgios Pinitas427bbbf2018-08-28 13:32:02 +0100520class EltwiseLayer final : public ILayer
521{
522public:
523 /** Construct an element-wise operation layer
524 *
525 * @param[in] sub_stream0 First graph sub-stream
526 * @param[in] sub_stream1 First graph sub-stream
527 * @param[in] op Element-wise operation to perform
528 */
529 EltwiseLayer(SubStream &&sub_stream0, SubStream &&sub_stream1, EltwiseOperation op)
530 : _ss0(std::move(sub_stream0)), _ss1(std::move(sub_stream1)), _op(op)
531 {
532 }
533
534 NodeID create_layer(IStream &s) override
535 {
536 NodeParams common_params = { name(), s.hints().target_hint };
537 NodeIdxPair input0 = { _ss0.tail_node(), 0 };
538 NodeIdxPair input1 = { _ss1.tail_node(), 0 };
539
540 return GraphBuilder::add_elementwise_node(s.graph(), common_params, input0, input1, _op);
541 }
542
543private:
544 SubStream _ss0;
545 SubStream _ss1;
546 EltwiseOperation _op;
547};
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000548/** Flatten Layer */
549class FlattenLayer final : public ILayer
550{
551public:
Alex Gildayc357c472018-03-21 13:54:09 +0000552 /** Construct a flatten layer. */
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000553 FlattenLayer()
554 {
555 }
556
557 NodeID create_layer(IStream &s) override
558 {
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +0100559 NodeParams common_params = { name(), s.hints().target_hint };
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000560 NodeIdxPair input = { s.tail_node(), 0 };
561 return GraphBuilder::add_flatten_node(s.graph(), common_params, input);
562 }
563};
564
565/** Fully Connected Layer */
566class FullyConnectedLayer final : public ILayer
567{
568public:
Alex Gildayc357c472018-03-21 13:54:09 +0000569 /** Construct a fully connected layer.
570 *
Georgios Pinitas2f1366a2018-07-31 16:33:06 +0100571 * @param[in] num_outputs Number of outputs.
572 * @param[in] weights Accessor to get weights from.
573 * @param[in] bias Accessor to get bias from.
Georgios Pinitasc55cef12018-08-01 15:24:18 +0100574 * @param[in] fc_info (Optional) Fully connected layer metadata
Georgios Pinitas2f1366a2018-07-31 16:33:06 +0100575 * @param[in] weights_quant_info (Optional) Weights quantization information
576 * @param[in] out_quant_info (Optional) Output quantization info
Alex Gildayc357c472018-03-21 13:54:09 +0000577 */
Georgios Pinitasc55cef12018-08-01 15:24:18 +0100578 FullyConnectedLayer(unsigned int num_outputs,
579 ITensorAccessorUPtr weights,
580 ITensorAccessorUPtr bias,
581 const FullyConnectedLayerInfo fc_info = FullyConnectedLayerInfo(),
582 const QuantizationInfo weights_quant_info = QuantizationInfo(),
583 const QuantizationInfo out_quant_info = QuantizationInfo())
Georgios Pinitas2f1366a2018-07-31 16:33:06 +0100584 : _num_outputs(num_outputs),
585 _weights(std::move(weights)),
586 _bias(std::move(bias)),
Michele Di Giorgioa42f55f2019-03-08 14:52:17 +0000587 _weights_ss(nullptr),
588 _bias_ss(nullptr),
589 _fc_info(fc_info),
590 _weights_quant_info(std::move(weights_quant_info)),
591 _out_quant_info(std::move(out_quant_info))
592 {
593 }
594
595 /** Construct a fully connected layer.
596 *
597 * @param[in] num_outputs Number of outputs.
598 * @param[in] sub_stream_weights Graph sub-stream for the weights.
599 * @param[in] sub_stream_bias Graph sub-stream for the bias.
600 * @param[in] fc_info (Optional) Fully connected layer metadata
601 * @param[in] weights_quant_info (Optional) Weights quantization information
602 * @param[in] out_quant_info (Optional) Output quantization info
603 */
604 FullyConnectedLayer(unsigned int num_outputs,
605 SubStream &&sub_stream_weights,
606 SubStream &&sub_stream_bias,
607 const FullyConnectedLayerInfo fc_info = FullyConnectedLayerInfo(),
608 const QuantizationInfo weights_quant_info = QuantizationInfo(),
609 const QuantizationInfo out_quant_info = QuantizationInfo())
610 : _num_outputs(num_outputs),
611 _weights(nullptr),
612 _bias(nullptr),
613 _weights_ss(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream_weights))),
614 _bias_ss(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream_bias))),
Georgios Pinitasc55cef12018-08-01 15:24:18 +0100615 _fc_info(fc_info),
Georgios Pinitas2f1366a2018-07-31 16:33:06 +0100616 _weights_quant_info(std::move(weights_quant_info)),
617 _out_quant_info(std::move(out_quant_info))
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000618 {
619 }
620
Michele Di Giorgio47e6fed2018-11-13 12:04:25 +0000621 /** Create layer and add to the given stream.
622 *
623 * @param[in] s Stream to add layer to.
624 *
625 * @return ID of the created node.
626 */
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000627 NodeID create_layer(IStream &s) override
628 {
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +0100629 NodeParams common_params = { name(), s.hints().target_hint };
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000630 NodeIdxPair input = { s.tail_node(), 0 };
Michele Di Giorgioa42f55f2019-03-08 14:52:17 +0000631 if(_weights != nullptr)
632 {
633 return GraphBuilder::add_fully_connected_layer(s.graph(), common_params, input, _num_outputs,
634 std::move(_weights), std::move(_bias), _fc_info,
635 std::move(_weights_quant_info), std::move(_out_quant_info));
636 }
637 else
638 {
639 ARM_COMPUTE_ERROR_ON(_weights_ss == nullptr);
640
641 NodeID bias_nid = (_bias_ss == nullptr) ? EmptyNodeID : _bias_ss->tail_node();
642 return GraphBuilder::add_fully_connected_layer(s.graph(), common_params, input, _num_outputs,
643 _weights_ss->tail_node(), bias_nid, _fc_info,
644 std::move(_out_quant_info));
645 }
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000646 }
647
648private:
Georgios Pinitasc55cef12018-08-01 15:24:18 +0100649 unsigned int _num_outputs;
650 ITensorAccessorUPtr _weights;
651 ITensorAccessorUPtr _bias;
Michele Di Giorgioa42f55f2019-03-08 14:52:17 +0000652 std::unique_ptr<SubStream> _weights_ss;
653 std::unique_ptr<SubStream> _bias_ss;
Georgios Pinitasc55cef12018-08-01 15:24:18 +0100654 const FullyConnectedLayerInfo _fc_info;
655 const QuantizationInfo _weights_quant_info;
656 const QuantizationInfo _out_quant_info;
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000657};
658
Manuel Bottini5209be52019-02-13 16:34:56 +0000659/** Generate Proposals Layer */
660class GenerateProposalsLayer final : public ILayer
661{
662public:
663 /** Construct a generate proposals layer.
664 *
665 * @param[in] ss_scores Graph sub-stream for the scores.
666 * @param[in] ss_deltas Graph sub-stream for the deltas.
667 * @param[in] ss_anchors Graph sub-stream for the anchors.
668 * @param[in] info Generate Proposals operation information.
669 */
670 GenerateProposalsLayer(SubStream &&ss_scores, SubStream &&ss_deltas, SubStream &&ss_anchors, GenerateProposalsInfo info)
671 : _ss_scores(std::move(ss_scores)), _ss_deltas(std::move(ss_deltas)), _ss_anchors(std::move(ss_anchors)), _info(info)
672 {
673 }
674
675 /** Create layer and add to the given stream.
676 *
677 * @param[in] s Stream to add layer to.
678 *
679 * @return ID of the created node.
680 */
681 NodeID create_layer(IStream &s) override
682 {
683 NodeParams common_params = { name(), s.hints().target_hint };
684 NodeIdxPair scores = { _ss_scores.tail_node(), 0 };
685 NodeIdxPair deltas = { _ss_deltas.tail_node(), 0 };
686 NodeIdxPair anchors = { _ss_anchors.tail_node(), 0 };
687 return GraphBuilder::add_generate_proposals_node(s.graph(), common_params, scores, deltas, anchors, _info);
688 }
689
690private:
691 SubStream _ss_scores;
692 SubStream _ss_deltas;
693 SubStream _ss_anchors;
694 GenerateProposalsInfo _info;
695};
696
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000697/** Normalization Layer */
698class NormalizationLayer final : public ILayer
699{
700public:
Alex Gildayc357c472018-03-21 13:54:09 +0000701 /** Construct a normalization layer.
702 *
703 * @param[in] norm_info Normalization information.
704 */
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000705 NormalizationLayer(NormalizationLayerInfo norm_info)
706 : _norm_info(norm_info)
707 {
708 }
709
710 NodeID create_layer(IStream &s) override
711 {
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +0100712 NodeParams common_params = { name(), s.hints().target_hint };
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000713 NodeIdxPair input = { s.tail_node(), 0 };
714 return GraphBuilder::add_normalization_node(s.graph(), common_params, input, _norm_info);
715 }
716
717private:
718 NormalizationLayerInfo _norm_info;
719};
720
Michele Di Giorgio555d1102018-09-12 13:51:59 +0100721/** Normalize planar YUV Layer */
722class NormalizePlanarYUVLayer final : public ILayer
723{
724public:
725 /** Construct a normalize planar YUV layer.
726 *
727 * @param[in] mean Accessor to get mean tensor data from.
728 * @param[in] std Accessor to get std tensor data from.
729 */
730 NormalizePlanarYUVLayer(ITensorAccessorUPtr mean,
731 ITensorAccessorUPtr std)
732 : _mean(std::move(mean)), _std(std::move(std))
733 {
734 }
735
736 NodeID create_layer(IStream &s) override
737 {
738 ARM_COMPUTE_ERROR_ON(_mean == nullptr);
739 ARM_COMPUTE_ERROR_ON(_std == nullptr);
740
741 NodeParams common_params = { name(), s.hints().target_hint };
742 NodeIdxPair input = { s.tail_node(), 0 };
743 return GraphBuilder::add_normalize_planar_yuv_node(s.graph(), common_params, input,
744 std::move(_mean), std::move(_std));
745 }
746
747private:
748 ITensorAccessorUPtr _mean;
749 ITensorAccessorUPtr _std;
750};
751
Michele Di Giorgio4bb17332018-09-26 13:56:51 +0100752/** Pad Layer */
753class PadLayer final : public ILayer
754{
755public:
756 /** Construct a pad layer.
757 *
758 * @param[in] padding The padding for each spatial dimension of the input tensor. The pair padding[i]
759 * specifies the front and the end padding in the i-th dimension.
760 */
761 PadLayer(PaddingList padding)
762 : _padding(padding)
763 {
764 }
765
766 NodeID create_layer(IStream &s) override
767 {
768 NodeParams common_params = { name(), s.hints().target_hint };
769 NodeIdxPair input = { s.tail_node(), 0 };
770 return GraphBuilder::add_pad_node(s.graph(), common_params, input, _padding);
771 }
772
773private:
774 PaddingList _padding;
775};
776
Georgios Pinitas57c48242018-08-02 13:41:49 +0100777/** Permute Layer */
778class PermuteLayer final : public ILayer
779{
780public:
781 /** Construct a permute layer.
782 *
783 * @param[in] perm Permutation vector.
784 * @param[in] layout (Optional) Data layout to assign to permuted tensor.
785 * If UNKNOWN then the input's layout will be used.
786 */
787 PermuteLayer(PermutationVector perm, DataLayout layout = DataLayout::UNKNOWN)
788 : _perm(perm), _layout(layout)
789 {
790 }
791
792 NodeID create_layer(IStream &s) override
793 {
794 NodeParams common_params = { name(), s.hints().target_hint };
795 NodeIdxPair input = { s.tail_node(), 0 };
796 return GraphBuilder::add_permute_node(s.graph(), common_params, input, _perm, _layout);
797 }
798
799private:
800 PermutationVector _perm;
801 DataLayout _layout;
802};
803
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000804/** Pooling Layer */
805class PoolingLayer final : public ILayer
806{
807public:
Alex Gildayc357c472018-03-21 13:54:09 +0000808 /** Construct a pooling layer.
809 *
810 * @param[in] pool_info Pooling information.
811 */
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000812 PoolingLayer(PoolingLayerInfo pool_info)
813 : _pool_info(pool_info)
814 {
815 }
816
817 NodeID create_layer(IStream &s) override
818 {
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +0100819 NodeParams common_params = { name(), s.hints().target_hint };
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000820 NodeIdxPair input = { s.tail_node(), 0 };
821 return GraphBuilder::add_pooling_node(s.graph(), common_params, input, _pool_info);
822 }
823
824private:
825 PoolingLayerInfo _pool_info;
826};
827
Pablo Tello32521432018-11-15 14:43:10 +0000828/** PriorBox Layer */
829class PriorBoxLayer final : public ILayer
830{
831public:
832 /** Construct a priorbox layer.
833 *
834 * @param[in] sub_stream First graph sub-stream
835 * @param[in] prior_info PriorBox parameters.
836 */
Georgios Pinitasf52cd782019-03-25 14:06:14 +0000837 PriorBoxLayer(SubStream &&sub_stream, const PriorBoxLayerInfo &prior_info)
Pablo Tello32521432018-11-15 14:43:10 +0000838 : _ss(std::move(sub_stream)), _prior_info(prior_info)
839 {
840 }
841
842 NodeID create_layer(IStream &s) override
843 {
844 NodeParams common_params = { name(), s.hints().target_hint };
845 NodeIdxPair input0 = { s.tail_node(), 0 };
846 NodeIdxPair input1 = { _ss.tail_node(), 0 };
847 return GraphBuilder::add_priorbox_node(s.graph(), common_params, input0, input1, _prior_info);
848 }
849
850private:
851 SubStream _ss;
852 PriorBoxLayerInfo _prior_info;
853};
854
Isabella Gottardi3db1ba92019-05-17 12:35:20 +0100855/** Quantization Layer */
856class QuantizationLayer final : public ILayer
857{
858public:
859 /** Construct a quantization layer.
860 *
861 * @param[in] out_quant_info Output tensor quantization info
862 */
863 QuantizationLayer(QuantizationInfo out_quant_info)
864 : _out_quant_info(out_quant_info)
865 {
866 }
867
868 NodeID create_layer(IStream &s) override
869 {
870 NodeParams common_params = { name(), s.hints().target_hint };
871 NodeIdxPair input = { s.tail_node(), 0 };
872 return GraphBuilder::add_quantization_node(s.graph(), common_params, input, _out_quant_info);
873 }
874
875private:
876 QuantizationInfo _out_quant_info;
877};
878
Gian Marco Iodice23e24792018-09-07 15:32:14 +0100879/** Reorg Layer */
880class ReorgLayer final : public ILayer
881{
882public:
883 /** Construct a reorg layer.
884 *
885 * @param[in] stride Stride value to use for reorganizing the values in the output tensor.
886 * It defines the spatial distance between 2 consecutive pixels in the x and y direction
887 */
888 ReorgLayer(int stride)
889 : _stride(stride)
890 {
891 }
892
893 NodeID create_layer(IStream &s) override
894 {
895 NodeParams common_params = { name(), s.hints().target_hint };
896 NodeIdxPair input = { s.tail_node(), 0 };
897 return GraphBuilder::add_reorg_node(s.graph(), common_params, input, _stride);
898 }
899
900private:
901 int _stride;
902};
903
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000904/** Reshape Layer */
905class ReshapeLayer final : public ILayer
906{
907public:
Alex Gildayc357c472018-03-21 13:54:09 +0000908 /** Construct a reshape layer.
909 *
910 * @param[in] shape Target shape.
911 */
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000912 ReshapeLayer(TensorShape shape)
913 : _shape(shape)
914 {
915 }
916
917 NodeID create_layer(IStream &s) override
918 {
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +0100919 NodeParams common_params = { name(), s.hints().target_hint };
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000920 NodeIdxPair input = { s.tail_node(), 0 };
921 return GraphBuilder::add_reshape_node(s.graph(), common_params, input, _shape);
922 }
923
924private:
925 TensorShape _shape;
926};
927
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100928/** Resize Layer */
929class ResizeLayer final : public ILayer
930{
931public:
932 ResizeLayer(InterpolationPolicy policy, float width_scale, float height_scale)
933 : _policy(policy), _width_scale(width_scale), _height_scale(height_scale)
934 {
935 }
936
937 NodeID create_layer(IStream &s) override
938 {
939 NodeParams common_params = { name(), s.hints().target_hint };
940 NodeIdxPair input = { s.tail_node(), 0 };
941 return GraphBuilder::add_resize_node(s.graph(), common_params, input, _policy, _width_scale, _height_scale);
942 }
943
944private:
945 InterpolationPolicy _policy;
946 float _width_scale;
947 float _height_scale;
948};
949
Manuel Bottini3f9d4d72018-10-19 14:04:42 +0100950/** ROIAlign Layer */
951class ROIAlignLayer final : public ILayer
952{
953public:
954 /** Construct a RoiAlign layer.
955 *
956 * @param[in] sub_stream_input Graph sub-stream for the input
957 * @param[in] sub_stream_rois Graph sub-stream for the rois
958 * @param[in] pool_info Pooling information.
959 */
960 ROIAlignLayer(SubStream &&sub_stream_input, SubStream &&sub_stream_rois, ROIPoolingLayerInfo pool_info)
961 : _ss_input(sub_stream_input), _ss_rois(sub_stream_rois), _pool_info(pool_info)
962 {
963 }
964
965 /** Prevent instances of this class from being copy constructed */
966 ROIAlignLayer(const ROIAlignLayer &) = delete;
967 /** Prevent instances of this class from being copied */
968 ROIAlignLayer &operator=(const ROIAlignLayer &) = delete;
969
970 NodeID create_layer(IStream &s) override
971 {
972 NodeParams common_params = { name(), s.hints().target_hint };
973 NodeIdxPair input = { _ss_input.tail_node(), 0 };
974 NodeIdxPair rois = { _ss_rois.tail_node(), 0 };
975 return GraphBuilder::add_roi_align_node(s.graph(), common_params, input, rois, _pool_info);
976 }
977
978private:
979 SubStream _ss_input;
980 SubStream _ss_rois;
981 ROIPoolingLayerInfo _pool_info;
982};
983
Isabella Gottardi88d5b222018-04-06 12:24:55 +0100984/** Scale Layer */
985class ScaleLayer final : public ILayer
986{
987public:
988 /** Construct a scale layer.
989 *
990 * @param[in] mul_w Accessor to get mul weight from.
991 * @param[in] add_w Accessor to get add weight from.
992 */
993 ScaleLayer(ITensorAccessorUPtr mul_w,
994 ITensorAccessorUPtr add_w)
995 : _mul_w(std::move(mul_w)), _add_w(std::move(add_w))
996 {
997 }
998
999 NodeID create_layer(IStream &s) override
1000 {
1001 NodeParams common_params = { name(), s.hints().target_hint };
1002 NodeIdxPair input = { s.tail_node(), 0 };
1003 return GraphBuilder::add_scale_layer(s.graph(), common_params, input, std::move(_mul_w), std::move(_add_w));
1004 }
1005
1006private:
1007 ITensorAccessorUPtr _mul_w;
1008 ITensorAccessorUPtr _add_w;
1009};
1010
Michele Di Giorgioc30b6682018-09-12 17:44:08 +01001011/** Slice Layer */
1012class SliceLayer final : public ILayer
1013{
1014public:
1015 /** Construct a slice layer.
1016 *
1017 * @param[in] starts The starts of the dimensions of the input tensor to be sliced. The length must be of rank(input).
1018 * @param[in] ends The ends of the dimensions of the input tensor to be sliced. The length must be of rank(input).
1019 */
1020 SliceLayer(Coordinates &starts, Coordinates &ends)
1021 : _starts(starts), _ends(ends)
1022 {
1023 }
1024
1025 NodeID create_layer(IStream &s) override
1026 {
1027 NodeParams common_params = { name(), s.hints().target_hint };
1028 NodeIdxPair input = { s.tail_node(), 0 };
1029 return GraphBuilder::add_slice_node(s.graph(), common_params, input, _starts, _ends);
1030 }
1031
1032private:
1033 Coordinates _starts;
1034 Coordinates _ends;
1035};
1036
Georgios Pinitasd8734b52017-12-22 15:27:52 +00001037/** Softmax Layer */
1038class SoftmaxLayer final : public ILayer
1039{
1040public:
Alex Gildayc357c472018-03-21 13:54:09 +00001041 /** Construct a softmax layer.
1042 *
1043 * @param[in] beta (Optional) Beta value. Default 1.0.
1044 */
Georgios Pinitasd8734b52017-12-22 15:27:52 +00001045 SoftmaxLayer(float beta = 1.0f)
1046 : _beta(beta)
1047 {
1048 }
1049
1050 NodeID create_layer(IStream &s) override
1051 {
Georgios Pinitas5c2fb3f2018-05-01 15:26:20 +01001052 NodeParams common_params = { name(), s.hints().target_hint };
Georgios Pinitasd8734b52017-12-22 15:27:52 +00001053 NodeIdxPair input = { s.tail_node(), 0 };
1054 return GraphBuilder::add_softmax_node(s.graph(), common_params, input, _beta);
1055 }
1056
1057private:
1058 float _beta;
1059};
Michalis Spyrou96f67692018-09-13 11:39:28 +01001060
Michele Di Giorgioec699752019-03-22 15:25:32 +00001061/** Stack Layer */
1062class StackLayer final : public ILayer
1063{
1064public:
1065 /** Construct a concatenation layer
1066 *
1067 * @param[in] sub_stream1 First graph branch
1068 * @param[in] sub_stream2 Second graph branch
1069 * @param[in] rest_sub_streams Rest sub-graph branches
1070 */
1071 template <typename... Ts>
1072 StackLayer(SubStream &&sub_stream1, SubStream &&sub_stream2, Ts &&... rest_sub_streams)
1073 : _sub_streams(), _axis(0)
1074 {
1075 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream1)));
1076 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream2)));
1077
1078 utility::for_each([&](SubStream && sub_stream)
1079 {
1080 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream)));
1081 },
1082 std::move(rest_sub_streams)...);
1083 }
1084 /** Construct a concatenation layer
1085 *
1086 * @param[in] axis Stack layer axis along which to stack the inputs
1087 * @param[in] sub_stream1 First graph branch
1088 * @param[in] sub_stream2 Second graph branch
1089 * @param[in] rest_sub_streams Rest sub-graph branches
1090 */
1091 template <typename... Ts>
1092 StackLayer(int axis, SubStream &&sub_stream1, SubStream &&sub_stream2, Ts &&... rest_sub_streams)
1093 : _sub_streams(), _axis(axis)
1094 {
1095 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream1)));
1096 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream2)));
1097
1098 utility::for_each([&](SubStream && sub_stream)
1099 {
1100 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream)));
1101 },
1102 std::move(rest_sub_streams)...);
1103 }
1104 /** Construct a concat layer
1105 *
1106 * @param[in] sub_stream Sub-stream
1107 */
1108 template <typename... Ts>
1109 StackLayer(SubStream &&sub_stream)
1110 : _sub_streams(), _axis(0)
1111 {
1112 _sub_streams.push_back(arm_compute::support::cpp14::make_unique<SubStream>(std::move(sub_stream)));
1113 }
1114 NodeID create_layer(IStream &s) override
1115 {
1116 NodeID nid = EmptyNodeID;
1117 NodeParams common_params = { name(), s.hints().target_hint };
1118 if(_sub_streams.size() == 1 && _sub_streams.at(0) != nullptr)
1119 {
1120 nid = _sub_streams[0]->tail_node();
1121 }
1122 else
1123 {
1124 // Collect tail nodes and stack
1125 std::vector<NodeIdxPair> nodes;
1126 for(auto &ss : _sub_streams)
1127 {
1128 if(ss && (ss->tail_node() != EmptyNodeID))
1129 {
1130 const auto tail_node = s.graph().node(ss->tail_node());
1131 if(tail_node != nullptr && tail_node->type() != NodeType::Output)
1132 {
1133 nodes.push_back({ ss->tail_node(), 0 });
1134 }
1135 }
1136 }
1137 nid = GraphBuilder::add_stack_node(s.graph(), common_params, nodes, _axis);
1138 }
1139 return nid;
1140 }
1141
1142private:
1143 std::vector<std::unique_ptr<SubStream>> _sub_streams;
1144 int _axis;
1145};
1146
Michalis Spyrou4e1c3f32018-09-20 17:14:03 +01001147/** Upsample Layer */
1148class UpsampleLayer final : public ILayer
1149{
1150public:
1151 /** Construct a Upsample layer.
1152 *
1153 * @param[in] info Stride info
1154 * @param[in] upsampling_policy Upsampling policy
1155 */
1156 UpsampleLayer(Size2D info, InterpolationPolicy upsampling_policy)
1157 : _info(info), _upsampling_policy(upsampling_policy)
1158 {
1159 }
1160
1161 NodeID create_layer(IStream &s) override
1162 {
1163 NodeParams common_params = { name(), s.hints().target_hint };
1164 NodeIdxPair input = { s.tail_node(), 0 };
1165 return GraphBuilder::add_upsample_node(s.graph(), common_params, input, _info, _upsampling_policy);
1166 }
1167
1168private:
1169 Size2D _info;
1170 InterpolationPolicy _upsampling_policy;
1171};
1172
Michalis Spyrou96f67692018-09-13 11:39:28 +01001173/** YOLO Layer */
1174class YOLOLayer final : public ILayer
1175{
1176public:
1177 /** Construct a YOLO layer.
1178 *
1179 * @param[in] act_info Activation info
1180 * @param[in] num_classes Number of classes to activate
1181 */
1182 YOLOLayer(ActivationLayerInfo act_info, int32_t num_classes)
1183 : _act_info(act_info), _num_classes(num_classes)
1184 {
1185 }
1186
1187 NodeID create_layer(IStream &s) override
1188 {
1189 NodeParams common_params = { name(), s.hints().target_hint };
1190 NodeIdxPair input = { s.tail_node(), 0 };
1191 return GraphBuilder::add_yolo_node(s.graph(), common_params, input, _act_info, _num_classes);
1192 }
1193
1194private:
1195 ActivationLayerInfo _act_info;
1196 int32_t _num_classes;
1197};
Georgios Pinitasd8734b52017-12-22 15:27:52 +00001198} // namespace frontend
Georgios Pinitasd9eb2752018-04-03 13:44:29 +01001199} // namespace graph
Georgios Pinitasd8734b52017-12-22 15:27:52 +00001200} // namespace arm_compute
Georgios Pinitasd9eb2752018-04-03 13:44:29 +01001201#endif /* __ARM_COMPUTE_GRAPH_LAYERS_H__ */