COMPMID-556: Rename CPP folder to reference

Change-Id: I147644349547c4e3804a80b564a9ad95131ad2d0
Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/111560
Reviewed-by: Michalis Spyrou <michalis.spyrou@arm.com>
Tested-by: BSG Visual Compute Jenkins server to access repositories on http://mpd-gerrit.cambridge.arm.com <bsgcomp@arm.com>
diff --git a/tests/validation/reference/AbsoluteDifference.cpp b/tests/validation/reference/AbsoluteDifference.cpp
new file mode 100644
index 0000000..f518e67
--- /dev/null
+++ b/tests/validation/reference/AbsoluteDifference.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "AbsoluteDifference.h"
+
+#include "arm_compute/core/Types.h"
+#include "tests/validation/FixedPoint.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> absolute_difference(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2, DataType dst_data_type)
+{
+    SimpleTensor<T> result(src1.shape(), dst_data_type);
+
+    using intermediate_type = typename common_promoted_signed_type<T>::intermediate_type;
+
+    for(int i = 0; i < src1.num_elements(); ++i)
+    {
+        intermediate_type val = std::abs(static_cast<intermediate_type>(src1[i]) - static_cast<intermediate_type>(src2[i]));
+        result[i]             = saturate_cast<T>(val);
+    }
+
+    return result;
+}
+
+template SimpleTensor<uint8_t> absolute_difference(const SimpleTensor<uint8_t> &src1, const SimpleTensor<uint8_t> &src2, DataType dst_data_type);
+template SimpleTensor<int16_t> absolute_difference(const SimpleTensor<int16_t> &src1, const SimpleTensor<int16_t> &src2, DataType dst_data_type);
+template SimpleTensor<int8_t> absolute_difference(const SimpleTensor<int8_t> &src1, const SimpleTensor<int8_t> &src2, DataType dst_data_type);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/AbsoluteDifference.h b/tests/validation/reference/AbsoluteDifference.h
new file mode 100644
index 0000000..b14da15
--- /dev/null
+++ b/tests/validation/reference/AbsoluteDifference.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_ABSOLUTE_DIFFERENCE_H__
+#define __ARM_COMPUTE_TEST_ABSOLUTE_DIFFERENCE_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> absolute_difference(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2, DataType dst_data_type);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_ABSOLUTE_DIFFERENCE_H__ */
diff --git a/tests/validation/reference/Accumulate.cpp b/tests/validation/reference/Accumulate.cpp
new file mode 100644
index 0000000..29a2007
--- /dev/null
+++ b/tests/validation/reference/Accumulate.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "Accumulate.h"
+
+#include "arm_compute/core/Types.h"
+#include "tests/validation/FixedPoint.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T1, typename T2>
+SimpleTensor<T2> accumulate(const SimpleTensor<T1> &src, DataType output_data_type)
+{
+    SimpleTensor<T2> dst{ src.shape(), output_data_type };
+
+    library->fill_tensor_uniform(dst, 1, static_cast<T2>(0), static_cast<T2>(std::numeric_limits<T1>::max()));
+
+    using intermediate_type = typename common_promoted_signed_type<T1, T2>::intermediate_type;
+
+    for(int i = 0; i < src.num_elements(); ++i)
+    {
+        intermediate_type val = static_cast<intermediate_type>(src[i]) + static_cast<intermediate_type>(dst[i]);
+        dst[i]                = saturate_cast<T2>(val);
+    }
+
+    return dst;
+}
+
+template <typename T1, typename T2>
+SimpleTensor<T2> accumulate_weighted(const SimpleTensor<T1> &src, float alpha, DataType output_data_type)
+{
+    ARM_COMPUTE_ERROR_ON_MSG(alpha < 0.f || alpha > 1.f, "Weight (alpha) specified in accumulate_weighted must be within the range [0, 1]");
+
+    SimpleTensor<T2> dst{ src.shape(), output_data_type };
+
+    library->fill_tensor_uniform(dst, 1, static_cast<T2>(0), static_cast<T2>(std::numeric_limits<T1>::max()));
+
+    using intermediate_type = typename common_promoted_signed_type<T1, T2>::intermediate_type;
+
+    for(int i = 0; i < src.num_elements(); ++i)
+    {
+        double val = (1. - static_cast<double>(alpha)) * static_cast<intermediate_type>(dst[i]) + static_cast<double>(alpha) * static_cast<intermediate_type>(src[i]);
+        dst[i]     = static_cast<T2>(val);
+    }
+
+    return dst;
+}
+
+template <typename T1, typename T2>
+SimpleTensor<T2> accumulate_squared(const SimpleTensor<T1> &src, uint32_t shift, DataType output_data_type)
+{
+    ARM_COMPUTE_ERROR_ON_MSG(shift > 15, "Shift in accumulate_squared must be within the range [0, 15]");
+
+    SimpleTensor<T2> dst{ src.shape(), output_data_type };
+
+    library->fill_tensor_uniform(dst, 1, static_cast<T2>(0), static_cast<T2>(std::numeric_limits<T1>::max()));
+
+    using intermediate_type = typename common_promoted_signed_type<T1, T2>::intermediate_type;
+    intermediate_type denom = 1 << shift;
+
+    for(int i = 0; i < src.num_elements(); ++i)
+    {
+        intermediate_type val = static_cast<intermediate_type>(dst[i]) + (static_cast<intermediate_type>(src[i]) * static_cast<intermediate_type>(src[i]) / denom);
+        dst[i]                = saturate_cast<T2>(val);
+    }
+
+    return dst;
+}
+
+template SimpleTensor<int16_t> accumulate(const SimpleTensor<uint8_t> &src, DataType output_data_type);
+template SimpleTensor<uint8_t> accumulate_weighted(const SimpleTensor<uint8_t> &src, float alpha, DataType output_data_type);
+template SimpleTensor<int16_t> accumulate_squared(const SimpleTensor<uint8_t> &src, uint32_t shift, DataType output_data_type);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/Accumulate.h b/tests/validation/reference/Accumulate.h
new file mode 100644
index 0000000..faa570b
--- /dev/null
+++ b/tests/validation/reference/Accumulate.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_ACCUMULATE_H__
+#define __ARM_COMPUTE_TEST_ACCUMULATE_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T1, typename T2>
+SimpleTensor<T2> accumulate(const SimpleTensor<T1> &src, DataType output_data_type);
+
+template <typename T1, typename T2>
+SimpleTensor<T2> accumulate_weighted(const SimpleTensor<T1> &src, float alpha, DataType output_data_type);
+
+template <typename T1, typename T2>
+SimpleTensor<T2> accumulate_squared(const SimpleTensor<T1> &src, uint32_t shift, DataType output_data_type);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_ACCUMULATE_H__ */
diff --git a/tests/validation/reference/ActivationLayer.cpp b/tests/validation/reference/ActivationLayer.cpp
new file mode 100644
index 0000000..2243e6f
--- /dev/null
+++ b/tests/validation/reference/ActivationLayer.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "ActivationLayer.h"
+
+#include "arm_compute/core/Types.h"
+#include "tests/validation/FixedPoint.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type>
+SimpleTensor<T> activation_layer(const SimpleTensor<T> &src, ActivationLayerInfo info)
+{
+    // Create reference
+    SimpleTensor<T> dst{ src.shape(), src.data_type(), 1, src.fixed_point_position() };
+
+    // Compute reference
+    const T a(info.a());
+    const T b(info.b());
+
+    for(int i = 0; i < src.num_elements(); ++i)
+    {
+        T x = src[i];
+
+        switch(info.activation())
+        {
+            case ActivationLayerInfo::ActivationFunction::ABS:
+                dst[i] = std::abs(x);
+                break;
+            case ActivationLayerInfo::ActivationFunction::LINEAR:
+                dst[i] = a * x + b;
+                break;
+            case ActivationLayerInfo::ActivationFunction::LOGISTIC:
+                dst[i] = static_cast<T>(1) / (static_cast<T>(1) + std::exp(-x));
+                break;
+            case ActivationLayerInfo::ActivationFunction::RELU:
+                dst[i] = std::max<T>(static_cast<T>(0), x);
+                break;
+            case ActivationLayerInfo::ActivationFunction::BOUNDED_RELU:
+                dst[i] = std::min<T>(a, std::max(static_cast<T>(0), x));
+                break;
+            case ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU:
+                dst[i] = std::min<T>(a, std::max<T>(b, x));
+                break;
+            case ActivationLayerInfo::ActivationFunction::LEAKY_RELU:
+                dst[i] = (x > 0) ? x : a * x;
+                break;
+            case ActivationLayerInfo::ActivationFunction::SOFT_RELU:
+                dst[i] = std::log(static_cast<T>(1) + std::exp(x));
+                break;
+            case ActivationLayerInfo::ActivationFunction::SQRT:
+                dst[i] = std::sqrt(x);
+                break;
+            case ActivationLayerInfo::ActivationFunction::SQUARE:
+                dst[i] = x * x;
+                break;
+            case ActivationLayerInfo::ActivationFunction::TANH:
+                dst[i] = a * std::tanh(b * x);
+                break;
+            default:
+                ARM_COMPUTE_ERROR("Unsupported activation function");
+        }
+    }
+
+    return dst;
+}
+
+template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type>
+SimpleTensor<T> activation_layer(const SimpleTensor<T> &src, ActivationLayerInfo info)
+{
+    using namespace fixed_point_arithmetic;
+
+    // Create reference
+    SimpleTensor<T> dst{ src.shape(), src.data_type(), 1, src.fixed_point_position() };
+
+    // Compute reference
+    const int            fixed_point_position = src.fixed_point_position();
+    const fixed_point<T> a(info.a(), fixed_point_position);
+    const fixed_point<T> b(info.b(), fixed_point_position);
+    const fixed_point<T> const_0(0, fixed_point_position);
+    const fixed_point<T> const_1(1, fixed_point_position);
+
+    for(int i = 0; i < src.num_elements(); ++i)
+    {
+        fixed_point<T> x(src[i], fixed_point_position, true);
+
+        switch(info.activation())
+        {
+            case ActivationLayerInfo::ActivationFunction::ABS:
+                dst[i] = abs(x).raw();
+                break;
+            case ActivationLayerInfo::ActivationFunction::LINEAR:
+                dst[i] = add(b, mul(a, x)).raw();
+                break;
+            case ActivationLayerInfo::ActivationFunction::LOGISTIC:
+                dst[i] = (const_1 / (const_1 + exp(-x))).raw();
+                break;
+            case ActivationLayerInfo::ActivationFunction::RELU:
+                dst[i] = max(const_0, x).raw();
+                break;
+            case ActivationLayerInfo::ActivationFunction::BOUNDED_RELU:
+                dst[i] = min(a, max(const_0, x)).raw();
+                break;
+            case ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU:
+                dst[i] = min(a, max(b, x)).raw();
+                break;
+            case ActivationLayerInfo::ActivationFunction::LEAKY_RELU:
+                dst[i] = (x > const_0) ? x.raw() : mul(a, x).raw();
+                break;
+            case ActivationLayerInfo::ActivationFunction::SOFT_RELU:
+                dst[i] = log(const_1 + exp(x)).raw();
+                break;
+            case ActivationLayerInfo::ActivationFunction::SQRT:
+                dst[i] = (const_1 / inv_sqrt(x)).raw();
+                break;
+            case ActivationLayerInfo::ActivationFunction::SQUARE:
+                dst[i] = mul(x, x).raw();
+                break;
+            case ActivationLayerInfo::ActivationFunction::TANH:
+                dst[i] = mul(a, tanh(mul(b, x))).raw();
+                break;
+            default:
+                ARM_COMPUTE_ERROR("Unsupported activation function");
+        }
+    }
+
+    return dst;
+}
+
+template SimpleTensor<float> activation_layer(const SimpleTensor<float> &src, ActivationLayerInfo info);
+template SimpleTensor<half> activation_layer(const SimpleTensor<half> &src, ActivationLayerInfo info);
+template SimpleTensor<qint8_t> activation_layer(const SimpleTensor<qint8_t> &src, ActivationLayerInfo info);
+template SimpleTensor<qint16_t> activation_layer(const SimpleTensor<qint16_t> &src, ActivationLayerInfo info);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/ActivationLayer.h b/tests/validation/reference/ActivationLayer.h
new file mode 100644
index 0000000..09f602f
--- /dev/null
+++ b/tests/validation/reference/ActivationLayer.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_ACTIVATION_LAYER_H__
+#define __ARM_COMPUTE_TEST_ACTIVATION_LAYER_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type = 0>
+SimpleTensor<T> activation_layer(const SimpleTensor<T> &src, ActivationLayerInfo info);
+
+template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
+SimpleTensor<T> activation_layer(const SimpleTensor<T> &src, ActivationLayerInfo info);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_ACTIVATION_LAYER_H__ */
diff --git a/tests/validation/reference/ArithmeticAddition.cpp b/tests/validation/reference/ArithmeticAddition.cpp
new file mode 100644
index 0000000..82dd143
--- /dev/null
+++ b/tests/validation/reference/ArithmeticAddition.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "ArithmeticAddition.h"
+
+#include "arm_compute/core/Types.h"
+#include "tests/validation/FixedPoint.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> arithmetic_addition(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2, DataType dst_data_type, ConvertPolicy convert_policy)
+{
+    SimpleTensor<T> result(src1.shape(), dst_data_type);
+
+    using intermediate_type = typename common_promoted_signed_type<T>::intermediate_type;
+
+    for(int i = 0; i < src1.num_elements(); ++i)
+    {
+        intermediate_type val = static_cast<intermediate_type>(src1[i]) + static_cast<intermediate_type>(src2[i]);
+        result[i]             = (convert_policy == ConvertPolicy::SATURATE) ? saturate_cast<T>(val) : static_cast<T>(val);
+    }
+
+    return result;
+}
+
+template SimpleTensor<uint8_t> arithmetic_addition(const SimpleTensor<uint8_t> &src1, const SimpleTensor<uint8_t> &src2, DataType dst_data_type, ConvertPolicy convert_policy);
+template SimpleTensor<int16_t> arithmetic_addition(const SimpleTensor<int16_t> &src1, const SimpleTensor<int16_t> &src2, DataType dst_data_type, ConvertPolicy convert_policy);
+template SimpleTensor<int8_t> arithmetic_addition(const SimpleTensor<int8_t> &src1, const SimpleTensor<int8_t> &src2, DataType dst_data_type, ConvertPolicy convert_policy);
+template SimpleTensor<half> arithmetic_addition(const SimpleTensor<half> &src1, const SimpleTensor<half> &src2, DataType dst_data_type,
+                                                ConvertPolicy convert_policy);
+template SimpleTensor<float> arithmetic_addition(const SimpleTensor<float> &src1, const SimpleTensor<float> &src2, DataType dst_data_type, ConvertPolicy convert_policy);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/ArithmeticAddition.h b/tests/validation/reference/ArithmeticAddition.h
new file mode 100644
index 0000000..5902a6f
--- /dev/null
+++ b/tests/validation/reference/ArithmeticAddition.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_ARITHMETIC_ADDITION_H__
+#define __ARM_COMPUTE_TEST_ARITHMETIC_ADDITION_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> arithmetic_addition(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2, DataType dst_data_type, ConvertPolicy convert_policy);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_ARITHMETIC_ADDITION_H__ */
diff --git a/tests/validation/reference/ArithmeticSubtraction.cpp b/tests/validation/reference/ArithmeticSubtraction.cpp
new file mode 100644
index 0000000..bed2d37
--- /dev/null
+++ b/tests/validation/reference/ArithmeticSubtraction.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "ArithmeticSubtraction.h"
+
+#include "tests/validation/FixedPoint.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T1, typename T2, typename T3>
+SimpleTensor<T3> arithmetic_subtraction(const SimpleTensor<T1> &src1, const SimpleTensor<T2> &src2, DataType dst_data_type, ConvertPolicy convert_policy)
+{
+    SimpleTensor<T3> result(src1.shape(), dst_data_type);
+
+    using intermediate_type = typename common_promoted_signed_type<typename std::conditional<sizeof(T1) >= sizeof(T2), T1, T2>::type >::intermediate_type;
+
+    for(int i = 0; i < src1.num_elements(); ++i)
+    {
+        intermediate_type val = static_cast<intermediate_type>(src1[i]) - static_cast<intermediate_type>(src2[i]);
+        result[i]             = (convert_policy == ConvertPolicy::SATURATE) ? saturate_cast<T3>(val) : static_cast<T3>(val);
+    }
+
+    return result;
+}
+
+template SimpleTensor<uint8_t> arithmetic_subtraction(const SimpleTensor<uint8_t> &src1, const SimpleTensor<uint8_t> &src2, DataType dst_data_type, ConvertPolicy convert_policy);
+template SimpleTensor<int16_t> arithmetic_subtraction(const SimpleTensor<uint8_t> &src1, const SimpleTensor<uint8_t> &src2, DataType dst_data_type, ConvertPolicy convert_policy);
+template SimpleTensor<int16_t> arithmetic_subtraction(const SimpleTensor<uint8_t> &src1, const SimpleTensor<int16_t> &src2, DataType dst_data_type, ConvertPolicy convert_policy);
+template SimpleTensor<int16_t> arithmetic_subtraction(const SimpleTensor<int16_t> &src1, const SimpleTensor<uint8_t> &src2, DataType dst_data_type, ConvertPolicy convert_policy);
+template SimpleTensor<int16_t> arithmetic_subtraction(const SimpleTensor<int16_t> &src1, const SimpleTensor<int16_t> &src2, DataType dst_data_type, ConvertPolicy convert_policy);
+template SimpleTensor<int8_t> arithmetic_subtraction(const SimpleTensor<int8_t> &src1, const SimpleTensor<int8_t> &src2, DataType dst_data_type, ConvertPolicy convert_policy);
+template SimpleTensor<half> arithmetic_subtraction(const SimpleTensor<half> &src1, const SimpleTensor<half> &src2, DataType dst_data_type, ConvertPolicy convert_policy);
+template SimpleTensor<float> arithmetic_subtraction(const SimpleTensor<float> &src1, const SimpleTensor<float> &src2, DataType dst_data_type, ConvertPolicy convert_policy);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/ArithmeticSubtraction.h b/tests/validation/reference/ArithmeticSubtraction.h
new file mode 100644
index 0000000..9308314
--- /dev/null
+++ b/tests/validation/reference/ArithmeticSubtraction.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_ARITHMETIC_SUBTRACTION_H__
+#define __ARM_COMPUTE_TEST_ARITHMETIC_SUBTRACTION_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T1, typename T2, typename T3>
+SimpleTensor<T3> arithmetic_subtraction(const SimpleTensor<T1> &src1, const SimpleTensor<T2> &src2, DataType dst_data_type, ConvertPolicy convert_policy);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_ARITHMETIC_SUBTRACTION_H__ */
diff --git a/tests/validation/reference/BatchNormalizationLayer.cpp b/tests/validation/reference/BatchNormalizationLayer.cpp
new file mode 100644
index 0000000..e4446d1
--- /dev/null
+++ b/tests/validation/reference/BatchNormalizationLayer.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "BatchNormalizationLayer.h"
+
+#include "tests/validation/FixedPoint.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+// Batch Normalization Layer for fixed point type
+template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type *>
+SimpleTensor<T> batch_normalization_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &mean, const SimpleTensor<T> &var, const SimpleTensor<T> &beta, const SimpleTensor<T> &gamma, float epsilon,
+                                          int fixed_point_position)
+{
+    SimpleTensor<T> result(src.shape(), src.data_type());
+
+    const auto cols       = static_cast<int>(src.shape()[0]);
+    const auto rows       = static_cast<int>(src.shape()[1]);
+    const auto depth      = static_cast<int>(src.shape()[2]);
+    const int  upper_dims = src.shape().total_size() / (cols * rows * depth);
+
+    for(int r = 0; r < upper_dims; ++r)
+    {
+        for(int i = 0; i < depth; ++i)
+        {
+            for(int k = 0; k < rows; ++k)
+            {
+                for(int l = 0; l < cols; ++l)
+                {
+                    const int pos = l + k * cols + i * rows * cols + r * cols * rows * depth;
+
+                    fixed_point_arithmetic::fixed_point<T> src_qs(src[pos], fixed_point_position, true);
+                    fixed_point_arithmetic::fixed_point<T> var_qs(var[i], fixed_point_position, true);
+                    fixed_point_arithmetic::fixed_point<T> mean_qs(mean[i], fixed_point_position, true);
+                    fixed_point_arithmetic::fixed_point<T> beta_qs(beta[i], fixed_point_position, true);
+                    fixed_point_arithmetic::fixed_point<T> gamma_qs(gamma[i], fixed_point_position, true);
+                    fixed_point_arithmetic::fixed_point<T> epsilon_qs(epsilon, fixed_point_position);
+
+                    auto denominator = fixed_point_arithmetic::inv_sqrt(var_qs + epsilon_qs);
+                    auto numerator   = src_qs - mean_qs;
+                    auto x_bar       = numerator * denominator;
+                    x_bar            = beta_qs + x_bar * gamma_qs;
+                    result[pos]      = x_bar.raw();
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+// Batch Normalization Layer for floating point type
+template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type *>
+SimpleTensor<T> batch_normalization_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &mean, const SimpleTensor<T> &var, const SimpleTensor<T> &beta, const SimpleTensor<T> &gamma, float epsilon,
+                                          int fixed_point_position)
+{
+    ARM_COMPUTE_UNUSED(fixed_point_position);
+
+    SimpleTensor<T> result(src.shape(), src.data_type());
+
+    const auto cols       = static_cast<int>(src.shape()[0]);
+    const auto rows       = static_cast<int>(src.shape()[1]);
+    const auto depth      = static_cast<int>(src.shape()[2]);
+    const int  upper_dims = src.shape().total_size() / (cols * rows * depth);
+
+    for(int r = 0; r < upper_dims; ++r)
+    {
+        for(int i = 0; i < depth; ++i)
+        {
+            for(int k = 0; k < rows; ++k)
+            {
+                for(int l = 0; l < cols; ++l)
+                {
+                    const int   pos         = l + k * cols + i * rows * cols + r * cols * rows * depth;
+                    const float denominator = sqrt(var[i] + epsilon);
+                    const float numerator   = src[pos] - mean[i];
+                    const float x_bar       = numerator / denominator;
+                    result[pos]             = beta[i] + x_bar * gamma[i];
+                }
+            }
+        }
+    }
+    return result;
+}
+template SimpleTensor<float> batch_normalization_layer(const SimpleTensor<float> &src, const SimpleTensor<float> &mean, const SimpleTensor<float> &var, const SimpleTensor<float> &beta,
+                                                       const SimpleTensor<float> &gamma, float epsilon, int fixed_point_position);
+template SimpleTensor<int8_t> batch_normalization_layer(const SimpleTensor<int8_t> &src, const SimpleTensor<int8_t> &mean, const SimpleTensor<int8_t> &var, const SimpleTensor<int8_t> &beta,
+                                                        const SimpleTensor<int8_t> &gamma, float epsilon, int fixed_point_position);
+template SimpleTensor<int16_t> batch_normalization_layer(const SimpleTensor<int16_t> &src, const SimpleTensor<int16_t> &mean, const SimpleTensor<int16_t> &var, const SimpleTensor<int16_t> &beta,
+                                                         const SimpleTensor<int16_t> &gamma, float epsilon, int fixed_point_position);
+template SimpleTensor<half> batch_normalization_layer(const SimpleTensor<half> &src, const SimpleTensor<half> &mean, const SimpleTensor<half> &var,
+                                                      const SimpleTensor<half> &beta,
+                                                      const SimpleTensor<half> &gamma, float epsilon, int fixed_point_position);
+
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/BatchNormalizationLayer.h b/tests/validation/reference/BatchNormalizationLayer.h
new file mode 100644
index 0000000..1a554ad
--- /dev/null
+++ b/tests/validation/reference/BatchNormalizationLayer.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_BATCH_NORMALIZATION_LAYER_H__
+#define __ARM_COMPUTE_TEST_BATCH_NORMALIZATION_LAYER_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type * = nullptr>
+SimpleTensor<T> batch_normalization_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &mean, const SimpleTensor<T> &var, const SimpleTensor<T> &beta, const SimpleTensor<T> &gamma, float epsilon,
+                                          int fixed_point_position);
+
+template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type * = nullptr>
+SimpleTensor<T> batch_normalization_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &mean, const SimpleTensor<T> &var, const SimpleTensor<T> &beta, const SimpleTensor<T> &gamma, float epsilon,
+                                          int fixed_point_position);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_BATCH_NORMALIZATION_LAYER_H__ */
diff --git a/tests/validation/reference/BitwiseAnd.cpp b/tests/validation/reference/BitwiseAnd.cpp
new file mode 100644
index 0000000..6fc46b4
--- /dev/null
+++ b/tests/validation/reference/BitwiseAnd.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "BitwiseAnd.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> bitwise_and(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2)
+{
+    SimpleTensor<T> dst(src1.shape(), src1.data_type());
+
+    for(int i = 0; i < src1.num_elements(); ++i)
+    {
+        dst[i] = src1[i] & src2[i];
+    }
+
+    return dst;
+}
+
+template SimpleTensor<uint8_t> bitwise_and(const SimpleTensor<uint8_t> &src1, const SimpleTensor<uint8_t> &src2);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/BitwiseAnd.h b/tests/validation/reference/BitwiseAnd.h
new file mode 100644
index 0000000..eba2fd6
--- /dev/null
+++ b/tests/validation/reference/BitwiseAnd.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_BITWISE_AND_H__
+#define __ARM_COMPUTE_TEST_BITWISE_AND_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> bitwise_and(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_BITWISE_AND_H__ */
diff --git a/tests/validation/reference/BitwiseNot.cpp b/tests/validation/reference/BitwiseNot.cpp
new file mode 100644
index 0000000..5a6a13b
--- /dev/null
+++ b/tests/validation/reference/BitwiseNot.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "BitwiseNot.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> bitwise_not(const SimpleTensor<T> &src)
+{
+    SimpleTensor<T> dst(src.shape(), src.data_type());
+
+    for(int i = 0; i < src.num_elements(); ++i)
+    {
+        dst[i] = ~src[i];
+    }
+
+    return dst;
+}
+
+template SimpleTensor<uint8_t> bitwise_not(const SimpleTensor<uint8_t> &src);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/BitwiseNot.h b/tests/validation/reference/BitwiseNot.h
new file mode 100644
index 0000000..b4206f9
--- /dev/null
+++ b/tests/validation/reference/BitwiseNot.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_BITWISE_NOT_H__
+#define __ARM_COMPUTE_TEST_BITWISE_NOT_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> bitwise_not(const SimpleTensor<T> &src);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_BITWISE_NOT_H__ */
diff --git a/tests/validation/reference/BitwiseOr.cpp b/tests/validation/reference/BitwiseOr.cpp
new file mode 100644
index 0000000..fc258d5
--- /dev/null
+++ b/tests/validation/reference/BitwiseOr.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "BitwiseOr.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> bitwise_or(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2)
+{
+    SimpleTensor<T> dst(src1.shape(), src1.data_type());
+
+    for(int i = 0; i < src1.num_elements(); ++i)
+    {
+        dst[i] = src1[i] | src2[i];
+    }
+
+    return dst;
+}
+
+template SimpleTensor<uint8_t> bitwise_or(const SimpleTensor<uint8_t> &src1, const SimpleTensor<uint8_t> &src2);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/BitwiseOr.h b/tests/validation/reference/BitwiseOr.h
new file mode 100644
index 0000000..39158cb
--- /dev/null
+++ b/tests/validation/reference/BitwiseOr.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_BITWISE_OR_H__
+#define __ARM_COMPUTE_TEST_BITWISE_OR_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> bitwise_or(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_BITWISE_OR_H__ */
diff --git a/tests/validation/reference/BitwiseXor.cpp b/tests/validation/reference/BitwiseXor.cpp
new file mode 100644
index 0000000..b8d275d
--- /dev/null
+++ b/tests/validation/reference/BitwiseXor.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "BitwiseXor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> bitwise_xor(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2)
+{
+    SimpleTensor<T> dst(src1.shape(), src1.data_type());
+
+    for(int i = 0; i < src1.num_elements(); ++i)
+    {
+        dst[i] = src1[i] ^ src2[i];
+    }
+
+    return dst;
+}
+
+template SimpleTensor<uint8_t> bitwise_xor(const SimpleTensor<uint8_t> &src1, const SimpleTensor<uint8_t> &src2);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/BitwiseXor.h b/tests/validation/reference/BitwiseXor.h
new file mode 100644
index 0000000..3e7721e
--- /dev/null
+++ b/tests/validation/reference/BitwiseXor.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_BITWISE_XOR_H__
+#define __ARM_COMPUTE_TEST_BITWISE_XOR_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> bitwise_xor(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_BITWISE_XOR_H__ */
diff --git a/tests/validation/reference/Box3x3.cpp b/tests/validation/reference/Box3x3.cpp
new file mode 100644
index 0000000..8d304a8
--- /dev/null
+++ b/tests/validation/reference/Box3x3.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "arm_compute/core/Helpers.h"
+
+#include "Box3x3.h"
+#include "Utils.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> box3x3(const SimpleTensor<T> &src, BorderMode border_mode, T constant_border_value)
+{
+    SimpleTensor<T> dst(src.shape(), src.data_type());
+    const std::array<T, 9> filter{ { 1, 1, 1, 1, 1, 1, 1, 1, 1 } };
+    const float scale = 1.f / static_cast<float>(filter.size());
+    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, dst, TensorShape(3U, 3U), filter.data(), scale, border_mode, constant_border_value);
+    }
+    return dst;
+}
+
+template SimpleTensor<uint8_t> box3x3(const SimpleTensor<uint8_t> &src, BorderMode border_mode, uint8_t constant_border_value);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/Box3x3.h b/tests/validation/reference/Box3x3.h
new file mode 100644
index 0000000..80ac451
--- /dev/null
+++ b/tests/validation/reference/Box3x3.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_BOX3X3_H__
+#define __ARM_COMPUTE_TEST_BOX3X3_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> box3x3(const SimpleTensor<T> &src, BorderMode border_mode, T constant_border_value);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_BOX3X3_H__ */
diff --git a/tests/validation/reference/ConvolutionLayer.cpp b/tests/validation/reference/ConvolutionLayer.cpp
new file mode 100644
index 0000000..1066411
--- /dev/null
+++ b/tests/validation/reference/ConvolutionLayer.cpp
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "ConvolutionLayer.h"
+
+#include "tests/validation/FixedPoint.h"
+#include "tests/validation/Helpers.h"
+#include "tests/validation/reference/Utils.h"
+#include "tests/validation/reference/UtilsQuantizedAsymm.h"
+
+#include "tests/framework/Asserts.h"
+
+#include "arm_compute/core/utils/quantization/AsymmHelpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+namespace
+{
+inline bool is_valid_pixel(int i, int min, int max)
+{
+    return (i >= min && i < max);
+}
+
+// 3D convolution for floating point type
+template < typename T, typename TB, typename std::enable_if < is_floating_point<T>::value &&is_floating_point<TB>::value, int >::type = 0 >
+void convolution3d(const SimpleTensor<T> &in, const SimpleTensor<T> &weights, const SimpleTensor<TB> &bias, SimpleTensor<T> &out,
+                   int i_offset, int w_offset, int b_offset, int o_offset,
+                   int xi, int yi, int width_in, int height_in, int depth_in, int width_weights, int height_weights)
+{
+    const T *in_ptr  = in.data() + i_offset;
+    const T *w_ptr   = weights.data() + w_offset;
+    const TB *b_ptr   = bias.data() + b_offset;
+    T        *out_ptr = out.data() + o_offset;
+
+    const int half_width_weights  = width_weights / 2;
+    const int half_height_weights = height_weights / 2;
+
+    // Reset accumulator
+    T acc(0);
+
+    // Compute a 2D convolution for each IFM and accumulate the result
+    for(int ifm = 0; ifm < depth_in; ++ifm)
+    {
+        // Compute the offset for the input slice
+        const int offset_slice_in = xi + yi * width_in + ifm * width_in * height_in;
+
+        // Compute 2D convolution
+        for(int yk = -half_height_weights; yk <= half_height_weights; ++yk)
+        {
+            for(int xk = -half_width_weights; xk <= half_width_weights; ++xk)
+            {
+                // Check if the pixel is out-of-bound
+                if(is_valid_pixel(xi + xk, 0, width_in) && is_valid_pixel(yi + yk, 0, height_in))
+                {
+                    const int idx = xk + half_width_weights;
+                    const int idy = yk + half_height_weights;
+
+                    const T i_value = in_ptr[offset_slice_in + xk + yk * width_in];
+                    const T w_value = w_ptr[idx + idy * width_weights + ifm * width_weights * height_weights];
+
+                    acc += i_value * w_value;
+                }
+            }
+        }
+    }
+
+    // Accumulate the bias and store the result
+    *out_ptr = acc + (*b_ptr);
+}
+
+// 3D convolution for fixed point type
+template < typename T, typename TB, typename std::enable_if < std::is_integral<T>::value &&std::is_integral<TB>::value, int >::type = 0 >
+void convolution3d(const SimpleTensor<T> &in, const SimpleTensor<T> &weights, const SimpleTensor<TB> &bias, SimpleTensor<T> &out,
+                   int i_offset, int w_offset, int b_offset, int o_offset,
+                   int xi, int yi, int width_in, int height_in, int depth_in, int width_weights, int height_weights)
+{
+    const T *in_ptr               = in.data() + i_offset;
+    const T *w_ptr                = weights.data() + w_offset;
+    const T *b_ptr                = bias.data() + b_offset;
+    T       *out_ptr              = out.data() + o_offset;
+    int      fixed_point_position = in.fixed_point_position();
+
+    const int half_width_weights  = width_weights / 2;
+    const int half_height_weights = height_weights / 2;
+
+    using namespace fixed_point_arithmetic;
+    using promoted_type = fixed_point_arithmetic::traits::promote_t<T>;
+
+    // Reset accumulator
+    fixed_point<promoted_type> acc(0, fixed_point_position);
+
+    // Compute a 2D convolution for each IFM and accumulate the result
+    for(int ifm = 0; ifm < depth_in; ++ifm)
+    {
+        // Compute the offset for the input slice
+        const int offset_slice_in = xi + yi * width_in + ifm * width_in * height_in;
+
+        // Compute 2D convolution
+        for(int yk = -half_height_weights; yk <= half_height_weights; ++yk)
+        {
+            for(int xk = -half_width_weights; xk <= half_width_weights; ++xk)
+            {
+                // Check if the pixel is out-of-bound
+                if(is_valid_pixel(xi + xk, 0, width_in) && is_valid_pixel(yi + yk, 0, height_in))
+                {
+                    const int idx = xk + half_width_weights;
+                    const int idy = yk + half_height_weights;
+
+                    const fixed_point<promoted_type> i_value(in_ptr[offset_slice_in + xk + yk * width_in], fixed_point_position, true);
+                    const fixed_point<promoted_type> w_value(w_ptr[idx + idy * width_weights + ifm * width_weights * height_weights], fixed_point_position, true);
+                    const fixed_point<promoted_type> iw = i_value * w_value;
+                    acc                                 = iw + acc;
+                }
+            }
+        }
+    }
+
+    // Get the bias
+    const fixed_point<promoted_type> b(*b_ptr, fixed_point_position, true);
+
+    // Accumulate the bias and covert back
+    acc = acc + b;
+    fixed_point<T> res(acc);
+    *out_ptr = res.raw();
+}
+
+// 3D convolution for QASYMM8 type
+template <>
+void convolution3d(const SimpleTensor<uint8_t> &in, const SimpleTensor<uint8_t> &weights, const SimpleTensor<int32_t> &bias, SimpleTensor<uint8_t> &out,
+                   int i_offset, int w_offset, int b_offset, int o_offset,
+                   int xi, int yi, int width_in, int height_in, int depth_in, int width_weights, int height_weights)
+{
+    const uint8_t *in_ptr  = in.data() + i_offset;
+    const uint8_t *w_ptr   = weights.data() + w_offset;
+    const int32_t *b_ptr   = bias.data() + b_offset;
+    uint8_t       *out_ptr = out.data() + o_offset;
+
+    const int   input_offset   = -in.quantization_info().offset;
+    const float input_scale    = in.quantization_info().scale;
+    const int   weights_offset = -weights.quantization_info().offset;
+    const float weights_scale  = weights.quantization_info().scale;
+    const int   output_offset  = out.quantization_info().offset;
+    const float output_scale   = out.quantization_info().scale;
+
+    int         output_multiplier = 0;
+    int         output_shift      = 0;
+    const float multiplier        = input_scale * weights_scale / output_scale;
+    arm_compute::quantization::calculate_quantized_multiplier_less_than_one(multiplier, &output_multiplier, &output_shift);
+
+    const int half_width_weights  = width_weights / 2;
+    const int half_height_weights = height_weights / 2;
+
+    // Reset accumulator
+    int32_t acc(0);
+
+    // Compute a 2D convolution for each IFM and accumulate the result
+    for(int ifm = 0; ifm < depth_in; ++ifm)
+    {
+        // Compute the offset for the input slice
+        const int offset_slice_in = xi + yi * width_in + ifm * width_in * height_in;
+
+        // Compute 2D convolution
+        for(int yk = -half_height_weights; yk <= half_height_weights; ++yk)
+        {
+            for(int xk = -half_width_weights; xk <= half_width_weights; ++xk)
+            {
+                // Check if the pixel is out-of-bound
+                if(is_valid_pixel(xi + xk, 0, width_in) && is_valid_pixel(yi + yk, 0, height_in))
+                {
+                    const int idx = xk + half_width_weights;
+                    const int idy = yk + half_height_weights;
+
+                    const uint8_t i_value = in_ptr[offset_slice_in + xk + yk * width_in];
+                    const uint8_t w_value = w_ptr[idx + idy * width_weights + ifm * width_weights * height_weights];
+
+                    acc += (i_value + input_offset) * (w_value + weights_offset);
+                }
+            }
+        }
+    }
+
+    // Accumulate the bias
+    acc += (*b_ptr);
+
+    acc = asymm_rounding_divide_by_pow2(asymm_int_mult(acc, output_multiplier), output_shift);
+    acc += output_offset;
+    acc = clamp<int32_t>(acc, 0, 255);
+
+    // Store the result
+    *out_ptr = acc;
+}
+} // namespace
+
+template <typename T, typename TB>
+SimpleTensor<T> convolution_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<TB> &bias, const TensorShape &output_shape, const PadStrideInfo &info)
+{
+    // Create reference
+    SimpleTensor<T> dst{ output_shape, src.data_type(), 1, src.fixed_point_position(), src.quantization_info() };
+
+    // Compute reference
+    const int width_in       = src.shape().x();
+    const int height_in      = src.shape().y();
+    const int depth_in       = src.shape().z();
+    const int width_out      = dst.shape().x();
+    const int height_out     = dst.shape().y();
+    const int depth_out      = dst.shape().z();
+    const int width_weights  = weights.shape().x();
+    const int height_weights = weights.shape().y();
+    const int depth_weights  = weights.shape().z();
+    const int pad_left       = std::min(static_cast<int>(info.pad_left()), width_weights / 2);
+    const int pad_top        = std::min(static_cast<int>(info.pad_top()), height_weights / 2);
+    const int pad_right      = std::min(static_cast<int>(info.pad_right()), width_weights / 2);
+    const int pad_bottom     = std::min(static_cast<int>(info.pad_bottom()), height_weights / 2);
+
+    const int start_xi    = width_weights / 2 - pad_left;
+    const int start_yi    = height_weights / 2 - pad_top;
+    const int end_xi      = width_in + pad_left - width_weights / 2 + pad_right - width_weights / 2;
+    const int end_yi      = height_in + pad_top - height_weights / 2 + pad_bottom - height_weights / 2;
+    const int stride_xi   = info.stride().first;
+    const int stride_yi   = info.stride().second;
+    const int num_batches = src.shape().total_size() / (width_in * height_in * depth_in);
+
+    for(int r = 0; r < num_batches; ++r)
+    {
+        for(int yi = start_yi; yi < start_yi + end_yi; yi += stride_yi)
+        {
+            for(int xi = start_xi; xi < start_xi + end_xi; xi += stride_xi)
+            {
+                for(int ofm = 0; ofm < depth_out; ++ofm)
+                {
+                    // Compute input and output offsets
+                    const int offset_in  = r * width_in * height_in * depth_in;
+                    const int xo         = (xi - start_xi) / stride_xi;
+                    const int yo         = (yi - start_yi) / stride_yi;
+                    const int offset_out = xo + yo * width_out + ofm * width_out * height_out + r * width_out * height_out * depth_out;
+
+                    ARM_COMPUTE_ASSERT(xo < width_out);
+                    ARM_COMPUTE_ASSERT(yo < height_out);
+
+                    // Compute 3D convolution
+                    convolution3d(src, weights, bias, dst,
+                                  offset_in, ofm * width_weights * height_weights * depth_weights, ofm, offset_out,
+                                  xi, yi,
+                                  width_in, height_in, depth_in,
+                                  width_weights, height_weights);
+                }
+            }
+        }
+    }
+
+    return dst;
+}
+
+template SimpleTensor<float> convolution_layer(const SimpleTensor<float> &src, const SimpleTensor<float> &weights, const SimpleTensor<float> &bias, const TensorShape &output_shape,
+                                               const PadStrideInfo &info);
+template SimpleTensor<half> convolution_layer(const SimpleTensor<half> &src, const SimpleTensor<half> &weights, const SimpleTensor<half> &bias, const TensorShape &output_shape,
+                                              const PadStrideInfo &info);
+template SimpleTensor<qint8_t> convolution_layer(const SimpleTensor<qint8_t> &src, const SimpleTensor<qint8_t> &weights, const SimpleTensor<qint8_t> &bias, const TensorShape &output_shape,
+                                                 const PadStrideInfo &info);
+template SimpleTensor<qint16_t> convolution_layer(const SimpleTensor<qint16_t> &src, const SimpleTensor<qint16_t> &weights, const SimpleTensor<qint16_t> &bias, const TensorShape &output_shape,
+                                                  const PadStrideInfo &info);
+template SimpleTensor<uint8_t> convolution_layer(const SimpleTensor<uint8_t> &src, const SimpleTensor<uint8_t> &weights, const SimpleTensor<int32_t> &bias, const TensorShape &output_shape,
+                                                 const PadStrideInfo &info);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/ConvolutionLayer.h b/tests/validation/reference/ConvolutionLayer.h
new file mode 100644
index 0000000..57455ba
--- /dev/null
+++ b/tests/validation/reference/ConvolutionLayer.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_CONVOLUTION_LAYER_H__
+#define __ARM_COMPUTE_TEST_CONVOLUTION_LAYER_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T, typename TB>
+SimpleTensor<T> convolution_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<TB> &bias, const TensorShape &output_shape, const PadStrideInfo &info);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_CONVOLUTION_LAYER_H__ */
diff --git a/tests/validation/reference/DeconvolutionLayer.cpp b/tests/validation/reference/DeconvolutionLayer.cpp
new file mode 100644
index 0000000..82c2188
--- /dev/null
+++ b/tests/validation/reference/DeconvolutionLayer.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "ConvolutionLayer.h"
+
+#include "tests/validation/FixedPoint.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> deconvolution_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<T> &bias, const TensorShape &output_shape,
+                                    const PadStrideInfo &info, const std::pair<unsigned int, unsigned int> &a)
+{
+    // Create reference
+    TensorShape scaled_shape = src.shape();
+    scaled_shape.set(0, output_shape.x());
+    scaled_shape.set(1, output_shape.y());
+    SimpleTensor<T> scaled{ scaled_shape, src.data_type(), 1, src.fixed_point_position() };
+
+    const int          width_in      = src.shape().x();
+    const int          height_in     = src.shape().y();
+    const int          width_scaled  = scaled.shape().x();
+    const int          height_scaled = scaled.shape().y();
+    const int          num_2d_slices = src.shape().total_size() / (width_in * height_in);
+    const float        width_ratio   = static_cast<float>(width_in) / static_cast<float>(width_scaled);
+    const float        height_ratio  = static_cast<float>(height_in) / static_cast<float>(height_scaled);
+    const int          ax            = a.first;  // The number of zeros added to right edge of the input.
+    const int          ay            = a.second; // The number of zeros added to bottom edge of the input.
+    const unsigned int kernel_size   = weights.shape().x();
+    ARM_COMPUTE_ERROR_ON(info.pad().first > (kernel_size - 1));
+    const int transposed_convolution_padx = kernel_size - info.pad().first - 1;
+    const int transposed_convolution_pady = kernel_size - info.pad().second - 1;
+    const int stridex                     = info.stride().first;
+    const int stridey                     = info.stride().second;
+    for(int j = 0; j < scaled.num_elements(); ++j)
+    {
+        scaled[j] = T(0);
+    }
+
+    for(int slice = 0; slice < num_2d_slices; ++slice)
+    {
+        const int offset_slice_in  = slice * width_in * height_in;
+        const int offset_slice_out = slice * width_scaled * height_scaled;
+        for(int yi = ay; yi < height_scaled; yi += stridey)
+        {
+            for(int xi = transposed_convolution_padx; xi < width_scaled; xi += stridex)
+            {
+                const float x_src     = (xi + 0.5f) * width_ratio - 0.5f;
+                const float y_src     = (yi + 0.5f) * height_ratio - 0.5f;
+                T          *out       = scaled.data() + offset_slice_out + xi + yi * width_scaled;
+                const bool  in_bounds = x_src > -1 && y_src > -1 && x_src < width_in && y_src < height_in;
+                const bool  in_axy    = xi < transposed_convolution_padx || xi >= (width_scaled - ax)  // this is checking if the x coordinate is in the padded left/right area
+                                        || yi < ay || yi >= (height_scaled - transposed_convolution_pady); // like above but top and bottom padding in the upscaled XY plane
+                if(!in_axy)
+                {
+                    if(in_bounds)
+                    {
+                        const int in_scaled_x = (x_src < 0.f) ? static_cast<int>(x_src - 0.5f) : static_cast<int>(x_src + 0.5f);
+                        const int in_scaled_y = (y_src < 0.f) ? static_cast<int>(y_src - 0.5f) : static_cast<int>(y_src + 0.5f);
+                        const T *in          = src.data() + offset_slice_in + in_scaled_x + in_scaled_y * width_in;
+                        *out                  = *in;
+                    }
+                    else
+                    {
+                        *out = T(0);
+                    }
+                }
+            }
+        }
+    }
+    const PadStrideInfo conv_info(1, 1, 1, 1, DimensionRoundingType::CEIL);
+    return convolution_layer(scaled, weights, bias, output_shape, conv_info);
+}
+
+template SimpleTensor<float> deconvolution_layer(const SimpleTensor<float> &src, const SimpleTensor<float> &weights, const SimpleTensor<float> &bias, const TensorShape &output_shape,
+                                                 const PadStrideInfo &info, const std::pair<unsigned int, unsigned int> &a);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/DeconvolutionLayer.h b/tests/validation/reference/DeconvolutionLayer.h
new file mode 100644
index 0000000..8222e32
--- /dev/null
+++ b/tests/validation/reference/DeconvolutionLayer.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_DECONVOLUTION_LAYER_H__
+#define __ARM_COMPUTE_TEST_DECONVOLUTION_LAYER_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+/** Deconvolution reference implementation.
+ *
+ * src              Input tensor. 3 lower dimensions represent a single input, and an optional 4th dimension for batch of inputs. Data types supported: F32.
+ * weights          The 4d weights with dimensions [width, height, OFM, IFM]. Data type supported: Same as @p input.
+ * bias             Optional, ignored if NULL. The biases have one dimension. Data type supported: Same as @p input.
+ * output_shape     Output tensor shape. The output has the same number of dimensions as the @p input.
+ * info             Contains padding and policies to be used in the deconvolution, this is decribed in @ref PadStrideInfo.
+ * a                The number of zeros added to right edge of the input.
+ *
+ */
+template <typename T>
+SimpleTensor<T> deconvolution_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<T> &bias, const TensorShape &output_shape, const PadStrideInfo &info,
+                                    const std::pair<unsigned int, unsigned int> &a);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_DECONVOLUTION_LAYER_H__ */
diff --git a/tests/validation/reference/DepthConcatenateLayer.cpp b/tests/validation/reference/DepthConcatenateLayer.cpp
new file mode 100644
index 0000000..9a72484
--- /dev/null
+++ b/tests/validation/reference/DepthConcatenateLayer.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "DepthConcatenateLayer.h"
+
+#include "tests/validation/FixedPoint.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> depthconcatenate_layer(const std::vector<SimpleTensor<T>> &srcs)
+{
+    // Create reference
+    std::vector<TensorShape> shapes;
+
+    for(const auto &src : srcs)
+    {
+        shapes.emplace_back(src.shape());
+    }
+
+    DataType        dst_type  = srcs.empty() ? DataType::UNKNOWN : srcs[0].data_type();
+    TensorShape     dst_shape = calculate_depth_concatenate_shape(shapes);
+    SimpleTensor<T> dst(dst_shape, dst_type);
+
+    // Compute reference
+    int       depth_offset = 0;
+    const int width_out    = dst.shape().x();
+    const int height_out   = dst.shape().y();
+    const int depth_out    = dst.shape().z();
+    const int out_stride_z = width_out * height_out;
+    const int batches      = dst.shape().total_size_upper(3);
+
+    // Set output tensor to 0
+    std::fill_n(dst.data(), dst.num_elements(), 0);
+
+    for(const auto &src : srcs)
+    {
+        ARM_COMPUTE_ERROR_ON(depth_offset >= depth_out);
+        ARM_COMPUTE_ERROR_ON(batches != static_cast<int>(src.shape().total_size_upper(3)));
+
+        const int width  = src.shape().x();
+        const int height = src.shape().y();
+        const int depth  = src.shape().z();
+        const int x_diff = (width_out - width) / 2;
+        const int y_diff = (height_out - height) / 2;
+
+        const T *src_ptr = src.data();
+
+        for(int b = 0; b < batches; ++b)
+        {
+            const size_t offset_to_first_element = b * out_stride_z * depth_out + depth_offset * out_stride_z + y_diff * width_out + x_diff;
+
+            for(int d = 0; d < depth; ++d)
+            {
+                for(int r = 0; r < height; ++r)
+                {
+                    std::copy(src_ptr, src_ptr + width, dst.data() + offset_to_first_element + d * out_stride_z + r * width_out);
+                    src_ptr += width;
+                }
+            }
+        }
+
+        depth_offset += depth;
+    }
+
+    return dst;
+}
+
+template SimpleTensor<float> depthconcatenate_layer(const std::vector<SimpleTensor<float>> &srcs);
+template SimpleTensor<half> depthconcatenate_layer(const std::vector<SimpleTensor<half>> &srcs);
+template SimpleTensor<qint8_t> depthconcatenate_layer(const std::vector<SimpleTensor<qint8_t>> &srcs);
+template SimpleTensor<qint16_t> depthconcatenate_layer(const std::vector<SimpleTensor<qint16_t>> &srcs);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/DepthConcatenateLayer.h b/tests/validation/reference/DepthConcatenateLayer.h
new file mode 100644
index 0000000..3c486a8
--- /dev/null
+++ b/tests/validation/reference/DepthConcatenateLayer.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_DEPTHCONCATENATE_LAYER_H__
+#define __ARM_COMPUTE_TEST_DEPTHCONCATENATE_LAYER_H__
+
+#include "tests/SimpleTensor.h"
+
+#include <vector>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> depthconcatenate_layer(const std::vector<SimpleTensor<T>> &srcs);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_DEPTHCONCATENATE_LAYER_H__ */
diff --git a/tests/validation/reference/DepthConvertLayer.cpp b/tests/validation/reference/DepthConvertLayer.cpp
new file mode 100644
index 0000000..dd095b8
--- /dev/null
+++ b/tests/validation/reference/DepthConvertLayer.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "DepthConvertLayer.h"
+
+#include "tests/validation/FixedPoint.h"
+#include "tests/validation/Helpers.h"
+
+#include "tests/Types.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template < typename T1, typename T2, typename std::enable_if < std::is_integral<T1>::value &&std::is_floating_point<T2>::value, int >::type >
+SimpleTensor<T2> depth_convert(const SimpleTensor<T1> &src, DataType dt_out, ConvertPolicy policy, uint32_t shift)
+{
+    ARM_COMPUTE_UNUSED(policy);
+    ARM_COMPUTE_UNUSED(shift);
+
+    using namespace fixed_point_arithmetic;
+    SimpleTensor<T2> result(src.shape(), dt_out);
+
+    const int fixed_point_position = src.fixed_point_position();
+
+    for(int i = 0; i < src.num_elements(); ++i)
+    {
+        result[i] = static_cast<float>(fixed_point<T1>(src[i], fixed_point_position, true));
+    }
+
+    return result;
+}
+
+template < typename T1, typename T2, typename std::enable_if < std::is_floating_point<T1>::value &&std::is_integral<T2>::value, int >::type >
+SimpleTensor<T2> depth_convert(const SimpleTensor<T1> &src, DataType dt_out, ConvertPolicy policy, uint32_t shift)
+{
+    ARM_COMPUTE_UNUSED(policy);
+    ARM_COMPUTE_UNUSED(shift);
+
+    using namespace fixed_point_arithmetic;
+    SimpleTensor<T2> result(src.shape(), dt_out, 1, src.fixed_point_position());
+
+    const int fixed_point_position = result.fixed_point_position();
+
+    for(int i = 0; i < src.num_elements(); ++i)
+    {
+        result[i] = fixed_point<T2>(src[i], fixed_point_position).raw();
+    }
+
+    return result;
+}
+
+template < typename T1, typename T2, typename std::enable_if < std::is_integral<T1>::value &&std::is_integral<T2>::value &&!std::is_same<T1, T2>::value, int >::type >
+SimpleTensor<T2> depth_convert(const SimpleTensor<T1> &src, DataType dt_out, ConvertPolicy policy, uint32_t shift)
+{
+    SimpleTensor<T2> result(src.shape(), dt_out);
+
+    // Up-casting
+    if(src.data_type() <= dt_out)
+    {
+        for(int i = 0; i < src.num_elements(); ++i)
+        {
+            result[i] = src[i] << shift;
+        }
+    }
+    // Down-casting
+    else
+    {
+        for(int i = 0; i < src.num_elements(); ++i)
+        {
+            T1 val    = src[i] >> shift;
+            result[i] = (policy == ConvertPolicy::SATURATE) ? saturate_cast<T2>(val) : static_cast<T2>(val);
+        }
+    }
+    return result;
+}
+
+template < typename T1, typename T2, typename std::enable_if < std::is_integral<T1>::value &&std::is_integral<T2>::value &&std::is_same<T1, T2>::value, int >::type >
+SimpleTensor<T2> depth_convert(const SimpleTensor<T1> &src, DataType dt_out, ConvertPolicy policy, uint32_t shift)
+{
+    ARM_COMPUTE_UNUSED(policy);
+
+    using namespace fixed_point_arithmetic;
+
+    SimpleTensor<T2> result(src.shape(), dt_out);
+
+    bool is_in_place = (&src == &result);
+
+    const int fixed_point_position_in  = src.fixed_point_position();
+    const int fixed_point_position_out = (is_in_place) ? static_cast<int>(shift) : result.fixed_point_position();
+
+    if(!is_in_place || (fixed_point_position_in != fixed_point_position_out))
+    {
+        for(int i = 0; i < src.num_elements(); ++i)
+        {
+            auto x = fixed_point<T2>(src[i], fixed_point_position_in, true);
+            x.resacle(fixed_point_position_out);
+            result[i] = x.raw();
+        }
+    }
+
+    return result;
+}
+
+template < typename T1, typename T2, typename std::enable_if < std::is_floating_point<T1>::value &&is_floating_point<T2>::value, int >::type >
+SimpleTensor<T2> depth_convert(const SimpleTensor<T1> &src, DataType dt_out, ConvertPolicy policy, uint32_t shift)
+{
+    ARM_COMPUTE_UNUSED(policy);
+    ARM_COMPUTE_UNUSED(shift);
+
+    SimpleTensor<T2> result(src.shape(), dt_out);
+
+    for(int i = 0; i < src.num_elements(); ++i)
+    {
+        result[i] = static_cast<T2>(src[i]);
+    }
+}
+
+template SimpleTensor<uint16_t> depth_convert(const SimpleTensor<uint8_t> &src, DataType dt_out, ConvertPolicy policy, uint32_t shift);
+template SimpleTensor<int16_t> depth_convert(const SimpleTensor<uint8_t> &src, DataType dt_out, ConvertPolicy policy, uint32_t shift);
+template SimpleTensor<int32_t> depth_convert(const SimpleTensor<uint8_t> &src, DataType dt_out, ConvertPolicy policy, uint32_t shift);
+template SimpleTensor<uint8_t> depth_convert(const SimpleTensor<uint16_t> &src, DataType dt_out, ConvertPolicy policy, uint32_t shift);
+template SimpleTensor<uint32_t> depth_convert(const SimpleTensor<uint16_t> &src, DataType dt_out, ConvertPolicy policy, uint32_t shift);
+template SimpleTensor<uint8_t> depth_convert(const SimpleTensor<int16_t> &src, DataType dt_out, ConvertPolicy policy, uint32_t shift);
+template SimpleTensor<int32_t> depth_convert(const SimpleTensor<int16_t> &src, DataType dt_out, ConvertPolicy policy, uint32_t shift);
+template SimpleTensor<float> depth_convert(const SimpleTensor<int8_t> &src, DataType dt_out, ConvertPolicy policy, uint32_t shift);
+template SimpleTensor<float> depth_convert(const SimpleTensor<int16_t> &src, DataType dt_out, ConvertPolicy policy, uint32_t shift);
+template SimpleTensor<int8_t> depth_convert(const SimpleTensor<float> &src, DataType dt_out, ConvertPolicy policy, uint32_t shift);
+template SimpleTensor<int16_t> depth_convert(const SimpleTensor<float> &src, DataType dt_out, ConvertPolicy policy, uint32_t shift);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/DepthConvertLayer.h b/tests/validation/reference/DepthConvertLayer.h
new file mode 100644
index 0000000..1446bfd
--- /dev/null
+++ b/tests/validation/reference/DepthConvertLayer.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_DEPTH_CONVERT_H__
+#define __ARM_COMPUTE_TEST_DEPTH_CONVERT_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template < typename T1, typename T2, typename std::enable_if < std::is_integral<T1>::value &&std::is_floating_point<T2>::value, int >::type = 0 >
+SimpleTensor<T2> depth_convert(const SimpleTensor<T1> &src, DataType dt_out, ConvertPolicy policy, uint32_t shift);
+
+template < typename T1, typename T2, typename std::enable_if < std::is_floating_point<T1>::value &&std::is_integral<T2>::value, int >::type = 0 >
+SimpleTensor<T2> depth_convert(const SimpleTensor<T1> &src, DataType dt_out, ConvertPolicy policy, uint32_t shift);
+
+template < typename T1, typename T2, typename std::enable_if < std::is_integral<T1>::value &&std::is_integral<T2>::value &&!std::is_same<T1, T2>::value, int >::type = 0 >
+SimpleTensor<T2> depth_convert(const SimpleTensor<T1> &src, DataType dt_out, ConvertPolicy policy, uint32_t shift);
+
+template < typename T1, typename T2, typename std::enable_if < std::is_integral<T1>::value &&std::is_integral<T2>::value &&std::is_same<T1, T2>::value, int >::type = 0 >
+SimpleTensor<T2> depth_convert(const SimpleTensor<T1> &src, DataType dt_out, ConvertPolicy policy, uint32_t shift);
+
+template < typename T1, typename T2, typename std::enable_if < std::is_floating_point<T1>::value &&is_floating_point<T2>::value, int >::type = 0 >
+SimpleTensor<T2> depth_convert(const SimpleTensor<T1> &src, DataType dt_out, ConvertPolicy policy, uint32_t shift);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_DEPTH_CONVERT_H__ */
diff --git a/tests/validation/reference/DepthwiseConvolutionLayer.cpp b/tests/validation/reference/DepthwiseConvolutionLayer.cpp
new file mode 100644
index 0000000..0e88d3d
--- /dev/null
+++ b/tests/validation/reference/DepthwiseConvolutionLayer.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "DepthwiseConvolutionLayer.h"
+
+#include "ConvolutionLayer.h"
+#include "Utils.h"
+
+#include "tests/validation/FixedPoint.h"
+#include "tests/validation/Helpers.h"
+#include "tests/validation/reference/Utils.h"
+#include "tests/validation/reference/UtilsQuantizedAsymm.h"
+
+#include "arm_compute/core/utils/quantization/AsymmHelpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+/** Perform a depthwise convolution
+ *
+ * - Three dimensions tensors
+ * - Third dimention is number of channels
+ * - Depths of input tensor and filter are equals
+ * - Padding, stride and output shape "match"
+ *
+ */
+template <typename T, typename TB>
+SimpleTensor<T> depthwise_convolution(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<TB> &biases, const TensorShape &dst_shape, const PadStrideInfo &conv_info)
+{
+    // Create reference
+    SimpleTensor<T> dst{ dst_shape, src.data_type(), 1, src.fixed_point_position() };
+
+    // Compute reference
+    const int filter_width  = weights.shape().x();
+    const int filter_height = weights.shape().y();
+    const int filter_plane  = filter_width * filter_height;
+    const int input_width   = src.shape().x();
+    const int input_height  = src.shape().y();
+    const int input_depth   = src.shape().z();
+    const int num_batches   = src.shape().total_size() / (input_width * input_height * input_depth);
+
+    const int filter_half_width  = filter_width / 2;
+    const int filter_half_height = filter_height / 2;
+
+    const int pad_left   = std::min(static_cast<int>(conv_info.pad_left()), filter_half_width);
+    const int pad_top    = std::min(static_cast<int>(conv_info.pad_top()), filter_half_height);
+    const int pad_right  = std::min(static_cast<int>(conv_info.pad_right()), filter_half_width);
+    const int pad_bottom = std::min(static_cast<int>(conv_info.pad_bottom()), filter_half_height);
+
+    const int minimum_x = -pad_left + filter_half_width;
+    const int minimum_y = -pad_top + filter_half_height;
+    const int maximum_x = input_width + pad_left - filter_half_width + pad_right - filter_half_width;
+    const int maximum_y = input_height + pad_top - filter_half_height + pad_bottom - filter_half_height;
+
+    int out_pos = 0;
+    for(int r = 0; r < num_batches; ++r)
+    {
+        for(int z = 0; z < input_depth; ++z)
+        {
+            for(int y = minimum_y; y < minimum_y + maximum_y; y += conv_info.stride().second)
+            {
+                for(int x = minimum_x; x < minimum_x + maximum_x; x += conv_info.stride().first)
+                {
+                    Coordinates coords(static_cast<int>(x), static_cast<int>(y), static_cast<int>(z), static_cast<int>(r));
+                    size_t      filter_offset = filter_plane * z;
+
+                    T val = 0;
+                    for(int j = y - filter_half_height; j <= static_cast<int>(y + filter_half_height); ++j)
+                    {
+                        for(int i = x - filter_half_width; i <= static_cast<int>(x + filter_half_width); ++i)
+                        {
+                            coords.set(0, i);
+                            coords.set(1, j);
+                            val += *(weights.data() + filter_offset) * tensor_elem_at(src, coords, BorderMode::CONSTANT, 0.f);
+                            ++filter_offset;
+                        }
+                    }
+                    coords.set(0, x);
+                    coords.set(1, y);
+                    dst[out_pos++] = saturate_cast<T>(val + *static_cast<const TB *>(biases(Coordinates(z))));
+                }
+            }
+        }
+    }
+
+    return dst;
+}
+
+template <>
+SimpleTensor<uint8_t> depthwise_convolution(const SimpleTensor<uint8_t> &src, const SimpleTensor<uint8_t> &weights, const SimpleTensor<int32_t> &biases, const TensorShape &dst_shape,
+                                            const PadStrideInfo &conv_info)
+{
+    // Create reference
+    SimpleTensor<uint8_t> dst{ dst_shape, src.data_type(), 1, src.fixed_point_position(), src.quantization_info() };
+
+    const int   input_offset   = -src.quantization_info().offset;
+    const float input_scale    = src.quantization_info().scale;
+    const int   weights_offset = -weights.quantization_info().offset;
+    const float weights_scale  = weights.quantization_info().scale;
+    const int   output_offset  = dst.quantization_info().offset;
+    const float output_scale   = dst.quantization_info().scale;
+
+    int         output_multiplier;
+    int         output_shift;
+    const float multiplier = input_scale * weights_scale / output_scale;
+    arm_compute::quantization::calculate_quantized_multiplier_less_than_one(multiplier, &output_multiplier, &output_shift);
+
+    // Compute reference
+    const int filter_width  = weights.shape().x();
+    const int filter_height = weights.shape().y();
+    const int filter_plane  = filter_width * filter_height;
+    const int input_width   = src.shape().x();
+    const int input_height  = src.shape().y();
+    const int input_depth   = src.shape().z();
+    const int num_batches   = src.shape().total_size() / (input_width * input_height * input_depth);
+
+    const int filter_half_size = filter_width / 2;
+    const int pad_x            = std::min(filter_half_size, static_cast<int>(conv_info.pad().first));
+    const int pad_y            = std::min(filter_half_size, static_cast<int>(conv_info.pad().second));
+    const int minimum_x        = -pad_x + filter_half_size;
+    const int minimum_y        = -pad_y + filter_half_size;
+
+    int out_pos = 0;
+    for(int r = 0; r < num_batches; ++r)
+    {
+        for(int z = 0; z < input_depth; ++z)
+        {
+            int32_t bias_val = *static_cast<const int32_t *>(biases(Coordinates(z)));
+            for(int y = minimum_y; y < input_height + pad_y - filter_half_size; y += conv_info.stride().second)
+            {
+                for(int x = minimum_x; x < input_width + pad_x - filter_half_size; x += conv_info.stride().first)
+                {
+                    Coordinates coords(x, y, z);
+                    int         filter_offset = filter_plane * z;
+
+                    uint32_t val = 0;
+                    for(int j = y - filter_half_size; j <= (y + filter_half_size); ++j)
+                    {
+                        for(int i = x - filter_half_size; i <= (x + filter_half_size); ++i)
+                        {
+                            coords.set(0, i);
+                            coords.set(1, j);
+                            auto    in_val = tensor_elem_at<uint8_t>(src, coords, BorderMode::CONSTANT, 0);
+                            uint8_t w_val  = *(weights.data() + filter_offset);
+                            val += (in_val + input_offset) * (w_val + weights_offset);
+                            ++filter_offset;
+                        }
+                    }
+                    val += bias_val;
+                    val = asymm_rounding_divide_by_pow2(asymm_int_mult(val, output_multiplier), output_shift);
+                    val += output_offset;
+                    val = std::max<int32_t>(val, 0);
+                    val = std::min<int32_t>(val, 255);
+
+                    // Store the result
+                    dst[out_pos++] = val;
+                }
+            }
+        }
+    }
+
+    return dst;
+}
+
+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
+} // namespace arm_compute
diff --git a/tests/validation/reference/DepthwiseConvolutionLayer.h b/tests/validation/reference/DepthwiseConvolutionLayer.h
new file mode 100644
index 0000000..df743a5
--- /dev/null
+++ b/tests/validation/reference/DepthwiseConvolutionLayer.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_DEPTHWISE_CONVOLUTION_H__
+#define __ARM_COMPUTE_TEST_DEPTHWISE_CONVOLUTION_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T, typename TB>
+SimpleTensor<T> depthwise_convolution(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<TB> &biases, const TensorShape &dst_shape, const PadStrideInfo &conv_info);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_DEPTHWISE_SEPARABLE_CONVOLUTION_LAYER_H__ */
diff --git a/tests/validation/reference/DepthwiseSeparableConvolutionLayer.cpp b/tests/validation/reference/DepthwiseSeparableConvolutionLayer.cpp
new file mode 100644
index 0000000..ca6c168
--- /dev/null
+++ b/tests/validation/reference/DepthwiseSeparableConvolutionLayer.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "DepthwiseConvolutionLayer.h"
+
+#include "DepthwiseSeparableConvolutionLayer.h"
+
+#include "ConvolutionLayer.h"
+#include "Utils.h"
+
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+// Depthwise separable convolution layer
+template <typename T>
+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)
+{
+    // Compute reference
+    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 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
+} // namespace arm_compute
diff --git a/tests/validation/reference/DepthwiseSeparableConvolutionLayer.h b/tests/validation/reference/DepthwiseSeparableConvolutionLayer.h
new file mode 100644
index 0000000..0fcce2c
--- /dev/null
+++ b/tests/validation/reference/DepthwiseSeparableConvolutionLayer.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_DEPTHWISE_SEPARABLE_CONVOLUTION_LAYER_H__
+#define __ARM_COMPUTE_TEST_DEPTHWISE_SEPARABLE_CONVOLUTION_LAYER_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+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
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_DEPTHWISE_SEPARABLE_CONVOLUTION_LAYER_H__ */
diff --git a/tests/validation/reference/DequantizationLayer.cpp b/tests/validation/reference/DequantizationLayer.cpp
new file mode 100644
index 0000000..33096a1
--- /dev/null
+++ b/tests/validation/reference/DequantizationLayer.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "DequantizationLayer.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type>
+SimpleTensor<float> dequantization_layer(const SimpleTensor<T> &src, const SimpleTensor<float> &min_max)
+{
+    // Create reference
+    SimpleTensor<float> dst{ src.shape(), DataType::F32 };
+
+    // Compute reference
+    const int width       = src.shape().x();
+    const int height      = src.shape().y();
+    const int depth       = src.shape().z();
+    const int stride_w    = width * height * depth;
+    const int num_batches = min_max.shape().total_size_upper(1);
+
+    for(int k = 0; k < num_batches; ++k)
+    {
+        const float min     = min_max[k * 2 + 0];
+        const float max     = min_max[k * 2 + 1];
+        const float range   = max - min;
+        const float scaling = range / 255.0f;
+
+        for(int i = 0; i < stride_w; ++i)
+        {
+            dst[i + k * stride_w] = (static_cast<float>(src[i + k * stride_w]) * scaling) + min;
+        }
+    }
+
+    return dst;
+}
+
+template SimpleTensor<float> dequantization_layer(const SimpleTensor<uint8_t> &src, const SimpleTensor<float> &min_max);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/DequantizationLayer.h b/tests/validation/reference/DequantizationLayer.h
new file mode 100644
index 0000000..1a8adcf
--- /dev/null
+++ b/tests/validation/reference/DequantizationLayer.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_DEQUANTIZATION_LAYER_H__
+#define __ARM_COMPUTE_TEST_DEQUANTIZATION_LAYER_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
+SimpleTensor<float> dequantization_layer(const SimpleTensor<T> &src, const SimpleTensor<float> &min_max);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_DEQUANTIZATION_LAYER_H__ */
diff --git a/tests/validation/reference/Dilate.cpp b/tests/validation/reference/Dilate.cpp
new file mode 100644
index 0000000..0683a0a
--- /dev/null
+++ b/tests/validation/reference/Dilate.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "Dilate.h"
+
+#include "Utils.h"
+#include "tests/validation/Helpers.h"
+
+#include <algorithm>
+#include <array>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> dilate(const SimpleTensor<T> &src, BorderMode border_mode, T constant_border_value)
+{
+    /*
+             -1   x  +1
+         -1 [tl][tc][tr] -1
+          y [ml][xy][mr]  y
+         +1 [bl][bc][br] +1
+             -1   x  +1
+        dilate:
+        dst(x, y) = max[ src(x', y') for x-1<=x'<=x+1, y-1<=y'<=y+1 ] = max({tl, tc, tr, ml, xy, mr, bl, bc, br})
+    */
+    SimpleTensor<T> dst(src.shape(), src.data_type());
+
+    for(int i = 0; i < src.num_elements(); ++i)
+    {
+        Coordinates coord = index2coord(src.shape(), i);
+        const int   x     = coord.x();
+        const int   y     = coord.y();
+
+        std::array<T, 9> neighbours = { { 0 } };
+        for(int row = y - 1, j = 0; row <= y + 1; ++row)
+        {
+            for(int col = x - 1; col <= x + 1; ++col, ++j)
+            {
+                coord.set(0, col);
+                coord.set(1, row);
+                neighbours[j] = tensor_elem_at(src, coord, border_mode, constant_border_value);
+            }
+        }
+
+        dst[i] = *std::max_element(neighbours.cbegin(), neighbours.cend());
+    }
+
+    return dst;
+}
+
+template SimpleTensor<uint8_t> dilate(const SimpleTensor<uint8_t> &src, BorderMode border_mode, uint8_t constant_border_value);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/Dilate.h b/tests/validation/reference/Dilate.h
new file mode 100644
index 0000000..6586cbf
--- /dev/null
+++ b/tests/validation/reference/Dilate.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_DILATE_H__
+#define __ARM_COMPUTE_TEST_DILATE_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> dilate(const SimpleTensor<T> &src, BorderMode border_mode, T constant_border_value = 0);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_DILATE_H__ */
diff --git a/tests/validation/reference/Erode.cpp b/tests/validation/reference/Erode.cpp
new file mode 100644
index 0000000..5e8b36f
--- /dev/null
+++ b/tests/validation/reference/Erode.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "Erode.h"
+
+#include "Utils.h"
+#include "tests/validation/Helpers.h"
+
+#include <algorithm>
+#include <array>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> erode(const SimpleTensor<T> &src, BorderMode border_mode, T constant_border_value)
+{
+    /*
+             -1   x  +1
+         -1 [tl][tc][tr] -1
+          y [ml][xy][mr]  y
+         +1 [bl][bc][br] +1
+             -1   x  +1
+        erode:
+        dst(x, y) = min[ src(x', y') for x-1<=x'<=x+1, y-1<=y'<=y+1 ] = min({tl, tc, tr, ml, xy, mr, bl, bc, br})
+    */
+    SimpleTensor<T> dst(src.shape(), src.data_type());
+
+    for(int i = 0; i < src.num_elements(); ++i)
+    {
+        Coordinates coord = index2coord(src.shape(), i);
+        const int   x     = coord.x();
+        const int   y     = coord.y();
+
+        std::array<T, 9> neighbours = { { 0 } };
+        for(int row = y - 1, j = 0; row <= y + 1; ++row)
+        {
+            for(int col = x - 1; col <= x + 1; ++col, ++j)
+            {
+                coord.set(0, col);
+                coord.set(1, row);
+                neighbours[j] = tensor_elem_at(src, coord, border_mode, constant_border_value);
+            }
+        }
+
+        dst[i] = *std::min_element(neighbours.cbegin(), neighbours.cend());
+    }
+
+    return dst;
+}
+
+template SimpleTensor<uint8_t> erode(const SimpleTensor<uint8_t> &src, BorderMode border_mode, uint8_t constant_border_value);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/Erode.h b/tests/validation/reference/Erode.h
new file mode 100644
index 0000000..5e27513
--- /dev/null
+++ b/tests/validation/reference/Erode.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_ERODE_H__
+#define __ARM_COMPUTE_TEST_ERODE_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> erode(const SimpleTensor<T> &src, BorderMode border_mode, T constant_border_value = 0);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_ERODE_H__ */
diff --git a/tests/validation/reference/FixedPoint.cpp b/tests/validation/reference/FixedPoint.cpp
new file mode 100644
index 0000000..a016093
--- /dev/null
+++ b/tests/validation/reference/FixedPoint.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "FixedPoint.h"
+
+#include "arm_compute/core/Types.h"
+#include "tests/validation/FixedPoint.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> fixed_point_operation(const SimpleTensor<T> &src, FixedPointOp op)
+{
+    SimpleTensor<T> result(src.shape(), src.data_type());
+
+    const int p = src.fixed_point_position();
+    switch(op)
+    {
+        case FixedPointOp::EXP:
+            for(int i = 0; i < src.num_elements(); ++i)
+            {
+                result[i] = fixed_point_arithmetic::exp(fixed_point_arithmetic::fixed_point<T>(src[i], p, true)).raw();
+            }
+            break;
+        case FixedPointOp::LOG:
+            for(int i = 0; i < src.num_elements(); ++i)
+            {
+                result[i] = fixed_point_arithmetic::log(fixed_point_arithmetic::fixed_point<T>(src[i], p, true)).raw();
+            }
+            break;
+        case FixedPointOp::INV_SQRT:
+            for(int i = 0; i < src.num_elements(); ++i)
+            {
+                result[i] = fixed_point_arithmetic::inv_sqrt(fixed_point_arithmetic::fixed_point<T>(src[i], p, true)).raw();
+            }
+            break;
+        case FixedPointOp::RECIPROCAL:
+            for(int i = 0; i < src.num_elements(); ++i)
+            {
+                result[i] = fixed_point_arithmetic::div(fixed_point_arithmetic::fixed_point<T>(1, p), fixed_point_arithmetic::fixed_point<T>(src[i], p, true)).raw();
+            }
+            break;
+        default:
+            ARM_COMPUTE_ERROR("Fixed point operation not supported");
+            break;
+    }
+
+    return result;
+}
+
+template SimpleTensor<int8_t> fixed_point_operation(const SimpleTensor<int8_t> &src, FixedPointOp op);
+template SimpleTensor<int16_t> fixed_point_operation(const SimpleTensor<int16_t> &src, FixedPointOp op);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/FixedPoint.h b/tests/validation/reference/FixedPoint.h
new file mode 100644
index 0000000..f0117f9
--- /dev/null
+++ b/tests/validation/reference/FixedPoint.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_FIXED_POINT_OPERATION_H__
+#define __ARM_COMPUTE_TEST_FIXED_POINT_OPERATION_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/Types.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> fixed_point_operation(const SimpleTensor<T> &src, FixedPointOp op);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_FIXED_POINT_OPERATION_H__ */
diff --git a/tests/validation/reference/FixedPointPixelWiseMultiplication.cpp b/tests/validation/reference/FixedPointPixelWiseMultiplication.cpp
new file mode 100644
index 0000000..636919b
--- /dev/null
+++ b/tests/validation/reference/FixedPointPixelWiseMultiplication.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * dst OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "FixedPointPixelWiseMultiplication.h"
+
+#include "tests/validation/FixedPoint.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> fixed_point_pixel_wise_multiplication(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2, float scale, ConvertPolicy convert_policy)
+{
+    using namespace fixed_point_arithmetic;
+
+    SimpleTensor<T> dst(src2.shape(), src2.data_type(), 1, src2.fixed_point_position());
+
+    const int fixed_point_position = src1.fixed_point_position();
+
+    ARM_COMPUTE_ERROR_ON_MSG(src1.data_type() != src2.data_type() || src1.data_type() != dst.data_type(),
+                             "Tensors must all have the same DataType");
+    ARM_COMPUTE_ERROR_ON_MSG(fixed_point_position != src2.fixed_point_position() || fixed_point_position != dst.fixed_point_position(),
+                             "Fixed-point position must be the same for both inputs and outputs");
+
+    // Validate fixed_point_position
+    ARM_COMPUTE_ERROR_ON((src1.data_type() == DataType::QS8) && (fixed_point_position == 0 || fixed_point_position > 7));
+    ARM_COMPUTE_ERROR_ON((src1.data_type() == DataType::QS16) && (fixed_point_position == 0 || fixed_point_position > 15));
+
+    const fixed_point<T> fp_scale(scale, fixed_point_position);
+    const bool           is_sat = convert_policy == ConvertPolicy::SATURATE;
+
+    for(int i = 0; i < src1.num_elements(); ++i)
+    {
+        const fixed_point<T> val1(src1[i], fixed_point_position, true);
+        fixed_point<T>       res(src2[i], fixed_point_position, true);
+        if(is_sat)
+        {
+            res = mul(mul(res, val1), fp_scale);
+        }
+        else
+        {
+            res = mul<OverflowPolicy::WRAP>(mul<OverflowPolicy::WRAP>(res, val1), fp_scale);
+        }
+        dst[i] = res.raw();
+    }
+
+    return dst;
+}
+
+// *INDENT-OFF*
+// clang-format off
+template SimpleTensor<qint8_t> fixed_point_pixel_wise_multiplication(const SimpleTensor<qint8_t> &src1, const SimpleTensor<qint8_t> &src2, float scale, ConvertPolicy convert_policy);
+template SimpleTensor<qint16_t> fixed_point_pixel_wise_multiplication(const SimpleTensor<qint16_t> &src1, const SimpleTensor<qint16_t> &src2, float scale, ConvertPolicy convert_policy);
+// *INDENT-ON*
+// clang-format on
+
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/FixedPointPixelWiseMultiplication.h b/tests/validation/reference/FixedPointPixelWiseMultiplication.h
new file mode 100644
index 0000000..124a33c
--- /dev/null
+++ b/tests/validation/reference/FixedPointPixelWiseMultiplication.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_FIXED_POINT_PIXEL_WISE_MULTIPLICATION_H__
+#define __ARM_COMPUTE_TEST_FIXED_POINT_PIXEL_WISE_MULTIPLICATION_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> fixed_point_pixel_wise_multiplication(const SimpleTensor<T> &src1, const SimpleTensor<T> &src2, float scale, ConvertPolicy convert_policy);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_FIXED_POINT_PIXEL_WISE_MULTIPLICATION_H__ */
diff --git a/tests/validation/reference/FlattenLayer.cpp b/tests/validation/reference/FlattenLayer.cpp
new file mode 100644
index 0000000..611701d
--- /dev/null
+++ b/tests/validation/reference/FlattenLayer.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "FlattenLayer.h"
+
+#include "tests/validation/FixedPoint.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> flatten_layer(const SimpleTensor<T> &src)
+{
+    TensorShape shape_flatten(src.shape());
+    shape_flatten.set(0, src.shape()[0] * src.shape()[1] * src.shape()[2]);
+    shape_flatten.remove_dimension(1);
+    shape_flatten.remove_dimension(1);
+    SimpleTensor<T> dst(shape_flatten, src.data_type(), 1, src.fixed_point_position());
+
+    // Note: Since the reference implementation does not use padding bytes, we can copy directly the content of the source tensor
+    std::copy(src.data(), src.data() + src.num_elements(), dst.data());
+
+    return dst;
+}
+
+template SimpleTensor<float> flatten_layer(const SimpleTensor<float> &src);
+template SimpleTensor<half> flatten_layer(const SimpleTensor<half> &src);
+template SimpleTensor<qint8_t> flatten_layer(const SimpleTensor<qint8_t> &src);
+template SimpleTensor<qint16_t> flatten_layer(const SimpleTensor<qint16_t> &src);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/FlattenLayer.h b/tests/validation/reference/FlattenLayer.h
new file mode 100644
index 0000000..b1286fe
--- /dev/null
+++ b/tests/validation/reference/FlattenLayer.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_FLATTEN_LAYER_H__
+#define __ARM_COMPUTE_TEST_FLATTEN_LAYER_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> flatten_layer(const SimpleTensor<T> &src);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_FLATTEN_LAYER_H__ */
diff --git a/tests/validation/reference/Floor.cpp b/tests/validation/reference/Floor.cpp
new file mode 100644
index 0000000..1c73944
--- /dev/null
+++ b/tests/validation/reference/Floor.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "Floor.h"
+
+#include "tests/validation/Helpers.h"
+
+#include <cmath>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> floor_layer(const SimpleTensor<T> &src)
+{
+    // Create reference
+    SimpleTensor<T> dst{ src.shape(), src.data_type() };
+
+    // Compute reference
+    for(int i = 0; i < src.num_elements(); ++i)
+    {
+        dst[i] = std::floor(src[i]);
+    }
+
+    return dst;
+}
+
+template SimpleTensor<float> floor_layer(const SimpleTensor<float> &src);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/Floor.h b/tests/validation/reference/Floor.h
new file mode 100644
index 0000000..d95ee30
--- /dev/null
+++ b/tests/validation/reference/Floor.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_FLOOR_H__
+#define __ARM_COMPUTE_TEST_FLOOR_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> floor_layer(const SimpleTensor<T> &src);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_FLOOR_H__ */
diff --git a/tests/validation/reference/FullyConnectedLayer.cpp b/tests/validation/reference/FullyConnectedLayer.cpp
new file mode 100644
index 0000000..c24881e
--- /dev/null
+++ b/tests/validation/reference/FullyConnectedLayer.cpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "FullyConnectedLayer.h"
+
+#include "arm_compute/core/Types.h"
+#include "tests/validation/FixedPoint.h"
+#include "tests/validation/reference/UtilsQuantizedAsymm.h"
+
+#include "arm_compute/core/utils/quantization/AsymmHelpers.h"
+
+#include <numeric>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+namespace
+{
+// Vector matrix multiply for floating point
+template < typename T, typename TB, typename std::enable_if < is_floating_point<T>::value &&is_floating_point<TB>::value, int >::type = 0 >
+void vector_matrix_multiply(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<TB> &bias, SimpleTensor<T> &dst, int offset_src, int offset_dst, int cols_weights,
+                            int rows_weights, uint8_t fixed_point_position)
+{
+    ARM_COMPUTE_UNUSED(fixed_point_position);
+
+    const T *src_ptr     = src.data() + offset_src;
+    const T *weights_ptr = weights.data();
+    const TB *bias_ptr    = bias.data();
+    T        *dst_ptr     = dst.data() + offset_dst;
+
+    for(int y = 0; y < rows_weights; ++y)
+    {
+        dst_ptr[y] = std::inner_product(src_ptr, src_ptr + cols_weights, weights_ptr, static_cast<T>(0)) + bias_ptr[y];
+        weights_ptr += cols_weights;
+    }
+}
+
+// Vector matrix multiply for fixed point type
+template < typename T, typename TB, typename std::enable_if < std::is_integral<T>::value &&std::is_integral<TB>::value, int >::type = 0 >
+void vector_matrix_multiply(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<TB> &bias, SimpleTensor<T> &dst, int offset_src, int offset_dst, int cols_weights,
+                            int rows_weights, uint8_t fixed_point_position)
+{
+    const T *src_ptr     = src.data() + offset_src;
+    const T *weights_ptr = weights.data();
+    const TB *bias_ptr    = bias.data();
+    T        *dst_ptr     = dst.data() + offset_dst;
+
+    using namespace fixed_point_arithmetic;
+    using promoted_type = fixed_point_arithmetic::traits::promote_t<T>;
+
+    for(int y = 0; y < rows_weights; ++y)
+    {
+        // Reset accumulator
+        fixed_point<promoted_type> acc(0, fixed_point_position);
+
+        for(int x = 0; x < cols_weights; ++x)
+        {
+            const fixed_point<promoted_type> i_value(src_ptr[x], fixed_point_position, true);
+            const fixed_point<promoted_type> w_value(weights_ptr[x], fixed_point_position, true);
+            acc = acc + i_value * w_value;
+        }
+
+        // Get the bias
+        const fixed_point<T> b(bias_ptr[y], fixed_point_position, true);
+
+        // Convert back and accumulate the bias
+        fixed_point<T> res(acc);
+        res = res + b;
+
+        // Store the result
+        dst_ptr[y] = res.raw();
+
+        weights_ptr += cols_weights;
+    }
+}
+
+// Vector matrix multiply for quantized type
+template <>
+void vector_matrix_multiply(const SimpleTensor<uint8_t> &src, const SimpleTensor<uint8_t> &weights, const SimpleTensor<int32_t> &bias, SimpleTensor<uint8_t> &dst, int offset_src, int offset_dst,
+                            int cols_weights, int rows_weights, uint8_t fixed_point_position)
+{
+    ARM_COMPUTE_UNUSED(fixed_point_position);
+
+    const uint8_t *src_ptr     = src.data() + offset_src;
+    const uint8_t *weights_ptr = weights.data();
+    const int32_t *bias_ptr    = bias.data();
+    uint8_t       *dst_ptr     = dst.data() + offset_dst;
+
+    const int   input_offset   = -src.quantization_info().offset;
+    const float input_scale    = src.quantization_info().scale;
+    const int   weights_offset = -weights.quantization_info().offset;
+    const float weights_scale  = weights.quantization_info().scale;
+    const int   output_offset  = dst.quantization_info().offset;
+    const float output_scale   = dst.quantization_info().scale;
+
+    int         output_multiplier = 0;
+    int         output_shift      = 0;
+    const float multiplier        = input_scale * weights_scale / output_scale;
+    arm_compute::quantization::calculate_quantized_multiplier_less_than_one(multiplier, &output_multiplier, &output_shift);
+
+    for(int y = 0; y < rows_weights; ++y)
+    {
+        // Reset accumulator
+        int32_t acc = 0;
+
+        for(int x = 0; x < cols_weights; ++x)
+        {
+            acc += (src_ptr[x] + input_offset) * (weights_ptr[x] + weights_offset);
+        }
+
+        // Accumulate the bias
+        acc += bias_ptr[y];
+
+        acc = asymm_rounding_divide_by_pow2(asymm_int_mult(acc, output_multiplier), output_shift);
+        acc += output_offset;
+        acc = clamp<int32_t>(acc, 0, 255);
+
+        // Store the result
+        dst_ptr[y] = static_cast<uint8_t>(acc);
+
+        weights_ptr += cols_weights;
+    }
+}
+} // namespace
+
+template <typename T, typename TB>
+SimpleTensor<T> fully_connected_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<TB> &bias, const TensorShape &dst_shape)
+{
+    // Create reference
+    SimpleTensor<T> dst{ TensorShape{ dst_shape }, src.data_type(), 1, src.fixed_point_position(), src.quantization_info() };
+
+    // Sanity checks
+    const int          num_batch_dimensions = std::max(0, static_cast<int>(dst_shape.num_dimensions()) - 1);
+    const int          num_input_dimensions = src.shape().num_dimensions() - num_batch_dimensions;
+    const unsigned int linear_input_size    = src.shape().total_size_lower(num_input_dimensions);
+
+    ARM_COMPUTE_UNUSED(num_batch_dimensions);
+    ARM_COMPUTE_UNUSED(num_input_dimensions);
+    ARM_COMPUTE_UNUSED(linear_input_size);
+    ARM_COMPUTE_ERROR_ON(weights.shape().x() != linear_input_size);
+    ARM_COMPUTE_ERROR_ON(weights.shape().y() != bias.shape().x());
+    ARM_COMPUTE_ERROR_ON(weights.shape().y() != dst.shape().x());
+
+    // Compute reference
+    const int cols_weights = weights.shape().x();
+    const int rows_weights = weights.shape().y();
+    const int num_batches  = dst_shape.total_size_upper(1);
+
+    for(int k = 0; k < num_batches; ++k)
+    {
+        const int offset_in  = k * cols_weights;
+        const int offset_out = k * rows_weights;
+
+        vector_matrix_multiply<T>(src,
+                                  weights,
+                                  bias,
+                                  dst,
+                                  offset_in,
+                                  offset_out,
+                                  cols_weights,
+                                  rows_weights,
+                                  src.fixed_point_position());
+    }
+
+    return dst;
+}
+
+template SimpleTensor<float> fully_connected_layer(const SimpleTensor<float> &src, const SimpleTensor<float> &weights, const SimpleTensor<float> &bias, const TensorShape &dst_shape);
+template SimpleTensor<half> fully_connected_layer(const SimpleTensor<half> &src, const SimpleTensor<half> &weights, const SimpleTensor<half> &bias, const TensorShape &dst_shape);
+template SimpleTensor<qint8_t> fully_connected_layer(const SimpleTensor<qint8_t> &src, const SimpleTensor<qint8_t> &weights, const SimpleTensor<qint8_t> &bias, const TensorShape &dst_shape);
+template SimpleTensor<qint16_t> fully_connected_layer(const SimpleTensor<qint16_t> &src, const SimpleTensor<qint16_t> &weights, const SimpleTensor<qint16_t> &bias, const TensorShape &dst_shape);
+template SimpleTensor<uint8_t> fully_connected_layer(const SimpleTensor<uint8_t> &src, const SimpleTensor<uint8_t> &weights, const SimpleTensor<int32_t> &bias, const TensorShape &dst_shape);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/FullyConnectedLayer.h b/tests/validation/reference/FullyConnectedLayer.h
new file mode 100644
index 0000000..1dfb496
--- /dev/null
+++ b/tests/validation/reference/FullyConnectedLayer.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_FULLY_CONNECTED_LAYER_H__
+#define __ARM_COMPUTE_TEST_FULLY_CONNECTED_LAYER_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T, typename TB>
+SimpleTensor<T> fully_connected_layer(const SimpleTensor<T> &src, const SimpleTensor<T> &weights, const SimpleTensor<TB> &bias, const TensorShape &dst_shape);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_FULLY_CONNECTED_LAYER_H__ */
diff --git a/tests/validation/reference/GEMM.cpp b/tests/validation/reference/GEMM.cpp
new file mode 100644
index 0000000..77d025e
--- /dev/null
+++ b/tests/validation/reference/GEMM.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "GEMM.h"
+
+#include "arm_compute/core/Types.h"
+#include "tests/validation/FixedPoint.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type>
+SimpleTensor<T> gemm(const SimpleTensor<T> &a, const SimpleTensor<T> &b, const SimpleTensor<T> &c, float alpha, float beta)
+{
+    // Create reference
+    SimpleTensor<T> dst{ c.shape(), c.data_type(), 1, c.fixed_point_position() };
+
+    // Compute reference
+    const int M = dst.shape().y();
+    const int N = dst.shape().x();
+    const int K = a.shape().x();
+
+    for(int row = 0; row < M; ++row)
+    {
+        for(int col = 0; col < N; ++col)
+        {
+            T acc(0);
+
+            for(int k = 0; k < K; ++k)
+            {
+                acc += a[row * K + k] * b[k * N + col];
+            }
+
+            // Finalize the result: alpha * A * B + beta * C
+            dst[col + row * N] = alpha * acc + beta * c[col + row * N];
+        }
+    }
+
+    return dst;
+}
+
+template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type>
+SimpleTensor<T> gemm(const SimpleTensor<T> &a, const SimpleTensor<T> &b, const SimpleTensor<T> &c, float alpha, float beta)
+{
+    using namespace fixed_point_arithmetic;
+
+    // Create reference
+    SimpleTensor<T> dst{ c.shape(), c.data_type(), 1, c.fixed_point_position() };
+
+    // Compute reference
+    using promoted_type = fixed_point_arithmetic::traits::promote_t<T>;
+
+    const int M                    = dst.shape().y();
+    const int N                    = dst.shape().x();
+    const int K                    = a.shape().x();
+    const int fixed_point_position = a.fixed_point_position();
+
+    const fixed_point<T> alpha_q(alpha, fixed_point_position);
+    const fixed_point<T> beta_q(beta, fixed_point_position);
+
+    for(int row = 0; row < M; ++row)
+    {
+        for(int col = 0; col < N; ++col)
+        {
+            fixed_point<promoted_type> acc_q(0, fixed_point_position);
+
+            for(int k = 0; k < K; ++k)
+            {
+                const fixed_point<promoted_type> a0_q(a[row * K + k], fixed_point_position, true);
+                const fixed_point<promoted_type> b0_q(b[k * N + col], fixed_point_position, true);
+
+                acc_q = acc_q + (a0_q * b0_q);
+            }
+
+            // Finalize the result: alpha * A * B + beta * C
+            const fixed_point<T> c0_q(c[col + row * N], fixed_point_position, true);
+
+            fixed_point<T> res_q(acc_q);
+            res_q = alpha_q * res_q;
+            res_q = res_q + (beta_q * c0_q);
+
+            // Store the result
+            dst[col + row * N] = res_q.raw();
+        }
+    }
+
+    return dst;
+}
+
+template SimpleTensor<float> gemm(const SimpleTensor<float> &a, const SimpleTensor<float> &b, const SimpleTensor<float> &c, float alpha, float beta);
+template SimpleTensor<half> gemm(const SimpleTensor<half> &a, const SimpleTensor<half> &b, const SimpleTensor<half> &c, float alpha, float beta);
+template SimpleTensor<qint8_t> gemm(const SimpleTensor<qint8_t> &a, const SimpleTensor<qint8_t> &b, const SimpleTensor<qint8_t> &c, float alpha, float beta);
+template SimpleTensor<qint16_t> gemm(const SimpleTensor<qint16_t> &a, const SimpleTensor<qint16_t> &b, const SimpleTensor<qint16_t> &c, float alpha, float beta);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/GEMM.h b/tests/validation/reference/GEMM.h
new file mode 100644
index 0000000..cda792b
--- /dev/null
+++ b/tests/validation/reference/GEMM.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_GEMM_H__
+#define __ARM_COMPUTE_TEST_GEMM_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type = 0>
+SimpleTensor<T> gemm(const SimpleTensor<T> &a, const SimpleTensor<T> &b, const SimpleTensor<T> &c, float alpha, float beta);
+
+template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
+SimpleTensor<T> gemm(const SimpleTensor<T> &a, const SimpleTensor<T> &b, const SimpleTensor<T> &c, float alpha, float beta);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_GEMM_H__ */
diff --git a/tests/validation/reference/GEMMInterleave4x4.h b/tests/validation/reference/GEMMInterleave4x4.h
new file mode 100644
index 0000000..e6b09af
--- /dev/null
+++ b/tests/validation/reference/GEMMInterleave4x4.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "GEMM.h"
+
+#include "arm_compute/core/Types.h"
+#include "tests/validation/FixedPoint.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> gemm_interleave_4x4(const SimpleTensor<T> &in, SimpleTensor<T> &out)
+{
+    const T      *mtx_in     = reinterpret_cast<const T *>(in.data());
+    T            *mtx_ref    = reinterpret_cast<T *>(out.data());
+    const int32_t in_rows    = in.shape().y();
+    const int32_t in_cols    = in.shape().x();
+    const int32_t out_stride = out.shape().x();
+    int32_t       y          = 0;
+    for(; y <= (in_rows - 4); y += 4)
+    {
+        const T *in_ptr = &mtx_in[y * in_cols];
+
+        for(int32_t x = 0; x < in_cols; x++)
+        {
+            const T tmp[4] = { in_ptr[x + 0 * in_cols],
+                               in_ptr[x + 1 * in_cols],
+                               in_ptr[x + 2 * in_cols],
+                               in_ptr[x + 3 * in_cols]
+                             };
+
+            T *dst = &mtx_ref[static_cast<size_t>(x * 4.f) + static_cast<size_t>(std::ceil(y / 4.f)) * out_stride];
+            memcpy(dst, tmp, sizeof(T) * 4);
+        }
+    }
+
+    // Leftover along the Y direction
+    const int32_t leftover_y = in_rows - y;
+
+    if(leftover_y != 0)
+    {
+        const T *in_ptr = &mtx_in[y * in_cols];
+
+        for(int32_t x = 0; x < in_cols; x++)
+        {
+            T tmp[4] = { 0, 0, 0, 0 };
+
+            for(int32_t k = 0; k < leftover_y; k++)
+            {
+                tmp[k] = in_ptr[k * in_cols + x];
+            }
+            T *dst = &mtx_ref[static_cast<size_t>(x * 4.f) + static_cast<size_t>(std::ceil(y / 4.f)) * out_stride];
+            memcpy(dst, tmp, sizeof(T) * 4);
+        }
+    }
+
+    return out;
+}
+
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/GEMMInterleaveBlocked.h b/tests/validation/reference/GEMMInterleaveBlocked.h
new file mode 100644
index 0000000..ff5a0d6
--- /dev/null
+++ b/tests/validation/reference/GEMMInterleaveBlocked.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "GEMM.h"
+
+#include "arm_compute/core/Types.h"
+#include "tests/validation/FixedPoint.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+T safe_read(const SimpleTensor<T> &t, int y, int x)
+{
+    const int stride = t.shape().x();
+    const int M      = t.shape().y();
+    const int N      = t.shape().x();
+    if((y < M) && (x < N))
+    {
+        return t[y * stride + x];
+    }
+    return 0;
+}
+
+template <typename T>
+SimpleTensor<T> gemm_interleave_blocked(const SimpleTensor<T> &in, SimpleTensor<T> &out, int int_by, int block, bool transposed)
+{
+    const int M = out.shape().y();
+    const int N = out.shape().x();
+    for(int y = 0; y < M; y++)
+    {
+        T *out_ptr = &out[y * N];
+        for(int x = 0; x < (N / int_by); x += block)
+        {
+            for(int z = 0; z < int_by; z++)
+            {
+                for(int a = 0; (out_ptr <= &out[y * N + (N - 1)]) && a < block; a++)
+                {
+                    if(!transposed)
+                        *out_ptr++ = safe_read(in, (y * int_by) + z, x + a);
+                    else
+                    {
+                        const T value = safe_read(in, x + a, (y * int_by) + z);
+                        *out_ptr++    = value;
+                    }
+                }
+            }
+        }
+    }
+    return out;
+}
+
+template SimpleTensor<uint8_t> gemm_interleave_blocked(const SimpleTensor<uint8_t> &in, SimpleTensor<uint8_t> &out, int int_by, int block, bool transposed);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/GEMMLowp.cpp b/tests/validation/reference/GEMMLowp.cpp
new file mode 100644
index 0000000..8e41aef
--- /dev/null
+++ b/tests/validation/reference/GEMMLowp.cpp
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "GEMMLowp.h"
+
+#include "arm_compute/core/Types.h"
+#include "tests/validation/reference/UtilsQuantizedAsymm.h"
+
+#include <limits>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+namespace
+{
+template <typename T>
+void quantize_down_int32_to_uint8_scale(const SimpleTensor<T> *in, const SimpleTensor<T> *bias, SimpleTensor<uint8_t> *dst, int32_t result_offset, int32_t result_mult_int, int32_t result_shift,
+                                        int32_t min, int32_t max)
+{
+    const int cols_in = in->shape().x();
+
+    for(int i = 0; i < in->num_elements(); ++i)
+    {
+        int32_t result = ((*in)[i] + result_offset);
+
+        if(bias != nullptr)
+        {
+            result += (*bias)[i % cols_in];
+        }
+
+        result *= result_mult_int;
+
+        result >>= result_shift;
+
+        // Bounded ReLu
+        if(min != max)
+        {
+            result = std::max(min, std::min(max, result));
+        }
+
+        (*dst)[i] = static_cast<uint8_t>(std::max(0, std::min(255, result)));
+    }
+}
+
+template <typename T>
+void quantize_down_int32_to_uint8_scale_by_fixedpoint(const SimpleTensor<T> *in, const SimpleTensor<T> *bias, SimpleTensor<uint8_t> *dst, int32_t result_fixedpoint_multiplier, int32_t result_shift,
+                                                      int32_t result_offset_after_shift, int32_t min, int32_t max)
+{
+    const int cols_in = in->shape().x();
+
+    for(int i = 0; i < in->num_elements(); ++i)
+    {
+        int32_t result = (*in)[i];
+
+        if(bias != nullptr)
+        {
+            result += (*bias)[i % cols_in];
+        }
+
+        // Fixed point multiplication
+        result = asymm_rounding_divide_by_pow2(asymm_int_mult(result, result_fixedpoint_multiplier), result_shift);
+        result += result_offset_after_shift;
+
+        // Bounded ReLu
+        if(min != max)
+        {
+            result = std::max(min, std::min(max, result));
+        }
+
+        (*dst)[i] = static_cast<uint8_t>(std::max(0, std::min(255, result)));
+    }
+}
+} // namespace
+
+template <typename T_out, typename T_in>
+SimpleTensor<T_out> gemmlowp_matrix_multiply_core(const SimpleTensor<T_in> &a, const SimpleTensor<T_in> &b, int32_t a_offset, int32_t b_offset)
+{
+    static_assert(std::is_same<typename std::decay<T_out>::type, int32_t>::value, "Only int32_t is allowed for the output");
+
+    TensorShape         shape(b.shape()[0], a.shape()[1]);
+    DataType            dt = std::is_same<T_out, int32_t>::value ? DataType::S32 : DataType::U32;
+    SimpleTensor<T_out> c(shape, dt);
+
+    const int K       = a.shape().x();
+    const int b_width = b.shape().x();
+    const int rows    = c.shape().y(); //M
+    const int cols    = c.shape().x(); //N
+
+    std::vector<T_out> acc;
+    acc.resize(cols);
+
+    for(int i = 0; i < rows; ++i)
+    {
+        for(int j = 0; j < cols; ++j)
+        {
+            acc[j] = 0;
+        }
+        for(int k = 0; k < K; ++k)
+        {
+            const T_out tmp_a = a_offset + static_cast<T_out>(a[k + i * K]);
+            for(int j = 0; j < b_width; ++j)
+            {
+                const T_out tmp_b       = b_offset + static_cast<T_out>(b[j + k * b_width]);
+                const T_out mult_as_int = tmp_a * tmp_b;
+                acc[j] += mult_as_int;
+            }
+        }
+        for(int j = 0; j < cols; ++j)
+        {
+            c[j + i * cols] = acc[j];
+        }
+    }
+
+    return c;
+}
+
+// used to validate assembly kernels which don't know anything about offsets
+template <typename T1, typename T2>
+SimpleTensor<T1> gemmlowp(const SimpleTensor<T2> &a, const SimpleTensor<T2> &b)
+{
+    return gemmlowp_matrix_multiply_core<T1, T2>(a, b, 0, 0);
+}
+
+template <typename T>
+SimpleTensor<uint8_t> gemmlowp_quantize_down_int32_to_uint8_scale(const SimpleTensor<T> &in, int32_t result_offset, int32_t result_mult_int, int32_t result_shift, int32_t min, int32_t max)
+{
+    SimpleTensor<uint8_t> dst(in.shape(), DataType::QASYMM8);
+
+    quantize_down_int32_to_uint8_scale<T>(&in, nullptr, &dst, result_offset, result_mult_int, result_shift, min, max);
+
+    return dst;
+}
+
+template <typename T>
+SimpleTensor<uint8_t> gemmlowp_quantize_down_int32_to_uint8_scale(const SimpleTensor<T> &in, const SimpleTensor<T> &bias, int32_t result_offset, int32_t result_mult_int, int32_t result_shift,
+                                                                  int32_t min, int32_t max)
+{
+    SimpleTensor<uint8_t> dst(in.shape(), DataType::QASYMM8);
+
+    quantize_down_int32_to_uint8_scale<T>(&in, &bias, &dst, result_offset, result_mult_int, result_shift, min, max);
+
+    return dst;
+}
+
+template <typename T>
+SimpleTensor<uint8_t> gemmlowp_quantize_down_int32_to_uint8_scale_by_fixedpoint(const SimpleTensor<T> &in, int32_t result_fixedpoint_multiplier, int32_t result_shift,
+                                                                                int32_t result_offset_after_shift, int32_t min,
+                                                                                int32_t max)
+{
+    SimpleTensor<uint8_t> dst(in.shape(), DataType::QASYMM8);
+
+    quantize_down_int32_to_uint8_scale_by_fixedpoint<T>(&in, nullptr, &dst, result_fixedpoint_multiplier, result_shift, result_offset_after_shift, min, max);
+
+    return dst;
+}
+
+template <typename T>
+SimpleTensor<uint8_t> gemmlowp_quantize_down_int32_to_uint8_scale_by_fixedpoint(const SimpleTensor<T> &in, const SimpleTensor<T> &bias, int32_t result_fixedpoint_multiplier, int32_t result_shift,
+                                                                                int32_t result_offset_after_shift, int32_t min, int32_t max)
+{
+    SimpleTensor<uint8_t> dst(in.shape(), DataType::QASYMM8);
+
+    quantize_down_int32_to_uint8_scale_by_fixedpoint<T>(&in, &bias, &dst, result_fixedpoint_multiplier, result_shift, result_offset_after_shift, min, max);
+
+    return dst;
+}
+
+template SimpleTensor<uint8_t> gemmlowp_quantize_down_int32_to_uint8_scale_by_fixedpoint(const SimpleTensor<int32_t> &a, int32_t result_fixedpoint_multiplier, int32_t result_shift,
+                                                                                         int32_t result_offset_after_shift, int32_t min, int32_t max);
+template SimpleTensor<uint8_t> gemmlowp_quantize_down_int32_to_uint8_scale_by_fixedpoint(const SimpleTensor<int32_t> &a, const SimpleTensor<int32_t> &b, int32_t result_fixedpoint_multiplier,
+                                                                                         int32_t result_shift, int32_t result_offset_after_shift, int32_t min, int32_t max);
+template SimpleTensor<uint8_t> gemmlowp_quantize_down_int32_to_uint8_scale(const SimpleTensor<int32_t> &a, int32_t result_offset, int32_t result_mult_int, int32_t result_shift, int32_t min,
+                                                                           int32_t max);
+template SimpleTensor<uint8_t> gemmlowp_quantize_down_int32_to_uint8_scale(const SimpleTensor<int32_t> &a, const SimpleTensor<int32_t> &b, int32_t result_offset, int32_t result_mult_int,
+                                                                           int32_t result_shift, int32_t min, int32_t max);
+template SimpleTensor<int32_t> gemmlowp_matrix_multiply_core(const SimpleTensor<int8_t> &a, const SimpleTensor<int8_t> &b, int32_t a_offset, int32_t b_offset);
+template SimpleTensor<int32_t> gemmlowp_matrix_multiply_core(const SimpleTensor<uint8_t> &a, const SimpleTensor<uint8_t> &b, int32_t a_offset, int32_t b_offset);
+template SimpleTensor<int32_t> gemmlowp(const SimpleTensor<int8_t> &a, const SimpleTensor<int8_t> &b);
+template SimpleTensor<int32_t> gemmlowp(const SimpleTensor<uint8_t> &a, const SimpleTensor<uint8_t> &b);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/GEMMLowp.h b/tests/validation/reference/GEMMLowp.h
new file mode 100644
index 0000000..a3d0beb
--- /dev/null
+++ b/tests/validation/reference/GEMMLowp.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_GEMMLOWP_H__
+#define __ARM_COMPUTE_TEST_GEMMLOWP_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<uint8_t> gemmlowp_quantize_down_int32_to_uint8_scale(const SimpleTensor<T> &in, int32_t result_offset, int32_t result_mult_int, int32_t result_shift, int32_t min = 0, int32_t max = 0);
+template <typename T1, typename T2>
+SimpleTensor<T1> gemmlowp_matrix_multiply_core(const SimpleTensor<T2> &a, const SimpleTensor<T2> &b, int32_t a_offset, int32_t b_offset);
+
+template <typename T>
+SimpleTensor<uint8_t> gemmlowp_quantize_down_int32_to_uint8_scale(const SimpleTensor<T> &in, int32_t result_offset, int32_t result_mult_int, int32_t result_shift);
+
+template <typename T1, typename T2>
+SimpleTensor<T1> gemmlowp(const SimpleTensor<T2> &a, const SimpleTensor<T2> &b);
+
+template <typename T>
+SimpleTensor<uint8_t> gemmlowp_quantize_down_int32_to_uint8_scale(const SimpleTensor<T> &in, const SimpleTensor<T> &bias, int32_t result_offset, int32_t result_mult_int, int32_t result_shift,
+                                                                  int32_t min = 0, int32_t max = 0);
+
+template <typename T>
+SimpleTensor<uint8_t> gemmlowp_quantize_down_int32_to_uint8_scale_by_fixedpoint(const SimpleTensor<T> &in, int32_t result_fixedpoint_multiplier, int32_t result_shift,
+                                                                                int32_t result_offset_after_shift,
+                                                                                int32_t min = 0, int32_t max = 0);
+
+template <typename T>
+SimpleTensor<uint8_t> gemmlowp_quantize_down_int32_to_uint8_scale_by_fixedpoint(const SimpleTensor<T> &in, const SimpleTensor<T> &bias, int32_t result_fixedpoint_multiplier, int32_t result_shift,
+                                                                                int32_t result_offset_after_shift, int32_t min = 0, int32_t max = 0);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_GEMMLOWP_H__ */
diff --git a/tests/validation/reference/Gaussian3x3.cpp b/tests/validation/reference/Gaussian3x3.cpp
new file mode 100644
index 0000000..c71eade
--- /dev/null
+++ b/tests/validation/reference/Gaussian3x3.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "arm_compute/core/Helpers.h"
+
+#include "Gaussian3x3.h"
+#include "Utils.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> gaussian3x3(const SimpleTensor<T> &src, BorderMode border_mode, T constant_border_value)
+{
+    SimpleTensor<T> dst(src.shape(), src.data_type());
+    const std::array<T, 9> filter{ { 1, 2, 1, 2, 4, 2, 1, 2, 1 } };
+    const float scale = 1.f / 16.f;
+    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, dst, TensorShape(3U, 3U), filter.data(), scale, border_mode, constant_border_value);
+    }
+    return dst;
+}
+
+template SimpleTensor<uint8_t> gaussian3x3(const SimpleTensor<uint8_t> &src, BorderMode border_mode, uint8_t constant_border_value);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/Gaussian3x3.h b/tests/validation/reference/Gaussian3x3.h
new file mode 100644
index 0000000..85a7acd
--- /dev/null
+++ b/tests/validation/reference/Gaussian3x3.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_GAUSSIAN3X3_H__
+#define __ARM_COMPUTE_TEST_GAUSSIAN3X3_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> gaussian3x3(const SimpleTensor<T> &src, BorderMode border_mode, T constant_border_value);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_GAUSSIAN3X3_H__ */
diff --git a/tests/validation/reference/Gaussian5x5.cpp b/tests/validation/reference/Gaussian5x5.cpp
new file mode 100644
index 0000000..55bb287
--- /dev/null
+++ b/tests/validation/reference/Gaussian5x5.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "arm_compute/core/Helpers.h"
+
+#include "Gaussian5x5.h"
+#include "Utils.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> gaussian5x5(const SimpleTensor<T> &src, BorderMode border_mode, T constant_border_value)
+{
+    SimpleTensor<T> dst(src.shape(), src.data_type());
+    const std::array<T, 25> filter{ {
+            1, 4, 6, 4, 1,
+            4, 16, 24, 16, 4,
+            6, 24, 36, 24, 6,
+            4, 16, 24, 16, 4,
+            1, 4, 6, 4, 1
+        } };
+    const float scale = 1.f / 256.f;
+    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, dst, TensorShape(5U, 5U), filter.data(), scale, border_mode, constant_border_value);
+    }
+    return dst;
+}
+
+template SimpleTensor<uint8_t> gaussian5x5(const SimpleTensor<uint8_t> &src, BorderMode border_mode, uint8_t constant_border_value);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/Gaussian5x5.h b/tests/validation/reference/Gaussian5x5.h
new file mode 100644
index 0000000..df981c7
--- /dev/null
+++ b/tests/validation/reference/Gaussian5x5.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_GAUSSIAN5X5_H__
+#define __ARM_COMPUTE_TEST_GAUSSIAN5X5_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> gaussian5x5(const SimpleTensor<T> &src, BorderMode border_mode, T constant_border_value);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_GAUSSIAN5X5_H__ */
diff --git a/tests/validation/reference/GaussianPyramidHalf.cpp b/tests/validation/reference/GaussianPyramidHalf.cpp
new file mode 100644
index 0000000..0a68ded
--- /dev/null
+++ b/tests/validation/reference/GaussianPyramidHalf.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "GaussianPyramidHalf.h"
+
+#include "arm_compute/core/Helpers.h"
+
+#include "Gaussian5x5.h"
+#include "Scale.h"
+#include "Utils.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+std::vector<SimpleTensor<T>> gaussian_pyramid_half(const SimpleTensor<T> &src, BorderMode border_mode, uint8_t constant_border_value, size_t num_levels)
+{
+    std::vector<SimpleTensor<T>> dst;
+
+    // Level0 is equal to src
+    dst.push_back(src);
+
+    for(size_t i = 1; i < num_levels; ++i)
+    {
+        // Gaussian Filter
+        const SimpleTensor<T> out_gaus5x5 = reference::gaussian5x5(dst[i - 1], border_mode, constant_border_value);
+
+        // Scale down by 2 with nearest interpolation
+        const SimpleTensor<T> out = reference::scale(out_gaus5x5, SCALE_PYRAMID_HALF, SCALE_PYRAMID_HALF, InterpolationPolicy::NEAREST_NEIGHBOR, border_mode, constant_border_value, SamplingPolicy::CENTER,
+                                                     true);
+
+        dst.push_back(out);
+    }
+
+    return dst;
+}
+
+template std::vector<SimpleTensor<uint8_t>> gaussian_pyramid_half(const SimpleTensor<uint8_t> &src, BorderMode border_mode, uint8_t constant_border_value, size_t num_levels);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/GaussianPyramidHalf.h b/tests/validation/reference/GaussianPyramidHalf.h
new file mode 100644
index 0000000..abd29e1
--- /dev/null
+++ b/tests/validation/reference/GaussianPyramidHalf.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_GAUSSIAN_PYRAMID_HALF_H__
+#define __ARM_COMPUTE_TEST_GAUSSIAN_PYRAMID_HALF_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+std::vector<SimpleTensor<T>> gaussian_pyramid_half(const SimpleTensor<T> &src, BorderMode border_mode, uint8_t constant_border_value, size_t num_levels);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_GAUSSIAN_PYRAMID_HALF_H__ */
\ No newline at end of file
diff --git a/tests/validation/reference/HarrisCornerDetector.cpp b/tests/validation/reference/HarrisCornerDetector.cpp
new file mode 100644
index 0000000..12afd95
--- /dev/null
+++ b/tests/validation/reference/HarrisCornerDetector.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "HarrisCornerDetector.h"
+
+#include "Utils.h"
+#include "tests/validation/Helpers.h"
+#include "tests/validation/reference/NonMaximaSuppression.h"
+#include "tests/validation/reference/Sobel.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+namespace
+{
+template <typename T>
+std::tuple<SimpleTensor<T>, SimpleTensor<T>, float> compute_sobel(const SimpleTensor<uint8_t> &src, int gradient_size, int block_size, BorderMode border_mode, uint8_t constant_border_value)
+{
+    SimpleTensor<T> grad_x;
+    SimpleTensor<T> grad_y;
+    float           norm_factor = 0.f;
+
+    std::tie(grad_x, grad_y) = sobel<T>(src, gradient_size, border_mode, constant_border_value, GradientDimension::GRAD_XY);
+
+    switch(gradient_size)
+    {
+        case 3:
+            norm_factor = 1.f / (4 * 255 * block_size);
+            break;
+        case 5:
+            norm_factor = 1.f / (16 * 255 * block_size);
+            break;
+        case 7:
+            norm_factor = 1.f / (64 * 255 * block_size);
+            break;
+        default:
+            ARM_COMPUTE_ERROR("Gradient size not supported.");
+    }
+
+    return std::make_tuple(grad_x, grad_y, norm_factor);
+}
+
+template <typename T, typename U>
+std::vector<KeyPoint> harris_corner_detector_impl(const SimpleTensor<U> &src, float threshold, float min_dist, float sensitivity, int gradient_size, int block_size, BorderMode border_mode,
+                                                  U constant_border_value)
+{
+    ARM_COMPUTE_ERROR_ON(block_size != 3 && block_size != 5 && block_size != 7);
+
+    SimpleTensor<T> grad_x;
+    SimpleTensor<T> grad_y;
+    float           norm_factor = 0.f;
+
+    // Sobel
+    std::tie(grad_x, grad_y, norm_factor) = compute_sobel<T>(src, gradient_size, block_size, border_mode, constant_border_value);
+
+    SimpleTensor<float> scores(src.shape(), DataType::F32);
+    ValidRegion         scores_region = shape_to_valid_region(scores.shape(), border_mode == BorderMode::UNDEFINED, BorderSize(gradient_size / 2 + block_size / 2));
+
+    // Calculate scores
+    for(int i = 0; i < scores.num_elements(); ++i)
+    {
+        Coordinates src_coord = index2coord(src.shape(), i);
+        Coordinates block_top_left{ src_coord.x() - block_size / 2, src_coord.y() - block_size / 2 };
+        Coordinates block_bottom_right{ src_coord.x() + block_size / 2, src_coord.y() + block_size / 2 };
+
+        if(!is_in_valid_region(scores_region, src_coord))
+        {
+            scores[i] = 0.f;
+            continue;
+        }
+
+        float Gx2 = 0.f;
+        float Gy2 = 0.f;
+        float Gxy = 0.f;
+
+        // Calculate Gx^2, Gy^2 and Gxy within the given window
+        for(int y = src_coord.y() - block_size / 2; y <= src_coord.y() + block_size / 2; ++y)
+        {
+            for(int x = src_coord.x() - block_size / 2; x <= src_coord.x() + block_size / 2; ++x)
+            {
+                Coordinates block_coord(x, y);
+
+                const float norm_x = tensor_elem_at(grad_x, block_coord, border_mode, static_cast<T>(constant_border_value)) * norm_factor;
+                const float norm_y = tensor_elem_at(grad_y, block_coord, border_mode, static_cast<T>(constant_border_value)) * norm_factor;
+
+                Gx2 += std::pow(norm_x, 2);
+                Gy2 += std::pow(norm_y, 2);
+                Gxy += norm_x * norm_y;
+            }
+        }
+
+        const float trace2   = std::pow(Gx2 + Gy2, 2);
+        const float det      = Gx2 * Gy2 - std::pow(Gxy, 2);
+        const float response = det - sensitivity * trace2;
+
+        if(response > threshold)
+        {
+            scores[i] = response;
+        }
+        else
+        {
+            scores[i] = 0.f;
+        }
+    }
+
+    // Suppress non-maxima candidates
+    SimpleTensor<float> suppressed_scores        = non_maxima_suppression(scores, border_mode != BorderMode::UNDEFINED ? BorderMode::CONSTANT : BorderMode::UNDEFINED, 0.f);
+    ValidRegion         suppressed_scores_region = shape_to_valid_region(suppressed_scores.shape(), border_mode == BorderMode::UNDEFINED, BorderSize(gradient_size / 2 + block_size / 2 + 1));
+
+    // Create vector of candidate corners
+    std::vector<KeyPoint> corner_candidates;
+
+    for(int i = 0; i < suppressed_scores.num_elements(); ++i)
+    {
+        Coordinates coord = index2coord(suppressed_scores.shape(), i);
+
+        if(is_in_valid_region(suppressed_scores_region, coord) && suppressed_scores[i] > 0.f)
+        {
+            KeyPoint corner;
+            corner.x               = coord.x();
+            corner.y               = coord.y();
+            corner.tracking_status = 1;
+            corner.strength        = suppressed_scores[i];
+            corner.scale           = 0.f;
+            corner.orientation     = 0.f;
+            corner.error           = 0.f;
+
+            corner_candidates.emplace_back(corner);
+        }
+    }
+
+    // Sort descending by strength
+    std::sort(corner_candidates.begin(), corner_candidates.end(), [](const KeyPoint & a, const KeyPoint & b)
+    {
+        return a.strength > b.strength;
+    });
+
+    std::vector<KeyPoint> corners;
+    corners.reserve(corner_candidates.size());
+
+    // Only add corner if there is no stronger within min_dist
+    for(const KeyPoint &point : corner_candidates)
+    {
+        const auto strongest = std::find_if(corners.begin(), corners.end(), [&](const KeyPoint & other)
+        {
+            return std::sqrt((std::pow(point.x - other.x, 2) + std::pow(point.y - other.y, 2))) < min_dist;
+        });
+
+        if(strongest == corners.end())
+        {
+            corners.emplace_back(point);
+        }
+    }
+
+    corners.shrink_to_fit();
+
+    return corners;
+}
+} // namespace
+
+template <typename T>
+std::vector<KeyPoint> harris_corner_detector(const SimpleTensor<T> &src, float threshold, float min_dist, float sensitivity, int gradient_size, int block_size, BorderMode border_mode,
+                                             T constant_border_value)
+{
+    if(gradient_size < 7)
+    {
+        return harris_corner_detector_impl<int16_t>(src, threshold, min_dist, sensitivity, gradient_size, block_size, border_mode, constant_border_value);
+    }
+    else
+    {
+        return harris_corner_detector_impl<int32_t>(src, threshold, min_dist, sensitivity, gradient_size, block_size, border_mode, constant_border_value);
+    }
+}
+
+template std::vector<KeyPoint> harris_corner_detector(const SimpleTensor<uint8_t> &src, float threshold, float min_dist, float sensitivity, int gradient_size, int block_size, BorderMode border_mode,
+                                                      uint8_t constant_border_value);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/HarrisCornerDetector.h b/tests/validation/reference/HarrisCornerDetector.h
new file mode 100644
index 0000000..042e857
--- /dev/null
+++ b/tests/validation/reference/HarrisCornerDetector.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_HARRIS_CORNER_DETECTOR_H__
+#define __ARM_COMPUTE_TEST_HARRIS_CORNER_DETECTOR_H__
+
+#include "arm_compute/core/Types.h"
+#include "tests/SimpleTensor.h"
+
+#include <vector>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+std::vector<KeyPoint> harris_corner_detector(const SimpleTensor<T> &src, float threshold, float min_dist, float sensitivity, int gradient_size, int block_size, BorderMode border_mode,
+                                             T constant_border_value = 0);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_HARRIS_CORNER_DETECTOR_H__ */
diff --git a/tests/validation/reference/Histogram.cpp b/tests/validation/reference/Histogram.cpp
new file mode 100644
index 0000000..594c4fb
--- /dev/null
+++ b/tests/validation/reference/Histogram.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "Histogram.h"
+
+#include "Utils.h"
+#include "arm_compute/core/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<uint32_t> histogram(const SimpleTensor<T> &src, size_t num_bins, int32_t offset, uint32_t range)
+{
+    SimpleTensor<uint32_t> dst(TensorShape(num_bins), DataType::U32);
+
+    // Clear the distribution
+    for(size_t element_idx = 0; element_idx < num_bins; ++element_idx)
+    {
+        dst[element_idx] = 0;
+    }
+
+    // Create the histogram
+    for(int element_idx = 0; element_idx < src.num_elements(); ++element_idx)
+    {
+        if((offset <= src[element_idx]) && (src[element_idx] < (offset + range)))
+        {
+            const int index = (src[element_idx] - offset) * num_bins / range;
+            dst[index]++;
+        }
+    }
+
+    return dst;
+}
+
+template SimpleTensor<uint32_t> histogram(const SimpleTensor<uint8_t> &src, size_t num_bins, int32_t offset, uint32_t range);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/Histogram.h b/tests/validation/reference/Histogram.h
new file mode 100644
index 0000000..7ec1669
--- /dev/null
+++ b/tests/validation/reference/Histogram.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_HISTOGRAM_H__
+#define __ARM_COMPUTE_TEST_HISTOGRAM_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<uint32_t> histogram(const SimpleTensor<T> &src, size_t num_bins, int32_t offset, uint32_t range);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_HISTOGRAM_H__ */
diff --git a/tests/validation/reference/IntegralImage.cpp b/tests/validation/reference/IntegralImage.cpp
new file mode 100644
index 0000000..8d07e99
--- /dev/null
+++ b/tests/validation/reference/IntegralImage.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "IntegralImage.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<uint32_t> integral_image(const SimpleTensor<T> &src)
+{
+    SimpleTensor<uint32_t> dst(src.shape(), DataType::U32);
+
+    // Length of dimensions
+    const size_t width  = src.shape().x();
+    const size_t height = src.shape().y();
+    const size_t depth  = src.shape().total_size_upper(2);
+
+    const size_t image_size = width * height;
+
+    for(size_t z = 0; z < depth; ++z)
+    {
+        size_t current_image = z * image_size;
+
+        //First element of each image
+        dst[current_image] = src[current_image];
+
+        // First row of each image (add only pixel on the left)
+        for(size_t x = 1; x < width; ++x)
+        {
+            dst[current_image + x] = static_cast<uint32_t>(src[current_image + x]) + dst[current_image + x - 1];
+        }
+
+        // Subsequent rows
+        for(size_t y = 1; y < height; ++y)
+        {
+            size_t current_row = current_image + (width * y);
+
+            // First element of each row (add only pixel up)
+            dst[current_row] = static_cast<uint32_t>(src[current_row]) + dst[current_row - width];
+
+            // Following row elements
+            for(size_t x = 1; x < width; ++x)
+            {
+                size_t current_pixel = current_row + x;
+
+                // out = in + up(out) + left(out) - up_left(out)
+                dst[current_pixel] = static_cast<uint32_t>(src[current_pixel]) + dst[current_pixel - 1]
+                                     + dst[current_pixel - width] - dst[current_pixel - width - 1];
+            }
+        }
+    }
+
+    return dst;
+}
+
+template SimpleTensor<uint32_t> integral_image(const SimpleTensor<uint8_t> &src);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/IntegralImage.h b/tests/validation/reference/IntegralImage.h
new file mode 100644
index 0000000..c766aae
--- /dev/null
+++ b/tests/validation/reference/IntegralImage.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_INTEGRAL_IMAGE_H__
+#define __ARM_COMPUTE_TEST_INTEGRAL_IMAGE_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<uint32_t> integral_image(const SimpleTensor<T> &src);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_INTEGRAL_IMAGE_H__ */
diff --git a/tests/validation/reference/L2NormalizeLayer.cpp b/tests/validation/reference/L2NormalizeLayer.cpp
new file mode 100644
index 0000000..99f4e8a
--- /dev/null
+++ b/tests/validation/reference/L2NormalizeLayer.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "L2NormalizeLayer.h"
+#include "ReductionOperation.h"
+
+#include "tests/validation/Helpers.h"
+
+#include <algorithm>
+#include <cmath>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+namespace
+{
+TensorShape get_output_shape(TensorShape shape, unsigned int axis)
+{
+    TensorShape output_shape(shape);
+    output_shape.set(axis, 1);
+    return output_shape;
+}
+} // namespace
+
+template <typename T>
+SimpleTensor<T> l2_normalize(const SimpleTensor<T> &src, unsigned int axis, float epsilon)
+{
+    // Create reference
+    SimpleTensor<T> dst{ src.shape(), src.data_type() };
+
+    // Reduce across given axis
+    SimpleTensor<T> sum = reduction_operation(src, get_output_shape(src.shape(), axis), axis, ReductionOperation::SUM_SQUARE);
+
+    // Compute reference
+    const int elems      = src.shape()[axis];
+    const int upper_dims = src.shape().total_size_upper(axis + 1);
+
+    for(int du = 0; du < upper_dims; ++du)
+    {
+        if(axis == 0)
+        {
+            const T *src_row_ptr         = src.data() + du * elems;
+            T       *dst_row_ptr         = dst.data() + du * elems;
+            const T  normalization_value = std::sqrt(std::max(sum[du], epsilon));
+            std::transform(src_row_ptr, src_row_ptr + elems, dst_row_ptr, [normalization_value](T val)
+            {
+                return val / normalization_value;
+            });
+        }
+        else
+        {
+            ARM_COMPUTE_ERROR("Unsupported normalization axis");
+        }
+    }
+
+    return dst;
+}
+
+template SimpleTensor<float> l2_normalize(const SimpleTensor<float> &src, unsigned int axis, float epsilon);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/L2NormalizeLayer.h b/tests/validation/reference/L2NormalizeLayer.h
new file mode 100644
index 0000000..1db3ae6
--- /dev/null
+++ b/tests/validation/reference/L2NormalizeLayer.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_L2NORMALIZE_H__
+#define __ARM_COMPUTE_TEST_L2NORMALIZE_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> l2_normalize(const SimpleTensor<T> &src, unsigned int axis, float epsilon);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_L2NORMALIZE_H__ */
diff --git a/tests/validation/reference/Magnitude.cpp b/tests/validation/reference/Magnitude.cpp
new file mode 100644
index 0000000..f0002bf
--- /dev/null
+++ b/tests/validation/reference/Magnitude.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "Magnitude.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> magnitude(const SimpleTensor<T> &gx, const SimpleTensor<T> &gy, MagnitudeType magnitude_type)
+{
+    SimpleTensor<T> mag(gx.shape(), gx.data_type());
+
+    using intermediate_type = typename common_promoted_unsigned_type<T>::intermediate_type;
+
+    for(int i = 0; i < gx.num_elements(); ++i)
+    {
+        double val = 0.f;
+
+        if(magnitude_type == MagnitudeType::L1NORM)
+        {
+            val = static_cast<intermediate_type>(std::abs(gx[i])) + static_cast<intermediate_type>(std::abs(gy[i]));
+        }
+        else // MagnitudeType::L2NORM
+        {
+            // Note: kernel saturates to uint32_t instead of intermediate_type for S32 format
+            auto sum = static_cast<uint32_t>(gx[i] * gx[i]) + static_cast<uint32_t>(gy[i] * gy[i]);
+            val      = std::sqrt(sum) + 0.5f;
+        }
+
+        mag[i] = saturate_cast<T>(val);
+    }
+
+    return mag;
+}
+
+template SimpleTensor<int16_t> magnitude(const SimpleTensor<int16_t> &gx, const SimpleTensor<int16_t> &gy, MagnitudeType magnitude_type);
+template SimpleTensor<int32_t> magnitude(const SimpleTensor<int32_t> &gx, const SimpleTensor<int32_t> &gy, MagnitudeType magnitude_type);
+template SimpleTensor<half_float::half> magnitude(const SimpleTensor<half_float::half> &gx, const SimpleTensor<half_float::half> &gy, MagnitudeType magnitude_type);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/Magnitude.h b/tests/validation/reference/Magnitude.h
new file mode 100644
index 0000000..7562071
--- /dev/null
+++ b/tests/validation/reference/Magnitude.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_MAGNITUDE_H__
+#define __ARM_COMPUTE_TEST_MAGNITUDE_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> magnitude(const SimpleTensor<T> &gx, const SimpleTensor<T> &gy, MagnitudeType magnitude_type);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_MAGNITUDE_H__ */
diff --git a/tests/validation/reference/MeanStdDev.cpp b/tests/validation/reference/MeanStdDev.cpp
new file mode 100644
index 0000000..4a39b13
--- /dev/null
+++ b/tests/validation/reference/MeanStdDev.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "MeanStdDev.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+std::pair<float, float> mean_and_standard_deviation(const SimpleTensor<T> &in)
+{
+    const int num_elements = in.num_elements();
+
+    // Calculate mean
+    float mean = std::accumulate(in.data(), in.data() + num_elements, 0.f) / num_elements;
+
+    // Calculate standard deviation
+    float std_dev = std::accumulate(in.data(), in.data() + num_elements, 0.f, [&mean](float a, float b)
+    {
+        return a + (mean - b) * (mean - b);
+    });
+
+    std_dev = std::sqrt(std_dev / num_elements);
+
+    return std::make_pair(mean, std_dev);
+}
+
+template std::pair<float, float> mean_and_standard_deviation(const SimpleTensor<uint8_t> &in);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/MeanStdDev.h b/tests/validation/reference/MeanStdDev.h
new file mode 100644
index 0000000..6b89ae0
--- /dev/null
+++ b/tests/validation/reference/MeanStdDev.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_STD_MEAN_DEV_H__
+#define __ARM_COMPUTE_TEST_STD_MEAN_DEV_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+std::pair<float, float> mean_and_standard_deviation(const SimpleTensor<T> &in);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_STD_MEAN_DEV_H__ */
diff --git a/tests/validation/reference/Median3x3.cpp b/tests/validation/reference/Median3x3.cpp
new file mode 100644
index 0000000..91a787a
--- /dev/null
+++ b/tests/validation/reference/Median3x3.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "arm_compute/core/Helpers.h"
+
+#include "Median3x3.h"
+#include "Utils.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+namespace
+{
+constexpr unsigned int filter_size = 3;              /* Size of the kernel/filter in number of elements. */
+constexpr BorderSize   border_size(filter_size / 2); /* Border size of the kernel/filter around its central element. */
+} // namespace
+
+template <typename T>
+SimpleTensor<T> median3x3(const SimpleTensor<T> &src, BorderMode border_mode, T constant_border_value)
+{
+    SimpleTensor<T> dst(src.shape(), src.data_type());
+    const int       size_tot_filter = filter_size * filter_size;
+
+    for(int src_idx = 0; src_idx < src.num_elements(); ++src_idx)
+    {
+        std::array<T, size_tot_filter> filter_elems = { { 0 } };
+        Coordinates id = index2coord(src.shape(), src_idx);
+        const int   x  = id.x();
+        const int   y  = id.y();
+
+        for(int j = y - static_cast<int>(border_size.top), index = 0; j <= y + static_cast<int>(border_size.bottom); ++j)
+        {
+            for(int i = x - static_cast<int>(border_size.left); i <= x + static_cast<int>(border_size.right); ++i, ++index)
+            {
+                id.set(0, i);
+                id.set(1, j);
+                filter_elems[index] = tensor_elem_at(src, id, border_mode, constant_border_value);
+            }
+        }
+        std::sort(filter_elems.begin(), filter_elems.end());
+        dst[src_idx] = filter_elems[size_tot_filter / 2];
+    }
+
+    return dst;
+}
+
+template SimpleTensor<uint8_t> median3x3(const SimpleTensor<uint8_t> &src, BorderMode border_mode, uint8_t constant_border_value);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/Median3x3.h b/tests/validation/reference/Median3x3.h
new file mode 100644
index 0000000..8345daa
--- /dev/null
+++ b/tests/validation/reference/Median3x3.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_MEDIAN3X3_H__
+#define __ARM_COMPUTE_TEST_MEDIAN3X3_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> median3x3(const SimpleTensor<T> &src, BorderMode border_mode, T constant_border_value);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_MEDIAN3X3_H__ */
diff --git a/tests/validation/reference/MinMaxLocation.cpp b/tests/validation/reference/MinMaxLocation.cpp
new file mode 100644
index 0000000..427adeb
--- /dev/null
+++ b/tests/validation/reference/MinMaxLocation.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal src the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included src all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. src NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER src AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR src CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "MinMaxLocation.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+void compute_min_max(const SimpleTensor<T> &src, T &min, T &max)
+{
+    // Set min and max to first pixel
+    min = src[0];
+    max = src[0];
+
+    ARM_COMPUTE_ERROR_ON(src.num_elements() == 0);
+
+    // Look for min and max values
+    for(int i = 1; i < src.num_elements(); ++i)
+    {
+        if(src[i] < min)
+        {
+            min = src[i];
+        }
+        if(src[i] > max)
+        {
+            max = src[i];
+        }
+    }
+}
+
+template <typename T>
+MinMaxLocationValues<T> min_max_location(const SimpleTensor<T> &src)
+{
+    MinMaxLocationValues<T> dst;
+
+    const size_t width = src.shape().x();
+
+    compute_min_max<T>(src, dst.min, dst.max);
+
+    Coordinates2D coord{ 0, 0 };
+
+    for(int i = 0; i < src.num_elements(); ++i)
+    {
+        coord.x = static_cast<int32_t>(i % width);
+        coord.y = static_cast<int32_t>(i / width);
+
+        if(src[i] == dst.min)
+        {
+            dst.min_loc.push_back(coord);
+        }
+        if(src[i] == dst.max)
+        {
+            dst.max_loc.push_back(coord);
+        }
+    }
+
+    return dst;
+}
+
+template MinMaxLocationValues<uint8_t> min_max_location(const SimpleTensor<uint8_t> &src);
+template MinMaxLocationValues<int16_t> min_max_location(const SimpleTensor<int16_t> &src);
+template MinMaxLocationValues<float> min_max_location(const SimpleTensor<float> &src);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/MinMaxLocation.h b/tests/validation/reference/MinMaxLocation.h
new file mode 100644
index 0000000..ebaf90b
--- /dev/null
+++ b/tests/validation/reference/MinMaxLocation.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_MIN_MAX_LOCATION_H__
+#define __ARM_COMPUTE_TEST_MIN_MAX_LOCATION_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/Types.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+MinMaxLocationValues<T> min_max_location(const SimpleTensor<T> &src);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_MIN_MAX_LOCATION_H__ */
diff --git a/tests/validation/reference/NonLinearFilter.cpp b/tests/validation/reference/NonLinearFilter.cpp
new file mode 100644
index 0000000..8669c9c
--- /dev/null
+++ b/tests/validation/reference/NonLinearFilter.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal src the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included src all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. src NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER src AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * dst OF OR src CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "NonLinearFilter.h"
+#include "Utils.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> non_linear_filter(const SimpleTensor<T> &src, NonLinearFilterFunction function, unsigned int mask_size, MatrixPattern pattern, const uint8_t *mask, BorderMode border_mode,
+                                  uint8_t constant_border_value)
+{
+    SimpleTensor<T> dst(src.shape(), src.data_type());
+
+    ARM_COMPUTE_ERROR_ON(pattern == MatrixPattern::OTHER && mask == nullptr);
+    ARM_COMPUTE_UNUSED(pattern);
+
+    using intermediate_type = typename common_promoted_signed_type<T>::intermediate_type;
+
+    const int                      sq_mask_size   = mask_size * mask_size;
+    const int                      half_mask_size = mask_size / 2;
+    std::vector<intermediate_type> vals(sq_mask_size);
+    intermediate_type              current_value = 0;
+
+    const ValidRegion valid_region = shape_to_valid_region(src.shape(), border_mode == BorderMode::UNDEFINED, BorderSize(half_mask_size));
+
+    for(int element_idx = 0, count = 0, index = 0; element_idx < src.num_elements(); ++element_idx, count = 0, index = 0)
+    {
+        Coordinates id = index2coord(src.shape(), element_idx);
+        if(is_in_valid_region(valid_region, id))
+        {
+            int idx = id.x();
+            int idy = id.y();
+            for(int y = idy - half_mask_size; y <= idy + half_mask_size; ++y)
+            {
+                for(int x = idx - half_mask_size; x <= idx + half_mask_size; ++x, ++index)
+                {
+                    id.set(0, x);
+                    id.set(1, y);
+                    current_value = tensor_elem_at(src, id, border_mode, constant_border_value);
+
+                    if(mask[index] == 255)
+                    {
+                        vals[count] = static_cast<intermediate_type>(current_value);
+                        ++count;
+                    }
+                }
+            }
+            std::sort(vals.begin(), vals.begin() + count);
+
+            ARM_COMPUTE_ERROR_ON(count == 0);
+
+            switch(function)
+            {
+                case NonLinearFilterFunction::MIN:
+                    dst[element_idx] = saturate_cast<T>(vals[0]);
+                    break;
+                case NonLinearFilterFunction::MAX:
+                    dst[element_idx] = saturate_cast<T>(vals[count - 1]);
+                    break;
+                case NonLinearFilterFunction::MEDIAN:
+                    dst[element_idx] = saturate_cast<T>(vals[count / 2]);
+                    break;
+                default:
+                    ARM_COMPUTE_ERROR("Unsupported NonLinearFilter function.");
+            }
+        }
+    }
+
+    return dst;
+}
+
+template SimpleTensor<uint8_t> non_linear_filter(const SimpleTensor<uint8_t> &src, NonLinearFilterFunction function, unsigned int mask_size, MatrixPattern pattern, const uint8_t *mask,
+                                                 BorderMode border_mode, uint8_t constant_border_value);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/NonLinearFilter.h b/tests/validation/reference/NonLinearFilter.h
new file mode 100644
index 0000000..1df47c8
--- /dev/null
+++ b/tests/validation/reference/NonLinearFilter.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_BITWISE_NOT_H__
+#define __ARM_COMPUTE_TEST_BITWISE_NOT_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> non_linear_filter(const SimpleTensor<T> &src, NonLinearFilterFunction function, unsigned int mask_size, MatrixPattern pattern, const uint8_t *mask, BorderMode border_mode,
+                                  uint8_t constant_border_value);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_BITWISE_NOT_H__ */
diff --git a/tests/validation/reference/NonMaximaSuppression.cpp b/tests/validation/reference/NonMaximaSuppression.cpp
new file mode 100644
index 0000000..eab5cec
--- /dev/null
+++ b/tests/validation/reference/NonMaximaSuppression.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "NonMaximaSuppression.h"
+
+#include "Utils.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> non_maxima_suppression(const SimpleTensor<T> &src, BorderMode border_mode, T constant_border_value)
+{
+    constexpr int   block_size = 3;
+    SimpleTensor<T> dst(src.shape(), src.data_type(), src.num_channels());
+    ValidRegion     valid_region = shape_to_valid_region(src.shape(), border_mode == BorderMode::UNDEFINED, BorderSize(block_size / 2));
+
+    for(int i = 0; i < src.num_elements(); ++i)
+    {
+        Coordinates coord = index2coord(src.shape(), i);
+        int         x     = coord.x();
+        int         y     = coord.y();
+
+        if(!is_in_valid_region(valid_region, coord))
+        {
+            continue;
+        }
+
+        if(src[i] >= tensor_elem_at(src, Coordinates(x - 1, y - 1), border_mode, constant_border_value) && src[i] >= tensor_elem_at(src, Coordinates(x, y - 1), border_mode, constant_border_value)
+           && src[i] >= tensor_elem_at(src, Coordinates(x + 1, y - 1), border_mode, constant_border_value) && src[i] >= tensor_elem_at(src, Coordinates(x - 1, y), border_mode, constant_border_value)
+           && src[i] > tensor_elem_at(src, Coordinates(x + 1, y), border_mode, constant_border_value) && src[i] > tensor_elem_at(src, Coordinates(x - 1, y + 1), border_mode, constant_border_value)
+           && src[i] > tensor_elem_at(src, Coordinates(x, y + 1), border_mode, constant_border_value) && src[i] > tensor_elem_at(src, Coordinates(x + 1, y + 1), border_mode, constant_border_value))
+        {
+            dst[i] = src[i];
+        }
+        else
+        {
+            dst[i] = T(0);
+        }
+    }
+
+    return dst;
+}
+
+template SimpleTensor<float> non_maxima_suppression(const SimpleTensor<float> &src, BorderMode border_mode, float constant_border_value);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/NonMaximaSuppression.h b/tests/validation/reference/NonMaximaSuppression.h
new file mode 100644
index 0000000..2086abf
--- /dev/null
+++ b/tests/validation/reference/NonMaximaSuppression.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_NON_MAXIMA_SUPPRESSION_H__
+#define __ARM_COMPUTE_TEST_NON_MAXIMA_SUPPRESSION_H__
+
+#include "arm_compute/core/Types.h"
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> non_maxima_suppression(const SimpleTensor<T> &src, BorderMode border_mode, T constant_border_value = 0);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_NON_MAXIMA_SUPPRESSION_H__ */
diff --git a/tests/validation/reference/NormalizationLayer.cpp b/tests/validation/reference/NormalizationLayer.cpp
new file mode 100644
index 0000000..226af96
--- /dev/null
+++ b/tests/validation/reference/NormalizationLayer.cpp
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "NormalizationLayer.h"
+
+#include "arm_compute/core/Types.h"
+#include "tests/validation/FixedPoint.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type>
+SimpleTensor<T> normalization_layer(const SimpleTensor<T> &src, NormalizationLayerInfo info)
+{
+    // Create reference
+    SimpleTensor<T> dst{ src.shape(), src.data_type(), 1, src.fixed_point_position() };
+
+    // Compute reference
+    const uint32_t norm_size = info.norm_size();
+    NormType       type      = info.type();
+    float          beta      = info.beta();
+    uint32_t       kappa     = info.kappa();
+
+    const int cols       = src.shape()[0];
+    const int rows       = src.shape()[1];
+    const int depth      = src.shape()[2];
+    int       upper_dims = src.shape().total_size() / (cols * rows);
+
+    float coeff       = info.scale_coeff();
+    int   radius_cols = norm_size / 2;
+
+    // IN_MAP_1D and CROSS_MAP normalize over a single axis only
+    int radius_rows = (NormType::IN_MAP_2D == type) ? norm_size / 2 : 0;
+
+    if(type == NormType::CROSS_MAP)
+    {
+        // Remove also depth from upper dimensions since it is the dimension we
+        // want to use for normalization
+        upper_dims /= depth;
+
+        for(int r = 0; r < upper_dims; ++r)
+        {
+            for(int i = 0; i < rows; ++i)
+            {
+                for(int k = 0; k < cols; ++k)
+                {
+                    for(int l = 0; l < depth; ++l)
+                    {
+                        float accumulated_scale = 0.f;
+
+                        for(int j = -radius_cols; j <= radius_cols; ++j)
+                        {
+                            const int z = l + j;
+
+                            if(z >= 0 && z < depth)
+                            {
+                                const T value = src[k + i * cols + z * rows * cols + r * cols * rows * depth];
+                                accumulated_scale += value * value;
+                            }
+                        }
+
+                        dst[k + i * cols + l * rows * cols + r * cols * rows * depth] = kappa + accumulated_scale * coeff;
+                    }
+                }
+            }
+        }
+    }
+    else
+    {
+        for(int r = 0; r < upper_dims; ++r)
+        {
+            for(int i = 0; i < rows; ++i)
+            {
+                for(int k = 0; k < cols; ++k)
+                {
+                    float accumulated_scale = 0.f;
+
+                    for(int j = -radius_rows; j <= radius_rows; ++j)
+                    {
+                        const int y = i + j;
+                        for(int l = -radius_cols; l <= radius_cols; ++l)
+                        {
+                            const int x = k + l;
+
+                            if((x >= 0 && y >= 0) && (x < cols && y < rows))
+                            {
+                                const T value = src[x + y * cols + r * cols * rows];
+                                accumulated_scale += value * value;
+                            }
+                        }
+                    }
+
+                    dst[k + i * cols + r * cols * rows] = kappa + accumulated_scale * coeff;
+                }
+            }
+        }
+    }
+
+    if(beta == 1.f)
+    {
+        for(int i = 0; i < dst.num_elements(); ++i)
+        {
+            dst[i] = src[i] / dst[i];
+        }
+    }
+    else if(beta == 0.5f)
+    {
+        for(int i = 0; i < dst.num_elements(); ++i)
+        {
+            dst[i] = src[i] / std::sqrt(dst[i]);
+        }
+    }
+    else
+    {
+        for(int i = 0; i < dst.num_elements(); ++i)
+        {
+            dst[i] = src[i] * std::exp(std::log(dst[i]) * -beta);
+        }
+    }
+
+    return dst;
+}
+
+template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type>
+SimpleTensor<T> normalization_layer(const SimpleTensor<T> &src, NormalizationLayerInfo info)
+{
+    using namespace fixed_point_arithmetic;
+
+    // Create reference
+    SimpleTensor<T> dst{ src.shape(), src.data_type(), 1, src.fixed_point_position() };
+
+    // Compute reference
+    const int fixed_point_position = src.fixed_point_position();
+
+    const uint32_t norm_size = info.norm_size();
+    NormType       type      = info.type();
+    fixed_point<T> beta(info.beta(), fixed_point_position);
+    fixed_point<T> kappa(info.kappa(), fixed_point_position);
+
+    const int cols       = src.shape()[0];
+    const int rows       = src.shape()[1];
+    const int depth      = src.shape()[2];
+    int       upper_dims = src.shape().total_size() / (cols * rows);
+
+    fixed_point<T> coeff(info.scale_coeff(), fixed_point_position);
+    int            radius_cols = norm_size / 2;
+
+    // IN_MAP_1D and CROSS_MAP normalize over a single axis only
+    int radius_rows = (NormType::IN_MAP_2D == type) ? norm_size / 2 : 0;
+
+    if(type == NormType::CROSS_MAP)
+    {
+        // Remove also depth from upper dimensions since it is the dimension we
+        // want to use for normalization
+        upper_dims /= depth;
+
+        for(int r = 0; r < upper_dims; ++r)
+        {
+            for(int i = 0; i < rows; ++i)
+            {
+                for(int k = 0; k < cols; ++k)
+                {
+                    for(int l = 0; l < depth; ++l)
+                    {
+                        fixed_point<T> accumulated_scale(0.f, fixed_point_position);
+
+                        for(int j = -radius_cols; j <= radius_cols; ++j)
+                        {
+                            const int z = l + j;
+
+                            if(z >= 0 && z < depth)
+                            {
+                                const T              value = src[k + i * cols + z * rows * cols + r * cols * rows * depth];
+                                const fixed_point<T> fp_value(value, fixed_point_position, true);
+                                accumulated_scale = add(accumulated_scale, mul(fp_value, fp_value));
+                            }
+                        }
+
+                        accumulated_scale                                             = add(kappa, mul(accumulated_scale, coeff));
+                        dst[k + i * cols + l * rows * cols + r * cols * rows * depth] = accumulated_scale.raw();
+                    }
+                }
+            }
+        }
+    }
+    else
+    {
+        for(int r = 0; r < upper_dims; ++r)
+        {
+            for(int i = 0; i < rows; ++i)
+            {
+                for(int k = 0; k < cols; ++k)
+                {
+                    fixed_point<T> accumulated_scale(0.f, fixed_point_position);
+
+                    for(int j = -radius_rows; j <= radius_rows; ++j)
+                    {
+                        const int y = i + j;
+
+                        for(int l = -radius_cols; l <= radius_cols; ++l)
+                        {
+                            const int x = k + l;
+
+                            if((x >= 0 && y >= 0) && (x < cols && y < rows))
+                            {
+                                const T              value = src[x + y * cols + r * cols * rows];
+                                const fixed_point<T> fp_value(value, fixed_point_position, true);
+                                accumulated_scale = add(accumulated_scale, mul(fp_value, fp_value));
+                            }
+                        }
+                    }
+
+                    accumulated_scale                   = add(kappa, mul(accumulated_scale, coeff));
+                    dst[k + i * cols + r * cols * rows] = accumulated_scale.raw();
+                }
+            }
+        }
+    }
+
+    if(info.beta() == 1.f)
+    {
+        for(int i = 0; i < dst.num_elements(); ++i)
+        {
+            fixed_point<T> res = div(fixed_point<T>(src[i], fixed_point_position, true), fixed_point<T>(dst[i], fixed_point_position, true));
+            dst[i]             = res.raw();
+        }
+    }
+    else
+    {
+        const fixed_point<T> beta(info.beta(), fixed_point_position);
+
+        for(int i = 0; i < dst.num_elements(); ++i)
+        {
+            fixed_point<T> res = pow(fixed_point<T>(dst[i], fixed_point_position, true), beta);
+            res                = div(fixed_point<T>(src[i], fixed_point_position, true), res);
+            dst[i]             = res.raw();
+        }
+    }
+
+    return dst;
+}
+
+template SimpleTensor<float> normalization_layer(const SimpleTensor<float> &src, NormalizationLayerInfo info);
+template SimpleTensor<half> normalization_layer(const SimpleTensor<half> &src, NormalizationLayerInfo info);
+template SimpleTensor<qint8_t> normalization_layer(const SimpleTensor<qint8_t> &src, NormalizationLayerInfo info);
+template SimpleTensor<qint16_t> normalization_layer(const SimpleTensor<qint16_t> &src, NormalizationLayerInfo info);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/NormalizationLayer.h b/tests/validation/reference/NormalizationLayer.h
new file mode 100644
index 0000000..3f624ff
--- /dev/null
+++ b/tests/validation/reference/NormalizationLayer.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_NORMALIZATION_LAYER_H__
+#define __ARM_COMPUTE_TEST_NORMALIZATION_LAYER_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type = 0>
+SimpleTensor<T> normalization_layer(const SimpleTensor<T> &src, NormalizationLayerInfo info);
+
+template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
+SimpleTensor<T> normalization_layer(const SimpleTensor<T> &src, NormalizationLayerInfo info);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_NORMALIZATION_LAYER_H__ */
diff --git a/tests/validation/reference/Phase.cpp b/tests/validation/reference/Phase.cpp
new file mode 100644
index 0000000..7827cd2
--- /dev/null
+++ b/tests/validation/reference/Phase.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "Phase.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<uint8_t> phase(const SimpleTensor<T> &gx, const SimpleTensor<T> &gy, PhaseType phase_type)
+{
+    const float           PI = std::atan(1) * 4;
+    SimpleTensor<uint8_t> phase(gx.shape(), DataType::U8);
+
+    if(phase_type == PhaseType::UNSIGNED) // unsigned: map to [0-255)
+    {
+        for(int i = 0; i < gx.num_elements(); ++i)
+        {
+            float angle_deg = (std::atan2(float(gy[i]), float(gx[i])) / PI) * 180.0f;
+            phase[i]        = (angle_deg < 0.0f) ? 180.f + angle_deg : angle_deg;
+        }
+    }
+    else // signed: map to [0-180) degrees
+    {
+        for(int i = 0; i < gx.num_elements(); ++i)
+        {
+            float angle_pi = std::atan2(gy[i], gx[i]) / PI;
+            angle_pi       = (angle_pi < 0.0f) ? 2 + angle_pi : angle_pi;
+            phase[i]       = lround(angle_pi * 128) & 0xFFu;
+        }
+    }
+
+    return phase;
+}
+
+template SimpleTensor<uint8_t> phase(const SimpleTensor<int16_t> &gx, const SimpleTensor<int16_t> &gy, PhaseType phase_type);
+template SimpleTensor<uint8_t> phase(const SimpleTensor<int32_t> &gx, const SimpleTensor<int32_t> &gy, PhaseType phase_type);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/Phase.h b/tests/validation/reference/Phase.h
new file mode 100644
index 0000000..d322d53
--- /dev/null
+++ b/tests/validation/reference/Phase.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_PHASE_H__
+#define __ARM_COMPUTE_TEST_PHASE_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<uint8_t> phase(const SimpleTensor<T> &gx, const SimpleTensor<T> &gy, PhaseType phase_type);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_PHASE_H__ */
diff --git a/tests/validation/reference/PixelWiseMultiplication.cpp b/tests/validation/reference/PixelWiseMultiplication.cpp
new file mode 100644
index 0000000..b3647fc
--- /dev/null
+++ b/tests/validation/reference/PixelWiseMultiplication.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * dst OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "PixelWiseMultiplication.h"
+
+#include "tests/validation/FixedPoint.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <class T>
+struct is_floating_point
+    : std::integral_constant < bool,
+      std::is_same<float, typename std::remove_cv<T>::type>::value || std::is_same<half_float::half, typename std::remove_cv<T>::type>::value
+      || std::is_same<double, typename std::remove_cv<T>::type>::value || std::is_same<long double, typename std::remove_cv<T>::type>::value >
+{
+};
+
+template <typename T1, typename T2>
+SimpleTensor<T2> pixel_wise_multiplication(const SimpleTensor<T1> &src1, const SimpleTensor<T2> &src2, float scale, ConvertPolicy convert_policy, RoundingPolicy rounding_policy)
+{
+    SimpleTensor<T2> dst(src2.shape(), src2.data_type());
+
+    if(scale < 0)
+    {
+        ARM_COMPUTE_ERROR("Scale of pixel-wise multiplication must be non-negative");
+    }
+
+    using intermediate_type = typename common_promoted_signed_type<T1, T2, T2>::intermediate_type;
+
+    for(int i = 0; i < src1.num_elements(); ++i)
+    {
+        double val = static_cast<intermediate_type>(src1[i]) * static_cast<intermediate_type>(src2[i]) * static_cast<double>(scale);
+        if(is_floating_point<T2>::value)
+        {
+            dst[i] = val;
+        }
+        else
+        {
+            double rounded_val = 0;
+            switch(rounding_policy)
+            {
+                case(RoundingPolicy::TO_ZERO):
+                    rounded_val = support::cpp11::trunc(val);
+                    break;
+                case(RoundingPolicy::TO_NEAREST_UP):
+                    rounded_val = round_half_up(val);
+                    break;
+                case(RoundingPolicy::TO_NEAREST_EVEN):
+                    rounded_val = round_half_even(val);
+                    break;
+                default:
+                    ARM_COMPUTE_ERROR("Unsupported rounding policy");
+            }
+
+            dst[i] = (convert_policy == ConvertPolicy::SATURATE) ? saturate_cast<T2>(rounded_val) : static_cast<T2>(rounded_val);
+        }
+    }
+
+    return dst;
+}
+
+// *INDENT-OFF*
+// clang-format off
+template SimpleTensor<uint8_t> pixel_wise_multiplication(const SimpleTensor<uint8_t> &src1, const SimpleTensor<uint8_t> &src2, float scale, ConvertPolicy convert_policy, RoundingPolicy rounding_policy);
+template SimpleTensor<int16_t> pixel_wise_multiplication(const SimpleTensor<uint8_t> &src1, const SimpleTensor<int16_t> &src2, float scale, ConvertPolicy convert_policy, RoundingPolicy rounding_policy);
+template SimpleTensor<int16_t> pixel_wise_multiplication(const SimpleTensor<int16_t> &src1, const SimpleTensor<int16_t> &src2, float scale, ConvertPolicy convert_policy, RoundingPolicy rounding_policy);
+template SimpleTensor<float> pixel_wise_multiplication(const SimpleTensor<float> &src1, const SimpleTensor<float> &src2, float scale, ConvertPolicy convert_policy, RoundingPolicy rounding_policy);
+template SimpleTensor<half_float::half> pixel_wise_multiplication(const SimpleTensor<half_float::half> &src1, const SimpleTensor<half_float::half> &src2, float scale, ConvertPolicy convert_policy, RoundingPolicy rounding_policy);
+// clang-format on
+// *INDENT-ON*
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/PixelWiseMultiplication.h b/tests/validation/reference/PixelWiseMultiplication.h
new file mode 100644
index 0000000..1dce154
--- /dev/null
+++ b/tests/validation/reference/PixelWiseMultiplication.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_PIXEL_WISE_MULTIPLICATION_H__
+#define __ARM_COMPUTE_TEST_PIXEL_WISE_MULTIPLICATION_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T1, typename T2>
+SimpleTensor<T2> pixel_wise_multiplication(const SimpleTensor<T1> &src1, const SimpleTensor<T2> &src2, float scale, ConvertPolicy convert_policy, RoundingPolicy rounding_policy);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_PIXEL_WISE_MULTIPLICATION_H__ */
diff --git a/tests/validation/reference/PoolingLayer.cpp b/tests/validation/reference/PoolingLayer.cpp
new file mode 100644
index 0000000..1a7dd4c
--- /dev/null
+++ b/tests/validation/reference/PoolingLayer.cpp
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "PoolingLayer.h"
+
+#include "arm_compute/core/Types.h"
+#include "tests/validation/FixedPoint.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+namespace
+{
+TensorShape calculate_output_shape(TensorShape shape, PoolingLayerInfo info)
+{
+    TensorShape dst_shape = shape;
+    const int   pool_size = info.is_global_pooling() ? shape.x() : info.pool_size();
+    const std::pair<unsigned int, unsigned int> scaled_dims = arm_compute::scaled_dimensions(shape.x(),
+                                                                                             shape.y(),
+                                                                                             pool_size,
+                                                                                             pool_size,
+                                                                                             info.pad_stride_info());
+    dst_shape.set(0, scaled_dims.first);
+    dst_shape.set(1, scaled_dims.second);
+
+    return dst_shape;
+}
+} // namespace
+
+template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type>
+SimpleTensor<T> pooling_layer(const SimpleTensor<T> &src, PoolingLayerInfo info)
+{
+    ARM_COMPUTE_ERROR_ON(info.is_global_pooling() && (src.shape().x() != src.shape().y()));
+
+    const int   pool_size       = info.is_global_pooling() ? src.shape().x() : info.pool_size();
+    PoolingType type            = info.pool_type();
+    int         pool_stride_x   = info.pad_stride_info().stride().first;
+    int         pool_stride_y   = info.pad_stride_info().stride().second;
+    int         pad_x           = info.pad_stride_info().pad().first;
+    int         pad_y           = info.pad_stride_info().pad().second;
+    bool        exclude_padding = info.exclude_padding();
+
+    const auto w_src      = static_cast<int>(src.shape()[0]);
+    const auto h_src      = static_cast<int>(src.shape()[1]);
+    const int  upper_dims = src.shape().total_size() / (w_src * h_src);
+
+    // Create reference
+    SimpleTensor<T> dst{ calculate_output_shape(src.shape(), info), src.data_type(), 1, src.fixed_point_position() };
+
+    const auto w_dst = static_cast<int>(dst.shape()[0]);
+    const auto h_dst = static_cast<int>(dst.shape()[1]);
+
+    if(type == PoolingType::MAX)
+    {
+        for(int r = 0; r < upper_dims; ++r)
+        {
+            for(int h = 0; h < h_dst; ++h)
+            {
+                for(int w = 0; w < w_dst; ++w)
+                {
+                    int wstart = w * pool_stride_x - pad_x;
+                    int hstart = h * pool_stride_y - pad_y;
+                    int wend   = std::min(wstart + pool_size, w_src);
+                    int hend   = std::min(hstart + pool_size, h_src);
+                    wstart     = std::max(wstart, 0);
+                    hstart     = std::max(hstart, 0);
+
+                    T max_val = std::numeric_limits<T>::lowest();
+                    for(int y = hstart; y < hend; ++y)
+                    {
+                        for(int x = wstart; x < wend; ++x)
+                        {
+                            const T val = src[r * h_src * w_src + y * w_src + x];
+                            if(val > max_val)
+                            {
+                                max_val = val;
+                            }
+                        }
+                    }
+
+                    dst[r * h_dst * w_dst + h * w_dst + w] = max_val;
+                }
+            }
+        }
+    }
+    else // Average or l2 pooling
+    {
+        for(int r = 0; r < upper_dims; ++r)
+        {
+            for(int h = 0; h < h_dst; ++h)
+            {
+                for(int w = 0; w < w_dst; ++w)
+                {
+                    T   avg_val(0);
+                    int wstart = w * pool_stride_x - pad_x;
+                    int hstart = h * pool_stride_y - pad_y;
+                    int wend   = std::min(wstart + pool_size, w_src + pad_x);
+                    int hend   = std::min(hstart + pool_size, h_src + pad_y);
+                    int pool   = (hend - hstart) * (wend - wstart);
+                    wstart     = std::max(wstart, 0);
+                    hstart     = std::max(hstart, 0);
+                    wend       = std::min(wend, w_src);
+                    hend       = std::min(hend, h_src);
+                    // Exclude padding pixels from the average
+                    if(exclude_padding)
+                    {
+                        pool = (hend - hstart) * (wend - wstart);
+                    }
+
+                    if(type == PoolingType::AVG)
+                    {
+                        for(int y = hstart; y < hend; ++y)
+                        {
+                            for(int x = wstart; x < wend; ++x)
+                            {
+                                avg_val += src[r * h_src * w_src + y * w_src + x];
+                            }
+                        }
+                        dst[r * h_dst * w_dst + h * w_dst + w] = avg_val / pool;
+                    }
+                    else
+                    {
+                        for(int y = hstart; y < hend; ++y)
+                        {
+                            for(int x = wstart; x < wend; ++x)
+                            {
+                                const T val = src[r * h_src * w_src + y * w_src + x];
+                                avg_val += val * val;
+                            }
+                        }
+                        dst[r * h_dst * w_dst + h * w_dst + w] = std::sqrt(avg_val / pool);
+                    }
+                }
+            }
+        }
+    }
+
+    return dst;
+}
+
+template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type>
+SimpleTensor<T> pooling_layer(const SimpleTensor<T> &src, PoolingLayerInfo info)
+{
+    ARM_COMPUTE_ERROR_ON(info.is_global_pooling() && (src.shape().x() != src.shape().y()));
+
+    const int   pool_size       = info.is_global_pooling() ? src.shape().x() : info.pool_size();
+    PoolingType type            = info.pool_type();
+    int         pool_stride_x   = info.pad_stride_info().stride().first;
+    int         pool_stride_y   = info.pad_stride_info().stride().second;
+    int         pad_x           = info.pad_stride_info().pad().first;
+    int         pad_y           = info.pad_stride_info().pad().second;
+    bool        exclude_padding = info.exclude_padding();
+
+    const auto w_src      = static_cast<int>(src.shape()[0]);
+    const auto h_src      = static_cast<int>(src.shape()[1]);
+    const int  upper_dims = src.shape().total_size() / (w_src * h_src);
+
+    // Create reference
+    SimpleTensor<T> dst{ calculate_output_shape(src.shape(), info), src.data_type(), 1, src.fixed_point_position() };
+
+    const auto w_dst = static_cast<int>(dst.shape()[0]);
+    const auto h_dst = static_cast<int>(dst.shape()[1]);
+
+    if(type == PoolingType::MAX)
+    {
+        for(int r = 0; r < upper_dims; ++r)
+        {
+            for(int h = 0; h < h_dst; ++h)
+            {
+                for(int w = 0; w < w_dst; ++w)
+                {
+                    int wstart = w * pool_stride_x - pad_x;
+                    int hstart = h * pool_stride_y - pad_y;
+                    int wend   = std::min(wstart + pool_size, w_src);
+                    int hend   = std::min(hstart + pool_size, h_src);
+                    wstart     = std::max(wstart, 0);
+                    hstart     = std::max(hstart, 0);
+
+                    T max_val = std::numeric_limits<T>::lowest();
+                    for(int y = hstart; y < hend; ++y)
+                    {
+                        for(int x = wstart; x < wend; ++x)
+                        {
+                            const T val = src[r * h_src * w_src + y * w_src + x];
+                            if(val > max_val)
+                            {
+                                max_val = val;
+                            }
+                        }
+                    }
+
+                    dst[r * h_dst * w_dst + h * w_dst + w] = max_val;
+                }
+            }
+        }
+    }
+    else // Average or l2 pooling
+    {
+        for(int r = 0; r < upper_dims; ++r)
+        {
+            for(int h = 0; h < h_dst; ++h)
+            {
+                for(int w = 0; w < w_dst; ++w)
+                {
+                    int wstart = w * pool_stride_x - pad_x;
+                    int hstart = h * pool_stride_y - pad_y;
+                    int wend   = std::min(wstart + pool_size, w_src + pad_x);
+                    int hend   = std::min(hstart + pool_size, h_src + pad_y);
+                    int pool   = (hend - hstart) * (wend - wstart);
+                    wstart     = std::max(wstart, 0);
+                    hstart     = std::max(hstart, 0);
+                    wend       = std::min(wend, w_src);
+                    hend       = std::min(hend, h_src);
+                    // Exclude padding pixels from the average
+                    if(exclude_padding)
+                    {
+                        pool = (hend - hstart) * (wend - wstart);
+                    }
+
+                    using namespace fixed_point_arithmetic;
+
+                    const int            fixed_point_position = src.fixed_point_position();
+                    const fixed_point<T> const_1(1, fixed_point_position);
+                    const fixed_point<T> invpool_fp(1.f / static_cast<float>(pool), fixed_point_position);
+                    fixed_point<T>       avg_val(0, fixed_point_position, true);
+
+                    if(type == PoolingType::AVG)
+                    {
+                        for(int y = hstart; y < hend; ++y)
+                        {
+                            for(int x = wstart; x < wend; ++x)
+                            {
+                                const fixed_point<T> in_fp(src[r * h_src * w_src + y * w_src + x], fixed_point_position, true);
+                                avg_val = add(avg_val, in_fp);
+                            }
+                        }
+                        dst[r * h_dst * w_dst + h * w_dst + w] = mul(avg_val, invpool_fp).raw();
+                    }
+                    else
+                    {
+                        for(int y = hstart; y < hend; ++y)
+                        {
+                            for(int x = wstart; x < wend; ++x)
+                            {
+                                const fixed_point<T> in_fp(src[r * h_src * w_src + y * w_src + x], fixed_point_position, true);
+                                avg_val = add(avg_val, mul(in_fp, in_fp));
+                            }
+                        }
+                        auto res                               = div(const_1, (inv_sqrt(mul(avg_val, invpool_fp))));
+                        dst[r * h_dst * w_dst + h * w_dst + w] = res.raw();
+                    }
+                }
+            }
+        }
+    }
+
+    return dst;
+}
+
+template <>
+SimpleTensor<uint8_t> pooling_layer<uint8_t>(const SimpleTensor<uint8_t> &src, PoolingLayerInfo info)
+{
+    SimpleTensor<float>   src_tmp = convert_from_asymmetric(src);
+    SimpleTensor<float>   dst_tmp = pooling_layer<float>(src_tmp, info);
+    SimpleTensor<uint8_t> dst     = convert_to_asymmetric(dst_tmp, src.quantization_info());
+    return dst;
+}
+
+template SimpleTensor<float> pooling_layer(const SimpleTensor<float> &src, PoolingLayerInfo info);
+template SimpleTensor<half> pooling_layer(const SimpleTensor<half> &src, PoolingLayerInfo info);
+template SimpleTensor<qint8_t> pooling_layer(const SimpleTensor<qint8_t> &src, PoolingLayerInfo info);
+template SimpleTensor<qint16_t> pooling_layer(const SimpleTensor<qint16_t> &src, PoolingLayerInfo info);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/PoolingLayer.h b/tests/validation/reference/PoolingLayer.h
new file mode 100644
index 0000000..334054a
--- /dev/null
+++ b/tests/validation/reference/PoolingLayer.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_POOLING_LAYER_H__
+#define __ARM_COMPUTE_TEST_POOLING_LAYER_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type = 0>
+SimpleTensor<T> pooling_layer(const SimpleTensor<T> &src, PoolingLayerInfo info);
+
+template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
+SimpleTensor<T> pooling_layer(const SimpleTensor<T> &src, PoolingLayerInfo info);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_POOLING_LAYER_H__ */
diff --git a/tests/validation/reference/QuantizationLayer.cpp b/tests/validation/reference/QuantizationLayer.cpp
new file mode 100644
index 0000000..d7ce490
--- /dev/null
+++ b/tests/validation/reference/QuantizationLayer.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "QuantizationLayer.h"
+
+#include <cmath>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type>
+SimpleTensor<uint8_t> quantization_layer(const SimpleTensor<T> &src)
+{
+    // Create reference
+    SimpleTensor<uint8_t> dst{ src.shape(), DataType::U8 };
+
+    const int width       = src.shape().x();
+    const int height      = src.shape().y();
+    const int depth       = src.shape().z();
+    const int stride_w    = width * height * depth;
+    const int num_batches = src.shape().total_size_upper(3);
+
+    for(int k = 0; k < num_batches; ++k)
+    {
+        // Compute min and max of the 3D tensor
+        float min = src[k * stride_w];
+        float max = src[k * stride_w];
+
+        // Look for min and max values
+        for(int i = 1; i < stride_w; ++i)
+        {
+            float val = src[i + k * stride_w];
+            min       = std::min(min, val);
+            max       = std::max(max, val);
+        }
+
+        // Saturate the result in case min = max
+        if(min == max)
+        {
+            min = 0.0f;
+            max = 1.0f;
+        }
+
+        const float range = max - min;
+
+        for(int i = 0; i < stride_w; ++i)
+        {
+            // map values to range [0.0, 1.0]
+            float       val        = src[i + k * stride_w];
+            const float normalized = (val - min) / range;
+            dst[i + k * stride_w]  = static_cast<uint8_t>(std::min(255.0f, normalized * 256.0f));
+        }
+    }
+
+    return dst;
+}
+
+template SimpleTensor<uint8_t> quantization_layer(const SimpleTensor<float> &src);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/QuantizationLayer.h b/tests/validation/reference/QuantizationLayer.h
new file mode 100644
index 0000000..7c5572c
--- /dev/null
+++ b/tests/validation/reference/QuantizationLayer.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_QUANTIZATION_LAYER_H__
+#define __ARM_COMPUTE_TEST_QUANTIZATION_LAYER_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type = 0>
+SimpleTensor<uint8_t> quantization_layer(const SimpleTensor<T> &src);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_QUANTIZATION_LAYER_H__ */
diff --git a/tests/validation/reference/ReductionOperation.cpp b/tests/validation/reference/ReductionOperation.cpp
new file mode 100644
index 0000000..acfcc09
--- /dev/null
+++ b/tests/validation/reference/ReductionOperation.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "ReductionOperation.h"
+
+#include "tests/validation/Helpers.h"
+
+#include <algorithm>
+#include <cmath>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+namespace
+{
+template <typename T>
+struct square
+{
+    T operator()(const T &lhs, const T &rhs) const
+    {
+        return (lhs + rhs * rhs);
+    }
+};
+
+template <typename T>
+T reduce_operation(T *ptr, int reduce_elements, ReductionOperation op)
+{
+    switch(op)
+    {
+        case ReductionOperation::SUM_SQUARE:
+            return std::accumulate(ptr, ptr + reduce_elements, 0.f, square<T>());
+        default:
+            ARM_COMPUTE_ERROR("Unsupported reduction operation");
+    }
+}
+} // namespace
+
+template <typename T>
+SimpleTensor<T> reduction_operation(const SimpleTensor<T> &src, const TensorShape &dst_shape, unsigned int axis, ReductionOperation op)
+{
+    // Create reference
+    SimpleTensor<T> dst{ dst_shape, src.data_type() };
+
+    // Compute reference
+    const int reduce_elems = src.shape()[axis];
+    const int upper_dims   = src.shape().total_size_upper(axis + 1);
+
+    for(int du = 0; du < upper_dims; ++du)
+    {
+        if(axis == 0)
+        {
+            const T *src_row_ptr = src.data() + du * reduce_elems;
+            dst[du]              = reduce_operation(src_row_ptr, reduce_elems, op);
+        }
+        else
+        {
+            ARM_COMPUTE_ERROR("Unsupported reduction axis");
+        }
+    }
+
+    return dst;
+}
+
+template SimpleTensor<float> reduction_operation(const SimpleTensor<float> &src, const TensorShape &dst_shape, unsigned int axis, ReductionOperation op);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/ReductionOperation.h b/tests/validation/reference/ReductionOperation.h
new file mode 100644
index 0000000..6da6436
--- /dev/null
+++ b/tests/validation/reference/ReductionOperation.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_REDUCTION_OPERATION_H__
+#define __ARM_COMPUTE_TEST_REDUCTION_OPERATION_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> reduction_operation(const SimpleTensor<T> &src, const TensorShape &dst_shape, unsigned int axis, ReductionOperation op);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_FLOOR_H__ */
diff --git a/tests/validation/reference/Remap.cpp b/tests/validation/reference/Remap.cpp
new file mode 100644
index 0000000..bef5962
--- /dev/null
+++ b/tests/validation/reference/Remap.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "Remap.h"
+
+#include "Utils.h"
+#include "tests/validation/Helpers.h"
+
+#include <algorithm>
+#include <array>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> remap(const SimpleTensor<T> &in, SimpleTensor<float> &map_x, SimpleTensor<float> &map_y, SimpleTensor<T> &valid_mask, InterpolationPolicy policy, BorderMode border_mode,
+                      T constant_border_value)
+{
+    ARM_COMPUTE_ERROR_ON_MSG(border_mode == BorderMode::REPLICATE, "BorderMode not supported");
+
+    SimpleTensor<T> out(in.shape(), in.data_type());
+
+    const int width  = in.shape().x();
+    const int height = in.shape().y();
+
+    for(int idx = 0; idx < out.num_elements(); idx++)
+    {
+        valid_mask[idx] = 1;
+        Coordinates src_idx;
+        src_idx.set(0, static_cast<int>(std::floor(map_x[idx])));
+        src_idx.set(1, static_cast<int>(std::floor(map_y[idx])));
+        if((0 <= map_y[idx]) && (map_y[idx] < height) && (0 <= map_x[idx]) && (map_x[idx] < width))
+        {
+            switch(policy)
+            {
+                case InterpolationPolicy::NEAREST_NEIGHBOR:
+                    out[idx] = tensor_elem_at(in, src_idx, border_mode, constant_border_value);
+                    break;
+                case InterpolationPolicy::BILINEAR:
+                    (valid_bilinear_policy(map_x[idx], map_y[idx], width, height, border_mode)) ? out[idx] = bilinear_policy(in, src_idx, map_x[idx], map_y[idx], border_mode, constant_border_value) : valid_mask[idx] = 0;
+                    break;
+                case InterpolationPolicy::AREA:
+                default:
+                    ARM_COMPUTE_ERROR("Interpolation not supported");
+                    break;
+            }
+        }
+        else
+        {
+            if(border_mode == BorderMode::UNDEFINED)
+            {
+                valid_mask[idx] = 0;
+            }
+            else
+            {
+                switch(policy)
+                {
+                    case InterpolationPolicy::NEAREST_NEIGHBOR:
+                        out[idx] = constant_border_value;
+                        break;
+                    case InterpolationPolicy::BILINEAR:
+                        out[idx] = bilinear_policy(in, src_idx, map_x[idx], map_y[idx], border_mode, constant_border_value);
+                        break;
+                    case InterpolationPolicy::AREA:
+                    default:
+                        break;
+                }
+            }
+        }
+    }
+
+    return out;
+}
+
+template SimpleTensor<uint8_t> remap(const SimpleTensor<uint8_t> &src, SimpleTensor<float> &map_x, SimpleTensor<float> &map_y, SimpleTensor<uint8_t> &valid_mask, InterpolationPolicy policy,
+                                     BorderMode border_mode,
+                                     uint8_t    constant_border_value);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/Remap.h b/tests/validation/reference/Remap.h
new file mode 100644
index 0000000..918ba95
--- /dev/null
+++ b/tests/validation/reference/Remap.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_REMAP_H__
+#define __ARM_COMPUTE_TEST_REMAP_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> remap(const SimpleTensor<T> &in, SimpleTensor<float> &map_x, SimpleTensor<float> &map_y, SimpleTensor<T> &valid_mask, InterpolationPolicy policy, BorderMode border_mode,
+                      T constant_border_value = 0);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_REMAP_H__ */
diff --git a/tests/validation/reference/ReshapeLayer.cpp b/tests/validation/reference/ReshapeLayer.cpp
new file mode 100644
index 0000000..42f06e4
--- /dev/null
+++ b/tests/validation/reference/ReshapeLayer.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "ReshapeLayer.h"
+
+#include "arm_compute/core/Types.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> reshape_layer(const SimpleTensor<T> &src, const TensorShape &output_shape)
+{
+    ARM_COMPUTE_ERROR_ON(src.shape().total_size() != output_shape.total_size());
+
+    SimpleTensor<T> dst(output_shape, src.data_type());
+    std::copy_n(src.data(), src.num_elements(), dst.data());
+    return dst;
+}
+
+template SimpleTensor<uint8_t> reshape_layer(const SimpleTensor<uint8_t> &src, const TensorShape &output_shape);
+template SimpleTensor<int8_t> reshape_layer(const SimpleTensor<int8_t> &src, const TensorShape &output_shape);
+template SimpleTensor<uint16_t> reshape_layer(const SimpleTensor<uint16_t> &src, const TensorShape &output_shape);
+template SimpleTensor<int16_t> reshape_layer(const SimpleTensor<int16_t> &src, const TensorShape &output_shape);
+template SimpleTensor<uint32_t> reshape_layer(const SimpleTensor<uint32_t> &src, const TensorShape &output_shape);
+template SimpleTensor<int32_t> reshape_layer(const SimpleTensor<int32_t> &src, const TensorShape &output_shape);
+template SimpleTensor<half> reshape_layer(const SimpleTensor<half> &src, const TensorShape &output_shape);
+template SimpleTensor<float> reshape_layer(const SimpleTensor<float> &src, const TensorShape &output_shape);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/ReshapeLayer.h b/tests/validation/reference/ReshapeLayer.h
new file mode 100644
index 0000000..fc6c716
--- /dev/null
+++ b/tests/validation/reference/ReshapeLayer.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_RESHAPE_LAYER_H__
+#define __ARM_COMPUTE_TEST_RESHAPE_LAYER_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> reshape_layer(const SimpleTensor<T> &src, const TensorShape &output_shape);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_RESHAPE_LAYER_H__ */
diff --git a/tests/validation/reference/Scale.cpp b/tests/validation/reference/Scale.cpp
new file mode 100644
index 0000000..727325f
--- /dev/null
+++ b/tests/validation/reference/Scale.cpp
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "arm_compute/core/Helpers.h"
+
+#include "Scale.h"
+#include "Utils.h"
+#include "support/ToolchainSupport.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> scale(const SimpleTensor<T> &in, float scale_x, float scale_y, InterpolationPolicy policy, BorderMode border_mode, T constant_border_value,
+                      SamplingPolicy sampling_policy, bool ceil_policy_scale)
+{
+    // Add 1 if ceil_policy_scale is true
+    const size_t round_value = ceil_policy_scale ? 1U : 0U;
+    TensorShape  shape_scaled(in.shape());
+    shape_scaled.set(0, (in.shape()[0] + round_value) * scale_x);
+    shape_scaled.set(1, (in.shape()[1] + round_value) * scale_y);
+    SimpleTensor<T> out(shape_scaled, in.data_type());
+
+    // Compute the ratio between source width/height and destination width/height
+    const auto wr = static_cast<float>(in.shape()[0]) / static_cast<float>(out.shape()[0]);
+    const auto hr = static_cast<float>(in.shape()[1]) / static_cast<float>(out.shape()[1]);
+
+    const auto width  = static_cast<int>(in.shape().x());
+    const auto height = static_cast<int>(in.shape().y());
+
+    // Determine border size
+    const int border_size = (border_mode == BorderMode::UNDEFINED) ? 0 : 1;
+
+    // Area interpolation behaves as Nearest Neighbour in case of up-sampling
+    if(policy == InterpolationPolicy::AREA && wr <= 1.f && hr <= 1.f)
+    {
+        policy = InterpolationPolicy::NEAREST_NEIGHBOR;
+    }
+
+    for(int element_idx = 0, count = 0; element_idx < out.num_elements(); ++element_idx, ++count)
+    {
+        Coordinates id    = index2coord(out.shape(), element_idx);
+        int         idx   = id.x();
+        int         idy   = id.y();
+        float       x_src = 0;
+        float       y_src = 0;
+
+        switch(sampling_policy)
+        {
+            case SamplingPolicy::TOP_LEFT:
+                x_src = idx * wr;
+                y_src = idy * hr;
+                break;
+            case SamplingPolicy::CENTER:
+                x_src = (idx + 0.5f) * wr - 0.5f;
+                y_src = (idy + 0.5f) * hr - 0.5f;
+                break;
+            default:
+                ARM_COMPUTE_ERROR("Unsupported sampling policy.");
+                break;
+        }
+
+        switch(policy)
+        {
+            case InterpolationPolicy::NEAREST_NEIGHBOR:
+            {
+                //Calculate the source coords without -0.5f is equivalent to round the x_scr/y_src coords
+                x_src = (idx + 0.5f) * wr;
+                y_src = (idy + 0.5f) * hr;
+                id.set(0, x_src);
+                id.set(1, y_src);
+
+                // If coordinates in range of tensor's width or height
+                if(is_valid_pixel_index(x_src, y_src, width, height, border_size))
+                {
+                    out[element_idx] = tensor_elem_at(in, id, border_mode, constant_border_value);
+                }
+                break;
+            }
+            case InterpolationPolicy::BILINEAR:
+            {
+                id.set(0, std::floor(x_src));
+                id.set(1, std::floor(y_src));
+                if(is_valid_pixel_index(x_src, y_src, width, height, border_size))
+                {
+                    out[element_idx] = bilinear_policy(in, id, x_src, y_src, border_mode, constant_border_value);
+                }
+                else
+                {
+                    if(border_mode == BorderMode::CONSTANT)
+                    {
+                        out[element_idx] = constant_border_value;
+                    }
+                    else if(border_mode == BorderMode::REPLICATE)
+                    {
+                        id.set(0, clamp(static_cast<int>(x_src), 0, width - 1));
+                        id.set(1, clamp(static_cast<int>(y_src), 0, height - 1));
+                        out[element_idx] = in[coord2index(in.shape(), id)];
+                    }
+                }
+                break;
+            }
+            case InterpolationPolicy::AREA:
+            {
+                int       x_from = std::floor(idx * wr - 0.5f - x_src);
+                int       y_from = std::floor(idy * hr - 0.5f - y_src);
+                int       x_to   = std::ceil((idx + 1) * wr - 0.5f - x_src);
+                int       y_to   = std::ceil((idy + 1) * hr - 0.5f - y_src);
+                const int xi     = std::floor(x_src);
+                const int yi     = std::floor(y_src);
+
+                // Clamp position to borders
+                x_src = std::max(-static_cast<float>(border_size), std::min(x_src, static_cast<float>(width - 1 + border_size)));
+                y_src = std::max(-static_cast<float>(border_size), std::min(y_src, static_cast<float>(height - 1 + border_size)));
+
+                // Clamp bounding box offsets to borders
+                x_from = ((x_src + x_from) < -border_size) ? -border_size : x_from;
+                y_from = ((y_src + y_from) < -border_size) ? -border_size : y_from;
+                x_to   = ((x_src + x_to) >= (width + border_size)) ? (width - 1 + border_size) : x_to;
+                y_to   = ((y_src + y_to) >= (height + border_size)) ? (height - 1 + border_size) : y_to;
+                ARM_COMPUTE_ERROR_ON((x_to - x_from + 1) == 0 || (y_to - y_from + 1) == 0);
+
+                float sum = 0;
+                for(int j = yi + y_from, je = yi + y_to; j <= je; ++j)
+                {
+                    for(int i = xi + x_from, ie = xi + x_to; i <= ie; ++i)
+                    {
+                        id.set(0, static_cast<int>(i));
+                        id.set(1, static_cast<int>(j));
+                        sum += tensor_elem_at(in, id, border_mode, constant_border_value);
+                    }
+                }
+                out[element_idx] = sum / ((x_to - x_from + 1) * (y_to - y_from + 1));
+
+                break;
+            }
+            default:
+                ARM_COMPUTE_ERROR("Unsupported interpolation mode");
+        }
+    }
+
+    return out;
+}
+
+template SimpleTensor<uint8_t> scale(const SimpleTensor<uint8_t> &src, float scale_x, float scale_y, InterpolationPolicy policy, BorderMode border_mode, uint8_t constant_border_value,
+                                     SamplingPolicy sampling_policy, bool ceil_policy_scale);
+template SimpleTensor<int16_t> scale(const SimpleTensor<int16_t> &src, float scale_x, float scale_y, InterpolationPolicy policy, BorderMode border_mode, int16_t constant_border_value,
+                                     SamplingPolicy sampling_policy, bool ceil_policy_scale);
+template SimpleTensor<half> scale(const SimpleTensor<half> &src, float scale_x, float scale_y, InterpolationPolicy policy, BorderMode border_mode, half constant_border_value,
+                                  SamplingPolicy sampling_policy, bool ceil_policy_scale);
+template SimpleTensor<float> scale(const SimpleTensor<float> &src, float scale_x, float scale_y, InterpolationPolicy policy, BorderMode border_mode, float constant_border_value,
+                                   SamplingPolicy sampling_policy, bool ceil_policy_scale);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/Scale.h b/tests/validation/reference/Scale.h
new file mode 100644
index 0000000..566e30a
--- /dev/null
+++ b/tests/validation/reference/Scale.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_SCALE_H__
+#define __ARM_COMPUTE_TEST_SCALE_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> scale(const SimpleTensor<T> &in, float scale_x, float scale_y, InterpolationPolicy policy, BorderMode border_mode, T constant_border_value = 0,
+                      SamplingPolicy sampling_policy = SamplingPolicy::CENTER, bool ceil_policy_scale = false);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_SCALE_H__ */
diff --git a/tests/validation/reference/Scharr.cpp b/tests/validation/reference/Scharr.cpp
new file mode 100644
index 0000000..98e4d62
--- /dev/null
+++ b/tests/validation/reference/Scharr.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "Scharr.h"
+
+#include "Utils.h"
+#include "tests/validation/Helpers.h"
+
+#include <array>
+#include <map>
+#include <utility>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+namespace
+{
+const std::array<int8_t, 9> scharr_3_x{ { -3, 0, 3, -10, 0, 10, -3, 0, 3 } };
+const std::array<int8_t, 9> scharr_3_y{ { -3, -10, -3, 0, 0, 0, 3, 10, 3 } };
+
+const std::map<int, std::pair<const int8_t *, const int8_t *>> masks
+{
+    { 3, { scharr_3_x.data(), scharr_3_y.data() } }
+};
+
+template <typename T>
+struct data_type;
+
+template <>
+struct data_type<int16_t>
+{
+    const static DataType value = DataType::S16;
+};
+} // namespace
+
+template <typename T, typename U>
+std::pair<SimpleTensor<T>, SimpleTensor<T>> scharr(const SimpleTensor<U> &src, int filter_size, BorderMode border_mode, uint8_t constant_border_value, GradientDimension gradient_dimension)
+{
+    const auto shape_size = static_cast<unsigned int>(filter_size);
+
+    SimpleTensor<T> dst_x(src.shape(), data_type<T>::value, src.num_channels());
+    SimpleTensor<T> dst_y(src.shape(), data_type<T>::value, src.num_channels());
+
+    ValidRegion valid_region = shape_to_valid_region(src.shape(), border_mode == BorderMode::UNDEFINED, BorderSize(filter_size / 2));
+
+    for(int i = 0; i < src.num_elements(); ++i)
+    {
+        Coordinates coord = index2coord(src.shape(), i);
+
+        if(!is_in_valid_region(valid_region, coord))
+        {
+            continue;
+        }
+
+        switch(gradient_dimension)
+        {
+            case GradientDimension::GRAD_X:
+                apply_2d_spatial_filter(coord, src, dst_x, TensorShape{ shape_size, shape_size }, masks.at(filter_size).first, 1.f, border_mode, constant_border_value);
+                break;
+            case GradientDimension::GRAD_Y:
+                apply_2d_spatial_filter(coord, src, dst_y, TensorShape{ shape_size, shape_size }, masks.at(filter_size).second, 1.f, border_mode, constant_border_value);
+                break;
+            case GradientDimension::GRAD_XY:
+                apply_2d_spatial_filter(coord, src, dst_x, TensorShape{ shape_size, shape_size }, masks.at(filter_size).first, 1.f, border_mode, constant_border_value);
+                apply_2d_spatial_filter(coord, src, dst_y, TensorShape{ shape_size, shape_size }, masks.at(filter_size).second, 1.f, border_mode, constant_border_value);
+                break;
+            default:
+                ARM_COMPUTE_ERROR("Gradient dimension not supported");
+        }
+    }
+
+    return std::make_pair(dst_x, dst_y);
+}
+
+template std::pair<SimpleTensor<int16_t>, SimpleTensor<int16_t>> scharr(const SimpleTensor<uint8_t> &src, int filter_size, BorderMode border_mode, uint8_t constant_border_value,
+                                                                        GradientDimension gradient_dimension);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/Scharr.h b/tests/validation/reference/Scharr.h
new file mode 100644
index 0000000..8f38381
--- /dev/null
+++ b/tests/validation/reference/Scharr.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_SCHARR_H__
+#define __ARM_COMPUTE_TEST_SCHARR_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/Types.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T, typename U>
+std::pair<SimpleTensor<T>, SimpleTensor<T>> scharr(const SimpleTensor<U> &src, int filter_size, BorderMode border_mode, uint8_t constant_border_value, GradientDimension gradient_dimension);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_SCHARR_H__ */
diff --git a/tests/validation/reference/Sobel.cpp b/tests/validation/reference/Sobel.cpp
new file mode 100644
index 0000000..ff0e11d
--- /dev/null
+++ b/tests/validation/reference/Sobel.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "Sobel.h"
+
+#include "Utils.h"
+#include "tests/validation/Helpers.h"
+
+#include <array>
+#include <map>
+#include <utility>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+namespace
+{
+const std::array<int8_t, 9> sobel_3_x{ { -1, 0, 1, -2, 0, 2, -1, 0, 1 } };
+const std::array<int8_t, 9> sobel_3_y{ { -1, -2, -1, 0, 0, 0, 1, 2, 1 } };
+
+const std::array<int8_t, 25> sobel_5_x{ {
+        -1, -2, 0, 2, 1,
+        -4, -8, 0, 8, 4,
+        -6, -12, 0, 12, 6,
+        -4, -8, 0, 8, 4,
+        -1, -2, 0, 2, 1
+    } };
+
+const std::array<int8_t, 25> sobel_5_y{ {
+        -1, -4, -6, -4, -1,
+        -2, -8, -12, -8, -2,
+        0, 0, 0, 0, 0,
+        2, 8, 12, 8, 2,
+        1, 4, 6, 4, 1
+    } };
+
+const std::array<int8_t, 49> sobel_7_x{ {
+        -1, -4, -5, 0, 5, 4, 1,
+        -6, -24, -30, 0, 30, 24, 6,
+        -15, -60, -75, 0, 75, 60, 15,
+        -20, -80, -100, 0, 100, 80, 20,
+        -15, -60, -75, 0, 75, 60, 15,
+        -6, -24, -30, 0, 30, 24, 6,
+        -1, -4, -5, 0, 5, 4, 1
+    } };
+
+const std::array<int8_t, 49> sobel_7_y{ {
+        -1, -6, -15, -20, -15, -6, -1,
+        -4, -24, -60, -80, -60, -24, -4,
+        -5, -30, -75, -100, -75, -30, -5,
+        0, 0, 0, 0, 0, 0, 0,
+        5, 30, 75, 100, 75, 30, 5,
+        4, 24, 60, 80, 60, 24, 4,
+        1, 6, 15, 20, 15, 6, 1
+    } };
+
+const std::map<int, std::pair<const int8_t *, const int8_t *>> masks
+{
+    { 3, { sobel_3_x.data(), sobel_3_y.data() } },
+    { 5, { sobel_5_x.data(), sobel_5_y.data() } },
+    { 7, { sobel_7_x.data(), sobel_7_y.data() } },
+};
+
+template <typename T>
+struct data_type;
+
+template <>
+struct data_type<int16_t>
+{
+    const static DataType value = DataType::S16;
+};
+
+template <>
+struct data_type<int>
+{
+    const static DataType value = DataType::S32;
+};
+} // namespace
+
+template <typename T, typename U>
+std::pair<SimpleTensor<T>, SimpleTensor<T>> sobel(const SimpleTensor<U> &src, int filter_size, BorderMode border_mode, uint8_t constant_border_value, GradientDimension gradient_dimension)
+{
+    SimpleTensor<T> dst_x(src.shape(), data_type<T>::value, src.num_channels());
+    SimpleTensor<T> dst_y(src.shape(), data_type<T>::value, src.num_channels());
+
+    ValidRegion valid_region = shape_to_valid_region(src.shape(), border_mode == BorderMode::UNDEFINED, BorderSize(filter_size / 2));
+
+    for(int i = 0; i < src.num_elements(); ++i)
+    {
+        Coordinates coord = index2coord(src.shape(), i);
+
+        if(!is_in_valid_region(valid_region, coord))
+        {
+            continue;
+        }
+        switch(gradient_dimension)
+        {
+            case GradientDimension::GRAD_X:
+                apply_2d_spatial_filter(coord, src, dst_x, TensorShape{ static_cast<unsigned int>(filter_size), static_cast<unsigned int>(filter_size) }, masks.at(filter_size).first, 1.f, border_mode,
+                                        constant_border_value);
+                break;
+            case GradientDimension::GRAD_Y:
+                apply_2d_spatial_filter(coord, src, dst_y, TensorShape{ static_cast<unsigned int>(filter_size), static_cast<unsigned int>(filter_size) }, masks.at(filter_size).second, 1.f, border_mode,
+                                        constant_border_value);
+                break;
+            case GradientDimension::GRAD_XY:
+                apply_2d_spatial_filter(coord, src, dst_x, TensorShape{ static_cast<unsigned int>(filter_size), static_cast<unsigned int>(filter_size) }, masks.at(filter_size).first, 1.f, border_mode,
+                                        constant_border_value);
+                apply_2d_spatial_filter(coord, src, dst_y, TensorShape{ static_cast<unsigned int>(filter_size), static_cast<unsigned int>(filter_size) }, masks.at(filter_size).second, 1.f, border_mode,
+                                        constant_border_value);
+                break;
+            default:
+                ARM_COMPUTE_ERROR("Gradient dimension not supported");
+        }
+    }
+
+    return std::make_pair(dst_x, dst_y);
+}
+
+template std::pair<SimpleTensor<int16_t>, SimpleTensor<int16_t>> sobel(const SimpleTensor<uint8_t> &src, int filter_size, BorderMode border_mode, uint8_t constant_border_value,
+                                                                       GradientDimension gradient_dimension);
+template std::pair<SimpleTensor<int>, SimpleTensor<int>> sobel(const SimpleTensor<uint8_t> &src, int filter_size, BorderMode border_mode, uint8_t constant_border_value,
+                                                               GradientDimension gradient_dimension);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/Sobel.h b/tests/validation/reference/Sobel.h
new file mode 100644
index 0000000..9099f1a
--- /dev/null
+++ b/tests/validation/reference/Sobel.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_SOBEL_H__
+#define __ARM_COMPUTE_TEST_SOBEL_H__
+
+#include "arm_compute/core/Types.h"
+#include "tests/SimpleTensor.h"
+#include "tests/Types.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T, typename U>
+std::pair<SimpleTensor<T>, SimpleTensor<T>> sobel(const SimpleTensor<U> &src, int filter_size, BorderMode border_mode, uint8_t constant_border_value, GradientDimension gradient_dimension);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_SOBEL_H__ */
diff --git a/tests/validation/reference/SoftmaxLayer.cpp b/tests/validation/reference/SoftmaxLayer.cpp
new file mode 100644
index 0000000..8e8cc1b
--- /dev/null
+++ b/tests/validation/reference/SoftmaxLayer.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "SoftmaxLayer.h"
+
+#include "arm_compute/core/Types.h"
+#include "tests/validation/FixedPoint.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type>
+SimpleTensor<T> softmax_layer(const SimpleTensor<T> &src)
+{
+    // Create reference
+    SimpleTensor<T> dst{ src.shape(), src.data_type(), 1, src.fixed_point_position() };
+
+    // Compute reference
+    const int cols       = src.shape()[0];
+    const int upper_dims = src.num_elements() / cols;
+
+    for(int r = 0; r < upper_dims; ++r)
+    {
+        const T *src_row_ptr = src.data() + r * cols;
+        T       *dst_row_ptr = dst.data() + r * cols;
+
+        // Find max
+        const T max = *std::max_element(src_row_ptr, src_row_ptr + cols);
+
+        // Regularize
+        T sum(0.f);
+        std::transform(src_row_ptr, src_row_ptr + cols, dst_row_ptr, [&sum, max](T val)
+        {
+            const T res(std::exp(val - max));
+            sum += res;
+            return res;
+        });
+
+        // Normalize
+        std::transform(dst_row_ptr, dst_row_ptr + cols, dst_row_ptr, [sum](T val)
+        {
+            return val / sum;
+        });
+    }
+
+    return dst;
+}
+
+template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type>
+SimpleTensor<T> softmax_layer(const SimpleTensor<T> &src)
+{
+    using namespace fixed_point_arithmetic;
+
+    // Create reference
+    SimpleTensor<T> dst{ src.shape(), src.data_type(), 1, src.fixed_point_position() };
+
+    // Compute reference
+    const int cols       = src.shape()[0];
+    const int upper_dims = src.num_elements() / cols;
+
+    for(int r = 0; r < upper_dims; ++r)
+    {
+        const T *src_row_ptr = src.data() + r * cols;
+        T       *dst_row_ptr = dst.data() + r * cols;
+
+        // Find max
+        const fixed_point<T> max(*std::max_element(src_row_ptr, src_row_ptr + cols), src.fixed_point_position(), true);
+
+        // Regularize
+        using promoted_type = fixed_point_arithmetic::traits::promote_t<T>;
+        fixed_point<promoted_type> sum(0, src.fixed_point_position(), true);
+        std::transform(src_row_ptr, src_row_ptr + cols, dst_row_ptr, [&](T val)
+        {
+            const fixed_point<T> res = exp(fixed_point<T>(val, src.fixed_point_position(), true) - max);
+            sum                      = add(sum, fixed_point<promoted_type>(res.raw(), src.fixed_point_position(), true));
+            return res.raw();
+        });
+
+        // Normalize
+        fixed_point<T> saturated_sum(sum);
+        std::transform(dst_row_ptr, dst_row_ptr + cols, dst_row_ptr, [&](T val)
+        {
+            return div(fixed_point<T>(val, src.fixed_point_position(), true), saturated_sum).raw();
+        });
+    }
+
+    return dst;
+}
+
+template <>
+SimpleTensor<uint8_t> softmax_layer<uint8_t>(const SimpleTensor<uint8_t> &src)
+{
+    // Note: Output quantization info should always have scale = 1/256 and offset = 0
+    const QuantizationInfo output_quantization_info = QuantizationInfo(1.f / 256, 0);
+
+    SimpleTensor<float>   src_tmp = convert_from_asymmetric(src);
+    SimpleTensor<float>   dst_tmp = softmax_layer<float>(src_tmp);
+    SimpleTensor<uint8_t> dst     = convert_to_asymmetric(dst_tmp, output_quantization_info);
+    return dst;
+}
+
+template SimpleTensor<float> softmax_layer(const SimpleTensor<float> &src);
+template SimpleTensor<half> softmax_layer(const SimpleTensor<half> &src);
+template SimpleTensor<qint8_t> softmax_layer(const SimpleTensor<qint8_t> &src);
+template SimpleTensor<qint16_t> softmax_layer(const SimpleTensor<qint16_t> &src);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/SoftmaxLayer.h b/tests/validation/reference/SoftmaxLayer.h
new file mode 100644
index 0000000..ab79bc4
--- /dev/null
+++ b/tests/validation/reference/SoftmaxLayer.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_SOFTMAX_LAYER_H__
+#define __ARM_COMPUTE_TEST_SOFTMAX_LAYER_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T, typename std::enable_if<is_floating_point<T>::value, int>::type = 0>
+SimpleTensor<T> softmax_layer(const SimpleTensor<T> &src);
+
+template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
+SimpleTensor<T> softmax_layer(const SimpleTensor<T> &src);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_SOFTMAX_LAYER_H__ */
diff --git a/tests/validation/reference/TableLookup.cpp b/tests/validation/reference/TableLookup.cpp
new file mode 100644
index 0000000..7f105d9
--- /dev/null
+++ b/tests/validation/reference/TableLookup.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "TableLookup.h"
+
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> table_lookup(const SimpleTensor<T> &src, const std::map<T, T> &rawlut)
+{
+    SimpleTensor<T> result(src.shape(), src.data_type());
+
+    for(int i = 0; i < src.num_elements(); ++i)
+    {
+        result[i] = rawlut.at(src[i]);
+    }
+
+    return result;
+}
+
+template SimpleTensor<uint8_t> table_lookup(const SimpleTensor<uint8_t> &src, const std::map<uint8_t, uint8_t> &rawlut);
+template SimpleTensor<int16_t> table_lookup(const SimpleTensor<int16_t> &src, const std::map<int16_t, int16_t> &rawlut);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/TableLookup.h b/tests/validation/reference/TableLookup.h
new file mode 100644
index 0000000..3fdecac
--- /dev/null
+++ b/tests/validation/reference/TableLookup.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_TABLE_LOOKUP_H__
+#define __ARM_COMPUTE_TEST_TABLE_LOOKUP_H__
+
+#include "tests/SimpleTensor.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> table_lookup(const SimpleTensor<T> &src, const std::map<T, T> &rawlut);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_TABLE_LOOKUP_H__ */
diff --git a/tests/validation/reference/Threshold.cpp b/tests/validation/reference/Threshold.cpp
new file mode 100644
index 0000000..d0ef31d
--- /dev/null
+++ b/tests/validation/reference/Threshold.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal src the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included src all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. src NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER src AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * dst OF OR src CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS src THE
+ * SOFTWARE.
+ */
+#include "Threshold.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> threshold(const SimpleTensor<T> &src, T threshold, T false_value, T true_value, ThresholdType type, T upper)
+{
+    SimpleTensor<T> dst(src.shape(), src.data_type());
+
+    switch(type)
+    {
+        case ThresholdType::BINARY:
+            for(int i = 0; i < src.num_elements(); ++i)
+            {
+                dst[i] = ((src[i] > threshold) ? true_value : false_value);
+            }
+            break;
+        case ThresholdType::RANGE:
+            for(int i = 0; i < src.num_elements(); ++i)
+            {
+                if(src[i] > upper)
+                {
+                    dst[i] = false_value;
+                }
+                else if(src[i] < threshold)
+                {
+                    dst[i] = false_value;
+                }
+                else
+                {
+                    dst[i] = true_value;
+                }
+            }
+            break;
+        default:
+            ARM_COMPUTE_ERROR("Thresholding type not recognised");
+            break;
+    }
+
+    return dst;
+}
+
+template SimpleTensor<uint8_t> threshold(const SimpleTensor<uint8_t> &src, uint8_t threshold, uint8_t false_value, uint8_t true_value, ThresholdType type, uint8_t upper);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/Threshold.h b/tests/validation/reference/Threshold.h
new file mode 100644
index 0000000..fbe2dba
--- /dev/null
+++ b/tests/validation/reference/Threshold.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_THRESHOLD_H__
+#define __ARM_COMPUTE_TEST_THRESHOLD_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> threshold(const SimpleTensor<T> &src, T threshold, T false_value, T true_value, ThresholdType type, T upper);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_THRESHOLD_H__ */
diff --git a/tests/validation/reference/Transpose.cpp b/tests/validation/reference/Transpose.cpp
new file mode 100644
index 0000000..9f2e62e
--- /dev/null
+++ b/tests/validation/reference/Transpose.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "Transpose.h"
+
+#include "arm_compute/core/Types.h"
+#include "tests/validation/FixedPoint.h"
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> transpose(const SimpleTensor<T> &src)
+{
+    // Make rows the columns of the original shape
+    TensorShape dst_shape{ src.shape().y(), src.shape().x() };
+
+    // Create reference
+    SimpleTensor<T> dst{ dst_shape, src.data_type() };
+
+    // Compute reference
+    for(int i = 0; i < src.num_elements(); ++i)
+    {
+        const Coordinates coord = index2coord(src.shape(), i);
+        const Coordinates dst_coord{ coord.y(), coord.x() };
+        const size_t      dst_index = coord2index(dst.shape(), dst_coord);
+
+        dst[dst_index] = src[i];
+    }
+
+    return dst;
+}
+
+template SimpleTensor<uint8_t> transpose(const SimpleTensor<uint8_t> &src);
+template SimpleTensor<uint16_t> transpose(const SimpleTensor<uint16_t> &src);
+template SimpleTensor<uint32_t> transpose(const SimpleTensor<uint32_t> &src);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/Transpose.h b/tests/validation/reference/Transpose.h
new file mode 100644
index 0000000..3f42f41
--- /dev/null
+++ b/tests/validation/reference/Transpose.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_TRANSPOSE_H__
+#define __ARM_COMPUTE_TEST_TRANSPOSE_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> transpose(const SimpleTensor<T> &src);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_TRANSPOSE_H__ */
diff --git a/tests/validation/reference/Utils.cpp b/tests/validation/reference/Utils.cpp
new file mode 100644
index 0000000..d163e84
--- /dev/null
+++ b/tests/validation/reference/Utils.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "Utils.h"
+
+#include "tests/validation/Helpers.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+// Return the bilinear value at a specified coordinate with different border modes
+template <typename T>
+T bilinear_policy(const SimpleTensor<T> &in, Coordinates id, float xn, float yn, BorderMode border_mode, T constant_border_value)
+{
+    const int idx = std::floor(xn);
+    const int idy = std::floor(yn);
+
+    const float dx   = xn - idx;
+    const float dy   = yn - idy;
+    const float dx_1 = 1.0f - dx;
+    const float dy_1 = 1.0f - dy;
+
+    const T border_value = constant_border_value;
+
+    id.set(0, idx);
+    id.set(1, idy);
+    const float tl = tensor_elem_at(in, id, border_mode, border_value);
+    id.set(0, idx + 1);
+    id.set(1, idy);
+    const float tr = tensor_elem_at(in, id, border_mode, border_value);
+    id.set(0, idx);
+    id.set(1, idy + 1);
+    const float bl = tensor_elem_at(in, id, border_mode, border_value);
+    id.set(0, idx + 1);
+    id.set(1, idy + 1);
+    const float br = tensor_elem_at(in, id, border_mode, border_value);
+
+    return static_cast<T>(tl * (dx_1 * dy_1) + tr * (dx * dy_1) + bl * (dx_1 * dy) + br * (dx * dy));
+}
+
+template uint8_t bilinear_policy(const SimpleTensor<uint8_t> &in, Coordinates id, float xn, float yn, BorderMode border_mode, uint8_t constant_border_value);
+template int16_t bilinear_policy(const SimpleTensor<int16_t> &in, Coordinates id, float xn, float yn, BorderMode border_mode, int16_t constant_border_value);
+template half bilinear_policy(const SimpleTensor<half> &in, Coordinates id, float xn, float yn, BorderMode border_mode, half constant_border_value);
+template float bilinear_policy(const SimpleTensor<float> &in, Coordinates id, float xn, float yn, BorderMode border_mode, float constant_border_value);
+
+RawTensor transpose(const RawTensor &src, int chunk_width)
+{
+    // Create reference
+    TensorShape dst_shape(src.shape());
+    dst_shape.set(0, src.shape().y() * chunk_width);
+    dst_shape.set(1, std::ceil(src.shape().x() / static_cast<float>(chunk_width)));
+
+    RawTensor dst{ dst_shape, src.data_type() };
+
+    // Compute reference
+    uint8_t *out_ptr = dst.data();
+
+    for(int i = 0; i < dst.num_elements(); i += chunk_width)
+    {
+        Coordinates coord   = index2coord(dst.shape(), i);
+        size_t      coord_x = coord.x();
+        coord.set(0, coord.y() * chunk_width);
+        coord.set(1, coord_x / chunk_width);
+
+        const int num_elements = std::min<int>(chunk_width, src.shape().x() - coord.x());
+
+        std::copy_n(static_cast<const uint8_t *>(src(coord)), num_elements * src.element_size(), out_ptr);
+
+        out_ptr += chunk_width * dst.element_size();
+    }
+
+    return dst;
+}
+
+bool valid_bilinear_policy(float xn, float yn, int width, int height, BorderMode border_mode)
+{
+    if(border_mode != BorderMode::UNDEFINED)
+    {
+        return true;
+    }
+    if((0 <= yn + 1) && (yn + 1 < height) && (0 <= xn + 1) && (xn + 1 < width))
+    {
+        return true;
+    }
+    return false;
+}
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/Utils.h b/tests/validation/reference/Utils.h
new file mode 100644
index 0000000..2aa77c6
--- /dev/null
+++ b/tests/validation/reference/Utils.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_VALIDATION_UTILS_H__
+#define __ARM_COMPUTE_TEST_VALIDATION_UTILS_H__
+
+#include "arm_compute/core/Types.h"
+#include "tests/Globals.h"
+#include "tests/ILutAccessor.h"
+#include "tests/Types.h"
+
+#include <array>
+#include <random>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+/** Checks if a pixel has valid coordinates
+ *
+ * @param x            X coordinate
+ * @param y            Y coordinate
+ * @param width        Width of the image
+ * @param height       Height of the image
+ * @param border_size  Border size
+ *
+ * @return True if pixel is valid else false
+ */
+inline bool is_valid_pixel_index(int x, int y, int width, int height, int border_size)
+{
+    return ((x >= -border_size) && (y >= -border_size) && (x < (width + border_size)) && (y < height + border_size));
+}
+
+// Return a tensor element at a specified coordinate with different border modes
+template <typename T>
+T tensor_elem_at(const SimpleTensor<T> &src, Coordinates coord, BorderMode border_mode, T constant_border_value)
+{
+    const int x      = coord.x();
+    const int y      = coord.y();
+    const int width  = src.shape().x();
+    const int height = src.shape().y();
+
+    // If coordinates beyond range of tensor's width or height
+    if(x < 0 || y < 0 || x >= width || y >= height)
+    {
+        if(border_mode == BorderMode::REPLICATE)
+        {
+            coord.set(0, std::max(0, std::min(x, width - 1)));
+            coord.set(1, std::max(0, std::min(y, height - 1)));
+        }
+        else
+        {
+            return constant_border_value;
+        }
+    }
+
+    return src[coord2index(src.shape(), coord)];
+}
+
+template <typename T>
+T bilinear_policy(const SimpleTensor<T> &in, Coordinates id, float xn, float yn, BorderMode border_mode, T constant_border_value);
+
+/* Apply 2D spatial filter on a single element of @p in at coordinates @p coord
+ *
+ * - filter sizes have to be odd number
+ * - Row major order of filter assumed
+ * - TO_ZERO rounding policy assumed
+ * - SATURATE convert policy assumed
+ */
+template <typename T, typename U, typename V>
+void apply_2d_spatial_filter(Coordinates coord, const SimpleTensor<T> &src, SimpleTensor<U> &dst, const TensorShape &filter_shape, const V *filter_itr, double scale, BorderMode border_mode,
+                             T constant_border_value = T(0))
+{
+    double    val = 0.;
+    const int x   = coord.x();
+    const int y   = coord.y();
+    for(int j = y - static_cast<int>(filter_shape[1] / 2); j <= y + static_cast<int>(filter_shape[1] / 2); ++j)
+    {
+        for(int i = x - static_cast<int>(filter_shape[0] / 2); i <= x + static_cast<int>(filter_shape[0] / 2); ++i)
+        {
+            coord.set(0, i);
+            coord.set(1, j);
+            val += static_cast<double>(*filter_itr) * tensor_elem_at(src, coord, border_mode, constant_border_value);
+            ++filter_itr;
+        }
+    }
+    coord.set(0, x);
+    coord.set(1, y);
+    dst[coord2index(src.shape(), coord)] = saturate_cast<U>(support::cpp11::trunc(val * scale));
+}
+
+RawTensor transpose(const RawTensor &src, int chunk_width = 1);
+
+/** Fill matrix random.
+ *
+ * @param[in,out] matrix Matrix
+ */
+template <std::size_t SIZE>
+inline void fill_warp_matrix(std::array<float, SIZE> &matrix)
+{
+    std::mt19937                          gen(library.get()->seed());
+    std::uniform_real_distribution<float> dist(-1, 1);
+    for(auto &x : matrix)
+    {
+        x = dist(gen);
+    }
+    if(SIZE == 9)
+    {
+        // This is only used in Warp Perspective, we set M[3][3] = 1 so that Z0 is not 0 and we avoid division by 0.
+        matrix[8] = 1.f;
+    }
+}
+
+bool valid_bilinear_policy(float xn, float yn, int width, int height, BorderMode border_mode);
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_VALIDATION_UTILS_H__ */
diff --git a/tests/validation/reference/UtilsQuantizedAsymm.h b/tests/validation/reference/UtilsQuantizedAsymm.h
new file mode 100644
index 0000000..b7b69d5
--- /dev/null
+++ b/tests/validation/reference/UtilsQuantizedAsymm.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_VALIDATION_UTILS_QUANTIZED_ASYMM_H__
+#define __ARM_COMPUTE_TEST_VALIDATION_UTILS_QUANTIZED_ASYMM_H__
+
+#include <cstdint>
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+/** Rounded to nearest division by a power-of-two. */
+inline int32_t asymm_rounding_divide_by_pow2(int32_t x, int exponent)
+{
+    const int32_t mask      = (1 << exponent) - 1;
+    const int32_t threshold = (mask >> 1) + (x < 0 ? 1 : 0);
+    return (x >> exponent) + ((x & mask) > threshold ? 1 : 0);
+}
+
+/** Multiplication of two integers. The same as ARMv7 NEON VQRDMULH instruction. */
+inline int32_t asymm_int_mult(int32_t a, int32_t b)
+{
+    bool    overflow = a == b && a == std::numeric_limits<int32_t>::min();
+    int64_t a_64(a);
+    int64_t b_64(b);
+    int64_t ab_64        = a_64 * b_64;
+    int32_t nudge        = ab_64 >= 0 ? (1 << 30) : (1 - (1 << 30));
+    int32_t ab_x2_high32 = static_cast<int32_t>((ab_64 + nudge) / (1ll << 31));
+    return overflow ? std::numeric_limits<int32_t>::max() : ab_x2_high32;
+}
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_VALIDATION_UTILS_QUANTIZED_ASYMM_H__ */
diff --git a/tests/validation/reference/WarpAffine.cpp b/tests/validation/reference/WarpAffine.cpp
new file mode 100644
index 0000000..7b903b7
--- /dev/null
+++ b/tests/validation/reference/WarpAffine.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "WarpAffine.h"
+
+#include "Utils.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+bool valid_bilinear_policy(float xn, float yn, int width, int height, BorderMode border_mode)
+{
+    if(border_mode != BorderMode::UNDEFINED)
+    {
+        return true;
+    }
+    if((0 <= yn + 1) && (yn + 1 < height) && (0 <= xn + 1) && (xn + 1 < width))
+    {
+        return true;
+    }
+    return false;
+}
+
+template <typename T>
+SimpleTensor<T> warp_affine(const SimpleTensor<T> &src, SimpleTensor<T> &valid_mask, const float *matrix, InterpolationPolicy policy, BorderMode border_mode, uint8_t constant_border_value)
+{
+    SimpleTensor<T> dst(src.shape(), src.data_type());
+
+    // x0 = M00 * x + M01 * y + M02
+    // y0 = M10 * x + M11 * y + M12
+    const float M00 = matrix[0];
+    const float M10 = matrix[1];
+    const float M01 = matrix[0 + 1 * 2];
+    const float M11 = matrix[1 + 1 * 2];
+    const float M02 = matrix[0 + 2 * 2];
+    const float M12 = matrix[1 + 2 * 2];
+
+    const int width  = src.shape().x();
+    const int height = src.shape().y();
+
+    for(int element_idx = 0; element_idx < src.num_elements(); ++element_idx)
+    {
+        valid_mask[element_idx] = 1;
+        Coordinates id          = index2coord(src.shape(), element_idx);
+        int         idx         = id.x();
+        int         idy         = id.y();
+
+        float x0 = M00 * idx + M01 * idy + M02;
+        float y0 = M10 * idx + M11 * idy + M12;
+
+        id.set(0, static_cast<int>(std::floor(x0)));
+        id.set(1, static_cast<int>(std::floor(y0)));
+        if((0 <= y0) && (y0 < height) && (0 <= x0) && (x0 < width))
+        {
+            switch(policy)
+            {
+                case InterpolationPolicy::NEAREST_NEIGHBOR:
+                    dst[element_idx] = tensor_elem_at(src, id, border_mode, constant_border_value);
+                    break;
+                case InterpolationPolicy::BILINEAR:
+                    (valid_bilinear_policy(x0, y0, width, height, border_mode)) ? dst[element_idx] = bilinear_policy(src, id, x0, y0, border_mode, constant_border_value) :
+                                                                                                     valid_mask[element_idx] = 0;
+                    break;
+                case InterpolationPolicy::AREA:
+                default:
+                    ARM_COMPUTE_ERROR("Interpolation not supported");
+            }
+        }
+        else
+        {
+            if(border_mode == BorderMode::UNDEFINED)
+            {
+                valid_mask[element_idx] = 0;
+            }
+            else
+            {
+                switch(policy)
+                {
+                    case InterpolationPolicy::NEAREST_NEIGHBOR:
+                        if(border_mode == BorderMode::CONSTANT)
+                        {
+                            dst[element_idx] = constant_border_value;
+                        }
+                        else if(border_mode == BorderMode::REPLICATE)
+                        {
+                            id.set(0, std::max(0, std::min(static_cast<int>(x0), width - 1)));
+                            id.set(1, std::max(0, std::min(static_cast<int>(y0), height - 1)));
+                            dst[element_idx] = src[coord2index(src.shape(), id)];
+                        }
+                        break;
+                    case InterpolationPolicy::BILINEAR:
+                        dst[element_idx] = bilinear_policy(src, id, x0, y0, border_mode, constant_border_value);
+                        break;
+                    case InterpolationPolicy::AREA:
+                    default:
+                        ARM_COMPUTE_ERROR("Interpolation not supported");
+                }
+            }
+        }
+    }
+
+    return dst;
+}
+
+template SimpleTensor<uint8_t> warp_affine(const SimpleTensor<uint8_t> &src, SimpleTensor<uint8_t> &valid_mask, const float *matrix, InterpolationPolicy policy, BorderMode border_mode,
+                                           uint8_t constant_border_value);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
\ No newline at end of file
diff --git a/tests/validation/reference/WarpAffine.h b/tests/validation/reference/WarpAffine.h
new file mode 100644
index 0000000..973b1b2
--- /dev/null
+++ b/tests/validation/reference/WarpAffine.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_WARP_AFFINE_H__
+#define __ARM_COMPUTE_TEST_WARP_AFFINE_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> warp_affine(const SimpleTensor<T> &src, SimpleTensor<T> &valid_mask, const float *matrix, InterpolationPolicy policy, BorderMode border_mode, uint8_t constant_border_value);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_WARP_AFFINE_H__ */
diff --git a/tests/validation/reference/WarpPerspective.cpp b/tests/validation/reference/WarpPerspective.cpp
new file mode 100644
index 0000000..7a50253
--- /dev/null
+++ b/tests/validation/reference/WarpPerspective.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "arm_compute/core/Helpers.h"
+
+#include "Utils.h"
+#include "WarpPerspective.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> warp_perspective(const SimpleTensor<T> &src, SimpleTensor<T> &valid_mask, const float *matrix, InterpolationPolicy policy, BorderMode border_mode, uint8_t constant_border_value)
+{
+    SimpleTensor<T> dst(src.shape(), src.data_type());
+
+    // x0 = M00 * x + M01 * y + M02
+    // y0 = M10 * x + M11 * y + M12
+    // z0 = M20 * x + M21 * y + M22
+    // xn = x0 / z0
+    // yn = y0 / z0
+    const float M00 = matrix[0];
+    const float M10 = matrix[1];
+    const float M20 = matrix[2];
+    const float M01 = matrix[0 + 1 * 3];
+    const float M11 = matrix[1 + 1 * 3];
+    const float M21 = matrix[2 + 1 * 3];
+    const float M02 = matrix[0 + 2 * 3];
+    const float M12 = matrix[1 + 2 * 3];
+    const float M22 = matrix[2 + 2 * 3];
+
+    const int width  = src.shape().x();
+    const int height = src.shape().y();
+
+    for(int element_idx = 0; element_idx < src.num_elements(); ++element_idx)
+    {
+        valid_mask[element_idx] = 1;
+        Coordinates id          = index2coord(src.shape(), element_idx);
+        const int   idx         = id.x();
+        const int   idy         = id.y();
+        const float z0          = M20 * idx + M21 * idy + M22;
+
+        const float x0 = (M00 * idx + M01 * idy + M02);
+        const float y0 = (M10 * idx + M11 * idy + M12);
+
+        const float xn = x0 / z0;
+        const float yn = y0 / z0;
+        id.set(0, static_cast<int>(std::floor(xn)));
+        id.set(1, static_cast<int>(std::floor(yn)));
+        if((0 <= yn) && (yn < height) && (0 <= xn) && (xn < width))
+        {
+            switch(policy)
+            {
+                case InterpolationPolicy::NEAREST_NEIGHBOR:
+                    dst[element_idx] = tensor_elem_at(src, id, border_mode, constant_border_value);
+                    break;
+                case InterpolationPolicy::BILINEAR:
+                    (valid_bilinear_policy(xn, yn, width, height, border_mode)) ? dst[element_idx] = bilinear_policy(src, id, xn, yn, border_mode, constant_border_value) : valid_mask[element_idx] = 0;
+                    break;
+                case InterpolationPolicy::AREA:
+                default:
+                    ARM_COMPUTE_ERROR("Interpolation not supported");
+                    break;
+            }
+        }
+        else
+        {
+            if(border_mode == BorderMode::UNDEFINED)
+            {
+                valid_mask[element_idx] = 0;
+            }
+            else
+            {
+                switch(policy)
+                {
+                    case InterpolationPolicy::NEAREST_NEIGHBOR:
+                        if(border_mode == BorderMode::CONSTANT)
+                        {
+                            dst[element_idx] = constant_border_value;
+                        }
+                        else if(border_mode == BorderMode::REPLICATE)
+                        {
+                            id.set(0, std::max(0, std::min(static_cast<int>(xn), width - 1)));
+                            id.set(1, std::max(0, std::min(static_cast<int>(yn), height - 1)));
+                            dst[element_idx] = src[coord2index(src.shape(), id)];
+                        }
+                        break;
+                    case InterpolationPolicy::BILINEAR:
+                        dst[element_idx] = bilinear_policy(src, id, xn, yn, border_mode, constant_border_value);
+                        break;
+                    case InterpolationPolicy::AREA:
+                    default:
+                        ARM_COMPUTE_ERROR("Interpolation not supported");
+                        break;
+                }
+            }
+        }
+    }
+    return dst;
+}
+
+template SimpleTensor<uint8_t> warp_perspective(const SimpleTensor<uint8_t> &src, SimpleTensor<uint8_t> &valid_mask, const float *matrix, InterpolationPolicy policy, BorderMode border_mode,
+                                                uint8_t constant_border_value);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/reference/WarpPerspective.h b/tests/validation/reference/WarpPerspective.h
new file mode 100644
index 0000000..2367f4d
--- /dev/null
+++ b/tests/validation/reference/WarpPerspective.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_WARP_PERSPECTIVE_H__
+#define __ARM_COMPUTE_TEST_WARP_PERSPECTIVE_H__
+
+#include "tests/SimpleTensor.h"
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+namespace reference
+{
+template <typename T>
+SimpleTensor<T> warp_perspective(const SimpleTensor<T> &src, SimpleTensor<T> &valid_mask, const float *matrix, InterpolationPolicy policy, BorderMode border_mode, uint8_t constant_border_value);
+} // namespace reference
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_WARP_PERSPECTIVE_H__ */