Imported Upstream version 1.21.0
[platform/core/ml/nnfw.git] / compiler / coco / generic / src / IR / Data.cpp
1 /*
2  * Copyright (c) 2018 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 "coco/IR/Data.h"
18
19 #include <nncc/core/ADT/kernel/NCHWLayout.h>
20 #include <nncc/core/ADT/kernel/Overlay.h>
21
22 #include <memory>
23 #include <map>
24
25 using namespace nncc::core::ADT;
26
27 using std::make_unique;
28
29 namespace
30 {
31 class BlobContext
32 {
33 public:
34   void allocate(const coco::Bag *b, uint32_t elemsize)
35   {
36     auto buffer = make_unique<std::vector<uint8_t>>();
37     buffer->resize(b->size() * elemsize);
38
39     _data[b] = std::move(buffer);
40   }
41
42   void release(const coco::Bag *b) { _data.erase(b); }
43
44 public:
45   uint8_t *at(const coco::Bag *b)
46   {
47     auto it = _data.find(b);
48
49     if (it != _data.end())
50     {
51       return it->second->data();
52     }
53
54     return nullptr;
55   }
56
57 public:
58   uint32_t size(const coco::Bag *b) const
59   {
60     auto it = _data.find(b);
61
62     if (it != _data.end())
63     {
64       return it->second->size();
65     }
66
67     return 0;
68   }
69
70 private:
71   std::map<const coco::Bag *, std::unique_ptr<std::vector<uint8_t>>> _data;
72 };
73 } // namespace
74
75 namespace
76 {
77
78 template <typename T> class KernelOverlay : public kernel::Reader<T>, public kernel::Accessor<T>
79 {
80 public:
81   KernelOverlay(T *base, const coco::KernelObject *object) : _base{base}, _object{object}
82   {
83     // DO NOTHING
84   }
85
86 public:
87   T at(uint32_t nth, uint32_t ch, uint32_t row, uint32_t col) const override
88   {
89     assert(_object->layout() != nullptr);
90     auto offset = _object->layout()->at(nth, ch, row, col);
91     return *(_base + offset.value());
92   }
93
94 public:
95   T &at(uint32_t nth, uint32_t ch, uint32_t row, uint32_t col) override
96   {
97     assert(_object->layout() != nullptr);
98     auto offset = _object->layout()->at(nth, ch, row, col);
99     return *(_base + offset.value());
100   }
101
102 private:
103   T *_base;
104   const coco::KernelObject *_object;
105 };
106
107 } // namespace
108
109 namespace
110 {
111 template <typename T> class PlainWeightContextImpl final : public coco::PlainWeightContext<T>
112 {
113 public:
114   PlainWeightContextImpl(BlobContext *blob) : _blob{blob}
115   {
116     // DO NOTHING
117   }
118
119 public:
120   PlainWeightContextImpl(const PlainWeightContextImpl &) = delete;
121   PlainWeightContextImpl(PlainWeightContextImpl &&) = delete;
122
123 public:
124   coco::Span<T> allocate(const coco::Bag *bag) override
125   {
126     assert(bag != nullptr);
127     _blob->allocate(bag, sizeof(T));
128     return weight(bag);
129   }
130
131   coco::Span<T> weight(const coco::Bag *b) override
132   {
133     // TODO Check type later
134     if (auto data = _blob->at(b))
135     {
136       uint32_t byte_size = _blob->size(b);
137       assert(byte_size % sizeof(T) == 0);
138       uint32_t elem_size = static_cast<uint32_t>(byte_size / sizeof(T));
139
140       return coco::Span<T>{reinterpret_cast<T *>(data), elem_size};
141     }
142
143     return coco::Span<T>{nullptr, 0};
144   }
145
146 public:
147   std::unique_ptr<kernel::Accessor<T>> access(const coco::KernelObject *o) override
148   {
149     auto b = o->bag();
150     assert(b != nullptr);
151
152     if (auto base = reinterpret_cast<T *>(_blob->at(b)))
153     {
154       return make_unique<KernelOverlay<T>>(base, o);
155     }
156
157     return nullptr;
158   }
159
160 public:
161   std::unique_ptr<kernel::Reader<T>> read(const coco::KernelObject *o) const override
162   {
163     auto b = o->bag();
164     assert(b != nullptr);
165
166     if (auto base = reinterpret_cast<T *>(_blob->at(b)))
167     {
168       return make_unique<KernelOverlay<T>>(base, o);
169     }
170
171     return nullptr;
172   }
173
174 private:
175   BlobContext *const _blob;
176 };
177 } // namespace
178
179 namespace
180 {
181 struct DataImpl final : public coco::Data
182 {
183   std::unique_ptr<BlobContext> _blob;
184   std::unique_ptr<PlainWeightContextImpl<float>> _fp32;
185
186   bool allocated(const coco::Bag *b) const override { return _blob->at(b) != nullptr; }
187
188   void release(const coco::Bag *b) override
189   {
190     assert(allocated(b));
191     _blob->release(b);
192   }
193
194   coco::PlainWeightContext<float> *f32(void) override { return _fp32.get(); }
195   const coco::PlainWeightContext<float> *f32(void) const override { return _fp32.get(); }
196 };
197 } // namespace
198
199 namespace coco
200 {
201
202 std::unique_ptr<Data> Data::create(void)
203 {
204   auto blob = make_unique<BlobContext>();
205   auto fp32 = make_unique<PlainWeightContextImpl<float>>(blob.get());
206
207   auto data = make_unique<DataImpl>();
208
209   data->_blob = std::move(blob);
210   data->_fp32 = std::move(fp32);
211
212   return data;
213 }
214
215 } // namespace coco