/*
 * Copyright (c) 2021, 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/cpu/operators/CpuPool2d.h"

#include "arm_compute/core/ITensor.h"
#include "arm_compute/core/TensorInfo.h"
#include "arm_compute/runtime/NEON/NEScheduler.h"
#include "src/common/utils/Log.h"
#include "src/cpu/kernels/CpuPool2dKernel.h"
#include "src/cpu/kernels/internal/CpuPool2dAssemblyWrapperKernel.h"

using namespace arm_compute::experimental;

namespace arm_compute
{
namespace cpu
{
CpuPool2d::CpuPool2d()
    : _pooling_layer_kernel(),
      _asm_glue(),
      _is_global_pooling_layer(false),
      _use_kernel_indices(false),
      _data_layout(DataLayout::NCHW),
      _aux_mem(1)
{
}

CpuPool2d::~CpuPool2d() = default;

void CpuPool2d::configure(ITensorInfo *src, ITensorInfo *dst, const PoolingLayerInfo &pool_info, ITensorInfo *indices)
{
    ARM_COMPUTE_LOG_PARAMS(src, dst, pool_info, indices);

    // Check if we can run assembly kernels. Currently, indices are not supported by those kernels
    const bool run_optimised = bool(kernels::CpuPool2dAssemblyWrapperKernel::validate(src, dst, pool_info)) && (indices == nullptr);

    // Get data layout
    _data_layout = pool_info.data_layout == DataLayout::UNKNOWN ? src->data_layout() : pool_info.data_layout;

    // Check if we have Global Pooling Layer
    const unsigned int idx_width  = get_data_layout_dimension_index(_data_layout, DataLayoutDimension::WIDTH);
    const unsigned int idx_height = get_data_layout_dimension_index(_data_layout, DataLayoutDimension::HEIGHT);
    _is_global_pooling_layer      = (src->dimension(idx_width) == pool_info.pool_size.width) && (src->dimension(idx_height) == pool_info.pool_size.height);
    _use_kernel_indices           = pool_info.use_kernel_indices;

    if(run_optimised)
    {
        const CPUInfo     &ci          = NEScheduler::get().cpu_info();
        const unsigned int num_threads = NEScheduler::get().num_threads();

        auto pooling_wrapper = std::make_unique<kernels::CpuPool2dAssemblyWrapperKernel>();
        ARM_COMPUTE_ERROR_ON(pooling_wrapper == nullptr);
        pooling_wrapper->configure(src, dst, pool_info, ci);

        // Get kernel's memory requirements
        constexpr size_t alignment      = 4096;
        const size_t     workspace_size = pooling_wrapper->get_working_size(num_threads);
        _aux_mem[0]                     = MemoryInfo(TensorType::ACL_INT_0, MemoryLifetime::Temporary, workspace_size, alignment);

        _asm_glue = std::move(pooling_wrapper);
    }
    else
    {
        // Configure pooling kernel
        auto k = std::make_unique<kernels::CpuPool2dKernel>();
        k->configure(src, dst, pool_info, indices);
        _pooling_layer_kernel = std::move(k);
    }
}

Status CpuPool2d::validate(const ITensorInfo *src, const ITensorInfo *dst, const PoolingLayerInfo &pool_info, const ITensorInfo *indices)
{
    const bool run_optimised = bool(kernels::CpuPool2dAssemblyWrapperKernel::validate(src, dst, pool_info)) && (indices == nullptr);

    if(run_optimised)
    {
        return Status{};
    }

    return kernels::CpuPool2dKernel::validate(src, dst, pool_info, indices);
}

void CpuPool2d::run(ITensorPack &tensors)
{
    ARM_COMPUTE_ERROR_ON_MSG(tensors.empty(), "No tensors provided");

    if(_asm_glue)
    {
        const auto hints = (_is_global_pooling_layer) ? Window::DimX : Window::DimY;
        NEScheduler::get().schedule_op(_asm_glue.get(), hints, _asm_glue->window(), tensors);
    }
    else
    {
        switch(_data_layout)
        {
            case DataLayout::NCHW:
                NEScheduler::get().schedule_op(_pooling_layer_kernel.get(), _is_global_pooling_layer ? Window::DimZ : Window::DimY, _pooling_layer_kernel->window(), tensors);
                break;
            case DataLayout::NHWC:
                NEScheduler::get().schedule_op(_pooling_layer_kernel.get(), (_use_kernel_indices ? Window::DimY : Window::DimX), _pooling_layer_kernel->window(), tensors);
                break;
            default:
                ARM_COMPUTE_ERROR("Data layout not supported");
        }
    }
}

experimental::MemoryRequirements CpuPool2d::workspace() const
{
    return _aux_mem;
}
} // namespace cpu
} // namespace arm_compute
