/*
 * 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/CpuDepthwiseConv2d.h"

#include "arm_compute/core/TensorInfo.h"
#include "arm_compute/core/utils/misc/InfoHelpers.h"
#include "arm_compute/core/utils/misc/ShapeCalculator.h"
#include "arm_compute/core/Validate.h"
#include "arm_compute/runtime/NEON/NEScheduler.h"

#include "src/common/utils/Log.h"
#include "src/cpu/kernels/CpuDepthwiseConv2dNativeKernel.h"

namespace arm_compute
{
namespace cpu
{
namespace
{
Status validate_arguments_optimized(const ITensorInfo     *src,
                                    const ITensorInfo     *weights,
                                    const ITensorInfo     *biases,
                                    const ITensorInfo     *dst,
                                    const ConvolutionInfo &info)
{
    ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src, weights, dst);
    ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(src, 1, DataType::QASYMM8, DataType::QASYMM8_SIGNED,
                                                         DataType::F16, DataType::F32);
    if (!is_data_type_quantized_per_channel(weights->data_type()))
    {
        ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(src, weights);
    }
    ARM_COMPUTE_RETURN_ERROR_ON(src->data_layout() == DataLayout::UNKNOWN);
    ARM_COMPUTE_RETURN_ERROR_ON(info.dilation.x() < 1 || info.dilation.y() < 1);
    const size_t idx_w = get_data_layout_dimension_index(src->data_layout(), DataLayoutDimension::WIDTH);
    const size_t idx_h = get_data_layout_dimension_index(src->data_layout(), DataLayoutDimension::HEIGHT);
    ARM_COMPUTE_RETURN_ERROR_ON(weights->dimension(idx_w) + (weights->dimension(idx_w) - 1) * (info.dilation.x() - 1) >
                                src->dimension(idx_w) + info.pad_stride_info.pad_left() +
                                    info.pad_stride_info.pad_right());
    ARM_COMPUTE_RETURN_ERROR_ON(weights->dimension(idx_h) + (weights->dimension(idx_h) - 1) * (info.dilation.y() - 1) >
                                src->dimension(idx_h) + info.pad_stride_info.pad_top() +
                                    info.pad_stride_info.pad_bottom());

    if (biases != nullptr)
    {
        const unsigned int channel_idx =
            get_data_layout_dimension_index(src->data_layout(), DataLayoutDimension::CHANNEL);
        ARM_COMPUTE_RETURN_ERROR_ON(biases->num_dimensions() > 1);
        ARM_COMPUTE_RETURN_ERROR_ON(biases->dimension(0) != weights->dimension(channel_idx));
    }

    ARM_COMPUTE_RETURN_ON_ERROR(CpuDepthwiseConv2dAssemblyDispatch::validate(src, weights, biases, dst, info));

    // Validate Activation Layer
    if (info.act_info.enabled() && !CpuDepthwiseConv2dAssemblyDispatch::is_activation_supported(info.act_info))
    {
        ARM_COMPUTE_RETURN_ON_ERROR(CpuActivation::validate(dst, nullptr, info.act_info));
    }
    return Status{};
}
} // namespace

void CpuDepthwiseConv2d::CpuDepthwiseConv2dOptimizedInternal::configure(ITensorInfo           *src,
                                                                        const ITensorInfo     *weights,
                                                                        const ITensorInfo     *biases,
                                                                        ITensorInfo           *dst,
                                                                        const ConvolutionInfo &info)
{
    ARM_COMPUTE_ERROR_ON_NULLPTR(src, weights, dst);
    // Perform validation step
    ARM_COMPUTE_ERROR_THROW_ON(
        CpuDepthwiseConv2dOptimizedInternal::validate(src, weights, (biases == nullptr) ? nullptr : biases, dst, info));

    _is_quantized      = is_data_type_quantized_asymmetric(src->data_type());
    _has_bias          = biases != nullptr;
    _is_nchw           = src->data_layout() == DataLayout::NCHW;
    _permute           = _is_nchw;
    _is_prepared       = false;
    _are_weights_const = weights->are_values_constant();

    // Configure pipeline
    _is_activationlayer_enabled =
        info.act_info.enabled() && !CpuDepthwiseConv2dAssemblyDispatch::is_activation_supported(info.act_info);

    _dwc_optimized_func = std::make_unique<CpuDepthwiseConv2dAssemblyDispatch>();
    if (_is_nchw)
    {
        _permute_input   = std::make_unique<cpu::CpuPermute>();
        _permute_weights = std::make_unique<cpu::CpuPermute>();
        _permute_output  = std::make_unique<cpu::CpuPermute>();

        auto input_perm   = std::make_unique<TensorInfo>();
        auto weights_perm = std::make_unique<TensorInfo>();
        auto output_perm  = std::make_unique<TensorInfo>();

        // Configure the function to transform the input tensor from NCHW -> NHWC
        _permute_input->configure(src, input_perm.get(), PermutationVector(2U, 0U, 1U));
        input_perm->set_data_layout(DataLayout::NHWC);

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

        output_perm->set_data_layout(DataLayout::NHWC);
        output_perm->set_quantization_info(dst->quantization_info());

        // Configure optimized depthwise
        _dwc_optimized_func->configure(input_perm.get(), weights_perm.get(), biases, output_perm.get(), info);

        // Configure the function to transform the convoluted output to ACL's native ordering format NCHW
        output_perm->set_data_layout(DataLayout::NHWC);
        _permute_output->configure(output_perm.get(), dst, PermutationVector(1U, 2U, 0U));
    }
    else
    {
        _dwc_optimized_func->configure(src, weights, biases, dst, info);
    }

    // Configure activation
    if (_is_activationlayer_enabled)
    {
        _activationlayer_function = std::make_unique<cpu::CpuActivation>();
        _activationlayer_function->configure(dst, nullptr, info.act_info);
    }
}

Status CpuDepthwiseConv2d::CpuDepthwiseConv2dOptimizedInternal::validate(const ITensorInfo     *src,
                                                                         const ITensorInfo     *weights,
                                                                         const ITensorInfo     *biases,
                                                                         const ITensorInfo     *dst,
                                                                         const ConvolutionInfo &info)
{
    return validate_arguments_optimized(src, weights, biases, dst, info);
}

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

    auto bias           = tensors.get_const_tensor(TensorType::ACL_SRC_2);
    auto dst            = tensors.get_tensor(TensorType::ACL_DST_0);
    auto workspace      = tensors.get_tensor(TensorType::ACL_INT_3);
    auto packed_weights = tensors.get_tensor(TensorType::ACL_INT_4);

    // Permute input
    if (_permute)
    {
        ITensorPack pack;
        auto        src      = tensors.get_const_tensor(TensorType::ACL_SRC_0);
        auto        src_perm = tensors.get_tensor(TensorType::ACL_INT_0);
        pack.add_tensor(TensorType::ACL_SRC, src);
        pack.add_tensor(TensorType::ACL_DST, src_perm);
        _permute_input->run(pack);
    }

    // Run assembly function
    if (_is_nchw)
    {
        auto src_perm     = tensors.get_tensor(TensorType::ACL_INT_0);
        auto weights_perm = tensors.get_tensor(TensorType::ACL_INT_1);
        auto dst_perm     = tensors.get_tensor(TensorType::ACL_INT_2);

        ITensorPack pack;
        pack.add_tensor(TensorType::ACL_SRC_0, src_perm);
        pack.add_tensor(TensorType::ACL_SRC_1, weights_perm);
        pack.add_tensor(TensorType::ACL_SRC_2, bias);
        pack.add_tensor(TensorType::ACL_INT_0, workspace);
        pack.add_tensor(TensorType::ACL_INT_1, packed_weights);
        pack.add_tensor(TensorType::ACL_DST, dst_perm);
        _dwc_optimized_func->run(pack);
    }
    else
    {
        auto src     = tensors.get_tensor(TensorType::ACL_SRC_0);
        auto weights = tensors.get_tensor(TensorType::ACL_SRC_1);
        auto dst     = tensors.get_tensor(TensorType::ACL_DST);

        ITensorPack pack;
        pack.add_tensor(TensorType::ACL_SRC_0, src);
        pack.add_tensor(TensorType::ACL_SRC_1, weights);
        pack.add_tensor(TensorType::ACL_SRC_2, bias);
        pack.add_tensor(TensorType::ACL_INT_0, workspace);
        pack.add_tensor(TensorType::ACL_INT_1, packed_weights);
        pack.add_tensor(TensorType::ACL_DST, dst);
        _dwc_optimized_func->run(pack);
    }

    // Permute output
    if (_is_nchw)
    {
        ITensorPack pack;
        auto        dst_perm = tensors.get_tensor(TensorType::ACL_INT_2);
        pack.add_tensor(TensorType::ACL_SRC, dst_perm);
        pack.add_tensor(TensorType::ACL_DST, dst);
        _permute_output->run(pack);
    }

    // Run activation
    if (_is_activationlayer_enabled)
    {
        ITensorPack pack;
        pack.add_tensor(TensorType::ACL_SRC, dst);
        pack.add_tensor(TensorType::ACL_DST, dst);
        _activationlayer_function->run(pack);
    }
}

void CpuDepthwiseConv2d::CpuDepthwiseConv2dOptimizedInternal::prepare(ITensorPack &tensors)
{
    // if weights are not constant then we need to repack so that weights
    // can be updated in-place
    if (!_are_weights_const)
    {
        auto weights        = tensors.get_const_tensor(TensorType::ACL_SRC_1);
        auto bias           = tensors.get_const_tensor(TensorType::ACL_SRC_2);
        auto packed_weights = tensors.get_tensor(TensorType::ACL_INT_4);

        ITensorPack pack_opt;
        pack_opt.add_tensor(TensorType::ACL_SRC_1, weights);
        pack_opt.add_tensor(TensorType::ACL_SRC_2, bias);
        pack_opt.add_tensor(TensorType::ACL_INT_1, packed_weights);

        // Prepare optimized function
        _dwc_optimized_func->prepare(pack_opt);

        return;
    }

    if (!_is_prepared)
    {
        auto weights        = tensors.get_const_tensor(TensorType::ACL_SRC_1);
        auto bias           = tensors.get_const_tensor(TensorType::ACL_SRC_2);
        auto packed_weights = tensors.get_tensor(TensorType::ACL_INT_4);

        // Permute weights
        if (_permute)
        {
            auto permuted_weights = tensors.get_tensor(TensorType::ACL_INT_1);

            ITensorPack pack;
            pack.add_tensor(TensorType::ACL_SRC, weights);
            pack.add_tensor(TensorType::ACL_DST, permuted_weights);
            _permute_weights->run(pack);

            weights->mark_as_unused();

            ITensorPack pack_opt;
            pack_opt.add_const_tensor(TensorType::ACL_SRC_1, permuted_weights);
            pack_opt.add_tensor(TensorType::ACL_SRC_2, bias);
            pack_opt.add_tensor(TensorType::ACL_INT_1, packed_weights);

            // Prepare optimized function
            _dwc_optimized_func->prepare(pack_opt);
        }
        else
        {
            ITensorPack pack_opt;
            pack_opt.add_tensor(TensorType::ACL_SRC_1, weights);
            pack_opt.add_tensor(TensorType::ACL_SRC_2, bias);
            pack_opt.add_tensor(TensorType::ACL_INT_1, packed_weights);

            // Prepare optimized function
            _dwc_optimized_func->prepare(pack_opt);
        }

        _is_prepared = true;
    }
}

void CpuDepthwiseConv2d::CpuDepthwiseConv2dGeneric::configure(ITensorInfo           *src,
                                                              const ITensorInfo     *weights,
                                                              const ITensorInfo     *biases,
                                                              ITensorInfo           *dst,
                                                              const ConvolutionInfo &info)
{
    ARM_COMPUTE_ERROR_ON_NULLPTR(src, weights, dst);
    ARM_COMPUTE_ERROR_THROW_ON(
        CpuDepthwiseConv2d::validate(src, weights, (biases == nullptr) ? nullptr : biases, dst, info));

    _is_nchw     = src->data_layout() == DataLayout::NCHW;
    _is_prepared = !_is_nchw;

    ITensorInfo       *input_to_use   = src;
    const ITensorInfo *weights_to_use = weights;
    ITensorInfo       *output_to_use  = dst;

    auto input_perm   = std::make_unique<TensorInfo>();
    auto weights_perm = std::make_unique<TensorInfo>();
    auto output_perm  = std::make_unique<TensorInfo>(
        dst->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(TensorShape()));

    if (_is_nchw)
    {
        _permute_input   = std::make_unique<cpu::CpuPermute>();
        _permute_weights = std::make_unique<cpu::CpuPermute>();

        _permute_input->configure(src, input_perm.get(), PermutationVector(2U, 0U, 1U));
        input_perm->set_data_layout(DataLayout::NHWC);
        input_to_use = input_perm.get();

        _permute_weights->configure(weights, weights_perm.get(), PermutationVector(2U, 0U, 1U));
        weights_perm->set_data_layout(DataLayout::NHWC);
        weights_to_use = weights_perm.get();

        output_to_use = output_perm.get();
    }

    _depthwise_conv_kernel = std::make_unique<cpu::kernels::CpuDepthwiseConv2dNativeKernel>();
    _depthwise_conv_kernel->configure(input_to_use, weights_to_use, biases, output_to_use, info);

    if (_is_nchw)
    {
        _permute_output = std::make_unique<cpu::CpuPermute>();
        _permute_output->configure(output_perm.get(), dst, PermutationVector(1U, 2U, 0U));
        output_perm->set_data_layout(DataLayout::NHWC);
    }

    //Configure Activation Layer
    _is_activationlayer_enabled = info.act_info.enabled();
    if (_is_activationlayer_enabled)
    {
        _activationlayer_function = std::make_unique<cpu::CpuActivation>();
        _activationlayer_function->configure(dst, nullptr, info.act_info);
    }
}

Status CpuDepthwiseConv2d::CpuDepthwiseConv2dGeneric::validate(const ITensorInfo     *src,
                                                               const ITensorInfo     *weights,
                                                               const ITensorInfo     *biases,
                                                               const ITensorInfo     *dst,
                                                               const ConvolutionInfo &info)
{
    ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src, weights, dst);
    if (src->data_layout() == DataLayout::NCHW)
    {
        TensorShape permuted_input_shape   = src->tensor_shape();
        TensorShape permuted_weights_shape = weights->tensor_shape();
        TensorShape permuted_output_shape =
            misc::shape_calculator::compute_depthwise_convolution_shape(*src, *weights, info);
        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   = TensorInfo(src->clone()
                                                           ->set_is_resizable(true)
                                                           .reset_padding()
                                                           .set_tensor_shape(permuted_input_shape)
                                                           .set_data_layout(DataLayout::NHWC));
        const TensorInfo permuted_weights = TensorInfo(weights->clone()
                                                           ->set_is_resizable(true)
                                                           .reset_padding()
                                                           .set_tensor_shape(permuted_weights_shape)
                                                           .set_data_layout(DataLayout::NHWC));
        const TensorInfo permuted_output  = TensorInfo(dst->clone()
                                                           ->set_is_resizable(true)
                                                           .reset_padding()
                                                           .set_tensor_shape(permuted_output_shape)
                                                           .set_data_layout(DataLayout::NCHW));

        ARM_COMPUTE_RETURN_ON_ERROR(CpuPermute::validate(src, &permuted_input, PermutationVector(2U, 0U, 1U)));
        ARM_COMPUTE_RETURN_ON_ERROR(CpuPermute::validate(weights, &permuted_weights, PermutationVector(2U, 0U, 1U)));
        ARM_COMPUTE_RETURN_ON_ERROR(CpuPermute::validate(&permuted_output, dst, PermutationVector(1U, 2U, 0U)));

        ARM_COMPUTE_RETURN_ON_ERROR(cpu::kernels::CpuDepthwiseConv2dNativeKernel::validate(
            &permuted_input, &permuted_weights, biases, &permuted_output, info));
    }
    else
    {
        ARM_COMPUTE_RETURN_ON_ERROR(
            cpu::kernels::CpuDepthwiseConv2dNativeKernel::validate(src, weights, biases, dst, info));
    }

    // Validate Activation Layer
    if (info.act_info.enabled() && !CpuDepthwiseConv2dAssemblyDispatch::is_activation_supported(info.act_info))
    {
        ARM_COMPUTE_RETURN_ON_ERROR(CpuActivation::validate(dst, nullptr, info.act_info));
    }

    return Status{};
}

void CpuDepthwiseConv2d::CpuDepthwiseConv2dGeneric::run(ITensorPack &tensors)
{
    auto src     = tensors.get_const_tensor(TensorType::ACL_SRC_0);
    auto weights = tensors.get_const_tensor(TensorType::ACL_SRC_1);
    auto biases  = tensors.get_const_tensor(TensorType::ACL_SRC_2);
    auto dst     = tensors.get_tensor(TensorType::ACL_DST_0);

    if (_is_nchw)
    {
        prepare(tensors);
        auto src_perm     = tensors.get_tensor(TensorType::ACL_INT_0);
        auto weights_perm = tensors.get_tensor(TensorType::ACL_INT_1);
        auto dst_perm     = tensors.get_tensor(TensorType::ACL_INT_2);

        ITensorPack pack;
        pack.add_tensor(TensorType::ACL_SRC, src);
        pack.add_tensor(TensorType::ACL_DST, src_perm);
        _permute_input->run(pack);

        ITensorPack pack_depth;
        pack_depth.add_const_tensor(TensorType::ACL_SRC_0, src_perm);
        pack_depth.add_const_tensor(TensorType::ACL_SRC_1, weights_perm);
        pack_depth.add_tensor(TensorType::ACL_SRC_2, biases);
        pack_depth.add_tensor(TensorType::ACL_DST, dst_perm);
        NEScheduler::get().schedule_op(_depthwise_conv_kernel.get(), Window::DimY, _depthwise_conv_kernel->window(),
                                       pack_depth);
    }
    else
    {
        ITensorPack pack_depth;
        pack_depth.add_tensor(TensorType::ACL_SRC_0, src);
        pack_depth.add_tensor(TensorType::ACL_SRC_1, weights);
        pack_depth.add_tensor(TensorType::ACL_SRC_2, biases);
        pack_depth.add_tensor(TensorType::ACL_DST, dst);
        NEScheduler::get().schedule_op(_depthwise_conv_kernel.get(), Window::DimY, _depthwise_conv_kernel->window(),
                                       pack_depth);
    }

    if (_is_nchw)
    {
        ITensorPack pack;
        auto        dst_perm = tensors.get_tensor(TensorType::ACL_INT_2);
        pack.add_tensor(TensorType::ACL_SRC, dst_perm);
        pack.add_tensor(TensorType::ACL_DST, dst);
        _permute_output->run(pack);
    }

    if (_is_activationlayer_enabled)
    {
        ITensorPack pack;
        pack.add_tensor(TensorType::ACL_SRC, dst);
        pack.add_tensor(TensorType::ACL_DST, dst);
        _activationlayer_function->run(pack);
    }
}

void CpuDepthwiseConv2d::CpuDepthwiseConv2dGeneric::prepare(ITensorPack &tensors)
{
    if (!_is_prepared)
    {
        auto weights      = tensors.get_const_tensor(TensorType::ACL_SRC_1);
        auto weights_perm = tensors.get_tensor(TensorType::ACL_INT_1);

        ARM_COMPUTE_ERROR_ON(!weights->is_used());

        ITensorPack pack;
        pack.add_tensor(TensorType::ACL_SRC, weights);
        pack.add_tensor(TensorType::ACL_DST, weights_perm);

        _permute_weights->run(pack);
        weights->mark_as_unused();
        _is_prepared = true;
    }
}

void CpuDepthwiseConv2d::configure(ITensorInfo           *src,
                                   const ITensorInfo     *weights,
                                   const ITensorInfo     *biases,
                                   ITensorInfo           *dst,
                                   const ConvolutionInfo &info)
{
    ARM_COMPUTE_LOG_PARAMS(src, weights, biases, dst, info);

    _depth_conv_func =
        get_depthwiseconvolution_function(src, weights, (biases != nullptr) ? biases : nullptr, dst, info);
    switch (_depth_conv_func)
    {
        case DepthwiseConvolutionFunction::OPTIMIZED:
            _func_optimized.configure(src, weights, biases, dst, info);
            break;
        case DepthwiseConvolutionFunction::GENERIC:
            _func_generic.configure(src, weights, biases, dst, info);
            break;
        default:
            ARM_COMPUTE_ERROR("Unsupported DepthwiseConvolutionFunction");
    }
}

Status CpuDepthwiseConv2d::validate(const ITensorInfo     *src,
                                    const ITensorInfo     *weights,
                                    const ITensorInfo     *biases,
                                    const ITensorInfo     *dst,
                                    const ConvolutionInfo &info)
{
    DepthwiseConvolutionFunction depth_conv_func = get_depthwiseconvolution_function(src, weights, biases, dst, info);
    switch (depth_conv_func)
    {
        case DepthwiseConvolutionFunction::OPTIMIZED:
            return CpuDepthwiseConv2dOptimizedInternal::validate(src, weights, biases, dst, info);
            break;
        case DepthwiseConvolutionFunction::GENERIC:
            return CpuDepthwiseConv2dGeneric::validate(src, weights, biases, dst, info);
            break;
        default:
            ARM_COMPUTE_ERROR("Unsupported DepthwiseConvolutionFunction");
    }
}

DepthwiseConvolutionFunction CpuDepthwiseConv2d::get_depthwiseconvolution_function(const ITensorInfo     *src,
                                                                                   const ITensorInfo     *weights,
                                                                                   const ITensorInfo     *biases,
                                                                                   const ITensorInfo     *dst,
                                                                                   const ConvolutionInfo &info)
{
    if (bool(CpuDepthwiseConv2dOptimizedInternal::validate(src, weights, biases, dst, info)))
    {
        return DepthwiseConvolutionFunction::OPTIMIZED;
    }
    else
    {
        return DepthwiseConvolutionFunction::GENERIC;
    }
}

void CpuDepthwiseConv2d::run(ITensorPack &tensors)
{
    switch (_depth_conv_func)
    {
        case DepthwiseConvolutionFunction::OPTIMIZED:
            _func_optimized.run(tensors);
            break;
        case DepthwiseConvolutionFunction::GENERIC:
            _func_generic.run(tensors);
            break;
        default:
            ARM_COMPUTE_ERROR("DepthwiseConvolutionFunction not properly configured");
    }
}

void CpuDepthwiseConv2d::prepare(ITensorPack &tensors)
{
    switch (_depth_conv_func)
    {
        case DepthwiseConvolutionFunction::OPTIMIZED:
            _func_optimized.prepare(tensors);
            break;
        case DepthwiseConvolutionFunction::GENERIC:
            _func_generic.prepare(tensors);
            break;
        default:
            ARM_COMPUTE_ERROR("DepthwiseConvolutionFunction not properly configured");
    }
}
} // namespace cpu
} // namespace arm_compute
