IVGCVSW-2711 Add Serializer and Deserializer for Subtraction

Change-Id: I87836b5314c1f791b4df2ca90d239573ca28a2da
Signed-off-by: Conor Kennedy <conor.kennedy@arm.com>
Signed-off-by: Matteo Martincigh <matteo.martincigh@arm.com>
diff --git a/src/armnnSerializer/ArmnnSchema.fbs b/src/armnnSerializer/ArmnnSchema.fbs
index dea5889..9f1d8ec 100644
--- a/src/armnnSerializer/ArmnnSchema.fbs
+++ b/src/armnnSerializer/ArmnnSchema.fbs
@@ -106,7 +106,8 @@
     Floor = 22,
     BatchNormalization = 23,
     Greater = 24,
-    ResizeBilinear = 25
+    ResizeBilinear = 25,
+    Subtraction = 26
 }
 
 // Base layer table to be used as part of other layers
@@ -302,6 +303,10 @@
     dataLayout:DataLayout;
 }
 
+table SubtractionLayer {
+    base:LayerBase;
+}
+
 table BatchToSpaceNdLayer {
     base:LayerBase;
     descriptor:BatchToSpaceNdDescriptor;
@@ -402,7 +407,8 @@
     RsqrtLayer,
     FloorLayer,
     GreaterLayer,
-    ResizeBilinearLayer
+    ResizeBilinearLayer,
+    SubtractionLayer
 }
 
 table AnyLayer {
diff --git a/src/armnnSerializer/Serializer.cpp b/src/armnnSerializer/Serializer.cpp
index d6df61c..93231d0 100644
--- a/src/armnnSerializer/Serializer.cpp
+++ b/src/armnnSerializer/Serializer.cpp
@@ -588,6 +588,14 @@
     CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_NormalizationLayer);
 }
 
+void SerializerVisitor::VisitSubtractionLayer(const armnn::IConnectableLayer* layer, const char* name)
+{
+    auto fbSubtractionBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Subtraction);
+    auto fbSubtractionLayer = serializer::CreateSubtractionLayer(m_flatBufferBuilder, fbSubtractionBaseLayer);
+
+    CreateAnyLayer(fbSubtractionLayer.o, serializer::Layer::Layer_SubtractionLayer);
+}
+
 fb::Offset<serializer::LayerBase> SerializerVisitor::CreateLayerBase(const IConnectableLayer* layer,
                                                                      const serializer::LayerType layerType)
 {
diff --git a/src/armnnSerializer/Serializer.hpp b/src/armnnSerializer/Serializer.hpp
index bbc67d4..b6f5974 100644
--- a/src/armnnSerializer/Serializer.hpp
+++ b/src/armnnSerializer/Serializer.hpp
@@ -146,6 +146,9 @@
     void VisitNormalizationLayer(const armnn::IConnectableLayer* layer,
                                  const armnn::NormalizationDescriptor& normalizationDescriptor,
                                  const char* name = nullptr) override;
+
+    void VisitSubtractionLayer(const armnn::IConnectableLayer* layer,
+                               const char* name = nullptr) override;
 private:
 
     /// Creates the Input Slots and Output Slots and LayerBase for the layer.
diff --git a/src/armnnSerializer/SerializerSupport.md b/src/armnnSerializer/SerializerSupport.md
index 6071c9c..141a6fa 100644
--- a/src/armnnSerializer/SerializerSupport.md
+++ b/src/armnnSerializer/SerializerSupport.md
@@ -30,5 +30,6 @@
 * Rsqrt
 * Softmax
 * SpaceToBatchNd
+* Subtraction
 
 More machine learning layers will be supported in future releases.
diff --git a/src/armnnSerializer/test/SerializerTests.cpp b/src/armnnSerializer/test/SerializerTests.cpp
index ad6676e..572ee80 100644
--- a/src/armnnSerializer/test/SerializerTests.cpp
+++ b/src/armnnSerializer/test/SerializerTests.cpp
@@ -1250,4 +1250,44 @@
                                             {outputTensorInfo.GetShape()});
 }
 
+BOOST_AUTO_TEST_CASE(SerializeDeserializeSubtraction)
+{
+    class VerifySubtractionName : public armnn::LayerVisitorBase<armnn::VisitorNoThrowPolicy>
+    {
+    public:
+        void VisitSubtractionLayer(const armnn::IConnectableLayer*, const char* name) override
+        {
+            BOOST_TEST(name == "subtraction");
+        }
+    };
+
+    const armnn::TensorInfo info = armnn::TensorInfo({ 1, 4 }, armnn::DataType::Float32);
+
+    armnn::INetworkPtr network = armnn::INetwork::Create();
+    armnn::IConnectableLayer* const inputLayer0 = network->AddInputLayer(0);
+    armnn::IConnectableLayer* const inputLayer1 = network->AddInputLayer(1);
+    armnn::IConnectableLayer* const subtractionLayer = network->AddSubtractionLayer("subtraction");
+    armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
+
+    inputLayer0->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(0));
+    inputLayer1->GetOutputSlot(0).Connect(subtractionLayer->GetInputSlot(1));
+    subtractionLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
+
+    inputLayer0->GetOutputSlot(0).SetTensorInfo(info);
+    inputLayer1->GetOutputSlot(0).SetTensorInfo(info);
+    subtractionLayer->GetOutputSlot(0).SetTensorInfo(info);
+
+    armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
+    BOOST_CHECK(deserializedNetwork);
+
+    VerifySubtractionName nameChecker;
+    deserializedNetwork->Accept(nameChecker);
+
+    CheckDeserializedNetworkAgainstOriginal(*network,
+                                            *deserializedNetwork,
+                                            {info.GetShape(), info.GetShape()},
+                                            {info.GetShape()},
+                                            {0, 1});
+}
+
 BOOST_AUTO_TEST_SUITE_END()