IVGCVSW-3880 Add serialization support for SLICE

Signed-off-by: Aron Virginas-Tar <Aron.Virginas-Tar@arm.com>
Change-Id: I5eaf61cfd2c875805d2f37cd967d75ad1d20ad6d
diff --git a/src/armnnDeserializer/Deserializer.cpp b/src/armnnDeserializer/Deserializer.cpp
index 1dab9bf..1c4d86c 100644
--- a/src/armnnDeserializer/Deserializer.cpp
+++ b/src/armnnDeserializer/Deserializer.cpp
@@ -222,6 +222,7 @@
     m_ParserFunctions[Layer_ResizeBilinearLayer]         = &Deserializer::ParseResizeBilinear;
     m_ParserFunctions[Layer_ResizeLayer]                 = &Deserializer::ParseResize;
     m_ParserFunctions[Layer_RsqrtLayer]                  = &Deserializer::ParseRsqrt;
+    m_ParserFunctions[Layer_SliceLayer]                  = &Deserializer::ParseSlice;
     m_ParserFunctions[Layer_SoftmaxLayer]                = &Deserializer::ParseSoftmax;
     m_ParserFunctions[Layer_SpaceToBatchNdLayer]         = &Deserializer::ParseSpaceToBatchNd;
     m_ParserFunctions[Layer_SpaceToDepthLayer]           = &Deserializer::ParseSpaceToDepth;
@@ -317,6 +318,8 @@
             return graphPtr->layers()->Get(layerIndex)->layer_as_ResizeLayer()->base();
         case Layer::Layer_RsqrtLayer:
             return graphPtr->layers()->Get(layerIndex)->layer_as_RsqrtLayer()->base();
+        case Layer::Layer_SliceLayer:
+            return graphPtr->layers()->Get(layerIndex)->layer_as_SliceLayer()->base();
         case Layer::Layer_SoftmaxLayer:
             return graphPtr->layers()->Get(layerIndex)->layer_as_SoftmaxLayer()->base();
         case Layer::Layer_SpaceToBatchNdLayer:
@@ -338,8 +341,8 @@
         case Layer::Layer_NONE:
         default:
             throw ParseException(boost::str(
-                  boost::format("Layer must have a type %1%") %
-                  Layer::Layer_NONE));
+                  boost::format("Layer type %1% not recognized") %
+                  layerType));
     }
 }
 
@@ -1989,6 +1992,41 @@
     RegisterOutputSlots(graph, layerIndex, layer);
 }
 
+void Deserializer::ParseSlice(GraphPtr graph, unsigned int layerIndex)
+{
+    CHECK_LAYERS(graph, 0, layerIndex);
+
+    auto inputs = GetInputs(graph, layerIndex);
+    CHECK_VALID_SIZE(inputs.size(), 1);
+
+    auto outputs = GetOutputs(graph, layerIndex);
+    CHECK_VALID_SIZE(outputs.size(), 1);
+
+    auto fbDescriptor = graph->layers()->Get(layerIndex)->layer_as_SliceLayer()->descriptor();
+
+    auto fbBegin = fbDescriptor->begin();
+    auto fbSize  = fbDescriptor->size();
+
+    if (fbBegin->Length() != fbSize->Length())
+    {
+        throw ParseException(boost::str(
+            boost::format("Begin and size descriptors must have the same length %1%") % CHECK_LOCATION().AsString()));
+    }
+
+    armnn::SliceDescriptor descriptor;
+    descriptor.m_Begin.insert(descriptor.m_Begin.end(), fbBegin->begin(), fbBegin->end());
+    descriptor.m_Size.insert(descriptor.m_Size.end(), fbSize->begin(), fbSize->end());
+
+    auto layerName = GetLayerName(graph, layerIndex);
+    IConnectableLayer* layer = m_Network->AddSliceLayer(descriptor, layerName.c_str());
+
+    armnn::TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
+    layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
+
+    RegisterInputSlots(graph, layerIndex, layer);
+    RegisterOutputSlots(graph, layerIndex, layer);
+}
+
 void Deserializer::ParseStridedSlice(GraphPtr graph, unsigned int layerIndex)
 {
     CHECK_LAYERS(graph, 0, layerIndex);
diff --git a/src/armnnDeserializer/Deserializer.hpp b/src/armnnDeserializer/Deserializer.hpp
index f7743bc..30af024 100644
--- a/src/armnnDeserializer/Deserializer.hpp
+++ b/src/armnnDeserializer/Deserializer.hpp
@@ -113,6 +113,7 @@
     void ParseResize(GraphPtr graph, unsigned int layerIndex);
     void ParseResizeBilinear(GraphPtr graph, unsigned int layerIndex);
     void ParseRsqrt(GraphPtr graph, unsigned int layerIndex);
+    void ParseSlice(GraphPtr graph, unsigned int layerIndex);
     void ParseSoftmax(GraphPtr graph, unsigned int layerIndex);
     void ParseSpaceToBatchNd(GraphPtr graph, unsigned int layerIndex);
     void ParseSpaceToDepth(GraphPtr graph, unsigned int layerIndex);
diff --git a/src/armnnDeserializer/DeserializerSupport.md b/src/armnnDeserializer/DeserializerSupport.md
index 2fd706d..46bf92e 100644
--- a/src/armnnDeserializer/DeserializerSupport.md
+++ b/src/armnnDeserializer/DeserializerSupport.md
@@ -41,6 +41,7 @@
 * Reshape
 * ResizeBilinear
 * Rsqrt
+* Slice
 * Softmax
 * SpaceToBatchNd
 * SpaceToDepth
diff --git a/src/armnnSerializer/ArmnnSchema.fbs b/src/armnnSerializer/ArmnnSchema.fbs
index 97d2780..6b07510 100644
--- a/src/armnnSerializer/ArmnnSchema.fbs
+++ b/src/armnnSerializer/ArmnnSchema.fbs
@@ -139,7 +139,8 @@
     Stack = 44,
     QuantizedLstm = 45,
     Abs = 46,
-    ArgMinMax = 47
+    ArgMinMax = 47,
+    Slice = 48
 }
 
 // Base layer table to be used as part of other layers
@@ -471,6 +472,16 @@
     dataLayout:DataLayout;
 }
 
+table SliceLayer {
+    base:LayerBase;
+    descriptor:SliceDescriptor;
+}
+
+table SliceDescriptor {
+    begin:[uint];
+    size:[uint];
+}
+
 table StridedSliceLayer {
     base:LayerBase;
     descriptor:StridedSliceDescriptor;
@@ -710,7 +721,8 @@
     ResizeLayer,
     StackLayer,
     AbsLayer,
-    ArgMinMaxLayer
+    ArgMinMaxLayer,
+    SliceLayer
 }
 
 table AnyLayer {
diff --git a/src/armnnSerializer/Serializer.cpp b/src/armnnSerializer/Serializer.cpp
index 06bfb91..16b7cff 100644
--- a/src/armnnSerializer/Serializer.cpp
+++ b/src/armnnSerializer/Serializer.cpp
@@ -749,7 +749,14 @@
                                         const armnn::SliceDescriptor& sliceDescriptor,
                                         const char* name)
 {
-    throw UnimplementedException("SerializerVisitor::VisitSliceLayer is not implemented");
+    auto fbSliceBaseLayer  = CreateLayerBase(layer, serializer::LayerType::LayerType_Slice);
+    auto fbSliceDescriptor = CreateSliceDescriptor(m_flatBufferBuilder,
+                                                   m_flatBufferBuilder.CreateVector(sliceDescriptor.m_Begin),
+                                                   m_flatBufferBuilder.CreateVector(sliceDescriptor.m_Size));
+
+    auto fbSliceLayer = serializer::CreateSliceLayer(m_flatBufferBuilder, fbSliceBaseLayer, fbSliceDescriptor);
+
+    CreateAnyLayer(fbSliceLayer.o, serializer::Layer::Layer_SliceLayer);
 }
 
 // Build FlatBuffer for Softmax Layer
diff --git a/src/armnnSerializer/SerializerSupport.md b/src/armnnSerializer/SerializerSupport.md
index 534e9fa..136998c 100644
--- a/src/armnnSerializer/SerializerSupport.md
+++ b/src/armnnSerializer/SerializerSupport.md
@@ -42,6 +42,7 @@
 * Resize
 * ResizeBilinear
 * Rsqrt
+* Slice
 * Softmax
 * SpaceToBatchNd
 * SpaceToDepth
diff --git a/src/armnnSerializer/test/SerializerTests.cpp b/src/armnnSerializer/test/SerializerTests.cpp
index bbd5402..d4ad623 100644
--- a/src/armnnSerializer/test/SerializerTests.cpp
+++ b/src/armnnSerializer/test/SerializerTests.cpp
@@ -2259,6 +2259,65 @@
     deserializedNetwork->Accept(verifier);
 }
 
+BOOST_AUTO_TEST_CASE(SerializeSlice)
+{
+    class SliceLayerVerifier : public LayerVerifierBase
+    {
+    public:
+        SliceLayerVerifier(const std::string& layerName,
+                           const std::vector<armnn::TensorInfo>& inputInfos,
+                           const std::vector<armnn::TensorInfo>& outputInfos,
+                           const armnn::SliceDescriptor& descriptor)
+            : LayerVerifierBase(layerName, inputInfos, outputInfos)
+            , m_Descriptor(descriptor) {}
+
+        void VisitSliceLayer(const armnn::IConnectableLayer* layer,
+                             const armnn::SliceDescriptor& descriptor,
+                             const char* name) override
+        {
+            VerifyNameAndConnections(layer, name);
+            VerifyDescriptor(descriptor);
+        }
+
+    private:
+        void VerifyDescriptor(const armnn::SliceDescriptor& descriptor)
+        {
+            BOOST_CHECK_EQUAL_COLLECTIONS(descriptor.m_Begin.begin(), descriptor.m_Begin.end(),
+                                          m_Descriptor.m_Begin.begin(), m_Descriptor.m_Begin.end());
+
+            BOOST_CHECK_EQUAL_COLLECTIONS(descriptor.m_Size.begin(), descriptor.m_Size.end(),
+                                          m_Descriptor.m_Size.begin(), m_Descriptor.m_Size.end());
+        }
+
+        armnn::SliceDescriptor m_Descriptor;
+    };
+
+    const std::string layerName{"slice"};
+
+    const armnn::TensorInfo inputInfo  = armnn::TensorInfo({3, 2, 3, 1}, armnn::DataType::Float32);
+    const armnn::TensorInfo outputInfo = armnn::TensorInfo({2, 2, 2, 1}, armnn::DataType::Float32);
+
+    armnn::SliceDescriptor descriptor({ 0, 0, 1, 0}, {2, 2, 2, 1});
+
+    armnn::INetworkPtr network = armnn::INetwork::Create();
+
+    armnn::IConnectableLayer* const inputLayer  = network->AddInputLayer(0);
+    armnn::IConnectableLayer* const sliceLayer  = network->AddSliceLayer(descriptor, layerName.c_str());
+    armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
+
+    inputLayer->GetOutputSlot(0).Connect(sliceLayer->GetInputSlot(0));
+    sliceLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
+
+    inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
+    sliceLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
+
+    armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
+    BOOST_CHECK(deserializedNetwork);
+
+    SliceLayerVerifier verifier(layerName, {inputInfo}, {outputInfo}, descriptor);
+    deserializedNetwork->Accept(verifier);
+}
+
 BOOST_AUTO_TEST_CASE(SerializeSoftmax)
 {
     class SoftmaxLayerVerifier : public LayerVerifierBase