COMPMID-727 - Implement reference and CL/NEON validation for CustomConvolutionRectangle

Change-Id: I108a48ad5e6dc3f331fd5ceb38ced8ccdb31d81a
Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/113130
Tested-by: Jenkins <bsgcomp@arm.com>
Reviewed-by: Georgios Pinitas <georgios.pinitas@arm.com>
Reviewed-by: Anthony Barbier <anthony.barbier@arm.com>
diff --git a/src/core/NEON/kernels/NEConvolutionKernel.cpp b/src/core/NEON/kernels/NEConvolutionKernel.cpp
index 3a4884e..7468f58 100644
--- a/src/core/NEON/kernels/NEConvolutionKernel.cpp
+++ b/src/core/NEON/kernels/NEConvolutionKernel.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017 ARM Limited.
+ * Copyright (c) 2016, 2018 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -1522,13 +1522,13 @@
     };
 
     // Run appropriate function
-    switch(_output->info()->format())
+    switch(_output->info()->data_type())
     {
-        case Format::U8:
+        case DataType::U8:
             ARM_COMPUTE_ERROR_ON(_func_idx >= func_table_u8.size());
             (this->*func_table_u8[_func_idx])(window);
             break;
-        case Format::S16:
+        case DataType::S16:
             ARM_COMPUTE_ERROR_ON(_func_idx >= func_table_s16.size());
             (this->*func_table_s16[_func_idx])(window);
             break;
diff --git a/src/runtime/CL/functions/CLConvolution.cpp b/src/runtime/CL/functions/CLConvolution.cpp
index a9b0867..0131801 100644
--- a/src/runtime/CL/functions/CLConvolution.cpp
+++ b/src/runtime/CL/functions/CLConvolution.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017 ARM Limited.
+ * Copyright (c) 2016, 2018 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -53,7 +53,8 @@
 }
 
 template <unsigned int matrix_size>
-void CLConvolutionSquare<matrix_size>::configure(ICLTensor *input, ICLTensor *output, const int16_t *conv, uint32_t scale, BorderMode border_mode, uint8_t constant_border_value)
+void CLConvolutionSquare<matrix_size>::configure(ICLTensor *input, ICLTensor *output, const int16_t *conv, uint32_t scale, BorderMode border_mode,
+                                                 uint8_t constant_border_value)
 {
     ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::U8);
     ARM_COMPUTE_ERROR_ON(conv == nullptr);
diff --git a/src/runtime/NEON/functions/NEConvolution.cpp b/src/runtime/NEON/functions/NEConvolution.cpp
index f10ffa6..b84dfd3 100644
--- a/src/runtime/NEON/functions/NEConvolution.cpp
+++ b/src/runtime/NEON/functions/NEConvolution.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017 ARM Limited.
+ * Copyright (c) 2016, 2018 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -54,7 +54,8 @@
 }
 
 template <unsigned int matrix_size>
-void NEConvolutionSquare<matrix_size>::configure(ITensor *input, ITensor *output, const int16_t *conv, uint32_t scale, BorderMode border_mode, uint8_t constant_border_value)
+void NEConvolutionSquare<matrix_size>::configure(ITensor *input, ITensor *output, const int16_t *conv, uint32_t scale, BorderMode border_mode,
+                                                 uint8_t constant_border_value)
 {
     ARM_COMPUTE_ERROR_ON(conv == nullptr);
     ARM_COMPUTE_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(input, 1, DataType::U8);
diff --git a/tests/validation/CL/Convolution.cpp b/tests/validation/CL/Convolution.cpp
index c836eda..d640547 100644
--- a/tests/validation/CL/Convolution.cpp
+++ b/tests/validation/CL/Convolution.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017, 2018 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -43,30 +43,17 @@
 {
 namespace
 {
-/* Convolution3x3 */
-constexpr unsigned int filter_size_3x3 = 3;                  /* Size of the kernel/filter in number of elements. */
-constexpr BorderSize   border_size_3x3(filter_size_3x3 / 2); /* Border size of the kernel/filter around its central element. */
-
-/* Convolution5x5 */
-constexpr unsigned int filter_size_5x5 = 5;                  /* Size of the kernel/filter in number of elements. */
-constexpr BorderSize   border_size_5x5(filter_size_5x5 / 2); /* Border size of the kernel/filter around its central element. */
-
-/* Convolution7x7 */
-constexpr unsigned int filter_size_7x7 = 7;                  /* Size of the kernel/filter in number of elements. */
-constexpr BorderSize   border_size_7x7(filter_size_7x7 / 2); /* Border size of the kernel/filter around its central element. */
-
-/* Convolution9x9 */
-constexpr unsigned int filter_size_9x9 = 9;                  /* Size of the kernel/filter in number of elements. */
-constexpr BorderSize   border_size_9x9(filter_size_9x9 / 2); /* Border size of the kernel/filter around its central element. */
 } // namespace
 
 TEST_SUITE(CL)
 TEST_SUITE(CustomConvolution)
+TEST_SUITE(CustomConvolutionSquare)
 TEST_SUITE(CustomConvolution3x3)
 
-DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)),
-                                                                   datasets::BorderModes()),
-               shape, data_type, border_mode)
+DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)),
+                                                                           datasets::BorderModes()),
+                                                                   framework::dataset::make("filter_size", { 3 })),
+               shape, data_type, border_mode, filter_size)
 {
     // Create tensors
     CLTensor src = create_tensor<CLTensor>(shape, data_type);
@@ -75,20 +62,15 @@
     // Create conv matrix
     int16_t conv[9];
 
-    // Generate random scale value between 0 and 255.
-    std::mt19937                           gen(library->seed());
-    std::uniform_int_distribution<uint8_t> distribution(0, 255);
-    const uint32_t                         scale = distribution(gen);
-
     ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
     ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
 
     // Create and configure function
     CLConvolution3x3 convolution;
-    convolution.configure(&src, &dst, conv, scale, border_mode);
+    convolution.configure(&src, &dst, conv, 0, border_mode);
 
     // Validate valid region
-    const ValidRegion dst_valid_region = shape_to_valid_region(shape, (border_mode == BorderMode::UNDEFINED), border_size_3x3);
+    const ValidRegion dst_valid_region = shape_to_valid_region(shape, (border_mode == BorderMode::UNDEFINED), BorderSize(filter_size / 2));
     validate(dst.info()->valid_region(), dst_valid_region);
 
     // Validate padding
@@ -108,29 +90,33 @@
 }
 
 template <typename T>
-using CLConvolutionFixture = ConvolutionValidationFixture<CLTensor, CLAccessor, CLConvolution3x3, T, filter_size_3x3>;
+using CLConvolutionFixture = ConvolutionSquareValidationFixture<CLTensor, CLAccessor, CLConvolution3x3, T>;
 
-FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType",
+FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType",
                                                                                                                    DataType::U8)),
-                                                                                                           datasets::BorderModes()))
+                                                                                                                   datasets::BorderModes()),
+                                                                                                           framework::dataset::make("filter_size", { 3 })))
 {
     // Validate output
-    validate(CLAccessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), border_size_3x3));
+    validate(CLAccessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(_height / 2, _width / 2)));
 }
 
-FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType",
+FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType",
                                                                                                                  DataType::U8)),
-                                                                                                         datasets::BorderModes()))
+                                                                                                                 datasets::BorderModes()),
+                                                                                                         framework::dataset::make("filter_size", { 3 })))
 {
     // Validate output
-    validate(CLAccessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), border_size_3x3));
+    validate(CLAccessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(_height / 2, _width / 2)));
 }
 TEST_SUITE_END() /* Custom_Convolution 3x3 */
 
 TEST_SUITE(CustomConvolution5x5)
-DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)),
-                                                                   datasets::BorderModes()),
-               shape, data_type, border_mode)
+
+DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)),
+                                                                           datasets::BorderModes()),
+                                                                   framework::dataset::make("filter_size", { 5 })),
+               shape, data_type, border_mode, filter_size)
 {
     // Create tensors
     CLTensor src = create_tensor<CLTensor>(shape, data_type);
@@ -139,20 +125,15 @@
     // Create conv matrix
     int16_t conv[25];
 
-    // Generate random scale value between 0 and 255.
-    std::mt19937                           gen(library->seed());
-    std::uniform_int_distribution<uint8_t> distribution(0, 255);
-    const uint32_t                         scale = distribution(gen);
-
     ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
     ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
 
     // Create and configure function
     CLConvolution5x5 convolution;
-    convolution.configure(&src, &dst, conv, scale, border_mode);
+    convolution.configure(&src, &dst, conv, 0, border_mode);
 
     // Validate valid region
-    const ValidRegion dst_valid_region = shape_to_valid_region(shape, (border_mode == BorderMode::UNDEFINED), border_size_5x5);
+    const ValidRegion dst_valid_region = shape_to_valid_region(shape, (border_mode == BorderMode::UNDEFINED), BorderSize(filter_size / 2));
     validate(dst.info()->valid_region(), dst_valid_region);
 
     // Validate padding
@@ -172,29 +153,31 @@
 }
 
 template <typename T>
-using CLConvolutionFixture = ConvolutionValidationFixture<CLTensor, CLAccessor, CLConvolution5x5, T, filter_size_5x5>;
-
-FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType",
+using CLConvolutionFixture = ConvolutionSquareValidationFixture<CLTensor, CLAccessor, CLConvolution5x5, T>;
+FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType",
                                                                                                                    DataType::U8)),
-                                                                                                           datasets::BorderModes()))
+                                                                                                                   datasets::BorderModes()),
+                                                                                                           framework::dataset::make("filter_size", { 5 })))
 {
     // Validate output
-    validate(CLAccessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), border_size_5x5));
+    validate(CLAccessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(_height / 2, _width / 2)));
 }
 
-FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType",
+FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType",
                                                                                                                  DataType::U8)),
-                                                                                                         datasets::BorderModes()))
+                                                                                                                 datasets::BorderModes()),
+                                                                                                         framework::dataset::make("filter_size", { 5 })))
 {
     // Validate output
-    validate(CLAccessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), border_size_5x5));
+    validate(CLAccessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(_height / 2, _width / 2)));
 }
 TEST_SUITE_END() /* Custom Convolution 5x5 */
 
 TEST_SUITE(CustomConvolution7x7)
-DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)),
-                                                                   datasets::BorderModes()),
-               shape, data_type, border_mode)
+DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)),
+                                                                           datasets::BorderModes()),
+                                                                   framework::dataset::make("filter_size", { 7 })),
+               shape, data_type, border_mode, filter_size)
 {
     // Create tensors
     CLTensor src = create_tensor<CLTensor>(shape, data_type);
@@ -203,20 +186,15 @@
     // Create conv matrix
     int16_t conv[49];
 
-    // Generate random scale value between 0 and 255.
-    std::mt19937                           gen(library->seed());
-    std::uniform_int_distribution<uint8_t> distribution(0, 255);
-    const uint32_t                         scale = distribution(gen);
-
     ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
     ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
 
     // Create and configure function
     CLConvolution7x7 convolution;
-    convolution.configure(&src, &dst, conv, scale, border_mode);
+    convolution.configure(&src, &dst, conv, 0, border_mode);
 
     // Validate valid region
-    const ValidRegion dst_valid_region = shape_to_valid_region(shape, (border_mode == BorderMode::UNDEFINED), border_size_7x7);
+    const ValidRegion dst_valid_region = shape_to_valid_region(shape, (border_mode == BorderMode::UNDEFINED), BorderSize(filter_size / 2));
     validate(dst.info()->valid_region(), dst_valid_region);
 
     // Validate padding
@@ -236,29 +214,32 @@
 }
 
 template <typename T>
-using CLConvolutionFixture = ConvolutionValidationFixture<CLTensor, CLAccessor, CLConvolution7x7, T, filter_size_7x7>;
+using CLConvolutionFixture = ConvolutionSquareValidationFixture<CLTensor, CLAccessor, CLConvolution7x7, T>;
 
-FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType",
+FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType",
                                                                                                                    DataType::U8)),
-                                                                                                           datasets::BorderModes()))
+                                                                                                                   datasets::BorderModes()),
+                                                                                                           framework::dataset::make("filter_size", { 7 })))
 {
     // Validate output
-    validate(CLAccessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), border_size_7x7));
+    validate(CLAccessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(_height / 2, _width / 2)));
 }
 
-FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType",
+FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType",
                                                                                                                  DataType::U8)),
-                                                                                                         datasets::BorderModes()))
+                                                                                                                 datasets::BorderModes()),
+                                                                                                         framework::dataset::make("filter_size", { 7 })))
 {
     // Validate output
-    validate(CLAccessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), border_size_7x7));
+    validate(CLAccessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(_height / 2, _width / 2)));
 }
 TEST_SUITE_END() /* Custom Convolution 7x7 */
 
 TEST_SUITE(CustomConvolution9x9)
-DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)),
-                                                                   datasets::BorderModes()),
-               shape, data_type, border_mode)
+DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)),
+                                                                           datasets::BorderModes()),
+                                                                   framework::dataset::make("filter_size", { 9 })),
+               shape, data_type, border_mode, filter_size)
 {
     // Create tensors
     CLTensor src = create_tensor<CLTensor>(shape, data_type);
@@ -267,20 +248,15 @@
     // Create conv matrix
     int16_t conv[81];
 
-    // Generate random scale value between 0 and 255.
-    std::mt19937                           gen(library->seed());
-    std::uniform_int_distribution<uint8_t> distribution(0, 255);
-    const uint32_t                         scale = distribution(gen);
-
     ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
     ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
 
     // Create and configure function
     CLConvolution9x9 convolution;
-    convolution.configure(&src, &dst, conv, scale, border_mode);
+    convolution.configure(&src, &dst, conv, 0, border_mode);
 
     // Validate valid region
-    const ValidRegion dst_valid_region = shape_to_valid_region(shape, (border_mode == BorderMode::UNDEFINED), border_size_9x9);
+    const ValidRegion dst_valid_region = shape_to_valid_region(shape, (border_mode == BorderMode::UNDEFINED), BorderSize(filter_size / 2));
     validate(dst.info()->valid_region(), dst_valid_region);
 
     // Validate padding
@@ -300,24 +276,98 @@
 }
 
 template <typename T>
-using CLConvolutionFixture = ConvolutionValidationFixture<CLTensor, CLAccessor, CLConvolution9x9, T, filter_size_9x9>;
+using CLConvolutionFixture = ConvolutionSquareValidationFixture<CLTensor, CLAccessor, CLConvolution9x9, T>;
 
-FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType",
+FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType",
                                                                                                                    DataType::U8)),
-                                                                                                           datasets::BorderModes()))
+                                                                                                                   datasets::BorderModes()),
+                                                                                                           framework::dataset::make("filter_size", { 9 })))
 {
     // Validate output
-    validate(CLAccessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), border_size_9x9));
+    validate(CLAccessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(_height / 2, _width / 2)));
 }
 
-FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType",
+FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType",
                                                                                                                  DataType::U8)),
-                                                                                                         datasets::BorderModes()))
+                                                                                                                 datasets::BorderModes()),
+                                                                                                         framework::dataset::make("filter_size", { 9 })))
 {
     // Validate output
-    validate(CLAccessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), border_size_9x9));
+    validate(CLAccessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(_height / 2, _width / 2)));
 }
 TEST_SUITE_END() /* Custom Convolution 9x9 */
+TEST_SUITE_END() /* Custom Convolution Square */
+
+TEST_SUITE(CustomConvolutionRectangle)
+
+DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType",
+                                                                                           DataType::U8)),
+                                                                                   datasets::BorderModes()),
+                                                                           framework::dataset::make("filter_width", { 3, 5, 7, 9 })),
+                                                                   framework::dataset::make("filter_height", { 3, 5, 7, 9 })),
+               shape, data_type, border_mode, filter_width, filter_height)
+{
+    // Create tensors
+    CLTensor src = create_tensor<CLTensor>(shape, data_type);
+    CLTensor dst = create_tensor<CLTensor>(shape, data_type);
+
+    // Create conv matrix
+    int16_t conv[filter_width * filter_height];
+
+    ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
+    ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
+
+    // Create and configure function
+    CLConvolutionRectangle convolution;
+    convolution.configure(&src, &dst, conv, filter_width, filter_height, 1, border_mode);
+
+    // Validate valid region
+    const ValidRegion dst_valid_region = shape_to_valid_region(shape, (border_mode == BorderMode::UNDEFINED), BorderSize(filter_height / 2, filter_width / 2));
+    validate(dst.info()->valid_region(), dst_valid_region);
+
+    // Validate padding
+    PaddingCalculator calculator(shape.x(), 8);
+    calculator.set_border_size(filter_width / 2);
+    calculator.set_border_mode(border_mode);
+
+    const PaddingSize dst_padding = calculator.required_padding();
+
+    calculator.set_accessed_elements(16);
+    calculator.set_access_offset(-(filter_width / 2));
+
+    const PaddingSize width_padding = calculator.required_padding();
+
+    calculator.set_border_size(filter_height / 2);
+    calculator.set_access_offset(-(filter_height / 2));
+    const PaddingSize height_padding = calculator.required_padding();
+
+    validate(src.info()->padding(), width_padding, height_padding);
+    validate(dst.info()->padding(), dst_padding);
+}
+
+template <typename T>
+using CLConvolutionFixture = ConvolutionRectangleValidationFixture<CLTensor, CLAccessor, CLConvolutionRectangle, T>;
+
+FIXTURE_DATA_TEST_CASE(RunSmall, CLConvolutionFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType",
+                                                                                                                   DataType::U8)),
+                                                                                                                   datasets::BorderModes()),
+                                                                                                                   framework::dataset::make("filter_width", { 3, 5, 7, 9 })),
+                                                                                                           framework::dataset::make("filter_height", { 3, 5, 7, 9 })))
+{
+    // Validate output
+    validate(CLAccessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(_height / 2, _width / 2)));
+}
+
+FIXTURE_DATA_TEST_CASE(RunLarge, CLConvolutionFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType",
+                                                                                                                 DataType::U8)),
+                                                                                                                 datasets::BorderModes()),
+                                                                                                                 framework::dataset::make("filter_width", { 3, 5, 7, 9 })),
+                                                                                                         framework::dataset::make("filter_height", { 3, 5, 7, 9 })))
+{
+    // Validate output
+    validate(CLAccessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(_height / 2, _width / 2)));
+}
+TEST_SUITE_END() /* Custom Convolution Rectangle */
 TEST_SUITE_END()
 TEST_SUITE_END()
 } // namespace validation
diff --git a/tests/validation/NEON/Convolution.cpp b/tests/validation/NEON/Convolution.cpp
index 0fb61dc..5af8030 100644
--- a/tests/validation/NEON/Convolution.cpp
+++ b/tests/validation/NEON/Convolution.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017, 2018 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -49,47 +49,17 @@
  * while reference performs direct division with scale.
  */
 constexpr AbsoluteTolerance<uint8_t> tolerance_u8(1);
-
-/* Convolution3x3 */
-constexpr unsigned int filter_size_3x3 = 3;                  /* Size of the kernel/filter in number of elements. */
-constexpr BorderSize   border_size_3x3(filter_size_3x3 / 2); /* Border size of the kernel/filter around its central element. */
-
-/* Convolution5x5 */
-constexpr unsigned int filter_size_5x5 = 5;                  /* Size of the kernel/filter in number of elements. */
-constexpr BorderSize   border_size_5x5(filter_size_5x5 / 2); /* Border size of the kernel/filter around its central element. */
-
-/* Convolution7x7 */
-constexpr unsigned int filter_size_7x7 = 7;                  /* Size of the kernel/filter in number of elements. */
-constexpr BorderSize   border_size_7x7(filter_size_7x7 / 2); /* Border size of the kernel/filter around its central element. */
-
-/* Convolutionx */
-constexpr unsigned int filter_size_9x9 = 9;                  /* Size of the kernel/filter in number of elements. */
-constexpr BorderSize   border_size_9x9(filter_size_9x9 / 2); /* Border size of the kernel/filter around its central element. */
-
-/** Create conv matrix with filter size, and fill them with random value
- *
- * @param[in/out] conv        Convolution matrix to be filled with random int16_t
- * @param[in]     filter_size Filter Size.
- */
-void create_conv(int16_t *conv, const unsigned int filter_size)
-{
-    std::mt19937                           gen(library->seed());
-    std::uniform_int_distribution<int16_t> distribution_int16(-32768, 32767);
-
-    for(unsigned int i = 0; i < filter_size * filter_size; ++i)
-    {
-        conv[i] = distribution_int16(gen);
-    }
-}
 } // namespace
 
 TEST_SUITE(NEON)
 TEST_SUITE(CustomConvolution)
+TEST_SUITE(CustomConvolutionSuqare)
 TEST_SUITE(CustomConvolution3x3)
 
-DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)),
-                                                                   datasets::BorderModes()),
-               shape, data_type, border_mode)
+DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)),
+                                                                           datasets::BorderModes()),
+                                                                   framework::dataset::make("filter_size", { 3 })),
+               shape, data_type, border_mode, filter_size)
 {
     // Create tensors
     Tensor src = create_tensor<Tensor>(shape, data_type);
@@ -97,22 +67,16 @@
 
     // Create conv matrix
     int16_t conv[9];
-    create_conv(conv, filter_size_3x3);
-
-    // Generate random scale value between 0 and 255.
-    std::mt19937                           gen(library->seed());
-    std::uniform_int_distribution<uint8_t> distribution(0, 255);
-    uint32_t                               scale = distribution(gen);
 
     ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
     ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
 
     // Create and configure function
     NEConvolution3x3 convolution;
-    convolution.configure(&src, &dst, conv, scale, border_mode);
+    convolution.configure(&src, &dst, conv, 0, border_mode);
 
     // Validate valid region
-    const ValidRegion dst_valid_region = shape_to_valid_region(shape, (border_mode == BorderMode::UNDEFINED), border_size_3x3);
+    const ValidRegion dst_valid_region = shape_to_valid_region(shape, (border_mode == BorderMode::UNDEFINED), BorderSize(filter_size / 2));
     validate(dst.info()->valid_region(), dst_valid_region);
 
     // Validate padding
@@ -132,29 +96,32 @@
 }
 
 template <typename T>
-using NEConvolutionFixture = ConvolutionValidationFixture<Tensor, Accessor, NEConvolution3x3, T, filter_size_3x3>;
+using NEConvolutionFixture = ConvolutionSquareValidationFixture<Tensor, Accessor, NEConvolution3x3, T>;
 
-FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType",
+FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType",
                                                                                                                    DataType::U8)),
-                                                                                                           datasets::BorderModes()))
+                                                                                                                   datasets::BorderModes()),
+                                                                                                           framework::dataset::make("filter_size", { 3 })))
 {
     // Validate output
-    validate(Accessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), border_size_3x3), tolerance_u8);
+    validate(Accessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(_height / 2, _width / 2)), tolerance_u8);
 }
 
-FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType",
+FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType",
                                                                                                                  DataType::U8)),
-                                                                                                         datasets::BorderModes()))
+                                                                                                                 datasets::BorderModes()),
+                                                                                                         framework::dataset::make("filter_size", { 3 })))
 {
     // Validate output
-    validate(Accessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), border_size_3x3), tolerance_u8);
+    validate(Accessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(_height / 2, _width / 2)), tolerance_u8);
 }
 TEST_SUITE_END() /* Custom Convolution3x3 */
 
 TEST_SUITE(CustomConvolution5x5)
-DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)),
-                                                                   datasets::BorderModes()),
-               shape, data_type, border_mode)
+DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)),
+                                                                           datasets::BorderModes()),
+                                                                   framework::dataset::make("filter_size", { 5 })),
+               shape, data_type, border_mode, filter_size)
 {
     // Create tensors
     Tensor src = create_tensor<Tensor>(shape, data_type);
@@ -162,22 +129,16 @@
 
     // Create conv matrix
     int16_t conv[25];
-    create_conv(conv, filter_size_5x5);
-
-    // Generate random scale value between 0 and 255.
-    std::mt19937                           gen(library->seed());
-    std::uniform_int_distribution<uint8_t> distribution(0, 255);
-    uint32_t                               scale = distribution(gen);
 
     ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
     ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
 
     // Create and configure function
     NEConvolution5x5 convolution;
-    convolution.configure(&src, &dst, conv, scale, border_mode);
+    convolution.configure(&src, &dst, conv, 0, border_mode);
 
     // Validate valid region
-    const ValidRegion dst_valid_region = shape_to_valid_region(shape, (border_mode == BorderMode::UNDEFINED), border_size_5x5);
+    const ValidRegion dst_valid_region = shape_to_valid_region(shape, (border_mode == BorderMode::UNDEFINED), BorderSize(filter_size / 2));
     validate(dst.info()->valid_region(), dst_valid_region);
 
     // Validate padding
@@ -197,29 +158,32 @@
 }
 
 template <typename T>
-using NEConvolutionFixture = ConvolutionValidationFixture<Tensor, Accessor, NEConvolution5x5, T, filter_size_5x5>;
+using NEConvolutionFixture = ConvolutionSquareValidationFixture<Tensor, Accessor, NEConvolution5x5, T>;
 
-FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType",
+FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType",
                                                                                                                    DataType::U8)),
-                                                                                                           datasets::BorderModes()))
+                                                                                                                   datasets::BorderModes()),
+                                                                                                           framework::dataset::make("filter_size", { 5 })))
 {
     // Validate output
-    validate(Accessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), border_size_5x5), tolerance_u8);
+    validate(Accessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(_height / 2, _width / 2)), tolerance_u8);
 }
 
-FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType",
+FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType",
                                                                                                                  DataType::U8)),
-                                                                                                         datasets::BorderModes()))
+                                                                                                                 datasets::BorderModes()),
+                                                                                                         framework::dataset::make("filter_size", { 5 })))
 {
     // Validate output
-    validate(Accessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), border_size_5x5), tolerance_u8);
+    validate(Accessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(_height / 2, _width / 2)), tolerance_u8);
 }
 TEST_SUITE_END() /* Custom Convolution 5x5 */
 
 TEST_SUITE(CustomConvolution7x7)
-DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)),
-                                                                   datasets::BorderModes()),
-               shape, data_type, border_mode)
+DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)),
+                                                                           datasets::BorderModes()),
+                                                                   framework::dataset::make("filter_size", { 7 })),
+               shape, data_type, border_mode, filter_size)
 {
     // Create tensors
     Tensor src = create_tensor<Tensor>(shape, data_type);
@@ -227,22 +191,16 @@
 
     // Create conv matrix
     int16_t conv[49];
-    create_conv(conv, filter_size_7x7);
-
-    // Generate random scale value between 0 and 255.
-    std::mt19937                           gen(library->seed());
-    std::uniform_int_distribution<uint8_t> distribution(0, 255);
-    uint32_t                               scale = distribution(gen);
 
     ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
     ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
 
     // Create and configure function
     NEConvolution7x7 convolution;
-    convolution.configure(&src, &dst, conv, scale, border_mode);
+    convolution.configure(&src, &dst, conv, 0, border_mode);
 
     // Validate valid region
-    const ValidRegion dst_valid_region = shape_to_valid_region(shape, (border_mode == BorderMode::UNDEFINED), border_size_7x7);
+    const ValidRegion dst_valid_region = shape_to_valid_region(shape, (border_mode == BorderMode::UNDEFINED), BorderSize(filter_size / 2));
     validate(dst.info()->valid_region(), dst_valid_region);
 
     // Validate padding
@@ -262,29 +220,32 @@
 }
 
 template <typename T>
-using NEConvolutionFixture = ConvolutionValidationFixture<Tensor, Accessor, NEConvolution7x7, T, filter_size_7x7>;
+using NEConvolutionFixture = ConvolutionSquareValidationFixture<Tensor, Accessor, NEConvolution7x7, T>;
 
-FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType",
+FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType",
                                                                                                                    DataType::U8)),
-                                                                                                           datasets::BorderModes()))
+                                                                                                                   datasets::BorderModes()),
+                                                                                                           framework::dataset::make("filter_size", { 7 })))
 {
     // Validate output
-    validate(Accessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), border_size_7x7), tolerance_u8);
+    validate(Accessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(_height / 2, _width / 2)), tolerance_u8);
 }
 
-FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType",
+FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType",
                                                                                                                  DataType::U8)),
-                                                                                                         datasets::BorderModes()))
+                                                                                                                 datasets::BorderModes()),
+                                                                                                         framework::dataset::make("filter_size", { 7 })))
 {
     // Validate output
-    validate(Accessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), border_size_7x7), tolerance_u8);
+    validate(Accessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(_height / 2, _width / 2)), tolerance_u8);
 }
 TEST_SUITE_END() /* Custom Convolution 7x7 */
 
 TEST_SUITE(CustomConvolution9x9)
-DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)),
-                                                                   datasets::BorderModes()),
-               shape, data_type, border_mode)
+DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType", DataType::U8)),
+                                                                           datasets::BorderModes()),
+                                                                   framework::dataset::make("filter_size", { 9 })),
+               shape, data_type, border_mode, filter_size)
 {
     // Create tensors
     Tensor src = create_tensor<Tensor>(shape, data_type);
@@ -292,22 +253,16 @@
 
     // Create conv matrix
     int16_t conv[81];
-    create_conv(conv, filter_size_9x9);
-
-    // Generate random scale value between 0 and 255.
-    std::mt19937                           gen(library->seed());
-    std::uniform_int_distribution<uint8_t> distribution(0, 255);
-    uint32_t                               scale = distribution(gen);
 
     ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
     ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
 
     // Create and configure function
     NEConvolution9x9 convolution;
-    convolution.configure(&src, &dst, conv, scale, border_mode);
+    convolution.configure(&src, &dst, conv, 0, border_mode);
 
     // Validate valid region
-    const ValidRegion dst_valid_region = shape_to_valid_region(shape, (border_mode == BorderMode::UNDEFINED), border_size_9x9);
+    const ValidRegion dst_valid_region = shape_to_valid_region(shape, (border_mode == BorderMode::UNDEFINED), BorderSize(filter_size / 2));
     validate(dst.info()->valid_region(), dst_valid_region);
 
     // Validate padding
@@ -327,24 +282,98 @@
 }
 
 template <typename T>
-using NEConvolutionFixture = ConvolutionValidationFixture<Tensor, Accessor, NEConvolution9x9, T, filter_size_9x9>;
+using NEConvolutionFixture = ConvolutionSquareValidationFixture<Tensor, Accessor, NEConvolution9x9, T>;
 
-FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType",
+FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType",
                                                                                                                    DataType::U8)),
-                                                                                                           datasets::BorderModes()))
+                                                                                                                   datasets::BorderModes()),
+                                                                                                           framework::dataset::make("filter_size", { 9 })))
 {
     // Validate output
-    validate(Accessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), border_size_9x9), tolerance_u8);
+    validate(Accessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(_height / 2, _width / 2)), tolerance_u8);
 }
 
-FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType",
+FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType",
                                                                                                                  DataType::U8)),
-                                                                                                         datasets::BorderModes()))
+                                                                                                                 datasets::BorderModes()),
+                                                                                                         framework::dataset::make("filter_size", { 9 })))
 {
     // Validate output
-    validate(Accessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), border_size_9x9), tolerance_u8);
+    validate(Accessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(_height / 2, _width / 2)), tolerance_u8);
 }
 TEST_SUITE_END() /* Custom Convolution 9x9 */
+TEST_SUITE_END() /* Custom Convolution Square */
+
+TEST_SUITE(CustomConvolutionRectangle)
+
+DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(combine(combine(concat(datasets::SmallShapes(), datasets::LargeShapes()), framework::dataset::make("DataType",
+                                                                                           DataType::U8)),
+                                                                                   datasets::BorderModes()),
+                                                                           framework::dataset::make("filter_width", { 3, 5, 7, 9 })),
+                                                                   framework::dataset::make("filter_height", { 3, 5, 7, 9 })),
+               shape, data_type, border_mode, filter_width, filter_height)
+{
+    // Create tensors
+    Tensor src = create_tensor<Tensor>(shape, data_type);
+    Tensor dst = create_tensor<Tensor>(shape, data_type);
+
+    // Create conv matrix
+    int16_t conv[filter_width * filter_height];
+
+    ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
+    ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
+
+    // Create and configure function
+    NEConvolutionRectangle convolution;
+    convolution.configure(&src, &dst, conv, filter_width, filter_height, 1, border_mode);
+
+    // Validate valid region
+    const ValidRegion dst_valid_region = shape_to_valid_region(shape, (border_mode == BorderMode::UNDEFINED), BorderSize(filter_height / 2, filter_width / 2));
+    validate(dst.info()->valid_region(), dst_valid_region);
+
+    // Validate padding
+    PaddingCalculator calculator(shape.x(), 8);
+    calculator.set_border_size(filter_width / 2);
+    calculator.set_border_mode(border_mode);
+
+    const PaddingSize dst_padding = calculator.required_padding();
+
+    calculator.set_accessed_elements(16);
+    calculator.set_access_offset(-(filter_width / 2));
+
+    const PaddingSize width_padding = calculator.required_padding();
+
+    calculator.set_border_size(filter_height / 2);
+    calculator.set_access_offset(-(filter_height / 2));
+    const PaddingSize height_padding = calculator.required_padding();
+
+    validate(src.info()->padding(), width_padding, height_padding);
+    validate(dst.info()->padding(), dst_padding);
+}
+
+template <typename T>
+using NEConvolutionFixture = ConvolutionRectangleValidationFixture<Tensor, Accessor, NEConvolutionRectangle, T>;
+
+FIXTURE_DATA_TEST_CASE(RunSmall, NEConvolutionFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(combine(datasets::SmallShapes(), framework::dataset::make("DataType",
+                                                                                                                   DataType::U8)),
+                                                                                                                   datasets::BorderModes()),
+                                                                                                                   framework::dataset::make("filter_width", { 3, 5, 7, 9 })),
+                                                                                                           framework::dataset::make("filter_height", { 3, 5, 7, 9 })))
+{
+    // Validate output
+    validate(Accessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(_height / 2, _width / 2)), tolerance_u8);
+}
+
+FIXTURE_DATA_TEST_CASE(RunLarge, NEConvolutionFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(combine(datasets::LargeShapes(), framework::dataset::make("DataType",
+                                                                                                                 DataType::U8)),
+                                                                                                                 datasets::BorderModes()),
+                                                                                                                 framework::dataset::make("filter_width", { 3, 5, 7, 9 })),
+                                                                                                         framework::dataset::make("filter_height", { 3, 5, 7, 9 })))
+{
+    // Validate output
+    validate(Accessor(_target), _reference, shape_to_valid_region(_reference.shape(), (_border_mode == BorderMode::UNDEFINED), BorderSize(_height / 2, _width / 2)), tolerance_u8);
+}
+TEST_SUITE_END()
 TEST_SUITE_END()
 TEST_SUITE_END()
 } // namespace validation
diff --git a/tests/validation/Validation.cpp b/tests/validation/Validation.cpp
index ebca193..d01ac12 100644
--- a/tests/validation/Validation.cpp
+++ b/tests/validation/Validation.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017, 2018 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -170,6 +170,14 @@
     ARM_COMPUTE_EXPECT_EQUAL(padding.left, reference.left, framework::LogLevel::ERRORS);
 }
 
+void validate(const arm_compute::PaddingSize &padding, const arm_compute::PaddingSize &width_reference, const arm_compute::PaddingSize &height_reference)
+{
+    ARM_COMPUTE_EXPECT_EQUAL(padding.top, height_reference.top, framework::LogLevel::ERRORS);
+    ARM_COMPUTE_EXPECT_EQUAL(padding.right, width_reference.right, framework::LogLevel::ERRORS);
+    ARM_COMPUTE_EXPECT_EQUAL(padding.bottom, height_reference.bottom, framework::LogLevel::ERRORS);
+    ARM_COMPUTE_EXPECT_EQUAL(padding.left, width_reference.left, framework::LogLevel::ERRORS);
+}
+
 void validate(const IAccessor &tensor, const void *reference_value)
 {
     ARM_COMPUTE_ASSERT(reference_value != nullptr);
diff --git a/tests/validation/Validation.h b/tests/validation/Validation.h
index 1f81d38..b12d7de 100644
--- a/tests/validation/Validation.h
+++ b/tests/validation/Validation.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017, 2018 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -163,6 +163,12 @@
  */
 void validate(const arm_compute::PaddingSize &padding, const arm_compute::PaddingSize &reference);
 
+/** Validate padding.
+ *
+ * Padding on all sides has to be the same.
+ */
+void validate(const arm_compute::PaddingSize &padding, const arm_compute::PaddingSize &width_reference, const arm_compute::PaddingSize &height_reference);
+
 /** Validate tensors.
  *
  * - Dimensionality has to be the same.
diff --git a/tests/validation/fixtures/ConvolutionFixture.h b/tests/validation/fixtures/ConvolutionFixture.h
index 8bf6ea2..114d38a 100644
--- a/tests/validation/fixtures/ConvolutionFixture.h
+++ b/tests/validation/fixtures/ConvolutionFixture.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017, 2018 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -41,44 +41,40 @@
 {
 namespace validation
 {
-template <typename TensorType, typename AccessorType, typename FunctionType, typename T, const unsigned int filter_size>
+template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
 class ConvolutionValidationFixture : public framework::Fixture
 {
-public:
+protected:
     template <typename...>
-    void setup(TensorShape shape, DataType data_type, BorderMode border_mode)
+    void setup(TensorShape shape, DataType data_type, BorderMode border_mode, const unsigned int width, const unsigned int height)
     {
         std::mt19937                           gen(library->seed());
         std::uniform_int_distribution<uint8_t> distribution(0, 255);
         const uint8_t                          constant_border_value = distribution(gen);
 
-        // Generate random scale value between 0 and 255.
-        const uint32_t scale = distribution(gen);
+        // Generate random scale value between 1 and 255.
+        std::uniform_int_distribution<uint8_t> distribution_scale(1, 255);
+        const uint32_t                         scale = distribution_scale(gen);
 
-        switch(filter_size)
-        {
-            case 3:
-            case 5:
-            case 7:
-            case 9:
-                int16_t conv[filter_size * filter_size];
-                create_conv(conv);
+        ARM_COMPUTE_ERROR_ON(3 != width && 5 != width && 7 != width && 9 != width);
+        ARM_COMPUTE_ERROR_ON(3 != height && 5 != height && 7 != height && 9 != height);
 
-                _target    = compute_target(shape, data_type, conv, scale, border_mode, constant_border_value);
-                _reference = compute_reference(shape, data_type, conv, scale, border_mode, constant_border_value);
-                break;
-            default:
-                ARM_COMPUTE_ERROR("Filter Size Not Supported");
-        }
+        int16_t conv[width * height];
+        create_conv(conv);
+
+        _width     = width;
+        _height    = height;
+        _target    = compute_target(shape, data_type, conv, scale, border_mode, constant_border_value);
+        _reference = compute_reference(shape, data_type, conv, scale, border_mode, constant_border_value);
     }
 
-protected:
-    void create_conv(int16_t *conv)
+    void
+    create_conv(int16_t *conv)
     {
         std::mt19937                           gen(library->seed());
         std::uniform_int_distribution<int16_t> distribution_int16(-32768, 32767);
 
-        for(unsigned int i = 0; i < filter_size * filter_size; ++i)
+        for(unsigned int i = 0; i < _width * _height; ++i)
         {
             conv[i] = distribution_int16(gen);
         }
@@ -90,6 +86,40 @@
         library->fill_tensor_uniform(tensor, i);
     }
 
+    SimpleTensor<T> compute_reference(const TensorShape &shape, DataType data_type, const int16_t *conv, uint32_t scale, BorderMode border_mode, uint8_t constant_border_value)
+    {
+        ARM_COMPUTE_ERROR_ON(data_type != DataType::U8);
+
+        // Create reference
+        SimpleTensor<T> src{ shape, data_type };
+
+        // Fill reference
+        fill(src, 0);
+
+        // Compute reference
+        return reference::convolution<T>(src, conv, scale, border_mode, constant_border_value, _width, _height);
+    }
+
+    virtual TensorType compute_target(const TensorShape &shape, DataType data_type, const int16_t *conv, uint32_t scale, BorderMode border_mode, uint8_t constant_border_value) = 0;
+
+    BorderMode      _border_mode{};
+    TensorType      _target{};
+    SimpleTensor<T> _reference{};
+    unsigned int    _width{};
+    unsigned int    _height{};
+};
+
+template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
+class ConvolutionSquareValidationFixture : public ConvolutionValidationFixture<TensorType, AccessorType, FunctionType, T>
+{
+public:
+    template <typename...>
+    void setup(TensorShape shape, DataType data_type, BorderMode border_mode, const unsigned int width)
+    {
+        ConvolutionValidationFixture<TensorType, AccessorType, FunctionType, T>::setup(shape, data_type, border_mode, width, width);
+    }
+
+protected:
     TensorType compute_target(const TensorShape &shape, DataType data_type, const int16_t *conv, uint32_t scale, BorderMode border_mode, uint8_t constant_border_value)
     {
         // Create tensors
@@ -111,32 +141,56 @@
         ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS);
 
         // Fill tensors
-        fill(AccessorType(src), 0);
-        fill(AccessorType(dst), 1);
+        this->fill(AccessorType(src), 0);
+        this->fill(AccessorType(dst), 1);
 
         // Compute function
         convolution.run();
 
         return dst;
     }
+};
 
-    SimpleTensor<T> compute_reference(const TensorShape &shape, DataType data_type, const int16_t *conv, uint32_t scale, BorderMode border_mode, uint8_t constant_border_value)
+template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
+class ConvolutionRectangleValidationFixture : public ConvolutionValidationFixture<TensorType, AccessorType, FunctionType, T>
+{
+public:
+    template <typename...>
+    void setup(TensorShape shape, DataType data_type, BorderMode border_mode, const unsigned int width, const unsigned int height)
     {
-        ARM_COMPUTE_ERROR_ON(data_type != DataType::U8);
-
-        // Create reference
-        SimpleTensor<T> src{ shape, data_type };
-
-        // Fill reference
-        fill(src, 0);
-
-        // Compute reference
-        return reference::convolution<T>(src, conv, scale, border_mode, constant_border_value, filter_size);
+        ConvolutionValidationFixture<TensorType, AccessorType, FunctionType, T>::setup(shape, data_type, border_mode, width, height);
     }
 
-    BorderMode      _border_mode{};
-    TensorType      _target{};
-    SimpleTensor<T> _reference{};
+protected:
+    TensorType compute_target(const TensorShape &shape, DataType data_type, const int16_t *conv, uint32_t scale, BorderMode border_mode, uint8_t constant_border_value)
+    {
+        // Create tensors
+        TensorType src = create_tensor<TensorType>(shape, data_type);
+        TensorType dst = create_tensor<TensorType>(shape, data_type);
+
+        // Create and configure function
+        FunctionType convolution;
+        convolution.configure(&src, &dst, conv, this->_width, this->_height, scale, border_mode, constant_border_value);
+
+        ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
+        ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
+
+        // Allocate tensors
+        src.allocator()->allocate();
+        dst.allocator()->allocate();
+
+        ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS);
+        ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS);
+
+        // Fill tensors
+        this->fill(AccessorType(src), 0);
+        this->fill(AccessorType(dst), 1);
+
+        // Compute function
+        convolution.run();
+
+        return dst;
+    }
 };
 } // namespace validation
 } // namespace test
diff --git a/tests/validation/reference/Convolution.cpp b/tests/validation/reference/Convolution.cpp
index 84be858..777e2df 100644
--- a/tests/validation/reference/Convolution.cpp
+++ b/tests/validation/reference/Convolution.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017, 2018 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -35,7 +35,7 @@
 namespace reference
 {
 template <typename T>
-SimpleTensor<T> convolution(const SimpleTensor<T> &src, const int16_t *conv, uint32_t scale, BorderMode border_mode, T constant_border_value, const unsigned int filter_size)
+SimpleTensor<T> convolution(const SimpleTensor<T> &src, const int16_t *conv, uint32_t scale, BorderMode border_mode, T constant_border_value, const unsigned int width, const unsigned int height)
 {
     SimpleTensor<T>       dst(src.shape(), src.data_type());
     SimpleTensor<int32_t> sum(src.shape(), src.data_type());
@@ -43,7 +43,7 @@
     for(int element_idx = 0; element_idx < src.num_elements(); ++element_idx)
     {
         const Coordinates id = index2coord(src.shape(), element_idx);
-        apply_2d_spatial_filter(id, src, sum, TensorShape(filter_size, filter_size), conv, 1, border_mode, constant_border_value);
+        apply_2d_spatial_filter(id, src, sum, TensorShape(width, height), conv, 1, border_mode, constant_border_value);
 
         if(tensor_elem_at<int32_t>(sum, id, border_mode, constant_border_value) < 0)
         {
@@ -63,7 +63,7 @@
 }
 
 template SimpleTensor<uint8_t> convolution(const SimpleTensor<uint8_t> &src, const int16_t *conv, uint32_t scale, BorderMode border_mode, uint8_t constant_border_value,
-                                           const unsigned int filter_size);
+                                           const unsigned int widht, const unsigned int height);
 } // namespace reference
 } // namespace validation
 } // namespace test
diff --git a/tests/validation/reference/Convolution.h b/tests/validation/reference/Convolution.h
index bdaac28..ea9f4e4 100644
--- a/tests/validation/reference/Convolution.h
+++ b/tests/validation/reference/Convolution.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017, 2018 ARM Limited.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -35,7 +35,7 @@
 namespace reference
 {
 template <typename T>
-SimpleTensor<T> convolution(const SimpleTensor<T> &src, const int16_t *conv, uint32_t scale, BorderMode border_mode, T constant_border_value, const unsigned int filter_size);
+SimpleTensor<T> convolution(const SimpleTensor<T> &src, const int16_t *conv, uint32_t scale, BorderMode border_mode, T constant_border_value, const unsigned int width, const unsigned int height);
 } // namespace reference
 } // namespace validation
 } // namespace test