1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "OperationResolver"
18 
19 #include "OperationResolver.h"
20 
21 #include "NeuralNetworks.h"
22 
23 namespace android {
24 namespace nn {
25 
26 #define NN_FORWARD_DECLARE_OPERATION_REGISTRATION_FUNCTION(opType) \
27     const OperationRegistration* register_##opType();
28 
29 NN_FOR_EACH_OPERATION(NN_FORWARD_DECLARE_OPERATION_REGISTRATION_FUNCTION)
30 
31 #undef NN_FORWARD_DECLARE_OPERATION_REGISTRATION_FUNCTION
32 
33 NN_OPERATION_IS_NOT_IMPLEMENTED(DEPTH_TO_SPACE);
34 NN_OPERATION_IS_NOT_IMPLEMENTED(EMBEDDING_LOOKUP);
35 NN_OPERATION_IS_NOT_IMPLEMENTED(HASHTABLE_LOOKUP);
36 NN_OPERATION_IS_NOT_IMPLEMENTED(LSH_PROJECTION);
37 NN_OPERATION_IS_NOT_IMPLEMENTED(LSTM);
38 NN_OPERATION_IS_NOT_IMPLEMENTED(RESHAPE);
39 NN_OPERATION_IS_NOT_IMPLEMENTED(RNN);
40 NN_OPERATION_IS_NOT_IMPLEMENTED(SPACE_TO_DEPTH);
41 NN_OPERATION_IS_NOT_IMPLEMENTED(SVDF);
42 NN_OPERATION_IS_NOT_IMPLEMENTED(BATCH_TO_SPACE_ND);
43 NN_OPERATION_IS_NOT_IMPLEMENTED(MEAN);
44 NN_OPERATION_IS_NOT_IMPLEMENTED(PAD);
45 NN_OPERATION_IS_NOT_IMPLEMENTED(SPACE_TO_BATCH_ND);
46 NN_OPERATION_IS_NOT_IMPLEMENTED(ARGMAX);
47 NN_OPERATION_IS_NOT_IMPLEMENTED(ARGMIN);
48 NN_OPERATION_IS_NOT_IMPLEMENTED(BIDIRECTIONAL_SEQUENCE_LSTM);
49 NN_OPERATION_IS_NOT_IMPLEMENTED(CAST);
50 NN_OPERATION_IS_NOT_IMPLEMENTED(EXPAND_DIMS);
51 NN_OPERATION_IS_NOT_IMPLEMENTED(GROUPED_CONV_2D);
52 NN_OPERATION_IS_NOT_IMPLEMENTED(MAXIMUM);
53 NN_OPERATION_IS_NOT_IMPLEMENTED(MINIMUM);
54 NN_OPERATION_IS_NOT_IMPLEMENTED(PAD_V2);
55 NN_OPERATION_IS_NOT_IMPLEMENTED(POW);
56 NN_OPERATION_IS_NOT_IMPLEMENTED(QUANTIZED_16BIT_LSTM);
57 NN_OPERATION_IS_NOT_IMPLEMENTED(RANDOM_MULTINOMIAL);
58 NN_OPERATION_IS_NOT_IMPLEMENTED(SPLIT);
59 NN_OPERATION_IS_NOT_IMPLEMENTED(TILE);
60 NN_OPERATION_IS_NOT_IMPLEMENTED(IF);
61 NN_OPERATION_IS_NOT_IMPLEMENTED(WHILE);
62 NN_OPERATION_IS_NOT_IMPLEMENTED(OEM_OPERATION);
63 
BuiltinOperationResolver()64 BuiltinOperationResolver::BuiltinOperationResolver() {
65 #define NN_REGISTER_OPERATION_FUNCTION(opType) registerOperation(register_##opType());
66 
67     NN_FOR_EACH_OPERATION(NN_REGISTER_OPERATION_FUNCTION)
68 
69 #undef NN_REGISTER_OPERATION_FUNCTION
70 }
71 
findOperation(OperationType operationType) const72 const OperationRegistration* BuiltinOperationResolver::findOperation(
73         OperationType operationType) const {
74     auto index = static_cast<int32_t>(operationType);
75     if (index >= 0 && index < kNumberOfOperationTypes) {
76         return mRegistrations[index];
77     }
78 #ifdef NN_EXPERIMENTAL_FEATURE
79     if (index >= kStartOfExperimentalOperations &&
80         index < kStartOfExperimentalOperations + kNumberOfExperimentalOperationTypes) {
81         return mExperimentalRegistrations[index - kStartOfExperimentalOperations];
82     }
83 #endif  // NN_EXPERIMENTAL_FEATURE
84     return nullptr;
85 }
86 
registerOperation(const OperationRegistration * operationRegistration)87 void BuiltinOperationResolver::registerOperation(
88         const OperationRegistration* operationRegistration) {
89     // Some operations (such as IF and WHILE) are not implemented through registration. These
90     // operations call registerOperation with a nullptr, which skips registration.
91     if (operationRegistration == nullptr) {
92         return;
93     }
94 
95     auto index = static_cast<int32_t>(operationRegistration->type);
96 
97 #ifdef NN_EXPERIMENTAL_FEATURE
98     if (index >= kStartOfExperimentalOperations) {
99         CHECK_LT(index, kStartOfExperimentalOperations + kNumberOfExperimentalOperationTypes);
100         CHECK(mExperimentalRegistrations[index - kStartOfExperimentalOperations] == nullptr);
101         mExperimentalRegistrations[index - kStartOfExperimentalOperations] = operationRegistration;
102         return;
103     }
104 #endif  // NN_EXPERIMENTAL_FEATURE
105 
106     CHECK_LE(0, index);
107     CHECK_LT(index, kNumberOfOperationTypes);
108     CHECK(mRegistrations[index] == nullptr);
109     mRegistrations[index] = operationRegistration;
110 }
111 
112 }  // namespace nn
113 }  // namespace android
114