50struct DataChefRegistry final :
public Registry<DataChefFactory>
54DataChefRegistry &data_chef_registry(
const tflchef::TensorType &
type)
56 static DataChefRegistry s32;
57 static DataChefRegistry s64;
58 static DataChefRegistry fp32;
59 static DataChefRegistry u8;
60 static DataChefRegistry string;
61 static DataChefRegistry boolean;
62 static DataChefRegistry s16;
63 static DataChefRegistry fp16;
64 static DataChefRegistry s8;
65 static DataChefRegistry s4;
73 case tflchef::FLOAT32:
75 case tflchef::FLOAT16:
93 throw std::runtime_error{
"Unknown tensor type"};
96struct OpChefRegistry final :
public Registry<OpChefFactory>
100OpChefRegistry &op_chef_registry(
void)
102 static OpChefRegistry registry;
107std::map<tflite::BuiltinOperator, int32_t>
108gather_builtincode_map(const ::tflchef::ModelRecipe &model_recipe)
111 std::map<tflite::BuiltinOperator, int32_t> builtin_map;
113 for (
const auto &operation : model_recipe.operation())
115 if (operation.type() ==
"Custom")
118 auto op_chef = op_chef_registry().lookup(operation.type()).create(&operation);
120 if (builtin_map.find(op_chef->code()) == builtin_map.end() ||
121 builtin_map[op_chef->code()] < operation.version())
122 builtin_map[op_chef->code()] = operation.version();
126 for (
int g = 0;
g < model_recipe.graph_size(); ++
g)
128 const auto &
graph = model_recipe.graph(g);
129 for (
const auto &operation :
graph.operation())
131 if (operation.type() ==
"Custom")
134 auto op_chef = op_chef_registry().lookup(operation.type()).create(&operation);
136 if (builtin_map.find(op_chef->code()) == builtin_map.end() ||
137 builtin_map[op_chef->code()] < operation.version())
138 builtin_map[op_chef->code()] = operation.version();
146std::set<std::string> gather_customcode_set(const ::tflchef::ModelRecipe &model_recipe)
148 std::set<std::string> customcode_set;
149 for (
const auto &operation : model_recipe.operation())
151 if (operation.type() ==
"Custom")
153 assert(not operation.custom_code().empty());
154 customcode_set.insert(operation.custom_code());
159 for (
int g = 0;
g < model_recipe.graph_size(); ++
g)
161 const auto &
graph = model_recipe.graph(g);
162 for (
const auto &operation :
graph.operation())
164 if (operation.type() ==
"Custom")
166 assert(not operation.custom_code().empty());
167 customcode_set.insert(operation.custom_code());
172 return customcode_set;
180using SymboleTable_t = std::map<std::string, int32_t>;
181using SparsityParams_t = flatbuffers::Offset<tflite::SparsityParameters>;
182using SparsityDims_t = std::vector<sparsity::TfLiteDimensionType>;
183using QuantParams_t = flatbuffers::Offset<tflite::QuantizationParameters>;
188 ModelChef() =
default;
192 void cook(const ::tflchef::ModelRecipe &model_recipe);
195 void prepare_initial_buffer(
void);
196 void gather_operator_codes(const ::tflchef::ModelRecipe &model_recipe);
197 void gather_signature_defs(const ::tflchef::ModelRecipe &model_recipe);
199 void buffer_sparse_f32(int32_t &buffer_index,
DimsI32_t &dims,
200 std::vector<int> &traversal_order_vec, SparsityDims_t &format_vec,
202 void buffer_sparse_f16(int32_t &buffer_index,
DimsI32_t &dims,
203 std::vector<int> &traversal_order_vec, SparsityDims_t &format_vec,
205 void buffer_sparse(int32_t &buffer_index,
const tflchef::Operand &operand,
DimsI32_t &dims,
208 void buffer_dense(int32_t &buffer_index,
const tflchef::Operand &operand, int32_t count,
211 void buffer_empty(int32_t &buffer_index, int32_t buffer_start,
const int size_input,
212 const tflchef::Operand &operand,
const std::vector<std::string> &input_names,
213 const std::vector<std::string> &output_names);
215 void operand_quant(
const tflchef::Operand &operand, QuantParams_t &quant_index);
217 void operand_sparsity(
const tflchef::Operand &operand, SparsityParams_t &sparsity_index);
219 template <
typename T>
void cook_operands(
const T &graph);
221 template <
typename T>
void prepare_tensor_symbols(
const T &graph, SymboleTable_t &symbol_table);
223 template <
typename T>
void cook_operations(
const T &graph, SymboleTable_t &symbol_table);
225 template <
typename T>
void cook_graph(
const T &graph, SymboleTable_t &symbol_table);
227 bool finalize_ext_buffer(
void);
230 const char *get_buffer_pointer(
void)
const;
231 size_t get_size(
void)
const;
234 std::unique_ptr<flatbuffers::FlatBufferBuilder> _flatbuffer_builder;
236 std::vector<flatbuffers::Offset<::tflite::SignatureDef>> _signdef_vec;
237 std::vector<flatbuffers::Offset<::tflite::Buffer>> _buffer_vec;
238 std::vector<flatbuffers::Offset<::tflite::OperatorCode>> _code_vec;
239 std::vector<flatbuffers::Offset<::tflite::SubGraph>> _subgraph_vec;
240 std::map<tflite::BuiltinOperator, int32_t> _builtin_code_map;
241 std::vector<std::string> _custom_code_vec;
244 std::vector<SymboleTable_t> _symbol_tables;
248 std::vector<flatbuffers::Offset<::tflite::Tensor>> _tensor_vec;
250 std::vector<flatbuffers::Offset<::tflite::Operator>> _operator_vec;
252 std::string _graph_name;
255 bool _ext_offset =
false;
256 std::map<int32_t, std::vector<uint8_t>> _buffer_data_map;
257 std::string _ext_data;
260void ModelChef::init(
void)
262 _flatbuffer_builder =
266std::vector<flatbuffers::Offset<tflite::DimensionMetadata>>
268 const std::vector<int> &traversal_order_vec,
const SparsityDims_t &format_vec,
269 const std::vector<std::vector<int32_t>> &dim_metadata_src)
272 std::vector<flatbuffers::Offset<tflite::DimensionMetadata>> dim_metadata_vec(dims_count);
273 for (int32_t i = 0; i < dims_count; i++)
275 const int32_t metadata_idx = 2 * i;
278 auto array_segments =
279 tflite::CreateInt32Vector(*flatbuffer_builder,
280 flatbuffer_builder->
CreateVector(dim_metadata_src[metadata_idx]))
283 tflite::CreateInt32Vector(
284 *flatbuffer_builder, flatbuffer_builder->
CreateVector(dim_metadata_src[metadata_idx + 1]))
286 dim_metadata_vec[i] =
287 tflite::CreateDimensionMetadata(*flatbuffer_builder, tflite::DimensionType_SPARSE_CSR, 0,
288 tflite::SparseIndexVector_Int32Vector, array_segments,
289 tflite::SparseIndexVector_Int32Vector, array_indices);
293 dim_metadata_vec[i] = tflite::CreateDimensionMetadata(
294 *flatbuffer_builder, tflite::DimensionType_DENSE, dim_metadata_src[metadata_idx][0]);
297 return dim_metadata_vec;
300void ModelChef::buffer_sparse_f32(int32_t &buffer_index,
DimsI32_t &dims,
301 std::vector<int> &traversal_order_vec, SparsityDims_t &format_vec,
304 const int32_t dims_count =
dims.size();
307 converter.DenseToSparse(
reinterpret_cast<const float *
>(data_vec.data()));
308 const auto &sparse_data = converter.GetData();
310 std::vector<uint8_t> sparse_uint8;
311 for (
int c = 0; c < sparse_data.size(); ++c)
313 const float value = sparse_data.at(c);
314 const uint8_t *
arr =
reinterpret_cast<const uint8_t *
>(&value);
315 for (uint32_t b = 0;
b <
sizeof(float); ++
b)
317 sparse_uint8.emplace_back(arr[b]);
322 buffer_index = _buffer_vec.size();
323 _buffer_data_map[buffer_index] = sparse_uint8;
325 auto buffer = tflite::CreateBuffer(*_flatbuffer_builder, 0, 1, 1);
326 _buffer_vec.emplace_back(buffer);
330 auto data = _flatbuffer_builder->CreateVector(sparse_uint8);
332 tflite::BufferBuilder buffer_builder{*_flatbuffer_builder};
333 buffer_builder.add_data(data);
334 auto buffer = buffer_builder.Finish();
337 buffer_index = _buffer_vec.size();
338 _buffer_vec.emplace_back(buffer);
342 auto traversal_order = _flatbuffer_builder->CreateVector(traversal_order_vec);
345 std::vector<int> block_map_vec{};
346 auto block_map = _flatbuffer_builder->CreateVector(block_map_vec);
349 const auto &dim_metadata_src = converter.GetDimMetadata();
350 auto dim_metadata_vec = make_dim_metadata_vec(_flatbuffer_builder.get(), dims_count,
351 traversal_order_vec, format_vec, dim_metadata_src);
352 auto dim_metadata = _flatbuffer_builder->CreateVector(dim_metadata_vec);
353 sparsity_index = tflite::CreateSparsityParameters(*_flatbuffer_builder, traversal_order,
354 block_map, dim_metadata);
357void ModelChef::buffer_sparse_f16(int32_t &buffer_index,
DimsI32_t &dims,
358 std::vector<int> &traversal_order_vec, SparsityDims_t &format_vec,
361 const int32_t dims_count =
dims.size();
364 converter.DenseToSparse(
reinterpret_cast<const uint16_t *
>(data_vec.data()));
365 const auto &sparse_data = converter.GetData();
367 std::vector<uint8_t> sparse_uint8;
368 for (
int c = 0; c < sparse_data.size(); ++c)
370 const uint16_t value = sparse_data.at(c);
371 const uint8_t *
arr =
reinterpret_cast<const uint8_t *
>(&value);
372 for (uint32_t b = 0;
b <
sizeof(uint16_t); ++
b)
374 sparse_uint8.emplace_back(arr[b]);
379 buffer_index = _buffer_vec.size();
380 _buffer_data_map[buffer_index] = sparse_uint8;
382 auto buffer = tflite::CreateBuffer(*_flatbuffer_builder, 0, 1, 1);
383 _buffer_vec.emplace_back(buffer);
387 auto data = _flatbuffer_builder->CreateVector(sparse_uint8);
390 tflite::BufferBuilder buffer_builder{*_flatbuffer_builder};
391 buffer_builder.add_data(data);
392 auto buffer = buffer_builder.Finish();
395 buffer_index = _buffer_vec.size();
396 _buffer_vec.emplace_back(buffer);
400 auto traversal_order = _flatbuffer_builder->CreateVector(traversal_order_vec);
403 std::vector<int> block_map_vec{};
404 auto block_map = _flatbuffer_builder->CreateVector(block_map_vec);
407 const auto &dim_metadata_src = converter.GetDimMetadata();
408 auto dim_metadata_vec = make_dim_metadata_vec(_flatbuffer_builder.get(), dims_count,
409 traversal_order_vec, format_vec, dim_metadata_src);
410 auto dim_metadata = _flatbuffer_builder->CreateVector(dim_metadata_vec);
411 sparsity_index = tflite::CreateSparsityParameters(*_flatbuffer_builder, traversal_order,
412 block_map, dim_metadata);
415void ModelChef::buffer_sparse(int32_t &buffer_index,
const tflchef::Operand &operand,
417 SparsityParams_t &sparsity_index)
419 assert(not operand.has_sparsity());
420 assert(operand.has_shape());
421 assert(operand.type() != tflchef::TensorType::INT4);
423 const int32_t dims_count =
dims.size();
424 std::vector<int> traversal_order_vec;
425 SparsityDims_t format_vec;
426 for (int32_t o = 0; o < dims_count; ++o)
427 traversal_order_vec.push_back(o);
428 for (int32_t o = 0; o < dims_count - 1; ++o)
432 if (operand.type() == tflchef::FLOAT32)
434 buffer_sparse_f32(buffer_index, dims, traversal_order_vec, format_vec, data_vec,
437 else if (operand.type() == tflchef::FLOAT16)
439 buffer_sparse_f16(buffer_index, dims, traversal_order_vec, format_vec, data_vec,
444 throw std::runtime_error{
"NYI: unsupported operand type"};
448void ModelChef::buffer_dense(int32_t &buffer_index,
const tflchef::Operand &operand, int32_t count,
452 if (operand.type() == tflchef::TensorType::INT4)
454 uint32_t packed = (count + 1) / 2;
455 std::vector<uint8_t> data_packed(packed);
456 for (uint32_t idx = 0; idx < packed; ++idx)
458 uint32_t sidx = idx * 2;
459 data_packed[idx] = data_vec[sidx++] & 0x0f;
461 data_packed[idx] |= data_vec[sidx] << 4;
463 data_vec = data_packed;
468 buffer_index = _buffer_vec.size();
469 _buffer_data_map[buffer_index] = data_vec;
471 auto buffer = tflite::CreateBuffer(*_flatbuffer_builder, 0, 1, 1);
472 _buffer_vec.emplace_back(buffer);
476 auto data = _flatbuffer_builder->CreateVector(data_vec);
479 tflite::BufferBuilder buffer_builder{*_flatbuffer_builder};
480 buffer_builder.add_data(data);
481 auto buffer = buffer_builder.Finish();
484 buffer_index = _buffer_vec.size();
485 _buffer_vec.emplace_back(buffer);
489void ModelChef::buffer_empty(int32_t &buffer_index, int32_t buffer_start,
const int size_input,
490 const tflchef::Operand &operand,
491 const std::vector<std::string> &input_names,
492 const std::vector<std::string> &output_names)
496 for (
auto it = input_names.begin(); it != input_names.end(); ++it, ++idx)
498 if (*it == operand.name())
500 buffer_index = buffer_start + idx;
504 if (buffer_index == 0)
507 for (
auto it = output_names.begin(); it != output_names.end(); ++it, ++idx)
509 if (*it == operand.name())
511 buffer_index = buffer_start + size_input + idx;
516 if (buffer_index == 0)
519 buffer_index = _buffer_vec.size();
521 tflite::BufferBuilder buffer_builder{*_flatbuffer_builder};
522 _buffer_vec.emplace_back(buffer_builder.Finish());
526void ModelChef::operand_quant(
const tflchef::Operand &operand, QuantParams_t &quant_index)
528 const auto &quant = operand.quant();
532 std::vector<float> quant_max_vec(quant.max_size());
533 std::vector<float> quant_min_vec(quant.min_size());
534 std::vector<float> quant_scale_vec(quant.scale_size());
535 std::vector<int64_t> quant_zero_point_vec(quant.zero_point_size());
537 for (uint32_t i = 0; i < quant.max_size(); ++i)
538 quant_max_vec.at(i) = quant.max(i);
539 for (uint32_t i = 0; i < quant.min_size(); ++i)
540 quant_min_vec.at(i) = quant.min(i);
541 for (uint32_t i = 0; i < quant.scale_size(); ++i)
542 quant_scale_vec.at(i) = quant.scale(i);
543 for (uint32_t i = 0; i < quant.zero_point_size(); ++i)
544 quant_zero_point_vec.at(i) = quant.zero_point(i);
546 auto quant_max = _flatbuffer_builder->CreateVector(quant_max_vec);
547 auto quant_min = _flatbuffer_builder->CreateVector(quant_min_vec);
548 auto quant_scale = _flatbuffer_builder->CreateVector(quant_scale_vec);
549 auto quant_zero_point = _flatbuffer_builder->CreateVector(quant_zero_point_vec);
552 tflite::QuantizationParametersBuilder quant_builder{*_flatbuffer_builder};
553 quant_builder.add_max(quant_max);
554 quant_builder.add_min(quant_min);
555 quant_builder.add_scale(quant_scale);
556 quant_builder.add_zero_point(quant_zero_point);
557 quant_builder.add_quantized_dimension(quant.quantized_dimension());
560 quant_index = quant_builder.Finish();
563void ModelChef::operand_sparsity(
const tflchef::Operand &operand, SparsityParams_t &sparsity_index)
565 const auto &
sparsity = operand.sparsity();
568 std::vector<int> traversal_order_vec{
sparsity.traversal_order().dim().begin(),
569 sparsity.traversal_order().dim().end()};
570 auto traversal_order = _flatbuffer_builder->CreateVector(traversal_order_vec);
573 std::vector<int> block_map_vec{
sparsity.block_map().dim().begin(),
575 auto block_map = _flatbuffer_builder->CreateVector(block_map_vec);
578 std::vector<flatbuffers::Offset<tflite::DimensionMetadata>> dim_metadata_vec;
579 auto recipe_dim_metadata =
sparsity.dim_metadata();
580 for (
const auto &dm : recipe_dim_metadata)
583 auto tflite_array_segments =
587 auto tflite_array_indices =
590 auto tflite_dim_metadata_builder = tflite::DimensionMetadataBuilder{*_flatbuffer_builder};
592 tflite_dim_metadata_builder.add_dense_size(dm.dense_size());
593 tflite_dim_metadata_builder.add_array_segments(tflite_array_segments);
594 tflite_dim_metadata_builder.add_array_segments_type(
596 tflite_dim_metadata_builder.add_array_indices(tflite_array_indices);
597 tflite_dim_metadata_builder.add_array_indices_type(
599 auto tflite_dim_metadata = tflite_dim_metadata_builder.Finish();
600 dim_metadata_vec.emplace_back(tflite_dim_metadata);
602 auto dim_metadata = _flatbuffer_builder->CreateVector(dim_metadata_vec);
604 sparsity_index = tflite::CreateSparsityParameters(*_flatbuffer_builder, traversal_order,
605 block_map, dim_metadata);
608template <
typename T>
void ModelChef::cook_operands(
const T &graph)
610 int32_t buffer_start = _buffer_vec.size();
611 int32_t buffer_index = 0;
614 const auto size_input =
graph.input_size();
615 for (
int ci = 0; ci < size_input; ++ci)
617 tflite::BufferBuilder buffer_builder{*_flatbuffer_builder};
618 _buffer_vec.emplace_back(buffer_builder.Finish());
621 const auto size_output =
graph.output_size();
622 for (
int co = 0; co < size_output; ++co)
624 tflite::BufferBuilder buffer_builder{*_flatbuffer_builder};
625 _buffer_vec.emplace_back(buffer_builder.Finish());
631 for (
const auto &operand :
graph.operand())
633 assert(operand.has_name());
634 assert(operand.has_type());
636 SparsityParams_t sparsity_index;
638 flatbuffers::Offset<flatbuffers::Vector<int32_t>> shape;
640 if (operand.has_shape())
643 shape = _flatbuffer_builder->CreateVector(dims);
646 auto name = _flatbuffer_builder->CreateString(operand.name());
651 if (operand.has_filler())
654 for (
auto it = input_names.begin(); it != input_names.end(); ++it)
656 if (*it == operand.name())
657 throw std::runtime_error{
"Constant '" + *it +
"' cannot be graph I/O"};
659 for (
auto it = output_names.begin(); it != output_names.end(); ++it)
661 if (*it == operand.name())
662 throw std::runtime_error{
"Constant '" + *it +
"' cannot be graph I/O"};
665 const auto &filler = operand.filler();
667 assert(filler.has_tag());
670 auto chef = data_chef_registry(operand.type()).lookup(filler.tag()).create(args);
672 assert(chef !=
nullptr);
676 auto data_vec = chef->generate(count);
678 if (operand.has_make_sparse() && operand.make_sparse())
680 buffer_sparse(buffer_index, operand, dims, data_vec, sparsity_index);
684 buffer_dense(buffer_index, operand, count, data_vec);
689 buffer_empty(buffer_index, buffer_start, size_input, operand, input_names, output_names);
691 assert(buffer_index != 0);
693 QuantParams_t quant_index;
696 if (operand.has_quant())
698 operand_quant(operand, quant_index);
701 if (operand.has_sparsity())
703 operand_sparsity(operand, sparsity_index);
706 flatbuffers::Offset<flatbuffers::Vector<int32_t>> shape_signature;
707 if (operand.has_shape_signature())
709 auto signature =
as_dims(operand.shape_signature());
710 shape_signature = _flatbuffer_builder->CreateVector(signature);
714 tflite::TensorBuilder tensor_builder{*_flatbuffer_builder};
716 tensor_builder.add_shape(shape);
718 tensor_builder.add_buffer(buffer_index);
719 tensor_builder.add_name(name);
720 tensor_builder.add_is_variable(operand.is_variable());
721 if (operand.has_quant())
722 tensor_builder.add_quantization(quant_index);
723 tensor_builder.add_sparsity(sparsity_index);
724 if (operand.has_shape_signature())
725 tensor_builder.add_shape_signature(shape_signature);
728 _tensor_vec.emplace_back(tensor_builder.Finish());
733void ModelChef::prepare_tensor_symbols(
const T &graph, SymboleTable_t &symbol_table)
737 for (
const auto &operand :
graph.operand())
740 int32_t tensor_index = symbol_table.size();
743 INFO(l) <<
"Symbol [" <<
tensor_name <<
"] = Tensor " << tensor_index << std::endl;
749template <
typename T>
void ModelChef::cook_operations(
const T &graph, SymboleTable_t &symbol_table)
751 auto lookup = [&](
const std::string &
name) {
752 if (symbol_table.find(name) != symbol_table.end())
753 return symbol_table.at(name);
758 std::string msg =
"tflchef : input not found in " + _graph_name +
" graph";
759 throw std::runtime_error(msg.c_str());
764 for (
const auto &operation :
graph.operation())
766 assert(operation.has_type());
768 std::string op_type = operation.type();
769 if (not operation.custom_code().empty())
770 op_type = operation.custom_code();
772 auto op_chef = op_chef_registry().lookup(op_type).create(&operation);
775 std::vector<int32_t> input_vec =
as_dataset(operation.input()).map(lookup).vectorize();
776 auto inputs = _flatbuffer_builder->CreateVector(input_vec);
779 std::vector<int32_t> output_vec =
as_dataset(operation.output()).map(lookup).vectorize();
780 auto outputs = _flatbuffer_builder->CreateVector(output_vec);
783 auto options = op_chef->value(*_flatbuffer_builder);
789 tflite::OperatorBuilder
op_builder{*_flatbuffer_builder};
793 uint32_t opcode_index = 0;
794 auto op_it = _builtin_code_map.find(op_chef->code());
796 if (op_it != _builtin_code_map.end())
798 opcode_index = std::distance(_builtin_code_map.begin(), op_it);
803 assert(not operation.custom_code().empty());
804 const auto &custom_code = operation.custom_code();
805 auto op_it = std::find(_custom_code_vec.begin(), _custom_code_vec.end(), custom_code);
806 assert(op_it != _custom_code_vec.end());
807 opcode_index = _builtin_code_map.size();
808 opcode_index += std::distance(_custom_code_vec.begin(), op_it);
814 op_builder.add_builtin_options_type(op_chef->type());
816 op_builder.add_custom_options(circle_custom_options);
817 op_builder.add_custom_options_format(tflite::CustomOptionsFormat_FLEXBUFFERS);
819 _operator_vec.emplace_back(
op_builder.Finish());
823template <
typename T>
void ModelChef::cook_graph(
const T &graph, SymboleTable_t &symbol_table)
827 assert(symbol_table.empty());
828 assert(_tensor_vec.empty());
829 assert(_operator_vec.empty());
832 if (
graph.has_name())
833 _graph_name =
graph.name();
835 auto lookup = [&](
const std::string &
name) {
836 if (symbol_table.find(name) != symbol_table.end())
837 return symbol_table.at(name);
842 std::string msg =
"tflchef : input not found in " + _graph_name +
" graph";
843 throw std::runtime_error(msg.c_str());
847 cook_operands(graph);
849 prepare_tensor_symbols(graph, symbol_table);
851 cook_operations(graph, symbol_table);
854 std::vector<int32_t> input_vec =
as_dataset(
graph.input()).map(lookup).vectorize();
855 std::vector<int32_t> output_vec =
as_dataset(
graph.output()).map(lookup).vectorize();
858 auto tensors = _flatbuffer_builder->CreateVector(_tensor_vec);
859 auto inputs = _flatbuffer_builder->CreateVector(input_vec);
860 auto outputs = _flatbuffer_builder->CreateVector(output_vec);
861 auto operators = _flatbuffer_builder->CreateVector(_operator_vec);
862 auto name = _flatbuffer_builder->CreateString(_graph_name);
864 tflite::SubGraphBuilder subgraph_builder{*_flatbuffer_builder};
866 subgraph_builder.add_tensors(tensors);
867 subgraph_builder.add_inputs(inputs);
868 subgraph_builder.add_outputs(outputs);
869 subgraph_builder.add_operators(operators);
870 subgraph_builder.add_name(name);
872 _subgraph_vec.emplace_back(subgraph_builder.Finish());
875void ModelChef::gather_operator_codes(const ::tflchef::ModelRecipe &model_recipe)
878 _builtin_code_map = gather_builtincode_map(model_recipe);
879 for (
auto const &opcode : _builtin_code_map)
881 tflite::OperatorCodeBuilder code_builder{*_flatbuffer_builder};
886 if (opcode.first < 127)
888 code_builder.add_deprecated_builtin_code(opcode.first);
892 code_builder.add_deprecated_builtin_code(
893 ::tflite::BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES);
895 code_builder.add_version(opcode.second);
896 code_builder.add_builtin_code(opcode.first);
897 auto code = code_builder.Finish();
899 _code_vec.emplace_back(code);
904 std::set<std::string> custom_code_set = gather_customcode_set(model_recipe);
905 std::vector<std::string> custom_code_vec{custom_code_set.begin(), custom_code_set.end()};
906 _custom_code_vec = custom_code_vec;
909 for (
const auto &opcode : _custom_code_vec)
911 auto custom_code = _flatbuffer_builder->CreateString(opcode);
912 tflite::OperatorCodeBuilder code_builder{*_flatbuffer_builder};
913 code_builder.add_deprecated_builtin_code(tflite::BuiltinOperator_CUSTOM);
914 code_builder.add_custom_code(custom_code);
915 code_builder.add_builtin_code(tflite::BuiltinOperator_CUSTOM);
916 auto code = code_builder.Finish();
918 _code_vec.emplace_back(code);
922void ModelChef::prepare_initial_buffer(
void)
928 tflite::BufferBuilder buffer_builder{*_flatbuffer_builder};
929 _buffer_vec.emplace_back(buffer_builder.Finish());
932void ModelChef::gather_signature_defs(const ::tflchef::ModelRecipe &model_recipe)
934 for (
int s = 0;
s < model_recipe.signature_def_size(); ++
s)
937 const auto &rec_signature_def = model_recipe.signature_def(s);
939 std::vector<flatbuffers::Offset<::tflite::TensorMap>> tensormap_inputs;
940 std::vector<flatbuffers::Offset<::tflite::TensorMap>> tensormap_outputs;
943 auto subgraph_index = 0;
944 if (rec_signature_def.has_subgraph_index())
946 subgraph_index = rec_signature_def.subgraph_index();
948 assert(subgraph_index < _symbol_tables.size());
949 auto &symbol_table = _symbol_tables[subgraph_index];
952 for (
int si = 0; si < rec_signature_def.inputs_size(); ++si)
955 const auto &rec_tm_input = rec_signature_def.inputs(si);
956 auto name = _flatbuffer_builder->CreateString(rec_tm_input.name());
957 uint32_t tensor_index = 0;
959 assert(rec_tm_input.has_tensor() || rec_tm_input.has_tensor_index());
960 if (rec_tm_input.has_tensor())
963 const auto &
tensor = rec_tm_input.tensor();
964 tensor_index = symbol_table[
tensor];
969 tensor_index = rec_tm_input.tensor_index();
972 ::tflite::TensorMapBuilder tensormap_builder{*_flatbuffer_builder};
973 tensormap_builder.add_name(name);
974 tensormap_builder.add_tensor_index(tensor_index);
975 tensormap_inputs.push_back(tensormap_builder.Finish());
978 for (
int so = 0; so < rec_signature_def.outputs_size(); ++so)
980 const auto &rec_tm_output = rec_signature_def.outputs(so);
981 auto name = _flatbuffer_builder->CreateString(rec_tm_output.name());
982 uint32_t tensor_index = 0;
983 assert(rec_tm_output.has_tensor() || rec_tm_output.has_tensor_index());
984 if (rec_tm_output.has_tensor())
986 const auto &
tensor = rec_tm_output.tensor();
987 tensor_index = symbol_table[
tensor];
991 tensor_index = rec_tm_output.tensor_index();
994 ::tflite::TensorMapBuilder tensormap_builder{*_flatbuffer_builder};
995 tensormap_builder.add_name(name);
996 tensormap_builder.add_tensor_index(tensor_index);
997 tensormap_outputs.push_back(tensormap_builder.Finish());
1000 auto inputs = _flatbuffer_builder->CreateVector(tensormap_inputs);
1001 auto outputs = _flatbuffer_builder->CreateVector(tensormap_outputs);
1002 auto signature_key = _flatbuffer_builder->CreateString(rec_signature_def.signature_key());
1005 ::tflite::SignatureDefBuilder signature_def_builder{*_flatbuffer_builder};
1006 signature_def_builder.add_inputs(inputs);
1007 signature_def_builder.add_outputs(outputs);
1008 signature_def_builder.add_signature_key(signature_key);
1009 signature_def_builder.add_subgraph_index(rec_signature_def.subgraph_index());
1011 _signdef_vec.emplace_back(signature_def_builder.Finish());
1015bool ModelChef::finalize_ext_buffer(
void)
1020 auto align16 = [](
size_t &v) {
1026 size_t result_size = _flatbuffer_builder->GetSize();
1027 align16(result_size);
1028 for (
auto &it : _buffer_data_map)
1030 std::vector<uint8_t> &buffer_data = it.second;
1031 result_size += buffer_data.size();
1032 align16(result_size);
1034 align16(result_size);
1038 auto *buff_ptr =
reinterpret_cast<const char *
>(_flatbuffer_builder->GetBufferPointer());
1040 auto padalign16 = [](std::string &
str) {
1041 while (
str.size() % 16 != 0)
1045 result.reserve(result_size);
1046 result.append(buff_ptr, _flatbuffer_builder->GetSize());
1048 auto mutable_model = tflite::GetMutableModel(
result.data());
1049 auto mutable_buffers = mutable_model->mutable_buffers();
1053 for (
auto &it : _buffer_data_map)
1055 int32_t buffer_index = it.first;
1056 std::vector<uint8_t> &buffer_data = it.second;
1058 uint64_t
size = buffer_data.size();
1060 tflite::Buffer *mutable_buffer = mutable_buffers->GetMutableObject(buffer_index);
1061 ret &= mutable_buffer->mutate_offset(
offset);
1062 ret &= mutable_buffer->mutate_size(
size);
1064 result.append(buffer_data.begin(), buffer_data.end());
1075void ModelChef::cook(const ::tflchef::ModelRecipe &model_recipe)
1078 _ext_offset = model_recipe.has_ext_offset() ? model_recipe.ext_offset() :
false;
1080 prepare_initial_buffer();
1082 gather_operator_codes(model_recipe);
1088 _graph_name =
"main";
1090 SymboleTable_t symbol_table;
1091 cook_graph<::tflchef::ModelRecipe>(model_recipe, symbol_table);
1092 _symbol_tables.push_back(symbol_table);
1097 for (
int g = 0;
g < model_recipe.graph_size(); ++
g)
1099 const auto &
graph = model_recipe.graph(g);
1101 std::ostringstream stringStream;
1102 stringStream <<
"sub_" << (
g + 1);
1104 _graph_name = stringStream.str();
1106 symbol_table.clear();
1107 _tensor_vec.clear();
1108 _operator_vec.clear();
1109 cook_graph<::tflchef::Graph>(graph, symbol_table);
1110 _symbol_tables.push_back(symbol_table);
1113 gather_signature_defs(model_recipe);
1116 auto buffers = _flatbuffer_builder->CreateVector(_buffer_vec);
1117 auto signdefs = _flatbuffer_builder->CreateVector(_signdef_vec);
1118 auto operator_codes = _flatbuffer_builder->CreateVector(_code_vec);
1119 auto subgraphs = _flatbuffer_builder->CreateVector(_subgraph_vec);
1120 auto description = _flatbuffer_builder->CreateString(
"Generated by tflchef");
1123 tflite::ModelBuilder model_builder{*_flatbuffer_builder};
1125 model_builder.add_version(3);
1126 model_builder.add_operator_codes(operator_codes);
1127 model_builder.add_signature_defs(signdefs);
1128 model_builder.add_subgraphs(subgraphs);
1129 model_builder.add_description(description);
1130 model_builder.add_buffers(buffers);
1132 auto model = model_builder.Finish();
1135 ::tflite::FinishModelBuffer(*_flatbuffer_builder, model);
1138 finalize_ext_buffer();
1141const char *ModelChef::get_buffer_pointer(
void)
const
1144 return _ext_data.data();
1145 return reinterpret_cast<const char *
>(_flatbuffer_builder->GetBufferPointer());
1148size_t ModelChef::get_size(
void)
const
1151 return _ext_data.size();
1152 return _flatbuffer_builder->GetSize();
1163 GeneratedModelImpl()
1169 const char *
base(
void)
const override {
return _mc.get_buffer_pointer(); }
1171 size_t size(
void)
const override {
return _mc.get_size(); }
1174 ModelChef &model_chef(
void) {
return _mc; }
1188GeneratedModel
cook(const ::tflchef::ModelRecipe &model_recipe)
1191#define OP_CHEF(NAME, FACTORY_CLASS) \
1192 op_chef_registry().add(#NAME, std::unique_ptr<FACTORY_CLASS>(new FACTORY_CLASS()));
1193#include "OpChef.def"
1197#define DATA_CHEF(TYPE, NAME, FACTORY_CLASS) \
1198 data_chef_registry(::tflchef::TYPE) \
1199 .add(#NAME, std::unique_ptr<FACTORY_CLASS>(new FACTORY_CLASS()));
1200#include "DataChef.def"
1203 std::unique_ptr<GeneratedModelImpl> gen_model(
new GeneratedModelImpl());
1205 ModelChef &mc = gen_model->model_chef();
1208 mc.cook(model_recipe);
1211 return GeneratedModel{std::move(gen_model)};
OpBuilder op_builder(coco::Module *m)
OffsetT< VectorT< T > > CreateVector(const T *v, size_t len)
Serialize an array into a FlatBuffer vector.
__global uchar * offset(const Image *img, int x, int y)
GeneratedModel cook(const ModelRecipe &model_recipe)
Code * code(const SessionID &sess)
std::vector< int > dims(const std::string &src)
flatbuffers::Offset< flatbuffers::Vector< uint8_t > > circle_custom_options(flatbuffers::FlatBufferBuilder &fb, const luci::CircleNode *node)
const char * tensor_name(const circle::Tensor *tensor)
This file provides string <-> number cast helpers.
Dataset< T > as_dataset(const ::google::protobuf::RepeatedPtrField< T > &field)
RangedArguments< InputIt > ranged_arguments(InputIt beg, InputIt end)
DimsI32_t as_dims(const SHAPETYPE &shape)
std::vector< uint8_t > Data
int32_t element_count(const DimsI32_t &dims)
Dims< int32_t > DimsI32_t
GeneratedModel cook(const ModelRecipe &model_recipe)
virtual size_t size(void) const =0
virtual const char * base(void) const =0
tflite::DimensionType as_tflite_dimensiontype(const tflchef::DimensionType &value)
tflite::SparseIndexVector as_tflite_sparse_idx_vec_type(const tflchef::SparseIndexVecType &value)
flatbuffers::Offset< void > as_tflite_sparse_index_vec(flatbuffers::FlatBufferBuilder &fb, const ::tflchef::TensorSparsity_IndexVec &value)
tflite::TensorType as_tflite_tensortype(const tflchef::TensorType &value)