IVGCVSW-5539 'Elementwise layers with const tensors are not connecting up'

* Added Constant Input support to ElementwiseBinary Layers

Signed-off-by: Sadik Armagan <sadik.armagan@arm.com>
Change-Id: I1d429fd7958fe2aa53f06c229a863243569c0d71
diff --git a/delegate/src/DelegateUtils.hpp b/delegate/src/DelegateUtils.hpp
index e9f579b..0537ba9 100644
--- a/delegate/src/DelegateUtils.hpp
+++ b/delegate/src/DelegateUtils.hpp
@@ -17,6 +17,8 @@
 #include <tensorflow/lite/c/common.h>
 #include <tensorflow/lite/minimal_logging.h>
 
+#include "tensorflow/lite/kernels/kernel_util.h"
+
 namespace
 {
 
@@ -365,8 +367,20 @@
     auto tensorDimensionSize = tfLiteTensor.dims->size;
     if (tensorDimensionSize == 0)
     {
-        armnn::TensorShape tensorShape(armnn::Dimensionality::NotSpecified);
-        ret = armnn::TensorInfo(tensorShape, type);
+        if(tflite::IsConstantTensor(&tfLiteTensor))
+        {
+            std::vector<unsigned int> safeShape = { 1 };
+            bool dimensionsSpecificity[1] = { true };
+            armnn::TensorShape tensorShape(armnn::numeric_cast<unsigned int>(safeShape.size()),
+                                           safeShape.data(),
+                                           dimensionsSpecificity);
+            ret = armnn::TensorInfo(tensorShape, type);
+        }
+        else
+        {
+            armnn::TensorShape tensorShape(armnn::Dimensionality::NotSpecified);
+            ret = armnn::TensorInfo(tensorShape, type);
+        }
     }
     else
     {
@@ -468,6 +482,35 @@
     }
 }
 
+TfLiteStatus ConnectConstant(armnn::IConnectableLayer* layer,
+                             armnn::TensorInfo& constTensorInfo,
+                             TfLiteContext* tfLiteContext,
+                             const TfLiteTensor& tfLiteTensor,
+                             armnnDelegate::DelegateData& data,
+                             unsigned int slotIndex)
+{
+    bool isSupported = false;
+    FORWARD_LAYER_SUPPORT_FUNC(__func__,
+                               tfLiteContext,
+                               IsConstantSupported,
+                               data.m_Backends,
+                               isSupported,
+                               constTensorInfo);
+    if (!isSupported)
+    {
+        return kTfLiteError;
+    }
 
+    auto constantInput = CreateConstTensor(&tfLiteTensor,
+                                           constTensorInfo,
+                                           armnn::Optional<armnn::PermutationVector&>());
+    armnn::IConnectableLayer* constantLayer = data.m_Network->AddConstantLayer(constantInput);
+    armnn::IOutputSlot& outputSlot = constantLayer->GetOutputSlot(0);
+    outputSlot.SetTensorInfo(constTensorInfo);
+
+    data.m_OutputSlotForNode[static_cast<unsigned long>(slotIndex)] = &outputSlot;
+
+    return kTfLiteOk;
+}
 
 } // namespace anonymous
diff --git a/delegate/src/ElementwiseBinary.hpp b/delegate/src/ElementwiseBinary.hpp
index 3d3f1a0..e527005 100644
--- a/delegate/src/ElementwiseBinary.hpp
+++ b/delegate/src/ElementwiseBinary.hpp
@@ -11,6 +11,7 @@
 #include <tensorflow/lite/c/builtin_op_data.h>
 #include <tensorflow/lite/c/common.h>
 #include <tensorflow/lite/minimal_logging.h>
+#include "tensorflow/lite/delegates/utils.h"
 
 namespace armnnDelegate
 {
@@ -193,8 +194,9 @@
         return kTfLiteError;
     }
 
-    const armnn::TensorInfo& inputTensorInfo0 = GetTensorInfoForTfLiteTensor(tfLiteInputTensor0);
-    const armnn::TensorInfo& inputTensorInfo1 = GetTensorInfoForTfLiteTensor(tfLiteInputTensor1);
+    armnn::TensorInfo inputTensorInfo0 = GetTensorInfoForTfLiteTensor(tfLiteInputTensor0);
+    armnn::TensorInfo inputTensorInfo1 = GetTensorInfoForTfLiteTensor(tfLiteInputTensor1);
+
     const armnn::TensorInfo& outputTensorInfo = GetTensorInfoForTfLiteTensor(tfLiteOutputTensor);
 
     if (!delegateData.m_Network)
@@ -268,10 +270,37 @@
             return kTfLiteError;
     }
     ARMNN_ASSERT(elementwiseBinaryLayer != nullptr);
-
     armnn::IOutputSlot& outputSlot = elementwiseBinaryLayer->GetOutputSlot(0);
     outputSlot.SetTensorInfo(outputTensorInfo);
 
+    if(tflite::IsConstantTensor(&tfLiteInputTensor0))
+    {
+        auto status = ConnectConstant(elementwiseBinaryLayer,
+                                      inputTensorInfo0,
+                                      tfLiteContext,
+                                      tfLiteInputTensor0,
+                                      delegateData,
+                                      tfLiteNode->inputs->data[0]);
+        if (status == kTfLiteError)
+        {
+            return status;
+        }
+    }
+
+    if(tflite::IsConstantTensor(&tfLiteInputTensor1))
+    {
+        auto status = ConnectConstant(elementwiseBinaryLayer,
+                                      inputTensorInfo1,
+                                      tfLiteContext,
+                                      tfLiteInputTensor1,
+                                      delegateData,
+                                      tfLiteNode->inputs->data[1]);
+        if (status == kTfLiteError)
+        {
+            return status;
+        }
+    }
+
     auto reshapeLayer = BroadcastTensor(inputTensorInfo0,
                                         inputTensorInfo1,
                                         elementwiseBinaryLayer,
@@ -291,7 +320,7 @@
     }
     // Check activation
     TfLiteFusedActivation activationType = tfLiteNodeParameters->activation;
-    return FusedActivation(tfLiteContext, tfLiteNode, activationType, reshapeLayer, 0, delegateData);
+    return FusedActivation(tfLiteContext, tfLiteNode, activationType, elementwiseBinaryLayer, 0, delegateData);
 }
 
 } // namespace armnnDelegate