ONE - On-device Neural Engine
Loading...
Searching...
No Matches
circlechef Namespace Reference

Data Structures

class  CircleImport
 Loads TF lite file and provides helpers to access attributes. More...
 
class  CircleOpBatchMatMul
 circlechef operator builder for batchmatmul More...
 
class  CircleOpBCQFullyConnected
 circlechef operator builder for BCQFullyConnected More...
 
class  CircleOpBCQGather
 circlechef operator builder for BCQGather More...
 
class  CircleOpChef
 Interface for each operators to build circlechef. More...
 
class  CircleOpGRU
 circlechef operator builder for GRU More...
 
class  CircleOpInstanceNorm
 circlechef operator builder for INSTANCE_NORM More...
 
class  CircleOpRegistry
 circlechef operator registry More...
 
class  CircleOpRmsNorm
 circlechef operator builder for RMS_NORM More...
 
class  CircleOpRoPE
 circlechef operator builder for RoPE More...
 
class  GeneratedModel
 
class  Logger
 Logger Implementation. More...
 
class  LoggerConfig
 Logger Configuration. More...
 
struct  LoggingContext
 Global logging context. More...
 

Typedefs

using CircleSubGraphs_t = flatbuffers::Vector< flatbuffers::Offset< circle::SubGraph > >
 
using CircleTensors_t = flatbuffers::Vector< flatbuffers::Offset< circle::Tensor > >
 
using CircleBuffers_t = flatbuffers::Vector< flatbuffers::Offset< circle::Buffer > >
 
using CircleOperators_t = flatbuffers::Vector< flatbuffers::Offset< circle::Operator > >
 

Functions

std::unique_ptr< ModelRecipe > generate_recipe (const circle::Model *model)
 Create ModelRecipe from circle::Model.
 
bool write_recipe (const std::string &filename, std::unique_ptr< ModelRecipe > &recipe)
 Write ModelRecipe to file with given name.
 
circlechef::TensorType as_circlechef_type (const circle::TensorType type)
 
circlechef::Activation as_circlechef_activation (const circle::ActivationFunctionType type)
 
circlechef::Padding as_circlechef_padding (const circle::Padding padding)
 
template<typename DT >
std::vector< DT > extract_buffer (const circle::Buffer *buffer)
 extract buffer data to std::vector<DT>
 
template<typename T >
std::vector< T > as_index_vector (const flatbuffers::Vector< T > *flat_array)
 
void set_inputs (CircleImport *import, circlechef::Operation *operation, const circle::Operator *op)
 
void set_outputs (CircleImport *import, circlechef::Operation *operation, const circle::Operator *op)
 
GeneratedModel cook (const ModelRecipe &model_recipe)
 
GeneratedModel cook (const ::circlechef::ModelRecipe &model_recipe)
 Generate a (in-memory) TensorFlow Lite model from a given model recipe.
 

Typedef Documentation

◆ CircleBuffers_t

Definition at line 34 of file CircleImport.h.

◆ CircleOperators_t

Definition at line 35 of file CircleImport.h.

◆ CircleSubGraphs_t

Definition at line 32 of file CircleImport.h.

◆ CircleTensors_t

Definition at line 33 of file CircleImport.h.

Function Documentation

◆ as_circlechef_activation()

circlechef::Activation circlechef::as_circlechef_activation ( const circle::ActivationFunctionType  type)

Definition at line 55 of file Convert.cpp.

56{
57 switch (type)
58 {
59 case circle::ActivationFunctionType_NONE:
60 return circlechef::NONE;
61 case circle::ActivationFunctionType_RELU:
62 return circlechef::RELU;
63 case circle::ActivationFunctionType_RELU6:
64 return circlechef::RELU6;
65 // TODO handle other types
66 // ActivationFunctionType_RELU_N1_TO_1
67 // ActivationFunctionType_TANH
68 // ActivationFunctionType_SIGN_BIT
69 default:
70 throw std::runtime_error{"unsupported activation type"};
71 }
72}

Referenced by circlechef::CircleOpBCQFullyConnected::build(), circlechef::CircleOpGRU::build(), and circlechef::CircleOpInstanceNorm::build().

◆ as_circlechef_padding()

circlechef::Padding circlechef::as_circlechef_padding ( const circle::Padding  padding)

Definition at line 74 of file Convert.cpp.

75{
76 switch (padding)
77 {
78 case circle::Padding_SAME:
79 return circlechef::SAME;
80 case circle::Padding_VALID:
81 return circlechef::VALID;
82 default:
83 throw std::runtime_error{"unsupported padding"};
84 }
85}

◆ as_circlechef_type()

circlechef::TensorType circlechef::as_circlechef_type ( const circle::TensorType  type)

Definition at line 22 of file Convert.cpp.

23{
24 switch (type)
25 {
26 case circle::TensorType_FLOAT32:
27 return circlechef::FLOAT32;
28 case circle::TensorType_INT32:
29 return circlechef::INT32;
30 case circle::TensorType_INT64:
31 return circlechef::INT64;
32 case circle::TensorType_UINT8:
33 return circlechef::UINT8;
34 case circle::TensorType_UINT4:
35 return circlechef::UINT4;
36 case circle::TensorType_BOOL:
37 return circlechef::BOOL;
38 case circle::TensorType_INT16:
39 return circlechef::INT16;
40 case circle::TensorType_INT4:
41 return circlechef::INT4;
42 case circle::TensorType_MXFP4:
43 return circlechef::MXFP4;
44 case circle::TensorType_MXINT8:
45 return circlechef::MXINT8;
46 // TODO handle other types
47 // TensorType_FLOAT16
48 // TensorType_STRING
49 // TensorType_COMPLEX64
50 default:
51 throw std::runtime_error{"unsupported tensor type"};
52 }
53}

Referenced by generate_recipe().

◆ as_index_vector()

template<typename T >
std::vector< T > circlechef::as_index_vector ( const flatbuffers::Vector< T > *  flat_array)

Definition at line 43 of file Convert.h.

44{
45 if (flat_array == nullptr)
46 throw std::runtime_error("flat_array is nullptr");
47
48 std::vector<T> ret(flat_array->size());
49 for (uint32_t i = 0; i < flat_array->size(); i++)
50 {
51 ret[i] = flat_array->Get(i);
52 }
53 return ret;
54}
return_type Get(uoffset_t i) const
uoffset_t size() const

References flatbuffers::Vector< T >::Get(), and flatbuffers::Vector< T >::size().

Referenced by circlechef::CircleOpBCQFullyConnected::filler(), circlechef::CircleOpBCQGather::filler(), circlechef::CircleOpGRU::filler(), circlechef::CircleOpInstanceNorm::filler(), circlechef::CircleOpRmsNorm::filler(), circlechef::CircleOpRoPE::filler(), generate_recipe(), circlechef::CircleImport::select_sub_graph(), set_inputs(), and set_outputs().

◆ cook() [1/2]

GeneratedModel circlechef::cook ( const ::circlechef::ModelRecipe &  model_recipe)

Generate a (in-memory) TensorFlow Lite model from a given model recipe.

Definition at line 529 of file ModelChef.cpp.

530{
531// Initialize Op Chef Registry
532#define OP_CHEF(NAME, FACTORY_CLASS) \
533 op_chef_registry().add(#NAME, std::unique_ptr<FACTORY_CLASS>(new FACTORY_CLASS()));
534#include "OpChef.def"
535#undef OP_CHEF
536
537// Initialize Data Chef Registry
538#define DATA_CHEF(TYPE, NAME, FACTORY_CLASS) \
539 data_chef_registry(::circlechef::TYPE) \
540 .add(#NAME, std::unique_ptr<FACTORY_CLASS>(new FACTORY_CLASS()));
541#include "DataChef.def"
542#undef DATA_CHEF
543
544 //
545 // Create FlatBufferBuilder
546 //
547 auto flatbuffer_builder =
548 std::unique_ptr<flatbuffers::FlatBufferBuilder>(new flatbuffers::FlatBufferBuilder(1024));
549
550 // Operand-related
551 std::vector<flatbuffers::Offset<::circle::Buffer>> buffer_vec;
552
553 // Operation-related
554 std::vector<flatbuffers::Offset<::circle::OperatorCode>> code_vec;
555
556 // Graphs-related
557 std::vector<flatbuffers::Offset<::circle::SubGraph>> subgraph_vec;
558
559 // Create OperatorCode with Builtin Operator
560 std::map<circle::BuiltinOperator, int32_t> builtin_code_map =
561 gather_builtincode_map(model_recipe);
562 for (auto const &opcode : builtin_code_map)
563 {
564 circle::OperatorCodeBuilder code_builder{*flatbuffer_builder};
565 int8_t dep_code = 127; // BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES
566 if (opcode.first < circle::BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES)
567 dep_code = static_cast<int8_t>(opcode.first);
568 code_builder.add_deprecated_builtin_code(dep_code);
569 code_builder.add_builtin_code(opcode.first);
570 code_builder.add_version(opcode.second);
571 auto code = code_builder.Finish();
572 // Update OperatorCode vector
573 code_vec.emplace_back(code);
574 }
575
576 // Create OperatorCode with Custom Operator
577 std::set<std::string> custom_code_set = gather_customcode_set(model_recipe);
578 if (custom_code_set.size() &&
579 builtin_code_map.find(circle::BuiltinOperator_CUSTOM) == builtin_code_map.end())
580 builtin_code_map[circle::BuiltinOperator_CUSTOM] = 1;
581
582 for (auto opcode : custom_code_set)
583 {
584 auto custom_code = flatbuffer_builder->CreateString(opcode);
585 circle::OperatorCodeBuilder code_builder{*flatbuffer_builder};
586 code_builder.add_builtin_code(circle::BuiltinOperator_CUSTOM);
587 code_builder.add_custom_code(custom_code);
588 auto code = code_builder.Finish();
589 // Update OperatorCode vector
590 code_vec.emplace_back(code);
591 }
592
593 // Create an Empty Buffer
594 //
595 // Buffer 0 SHOULD be an empty buffer in TensorFlow Lite model file
596 // (Please refer to the comment for Tensor.buffer field in schema)
597 {
598 circle::BufferBuilder buffer_builder{*flatbuffer_builder};
599 buffer_vec.emplace_back(buffer_builder.Finish());
600 }
601
602 //
603 // Create Main graph
604 //
605 CookParams cp{buffer_vec, code_vec, subgraph_vec, flatbuffer_builder, builtin_code_map, "main"};
606
607 cook_graph<::circlechef::ModelRecipe>(model_recipe, cp);
608
609 //
610 // Create subgraphs if exist
611 //
612 for (int g = 0; g < model_recipe.graph_size(); ++g)
613 {
614 const auto &graph = model_recipe.graph(g);
615
616 std::ostringstream stringStream;
617 stringStream << "sub_" << (g + 1);
618
619 CookParams cp{buffer_vec, code_vec, subgraph_vec,
620 flatbuffer_builder, builtin_code_map, stringStream.str()};
621
622 cook_graph<::circlechef::Graph>(graph, cp);
623 }
624
625 // Create "Model" arguments
626 auto buffers = flatbuffer_builder->CreateVector(buffer_vec);
627 auto operator_codes = flatbuffer_builder->CreateVector(code_vec);
628 auto subgraphs = flatbuffer_builder->CreateVector(subgraph_vec);
629 auto description = flatbuffer_builder->CreateString("Generated by circlechef");
630
631 // Create "Model"
632 circle::ModelBuilder model_builder{*flatbuffer_builder};
633
634 model_builder.add_version(3);
635 model_builder.add_operator_codes(operator_codes);
636 model_builder.add_subgraphs(subgraphs);
637 model_builder.add_description(description);
638 model_builder.add_buffers(buffers);
639
640 auto model = model_builder.Finish();
641
642 // Finalize
643 ::circle::FinishModelBuffer(*flatbuffer_builder, model);
644
645 // Return "GenerateModel"
646 return GeneratedModel{
647 std::unique_ptr<GeneratedModelImpl>(new GeneratedModelImpl(std::move(flatbuffer_builder)))};
648}
Helper class to hold data needed in creation of a FlatBuffer. To serialize data, you typically call o...
Code * code(const SessionID &sess)
Definition Session.cpp:54

◆ cook() [2/2]

GeneratedModel circlechef::cook ( const ModelRecipe &  model_recipe)

Referenced by entry(), and entry_stream().

◆ extract_buffer()

template<typename DT >
std::vector< DT > circlechef::extract_buffer ( const circle::Buffer *  buffer)

extract buffer data to std::vector<DT>

Definition at line 34 of file Convert.h.

35{
36 auto buffer_length = buffer->data()->size();
37 auto num_elements = buffer_length / sizeof(DT);
38 std::vector<DT> result(num_elements);
39 std::memcpy(result.data(), buffer->data()->data(), buffer_length);
40 return result;
41}

◆ generate_recipe()

std::unique_ptr< ModelRecipe > circlechef::generate_recipe ( const circle::Model *  model)

Create ModelRecipe from circle::Model.

This will build ModelRecipe from circle::Model First to check operand filler options by scanning all operators, then translate all operands and operators. Last will set network inputs and outputs.

Definition at line 71 of file RecipeChef.cpp.

72{
73 std::unique_ptr<ModelRecipe> model_recipe{new ModelRecipe()};
74
75 CircleImport circle_import(model);
76
77 assert(circle_import.num_subgraph() == 1);
78 circle_import.select_sub_graph(0);
79
80 auto tensors = circle_import.tensors();
81 auto buffers = circle_import.buffers();
82 auto operators = circle_import.operators();
83
84 // operand fillers for adding all operators
85 for (uint32_t i = 0; i < operators->size(); ++i)
86 {
87 const auto *op = operators->Get(i);
88 circle::BuiltinOperator builtincode = circle_import.builtin_code(op);
89
90 if (const auto *graph_builder = CircleOpRegistry::get().lookup(builtincode))
91 {
92 graph_builder->filler(op, &circle_import, model_recipe.get());
93 }
94 else
95 {
96 std::string opcodename = circle_import.opcode_name(op);
97 throw std::runtime_error{"Not supported: " + opcodename};
98 }
99 }
100
101 // add all operands(tensors)
102 for (uint32_t i = 0; i < tensors->size(); ++i)
103 {
104 auto tensor = tensors->Get(i);
105
106 // check buffer
107 if (tensor->buffer() >= buffers->size())
108 throw std::runtime_error{"file load failed"};
109
110 ::circlechef::Operand *operand = model_recipe->add_operand();
111
112 operand->set_name(mio::circle::tensor_name(tensor));
113 operand->set_type(as_circlechef_type(tensor->type()));
114
115 std::vector<int32_t> dims = as_index_vector(tensor->shape());
116 ::circlechef::TensorShape *shape = operand->mutable_shape();
117 for (auto dim : dims)
118 {
119 shape->add_dim(dim);
120 }
121
122 // filler for weights, bias and so on
123 std::vector<int32_t> expvalues;
124 std::vector<float> expfvalues;
125 if (circle_import.get_tensor_filler(i))
126 {
127 circlechef::TensorFiller *filler = operand->mutable_filler();
128 // Note: it is OK to use random weights for functionality validation
129 filler->set_tag("gaussian");
130 filler->add_arg("0.0"); // average
131 filler->add_arg("0.1"); // standard deviation
132 }
133 else if (circle_import.get_tensor_filler(i, expvalues))
134 {
135 circlechef::TensorFiller *filler = operand->mutable_filler();
136 filler->set_tag("explicit");
137 for (auto value : expvalues)
138 {
139 std::ostringstream ss;
140 ss << value;
141 filler->add_arg(ss.str());
142 }
143 }
144 else if (circle_import.get_tensor_filler(i, expfvalues))
145 {
146 circlechef::TensorFiller *filler = operand->mutable_filler();
147 filler->set_tag("explicit");
148 for (auto value : expfvalues)
149 {
150 std::ostringstream ss;
151 ss << value;
152 filler->add_arg(ss.str());
153 }
154 }
155
156 auto quant = tensor->quantization();
157 if (quant != nullptr)
158 {
159 // Note: Calling 'operand->mutable_quant()' will create empty 'quant' node
160 // in the recipe file. We want this only when valid parameter exist.
161 if (quant->min() != nullptr && quant->min()->size() > 0)
162 {
163 circlechef::TensorQuantization *chef_quant = operand->mutable_quant();
164 for (uint32_t idx = 0; idx < quant->min()->size(); ++idx)
165 chef_quant->add_min(quant->min()->Get(idx));
166 }
167 if (quant->max() != nullptr && quant->max()->size() > 0)
168 {
169 circlechef::TensorQuantization *chef_quant = operand->mutable_quant();
170 for (uint32_t idx = 0; idx < quant->max()->size(); idx++)
171 chef_quant->add_max(quant->max()->Get(idx));
172 }
173 if (quant->scale() != nullptr && quant->scale()->size() > 0)
174 {
175 circlechef::TensorQuantization *chef_quant = operand->mutable_quant();
176 for (uint32_t idx = 0; idx < quant->scale()->size(); ++idx)
177 chef_quant->add_scale(quant->scale()->Get(idx));
178 }
179 if (quant->zero_point() != nullptr && quant->zero_point()->size() > 0)
180 {
181 circlechef::TensorQuantization *chef_quant = operand->mutable_quant();
182 for (uint32_t idx = 0; idx < quant->zero_point()->size(); ++idx)
183 chef_quant->add_zero_point(quant->zero_point()->Get(idx));
184 }
185 circlechef::TensorQuantization *chef_quant = operand->mutable_quant();
186 chef_quant->set_quantized_dimension(quant->quantized_dimension());
187 }
188
189 auto shape_signature = tensor->shape_signature();
190 if (shape_signature != nullptr)
191 {
192 circlechef::ShapeSignature *chef_shape_signature = operand->mutable_shape_signature();
193 for (uint32_t i = 0; i < shape_signature->size(); ++i)
194 {
195 chef_shape_signature->add_dim(shape_signature->Get(i));
196 }
197 }
198 }
199
200 // add all operators
201 for (uint32_t i = 0; i < operators->size(); ++i)
202 {
203 const auto *op = operators->Get(i);
204 circle::BuiltinOperator builtincode = circle_import.builtin_code(op);
205
206 if (const auto *graph_builder = CircleOpRegistry::get().lookup(builtincode))
207 {
208 auto operation = graph_builder->build(op, &circle_import, model_recipe.get());
209
210 // common for all operators: inputs, outputs
211 set_inputs(&circle_import, operation, op);
212 set_outputs(&circle_import, operation, op);
213 }
214 else
215 {
216 std::string opcodename = circle_import.opcode_name(op);
217 throw std::runtime_error{"Not supported: " + opcodename};
218 }
219 }
220
221 // network inputs/outputs
222 const std::vector<int32_t> &inputs = circle_import.inputs();
223 const std::vector<int32_t> &outputs = circle_import.outputs();
224
225 for (const auto input : inputs)
226 {
227 auto tensor = tensors->Get(input);
228 std::string name = mio::circle::tensor_name(tensor);
229
230 model_recipe->add_input(name);
231 }
232 for (const auto output : outputs)
233 {
234 auto tensor = tensors->Get(output);
235 std::string name = mio::circle::tensor_name(tensor);
236
237 model_recipe->add_output(name);
238 }
239
240 return std::move(model_recipe);
241}
std::vector< T > as_index_vector(const flatbuffers::Vector< T > *flat_array)
Definition Convert.h:43
void set_outputs(CircleImport *import, circlechef::Operation *operation, const circle::Operator *op)
void set_inputs(CircleImport *import, circlechef::Operation *operation, const circle::Operator *op)
circlechef::TensorType as_circlechef_type(const circle::TensorType type)
Definition Convert.cpp:22
const char * tensor_name(const ::circle::Tensor *tensor)
Definition Helper.cpp:69
int32_t size[5]
Definition Slice.cpp:35

References as_circlechef_type(), as_index_vector(), circlechef::CircleImport::buffers(), circlechef::CircleImport::builtin_code(), circlechef::CircleOpRegistry::get(), flatbuffers::Vector< T >::Get(), souschef::TensorFiller::get_tensor_filler(), circlechef::CircleImport::inputs(), circlechef::CircleOpRegistry::lookup(), circlechef::CircleImport::num_subgraph(), circlechef::CircleImport::opcode_name(), circlechef::CircleImport::operators(), circlechef::CircleImport::outputs(), circlechef::CircleImport::select_sub_graph(), set_inputs(), set_outputs(), mio::circle::tensor_name(), and circlechef::CircleImport::tensors().

Referenced by entry().

◆ set_inputs()

void circlechef::set_inputs ( CircleImport import,
circlechef::Operation *  operation,
const circle::Operator *  op 
)

Definition at line 32 of file RecipeChef.cpp.

33{
34 auto tensors = import->tensors();
35 const std::vector<int32_t> &inputs = as_index_vector(op->inputs());
36
37 for (auto input : inputs)
38 {
39 if (input == -1)
40 {
41 operation->add_input("");
42 }
43 else
44 {
45 auto tensor = tensors->Get(input);
46 std::string name = mio::circle::tensor_name(tensor);
47 operation->add_input(name);
48 }
49 }
50}

References as_index_vector(), and mio::circle::tensor_name().

Referenced by generate_recipe().

◆ set_outputs()

void circlechef::set_outputs ( CircleImport import,
circlechef::Operation *  operation,
const circle::Operator *  op 
)

Definition at line 52 of file RecipeChef.cpp.

53{
54 auto tensors = import->tensors();
55 const std::vector<int32_t> &outputs = as_index_vector(op->outputs());
56
57 for (auto output : outputs)
58 {
59 auto tensor = tensors->Get(output);
60 std::string name = mio::circle::tensor_name(tensor);
61 operation->add_output(name);
62 }
63}

References as_index_vector(), and mio::circle::tensor_name().

Referenced by generate_recipe().

◆ write_recipe()

bool circlechef::write_recipe ( const std::string &  filename,
std::unique_ptr< ModelRecipe > &  recipe 
)

Write ModelRecipe to file with given name.

Definition at line 243 of file RecipeChef.cpp.

244{
245 std::fstream fo(filename, std::ios::binary | std::ios::out);
246
247 if (!fo.is_open())
248 {
249 throw std::runtime_error{"file store failed"};
250 }
251
252 // Note: SerializeToString() or SerializeToOstream() writes in binary mode
253 // DebugString() and Utf8DebugString() will print as a human readable text
254 fo << recipe->Utf8DebugString();
255
256 fo.close();
257
258 return true;
259}

Referenced by entry().