IVGCVSW-1881 Add PadLayer to ArmNN

Change-Id: Ib70883a20fa7b82bfb090aa98cc51a6d645b5722
diff --git a/src/armnn/InternalTypes.hpp b/src/armnn/InternalTypes.hpp
index 13ab2bc..1a612e9 100644
--- a/src/armnn/InternalTypes.hpp
+++ b/src/armnn/InternalTypes.hpp
@@ -35,6 +35,7 @@
     Multiplication,
     Normalization,
     Output,
+    Pad,
     Permute,
     Pooling2d,
     Reshape,
diff --git a/src/armnn/LayerSupport.cpp b/src/armnn/LayerSupport.cpp
index 7ed56c5..9bbe179 100644
--- a/src/armnn/LayerSupport.cpp
+++ b/src/armnn/LayerSupport.cpp
@@ -355,4 +355,15 @@
     FORWARD_LAYER_SUPPORT_FUNC(compute, IsMeanSupported, input, output, descriptor);
 }
 
+bool IsPadSupported(Compute compute,
+                    const TensorInfo& input,
+                    const TensorInfo& output,
+                    const PadDescriptor& descriptor,
+                    char* reasonIfUnsupported,
+                    size_t reasonIfUnsupportedMaxLength)
+{
+    CopyErrorMessage(reasonIfUnsupported, "Not implemented", reasonIfUnsupportedMaxLength);
+    return false;
+}
+
 }
diff --git a/src/armnn/LayersFwd.hpp b/src/armnn/LayersFwd.hpp
index c9ee9db..8321be4 100644
--- a/src/armnn/LayersFwd.hpp
+++ b/src/armnn/LayersFwd.hpp
@@ -27,6 +27,7 @@
 #include "layers/MultiplicationLayer.hpp"
 #include "layers/NormalizationLayer.hpp"
 #include "layers/OutputLayer.hpp"
+#include "layers/PadLayer.hpp"
 #include "layers/PermuteLayer.hpp"
 #include "layers/Pooling2dLayer.hpp"
 #include "layers/ReshapeLayer.hpp"
@@ -83,6 +84,7 @@
 DECLARE_LAYER(Multiplication)
 DECLARE_LAYER(Normalization)
 DECLARE_LAYER(Output)
+DECLARE_LAYER(Pad)
 DECLARE_LAYER(Permute)
 DECLARE_LAYER(Pooling2d)
 DECLARE_LAYER(Reshape)
diff --git a/src/armnn/Network.cpp b/src/armnn/Network.cpp
index 22d80d3..4f5e297 100644
--- a/src/armnn/Network.cpp
+++ b/src/armnn/Network.cpp
@@ -599,6 +599,11 @@
     return m_Graph->AddLayer<MeanLayer>(meanDescriptor,name);
 }
 
+IConnectableLayer* Network::AddPadLayer(const PadDescriptor& padDescriptor, const char* name)
+{
+    return m_Graph->AddLayer<PadLayer>(padDescriptor,name);
+}
+
 OptimizedNetwork::OptimizedNetwork(std::unique_ptr<Graph> graph)
     : m_Graph(std::move(graph))
 {
diff --git a/src/armnn/Network.hpp b/src/armnn/Network.hpp
index 1411242..ea4284e 100644
--- a/src/armnn/Network.hpp
+++ b/src/armnn/Network.hpp
@@ -119,6 +119,8 @@
 
     IConnectableLayer* AddMeanLayer(const MeanDescriptor& meanDescriptor, const char* name = nullptr) override;
 
+    IConnectableLayer* AddPadLayer(const PadDescriptor& padDescriptor, const char* name = nullptr) override;
+
 private:
     IConnectableLayer* AddFullyConnectedLayerImpl(const FullyConnectedDescriptor& fullyConnectedDescriptor,
         const ConstTensor& weights,
diff --git a/src/armnn/layers/PadLayer.cpp b/src/armnn/layers/PadLayer.cpp
new file mode 100644
index 0000000..6a1e915
--- /dev/null
+++ b/src/armnn/layers/PadLayer.cpp
@@ -0,0 +1,45 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "PadLayer.hpp"
+#include "LayerCloneBase.hpp"
+
+#include "backends/CpuTensorHandle.hpp"
+#include "backends/WorkloadData.hpp"
+#include "backends/WorkloadFactory.hpp"
+
+#include <cstring>
+
+namespace armnn
+{
+
+PadLayer::PadLayer(const armnn::PadDescriptor& param, const char* name)
+    : LayerWithParameters(1, 1, LayerType::Pad, param, name)
+{}
+
+std::unique_ptr<IWorkload> PadLayer::CreateWorkload(const armnn::Graph& graph,
+                                                    const armnn::IWorkloadFactory& factory) const
+{
+    PadQueueDescriptor descriptor;
+    descriptor.m_Parameters.m_PadList = m_Param.m_PadList;
+
+    return factory.CreatePad(descriptor, PrepInfoAndDesc(descriptor, graph));
+}
+
+PadLayer* PadLayer::Clone(Graph& graph) const
+{
+    auto layer = CloneBase<PadLayer>(graph, m_Param, GetName());
+
+    layer->m_Param.m_PadList = m_Param.m_PadList;
+
+    return std::move(layer);
+}
+
+void PadLayer::ValidateTensorShapesFromInputs()
+{
+    return;
+}
+
+} // namespace armnn
\ No newline at end of file
diff --git a/src/armnn/layers/PadLayer.hpp b/src/armnn/layers/PadLayer.hpp
new file mode 100644
index 0000000..e53a90c
--- /dev/null
+++ b/src/armnn/layers/PadLayer.hpp
@@ -0,0 +1,29 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "LayerWithParameters.hpp"
+
+namespace armnn
+{
+
+class PadLayer : public LayerWithParameters<PadDescriptor>
+{
+public:
+    virtual std::unique_ptr<IWorkload> CreateWorkload(const Graph&            graph,
+                                                      const IWorkloadFactory& factory) const override;
+
+    PadLayer* Clone(Graph& graph) const override;
+
+    void ValidateTensorShapesFromInputs() override;
+
+protected:
+    PadLayer(const PadDescriptor& param, const char* name);
+    ~PadLayer() = default;
+
+};
+
+}
\ No newline at end of file
diff --git a/src/backends/WorkloadFactory.cpp b/src/backends/WorkloadFactory.cpp
index 773a8c1..2666e7f 100644
--- a/src/backends/WorkloadFactory.cpp
+++ b/src/backends/WorkloadFactory.cpp
@@ -472,6 +472,19 @@
                                         cLayer->GetParameters(), reason, reasonCapacity);
             break;
         }
+        case LayerType::Pad:
+        {
+            auto cLayer = boost::polymorphic_downcast<const PadLayer*>(&layer);
+            const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo();
+            const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo();
+            result = IsPadSupported(compute,
+                                    OverrideDataType(input, dataType),
+                                    OverrideDataType(output, dataType),
+                                    cLayer->GetParameters(),
+                                    reason,
+                                    reasonCapacity);
+            break;
+        }
         case LayerType::Pooling2d:
         {
             auto cLayer = boost::polymorphic_downcast<const Pooling2dLayer*>(&layer);
diff --git a/src/backends/test/IsLayerSupportedTestImpl.hpp b/src/backends/test/IsLayerSupportedTestImpl.hpp
index c5389df..e166513 100644
--- a/src/backends/test/IsLayerSupportedTestImpl.hpp
+++ b/src/backends/test/IsLayerSupportedTestImpl.hpp
@@ -338,6 +338,8 @@
 
 DECLARE_LAYER_POLICY_CUSTOM_PARAM(Output, armnn::LayerBindingId)
 
+DECLARE_LAYER_POLICY_2_PARAM(Pad)
+
 DECLARE_LAYER_POLICY_2_PARAM(Permute)
 
 DECLARE_LAYER_POLICY_2_PARAM(Pooling2d)