blob: 5b6ad17ce00cca3de0b5f37b45bf309eeb999d20 [file] [log] [blame]
Usama Arif0681e3b2019-04-25 14:28:07 +01001/*
Michele Di Giorgiod9eaf612020-07-08 11:12:57 +01002 * Copyright (c) 2019-2020 Arm Limited.
Usama Arif0681e3b2019-04-25 14:28:07 +01003 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
Gian Marco Iodiceca1f4602019-07-16 15:46:48 +010024#include "activation_float_helpers.h"
Usama Arif0681e3b2019-04-25 14:28:07 +010025#include "helpers.h"
26
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +000027/** Loads the rows from 0 to n-1 in the given variables (BASENAME0 to BASENAMEn-1).
28 * @name LOAD_ROW_n
29 *
30 * @param[in] N0 The number of rows to load
31 * @param[in] DATA_TYPE The data type of variables
32 * @param[in] BASENAME The basename of the destination variables for the loaded rows
33 * @param[in] PTR The base pointer
34 * @param[in] OFFSET The offset within a row
35 * @param[in] STRIDE_Y The stride value in y-axis direction
36 * @param[in] Z The z-axis offset vector
37 * @{
38 */
Usama Arif0681e3b2019-04-25 14:28:07 +010039#define LOAD_ROW_1(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
40 VEC_DATA_TYPE(DATA_TYPE, N0) \
41 BASENAME##0 = VLOAD(N0)(0, (__global DATA_TYPE *)(PTR + OFFSET + 0 * STRIDE_Y + Z##0));
42
43#define LOAD_ROW_2(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
44 LOAD_ROW_1(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
45 VEC_DATA_TYPE(DATA_TYPE, N0) \
46 BASENAME##1 = VLOAD(N0)(0, (__global DATA_TYPE *)(PTR + OFFSET + 1 * STRIDE_Y + Z##1));
47
48#define LOAD_ROW_3(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
49 LOAD_ROW_2(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
50 VEC_DATA_TYPE(DATA_TYPE, N0) \
51 BASENAME##2 = VLOAD(N0)(0, (__global DATA_TYPE *)(PTR + OFFSET + 2 * STRIDE_Y + Z##2));
52
53#define LOAD_ROW_4(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
54 LOAD_ROW_3(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
55 VEC_DATA_TYPE(DATA_TYPE, N0) \
56 BASENAME##3 = VLOAD(N0)(0, (__global DATA_TYPE *)(PTR + OFFSET + 3 * STRIDE_Y + Z##3));
57
58#define LOAD_ROW_5(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
59 LOAD_ROW_4(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
60 VEC_DATA_TYPE(DATA_TYPE, N0) \
61 BASENAME##4 = VLOAD(N0)(0, (__global DATA_TYPE *)(PTR + OFFSET + 4 * STRIDE_Y + Z##4));
62
63#define LOAD_ROW_6(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
64 LOAD_ROW_5(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
65 VEC_DATA_TYPE(DATA_TYPE, N0) \
66 BASENAME##5 = VLOAD(N0)(0, (__global DATA_TYPE *)(PTR + OFFSET + 5 * STRIDE_Y + Z##5));
67
68#define LOAD_ROW_7(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
69 LOAD_ROW_6(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
70 VEC_DATA_TYPE(DATA_TYPE, N0) \
71 BASENAME##6 = VLOAD(N0)(0, (__global DATA_TYPE *)(PTR + OFFSET + 6 * STRIDE_Y + Z##6));
72
73#define LOAD_ROW_8(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
74 LOAD_ROW_7(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
75 VEC_DATA_TYPE(DATA_TYPE, N0) \
76 BASENAME##7 = VLOAD(N0)(0, (__global DATA_TYPE *)(PTR + OFFSET + 7 * STRIDE_Y + Z##7));
77
78#define LOAD_ROW_9(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
79 LOAD_ROW_8(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
80 VEC_DATA_TYPE(DATA_TYPE, N0) \
81 BASENAME##8 = VLOAD(N0)(0, (__global DATA_TYPE *)(PTR + OFFSET + 8 * STRIDE_Y + Z##8));
82
83#define LOAD_ROW_10(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
84 LOAD_ROW_9(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
85 VEC_DATA_TYPE(DATA_TYPE, N0) \
86 BASENAME##9 = VLOAD(N0)(0, (__global DATA_TYPE *)(PTR + OFFSET + 9 * STRIDE_Y + Z##9));
87
88#define LOAD_ROW_11(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
89 LOAD_ROW_10(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
90 VEC_DATA_TYPE(DATA_TYPE, N0) \
91 BASENAME##A = VLOAD(N0)(0, (__global DATA_TYPE *)(PTR + OFFSET + 10 * STRIDE_Y + Z##A));
92
93#define LOAD_ROW_12(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
94 LOAD_ROW_11(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
95 VEC_DATA_TYPE(DATA_TYPE, N0) \
96 BASENAME##B = VLOAD(N0)(0, (__global DATA_TYPE *)(PTR + OFFSET + 11 * STRIDE_Y + Z##B));
97
98#define LOAD_ROW_13(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
99 LOAD_ROW_12(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
100 VEC_DATA_TYPE(DATA_TYPE, N0) \
101 BASENAME##C = VLOAD(N0)(0, (__global DATA_TYPE *)(PTR + OFFSET + 12 * STRIDE_Y + Z##C));
102
103#define LOAD_ROW_14(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
104 LOAD_ROW_13(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
105 VEC_DATA_TYPE(DATA_TYPE, N0) \
106 BASENAME##D = VLOAD(N0)(0, (__global DATA_TYPE *)(PTR + OFFSET + 13 * STRIDE_Y + Z##D));
107
108#define LOAD_ROW_15(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
109 LOAD_ROW_14(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
110 VEC_DATA_TYPE(DATA_TYPE, N0) \
111 BASENAME##E = VLOAD(N0)(0, (__global DATA_TYPE *)(PTR + OFFSET + 14 * STRIDE_Y + Z##E));
112
113#define LOAD_ROW_16(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
114 LOAD_ROW_15(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) \
115 VEC_DATA_TYPE(DATA_TYPE, N0) \
116 BASENAME##F = VLOAD(N0)(0, (__global DATA_TYPE *)(PTR + OFFSET + 15 * STRIDE_Y + Z##F));
117
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +0000118/** @}*/ // end of group LOAD_ROW_n
Usama Arif0681e3b2019-04-25 14:28:07 +0100119
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +0000120/** Load Blocks (consecutive rows and columns) with Z offset.
121 * @name LOAD_BLOCK
122 *
123 * Supported cases are M0=1,2,3,...,16 and N0=1,2,3,4,8,16
124 * The data to load is expected to have consecutive names for each row.
125 * E.g., for M0=3, and BASENAME=c, the expected data is c0, c1 and c2.
126 * The Z offset is expected to have consecutive names.
127 * E.g., for M0=3, and Z=zin, the expected Z offsets are zin0, zin1 and zin2.
128 *
129 * @param[in] M0 The number of consecutive rows
130 * @param[in] N0 The number of consecutive columns
131 * @param[in] DATA_TYPE The data type of the target
132 * @param[in] BASENAME The basename of the result variables
133 * @param[in] PTR The base pointer for the data
134 * @param[in] OFFSET The offset within a row
135 * @param[in] STRIDE_Y The stride in y-axis direction
136 * @param[in] Z The z-axis offset vector
137 * @{
138 */
139#define LOAD_BLOCK_STR(M0, N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) LOAD_ROW_##M0(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z)
140#define LOAD_BLOCK(M0, N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z) LOAD_BLOCK_STR(M0, N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y, Z)
141/** @} */ // end of group LOAD_BLOCK
142
Gian Marco Iodicee3a849a2020-06-10 17:59:30 +0100143/** Loads the rows from 0 to n-1 in the given variables (BASENAME0 to BASENAMEn-1).
144 * @name LOAD_TEXTURE2D_ROW_n
145 *
146 * @param[in] N0 The number of pixels to read
147 * @param[in] DATA_TYPE The data type of variables
148 * @param[in] BASENAME The basename of the destination variables for the loaded rows
149 * @param[in] IMG The 2D OpenCL image object
150 * @param[in] X_COORD The x coordinate for the top-left pixel
151 * @param[in] Y_COORD The y coordinate for the top-left pixel
152 * @param[in] X_STEP_ROW The incremental step row for the x coordinate (in pixels)
153 * @param[in] Y_STEP_ROW The incremental step row for the y coordinate (in pixels)
154 * @{
155 */
156#define LOAD_TEXTURE2D_ROW_1(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
157 BASENAME##0 = READ_IMAGE2D(DATA_TYPE, N0, IMG, (X_COORD + 0 * X_STEP_ROW), (Y_COORD + 0 * Y_STEP_ROW))
158
159#define LOAD_TEXTURE2D_ROW_2(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
160 LOAD_TEXTURE2D_ROW_1(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
161 BASENAME##1 = READ_IMAGE2D(DATA_TYPE, N0, IMG, (X_COORD + 1 * X_STEP_ROW), (Y_COORD + 1 * Y_STEP_ROW))
162
163#define LOAD_TEXTURE2D_ROW_3(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
164 LOAD_TEXTURE2D_ROW_2(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
165 BASENAME##2 = READ_IMAGE2D(DATA_TYPE, N0, IMG, (X_COORD + 2 * X_STEP_ROW), (Y_COORD + 2 * Y_STEP_ROW))
166
167#define LOAD_TEXTURE2D_ROW_4(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
168 LOAD_TEXTURE2D_ROW_3(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
169 BASENAME##3 = READ_IMAGE2D(DATA_TYPE, N0, IMG, (X_COORD + 3 * X_STEP_ROW), (Y_COORD + 3 * Y_STEP_ROW))
170
171#define LOAD_TEXTURE2D_ROW_5(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
172 LOAD_TEXTURE2D_ROW_4(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
173 BASENAME##4 = READ_IMAGE2D(DATA_TYPE, N0, IMG, (X_COORD + 4 * X_STEP_ROW), (Y_COORD + 4 * Y_STEP_ROW))
174
175#define LOAD_TEXTURE2D_ROW_6(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
176 LOAD_TEXTURE2D_ROW_5(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
177 BASENAME##5 = READ_IMAGE2D(DATA_TYPE, N0, IMG, (X_COORD + 5 * X_STEP_ROW), (Y_COORD + 5 * Y_STEP_ROW))
178
179#define LOAD_TEXTURE2D_ROW_7(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
180 LOAD_TEXTURE2D_ROW_6(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
181 BASENAME##6 = READ_IMAGE2D(DATA_TYPE, N0, IMG, (X_COORD + 6 * X_STEP_ROW), (Y_COORD + 6 * Y_STEP_ROW))
182
183#define LOAD_TEXTURE2D_ROW_8(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
184 LOAD_TEXTURE2D_ROW_7(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
185 BASENAME##7 = READ_IMAGE2D(DATA_TYPE, N0, IMG, (X_COORD + 7 * X_STEP_ROW), (Y_COORD + 7 * Y_STEP_ROW))
186
187#define LOAD_TEXTURE2D_ROW_9(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
188 LOAD_TEXTURE2D_ROW_8(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
189 BASENAME##8 = READ_IMAGE2D(DATA_TYPE, N0, IMG, (X_COORD + 8 * X_STEP_ROW), (Y_COORD + 8 * Y_STEP_ROW))
190
191#define LOAD_TEXTURE2D_ROW_10(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
192 LOAD_TEXTURE2D_ROW_9(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
193 BASENAME##9 = READ_IMAGE2D(DATA_TYPE, N0, IMG, (X_COORD + 9 * X_STEP_ROW), (Y_COORD + 9 * Y_STEP_ROW))
194
195#define LOAD_TEXTURE2D_ROW_11(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
196 LOAD_TEXTURE2D_ROW_10(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
197 BASENAME##A = READ_IMAGE2D(DATA_TYPE, N0, IMG, (X_COORD + 10 * X_STEP_ROW), (Y_COORD + 10 * Y_STEP_ROW))
198
199#define LOAD_TEXTURE2D_ROW_12(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
200 LOAD_TEXTURE2D_ROW_11(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
201 BASENAME##B = READ_IMAGE2D(DATA_TYPE, N0, IMG, (X_COORD + 11 * X_STEP_ROW), (Y_COORD + 11 * Y_STEP_ROW))
202
203#define LOAD_TEXTURE2D_ROW_13(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
204 LOAD_TEXTURE2D_ROW_12(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
205 BASENAME##C = READ_IMAGE2D(DATA_TYPE, N0, IMG, (X_COORD + 12 * X_STEP_ROW), (Y_COORD + 12 * Y_STEP_ROW))
206
207#define LOAD_TEXTURE2D_ROW_14(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
208 LOAD_TEXTURE2D_ROW_13(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
209 BASENAME##D = READ_IMAGE2D(DATA_TYPE, N0, IMG, (X_COORD + 13 * X_STEP_ROW), (Y_COORD + 13 * Y_STEP_ROW))
210
211#define LOAD_TEXTURE2D_ROW_15(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
212 LOAD_TEXTURE2D_ROW_14(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
213 BASENAME##E = READ_IMAGE2D(DATA_TYPE, N0, IMG, (X_COORD + 14 * X_STEP_ROW), (Y_COORD + 14 * Y_STEP_ROW))
214
215#define LOAD_TEXTURE2D_ROW_16(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
216 LOAD_TEXTURE2D_ROW_15(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) \
217 BASENAME##F = READ_IMAGE2D(DATA_TYPE, N0, IMG, (X_COORD + 15 * X_STEP_ROW), (Y_COORD + 15 * Y_STEP_ROW))
218/** @} */ // end of group LOAD_TEXTURE2D_ROW_n
219
220/** Load a 2D texture in unit of pixel. A pixel is made of 4 floating point values
221 * @name LOAD_TEXTURE2D
222 *
223 * Supported cases are M0=1,2,3,...,16 and N0=1
224 * The data to load is expected to have consecutive names for each row.
225 * E.g., for M0=3, and BASENAME=c, the expected data is c0, c1 and c2.
226 *
227 * @param[in] M0 The number of consecutive rows
228 * @param[in] N0 The number of consecutive pixels. Only 1, 2 and 4 are supported
229 * @param[in] DATA_TYPE The data type of the target
230 * @param[in] BASENAME The basename of the result variables
231 * @param[in] IMG The 2D OpenCL image object
232 * @param[in] X_COORD The x coordinate for the top-left pixel
233 * @param[in] Y_COORD The y coordinate for the top-left pixel
234 * @param[in] X_STEP_ROW The incremental step row for the x coordinate (in pixels)
235 * @param[in] Y_STEP_ROW The incremental step row for the y coordinate (in pixels)
236 * @{
237 */
238#define LOAD_TEXTURE2D_STR(M0, N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) LOAD_TEXTURE2D_ROW_##M0(N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW)
239#define LOAD_TEXTURE2D(M0, N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW) LOAD_TEXTURE2D_STR(M0, N0, DATA_TYPE, BASENAME, IMG, X_COORD, Y_COORD, X_STEP_ROW, Y_STEP_ROW)
240/** @} */ // end of group LOAD_TEXTURE2D
241
Michele Di Giorgiob54ba282020-01-14 15:31:55 +0000242/** Loads the elements from 0 to n-1 in the given variables (BASENAME0 to BASENAMEn-1).
243 * @name LOAD_ELEMENT_n
244 *
245 * @param[in] N0 The number of rows to load
246 * @param[in] DATA_TYPE The data type of variables
247 * @param[in] BASENAME The basename of the destination variables for the loaded rows
248 * @param[in] PTR The base pointer
249 * @param[in] OFFSET The offset within a row
250 * @param[in] STRIDE_Y The stride value in y-axis direction
251 * @{
252 */
253#define LOAD_ELEMENT_1(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
254 VEC_DATA_TYPE(DATA_TYPE, N0) \
255 BASENAME##0 = *((__global DATA_TYPE *)(PTR + OFFSET + 0 * STRIDE_Y));
256
257#define LOAD_ELEMENT_2(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
258 LOAD_ELEMENT_1(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
259 VEC_DATA_TYPE(DATA_TYPE, N0) \
260 BASENAME##1 = *((__global DATA_TYPE *)(PTR + OFFSET + 1 * STRIDE_Y));
261
262#define LOAD_ELEMENT_3(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
263 LOAD_ELEMENT_2(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
264 VEC_DATA_TYPE(DATA_TYPE, N0) \
265 BASENAME##2 = *((__global DATA_TYPE *)(PTR + OFFSET + 2 * STRIDE_Y));
266
267#define LOAD_ELEMENT_4(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
268 LOAD_ELEMENT_3(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
269 VEC_DATA_TYPE(DATA_TYPE, N0) \
270 BASENAME##3 = *((__global DATA_TYPE *)(PTR + OFFSET + 3 * STRIDE_Y));
271
272#define LOAD_ELEMENT_5(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
273 LOAD_ELEMENT_4(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
274 VEC_DATA_TYPE(DATA_TYPE, N0) \
275 BASENAME##4 = *((__global DATA_TYPE *)(PTR + OFFSET + 4 * STRIDE_Y));
276
277#define LOAD_ELEMENT_6(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
278 LOAD_ELEMENT_5(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
279 VEC_DATA_TYPE(DATA_TYPE, N0) \
280 BASENAME##5 = *((__global DATA_TYPE *)(PTR + OFFSET + 5 * STRIDE_Y));
281
282#define LOAD_ELEMENT_7(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
283 LOAD_ELEMENT_6(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
284 VEC_DATA_TYPE(DATA_TYPE, N0) \
285 BASENAME##6 = *((__global DATA_TYPE *)(PTR + OFFSET + 6 * STRIDE_Y));
286
287#define LOAD_ELEMENT_8(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
288 LOAD_ELEMENT_7(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
289 VEC_DATA_TYPE(DATA_TYPE, N0) \
290 BASENAME##7 = *((__global DATA_TYPE *)(PTR + OFFSET + 7 * STRIDE_Y));
291
292#define LOAD_ELEMENT_9(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
293 LOAD_ELEMENT_8(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
294 VEC_DATA_TYPE(DATA_TYPE, N0) \
295 BASENAME##8 = *((__global DATA_TYPE *)(PTR + OFFSET + 8 * STRIDE_Y));
296
297#define LOAD_ELEMENT_10(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
298 LOAD_ELEMENT_9(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
299 VEC_DATA_TYPE(DATA_TYPE, N0) \
300 BASENAME##9 = *((__global DATA_TYPE *)(PTR + OFFSET + 9 * STRIDE_Y));
301
302#define LOAD_ELEMENT_11(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
303 LOAD_ELEMENT_10(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
304 VEC_DATA_TYPE(DATA_TYPE, N0) \
305 BASENAME##A = *((__global DATA_TYPE *)(PTR + OFFSET + 10 * STRIDE_Y));
306
307#define LOAD_ELEMENT_12(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
308 LOAD_ELEMENT_11(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
309 VEC_DATA_TYPE(DATA_TYPE, N0) \
310 BASENAME##B = *((__global DATA_TYPE *)(PTR + OFFSET + 11 * STRIDE_Y));
311
312#define LOAD_ELEMENT_13(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
313 LOAD_ELEMENT_12(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
314 VEC_DATA_TYPE(DATA_TYPE, N0) \
315 BASENAME##C = *((__global DATA_TYPE *)(PTR + OFFSET + 12 * STRIDE_Y));
316
317#define LOAD_ELEMENT_14(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
318 LOAD_ELEMENT_13(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
319 VEC_DATA_TYPE(DATA_TYPE, N0) \
320 BASENAME##D = *((__global DATA_TYPE *)(PTR + OFFSET + 13 * STRIDE_Y));
321
322#define LOAD_ELEMENT_15(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
323 LOAD_ELEMENT_14(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
324 VEC_DATA_TYPE(DATA_TYPE, N0) \
325 BASENAME##E = *((__global DATA_TYPE *)(PTR + OFFSET + 14 * STRIDE_Y));
326
327#define LOAD_ELEMENT_16(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
328 LOAD_ELEMENT_15(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) \
329 VEC_DATA_TYPE(DATA_TYPE, N0) \
330 BASENAME##F = *((__global DATA_TYPE *)(PTR + OFFSET + 15 * STRIDE_Y));
331
332/** @}*/ // end of group LOAD_ELEMENT_n
333
334/** Load Scalar as Vector (consecutive elements).
335 * @name LOAD_SCALAR_AS_VECTOR
336 *
337 * Supported cases are M0=1,2,3,...,16 and N0=1,2,3,4,8,16
338 * The data to load is expected to have consecutive names for each row.
339 * E.g., for M0=3, and BASENAME=c, the expected data is c0, c1 and c2.
340 *
341 * @param[in] M0 The number of consecutive rows
342 * @param[in] N0 The number of consecutive columns
343 * @param[in] DATA_TYPE The data type of the target
344 * @param[in] BASENAME The basename of the result variables
345 * @param[in] PTR The base pointer for the data
346 * @param[in] OFFSET The offset within a row
347 * @param[in] STRIDE_Y The stride in y-axis direction
348 * @{
349 */
350#define LOAD_SCALAR_AS_VECTOR_STR(M0, N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) LOAD_ELEMENT_##M0(N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y)
351#define LOAD_SCALAR_AS_VECTOR(M0, N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y) LOAD_SCALAR_AS_VECTOR_STR(M0, N0, DATA_TYPE, BASENAME, PTR, OFFSET, STRIDE_Y)
352/** @} */ // end of group LOAD_SCALAR_AS_VECTOR
353
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +0000354/** Basic macros to calculate Z offset values from Z0 to Zn-1
355 * @name CALCULATE_Z_OFFSET_n
356 *
357 * @param[in] M0 The number of offset values to calculate
358 * @param[in] DATA_TYPE The data type of the results
359 * @param[in] Z The basename of the result variables
360 * @param[in] Y The work-itme ID of y-axis
361 * @param[in] HEIGHT_GEMM3D The height of GEMM3D
362 * @param[in] DEPTH_GEMM3D The depth of GEMM3D
363 * @param[in] CROSS_PLANE_PAD The padding required for plane changes accross the z-dimension
364 * @param[in] STRIDE_Y The stride value in y-axis direction
365 *
366 * @{
367 */
Usama Arif0681e3b2019-04-25 14:28:07 +0100368#define CALCULATE_Z_OFFSET_1(M0, DATA_TYPE, Z, Y, HEIGHT_GEMM3D, DEPTH_GEMM3D, CROSS_PLANE_PAD, STRIDE_Y) \
Gian Marco Iodice43a129e2019-05-14 10:14:08 +0100369 Z##0 = (0 + (DATA_TYPE)(Y * (DATA_TYPE)M0)) / (DATA_TYPE)HEIGHT_GEMM3D; \
370 Z##0 = min((DATA_TYPE)(DEPTH_GEMM3D - 1), Z##0); \
Usama Arif0681e3b2019-04-25 14:28:07 +0100371 Z##0 *= (CROSS_PLANE_PAD * STRIDE_Y);
372
373#define CALCULATE_Z_OFFSET_2(M0, DATA_TYPE, Z, Y, HEIGHT_GEMM3D, DEPTH_GEMM3D, CROSS_PLANE_PAD, STRIDE_Y) \
374 CALCULATE_Z_OFFSET_1(M0, DATA_TYPE, Z, Y, HEIGHT_GEMM3D, DEPTH_GEMM3D, CROSS_PLANE_PAD, STRIDE_Y) \
Gian Marco Iodice43a129e2019-05-14 10:14:08 +0100375 Z##1 = (1 + (DATA_TYPE)(Y * (DATA_TYPE)M0)) / (DATA_TYPE)HEIGHT_GEMM3D; \
376 Z##1 = min((DATA_TYPE)(DEPTH_GEMM3D - 1), Z##1); \
Usama Arif0681e3b2019-04-25 14:28:07 +0100377 Z##1 *= (CROSS_PLANE_PAD * STRIDE_Y);
378
379#define CALCULATE_Z_OFFSET_3(M0, DATA_TYPE, Z, Y, HEIGHT_GEMM3D, DEPTH_GEMM3D, CROSS_PLANE_PAD, STRIDE_Y) \
380 CALCULATE_Z_OFFSET_2(M0, DATA_TYPE, Z, Y, HEIGHT_GEMM3D, DEPTH_GEMM3D, CROSS_PLANE_PAD, STRIDE_Y) \
Gian Marco Iodice43a129e2019-05-14 10:14:08 +0100381 Z##2 = (2 + (DATA_TYPE)(Y * (DATA_TYPE)M0)) / (DATA_TYPE)HEIGHT_GEMM3D; \
382 Z##2 = min((DATA_TYPE)(DEPTH_GEMM3D - 1), Z##2); \
Usama Arif0681e3b2019-04-25 14:28:07 +0100383 Z##2 *= (CROSS_PLANE_PAD * STRIDE_Y);
384
385#define CALCULATE_Z_OFFSET_4(M0, DATA_TYPE, Z, Y, HEIGHT_GEMM3D, DEPTH_GEMM3D, CROSS_PLANE_PAD, STRIDE_Y) \
386 CALCULATE_Z_OFFSET_3(M0, DATA_TYPE, Z, Y, HEIGHT_GEMM3D, DEPTH_GEMM3D, CROSS_PLANE_PAD, STRIDE_Y) \
Gian Marco Iodice43a129e2019-05-14 10:14:08 +0100387 Z##3 = (3 + (DATA_TYPE)(Y * (DATA_TYPE)M0)) / (DATA_TYPE)HEIGHT_GEMM3D; \
388 Z##3 = min((DATA_TYPE)(DEPTH_GEMM3D - 1), Z##3); \
Usama Arif0681e3b2019-04-25 14:28:07 +0100389 Z##3 *= (CROSS_PLANE_PAD * STRIDE_Y);
390
391#define CALCULATE_Z_OFFSET_5(M0, DATA_TYPE, Z, Y, HEIGHT_GEMM3D, DEPTH_GEMM3D, CROSS_PLANE_PAD, STRIDE_Y) \
392 CALCULATE_Z_OFFSET_4(M0, DATA_TYPE, Z, Y, HEIGHT_GEMM3D, DEPTH_GEMM3D, CROSS_PLANE_PAD, STRIDE_Y) \
Gian Marco Iodice43a129e2019-05-14 10:14:08 +0100393 Z##4 = (4 + (DATA_TYPE)(Y * (DATA_TYPE)M0)) / (DATA_TYPE)HEIGHT_GEMM3D; \
394 Z##4 = min((DATA_TYPE)(DEPTH_GEMM3D - 1), Z##4); \
Usama Arif0681e3b2019-04-25 14:28:07 +0100395 Z##4 *= (CROSS_PLANE_PAD * STRIDE_Y);
396
397#define CALCULATE_Z_OFFSET_6(M0, DATA_TYPE, Z, Y, HEIGHT_GEMM3D, DEPTH_GEMM3D, CROSS_PLANE_PAD, STRIDE_Y) \
398 CALCULATE_Z_OFFSET_5(M0, DATA_TYPE, Z, Y, HEIGHT_GEMM3D, DEPTH_GEMM3D, CROSS_PLANE_PAD, STRIDE_Y) \
Gian Marco Iodice43a129e2019-05-14 10:14:08 +0100399 Z##5 = (5 + (DATA_TYPE)(Y * (DATA_TYPE)M0)) / (DATA_TYPE)HEIGHT_GEMM3D; \
400 Z##5 = min((DATA_TYPE)(DEPTH_GEMM3D - 1), Z##5); \
Usama Arif0681e3b2019-04-25 14:28:07 +0100401 Z##5 *= (CROSS_PLANE_PAD * STRIDE_Y);
402
403#define CALCULATE_Z_OFFSET_7(M0, DATA_TYPE, Z, Y, HEIGHT_GEMM3D, DEPTH_GEMM3D, CROSS_PLANE_PAD, STRIDE_Y) \
404 CALCULATE_Z_OFFSET_6(M0, DATA_TYPE, Z, Y, HEIGHT_GEMM3D, DEPTH_GEMM3D, CROSS_PLANE_PAD, STRIDE_Y) \
Gian Marco Iodice43a129e2019-05-14 10:14:08 +0100405 Z##6 = (6 + (DATA_TYPE)(Y * (DATA_TYPE)M0)) / (DATA_TYPE)HEIGHT_GEMM3D; \
406 Z##6 = min((DATA_TYPE)(DEPTH_GEMM3D - 1), Z##6); \
Usama Arif0681e3b2019-04-25 14:28:07 +0100407 Z##6 *= (CROSS_PLANE_PAD * STRIDE_Y);
408
409#define CALCULATE_Z_OFFSET_8(M0, DATA_TYPE, Z, Y, HEIGHT_GEMM3D, DEPTH_GEMM3D, CROSS_PLANE_PAD, STRIDE_Y) \
410 CALCULATE_Z_OFFSET_7(M0, DATA_TYPE, Z, Y, HEIGHT_GEMM3D, DEPTH_GEMM3D, CROSS_PLANE_PAD, STRIDE_Y) \
Gian Marco Iodice43a129e2019-05-14 10:14:08 +0100411 Z##7 = (7 + (DATA_TYPE)(Y * (DATA_TYPE)M0)) / (DATA_TYPE)HEIGHT_GEMM3D; \
412 Z##7 = min((DATA_TYPE)(DEPTH_GEMM3D - 1), Z##7); \
Usama Arif0681e3b2019-04-25 14:28:07 +0100413 Z##7 *= (CROSS_PLANE_PAD * STRIDE_Y);
414
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +0000415/** @} */ // end of group CALCULATE_Z_OFFSET_n
Usama Arif0681e3b2019-04-25 14:28:07 +0100416
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +0000417/** Calculate Z offset values from Z0 to Zn-1
418 * @name CALCULATE_Z_OFFSET
419 *
420 * The Z offsets are expected to have consecutive names.
421 * E.g., for M0=3 and Z=zin, the expected names of Z offsets are zin1, zin2, zin3.
422 * Note that, CROSS_PLANE_PAD (cross plain padding) is required to take into account
423 * the possible cross plane paddings in case of the plance changes across the z-dimension.
424 *
425 * <!--
426 * | |
427 * | plane0 |
428 * | |
429 * |__________________|
430 * |******************|
431 * | cross_plane_pad |
432 * |******************|
433 * | |
434 * | plane1 |
435 * | |
436 * |__________________|
437 * -->
438 *
439 * @param[in] M0 The number of offset values to calculate
440 * @param[in] DATA_TYPE The data type of the results
441 * @param[in] Z The basename of the result variables
442 * @param[in] Y The work-itme ID of y-axis
443 * @param[in] HEIGHT_GEMM3D The height of GEMM3D
444 * @param[in] DEPTH_GEMM3D The depth of GEMM3D
445 * @param[in] CROSS_PLANE_PAD The padding required for plane changes accross the z-dimension
446 * @param[in] STRIDE_Y The stride value in y-axis direction
447 * @{
448 */
449#define CALCULATE_Z_OFFSET_STR(M0, DATA_TYPE, Z, Y, HEIGHT_GEMM3D, DEPTH_GEMM3D, CROSS_PLANE_PAD, STRIDE_Y) CALCULATE_Z_OFFSET_##M0(M0, DATA_TYPE, Z, Y, HEIGHT_GEMM3D, DEPTH_GEMM3D, CROSS_PLANE_PAD, STRIDE_Y)
450#define CALCULATE_Z_OFFSET(M0, DATA_TYPE, Z, Y, HEIGHT_GEMM3D, DEPTH_GEMM3D, CROSS_PLANE_PAD, STRIDE_Y) CALCULATE_Z_OFFSET_STR(M0, DATA_TYPE, Z, Y, HEIGHT_GEMM3D, DEPTH_GEMM3D, CROSS_PLANE_PAD, STRIDE_Y)
451/** @} */ // end of group CALCULATE_Z_OFFSET
452
453/** Store the 0 to (n-1)th rows of the given variables
454 * @name STORE_ROW_n
455 *
SiCong Li3a501662020-06-26 10:02:06 +0100456 * @param[in] N0 The width of the passed in vector. Supported: 1, 2, 3, 4, 8, 16
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +0000457 * @param[in] DATA_TYPE The data type of the vectors
458 * @param[in] BASENAME The basename of the variables
459 * @param[in] PTR The base pointer
460 * @param[in] STRIDE_Y The stride value in y-axis direction
461 * @param[in] Z The offset in z-axis direction
462 * @{
463 */
Usama Arif0681e3b2019-04-25 14:28:07 +0100464#define STORE_ROW_1(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
465 VSTORE(N0) \
466 (BASENAME##0, 0, (__global DATA_TYPE *)(PTR + 0 * STRIDE_Y + Z##0));
467
468#define STORE_ROW_2(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
469 STORE_ROW_1(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
470 VSTORE(N0) \
471 (BASENAME##1, 0, (__global DATA_TYPE *)(PTR + 1 * STRIDE_Y + Z##1));
472
473#define STORE_ROW_3(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
474 STORE_ROW_2(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
475 VSTORE(N0) \
476 (BASENAME##2, 0, (__global DATA_TYPE *)(PTR + 2 * STRIDE_Y + Z##2));
477
478#define STORE_ROW_4(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
479 STORE_ROW_3(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
480 VSTORE(N0) \
481 (BASENAME##3, 0, (__global DATA_TYPE *)(PTR + 3 * STRIDE_Y + Z##3));
482
483#define STORE_ROW_5(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
484 STORE_ROW_4(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
485 VSTORE(N0) \
486 (BASENAME##4, 0, (__global DATA_TYPE *)(PTR + 4 * STRIDE_Y + Z##4));
487
488#define STORE_ROW_6(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
489 STORE_ROW_5(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
490 VSTORE(N0) \
491 (BASENAME##5, 0, (__global DATA_TYPE *)(PTR + 5 * STRIDE_Y + Z##5));
492
493#define STORE_ROW_7(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
494 STORE_ROW_6(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
495 VSTORE(N0) \
496 (BASENAME##6, 0, (__global DATA_TYPE *)(PTR + 6 * STRIDE_Y + Z##6));
497
498#define STORE_ROW_8(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
499 STORE_ROW_7(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
500 VSTORE(N0) \
501 (BASENAME##7, 0, (__global DATA_TYPE *)(PTR + 7 * STRIDE_Y + Z##7));
502
503#define STORE_ROW_9(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
504 STORE_ROW_8(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
505 VSTORE(N0) \
506 (BASENAME##8, 0, (__global DATA_TYPE *)(PTR + 8 * STRIDE_Y + Z##8));
507
508#define STORE_ROW_10(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
509 STORE_ROW_9(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
510 VSTORE(N0) \
511 (BASENAME##9, 0, (__global DATA_TYPE *)(PTR + 9 * STRIDE_Y + Z##9));
512
513#define STORE_ROW_11(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
514 STORE_ROW_10(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
515 VSTORE(N0) \
516 (BASENAME##A, 0, (__global DATA_TYPE *)(PTR + 10 * STRIDE_Y + Z##A));
517
518#define STORE_ROW_12(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
519 STORE_ROW_11(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
520 VSTORE(N0) \
521 (BASENAME##B, 0, (__global DATA_TYPE *)(PTR + 11 * STRIDE_Y + Z##B));
522
523#define STORE_ROW_13(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
524 STORE_ROW_12(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
525 VSTORE(N0) \
526 (BASENAME##C, 0, (__global DATA_TYPE *)(PTR + 12 * STRIDE_Y + Z##C));
527
528#define STORE_ROW_14(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
529 STORE_ROW_13(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
530 VSTORE(N0) \
531 (BASENAME##D, 0, (__global DATA_TYPE *)(PTR + 13 * STRIDE_Y + Z##D));
532
533#define STORE_ROW_15(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
534 STORE_ROW_14(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
535 VSTORE(N0) \
536 (BASENAME##E, 0, (__global DATA_TYPE *)(PTR + 14 * STRIDE_Y + Z##E));
537
538#define STORE_ROW_16(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
539 STORE_ROW_15(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
540 VSTORE(N0) \
541 (BASENAME##F, 0, (__global DATA_TYPE *)(PTR + 15 * STRIDE_Y + Z##F));
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +0000542/** @} */ // end of groupd STORE_ROW_n
Usama Arif0681e3b2019-04-25 14:28:07 +0100543
SiCong Li3a501662020-06-26 10:02:06 +0100544/** Partially store the 0 to (n-1)th rows of the given variables
545 * @name STORE_ROW_PARTIAL_n
546 * Within each row, store the lower @p STORE_N0 elements of vectors of width @p N0
547 *
548 * @note in case @p STORE_N0 != 1, 2, 3, 4, 8, 16, extra vstore(s) will be invoked, thus incurring small performance penalty.
549 *
550 * @param[in] N0 The width of the passed in vector. Supported: 1, 2, 3, 4, 8, 16
551 * @param[in] STORE_N0 The **lower** size of the vectors to store. Supported: [1-16 and <= @p N0
552 * @param[in] DATA_TYPE The data type of the vectors
553 * @param[in] BASENAME The basename of the variables
554 * @param[in] PTR The base pointer
555 * @param[in] STRIDE_Y The stride value in y-axis direction
556 * @param[in] Z The offset in z-axis direction
557 * @{
558 */
559#define STORE_ROW_PARTIAL_1(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
560 VSTORE_PARTIAL(N0, STORE_N0) \
561 (BASENAME##0, 0, (__global DATA_TYPE *)(PTR + 0 * STRIDE_Y + Z##0));
562
563#define STORE_ROW_PARTIAL_2(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
564 STORE_ROW_PARTIAL_1(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
565 VSTORE_PARTIAL(N0, STORE_N0) \
566 (BASENAME##1, 0, (__global DATA_TYPE *)(PTR + 1 * STRIDE_Y + Z##1));
567
568#define STORE_ROW_PARTIAL_3(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
569 STORE_ROW_PARTIAL_2(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
570 VSTORE_PARTIAL(N0, STORE_N0) \
571 (BASENAME##2, 0, (__global DATA_TYPE *)(PTR + 2 * STRIDE_Y + Z##2));
572
573#define STORE_ROW_PARTIAL_4(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
574 STORE_ROW_PARTIAL_3(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
575 VSTORE_PARTIAL(N0, STORE_N0) \
576 (BASENAME##3, 0, (__global DATA_TYPE *)(PTR + 3 * STRIDE_Y + Z##3));
577
578#define STORE_ROW_PARTIAL_5(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
579 STORE_ROW_PARTIAL_4(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
580 VSTORE_PARTIAL(N0, STORE_N0) \
581 (BASENAME##4, 0, (__global DATA_TYPE *)(PTR + 4 * STRIDE_Y + Z##4));
582
583#define STORE_ROW_PARTIAL_6(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
584 STORE_ROW_PARTIAL_5(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
585 VSTORE_PARTIAL(N0, STORE_N0) \
586 (BASENAME##5, 0, (__global DATA_TYPE *)(PTR + 5 * STRIDE_Y + Z##5));
587
588#define STORE_ROW_PARTIAL_7(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
589 STORE_ROW_PARTIAL_6(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
590 VSTORE_PARTIAL(N0, STORE_N0) \
591 (BASENAME##6, 0, (__global DATA_TYPE *)(PTR + 6 * STRIDE_Y + Z##6));
592
593#define STORE_ROW_PARTIAL_8(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
594 STORE_ROW_PARTIAL_7(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
595 VSTORE_PARTIAL(N0, STORE_N0) \
596 (BASENAME##7, 0, (__global DATA_TYPE *)(PTR + 7 * STRIDE_Y + Z##7));
597
598#define STORE_ROW_PARTIAL_9(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
599 STORE_ROW_PARTIAL_8(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
600 VSTORE_PARTIAL(N0, STORE_N0) \
601 (BASENAME##8, 0, (__global DATA_TYPE *)(PTR + 8 * STRIDE_Y + Z##8));
602
603#define STORE_ROW_PARTIAL_10(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
604 STORE_ROW_PARTIAL_9(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
605 VSTORE_PARTIAL(N0, STORE_N0) \
606 (BASENAME##9, 0, (__global DATA_TYPE *)(PTR + 9 * STRIDE_Y + Z##9));
607
608#define STORE_ROW_PARTIAL_11(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
609 STORE_ROW_PARTIAL_10(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
610 VSTORE_PARTIAL(N0, STORE_N0) \
611 (BASENAME##A, 0, (__global DATA_TYPE *)(PTR + 10 * STRIDE_Y + Z##A));
612
613#define STORE_ROW_PARTIAL_12(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
614 STORE_ROW_PARTIAL_11(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
615 VSTORE_PARTIAL(N0, STORE_N0) \
616 (BASENAME##B, 0, (__global DATA_TYPE *)(PTR + 11 * STRIDE_Y + Z##B));
617
618#define STORE_ROW_PARTIAL_13(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
619 STORE_ROW_PARTIAL_12(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
620 VSTORE_PARTIAL(N0, STORE_N0) \
621 (BASENAME##C, 0, (__global DATA_TYPE *)(PTR + 12 * STRIDE_Y + Z##C));
622
623#define STORE_ROW_PARTIAL_14(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
624 STORE_ROW_PARTIAL_13(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
625 VSTORE_PARTIAL(N0, STORE_N0) \
626 (BASENAME##D, 0, (__global DATA_TYPE *)(PTR + 13 * STRIDE_Y + Z##D));
627
628#define STORE_ROW_PARTIAL_15(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
629 STORE_ROW_PARTIAL_14(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
630 VSTORE_PARTIAL(N0, STORE_N0) \
631 (BASENAME##E, 0, (__global DATA_TYPE *)(PTR + 14 * STRIDE_Y + Z##E));
632
633#define STORE_ROW_PARTIAL_16(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
634 STORE_ROW_PARTIAL_15(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
635 VSTORE_PARTIAL(N0, STORE_N0) \
636 (BASENAME##F, 0, (__global DATA_TYPE *)(PTR + 15 * STRIDE_Y + Z##F));
637/** @} */ // end of groupd STORE_ROW_PARTIAL_n
638
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +0000639/** Convert and store the 0th to (n-1)th rows of the given variables
640 * @name CONVERT_STORE_ROW_n
641 *
642 * @param[in] N0 The size of the vectors
643 * @param[in] DATA_TYPE The data type of the vectors
644 * @param[in] BASENAME The basename of the variables
645 * @param[in] PTR The base pointer
646 * @param[in] STRIDE_Y The stride value in y-axis direction
647 * @param[in] Z The offset in z-axis direction
648 * @{
649 */
Gian Marco Iodice43a129e2019-05-14 10:14:08 +0100650#define CONVERT_STORE_ROW_1(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
651 VSTORE(N0) \
652 (CONVERT_SAT((BASENAME##0), VEC_DATA_TYPE(DATA_TYPE, N0)), 0, (__global DATA_TYPE *)(PTR + 0 * STRIDE_Y + Z##0));
653
654#define CONVERT_STORE_ROW_2(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
655 CONVERT_STORE_ROW_1(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
656 VSTORE(N0) \
657 (CONVERT_SAT((BASENAME##1), VEC_DATA_TYPE(DATA_TYPE, N0)), 0, (__global DATA_TYPE *)(PTR + 1 * STRIDE_Y + Z##1));
658
659#define CONVERT_STORE_ROW_3(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
660 CONVERT_STORE_ROW_2(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
661 VSTORE(N0) \
662 (CONVERT_SAT((BASENAME##2), VEC_DATA_TYPE(DATA_TYPE, N0)), 0, (__global DATA_TYPE *)(PTR + 2 * STRIDE_Y + Z##2));
663
664#define CONVERT_STORE_ROW_4(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
665 CONVERT_STORE_ROW_3(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
666 VSTORE(N0) \
667 (CONVERT_SAT((BASENAME##3), VEC_DATA_TYPE(DATA_TYPE, N0)), 0, (__global DATA_TYPE *)(PTR + 3 * STRIDE_Y + Z##3));
668
669#define CONVERT_STORE_ROW_5(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
670 CONVERT_STORE_ROW_4(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
671 VSTORE(N0) \
672 (CONVERT_SAT((BASENAME##4), VEC_DATA_TYPE(DATA_TYPE, N0)), 0, (__global DATA_TYPE *)(PTR + 4 * STRIDE_Y + Z##4));
673
674#define CONVERT_STORE_ROW_6(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
675 CONVERT_STORE_ROW_5(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
676 VSTORE(N0) \
677 (CONVERT_SAT((BASENAME##5), VEC_DATA_TYPE(DATA_TYPE, N0)), 0, (__global DATA_TYPE *)(PTR + 5 * STRIDE_Y + Z##5));
678
679#define CONVERT_STORE_ROW_7(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
680 CONVERT_STORE_ROW_6(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
681 VSTORE(N0) \
682 (CONVERT_SAT((BASENAME##6), VEC_DATA_TYPE(DATA_TYPE, N0)), 0, (__global DATA_TYPE *)(PTR + 6 * STRIDE_Y + Z##6));
683
684#define CONVERT_STORE_ROW_8(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
685 CONVERT_STORE_ROW_7(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
686 VSTORE(N0) \
687 (CONVERT_SAT((BASENAME##7), VEC_DATA_TYPE(DATA_TYPE, N0)), 0, (__global DATA_TYPE *)(PTR + 7 * STRIDE_Y + Z##7));
688
689#define CONVERT_STORE_ROW_9(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
690 CONVERT_STORE_ROW_8(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
691 VSTORE(N0) \
692 (CONVERT_SAT((BASENAME##8), VEC_DATA_TYPE(DATA_TYPE, N0)), 0, (__global DATA_TYPE *)(PTR + 8 * STRIDE_Y + Z##8));
693
694#define CONVERT_STORE_ROW_10(N0, DATA, BASENAME, PTR, STRIDE_Y, Z) \
695 CONVERT_STORE_ROW_9(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
696 VSTORE(N0) \
697 (CONVERT_SAT((BASENAME##9), VEC_DATA_TYPE(DATA_TYPE, N0)), 0, (__global DATA_TYPE *)(PTR + 9 * STRIDE_Y + Z##9));
698
699#define CONVERT_STORE_ROW_11(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
700 CONVERT_STORE_ROW_10(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
701 VSTORE(N0) \
702 (CONVERT_SAT((BASENAME##A), VEC_DATA_TYPE(DATA_TYPE, N0)), 0, (__global DATA_TYPE *)(PTR + 10 * STRIDE_Y + Z##A));
703
704#define CONVERT_STORE_ROW_12(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
705 CONVERT_STORE_ROW_11(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
706 VSTORE(N0) \
707 (CONVERT_SAT((BASENAME##B), VEC_DATA_TYPE(DATA_TYPE, N0)), 0, (__global DATA_TYPE *)(PTR + 11 * STRIDE_Y + Z##B));
708
709#define CONVERT_STORE_ROW_13(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
710 CONVERT_STORE_ROW_12(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
711 VSTORE(N0) \
712 (CONVERT_SAT((BASENAME##C), VEC_DATA_TYPE(DATA_TYPE, N0)), 0, (__global DATA_TYPE *)(PTR + 12 * STRIDE_Y + Z##C));
713
714#define CONVERT_STORE_ROW_14(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
715 CONVERT_STORE_ROW_13(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
716 VSTORE(N0) \
717 (CONVERT_SAT((BASENAME##D), VEC_DATA_TYPE(DATA_TYPE, N0)), 0, (__global DATA_TYPE *)(PTR + 13 * STRIDE_Y + Z##D));
718
719#define CONVERT_STORE_ROW_15(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
720 CONVERT_STORE_ROW_14(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
721 VSTORE(N0) \
722 (CONVERT_SAT((BASENAME##E), VEC_DATA_TYPE(DATA_TYPE, N0)), 0, (__global DATA_TYPE *)(PTR + 14 * STRIDE_Y + Z##E));
723
724#define CONVERT_STORE_ROW_16(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
725 CONVERT_STORE_ROW_15(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) \
726 VSTORE(N0) \
727 (CONVERT_SAT((BASENAME##F), VEC_DATA_TYPE(DATA_TYPE, N0)), 0, (__global DATA_TYPE *)(PTR + 15 * STRIDE_Y + Z##F));
728
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +0000729/** @} */ // end of groupd CONVERT_STORE_ROW_n
730
731/** Store a block of the given size M0xN0
732 * @name STORE_BLOCK
733 *
734 * Supported cases are M0=1,2,3,...,16 and N0=2,3,4,8,16.
735 * The data to store is expected to have consecutive names for each row.
736 * E.g., for M0=3 and basename=c, the expected names are c0, c1 and c2.
737 * The Z offset is expected to have consecutive names.
738 * E.g., for M0=3 and Z=zin, the expected z offset names are zin0, zin1 and zin2.
739 *
740 * @param[in] M0 The number of rows to store
741 * @param[in] N0 The size of each vector
742 * @param[in] DATA_TYPE The data type of the vectors
743 * @param[in] BASENAME The basename of the variables
744 * @param[in] PTR The base pointer
745 * @param[in] STRIDE_Y The stride value in y-axis direction
746 * @param[in] Z The offset in z-axis direction
747 * @{
748 */
Usama Arif0681e3b2019-04-25 14:28:07 +0100749#define STORE_BLOCK_STR(M0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) STORE_ROW_##M0(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z)
Usama Arif0681e3b2019-04-25 14:28:07 +0100750#define STORE_BLOCK(M0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) STORE_BLOCK_STR(M0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z)
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +0000751/** @} */ // end of group STORE_BLOCK
Usama Arif0681e3b2019-04-25 14:28:07 +0100752
SiCong Li3a501662020-06-26 10:02:06 +0100753/** Partially store a block of the given size STORE_M0xSTORE_N0
754 * @name STORE_BLOCK_PARTIAL
755 *
756 * @note The vector width @p N0 is also required for correct partial storing behaviour.
757 * @note in case @p STORE_N0 != 1, 2, 3, 4, 8, 16, extra vstore(s) will be invoked, thus incurring small performance penalty.
758 *
759 * The data to store is expected to have consecutive names for each row.
760 * E.g., for STORE_M0=3 and basename=c, the expected names are c0, c1 and c2.
761 * The Z offset is expected to have consecutive names.
762 * E.g., for STORE_M0=3 and Z=zin, the expected z offset names are zin0, zin1 and zin2.
763 *
764 * @param[in] STORE_M0 The number of rows to store. Supported: 1-16
765 * @param[in] STORE_N0 The lower number of elements of vectors to store. Supported: 1-16 and <= @p N0
766 * @param[in] N0 The size of each vector. Supported: 1, 2, 3, 4, 8, 16
767 * @param[in] DATA_TYPE The data type of the vectors
768 * @param[in] BASENAME The basename of the variables
769 * @param[in] PTR The base pointer
770 * @param[in] STRIDE_Y The stride value in y-axis direction
771 * @param[in] Z The offset in z-axis direction
772 * @{
773 */
774#define STORE_BLOCK_PARTIAL_STR(STORE_M0, STORE_N0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) STORE_ROW_PARTIAL_##STORE_M0(N0, STORE_N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z)
775#define STORE_BLOCK_PARTIAL(STORE_M0, STORE_N0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) STORE_BLOCK_PARTIAL_STR(STORE_M0, STORE_N0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z)
776/** Store a block that can be partial in both x and y dimensions
777 *
778 * @note in cases @p PARTIAL_STORE_N0 != 1, 2, 3, 4, 8, 16, extra vstore(s) will be invoked, thus incurring small performance penalty.
779 *
780 * The data to store is expected to have consecutive names for each row.
781 * E.g., for M0=3 and basename=c, the expected names are c0, c1 and c2.
782 * The Z offset is expected to have consecutive names.
783 * E.g., for M0=3 and Z=zin, the expected z offset names are zin0, zin1 and zin2.
784 *
785 * @param[in] M0 The number of rows to store, for non-partial blocks. Supported: 1-16
786 * @param[in] N0 The size of each vector, for non-partial blocks. Supported: 1, 2, 3, 4, 8, 16
787 * @param[in] DATA_TYPE The data type of the vectors
788 * @param[in] BASENAME The basename of the variables
789 * @param[in] PTR The base pointer
790 * @param[in] STRIDE_Y The stride value in y-axis direction
791 * @param[in] Z The offset in z-axis direction
792 * @param[in] PARTIAL_STORE_M0 The partial size in y, for partial blocks. Supported range: [1, @p M0)
793 * @param[in] PARTIAL_STORE_N0 The partial size in x, for partial blocks. Supported range: [1, @p N0)
SiCong Li3a501662020-06-26 10:02:06 +0100794 * @param[in] N Total number of columns. Used to detect if current block is at the boundary in x.
795 * @param[in] y Global id of current block in y. Used to detect if current block is at the boundary in y.
796 * @param[in] x Global id of current block in x. Used to detect if current block is at the boundary in x.
797 */
SiCong Li406a13f2020-07-15 12:09:58 +0100798#define STORE_BLOCK_PARTIAL_IN_X_AND_Y(M0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z, PARTIAL_STORE_M0, PARTIAL_STORE_N0, N, y, x) \
799 bool at_y_boundary = y == 0; \
800 bool at_x_boundary = (x + 1) * N0 >= N; \
801 if(!at_y_boundary && !at_x_boundary) \
802 { \
803 STORE_BLOCK_PARTIAL(M0, N0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z); \
804 } \
805 else if(at_y_boundary && !at_x_boundary) \
806 { \
807 STORE_BLOCK_PARTIAL(PARTIAL_STORE_M0, N0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z); \
808 } \
809 else if(!at_y_boundary && at_x_boundary) \
810 { \
811 STORE_BLOCK_PARTIAL(M0, PARTIAL_STORE_N0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z); \
812 } \
813 else \
814 { \
815 STORE_BLOCK_PARTIAL(PARTIAL_STORE_M0, PARTIAL_STORE_N0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z); \
SiCong Li3a501662020-06-26 10:02:06 +0100816 }
817/** Store a block that can only be partial in x but not y.
818 *
819 * @note in case @p N0 or @p PARTIAL_STORE_N0 != 1, 2, 3, 4, 8, 16, extra vstore(s) will be invoked, thus incurring small performance penalty.
820 *
821 * The data to store is expected to have consecutive names for each row.
822 * E.g., for M0=3 and basename=c, the expected names are c0, c1 and c2.
823 * The Z offset is expected to have consecutive names.
824 * E.g., for M0=3 and Z=zin, the expected z offset names are zin0, zin1 and zin2.
825 *
826 * @param[in] M0 The number of rows to store, for non-partial blocks. Supported: 1-16
827 * @param[in] N0 The size of each vector, for non-partial blocks. Supported: 1, 2, 3, 4, 8, 16
828 * @param[in] DATA_TYPE The data type of the vectors
829 * @param[in] BASENAME The basename of the variables
830 * @param[in] PTR The base pointer
831 * @param[in] STRIDE_Y The stride value in y-axis direction
832 * @param[in] Z The offset in z-axis direction
833 * @param[in] PARTIAL_STORE_N0 The partial size in x, for partial blocks. Supported range: [1, @p N0)
834 * @param[in] N Total number of columns. Used to detect if current block is at the boundary in x.
835 * @param[in] x Global id of current block in x. Used to detect if current block is at the boundary in x.
836 */
837#define STORE_BLOCK_PARTIAL_IN_X(M0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z, PARTIAL_STORE_N0, N, x) \
838 bool at_x_boundary = (x + 1) * N0 >= N; \
839 if(!at_x_boundary) \
840 { \
841 STORE_BLOCK_PARTIAL(M0, N0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z); \
842 } \
843 else \
844 { \
845 STORE_BLOCK_PARTIAL(M0, PARTIAL_STORE_N0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z); \
846 }
847/** Store a block that can only be partial in y but not x.
848 *
849 * @note in case @p N0 or @p PARTIAL_STORE_N0 != 1, 2, 3, 4, 8, 16, extra vstore(s) will be invoked, thus incurring small performance penalty.
850 *
851 * The data to store is expected to have consecutive names for each row.
852 * E.g., for M0=3 and basename=c, the expected names are c0, c1 and c2.
853 * The Z offset is expected to have consecutive names.
854 * E.g., for M0=3 and Z=zin, the expected z offset names are zin0, zin1 and zin2.
855 *
856 * @param[in] M0 The number of rows to store, for non-partial blocks. Supported: 1-16
857 * @param[in] N0 The size of each vector, for non-partial blocks. Supported: 1, 2, 3, 4, 8, 16
858 * @param[in] DATA_TYPE The data type of the vectors
859 * @param[in] BASENAME The basename of the variables
860 * @param[in] PTR The base pointer
861 * @param[in] STRIDE_Y The stride value in y-axis direction
862 * @param[in] Z The offset in z-axis direction
863 * @param[in] PARTIAL_STORE_M0 The partial size in y, for partial blocks. Supported range: [1, @p M0)
SiCong Li3a501662020-06-26 10:02:06 +0100864 * @param[in] y Global id of current block in y. Used to detect if current block is at the boundary in y.
865 */
SiCong Li406a13f2020-07-15 12:09:58 +0100866#define STORE_BLOCK_PARTIAL_IN_Y(M0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z, PARTIAL_STORE_M0, y) \
867 bool at_y_boundary = y == 0; \
868 if(!at_y_boundary) \
869 { \
870 STORE_BLOCK_PARTIAL(M0, N0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z); \
871 } \
872 else \
873 { \
874 STORE_BLOCK_PARTIAL(PARTIAL_STORE_M0, N0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z); \
SiCong Li3a501662020-06-26 10:02:06 +0100875 }
876/** @} */ // end of group STORE_BLOCK_PARTIAL
877
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +0000878/** Convert and store a block of the given size M0xN0
879 * @name CONVERT_STORE_BLOCK
880 *
881 * Supported cases are M0=1,2,3,...,16 and N0=2,3,4,8,16.
882 * The data to store is expected to have consecutive names for each row.
883 * E.g., for M0=3 and basename=c, the expected names are c0, c1 and c2.
884 * The Z offset is expected to have consecutive names.
885 * E.g., for M0=3 and Z=zin, the expected z offset names are zin0, zin1 and zin2.
886 *
887 * @param[in] M0 The number of rows to store
888 * @param[in] N0 The size of each vector
889 * @param[in] DATA_TYPE The data type of the vectors
890 * @param[in] BASENAME The basename of the variables
891 * @param[in] PTR The base pointer
892 * @param[in] STRIDE_Y The stride value in y-axis direction
893 * @param[in] Z The offset in z-axis direction
894 * @{
Gian Marco Iodice43a129e2019-05-14 10:14:08 +0100895 */
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +0000896#define CONVERT_STORE_BLOCK_STR(M0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) CONVERT_STORE_ROW_##M0(N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z)
Gian Marco Iodice43a129e2019-05-14 10:14:08 +0100897#define CONVERT_STORE_BLOCK(M0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z) CONVERT_STORE_BLOCK_STR(M0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z)
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +0000898/** @} */ // end of group CONVERT_STORE_BLOCK
Gian Marco Iodice43a129e2019-05-14 10:14:08 +0100899
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +0000900/** Scale the rows in the given variables (BASENAME0 to BASENAMEn-1)
901 * @name SCALE_ROW_n
902 *
903 * @param[in] DATA_TYPE The data type of the variables
904 * @param[in] BASENAME The basename of the variables
905 * @param[in] SCALE The scale factor
906 * @{
907 */
Usama Arif0681e3b2019-04-25 14:28:07 +0100908#define SCALE_ROW_1(DATA_TYPE, BASENAME, SCALE) \
Georgios Pinitasb0f342e2019-05-21 13:32:43 +0100909 BASENAME##0 *= (DATA_TYPE)SCALE;
Usama Arif0681e3b2019-04-25 14:28:07 +0100910
911#define SCALE_ROW_2(DATA_TYPE, BASENAME, SCALE) \
912 SCALE_ROW_1(DATA_TYPE, BASENAME, SCALE) \
Georgios Pinitasb0f342e2019-05-21 13:32:43 +0100913 BASENAME##1 *= (DATA_TYPE)SCALE;
Usama Arif0681e3b2019-04-25 14:28:07 +0100914
915#define SCALE_ROW_3(DATA_TYPE, BASENAME, SCALE) \
916 SCALE_ROW_2(DATA_TYPE, BASENAME, SCALE) \
Georgios Pinitasb0f342e2019-05-21 13:32:43 +0100917 BASENAME##2 *= (DATA_TYPE)SCALE;
Usama Arif0681e3b2019-04-25 14:28:07 +0100918
919#define SCALE_ROW_4(DATA_TYPE, BASENAME, SCALE) \
920 SCALE_ROW_3(DATA_TYPE, BASENAME, SCALE) \
Georgios Pinitasb0f342e2019-05-21 13:32:43 +0100921 BASENAME##3 *= (DATA_TYPE)SCALE;
Usama Arif0681e3b2019-04-25 14:28:07 +0100922
923#define SCALE_ROW_5(DATA_TYPE, BASENAME, SCALE) \
924 SCALE_ROW_4(DATA_TYPE, BASENAME, SCALE) \
Georgios Pinitasb0f342e2019-05-21 13:32:43 +0100925 BASENAME##4 *= (DATA_TYPE)SCALE;
Usama Arif0681e3b2019-04-25 14:28:07 +0100926
927#define SCALE_ROW_6(DATA_TYPE, BASENAME, SCALE) \
928 SCALE_ROW_5(DATA_TYPE, BASENAME, SCALE) \
Georgios Pinitasb0f342e2019-05-21 13:32:43 +0100929 BASENAME##5 *= (DATA_TYPE)SCALE;
Usama Arif0681e3b2019-04-25 14:28:07 +0100930
931#define SCALE_ROW_7(DATA_TYPE, BASENAME, SCALE) \
932 SCALE_ROW_6(DATA_TYPE, BASENAME, SCALE) \
Georgios Pinitasb0f342e2019-05-21 13:32:43 +0100933 BASENAME##6 *= (DATA_TYPE)SCALE;
Usama Arif0681e3b2019-04-25 14:28:07 +0100934
935#define SCALE_ROW_8(DATA_TYPE, BASENAME, SCALE) \
936 SCALE_ROW_7(DATA_TYPE, BASENAME, SCALE) \
Georgios Pinitasb0f342e2019-05-21 13:32:43 +0100937 BASENAME##7 *= (DATA_TYPE)SCALE;
Usama Arif0681e3b2019-04-25 14:28:07 +0100938
939#define SCALE_ROW_9(DATA_TYPE, BASENAME, SCALE) \
940 SCALE_ROW_8(DATA_TYPE, BASENAME, SCALE) \
Georgios Pinitasb0f342e2019-05-21 13:32:43 +0100941 BASENAME##8 *= (DATA_TYPE)SCALE;
Usama Arif0681e3b2019-04-25 14:28:07 +0100942
943#define SCALE_ROW_10(DATA_TYPE, BASENAME, SCALE) \
944 SCALE_ROW_9(DATA_TYPE, BASENAME, SCALE) \
Georgios Pinitasb0f342e2019-05-21 13:32:43 +0100945 BASENAME##9 *= (DATA_TYPE)SCALE;
Usama Arif0681e3b2019-04-25 14:28:07 +0100946
947#define SCALE_ROW_11(DATA_TYPE, BASENAME, SCALE) \
948 SCALE_ROW_10(DATA_TYPE, BASENAME, SCALE) \
Georgios Pinitasb0f342e2019-05-21 13:32:43 +0100949 BASENAME##A *= (DATA_TYPE)SCALE;
Usama Arif0681e3b2019-04-25 14:28:07 +0100950
951#define SCALE_ROW_12(DATA_TYPE, BASENAME, SCALE) \
952 SCALE_ROW_11(DATA_TYPE, BASENAME, SCALE) \
Georgios Pinitasb0f342e2019-05-21 13:32:43 +0100953 BASENAME##B *= (DATA_TYPE)SCALE;
Usama Arif0681e3b2019-04-25 14:28:07 +0100954
955#define SCALE_ROW_13(DATA_TYPE, BASENAME, SCALE) \
956 SCALE_ROW_12(DATA_TYPE, BASENAME, SCALE) \
Georgios Pinitasb0f342e2019-05-21 13:32:43 +0100957 BASENAME##C *= (DATA_TYPE)SCALE;
Usama Arif0681e3b2019-04-25 14:28:07 +0100958
959#define SCALE_ROW_14(DATA_TYPE, BASENAME, SCALE) \
960 SCALE_ROW_13(DATA_TYPE, BASENAME, SCALE) \
Georgios Pinitasb0f342e2019-05-21 13:32:43 +0100961 BASENAME##D *= (DATA_TYPE)SCALE;
Usama Arif0681e3b2019-04-25 14:28:07 +0100962
963#define SCALE_ROW_15(DATA_TYPE, BASENAME, SCALE) \
964 SCALE_ROW_14(DATA_TYPE, BASENAME, SCALE) \
Georgios Pinitasb0f342e2019-05-21 13:32:43 +0100965 BASENAME##E *= (DATA_TYPE)SCALE;
Usama Arif0681e3b2019-04-25 14:28:07 +0100966
967#define SCALE_ROW_16(DATA_TYPE, BASENAME, SCALE) \
968 SCALE_ROW_15(DATA_TYPE, BASENAME, SCALE) \
Georgios Pinitasb0f342e2019-05-21 13:32:43 +0100969 BASENAME##F *= (DATA_TYPE)SCALE;
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +0000970/** @} */ // end of group SCALE_ROW_n
Usama Arif0681e3b2019-04-25 14:28:07 +0100971
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +0000972/** Scale elements stored in a block (BASENAME)
973 * @name SCALE_BLOCK
974 *
975 * Supported cases are N=1,2,3,...,16
976 *
977 * @param[in] N The number of rows in the block
978 * @param[in] DATA_TYPE The data type of the block
979 * @param[in] BASENAME The basename of the block
980 * @param[in] SCALE The scale factor
981 * @{
Usama Arif0681e3b2019-04-25 14:28:07 +0100982 */
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +0000983#define SCALE_BLOCK_STR(N, DATA_TYPE, BASENAME, SCALE) SCALE_ROW_##N(DATA_TYPE, BASENAME, SCALE)
Usama Arif0681e3b2019-04-25 14:28:07 +0100984#define SCALE_BLOCK(N, DATA_TYPE, BASENAME, SCALE) SCALE_BLOCK_STR(N, DATA_TYPE, BASENAME, SCALE)
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +0000985/** @} */ // end of group SCALE_BLOCK
Gian Marco Iodice43a129e2019-05-14 10:14:08 +0100986
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +0000987/** Create a new vector containing the values at the given index for a set of given vectors
988 * @name COLUMN_VECTORn
989 *
990 * @param[in] IDX_COL The index value
991 * @param[in] BASENAME The basename of the destination vectors
992 * @param[in] X The basename of the source vectors
Michele Di Giorgiof9179d32019-11-27 16:17:30 +0000993 * @param[in] TYPE The data type of the destination vectors
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +0000994 * @{
995 */
Michele Di Giorgiof9179d32019-11-27 16:17:30 +0000996#define COLUMN_VECTOR1(IDX_COL, BASENAME, X, TYPE) \
997 TYPE BASENAME##IDX_COL = (TYPE)((X##0).s##IDX_COL);
998#define COLUMN_VECTOR2(IDX_COL, BASENAME, X, TYPE) \
999 VEC_DATA_TYPE(TYPE, 2) \
1000 BASENAME##IDX_COL = (VEC_DATA_TYPE(TYPE, 2))((X##0).s##IDX_COL, (X##1).s##IDX_COL);
1001#define COLUMN_VECTOR3(IDX_COL, BASENAME, X, TYPE) \
1002 VEC_DATA_TYPE(TYPE, 3) \
1003 BASENAME##IDX_COL = (VEC_DATA_TYPE(TYPE, 3))((X##0).s##IDX_COL, (X##1).s##IDX_COL, (X##2).s##IDX_COL);
1004#define COLUMN_VECTOR4(IDX_COL, BASENAME, X, TYPE) \
1005 VEC_DATA_TYPE(TYPE, 4) \
1006 BASENAME##IDX_COL = (VEC_DATA_TYPE(TYPE, 4))((X##0).s##IDX_COL, (X##1).s##IDX_COL, (X##2).s##IDX_COL, (X##3).s##IDX_COL);
1007#define COLUMN_VECTOR8(IDX_COL, BASENAME, X, TYPE) \
1008 VEC_DATA_TYPE(TYPE, 8) \
1009 BASENAME##IDX_COL = (VEC_DATA_TYPE(TYPE, 8))((X##0).s##IDX_COL, (X##1).s##IDX_COL, (X##2).s##IDX_COL, (X##3).s##IDX_COL, (X##4).s##IDX_COL, (X##5).s##IDX_COL, (X##6).s##IDX_COL, (X##7).s##IDX_COL);
1010#define COLUMN_VECTOR16(IDX_COL, BASENAME, X, TYPE) \
1011 VEC_DATA_TYPE(TYPE, 16) \
1012 BASENAME##IDX_COL = (VEC_DATA_TYPE(TYPE, 16))((X##0).s##IDX_COL, (X##1).s##IDX_COL, (X##2).s##IDX_COL, (X##3).s##IDX_COL, (X##4).s##IDX_COL, (X##5).s##IDX_COL, (X##6).s##IDX_COL, (X##7).s##IDX_COL, (X##8).s##IDX_COL, (X##9).s##IDX_COL, (X##A).s##IDX_COL, (X##B).s##IDX_COL, (X##C).s##IDX_COL, (X##D).s##IDX_COL, (X##E).s##IDX_COL, (X##F).s##IDX_COL);
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001013/** @} */ // end of group COLUMN_VECTORn
Gian Marco Iodice43a129e2019-05-14 10:14:08 +01001014
Gian Marco Iodice061eefd2020-04-23 13:40:00 +01001015/** Create a new vector containing the values at the given index. Utility macros for transposing a colum-vector
1016 * @name COLUMN_VECTOR_SCALARn
1017 *
1018 * @param[in] IDX_COL The index value
1019 * @param[in] BASENAME The basename of the destination vectors
1020 * @param[in] X The basename of the source vectors
1021 * @param[in] TYPE The data type of the destination vectors
1022 * @{
1023 */
1024#define COLUMN_VECTOR_SCALAR1(IDX_COL, BASENAME, X, TYPE) \
1025 TYPE BASENAME##IDX_COL = (TYPE)((X##0));
1026#define COLUMN_VECTOR_SCALAR2(IDX_COL, BASENAME, X, TYPE) \
1027 VEC_DATA_TYPE(TYPE, 2) \
1028 BASENAME##IDX_COL = (VEC_DATA_TYPE(TYPE, 2))((X##0), (X##1));
1029#define COLUMN_VECTOR_SCALAR3(IDX_COL, BASENAME, X, TYPE) \
1030 VEC_DATA_TYPE(TYPE, 3) \
1031 BASENAME##IDX_COL = (VEC_DATA_TYPE(TYPE, 3))((X##0), (X##1), (X##2));
1032#define COLUMN_VECTOR_SCALAR4(IDX_COL, BASENAME, X, TYPE) \
1033 VEC_DATA_TYPE(TYPE, 4) \
1034 BASENAME##IDX_COL = (VEC_DATA_TYPE(TYPE, 4))((X##0), (X##1), (X##2), (X##3));
1035#define COLUMN_VECTOR_SCALAR8(IDX_COL, BASENAME, X, TYPE) \
1036 VEC_DATA_TYPE(TYPE, 8) \
1037 BASENAME##IDX_COL = (VEC_DATA_TYPE(TYPE, 8))((X##0), (X##1), (X##2), (X##3), (X##4), (X##5), (X##6), (X##7));
1038#define COLUMN_VECTOR_SCALAR16(IDX_COL, BASENAME, X, TYPE) \
1039 VEC_DATA_TYPE(TYPE, 16) \
1040 BASENAME##IDX_COL = (VEC_DATA_TYPE(TYPE, 16))((X##0), (X##1), (X##2), (X##3), (X##4), (X##5), (X##6), (X##7), (X##8), (X##9), (X##A), (X##B), (X##C), (X##D), (X##E), (X##F));
1041/** @} */ // end of group COLUMN_VECTORn
1042
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001043/** Create transposed vectors of the given vectors
1044 * @name TRANSPOSE_K0Xn
1045 *
1046 * @param[in] K0 The size of the source vectors
1047 * @param[in] BASENAME The basename of transposed vectors
1048 * @param[in] B The basename of source vectors for transposition
Michele Di Giorgiof9179d32019-11-27 16:17:30 +00001049 * @param[in] TYPE The data type of the transposed vectors
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001050 * @{
1051 */
Michele Di Giorgiof9179d32019-11-27 16:17:30 +00001052#define TRANSPOSE_K0X1(K0, BASENAME, B, TYPE) \
Gian Marco Iodice061eefd2020-04-23 13:40:00 +01001053 COLUMN_VECTOR_SCALAR(K0, 0, BASENAME, B, TYPE);
Michele Di Giorgiof9179d32019-11-27 16:17:30 +00001054#define TRANSPOSE_K0X2(K0, BASENAME, B, TYPE) \
Gian Marco Iodice061eefd2020-04-23 13:40:00 +01001055 COLUMN_VECTOR(K0, 0, BASENAME, B, TYPE); \
Michele Di Giorgiof9179d32019-11-27 16:17:30 +00001056 COLUMN_VECTOR(K0, 1, BASENAME, B, TYPE);
1057#define TRANSPOSE_K0X3(K0, BASENAME, B, TYPE) \
1058 TRANSPOSE_K0X2(K0, BASENAME, B, TYPE); \
1059 COLUMN_VECTOR(K0, 2, BASENAME, B, TYPE);
1060#define TRANSPOSE_K0X4(K0, BASENAME, B, TYPE) \
1061 TRANSPOSE_K0X3(K0, BASENAME, B, TYPE); \
1062 COLUMN_VECTOR(K0, 3, BASENAME, B, TYPE);
1063#define TRANSPOSE_K0X8(K0, BASENAME, B, TYPE) \
1064 TRANSPOSE_K0X4(K0, BASENAME, B, TYPE); \
1065 COLUMN_VECTOR(K0, 4, BASENAME, B, TYPE); \
1066 COLUMN_VECTOR(K0, 5, BASENAME, B, TYPE); \
1067 COLUMN_VECTOR(K0, 6, BASENAME, B, TYPE); \
1068 COLUMN_VECTOR(K0, 7, BASENAME, B, TYPE);
1069#define TRANSPOSE_K0X16(K0, BASENAME, B, TYPE) \
1070 TRANSPOSE_K0X8(K0, BASENAME, B, TYPE); \
1071 COLUMN_VECTOR(K0, 8, BASENAME, B, TYPE); \
1072 COLUMN_VECTOR(K0, 9, BASENAME, B, TYPE); \
1073 COLUMN_VECTOR(K0, A, BASENAME, B, TYPE); \
1074 COLUMN_VECTOR(K0, B, BASENAME, B, TYPE); \
1075 COLUMN_VECTOR(K0, C, BASENAME, B, TYPE); \
1076 COLUMN_VECTOR(K0, D, BASENAME, B, TYPE); \
1077 COLUMN_VECTOR(K0, E, BASENAME, B, TYPE); \
1078 COLUMN_VECTOR(K0, F, BASENAME, B, TYPE);
Gian Marco Iodice43a129e2019-05-14 10:14:08 +01001079
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001080/** @} */ // end of group TRANSPOSE_K0Xn
1081
1082/** Create column vectors to contain the values at the given index for a set of given vectors
1083 *
1084 * @param[in] K0 The number of source vectors
1085 * @param[in] IDX_COL The index value
1086 * @param[in] BASENAME The basename of the destination vectors
1087 * @param[in] B The basename of the source vectors
Michele Di Giorgiof9179d32019-11-27 16:17:30 +00001088 * @param[in] TYPE The data type of the destination vectors
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001089 */
Michele Di Giorgiof9179d32019-11-27 16:17:30 +00001090#define COLUMN_VECTOR(K0, IDX_COL, BASENAME, B, TYPE) \
1091 CONCAT(COLUMN_VECTOR, K0) \
1092 (IDX_COL, BASENAME, B, TYPE);
Gian Marco Iodice43a129e2019-05-14 10:14:08 +01001093
Gian Marco Iodice061eefd2020-04-23 13:40:00 +01001094/** Create column vectors to contain the values at the given index. Utility macro for transposing a column-vector
1095 *
1096 * @param[in] K0 The number of source vectors
1097 * @param[in] IDX_COL The index value
1098 * @param[in] BASENAME The basename of the destination vectors
1099 * @param[in] B The basename of the source vectors
1100 * @param[in] TYPE The data type of the destination vectors
1101 */
1102#define COLUMN_VECTOR_SCALAR(K0, IDX_COL, BASENAME, B, TYPE) \
1103 CONCAT(COLUMN_VECTOR_SCALAR, K0) \
1104 (IDX_COL, BASENAME, B, TYPE);
1105
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001106/** Create transposed vectors form the given source vectors
1107 *
1108 * @param[in] K0 The size of source vectors
1109 * @param[in] N0 The number of source vectors
1110 * @param[in] BASENAME The basename of transposed vectors
1111 * @param[in] B The basename of source vectors for transposition
Michele Di Giorgiof9179d32019-11-27 16:17:30 +00001112 * @param[in] TYPE The data type of the transposed vectors
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001113 *
1114 */
Michele Di Giorgiof9179d32019-11-27 16:17:30 +00001115#define TRANSPOSE_K0XN0(K0, N0, BASENAME, B, TYPE) \
1116 CONCAT(TRANSPOSE_K0X, N0) \
1117 (K0, BASENAME, B, TYPE);
Georgios Pinitasb0f342e2019-05-21 13:32:43 +01001118
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001119/** Add the variables (BIAS0 to BIASn-1) to the others (BASENAME0 to BASENAMEn-1)
1120 * @name ADD_ROW_n
1121 *
1122 * @param[in] BASENAME The basename of the destination variables
1123 * @param[in] BIAS The basename of the added variables
1124 * @{
1125 */
Georgios Pinitasb0f342e2019-05-21 13:32:43 +01001126#define ADD_ROW_1(BASENAME, BIAS) \
1127 BASENAME##0 += BIAS##0;
1128
1129#define ADD_ROW_2(BASENAME, BIAS) \
1130 ADD_ROW_1(BASENAME, BIAS) \
1131 BASENAME##1 += BIAS##1;
1132
1133#define ADD_ROW_3(BASENAME, BIAS) \
1134 ADD_ROW_2(BASENAME, BIAS) \
1135 BASENAME##2 += BIAS##2;
1136
1137#define ADD_ROW_4(BASENAME, BIAS) \
1138 ADD_ROW_3(BASENAME, BIAS) \
1139 BASENAME##3 += BIAS##3;
1140
1141#define ADD_ROW_5(BASENAME, BIAS) \
1142 ADD_ROW_4(BASENAME, BIAS) \
1143 BASENAME##4 += BIAS##4;
1144
1145#define ADD_ROW_6(BASENAME, BIAS) \
1146 ADD_ROW_5(BASENAME, BIAS) \
1147 BASENAME##5 += BIAS##5;
1148
1149#define ADD_ROW_7(BASENAME, BIAS) \
1150 ADD_ROW_6(BASENAME, BIAS) \
1151 BASENAME##6 += BIAS##6;
1152
1153#define ADD_ROW_8(BASENAME, BIAS) \
1154 ADD_ROW_7(BASENAME, BIAS) \
1155 BASENAME##7 += BIAS##7;
1156
1157#define ADD_ROW_9(BASENAME, BIAS) \
1158 ADD_ROW_8(BASENAME, BIAS) \
1159 BASENAME##8 += BIAS##8;
1160
1161#define ADD_ROW_10(BASENAME, BIAS) \
1162 ADD_ROW_9(BASENAME, BIAS) \
1163 BASENAME##9 += BIAS##9;
1164
1165#define ADD_ROW_11(BASENAME, BIAS) \
1166 ADD_ROW_10(BASENAME, BIAS) \
1167 BASENAME##A += BIAS##A;
1168
1169#define ADD_ROW_12(BASENAME, BIAS) \
1170 ADD_ROW_11(BASENAME, BIAS) \
1171 BASENAME##B += BIAS##B;
1172
1173#define ADD_ROW_13(BASENAME, BIAS) \
1174 ADD_ROW_12(BASENAME, BIAS) \
1175 BASENAME##C += BIAS##C;
1176
1177#define ADD_ROW_14(BASENAME, BIAS) \
1178 ADD_ROW_13(BASENAME, BIAS) \
1179 BASENAME##D += BIAS##D;
1180
1181#define ADD_ROW_15(BASENAME, BIAS) \
1182 ADD_ROW_14(BASENAME, BIAS) \
1183 BASENAME##E += BIAS##E;
1184
1185#define ADD_ROW_16(BASENAME, BIAS) \
1186 ADD_ROW_15(BASENAME, BIAS) \
1187 BASENAME##F += BIAS##F;
1188
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001189/** @} */ // end of group ADD_ROW_n
Georgios Pinitasb0f342e2019-05-21 13:32:43 +01001190
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001191/** Add the block (BIAS) to another block (BASENAME)
1192 * @name ADD_BLOCK
1193 *
1194 * Supported cases are N=1,2,3,...,16
1195 *
1196 * @param[in] N The number of vectors in the block
1197 * @param[in] BASENAME The basename of the destination variables
1198 * @param[in] BIAS The basename of the added variables
1199 * @{
1200 */
1201#define ADD_BLOCK_STR(N, BASENAME, BIAS) ADD_ROW_##N(BASENAME, BIAS)
1202#define ADD_BLOCK(N, BASENAME, BIAS) ADD_BLOCK_STR(N, BASENAME, BIAS)
1203/** @} */ // end of group ADD_BLOCK
1204
1205/** Broadcast (add single value) to the each element of the destination variables
1206 * @name ADD_ROW_BROADCAST_n
1207 *
1208 * @param[in] BASENAME The basename of the destination variables
1209 * @param[in] BIAS The variable containing the value to add
1210 * @{
1211 */
Georgios Pinitasb0f342e2019-05-21 13:32:43 +01001212#define ADD_ROW_BROADCAST_1(BASENAME, BIAS) \
1213 BASENAME##0 += BIAS;
1214
1215#define ADD_ROW_BROADCAST_2(BASENAME, BIAS) \
1216 ADD_ROW_BROADCAST_1(BASENAME, BIAS) \
1217 BASENAME##1 += BIAS;
1218
1219#define ADD_ROW_BROADCAST_3(BASENAME, BIAS) \
1220 ADD_ROW_BROADCAST_2(BASENAME, BIAS) \
1221 BASENAME##2 += BIAS;
1222
1223#define ADD_ROW_BROADCAST_4(BASENAME, BIAS) \
1224 ADD_ROW_BROADCAST_3(BASENAME, BIAS) \
1225 BASENAME##3 += BIAS;
1226
1227#define ADD_ROW_BROADCAST_5(BASENAME, BIAS) \
1228 ADD_ROW_BROADCAST_4(BASENAME, BIAS) \
1229 BASENAME##4 += BIAS;
1230
1231#define ADD_ROW_BROADCAST_6(BASENAME, BIAS) \
1232 ADD_ROW_BROADCAST_5(BASENAME, BIAS) \
1233 BASENAME##5 += BIAS;
1234
1235#define ADD_ROW_BROADCAST_7(BASENAME, BIAS) \
1236 ADD_ROW_BROADCAST_6(BASENAME, BIAS) \
1237 BASENAME##6 += BIAS;
1238
1239#define ADD_ROW_BROADCAST_8(BASENAME, BIAS) \
1240 ADD_ROW_BROADCAST_7(BASENAME, BIAS) \
1241 BASENAME##7 += BIAS;
1242
1243#define ADD_ROW_BROADCAST_9(BASENAME, BIAS) \
1244 ADD_ROW_BROADCAST_8(BASENAME, BIAS) \
1245 BASENAME##8 += BIAS;
1246
1247#define ADD_ROW_BROADCAST_10(BASENAME, BIAS) \
1248 ADD_ROW_BROADCAST_9(BASENAME, BIAS) \
1249 BASENAME##9 += BIAS;
1250
1251#define ADD_ROW_BROADCAST_11(BASENAME, BIAS) \
1252 ADD_ROW_BROADCAST_10(BASENAME, BIAS) \
1253 BASENAME##A += BIAS;
1254
1255#define ADD_ROW_BROADCAST_12(BASENAME, BIAS) \
1256 ADD_ROW_BROADCAST_11(BASENAME, BIAS) \
1257 BASENAME##B += BIAS;
1258
1259#define ADD_ROW_BROADCAST_13(BASENAME, BIAS) \
1260 ADD_ROW_BROADCAST_12(BASENAME, BIAS) \
1261 BASENAME##C += BIAS;
1262
1263#define ADD_ROW_BROADCAST_14(BASENAME, BIAS) \
1264 ADD_ROW_BROADCAST_13(BASENAME, BIAS) \
1265 BASENAME##D += BIAS;
1266
1267#define ADD_ROW_BROADCAST_15(BASENAME, BIAS) \
1268 ADD_ROW_BROADCAST_14(BASENAME, BIAS) \
1269 BASENAME##E += BIAS;
1270
1271#define ADD_ROW_BROADCAST_16(BASENAME, BIAS) \
1272 ADD_ROW_BROADCAST_15(BASENAME, BIAS) \
1273 BASENAME##F += BIAS;
1274
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001275/** Broadcast (add a value) to the each element of the destination block (BASENAME)
1276 * @name ADD_BLOCK_BROADCAST
1277 *
1278 * Supported cases are N=1,2,3,...,16.
1279 *
1280 * @param[in] N The number of vectors in the block
1281 * @param[in] BASENAME The basename of the destination variables
1282 * @param[in] BIAS The variable containing the value to add
1283 * @{
Georgios Pinitasb0f342e2019-05-21 13:32:43 +01001284 */
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001285#define ADD_BLOCK_BROADCAST_STR(N, BASENAME, BIAS) ADD_ROW_BROADCAST_##N(BASENAME, BIAS)
Georgios Pinitasb0f342e2019-05-21 13:32:43 +01001286#define ADD_BLOCK_BROADCAST(N, BASENAME, BIAS) ADD_BLOCK_BROADCAST_STR(N, BASENAME, BIAS)
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001287/** @} */ // end of group ADD_BLOCK_BROADCAST
Gian Marco Iodiceca1f4602019-07-16 15:46:48 +01001288
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001289/** Apply activation to the given variables
1290 * @name ACTIVATION_ROW_n
1291 *
1292 * @param[in] ACTIVATION_TYPE The type of the activation
1293 * @param[in] DATA_TYPE The data type of the vectors
1294 * @param[in] BASENAME The basename of the variables
1295 * @param[in] A_VAL Additional value required by the activation
1296 * @param[in] B_VAL Additional value required by the activation
1297 * @{
1298 */
Gian Marco Iodiceca1f4602019-07-16 15:46:48 +01001299#define ACTIVATION_ROW_1(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1300 BASENAME##0 = ACTIVATION(ACTIVATION_TYPE, DATA_TYPE, BASENAME##0, A_VAL, B_VAL);
1301
1302#define ACTIVATION_ROW_2(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1303 ACTIVATION_ROW_1(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1304 BASENAME##1 = ACTIVATION(ACTIVATION_TYPE, DATA_TYPE, BASENAME##1, A_VAL, B_VAL);
1305
1306#define ACTIVATION_ROW_3(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1307 ACTIVATION_ROW_2(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1308 BASENAME##2 = ACTIVATION(ACTIVATION_TYPE, DATA_TYPE, BASENAME##2, A_VAL, B_VAL);
1309
1310#define ACTIVATION_ROW_4(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1311 ACTIVATION_ROW_3(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1312 BASENAME##3 = ACTIVATION(ACTIVATION_TYPE, DATA_TYPE, BASENAME##3, A_VAL, B_VAL);
1313
1314#define ACTIVATION_ROW_5(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1315 ACTIVATION_ROW_4(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1316 BASENAME##4 = ACTIVATION(ACTIVATION_TYPE, DATA_TYPE, BASENAME##4, A_VAL, B_VAL);
1317
1318#define ACTIVATION_ROW_6(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1319 ACTIVATION_ROW_5(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1320 BASENAME##5 = ACTIVATION(ACTIVATION_TYPE, DATA_TYPE, BASENAME##5, A_VAL, B_VAL);
1321
1322#define ACTIVATION_ROW_7(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1323 ACTIVATION_ROW_6(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1324 BASENAME##6 = ACTIVATION(ACTIVATION_TYPE, DATA_TYPE, BASENAME##6, A_VAL, B_VAL);
1325
1326#define ACTIVATION_ROW_8(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1327 ACTIVATION_ROW_7(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1328 BASENAME##7 = ACTIVATION(ACTIVATION_TYPE, DATA_TYPE, BASENAME##7, A_VAL, B_VAL);
1329
1330#define ACTIVATION_ROW_9(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1331 ACTIVATION_ROW_8(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1332 BASENAME##8 = ACTIVATION(ACTIVATION_TYPE, DATA_TYPE, BASENAME##8, A_VAL, B_VAL);
1333
1334#define ACTIVATION_ROW_10(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1335 ACTIVATION_ROW_9(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1336 BASENAME##9 = ACTIVATION(ACTIVATION_TYPE, DATA_TYPE, BASENAME##9, A_VAL, B_VAL);
1337
1338#define ACTIVATION_ROW_11(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1339 ACTIVATION_ROW_10(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1340 BASENAME##A = ACTIVATION(ACTIVATION_TYPE, DATA_TYPE, BASENAME##A, A_VAL, B_VAL);
1341
1342#define ACTIVATION_ROW_12(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1343 ACTIVATION_ROW_11(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1344 BASENAME##B = ACTIVATION(ACTIVATION_TYPE, DATA_TYPE, BASENAME##B, A_VAL, B_VAL);
1345
1346#define ACTIVATION_ROW_13(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1347 ACTIVATION_ROW_12(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1348 BASENAME##C = ACTIVATION(ACTIVATION_TYPE, DATA_TYPE, BASENAME##C, A_VAL, B_VAL);
1349
1350#define ACTIVATION_ROW_14(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1351 ACTIVATION_ROW_13(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1352 BASENAME##D = ACTIVATION(ACTIVATION_TYPE, DATA_TYPE, BASENAME##D, A_VAL, B_VAL);
1353
1354#define ACTIVATION_ROW_15(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1355 ACTIVATION_ROW_14(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1356 BASENAME##E = ACTIVATION(ACTIVATION_TYPE, DATA_TYPE, BASENAME##E, A_VAL, B_VAL);
1357
1358#define ACTIVATION_ROW_16(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1359 ACTIVATION_ROW_15(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) \
1360 BASENAME##F = ACTIVATION(ACTIVATION_TYPE, DATA_TYPE, BASENAME##F, A_VAL, B_VAL);
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001361/** @} */ // end of group ACTIVATION_ROW_n
Gian Marco Iodiceca1f4602019-07-16 15:46:48 +01001362
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001363/** Apply activation to a block (BASENAME)
1364 * @name ACTIVATION_BLOCK
1365 *
1366 * Supported cases are N=1,2,3,...,16.
1367 *
1368 * @param[in] N The number of vectors in the block
1369 * @param[in] ACTIVATION_TYPE The type of the activation
1370 * @param[in] DATA_TYPE The data type of the vectors
1371 * @param[in] BASENAME The basename of the variables
1372 * @param[in] A_VAL Additional value required by the activation
1373 * @param[in] B_VAL Additional value required by the activation
1374 * @{
Gian Marco Iodiceca1f4602019-07-16 15:46:48 +01001375 */
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001376#define ACTIVATION_BLOCK_STR(N, ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) ACTIVATION_ROW_##N(ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL)
Gian Marco Iodice0c17aa22019-09-27 09:23:15 +01001377#define ACTIVATION_BLOCK(N, ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL) ACTIVATION_BLOCK_STR(N, ACTIVATION_TYPE, DATA_TYPE, BASENAME, A_VAL, B_VAL)
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001378/** @} */ // end of group ACTIVATION_BLOCK
Gian Marco Iodice0c17aa22019-09-27 09:23:15 +01001379
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001380/** Apply convert_<data_type> to the given variables
1381 * @name CONVERT_ROW_n
1382 *
1383 * @param[in] N The size of the vectors
1384 * @param[in] DATA_TYPE The data type of the vectors
1385 * @param[in] BASENAME_SRC The basename of the source variables
1386 * @param[in] BASENAME_DST The basename of the destination variables
1387 */
Gian Marco Iodice0c17aa22019-09-27 09:23:15 +01001388#define CONVERT_ROW_1(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1389 VEC_DATA_TYPE(DATA_TYPE, N) \
1390 BASENAME_DST##0 = CONVERT(BASENAME_SRC##0, VEC_DATA_TYPE(DATA_TYPE, N));
1391
1392#define CONVERT_ROW_2(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1393 CONVERT_ROW_1(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1394 VEC_DATA_TYPE(DATA_TYPE, N) \
1395 BASENAME_DST##1 = CONVERT(BASENAME_SRC##1, VEC_DATA_TYPE(DATA_TYPE, N));
1396
1397#define CONVERT_ROW_3(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1398 CONVERT_ROW_2(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1399 VEC_DATA_TYPE(DATA_TYPE, N) \
1400 BASENAME_DST##2 = CONVERT(BASENAME_SRC##2, VEC_DATA_TYPE(DATA_TYPE, N));
1401
1402#define CONVERT_ROW_4(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1403 CONVERT_ROW_3(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1404 VEC_DATA_TYPE(DATA_TYPE, N) \
1405 BASENAME_DST##3 = CONVERT(BASENAME_SRC##3, VEC_DATA_TYPE(DATA_TYPE, N));
1406
1407#define CONVERT_ROW_5(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1408 CONVERT_ROW_4(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1409 VEC_DATA_TYPE(DATA_TYPE, N) \
1410 BASENAME_DST##4 = CONVERT(BASENAME_SRC##4, VEC_DATA_TYPE(DATA_TYPE, N));
1411
1412#define CONVERT_ROW_6(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1413 CONVERT_ROW_5(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1414 VEC_DATA_TYPE(DATA_TYPE, N) \
1415 BASENAME_DST##5 = CONVERT(BASENAME_SRC##5, VEC_DATA_TYPE(DATA_TYPE, N));
1416
1417#define CONVERT_ROW_7(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1418 CONVERT_ROW_6(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1419 VEC_DATA_TYPE(DATA_TYPE, N) \
1420 BASENAME_DST##6 = CONVERT(BASENAME_SRC##6, VEC_DATA_TYPE(DATA_TYPE, N));
1421
1422#define CONVERT_ROW_8(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1423 CONVERT_ROW_7(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1424 VEC_DATA_TYPE(DATA_TYPE, N) \
1425 BASENAME_DST##7 = CONVERT(BASENAME_SRC##7, VEC_DATA_TYPE(DATA_TYPE, N));
1426
1427#define CONVERT_ROW_9(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1428 CONVERT_ROW_8(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1429 VEC_DATA_TYPE(DATA_TYPE, N) \
1430 BASENAME_DST##8 = CONVERT(BASENAME_SRC##8, VEC_DATA_TYPE(DATA_TYPE, N));
1431
1432#define CONVERT_ROW_10(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1433 CONVERT_ROW_9(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1434 VEC_DATA_TYPE(DATA_TYPE, N) \
1435 BASENAME_DST##9 = CONVERT(BASENAME_SRC##9, VEC_DATA_TYPE(DATA_TYPE, N));
1436
1437#define CONVERT_ROW_11(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1438 CONVERT_ROW_10(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1439 VEC_DATA_TYPE(DATA_TYPE, N) \
1440 BASENAME_DST##A = CONVERT(BASENAME_SRC##A, VEC_DATA_TYPE(DATA_TYPE, N));
1441
1442#define CONVERT_ROW_12(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1443 CONVERT_ROW_11(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1444 VEC_DATA_TYPE(DATA_TYPE, N) \
1445 BASENAME_DST##B = CONVERT(BASENAME_SRC##B, VEC_DATA_TYPE(DATA_TYPE, N));
1446
1447#define CONVERT_ROW_13(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1448 CONVERT_ROW_12(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1449 VEC_DATA_TYPE(DATA_TYPE, N) \
1450 BASENAME_DST##C = CONVERT(BASENAME_SRC##C, VEC_DATA_TYPE(DATA_TYPE, N));
1451
1452#define CONVERT_ROW_14(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1453 CONVERT_ROW_13(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1454 VEC_DATA_TYPE(DATA_TYPE, N) \
1455 BASENAME_DST##D = CONVERT(BASENAME_SRC##D, VEC_DATA_TYPE(DATA_TYPE, N));
1456
1457#define CONVERT_ROW_15(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1458 CONVERT_ROW_14(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1459 VEC_DATA_TYPE(DATA_TYPE, N) \
1460 BASENAME_DST##E = CONVERT(BASENAME_SRC##E, VEC_DATA_TYPE(DATA_TYPE, N));
1461
1462#define CONVERT_ROW_16(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1463 CONVERT_ROW_15(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) \
1464 VEC_DATA_TYPE(DATA_TYPE, N) \
1465 BASENAME_DST##F = CONVERT(BASENAME_SRC##F, VEC_DATA_TYPE(DATA_TYPE, N));
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001466/** @} */ // end of group CONVERT_ROW_n
Gian Marco Iodice0c17aa22019-09-27 09:23:15 +01001467
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001468/** Apply convert_<data_type> to a block (BASENAME_SRC) and save to another block (BASENAME_DST)
1469 * @name CONVERT_BLOCK
1470 *
1471 * Supported cases N=1,2,3,...,16.
1472 *
1473 * @param[in] M The number of vectors to convert
1474 * @param[in] N The size of the vectors
1475 * @param[in] DATA_TYPE The data type of the vectors
1476 * @param[in] BASENAME_SRC The basename of the source variables
1477 * @param[in] BASENAME_DST The basename of the destination variables
Gian Marco Iodice0c17aa22019-09-27 09:23:15 +01001478 */
Sang-Hoon Park11b0b8a2019-11-05 13:29:19 +00001479#define CONVERT_BLOCK_STR(M, N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) CONVERT_ROW_##M(N, DATA_TYPE, BASENAME_SRC, BASENAME_DST)
1480#define CONVERT_BLOCK(M, N, DATA_TYPE, BASENAME_SRC, BASENAME_DST) CONVERT_BLOCK_STR(M, N, DATA_TYPE, BASENAME_SRC, BASENAME_DST)
SiCong Li3a501662020-06-26 10:02:06 +01001481/** @} */ // end of group CONVERT_BLOCK
1482
1483#if defined(PARTIAL_STORE_M0) && defined(PARTIAL_STORE_N0)
1484
SiCong Li406a13f2020-07-15 12:09:58 +01001485/** Boundary-aware GEMM block store
SiCong Li3a501662020-06-26 10:02:06 +01001486 * @name STORE_BLOCK_BOUNDARY_AWARE
SiCong Li406a13f2020-07-15 12:09:58 +01001487 * This macro assumes the following schemes to achieve boundary-awareness:
1488 * - Overlapping load in Y axis from lhs tensor. This implies lhs has no padding along y dim.
1489 * - Non-Overlapping(normal) load from rhs tensor. This imples rhs can have paddings.
1490 * - Overlapping load in Y axis from bias tensor. This implies rhs has no padding along y dim.
1491 * The macro then ensures that the dst tensor can be stored without any paddings in both x and y dim.
SiCong Li3a501662020-06-26 10:02:06 +01001492 *
SiCong Li406a13f2020-07-15 12:09:58 +01001493 * In the y dimension, we place the partial blocks **at the beginning** while in the x dimension, we place the partial
1494 * blocks **at the end**.
SiCong Li3a501662020-06-26 10:02:06 +01001495 * Say, the dst tensor is of shape MxN and we have M0 and N0 as the block size, this is how we define "partial blocks"/
1496 * "boundary block" (we use the 2 terms "partial blocks" and "boundary blocks" interchangeably) and its various parameters:
1497 *
1498 * *--x--> x == 0 x == 1
1499 * | |<------------------------------N-------------------------->|
1500 * y |<--------------N0------------->|<----PARTIAL_STORE_N0----->|
1501 * | -------------#############################################################
SiCong Li406a13f2020-07-15 12:09:58 +01001502 * * | | |...............................|...........................|
1503 * y == 0 | PAR_..._M0 |......Boundary block in y......|.Boundary block in x and y.|
1504 * | | |...............................|...........................|
SiCong Li3a501662020-06-26 10:02:06 +01001505 * M --#############################################################
SiCong Li406a13f2020-07-15 12:09:58 +01001506 * | | | |...........................|
1507 * y == 1 | M0 | Non-boundary block |....Boundary block in x....|
1508 * | | | |...........................|
SiCong Li3a501662020-06-26 10:02:06 +01001509 * |------------#############################################################
1510 *
1511 * Then @p PARTIAL_STORE_M0 = M % M0 and @p PARTIAL_STORE_N0 = N % N0
1512 *
1513 * @note in cases @p PARTIAL_STORE_N0 != 1, 2, 3, 4, 8, 16, extra vstore(s) will be invoked, thus incurring small performance penalty.
1514 *
SiCong Li3a501662020-06-26 10:02:06 +01001515 * It automatically detects if a giving M,N,M0,N0 combination can yield partial blocks in either X and Y dimension,
1516 * and select corresponding store methods such that the boundary detection logic is only added when needed.
1517 *
1518 * The data to store is expected to have consecutive names for each row.
1519 * E.g., for M0=3 and basename=c, the expected names are c0, c1 and c2.
1520 * The Z offset is expected to have consecutive names.
1521 * E.g., for M0=3 and Z=zin, the expected z offset names are zin0, zin1 and zin2.
1522 *
1523 * @param[in] M0 The number of rows to store, for non-partial blocks. Supported: 1-16
1524 * @param[in] N0 The size of each vector, for non-partial blocks. Supported: 1, 2, 3, 4, 8, 16
1525 * @param[in] DATA_TYPE The data type of the vectors
1526 * @param[in] BASENAME The basename of the variables
1527 * @param[in] PTR The base pointer
1528 * @param[in] STRIDE_Y The stride value in y-axis direction
1529 * @param[in] Z The offset in z-axis direction
1530 * @param[in] PARTIAL_STORE_M0 The partial size in y, for partial blocks. Supported: [0, @p M0)
1531 * @param[in] PARTIAL_STORE_N0 The partial size in x, for partial blocks. Supported: [0, @p N0)
SiCong Li3a501662020-06-26 10:02:06 +01001532 * @param[in] N Total number of columns. Used to detect if current block is at the boundary in x.
1533 * @param[in] y Global id of current block in y. Used to detect if current block is at the boundary in y.
1534 * @param[in] x Global id of current block in x. Used to detect if current block is at the boundary in x.
1535 * @{
1536 */
1537#if PARTIAL_STORE_M0 == 0 && PARTIAL_STORE_N0 == 0
1538// Case1: No partial blocks in either x or y
SiCong Li406a13f2020-07-15 12:09:58 +01001539#define STORE_BLOCK_BOUNDARY_AWARE(M0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z, PARTIAL_STORE_M0, PARTIAL_STORE_N0, N, y, x) \
SiCong Li3a501662020-06-26 10:02:06 +01001540 STORE_BLOCK(M0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z)
1541
1542#elif PARTIAL_STORE_M0 > 0 && PARTIAL_STORE_N0 == 0
1543// Case2: Partial blocks in y
SiCong Li406a13f2020-07-15 12:09:58 +01001544#define STORE_BLOCK_BOUNDARY_AWARE(M0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z, PARTIAL_STORE_M0, PARTIAL_STORE_N0, N, y, x) \
1545 STORE_BLOCK_PARTIAL_IN_Y(M0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z, PARTIAL_STORE_M0, y)
SiCong Li3a501662020-06-26 10:02:06 +01001546
1547#elif PARTIAL_STORE_M0 == 0 && PARTIAL_STORE_N0 > 0
1548// Case3: Partial blocks in x
SiCong Li406a13f2020-07-15 12:09:58 +01001549#define STORE_BLOCK_BOUNDARY_AWARE(M0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z, PARTIAL_STORE_M0, PARTIAL_STORE_N0, N, y, x) \
SiCong Li3a501662020-06-26 10:02:06 +01001550 STORE_BLOCK_PARTIAL_IN_X(M0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z, PARTIAL_STORE_N0, N, x)
1551
1552#else // PARTIAL_STORE_M0 == 0 && PARTIAL_STORE_N0 == 0
1553// Case4: Partial blocks in both x and y
SiCong Li406a13f2020-07-15 12:09:58 +01001554#define STORE_BLOCK_BOUNDARY_AWARE(M0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z, PARTIAL_STORE_M0, PARTIAL_STORE_N0, N, y, x) \
1555 STORE_BLOCK_PARTIAL_IN_X_AND_Y(M0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z, PARTIAL_STORE_M0, PARTIAL_STORE_N0, N, y, x)
SiCong Li3a501662020-06-26 10:02:06 +01001556
1557#endif // PARTIAL_STORE_M0 == 0 && PARTIAL_STORE_N0 == 0
1558
1559#else // defined(PARTIAL_STORE_M0) && defined(PARTIAL_STORE_N0)
1560
SiCong Li406a13f2020-07-15 12:09:58 +01001561#define STORE_BLOCK_BOUNDARY_AWARE(M0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z, PARTIAL_STORE_M0, PARTIAL_STORE_N0, N, y, x) \
SiCong Li3a501662020-06-26 10:02:06 +01001562 STORE_BLOCK(M0, N0, DATA_TYPE, BASENAME, PTR, STRIDE_Y, Z)
1563
1564#endif // defined(PARTIAL_STORE_M0) && defined(PARTIAL_STORE_N0)
SiCong Li406a13f2020-07-15 12:09:58 +01001565/** @} */ // end of group STORE_BLOCK_BOUNDARY_AWARE
1566
1567#if defined(PARTIAL_STORE_M0)
1568/** Compute the start m0 row (LHS, BIAS and DST) in a boundary-aware way so as to avoid padding
1569 * @name COMPUTE_M0_START_ROW
1570 * If there're any partial blocks in y dimension, they are placed at the beginning of the rows.
1571 * This shift amount is added to all rows such that the partial block (at the beginning) overlaps with the subsequent
1572 * blocks in the y dimension to avoid any padding.
1573 * EG: M0=4, PARTIAL_STORE_M0=1:
1574 * | Non-overlapping | +M0_ROW_SHIFT (Overlapping)
1575 * block 0 (partial)| start row = 0 | start row = 0
1576 * block 1 (full) | start row = 4 | start row = 1
1577 * block 2 (full) | start row = 8 | start row = 5
1578 *
1579 * @param[in] y Global id of current block in y.
1580 * @param[in] M0 The number of rows to store, for non-partial blocks. Supported: 1-16
1581 * @param[in] PARTIAL_STORE_M0 The partial size in y, for partial blocks. Supported: [0, @p M0)
1582 * @{
1583 */
1584#define COMPUTE_M0_START_ROW(y, M0, PARTIAL_STORE_M0) \
1585 ((uint)(max(0, (int)(y * M0) - (int)((M0 - PARTIAL_STORE_M0) % M0))))
1586#else // defined(PARTIAL_STORE_M0)
1587#define COMPUTE_M0_START_ROW(y, M0, PARTIAL_STORE_M0) \
1588 ((uint)(y * M0))
1589#endif // defined(PARTIAL_STORE_M0)
1590/** @} */ // end of group COMPUTE_M0_START_ROW