IVGCVSW-2771 Add end to end tests for splitter on Cl, Neon, Ref

Signed-off-by: Narumol Prangnawarat <narumol.prangnawarat@arm.com>
Change-Id: I44f8f1799f6182721751b1d117c9ada5b91f52e1
diff --git a/src/backends/backendsCommon/test/CMakeLists.txt b/src/backends/backendsCommon/test/CMakeLists.txt
index f91fd9c..8050a0a 100644
--- a/src/backends/backendsCommon/test/CMakeLists.txt
+++ b/src/backends/backendsCommon/test/CMakeLists.txt
@@ -44,6 +44,7 @@
     ReshapeTestImpl.hpp
     RuntimeTestImpl.hpp
     SoftmaxTestImpl.hpp
+    SplitterEndToEndTestImpl.hpp
     SplitterTestImpl.hpp
     StridedSliceTestImpl.hpp
     TensorCopyUtils.cpp
diff --git a/src/backends/backendsCommon/test/SplitterEndToEndTestImpl.hpp b/src/backends/backendsCommon/test/SplitterEndToEndTestImpl.hpp
new file mode 100644
index 0000000..f9fbcf5
--- /dev/null
+++ b/src/backends/backendsCommon/test/SplitterEndToEndTestImpl.hpp
@@ -0,0 +1,380 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+#pragma once
+
+#include <ResolveType.hpp>
+
+#include <armnn/INetwork.hpp>
+
+#include <backendsCommon/test/CommonTestUtils.hpp>
+
+#include <boost/test/unit_test.hpp>
+
+#include <vector>
+
+namespace
+{
+
+template<typename armnn::DataType DataType>
+INetworkPtr CreateSplitterNetwork(const TensorShape& inputShape,
+                                  const std::vector<TensorShape>& outputShapes,
+                                  unsigned int splitAxis,
+                                  unsigned int numSplit,
+                                  const float qScale = 1.0f,
+                                  const int32_t qOffset = 0)
+{
+    using namespace armnn;
+    // Builds up the structure of the network.
+    INetworkPtr net(INetwork::Create());
+
+    TensorInfo inputTensorInfo(inputShape, DataType, qScale, qOffset);
+
+    std::vector<unsigned int> splitterDimSizes(inputShape.GetNumDimensions());
+
+    // Add current input shape to splitterDimSizes
+    for (unsigned int i = 0; i < inputShape.GetNumDimensions(); ++i)
+    {
+        splitterDimSizes[i] = inputTensorInfo.GetShape()[i];
+    }
+
+    if (splitterDimSizes[splitAxis] % numSplit != 0)
+    {
+        throw ParseException("Number of splits must evenly divide the dimension");
+    }
+    splitterDimSizes[splitAxis] /= numSplit;
+
+    SplitterDescriptor splitDesc(numSplit);
+    for (unsigned int g = 0; g < numSplit; ++g)
+    {
+        // Set the size of the views.
+        for (unsigned int dimIdx = 0; dimIdx < splitterDimSizes.size(); ++dimIdx)
+        {
+            splitDesc.SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]);
+        }
+        splitDesc.SetViewOriginCoord(g, splitAxis, splitterDimSizes[splitAxis] * g);
+    }
+
+    IConnectableLayer* splitter = net->AddSplitterLayer(splitDesc, "splitter");
+    IConnectableLayer* input = net->AddInputLayer(0, "input");
+    Connect(input, splitter, inputTensorInfo, 0, 0);
+
+    for (unsigned int i = 0; i < outputShapes.size(); ++i)
+    {
+        TensorInfo outputTensorInfo(outputShapes[i], DataType, qScale, qOffset);
+        IConnectableLayer* output = net->AddOutputLayer(boost::numeric_cast<LayerBindingId>(i));
+        Connect(splitter, output, outputTensorInfo, i, 0);
+    }
+
+    return net;
+}
+
+template<armnn::DataType ArmnnType>
+void SplitterDim0EndToEnd(const std::vector<BackendId>& backends)
+{
+    using namespace armnn;
+    using T = ResolveType<ArmnnType>;
+
+    unsigned int splitAxis = 0;
+    unsigned int numSplit = 2;
+    const TensorShape& inputShape = { 4, 3, 2, 2 };
+    const std::vector<TensorShape> outputShapes{{ 2, 3, 2, 2 }, { 2, 3, 2, 2 }};
+
+    // Builds up the structure of the network
+    INetworkPtr net = CreateSplitterNetwork<ArmnnType>(inputShape, outputShapes, splitAxis, numSplit);
+
+    BOOST_TEST_CHECKPOINT("create a network");
+
+    // Creates structures for input & output.
+    std::vector<T> inputData{
+            1, 2,
+            3, 4,
+            5, 6,
+            7, 8,
+            9, 10,
+            11, 12,
+            13, 14,
+            15, 16,
+            17, 18,
+            19, 20,
+            21, 22,
+            23, 24,
+            25, 26,
+            27, 28,
+            29, 30,
+            31, 32,
+            33, 34,
+            35, 36,
+            37, 38,
+            39, 40,
+            41, 42,
+            43, 44,
+            45, 46,
+            47, 48
+    };
+
+    std::vector<T> expectedOutput0{
+            1, 2,
+            3, 4,
+            5, 6,
+            7, 8,
+            9, 10,
+            11, 12,
+            13, 14,
+            15, 16,
+            17, 18,
+            19, 20,
+            21, 22,
+            23, 24
+    };
+
+    std::vector<T> expectedOutput1{
+            25, 26,
+            27, 28,
+            29, 30,
+            31, 32,
+            33, 34,
+            35, 36,
+            37, 38,
+            39, 40,
+            41, 42,
+            43, 44,
+            45, 46,
+            47, 48
+    };
+
+    std::map<int, std::vector<T>> inputTensorData = {{ 0,inputData }};
+    std::map<int, std::vector<T>> expectedOutputData = {{ 0, expectedOutput0 }, { 1, expectedOutput1 }};
+
+    EndToEndLayerTestImpl<ArmnnType, ArmnnType>(move(net), inputTensorData, expectedOutputData, backends);
+}
+
+template<armnn::DataType ArmnnType>
+void SplitterDim1EndToEnd(const std::vector<BackendId>& backends)
+{
+    using namespace armnn;
+    using T = ResolveType<ArmnnType>;
+
+    unsigned int splitAxis = 1;
+    unsigned int numSplit = 2;
+    const TensorShape& inputShape = { 2, 6, 2, 2 };
+    const std::vector<TensorShape> outputShapes{{ 2, 3, 2, 2 }, { 2, 3, 2, 2 }};
+
+    // Builds up the structure of the network
+    INetworkPtr net = CreateSplitterNetwork<ArmnnType>(inputShape, outputShapes, splitAxis, numSplit);
+
+    BOOST_TEST_CHECKPOINT("create a network");
+
+    // Creates structures for input & output.
+    std::vector<T> inputData{
+            1, 2,
+            3, 4,
+            5, 6,
+            7, 8,
+            9, 10,
+            11, 12,
+            13, 14,
+            15, 16,
+            17, 18,
+            19, 20,
+            21, 22,
+            23, 24,
+            25, 26,
+            27, 28,
+            29, 30,
+            31, 32,
+            33, 34,
+            35, 36,
+            37, 38,
+            39, 40,
+            41, 42,
+            43, 44,
+            45, 46,
+            47, 48
+    };
+
+    std::vector<T> expectedOutput0{
+            1, 2,
+            3, 4,
+            5, 6,
+            7, 8,
+            9, 10,
+            11, 12,
+            25, 26,
+            27, 28,
+            29, 30,
+            31, 32,
+            33, 34,
+            35, 36
+    };
+
+    std::vector<T> expectedOutput1{
+            13, 14,
+            15, 16,
+            17, 18,
+            19, 20,
+            21, 22,
+            23, 24,
+            37, 38,
+            39, 40,
+            41, 42,
+            43, 44,
+            45, 46,
+            47, 48
+    };
+
+    std::map<int, std::vector<T>> inputTensorData = {{ 0,inputData }};
+    std::map<int, std::vector<T>> expectedOutputData = {{ 0, expectedOutput0 }, { 1, expectedOutput1 }};
+
+    EndToEndLayerTestImpl<ArmnnType, ArmnnType>(move(net), inputTensorData, expectedOutputData, backends);
+}
+
+template<armnn::DataType ArmnnType>
+void SplitterDim2EndToEnd(const std::vector<BackendId>& backends)
+{
+    using namespace armnn;
+    using T = ResolveType<ArmnnType>;
+
+    unsigned int splitAxis = 2;
+    unsigned int numSplit = 2;
+    const TensorShape& inputShape = { 2, 3, 4, 2 };
+    const std::vector<TensorShape> outputShapes{{ 2, 3, 2, 2 }, { 2, 3, 2, 2 }};
+
+    // Builds up the structure of the network
+    INetworkPtr net = CreateSplitterNetwork<ArmnnType>(inputShape, outputShapes, splitAxis, numSplit);
+
+    BOOST_TEST_CHECKPOINT("create a network");
+
+    // Creates structures for input & output.
+    std::vector<T> inputData{
+            1, 2,
+            3, 4,
+            5, 6,
+            7, 8,
+            9, 10,
+            11, 12,
+            13, 14,
+            15, 16,
+            17, 18,
+            19, 20,
+            21, 22,
+            23, 24,
+            25, 26,
+            27, 28,
+            29, 30,
+            31, 32,
+            33, 34,
+            35, 36,
+            37, 38,
+            39, 40,
+            41, 42,
+            43, 44,
+            45, 46,
+            47, 48
+    };
+
+    std::vector<T> expectedOutput0{
+            1, 2,
+            3, 4,
+            9, 10,
+            11, 12,
+            17, 18,
+            19, 20,
+            25, 26,
+            27, 28,
+            33, 34,
+            35, 36,
+            41, 42,
+            43, 44
+    };
+
+    std::vector<T> expectedOutput1{
+            5, 6,
+            7, 8,
+            13, 14,
+            15, 16,
+            21, 22,
+            23, 24,
+            29, 30,
+            31, 32,
+            37, 38,
+            39, 40,
+            45, 46,
+            47, 48
+    };
+
+    std::map<int, std::vector<T>> inputTensorData = {{ 0,inputData }};
+    std::map<int, std::vector<T>> expectedOutputData = {{ 0, expectedOutput0 }, { 1, expectedOutput1 }};
+
+    EndToEndLayerTestImpl<ArmnnType, ArmnnType>(move(net), inputTensorData, expectedOutputData, backends);
+}
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+void SplitterDim3EndToEnd(const std::vector<BackendId>& backends)
+{
+    using namespace armnn;
+
+    unsigned int splitAxis = 3;
+    unsigned int numSplit = 2;
+    const TensorShape& inputShape = { 2, 3, 4, 2 };
+    const std::vector<TensorShape> outputShapes{{ 2, 3, 4, 1 }, { 2, 3, 4, 1 }};
+
+    // Builds up the structure of the network
+    INetworkPtr net = CreateSplitterNetwork<ArmnnType>(inputShape, outputShapes, splitAxis, numSplit);
+
+    BOOST_TEST_CHECKPOINT("create a network");
+
+    // Creates structures for input & output.
+    std::vector<T> inputData{
+            1, 2,
+            3, 4,
+            5, 6,
+            7, 8,
+            9, 10,
+            11, 12,
+            13, 14,
+            15, 16,
+            17, 18,
+            19, 20,
+            21, 22,
+            23, 24,
+            25, 26,
+            27, 28,
+            29, 30,
+            31, 32,
+            33, 34,
+            35, 36,
+            37, 38,
+            39, 40,
+            41, 42,
+            43, 44,
+            45, 46,
+            47, 48
+    };
+
+    std::vector<T> expectedOutput0{
+            1, 3, 5, 7,
+            9, 11, 13, 15,
+            17, 19, 21, 23,
+            25, 27, 29, 31,
+            33, 35, 37, 39,
+            41, 43, 45, 47
+    };
+
+    std::vector<T> expectedOutput1{
+            2, 4, 6, 8,
+            10, 12, 14, 16,
+            18, 20, 22, 24,
+            26, 28, 30, 32,
+            34, 36, 38, 40,
+            42, 44, 46, 48
+    };
+
+    std::map<int, std::vector<T>> inputTensorData = {{ 0,inputData }};
+    std::map<int, std::vector<T>> expectedOutputData = {{ 0, expectedOutput0 }, { 1, expectedOutput1 }};
+
+    EndToEndLayerTestImpl<ArmnnType, ArmnnType>(move(net), inputTensorData, expectedOutputData, backends);
+}
+
+} // anonymous namespace
diff --git a/src/backends/cl/test/ClEndToEndTests.cpp b/src/backends/cl/test/ClEndToEndTests.cpp
index bc0bad2..9c010fc 100644
--- a/src/backends/cl/test/ClEndToEndTests.cpp
+++ b/src/backends/cl/test/ClEndToEndTests.cpp
@@ -6,6 +6,7 @@
 #include <backendsCommon/test/EndToEndTestImpl.hpp>
 #include <backendsCommon/test/MergerTestImpl.hpp>
 #include <backendsCommon/test/ArithmeticTestImpl.hpp>
+#include <backendsCommon/test/SplitterEndToEndTestImpl.hpp>
 
 #include <boost/test/unit_test.hpp>
 
@@ -88,5 +89,45 @@
                                                                                             expectedOutput);
 }
 
+BOOST_AUTO_TEST_CASE(ClSplitDim0EndToEndTest)
+{
+    SplitterDim0EndToEnd<armnn::DataType::Float32>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(ClSplitDim1EndToEndTest)
+{
+    SplitterDim1EndToEnd<armnn::DataType::Float32>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(ClSplitDim2EndToEndTest)
+{
+    SplitterDim2EndToEnd<armnn::DataType::Float32>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(ClSplitDim3EndToEndTest)
+{
+    SplitterDim3EndToEnd<armnn::DataType::Float32>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(ClSplitDim0EndToEndUint8Test)
+{
+    SplitterDim0EndToEnd<armnn::DataType::QuantisedAsymm8>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(ClSplitDim1EndToEndUint8Test)
+{
+    SplitterDim1EndToEnd<armnn::DataType::QuantisedAsymm8>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(ClSplitDim2EndToEndUint8Test)
+{
+    SplitterDim2EndToEnd<armnn::DataType::QuantisedAsymm8>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(ClSplitDim3EndToEndUint8Test)
+{
+    SplitterDim3EndToEnd<armnn::DataType::QuantisedAsymm8>(defaultBackends);
+}
+
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/backends/neon/test/NeonEndToEndTests.cpp b/src/backends/neon/test/NeonEndToEndTests.cpp
index deaa8eb..441efed 100644
--- a/src/backends/neon/test/NeonEndToEndTests.cpp
+++ b/src/backends/neon/test/NeonEndToEndTests.cpp
@@ -6,6 +6,7 @@
 #include <backendsCommon/test/EndToEndTestImpl.hpp>
 #include <backendsCommon/test/MergerTestImpl.hpp>
 #include <backendsCommon/test/ArithmeticTestImpl.hpp>
+#include <backendsCommon/test/SplitterEndToEndTestImpl.hpp>
 
 #include <boost/test/unit_test.hpp>
 
@@ -122,4 +123,44 @@
     MergerDim3EndToEnd<armnn::DataType::QuantisedAsymm8>(defaultBackends);
 }
 
+BOOST_AUTO_TEST_CASE(NeonSplitDim0EndToEndTest)
+{
+    SplitterDim0EndToEnd<armnn::DataType::Float32>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(NeonSplitDim1EndToEndTest)
+{
+    SplitterDim1EndToEnd<armnn::DataType::Float32>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(NeonSplitDim2EndToEndTest)
+{
+    SplitterDim2EndToEnd<armnn::DataType::Float32>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(NeonSplitDim3EndToEndTest)
+{
+    SplitterDim3EndToEnd<armnn::DataType::Float32>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(NeonSplitDim0EndToEndUint8Test)
+{
+    SplitterDim0EndToEnd<armnn::DataType::QuantisedAsymm8>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(NeonSplitDim1EndToEndUint8Test)
+{
+    SplitterDim1EndToEnd<armnn::DataType::QuantisedAsymm8>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(NeonSplitDim2EndToEndUint8Test)
+{
+    SplitterDim2EndToEnd<armnn::DataType::QuantisedAsymm8>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(NeonSplitDim3EndToEndUint8Test)
+{
+    SplitterDim3EndToEnd<armnn::DataType::QuantisedAsymm8>(defaultBackends);
+}
+
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/backends/reference/test/RefEndToEndTests.cpp b/src/backends/reference/test/RefEndToEndTests.cpp
index c89e586..6dacfab 100644
--- a/src/backends/reference/test/RefEndToEndTests.cpp
+++ b/src/backends/reference/test/RefEndToEndTests.cpp
@@ -9,6 +9,7 @@
 #include <backendsCommon/test/GatherEndToEndTestImpl.hpp>
 #include <backendsCommon/test/MergerTestImpl.hpp>
 #include <backendsCommon/test/ArithmeticTestImpl.hpp>
+#include <backendsCommon/test/SplitterEndToEndTestImpl.hpp>
 
 #include <boost/test/unit_test.hpp>
 #include <boost/test/execution_monitor.hpp>
@@ -619,4 +620,44 @@
                                                                           1.0f, 1, 0.01f, 0, 0.5f, 0);
 }
 
+BOOST_AUTO_TEST_CASE(RefSplitDim0EndToEndTest)
+{
+    SplitterDim0EndToEnd<armnn::DataType::Float32>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(RefSplitDim1EndToEndTest)
+{
+    SplitterDim1EndToEnd<armnn::DataType::Float32>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(RefSplitDim2EndToEndTest)
+{
+    SplitterDim2EndToEnd<armnn::DataType::Float32>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(RefSplitDim3EndToEndTest)
+{
+    SplitterDim3EndToEnd<armnn::DataType::Float32>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(RefSplitDim0EndToEndUint8Test)
+{
+    SplitterDim0EndToEnd<armnn::DataType::QuantisedAsymm8>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(RefSplitDim1EndToEndUint8Test)
+{
+    SplitterDim1EndToEnd<armnn::DataType::QuantisedAsymm8>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(RefSplitDim2EndToEndUint8Test)
+{
+    SplitterDim2EndToEnd<armnn::DataType::QuantisedAsymm8>(defaultBackends);
+}
+
+BOOST_AUTO_TEST_CASE(RefSplitDim3EndToEndUint8Test)
+{
+    SplitterDim3EndToEnd<armnn::DataType::QuantisedAsymm8>(defaultBackends);
+}
+
 BOOST_AUTO_TEST_SUITE_END()