Imported Upstream version 1.9.0
[platform/core/ml/nnfw.git] / compiler / locomotiv / src / Node / ConstGen.cpp
1 /*
2  * Copyright (c) 2019 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 "NodeExecution.h"
18
19 #include "NodeDataImpl.h"
20 #include "NodeDomain.h"
21
22 #include <nncc/core/ADT/tensor/Shape.h>
23 #include <nncc/core/ADT/tensor/Buffer.h>
24 #include <nncc/core/ADT/tensor/IndexEnumerator.h>
25 #include <nncc/core/ADT/tensor/LexicalLayout.h>
26
27 #include <stdexcept>
28 #include <cassert>
29
30 using nncc::core::ADT::tensor::Index;
31 using nncc::core::ADT::tensor::IndexEnumerator;
32 using nncc::core::ADT::tensor::Shape;
33 using nncc::core::ADT::tensor::LexicalLayout;
34 using nncc::core::ADT::tensor::make_buffer;
35
36 namespace
37 {
38
39 /**
40  * @brief Get offset based on given shape and index. Assume lexical layout.
41  *
42  * examples)
43  * For shape = {3, 4} and index = {1, 2},
44  *     offset would be 6 ( = 1 * (4) + 2 )
45  * For shape = {2, 3, 4} and index = {1, 0, 2},
46  *     offset would be 14 ( = 1 * (3*4) + 0 *(4) + 2 )
47  */
48 inline uint32_t offset_by_index(const Shape &shape, const Index &index)
49 {
50   static const nncc::core::ADT::tensor::LexicalLayout l;
51   return l.offset(shape, index);
52 }
53
54 } // namespace
55
56 namespace
57 {
58
59 using namespace locomotiv;
60
61 void execute_node(loco::ConstGen *constgen)
62 {
63   uint32_t volume = 1;
64
65   Shape shape;
66   shape.resize(constgen->rank());
67   for (uint32_t i = 0; i < shape.rank(); ++i)
68   {
69     shape.dim(i) = constgen->dim(i).value();
70     volume *= shape.dim(i);
71   }
72
73   std::unique_ptr<NodeData> data = nullptr;
74
75   switch (constgen->dtype())
76   {
77     case loco::DataType::S32:
78     {
79       assert(volume == constgen->size<loco::DataType::S32>());
80
81       auto buf = make_buffer<int32_t, LexicalLayout>(shape);
82
83       for (IndexEnumerator e{shape}; e.valid(); e.advance())
84       {
85         const auto &index = e.current();
86         uint32_t offset = ::offset_by_index(shape, index);
87         buf.at(index) = constgen->at<loco::DataType::S32>(offset);
88       }
89
90       data = locomotiv::make_data(buf);
91       break;
92     }
93     case loco::DataType::FLOAT32:
94     {
95       assert(volume == constgen->size<loco::DataType::FLOAT32>());
96
97       auto buf = make_buffer<float, LexicalLayout>(shape);
98
99       for (IndexEnumerator e{shape}; e.valid(); e.advance())
100       {
101         const auto &index = e.current();
102         uint32_t offset = ::offset_by_index(shape, index);
103         buf.at(index) = constgen->at<loco::DataType::FLOAT32>(offset);
104       }
105
106       data = locomotiv::make_data(buf);
107       break;
108     }
109     default:
110       throw std::runtime_error("NYI for this DataType");
111   }
112
113   assert(data != nullptr);
114   annot_data(constgen, std::move(data));
115   annot_domain(constgen, loco::Domain::Tensor);
116 }
117
118 } // namespace
119
120 namespace locomotiv
121 {
122
123 void NodeExecution::execute(loco::ConstGen *constgen) { execute_node(constgen); }
124
125 } // namespace locomotiv