IVGCVSW-4620 Add Fill Reference Implementation

 * Add Fill Reference Implementation
 * Refactor FP converter to use static_cast

Signed-off-by: Ryan OShea <Ryan.OShea2@arm.com>
Signed-off-by: Keith Davis <keith.davis@arm.com>
Change-Id: I532e2f982981d047690755fac43a0e9cf8b17dcd
diff --git a/src/armnnUtils/FloatingPointConverter.cpp b/src/armnnUtils/FloatingPointConverter.cpp
index 5d89a25..8123cf3 100644
--- a/src/armnnUtils/FloatingPointConverter.cpp
+++ b/src/armnnUtils/FloatingPointConverter.cpp
@@ -20,7 +20,7 @@
     ARMNN_ASSERT(srcFloat32Buffer != nullptr);
     ARMNN_ASSERT(dstFloat16Buffer != nullptr);
 
-    armnn::Half* pHalf = reinterpret_cast<armnn::Half*>(dstFloat16Buffer);
+    armnn::Half* pHalf = static_cast<armnn::Half*>(dstFloat16Buffer);
 
     for (size_t i = 0; i < numElements; i++)
     {
@@ -35,7 +35,7 @@
     ARMNN_ASSERT(srcFloat16Buffer != nullptr);
     ARMNN_ASSERT(dstFloat32Buffer != nullptr);
 
-    const armnn::Half* pHalf = reinterpret_cast<const armnn::Half*>(srcFloat16Buffer);
+    const armnn::Half* pHalf = static_cast<const armnn::Half*>(srcFloat16Buffer);
 
     for (size_t i = 0; i < numElements; i++)
     {
@@ -50,7 +50,7 @@
     ARMNN_ASSERT(srcFloat32Buffer != nullptr);
     ARMNN_ASSERT(dstBFloat16Buffer != nullptr);
 
-    armnn::BFloat16* bf16 = reinterpret_cast<armnn::BFloat16*>(dstBFloat16Buffer);
+    armnn::BFloat16* bf16 = static_cast<armnn::BFloat16*>(dstBFloat16Buffer);
 
     for (size_t i = 0; i < numElements; i++)
     {
@@ -65,7 +65,7 @@
     ARMNN_ASSERT(srcBFloat16Buffer != nullptr);
     ARMNN_ASSERT(dstFloat32Buffer != nullptr);
 
-    const armnn::BFloat16* bf16 = reinterpret_cast<const armnn::BFloat16*>(srcBFloat16Buffer);
+    const armnn::BFloat16* bf16 = static_cast<const armnn::BFloat16*>(srcBFloat16Buffer);
 
     for (size_t i = 0; i < numElements; i++)
     {
diff --git a/src/backends/backendsCommon/WorkloadData.hpp b/src/backends/backendsCommon/WorkloadData.hpp
index ba9b0f3..f2f7089 100644
--- a/src/backends/backendsCommon/WorkloadData.hpp
+++ b/src/backends/backendsCommon/WorkloadData.hpp
@@ -140,13 +140,6 @@
 // Fill layer workload data.
 struct FillQueueDescriptor : QueueDescriptorWithParameters<FillDescriptor>
 {
-    FillQueueDescriptor()
-        : m_Value(nullptr)
-    {
-    }
-
-    const ConstCpuTensorHandle* m_Value;
-
     void Validate(const WorkloadInfo& workloadInfo) const;
 };
 
diff --git a/src/backends/backendsCommon/common.mk b/src/backends/backendsCommon/common.mk
index 47e8821..c31b1f0 100644
--- a/src/backends/backendsCommon/common.mk
+++ b/src/backends/backendsCommon/common.mk
@@ -56,6 +56,7 @@
     test/layerTests/ElementwiseUnaryTestImpl.cpp \
     test/layerTests/ExpTestImpl.cpp \
     test/layerTests/FakeQuantizationTestImpl.cpp \
+    test/layerTests/FillTestImpl.cpp \
     test/layerTests/FloorTestImpl.cpp \
     test/layerTests/FullyConnectedTestImpl.cpp \
     test/layerTests/GatherTestImpl.cpp \
diff --git a/src/backends/backendsCommon/test/CMakeLists.txt b/src/backends/backendsCommon/test/CMakeLists.txt
index 81372da..0ce5299 100644
--- a/src/backends/backendsCommon/test/CMakeLists.txt
+++ b/src/backends/backendsCommon/test/CMakeLists.txt
@@ -95,6 +95,8 @@
     layerTests/ExpTestImpl.hpp
     layerTests/FakeQuantizationTestImpl.cpp
     layerTests/FakeQuantizationTestImpl.hpp
+    layerTests/FillTestImpl.cpp
+    layerTests/FillTestImpl.hpp
     layerTests/FloorTestImpl.cpp
     layerTests/FloorTestImpl.hpp
     layerTests/FullyConnectedTestImpl.cpp
diff --git a/src/backends/backendsCommon/test/LayerTests.hpp b/src/backends/backendsCommon/test/LayerTests.hpp
index 195ca80..7e8b301 100644
--- a/src/backends/backendsCommon/test/LayerTests.hpp
+++ b/src/backends/backendsCommon/test/LayerTests.hpp
@@ -27,6 +27,7 @@
 #include <backendsCommon/test/layerTests/ElementwiseUnaryTestImpl.hpp>
 #include <backendsCommon/test/layerTests/ExpTestImpl.hpp>
 #include <backendsCommon/test/layerTests/FakeQuantizationTestImpl.hpp>
+#include <backendsCommon/test/layerTests/FillTestImpl.hpp>
 #include <backendsCommon/test/layerTests/FloorTestImpl.hpp>
 #include <backendsCommon/test/layerTests/FullyConnectedTestImpl.hpp>
 #include <backendsCommon/test/layerTests/GatherTestImpl.hpp>
diff --git a/src/backends/backendsCommon/test/layerTests/FillTestImpl.cpp b/src/backends/backendsCommon/test/layerTests/FillTestImpl.cpp
new file mode 100644
index 0000000..00a185c
--- /dev/null
+++ b/src/backends/backendsCommon/test/layerTests/FillTestImpl.cpp
@@ -0,0 +1,70 @@
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "FillTestImpl.hpp"
+
+#include <backendsCommon/test/DataTypeUtils.hpp>
+#include <backendsCommon/test/TensorCopyUtils.hpp>
+#include <backendsCommon/test/WorkloadTestUtils.hpp>
+
+#include <test/TensorHelpers.hpp>
+
+template<armnn::DataType ArmnnType, typename T>
+LayerTestResult<T, 4> SimpleFillTest(
+    armnn::IWorkloadFactory& workloadFactory,
+    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
+{
+    IgnoreUnused(memoryManager);
+    armnn::TensorInfo inputTensorInfo({4}, ArmnnType);
+    inputTensorInfo.SetQuantizationScale(0.0f);
+
+    armnn::TensorInfo outputTensorInfo({2, 2, 3, 2}, ArmnnType);
+    outputTensorInfo.SetQuantizationScale(0.0f);
+
+    auto input = MakeTensor<T, 1>(inputTensorInfo, ConvertToDataType<ArmnnType>(
+        {2, 2, 3, 2},
+        inputTensorInfo));
+
+    LayerTestResult<T, 4> ret(outputTensorInfo);
+        ret.outputExpected = MakeTensor<T, 4>(outputTensorInfo, ConvertToDataType<ArmnnType>(
+        { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
+          1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },
+        outputTensorInfo));
+
+    std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
+    std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
+
+    armnn::FillQueueDescriptor data;
+    data.m_Parameters.m_Value = 1.0f;
+    armnn::WorkloadInfo info;
+    AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
+    AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
+
+    std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateFill(data, info);
+
+    inputHandle->Allocate();
+    outputHandle->Allocate();
+
+    CopyDataToITensorHandle(inputHandle.get(), &input[0]);
+
+    workload->Execute();
+
+    CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
+
+    return ret;
+}
+
+//
+// Explicit template specializations
+//
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 4>
+SimpleFillTest<armnn::DataType::Float32>(
+    armnn::IWorkloadFactory& workloadFactory,
+    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
+
+template LayerTestResult<armnn::ResolveType<armnn::DataType::Float16>, 4>
+SimpleFillTest<armnn::DataType::Float16>(
+    armnn::IWorkloadFactory& workloadFactory,
+    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
\ No newline at end of file
diff --git a/src/backends/backendsCommon/test/layerTests/FillTestImpl.hpp b/src/backends/backendsCommon/test/layerTests/FillTestImpl.hpp
new file mode 100644
index 0000000..9889007
--- /dev/null
+++ b/src/backends/backendsCommon/test/layerTests/FillTestImpl.hpp
@@ -0,0 +1,18 @@
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "LayerTestResult.hpp"
+
+#include <ResolveType.hpp>
+
+#include <armnn/backends/IBackendInternal.hpp>
+#include <backendsCommon/WorkloadFactory.hpp>
+
+template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
+LayerTestResult<T, 4> SimpleFillTest(
+    armnn::IWorkloadFactory& workloadFactory,
+    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
diff --git a/src/backends/reference/RefLayerSupport.cpp b/src/backends/reference/RefLayerSupport.cpp
index 2e404f9..52a7632 100644
--- a/src/backends/reference/RefLayerSupport.cpp
+++ b/src/backends/reference/RefLayerSupport.cpp
@@ -857,6 +857,28 @@
     return supported;
 }
 
+bool RefLayerSupport::IsFillSupported(const TensorInfo& input,
+                                      const TensorInfo& output,
+                                      const FillDescriptor& descriptor,
+                                      Optional<std::string&> reasonIfUnsupported) const
+{
+    IgnoreUnused(descriptor);
+    IgnoreUnused(output);
+
+    bool supported = true;
+
+    std::array<DataType,2> supportedTypes =
+    {
+        DataType::Float32,
+        DataType::Float16
+    };
+
+    supported &= CheckSupportRule(TypeAnyOf(input, supportedTypes), reasonIfUnsupported,
+                                  "Reference Fill: input type not supported.");
+
+    return supported;
+}
+
 bool RefLayerSupport::IsFloorSupported(const TensorInfo& input,
                                        const TensorInfo& output,
                                        Optional<std::string&> reasonIfUnsupported) const
diff --git a/src/backends/reference/RefLayerSupport.hpp b/src/backends/reference/RefLayerSupport.hpp
index eb89946..96bff56 100644
--- a/src/backends/reference/RefLayerSupport.hpp
+++ b/src/backends/reference/RefLayerSupport.hpp
@@ -141,6 +141,11 @@
                                      const FakeQuantizationDescriptor& descriptor,
                                      Optional<std::string&> reasonIfUnsupported = EmptyOptional()) const override;
 
+    bool IsFillSupported(const TensorInfo& input,
+                         const TensorInfo& output,
+                         const FillDescriptor& descriptor,
+                         Optional<std::string&> reasonIfUnsupported = EmptyOptional()) const override;
+
     bool IsFloorSupported(const TensorInfo& input,
                           const TensorInfo& output,
                           Optional<std::string&> reasonIfUnsupported = EmptyOptional()) const override;
diff --git a/src/backends/reference/RefWorkloadFactory.cpp b/src/backends/reference/RefWorkloadFactory.cpp
index ba84de4..643684c 100644
--- a/src/backends/reference/RefWorkloadFactory.cpp
+++ b/src/backends/reference/RefWorkloadFactory.cpp
@@ -7,6 +7,7 @@
 #include <backendsCommon/MemCopyWorkload.hpp>
 #include <backendsCommon/MemImportWorkload.hpp>
 #include <backendsCommon/MakeWorkloadHelper.hpp>
+#include <reference/workloads/RefFillWorkload.hpp>
 #include "RefWorkloadFactory.hpp"
 #include "RefBackendId.hpp"
 #include "workloads/RefWorkloads.hpp"
@@ -297,13 +298,18 @@
     return CreateComparison(comparisonDescriptor, info);
 }
 
-std::unique_ptr<IWorkload> RefWorkloadFactory::CreateFakeQuantization(
-    const FakeQuantizationQueueDescriptor& descriptor,
-    const WorkloadInfo& info) const
+std::unique_ptr<IWorkload> RefWorkloadFactory::CreateFakeQuantization(const FakeQuantizationQueueDescriptor& descriptor,
+                                                                      const WorkloadInfo& info) const
 {
     return MakeWorkload<RefFakeQuantizationFloat32Workload, NullWorkload>(descriptor, info);
 }
 
+std::unique_ptr<IWorkload> RefWorkloadFactory::CreateFill(const FillQueueDescriptor& descriptor,
+                                                          const WorkloadInfo& info) const
+{
+    return std::make_unique<RefFillWorkload>(descriptor, info);
+}
+
 std::unique_ptr<IWorkload> RefWorkloadFactory::CreateFloor(const FloorQueueDescriptor& descriptor,
                                                            const WorkloadInfo& info) const
 {
diff --git a/src/backends/reference/RefWorkloadFactory.hpp b/src/backends/reference/RefWorkloadFactory.hpp
index 4bfb9e2..0b41930 100644
--- a/src/backends/reference/RefWorkloadFactory.hpp
+++ b/src/backends/reference/RefWorkloadFactory.hpp
@@ -129,6 +129,9 @@
     std::unique_ptr<IWorkload> CreateFakeQuantization(const FakeQuantizationQueueDescriptor& descriptor,
                                                       const WorkloadInfo& info) const override;
 
+    std::unique_ptr<IWorkload> CreateFill(const FillQueueDescriptor& descriptor,
+                                                      const WorkloadInfo& info) const override;
+
     std::unique_ptr<IWorkload> CreateFloor(const FloorQueueDescriptor& descriptor,
                                            const WorkloadInfo& info) const override;
 
diff --git a/src/backends/reference/backend.mk b/src/backends/reference/backend.mk
index 8d7f63d..bf5f340 100644
--- a/src/backends/reference/backend.mk
+++ b/src/backends/reference/backend.mk
@@ -32,6 +32,7 @@
         workloads/DetectionPostProcess.cpp \
         workloads/Dequantize.cpp \
         workloads/ElementwiseFunction.cpp \
+        workloads/Fill.cpp \
         workloads/FullyConnected.cpp \
         workloads/Gather.cpp \
         workloads/InstanceNorm.cpp \
@@ -62,6 +63,7 @@
         workloads/RefElementwiseWorkload.cpp \
         workloads/RefElementwiseUnaryWorkload.cpp \
         workloads/RefFakeQuantizationFloat32Workload.cpp \
+        workloads/RefFillWorkload.cpp \
         workloads/RefFloorWorkload.cpp \
         workloads/RefFullyConnectedWorkload.cpp \
         workloads/RefGatherWorkload.cpp \
diff --git a/src/backends/reference/test/RefLayerTests.cpp b/src/backends/reference/test/RefLayerTests.cpp
index 09096b4..93bfb90 100644
--- a/src/backends/reference/test/RefLayerTests.cpp
+++ b/src/backends/reference/test/RefLayerTests.cpp
@@ -1202,6 +1202,10 @@
 ARMNN_AUTO_TEST_CASE(Concat4dDiffShapeDim2Uint8, Concat4dDiffShapeDim2Uint8Test)
 ARMNN_AUTO_TEST_CASE(Concat4dDiffShapeDim3Uint8, Concat4dDiffShapeDim3Uint8Test, true)
 
+// Fill
+ARMNN_AUTO_TEST_CASE(SimpleFill, SimpleFillTest<DataType::Float32>)
+ARMNN_AUTO_TEST_CASE(SimpleFillF16, SimpleFillTest<DataType::Float16>)
+
 // Floor
 ARMNN_AUTO_TEST_CASE(SimpleFloor, SimpleFloorTest<DataType::Float32>)
 ARMNN_AUTO_TEST_CASE(SimpleFloorFloat16, SimpleFloorTest<DataType::Float16>)
diff --git a/src/backends/reference/workloads/CMakeLists.txt b/src/backends/reference/workloads/CMakeLists.txt
index 94c8513..d51db36 100644
--- a/src/backends/reference/workloads/CMakeLists.txt
+++ b/src/backends/reference/workloads/CMakeLists.txt
@@ -33,6 +33,8 @@
     ElementwiseFunction.hpp
     Encoders.hpp
     Exp.hpp
+    Fill.cpp
+    Fill.hpp
     FullyConnected.cpp
     FullyConnected.hpp
     Gather.cpp
@@ -95,6 +97,8 @@
     RefElementwiseUnaryWorkload.hpp
     RefFakeQuantizationFloat32Workload.cpp
     RefFakeQuantizationFloat32Workload.hpp
+    RefFillWorkload.cpp
+    RefFillWorkload.hpp
     RefFloorWorkload.cpp
     RefFloorWorkload.hpp
     RefFullyConnectedWorkload.cpp
diff --git a/src/backends/reference/workloads/Fill.cpp b/src/backends/reference/workloads/Fill.cpp
new file mode 100644
index 0000000..a166a61
--- /dev/null
+++ b/src/backends/reference/workloads/Fill.cpp
@@ -0,0 +1,24 @@
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "Fill.hpp"
+
+#include "RefWorkloadUtils.hpp"
+
+namespace armnn
+{
+
+void Fill(Encoder<float>& output,
+          const TensorShape& desiredOutputShape,
+          const float value)
+{
+    for(unsigned int i = 0; i < desiredOutputShape.GetNumElements(); ++i)
+    {
+        output[i];
+        output.Set(value);
+    }
+}
+
+} //namespace armnn
diff --git a/src/backends/reference/workloads/Fill.hpp b/src/backends/reference/workloads/Fill.hpp
new file mode 100644
index 0000000..379eb04
--- /dev/null
+++ b/src/backends/reference/workloads/Fill.hpp
@@ -0,0 +1,22 @@
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "BaseIterator.hpp"
+#include "Decoders.hpp"
+#include "Encoders.hpp"
+#include <armnn/Tensor.hpp>
+#include <backendsCommon/WorkloadData.hpp>
+
+namespace armnn
+{
+
+/// Creates a tensor and fills it with a scalar value.
+void Fill(Encoder<float>& output,
+          const TensorShape& desiredOutputShape,
+          const float value);
+
+} //namespace armnn
diff --git a/src/backends/reference/workloads/RefFillWorkload.cpp b/src/backends/reference/workloads/RefFillWorkload.cpp
new file mode 100644
index 0000000..991ab45
--- /dev/null
+++ b/src/backends/reference/workloads/RefFillWorkload.cpp
@@ -0,0 +1,29 @@
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "RefFillWorkload.hpp"
+#include "Fill.hpp"
+
+#include "Decoders.hpp"
+#include "Encoders.hpp"
+#include "RefWorkloadUtils.hpp"
+#include "Profiling.hpp"
+
+namespace armnn
+{
+
+void RefFillWorkload::Execute() const
+{
+    ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefFillWorkload_Execute");
+
+    const TensorInfo &outputTensorInfo = GetTensorInfo(m_Data.m_Outputs[0]);
+
+    std::unique_ptr<Encoder<float>> encoderPtr = MakeEncoder<float>(outputTensorInfo, m_Data.m_Outputs[0]->Map());
+    Encoder<float> &encoder = *encoderPtr;
+
+    Fill(encoder, outputTensorInfo.GetShape(), m_Data.m_Parameters.m_Value);
+}
+
+} //namespace armnn
diff --git a/src/backends/reference/workloads/RefFillWorkload.hpp b/src/backends/reference/workloads/RefFillWorkload.hpp
new file mode 100644
index 0000000..9be773c
--- /dev/null
+++ b/src/backends/reference/workloads/RefFillWorkload.hpp
@@ -0,0 +1,21 @@
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include <backendsCommon/Workload.hpp>
+#include <backendsCommon/WorkloadData.hpp>
+
+namespace armnn
+{
+
+class RefFillWorkload : public BaseWorkload<FillQueueDescriptor>
+{
+public:
+    using BaseWorkload<FillQueueDescriptor>::BaseWorkload;
+    virtual void Execute() const override;
+};
+
+} //namespace armnn
diff --git a/src/backends/reference/workloads/RefWorkloads.hpp b/src/backends/reference/workloads/RefWorkloads.hpp
index e396a6b..951e3a1 100644
--- a/src/backends/reference/workloads/RefWorkloads.hpp
+++ b/src/backends/reference/workloads/RefWorkloads.hpp
@@ -34,6 +34,7 @@
 #include "RefDequantizeWorkload.hpp"
 #include "RefElementwiseWorkload.hpp"
 #include "RefElementwiseUnaryWorkload.hpp"
+#include "RefFillWorkload.hpp"
 #include "RefFullyConnectedWorkload.hpp"
 #include "RefFloorWorkload.hpp"
 #include "RefFakeQuantizationFloat32Workload.hpp"