diff options
Diffstat (limited to 'compute_kernel_writer/src/cl/CLTensorArgument.cpp')
-rw-r--r-- | compute_kernel_writer/src/cl/CLTensorArgument.cpp | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/compute_kernel_writer/src/cl/CLTensorArgument.cpp b/compute_kernel_writer/src/cl/CLTensorArgument.cpp new file mode 100644 index 0000000000..e53de2830d --- /dev/null +++ b/compute_kernel_writer/src/cl/CLTensorArgument.cpp @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2023 Arm Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "src/cl/CLTensorArgument.h" + +#include "ckw/Error.h" + +#include "src/cl/CLHelpers.h" +#include "src/cl/CLTensorComponent.h" +#include "src/ITensorArgument.h" +#include "src/ITensorComponent.h" +#include "src/types/TensorComponentType.h" + +#include <algorithm> +#include <vector> + +namespace ckw +{ +CLTensorArgument::CLTensorArgument(const std::string &name, const TensorInfo &info, bool return_dims_by_value) +{ + _return_dims_by_value = return_dims_by_value; + _basename = name; + _info = info; +} + +CLTensorArgument::~CLTensorArgument() = default; + +CLTensorComponent &CLTensorArgument::cl_component(TensorComponentType x) +{ + // Return the component if it has already been created. + { + const auto it = + std::find_if(_components_used.begin(), _components_used.end(), + [=](const std::unique_ptr<CLTensorComponent> &item) { return item->component_type() == x; }); + + if (it != _components_used.end()) + { + return **it; + } + } + + if (_return_dims_by_value) + { + uint32_t component_type = static_cast<uint32_t>(x); + + const bool is_dimension = (component_type & static_cast<uint32_t>(TensorComponentBitmask::Dimension)) != 0; + const bool is_folded_dimensions = + (component_type & static_cast<uint32_t>(TensorComponentBitmask::FoldedDimensions)) != 0; + + constexpr auto bitmask_all = static_cast<uint32_t>(TensorComponentIndexBitmask::All); + constexpr auto bitmask_index_0 = static_cast<uint32_t>(TensorComponentIndexBitmask::Index0); +#ifdef COMPUTE_KERNEL_WRITER_ASSERTS_ENABLED + constexpr auto bitmask_index_1 = static_cast<uint32_t>(TensorComponentIndexBitmask::Index1); + constexpr auto bitmask_index_2 = static_cast<uint32_t>(TensorComponentIndexBitmask::Index2); + constexpr auto bitmask_index_3 = static_cast<uint32_t>(TensorComponentIndexBitmask::Index3); +#endif // COMPUTE_KERNEL_WRITER_ASSERTS_ENABLED + + // Make sure that the encoding of component type hasn't changed and each nibble is 4 bits apart. + CKW_ASSERT(bitmask_all == (bitmask_index_0 | bitmask_index_1 | bitmask_index_2 | bitmask_index_3)); + CKW_ASSERT(bitmask_index_0 == bitmask_index_1 >> 4); + CKW_ASSERT(bitmask_index_1 == bitmask_index_2 >> 4); + CKW_ASSERT(bitmask_index_2 == bitmask_index_3 >> 4); + + // If we have a dimension or folded dimensions, we can return the corresponding value if it is not dynamic (not equal to -1) + if (is_dimension == true || is_folded_dimensions == true) + { + component_type = component_type & bitmask_all; + + int32_t idx = 1; + for (int32_t i = 0; i < tensor_component_index_max_count; ++i) + { + uint32_t dim_idx = component_type & bitmask_index_0; + + if (dim_idx == 0) + { + // Stop at the first nibble containing 0 + break; + } + + // Subtract - 1. Please refer to the TensorComponentIndexBitmask documentation + dim_idx -= 1; + + // Get the dimension value + const int32_t dim_val = _info.shape()[dim_idx]; + + if (dim_val == kDynamicTensorDimensionValue) + { + // We cannot return the dimension by value if it is dynamic. + // Therefore, force the idx variable to kDynamicTensorDimensionValue and break the loop. + idx = kDynamicTensorDimensionValue; + break; + } + + idx *= dim_val; + + // Go to the next nibble + component_type >>= 4; + } + + if (idx != kDynamicTensorDimensionValue) + { + _components_used.emplace_back(std::make_unique<CLTensorComponent>(*this, x, idx)); + + return *_components_used.back(); + } + } + } + + _components_used.emplace_back(std::make_unique<CLTensorComponent>(*this, x)); + + return *_components_used.back(); +} + +ITile &CLTensorArgument::component(TensorComponentType x) +{ + return cl_component(x); +} + +TensorStorageVariable &CLTensorArgument::storage(TensorStorageType x) +{ + // Return the storage if it has already been created. + { + const auto it = std::find_if(_storages_used.begin(), _storages_used.end(), + [=](const TensorStorageVariable &item) { return item.type == x; }); + + if (it != _storages_used.end()) + { + return *it; + } + } + + TensorStorageVariable t; + t.val = create_storage_name(x); + t.type = x; + + _storages_used.emplace_back(t); + + return _storages_used.back(); +} + +std::string CLTensorArgument::create_storage_name(TensorStorageType x) const +{ + std::string var_name = _basename; + + switch (x) + { + case TensorStorageType::BufferUint8Ptr: + var_name += "_ptr"; + break; + case TensorStorageType::Texture2dReadOnly: + case TensorStorageType::Texture2dWriteOnly: + var_name += "_img2d"; + break; + default: + CKW_ASSERT_FAILED_MSG("Unsupported tensor storage"); + return ""; + } + + return var_name; +} + +std::vector<TensorStorageVariable> CLTensorArgument::storages() const +{ + std::vector<TensorStorageVariable> storages; + storages.reserve(_storages_used.size()); + + std::copy(_storages_used.begin(), _storages_used.end(), std::back_inserter(storages)); + + return storages; +} + +std::vector<const ITensorComponent *> CLTensorArgument::components() const +{ + std::vector<const ITensorComponent *> components; + + for (const auto &component : _components_used) + { + if (component->is_assignable()) + { + components.push_back(component.get()); + } + } + + return components; +} +} // namespace ckw |