COMPMID-643: Add bias to CLDepthwiseConvolution.

Change-Id: Ibfe7b8c1172d10cbcae7971fe86b82090519d31d
Reviewed-on: http://mpd-gerrit.cambridge.arm.com/92798
Tested-by: Kaizen <jeremy.johnson+kaizengerrit@arm.com>
Reviewed-by: Jaroslaw Rzepecki <jaroslaw.rzepecki@arm.com>
Reviewed-by: Anthony Barbier <anthony.barbier@arm.com>
diff --git a/tests/validation/CPP/DepthwiseConvolution.cpp b/tests/validation/CPP/DepthwiseConvolution.cpp
index b57c268..e29d014 100644
--- a/tests/validation/CPP/DepthwiseConvolution.cpp
+++ b/tests/validation/CPP/DepthwiseConvolution.cpp
@@ -45,7 +45,7 @@
  *
  */
 template <typename T>
-SimpleTensor<T> depthwise_convolution(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const TensorShape &dst_shape, const PadStrideInfo &conv_info)
+SimpleTensor<T> depthwise_convolution(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<T> &biases, const TensorShape &dst_shape, const PadStrideInfo &conv_info)
 {
     // Create reference
     SimpleTensor<T> dst{ dst_shape, src.data_type(), 1, src.fixed_point_position() };
@@ -97,7 +97,7 @@
                     }
                     coords.set(0, x);
                     coords.set(1, y);
-                    dst[out_pos++] = saturate_cast<T>(val);
+                    dst[out_pos++] = saturate_cast<T>(val + *static_cast<const T *>(biases(Coordinates(z))));
                 }
             }
         }
@@ -106,7 +106,8 @@
     return dst;
 }
 
-template SimpleTensor<float> depthwise_convolution(const SimpleTensor<float> &src, const SimpleTensor<float> &weights, const TensorShape &dst_shape, const PadStrideInfo &conv_info);
+template SimpleTensor<float> depthwise_convolution(const SimpleTensor<float> &src, const SimpleTensor<float> &weights, const SimpleTensor<float> &biases, const TensorShape &dst_shape,
+                                                   const PadStrideInfo &conv_info);
 } // namespace reference
 } // namespace validation
 } // namespace test
diff --git a/tests/validation/CPP/DepthwiseConvolution.h b/tests/validation/CPP/DepthwiseConvolution.h
index 6be80fc..e8c55b1 100644
--- a/tests/validation/CPP/DepthwiseConvolution.h
+++ b/tests/validation/CPP/DepthwiseConvolution.h
@@ -36,7 +36,7 @@
 namespace reference
 {
 template <typename T>
-SimpleTensor<T> depthwise_convolution(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const TensorShape &dst_shape, const PadStrideInfo &conv_info);
+SimpleTensor<T> depthwise_convolution(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<T> &biases, const TensorShape &dst_shape, const PadStrideInfo &conv_info);
 } // namespace reference
 } // namespace validation
 } // namespace test
diff --git a/tests/validation/CPP/DepthwiseSeparableConvolutionLayer.cpp b/tests/validation/CPP/DepthwiseSeparableConvolutionLayer.cpp
index 3942ecf..8c8e50d 100644
--- a/tests/validation/CPP/DepthwiseSeparableConvolutionLayer.cpp
+++ b/tests/validation/CPP/DepthwiseSeparableConvolutionLayer.cpp
@@ -40,19 +40,22 @@
 {
 // Depthwise separable convolution layer
 template <typename T>
-SimpleTensor<T> depthwise_separable_convolution_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &depthwise_weights, const TensorShape &depthwise_out_shape,
+SimpleTensor<T> depthwise_separable_convolution_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &depthwise_weights, const SimpleTensor<T> &depthwise_biases,
+                                                      const TensorShape     &depthwise_out_shape,
                                                       const SimpleTensor<T> &pointwise_weights,
-                                                      const SimpleTensor<T> &biases, const TensorShape &dst_shape, const PadStrideInfo &depthwise_conv_info, const PadStrideInfo &pointwise_conv_info)
+                                                      const SimpleTensor<T> &pointwise_biases, const TensorShape &dst_shape, const PadStrideInfo &depthwise_conv_info, const PadStrideInfo &pointwise_conv_info)
 {
     // Compute reference
-    SimpleTensor<T> depthwise_out = depthwise_convolution(src, depthwise_weights, depthwise_out_shape, depthwise_conv_info);
-    SimpleTensor<T> dst           = convolution_layer(depthwise_out, pointwise_weights, biases, dst_shape, pointwise_conv_info);
+    SimpleTensor<T> depthwise_out = depthwise_convolution(src, depthwise_weights, depthwise_biases, depthwise_out_shape, depthwise_conv_info);
+    SimpleTensor<T> dst           = convolution_layer(depthwise_out, pointwise_weights, pointwise_biases, dst_shape, pointwise_conv_info);
 
     return dst;
 }
 
-template SimpleTensor<float> depthwise_separable_convolution_layer(const SimpleTensor<float> &in, const SimpleTensor<float> &depthwise_weights, const TensorShape &depthwise_out_shape,
-                                                                   const SimpleTensor<float> &pointwise_weights, const SimpleTensor<float> &biases, const TensorShape &dst_shape, const PadStrideInfo &depthwise_conv_info, const PadStrideInfo &pointwise_conv_info);
+template SimpleTensor<float> depthwise_separable_convolution_layer(const SimpleTensor<float> &in, const SimpleTensor<float> &depthwise_weights, const SimpleTensor<float> &depthwise_biases,
+                                                                   const TensorShape         &depthwise_out_shape,
+                                                                   const SimpleTensor<float> &pointwise_weights, const SimpleTensor<float> &pointwise_biases, const TensorShape &dst_shape, const PadStrideInfo &depthwise_conv_info,
+                                                                   const PadStrideInfo &pointwise_conv_info);
 } // namespace reference
 } // namespace validation
 } // namespace test
diff --git a/tests/validation/CPP/DepthwiseSeparableConvolutionLayer.h b/tests/validation/CPP/DepthwiseSeparableConvolutionLayer.h
index 71cd013..0fcce2c 100644
--- a/tests/validation/CPP/DepthwiseSeparableConvolutionLayer.h
+++ b/tests/validation/CPP/DepthwiseSeparableConvolutionLayer.h
@@ -36,9 +36,10 @@
 namespace reference
 {
 template <typename T>
-SimpleTensor<T> depthwise_separable_convolution_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &depthwise_weights, const TensorShape &depthwise_out_shape,
-                                                      const SimpleTensor<T> &pointwise_weights,
-                                                      const SimpleTensor<T> &biases, const TensorShape &dst_shape, const PadStrideInfo &depthwise_conv_info, const PadStrideInfo &pointwise_conv_info);
+SimpleTensor<T> depthwise_separable_convolution_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &depthwise_weights, const SimpleTensor<T> &depthwise_biases,
+                                                      const TensorShape     &depthwise_out_shape,
+                                                      const SimpleTensor<T> &pointwise_weights, const SimpleTensor<T> &pointwise_biases, const TensorShape &dst_shape,
+                                                      const PadStrideInfo &depthwise_conv_info, const PadStrideInfo &pointwise_conv_info);
 } // namespace reference
 } // namespace validation
 } // namespace test
diff --git a/tests/validation/fixtures/DepthwiseConvolutionFixture.h b/tests/validation/fixtures/DepthwiseConvolutionFixture.h
index 4a890f6..d883807 100644
--- a/tests/validation/fixtures/DepthwiseConvolutionFixture.h
+++ b/tests/validation/fixtures/DepthwiseConvolutionFixture.h
@@ -47,10 +47,10 @@
 {
 public:
     template <typename...>
-    void setup(TensorShape in_shape, TensorShape weights_shape, TensorShape out_shape, PadStrideInfo pad_stride_info)
+    void setup(TensorShape in_shape, TensorShape weights_shape, TensorShape biases_shape, TensorShape out_shape, PadStrideInfo pad_stride_info)
     {
-        _target    = compute_target(in_shape, weights_shape, out_shape, pad_stride_info);
-        _reference = compute_reference(in_shape, weights_shape, out_shape, pad_stride_info);
+        _target    = compute_target(in_shape, weights_shape, biases_shape, out_shape, pad_stride_info);
+        _reference = compute_reference(in_shape, weights_shape, biases_shape, out_shape, pad_stride_info);
     }
 
 protected:
@@ -70,29 +70,33 @@
         }
     }
 
-    TensorType compute_target(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &output_shape, PadStrideInfo &pad_stride_info)
+    TensorType compute_target(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &biases_shape, const TensorShape &output_shape, PadStrideInfo &pad_stride_info)
     {
         // Create tensors
         TensorType src     = create_tensor<TensorType>(input_shape, DataType::F32);
         TensorType weights = create_tensor<TensorType>(weights_shape, DataType::F32);
+        TensorType biases  = create_tensor<TensorType>(biases_shape, DataType::F32);
         TensorType dst     = create_tensor<TensorType>(output_shape, DataType::F32);
 
         // Create Depthwise Convolution configure function
         FunctionType depthwise_convolution;
-        depthwise_convolution.configure(&src, &dst, &weights, pad_stride_info);
+        depthwise_convolution.configure(&src, &dst, &weights, &biases, pad_stride_info);
 
         // Allocate tensors
         src.allocator()->allocate();
         weights.allocator()->allocate();
+        biases.allocator()->allocate();
         dst.allocator()->allocate();
 
         ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS);
         ARM_COMPUTE_EXPECT(!weights.info()->is_resizable(), framework::LogLevel::ERRORS);
+        ARM_COMPUTE_EXPECT(!biases.info()->is_resizable(), framework::LogLevel::ERRORS);
         ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS);
 
         // Fill tensors
         fill(AccessorType(src), 0);
         fill(AccessorType(weights), 1);
+        fill(AccessorType(biases), 2);
 
         // Compute function
         depthwise_convolution.run();
@@ -100,15 +104,17 @@
         return dst;
     }
 
-    SimpleTensor<T> compute_reference(const TensorShape &in_shape, const TensorShape &weights_shape, const TensorShape &out_shape, const PadStrideInfo &pad_stride_info)
+    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)
     {
         SimpleTensor<T> src(in_shape, DataType::F32);
         SimpleTensor<T> weights(weights_shape, DataType::F32);
+        SimpleTensor<T> biases(biases_shape, DataType::F32);
 
         fill(src, 0);
         fill(weights, 1);
+        fill(biases, 2);
 
-        return reference::depthwise_convolution(src, weights, out_shape, pad_stride_info);
+        return reference::depthwise_convolution(src, weights, biases, out_shape, pad_stride_info);
     }
 
     TensorType      _target{};
diff --git a/tests/validation/fixtures/DepthwiseSeparableConvolutionLayerFixture.h b/tests/validation/fixtures/DepthwiseSeparableConvolutionLayerFixture.h
index e8f6854..112bd19 100644
--- a/tests/validation/fixtures/DepthwiseSeparableConvolutionLayerFixture.h
+++ b/tests/validation/fixtures/DepthwiseSeparableConvolutionLayerFixture.h
@@ -47,22 +47,25 @@
 {
 public:
     template <typename...>
-    void setup(TensorShape in_shape, TensorShape depthwise_weights_shape, TensorShape depthwise_out_shape, TensorShape pointwise_weights_shape, TensorShape biases_shape, TensorShape output_shape,
+    void setup(TensorShape in_shape, TensorShape depthwise_weights_shape, TensorShape depthwise_biases_shape, TensorShape depthwise_out_shape, TensorShape pointwise_weights_shape,
+               TensorShape pointwise_biases_shape, TensorShape output_shape,
                PadStrideInfo pad_stride_depthwise_info, PadStrideInfo pad_stride_pointwise_info)
     {
-        _target    = compute_target(in_shape, depthwise_weights_shape, depthwise_out_shape, pointwise_weights_shape, biases_shape, output_shape, pad_stride_depthwise_info, pad_stride_pointwise_info);
-        _reference = compute_reference(in_shape, depthwise_weights_shape, depthwise_out_shape, pointwise_weights_shape, biases_shape, output_shape, pad_stride_depthwise_info, pad_stride_pointwise_info);
+        _target = compute_target(in_shape, depthwise_weights_shape, depthwise_biases_shape, depthwise_out_shape, pointwise_weights_shape, pointwise_biases_shape, output_shape, pad_stride_depthwise_info,
+                                 pad_stride_pointwise_info);
+        _reference = compute_reference(in_shape, depthwise_weights_shape, depthwise_biases_shape, depthwise_out_shape, pointwise_weights_shape, pointwise_biases_shape, output_shape, pad_stride_depthwise_info,
+                                       pad_stride_pointwise_info);
     }
 
 protected:
     template <typename U>
-    void fill(U &&tensor, int i)
+    void fill(U &&tensor, int i, bool zero_fill = false)
     {
         switch(tensor.data_type())
         {
             case DataType::F32:
             {
-                std::uniform_real_distribution<> distribution(-1.0f, 1.0f);
+                std::uniform_real_distribution<> distribution((zero_fill) ? 0.f : -1.0f, (zero_fill) ? 0.f : 1.0f);
                 library->fill(tensor, distribution, i);
                 break;
             }
@@ -71,42 +74,47 @@
         }
     }
 
-    TensorType compute_target(const TensorShape &input_shape, const TensorShape &depthwise_weights_shape, const TensorShape &depthwise_out_shape, const TensorShape &pointwise_weights_shape,
-                              const TensorShape &biases_shape,
-                              const TensorShape &output_shape, const PadStrideInfo &pad_stride_depthwise_info, const PadStrideInfo &pad_stride_pointwise_info)
+    TensorType compute_target(const TensorShape &input_shape, const TensorShape &depthwise_weights_shape, const TensorShape &depthwise_biases_shape, const TensorShape &depthwise_out_shape,
+                              const TensorShape &pointwise_weights_shape, const TensorShape &pointwise_biases_shape, const TensorShape &output_shape,
+                              const PadStrideInfo &pad_stride_depthwise_info, const PadStrideInfo &pad_stride_pointwise_info)
     {
         // Create tensors
         TensorType src               = create_tensor<TensorType>(input_shape, DataType::F32);
         TensorType depthwise_weights = create_tensor<TensorType>(depthwise_weights_shape, DataType::F32);
+        TensorType depthwise_biases  = create_tensor<TensorType>(depthwise_biases_shape, DataType::F32);
         TensorType depthwise_out     = create_tensor<TensorType>(depthwise_out_shape, DataType::F32);
         TensorType pointwise_weights = create_tensor<TensorType>(pointwise_weights_shape, DataType::F32);
-        TensorType biases            = create_tensor<TensorType>(biases_shape, DataType::F32);
+        TensorType pointwise_biases  = create_tensor<TensorType>(pointwise_biases_shape, DataType::F32);
         TensorType dst               = create_tensor<TensorType>(output_shape, DataType::F32);
 
         // Create Depthwise Separable Convolution Layer configure function
         CLDepthwiseSeparableConvolutionLayer depthwise_separable_convolution_layer;
-        depthwise_separable_convolution_layer.configure(&src, &depthwise_weights, &depthwise_out, &pointwise_weights, &biases, &dst, pad_stride_depthwise_info, pad_stride_pointwise_info);
+        depthwise_separable_convolution_layer.configure(&src, &depthwise_weights, &depthwise_biases, &depthwise_out, &pointwise_weights, &pointwise_biases, &dst, pad_stride_depthwise_info,
+                                                        pad_stride_pointwise_info);
 
         // Allocate tensors
         src.allocator()->allocate();
         depthwise_weights.allocator()->allocate();
+        depthwise_biases.allocator()->allocate();
         depthwise_out.allocator()->allocate();
         pointwise_weights.allocator()->allocate();
-        biases.allocator()->allocate();
+        pointwise_biases.allocator()->allocate();
         dst.allocator()->allocate();
 
         ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS);
         ARM_COMPUTE_EXPECT(!depthwise_weights.info()->is_resizable(), framework::LogLevel::ERRORS);
+        ARM_COMPUTE_EXPECT(!depthwise_biases.info()->is_resizable(), framework::LogLevel::ERRORS);
         ARM_COMPUTE_EXPECT(!depthwise_out.info()->is_resizable(), framework::LogLevel::ERRORS);
         ARM_COMPUTE_EXPECT(!pointwise_weights.info()->is_resizable(), framework::LogLevel::ERRORS);
-        ARM_COMPUTE_EXPECT(!biases.info()->is_resizable(), framework::LogLevel::ERRORS);
+        ARM_COMPUTE_EXPECT(!pointwise_biases.info()->is_resizable(), framework::LogLevel::ERRORS);
         ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS);
 
         // Fill tensors
         fill(AccessorType(src), 0);
         fill(AccessorType(depthwise_weights), 1);
-        fill(AccessorType(pointwise_weights), 2);
-        fill(AccessorType(biases), 3);
+        fill(AccessorType(depthwise_biases), 2, true);
+        fill(AccessorType(pointwise_weights), 3);
+        fill(AccessorType(pointwise_biases), 4);
 
         // Compute function
         depthwise_separable_convolution_layer.run();
@@ -114,20 +122,27 @@
         return dst;
     }
 
-    SimpleTensor<T> compute_reference(const TensorShape &in_shape, const TensorShape &depthwise_weights_shape, const TensorShape &depthwise_out_shape, const TensorShape &pointwise_weights_shape,
-                                      const TensorShape &biases_shape, const TensorShape &dst_shape, const PadStrideInfo &pad_stride_depthwise_info, const PadStrideInfo &pad_stride_pointwise_info)
+    SimpleTensor<T> compute_reference(const TensorShape &in_shape, const TensorShape &depthwise_weights_shape, const TensorShape &depthwise_biases_shape, const TensorShape &depthwise_out_shape,
+                                      const TensorShape &pointwise_weights_shape, const TensorShape &pointwise_biases_shape, const TensorShape &dst_shape,
+                                      const PadStrideInfo &pad_stride_depthwise_info, const PadStrideInfo &pad_stride_pointwise_info)
     {
         SimpleTensor<T> src(in_shape, DataType::F32);
         SimpleTensor<T> depthwise_weights(depthwise_weights_shape, DataType::F32);
+        SimpleTensor<T> depthwise_biases(depthwise_biases_shape, DataType::F32);
         SimpleTensor<T> pointwise_weights(pointwise_weights_shape, DataType::F32);
-        SimpleTensor<T> biases(biases_shape, DataType::F32);
+        SimpleTensor<T> pointwise_biases(pointwise_biases_shape, DataType::F32);
 
         fill(src, 0);
         fill(depthwise_weights, 1);
-        fill(pointwise_weights, 2);
-        fill(biases, 3);
+        fill(depthwise_biases, 2, true);
+        fill(pointwise_weights, 3);
+        fill(pointwise_biases, 4);
 
-        return reference::depthwise_separable_convolution_layer(src, depthwise_weights, depthwise_out_shape, pointwise_weights, biases, dst_shape, pad_stride_depthwise_info, pad_stride_pointwise_info);
+        return reference::depthwise_separable_convolution_layer(src,
+                                                                depthwise_weights, depthwise_biases, depthwise_out_shape,
+                                                                pointwise_weights, pointwise_biases,
+                                                                dst_shape,
+                                                                pad_stride_depthwise_info, pad_stride_pointwise_info);
     }
 
     TensorType      _target{};