IVGCVSW-7423 Add ArmnnDelegatePlugin

Signed-off-by: Narumol Prangnawarat <narumol.prangnawarat@arm.com>
Signed-off-by: Ryan OShea <ryan.oshea3@arm.com>
Change-Id: Ie02021ac56a512598760e4c6d05ef1a80f4aec8d
diff --git a/delegate/cmake/Modules/FindTfLiteAbsl.cmake b/delegate/cmake/Modules/FindTfLiteAbsl.cmake
new file mode 100644
index 0000000..46fab3b
--- /dev/null
+++ b/delegate/cmake/Modules/FindTfLiteAbsl.cmake
@@ -0,0 +1,62 @@
+#
+# Copyright © 2023 Arm Ltd and Contributors. All rights reserved.
+# SPDX-License-Identifier: MIT
+#
+
+include(FindPackageHandleStandardArgs)
+unset(TFLITEABSL_FOUND)
+
+find_path(TfLite_ABSL_SYNC_HEADERS
+        NAMES
+            absl
+        HINTS
+            ${TFLITE_LIB_ROOT}/abseil-cpp)
+
+# First look for the static version of tensorflow lite
+find_library(TfLite_LIB NAMES "libtensorflow-lite.a" HINTS ${TFLITE_LIB_ROOT} ${TFLITE_LIB_ROOT}/tensorflow/lite)
+
+# If the static library was found, gather extra absl libraries for opaque delegate
+if (TfLite_LIB MATCHES .a$)
+    find_library(TfLite_abseil_base_LIB "libabsl_base.a" PATH
+                ${TFLITE_LIB_ROOT}/_deps/abseil-cpp-build/absl/base)
+    find_library(TfLite_abseil_log_severity_LIB "libabsl_log_severity.a" PATH
+                ${TFLITE_LIB_ROOT}/_deps/abseil-cpp-build/absl/base)
+    find_library(TfLite_abseil_spinlock_wait_LIB "libabsl_spinlock_wait.a" PATH
+                ${TFLITE_LIB_ROOT}/_deps/abseil-cpp-build/absl/base)
+    find_library(TfLite_abseil_malloc_internal_LIB "libabsl_malloc_internal.a" PATH
+                ${TFLITE_LIB_ROOT}/_deps/abseil-cpp-build/absl/base)
+    find_library(TfLite_abseil_raw_logging_internal_LIB "libabsl_raw_logging_internal.a" PATH
+                ${TFLITE_LIB_ROOT}/_deps/abseil-cpp-build/absl/base)
+    find_library(TfLite_abseil_stacktrace_LIB "libabsl_stacktrace.a" PATH
+                ${TFLITE_LIB_ROOT}/_deps/abseil-cpp-build/absl/debugging)
+    find_library(TfLite_abseil_debugging_internal_LIB "libabsl_debugging_internal.a" PATH
+                ${TFLITE_LIB_ROOT}/_deps/abseil-cpp-build/absl/debugging)
+    find_library(TfLite_abseil_symbolize_LIB "libabsl_symbolize.a" PATH
+                ${TFLITE_LIB_ROOT}/_deps/abseil-cpp-build/absl/debugging)
+    find_library(TfLite_abseil_demangle_internal_LIB "libabsl_demangle_internal.a" PATH
+                ${TFLITE_LIB_ROOT}/_deps/abseil-cpp-build/absl/debugging)
+    find_library(TfLite_abseil_time_LIB "libabsl_time.a" PATH
+                ${TFLITE_LIB_ROOT}/_deps/abseil-cpp-build/absl/time)
+    find_library(TfLite_abseil_time_zone_LIB "libabsl_time_zone.a" PATH
+                ${TFLITE_LIB_ROOT}/_deps/abseil-cpp-build/absl/time)
+    find_library(TfLite_abseil_int128_LIB "libabsl_int128.a" PATH
+                ${TFLITE_LIB_ROOT}/_deps/abseil-cpp-build/absl/numeric)
+
+    ## Set TFLITEABSL_FOUND
+    find_package_handle_standard_args(TfLiteAbsl DEFAULT_MSG TfLite_ABSL_SYNC_HEADERS TfLite_abseil_base_LIB
+                                      TfLite_abseil_int128_LIB TfLite_abseil_spinlock_wait_LIB
+                                      TfLite_abseil_raw_logging_internal_LIB TfLite_abseil_malloc_internal_LIB
+                                      TfLite_abseil_symbolize_LIB  TfLite_abseil_stacktrace_LIB
+                                      TfLite_abseil_demangle_internal_LIB TfLite_abseil_debugging_internal_LIB
+                                      TfLite_abseil_time_LIB TfLite_abseil_time_zone_LIB)
+
+    ## Set external variables for usage in CMakeLists.txt
+    if(TFLITEABSL_FOUND)
+        set(TfLite_ABSL_SYNC_HEADERS ${TfLite_ABSL_SYNC_HEADERS})
+        set(TfLite_Extra_Absl_LIB ${TfLite_abseil_base_LIB} ${TfLite_abseil_int128_LIB} ${TfLite_abseil_spinlock_wait_LIB}
+                                  ${TfLite_abseil_raw_logging_internal_LIB} ${TfLite_abseil_malloc_internal_LIB}
+                                  ${TfLite_abseil_symbolize_LIB}  ${TfLite_abseil_stacktrace_LIB}
+                                  ${TfLite_abseil_demangle_internal_LIB} ${TfLite_abseil_debugging_internal_LIB}
+                                  ${TfLite_abseil_time_LIB} ${TfLite_abseil_time_zone_LIB})
+    endif()
+endif()
diff --git a/delegate/opaque/CMakeLists.txt b/delegate/opaque/CMakeLists.txt
index d7aed37..a33d3d8 100644
--- a/delegate/opaque/CMakeLists.txt
+++ b/delegate/opaque/CMakeLists.txt
@@ -92,6 +92,11 @@
 
 target_link_libraries(armnnOpaqueDelegateObject PUBLIC flatbuffer_headers_opaque)
 
+# Additional Absl Sync for Opaque Delegate
+find_package(TfLiteAbsl REQUIRED MODULE)
+target_include_directories(armnnOpaqueDelegateObject PUBLIC ${TfLite_ABSL_SYNC_HEADERS})
+target_link_libraries(armnnOpaqueDelegateObject PUBLIC ${TfLite_Extra_Absl_LIB})
+
 ####################################################
 ## Export targets
 install(TARGETS armnnOpaqueDelegateObject
diff --git a/delegate/opaque/include/armnn_delegate.hpp b/delegate/opaque/include/armnn_delegate.hpp
index 653015a..bb6451f 100644
--- a/delegate/opaque/include/armnn_delegate.hpp
+++ b/delegate/opaque/include/armnn_delegate.hpp
@@ -10,6 +10,7 @@
 #include <tensorflow/core/public/version.h>
 #include <tensorflow/lite/c/c_api_opaque.h>
 #include <tensorflow/lite/core/experimental/acceleration/configuration/c/stable_delegate.h>
+#include <tensorflow/lite/experimental/acceleration/configuration/delegate_registry.h>
 
 #if TF_MAJOR_VERSION > 2 || (TF_MAJOR_VERSION == 2 && TF_MINOR_VERSION > 5)
 #define ARMNN_POST_TFLITE_2_5
@@ -87,6 +88,35 @@
 
 extern const TfLiteStableDelegate TFL_TheStableDelegate;
 
+using tflite::delegates::DelegatePluginInterface;
+using TfLiteOpaqueDelegatePtr = tflite::delegates::TfLiteDelegatePtr;
+
+class ArmnnDelegatePlugin : public DelegatePluginInterface
+{
+public:
+    static std::unique_ptr<ArmnnDelegatePlugin> New(const tflite::TFLiteSettings& tflite_settings)
+    {
+        return std::make_unique<ArmnnDelegatePlugin>(tflite_settings);
+    }
+
+    tflite::delegates::TfLiteDelegatePtr Create() override
+    {
+        // Use default settings until options have been enabled.
+        return tflite::delegates::TfLiteDelegatePtr(
+            TfLiteArmnnOpaqueDelegateCreate(nullptr), TfLiteArmnnOpaqueDelegateDelete);
+    }
+
+    int GetDelegateErrno(TfLiteOpaqueDelegate* from_delegate) override
+    {
+        return 0;
+    }
+
+    explicit ArmnnDelegatePlugin(const tflite::TFLiteSettings& tfliteSettings)
+    {
+        // Use default settings until options have been enabled.
+    }
+};
+
 /// ArmnnSubgraph class where parsing the nodes to ArmNN format and creating the ArmNN Graph
 class ArmnnSubgraph
 {
diff --git a/delegate/opaque/src/armnn_delegate.cpp b/delegate/opaque/src/armnn_delegate.cpp
index fa64679..8cdf01f 100644
--- a/delegate/opaque/src/armnn_delegate.cpp
+++ b/delegate/opaque/src/armnn_delegate.cpp
@@ -62,11 +62,15 @@
 const TfLiteStableDelegate TFL_TheStableDelegate =
 {
     /*delegate_abi_version=*/ TFL_STABLE_DELEGATE_ABI_VERSION,
-    /*delegate_name=*/        "ArmnnDelegatePlugin",
-    /*delegate_version=*/     "1.0.0",
+    /*delegate_name=*/        "armnn_delegate",
+    /*delegate_version=*/     OPAQUE_DELEGATE_VERSION,
     /*delegate_plugin=*/      GetArmnnDelegatePluginApi()
 };
 
+static auto* g_delegate_plugin_ArmnnDelegatePlugin_ =
+    new tflite::delegates::DelegatePluginRegistry::Register(TFL_TheStableDelegate.delegate_name,
+                                                            ArmnnDelegatePlugin::New);
+
 ArmnnOpaqueDelegate::ArmnnOpaqueDelegate(armnnDelegate::DelegateOptions options)
     : m_Options(std::move(options))
 {
@@ -121,7 +125,9 @@
 
     // ArmNN Opaque Delegate Registration
     TfLiteRegistrationExternal* kernelRegistration =
-            TfLiteRegistrationExternalCreate(kTfLiteBuiltinDelegate, "TfLiteArmNNOpaqueDelegate", /*version=*/1);
+            TfLiteRegistrationExternalCreate(kTfLiteBuiltinDelegate,
+                                             TFL_TheStableDelegate.delegate_name,
+                                             /*version=*/OPAQUE_DELEGATE_MAJOR_VERSION);
     if(kernelRegistration == nullptr)
     {
         return kTfLiteError;
diff --git a/delegate/opaque/src/test/ArmnnOpaqueDelegateTest.cpp b/delegate/opaque/src/test/ArmnnOpaqueDelegateTest.cpp
index 1635b65..79f98a9 100644
--- a/delegate/opaque/src/test/ArmnnOpaqueDelegateTest.cpp
+++ b/delegate/opaque/src/test/ArmnnOpaqueDelegateTest.cpp
@@ -9,6 +9,9 @@
 #include <opaque/include/armnn_delegate.hpp>
 #include <opaque/include/Version.hpp>
 
+#include <flatbuffers/flatbuffers.h>
+#include <tensorflow/lite/experimental/acceleration/configuration/delegate_registry.h>
+
 namespace armnnOpaqueDelegate
 {
 
@@ -37,6 +40,28 @@
     armnnOpaqueDelegate::TfLiteArmnnOpaqueDelegateDelete(opaqueDelegate);
 }
 
+TEST_CASE ("DelegatePluginTest")
+{
+    // Use default settings until options have been enabled.
+    flatbuffers::FlatBufferBuilder flatBufferBuilder;
+    tflite::TFLiteSettingsBuilder tfliteSettingBuilder(flatBufferBuilder);
+    flatbuffers::Offset<tflite::TFLiteSettings> tfliteSettings = tfliteSettingBuilder.Finish();
+    flatBufferBuilder.Finish(tfliteSettings);
+    const tflite::TFLiteSettings* settings = flatbuffers::GetRoot<tflite::TFLiteSettings>(
+        flatBufferBuilder.GetBufferPointer());
+
+    std::unique_ptr<tflite::delegates::DelegatePluginInterface> delegatePlugin =
+        tflite::delegates::DelegatePluginRegistry::CreateByName("armnn_delegate", *settings);
+
+    // Plugin is created correctly using armnn_delegate name.
+    CHECK((delegatePlugin != nullptr));
+
+    tflite::delegates::TfLiteDelegatePtr armnnDelegate = delegatePlugin->Create();
+
+    // Armnn Opaque Delegate is created correctly.
+    CHECK((armnnDelegate != nullptr));
+    CHECK((armnnDelegate->opaque_delegate_builder != nullptr));
 }
 
+}
 } // namespace armnnDelegate