2 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #ifndef __NNFW_API_TEST_CIRCLE_GEN_H__
18 #define __NNFW_API_TEST_CIRCLE_GEN_H__
20 #include <circle_schema_generated.h>
25 * @brief Class for storing flatbuffer buffer
27 * This is a simple wrapper for a finished FlatBufferBuilder. It owns the buffer and a user can
28 * get the buffer pointer and size.
33 CircleBuffer() = default;
34 explicit CircleBuffer(flatbuffers::FlatBufferBuilder &&fbb) : _fbb{std::move(fbb)}
36 _fbb.Finished(); // The build must have been finished, so check that here
39 uint8_t *buffer() { return _fbb.GetBufferPointer(); }
40 size_t size() { return _fbb.GetSize(); }
43 flatbuffers::FlatBufferBuilder _fbb;
47 * @brief Circle flatbuffer file generator
49 * This is a helper class for generating circle file.
57 std::vector<int32_t> shape;
58 circle::TensorType tensor_type = circle::TensorType::TensorType_FLOAT32;
65 std::vector<int32_t> inputs;
66 std::vector<int32_t> outputs;
73 // 0th buffer is always the empty buffer for non-const tensors
74 addBuffer(nullptr, 0);
77 template <typename T> uint32_t addBuffer(const std::vector<T> &buf_vec)
79 auto buf = reinterpret_cast<const uint8_t *>(buf_vec.data());
80 auto size = buf_vec.size() * sizeof(T);
81 return addBuffer(buf, size);
84 uint32_t addBuffer(const uint8_t *buf, size_t size)
86 uint32_t ind = _buffers.size();
87 _buffers.emplace_back(buildBuffer(buf, size));
91 uint32_t addTensor(const TensorParams ¶ms)
93 int ind = _tensors.size();
94 _tensors.emplace_back(buildTensor(params));
98 uint32_t setInputsAndOutputs(const std::vector<int> &inputs, const std::vector<int> &outputs)
104 CircleBuffer finish()
106 // TODO Support multiple subgraphs, for now only single subgraph model is supported.
107 std::vector<flatbuffers::Offset<circle::SubGraph>> subgraphs{buildSubGraph()};
109 circle::CreateModelDirect(_fbb, 3, &_opcodes, &subgraphs, "CircleGen generated", &_buffers);
111 return CircleBuffer{std::move(_fbb)};
114 // ===== Add Operator methods begin =====
116 uint32_t addOperatorAdd(const OperatorParams ¶ms, circle::ActivationFunctionType actfn)
118 auto options = circle::CreateAddOptions(_fbb, actfn).Union();
119 return addOperatorWithOptions(params, circle::BuiltinOperator_ADD,
120 circle::BuiltinOptions_AddOptions, options);
123 uint32_t addOperatorAveragePool2D(const OperatorParams ¶ms, circle::Padding padding,
124 int stride_w, int stride_h, int filter_w, int filter_h,
125 circle::ActivationFunctionType actfn)
128 circle::CreatePool2DOptions(_fbb, padding, stride_w, stride_h, filter_w, filter_h, actfn)
130 return addOperatorWithOptions(params, circle::BuiltinOperator_AVERAGE_POOL_2D,
131 circle::BuiltinOptions_Pool2DOptions, options);
134 // NOTE Please add addOperator functions ABOVE this lie
136 // % How to add a new addOperatorXXX fuction
137 // 0. Copy code from one of the existing addOperatorXXX function
138 // 1. Change the function signature (need BuiltinOperator params)
139 // 2. Change enum BuiltinOperator
140 // 3. Change enum BuiltinOptions
141 // 4. Change CreateXXXOptions accordingly
143 // ===== Add Operator methods end =====
146 uint32_t addOperatorWithOptions(const OperatorParams ¶ms, circle::BuiltinOperator opcode,
147 circle::BuiltinOptions options_type,
148 flatbuffers::Offset<void> options)
150 uint32_t opcode_ind = addOperatorCode(opcode);
151 auto op = circle::CreateOperatorDirect(_fbb, opcode_ind, ¶ms.inputs, ¶ms.outputs,
152 options_type, options);
154 uint32_t ind = _operators.size();
155 _operators.emplace_back(op);
159 uint32_t addOperatorCode(circle::BuiltinOperator opcode)
161 // TODO If the same OperatorCode is registered already, just return it
162 uint32_t ind = _opcodes.size();
163 _opcodes.emplace_back(circle::CreateOperatorCode(_fbb, opcode));
167 flatbuffers::Offset<circle::Buffer> buildBuffer(const uint8_t *buf, size_t size)
169 if (buf == nullptr && size == 0)
170 return circle::CreateBuffer(_fbb);
171 auto buffer = _fbb.CreateVector(buf, size);
172 return circle::CreateBuffer(_fbb, buffer);
175 flatbuffers::Offset<circle::Tensor> buildTensor(const TensorParams ¶ms)
177 auto shape = _fbb.CreateVector(params.shape);
178 auto name = _fbb.CreateString(params.name);
179 return circle::CreateTensor(_fbb, shape, params.tensor_type, params.buffer, name,
180 0 /* QuantParam */, false /* is_variable */, 0 /* sparsity */,
181 0 /* shape_signature */);
184 flatbuffers::Offset<circle::SubGraph> buildSubGraph()
186 return circle::CreateSubGraphDirect(_fbb, &_tensors, &_inputs, &_outputs, &_operators, nullptr);
190 flatbuffers::FlatBufferBuilder _fbb{1024};
191 std::vector<flatbuffers::Offset<circle::Buffer>> _buffers;
192 std::vector<flatbuffers::Offset<circle::OperatorCode>> _opcodes;
195 std::vector<int> _inputs;
196 std::vector<int> _outputs;
197 std::vector<flatbuffers::Offset<circle::Tensor>> _tensors;
198 std::vector<flatbuffers::Offset<circle::Operator>> _operators;
201 #endif // __NNFW_API_TEST_CIRCLE_GEN_H__