Introduce enum `OperationCodeEx` to support extended operators (#1223)
author장지섭/동작제어Lab(SR)/Engineer/삼성전자 <jiseob.jang@samsung.com>
Thu, 17 May 2018 07:53:54 +0000 (16:53 +0900)
committer서상민/동작제어Lab(SR)/Senior Engineer/삼성전자 <sangmin7.seo@samsung.com>
Thu, 17 May 2018 07:53:54 +0000 (16:53 +0900)
This commit introduces enum `OperationCodeEx` to support extended operators.
The list of added operations:
  - ANEURALNETWORKS_EX_CAST
  - ANEURALNETWORKS_EX_GATHER
  - ANEURALNETWORKS_EX_TOPK_V2
  - ANEURALNETWORKS_EX_TENSORFLOW_MAX

Signed-off-by: jiseob.jang <jiseob.jang@samsung.com>
include/NeuralNetworksEX.h [new file with mode: 0644]
runtimes/nn/common/CpuExecutor.cpp
runtimes/nn/common/Utils.cpp
runtimes/nn/common/include/Utils.h
runtimes/nn/depend/hal/include/android/hardware/neuralnetworks/1.0/types.h
runtimes/nn/runtime/NeuralNetworks.cpp

diff --git a/include/NeuralNetworksEX.h b/include/NeuralNetworksEX.h
new file mode 100644 (file)
index 0000000..0b9f64d
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NN_RUNTIME_NEURAL_NETWORKS_EX_H
+#define NN_RUNTIME_NEURAL_NETWORKS_EX_H
+
+typedef enum {
+    /** extends operation. */
+    ANEURALNETWORKS_CAST_EX = 50000,
+    ANEURALNETWORKS_GATHER_EX = 50001,
+    ANEURALNETWORKS_TOPK_V2_EX = 50002,
+    ANEURALNETWORKS_TENSORFLOW_MAX_EX = 50003,
+} OperationCodeEx;  // extends OperationCode
+
+#endif  // NN_RUNTIME_NEURAL_NETWORKS_EX_H
index b2929d0..c4c9d1d 100644 (file)
@@ -1303,6 +1303,26 @@ int CpuExecutor::executeOperation(const Operation &operation)
     }
     break;
 #endif // REF-ANN
+    case OperationType::CAST:
+    {
+      // TODO-NNRT : implement this operation.
+    }
+    break;
+    case OperationType::GATHER:
+    {
+      // TODO-NNRT : implement this operation.
+    }
+    break;
+    case OperationType::TOPK_V2:
+    {
+      // TODO-NNRT : implement this operation.
+    }
+    break;
+    case OperationType::TENSORFLOW_MAX:
+    {
+      // TODO-NNRT : implement this operation.
+    }
+    break;
     default:
 #if 0 // TODO-NNRT : Enable if it is needed.
       nnAssert(false);
index e28ea3a..e1fdf24 100644 (file)
@@ -64,6 +64,30 @@ EntryType tableLookup(const EntryType (&table)[entryCount],
   }
 }
 
+template <typename EntryType, uint32_t entryCount, uint32_t entryCountOEM, uint32_t entryCountEX>
+EntryType tableLookup(const EntryType (&table)[entryCount],
+                      const EntryType (&tableOEM)[entryCountOEM],
+                      const EntryType (&tableEX)[entryCountEX], uint32_t code)
+{
+  if (code < entryCount)
+  {
+    return table[code];
+  }
+  else if (code >= kOEMCodeBase && (code - kOEMCodeBase) < entryCountOEM)
+  {
+    return tableOEM[code - kOEMCodeBase];
+  }
+  else if (code >= kEXCodeBase && (code - kEXCodeBase) < entryCountEX)
+  {
+    return tableEX[code - kEXCodeBase];
+  }
+  else
+  {
+    nnAssert(!"tableLookup: bad code");
+    return EntryType();
+  }
+}
+
 }; // anonymous namespace
 
 const char *kOperationNames[kNumberOfOperationTypes] = {
@@ -107,10 +131,17 @@ const char *kOperationNamesOEM[kNumberOfOperationTypesOEM] = {
 static_assert(COUNT(kOperationNamesOEM) == kNumberOfOperationTypesOEM,
               "kOperationNamesOEM is incorrect");
 
+const char *kOperationNamesEX[kNumberOfOperationTypesEX] = {
+    "CAST", "GATHER", "TOPK_V2", "TENSORFLOW_MAX",
+};
+
+static_assert(COUNT(kOperationNamesEX) == kNumberOfOperationTypesEX,
+              "kOperationNamesEX is incorrect");
+
 const char *getOperationName(OperationType type)
 {
   uint32_t n = static_cast<uint32_t>(type);
-  return tableLookup(kOperationNames, kOperationNamesOEM, n);
+  return tableLookup(kOperationNames, kOperationNamesOEM, kOperationNamesEX, n);
 }
 
 const uint32_t kSizeOfDataType[]{
@@ -343,7 +374,7 @@ static bool validOperations(const hidl_vec<Operation> &operations, size_t operan
 {
   for (auto &op : operations)
   {
-    if (!validCode(kNumberOfOperationTypes, kNumberOfOperationTypesOEM,
+    if (!validCode(kNumberOfOperationTypes, kNumberOfOperationTypesOEM, kNumberOfOperationTypesEX,
                    static_cast<uint32_t>(op.type)))
     {
       LOG(ERROR) << "Invalid operation type ";
index acd4ae3..b8ae832 100644 (file)
@@ -47,6 +47,12 @@ const int kNumberOfOperationTypesOEM = 1;
 // The lowest number assigned to any OEM Code in NeuralNetworksOEM.h.
 const int kOEMCodeBase = 10000;
 
+// The number of operation types (OperationCode) defined in NeuralNetworksEX.h.
+const int kNumberOfOperationTypesEX = 4;
+
+// The lowest number assigned to any EX Code in NeuralNetworksEX.h.
+const int kEXCodeBase = 50000;
+
 // Assert macro, as Android does not generally support assert.
 #define nnAssert(v)                                                                                \
   do                                                                                               \
@@ -119,6 +125,13 @@ inline bool validCode(uint32_t codeCount, uint32_t codeCountOEM, uint32_t code)
   return (code < codeCount) || (code >= kOEMCodeBase && (code - kOEMCodeBase) < codeCountOEM);
 }
 
+inline bool validCode(uint32_t codeCount, uint32_t codeCountOEM, uint32_t codeCountEX,
+                      uint32_t code)
+{
+  return (code < codeCount) || (code >= kOEMCodeBase && (code - kOEMCodeBase) < codeCountOEM) ||
+         (code >= kEXCodeBase && (code - kEXCodeBase) < codeCountEX);
+}
+
 int validateOperandType(const ANeuralNetworksOperandType &type, const char *tag, bool allowPartial);
 int validateOperandList(uint32_t count, const uint32_t *list, uint32_t operandCount,
                         const char *tag);
index 146d18d..b94959c 100644 (file)
@@ -55,6 +55,12 @@ enum class OperationType : int32_t {
     SVDF = 27,
     TANH = 28,
     OEM_OPERATION = 10000,
+    // TODO-NNRT : If values of ANeuralNetworksOperationTypeEx and this values don't map one-to-one,
+    //             should change to map ANeuralNetworksOperationTypeEx onto OperationType.
+    CAST = 50000,
+    GATHER = 50001,
+    TOPK_V2 = 50002,
+    TENSORFLOW_MAX = 50003,
 };
 
 enum class FusedActivationFunc : int32_t {
index 6a0abd0..b308d2a 100644 (file)
@@ -20,6 +20,7 @@
 // that implements the functionality.
 
 #include "NeuralNetworks.h"
+#include "NeuralNetworksEX.h"
 #include "Callbacks.h"
 #if 0 // TODO-NNRT : If we consider OEM operations, it will enable.
 #include "NeuralNetworksOEM.h"
@@ -47,7 +48,7 @@ static_assert(ANEURALNETWORKS_TENSOR_OEM_BYTE == 10001,
               "ANEURALNETWORKS_TENSOR_OEM_BYTE has changed");
 #endif
 // IMPORTANT: When adding new values, update kNumberOfOperationTypes or
-// kNumberOfOperationTypesOEMin Utils.h.
+// kNumberOfOperationTypesOEM kNumberOfOperationTypesEX in Utils.h.
 static_assert(ANEURALNETWORKS_ADD == 0, "ANEURALNETWORKS_ADD has changed");
 static_assert(ANEURALNETWORKS_AVERAGE_POOL_2D == 1, "ANEURALNETWORKS_AVERAGE_POOL_2D has changed");
 static_assert(ANEURALNETWORKS_CONCATENATION == 2, "ANEURALNETWORKS_CONCATENATION has changed");
@@ -86,6 +87,11 @@ static_assert(ANEURALNETWORKS_TANH == 28, "ANEURALNETWORKS_TANH has changed");
 static_assert(ANEURALNETWORKS_OEM_OPERATION == 10000,
               "ANEURALNETWORKS_OEM_OPERATION has changed");
 #endif
+static_assert(ANEURALNETWORKS_CAST_EX == 50000, "ANEURALNETWORKS_CAST_EX has changed");
+static_assert(ANEURALNETWORKS_GATHER_EX == 50001, "ANEURALNETWORKS_GATHER_EX has changed");
+static_assert(ANEURALNETWORKS_TOPK_V2_EX == 50002, "ANEURALNETWORKS_TOPK_V2_EX has changed");
+static_assert(ANEURALNETWORKS_TENSORFLOW_MAX_EX == 50003,
+              "ANEURALNETWORKS_TENSORFLOW_MAX_EX has changed");
 static_assert(ANEURALNETWORKS_FUSED_NONE == 0, "ANEURALNETWORKS_FUSED_NONE has changed");
 static_assert(ANEURALNETWORKS_FUSED_RELU == 1, "ANEURALNETWORKS_FUSED_RELU has changed");
 static_assert(ANEURALNETWORKS_FUSED_RELU1 == 2, "ANEURALNETWORKS_FUSED_RELU1 has changed");
@@ -196,6 +202,16 @@ static_assert(static_cast<int32_t>(OperationType::SVDF) == ANEURALNETWORKS_SVDF,
               "OperationType::SVDF != ANEURALNETWORKS_SVDF");
 static_assert(static_cast<int32_t>(OperationType::TANH) == ANEURALNETWORKS_TANH,
               "OperationType::TANH != ANEURALNETWORKS_TANH");
+// extends OperationCode
+static_assert(static_cast<int32_t>(OperationType::CAST) == ANEURALNETWORKS_CAST_EX,
+              "OperationType::CAST != ANEURALNETWORKS_CAST_EX");
+static_assert(static_cast<int32_t>(OperationType::GATHER) == ANEURALNETWORKS_GATHER_EX,
+              "OperationType::GATHER != ANEURALNETWORKS_GATHER_EX");
+static_assert(static_cast<int32_t>(OperationType::TOPK_V2) == ANEURALNETWORKS_TOPK_V2_EX,
+              "OperationType::TOPK_V2 != ANEURALNETWORKS_TOPK_V2_EX");
+static_assert(static_cast<int32_t>(OperationType::TENSORFLOW_MAX) ==
+                  ANEURALNETWORKS_TENSORFLOW_MAX_EX,
+              "OperationType::TENSORFLOW_MAX != ANEURALNETWORKS_TENSORFLOW_MAX_EX");
 
 static_assert(static_cast<int32_t>(FusedActivationFunc::NONE) == ANEURALNETWORKS_FUSED_NONE,
               "FusedActivationFunc::NONE != ANEURALNETWORKS_FUSED_NONE");