COMPMID-2306: CLDepthwiseConvolution: support for QUANT8_PER_CHANNEL_SYMM - Reference

This patch modifies the reference implementation and the fixtures of
depthwise convolution layer to support QSYMM8_PER_CHANNEL quantization.

Change-Id: I28adb5c110308b1024a213bec2d35a89180a46dc
Signed-off-by: Michele Di Giorgio <michele.digiorgio@arm.com>
Reviewed-on: https://review.mlplatform.org/c/2063
Reviewed-by: Giorgio Arena <giorgio.arena@arm.com>
Comments-Addressed: Arm Jenkins <bsgcomp@arm.com>
Reviewed-by: Giuseppe Rossini <giuseppe.rossini@arm.com>
Tested-by: Arm Jenkins <bsgcomp@arm.com>
diff --git a/tests/validation/fixtures/DepthwiseConvolutionLayerFixture.h b/tests/validation/fixtures/DepthwiseConvolutionLayerFixture.h
index 2c9b318..85930eb 100644
--- a/tests/validation/fixtures/DepthwiseConvolutionLayerFixture.h
+++ b/tests/validation/fixtures/DepthwiseConvolutionLayerFixture.h
@@ -48,32 +48,34 @@
 {
 using namespace arm_compute::misc::shape_calculator;
 
-template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
+template <typename TensorType, typename AccessorType, typename FunctionType, typename T, typename TW>
 class DepthwiseConvolutionLayerValidationGenericFixture : public framework::Fixture
 {
 public:
-    using TBias = typename std::conditional<std::is_same<typename std::decay<T>::type, uint8_t>::value, int32_t, T>::type;
+    using TBias = typename std::conditional < std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value, int32_t, T >::type;
 
 public:
     template <typename...>
-    void setup(TensorShape in_shape, Size2D kernel_size, PadStrideInfo pad_stride_info, Size2D dilation, unsigned int depth_multiplier, DataType data_type,
-               QuantizationInfo input_quantization_info, QuantizationInfo output_quantization_info, DataLayout data_layout, ActivationLayerInfo act_info)
+    void setup(TensorShape in_shape, Size2D kernel_size, PadStrideInfo pad_stride_info, Size2D dilation,
+               unsigned int depth_multiplier, DataType input_data_type, DataType weights_data_type,
+               QuantizationInfo input_quantization_info, QuantizationInfo weights_quantization_info, QuantizationInfo output_quantization_info,
+               DataLayout data_layout, ActivationLayerInfo act_info)
     {
-        const DataType bias_data_type = is_data_type_quantized_asymmetric(data_type) ? DataType::S32 : data_type;
+        const DataType bias_data_type = is_data_type_quantized(input_data_type) ? DataType::S32 : input_data_type;
 
         TensorShape weights_shape(kernel_size.width, kernel_size.height);
 
-        const TensorInfo  in_info(in_shape, 1, data_type);
-        const TensorInfo  we_info(weights_shape, 1, data_type);
+        const TensorInfo  in_info(in_shape, 1, input_data_type);
+        const TensorInfo  we_info(weights_shape, 1, weights_data_type);
         const TensorShape out_shape = compute_depthwise_convolution_shape(in_info, we_info, pad_stride_info, depth_multiplier, dilation);
 
         weights_shape.set(2, out_shape.z());
         const TensorShape biases_shape(weights_shape[2]);
 
         _target = compute_target(in_shape, weights_shape, biases_shape, out_shape, pad_stride_info, dilation, depth_multiplier,
-                                 data_type, bias_data_type, input_quantization_info, output_quantization_info, data_layout, act_info);
+                                 input_data_type, weights_data_type, bias_data_type, input_quantization_info, weights_quantization_info, output_quantization_info, data_layout, act_info);
         _reference = compute_reference(in_shape, weights_shape, biases_shape, out_shape, pad_stride_info, dilation, depth_multiplier,
-                                       data_type, bias_data_type, input_quantization_info, output_quantization_info, act_info);
+                                       input_data_type, weights_data_type, bias_data_type, input_quantization_info, weights_quantization_info, output_quantization_info, act_info);
     }
 
 protected:
@@ -88,6 +90,12 @@
                 library->fill(tensor, distribution, i);
                 break;
             }
+            case DataType::QSYMM8_PER_CHANNEL:
+            {
+                std::uniform_int_distribution<int8_t> distribution(-10, 10);
+                library->fill(tensor, distribution, i);
+                break;
+            }
             case DataType::F32:
             case DataType::F16:
             {
@@ -107,9 +115,8 @@
     }
 
     TensorType compute_target(TensorShape input_shape, TensorShape weights_shape, TensorShape biases_shape, TensorShape output_shape, PadStrideInfo &pad_stride_info, Size2D dilation,
-                              unsigned int   depth_multiplier,
-                              const DataType data_type, const DataType bias_data_type,
-                              const QuantizationInfo &input_quantization_info, const QuantizationInfo &output_quantization_info,
+                              unsigned int depth_multiplier, const DataType input_data_type, const DataType weights_data_type, const DataType bias_data_type,
+                              const QuantizationInfo &input_quantization_info, const QuantizationInfo &weights_quantization_info, const QuantizationInfo &output_quantization_info,
                               const DataLayout data_layout, const ActivationLayerInfo &act_info)
     {
         if(data_layout == DataLayout::NHWC)
@@ -120,10 +127,10 @@
         }
 
         // Create tensors
-        TensorType src     = create_tensor<TensorType>(input_shape, data_type, 1, input_quantization_info, data_layout);
-        TensorType weights = create_tensor<TensorType>(weights_shape, data_type, 1, input_quantization_info, data_layout);
+        TensorType src     = create_tensor<TensorType>(input_shape, input_data_type, 1, input_quantization_info, data_layout);
+        TensorType weights = create_tensor<TensorType>(weights_shape, weights_data_type, 1, weights_quantization_info, data_layout);
         TensorType biases  = create_tensor<TensorType>(biases_shape, bias_data_type, 1, input_quantization_info, data_layout);
-        TensorType dst     = create_tensor<TensorType>(output_shape, data_type, 1, output_quantization_info, data_layout);
+        TensorType dst     = create_tensor<TensorType>(output_shape, input_data_type, 1, output_quantization_info, data_layout);
 
         // Create Depthwise Convolution configure function
         FunctionType dwc;
@@ -157,14 +164,13 @@
     }
 
     SimpleTensor<T> compute_reference(const TensorShape &in_shape, const TensorShape &weights_shape, const TensorShape &biases_shape, const TensorShape &out_shape,
-                                      const PadStrideInfo &pad_stride_info,
-                                      const Size2D &dilation, unsigned int depth_multiplier,
-                                      const DataType data_type, const DataType bias_data_type,
-                                      const QuantizationInfo &input_quantization_info, const QuantizationInfo &output_quantization_info,
+                                      const PadStrideInfo &pad_stride_info, const Size2D &dilation, unsigned int depth_multiplier,
+                                      const DataType input_data_type, const DataType weights_data_type, const DataType bias_data_type,
+                                      const QuantizationInfo &input_quantization_info, const QuantizationInfo &weights_quantization_info, const QuantizationInfo &output_quantization_info,
                                       const ActivationLayerInfo &act_info)
     {
-        SimpleTensor<T>     src{ in_shape, data_type, 1, input_quantization_info };
-        SimpleTensor<T>     weights{ weights_shape, data_type, 1, input_quantization_info };
+        SimpleTensor<T>     src{ in_shape, input_data_type, 1, input_quantization_info };
+        SimpleTensor<TW>    weights{ weights_shape, weights_data_type, 1, weights_quantization_info };
         SimpleTensor<TBias> biases{ biases_shape, bias_data_type, 1, input_quantization_info };
 
         fill(src, 0);
@@ -180,20 +186,21 @@
 };
 
 template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
-class DepthwiseConvolutionLayerValidationFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T>
+class DepthwiseConvolutionLayerValidationFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
 {
 public:
     template <typename...>
     void setup(TensorShape in_shape, Size2D kernel_size, PadStrideInfo pad_stride_info, Size2D dilation, unsigned int depth_multiplier, DataType data_type, DataLayout data_layout,
                ActivationLayerInfo act_info)
     {
-        DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier,
-                                                                                                            data_type, QuantizationInfo(), QuantizationInfo(), data_layout, act_info);
+        DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier,
+                                                                                                               data_type, data_type, QuantizationInfo(), QuantizationInfo(), QuantizationInfo(),
+                                                                                                               data_layout, act_info);
     }
 };
 
 template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
-class DepthwiseConvolutionLayerNativeValidationFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T>
+class DepthwiseConvolutionLayerNativeValidationFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
 {
 public:
     template <typename...>
@@ -302,7 +309,7 @@
 };
 
 template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
-class DepthwiseConvolutionLayerNativeConfigurableValidationFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T>
+class DepthwiseConvolutionLayerNativeConfigurableValidationFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
 {
 public:
     template <typename...>
@@ -423,15 +430,32 @@
 };
 
 template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
-class DepthwiseConvolutionLayerValidationQuantizedFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T>
+class DepthwiseConvolutionLayerValidationQuantizedFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
 {
 public:
     template <typename...>
     void setup(TensorShape in_shape, Size2D kernel_size, PadStrideInfo pad_stride_info, Size2D dilation, unsigned int depth_multiplier, DataType data_type,
                QuantizationInfo input_quantization_info, QuantizationInfo output_quantization_info, DataLayout data_layout, ActivationLayerInfo act_info)
     {
-        DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier,
-                                                                                                            data_type, input_quantization_info, output_quantization_info, data_layout, act_info);
+        DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier, data_type,
+                                                                                                               data_type, input_quantization_info, input_quantization_info, output_quantization_info,
+                                                                                                               data_layout, act_info);
+    }
+};
+
+template <typename TensorType, typename AccessorType, typename FunctionType, typename T, typename TW>
+class DepthwiseConvolutionLayerValidationQuantizedPerChannelFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, TW>
+{
+public:
+    template <typename...>
+    void setup(TensorShape in_shape, Size2D kernel_size, PadStrideInfo pad_stride_info, Size2D dilation, unsigned int depth_multiplier, DataType input_data_type, DataType weights_data_type,
+               QuantizationInfo input_quantization_info, QuantizationInfo weights_quantization_info, QuantizationInfo output_quantization_info,
+               DataLayout data_layout, ActivationLayerInfo act_info)
+    {
+        DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, TW>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier,
+                                                                                                                input_data_type, weights_data_type,
+                                                                                                                input_quantization_info, weights_quantization_info, output_quantization_info,
+                                                                                                                data_layout, act_info);
     }
 };
 } // namespace validation