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

#include "arm_compute/core/Helpers.h"
#include "arm_compute/core/ITensorPack.h"
#include "arm_compute/core/Validate.h"
#include "arm_compute/core/utils/misc/ShapeCalculator.h"
#include "arm_compute/core/utils/quantization/AsymmHelpers.h"
#include "arm_compute/runtime/NEON/NEScheduler.h"
#include "src/common/utils/Log.h"
#include "src/core/helpers/AutoConfiguration.h"
#include "src/core/helpers/MemoryHelpers.h"
#include "src/core/utils/quantization/AsymmHelpers.h"
#include "src/cpu/kernels/CpuTransposeKernel.h"
#include "src/cpu/operators/CpuConvertFullyConnectedWeights.h"
#include "src/cpu/operators/CpuFlatten.h"
#include "src/cpu/operators/CpuGemm.h"
#include "src/cpu/operators/CpuGemmLowpMatrixMultiplyCore.h"
#include "src/cpu/utils/CpuAuxTensorHandler.h"

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

namespace
{
Status get_gemmlowp_output_stage_info(const ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *dst, const ActivationLayerInfo &act,
                                      GEMMLowpOutputStageInfo &gemmlowp_output_stage_info)
{
    const auto                    data_type = src->data_type();
    const QuantizationInfo        oq_info   = dst->quantization_info();
    const UniformQuantizationInfo iq_unif   = src->quantization_info().uniform();
    const UniformQuantizationInfo wq_unif   = weights->quantization_info().uniform();
    const UniformQuantizationInfo oq_unif   = oq_info.uniform();

    float   multiplier = (iq_unif.scale * wq_unif.scale) / oq_unif.scale;
    int32_t output_multiplier;
    int32_t output_shift;

    ARM_COMPUTE_RETURN_ON_ERROR(quantization::calculate_quantized_multiplier(multiplier, &output_multiplier, &output_shift));

    int32_t type_min = 0;
    int32_t type_max = 0;
    std::tie(type_min, type_max) = quantization::get_quantized_asymmetric_output_min_max(oq_info, act, data_type);

    gemmlowp_output_stage_info.gemmlowp_multiplier = output_multiplier;
    gemmlowp_output_stage_info.gemmlowp_shift      = output_shift;
    gemmlowp_output_stage_info.gemmlowp_offset     = oq_unif.offset;
    gemmlowp_output_stage_info.type                = GEMMLowpOutputStageType::QUANTIZE_DOWN_FIXEDPOINT;
    gemmlowp_output_stage_info.gemmlowp_min_bound  = type_min;
    gemmlowp_output_stage_info.gemmlowp_max_bound  = type_max;

    return Status{};
}

Status validate_mm(const ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *dst, const ActivationLayerInfo &act, bool enable_fast_math, WeightFormat weight_format)
{
    if(is_data_type_quantized_asymmetric(src->data_type()))
    {
        // Since we need negative offsets for computing convolution, we need to change QuantizationInfo()
        // Extract and negate src and weights offset
        const QuantizationInfo src_quantization_info(src->quantization_info().uniform().scale, -src->quantization_info().uniform().offset);
        const QuantizationInfo weights_quantization_info(weights->quantization_info().uniform().scale, -weights->quantization_info().uniform().offset);

        GEMMLowpOutputStageInfo gemmlowp_output_stage_info;
        ARM_COMPUTE_RETURN_ON_ERROR(get_gemmlowp_output_stage_info(src, weights, dst, act, gemmlowp_output_stage_info));

        GEMMInfo gemm_info;
        gemm_info.set_gemmlowp_output_stage(gemmlowp_output_stage_info);
        gemm_info.set_fast_math(enable_fast_math);

        // Validate gemmlowp function
        TensorInfo src_info     = src->clone()->set_quantization_info(src_quantization_info);
        TensorInfo weights_info = weights->clone()->set_quantization_info(weights_quantization_info);
        ARM_COMPUTE_RETURN_ON_ERROR(CpuGemmLowpMatrixMultiplyCore::validate(&src_info,
                                                                            &weights_info,
                                                                            biases,
                                                                            dst,
                                                                            gemm_info));
    }
    else
    {
        GEMMInfo gemm_info;
        gemm_info.set_weight_format(weight_format);
        gemm_info.set_fixed_format(weight_format != WeightFormat::UNSPECIFIED);
        gemm_info.set_fast_math(enable_fast_math);
        ARM_COMPUTE_RETURN_ON_ERROR(CpuGemm::validate(src, weights, biases, dst, 1.f, 1.0f, gemm_info));
    }

    return Status{};
}
} // namespace

CpuFullyConnected::CpuFullyConnected()
    : _flatten(nullptr),
      _convert_weights(nullptr),
      _transpose_weights(nullptr),
      _mm_gemm(nullptr),
      _mm_gemmlowp(nullptr),
      _flattened_src(),
      _converted_weights(),
      _reshaped_weights(),
      _trans_weights(),
      _trans_weights_idx(AuxTensorIdx::Count),
      _aux_mem(Count),
      _needs_weights_conversion(false),
      _needs_weights_reshape(false),
      _is_fc_after_conv(false),
      _is_quantized_asymmetric(false),
      _is_prepared(false),
      _enable_fast_math(false),
      _fixed_format(false),
      _weight_format(arm_compute::WeightFormat::UNSPECIFIED),
      _dynamic_weights(false)
{
}

CpuFullyConnected::~CpuFullyConnected() = default;

void CpuFullyConnected::configure_mm(const ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *biases, ITensorInfo *dst, const ActivationLayerInfo &act)
{
    if(_is_quantized_asymmetric)
    {
        // Since we need negative offsets for computing convolution, we need to change QuantizationInfo()
        // Extract and negate src and weights offset
        const QuantizationInfo src_quantization_info(src->quantization_info().uniform().scale, -src->quantization_info().uniform().offset);
        const QuantizationInfo weights_quantization_info(weights->quantization_info().uniform().scale, -weights->quantization_info().uniform().offset);

        TensorInfo src_info     = src->clone()->set_quantization_info(src_quantization_info);
        TensorInfo weights_info = weights->clone()->set_quantization_info(weights_quantization_info);

        // Configure gemmlowp function and output stage for asymmetric quantized types
        GEMMLowpOutputStageInfo gemmlowp_output_stage_info;
        const Status            status = get_gemmlowp_output_stage_info(&src_info, &weights_info, dst, act, gemmlowp_output_stage_info);
        ARM_COMPUTE_ERROR_ON(status.error_code() != ErrorCode::OK);

        GEMMInfo gemm_info;
        gemm_info.set_gemmlowp_output_stage(gemmlowp_output_stage_info);
        gemm_info.set_activation_info(act);
        gemm_info.set_fast_math(_enable_fast_math);
        _mm_gemmlowp = std::make_unique<CpuGemmLowpMatrixMultiplyCore>();
        _mm_gemmlowp->configure(&src_info, &weights_info, biases, dst, gemm_info);
    }
    else
    {
        // Configure matrix multiply kernel
        GEMMInfo gemm_info;
        gemm_info.set_activation_info(act);
        gemm_info.set_fast_math(_enable_fast_math);
        gemm_info.set_fixed_format(_fixed_format);
        gemm_info.set_weight_format(_weight_format);
        _mm_gemm = std::make_unique<CpuGemm>();
        _mm_gemm->configure(src, weights, biases, dst, 1.f, 1.0f, gemm_info);
    }
}

void CpuFullyConnected::configure_conv_fc(const ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *biases, ITensorInfo *dst, const ActivationLayerInfo &act)
{
    ARM_COMPUTE_ERROR_ON((weights->dimension(1) != (src->dimension(0) * src->dimension(1) * src->dimension(2))));

    // If the fully connected layer is called after a convolution layer, the src tensor must be linearized

    // Initialize output tensor for flatten
    auto_init_if_empty(_flattened_src, src->clone()->set_tensor_shape(compute_flatten_shape(src)));

    _flatten = std::make_unique<CpuFlatten>();
    _flatten->configure(src, &_flattened_src);

    // Configure matrix multiply kernel
    configure_mm(&_flattened_src, weights, biases, dst, act);
}

void CpuFullyConnected::configure_fc_fc(const ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *biases, ITensorInfo *dst, const ActivationLayerInfo &act)
{
    ARM_COMPUTE_ERROR_ON(src->dimension(0) != weights->dimension(1));

    // Configure matrix multiply kernel
    configure_mm(src, weights, biases, dst, act);
}

void CpuFullyConnected::configure(const ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *biases, ITensorInfo *dst,
                                  FullyConnectedLayerInfo fc_info, const WeightsInfo &weights_info)
{
    // Perform validate step
    ARM_COMPUTE_ERROR_ON_NULLPTR(src, weights, dst);
    ARM_COMPUTE_ERROR_THROW_ON(CpuFullyConnected::validate(src,
                                                           weights,
                                                           biases != nullptr ? biases : nullptr,
                                                           dst,
                                                           fc_info,
                                                           weights_info));
    ARM_COMPUTE_LOG_PARAMS(src, weights, biases, dst, fc_info);

    _needs_weights_conversion = false;
    _needs_weights_reshape    = fc_info.transpose_weights ? !fc_info.are_weights_reshaped : false;
    _needs_weights_reshape    = _needs_weights_reshape && !fc_info.retain_internal_weights;
    _is_fc_after_conv         = true;
    _is_quantized_asymmetric  = is_data_type_quantized_asymmetric(src->data_type());
    _is_prepared              = false;
    _trans_weights_idx        = AuxTensorIdx::Count;
    _enable_fast_math         = fc_info.enable_fast_math;
    _fixed_format             = weights_info.weight_format() != WeightFormat::UNSPECIFIED;
    _weight_format            = weights_info.weight_format();
    _dynamic_weights          = !weights->are_values_constant() && _needs_weights_reshape;

    // With the Fully Connected layer we can have 4 different cases:
    //  1) Convolution layer -> Fully Connected layer without batches
    //  2) Fully Connected layer -> Fully Connected layer without batches
    //  3) Convolution layer -> Fully Connected layer with batches
    //  4) Fully Connected layer -> Fully Connected layer with batches

    const ITensorInfo *weights_to_use = weights;

    // Check if we have a fully connected layer with batches
    const bool is_batched_fc_layer = dst->dimension(1) > 1;
    if(is_batched_fc_layer)
    {
        _is_fc_after_conv = (TensorShape::num_max_dimensions >= 4) && (std::equal(src->tensor_shape().cbegin() + 3, src->tensor_shape().cend(), dst->tensor_shape().cbegin() + 1));
    }
    else
    {
        _is_fc_after_conv = src->num_dimensions() > 1;
    }

    // Reshape weights if needed
    if(_needs_weights_reshape)
    {
        // Reshape the weights
        _transpose_weights = std::make_unique<kernels::CpuTransposeKernel>();
        _transpose_weights->configure(weights, &_reshaped_weights);
        _reshaped_weights.set_are_values_constant(weights->are_values_constant());

        weights_to_use     = &_reshaped_weights;
        _trans_weights_idx = AuxTensorIdx::TransposedWeights;
    }

    // Convert weights if needed
    if(_is_fc_after_conv && (src->data_layout() != fc_info.weights_trained_layout))
    {
        // Convert weights
        _convert_weights = std::make_unique<CpuConvertFullyConnectedWeights>();
        _convert_weights->configure(weights_to_use,
                                    &_converted_weights,
                                    src->tensor_shape(),
                                    fc_info.weights_trained_layout);
        _converted_weights.set_are_values_constant(weights_to_use->are_values_constant());

        weights_to_use            = &_converted_weights;
        _needs_weights_conversion = true;
        _trans_weights_idx        = AuxTensorIdx::ConvertedWeights;
    }

    if(_is_fc_after_conv)
    {
        // Fully Connected layer after a Convolution Layer without batches
        configure_conv_fc(src, weights_to_use, biases, dst, fc_info.activation_info);
    }
    else
    {
        // Fully Connected layer after a Fully Connected Layer without batches
        configure_fc_fc(src, weights_to_use, biases, dst, fc_info.activation_info);
    }

    // Retain the tensorinfo with the weights to use
    if(_needs_weights_reshape || _needs_weights_conversion)
    {
        _trans_weights = *weights_to_use;
    }

    // Set auxiliary memory requirements
    auto gemm_mem_req = (_is_quantized_asymmetric) ? _mm_gemmlowp->workspace() : _mm_gemm->workspace();
    for(unsigned int i = 0; i < gemm_mem_req.size(); ++i)
    {
        _aux_mem[i] = gemm_mem_req[i];
    }

    if(_aux_mem[Pretranspose].size > 0)
    {
        // Release permuted weights at the end of prepare as they are further transposed by the assembly dispatch
        // Do not release them if biases are dynamic and data type is quantized, since the weights tensor will be used for biases offset calculation
        // Keep all the auxiliary tensors in case of dynamic weights as they are recalculated every time.
        _aux_mem[TransposedWeights] = MemoryInfo(
            offset_int_vec(TransposedWeights),
            _dynamic_weights                                                         ? MemoryLifetime::Temporary  :
            (_is_quantized_asymmetric && biases && !(biases->are_values_constant())) ? MemoryLifetime::Persistent :
                                                                                       MemoryLifetime::Prepare,
            _reshaped_weights.total_size());

        _aux_mem[ConvertedWeights] = MemoryInfo(
            offset_int_vec(ConvertedWeights),
            _dynamic_weights ? MemoryLifetime::Temporary : MemoryLifetime::Prepare,
            _converted_weights.total_size());
    }
    else
    {
        _aux_mem[TransposedWeights] = MemoryInfo(
            offset_int_vec(TransposedWeights),
            _dynamic_weights          ? MemoryLifetime::Temporary :
            _needs_weights_conversion ? MemoryLifetime::Prepare   :
                                        MemoryLifetime::Persistent,
            _reshaped_weights.total_size());

        _aux_mem[ConvertedWeights] = MemoryInfo(
            offset_int_vec(ConvertedWeights),
            _dynamic_weights ? MemoryLifetime::Temporary : MemoryLifetime::Persistent,
            _converted_weights.total_size());
    }
    _aux_mem[FlattenedSrc] = MemoryInfo(offset_int_vec(FlattenedSrc), MemoryLifetime::Temporary, _flattened_src.total_size());
}

Status CpuFullyConnected::has_opt_impl(arm_compute::WeightFormat &expected_weight_format, const ITensorInfo *src, const ITensorInfo *weights,
                                       const ITensorInfo *biases, const ITensorInfo *dst, FullyConnectedLayerInfo fc_info, WeightsInfo weights_info)
{
    GEMMInfo gemm_info;
    gemm_info.set_activation_info(fc_info.activation_info);
    gemm_info.set_fast_math(fc_info.enable_fast_math);
    gemm_info.set_fixed_format(weights_info.weight_format() != WeightFormat::UNSPECIFIED);
    gemm_info.set_weight_format(weights_info.weight_format());

    return CpuGemm::has_opt_impl(expected_weight_format, src, weights, biases, dst, gemm_info);
}

Status CpuFullyConnected::validate(const ITensorInfo *src, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *dst,
                                   FullyConnectedLayerInfo fc_info, const WeightsInfo &weights_info)
{
    ARM_COMPUTE_UNUSED(fc_info.retain_internal_weights);
    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_fixed_format_fast_math(weights_info.weight_format()))
    {
        ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_NOT_IN(src, DataType::F32);
        ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_NOT_IN(weights, DataType::BFLOAT16);
        ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_NOT_IN(dst, DataType::F32);
    }
    else
    {
        ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(src, weights, dst);
    }

    ARM_COMPUTE_RETURN_ERROR_ON(weights->num_dimensions() > 2);
    ARM_COMPUTE_RETURN_ERROR_ON(fc_info.activation_info.enabled() && is_data_type_quantized(src->data_type()) && fc_info.activation_info.activation() != ActivationLayerInfo::ActivationFunction::RELU
                                && fc_info.activation_info.activation() != ActivationLayerInfo::ActivationFunction::BOUNDED_RELU && fc_info.activation_info.activation() != ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU);

    bool weights_reshaped = fc_info.transpose_weights ? fc_info.are_weights_reshaped : true;
    bool is_fc_after_conv = true;

    const ITensorInfo &flatten_src       = TensorInfo(src->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(compute_flatten_shape(src)));
    const ITensorInfo &reshaped_weights  = TensorInfo(weights->clone()->set_is_resizable(true).reset_padding().set_tensor_shape(compute_transposed_shape(*weights)));
    const ITensorInfo &converted_weights = weights_reshaped ? TensorInfo(weights->clone()->set_is_resizable(true).reset_padding()) : TensorInfo(*reshaped_weights.clone());

    // With the Fully Connected layer we can have 4 different cases:
    //  1) Convolution layer -> Fully Connected layer without batches
    //  2) Fully Connected layer -> Fully Connected layer without batches
    //  3) Convolution layer -> Fully Connected layer with batches
    //  4) Fully Connected layer -> Fully Connected layer with batches

    const ITensorInfo *src_to_use     = src;
    const ITensorInfo *weights_to_use = weights;

    // Check if we have a fully connected layer with batches
    const bool is_batched_fc_layer = dst->dimension(1) > 1;

    if(biases != nullptr)
    {
        ARM_COMPUTE_RETURN_ERROR_ON(biases->num_dimensions() > 1);
        if(is_data_type_quantized(src->data_type()))
        {
            ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(biases, 1, DataType::S32);
        }
        else
        {
            ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(src, biases);
        }
    }

    if(is_batched_fc_layer)
    {
        is_fc_after_conv = (TensorShape::num_max_dimensions >= 4) && (std::equal(src->tensor_shape().cbegin() + 3, src->tensor_shape().cend(), dst->tensor_shape().cbegin() + 1));
    }
    else
    {
        is_fc_after_conv = src->num_dimensions() > 1;
    }

    if(!weights_reshaped)
    {
        // Validate reshape weights kernel
        ARM_COMPUTE_RETURN_ON_ERROR(kernels::CpuTransposeKernel::validate(weights, &reshaped_weights));
        weights_to_use = &reshaped_weights;
    }

    if(is_fc_after_conv && (src->data_layout() != fc_info.weights_trained_layout))
    {
        // Validate convert weights kernel
        ARM_COMPUTE_RETURN_ON_ERROR(CpuConvertFullyConnectedWeights::validate(weights_to_use,
                                                                              &converted_weights,
                                                                              src->tensor_shape(),
                                                                              fc_info.weights_trained_layout));
        weights_to_use = &converted_weights;
    }

    if(is_fc_after_conv)
    {
        // Fully Connected layer after a Convolution Layer without batches
        ARM_COMPUTE_RETURN_ERROR_ON((weights_to_use->dimension(1) != (src->dimension(0) * src->dimension(1) * src->dimension(2))));

        // Validate flatten kernel
        ARM_COMPUTE_RETURN_ON_ERROR(CpuFlatten::validate(src, &flatten_src));
        src_to_use = &flatten_src;
    }
    else
    {
        // Fully Connected layer after a Fully Connected Layer without batches
        ARM_COMPUTE_RETURN_ERROR_ON(src->dimension(0) != weights_to_use->dimension(1));
    }
    // Validate matrix multiply kernel
    ARM_COMPUTE_RETURN_ON_ERROR(validate_mm(src_to_use, weights_to_use, biases, dst, fc_info.activation_info, fc_info.enable_fast_math, weights_info.weight_format()));

    return Status{};
}

void CpuFullyConnected::run(ITensorPack &tensors)
{
    prepare(tensors);

#ifdef ARM_COMPUTE_ASSERTS_ENABLED
    ++_asrt_run_count;
    ARM_COMPUTE_ERROR_ON(_dynamic_weights && _asrt_prepare_count != _asrt_run_count);
#endif // ARM_COMPUTE_ASSERTS_ENABLED

    auto src = tensors.get_const_tensor(ACL_SRC_0);

    CpuAuxTensorHandler flattened_src(offset_int_vec(FlattenedSrc), _flattened_src, tensors, false);
    CpuAuxTensorHandler transformed_wei(offset_int_vec(_trans_weights_idx), _trans_weights, tensors, false);

    // Linearize src if it comes from a convolutional layer
    if(_is_fc_after_conv)
    {
        ITensorPack flatten_pack{ { ACL_SRC, src }, { ACL_DST, flattened_src.get() } };
        _flatten->run(flatten_pack);
    }

    ITensorPack gemm_pack = tensors;
    gemm_pack.add_const_tensor(ACL_SRC_0, (_is_fc_after_conv) ? flattened_src.get() : src);
    if(_needs_weights_reshape || _needs_weights_conversion)
    {
        gemm_pack.add_const_tensor(ACL_SRC_1, transformed_wei.get());
    }

    // Run matrix multiply
    if(_is_quantized_asymmetric)
    {
        _mm_gemmlowp->run(gemm_pack);
    }
    else
    {
        _mm_gemm->run(gemm_pack);
    }
}

void CpuFullyConnected::prepare(ITensorPack &tensors)
{
    if(!_is_prepared || _dynamic_weights)
    {
#ifdef ARM_COMPUTE_ASSERTS_ENABLED
        ++_asrt_prepare_count;
        ARM_COMPUTE_ERROR_ON(!_dynamic_weights && _asrt_prepare_count > 1);
#endif // ARM_COMPUTE_ASSERTS_ENABLED

        auto weights = tensors.get_const_tensor(ACL_SRC_1);

        CpuAuxTensorHandler reshaped_weights(offset_int_vec(TransposedWeights), _reshaped_weights, tensors, false);
        CpuAuxTensorHandler converted_weights(offset_int_vec(ConvertedWeights), _converted_weights, tensors, false);

        // Pointer to current weights
        const ITensor *cur_weights = weights;

        // Reshape of the weights (happens only once)
        if(_needs_weights_reshape)
        {
            // Run reshape weights kernel and mark weights as unused
            ITensorPack transpose_pack{ { ACL_SRC, weights }, { ACL_DST, reshaped_weights.get() } };
            NEScheduler::get().schedule_op(_transpose_weights.get(), Window::DimY, _transpose_weights->window(), transpose_pack);

            cur_weights->mark_as_unused();
            cur_weights = reshaped_weights.get();
        }

        // Convert weights if needed (happens only once)
        if(_needs_weights_conversion)
        {
            ITensorPack convert_pack{ { ACL_SRC, cur_weights }, { ACL_DST, converted_weights.get() } };
            _convert_weights->run(convert_pack);

            cur_weights->mark_as_unused();
            cur_weights = converted_weights.get();
        }

        ITensorPack gemm_pack = tensors;
        gemm_pack.add_const_tensor(ACL_SRC_1, cur_weights);

        // Prepare GEMM prepare and release unused weights
        if(!_is_quantized_asymmetric)
        {
            _mm_gemm->prepare(gemm_pack);
        }
        else
        {
            _mm_gemmlowp->prepare(gemm_pack);
        }

        _is_prepared = true;
    }
}

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