ONE - On-device Neural Engine
Loading...
Searching...
No Matches
Conv2D.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17#include "Conv2D.h"
18
19#include "Convert.h"
20#include "IRBuilder.h"
21#include "GraphBuilder.h"
22#include "Padding.h"
23#include "Activation.h"
24
25#include <morph/tflite.h>
26#include <coco/IR/Module.h>
29
31#include <schema_generated.h>
32
33#include <cassert>
34
35using namespace nncc::core::ADT;
36using namespace morph::tflite;
37
38namespace tflimport
39{
40
41bool Conv2DGraphBuilder::validate(const tflite::Operator *op) const
42{
43 auto const options = op->builtin_options_as_Conv2DOptions();
44
45 if ((options->stride_h() == 0) || (options->stride_w() == 0))
46 {
47 return false;
48 }
49
50 return true;
51}
52
53void Conv2DGraphBuilder::build(const tflite::Operator *op, GraphBuilderContext *context) const
54{
55 assert(context != nullptr);
56
57 // preparation
58 coco::Module *m = context->m();
59 coco::Data *d = context->d();
60 coco::Block *blk = context->block();
61 TensorContext &tensor_context = context->tensor();
62 TensorBags &bags = context->bags();
63 TflBufferContext &buffer_context = context->buffer();
64 const tflite::SubGraph *graph = context->graph();
65 IndexVector opinputs = as_index_vector(op->inputs());
66 IndexVector opoutputs = as_index_vector(op->outputs());
67
68 // these are fixed in tflite
69 // input index 0 : input feature
70 // input index 1 : kernel
71 // input index 2 : bias (optional)
72 bool hasBias = (opinputs.size() == 3);
73 assert(opinputs.size() == 2 || hasBias);
74 assert(opoutputs.size() == 1);
75
76 int ifm_idx = opinputs.at(0);
77 int ker_idx = opinputs.at(1);
78 int ofm_idx = opoutputs.at(0);
79
80 const tensor::Shape &ifm_shape = tensor_context.shape(ifm_idx);
81 const tensor::Shape &ofm_shape = tensor_context.shape(ofm_idx);
82 const tensor::Shape &ker_shape = tensor_context.shape(ker_idx);
83
84 // Create an input feature map object
85 auto *ifm_obj = m->entity()->object()->create<coco::FeatureObject>();
86 auto *ifm_bag = bags.bag(ifm_idx);
87 ifm_obj->bag(ifm_bag);
88 ifm_obj->layout(coco::FeatureLayouts::BHWC::create(as_feature_shape(ifm_shape)));
89
90 // Create an an output feature map object
91 auto *ofm_obj = m->entity()->object()->create<coco::FeatureObject>();
92 auto *ofm_bag = bags.bag(ofm_idx);
93 ofm_obj->bag(ofm_bag);
94 ofm_obj->layout(coco::FeatureLayouts::BHWC::create(as_feature_shape(ofm_shape)));
95
96 // Create an kernel object
97 auto *ker_obj = m->entity()->object()->create<coco::KernelObject>();
98 auto *ker_bag = bags.bag(ker_idx);
99 ker_obj->bag(ker_bag);
100 ker_obj->layout(coco::KernelLayouts::NHWC::create(as_kernel_shape(ker_shape)));
101
102 // Create a Load op
103 auto load = op_builder(m).load(ifm_obj).pop();
104
105 // Create a Conv2D op
106 auto coco_conv2d = m->entity()->op()->create<coco::Conv2D>();
107
108 // populating Conv2D objects and options such as stride and padding
109 coco_conv2d->ker(ker_obj);
110
111 auto *conv_params = op->builtin_options_as_Conv2DOptions();
112
113 coco_conv2d->stride()->vertical(conv_params->stride_h());
114 coco_conv2d->stride()->horizontal(conv_params->stride_w());
115
116 // conv_params->padding() to left, top, right, bottom
117 coco::Padding2D padding = conv2D_padding(conv_params, ifm_shape, ker_shape);
118
119 coco_conv2d->pad()->top(padding.top());
120 coco_conv2d->pad()->bottom(padding.bottom());
121 coco_conv2d->pad()->left(padding.left());
122 coco_conv2d->pad()->right(padding.right());
123
124 // Link ops
125 coco_conv2d->arg(load);
126
127 // Object to store Conv2D output
128 auto *conv2d_obj = m->entity()->object()->create<coco::FeatureObject>();
129 auto *conv2d_bag = m->entity()->bag()->create(num_elements(ofm_shape));
130 conv2d_obj->bag(conv2d_bag);
131 conv2d_obj->layout(coco::FeatureLayouts::BHWC::create(as_feature_shape(ofm_shape)));
132
133 // Create an Eval instruction for Conv2D
134 auto conv2d_ins = instr_builder(m).eval(conv2d_obj, coco_conv2d);
135
136 // Append the instruction to the block
137 blk->instr()->append(conv2d_ins);
138
139 // Last Object to make a copy to Output Object
140 coco::FeatureObject *last_obj = conv2d_obj;
141
142 if (hasBias)
143 {
144 // When there is a bias, use btmp_obj as bias add output
145 // Bias is adding last_obj with bias weight values
146 auto *btmp_obj = m->entity()->object()->create<coco::FeatureObject>();
147 auto *btmp_bag = m->entity()->bag()->create(num_elements(ofm_shape));
148 btmp_obj->bag(btmp_bag);
149 btmp_obj->layout(coco::FeatureLayouts::BHWC::create(ofm_obj->shape()));
150
151 int bias_idx = opinputs.at(2);
152
153 // Create an object for bias
154 auto bias_obj = m->entity()->object()->create<coco::FeatureObject>();
155 coco::Bag *bias_bag = bags.bag(bias_idx);
156 bias_obj->bag(bias_bag);
157 bias_obj->layout(coco::FeatureLayouts::BC::create(ofm_obj->shape()));
158
159 // Create Op of conv2d output (last_obj) + bias values(bias_obj)
160 auto bias_add = op_builder(m).load(last_obj).load(bias_obj).add().pop();
161
162 // Create Instr as bias add result write to btmp_obj
163 auto bias_add_ins = instr_builder(m).eval(btmp_obj, bias_add);
164
165 // Append the instruction
166 blk->instr()->append(bias_add_ins);
167
168 // Update last_obj to btmp_obj
169 last_obj = btmp_obj;
170 }
171
172 // fused activation
173 coco::FeatureObject *act_output =
174 build_activation(conv_params->fused_activation_function(), blk, last_obj);
175
176 // Create Copy Instr of last_obj to Output Object
177 auto copy_ins = instr_builder(m).copy(ofm_obj, act_output);
178 blk->instr()->append(copy_ins);
179}
180
181} // namespace tflimport
OpBuilder op_builder(coco::Module *m)
Definition IRBuilder.h:144
InstrBuilder instr_builder(coco::Module *m)
Definition IRBuilder.h:174
coco::Copy * copy(coco::Object *into, coco::Object *from) const
Create "Copy" instruction with given two "Object".
Definition IRBuilder.h:161
coco::Eval * eval(coco::Object *out, coco::Op *op) const
Create "Eval" instruction with a given "Object" and "Op".
Definition IRBuilder.h:162
OpBuilder & load(coco::Object *obj)
Create "Load" op and push it onto the internal stack.
Definition IRBuilder.h:70
coco::Op * pop(void)
Pop op from the internal stack.
Definition IRBuilder.h:116
OpBuilder & add(void)
Create "Add" op and push it onto the internal stack.
Definition IRBuilder.h:84
A collection of (abstracted) elements of the same type.
Definition Bag.h:48
A unit of (grouped) instructions.
Definition Block.h:40
InstrList * instr(void)
Definition Block.h:65
2D Convolution over 3D Feature Map with 4D kernel
Definition Ops.h:74
KernelObject * ker(void) const
Definition Conv2D.cpp:64
void append(Child *child)
static std::unique_ptr< BC > create(const nncc::core::ADT::feature::Shape &shape)
static std::unique_ptr< BHWC > create(const nncc::core::ADT::feature::Shape &shape)
FeatureMap values (used in CNN)
static std::unique_ptr< NHWC > create(const nncc::core::ADT::kernel::Shape &shape)
Convolution Kernel (in CNN) values.
Top-level element of coco IR which represents a neural network.
Definition Module.h:34
coco::Bag * bag(void) const
Definition Object.h:74
uint32_t left(void) const
Definition Padding2D.h:49
uint32_t right(void) const
Definition Padding2D.h:53
uint32_t top(void) const
Definition Padding2D.h:41
uint32_t bottom(void) const
Definition Padding2D.h:45
bool validate(const tflite::Operator *op) const override
Definition Conv2D.cpp:41
void build(const tflite::Operator *op, GraphBuilderContext *context) const override
Definition Conv2D.cpp:53
Class to store context to build IR from tflite.
Definition Context.h:133
TensorContext & tensor()
Definition Context.h:152
TflBufferContext & buffer()
Definition Context.h:154
const tflite::SubGraph * graph()
Definition Context.h:155
Pre-creates coco:Bags for each operands(tensors)
Definition TensorBags.h:38
coco::Bag * bag(int32_t tensor_id)
Definition TensorBags.h:52
Extracts and holds operand(tensor) information such as name, shape, and type.
Definition Context.h:39
const tensor::Shape & shape(uint32_t tensor_id)
Definition Context.h:44
Class to read and provide buffer information of tflite.
Definition Context.h:87
nncc::core::ADT::feature::Shape as_feature_shape(const nncc::core::ADT::tensor::Shape &)
Definition tflite.cpp:54
nncc::core::ADT::kernel::Shape as_kernel_shape(const nncc::core::ADT::tensor::Shape &)
Definition tflite.cpp:61
std::vector< int32_t > IndexVector
Definition Convert.h:29
coco::Padding2D conv2D_padding(const tflite::Conv2DOptions *options, const tensor::Shape &ifm_shape, const tensor::Shape &kernel_shape)
Definition Padding.cpp:88
coco::FeatureObject * build_activation(tflite::ActivationFunctionType act, coco::Block *block, coco::FeatureObject *ifm)
Add coco::Eval for fused activation. This method creates an ofm object, appends Eval(ofm object,...
IndexVector as_index_vector(const flatbuffers::Vector< int32_t > *array)
Converts flatbuffers::Vector to IndexVector.
Definition Convert.cpp:28
Core coco entity for constant weights.
Definition Data.h:31