blob: ed1c5bd6871b9900c01bbfe0f97bc2b2938750de [file] [log] [blame]
Gian Marco Iodiceebfdb5a2023-07-07 11:25:57 +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 "src/cl/CLTensorArgument.h"
26#include "ckw/Error.h"
27#include "src/cl/CLHelpers.h"
28#include "src/types/TensorComponentType.h"
29
30#include <algorithm>
31#include <vector>
32
33namespace ckw
34{
35CLTensorArgument::CLTensorArgument(const std::string &name, const TensorInfo &info, bool return_dims_by_value)
36{
37 _return_dims_by_value = return_dims_by_value;
38 _basename = name;
39 _info = info;
40}
41
42TileVariable CLTensorArgument::component(TensorComponentType x)
43{
44 if(_return_dims_by_value)
45 {
46 uint32_t component_type = static_cast<uint32_t>(x);
47
48 const bool is_dimension = (component_type & static_cast<uint32_t>(TensorComponentBitmask::Dimension)) != 0;
49 const bool is_folded_dimensions = (component_type & static_cast<uint32_t>(TensorComponentBitmask::FoldedDimensions)) != 0;
50
51 constexpr auto bitmask_all = static_cast<uint32_t>(TensorComponentIndexBitmask::All);
52 constexpr auto bitmask_index_0 = static_cast<uint32_t>(TensorComponentIndexBitmask::Index0);
53#ifdef COMPUTE_KERNEL_WRITER_ASSERTS_ENABLED
54 constexpr auto bitmask_index_1 = static_cast<uint32_t>(TensorComponentIndexBitmask::Index1);
55 constexpr auto bitmask_index_2 = static_cast<uint32_t>(TensorComponentIndexBitmask::Index2);
56 constexpr auto bitmask_index_3 = static_cast<uint32_t>(TensorComponentIndexBitmask::Index3);
57#endif // COMPUTE_KERNEL_WRITER_ASSERTS_ENABLED
58
59 // Make sure that the encoding of component type hasn't changed and each nibble is 4 bits apart.
60 CKW_ASSERT(bitmask_all == (bitmask_index_0 | bitmask_index_1 | bitmask_index_2 | bitmask_index_3));
61 CKW_ASSERT(bitmask_index_0 == bitmask_index_1 >> 4);
62 CKW_ASSERT(bitmask_index_1 == bitmask_index_2 >> 4);
63 CKW_ASSERT(bitmask_index_2 == bitmask_index_3 >> 4);
64
65 // If we have a dimension or folded dimensions, we can return the corresponding value if it is not dynamic (not equal to -1)
66 if(is_dimension == true || is_folded_dimensions == true)
67 {
68 component_type = component_type & bitmask_all;
69
70 int32_t idx = 1;
71 for(int32_t i = 0; i < tensor_component_index_max_count; ++i)
72 {
73 uint32_t dim_idx = component_type & bitmask_index_0;
74
75 if(dim_idx == 0)
76 {
77 // Stop at the first nibble containing 0
78 break;
79 }
80
81 // Subtract - 1. Please refer to the TensorComponentIndexBitmask documentation
82 dim_idx -= 1;
83
84 // Get the dimension value
85 const int32_t dim_val = _info.shape()[dim_idx];
86
87 if(dim_val == kDynamicTensorDimensionValue)
88 {
89 // We cannot return the dimension by value if it is dynamic.
90 // Therefore, force the idx variable to kDynamicTensorDimensionValue and break the loop.
91 idx = kDynamicTensorDimensionValue;
92 break;
93 }
94
95 idx *= dim_val;
96
97 // Go to the next nibble
98 component_type >>= 4;
99 }
100
101 if(idx != kDynamicTensorDimensionValue)
102 {
103 TileVariable t;
104 t.str = std::to_string(idx);
105 t.desc.dt = DataType::Uint32;
106 t.desc.len = 1;
107 return t;
108 }
109 }
110 }
111
112 auto it = std::find(_components_used.begin(), _components_used.end(), x);
113
114 // Add to the list of used components if not present yet
115 if(it == _components_used.end())
116 {
117 _components_used.push_back(x);
118 }
119
120 TileVariable t;
121 t.str = create_component_name(x);
122 t.desc.dt = DataType::Int32;
123 t.desc.len = 1;
124 return t;
125}
126
127TensorStorageVariable CLTensorArgument::storage(TensorStorageType x)
128{
129 if(std::find(_storages_used.begin(), _storages_used.end(), x) == _storages_used.end())
130 {
131 _storages_used.push_back(x);
132 }
133
134 TensorStorageVariable t;
135 t.val = create_storage_name(x);
136 t.type = cl_get_variable_storagetype_as_string(x);
137
138 return t;
139}
140
141std::string CLTensorArgument::create_storage_name(TensorStorageType x) const
142{
143 std::string var_name = _basename;
144
145 switch(x)
146 {
147 case TensorStorageType::BufferUint8Ptr:
148 var_name += "_ptr";
149 break;
150 case TensorStorageType::Texture2dReadOnly:
151 case TensorStorageType::Texture2dWriteOnly:
152 var_name += "_img2d";
153 break;
154 default:
155 CKW_ASSERT_FAILED_MSG("Unsupported tensor storage");
156 return "";
157 }
158
159 return var_name;
160}
161
162std::string CLTensorArgument::create_component_name(TensorComponentType x) const
163{
164 std::string var_name = _basename;
165
166 switch(x)
167 {
168 case TensorComponentType::OffsetFirstElement:
169 var_name += "_offset_first_element";
170 break;
171 case TensorComponentType::Stride0:
172 var_name += "_stride0";
173 break;
174 case TensorComponentType::Stride1:
175 var_name += "_stride1";
176 break;
177 case TensorComponentType::Stride2:
178 var_name += "_stride2";
179 break;
180 case TensorComponentType::Stride3:
181 var_name += "_stride3";
182 break;
183 case TensorComponentType::Stride4:
184 var_name += "_stride4";
185 break;
186 case TensorComponentType::Dim0:
187 var_name += "_dim0";
188 break;
189 case TensorComponentType::Dim1:
190 var_name += "_dim1";
191 break;
192 case TensorComponentType::Dim2:
193 var_name += "_dim2";
194 break;
195 case TensorComponentType::Dim3:
196 var_name += "_dim3";
197 break;
198 case TensorComponentType::Dim4:
199 var_name += "_dim4";
200 break;
201 case TensorComponentType::Dim1xDim2:
202 var_name += "_dim1xdim2";
203 break;
204 case TensorComponentType::Dim2xDim3:
205 var_name += "_dim2xdim3";
206 break;
207 case TensorComponentType::Dim1xDim2xDim3:
208 var_name += "_dim1xdim2xdim3";
209 break;
210 default:
211 COMPUTE_KERNEL_WRITER_ERROR_ON_MSG("Unsupported tensor component");
212 return "";
213 }
214
215 return var_name;
216}
217
218std::vector<TensorStorageVariable> CLTensorArgument::storages() const
219{
220 std::vector<TensorStorageVariable> storages;
221 for(auto &val : _storages_used)
222 {
223 TensorStorageVariable t;
224 t.val = create_storage_name(val);
225 t.type = cl_get_variable_storagetype_as_string(val);
226 storages.push_back(t);
227 }
228
229 return storages;
230}
231
232std::vector<TileVariable> CLTensorArgument::components() const
233{
234 std::vector<TileVariable> components;
235
236 for(auto &val : _components_used)
237 {
238 TileVariable t;
239 t.str = create_component_name(val);
240 t.desc.dt = DataType::Int32;
241 t.desc.len = 1;
242 components.push_back(t);
243 }
244
245 return components;
246}
247} // namespace ckw