IVGCVSW-8229 & IVGCVSW-8237 ScatterNd: Front end and reference implementation
(scatter_nd, scatter_nd_add, and scatter_nd_update, scatter_nd_sub, scatter_nd_min, scatter_nd_max, scatter_nd_mul)

  * Front end support for ScatterNd added.
  * Reference implementation for ScatterNd added.
  * Unit tests added.

Signed-off-by: Tianle Cheng <tianle.cheng@arm.com>
Change-Id: I30da9056d9b03ca9b5fb8d09987341128badbcf4
diff --git a/src/backends/reference/RefLayerSupport.cpp b/src/backends/reference/RefLayerSupport.cpp
index f97d03a..654aeb5 100644
--- a/src/backends/reference/RefLayerSupport.cpp
+++ b/src/backends/reference/RefLayerSupport.cpp
@@ -356,6 +356,13 @@
                                      infos[1],
                                      *(PolymorphicDowncast<const ReduceDescriptor*>(&descriptor)),
                                      reasonIfUnsupported);
+        case LayerType::ScatterNd:
+            return IsScatterNdSupported(infos[0],
+                                        infos[1],
+                                        infos[2],
+                                        infos[3],
+                                        *(PolymorphicDowncast<const ScatterNdDescriptor*>(&descriptor)),
+                                        reasonIfUnsupported);
         case LayerType::Slice:
             return IsSliceSupported(infos[0],
                                     infos[1],
@@ -2442,6 +2449,64 @@
     return supported;
 }
 
+bool RefLayerSupport::IsScatterNdSupported(const TensorInfo& input,
+                                           const TensorInfo& indices,
+                                           const TensorInfo& updates,
+                                           const TensorInfo& output,
+                                           const ScatterNdDescriptor& descriptor,
+                                            Optional<std::string&> reasonIfUnsupported) const
+{
+    IgnoreUnused(descriptor);
+
+    bool supported = true;
+
+    std::array<DataType, 7> supportedTypes
+    {
+        DataType::Float32,
+        DataType::Float16,
+        DataType::QAsymmS8,
+        DataType::QAsymmU8,
+        DataType::QSymmS8,
+        DataType::QSymmS16,
+        DataType::Signed32
+    };
+
+    std::array<DataType, 1> indicesSupportedTypes =
+    {
+        DataType::Signed32
+    };
+
+    supported &= CheckSupportRule(TypeAnyOf(indices, indicesSupportedTypes), reasonIfUnsupported,
+                                  "ScatterNd: indices type not supported.");
+
+    supported &= CheckSupportRule(TypeAnyOf(updates, supportedTypes), reasonIfUnsupported,
+                                  "ScatterNd: updates type not supported.");
+
+    supported &= CheckSupportRule(TypeAnyOf(output, supportedTypes), reasonIfUnsupported,
+                                  "ScatterNd: output type not supported");
+
+    supported &= CheckSupportRule(TypesAreEqual(updates, output), reasonIfUnsupported,
+                                  "ScatterNd: input and updates types are mismatched");
+
+    if (descriptor.m_InputEnabled)
+    {
+        // If the input slot is enabled, we have the input tensor in this slot
+        supported &= CheckSupportRule(TypeAnyOf(input, supportedTypes), reasonIfUnsupported,
+                                      "ScatterNd: input type not supported.");
+
+        supported &= CheckSupportRule(TypesAreEqual(input, output), reasonIfUnsupported,
+                                      "ScatterNd: input and output types are mismatched");
+    }
+    else
+    {
+        // If the input slot is not enabled, we have the shape tensor in this slot
+        supported &= CheckSupportRule(TypeAnyOf(input, indicesSupportedTypes), reasonIfUnsupported,
+                                      "ScatterNd: shape type not supported.");
+    }
+
+    return supported;
+}
+
 bool RefLayerSupport::IsShapeSupported(const TensorInfo& input,
                                        const TensorInfo& output,
                                        Optional<std::string&> reasonIfUnsupported) const