4bbcbb3a4011663538fe96e90803e3e2b40d4048
[platform/upstream/armcl.git] / arm_compute / core / IAccessWindow.h
1 /*
2  * Copyright (c) 2017-2018 ARM Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #ifndef __ARM_COMPUTE_IACCESS_WINDOW_H__
25 #define __ARM_COMPUTE_IACCESS_WINDOW_H__
26
27 #include "arm_compute/core/Coordinates.h"
28 #include "arm_compute/core/TensorShape.h"
29 #include "arm_compute/core/Types.h"
30
31 #include <array>
32
33 namespace arm_compute
34 {
35 class Window;
36 class ITensorInfo;
37
38 /** Decrease @p required in steps of @p step until it's less than @p available.
39  *
40  * @param[in] required  Number of required bytes.
41  * @param[in] available Number of available bytes.
42  * @param[in] step      Step size used to decrease required bytes.
43  *
44  * @return Largest value smaller than @p available that is a multiple of @p step
45  *
46  **/
47 inline int adjust_down(int required, int available, int step)
48 {
49     ARM_COMPUTE_ERROR_ON(step <= 0);
50
51     return required - step * ((required - available + step - 1) / step);
52 }
53
54 /** Increase @p required in steps of @p step until it's greater than @p available.
55  *
56  * @param[in] required  Number of required bytes.
57  * @param[in] available Number of available bytes.
58  * @param[in] step      Step size used to increase required bytes.
59  *
60  * @return Largest value smaller than @p available that is a multiple of @p step
61  *
62  **/
63 inline int adjust_up(int required, int available, int step)
64 {
65     ARM_COMPUTE_ERROR_ON(step <= 0);
66
67     return required + step * ((available - required + step - 1) / step);
68 }
69
70 /** Interface describing methods to update access window and padding based on kernel parameters. */
71 class IAccessWindow
72 {
73 public:
74     virtual ~IAccessWindow() = default;
75     /** Shrink the window if padding is not large enough.
76      *
77      * @param[in] window Window used by the kernel.
78      *
79      * @return True if the window has been changed.
80      */
81     virtual bool update_window_if_needed(Window &window) const = 0;
82     /** Increase the padding to be large enough for the window.
83      *
84      * @param[in] window Window used by the kernel.
85      *
86      * @return True if the padding has been changed.
87      */
88     virtual bool update_padding_if_needed(const Window &window) = 0;
89     /** Compute the valid region based on access pattern and valid region of the inputs.
90      *
91      * @note This method assumes that there is no border.
92      *
93      * @param[in] window             Execution window of the kernel.
94      * @param[in] input_valid_region Combined valid region of all inputs.
95      * @param[in] border_undefined   Undefined borders are excluded from the valid region.
96      * @param[in] border_size        Size of the border around the XY-plane of the tensor.
97      */
98     virtual ValidRegion compute_valid_region(const Window &window, ValidRegion input_valid_region, bool border_undefined, BorderSize border_size) const = 0;
99 };
100
101 /** Implementation of a rectangular access pattern. */
102 class AccessWindowRectangle : public IAccessWindow
103 {
104 public:
105     /** Constructor for a rectangular access pattern.
106      *
107      * @note Width and height have to be non-negative.
108      *
109      * @param[in,out] info   Tensor info of the accessed kernel.
110      * @param[in]     x      Offset of the access in X direction.
111      * @param[in]     y      Offset of the access in Y direction.
112      * @param[in]     width  Number of elements that are accessed in X direction.
113      * @param[in]     height Number of elements that are accessed in Y direction.
114      */
115     AccessWindowRectangle(ITensorInfo *info, int x, int y, int width, int height)
116         : AccessWindowRectangle(info, x, y, width, height, 1.f, 1.f)
117     {
118     }
119
120     /** Constructor for a rectangular access pattern.
121      *
122      * @note Width, height and scale have to be non-negative.
123      *
124      * @param[in,out] info    Tensor info of the accessed kernel.
125      * @param[in]     x       Offset of the access in X direction.
126      * @param[in]     y       Offset of the access in Y direction.
127      * @param[in]     width   Number of elements that are accessed in X direction.
128      * @param[in]     height  Number of elements that are accessed in Y direction.
129      * @param[in]     scale_x Ratio along the X direction between the window used by the execute_window_loop and the rectangular access pattern defined
130      * @param[in]     scale_y Ratio along the Y direction between the window used by the execute_window_loop and the rectangular access pattern defined
131      */
132     AccessWindowRectangle(ITensorInfo *info, int x, int y, int width, int height, float scale_x, float scale_y)
133         : _info(info), _x(x), _y(y), _width(width), _height(height), _scale_x(scale_x), _scale_y(scale_y)
134     {
135         ARM_COMPUTE_ERROR_ON(width < 0);
136         ARM_COMPUTE_ERROR_ON(height < 0);
137         ARM_COMPUTE_ERROR_ON(scale_x < 0);
138         ARM_COMPUTE_ERROR_ON(scale_y < 0);
139     }
140
141     AccessWindowRectangle(const AccessWindowRectangle &) = delete;
142     AccessWindowRectangle(AccessWindowRectangle &&)      = delete;
143     AccessWindowRectangle &operator=(const AccessWindowRectangle &) = delete;
144     AccessWindowRectangle &operator=(AccessWindowRectangle &&) = default;
145     ~AccessWindowRectangle()                                   = default;
146
147     /** Set the valid region based on access pattern, valid region of the inputs and border mode.
148      *
149      * @param[in] window             Execution window of the kernel.
150      * @param[in] input_valid_region Combined valid region of all inputs.
151      * @param[in] border_undefined   (Optional) Undefined borders are excluded from the valid region.
152      * @param[in] border_size        (Optional) Size of the border around the XY-plane of the tensor.
153      */
154     void set_valid_region(const Window &window, const ValidRegion &input_valid_region, bool border_undefined = false, const BorderSize &border_size = BorderSize(0));
155
156     /** Compute the valid region based on access pattern, valid region of the inputs and border mode.
157      *
158      * @note This method assumes that there is no border.
159      *
160      * @param[in] window             Execution window of the kernel.
161      * @param[in] input_valid_region Combined valid region of all inputs.
162      */
163     ValidRegion compute_valid_region(const Window &window, const ValidRegion &input_valid_region) const;
164
165     // Inherited methods overridden:
166
167     /** @note This method assumes that all elements written by the kernel are valid. */
168     ValidRegion compute_valid_region(const Window &window, ValidRegion input_valid_region, bool border_undefined, BorderSize border_size) const override;
169
170     bool update_window_if_needed(Window &window) const override;
171     bool update_padding_if_needed(const Window &window) override;
172
173 protected:
174     ITensorInfo *_info;
175     int          _x;
176     int          _y;
177     int          _width;
178     int          _height;
179     float        _scale_x;
180     float        _scale_y;
181 };
182
183 /** Implementation of a column access pattern. */
184 class AccessWindowVertical : public AccessWindowRectangle
185 {
186 public:
187     /** Constructor for a column access pattern.
188      *
189      * @note Height has to be non-negative.
190      *
191      * @param[in,out] info    Tensor info of the accessed kernel.
192      * @param[in]     y       Offset of the access in Y direction.
193      * @param[in]     height  Number of elements that are accessed in Y direction.
194      * @param[in]     scale_y Ratio along the Y direction between the window used by the execute_window_loop and the rectangular access pattern defined
195      */
196     AccessWindowVertical(ITensorInfo *info, int y, int height, float scale_y = 1.f)
197         : AccessWindowRectangle(info, 0, y, 1, height, 1.f, scale_y)
198     {
199         ARM_COMPUTE_ERROR_ON(height < 0);
200         ARM_COMPUTE_ERROR_ON(scale_y < 0);
201     }
202 };
203
204 /** Implementation of a row access pattern. */
205 class AccessWindowHorizontal : public AccessWindowRectangle
206 {
207 public:
208     /** Constructor for a row access pattern.
209      *
210      * @note Width has to be non-negative.
211      *
212      * @param[in,out] info    Tensor info of the accessed kernel.
213      * @param[in]     x       Offset of the access in X direction.
214      * @param[in]     width   Number of elements that are accessed in X direction.
215      * @param[in]     scale_x Ratio along the X direction between the window used by the execute_window_loop and the rectangular access pattern defined
216      */
217     AccessWindowHorizontal(ITensorInfo *info, int x, int width, float scale_x = 1.f)
218         : AccessWindowRectangle(info, x, 0, width, 1, scale_x, 1.f)
219     {
220         ARM_COMPUTE_ERROR_ON(width < 0);
221         ARM_COMPUTE_ERROR_ON(scale_x < 0);
222     }
223 };
224 } // namespace arm_compute
225 #endif /*__ARM_COMPUTE_IACCESS_WINDOW_H__*/