blob: da41b940d79c2281c7b302eca38379275590370c [file] [log] [blame]
Viet-Hoa Do3389f532023-07-05 17:36:40 +01001/*
2 * Copyright (c) 2023 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
25#ifndef CKW_INCLUDE_CKW_KERNELWRITER_H
26#define CKW_INCLUDE_CKW_KERNELWRITER_H
27
Gunes Bayir2b9fa592024-01-17 16:07:03 +000028#include "ckw/Kernel.h"
29#include "ckw/TensorInfo.h"
Viet-Hoa Do0b23e0e2023-07-25 14:00:46 +010030#include "ckw/TensorOperand.h"
Gunes Bayir2b9fa592024-01-17 16:07:03 +000031#include "ckw/TensorSampler.h"
32#include "ckw/TileInfo.h"
Gunes Bayir3c776062023-07-12 14:50:56 +010033#include "ckw/TileOperand.h"
Gunes Bayir806b8e82023-08-23 23:28:31 +010034#include "ckw/types/ConstantData.h"
Viet-Hoa Doe1c3b462023-07-31 17:13:34 +010035#include "ckw/types/ConvertPolicy.h"
Gunes Bayir2b9fa592024-01-17 16:07:03 +000036#include "ckw/types/DataType.h"
Viet-Hoa Doe1c3b462023-07-31 17:13:34 +010037#include "ckw/types/Operators.h"
Gunes Bayir2b9fa592024-01-17 16:07:03 +000038#include "ckw/types/TargetArchitecture.h"
39#include "ckw/types/TargetLanguage.h"
40#include "ckw/types/TensorComponentType.h"
41#include "ckw/types/TensorDataLayout.h"
42#include "ckw/types/TensorSamplerTypes.h"
43#include "ckw/types/TensorStorageType.h"
Gunes Bayirab0b7502023-07-11 14:57:36 +010044
Viet-Hoa Doe1c3b462023-07-31 17:13:34 +010045#include <functional>
Viet-Hoa Do3389f532023-07-05 17:36:40 +010046#include <memory>
47#include <string>
Viet-Hoa Docd1f03e2023-09-19 16:41:34 +010048#include <tuple>
Viet-Hoa Do3389f532023-07-05 17:36:40 +010049
50namespace ckw
51{
52
Gunes Bayir2b9fa592024-01-17 16:07:03 +000053/** Forward Declarations */
Viet-Hoa Docd1f03e2023-09-19 16:41:34 +010054class TileArea;
Gunes Bayirab0b7502023-07-11 14:57:36 +010055
Viet-Hoa Do3389f532023-07-05 17:36:40 +010056/** A kernel writer.
57 *
58 * This class is used to construct a new kernel by defining arguments, declaring variable and writing code.
59 *
60 * Use @ref KernelWriter::create_instance method to create the kernel writer for the specific target architecture and language.
61 *
62 * After having finished constructing the kernel, call @ref KernelWriter::emit_kernel to get the kernel object.
63 */
64class KernelWriter
65{
66public:
67 // =============================================================================================
68 // Construtors and destructor
69 // =============================================================================================
70
71 /** Initialize a new instance of @ref KernelWriter class for the specific architecture and language.
72 *
73 * Supported target architectures and languages:
74 *
75 * Architecture | Languages |
76 * ------------------------------|------------------------------|
77 * GpuArmMaliValhall | OpenCL |
78 *
79 * @param[in] architecture The architecture on which the kernel is executed.
80 * @param[in] language The language to write the kernel.
81 */
82 static std::unique_ptr<KernelWriter> create_instance(TargetArchitecture architecture, TargetLanguage language);
83
84 /** Destructor */
85 virtual ~KernelWriter();
86
87 // =============================================================================================
Viet-Hoa Doe1c3b462023-07-31 17:13:34 +010088 // Data processing
89 // =============================================================================================
90
91 /** Write assignment statement: `<dst> = <src>;`.
92 *
93 * @param[in] dst The destination tile.
94 * @param[in] src The source tile.
95 */
96 virtual void op_assign(const TileOperand &dst, const TileOperand &src) = 0;
97
98 /** Write the cast statement: `<dst> = convert_<dst.type><policy>(<src>);`.
99 *
100 * @param[in] dst The destination tile.
101 * @param[in] src The source tile.
102 * @param[in] policy The policy governing the behavior of the cast.
103 */
104 virtual void op_cast(const TileOperand &dst, const TileOperand &src, ConvertPolicy policy) = 0;
105
106 /** Write the unary expression statement: `<dst> = <op> <src>;`.
107 *
108 * @param[in] dst The destination tile.
Viet-Hoa Doe1c3b462023-07-31 17:13:34 +0100109 * @param[in] op The unary operator.
Viet-Hoa Do34b6c3a2023-08-22 11:11:23 +0100110 * @param[in] src The source tile.
Viet-Hoa Doe1c3b462023-07-31 17:13:34 +0100111 */
Viet-Hoa Do34b6c3a2023-08-22 11:11:23 +0100112 virtual void op_unary(const TileOperand &dst, UnaryOp op, const TileOperand &src) = 0;
113
114 /** Write the binary expression statement: `<dst> = <op>(<first>, <second>);`.
115 *
116 * @param[in] dst The destination tile.
117 * @param[in] op The binary operator.
118 * @param[in] first The first source tile.
119 * @param[in] second The second source tile.
120 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100121 virtual void
122 op_binary(const TileOperand &dst, BinaryOp op, const TileOperand &first, const TileOperand &second) = 0;
Viet-Hoa Do34b6c3a2023-08-22 11:11:23 +0100123
124 /** Write ternary expression statement: `<dst> = <op>(<first>, <second>, <third>);`.
125 *
126 * @param[in] dst The destination tile.
127 * @param[in] op The ternary operator.
128 * @param[in] first The first source tile.
129 * @param[in] second The second source tile.
130 * @param[in] third The third source tile.
131 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100132 virtual void op_ternary(const TileOperand &dst,
133 TernaryOp op,
134 const TileOperand &first,
135 const TileOperand &second,
136 const TileOperand &third) = 0;
Viet-Hoa Doe1c3b462023-07-31 17:13:34 +0100137
138 // =============================================================================================
Viet-Hoa Do2d0c2f52023-08-24 11:48:19 +0100139 // Flow control
140 // =============================================================================================
141
142 /** Write if block: `if(<lhs> <op> <rhs>) { <body> }`.
143 *
144 * @param[in] lhs The LHS tile of the condition.
145 * @param[in] op The relational binary operator.
146 * @param[in] rhs The RHS tile of the condition.
147 * @param[in] body The function that writes the body of the if block.
148 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100149 virtual void
150 op_if(const TileOperand &lhs, BinaryOp op, const TileOperand &rhs, const std::function<void()> &body) = 0;
Viet-Hoa Do2d0c2f52023-08-24 11:48:19 +0100151
152 /** Write else-if block: `else if(<lhs> <op> <rhs>) { <body> }`.
153 *
154 * @param[in] lhs The LHS tile of the condition.
155 * @param[in] op The relational binary operator.
156 * @param[in] rhs The RHS tile of the condition.
157 * @param[in] body The function that writes the body of the else-if block.
158 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100159 virtual void
160 op_else_if(const TileOperand &lhs, BinaryOp op, const TileOperand &rhs, const std::function<void()> &body) = 0;
Viet-Hoa Do2d0c2f52023-08-24 11:48:19 +0100161
162 /** Write an else block: `else { <body> }`.
163 *
164 * @param[in] body The function that writes the body of the else block.
165 */
166 virtual void op_else(const std::function<void()> &body) = 0;
167
168 /** Write for-loop block: `for(; <var> <cond_op> <cond_value>; <update_var> <update_op> <update_value>) { body }`.
169 *
170 * @param[in] var The scalar tile used in loop condition.
171 * @param[in] cond_op The relational binary operator used in loop condition.
172 * @param[in] cond_value The value which the variable is compared against.
173 * @param[in] update_var The scalar tile which is updated each iteration.
174 * @param[in] update_op The assignment operator used for updating the update value.
175 * @param[in] update_value The value which is updated at every iteration.
176 * @param[in] body The function that writes the body of the for-loop block.
177 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100178 virtual void op_for_loop(const TileOperand &var,
179 BinaryOp cond_op,
180 const TileOperand &cond_value,
181 const TileOperand &update_var,
182 AssignmentOp update_op,
183 const TileOperand &update_value,
184 const std::function<void()> &body) = 0;
Viet-Hoa Do2d0c2f52023-08-24 11:48:19 +0100185
186 /** Write the return statement. */
187 virtual void op_return() = 0;
188
189 // =============================================================================================
Viet-Hoa Do3389f532023-07-05 17:36:40 +0100190 // Misc
191 // =============================================================================================
192
Viet-Hoa Dod0d8f2e2023-08-29 16:01:13 +0100193 /** Write the statement to get the global ID of the specified dimension.
194 *
195 * @param[in] dst The tile to write the global ID into.
196 * @param[in] dim The dimension.
197 */
198 virtual void op_get_global_id(const TileOperand &dst, int32_t dim) = 0;
199
Viet-Hoa Do3389f532023-07-05 17:36:40 +0100200 /** Write the line comment in debug build.
Gunes Bayirab0b7502023-07-11 14:57:36 +0100201 *
Viet-Hoa Do3389f532023-07-05 17:36:40 +0100202 * This function does not take effect on release build.
203 *
204 * The comment must only contain one line (i.e. no newline character is allowed).
205 *
206 * @param[in] text The comment to be written.
207 */
Viet-Hoa Doe1c3b462023-07-31 17:13:34 +0100208 virtual void op_comment(const std::string &text) = 0;
209
Viet-Hoa Dod0d8f2e2023-08-29 16:01:13 +0100210 /** Write the statement to print out the value of all the specified tiles.
211 *
212 * The printing statement is constructed so that the prefix and each of the operand are printed in separate lines.
213 * The format for each operand varies depending on whether it is a 2D tile, a vector or a scalar value.
214 *
215 * Example output of the printing statement when it is executed:
216 *
217 * prefix
218 * scalar_name = scalar_value
219 * vector_name = [vector_value_0, vector_value_1, vector_value_2]
220 * tile_name = [[tile_value_00, tile_value_01], [tile_value_10, tile_value_11]]
221 *
222 * @param[in] prefix The first string to be printed out before the list of operands.
223 * @param[in] operands The list of tiles to be included in the printing statement.
224 */
225 virtual void op_print(const std::string &prefix, const std::vector<TileOperand> &operands) = 0;
226
Viet-Hoa Doe1c3b462023-07-31 17:13:34 +0100227 /** Write the given raw code to kernel source code
228 * It's used to address the cases where the user needs to
229 * explicitly add a code where it's not (yet) supported by
230 * the kernel writer utility calls.
231 *
232 * @param[in] raw_code raw code to write as string
233 */
234 virtual void op_write_raw_code(const std::string &raw_code) = 0;
Viet-Hoa Do3389f532023-07-05 17:36:40 +0100235
236 // =============================================================================================
237 // Code generation
238 // =============================================================================================
239
240 /** Emit the kernel object.
241 *
242 * @param[in] name The name of the kernel object to be generated.
243 */
244 virtual std::unique_ptr<Kernel> emit_kernel(const std::string &name) = 0;
Gunes Bayirab0b7502023-07-11 14:57:36 +0100245
Viet-Hoa Do0b23e0e2023-07-25 14:00:46 +0100246 // =============================================================================================
247 // Tensor and tile declaration
248 // =============================================================================================
249
250 /** Declare a tensor argument.
251 *
252 * @param[in] name The name of the tensor.
253 * @param[in] info The tensor info.
254 *
255 * @return The @ref TensorOperand object.
256 */
257 virtual TensorOperand declare_tensor_argument(const std::string &name, const TensorInfo &info) = 0;
258
Gunes Bayirab0b7502023-07-11 14:57:36 +0100259 /** Declare a tile given its name and tile info
260 *
261 * @param[in] name Name of the tile
262 * @param[in] tile_info Shape and data type of the tile
263 *
Gunes Bayir806b8e82023-08-23 23:28:31 +0100264 * @return The created tile operand
Gunes Bayirab0b7502023-07-11 14:57:36 +0100265 */
Viet-Hoa Do25d26f42023-07-20 17:31:47 +0100266 virtual TileOperand declare_tile(const std::string &name, const TileInfo &tile_info) = 0;
Gunes Bayirab0b7502023-07-11 14:57:36 +0100267
Gunes Bayir806b8e82023-08-23 23:28:31 +0100268 /** Declare a constant tile given a @ref:ConstantData object
269 *
270 * @param[in] data a @ref ckw::ConstantData object that has the values and the
271 * underlying data type of the constant tile
272 *
273 * @return The created constant tile operand
274 */
275 virtual TileOperand declare_constant_tile(const ConstantData &data) = 0;
276
Gunes Bayir47a396e2023-08-17 11:04:02 +0100277 /** Load the data from the tensor memory to the tile using the sampling information.
278 *
279 * @param[in] tile_op The tile to be loaded.
280 * @param[in] tensor_op The tensor to be read.
281 * @param[in] sampler The tensor sampling information.
282 * @param[in] x x-coordinate
283 * @param[in] y y-coordinate
284 * @param[in] z z-coordinate
Gunes Bayird5f9a1c2023-08-17 11:04:02 +0100285 * @param[in] batch batch
Gunes Bayir47a396e2023-08-17 11:04:02 +0100286 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100287 virtual void op_load(const TileOperand &tile_op,
288 const TensorOperand &tensor_op,
289 TensorSampler &sampler,
290 const TileOperand &x,
291 const TileOperand &y,
292 const TileOperand &z,
293 const TileOperand &batch) = 0;
Gunes Bayir47a396e2023-08-17 11:04:02 +0100294
295 /** Load the data from the tensor memory to the tile in a dilated way using the sampling information.
296 *
297 * Similar to @ref KernelWriter::op_load() and
298 *
299 * @param[in] dilation_x Dilation while reading in x-dimension
300 * @param[in] dilation_y Dilation while reading in y-dimension
301 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100302 virtual void op_load_dilated(const TileOperand &tile_op,
303 const TensorOperand &tensor_op,
304 TensorSampler &sampler,
305 const TileOperand &x,
306 const TileOperand &y,
307 const TileOperand &z,
308 const TileOperand &batch,
309 const TileOperand &dilation_x,
310 const TileOperand &dilation_y) = 0;
Gunes Bayir47a396e2023-08-17 11:04:02 +0100311
312 /** Store the data to the tensor memory from the tile using the sampling information.
313 *
314 * Similar to @ref KernelWriter::op_load()
315 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100316 virtual void op_store(const TensorOperand &tensor_op,
317 const TileOperand &tile_op,
318 TensorSampler &sampler,
319 const TileOperand &x,
320 const TileOperand &y,
321 const TileOperand &z,
322 const TileOperand &batch) = 0;
Gunes Bayir47a396e2023-08-17 11:04:02 +0100323
324 /** Store the data to the tensor memory from the tile in a dilated way using the sampling information.
325 *
326 * Similar to @ref KernelWriter::op_load_dilated()
327 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100328 virtual void op_store_dilated(const TensorOperand &tensor_op,
329 const TileOperand &tile_op,
330 TensorSampler &sampler,
331 const TileOperand &x,
332 const TileOperand &y,
333 const TileOperand &z,
334 const TileOperand &batch,
335 const TileOperand &dilation_x,
336 const TileOperand &dilation_y) = 0;
Gunes Bayir47a396e2023-08-17 11:04:02 +0100337
Gunes Bayird5f9a1c2023-08-17 11:04:02 +0100338 /** Load the data from the tensor memory to the tile using the indirect buffer approach and respecting the sampling information.
339 *
340 * @param[in] tile_op The tile to be loaded.
341 * @param[in] tensor_op The tensor to be read.
342 * @param[in] sampler The tensor sampling information.
343 * @param[in] x x-coordinate
344 * @param[in] y y-coordinate
345 * @param[in] z z-coordinate
346 * @param[in] batch batch
347 */
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100348 virtual void op_load_indirect(const TileOperand &tile_op,
349 const TensorOperand &tensor_op,
350 TensorSampler &sampler,
351 const TileOperand &x,
352 const TileOperand &y,
353 const TileOperand &z,
354 const TileOperand &batch_op) = 0;
Gunes Bayird5f9a1c2023-08-17 11:04:02 +0100355
Viet-Hoa Do2d0c2f52023-08-24 11:48:19 +0100356 // =============================================================================================
357 // ID space management
358 // =============================================================================================
359
360 /** Create the new unique ID space and return the value.
361 *
362 * This function changes the ID space to a new number which hasn't been used since the creation
363 * of this kernel writer object.
364 *
365 * @return The new ID space value.
366 */
367 int32_t new_id_space();
368
369 /** Get the current ID space. */
Gunes Bayirab0b7502023-07-11 14:57:36 +0100370 int32_t id_space() const;
371
Gunes Bayir2b9fa592024-01-17 16:07:03 +0000372protected:
Viet-Hoa Do2d0c2f52023-08-24 11:48:19 +0100373 /** Set the current ID space.
374 *
375 * @param[in] value The ID space to be used.
376 */
377 KernelWriter &id_space(int32_t value);
378
379 /** Write the body code using the specified function.
380 *
381 * This function makes sure that a new ID space is created before and then is used solely
382 * by the specified body writing function.
383 * The ID space will not be reused after that.
384 *
385 * @param[in] body The function that writes the body code.
386 */
387 void write_body(const std::function<void()> &body);
388
389protected:
Gunes Bayirab0b7502023-07-11 14:57:36 +0100390 /** Generate full variable name by prefixing it with id space */
391 std::string generate_full_name(const std::string &name) const;
392
Viet-Hoa Do0b23e0e2023-07-25 14:00:46 +0100393 /** Create a new tile operand referring to the specified tile object. */
Viet-Hoa Do25d26f42023-07-20 17:31:47 +0100394 static TileOperand create_tile_operand(ITile &tile);
395
Viet-Hoa Docd1f03e2023-09-19 16:41:34 +0100396 /** Get the reference to the tile object and the active area from the tile operand. */
397 static std::tuple<ITile &, TileArea> get_tile(const TileOperand &operand);
Viet-Hoa Do25d26f42023-07-20 17:31:47 +0100398
Viet-Hoa Do0b23e0e2023-07-25 14:00:46 +0100399 /** Create a new tensor operand from a tensor object. */
400 static TensorOperand create_tensor_operand(ITensor &tensor);
401
402 /** Get the reference to tensor object from the tensor operand. */
403 static ITensor &get_tensor(const TensorOperand &operand);
404
Gunes Bayir806b8e82023-08-23 23:28:31 +0100405 /** Get the values of a constant data object. */
406 static const std::vector<std::vector<std::string>> &get_values(const ConstantData &data);
407
408 /** Get the data type of a constant data object. */
409 static DataType get_data_type(const ConstantData &data);
410
Gunes Bayirab0b7502023-07-11 14:57:36 +0100411private:
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100412 int32_t _id_space{0};
413 int32_t _last_created_id_space{0};
Viet-Hoa Do3389f532023-07-05 17:36:40 +0100414};
415
416} // namespace ckw
417
418#endif // CKW_INCLUDE_CKW_KERNELWRITER_H