blob: 9122e518b441319079bfc21d1c42d943318fc3a9 [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 }
Viet-Hoa Doc8e16172023-06-27 14:09:46 +0100131
132 return operand;
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100133}
134
135// =================================================================================================
136// Load and store
137// =================================================================================================
138
139void KernelWriter::op_load(TileOperand &tile, TensorOperand &tensor, const TensorTileSampler &sampler)
140{
Viet-Hoa Doe1880f02023-06-28 10:25:35 +0100141 prototype::TensorOperand impl_tensor(
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100142 tensor.name(),
143 prototype::GpuSampler{
144 sampler.format(),
Viet-Hoa Doc8e16172023-06-27 14:09:46 +0100145 prototype::to_gpu_tensor_storage(tensor.storage_type()),
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100146 sampler.address_mode_x(),
147 sampler.address_mode_y(),
148 sampler.address_mode_z() });
149
150 auto impl_x = sampler.x().create_impl_operand(_impl.get());
151 auto impl_y = sampler.y().create_impl_operand(_impl.get());
152 auto impl_z = sampler.z().create_impl_operand(_impl.get());
153 auto impl_b = sampler.b().create_impl_operand(_impl.get());
154
155 auto impl_dst = tile.create_impl_operand(_impl.get());
156
157 _impl->op_load_immediate(impl_tensor, impl_dst, impl_x, impl_y, impl_z, impl_b);
158}
159
160void KernelWriter::op_store(TensorOperand &tensor, const TileOperand &tile, const TensorTileSampler &sampler)
161{
Viet-Hoa Doe1880f02023-06-28 10:25:35 +0100162 prototype::TensorOperand impl_tensor(
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100163 tensor.name(),
164 prototype::GpuSampler{
165 sampler.format(),
Viet-Hoa Doc8e16172023-06-27 14:09:46 +0100166 prototype::to_gpu_tensor_storage(tensor.storage_type()),
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100167 sampler.address_mode_x(),
168 sampler.address_mode_y(),
169 sampler.address_mode_z() });
170 auto impl_src = tile.create_impl_operand(_impl.get());
171 auto impl_x = sampler.x().create_impl_operand(_impl.get());
172 auto impl_y = sampler.y().create_impl_operand(_impl.get());
173 auto impl_z = sampler.z().create_impl_operand(_impl.get());
174 auto impl_b = sampler.b().create_impl_operand(_impl.get());
175
176 _impl->op_store_immediate(impl_tensor, impl_src, impl_x, impl_y, impl_z, impl_b);
177}
178
179// =================================================================================================
180// Data processing
181// =================================================================================================
182
Nikolaj Jensen5ff48022023-06-27 14:13:24 +0100183void KernelWriter::op_assign(const TileOperand &dst, const TileOperand &src)
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100184{
185 auto impl_dst = dst.create_impl_operand(_impl.get());
186 auto impl_src = src.create_impl_operand(_impl.get());
187
188 _impl->op_assign(impl_dst, impl_src);
189}
190
Nikolaj Jensen5ff48022023-06-27 14:13:24 +0100191void KernelWriter::op_cast_expression(const TileOperand &dst, const TileOperand &src, const ConvertPolicy policy)
192{
193 auto impl_dst = dst.create_impl_operand(_impl.get());
194 auto impl_src = src.create_impl_operand(_impl.get());
195
196 _impl->op_cast_expression(impl_dst, impl_src, policy);
197}
198
199void KernelWriter::op_binary_expression(const TileOperand &dst, const TileOperand &lhs, BinaryOp op, const TileOperand &rhs)
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100200{
201 auto impl_lhs = lhs.create_impl_operand(_impl.get());
202 auto impl_rhs = rhs.create_impl_operand(_impl.get());
203 auto impl_dst = dst.create_impl_operand(_impl.get());
204
205 _impl->op_binary_expression(impl_dst, impl_lhs, op, impl_rhs);
206}
207
Nikolaj Jensen5ff48022023-06-27 14:13:24 +0100208void KernelWriter::op_unary_expression(const TileOperand &dst, UnaryOp op, const TileOperand &src)
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100209{
210 auto impl_dst = dst.create_impl_operand(_impl.get());
211 auto impl_src = src.create_impl_operand(_impl.get());
212
Nikolaj Jensen5ff48022023-06-27 14:13:24 +0100213 _impl->op_unary_expression(impl_dst, op, impl_src);
214}
215
216void KernelWriter::op_unary_elementwise_function(const TileOperand &dst, UnaryFunction opcode, const TileOperand &src)
217{
218 auto impl_dst = dst.create_impl_operand(_impl.get());
219 auto impl_src = src.create_impl_operand(_impl.get());
220
221 _impl->op_unary_elementwise_function(impl_dst, opcode, impl_src);
222}
223
224void KernelWriter::op_binary_elementwise_function(const TileOperand &dst, BinaryFunction opcode, const TileOperand &first, const TileOperand &second)
225{
226 auto impl_dst = dst.create_impl_operand(_impl.get());
227 auto impl_first = first.create_impl_operand(_impl.get());
228 auto impl_second = second.create_impl_operand(_impl.get());
229
230 _impl->op_binary_elementwise_function(impl_dst, opcode, impl_first, impl_second);
231}
232
233void KernelWriter::op_ternary_elementwise_function(const TileOperand &dst, TernaryFunction opcode, const TileOperand &first, const TileOperand &second, const TileOperand &third)
234{
235 auto impl_dst = dst.create_impl_operand(_impl.get());
236 auto impl_first = first.create_impl_operand(_impl.get());
237 auto impl_second = second.create_impl_operand(_impl.get());
238 auto impl_third = third.create_impl_operand(_impl.get());
239
240 _impl->op_ternary_elementwise_function(impl_dst, opcode, impl_first, impl_second, impl_third);
241}
242
243void KernelWriter::op_if(const TileOperand &lhs, BinaryOp op, const TileOperand &rhs, const std::function<void()> &body)
244{
245 auto impl_lhs = lhs.create_impl_operand(_impl.get());
246 auto impl_rhs = rhs.create_impl_operand(_impl.get());
247
248 _impl->op_if_header(impl_lhs, op, impl_rhs);
249 _impl->compound_statement_begin();
250 body();
251 _impl->compound_statement_end();
252}
253
254void KernelWriter::op_else_if(const TileOperand &lhs, BinaryOp op, const TileOperand &rhs, const std::function<void()> &body)
255{
256 auto impl_lhs = lhs.create_impl_operand(_impl.get());
257 auto impl_rhs = rhs.create_impl_operand(_impl.get());
258
259 _impl->op_else_if_header(impl_lhs, op, impl_rhs);
260 _impl->compound_statement_begin();
261 body();
262 _impl->compound_statement_end();
263}
264
265void KernelWriter::op_else(const std::function<void()> &body)
266{
267 _impl->op_else_header();
268 _impl->compound_statement_begin();
269 body();
270 _impl->compound_statement_end();
271}
272
Nikolaj Jensenfab6c212023-06-27 14:13:24 +0100273void 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 +0100274{
275 auto impl_var_name = var_name.create_impl_operand(_impl.get());
276 auto impl_cond_value_name = cond_value_name.create_impl_operand(_impl.get());
Nikolaj Jensenfab6c212023-06-27 14:13:24 +0100277 auto impl_update_var_name = update_var_name.create_impl_operand(_impl.get());
Nikolaj Jensen5ff48022023-06-27 14:13:24 +0100278 auto impl_update_value_name = update_value_name.create_impl_operand(_impl.get());
279
Nikolaj Jensenfab6c212023-06-27 14:13:24 +0100280 _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 +0100281 _impl->compound_statement_begin();
282 body();
283 _impl->compound_statement_end();
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100284}
285
286// =================================================================================================
287// Misc
288// =================================================================================================
289
290void KernelWriter::op_get_global_id(TileOperand &dst, int32_t dim)
291{
292 _impl->op_get_global_id(prototype::Operand(dst.name()), dim);
293}
294
Nikolaj Jensen5ff48022023-06-27 14:13:24 +0100295void KernelWriter::op_return()
296{
297 _impl->op_return();
298}
299
Viet-Hoa Dobd4f6b92023-05-30 09:34:32 +0100300// =================================================================================================
301// Code generation
302// =================================================================================================
303
304std::string KernelWriter::generate_code()
305{
306 return prototype::generate_code(*_kernel->impl(), _kernel->name());
307}
308
309} // namespace ckw