IVGCVSW-3073 Refactor reference DepthwiseConvolution2d workloads

Change-Id: I3cf8d9dbc4f8c95e0e2311505dd7e9f9069f1ab5
Signed-off-by: Ruomei Yan <ruomei.yan@arm.com>
diff --git a/src/backends/backendsCommon/test/Conv2dTestImpl.hpp b/src/backends/backendsCommon/test/Conv2dTestImpl.hpp
index 0533c77..73b170e 100644
--- a/src/backends/backendsCommon/test/Conv2dTestImpl.hpp
+++ b/src/backends/backendsCommon/test/Conv2dTestImpl.hpp
@@ -456,7 +456,7 @@
 
     CopyDataToITensorHandle(inputHandle.get(), &batchedInput[0][0][0][0]);
 
-    workload->Execute();
+    ExecuteWorkload(*workload, memoryManager);
 
     CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
 
@@ -601,7 +601,7 @@
 
     CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
 
-    workload->Execute();
+    ExecuteWorkload(*workload, memoryManager);
 
     CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
 
@@ -804,7 +804,7 @@
 
     CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
 
-    workload->Execute();
+    ExecuteWorkload(*workload, memoryManager);
 
     CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
 
@@ -910,7 +910,7 @@
 
     CopyDataToITensorHandle(inputHandle.get(), &batchedInput[0][0][0][0]);
 
-    workload->Execute();
+    ExecuteWorkload(*workload, memoryManager);
 
     CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
 
@@ -1246,8 +1246,9 @@
     CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
     CopyDataToITensorHandle(inputHandleRef.get(), &input[0][0][0][0]);
 
-    workload->Execute();
+    ExecuteWorkload(*workload, memoryManager);
 
+    workloadRef->PostAllocationConfigure();
     workloadRef->Execute();
 
     CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
diff --git a/src/backends/reference/RefWorkloadFactory.cpp b/src/backends/reference/RefWorkloadFactory.cpp
index be92094..2266fcd 100644
--- a/src/backends/reference/RefWorkloadFactory.cpp
+++ b/src/backends/reference/RefWorkloadFactory.cpp
@@ -163,11 +163,10 @@
     return std::make_unique<RefConvolution2dWorkload>(descriptor, info);
 }
 
-std::unique_ptr<IWorkload> RefWorkloadFactory::CreateDepthwiseConvolution2d(
+std::unique_ptr<armnn::IWorkload> RefWorkloadFactory::CreateDepthwiseConvolution2d(
     const DepthwiseConvolution2dQueueDescriptor& descriptor, const WorkloadInfo& info) const
 {
-    return MakeWorkload<RefDepthwiseConvolution2dFloat32Workload,
-        RefDepthwiseConvolution2dUint8Workload>(descriptor, info);
+    return std::make_unique<RefDepthwiseConvolution2dWorkload>(descriptor, info);
 }
 
 std::unique_ptr<IWorkload> RefWorkloadFactory::CreateDetectionPostProcess(
diff --git a/src/backends/reference/backend.mk b/src/backends/reference/backend.mk
index 3146fca..b7a35ab 100644
--- a/src/backends/reference/backend.mk
+++ b/src/backends/reference/backend.mk
@@ -35,8 +35,7 @@
         workloads/RefConvertFp32ToFp16Workload.cpp \
         workloads/RefConvolution2dWorkload.cpp \
         workloads/RefDebugWorkload.cpp \
-        workloads/RefDepthwiseConvolution2dFloat32Workload.cpp \
-        workloads/RefDepthwiseConvolution2dUint8Workload.cpp \
+        workloads/RefDepthwiseConvolution2dWorkload.cpp \
         workloads/RefDequantizeWorkload.cpp \
         workloads/RefDetectionPostProcessFloat32Workload.cpp \
         workloads/RefDetectionPostProcessUint8Workload.cpp \
diff --git a/src/backends/reference/test/RefCreateWorkloadTests.cpp b/src/backends/reference/test/RefCreateWorkloadTests.cpp
index 62e8788..7226bd0 100644
--- a/src/backends/reference/test/RefCreateWorkloadTests.cpp
+++ b/src/backends/reference/test/RefCreateWorkloadTests.cpp
@@ -278,6 +278,30 @@
     RefCreateConvolution2dWorkloadTest(DataLayout::NHWC);
 }
 
+static void RefCreateDepthwiseConvolutionWorkloadTest(DataLayout dataLayout)
+{
+    Graph graph;
+    RefWorkloadFactory factory;
+    auto workload = CreateDepthwiseConvolution2dWorkloadTest<RefDepthwiseConvolution2dWorkload, DataType::Float32>
+            (factory, graph, dataLayout);
+
+    std::initializer_list<unsigned int> inputShape  = (dataLayout == DataLayout::NCHW)
+                                                      ? std::initializer_list<unsigned int>({ 2, 2, 5, 5 })
+                                                      : std::initializer_list<unsigned int>({ 2, 5, 5, 2 });
+    std::initializer_list<unsigned int> outputShape = (dataLayout == DataLayout::NCHW)
+                                                      ? std::initializer_list<unsigned int>({ 2, 2, 5, 5 })
+                                                      : std::initializer_list<unsigned int>({ 2, 5, 5, 2 });
+    // Checks that inputs/outputs are as we expect them (see definition of CreateDepthwiseConvolution2dWorkloadTest).
+    CheckInputOutput(std::move(workload),
+                     TensorInfo(inputShape, DataType::Float32),
+                     TensorInfo(outputShape, DataType::Float32));
+}
+
+BOOST_AUTO_TEST_CASE(CreateDepthwiseConvolutionFloat32NhwcWorkload)
+{
+    RefCreateDepthwiseConvolutionWorkloadTest(DataLayout::NHWC);
+}
+
 template <typename FullyConnectedWorkloadType, armnn::DataType DataType>
 static void RefCreateFullyConnectedWorkloadTest()
 {
diff --git a/src/backends/reference/workloads/CMakeLists.txt b/src/backends/reference/workloads/CMakeLists.txt
index ab4fea6..ef5e46a 100644
--- a/src/backends/reference/workloads/CMakeLists.txt
+++ b/src/backends/reference/workloads/CMakeLists.txt
@@ -57,10 +57,8 @@
     RefElementwiseWorkload.hpp
     RefDebugWorkload.cpp
     RefDebugWorkload.hpp
-    RefDepthwiseConvolution2dFloat32Workload.cpp
-    RefDepthwiseConvolution2dFloat32Workload.hpp
-    RefDepthwiseConvolution2dUint8Workload.cpp
-    RefDepthwiseConvolution2dUint8Workload.hpp
+    RefDepthwiseConvolution2dWorkload.cpp
+    RefDepthwiseConvolution2dWorkload.hpp
     RefDequantizeWorkload.cpp
     RefDequantizeWorkload.hpp
     RefDetectionPostProcessUint8Workload.cpp
@@ -81,8 +79,8 @@
     RefL2NormalizationFloat32Workload.hpp
     RefLstmWorkload.cpp
     RefLstmWorkload.hpp
-        RefConcatWorkload.cpp
-        RefConcatWorkload.hpp
+    RefConcatWorkload.cpp
+    RefConcatWorkload.hpp
     RefNormalizationFloat32Workload.cpp
     RefNormalizationFloat32Workload.hpp
     RefPadWorkload.cpp
diff --git a/src/backends/reference/workloads/RefDepthwiseConvolution2dFloat32Workload.cpp b/src/backends/reference/workloads/RefDepthwiseConvolution2dFloat32Workload.cpp
deleted file mode 100644
index 756e958..0000000
--- a/src/backends/reference/workloads/RefDepthwiseConvolution2dFloat32Workload.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// Copyright © 2017 Arm Ltd. All rights reserved.
-// SPDX-License-Identifier: MIT
-//
-
-#include "RefDepthwiseConvolution2dFloat32Workload.hpp"
-
-#include "ConvImpl.hpp"
-#include "RefWorkloadUtils.hpp"
-
-#include "Profiling.hpp"
-
-namespace armnn
-{
-RefDepthwiseConvolution2dFloat32Workload::RefDepthwiseConvolution2dFloat32Workload(
-    const DepthwiseConvolution2dQueueDescriptor& descriptor, const WorkloadInfo& info)
-        : Float32Workload<DepthwiseConvolution2dQueueDescriptor>(descriptor, info),
-          m_Weight(std::make_unique<ScopedCpuTensorHandle>(*(descriptor.m_Weight))),
-          m_Bias(descriptor.m_Parameters.m_BiasEnabled
-                 ? std::make_unique<ScopedCpuTensorHandle>(*(descriptor.m_Bias)) : nullptr) {}
-
-void RefDepthwiseConvolution2dFloat32Workload::Execute() const
-{
-    ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefDepthwiseConvolution2dFloat32Workload_Execute");
-
-    const float* inputData  = GetInputTensorDataFloat(0, m_Data);
-    const float* weightData = m_Weight->template GetConstTensor<float>();
-    const float* biasData   = m_Data.m_Parameters.m_BiasEnabled ? m_Bias->template GetConstTensor<float>() : nullptr;
-    const TensorInfo& filterInfo = m_Weight->GetTensorInfo();
-
-    ConvImpl<armnn::DepthwiseConvolution2dQueueDescriptor, float, float, float>
-        (m_Data, inputData, 0.0f, 0, weightData, 0.0f, 0, biasData, 0.0f, 0, filterInfo, true);
-}
-
-} //namespace armnn
diff --git a/src/backends/reference/workloads/RefDepthwiseConvolution2dFloat32Workload.hpp b/src/backends/reference/workloads/RefDepthwiseConvolution2dFloat32Workload.hpp
deleted file mode 100644
index d09497c..0000000
--- a/src/backends/reference/workloads/RefDepthwiseConvolution2dFloat32Workload.hpp
+++ /dev/null
@@ -1,27 +0,0 @@
-//
-// Copyright © 2017 Arm Ltd. All rights reserved.
-// SPDX-License-Identifier: MIT
-//
-
-#pragma once
-
-#include <backendsCommon/Workload.hpp>
-#include <backendsCommon/WorkloadData.hpp>
-
-namespace armnn
-{
-
-class RefDepthwiseConvolution2dFloat32Workload : public Float32Workload<DepthwiseConvolution2dQueueDescriptor>
-{
-public:
-    explicit RefDepthwiseConvolution2dFloat32Workload(const DepthwiseConvolution2dQueueDescriptor& descriptor,
-                                             const WorkloadInfo& info);
-
-    virtual void Execute() const override;
-
-private:
-    std::unique_ptr<ScopedCpuTensorHandle> m_Weight;
-    std::unique_ptr<ScopedCpuTensorHandle> m_Bias;
-};
-
-} //namespace armnn
diff --git a/src/backends/reference/workloads/RefDepthwiseConvolution2dUint8Workload.cpp b/src/backends/reference/workloads/RefDepthwiseConvolution2dUint8Workload.cpp
deleted file mode 100644
index 629b729..0000000
--- a/src/backends/reference/workloads/RefDepthwiseConvolution2dUint8Workload.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Copyright © 2017 Arm Ltd. All rights reserved.
-// SPDX-License-Identifier: MIT
-//
-
-#include "RefDepthwiseConvolution2dUint8Workload.hpp"
-
-#include "ConvImpl.hpp"
-#include "RefWorkloadUtils.hpp"
-
-#include "Profiling.hpp"
-
-namespace armnn
-{
-
-RefDepthwiseConvolution2dUint8Workload::RefDepthwiseConvolution2dUint8Workload(
-        const DepthwiseConvolution2dQueueDescriptor& descriptor, const WorkloadInfo& info)
-        : Uint8Workload<DepthwiseConvolution2dQueueDescriptor>(descriptor, info),
-          m_Weight(std::make_unique<ScopedCpuTensorHandle>(*(descriptor.m_Weight))),
-          m_Bias(descriptor.m_Parameters.m_BiasEnabled
-                 ? std::make_unique<ScopedCpuTensorHandle>(*(descriptor.m_Bias)) : nullptr) {}
-
-void RefDepthwiseConvolution2dUint8Workload::Execute() const
-{
-    ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefDepthwiseConvolution2dUint8Workload_Execute");
-
-    const uint8_t* inputData = GetInputTensorDataU8(0, m_Data);
-    const TensorInfo& inputInfo = GetTensorInfo(m_Data.m_Inputs[0]);
-    const uint8_t* weightsData = m_Weight->template GetConstTensor<uint8_t>();
-    const TensorInfo& weightsInfo = GetTensorInfo(m_Weight.get());
-    const int32_t* biasData = m_Data.m_Parameters.m_BiasEnabled ? m_Bias->template GetConstTensor<int32_t>() : nullptr;
-    const TensorInfo& outputInfo = GetTensorInfo(m_Data.m_Outputs[0]);
-    const TensorInfo& filterInfo = m_Weight->GetTensorInfo();
-
-    ConvImpl<armnn::DepthwiseConvolution2dQueueDescriptor, uint8_t, int32_t, int32_t>(
-        m_Data,
-        inputData, inputInfo.GetQuantizationScale(),  inputInfo.GetQuantizationOffset(),
-        weightsData, weightsInfo.GetQuantizationScale(), weightsInfo.GetQuantizationOffset(),
-        biasData,
-        outputInfo.GetQuantizationScale(), outputInfo.GetQuantizationOffset(), filterInfo, true);
-}
-
-} //namespace armnn
diff --git a/src/backends/reference/workloads/RefDepthwiseConvolution2dUint8Workload.hpp b/src/backends/reference/workloads/RefDepthwiseConvolution2dUint8Workload.hpp
deleted file mode 100644
index d35b43c..0000000
--- a/src/backends/reference/workloads/RefDepthwiseConvolution2dUint8Workload.hpp
+++ /dev/null
@@ -1,26 +0,0 @@
-//
-// Copyright © 2017 Arm Ltd. All rights reserved.
-// SPDX-License-Identifier: MIT
-//
-
-#pragma once
-
-#include <backendsCommon/Workload.hpp>
-#include <backendsCommon/WorkloadData.hpp>
-
-namespace armnn
-{
-
-class RefDepthwiseConvolution2dUint8Workload : public Uint8Workload<DepthwiseConvolution2dQueueDescriptor>
-{
-public:
-    explicit RefDepthwiseConvolution2dUint8Workload(const DepthwiseConvolution2dQueueDescriptor& descriptor,
-                                           const WorkloadInfo& info);
-    virtual void Execute() const override;
-
-private:
-    std::unique_ptr<ScopedCpuTensorHandle> m_Weight;
-    std::unique_ptr<ScopedCpuTensorHandle> m_Bias;
-};
-
-} //namespace armnn
diff --git a/src/backends/reference/workloads/RefDepthwiseConvolution2dWorkload.cpp b/src/backends/reference/workloads/RefDepthwiseConvolution2dWorkload.cpp
new file mode 100644
index 0000000..c7dc4af
--- /dev/null
+++ b/src/backends/reference/workloads/RefDepthwiseConvolution2dWorkload.cpp
@@ -0,0 +1,59 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "RefDepthwiseConvolution2dWorkload.hpp"
+
+#include "ConvImpl.hpp"
+#include "RefWorkloadUtils.hpp"
+#include "Decoders.hpp"
+#include "Encoders.hpp"
+#include "Profiling.hpp"
+#include <ResolveType.hpp>
+
+namespace armnn
+{
+
+RefDepthwiseConvolution2dWorkload::RefDepthwiseConvolution2dWorkload(
+        const DepthwiseConvolution2dQueueDescriptor& descriptor, const WorkloadInfo& info)
+        : BaseWorkload<DepthwiseConvolution2dQueueDescriptor>(descriptor, info)
+{
+    m_Weight = std::make_unique<ScopedCpuTensorHandle>(*(descriptor.m_Weight));
+    const TensorInfo& rFilterInfo = GetTensorInfo(m_Weight.get());
+    m_FilterShape = rFilterInfo.GetShape();
+    m_FilterDecoder = MakeDecoder<float>(rFilterInfo, m_Weight.get()->Map(true));
+
+    if (descriptor.m_Parameters.m_BiasEnabled)
+    {
+        m_Bias = std::make_unique<ScopedCpuTensorHandle>(*(descriptor.m_Bias));
+        const TensorInfo& biasInfo = GetTensorInfo(m_Bias.get());
+        m_BiasDecoder = MakeDecoder<float>(biasInfo, m_Bias.get()->Map(true));
+    }
+}
+
+void RefDepthwiseConvolution2dWorkload::PostAllocationConfigure()
+{
+    const TensorInfo& inputInfo = GetTensorInfo(m_Data.m_Inputs[0]);
+    m_InputShape = inputInfo.GetShape();
+    m_InputDecoder = MakeDecoder<float>(inputInfo, m_Data.m_Inputs[0]->Map());
+
+    const TensorInfo& outputInfo = GetTensorInfo(m_Data.m_Outputs[0]);
+    m_OutputShape = outputInfo.GetShape();
+    m_OutputEncoder = MakeEncoder<float>(outputInfo, m_Data.m_Outputs[0]->Map());
+}
+
+void RefDepthwiseConvolution2dWorkload::Execute() const
+{
+    ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefDepthwiseConvolution2dWorkload_Execute");
+    std::unique_ptr<Decoder<float>> pBiasDecoder{};
+
+    Convolve(m_InputShape, *m_InputDecoder, m_OutputShape, *m_OutputEncoder,
+             m_FilterShape, *m_FilterDecoder, m_Data.m_Parameters.m_BiasEnabled, m_BiasDecoder.get(),
+             m_Data.m_Parameters.m_DataLayout, m_Data.m_Parameters.m_PadTop, m_Data.m_Parameters.m_PadLeft,
+             m_Data.m_Parameters.m_StrideX, m_Data.m_Parameters.m_StrideY,
+             m_Data.m_Parameters.m_DilationX,
+             m_Data.m_Parameters.m_DilationY, true);
+}
+
+} //namespace armnn
diff --git a/src/backends/reference/workloads/RefDepthwiseConvolution2dWorkload.hpp b/src/backends/reference/workloads/RefDepthwiseConvolution2dWorkload.hpp
new file mode 100644
index 0000000..6d7037f
--- /dev/null
+++ b/src/backends/reference/workloads/RefDepthwiseConvolution2dWorkload.hpp
@@ -0,0 +1,39 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+#include <backendsCommon/Workload.hpp>
+#include <backendsCommon/WorkloadData.hpp>
+#include "Decoders.hpp"
+#include "Encoders.hpp"
+
+#include <armnn/TypesUtils.hpp>
+
+namespace armnn
+{
+
+class RefDepthwiseConvolution2dWorkload : public BaseWorkload<DepthwiseConvolution2dQueueDescriptor> {
+public:
+    explicit RefDepthwiseConvolution2dWorkload(const DepthwiseConvolution2dQueueDescriptor &descriptor,
+                                               const WorkloadInfo &info);
+
+    void PostAllocationConfigure() override;
+
+    virtual void Execute() const override;
+
+private:
+
+    std::unique_ptr <ScopedCpuTensorHandle> m_Weight;
+    std::unique_ptr <ScopedCpuTensorHandle> m_Bias;
+
+    std::unique_ptr <Decoder<float>> m_InputDecoder;
+    std::unique_ptr <Encoder<float>> m_OutputEncoder;
+    std::unique_ptr <Decoder<float>> m_FilterDecoder;
+    std::unique_ptr <Decoder<float>> m_BiasDecoder;
+
+    TensorShape m_InputShape;
+    TensorShape m_OutputShape;
+    TensorShape m_FilterShape;
+};
+
+} //namespace armnn
diff --git a/src/backends/reference/workloads/RefWorkloads.hpp b/src/backends/reference/workloads/RefWorkloads.hpp
index 5a65f60..291f991 100644
--- a/src/backends/reference/workloads/RefWorkloads.hpp
+++ b/src/backends/reference/workloads/RefWorkloads.hpp
@@ -25,7 +25,7 @@
 #include "Splitter.hpp"
 #include "RefFullyConnectedUint8Workload.hpp"
 #include "RefReshapeFloat32Workload.hpp"
-#include "RefDepthwiseConvolution2dUint8Workload.hpp"
+#include "RefDepthwiseConvolution2dWorkload.hpp"
 #include "FullyConnected.hpp"
 #include "Gather.hpp"
 #include "RefFloorFloat32Workload.hpp"
@@ -36,7 +36,6 @@
 #include "RefBatchNormalizationUint8Workload.hpp"
 #include "ResizeBilinear.hpp"
 #include "RefNormalizationFloat32Workload.hpp"
-#include "RefDepthwiseConvolution2dFloat32Workload.hpp"
 #include "RefDetectionPostProcessFloat32Workload.hpp"
 #include "RefDetectionPostProcessUint8Workload.hpp"
 #include "RefPooling2dUint8Workload.hpp"