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

#include "arm_compute/core/ITensorInfo.h"
#include "arm_compute/runtime/NEON/NEScheduler.h"
#include "src/core/CPP/Validate.h"
#include "src/core/cpu/kernels/internal/CpuDepthwiseConv2dAssemblyWrapperKernel.h"
#include "src/core/helpers/AutoConfiguration.h"
#include "src/core/utils/AssemblyUtils.h"

namespace arm_compute
{
namespace cpu
{
struct CpuDepthwiseConv2dAssemblyDispatch::LocalImpl
{
    std::unique_ptr<kernels::CpuDepthwiseConv2dAssemblyWrapperKernel> asm_kernel{ nullptr };
    bool                                                              is_prepared{ false };
    experimental::MemoryRequirements                                  mem_req{};
};

#ifndef DOXYGEN_SKIP_THIS
CpuDepthwiseConv2dAssemblyDispatch::CpuDepthwiseConv2dAssemblyDispatch()
    : _pImpl(std::make_unique<LocalImpl>())
{
}
#endif /* DOXYGEN_SKIP_THIS */

CpuDepthwiseConv2dAssemblyDispatch::~CpuDepthwiseConv2dAssemblyDispatch() = default;

void CpuDepthwiseConv2dAssemblyDispatch::configure(const ITensorInfo     *src,
                                                   const ITensorInfo     *weights,
                                                   const ITensorInfo     *bias,
                                                   ITensorInfo           *dst,
                                                   const ConvolutionInfo &info)
{
    const CPUInfo     &ci          = NEScheduler::get().cpu_info();
    const unsigned int num_threads = NEScheduler::get().num_threads();
    _pImpl->is_prepared            = false;

    // If we don't support a combination of data types, silently return: it is the caller's responsibility to check if configure() was successful via is_configured()
    if(!CpuDepthwiseConv2dAssemblyDispatch::validate(src, weights, bias, dst, info))
    {
        return;
    }

    auto dwc_wrapper = std::make_unique<kernels::CpuDepthwiseConv2dAssemblyWrapperKernel>();
    ARM_COMPUTE_ERROR_ON(dwc_wrapper == nullptr);
    dwc_wrapper->configure(src, weights, bias, dst, info, ci);

    // Compute memory requirements for assembly kernels
    constexpr size_t alignment = 4096;
    _pImpl->mem_req.push_back({ TensorType::ACL_INT_0, dwc_wrapper->get_working_size(num_threads, src->dimension(0)), alignment });
    _pImpl->mem_req.push_back({ TensorType::ACL_INT_1, dwc_wrapper->get_storage_size(), alignment });
    _pImpl->asm_kernel = std::move(dwc_wrapper);
}

Status CpuDepthwiseConv2dAssemblyDispatch::validate(const ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *bias, const ITensorInfo *dst, const ConvolutionInfo &info)
{
    return kernels::CpuDepthwiseConv2dAssemblyWrapperKernel::validate(src, weights, bias, dst, info);
}

experimental::MemoryRequirements CpuDepthwiseConv2dAssemblyDispatch::workspace() const
{
    return _pImpl->mem_req;
}

bool CpuDepthwiseConv2dAssemblyDispatch::is_activation_supported(const ActivationLayerInfo &activation)
{
    arm_gemm::Activation act = assembly_utils::map_to_arm_gemm_activation(activation);
    return act.type != arm_gemm::Activation::Type::None;
}

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

    prepare(tensors);

    NEScheduler::get().schedule_op(_pImpl->asm_kernel.get(), Window::DimY, _pImpl->asm_kernel->window(), tensors);
}

void CpuDepthwiseConv2dAssemblyDispatch::prepare(ITensorPack &tensors)
{
    if(!_pImpl->is_prepared)
    {
        // Pack weights and bias
        const ITensor *weights = tensors.get_const_tensor(TensorType::ACL_SRC_1);
        const ITensor *bias    = tensors.get_const_tensor(TensorType::ACL_SRC_2);
        ITensor       *storage = tensors.get_tensor(TensorType::ACL_INT_1);

        const auto weights_ptr    = weights->buffer() + weights->info()->offset_first_element_in_bytes();
        const auto bias_ptr       = (bias) ? bias->buffer() + bias->info()->offset_first_element_in_bytes() : nullptr;
        auto       parameters_ptr = storage->buffer() + storage->info()->offset_first_element_in_bytes();

        const auto weights_shape   = weights->info()->tensor_shape();
        const auto weights_padding = weights->info()->padding();

        const size_t ld_weights_col = weights_shape[0] + weights_padding.left + weights_padding.right;
        const size_t ld_weights_row = ld_weights_col * (weights_shape[1] + weights_padding.top + weights_padding.bottom);
        _pImpl->asm_kernel->pack_parameters(parameters_ptr, bias_ptr, weights_ptr, ld_weights_col, ld_weights_row);

        weights->mark_as_unused();
        if(bias != nullptr)
        {
            bias->mark_as_unused();
        }
        _pImpl->is_prepared = true;
    }
}
} // namespace cpu
} // namespace arm_compute
