Imported Upstream version 1.25.0
[platform/core/ml/nnfw.git] / runtime / onert / core / src / backend / builtin / KernelGenerator.cc
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
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 #include "KernelGenerator.h"
18
19 #include "kernel/IfLayer.h"
20 #include "kernel/PermuteLayer.h"
21 #include "kernel/WhileLayer.h"
22
23 #include "exec/FunctionSequence.h"
24
25 namespace onert
26 {
27 namespace backend
28 {
29 namespace builtin
30 {
31
32 KernelGenerator::KernelGenerator(const ir::Graph &graph, DynamicTensorManager *dyn_tensor_manager,
33                                  const std::shared_ptr<TensorRegistry> &tensor_reg,
34                                  const std::shared_ptr<ExternalContext> &external_context)
35   : basic::KernelGeneratorBase{graph}, _dyn_tensor_manager{dyn_tensor_manager},
36     _tensor_reg{tensor_reg}, _tensor_registries{}, _executors{nullptr}, _model_index{},
37     _external_context{external_context}
38 {
39   UNUSED_RELEASE(_graph);
40   UNUSED_RELEASE(_tensor_registries);
41   UNUSED_RELEASE(_executors);
42 }
43
44 std::unique_ptr<exec::FunctionSequence> KernelGenerator::generate(ir::OperationIndex ind)
45 {
46   assert(_dyn_tensor_manager);
47   assert(_tensor_reg);
48
49   auto ret = std::make_unique<exec::FunctionSequence>();
50
51   // Prepare to handle dynamic tensors later
52   auto dyn_ctx = std::make_shared<exec::FunctionSequence::DynamicTensorCtx>();
53   {
54     dyn_ctx->op = &_graph.operations().at(ind);
55     dyn_ctx->dynamic_shape_inferer =
56       std::make_unique<exec::DynamicShapeInferer>(_graph.operands(), _tensor_reg);
57   }
58   ret->dynamic_tensor_ctx(dyn_ctx);
59
60   auto &op = _graph.operations().at(ind);
61   op.accept(*this);
62   assert(_return_fn); // _return_fn must have been generated
63   ret->append(std::move(_return_fn));
64
65   return ret;
66 }
67
68 void KernelGenerator::visit(const ir::operation::If &node)
69 {
70   const auto then_subg_index = node.param().then_subg_index;
71   const auto else_subg_index = node.param().else_subg_index;
72
73   std::vector<backend::IPortableTensor *> input_tensors;
74   for (const auto &input_index : node.getInputs())
75   {
76     auto input_tensor = getPortableTensor(input_index);
77     input_tensors.emplace_back(input_tensor);
78   }
79
80   std::vector<backend::IPortableTensor *> output_tensors;
81   for (const auto &output_index : node.getOutputs())
82   {
83     auto output_tensor = getPortableTensor(output_index);
84     output_tensors.emplace_back(output_tensor);
85   }
86
87   // IfLayer just set Executors instead of then and else executor to avoid complexity of
88   // creating executor recusively
89   const auto cond_tensor = input_tensors.front();
90   input_tensors.erase(input_tensors.begin());
91   auto fn = std::make_unique<::onert::backend::builtin::kernel::IfLayer>(
92     cond_tensor, input_tensors, output_tensors, then_subg_index, else_subg_index, _executors,
93     _model_index, _external_context);
94
95   _return_fn = std::move(fn);
96 }
97
98 void KernelGenerator::visit(const ir::operation::Permute &node)
99 {
100   const auto output_index{node.getOutputs().at(0)};
101   const auto input_index{node.getInputs().at(0)};
102
103   // Add PermuteLayer
104   std::vector<ITensor *> output_tensors{getTensor(output_index)};
105   std::vector<ITensor *> input_tensors{getTensor(input_index)};
106
107   auto fn =
108     std::make_unique<kernel::PermuteLayer>(input_tensors, output_tensors, _external_context);
109   _return_fn = std::move(fn);
110 }
111
112 void KernelGenerator::visit(const ir::operation::While &node)
113 {
114   const auto cond_subg_index = node.param().cond_subg_index;
115   const auto body_subg_index = node.param().body_subg_index;
116
117   // This op does not support input as a constant, because builtin backend does not have
118   // TensorBuilder
119   std::vector<backend::IPortableTensor *> input_tensors;
120   for (const auto &input_index : node.getInputs())
121   {
122     auto input_tensor = getPortableTensor(input_index);
123     input_tensors.emplace_back(input_tensor);
124   }
125
126   std::vector<backend::IPortableTensor *> output_tensors;
127   for (const auto &output_index : node.getOutputs())
128   {
129     auto output_tensor = getPortableTensor(output_index);
130     output_tensors.emplace_back(output_tensor);
131   }
132
133   // WhileLayer just set Executors instead of cond and body executor to avoid complexity of
134   // creating executor recusively
135   auto fn = std::make_unique<::onert::backend::builtin::kernel::WhileLayer>(
136     input_tensors, output_tensors, cond_subg_index, body_subg_index, _executors, _model_index,
137     _dyn_tensor_manager->dynamic_mem_mgr().get(), _external_context);
138
139   _return_fn = std::move(fn);
140 }
141
142 backend::ITensor *KernelGenerator::getTensor(const ir::OperandIndex &index)
143 {
144   // get Tensor from all tensor registries (for Permute op)
145   auto ret = _tensor_registries.getITensor(index);
146   assert(ret != nullptr);
147   return ret;
148 }
149
150 backend::IPortableTensor *KernelGenerator::getPortableTensor(const ir::OperandIndex &index)
151 {
152   auto ret = _tensor_reg->getPortableTensor(index);
153   assert(ret != nullptr);
154   return ret;
155 }
156
157 } // namespace builtin
158 } // namespace backend
159 } // namespace onert