Imported Upstream version 1.8.0
[platform/core/ml/nnfw.git] / runtime / onert / core / include / backend / cpu_common / Tensor.h
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 #ifndef __ONERT_BACKEND_CPU_COMMON_TENSOR_H__
18 #define __ONERT_BACKEND_CPU_COMMON_TENSOR_H__
19
20 #include "Allocator.h"
21
22 #include <backend/IPortableTensor.h>
23 #include <ir/OperandInfo.h>
24
25 namespace onert
26 {
27 namespace backend
28 {
29 namespace cpu_common
30 {
31
32 class Tensor : public IPortableTensor
33 {
34 public:
35   Tensor() = delete;
36
37 public:
38   Tensor(const ir::OperandInfo &info, const ir::Layout layout,
39          IDynamicTensorManager *dynamic_tensor_manager)
40       : _info(info), _layout(layout), _buffer(nullptr), _num_references(0),
41         _dynamic_tensor_manager(dynamic_tensor_manager), _allocator(nullptr)
42   {
43     // DO NOTHING
44   }
45
46 public:
47   // Only one of two method 'setBuffer' must be called once
48
49   /**
50    * @brief Set the Buffer object. This method is called for static and non-const tensor
51    */
52   void setBuffer(uint8_t *buffer)
53   {
54     assert(_buffer == nullptr);
55     _buffer = buffer;
56   }
57
58   /**
59    * @brief Set the Buffer object. This method is called for dynamic or const tensor
60    */
61   void setBuffer(const std::shared_ptr<Allocator> &alloc)
62   {
63     assert(_buffer == nullptr);
64     _allocator = alloc;
65     _buffer = alloc->base();
66   }
67
68   // This works just as setBuffer but it simply overwrite existing Allocator without nullptr check
69   void overwriteBuffer(const std::shared_ptr<Allocator> &alloc)
70   {
71     _allocator = alloc;
72     _buffer = alloc->base();
73   }
74
75   /**
76    * @brief Mark this tensor does not have memory.
77    *        Real memory deallocation should be done by caller.
78    */
79   void resetBuffer()
80   {
81     _allocator.reset();
82     _buffer = nullptr;
83   }
84
85 public:
86   uint8_t *buffer() const override { return _buffer; }
87   /**
88    * @brief Get dimension by index
89    *
90    * @param index Index to get diemension
91    * @return size_t Dimension at index
92    * @note N : dimension(0)
93    *       H : dimension(1)
94    *       W : dimension(2)
95    *       C : dimension(3)
96    */
97   size_t dimension(size_t index) const override { return _info.shape().dim(index); }
98   size_t num_dimensions() const override { return _info.shape().rank(); }
99   size_t total_size() const override { return _info.total_size(); }
100   size_t calcOffset(const ir::Coordinates &coords) const override;
101   ir::Layout layout() const override { return _layout; }
102   ir::DataType data_type() const override { return _info.typeInfo().type(); }
103   float data_scale() const override { return _info.typeInfo().scale(); }
104   int32_t data_offset() const override { return _info.typeInfo().offset(); }
105   bool is_constant() const override { return _info.isConstant(); }
106   bool is_dynamic() const override { return _info.isDynamic(); }
107   void set_dynamic() override { _info.setDynamic(); }
108   IDynamicTensorManager *dynamic_tensor_manager() override { return _dynamic_tensor_manager; }
109   bool is_sparse() const override { return _info.typeInfo().sparse(); }
110   virtual const uint16_t *w1_segments() const override { return _info.typeInfo().w1_segments(); }
111   virtual const uint16_t *w1_indices() const override { return _info.typeInfo().w1_indices(); }
112
113   virtual void increase_ref()
114   {
115     assert(is_dynamic() ||
116            // when not dynamic
117            (_buffer != nullptr));
118
119     ++_num_references;
120   }
121   virtual void decrease_ref()
122   {
123     assert(_buffer != nullptr || _allocator != nullptr);
124     assert(_num_references > 0);
125     --_num_references;
126     // constant tensor and dynamic tensor has _allocator
127     if (_num_references == 0)
128     {
129       if (_buffer != nullptr)
130         _buffer = nullptr;
131       if (_allocator != nullptr)
132       {
133         _allocator->release();
134         _allocator = nullptr;
135       }
136     }
137   }
138
139   void setShape(const ir::Shape &new_shape) override;
140
141 protected:
142   ir::OperandInfo _info;
143   ir::Layout _layout;
144   uint8_t *_buffer;
145   int32_t _num_references;
146   IDynamicTensorManager *_dynamic_tensor_manager;
147
148 private:
149   /**
150    * @brief Memory allocator for dynamic tensor and const tensor
151    *        Since maintaing _allocator and also _buffer makes confusion,
152    *        we will mainly use _buffer (not _allocator.base()) for memory pointer in this code.
153    *        _allocator(shared_ptr) is used to guarantee that we have valid _buffer.
154    */
155   std::shared_ptr<Allocator> _allocator;
156 };
157
158 } // namespace cpu_common
159 } // namespace backend
160 } // namespace onert
161
162 #endif // __ONERT_BACKEND_CPU_COMMON_TENSOR_H__