17#include "loader/GraphLoader.h"
29template <
typename NodeT>
Shape getNodeShape(
const NodeT *node)
31 Shape shape(node->rank());
32 for (uint32_t i = 0; i < node->rank(); ++i)
34 shape.dim(i) = node->dim(i).value();
39template <DataType DT>
const void *getNodeDataImpl(
const luci::CircleConst *node,
size_t *data_size)
48 return &node->
at<DT>(0);
55 switch (node->dtype())
58 return getNodeDataImpl<DataType::U4>(node, data_size);
60 return getNodeDataImpl<DataType::U8>(node, data_size);
61 case DataType::FLOAT32:
62 return getNodeDataImpl<DataType::FLOAT32>(node, data_size);
64 return getNodeDataImpl<DataType::S4>(node, data_size);
66 return getNodeDataImpl<DataType::S8>(node, data_size);
68 return getNodeDataImpl<DataType::S16>(node, data_size);
70 return getNodeDataImpl<DataType::S32>(node, data_size);
72 return getNodeDataImpl<DataType::S64>(node, data_size);
74 return getNodeDataImpl<DataType::BOOL>(node, data_size);
76 throw std::runtime_error(
"luci-intp (getNodeData) Unsupported type.");
82 if (node->
custom_code() !=
"CircleReferencingConst")
87 struct ConstDataReference
89 const uint8_t *
data =
nullptr;
94 const auto &const_data_ref = *
reinterpret_cast<const ConstDataReference *
>(custom_options.data());
96 *data_size = const_data_ref.size;
97 return const_data_ref.data;
105 case luci::CircleOpcode::CIRCLECONST:
106 case luci::CircleOpcode::CIRCLEINPUT:
107 case luci::CircleOpcode::CIRCLEOUTPUT:
108 case luci::CircleOpcode::CIRCLEOUTPUTEXCLUDE:
110 case luci::CircleOpcode::CIRCLEBIDIRECTIONAL_SEQUENCE_LSTM_OUT:
111 case luci::CircleOpcode::CIRCLECUSTOMOUT:
112 case luci::CircleOpcode::CIRCLEIFOUT:
113 case luci::CircleOpcode::CIRCLENONMAXSUPPRESSIONV4OUT:
114 case luci::CircleOpcode::CIRCLENONMAXSUPPRESSIONV5OUT:
115 case luci::CircleOpcode::CIRCLESPLITOUT:
116 case luci::CircleOpcode::CIRCLESPLITVOUT:
117 case luci::CircleOpcode::CIRCLETOPKV2OUT:
118 case luci::CircleOpcode::CIRCLEUNIQUEOUT:
119 case luci::CircleOpcode::CIRCLEUNPACKOUT:
120 case luci::CircleOpcode::CIRCLEVARIABLE:
121 case luci::CircleOpcode::CIRCLEWHILEOUT:
124 case luci::CircleOpcode::CUSTOM:
126 auto const custom_node = loco::must_cast<const luci::CircleCustom *>(node);
129 if (custom_node->custom_code() ==
"CircleReferencingConst")
144 case luci::CircleOpcode::CIRCLEOUTPUT:
147 case luci::CircleOpcode::BIDIRECTIONAL_SEQUENCE_LSTM:
148 case luci::CircleOpcode::CUSTOM:
149 case luci::CircleOpcode::IF:
150 case luci::CircleOpcode::NON_MAX_SUPPRESSION_V4:
151 case luci::CircleOpcode::NON_MAX_SUPPRESSION_V5:
152 case luci::CircleOpcode::SPLIT:
153 case luci::CircleOpcode::SPLIT_V:
154 case luci::CircleOpcode::TOPK_V2:
155 case luci::CircleOpcode::UNIQUE:
156 case luci::CircleOpcode::UNPACK:
157 case luci::CircleOpcode::WHILE:
166 const auto custom_node = loco::must_cast<const luci::CircleCustom *>(node);
169 if (custom_node->custom_code() ==
"CircleReferencingConst")
179 const std::unordered_map<const loco::Graph *, RuntimeGraph *> &graph_to_runtime_graph,
180 std::unordered_map<const loco::Node *, Tensor *> &node_to_tensor,
IMemoryManager *memory_manager)
181 : _graph(graph), _runtime_graph(runtime_graph), _runtime_to_ir(runtime_to_ir),
182 _graph_to_runtime_graph(graph_to_runtime_graph), _node_to_tensor(node_to_tensor),
183 _memory_manager(memory_manager)
189 for (uint32_t i = 0; i < _graph->
nodes()->
size(); ++i)
191 const auto *node = loco::must_cast<const luci::CircleNode *>(_graph->
nodes()->
at(i));
193 if (node->
opcode() == luci::CircleOpcode::CUSTOM && !isSupportedCustomNode(node))
195 const auto *cnode = loco::must_cast<const luci::CircleCustom *>(node);
196 throw std::runtime_error(
"Unsupported Custom operator. " + cnode->custom_code() +
" in " +
200 if (!isTensorProducingNode(node))
208 case luci::CircleOpcode::CIRCLECONST:
209 case luci::CircleOpcode::CIRCLECUSTOMOUT:
210 case luci::CircleOpcode::CIRCLEINPUT:
211 case luci::CircleOpcode::CIRCLEVARIABLE:
212 shape = getNodeShape(node);
222 assert(params->
scale.size() == params->
zerop.size());
223 quantization.
scale.assign(params->
scale.cbegin(), params->
scale.cend());
228 auto tensor = std::make_unique<Tensor>(node->dtype(), std::move(shape), std::move(quantization),
236 assert(!execution_plan.offsets().empty());
237 tensor->set_offset(execution_plan.offsets().front());
243 const void *const_data = getNodeData(const_node, &data_size);
244 if (const_data !=
nullptr)
247 tensor->writeData(const_data, data_size);
252 const auto *custom_node =
253 loco::must_cast<const luci::CircleCustom *>(custom_out_node->input());
255 if (custom_node->custom_code() ==
"CircleReferencingConst")
258 const void *const_data = getNodeData(custom_node, &data_size);
259 if (const_data !=
nullptr)
262 tensor->writeData(const_data, data_size);
267 _node_to_tensor.emplace(node, tensor.get());
270 _runtime_graph->
addTensor(std::move(tensor));
277 std::vector<Tensor *> input_tensors(input_nodes.size());
278 for (
size_t i = 0; i < input_nodes.size(); ++i)
280 input_tensors[i] = _node_to_tensor.at(input_nodes[i]);
286 std::vector<Tensor *> output_tensors(output_nodes.size());
287 for (
size_t i = 0; i < output_nodes.size(); ++i)
289 const auto *node = loco::must_cast<const luci::CircleOutput *>(output_nodes[i]);
290 output_tensors[i] = _node_to_tensor.at(node->from());
297 KernelBuilder kernel_builder(_graph_to_runtime_graph, _node_to_tensor);
305 bool has_execution_annotation =
true;
306 auto const checking_exec_plan = [&has_execution_annotation](
auto const node) {
307 const auto *circle_node = loco::must_cast<const luci::CircleNode *>(node);
309 has_execution_annotation =
false;
311 std::for_each(
begin(graph_nodes), end(graph_nodes), checking_exec_plan);
313 if (has_execution_annotation)
316 std::vector<const luci::CircleNode *> ordered_nodes(graph_nodes.size());
318 auto const filler = [&ordered_nodes](
auto const node) {
319 const auto *circle_node = loco::must_cast<const luci::CircleNode *>(node);
321 ordered_nodes.at(position) = circle_node;
323 std::for_each(
begin(graph_nodes), end(graph_nodes), filler);
325 for (
auto node : ordered_nodes)
327 if (isExecutableNode(node))
329 std::unique_ptr<Kernel> kernel = kernel_builder.
build(node);
331 _runtime_graph->
addKernel(std::move(kernel));
341 const auto *node = loco::must_cast<const luci::CircleNode *>(loco_node);
342 if (isExecutableNode(node))
344 std::unique_ptr<Kernel> kernel = kernel_builder.
build(node);
346 _runtime_graph->
addKernel(std::move(kernel));
NodeContext * nodes(void)
Logical unit of computation.
T * at(uint32_t n) const
Access N-th object.
Class to build tensor data.
const loco::DataTypeImpl< DT >::Type & at(uint32_t n) const
uint32_t size(void) const
const std::vector< uint8_t > & custom_options(void) const
const std::string & custom_code(void) const
Virtual CIRCLECUSTOMOUT in Circle.
uint32_t order_in_plan(void) const
void initInputOutputTensors() const
GraphLoader(const loco::Graph *graph, RuntimeGraph *runtime_graph, RuntimeToIR &runtime_to_ir, const std::unordered_map< const loco::Graph *, RuntimeGraph * > &graph_to_runtime_graph, std::unordered_map< const loco::Node *, Tensor * > &node_to_tensor, IMemoryManager *memory_manager)
virtual void allocate_memory(luci_interpreter::Tensor &tensor)=0
std::unique_ptr< Kernel > build(const luci::CircleNode *node)
void addKernel(std::unique_ptr< Kernel > &&kernel)
Tensor * addTensor(std::unique_ptr< Tensor > &&tensor)
void setOutputTensors(const std::vector< Tensor * > &output_tensors)
void setInputTensors(const std::vector< Tensor * > &input_tensors)
std::vector< loco::Node * > postorder_traversal(const std::vector< loco::Node * > &roots)
Generate postorder traversal sequence starting from "roots".
std::set< Node * > all_nodes(Graph *)
Enumerate all the nodes in a given graph.
std::vector< Node * > input_nodes(const Graph *)
std::vector< Node * > output_nodes(Graph *)
size_t getDataTypeSize(DataType data_type)
bool has_execution_plan(const luci::CircleNode *circle_node)
luci::CircleNodeExecutionPlan get_execution_plan(const luci::CircleNode *circle_node)
uint32_t num_elements(const Shape &shape)
The number of elements of a feature map of a given shape.
CircleQuantParam * quantparam(void) const
NodeName name(void) const
virtual CircleOpcode opcode(void) const =0
std::vector< float > scale
int32_t quantized_dimension
std::vector< int64_t > zerop
int32_t quantized_dimension
std::vector< float > scale
std::vector< int32_t > zero_point
std::unordered_map< const Tensor *, const luci::CircleNode * > tensor_to_node
std::unordered_map< const Kernel *, const luci::CircleNode * > kernel_to_node