/*
 * Copyright (c) 2017-2019 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 "arm_compute/runtime/CL/functions/CLDepthwiseConvolutionLayer.h"

#include "arm_compute/core/CL/ICLTensor.h"
#include "arm_compute/core/CL/kernels/CLDepthwiseConvolutionLayer3x3NCHWKernel.h"
#include "arm_compute/core/CL/kernels/CLDepthwiseConvolutionLayer3x3NHWCKernel.h"
#include "arm_compute/core/Helpers.h"
#include "arm_compute/core/PixelValue.h"
#include "arm_compute/core/utils/misc/ShapeCalculator.h"
#include "arm_compute/core/utils/quantization/AsymmHelpers.h"
#include "arm_compute/runtime/CL/CLScheduler.h"
#include "support/ToolchainSupport.h"

namespace arm_compute
{
using namespace arm_compute::misc;
using namespace arm_compute::misc::shape_calculator;

namespace
{
Status validate_arguments_3x3(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output, const PadStrideInfo &conv_info,
                              unsigned int depth_multiplier, ActivationLayerInfo act_info, GPUTarget gpu_target, const Size2D &dilation)
{
    // This function should be removed and incorporated inside CLDepthwiseConvolutionLayerInternal3x3 once CLDepthwiseConvolutionLayer3x3 is properly removed
    ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input, weights, output);
    ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::QASYMM8, DataType::F16, DataType::F32);
    ARM_COMPUTE_RETURN_ERROR_ON(input->data_layout() == DataLayout::UNKNOWN);

    const bool                      is_quantized           = is_data_type_quantized_asymmetric(input->data_type());
    const bool                      is_nhwc                = input->data_layout() == DataLayout::NHWC;
    const bool                      needs_permute          = is_nhwc && (depth_multiplier > 1);
    const bool                      needs_weights_reshape  = is_nhwc && (depth_multiplier == 1) && is_quantized;
    const bool                      is_stride_1            = ((conv_info.stride().first == conv_info.stride().second) && (conv_info.stride().first == 1));
    const bool                      is_stride_1_dilation_1 = (is_stride_1 && dilation.x() == 1 && dilation.y() == 1);
    const bool                      is_dot8_supported      = dot8_supported(CLKernelLibrary::get().get_device());
    DepthwiseConvolutionReshapeInfo info;
    info.c0        = 4;
    info.transpose = is_stride_1_dilation_1 && is_dot8_supported;

    TensorInfo output_multipliers_shifts_info(TensorInfo(TensorShape(1U), 1, DataType::S32));
    if(is_quantized)
    {
        if(is_data_type_quantized_per_channel(weights->data_type()))
        {
            ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(weights, 1, DataType::QSYMM8_PER_CHANNEL);

            const size_t idx_c = get_data_layout_dimension_index(weights->data_layout(), DataLayoutDimension::CHANNEL);
            output_multipliers_shifts_info.set_tensor_shape(TensorShape(weights->dimension(idx_c)));
        }
        else
        {
            ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, weights);
        }
    }

    if(needs_permute)
    {
        TensorShape permuted_input_shape   = input->tensor_shape();
        TensorShape permuted_weights_shape = weights->tensor_shape();
        TensorShape permuted_output_shape  = shape_calculator::compute_depthwise_convolution_shape(*input, *weights, conv_info, depth_multiplier, dilation);

        permute(permuted_input_shape, PermutationVector(1U, 2U, 0U));
        permute(permuted_weights_shape, PermutationVector(1U, 2U, 0U));
        permute(permuted_output_shape, PermutationVector(1U, 2U, 0U));

        const TensorInfo permuted_input   = input->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(permuted_input_shape).set_data_layout(DataLayout::NCHW);
        const TensorInfo permuted_weights = weights->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(permuted_weights_shape).set_data_layout(DataLayout::NCHW);
        const TensorInfo permuted_output  = output->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(permuted_output_shape).set_data_layout(DataLayout::NCHW);

        ARM_COMPUTE_RETURN_ON_ERROR(CLDepthwiseConvolutionLayer3x3NCHWKernel::validate(&permuted_input, &permuted_weights, biases, &permuted_output,
                                                                                       conv_info, depth_multiplier, act_info, gpu_target,
                                                                                       dilation, &output_multipliers_shifts_info, &output_multipliers_shifts_info));
    }
    else if(is_nhwc)
    {
        if(needs_weights_reshape)
        {
            auto reshaped_weights_shape = arm_compute::misc::shape_calculator::compute_reshaped_depthwise_weights_shape(*weights, info);
            ARM_COMPUTE_RETURN_ON_ERROR(CLDepthwiseConvolutionLayer3x3NHWCKernel::validate(input, &weights->clone()->set_tensor_shape(reshaped_weights_shape), biases,
                                                                                           output, conv_info, depth_multiplier, act_info,
                                                                                           dilation, &output_multipliers_shifts_info, &output_multipliers_shifts_info));
        }
        else
        {
            ARM_COMPUTE_RETURN_ON_ERROR(CLDepthwiseConvolutionLayer3x3NHWCKernel::validate(input, weights, biases, output, conv_info, depth_multiplier, act_info,
                                                                                           dilation, &output_multipliers_shifts_info, &output_multipliers_shifts_info));
        }
    }
    else
    {
        ARM_COMPUTE_RETURN_ON_ERROR(CLDepthwiseConvolutionLayer3x3NCHWKernel::validate(input, weights, biases, output, conv_info, depth_multiplier, act_info, gpu_target,
                                                                                       dilation, &output_multipliers_shifts_info, &output_multipliers_shifts_info));
    }
    return Status{};
}
} // namespace

CLDepthwiseConvolutionLayer3x3::CLDepthwiseConvolutionLayer3x3(std::shared_ptr<IMemoryManager> memory_manager)
    : _func(std::move(memory_manager))
{
}

void CLDepthwiseConvolutionLayer3x3::configure(ICLTensor *input, const ICLTensor *weights, const ICLTensor *biases, ICLTensor *output, const PadStrideInfo &conv_info, unsigned int depth_multiplier,
                                               ActivationLayerInfo act_info, const Size2D &dilation)
{
    _func.configure(input, weights, biases, output, conv_info, depth_multiplier, act_info, dilation);
}

Status CLDepthwiseConvolutionLayer3x3::validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output, const PadStrideInfo &conv_info,
                                                unsigned int depth_multiplier, ActivationLayerInfo act_info, GPUTarget gpu_target, const Size2D &dilation)
{
    return validate_arguments_3x3(input, weights, biases, output, conv_info, depth_multiplier, act_info, gpu_target, dilation);
}

void CLDepthwiseConvolutionLayer3x3::run()
{
    _func.run();
}

void CLDepthwiseConvolutionLayer3x3::prepare()
{
    _func.prepare();
}

CLDepthwiseConvolutionLayer::CLDepthwiseConvolutionLayerGeneric::CLDepthwiseConvolutionLayerGeneric(std::shared_ptr<IMemoryManager> memory_manager)
    : _memory_group(std::move(memory_manager)),
      _dwc_native_kernel(),
      _permute_input_to_nhwc(),
      _permute_weights_to_nhwc(),
      _permute_output_to_nchw(),
      _permuted_input(),
      _permuted_weights(),
      _permuted_output(),
      _output_multipliers(),
      _output_shifts(),
      _original_weights(),
      _input(),
      _output(),
      _needs_permute(false),
      _is_prepared(false),
      _is_quantized(false)
{
}

void CLDepthwiseConvolutionLayer::CLDepthwiseConvolutionLayerGeneric::configure(ICLTensor *input, const ICLTensor *weights, const ICLTensor *biases, ICLTensor *output, const PadStrideInfo &conv_info,
                                                                                unsigned int depth_multiplier, const ActivationLayerInfo &act_info, const Size2D &dilation)
{
    ARM_COMPUTE_ERROR_ON_NULLPTR(input, weights, output);
    ARM_COMPUTE_ERROR_THROW_ON(CLDepthwiseConvolutionLayer::validate(input->info(),
                                                                     weights->info(),
                                                                     biases != nullptr ? biases->info() : nullptr,
                                                                     output->info(),
                                                                     conv_info,
                                                                     depth_multiplier,
                                                                     act_info,
                                                                     dilation));

    _is_quantized     = is_data_type_quantized(input->info()->data_type());
    _is_prepared      = false;
    _original_weights = weights;
    _input            = input;
    _output           = output;
    _needs_permute    = input->info()->data_layout() == DataLayout::NCHW;

    ICLTensor       *input_to_use   = input;
    const ICLTensor *weights_to_use = weights;
    ICLTensor       *output_to_use  = output;
    if(_needs_permute)
    {
        _memory_group.manage(&_permuted_input);
        _memory_group.manage(&_permuted_output);

        // Configure the function to transform the input tensor from NCHW -> NHWC
        _permute_input_to_nhwc.configure(input, &_permuted_input, PermutationVector(2U, 0U, 1U));
        _permuted_input.info()->set_data_layout(DataLayout::NHWC);

        // Configure the function to transform the weights tensor from IHW -> HWI
        _permute_weights_to_nhwc.configure(weights, &_permuted_weights, PermutationVector(2U, 0U, 1U));
        _permuted_weights.info()->set_data_layout(DataLayout::NHWC);

        // Set output quantization info before dwc kernel configure
        _permuted_output.info()->set_quantization_info(output->info()->quantization_info());

        input_to_use   = &_permuted_input;
        weights_to_use = &_permuted_weights;
        output_to_use  = &_permuted_output;
    }

    CLTensor *output_multipliers_to_use = nullptr;
    CLTensor *output_shifts_to_use      = nullptr;
    if(_is_quantized)
    {
        const size_t idx_c       = get_data_layout_dimension_index(weights->info()->data_layout(), DataLayoutDimension::CHANNEL);
        const size_t num_filters = (is_data_type_quantized_per_channel(weights->info()->data_type())) ? weights->info()->dimension(idx_c) : 1;

        _output_multipliers.allocator()->init(TensorInfo(TensorShape(num_filters), 1, DataType::S32));
        _output_shifts.allocator()->init(TensorInfo(TensorShape(num_filters), 1, DataType::S32));

        output_multipliers_to_use = &_output_multipliers;
        output_shifts_to_use      = &_output_shifts;
    }

    DWCWeightsKernelInfo dwc_weights_info;
    dwc_weights_info.n0 = (depth_multiplier == 1) ? 8 : 1;
    DWCKernelInfo dwc_info;
    dwc_info.activation_info = act_info;
    _dwc_native_kernel.configure(input_to_use, weights_to_use, biases, output_to_use,
                                 dwc_weights_info, dwc_info, conv_info, depth_multiplier, dilation,
                                 output_multipliers_to_use, output_shifts_to_use);

    if(_needs_permute)
    {
        _permuted_input.allocator()->allocate();

        // Configure the function to transform the convoluted output to NCHW format
        _permuted_output.info()->set_data_layout(DataLayout::NCHW);
        _permute_output_to_nchw.configure(&_permuted_output, output, PermutationVector(1U, 2U, 0U));
        _permuted_output.allocator()->allocate();
    }

    if(_is_quantized)
    {
        _output_multipliers.allocator()->allocate();
        _output_shifts.allocator()->allocate();
    }
}

Status CLDepthwiseConvolutionLayer::CLDepthwiseConvolutionLayerGeneric::validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output,
                                                                                 const PadStrideInfo &conv_info,
                                                                                 unsigned int depth_multiplier, const ActivationLayerInfo &act_info, const Size2D &dilation)
{
    ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_LAYOUT(input, output);
    const size_t idx_w = get_data_layout_dimension_index(input->data_layout(), DataLayoutDimension::WIDTH);
    const size_t idx_h = get_data_layout_dimension_index(input->data_layout(), DataLayoutDimension::HEIGHT);

    ARM_COMPUTE_RETURN_ERROR_ON(weights->dimension(idx_w) + (weights->dimension(idx_w) - 1) * (dilation.x() - 1) > input->dimension(idx_w) + conv_info.pad_left() + conv_info.pad_right());
    ARM_COMPUTE_RETURN_ERROR_ON(weights->dimension(idx_h) + (weights->dimension(idx_h) - 1) * (dilation.y() - 1) > input->dimension(idx_h) + conv_info.pad_top() + conv_info.pad_bottom());

    DWCWeightsKernelInfo dwc_weights_info;
    dwc_weights_info.n0 = (depth_multiplier == 1) ? 8 : 1;
    DWCKernelInfo dwc_info;
    dwc_info.activation_info = act_info;

    const bool needs_permute = input->data_layout() == DataLayout::NCHW;

    const bool is_quantized = is_data_type_quantized(input->data_type());

    TensorInfo output_multipliers_shifts_info(TensorInfo(TensorShape(1U), 1, DataType::S32));
    if(is_quantized)
    {
        if(is_data_type_quantized_per_channel(weights->data_type()))
        {
            ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(weights, 1, DataType::QSYMM8_PER_CHANNEL);

            const size_t idx_c = get_data_layout_dimension_index(weights->data_layout(), DataLayoutDimension::CHANNEL);
            output_multipliers_shifts_info.set_tensor_shape(TensorShape(weights->dimension(idx_c)));
        }
        else
        {
            ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(input, weights);
        }
    }

    if(needs_permute)
    {
        TensorShape permuted_input_shape   = input->tensor_shape();
        TensorShape permuted_weights_shape = weights->tensor_shape();
        TensorShape permuted_output_shape  = shape_calculator::compute_depthwise_convolution_shape(*input, *weights, conv_info, depth_multiplier, dilation);

        permute(permuted_input_shape, PermutationVector(2U, 0U, 1U));
        permute(permuted_weights_shape, PermutationVector(2U, 0U, 1U));
        permute(permuted_output_shape, PermutationVector(2U, 0U, 1U));

        const TensorInfo permuted_input   = input->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(permuted_input_shape).set_data_layout(DataLayout::NHWC);
        const TensorInfo permuted_weights = weights->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(permuted_weights_shape).set_data_layout(DataLayout::NHWC);
        const TensorInfo permuted_output  = output->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(permuted_output_shape).set_data_layout(DataLayout::NHWC);

        ARM_COMPUTE_RETURN_ON_ERROR(CLPermute::validate(input, &permuted_input, PermutationVector(2U, 0U, 1U)));
        ARM_COMPUTE_RETURN_ON_ERROR(CLPermute::validate(weights, &permuted_weights, PermutationVector(2U, 0U, 1U)));
        ARM_COMPUTE_RETURN_ON_ERROR(CLDepthwiseConvolutionLayerNativeKernel::validate(&permuted_input, &permuted_weights, biases, &permuted_output, dwc_weights_info,
                                                                                      dwc_info, conv_info, depth_multiplier, dilation,
                                                                                      &output_multipliers_shifts_info, &output_multipliers_shifts_info));
        ARM_COMPUTE_RETURN_ON_ERROR(CLPermute::validate(&permuted_output, output, PermutationVector(1U, 2U, 0U)));
    }
    else
    {
        ARM_COMPUTE_RETURN_ON_ERROR(CLDepthwiseConvolutionLayerNativeKernel::validate(input, weights, biases, output, dwc_weights_info, dwc_info, conv_info, depth_multiplier,
                                                                                      dilation, &output_multipliers_shifts_info, &output_multipliers_shifts_info));
    }
    return Status{};
}

void CLDepthwiseConvolutionLayer::CLDepthwiseConvolutionLayerGeneric::run()
{
    prepare();

    MemoryGroupResourceScope scope_mg(_memory_group);

    if(_needs_permute)
    {
        _permute_input_to_nhwc.run();
    }
    CLScheduler::get().enqueue(_dwc_native_kernel);
    if(_needs_permute)
    {
        _permute_output_to_nchw.run();
    }
}

void CLDepthwiseConvolutionLayer::CLDepthwiseConvolutionLayerGeneric::prepare()
{
    if(!_is_prepared)
    {
        if(_is_quantized)
        {
            _output_multipliers.map();
            _output_shifts.map();
            const unsigned int idx_ofms = get_data_layout_dimension_index(_output->info()->data_layout(), DataLayoutDimension::CHANNEL);
            quantization::compute_quantized_multipliers_and_shifts(_input->info(),
                                                                   _original_weights->info(),
                                                                   _output->info(),
                                                                   idx_ofms,
                                                                   reinterpret_cast<int32_t *>(_output_multipliers.ptr_to_element(Coordinates(0))),
                                                                   reinterpret_cast<int32_t *>(_output_shifts.ptr_to_element(Coordinates(0))));
            _output_multipliers.unmap();
            _output_shifts.unmap();
        }

        if(_needs_permute)
        {
            ARM_COMPUTE_ERROR_ON(!_original_weights->is_used());

            _permuted_weights.allocator()->allocate();
            _permute_weights_to_nhwc.run();
            _original_weights->mark_as_unused();
        }
        _is_prepared = true;
    }
}

CLDepthwiseConvolutionLayer::CLDepthwiseConvolutionLayerInternal3x3::CLDepthwiseConvolutionLayerInternal3x3(std::shared_ptr<IMemoryManager> memory_manager)
    : _memory_group(std::move(memory_manager)),
      _kernel(nullptr),
      _border_handler(),
      _permute_input_to_nchw(),
      _permute_weights_to_nchw(),
      _permute_output_to_nhwc(),
      _reshape_weights(),
      _permuted_input(),
      _permuted_weights(),
      _permuted_output(),
      _output_multipliers(),
      _output_shifts(),
      _original_weights(nullptr),
      _input(nullptr),
      _output(nullptr),
      _needs_permute(false),
      _needs_weights_reshape(false),
      _is_prepared(false),
      _is_quantized(false)
{
}

void CLDepthwiseConvolutionLayer::CLDepthwiseConvolutionLayerInternal3x3::configure(ICLTensor *input, const ICLTensor *weights, const ICLTensor *biases, ICLTensor *output,
                                                                                    const PadStrideInfo &conv_info, unsigned int depth_multiplier, ActivationLayerInfo act_info, const Size2D &dilation)
{
    const GPUTarget gpu_target = CLScheduler::get().target();

    // Perform validation step
    ARM_COMPUTE_ERROR_ON_NULLPTR(input, weights, output);
    ARM_COMPUTE_ERROR_THROW_ON(CLDepthwiseConvolutionLayer3x3::validate(input->info(),
                                                                        weights->info(),
                                                                        biases != nullptr ? biases->info() : nullptr,
                                                                        output->info(),
                                                                        conv_info,
                                                                        depth_multiplier,
                                                                        act_info,
                                                                        gpu_target,
                                                                        dilation));

    const bool is_nhwc     = input->info()->data_layout() == DataLayout::NHWC;
    _is_quantized          = is_data_type_quantized_asymmetric(input->info()->data_type());
    _needs_permute         = is_nhwc && (depth_multiplier > 1);
    _needs_weights_reshape = is_nhwc && (depth_multiplier == 1) && _is_quantized;

    _is_prepared      = false;
    _original_weights = weights;
    _input            = input;
    _output           = output;

    ICLTensor       *input_to_use   = input;
    const ICLTensor *weights_to_use = weights;
    ICLTensor       *output_to_use  = output;

    const bool is_quantized_per_channel = is_data_type_quantized_per_channel(weights->info()->data_type());
    const bool is_stride_1              = ((conv_info.stride().first == conv_info.stride().second) && (conv_info.stride().first == 1));
    const bool is_dot8_supported        = dot8_supported(CLKernelLibrary::get().get_device()) && !is_quantized_per_channel;
    const bool is_stride_1_dilation_1   = (is_stride_1 && dilation.x() == 1 && dilation.y() == 1);

    DepthwiseConvolutionReshapeInfo info;
    info.c0        = 4;
    info.transpose = is_stride_1_dilation_1 && is_dot8_supported;

    if(_needs_permute)
    {
        _memory_group.manage(&_permuted_input);
        _memory_group.manage(&_permuted_output);

        // Configure the function to transform the input tensor from NHWC -> NCHW
        _permute_input_to_nchw.configure(input, &_permuted_input, PermutationVector(1U, 2U, 0U));
        _permuted_input.info()->set_data_layout(DataLayout::NCHW);

        // Configure the function to transform the weights tensor from HWI -> IHW
        _permute_weights_to_nchw.configure(weights, &_permuted_weights, PermutationVector(1U, 2U, 0U));
        _permuted_weights.info()->set_data_layout(DataLayout::NCHW);
        _permuted_output.info()->set_quantization_info(output->info()->quantization_info());

        input_to_use   = &_permuted_input;
        weights_to_use = &_permuted_weights;
        output_to_use  = &_permuted_output;

        _kernel = arm_compute::support::cpp14::make_unique<CLDepthwiseConvolutionLayer3x3NCHWKernel>();
    }
    else if(is_nhwc)
    {
        if(_needs_weights_reshape)
        {
            _reshape_weights.configure(weights, &_permuted_weights, info);
            weights_to_use = &_permuted_weights;
        }
        _kernel = arm_compute::support::cpp14::make_unique<CLDepthwiseConvolutionLayer3x3NHWCKernel>();
    }
    else
    {
        _kernel = arm_compute::support::cpp14::make_unique<CLDepthwiseConvolutionLayer3x3NCHWKernel>();
    }

    CLTensor *output_multipliers_to_use = nullptr;
    CLTensor *output_shifts_to_use      = nullptr;
    if(_is_quantized)
    {
        const size_t idx_c       = get_data_layout_dimension_index(weights->info()->data_layout(), DataLayoutDimension::CHANNEL);
        const size_t num_filters = (is_quantized_per_channel) ? weights->info()->dimension(idx_c) : 1;

        _output_multipliers.allocator()->init(TensorInfo(TensorShape(num_filters), 1, DataType::S32));
        _output_shifts.allocator()->init(TensorInfo(TensorShape(num_filters), 1, DataType::S32));

        output_multipliers_to_use = &_output_multipliers;
        output_shifts_to_use      = &_output_shifts;
    }

    // Configure kernel
    _kernel->set_target(gpu_target);
    _kernel->configure(input_to_use, weights_to_use, biases, output_to_use, conv_info, depth_multiplier,
                       act_info, dilation, output_multipliers_to_use, output_shifts_to_use);

    if(_is_quantized)
    {
        _output_multipliers.allocator()->allocate();
        _output_shifts.allocator()->allocate();
    }

    // Permute output if needed
    if(_needs_permute)
    {
        // Configure the function to transform the convoluted output to ACL's native ordering format NCHW
        _permuted_output.info()->set_data_layout(DataLayout::NCHW);
        _permute_output_to_nhwc.configure(&_permuted_output, output, PermutationVector(2U, 0U, 1U));

        // Allocate tensors
        _permuted_input.allocator()->allocate();
        _permuted_output.allocator()->allocate();
    }
    // Configure border handler
    PixelValue &&zero_value(0.f);
    if(is_data_type_quantized_asymmetric(input->info()->data_type()))
    {
        zero_value = PixelValue(static_cast<uint8_t>(input->info()->quantization_info().uniform().offset));
    }
    _border_handler.configure(input_to_use, _kernel->border_size(), BorderMode::CONSTANT, zero_value);
}

Status CLDepthwiseConvolutionLayer::CLDepthwiseConvolutionLayerInternal3x3::validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output,
                                                                                     const PadStrideInfo &conv_info, unsigned int depth_multiplier, ActivationLayerInfo act_info, GPUTarget gpu_target, const Size2D &dilation)
{
    return validate_arguments_3x3(input, weights, biases, output, conv_info, depth_multiplier, act_info, gpu_target, dilation);
}

void CLDepthwiseConvolutionLayer::CLDepthwiseConvolutionLayerInternal3x3::run()
{
    prepare();

    MemoryGroupResourceScope scope_mg(_memory_group);

    if(_needs_permute)
    {
        _permute_input_to_nchw.run();
    }
    CLScheduler::get().enqueue(_border_handler);
    CLScheduler::get().enqueue(*_kernel);

    if(_needs_permute)
    {
        _permute_output_to_nhwc.run();
    }
}

void CLDepthwiseConvolutionLayer::CLDepthwiseConvolutionLayerInternal3x3::prepare()
{
    if(!_is_prepared)
    {
        if(_is_quantized)
        {
            _output_multipliers.map();
            _output_shifts.map();
            const unsigned int idx_ofms = get_data_layout_dimension_index(_output->info()->data_layout(), DataLayoutDimension::CHANNEL);
            quantization::compute_quantized_multipliers_and_shifts(_input->info(),
                                                                   _original_weights->info(),
                                                                   _output->info(),
                                                                   idx_ofms,
                                                                   reinterpret_cast<int32_t *>(_output_multipliers.ptr_to_element(Coordinates(0))),
                                                                   reinterpret_cast<int32_t *>(_output_shifts.ptr_to_element(Coordinates(0))));
            _output_multipliers.unmap();
            _output_shifts.unmap();
        }

        if(_needs_permute)
        {
            ARM_COMPUTE_ERROR_ON(!_original_weights->is_used());

            _permuted_weights.allocator()->allocate();
            _permute_weights_to_nchw.run();
            _original_weights->mark_as_unused();
        }

        if(_needs_weights_reshape)
        {
            ARM_COMPUTE_ERROR_ON(_needs_permute);
            ARM_COMPUTE_ERROR_ON(!_original_weights->is_used());
            _permuted_weights.allocator()->allocate();
            CLScheduler::get().enqueue(_reshape_weights);
            _original_weights->mark_as_unused();
        }
        _is_prepared = true;
    }
}

CLDepthwiseConvolutionLayer::CLDepthwiseConvolutionLayer(std::shared_ptr<IMemoryManager> memory_manager)
    : _memory_manager(std::move(memory_manager)), _depth_conv_func(DepthwiseConvolutionFunction::GENERIC), _func_3x3(), _func_generic()
{
}

void CLDepthwiseConvolutionLayer::configure(ICLTensor *input, const ICLTensor *weights, const ICLTensor *biases, ICLTensor *output, const PadStrideInfo &conv_info, unsigned int depth_multiplier,
                                            ActivationLayerInfo act_info, const Size2D &dilation)
{
    const GPUTarget gpu_target = CLScheduler::get().target();
    _depth_conv_func           = get_depthwiseconvolution_function(input->info(), weights->info(), (biases != nullptr) ? biases->info() : nullptr, output->info(), conv_info, depth_multiplier, act_info,
                                                                   dilation, gpu_target);
    switch(_depth_conv_func)
    {
        case DepthwiseConvolutionFunction::OPTIMIZED:
            _func_3x3.set_memory_group(_memory_manager);
            _func_3x3.configure(input, weights, biases, output, conv_info, depth_multiplier, act_info, dilation);
            break;
        case DepthwiseConvolutionFunction::GENERIC:
        {
            _func_generic.set_memory_group(_memory_manager);
            _func_generic.configure(input, weights, biases, output, conv_info, depth_multiplier, act_info, dilation);
        }
        break;
        default:
            ARM_COMPUTE_ERROR("Unsupported DepthwiseConvolutionFunction");
    }
}

Status CLDepthwiseConvolutionLayer::validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output, const PadStrideInfo &conv_info,
                                             unsigned int depth_multiplier, ActivationLayerInfo act_info, const Size2D &dilation)
{
    const GPUTarget              gpu_target      = CLScheduler::get().target();
    DepthwiseConvolutionFunction depth_conv_func = get_depthwiseconvolution_function(input, weights, biases, output, conv_info, depth_multiplier, act_info, dilation, gpu_target);
    switch(depth_conv_func)
    {
        case DepthwiseConvolutionFunction::OPTIMIZED:
            return CLDepthwiseConvolutionLayerInternal3x3::validate(input, weights, biases, output, conv_info, depth_multiplier, act_info, gpu_target, dilation);
        case DepthwiseConvolutionFunction::GENERIC:
            return CLDepthwiseConvolutionLayerGeneric::validate(input, weights, biases, output, conv_info, depth_multiplier, act_info, dilation);
        default:
            ARM_COMPUTE_ERROR("Unsupported DepthwiseConvolutionFunction");
    }
}

DepthwiseConvolutionFunction CLDepthwiseConvolutionLayer::get_depthwiseconvolution_function(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output,
                                                                                            const PadStrideInfo &conv_info,
                                                                                            unsigned int depth_multiplier, ActivationLayerInfo act_info, const Size2D &dilation, GPUTarget gpu_target)
{
    if(bool(CLDepthwiseConvolutionLayerInternal3x3::validate(input, weights, biases, output, conv_info, depth_multiplier, act_info, gpu_target, dilation)) && (is_data_type_float(input->data_type())
            || get_arch_from_target(gpu_target) == GPUTarget::MIDGARD))
    {
        return DepthwiseConvolutionFunction::OPTIMIZED;
    }
    else
    {
        return DepthwiseConvolutionFunction::GENERIC;
    }
}

void CLDepthwiseConvolutionLayer::run()
{
    switch(_depth_conv_func)
    {
        case DepthwiseConvolutionFunction::OPTIMIZED:
            _func_3x3.run();
            break;
        case DepthwiseConvolutionFunction::GENERIC:
            _func_generic.run();
            break;
        default:
            ARM_COMPUTE_ERROR("DepthwiseConvolutionFunction not properly configured");
    }
}

void CLDepthwiseConvolutionLayer::prepare()
{
    switch(_depth_conv_func)
    {
        case DepthwiseConvolutionFunction::OPTIMIZED:
            _func_3x3.prepare();
            break;
        case DepthwiseConvolutionFunction::GENERIC:
            _func_generic.prepare();
            break;
        default:
            ARM_COMPUTE_ERROR("DepthwiseConvolutionFunction not properly configured");
    }
}
} // namespace arm_compute
