104{
105 assert(context != nullptr);
106
110 TensorContext &tensor_context = context->tensor();
111 TensorBags &bags = context->bags();
114
115
116
117
118 assert(opinputs.size() > 0);
119 assert(opoutputs.size() == 1);
120
121
122 int32_t concat_axis = 0;
123 tflite::ActivationFunctionType activation = tflite::ActivationFunctionType_NONE;
124
125 if (auto *concatenation_params = op->builtin_options_as_ConcatenationOptions())
126 {
127 activation = concatenation_params->fused_activation_function();
128 concat_axis = concatenation_params->axis();
129
130 const int32_t rank = static_cast<int32_t>(tensor_context.shape(opinputs.at(0)).rank());
131 if (concat_axis < 0)
132 {
133 concat_axis += rank;
134 }
135 assert(concat_axis >= 0);
136 assert(concat_axis < rank);
137 }
139 assert(activation == tflite::ActivationFunctionType_NONE);
140
141
142 std::vector<coco::FeatureObject *> input_objects;
143
144 for (auto &input_index : opinputs)
145 {
146 const tensor::Shape &input_shape = tensor_context.shape(input_index);
148 coco::Bag *input_bag = bags.bag(input_index);
149 input_obj->
bag(input_bag);
151
152 input_objects.emplace_back(input_obj);
153 }
154
156
157 assert(last_feature != nullptr);
158 assert(last_feature->
bag() !=
nullptr);
159
160
161
162
163
164
165
166
167
168
169
170
171
172 for (uint32_t n = 1; n < input_objects.size(); ++n)
173 {
174 auto const left_feature = last_feature;
175 auto const left_shape = left_feature->
layout()->
shape();
176
177 auto right_feature = input_objects.at(n);
178 auto right_shape = right_feature->layout()->shape();
179
180
181 auto compute_out_dims = [&left_shape, &right_shape, concat_axis](void) {
182 std::array<uint32_t, 4> out_dims;
183
184 const auto left_dims =
as_dims(left_shape);
185 const auto right_dims =
as_dims(right_shape);
186
187 for (uint32_t axis = 0; axis < 4 ; ++axis)
188 {
189
190 assert((concat_axis == axis) || (left_dims[axis] == right_dims[axis]));
191
192 out_dims[axis] = left_dims[axis];
193 if (axis == concat_axis)
194 {
195 out_dims[axis] += right_dims[axis];
196 }
197 }
198
199 return out_dims;
200 };
201
202 const auto out_dims = compute_out_dims();
203
204 const uint32_t B = out_dims[0 ];
205 const uint32_t
C = out_dims[3 ];
206 const uint32_t H = out_dims[1 ];
207 const uint32_t W = out_dims[2 ];
208
210
211 auto out_bag =
m->entity()->bag()->create(B *
num_elements(out_shape));
213
214 out_feature->
bag(out_bag);
216
219
221
222 concat_f->
axis(as_ConcatF_axis(concat_axis));
223 concat_f->left(left_load);
224 concat_f->right(right_load);
225
227
228
230
231
232 last_feature = out_feature;
233 }
234
235
236 int const ofm_idx = opoutputs.at(0);
237 auto const ofm_shape = tensor_context.
shape(ofm_idx);
238
239 auto ofm_bag = bags.bag(ofm_idx);
241
242 ofm_obj->
bag(ofm_bag);
244
245
247
248
250}
OpBuilder op_builder(coco::Module *m)
InstrBuilder instr_builder(coco::Module *m)
coco::Copy * copy(coco::Object *into, coco::Object *from) const
Create "Copy" instruction with given two "Object".
coco::Eval * eval(coco::Object *out, coco::Op *op) const
Create "Eval" instruction with a given "Object" and "Op".
OpBuilder & load(coco::Object *obj)
Create "Load" op and push it onto the internal stack.
coco::Op * pop(void)
Pop op from the internal stack.
A collection of (abstracted) elements of the same type.
A unit of (grouped) instructions.
Concatenate two feature maps.
const Axis & axis(void) const
void append(Child *child)
static std::unique_ptr< BHWC > create(const nncc::core::ADT::feature::Shape &shape)
FeatureMap values (used in CNN)
const FeatureShape & shape(void) const
const FeatureLayout * layout(void) const
The shape of a feature map.
Top-level element of coco IR which represents a neural network.
coco::Bag * bag(void) const
loco::FeatureShape as_feature_shape(const loco::NodeShape &nodeshape, const TFDataLayout &data_layout)
Dims< uint32_t > as_dims(const nncc::core::ADT::tensor::Shape &)
uint32_t num_elements(const Shape &shape)
The number of elements of a feature map of a given shape.
std::vector< int32_t > IndexVector
IndexVector as_index_vector(const flatbuffers::Vector< int32_t > *array)
Converts flatbuffers::Vector to IndexVector.
Core coco entity for constant weights.
virtual const FeatureShape & shape(void) const =0