ONE - On-device Neural Engine
Loading...
Searching...
No Matches
luci::CircleConstNodeBuilder Class Reference

Builder creates CircleConst node from Tensor with buffer. More...

#include <CircleConst.h>

Collaboration diagram for luci::CircleConstNodeBuilder:

Public Member Functions

CircleNodebuild (TensorIndex tensor_index, GraphBuilderContext *ctx) const final
 
- Public Member Functions inherited from luci::TypedNodeBuilder< NodeBuilderType::BUFFER >
NodeBuilderType builder_type () const final
 
- Public Member Functions inherited from luci::NodeBuilderBase
virtual ~NodeBuilderBase ()=default
 

Detailed Description

Builder creates CircleConst node from Tensor with buffer.

Definition at line 30 of file CircleConst.h.

Member Function Documentation

◆ build()

CircleNode * luci::CircleConstNodeBuilder::build ( TensorIndex  tensor_index,
GraphBuilderContext ctx 
) const
finalvirtual

Implements luci::NodeBuilderBase.

Definition at line 163 of file CircleConst.cpp.

165{
166 assert(tensor_index >= 0);
167 LOGGER(l);
168
169 auto graph = context->graph();
170 auto reader = context->reader();
171 const auto tensors = reader->tensors();
172 const auto const_tensor = tensors[tensor_index];
173 assert(const_tensor != nullptr);
174 if (const_tensor->is_variable())
175 {
176 // Create CircleVariable for variable
177 return nullptr;
178 }
179
180 const auto r_buffers = reader->buffers();
181 const auto c_buffer = const_tensor->buffer();
182 const auto r_buffer = r_buffers[c_buffer];
183 assert(r_buffer != nullptr);
184 if (r_buffer->offset() == 1 || r_buffer->size() == 1)
185 {
186 // NOTE this shouldn't happen
187 throw std::runtime_error("CircleConst: Circle file with invalid extended Buffer.");
188 }
189 // temporary buffer to provide raw data from file
190 // must have life time same or longer than 'buffer' variable
191 std::vector<uint8_t> temp_buffer;
192 luci::VectorWrapper<uint8_t> buffer(nullptr);
193 if (r_buffer->offset() > 1)
194 {
195 if (r_buffer->size() >= std::numeric_limits<uint32_t>::max())
196 {
197 // NOTE uint32_t limit is to match "uoffset_t flatbuffers::Vector::size()"
198 throw std::runtime_error("CircleConst: Circle file with invalid extended Buffer.");
199 }
200 uint32_t r_size = static_cast<uint32_t>(r_buffer->size());
201 // match binary level to flatbuffers::Vector
202 temp_buffer.resize(r_size + sizeof(uint32_t));
203
204 uint8_t *t_data = temp_buffer.data();
205 const uint8_t *f_data = reader->file_data(r_buffer->offset());
206 if (f_data == nullptr)
207 {
208 // NOTE this shouldn't happen
209 assert(false);
210 return nullptr;
211 }
212 memcpy(t_data, &r_size, sizeof(r_size));
213 t_data = t_data + sizeof(r_size);
214 if (r_buffer->offset() + r_buffer->size() > reader->file_size())
215 {
216 // NOTE this shouldn't happen
217 assert(false);
218 return nullptr;
219 }
220 memcpy(t_data, f_data, r_buffer->size());
221
223 const fbv_t *v_data = reinterpret_cast<const fbv_t *>(temp_buffer.data());
224 buffer = wrap(v_data);
225
226 context->ext_buffer(true);
227 }
228 else
229 {
230 buffer = wrap(r_buffer->data());
231 }
232 const auto const_dims = wrap(const_tensor->shape()); // in NHWC
233 if (const_dims.size() == 0 && buffer.empty())
234 {
235 // unknown shape tensor and scalar tensor
236 return nullptr;
237 }
238
239 // if tensor_index is used as output to some other operator, this is not a constant
240 auto tensoroutputs = context->tensoroutputs();
241 if (tensoroutputs->find(tensor_index))
242 {
243 // other operator output tensor
244 return nullptr;
245 }
246
247 uint32_t num_elements = 1;
248 for (uint32_t r = 0; r < const_dims.size(); ++r)
249 {
250 num_elements = num_elements * const_dims[r];
251 }
252
253 if (buffer.empty() && num_elements > 0)
254 {
255 // normal empty tensor
256 return nullptr;
257 }
258
259 auto const_node = graph->nodes()->create<CircleConst>();
261 const_node->shape_status(luci::ShapeStatus::VALID);
262 INFO(l) << "[luci] NodeFinder const_node(" << tensor_index << ") -> " << const_node << " "
263 << const_dims << std::endl;
264 if (num_elements > 0)
265 {
266 switch (luci_datatype(const_tensor->type()))
267 {
268 case loco::DataType::FLOAT32:
269 copy_data<loco::DataType::FLOAT32>(buffer, num_elements, const_node);
270 break;
271
272 case loco::DataType::FLOAT16:
273 copy_data<loco::DataType::FLOAT16>(buffer, num_elements, const_node);
274 break;
275
276 case loco::DataType::U4:
277 copy_data_4<loco::DataType::U4>(buffer, num_elements, const_node);
278 break;
279
280 case loco::DataType::U8:
281 copy_data<loco::DataType::U8>(buffer, num_elements, const_node);
282 break;
283
284 case loco::DataType::S4:
285 copy_data_4<loco::DataType::S4>(buffer, num_elements, const_node);
286 break;
287
288 case loco::DataType::S8:
289 copy_data<loco::DataType::S8>(buffer, num_elements, const_node);
290 break;
291
292 case loco::DataType::S16:
293 copy_data<loco::DataType::S16>(buffer, num_elements, const_node);
294 break;
295
296 case loco::DataType::S32:
297 copy_data<loco::DataType::S32>(buffer, num_elements, const_node);
298 break;
299
300 case loco::DataType::S64:
301 copy_data<loco::DataType::S64>(buffer, num_elements, const_node);
302 break;
303
304 case loco::DataType::BOOL:
305 copy_data<loco::DataType::BOOL>(buffer, num_elements, const_node);
306 break;
307
308 case loco::DataType::STRING:
309 copy_data<loco::DataType::STRING>(buffer, num_elements, const_node);
310 break;
311
312 default:
313 throw oops::UserExn("Unsupported tensor type",
314 circle::EnumNameTensorType(const_tensor->type()));
315 }
316 }
317
318 return const_node;
319}
Class to build tensor data.
Definition CircleConst.h:35
Wrapper to use flatbuffers::Vector pointer as std::vector entity.
Exception to user.
Definition UserExn.h:42
loco::DataType luci_datatype(circle::TensorType type)
void copy_tensor_attributes(const circle::Tensor *tensor, CircleNode *node)
Copy common tensor attributes such as name, type, etc. to node.
T must_cast(loco::Node *node)
VectorWrapper< T > wrap(const flatbuffers::Vector< T > *vec)
#define LOGGER(name)
#define INFO(name)

References luci::copy_tensor_attributes(), luci::VectorWrapper< T >::empty(), luci::GraphBuilderContext::ext_buffer(), luci::GraphBuilderContext::graph(), INFO, LOGGER, luci::luci_datatype(), luci::must_cast(), luci::GraphBuilderContext::reader(), luci::CircleNode::shape_status(), luci::GraphBuilderContext::tensoroutputs(), luci::CircleReader::tensors(), luci::VALID, and luci::wrap().


The documentation for this class was generated from the following files: