IVGCVSW-7888 Add Tile convert function


Signed-off-by: Teresa Charlin <teresa.charlinreyes@arm.com>
Change-Id: Ic9479be6b3e6cf0e529c685c9b28c642e9dd00d5
diff --git a/1.2/HalPolicy.cpp b/1.2/HalPolicy.cpp
index 4e53c74..39616c5 100644
--- a/1.2/HalPolicy.cpp
+++ b/1.2/HalPolicy.cpp
@@ -185,6 +185,8 @@
             return ConvertTransposeConv2d(operation, model, data);
         case V1_2::OperationType::TANH:
             return ConvertTanH(operation, model, data);
+        case V1_2::OperationType::TILE:
+            return ConvertTile(operation, model, data);
         case V1_2::OperationType::UNIDIRECTIONAL_SEQUENCE_LSTM:
             return ConvertUnidirectionalSequenceLstm(operation, model, data);
         default:
@@ -498,6 +500,12 @@
     return ::ConvertTransposeConv2d<hal_1_2::HalPolicy>(operation, model, data);
 }
 
+bool HalPolicy::ConvertTile(const Operation& operation, const Model& model, ConversionData& data)
+{
+    ALOGV("hal_1_2::HalPolicy::ConvertTile()");
+    return ::ConvertTile<hal_1_2::HalPolicy>(operation, model, data);
+}
+
 bool HalPolicy::ConvertUnidirectionalSequenceLstm(const Operation& operation, const Model& model, ConversionData& data)
 {
     ALOGV("hal_1_2::HalPolicy::ConvertUnidirectionalSequenceLstm()");
diff --git a/1.2/HalPolicy.hpp b/1.2/HalPolicy.hpp
index 4121ec9..796f4de 100644
--- a/1.2/HalPolicy.hpp
+++ b/1.2/HalPolicy.hpp
@@ -153,6 +153,8 @@
 
     static bool ConvertTransposeConv2d(const Operation& operation, const Model& model, ConversionData& data);
 
+    static bool ConvertTile(const Operation& operation, const Model& model, ConversionData& data);
+
     static bool ConvertUnidirectionalSequenceLstm(const Operation& operation,
                                                   const Model& model,
                                                   ConversionData& data);
diff --git a/1.3/HalPolicy.cpp b/1.3/HalPolicy.cpp
index aaf0813..2c8ef06 100644
--- a/1.3/HalPolicy.cpp
+++ b/1.3/HalPolicy.cpp
@@ -173,6 +173,8 @@
             return ConvertTransposeConv2d(operation, model, data);
         case V1_3::OperationType::TANH:
             return ConvertTanH(operation, model, data);
+        case V1_3::OperationType::TILE:
+            return ConvertTile(operation, model, data);
         case V1_3::OperationType::UNIDIRECTIONAL_SEQUENCE_LSTM:
             return ConvertUnidirectionalSequenceLstm(operation, model, data);
         default:
@@ -501,6 +503,12 @@
     return ::ConvertTransposeConv2d<hal_1_3::HalPolicy>(operation, model, data);
 }
 
+bool HalPolicy::ConvertTile(const Operation& operation, const Model& model, ConversionData& data)
+{
+    ALOGV("hal_1_3::HalPolicy::ConvertTile()");
+    return ::ConvertTile<hal_1_3::HalPolicy>(operation, model, data);
+}
+
 bool HalPolicy::ConvertSqrt(const Operation& operation, const Model& model, ConversionData& data)
 {
     ALOGV("hal_1_3::HalPolicy::ConvertSqrt()");
diff --git a/1.3/HalPolicy.hpp b/1.3/HalPolicy.hpp
index 63e5ee7..b0bc09b 100644
--- a/1.3/HalPolicy.hpp
+++ b/1.3/HalPolicy.hpp
@@ -165,6 +165,8 @@
 
     static bool ConvertTransposeConv2d(const Operation& operation, const Model& model, ConversionData& data);
 
+    static bool ConvertTile(const Operation& operation, const Model& model, ConversionData& data);
+
     static bool ConvertUnidirectionalSequenceLstm(const Operation& operation,
                                                   const Model& model,
                                                   ConversionData& data);
diff --git a/ConversionUtils_1_2.hpp b/ConversionUtils_1_2.hpp
index 2ad14c2..5b38b07 100644
--- a/ConversionUtils_1_2.hpp
+++ b/ConversionUtils_1_2.hpp
@@ -2888,6 +2888,84 @@
 template<typename HalPolicy,
          typename HalOperation = typename HalPolicy::Operation,
          typename HalModel     = typename HalPolicy::Model>
+bool ConvertTile(const HalOperation& operation, const HalModel& model, ConversionData& data)
+{
+    using HalOperand     = typename HalPolicy::Operand;
+
+    LayerInputHandle input = ConvertToLayerInputHandle<HalPolicy>(operation, 0, model, data);
+
+    if (!input.IsValid())
+    {
+        return Fail("%s: Operation has invalid inputs", __func__);
+    }
+
+    const HalOperand* output = GetOutputOperand<HalPolicy>(operation, 0, model);
+
+    if (!output)
+    {
+        return Fail("%s: Could not read output", __func__);
+    }
+
+    const HalOperand* multiplesOperand = GetInputOperand<HalPolicy>(operation, 1, model);
+    if (!multiplesOperand)
+    {
+        return Fail("%s: Could not read input 1", __func__);
+    }
+    std::vector<int32_t> multiples;
+    if (!GetTensorInt32Values<HalPolicy>(*multiplesOperand, multiples, model, data))
+    {
+        return Fail("%s: Input 1 has invalid values", __func__);
+    }
+    // Convert the multiples from int to unsigned int,
+    // as values are always going to be positive despite the data type being integer.
+    TileDescriptor descriptor;
+    descriptor.m_Multiples.assign(multiples.begin(), multiples.end());
+
+    const TensorInfo& inputInfo  = input.GetTensorInfo();
+    const TensorInfo& outputInfo = GetTensorInfoForOperand(*output);
+
+    bool isSupported = false;
+    armnn::BackendId setBackend;
+    auto validateFunc = [&](const armnn::TensorInfo& outputInfo, bool& isSupported)
+    {
+        FORWARD_LAYER_SUPPORT_FUNC(__func__,
+                                   IsTileSupported,
+                                   data.m_Backends,
+                                   isSupported,
+                                   setBackend,
+                                   inputInfo,
+                                   outputInfo,
+                                   descriptor);
+    };
+
+    if(IsDynamicTensor(outputInfo))
+    {
+        isSupported = AreDynamicTensorsSupported();
+    }
+    else
+    {
+        validateFunc(outputInfo, isSupported);
+    }
+    if (!isSupported)
+    {
+        return false;
+    }
+
+    IConnectableLayer* tileLayer = data.m_Network->AddTileLayer(descriptor);
+    if (!tileLayer)
+    {
+        return Fail("%s: AddTileLayer failed", __func__);
+    }
+    tileLayer->SetBackendId(setBackend);
+
+    input.Connect(tileLayer->GetInputSlot(0));
+
+    return SetupAndTrackLayerOutputSlot<HalPolicy>(operation, 0, *tileLayer, model, data, nullptr, validateFunc);
+}
+
+template<typename HalPolicy,
+         typename HalOperation = typename HalPolicy::Operation,
+         typename HalModel     = typename HalPolicy::Model>
 bool ConvertTransposeConv2d(const HalOperation& operation, const HalModel& model, ConversionData& data)
 {
     using HalOperand     = typename HalPolicy::Operand;