ONE - On-device Neural Engine
Loading...
Searching...
No Matches
Dump.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
33#include "Dump.h"
34
35#include <functional>
36#include <iostream>
37
38std::string tab(int n) { return std::string(n * 2, ' '); }
39
40struct OpPrinter final : public coco::Op::Visitor<void>
41{
42public:
43 OpPrinter(std::ostream &os, int indent) : _os(os), _indent(indent) {}
44
45public:
46 void visit(const coco::Load *op) override
47 {
48 _os << tab(_indent) << "Load(" << dynamic_cast<const coco::Op *>(op)
49 << ", obj: " << op->object() << ")" << std::endl;
50 }
51
52 void visit(const coco::PadF *op) override
53 {
54 op->arg()->accept(this);
55 _os << tab(_indent) << "PadF" << std::endl;
56 }
57
58 void visit(const coco::Conv2D *op) override
59 {
60 op->arg()->accept(this);
61 const coco::Padding2D *pad = op->pad();
62 const coco::Stride2D *stride = op->stride();
63
64 _os << tab(_indent) << "Conv2D(" << dynamic_cast<const coco::Op *>(op)
65 << ", ker obj: " << op->ker() << ", padding [T/B/L/R=" << pad->top() << "," << pad->bottom()
66 << "," << pad->left() << "," << pad->right() << "]"
67 << ", stride [V/H = " << stride->vertical() << "," << stride->horizontal() << "]"
68 << ")" << std::endl;
69 }
70
71 void visit(const coco::MaxPool2D *op) override
72 {
73 op->arg()->accept(this);
74 _os << tab(_indent) << "MaxPool2D" << std::endl;
75 }
76
77 void visit(const coco::AvgPool2D *op) override
78 {
79 op->arg()->accept(this);
80 _os << tab(_indent) << "AvgPool2D" << std::endl;
81 }
82
83 void visit(const coco::Add *op) override
84 {
85 op->left()->accept(this);
86 op->right()->accept(this);
87 _os << tab(_indent) << "Add" << std::endl;
88 }
89
90 void visit(const coco::Mul *op) override
91 {
92 op->left()->accept(this);
93 op->right()->accept(this);
94 _os << tab(_indent) << "Mul" << std::endl;
95 }
96
97 void visit(const coco::ReLU *op) override
98 {
99 op->arg()->accept(this);
100 _os << tab(_indent) << "ReLU" << std::endl;
101 }
102
103 void visit(const coco::ReLU6 *op) override
104 {
105 op->arg()->accept(this);
106 _os << tab(_indent) << "ReLU6" << std::endl;
107 }
108
109 void visit(const coco::Sub *op) override
110 {
111 op->left()->accept(this);
112 op->right()->accept(this);
113 _os << tab(_indent) << "Sub" << std::endl;
114 }
115
116 void visit(const coco::ConcatF *op) override
117 {
118 op->left()->accept(this);
119 op->right()->accept(this);
120 _os << tab(_indent) << "ConcatF" << std::endl;
121 }
122
123 void visit(const coco::Div *op) override
124 {
125 op->left()->accept(this);
126 op->right()->accept(this);
127 _os << tab(_indent) << "Div" << std::endl;
128 }
129
130private:
131 std::ostream &_os;
132
133private:
134 int _indent;
135};
136
137struct InstrPrinter final : public coco::Instr::Visitor<void>
138{
139public:
140 InstrPrinter() = delete;
141
142 InstrPrinter(int indent) : _indent(indent) {}
143
144 void visit(const coco::Eval *ins) override
145 {
146 std::cout << tab(_indent) << "Eval (" << dynamic_cast<const coco::Instr *>(ins) << ")"
147 << std::endl;
148 std::cout << tab(_indent + 1) << "out: " << ins->out() << std::endl;
149 std::cout << tab(_indent + 1) << "<op>: " << std::endl;
150 {
151 OpPrinter prn(std::cout, _indent + 2);
152 ins->op()->accept(prn);
153 }
154 }
155
156 void visit(const coco::Copy *ins) override
157 {
158 // copy is Producer and also Customer. We will use address for Producer
159 std::cout << tab(_indent) << "Copy (" << dynamic_cast<const coco::Instr *>(ins) << ")"
160 << std::endl;
161 std::cout << tab(_indent) << " from: " << ins->from() << std::endl;
162 std::cout << tab(_indent) << " into: " << ins->into() << std::endl;
163 }
164
165 void visit(const coco::Shuffle *ins) override
166 {
167 std::cout << tab(_indent) << "Shuffle (" << dynamic_cast<const coco::Instr *>(ins) << ")"
168 << std::endl;
169 std::cout << tab(_indent) << " from: " << ins->from() << std::endl;
170 std::cout << tab(_indent) << " into: " << ins->into() << std::endl;
171 }
172
173private:
174 int _indent;
175};
176
177void dump(const coco::Op *op, int indent)
178{
179 OpPrinter prn(std::cout, indent);
180 op->accept(prn);
181}
182
183void dump(const coco::Instr *ins, int indent)
184{
185 std::cout << tab(indent) << "<Inst>:" << std::endl;
186
187 static InstrPrinter prn(indent + 1);
188
189 ins->accept(prn);
190}
191
192void dump(const coco::Block *B, int indent)
193{
194 std::cout << tab(indent) << "<Block> (index: " << B->index().value() << ")" << std::endl;
195 for (auto I = B->instr()->head(); I != nullptr; I = I->next())
196 {
197 dump(I, indent + 1);
198 }
199}
200
201void dump(const coco::BlockList *L, int indent)
202{
203 for (auto B = L->head(); B != nullptr; B = B->next())
204 {
205 dump(B, indent);
206 }
207}
208
209template <typename SetT, typename EntityF>
210void dump(std::string header, SetT set, EntityF print_addr_f)
211{
212 std::cout << header << ": [";
213 if (set->size() == 0)
214 std::cout << "x";
215 else
216 {
217 int idx = 0;
218 for (auto entity : *set)
219 {
220 if (idx++ != 0)
221 std::cout << ", ";
222 print_addr_f(entity);
223 }
224 }
225 std::cout << "]";
226}
227
228void dump(const coco::BagManager *l, int indent)
229{
230 std::cout << tab(indent) << "<Bag>:" << std::endl;
231
232 for (auto n = 0; n < l->size(); ++n)
233 {
234 auto bag = l->at(n);
235
236 std::cout << tab(indent + 1) << bag << ", ";
237
238 // print objects in bag->deps()
239 auto print_dep_object = [](coco::Dep *dep) { std::cout << dep->object(); };
240 dump("obj", bag->deps(), print_dep_object);
241 std::cout << ", ";
242
243 std::cout << "size: " << bag->size() << ", ";
244
245 if (bag->isInput())
246 std::cout << "input, ";
247 if (bag->isOutput())
248 std::cout << "output, ";
249 if ((!bag->isInput()) || (!bag->isOutput()))
250 std::cout << "const, ";
251
252 // print readers in bag->reads()
253 auto print_read_reader = [](coco::Read *read) {
254 if (coco::Op *op = dynamic_cast<coco::Op *>(read->reader()))
255 std::cout << "op: " << op;
256 else if (coco::Instr *instr = dynamic_cast<coco::Instr *>(read->reader()))
257 std::cout << "instr: " << instr;
258 else
259 std::cout << "x";
260 };
261 dump("reader", bag->reads(), print_read_reader);
262 std::cout << ", ";
263
264 // print updaters in bag->updates()
265 auto print_update_updater = [](coco::Update *update) {
266 if (coco::Op *op = dynamic_cast<coco::Op *>(update->updater()))
267 std::cout << "op: " << op;
268 else if (coco::Instr *instr = dynamic_cast<coco::Instr *>(update->updater()))
269 std::cout << "instr: " << instr;
270 else
271 std::cout << "x";
272 };
273 dump("updater", bag->updates(), print_update_updater);
274 std::cout << ", ";
275
276 std::cout << std::endl;
277 }
278}
279
280void dump(coco::FeatureObject *feature_ob)
281{
282 auto shape = feature_ob->shape();
283 std::cout << "kind: Feature, Shape [H/W/D=" << shape.height() << "," << shape.width() << ","
284 << shape.depth() << "]";
285}
286
287void dump(coco::KernelObject *kernel_ob)
288{
289 auto shape = kernel_ob->shape();
290 std::cout << "kind: Kernel, Shape [N/H/W/D=" << shape.count() << "," << shape.height() << ","
291 << shape.width() << "," << shape.depth() << "]";
292}
293
294void dump(const coco::ObjectManager *l, int indent)
295{
296 std::cout << tab(indent) << "<Object>:" << std::endl;
297 for (auto n = 0; n < l->size(); ++n)
298 {
299 auto obj = l->at(n);
300 std::cout << tab(indent + 1) << obj << ", bag: " << obj->bag() << ", ";
301
302 using ObDumpers = std::function<void(coco::Object * ob)>;
303
304 std::map<coco::Object::Kind, ObDumpers> ob_dumpers;
305
306 ob_dumpers[coco::Object::Kind::Feature] = [](coco::Object *ob) { dump(ob->asFeature()); };
307 ob_dumpers[coco::Object::Kind::Kernel] = [](coco::Object *ob) { dump(ob->asKernel()); };
308 ob_dumpers[coco::Object::Kind::Unknown] = [](coco::Object *ob) {
309 std::cout << "kind: Unknown";
310 };
311
312 ob_dumpers[obj->kind()](obj);
313
314 std::cout << ", producer: ";
315 auto def = obj->def();
316 if (def)
317 {
318 if (coco::Op *op = dynamic_cast<coco::Op *>(def->producer()))
319 std::cout << "op: " << op;
320 else if (coco::Instr *instr = dynamic_cast<coco::Instr *>(def->producer()))
321 std::cout << "instr: " << instr;
322 else
323 std::cout << "x";
324 }
325 else
326 std::cout << "x";
327 std::cout << ", ";
328
329 // print consumers in obj->uses()
330 auto print_consumer = [](coco::Use *use) {
331 if (coco::Op *op = dynamic_cast<coco::Op *>(use->consumer()))
332 std::cout << "op: " << op;
333 else if (coco::Instr *instr = dynamic_cast<coco::Instr *>(use->consumer()))
334 std::cout << "inst: " << instr;
335 else
336 std::cout << "x";
337 };
338 dump("comsumer", obj->uses(), print_consumer);
339 std::cout << std::endl;
340 }
341}
342
343template <typename T> void head(int indent);
344
345template <> void head<coco::Input>(int indent) { std::cout << tab(indent) << "<Input>: "; }
346
347template <> void head<coco::Output>(int indent) { std::cout << tab(indent) << "<Output>: "; }
348
349template <typename PtrItemT> void dump(const coco::PtrList<PtrItemT> *list, int indent)
350{
351 head<PtrItemT>(indent);
352 for (int n = 0; n < list->size(); n++)
353 {
354 const PtrItemT *item = list->at(n);
355 if (n != 0)
356 std::cout << ", ";
357 std::cout << "bag " << item->bag() << ", name=" << item->name();
358 }
359 std::cout << std::endl;
360}
361
362void dump(const coco::Module *module)
363{
364 std::cout << "<Module>" << std::endl;
365
366 dump(module->block(), 1);
367 dump(module->input(), 1);
368 dump(module->output(), 1);
369 dump(module->entity()->bag(), 1);
370 dump(module->entity()->object(), 1);
371}
Element-wise addition.
Definition Ops.h:287
2D Average Pooling
Definition Ops.h:176
Op * right(void) const
Definition Op.h:236
Op * left(void) const
Definition Op.h:232
A unit of (grouped) instructions.
Definition Block.h:40
InstrList * instr(void)
Definition Block.h:65
const BlockIndex & index(void) const
Definition Block.h:69
uint32_t value(void) const
Definition BlockIndex.h:46
Concatenate two feature maps.
Definition Ops.h:363
2D Convolution over 3D Feature Map with 4D kernel
Definition Ops.h:74
Padding2D * pad(void)
Definition Ops.h:120
KernelObject * ker(void) const
Definition Conv2D.cpp:64
Stride2D * stride(void)
Definition Ops.h:124
Op * arg(uint32_t n) const final
Return N-th argument.
Index-wise element transfer between two objects.
Definition Instrs.h:85
Object * from(void) const
Definition Instrs.h:100
Object * into(void) const
Definition Instrs.h:104
Child * head(void) const
Definition DLinkedList.h:48
A Dep represents the edge between a Bag and its dependent Object.
Definition Dep.h:33
Element-wise division.
Definition Ops.h:344
Evaluate an Object from a given Op.
Definition Instrs.h:43
Op * op(void) const
Definition Instrs.h:59
Object * out(void) const
Definition Instrs.h:55
FeatureMap values (used in CNN)
const FeatureShape & shape(void) const
Base interface on explicit computation steps in coco IR.
Definition Instr.h:57
T accept(IVisitor< T > *v) const
Definition Instr.h:114
Convolution Kernel (in CNN) values.
const nncc::core::ADT::kernel::Shape & shape(void) const
Load an Object.
Definition Ops.h:38
void object(Object *o)
Definition Ops.h:60
2D Max Pooling
Definition Ops.h:142
Top-level element of coco IR which represents a neural network.
Definition Module.h:34
Element-wise multiplication.
Definition Ops.h:325
Base interface on all typed NN values.
Definition Object.h:38
virtual KernelObject * asKernel(void)
Definition Object.h:81
virtual FeatureObject * asFeature(void)
Definition Object.h:78
Introduce padding area.
Definition Ops.h:226
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
T * at(uint32_t n) const
Definition PtrList.h:43
uint32_t size(void) const
Definition PtrList.h:40
Apply ReLU6 over elements.
Definition Ops.h:268
Apply ReLU over elements.
Definition Ops.h:250
A Read represents an edge between a Bag and its Reader.
Definition Read.h:29
Generic element transfer.
Definition Instrs.h:116
Bag * from(void) const
Definition Instrs.h:131
Bag * into(void) const
Definition Instrs.h:135
uint32_t vertical(void) const
Definition Stride2D.h:40
uint32_t horizontal(void) const
Definition Stride2D.h:44
Element-wise subtraction.
Definition Ops.h:306
Op * arg(uint32_t n) const final
Return N-th argument.
A Update represents an edge between a Bag and its Updater.
Definition Update.h:29
uint32_t height(void) const
Definition Shape.h:45
uint32_t count(void) const
Definition Shape.h:44
std::string tab(int n)
Definition Dump.cpp:38
void head< coco::Output >(int indent)
Definition Dump.cpp:347
void head(int indent)
void dump(const coco::Op *op, int indent)
Definition Dump.cpp:177
void head< coco::Input >(int indent)
Definition Dump.cpp:345
void visit(const coco::Eval *ins) override
Definition Dump.cpp:144
void visit(const coco::Copy *ins) override
Definition Dump.cpp:156
InstrPrinter()=delete
InstrPrinter(int indent)
Definition Dump.cpp:142
void visit(const coco::Shuffle *ins) override
Definition Dump.cpp:165
void visit(const coco::Add *op) override
Definition Dump.cpp:83
void visit(const coco::AvgPool2D *op) override
Definition Dump.cpp:77
void visit(const coco::Mul *op) override
Definition Dump.cpp:90
void visit(const coco::PadF *op) override
Definition Dump.cpp:52
void visit(const coco::Conv2D *op) override
Definition Dump.cpp:58
void visit(const coco::MaxPool2D *op) override
Definition Dump.cpp:71
void visit(const coco::ReLU6 *op) override
Definition Dump.cpp:103
void visit(const coco::Sub *op) override
Definition Dump.cpp:109
void visit(const coco::Load *op) override
Definition Dump.cpp:46
OpPrinter(std::ostream &os, int indent)
Definition Dump.cpp:43
void visit(const coco::ReLU *op) override
Definition Dump.cpp:97
void visit(const coco::ConcatF *op) override
Definition Dump.cpp:116
void visit(const coco::Div *op) override
Definition Dump.cpp:123
Base interface on all supported NN operations.
Definition Op.h:45
T accept(IVisitor< T > *v) const
Definition Op.h:101