8d5c455a6ed2cd7248a60908c3a5b32d7c9627c8
[platform/upstream/armcl.git] / arm_compute / core / IAccessWindow.h
1 /*
2  * Copyright (c) 2017 ARM Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #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 TensorInfo;
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) const = 0;
89     /** Set the valid region based on access pattern, valid region of the inputs and border mode.
90      *
91      * @param[in] window             Execution window of the kernel.
92      * @param[in] input_valid_region Combined valid region of all inputs.
93      * @param[in] border_undefined   Undefined borders are excluded from the valid region.
94      * @param[in] border_size        Size of the border around the XY-plane of the tensor.
95      */
96     virtual void set_valid_region(const Window &window, ValidRegion input_valid_region, bool border_undefined, BorderSize border_size) = 0;
97 };
98
99 /** Implementation of a rectangular access pattern. */
100 class AccessWindowRectangle : public IAccessWindow
101 {
102 public:
103     /** Constructor for a rectangular access pattern.
104      *
105      * @note Width and height have to be non-negative.
106      *
107      * @param[in,out] info   Tensor info of the accessed kernel.
108      * @param[in]     x      Offset of the access in X direction.
109      * @param[in]     y      Offset of the access in Y direction.
110      * @param[in]     width  Number of elements that are accessed in X direction.
111      * @param[in]     height Number of elements that are accessed in Y direction.
112      */
113     AccessWindowRectangle(TensorInfo *info, int x, int y, int width, int height)
114         : AccessWindowRectangle(info, x, y, width, height, 1.f, 1.f)
115     {
116     }
117
118     /** Constructor for a rectangular access pattern.
119      *
120      * @note Width, height and scale have to be non-negative.
121      *
122      * @param[in,out] info    Tensor info of the accessed kernel.
123      * @param[in]     x       Offset of the access in X direction.
124      * @param[in]     y       Offset of the access in Y direction.
125      * @param[in]     width   Number of elements that are accessed in X direction.
126      * @param[in]     height  Number of elements that are accessed in Y direction.
127      * @param[in]     scale_x Ratio along the X direction between the window used by the execute_window_loop and the rectangular access pattern defined
128      * @param[in]     scale_y Ratio along the Y direction between the window used by the execute_window_loop and the rectangular access pattern defined
129      */
130     AccessWindowRectangle(TensorInfo *info, int x, int y, int width, int height, float scale_x, float scale_y)
131         : _info(info), _x(x), _y(y), _width(width), _height(height), _scale_x(scale_x), _scale_y(scale_y)
132     {
133         ARM_COMPUTE_ERROR_ON(width < 0);
134         ARM_COMPUTE_ERROR_ON(height < 0);
135         ARM_COMPUTE_ERROR_ON(scale_x < 0);
136         ARM_COMPUTE_ERROR_ON(scale_y < 0);
137     }
138
139     AccessWindowRectangle(const AccessWindowRectangle &) = delete;
140     AccessWindowRectangle &operator=(const AccessWindowRectangle &) = delete;
141     AccessWindowRectangle(AccessWindowRectangle &&)                 = default;
142     AccessWindowRectangle &operator=(AccessWindowRectangle &&) = default;
143     ~AccessWindowRectangle()                                   = default;
144
145     /** Set the valid region based on access pattern and valid region of the inputs.
146      *
147      * @note This method assumes that there is no border.
148      * @note This method assumes that all elements written by the kernel are valid.
149      *
150      * @param[in] window             Execution window of the kernel.
151      * @param[in] input_valid_region Combined valid region of all inputs.
152      */
153     void set_valid_region(const Window &window, ValidRegion input_valid_region);
154
155     // Inherited methods overridden:
156
157     /** @note This method assumes that all elements written by the kernel are valid. */
158     void set_valid_region(const Window &window, ValidRegion input_valid_region, bool border_undefined, BorderSize border_size) override;
159
160     bool update_window_if_needed(Window &window) const override;
161     bool update_padding_if_needed(const Window &window) const override;
162
163 protected:
164     TensorInfo *_info;
165     int         _x;
166     int         _y;
167     int         _width;
168     int         _height;
169     float       _scale_x;
170     float       _scale_y;
171 };
172
173 /** Implementation of a column access pattern. */
174 class AccessWindowVertical : public AccessWindowRectangle
175 {
176 public:
177     /** Constructor for a column access pattern.
178      *
179      * @note Height has to be non-negative.
180      *
181      * @param[in,out] info    Tensor info of the accessed kernel.
182      * @param[in]     y       Offset of the access in Y direction.
183      * @param[in]     height  Number of elements that are accessed in Y direction.
184      * @param[in]     scale_y Ratio along the Y direction between the window used by the execute_window_loop and the rectangular access pattern defined
185      */
186     AccessWindowVertical(TensorInfo *info, int y, int height, float scale_y = 1.f)
187         : AccessWindowRectangle(info, 0, y, 1, height, 1.f, scale_y)
188     {
189         ARM_COMPUTE_ERROR_ON(height < 0);
190         ARM_COMPUTE_ERROR_ON(scale_y < 0);
191     }
192 };
193
194 /** Implementation of a row access pattern. */
195 class AccessWindowHorizontal : public AccessWindowRectangle
196 {
197 public:
198     /** Constructor for a row access pattern.
199      *
200      * @note Width has to be non-negative.
201      *
202      * @param[in,out] info    Tensor info of the accessed kernel.
203      * @param[in]     x       Offset of the access in X direction.
204      * @param[in]     width   Number of elements that are accessed in X direction.
205      * @param[in]     scale_x Ratio along the X direction between the window used by the execute_window_loop and the rectangular access pattern defined
206      */
207     AccessWindowHorizontal(TensorInfo *info, int x, int width, float scale_x = 1.f)
208         : AccessWindowRectangle(info, x, 0, width, 1, scale_x, 1.f)
209     {
210         ARM_COMPUTE_ERROR_ON(width < 0);
211         ARM_COMPUTE_ERROR_ON(scale_x < 0);
212     }
213 };
214 } // namespace arm_compute
215 #endif /*__ARM_COMPUTE_IACCESS_WINDOW_H__*/