COMPMID-3381: Implement graph example for YoLo v3 output detector

Add sub/exp/splitv support in graph api

Signed-off-by: Sheri Zhang <sheri.zhang@arm.com>
Change-Id: I4e08cc19a46655717068b12c93d67e619a595d9a
Reviewed-on: https://review.mlplatform.org/c/ml/ComputeLibrary/+/3309
Reviewed-by: Georgios Pinitas <georgios.pinitas@arm.com>
Tested-by: Arm Jenkins <bsgcomp@arm.com>
Comments-Addressed: Arm Jenkins <bsgcomp@arm.com>
diff --git a/arm_compute/graph/backends/FunctionHelpers.h b/arm_compute/graph/backends/FunctionHelpers.h
index 975e5fe..e21b8ed 100644
--- a/arm_compute/graph/backends/FunctionHelpers.h
+++ b/arm_compute/graph/backends/FunctionHelpers.h
@@ -816,6 +816,54 @@
     return RETURN_UNIQUE_PTR(func);
 }
 
+/** Create a backend unary element-wise operation layer function
+ *
+ * @tparam UnaryEltwiseFunctions Backend unary element-wise function
+ * @tparam TargetInfo       Target-specific information
+ *
+ * @param[in] node Node to create the backend function for
+ *
+ * @return Backend unary element-wise operation layer function
+ */
+template <typename UnaryEltwiseFunctions, typename TargetInfo>
+std::unique_ptr<IFunction> create_unary_eltwise_layer(UnaryEltwiseLayerNode &node)
+{
+    validate_node<TargetInfo>(node, 1 /* expected inputs */, 1 /* expected outputs */);
+
+    // Extract IO and info
+    typename TargetInfo::TensorType *input      = get_backing_tensor<TargetInfo>(node.input(0));
+    typename TargetInfo::TensorType *output     = get_backing_tensor<TargetInfo>(node.output(0));
+    const UnaryEltwiseOperation      eltwise_op = node.eltwise_descriptor().op;
+
+    ARM_COMPUTE_ERROR_ON(input == nullptr);
+    ARM_COMPUTE_ERROR_ON(output == nullptr);
+
+    std::unique_ptr<IFunction> func = nullptr;
+    std::string                func_name;
+    if(eltwise_op == UnaryEltwiseOperation::Exp)
+    {
+        std::tie(func, func_name) = create_named_function<typename UnaryEltwiseFunctions::Exp>(
+                                        std::string("Exp"),
+                                        input, output);
+    }
+    else
+    {
+        ARM_COMPUTE_ERROR("Unsupported unary element-wise operation!");
+    }
+
+    // Log info
+    ARM_COMPUTE_LOG_GRAPH_INFO("Instantiated "
+                               << node.name()
+                               << " Type: " << node.type()
+                               << " Target: " << TargetInfo::TargetType
+                               << " Operation: " << func_name
+                               << " Data Type: " << input->info()->data_type()
+                               << " Shape: " << input->info()->tensor_shape()
+                               << std::endl);
+
+    return RETURN_UNIQUE_PTR(func);
+}
+
 /** Create a backend flatten layer function
  *
  * @tparam FlattenLayerFunction Backend flatten function
diff --git a/arm_compute/graph/backends/ValidateHelpers.h b/arm_compute/graph/backends/ValidateHelpers.h
index 673caf9..d689c1f 100644
--- a/arm_compute/graph/backends/ValidateHelpers.h
+++ b/arm_compute/graph/backends/ValidateHelpers.h
@@ -579,6 +579,79 @@
     // Validate function
     return YOLOLayer::validate(input, output, node.activation_info(), node.num_classes());
 }
+/** Validates a element-wise layer node
+ *
+ * @param[in] node Node to validate
+ *
+ * @return Status
+ */
+template <typename EltwiseLayerFunctions>
+Status validate_eltwise_Layer(EltwiseLayerNode &node)
+{
+    ARM_COMPUTE_LOG_GRAPH_VERBOSE("Validating EltwiseLayer node with ID : " << node.id() << " and Name: " << node.name() << std::endl);
+    ARM_COMPUTE_RETURN_ERROR_ON(node.num_inputs() != 2);
+    ARM_COMPUTE_RETURN_ERROR_ON(node.num_outputs() != 1);
+
+    // Extract input and output
+    const arm_compute::ITensorInfo *input1         = detail::get_backing_tensor_info(node.input(0));
+    const arm_compute::ITensorInfo *input2         = detail::get_backing_tensor_info(node.input(1));
+    const arm_compute::ITensorInfo *output         = get_backing_tensor_info(node.output(0));
+    const EltwiseOperation          eltwise_op     = node.eltwise_operation();
+    const ConvertPolicy             convert_policy = node.convert_policy();
+    const RoundingPolicy            round_policy   = node.rounding_policy();
+    const ActivationLayerInfo       act_info       = node.fused_activation();
+    const QuantizationInfo          quant_info     = node.output_quant_info();
+    const float                     scale          = (quant_info.scale().empty()) ? 1.0f : quant_info.scale()[0];
+
+    // Validate function
+    if(eltwise_op == EltwiseOperation::Add)
+    {
+        return EltwiseLayerFunctions::ArithmeticAddition::validate(input1, input2, output, convert_policy, act_info);
+    }
+    else if(eltwise_op == EltwiseOperation::Sub)
+    {
+        return EltwiseLayerFunctions::ArithmeticSubtraction::validate(input1, input2, output, convert_policy, act_info);
+    }
+    else if(eltwise_op == EltwiseOperation::Mul)
+    {
+        return EltwiseLayerFunctions::PixelWiseMultiplication::validate(input1, input2, output, scale, convert_policy, round_policy, act_info);
+    }
+    else
+    {
+        ARM_COMPUTE_ERROR("Unsupported element-wise operation!");
+    }
+    return Status{};
+}
+/** Validates a unary element-wise layer node
+ *
+ * @param[in] node Node to validate
+ *
+ * @return Status
+ */
+template <typename UnaryEltwiseLayerFunctions>
+Status validate_unary_eltwise_layer(UnaryEltwiseLayerNode &node)
+{
+    ARM_COMPUTE_LOG_GRAPH_VERBOSE("Validating EltwiseLayer node with ID : " << node.id() << " and Name: " << node.name() << std::endl);
+    ARM_COMPUTE_RETURN_ERROR_ON(node.num_inputs() != 1);
+    ARM_COMPUTE_RETURN_ERROR_ON(node.num_outputs() != 1);
+
+    // Extract input and output
+    arm_compute::ITensorInfo   *input      = detail::get_backing_tensor_info(node.input(0));
+    arm_compute::ITensorInfo   *output     = get_backing_tensor_info(node.output(0));
+    const UnaryEltwiseOperation eltwise_op = node.eltwise_descriptor().op;
+
+    // Validate function
+    if(eltwise_op == UnaryEltwiseOperation::Exp)
+    {
+        return UnaryEltwiseLayerFunctions::ExpLayer::validate(input, output);
+    }
+    else
+    {
+        ARM_COMPUTE_ERROR("Unsupported unary element-wise operation!");
+    }
+
+    return Status{};
+}
 } // namespace detail
 } // namespace backends
 } // namespace graph