Migration to tensorflow v1.9.0 (#2054)
author오형석/동작제어Lab(SR)/Staff Engineer/삼성전자 <hseok82.oh@samsung.com>
Tue, 24 Jul 2018 00:38:41 +0000 (09:38 +0900)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Tue, 24 Jul 2018 00:38:41 +0000 (09:38 +0900)
Fix test using tensorflow function
Update nnapi_delegate.cpp/h
Update supporting custom operation
Add submodules for dependency

To use this, need to update tensorflow submodule

Signed-off-by: Hyeongseok Oh <hseok82.oh@samsung.com>
68 files changed:
.gitmodules
cmake/option/option_linux.cmake
externals/eigen [new submodule]
externals/farmhash [new submodule]
externals/flatbuffers [new submodule]
externals/gemmlowp [new submodule]
externals/neon_2_sse [new submodule]
externals/tensorflow
include/support/tflite/kernels/register.h
include/support/tflite/nnapi_delegate.h
libs/support/tflite/src/kernels/TensorFlowMax.cpp
libs/support/tflite/src/kernels/register.cpp
libs/support/tflite/src/nnapi_delegate.cpp
tools/nnapi_unittests/tests/add_1.cpp
tools/nnapi_unittests/tests/add_2.cpp
tools/nnapi_unittests/tests/add_3.cpp
tools/nnapi_unittests/tests/add_4.cpp
tools/nnapi_unittests/tests/add_5.cpp
tools/nnapi_unittests/tests/add_6.cpp
tools/nnapi_unittests/tests/add_7.cpp
tools/nnapi_unittests/tests/add_8.cpp
tools/nnapi_unittests/tests/add_9.cpp
tools/nnapi_unittests/tests/add_quan_1.cpp
tools/nnapi_unittests/tests/avg_pool_1.cpp
tools/nnapi_unittests/tests/avg_pool_quan_1.cpp
tools/nnapi_unittests/tests/cast_1.cpp
tools/nnapi_unittests/tests/cast_2.cpp
tools/nnapi_unittests/tests/cast_q_to_f_1.cpp
tools/nnapi_unittests/tests/concat_1.cpp
tools/nnapi_unittests/tests/concat_quan_1.cpp
tools/nnapi_unittests/tests/conv_1.cpp
tools/nnapi_unittests/tests/conv_quan_1.cpp
tools/nnapi_unittests/tests/dconv_1.cpp
tools/nnapi_unittests/tests/dconv_quan_1.cpp
tools/nnapi_unittests/tests/dequantize_1.cpp
tools/nnapi_unittests/tests/div_1.cpp
tools/nnapi_unittests/tests/div_2.cpp
tools/nnapi_unittests/tests/fully_connected_1.cpp
tools/nnapi_unittests/tests/fully_connected_quan_1.cpp
tools/nnapi_unittests/tests/gather_1.cpp
tools/nnapi_unittests/tests/gather_2.cpp
tools/nnapi_unittests/tests/max_pool_1.cpp
tools/nnapi_unittests/tests/max_pool_quan_1.cpp
tools/nnapi_unittests/tests/mul_1.cpp
tools/nnapi_unittests/tests/mul_2.cpp
tools/nnapi_unittests/tests/mul_quan_1.cpp
tools/nnapi_unittests/tests/relu1_1.cpp
tools/nnapi_unittests/tests/relu6_1.cpp
tools/nnapi_unittests/tests/relu6_quan_1.cpp
tools/nnapi_unittests/tests/relu_1.cpp
tools/nnapi_unittests/tests/relu_2.cpp
tools/nnapi_unittests/tests/relu_3.cpp
tools/nnapi_unittests/tests/relu_quan_1.cpp
tools/nnapi_unittests/tests/reshape_1.cpp
tools/nnapi_unittests/tests/reshape_quan_1.cpp
tools/nnapi_unittests/tests/resize_bilinear_1.cpp
tools/nnapi_unittests/tests/softmax_1.cpp
tools/nnapi_unittests/tests/softmax_2.cpp
tools/nnapi_unittests/tests/softmax_quan_1.cpp
tools/nnapi_unittests/tests/sub_1.cpp
tools/nnapi_unittests/tests/sub_2.cpp
tools/nnapi_unittests/tests/sub_3.cpp
tools/nnapi_unittests/tests/sub_4.cpp
tools/nnapi_unittests/tests/sub_5.cpp
tools/nnapi_unittests/tests/sub_6.cpp
tools/nnapi_unittests/tests/tanh_1.cpp
tools/nnapi_unittests/tests/topk_v2_1.cpp
tools/tflite_examples/src/conv.cpp

index f8aaee4..34efb97 100644 (file)
@@ -7,3 +7,18 @@
        url = git@github.sec.samsung.net:RS7-RuntimeNTools/ComputeLibrary.git
        branch = nnfw
        ignore = dirty
+[submodule "farmhash"]
+       path = externals/farmhash
+       url = git://github.com/google/farmhash
+[submodule "flatbuffers"]
+       path = externals/flatbuffers
+       url = git://github.com/google/flatbuffers
+[submodule "gemmlowp"]
+       path = externals/gemmlowp
+       url = git://github.com/google/gemmlowp
+[submodule "neon_2_sse"]
+       path = externals/neon_2_sse
+       url = git://github.com/intel/ARM_NEON_2_x86_SSE
+[submodule "eigen"]
+       path = externals/eigen
+       url = git://github.com/eigenteam/eigen-git-mirror
index f668fad..8cae4e9 100644 (file)
@@ -26,4 +26,8 @@ set(LIB_PTHREAD pthread)
 # nnfw common path
 set(NNFW_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/include)
 set(NNFW_EXTERNALS_DIR ${CMAKE_SOURCE_DIR}/externals)
-set(TFLITE_DEPEND_DIR ${NNFW_EXTERNALS_DIR}/tensorflow/tensorflow/contrib/lite/downloads)
+
+# External sources to build tflite
+# If already downloaded files are in tensorflow/tensorflow/contrib/lite/downloads,
+# set TFLITE_DEPEND_DIR to ${NNFW_EXTERNALS_DIR}/tensorflow/tensorflow/contrib/lite/downloads
+set(TFLITE_DEPEND_DIR ${NNFW_EXTERNALS_DIR})
diff --git a/externals/eigen b/externals/eigen
new file mode 160000 (submodule)
index 0000000..f21be5f
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit f21be5f8d1591d2e2f774af30cb265b5781c4ce9
diff --git a/externals/farmhash b/externals/farmhash
new file mode 160000 (submodule)
index 0000000..816a4ae
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit 816a4ae622e964763ca0862d9dbd19324a1eaf45
diff --git a/externals/flatbuffers b/externals/flatbuffers
new file mode 160000 (submodule)
index 0000000..971a681
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit 971a68110e4fc1bace10fcb6deeb189e7e1a34ce
diff --git a/externals/gemmlowp b/externals/gemmlowp
new file mode 160000 (submodule)
index 0000000..38ebac7
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit 38ebac7b059e84692f53e5938f97a9943c120d98
diff --git a/externals/neon_2_sse b/externals/neon_2_sse
new file mode 160000 (submodule)
index 0000000..0f77d9d
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit 0f77d9d182265259b135dad949230ecbf1a2633d
index 040ac56..dc9fc1b 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 040ac56a2db2b5318d5b0d9a97c2af88d0be830d
+Subproject commit dc9fc1bff1e381f395a157b8ea1e7762c39f5c58
index 365370c..43a4c1a 100644 (file)
@@ -24,37 +24,17 @@ limitations under the License.
 #include "tensorflow/contrib/lite/model.h"
 
 // TODO Use namespace nnfw
-namespace tflite
-{
-namespace ops
-{
-namespace builtin
-{
-
-class BuiltinOpResolver : public OpResolver
-{
-public:
+namespace tflite {
+namespace ops {
+namespace builtin {
+
+class BuiltinOpResolver : public MutableOpResolver {
+ public:
   BuiltinOpResolver();
-  TfLiteRegistration *FindOp(tflite::BuiltinOperator op) const override;
-  TfLiteRegistration *FindOp(const char *op) const override;
-  void AddBuiltin(tflite::BuiltinOperator op, TfLiteRegistration *registration);
-  void AddCustom(const char *name, TfLiteRegistration *registration);
-
-private:
-  struct BuiltinOperatorHasher
-  {
-    size_t operator()(const tflite::BuiltinOperator &x) const
-    {
-      return std::hash<size_t>()(static_cast<size_t>(x));
-    }
-  };
-  std::unordered_map<tflite::BuiltinOperator, TfLiteRegistration *, BuiltinOperatorHasher>
-      builtins_;
-  std::unordered_map<std::string, TfLiteRegistration *> custom_ops_;
 };
 
-} // namespace builtin
-} // namespace ops
-} // namespace tflite
+}  // namespace builtin
+}  // namespace ops
+}  // namespace tflite
 
 #endif // __NNFW_SUPPORT_TFLITE_KERNELS_REGISTER_H__
index 0d0c686..a5da8ac 100644 (file)
@@ -14,18 +14,44 @@ See the License for the specific language governing permissions and
 limitations under the License.
 ==============================================================================*/
 
+// NOTE To minimize diff with upstream tensorflow, disable clang-format
+// clang-format off
+
 // NOTE This header is derived from the following file (in TensorFlow)
 //        'externals/tensorflow/tensorflow/contrib/lite/nnapi_delegate.h'
 #ifndef __NNFW_SUPPORT_TFLITE_NNAPI_DELEGATE_H__
 #define __NNFW_SUPPORT_TFLITE_NNAPI_DELEGATE_H__
 
+#include "tensorflow/contrib/lite/allocation.h"
+#include "tensorflow/contrib/lite/context.h"
+#include "tensorflow/contrib/lite/error_reporter.h"
 #include "tensorflow/contrib/lite/interpreter.h"
+#include "NeuralNetworksShim.h"
 
 class ANeuralNetworksModel;
 class ANeuralNetworksCompilation;
 
 namespace nnfw {
 
+class NNAPIAllocation : public tflite::MMAPAllocation {
+ public:
+  NNAPIAllocation(const char* filename, ::tflite::ErrorReporter* error_reporter);
+  ~NNAPIAllocation();
+
+  size_t offset(const void* ptr) const {
+    auto signed_offset = reinterpret_cast<const uint8_t*>(ptr) -
+                         reinterpret_cast<const uint8_t*>(mmapped_buffer_);
+
+    return static_cast<size_t>(signed_offset);
+  }
+
+  ANeuralNetworksMemory* memory() const { return handle_; }
+  bool valid() const override { return handle_ != nullptr; }
+
+ private:
+  mutable ANeuralNetworksMemory* handle_ = nullptr;
+};
+
 class NNAPIDelegate {
  public:
   ~NNAPIDelegate();
@@ -41,8 +67,18 @@ class NNAPIDelegate {
   ANeuralNetworksModel* nn_model_ = nullptr;
   // The NN API compilation handle
   ANeuralNetworksCompilation* nn_compiled_model_ = nullptr;
+
+  // List of state tensors for LSTM, RNN, SVDF.
+  // NN API does not allow ops to maintain states across multiple
+  // invocations. We need to manually create state input tensors from
+  // corresponding state output tensors of TFLite operations, and map them
+  // correctly.
+  std::vector<int> model_states_inputs_;   // holds NNAPI operand ids
+  std::vector<int> model_states_outputs_;  // holds TFLite tensor ids
 };
 
 } // namespace nnfw
 
 #endif  // TENSORFLOW_CONTRIB_LITE_NNAPI_DELEGATE_H_
+
+// clang-format on
index 7979387..abc6fda 100644 (file)
@@ -38,8 +38,8 @@ struct TensorFlowMaxOp
     axis = tflite::GetInput(context, node, 1);
     output = tflite::GetOutput(context, node, 0);
   }
-  TfLiteTensor *input;
-  TfLiteTensor *axis;
+  const TfLiteTensor *input;
+  const TfLiteTensor *axis;
   TfLiteTensor *output;
 };
 
index 2f1634d..70eae8d 100644 (file)
@@ -130,30 +130,6 @@ BuiltinOpResolver::BuiltinOpResolver()
   AddCustom("TensorFlowMax", tflite::ops::custom::nnfw::Register_TensorFlowMax());
 }
 
-TfLiteRegistration *BuiltinOpResolver::FindOp(tflite::BuiltinOperator op) const
-{
-  auto it = builtins_.find(op);
-  return it != builtins_.end() ? it->second : nullptr;
-}
-
-TfLiteRegistration *BuiltinOpResolver::FindOp(const char *op) const
-{
-  auto it = custom_ops_.find(op);
-  return it != custom_ops_.end() ? it->second : nullptr;
-}
-
-void BuiltinOpResolver::AddBuiltin(tflite::BuiltinOperator op, TfLiteRegistration *registration)
-{
-  registration->builtin_code = op;
-  builtins_.insert(std::make_pair(op, registration));
-}
-
-void BuiltinOpResolver::AddCustom(const char *name, TfLiteRegistration *registration)
-{
-  registration->builtin_code = BuiltinOperator_CUSTOM;
-  custom_ops_.insert(std::make_pair(std::string(name), registration));
-}
-
 } // namespace builtin
 } // namespace ops
 } // namespace tflite
index fbbfced..45b70de 100644 (file)
@@ -14,21 +14,31 @@ See the License for the specific language governing permissions and
 limitations under the License.
 ==============================================================================*/
 
+// NOTE To minimize diff with upstream tensorflow, disable clang-format
+// clang-format off
+
 // NOTE This code is derived from the following file (in TensorFlow)
 //        'externals/tensorflow/tensorflow/contrib/lite/nnapi_delegate.cc'
-#include "NeuralNetworksShim.h"
-#include "NeuralNetworksExShim.h"
 #include "support/tflite/nnapi_delegate.h"
-
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #include "tensorflow/contrib/lite/builtin_op_data.h"
+#include "tensorflow/contrib/lite/error_reporter.h"
 #include "tensorflow/contrib/lite/model.h"
+#include "NeuralNetworksShim.h"
+#include "NeuralNetworksExShim.h"
+
+#ifdef __ANDROID__
+#include <sys/system_properties.h>
+#endif
 
 namespace nnfw
 {
 
 // TODO(aselle): FATAL leaves resources hanging.
-void FATAL(const char *format, ...)
-{
+void FATAL(const char* format, ...) {
   va_list args;
   va_start(args, format);
   vfprintf(stderr, format, args);
@@ -38,16 +48,62 @@ void FATAL(const char *format, ...)
 }
 
 // TODO(aselle): Change the error model to use status codes.
+#define CHECK_TFLITE_SUCCESS(x)                       \
+  if (x != kTfLiteOk) {                               \
+    FATAL("Aborting since tflite returned failure."); \
+  }
+
 #define CHECK_NN(x)                                   \
-  if (x != ANEURALNETWORKS_NO_ERROR)                  \
-  {                                                   \
+  if (x != ANEURALNETWORKS_NO_ERROR) {                \
     FATAL("Aborting since tflite returned failure."); \
   }
 
-NNAPIDelegate::~NNAPIDelegate()
-{
-  if (nn_model_)
-  {
+namespace {
+
+int32_t GetAndroidSdkVersion() {
+#ifdef __ANDROID__
+  const char* sdkProp = "ro.build.version.sdk";
+  char sdkVersion[PROP_VALUE_MAX];
+  int length = __system_property_get(sdkProp, sdkVersion);
+  if (length != 0) {
+    for (int i = 0; i < length; ++i) {
+      int digit = sdkVersion[i] - '0';
+      if (digit < 0 || digit > 9) {
+        // Non-numeric SDK version, assume it's higher then expected;
+        return 0xFFFF;
+      }
+    }
+    return atoi(sdkVersion);
+  }
+  FATAL("No %s prop", sdkProp);
+#endif  // __ANDROID__
+  return 0;
+}
+
+static const int32_t kAndroidSdkVersion = GetAndroidSdkVersion();
+
+}  // namespace
+
+NNAPIAllocation::NNAPIAllocation(const char* filename,
+                                 ::tflite::ErrorReporter* error_reporter)
+    : MMAPAllocation(filename, error_reporter) {
+  if (mmapped_buffer_ != MAP_FAILED)
+    CHECK_NN(ANeuralNetworksMemory_createFromFd(buffer_size_bytes_, PROT_READ,
+                                                mmap_fd_, 0, &handle_));
+}
+
+NNAPIAllocation::~NNAPIAllocation() {
+  if (handle_) {
+    ANeuralNetworksMemory_free(handle_);
+  }
+}
+
+NNAPIDelegate::~NNAPIDelegate() {
+  if (nn_compiled_model_) {
+    ANeuralNetworksCompilation_free(nn_compiled_model_);
+    nn_compiled_model_ = nullptr;
+  }
+  if (nn_model_) {
     ANeuralNetworksModel_free(nn_model_);
     nn_model_ = nullptr;
     // TODO(aselle): Is this thread-safe and callable multiple times?
@@ -57,32 +113,27 @@ NNAPIDelegate::~NNAPIDelegate()
 
 // Adds the tensors of the interpreter to the NN API model.
 // Returns the number of operands added.
-uint32_t addTensorOperands(tflite::Interpreter *interpreter, ANeuralNetworksModel *nn_model,
-                           const std::vector<uint32_t> &skip_list)
-{
+uint32_t addTensorOperands(tflite::Interpreter* interpreter,
+                               ANeuralNetworksModel* nn_model,
+                               const std::vector<uint32_t>& skip_list) {
   uint32_t next_id = 0;
-  for (size_t i = 0; i < interpreter->tensors_size(); i++)
-  {
+  for (size_t i = 0; i < interpreter->tensors_size(); i++) {
     // skip temporaries tensors.
     bool shouldSkip = false;
-    for (auto skip_idx : skip_list)
-    {
-      if (i == skip_idx)
-      {
+    for (auto skip_idx : skip_list) {
+      if (i == skip_idx) {
         shouldSkip = true;
         break;
       }
     }
-    if (shouldSkip)
-      continue;
+    if (shouldSkip) continue;
 
     int32_t nn_type = 0;
     // NNAPI requires 32-bit float scale to be zero, tflite doesn't care
     float scale = 0.0f;
     int32_t zeroPoint = 0;
-    TfLiteTensor *tensor = interpreter->tensor(i);
-    switch (tensor->type)
-    {
+    TfLiteTensor* tensor = interpreter->tensor(i);
+    switch (tensor->type) {
       case kTfLiteNoType:
         // Tensors added during initialization of Ops don't have a type yet and
         // should not be registered with the NNAPI.
@@ -93,10 +144,12 @@ uint32_t addTensorOperands(tflite::Interpreter *interpreter, ANeuralNetworksMode
       case kTfLiteUInt8:
         nn_type = ANEURALNETWORKS_TENSOR_QUANT8_ASYMM;
         scale = tensor->params.scale;
-        // FIXME The next line is a workaround because currently zero scale is passed down from TF
+        // FIXME The next line is a workaround because currently zero scale is
+        // passed down from TF
         //       Lite.  Note that the latest NeuralNetworks.h (see
         //       https://android.googlesource.com/platform/frameworks/ml/+/master/nn/runtime/include/NeuralNetworks.h)
-        //       requires scale to be greater than zero.  Remove this workaround when the scale
+        //       requires scale to be greater than zero.  Remove this workaround
+        //       when the scale
         //       value is correctly passed.
         scale = (scale == 0.0f) ? 1.0f : scale;
         zeroPoint = tensor->params.zero_point;
@@ -114,18 +167,28 @@ uint32_t addTensorOperands(tflite::Interpreter *interpreter, ANeuralNetworksMode
     // on all of them, but I shouldn't in the future.
     // Answer(jeanluc): If all the operators can set the dimension correctly,
     // you won't need to.
-    ANeuralNetworksOperandType operand_type{nn_type, static_cast<uint32_t>(tensor->dims->size),
-                                            reinterpret_cast<uint32_t *>(tensor->dims->data), scale,
-                                            zeroPoint};
+    ANeuralNetworksOperandType operand_type{
+        nn_type, static_cast<uint32_t>(tensor->dims->size),
+        reinterpret_cast<uint32_t*>(tensor->dims->data), scale, zeroPoint};
     CHECK_NN(ANeuralNetworksModel_addOperand(nn_model, &operand_type));
-
     // TODO(aselle): Based on Michael's suggestion, limiting this to read
     // only memory
-    if (tensor->allocation_type == kTfLiteMmapRo)
-    {
+    if (tensor->allocation_type == kTfLiteMmapRo) {
+      if (const NNAPIAllocation* alloc = dynamic_cast<const NNAPIAllocation*>(
+              static_cast<const ::tflite::Allocation*>(tensor->allocation))) {
+        CHECK_NN(ANeuralNetworksModel_setOperandValueFromMemory(
+            nn_model, next_id, alloc->memory(), alloc->offset(tensor->data.raw),
+            tensor->bytes));
+      } else {
+        CHECK_NN(ANeuralNetworksModel_setOperandValue(
+            nn_model, next_id, tensor->data.raw, tensor->bytes));
+      }
+    } else if (tensor->bytes == 0) {
+      // These size 0 tensors are optional tensors reserved.
       CHECK_NN(
-          ANeuralNetworksModel_setOperandValue(nn_model, next_id, tensor->data.raw, tensor->bytes));
+          ANeuralNetworksModel_setOperandValue(nn_model, next_id, nullptr, 0));
     }
+
     ++next_id;
   }
   return next_id;
@@ -133,47 +196,64 @@ uint32_t addTensorOperands(tflite::Interpreter *interpreter, ANeuralNetworksMode
 
 // Adds the operations and their parameters to the NN API model.
 // 'next-id' is the operand ID of the next operand of the model.
-void AddOpsAndParams(tflite::Interpreter *interpreter, ANeuralNetworksModel *nn_model,
-                     uint32_t next_id)
-{
-  for (size_t i = 0; i < interpreter->nodes_size(); i++)
-  {
-    const auto *node_and_registration = interpreter->node_and_registration(i);
-    const TfLiteNode &node = node_and_registration->first;
-    const TfLiteRegistration &registration = node_and_registration->second;
+void AddOpsAndParams(tflite::Interpreter* interpreter,
+                     ANeuralNetworksModel* nn_model, uint32_t next_id,
+                     std::vector<int>* model_state_inputs,
+                     std::vector<int>* model_state_outputs) {
+  for (size_t i = 0; i < interpreter->nodes_size(); i++) {
+    const autonode_and_registration = interpreter->node_and_registration(i);
+    const TfLiteNodenode = node_and_registration->first;
+    const TfLiteRegistrationregistration = node_and_registration->second;
     tflite::BuiltinOperator builtin =
         static_cast<tflite::BuiltinOperator>(registration.builtin_code);
 
     // Add the parameters.
-    std::vector<uint32_t> augmented_inputs(node.inputs->data,
-                                           node.inputs->data + node.inputs->size);
+    std::vector<uint32_t> augmented_inputs(
+        node.inputs->data, node.inputs->data + node.inputs->size);
+    std::vector<uint32_t> augmented_outputs(
+        node.outputs->data, node.outputs->data + node.outputs->size);
 
-    auto add_scalar_int32 = [&nn_model, &augmented_inputs, &next_id](int value) {
+    auto add_scalar_int32 = [&nn_model, &augmented_inputs,
+                             &next_id](int value) {
       ANeuralNetworksOperandType operand_type{.type = ANEURALNETWORKS_INT32};
       CHECK_NN(ANeuralNetworksModel_addOperand(nn_model, &operand_type))
-      CHECK_NN(ANeuralNetworksModel_setOperandValue(nn_model, next_id, &value, sizeof(int32_t)))
+      CHECK_NN(ANeuralNetworksModel_setOperandValue(nn_model, next_id, &value,
+                                                    sizeof(int32_t)))
       augmented_inputs.push_back(next_id++);
     };
 
-    auto add_scalar_float32 = [&nn_model, &augmented_inputs, &next_id](float value) {
+    auto add_scalar_float32 = [&nn_model, &augmented_inputs,
+                               &next_id](float value) {
       ANeuralNetworksOperandType operand_type{.type = ANEURALNETWORKS_FLOAT32};
       CHECK_NN(ANeuralNetworksModel_addOperand(nn_model, &operand_type))
-      CHECK_NN(ANeuralNetworksModel_setOperandValue(nn_model, next_id, &value, sizeof(float)))
+      CHECK_NN(ANeuralNetworksModel_setOperandValue(nn_model, next_id, &value,
+                                                    sizeof(float)))
       augmented_inputs.push_back(next_id++);
     };
 
-    auto duplicate_state_tensor_float32 = [interpreter, &nn_model, &augmented_inputs,
-                                           &next_id](int tensor_id) {
-      const TfLiteTensor *tensor = interpreter->tensor(tensor_id);
-      CHECK_NN(ANeuralNetworksModel_setOperandValue(nn_model, tensor_id, tensor->data.raw,
-                                                    tensor->bytes));
-      augmented_inputs.push_back(tensor_id);
-    };
+    // Handle state tensors of RNN, LSTM, SVDF.
+    // For each state_out tensor, a corresponding state_in operand needs to be
+    // created for NNAPI.
+    auto duplicate_state_tensor_float32 =
+        [interpreter, &nn_model, &next_id, &augmented_inputs,
+         &model_state_inputs, &model_state_outputs](int tensor_id) {
+          const TfLiteTensor* tensor = interpreter->tensor(tensor_id);
+          ANeuralNetworksOperandType operand_type{
+              ANEURALNETWORKS_TENSOR_FLOAT32,
+              static_cast<uint32_t>(tensor->dims->size),
+              reinterpret_cast<uint32_t*>(tensor->dims->data),
+              tensor->params.scale, tensor->params.zero_point};
+          CHECK_NN(ANeuralNetworksModel_addOperand(nn_model, &operand_type));
+          augmented_inputs.push_back(next_id);
+          model_state_inputs->push_back(next_id);
+          model_state_outputs->push_back(tensor_id);
+          next_id++;
+        };
 
     auto add_add_params = [&add_scalar_int32]() { add_scalar_int32(0); };
 
-    auto add_pooling_params = [&add_scalar_int32](void *data) {
-      auto builtin = reinterpret_cast<TfLitePoolParams *>(data);
+    auto add_pooling_params = [&add_scalar_int32](voiddata) {
+      auto builtin = reinterpret_cast<TfLitePoolParams*>(data);
       add_scalar_int32(builtin->padding);
       add_scalar_int32(builtin->stride_width);
       add_scalar_int32(builtin->stride_height);
@@ -182,16 +262,16 @@ void AddOpsAndParams(tflite::Interpreter *interpreter, ANeuralNetworksModel *nn_
       add_scalar_int32(builtin->activation);
     };
 
-    auto add_convolution_params = [&add_scalar_int32](void *data) {
-      auto builtin = reinterpret_cast<TfLiteConvParams *>(data);
+    auto add_convolution_params = [&add_scalar_int32](voiddata) {
+      auto builtin = reinterpret_cast<TfLiteConvParams*>(data);
       add_scalar_int32(builtin->padding);
       add_scalar_int32(builtin->stride_width);
       add_scalar_int32(builtin->stride_height);
       add_scalar_int32(builtin->activation);
     };
 
-    auto add_depthwise_conv_params = [&add_scalar_int32](void *data) {
-      auto builtin = reinterpret_cast<TfLiteDepthwiseConvParams *>(data);
+    auto add_depthwise_conv_params = [&add_scalar_int32](voiddata) {
+      auto builtin = reinterpret_cast<TfLiteDepthwiseConvParams*>(data);
       add_scalar_int32(builtin->padding);
       add_scalar_int32(builtin->stride_width);
       add_scalar_int32(builtin->stride_height);
@@ -199,60 +279,88 @@ void AddOpsAndParams(tflite::Interpreter *interpreter, ANeuralNetworksModel *nn_
       add_scalar_int32(builtin->activation);
     };
 
-    auto add_fully_connected_params = [&add_scalar_int32](void *data) {
-      auto builtin = reinterpret_cast<TfLiteFullyConnectedParams *>(data);
+    auto add_fully_connected_params = [&add_scalar_int32](voiddata) {
+      auto builtin = reinterpret_cast<TfLiteFullyConnectedParams*>(data);
       add_scalar_int32(builtin->activation);
     };
 
-    auto add_concatenation_params = [&add_scalar_int32](void *data) {
-      auto builtin = reinterpret_cast<TfLiteConcatenationParams *>(data);
+    auto add_concatenation_params = [&add_scalar_int32](voiddata) {
+      auto builtin = reinterpret_cast<TfLiteConcatenationParams*>(data);
       add_scalar_int32(builtin->axis);
-      if (builtin->activation != kTfLiteActNone)
-      {
+      if (builtin->activation != kTfLiteActNone) {
         FATAL("Concatenation does not support fused activation in NNAPI");
       }
     };
 
-    auto add_softmax_params = [&add_scalar_float32](void *data) {
-      auto builtin = reinterpret_cast<TfLiteSoftmaxParams *>(data);
+    auto add_softmax_params = [&add_scalar_float32](voiddata) {
+      auto builtin = reinterpret_cast<TfLiteSoftmaxParams*>(data);
       add_scalar_float32(builtin->beta);
     };
 
-    auto add_space_to_depth_params = [&add_scalar_int32](void *data) {
-      auto builtin = reinterpret_cast<TfLiteSpaceToDepthParams *>(data);
+    auto add_space_to_depth_params = [&add_scalar_int32](voiddata) {
+      auto builtin = reinterpret_cast<TfLiteSpaceToDepthParams*>(data);
       add_scalar_int32(builtin->block_size);
     };
 
-    auto add_lstm_params = [&add_scalar_int32, &add_scalar_float32](void *data) {
-      auto builtin = reinterpret_cast<TfLiteLSTMParams *>(data);
+    auto add_lstm_params = [&add_scalar_int32,
+                            &add_scalar_float32](void* data) {
+      auto builtin = reinterpret_cast<TfLiteLSTMParams*>(data);
       add_scalar_int32(builtin->activation);
       add_scalar_float32(builtin->cell_clip);
       add_scalar_float32(builtin->proj_clip);
     };
 
-#if 0
-    auto add_reshape_params = [&](void* data) {
-      auto builtin = reinterpret_cast<TfLiteReshapeParams*>(data);
-      uint32_t tensor_size_shape = builtin->num_dimensions;
+    // LSTM in NNAPI requires scratch tensor as an output operand.
+    auto add_lstm_scratch_tensor_float32 = [interpreter, &node, &nn_model,
+                                            &next_id, &augmented_outputs]() {
+      int scratch_buffer_index = node.temporaries->data[0];
+      const TfLiteTensor* tensor = interpreter->tensor(scratch_buffer_index);
       ANeuralNetworksOperandType operand_type{
-          ANEURALNETWORKS_TENSOR_INT32,
-          {static_cast<uint32_t>(1),
-           reinterpret_cast<uint32_t*>(&tensor_size_shape)},
-          0,
-          0};
-      CHECK_NN(ANeuralNetworksModel_addOperand(nn_model, &operand_type))
-      CHECK_NN(ANeuralNetworksModel_setOperandValue(
-          nn_model, next_id, builtin->shape,
-          sizeof(int) * builtin->num_dimensions));
-      augmented_inputs.push_back(next_id++);
+          ANEURALNETWORKS_TENSOR_FLOAT32,
+          static_cast<uint32_t>(tensor->dims->size),
+          reinterpret_cast<uint32_t*>(tensor->dims->data), tensor->params.scale,
+          tensor->params.zero_point};
+      CHECK_NN(ANeuralNetworksModel_addOperand(nn_model, &operand_type));
+      augmented_outputs.insert(augmented_outputs.begin(), next_id++);
+    };
+
+    auto add_mean_params = [&add_scalar_int32](void* data) {
+      auto builtin = reinterpret_cast<TfLiteMeanParams*>(data);
+      add_scalar_int32(builtin->keep_dims);
+    };
+
+    auto add_svdf_params = [&add_scalar_int32](void* data) {
+      auto builtin = reinterpret_cast<TfLiteSVDFParams*>(data);
+      add_scalar_int32(builtin->rank);
+      add_scalar_int32(builtin->activation);
+    };
+
+    auto add_rnn_params = [&add_scalar_int32](void* data) {
+      auto builtin = reinterpret_cast<TfLiteRNNParams*>(data);
+      add_scalar_int32(builtin->activation);
+    };
+
+    // Handle optional input tensors.
+    auto add_optional_tensors = [&nn_model, &augmented_inputs,
+                                 &next_id](int nn_type) {
+      for (size_t idx = 0; idx < augmented_inputs.size(); idx++) {
+        if (augmented_inputs[idx] == kOptionalTensor) {
+          const std::vector<uint32_t> dim = {0, 0};
+          ANeuralNetworksOperandType operand_type{nn_type, 2, dim.data(), 0, 0};
+          CHECK_NN(ANeuralNetworksModel_addOperand(nn_model, &operand_type))
+          CHECK_NN(ANeuralNetworksModel_setOperandValue(nn_model, next_id,
+                                                        nullptr, 0))
+          augmented_inputs[idx] = next_id++;
+        }
+      }
     };
-#endif
 
+    int nnapi_version = 10;
 #include "nnapi_delegate_ex_AddOpsAndParams_lambda.inc"
 
     ANeuralNetworksOperationType nn_op_type;
-    switch (builtin)
-    {
+
+    switch (builtin) {
       case tflite::BuiltinOperator_ADD:
         nn_op_type = ANEURALNETWORKS_ADD;
         add_add_params();
@@ -261,14 +369,6 @@ void AddOpsAndParams(tflite::Interpreter *interpreter, ANeuralNetworksModel *nn_
         nn_op_type = ANEURALNETWORKS_MUL;
         add_add_params();
         break;
-      case tflite::BuiltinOperator_SUB:
-        nn_op_type = ANEURALNETWORKS_SUB;
-        add_add_params();
-        break;
-      case tflite::BuiltinOperator_DIV:
-        nn_op_type = ANEURALNETWORKS_DIV;
-        add_add_params();
-        break;
       case tflite::BuiltinOperator_AVERAGE_POOL_2D:
         add_pooling_params(node.builtin_data);
         nn_op_type = ANEURALNETWORKS_AVERAGE_POOL_2D;
@@ -297,6 +397,9 @@ void AddOpsAndParams(tflite::Interpreter *interpreter, ANeuralNetworksModel *nn_
       case tflite::BuiltinOperator_TANH:
         nn_op_type = ANEURALNETWORKS_TANH;
         break;
+      case tflite::BuiltinOperator_FLOOR:
+        nn_op_type = ANEURALNETWORKS_FLOOR;
+        break;
       case tflite::BuiltinOperator_LOGISTIC:
         nn_op_type = ANEURALNETWORKS_LOGISTIC;
         break;
@@ -328,172 +431,248 @@ void AddOpsAndParams(tflite::Interpreter *interpreter, ANeuralNetworksModel *nn_
         add_space_to_depth_params(node.builtin_data);
         nn_op_type = ANEURALNETWORKS_SPACE_TO_DEPTH;
         break;
-      case tflite::BuiltinOperator_LSTM:
-      {
-        duplicate_state_tensor_float32(node.outputs->data[/*kOutputStateTensor*/ 1]);
-        duplicate_state_tensor_float32(node.outputs->data[/*kCellStateTensor*/ 2]);
+      case tflite::BuiltinOperator_LSTM: {
+        duplicate_state_tensor_float32(
+            node.outputs->data[/*kOutputStateTensor*/ 0]);
+        duplicate_state_tensor_float32(
+            node.outputs->data[/*kCellStateTensor*/ 1]);
         add_lstm_params(node.builtin_data);
+        add_lstm_scratch_tensor_float32();
+        add_optional_tensors(ANEURALNETWORKS_TENSOR_FLOAT32);
         nn_op_type = ANEURALNETWORKS_LSTM;
         break;
       }
       case tflite::BuiltinOperator_DEQUANTIZE:
         nn_op_type = ANEURALNETWORKS_DEQUANTIZE;
         break;
+      case tflite::BuiltinOperator_SVDF: {
+        duplicate_state_tensor_float32(node.outputs->data[/*kStateTensor*/ 0]);
+        add_svdf_params(node.builtin_data);
+        nn_op_type = ANEURALNETWORKS_SVDF;
+        break;
+      }
+      case tflite::BuiltinOperator_RNN: {
+        duplicate_state_tensor_float32(
+            node.outputs->data[/*kHiddenStateTensor*/ 0]);
+        add_rnn_params(node.builtin_data);
+        nn_op_type = ANEURALNETWORKS_RNN;
+        break;
+      }
+      case tflite::BuiltinOperator_EMBEDDING_LOOKUP:
+        nn_op_type = ANEURALNETWORKS_EMBEDDING_LOOKUP;
+        break;
+      case tflite::BuiltinOperator_PAD:
+        nnapi_version = 11;  // require NNAPI 1.1
+        nn_op_type = ANEURALNETWORKS_PAD;
+        break;
+      case tflite::BuiltinOperator_MEAN:
+        nnapi_version = 11;  // require NNAPI 1.1
+        add_mean_params(node.builtin_data);
+        nn_op_type = ANEURALNETWORKS_MEAN;
+        break;
+      case tflite::BuiltinOperator_DIV:
+        nnapi_version = 11;  // require NNAPI 1.1
+        nn_op_type = ANEURALNETWORKS_DIV;
+        add_add_params();
+        break;
+      case tflite::BuiltinOperator_SUB:
+        nnapi_version = 11;  // require NNAPI 1.1
+        nn_op_type = ANEURALNETWORKS_SUB;
+        add_add_params();
+        break;
       case tflite::BuiltinOperator_STRIDED_SLICE:
         add_strided_slice_ex_params(node.builtin_data);
         // FIXME: This call is ugly. please fix this
         // Use ANN_addOperationEx for STRIDED_SLICE
         CHECK_NN(ANeuralNetworksModel_addOperationEx(
             nn_model, ANEURALNETWORKS_STRIDED_SLICE_EX,
-            static_cast<uint32_t>(augmented_inputs.size()), augmented_inputs.data(),
-            static_cast<uint32_t>(node.outputs->size),
-            reinterpret_cast<uint32_t *>(node.outputs->data)));
+            static_cast<uint32_t>(augmented_inputs.size()),
+            augmented_inputs.data(), static_cast<uint32_t>(node.outputs->size),
+            reinterpret_cast<uint32_t*>(node.outputs->data)));
         continue;
       case tflite::BuiltinOperator_CAST:
         CHECK_NN(ANeuralNetworksModel_addOperationEx(
-            nn_model, ANEURALNETWORKS_CAST_EX, static_cast<uint32_t>(augmented_inputs.size()),
+            nn_model, ANEURALNETWORKS_CAST_EX,
+            static_cast<uint32_t>(augmented_inputs.size()),
             augmented_inputs.data(), static_cast<uint32_t>(node.outputs->size),
-            reinterpret_cast<uint32_t *>(node.outputs->data)));
+            reinterpret_cast<uint32_t*>(node.outputs->data)));
         continue;
       case tflite::BuiltinOperator_TOPK_V2:
         CHECK_NN(ANeuralNetworksModel_addOperationEx(
-            nn_model, ANEURALNETWORKS_TOPK_V2_EX, static_cast<uint32_t>(augmented_inputs.size()),
+            nn_model, ANEURALNETWORKS_TOPK_V2_EX,
+            static_cast<uint32_t>(augmented_inputs.size()),
             augmented_inputs.data(), static_cast<uint32_t>(node.outputs->size),
-            reinterpret_cast<uint32_t *>(node.outputs->data)));
+            reinterpret_cast<uint32_t*>(node.outputs->data)));
         continue;
       case tflite::BuiltinOperator_GATHER:
         add_gather_ex_params(node.builtin_data);
         CHECK_NN(ANeuralNetworksModel_addOperationEx(
-            nn_model, ANEURALNETWORKS_GATHER_EX, static_cast<uint32_t>(augmented_inputs.size()),
+            nn_model, ANEURALNETWORKS_GATHER_EX,
+            static_cast<uint32_t>(augmented_inputs.size()),
             augmented_inputs.data(), static_cast<uint32_t>(node.outputs->size),
-            reinterpret_cast<uint32_t *>(node.outputs->data)));
+            reinterpret_cast<uint32_t*>(node.outputs->data)));
         continue;
       case tflite::BuiltinOperator_CONCAT_EMBEDDINGS:
       case tflite::BuiltinOperator_LSH_PROJECTION:
-      case tflite::BuiltinOperator_SVDF:
       case tflite::BuiltinOperator_HASHTABLE_LOOKUP:
-      case tflite::BuiltinOperator_RNN:
       case tflite::BuiltinOperator_BIDIRECTIONAL_SEQUENCE_RNN:
       case tflite::BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_RNN:
-      case tflite::BuiltinOperator_EMBEDDING_LOOKUP:
       case tflite::BuiltinOperator_EMBEDDING_LOOKUP_SPARSE:
       case tflite::BuiltinOperator_BIDIRECTIONAL_SEQUENCE_LSTM:
       case tflite::BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM:
       case tflite::BuiltinOperator_L2_NORMALIZATION:
       case tflite::BuiltinOperator_LOCAL_RESPONSE_NORMALIZATION:
-      case tflite::BuiltinOperator_PAD:
+      case tflite::BuiltinOperator_PADV2:
       case tflite::BuiltinOperator_CALL:
       case tflite::BuiltinOperator_SKIP_GRAM:
       case tflite::BuiltinOperator_SPACE_TO_BATCH_ND:
       case tflite::BuiltinOperator_BATCH_TO_SPACE_ND:
       case tflite::BuiltinOperator_TRANSPOSE:
-      case tflite::BuiltinOperator_MEAN:
       case tflite::BuiltinOperator_SPLIT:
       case tflite::BuiltinOperator_SQUEEZE:
       case tflite::BuiltinOperator_EXP:
       case tflite::BuiltinOperator_LOG_SOFTMAX:
       case tflite::BuiltinOperator_DELEGATE:
+      case tflite::BuiltinOperator_PRELU:
+      case tflite::BuiltinOperator_MAXIMUM:
+      case tflite::BuiltinOperator_MINIMUM:
+      case tflite::BuiltinOperator_ARG_MAX:
+      case tflite::BuiltinOperator_GREATER:
+      case tflite::BuiltinOperator_GREATER_EQUAL:
+      case tflite::BuiltinOperator_LESS:
+      case tflite::BuiltinOperator_LESS_EQUAL:
+      case tflite::BuiltinOperator_NEG:
+      case tflite::BuiltinOperator_SELECT:
+      case tflite::BuiltinOperator_SLICE:
+      case tflite::BuiltinOperator_SIN:
+      case tflite::BuiltinOperator_TRANSPOSE_CONV:
+      case tflite::BuiltinOperator_SPARSE_TO_DENSE:
         FATAL("Op code %d is currently not delegated to NNAPI", builtin);
-        nn_op_type = -1; // set to invalid
+        nn_op_type = -1;  // set to invalid
         break;
       case tflite::BuiltinOperator_CUSTOM:
         std::string custom_name(registration.custom_name);
-        if (custom_name.compare("TensorFlowMax") == 0)
-        {
+        if (custom_name.compare("TensorFlowMax") == 0) {
           CHECK_NN(ANeuralNetworksModel_addOperationEx(
               nn_model, ANEURALNETWORKS_TENSORFLOW_MAX_EX,
-              static_cast<uint32_t>(augmented_inputs.size()), augmented_inputs.data(),
+              static_cast<uint32_t>(augmented_inputs.size()),
+              augmented_inputs.data(),
               static_cast<uint32_t>(node.outputs->size),
-              reinterpret_cast<uint32_t *>(node.outputs->data)));
+              reinterpret_cast<uint32_t*>(node.outputs->data)));
           continue;
         }
 
         FATAL("Custom operations are not supported when using NNAPI.");
-        nn_op_type = -1; // set to invalid
+        nn_op_type = -1;  // set to invalid
         break;
     }
 
+    //if (nnapi_version == 11 && kAndroidSdkVersion < 28) {
+    //  FATAL("Op %d needs NNAPI1.1", builtin);
+    //}
+
     // Add the operation.
     CHECK_NN(ANeuralNetworksModel_addOperation(
         nn_model, nn_op_type, static_cast<uint32_t>(augmented_inputs.size()),
-        augmented_inputs.data(), static_cast<uint32_t>(node.outputs->size),
-        reinterpret_cast<uint32_t *>(node.outputs->data)));
+        augmented_inputs.data(),
+        static_cast<uint32_t>(augmented_outputs.size()),
+        reinterpret_cast<uint32_t*>(augmented_outputs.data())));
   }
 }
 
-TfLiteStatus NNAPIDelegate::BuildGraph(::tflite::Interpreter *interpreter)
-{
+TfLiteStatus NNAPIDelegate::BuildGraph(::tflite::Interpreter* interpreter) {
   // TODO(aselle): This is not correct. need to handle resize invalidation.
-  if (nn_model_ && nn_compiled_model_)
-    return kTfLiteOk;
+  if (nn_model_ && nn_compiled_model_) return kTfLiteOk;
 
-  if (!nn_model_)
-  {
+  if (!nn_model_) {
     CHECK_NN(ANeuralNetworksModel_create(&nn_model_));
 
     // Find all the temporary tensors and put them in a skip_list.
     std::vector<uint32_t> skip_list;
-    for (size_t i = 0; i < interpreter->nodes_size(); i++)
-    {
-      const auto *node_and_registration = interpreter->node_and_registration(i);
-      const TfLiteNode &node = node_and_registration->first;
-      if (node.temporaries != nullptr)
-      {
-        for (int j = 0; j < node.temporaries->size; j++)
-        {
+    for (size_t i = 0; i < interpreter->nodes_size(); i++) {
+      const auto* node_and_registration = interpreter->node_and_registration(i);
+      const TfLiteNode& node = node_and_registration->first;
+      if (node.temporaries != nullptr) {
+        for (int j = 0; j < node.temporaries->size; j++) {
           skip_list.push_back(static_cast<uint32_t>(node.temporaries->data[j]));
         }
       }
     }
 
     uint32_t next_id = addTensorOperands(interpreter, nn_model_, skip_list);
-    AddOpsAndParams(interpreter, nn_model_, next_id);
+    AddOpsAndParams(interpreter, nn_model_, next_id, &model_states_inputs_,
+                    &model_states_outputs_);
+
+    std::vector<int> augmented_inputs = interpreter->inputs();
+    std::vector<int> augmented_outputs = interpreter->outputs();
+
+    // All state tensors input/output need to be treated as model input/output.
+    augmented_inputs.insert(augmented_inputs.end(),
+                            model_states_inputs_.begin(),
+                            model_states_inputs_.end());
+    augmented_outputs.insert(augmented_outputs.end(),
+                             model_states_outputs_.begin(),
+                             model_states_outputs_.end());
+
     CHECK_NN(ANeuralNetworksModel_identifyInputsAndOutputs(
-        nn_model_, static_cast<uint32_t>(interpreter->inputs().size()),
-        reinterpret_cast<const uint32_t *>(interpreter->inputs().data()),
-        static_cast<uint32_t>(interpreter->outputs().size()),
-        reinterpret_cast<const uint32_t *>(interpreter->outputs().data())));
+        nn_model_, static_cast<uint32_t>(augmented_inputs.size()),
+        reinterpret_cast<const uint32_t*>(augmented_inputs.data()),
+        static_cast<uint32_t>(augmented_outputs.size()),
+        reinterpret_cast<const uint32_t*>(augmented_outputs.data())));
     CHECK_NN(ANeuralNetworksModel_finish(nn_model_));
   }
-  if (!nn_compiled_model_)
-  {
+  if (!nn_compiled_model_) {
     CHECK_NN(ANeuralNetworksCompilation_create(nn_model_, &nn_compiled_model_));
     CHECK_NN(ANeuralNetworksCompilation_finish(nn_compiled_model_));
   }
   return kTfLiteOk;
 }
 
-TfLiteStatus NNAPIDelegate::Invoke(::tflite::Interpreter *interpreter)
-{
-  if (!nn_model_)
-  {
+TfLiteStatus NNAPIDelegate::Invoke(::tflite::Interpreter* interpreter) {
+  if (!nn_model_) {
     TF_LITE_ENSURE_STATUS(BuildGraph(interpreter));
   }
 
-  ANeuralNetworksExecution *execution = nullptr;
+  ANeuralNetworksExecutionexecution = nullptr;
   CHECK_NN(ANeuralNetworksExecution_create(nn_compiled_model_, &execution));
 
   // Currently perform deep copy of input buffer
-  for (size_t i = 0; i < interpreter->inputs().size(); i++)
-  {
+  for (size_t i = 0; i < interpreter->inputs().size(); i++) {
     int input = interpreter->inputs()[i];
     // TODO(aselle): Is this what we want or do we want input instead?
     // TODO(aselle): This should be called setInputValue maybe to be cons.
-    TfLiteTensor *tensor = interpreter->tensor(input);
-
-    CHECK_NN(
-        ANeuralNetworksExecution_setInput(execution, i, nullptr, tensor->data.raw, tensor->bytes));
+    TfLiteTensor* tensor = interpreter->tensor(input);
+    CHECK_NN(ANeuralNetworksExecution_setInput(
+        execution, i, nullptr, tensor->data.raw, tensor->bytes));
   }
+
   // Tell nn api where to place final data.
-  for (size_t i = 0; i < interpreter->outputs().size(); i++)
-  {
+  for (size_t i = 0; i < interpreter->outputs().size(); i++) {
     int output = interpreter->outputs()[i];
-    TfLiteTensor *tensor = interpreter->tensor(output);
-    CHECK_NN(
-        ANeuralNetworksExecution_setOutput(execution, i, nullptr, tensor->data.raw, tensor->bytes));
+    TfLiteTensor* tensor = interpreter->tensor(output);
+    CHECK_NN(ANeuralNetworksExecution_setOutput(
+        execution, i, nullptr, tensor->data.raw, tensor->bytes));
+  }
+
+  // The state_out of previous invocation need to be mapped to state_in of
+  // current invocation.
+  for (size_t i = 0; i < model_states_outputs_.size(); i++) {
+    int state_tensor_idx = model_states_outputs_[i];
+    TfLiteTensor* tensor = interpreter->tensor(state_tensor_idx);
+    // Here we are using a deep copy for state_in tensors so that we are not
+    // reading and writing into the same buffer during a invocation.
+    // TODO(miaowang): using double shared buffer to minimize the copies.
+    CHECK_NN(ANeuralNetworksExecution_setInput(
+        execution, i + interpreter->inputs().size(), nullptr, tensor->data.raw,
+        tensor->bytes));
+    // Tell NNAPI where to output the state_out.
+    CHECK_NN(ANeuralNetworksExecution_setOutput(
+        execution, i + interpreter->outputs().size(), nullptr, tensor->data.raw,
+        tensor->bytes));
   }
+
   // Currently use blocking compute.
-  ANeuralNetworksEvent *event = nullptr;
+  ANeuralNetworksEventevent = nullptr;
   CHECK_NN(ANeuralNetworksExecution_startCompute(execution, &event));
   CHECK_NN(ANeuralNetworksEvent_wait(event));
   ANeuralNetworksEvent_free(event);
@@ -516,3 +695,5 @@ TfLiteStatus NNAPIDelegate::Invoke(::tflite::Interpreter *interpreter)
 }
 
 } // namespace nnfw
+
+// clang-format on
index d73f3a2..5da88df 100644 (file)
@@ -140,7 +140,7 @@ TEST(NNAPI_Unittest_add_1, simple_test)
     //  - Read Left from Tensor #1
     //  - Read Left from Tensor #2,
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_ADD));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_ADD, 1));
 
     interp.SetInputs({1, 2});
     interp.SetOutputs({0});
index 71f6df1..aaf87bd 100644 (file)
@@ -158,7 +158,7 @@ TEST(NNAPI_Unittest_add_2, simple_test)
     //  - Read LHS from Tensor #1
     //  - Read RHS from Tensor #2,
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_ADD));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_ADD, 1));
 
     interp.SetInputs({2});
     interp.SetOutputs({0});
index 4d93632..1de9e6d 100644 (file)
@@ -115,7 +115,7 @@ TEST(NNAPI_Unittest_add_3, simple_test)
     //  - Read Left from Tensor #1
     //  - Read Left from Tensor #2,
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_ADD));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_ADD, 1));
 
     interp.SetInputs({1, 2});
     interp.SetOutputs({0});
index 9a10185..4c22fe0 100644 (file)
@@ -140,7 +140,7 @@ TEST(NNAPI_Unittest_add_4, simple_test)
     //  - Read Left from Tensor #1
     //  - Read Left from Tensor #2,
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_ADD));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_ADD, 1));
 
     interp.SetInputs({1, 2});
     interp.SetOutputs({0});
index e4690ed..266f4e1 100644 (file)
@@ -133,7 +133,7 @@ TEST(NNAPI_Unittest_add_5, simple_test)
     //  - Read Left from Tensor #1
     //  - Read Left from Tensor #2,
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_ADD));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_ADD, 1));
 
     interp.SetInputs({1, 2});
     interp.SetOutputs({0});
index 7153d26..5e4756a 100644 (file)
@@ -125,7 +125,7 @@ TEST(NNAPI_Unittest_add_6, simple_test)
     //  - Read Left from Tensor #1
     //  - Read Left from Tensor #2,
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_ADD));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_ADD, 1));
 
     interp.SetInputs({1, 2});
     interp.SetOutputs({0});
index 12999ab..4513416 100644 (file)
@@ -133,7 +133,7 @@ TEST(NNAPI_Unittest_add_7, simple_test)
     //  - Read Left from Tensor #1
     //  - Read Left from Tensor #2,
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_ADD));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_ADD, 1));
 
     interp.SetInputs({1, 2});
     interp.SetOutputs({0});
index d7936e6..0e02d19 100644 (file)
@@ -171,7 +171,7 @@ TEST(NNAPI_Unittest_add_8, simple_test)
     //  - Read LHS from Tensor #1
     //  - Read RHS from Tensor #2,
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_ADD));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_ADD, 1));
 
     interp.SetInputs({});
     interp.SetOutputs({0});
index e718032..ac39079 100644 (file)
@@ -168,7 +168,7 @@ TEST(NNAPI_Unittest_add_9, simple_test)
     //  - Read LHS from Tensor #1
     //  - Read RHS from Tensor #2,
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_ADD));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_ADD, 1));
 
     interp.SetInputs({});
     interp.SetOutputs({0});
index ceda77c..99d10a0 100644 (file)
@@ -143,7 +143,7 @@ TEST(NNAPI_Unittest_add_1, simple_test)
     //  - Read Left from Tensor #1
     //  - Read Left from Tensor #2,
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_ADD));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_ADD, 1));
 
     interp.SetInputs({1, 2});
     interp.SetOutputs({0});
index bae1221..368d942 100644 (file)
@@ -130,7 +130,7 @@ TEST(NNAPI_Unittest_avg_pool_1, simple_test)
     // Run Convolution and store its result into Tensor #0
     //  - Read IFM from Tensor #1
     interp.AddNodeWithParameters({1}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_AVERAGE_POOL_2D));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_AVERAGE_POOL_2D, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index 79749f8..fb42878 100644 (file)
@@ -129,7 +129,7 @@ TEST(NNAPI_Unittest_avg_pool_1, simple_test)
     // Run Convolution and store its result into Tensor #0
     //  - Read IFM from Tensor #1
     interp.AddNodeWithParameters({1}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_AVERAGE_POOL_2D));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_AVERAGE_POOL_2D, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index 526cf8b..c7069b4 100644 (file)
@@ -117,7 +117,7 @@ TEST(NNAPI_Unittest_cast_1, simple_test)
     // Run CAST and store the result into Tensor #0
     //  - Read input from Tensor #1
     interp.AddNodeWithParameters({1}, {0}, nullptr, 0, nullptr,
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_CAST));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_CAST, 1));
 
     interp.SetInputs({1});
     interp.SetOutputs({0});
index 415e290..f46d315 100644 (file)
@@ -115,7 +115,7 @@ TEST(NNAPI_Unittest_cast_2, simple_test)
     // Run CAST and store the result into Tensor #0
     //  - Read input from Tensor #1
     interp.AddNodeWithParameters({1}, {0}, nullptr, 0, nullptr,
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_CAST));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_CAST, 1));
 
     interp.SetInputs({1});
     interp.SetOutputs({0});
index 87fd79e..b24e67d 100644 (file)
@@ -117,7 +117,7 @@ TEST(NNAPI_Unittest_cast_1, simple_test)
     // Run CAST and store the result into Tensor #0
     //  - Read input from Tensor #1
     interp.AddNodeWithParameters({1}, {0}, nullptr, 0, nullptr,
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_CAST));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_CAST, 1));
 
     interp.SetInputs({1});
     interp.SetOutputs({0});
index c09c438..bbc55d2 100644 (file)
@@ -141,7 +141,7 @@ TEST(NNAPI_Unittest_concat_1, simple_test)
     // Run Convolution and store its result into Tensor #0
     //  - Read IFM from Tensor #1
     interp.AddNodeWithParameters(ifm_indexes, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_CONCATENATION));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_CONCATENATION, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs(ifm_indexes);
index 28b8e54..5a766f8 100644 (file)
@@ -143,7 +143,7 @@ TEST(NNAPI_Unittest_concat_1, simple_test)
     // Run Convolution and store its result into Tensor #0
     //  - Read IFM from Tensor #1
     interp.AddNodeWithParameters(ifm_indexes, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_CONCATENATION));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_CONCATENATION, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs(ifm_indexes);
index 7e709b5..6de7446 100644 (file)
@@ -187,7 +187,7 @@ TEST(NNAPI_Unittest_conv_1, simple_test)
     //  - Read Filter from Tensor #2,
     //  - Read Bias from Tensor #3
     interp.AddNodeWithParameters({1, 2, 3}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_CONV_2D));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_CONV_2D, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index e0fd7d2..57c4c21 100644 (file)
@@ -191,7 +191,7 @@ TEST(NNAPI_Unittest_conv_1, simple_test)
     //  - Read Filter from Tensor #2,
     //  - Read Bias from Tensor #3
     interp.AddNodeWithParameters({1, 2, 3}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_CONV_2D));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_CONV_2D, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index a3abc7a..51690ff 100644 (file)
@@ -185,7 +185,7 @@ TEST(NNAPI_Unittest_dconv_1, simple_test)
     //  - Read Filter from Tensor #2,
     //  - Read Bias from Tensor #3
     interp.AddNodeWithParameters({1, 2, 3}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_DEPTHWISE_CONV_2D));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_DEPTHWISE_CONV_2D, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index 63850b5..c0b9434 100644 (file)
@@ -189,7 +189,7 @@ TEST(NNAPI_Unittest_dconv_1, simple_test)
     //  - Read Filter from Tensor #2,
     //  - Read Bias from Tensor #3
     interp.AddNodeWithParameters({1, 2, 3}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_DEPTHWISE_CONV_2D));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_DEPTHWISE_CONV_2D, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index ade6fc5..969613a 100644 (file)
@@ -117,7 +117,7 @@ TEST(NNAPI_Unittest_dequantize_1, simple_test)
     // Run DEQUANTIZE and store the result into Tensor #0
     //  - Read input from Tensor #1
     interp.AddNodeWithParameters({1}, {0}, nullptr, 0, nullptr,
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_DEQUANTIZE));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_DEQUANTIZE, 1));
 
     interp.SetInputs({1});
     interp.SetOutputs({0});
index 58f2a25..585b9fd 100644 (file)
@@ -140,7 +140,7 @@ TEST(NNAPI_Unittest_div_1, simple_test)
     //  - Read Left from Tensor #1
     //  - Read Right from Tensor #2,
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_DIV));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_DIV, 1));
 
     interp.SetInputs({1, 2});
     interp.SetOutputs({0});
index 62d6816..200d918 100644 (file)
@@ -133,7 +133,7 @@ TEST(NNAPI_Unittest_div_2, simple_test)
     //  - Read Left from Tensor #1
     //  - Read Right from Tensor #2,
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_DIV));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_DIV, 1));
 
     interp.SetInputs({1, 2});
     interp.SetOutputs({0});
index 396a00e..77ed77b 100644 (file)
@@ -167,7 +167,7 @@ TEST(NNAPI_Unittest_fully_connected_1, simple_test)
     //  - Read Filter from Tensor #2,
     //  - Read Bias from Tensor #3
     interp.AddNodeWithParameters({1, 2, 3}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_FULLY_CONNECTED));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_FULLY_CONNECTED, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index 60e14ba..50536db 100644 (file)
@@ -169,7 +169,7 @@ TEST(NNAPI_Unittest_fully_connected_1, simple_test)
     //  - Read Filter from Tensor #2,
     //  - Read Bias from Tensor #3
     interp.AddNodeWithParameters({1, 2, 3}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_FULLY_CONNECTED));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_FULLY_CONNECTED, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index bb21555..513d56e 100644 (file)
@@ -112,7 +112,7 @@ TEST(NNAPI_Unittest_gather_1, simple_test)
     // Run GATHER and store its result into Tensor #2
     //  - Read input data and index_data from Tensor #0 and #1, respectively
     interp.AddNodeWithParameters({0, 1}, {2}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_GATHER));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_GATHER, 1));
 
     // Set Tensor #0 and #1 as Input, and Tensor #2 as Output
     interp.SetInputs({0, 1});
index b1a8622..9a19820 100644 (file)
@@ -116,7 +116,7 @@ TEST(NNAPI_Unittest_gather_2, simple_test)
     // Run GATHER and store its result into Tensor #2
     //  - Read input data and index_data from Tensor #0 and #1, respectively
     interp.AddNodeWithParameters({0, 1}, {2}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_GATHER));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_GATHER, 1));
 
     // Set Tensor #0 and #1 as Input, and Tensor #2 as Output
     interp.SetInputs({0, 1});
index e34d157..bb2e044 100644 (file)
@@ -136,7 +136,7 @@ TEST(NNAPI_Unittest_max_pool_1, simple_test)
     // Run Convolution and store its result into Tensor #0
     //  - Read IFM from Tensor #1
     interp.AddNodeWithParameters({1}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_MAX_POOL_2D));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_MAX_POOL_2D, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index 4c33179..99ac34b 100644 (file)
@@ -138,7 +138,7 @@ TEST(NNAPI_Unittest_max_pool_1, simple_test)
     // Run Convolution and store its result into Tensor #0
     //  - Read IFM from Tensor #1
     interp.AddNodeWithParameters({1}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_MAX_POOL_2D));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_MAX_POOL_2D, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index c470375..1884408 100644 (file)
@@ -131,7 +131,7 @@ TEST(NNAPI_Unittest_mul_1, simple_test)
     //  - Read Left from Tensor #1
     //  - Read Right from Tensor #2,
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_MUL));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_MUL, 1));
 
     interp.SetInputs({1, 2});
     interp.SetOutputs({0});
index e3cb1f7..c28e0dc 100644 (file)
@@ -131,7 +131,7 @@ TEST(NNAPI_Unittest_mul_2, simple_test)
     //  - Read Left from Tensor #1
     //  - Read Left from Tensor #2,
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_MUL));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_MUL, 1));
 
     interp.SetInputs({1, 2});
     interp.SetOutputs({0});
index 0b56b29..a68634e 100644 (file)
@@ -133,7 +133,7 @@ TEST(NNAPI_Unittest_mul_1, simple_test)
     //  - Read Left from Tensor #1
     //  - Read Right from Tensor #2,
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_MUL));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_MUL, 1));
 
     interp.SetInputs({1, 2});
     interp.SetOutputs({0});
index 845c019..aeefe2f 100644 (file)
@@ -103,7 +103,7 @@ int main(int argc, char **argv)
     // Run ReLU and store its result into Tensor #0
     //  - Read IFM from Tensor #1
     interp.AddNodeWithParameters({1}, {0}, nullptr, 0, nullptr,
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_RELU_N1_TO_1));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_RELU_N1_TO_1, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index debcfbc..85de96d 100644 (file)
@@ -105,7 +105,7 @@ TEST(NNAPI_Unittest_relu6_1, simple_test)
     // Run ReLU and store its result into Tensor #0
     //  - Read IFM from Tensor #1
     interp.AddNodeWithParameters({1}, {0}, nullptr, 0, nullptr,
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_RELU6));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_RELU6, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index 111c5a4..fe849f9 100644 (file)
@@ -105,7 +105,7 @@ int main(int argc, char **argv)
     // Run ReLU and store its result into Tensor #0
     //  - Read IFM from Tensor #1
     interp.AddNodeWithParameters({1}, {0}, nullptr, 0, nullptr,
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_RELU6));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_RELU6, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index 32eb909..10453ea 100644 (file)
@@ -105,7 +105,7 @@ TEST(NNAPI_Unittest_relu_1, simple_test)
     // Run ReLU and store its result into Tensor #0
     //  - Read IFM from Tensor #1
     interp.AddNodeWithParameters({1}, {0}, nullptr, 0, nullptr,
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_RELU));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_RELU, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index 293b272..16e1db4 100644 (file)
@@ -108,7 +108,7 @@ TEST(NNAPI_Unittest_relu_2, simple_test)
     // Run ReLU and store its result into Tensor #0
     //  - Read IFM from Tensor #1
     interp.AddNodeWithParameters({1}, {0}, nullptr, 0, nullptr,
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_RELU));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_RELU, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index 77abb94..f213a8c 100644 (file)
@@ -111,7 +111,7 @@ TEST(NNAPI_Unittest_relu_3, simple_test)
     // Run ReLU and store its result into Tensor #0
     //  - Read IFM from Tensor #1
     interp.AddNodeWithParameters({1}, {0}, nullptr, 0, nullptr,
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_RELU));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_RELU, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index 7bca8ec..59fe5d2 100644 (file)
@@ -105,7 +105,7 @@ int main(int argc, char **argv)
     // Run ReLU and store its result into Tensor #0
     //  - Read IFM from Tensor #1
     interp.AddNodeWithParameters({1}, {0}, nullptr, 0, nullptr,
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_RELU));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_RELU, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index 98da5f2..8c2082c 100644 (file)
@@ -121,7 +121,7 @@ TEST(NNAPI_Unittest_reshape_1, simple_test)
 
     // Run Reshapeand store its result into Tensor #0
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_RESHAPE));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_RESHAPE, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index 84faa5b..9164026 100644 (file)
@@ -123,7 +123,7 @@ TEST(NNAPI_Unittest_reshape_1, simple_test)
 
     // Run Reshapeand store its result into Tensor #0
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_RESHAPE));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_RESHAPE, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index 98dc40f..a4465f1 100644 (file)
@@ -121,7 +121,7 @@ TEST(NNAPI_Unittest_resize_bilinear_1, simple_test)
     param->align_corners = false;
 
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_RESIZE_BILINEAR));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_RESIZE_BILINEAR, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index 6415ef1..ba3e728 100644 (file)
@@ -100,7 +100,7 @@ TEST(NNAPI_Unittest_softmax_1, simple_test)
     // Run Softmax and store its result into Tensor #0
     //  - Read IFM from Tensor #1
     interp.AddNodeWithParameters({1}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_SOFTMAX));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_SOFTMAX, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index a75dc7d..3001088 100644 (file)
@@ -119,7 +119,7 @@ TEST(NNAPI_Unittest_softmax_2, simple_test)
     // Run Softmax and store its result into Tensor #0
     //  - Read IFM from Tensor #1
     interp.AddNodeWithParameters({1}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_SOFTMAX));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_SOFTMAX, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index 4cae025..826614a 100644 (file)
@@ -102,7 +102,7 @@ TEST(NNAPI_Unittest_softmax_1, simple_test)
     // Run Softmax and store its result into Tensor #0
     //  - Read IFM from Tensor #1
     interp.AddNodeWithParameters({1}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_SOFTMAX));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_SOFTMAX, 1));
 
     // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
     interp.SetInputs({1});
index e5ade26..881d7c6 100644 (file)
@@ -140,7 +140,7 @@ TEST(NNAPI_Unittest_sub_1, simple_test)
     //  - Read Left from Tensor #1
     //  - Read Right from Tensor #2,
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_SUB));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_SUB, 1));
 
     interp.SetInputs({1, 2});
     interp.SetOutputs({0});
index 208de17..24e1443 100644 (file)
@@ -133,7 +133,7 @@ TEST(NNAPI_Unittest_sub_2, simple_test)
     //  - Read Left from Tensor #1
     //  - Read Right from Tensor #2,
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_SUB));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_SUB, 1));
 
     interp.SetInputs({1, 2});
     interp.SetOutputs({0});
index 934b3d4..4647018 100644 (file)
@@ -125,7 +125,7 @@ TEST(NNAPI_Unittest_sub_3, simple_test)
     //  - Read Left from Tensor #1
     //  - Read Right from Tensor #2,
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_SUB));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_SUB, 1));
 
     interp.SetInputs({1, 2});
     interp.SetOutputs({0});
index d0a34ac..7de2b6d 100644 (file)
@@ -133,7 +133,7 @@ TEST(NNAPI_Unittest_sub_4, simple_test)
     //  - Read Left from Tensor #1
     //  - Read Right from Tensor #2,
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_SUB));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_SUB, 1));
 
     interp.SetInputs({1, 2});
     interp.SetOutputs({0});
index 726c9a7..26d4f39 100644 (file)
@@ -169,7 +169,7 @@ TEST(NNAPI_Unittest_sub_5, simple_test)
     //  - Read Left from Tensor #1
     //  - Read Right from Tensor #2,
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_SUB));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_SUB, 1));
 
     interp.SetInputs({});
     interp.SetOutputs({0});
index 0f39cc8..f8b33ee 100644 (file)
@@ -169,7 +169,7 @@ TEST(NNAPI_Unittest_sub_6, simple_test)
     //  - Read Left from Tensor #1
     //  - Read Right from Tensor #2,
     interp.AddNodeWithParameters({1, 2}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_SUB));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_SUB, 1));
 
     interp.SetInputs({});
     interp.SetOutputs({0});
index 221e223..0d07f12 100644 (file)
@@ -115,7 +115,7 @@ TEST(NNAPI_Unittest_tanh_1, simple_test)
     // Run Tanh and store the result into Tensor #0
     //  - Read input from Tensor #1
     interp.AddNodeWithParameters({1}, {0}, nullptr, 0, nullptr,
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_TANH));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_TANH, 1));
 
     interp.SetInputs({1});
     interp.SetOutputs({0});
index b313c81..f02c208 100644 (file)
@@ -118,7 +118,7 @@ TEST(NNAPI_Unittest_topk_v2_1, simple_test)
     // Run TopK_V2 and store its result into Tensor #2 and #3
     //  - Read input data and K from Tensor #0 and #1, respectively
     interp.AddNodeWithParameters({0, 1}, {2, 3}, nullptr, 0, nullptr,
-                                 BuiltinOpResolver().FindOp(BuiltinOperator_TOPK_V2));
+                                 BuiltinOpResolver().FindOp(BuiltinOperator_TOPK_V2, 1));
 
     // Set Tensor #0 as Input, and Tensor #2 and #3 as Output
     interp.SetInputs({0});
index 42c64f1..a647346 100644 (file)
@@ -278,7 +278,7 @@ int main(int argc, char **argv)
   //  - Read Filter from Tensor #2,
   //  - Read Bias from Tensor #3
   interp.AddNodeWithParameters({1, 2, 3}, {0}, nullptr, 0, reinterpret_cast<void *>(param),
-                               BuiltinOpResolver().FindOp(BuiltinOperator_CONV_2D));
+                               BuiltinOpResolver().FindOp(BuiltinOperator_CONV_2D, 1));
 
   // Set Tensor #1 as Input #0, and Tensor #0 as Output #0
   interp.SetInputs({1});