blob: 5c9a16ee33c48ac2362cd30b2afff2999bc432b3 [file] [log] [blame]
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +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#include "ckw/KernelWriter.h"
26#include "ckw/Error.h"
Viet-Hoa Doc8e16172023-06-27 14:09:46 +010027#include "ckw/TensorInfo.h"
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +010028#include "ckw/TensorOperand.h"
29#include "src/Prototype.h"
30
31#include <sstream>
32
33namespace ckw
34{
35
36namespace
37{
38
39inline prototype::TensorInfo create_impl_tensor_info(const TensorInfo &info)
40{
41 return prototype::TensorInfo{ info.shape(), info.data_type(), info.data_layout(), info.id() };
42}
43
44} // namespace
45
46// =================================================================================================
47// Constructors and destructor
48// =================================================================================================
49
50KernelWriter::KernelWriter(Kernel &kernel)
51 : _kernel(&kernel),
52 _impl_attr(std::make_unique<prototype::GpuKernelWriterAttribute>()),
53 _impl(prototype::GpuKernelWriterFactory::create(_impl_attr.get(), kernel.impl()))
54{
55 _impl->set_IdSpace(1);
56}
57
58KernelWriter::~KernelWriter()
59{
60}
61
62// =================================================================================================
63// Scope management
64// =================================================================================================
65
66int32_t KernelWriter::id_space() const
67{
68 return _id_space;
69}
70
71KernelWriter &KernelWriter::id_space(int32_t id_space)
72{
73 CKW_ASSERT(id_space <= _max_id_space);
74
75 _id_space = id_space;
76 return *this;
77}
78
79int32_t KernelWriter::next_id_space()
80{
81 id_space(++_max_id_space);
82 return _id_space;
83}
84
85// =================================================================================================
86// Tensor and tile declaration
87// =================================================================================================
88
Viet-Hoa Doc8e16172023-06-27 14:09:46 +010089TensorOperand &KernelWriter::declare_tensor_argument(const std::string &name, const TensorInfo &info, TensorStorageType storage_type)
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +010090{
91 const auto var_name = generate_variable_name(name);
92
93 _impl->declare_argument(var_name, create_impl_tensor_info(info));
94
Viet-Hoa Doc8e16172023-06-27 14:09:46 +010095 auto &operand = _kernel->register_operand(std::make_unique<TensorOperand>(var_name, info, storage_type));
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +010096
Viet-Hoa Doc8e16172023-06-27 14:09:46 +010097 return operand;
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +010098}
99
Nikolaj Jensen5ff48022023-06-27 14:13:24 +0100100TileOperand &KernelWriter::declare_tile_argument(const std::string &name, int32_t value)
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100101{
102 const auto var_name = generate_variable_name(name);
103
Viet-Hoa Doc8e16172023-06-27 14:09:46 +0100104 auto &operand = _kernel->register_operand(std::make_unique<TileOperand>(var_name, value));
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100105
Viet-Hoa Doc8e16172023-06-27 14:09:46 +0100106 return operand;
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100107}
108
Nikolaj Jensen5ff48022023-06-27 14:13:24 +0100109std::string KernelWriter::generate_variable_name(const std::string &name) const
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100110{
111 std::stringstream var_name;
112
113 var_name << "_" << _id_space << "_" << name;
114
115 return var_name.str();
116}
117
Viet-Hoa Doc8e16172023-06-27 14:09:46 +0100118TileOperand &KernelWriter::declare_tile_operand(std::unique_ptr<TileOperand> operand_ptr)
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100119{
Viet-Hoa Doc8e16172023-06-27 14:09:46 +0100120 auto &operand = _kernel->register_operand(std::move(operand_ptr));
121 const auto &name = operand.name();
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100122
Viet-Hoa Doc8e16172023-06-27 14:09:46 +0100123 if(!operand.is_constant())
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100124 {
Viet-Hoa Doc8e16172023-06-27 14:09:46 +0100125 const auto &info = operand.tile_info();
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100126
Viet-Hoa Doc8e16172023-06-27 14:09:46 +0100127 _impl->declare_tile(
128 name,
129 prototype::TileInfo(info.data_type(), info.width(), info.height()));
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100130 }
Jakub Sujake1c96e72023-07-31 13:36:58 +0100131 else
132 {
133 _impl->declare_const_tile(name, operand.value(), operand.data_type());
134 }
Viet-Hoa Doc8e16172023-06-27 14:09:46 +0100135
136 return operand;
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100137}
138
139// =================================================================================================
140// Load and store
141// =================================================================================================
142
Jakub Sujake1c96e72023-07-31 13:36:58 +0100143void KernelWriter::op_load(TileOperand &tile, const TensorOperand &tensor, const TensorTileSampler &sampler, const TileOperand &dilation_y)
144{
145 prototype::TensorOperand impl_tensor(
146 tensor.name(),
147 prototype::GpuSampler{
148 sampler.format(),
149 prototype::to_gpu_tensor_storage(tensor.storage_type()),
150 sampler.address_mode_x(),
151 sampler.address_mode_y(),
152 sampler.address_mode_z() });
153
154 auto impl_x = sampler.x().create_impl_operand(_impl.get());
155 auto impl_y = sampler.y().create_impl_operand(_impl.get());
156 auto impl_z = sampler.z().create_impl_operand(_impl.get());
157 auto impl_b = sampler.b().create_impl_operand(_impl.get());
158
159 auto impl_dilation_y = dilation_y.create_impl_operand(_impl.get());
160
161 auto impl_dst = tile.create_impl_operand(_impl.get());
162
163 _impl->op_load_immediate(impl_tensor, impl_dst, impl_x, impl_y, impl_z, impl_b, impl_dilation_y);
164}
165
166void KernelWriter::op_load_indirect(TileOperand &tile, const TensorOperand &tensor, const TensorTileSampler &sampler)
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100167{
Viet-Hoa Doe1880f02023-06-28 10:25:35 +0100168 prototype::TensorOperand impl_tensor(
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100169 tensor.name(),
170 prototype::GpuSampler{
171 sampler.format(),
Viet-Hoa Doc8e16172023-06-27 14:09:46 +0100172 prototype::to_gpu_tensor_storage(tensor.storage_type()),
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100173 sampler.address_mode_x(),
174 sampler.address_mode_y(),
175 sampler.address_mode_z() });
176
177 auto impl_x = sampler.x().create_impl_operand(_impl.get());
178 auto impl_y = sampler.y().create_impl_operand(_impl.get());
179 auto impl_z = sampler.z().create_impl_operand(_impl.get());
180 auto impl_b = sampler.b().create_impl_operand(_impl.get());
181
182 auto impl_dst = tile.create_impl_operand(_impl.get());
183
Jakub Sujake1c96e72023-07-31 13:36:58 +0100184 _impl->op_load_indirect(impl_tensor, impl_dst, impl_x, impl_y, impl_z, impl_b);
185}
186
187void KernelWriter::util_get_indirect_buffer(TileOperand &tile,
188 const TensorOperand &tensor,
189 const TensorTileSampler &sampler,
190 const TileOperand &x,
191 const TileOperand &y,
192 const TileOperand &x_off,
193 const TileOperand &y_off)
194{
195 prototype::TensorOperand impl_tensor(
196 tensor.name(),
197 prototype::GpuSampler{
198 sampler.format(),
199 prototype::to_gpu_tensor_storage(tensor.storage_type()),
200 sampler.address_mode_x(),
201 sampler.address_mode_y(),
202 sampler.address_mode_z() });
203
204 auto impl_x = x.create_impl_operand(_impl.get());
205 auto impl_y = y.create_impl_operand(_impl.get());
206 auto impl_x_off = x_off.create_impl_operand(_impl.get());
207 auto impl_y_off = y_off.create_impl_operand(_impl.get());
208
209 auto impl_dst = tile.create_impl_operand(_impl.get());
210
211 _impl->util_get_indirect_buffer(impl_dst, impl_tensor, impl_x, impl_y, impl_x_off, impl_y_off);
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100212}
213
214void KernelWriter::op_store(TensorOperand &tensor, const TileOperand &tile, const TensorTileSampler &sampler)
215{
Viet-Hoa Doe1880f02023-06-28 10:25:35 +0100216 prototype::TensorOperand impl_tensor(
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100217 tensor.name(),
218 prototype::GpuSampler{
219 sampler.format(),
Viet-Hoa Doc8e16172023-06-27 14:09:46 +0100220 prototype::to_gpu_tensor_storage(tensor.storage_type()),
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100221 sampler.address_mode_x(),
222 sampler.address_mode_y(),
223 sampler.address_mode_z() });
224 auto impl_src = tile.create_impl_operand(_impl.get());
225 auto impl_x = sampler.x().create_impl_operand(_impl.get());
226 auto impl_y = sampler.y().create_impl_operand(_impl.get());
227 auto impl_z = sampler.z().create_impl_operand(_impl.get());
228 auto impl_b = sampler.b().create_impl_operand(_impl.get());
229
230 _impl->op_store_immediate(impl_tensor, impl_src, impl_x, impl_y, impl_z, impl_b);
231}
232
233// =================================================================================================
234// Data processing
235// =================================================================================================
236
Nikolaj Jensen5ff48022023-06-27 14:13:24 +0100237void KernelWriter::op_assign(const TileOperand &dst, const TileOperand &src)
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100238{
239 auto impl_dst = dst.create_impl_operand(_impl.get());
240 auto impl_src = src.create_impl_operand(_impl.get());
241
242 _impl->op_assign(impl_dst, impl_src);
243}
244
Nikolaj Jensen5ff48022023-06-27 14:13:24 +0100245void KernelWriter::op_cast_expression(const TileOperand &dst, const TileOperand &src, const ConvertPolicy policy)
246{
247 auto impl_dst = dst.create_impl_operand(_impl.get());
248 auto impl_src = src.create_impl_operand(_impl.get());
249
250 _impl->op_cast_expression(impl_dst, impl_src, policy);
251}
252
253void KernelWriter::op_binary_expression(const TileOperand &dst, const TileOperand &lhs, BinaryOp op, const TileOperand &rhs)
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100254{
255 auto impl_lhs = lhs.create_impl_operand(_impl.get());
256 auto impl_rhs = rhs.create_impl_operand(_impl.get());
257 auto impl_dst = dst.create_impl_operand(_impl.get());
258
259 _impl->op_binary_expression(impl_dst, impl_lhs, op, impl_rhs);
260}
261
Nikolaj Jensen5ff48022023-06-27 14:13:24 +0100262void KernelWriter::op_unary_expression(const TileOperand &dst, UnaryOp op, const TileOperand &src)
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100263{
264 auto impl_dst = dst.create_impl_operand(_impl.get());
265 auto impl_src = src.create_impl_operand(_impl.get());
266
Nikolaj Jensen5ff48022023-06-27 14:13:24 +0100267 _impl->op_unary_expression(impl_dst, op, impl_src);
268}
269
270void KernelWriter::op_unary_elementwise_function(const TileOperand &dst, UnaryFunction opcode, const TileOperand &src)
271{
272 auto impl_dst = dst.create_impl_operand(_impl.get());
273 auto impl_src = src.create_impl_operand(_impl.get());
274
275 _impl->op_unary_elementwise_function(impl_dst, opcode, impl_src);
276}
277
278void KernelWriter::op_binary_elementwise_function(const TileOperand &dst, BinaryFunction opcode, const TileOperand &first, const TileOperand &second)
279{
280 auto impl_dst = dst.create_impl_operand(_impl.get());
281 auto impl_first = first.create_impl_operand(_impl.get());
282 auto impl_second = second.create_impl_operand(_impl.get());
283
284 _impl->op_binary_elementwise_function(impl_dst, opcode, impl_first, impl_second);
285}
286
287void KernelWriter::op_ternary_elementwise_function(const TileOperand &dst, TernaryFunction opcode, const TileOperand &first, const TileOperand &second, const TileOperand &third)
288{
289 auto impl_dst = dst.create_impl_operand(_impl.get());
290 auto impl_first = first.create_impl_operand(_impl.get());
291 auto impl_second = second.create_impl_operand(_impl.get());
292 auto impl_third = third.create_impl_operand(_impl.get());
293
294 _impl->op_ternary_elementwise_function(impl_dst, opcode, impl_first, impl_second, impl_third);
295}
296
297void KernelWriter::op_if(const TileOperand &lhs, BinaryOp op, const TileOperand &rhs, const std::function<void()> &body)
298{
299 auto impl_lhs = lhs.create_impl_operand(_impl.get());
300 auto impl_rhs = rhs.create_impl_operand(_impl.get());
301
302 _impl->op_if_header(impl_lhs, op, impl_rhs);
303 _impl->compound_statement_begin();
304 body();
305 _impl->compound_statement_end();
306}
307
308void KernelWriter::op_else_if(const TileOperand &lhs, BinaryOp op, const TileOperand &rhs, const std::function<void()> &body)
309{
310 auto impl_lhs = lhs.create_impl_operand(_impl.get());
311 auto impl_rhs = rhs.create_impl_operand(_impl.get());
312
313 _impl->op_else_if_header(impl_lhs, op, impl_rhs);
314 _impl->compound_statement_begin();
315 body();
316 _impl->compound_statement_end();
317}
318
319void KernelWriter::op_else(const std::function<void()> &body)
320{
321 _impl->op_else_header();
322 _impl->compound_statement_begin();
323 body();
324 _impl->compound_statement_end();
325}
326
Nikolaj Jensenfab6c212023-06-27 14:13:24 +0100327void KernelWriter::op_for_loop(const TileOperand &var_name, BinaryOp cond_op, const TileOperand &cond_value_name, const TileOperand &update_var_name, AssignmentOp update_op, const TileOperand &update_value_name, const std::function<void()> &body)
Nikolaj Jensen5ff48022023-06-27 14:13:24 +0100328{
329 auto impl_var_name = var_name.create_impl_operand(_impl.get());
330 auto impl_cond_value_name = cond_value_name.create_impl_operand(_impl.get());
Nikolaj Jensenfab6c212023-06-27 14:13:24 +0100331 auto impl_update_var_name = update_var_name.create_impl_operand(_impl.get());
Nikolaj Jensen5ff48022023-06-27 14:13:24 +0100332 auto impl_update_value_name = update_value_name.create_impl_operand(_impl.get());
333
Nikolaj Jensenfab6c212023-06-27 14:13:24 +0100334 _impl->op_for_loop_header(impl_var_name, cond_op, impl_cond_value_name, impl_update_var_name, update_op, impl_update_value_name);
Nikolaj Jensen5ff48022023-06-27 14:13:24 +0100335 _impl->compound_statement_begin();
336 body();
337 _impl->compound_statement_end();
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100338}
339
340// =================================================================================================
341// Misc
342// =================================================================================================
343
Gunes Bayir91cb7332023-07-25 17:00:33 +0100344void KernelWriter::op_get_global_id(const TileOperand &dst, int32_t dim)
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100345{
346 _impl->op_get_global_id(prototype::Operand(dst.name()), dim);
347}
348
Nikolaj Jensen5ff48022023-06-27 14:13:24 +0100349void KernelWriter::op_return()
350{
351 _impl->op_return();
352}
353
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100354// =================================================================================================
355// Code generation
356// =================================================================================================
357
358std::string KernelWriter::generate_code()
359{
360 return prototype::generate_code(*_kernel->impl(), _kernel->name());
361}
362
363} // namespace ckw