Imported Upstream version 1.7.0
[platform/core/ml/nnfw.git] / compiler / loco / src / Service / GraphTestcase.h
1 /*
2  * Copyright (c) 2019 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 #ifndef __GRAPH_TESTCASE_H__
18 #define __GRAPH_TESTCASE_H__
19
20 #include "loco/IR/Graph.h"
21 #include "loco/IR/PermutingCodec.h"
22
23 #include "GraphBuilder.h"
24
25 #include <stdex/Memory.h>
26
27 enum class GraphCode
28 {
29   Identity,
30   ConstGen,
31   Relu,
32   FeatureCodec,
33   AvgPool2D,
34   DepthwiseConv2D,
35   TransposedConv2D,
36   MaxPool2D,
37   TensorBroadcast,
38   TensorConcat,
39   TensorTranspose,
40   FixedReshape,
41 };
42
43 namespace
44 {
45
46 template <loco::Domain D> loco::Permutation<D> make_NHWC_perm(void);
47
48 template <> loco::Permutation<loco::Domain::Feature> make_NHWC_perm(void)
49 {
50   loco::Permutation<loco::Domain::Feature> perm;
51
52   perm[loco::FeatureAxis::Count] = 0;
53   perm[loco::FeatureAxis::Height] = 1;
54   perm[loco::FeatureAxis::Width] = 2;
55   perm[loco::FeatureAxis::Depth] = 3;
56
57   return perm;
58 }
59
60 template <loco::Domain D> loco::Permutation<D> make_HWCN_perm(void);
61
62 /// @note  Also known as HWIO permutation
63 template <> loco::Permutation<loco::Domain::Filter> make_HWCN_perm(void)
64 {
65   loco::Permutation<loco::Domain::Filter> perm;
66
67   perm[loco::FilterAxis::Height] = 0;
68   perm[loco::FilterAxis::Width] = 1;
69   perm[loco::FilterAxis::Depth] = 2;
70   perm[loco::FilterAxis::Count] = 3;
71
72   return perm;
73 }
74
75 template <loco::Domain D> loco::Permutation<D> make_HWCM_perm(void);
76
77 template <> loco::Permutation<loco::Domain::DepthwiseFilter> make_HWCM_perm(void)
78 {
79   loco::Permutation<loco::Domain::DepthwiseFilter> perm;
80
81   perm[loco::DepthwiseFilterAxis::Height] = 0;
82   perm[loco::DepthwiseFilterAxis::Width] = 1;
83   perm[loco::DepthwiseFilterAxis::Depth] = 2;
84   perm[loco::DepthwiseFilterAxis::Multiplier] = 3;
85
86   return perm;
87 }
88
89 } // namespace
90
91 template <GraphCode Code> class GraphTestcase;
92
93 template <> class GraphTestcase<GraphCode::Identity> final
94 {
95 private:
96   void init(std::initializer_list<uint32_t> dims)
97   {
98     // Create a sample network
99     _graph = loco::make_graph();
100
101     auto graph_builder = make_graph_builder(_graph.get());
102
103     pull_node = graph_builder->push<InputLayer>()->name("input")->shape(dims)->node();
104     push_node = graph_builder->push<OutputLayer>()->name("output")->node();
105   }
106
107 public:
108   // NOTE This default constructor guarantees backward compatbility.
109   GraphTestcase() { init({1, 4, 8, 3}); }
110   GraphTestcase(std::initializer_list<uint32_t> dims) { init(dims); }
111
112 public:
113   loco::Graph *graph() { return _graph.get(); }
114
115   loco::Pull *pull_node = nullptr;
116   loco::Push *push_node = nullptr;
117
118 private:
119   std::unique_ptr<loco::Graph> _graph;
120 };
121
122 template <> class GraphTestcase<GraphCode::ConstGen> final
123 {
124 public:
125   GraphTestcase()
126   {
127     _graph = loco::make_graph();
128
129     auto graph_builder = make_graph_builder(_graph.get());
130
131     const_node = graph_builder->push<ConstGenLayer>()->node();
132
133     push_node = graph_builder->push<OutputLayer>()->name("output")->node();
134   }
135
136 public:
137   loco::Graph *graph() { return _graph.get(); }
138
139   loco::ConstGen *const_node = nullptr;
140   loco::Push *push_node = nullptr;
141
142 private:
143   std::unique_ptr<loco::Graph> _graph;
144 };
145
146 template <> class GraphTestcase<GraphCode::Relu> final
147 {
148 public:
149   GraphTestcase()
150   {
151     // Create a sample network
152     _graph = loco::make_graph();
153
154     auto graph_builder = make_graph_builder(_graph.get());
155
156     pull_node = graph_builder->push<InputLayer>()->name("input")->node();
157     relu_node = graph_builder->push<ReLULayer>()->node();
158     push_node = graph_builder->push<OutputLayer>()->name("output")->node();
159   }
160
161 public:
162   loco::Graph *graph() { return _graph.get(); }
163
164   loco::Pull *pull_node = nullptr;
165   loco::ReLU *relu_node = nullptr;
166   loco::Push *push_node = nullptr;
167
168 private:
169   std::unique_ptr<loco::Graph> _graph;
170 };
171
172 template <> class GraphTestcase<GraphCode::FeatureCodec> final
173 {
174 public:
175   GraphTestcase()
176   {
177     using namespace loco;
178
179     Permutation<Domain::Feature> perm;
180
181     perm[FeatureAxis::Count] = 0;
182     perm[FeatureAxis::Height] = 1;
183     perm[FeatureAxis::Width] = 2;
184     perm[FeatureAxis::Depth] = 3;
185
186     // Create a sample network
187     _graph = make_graph();
188
189     auto graph_builder = make_graph_builder(_graph.get());
190
191     pull_node = graph_builder->push<InputLayer>()->name("input")->node();
192     encode_node = graph_builder->push<FeatureEncodeLayer>()->perm(perm)->node();
193     decode_node = graph_builder->push<FeatureDecodeLayer>()->perm(perm)->node();
194     push_node = graph_builder->push<OutputLayer>()->name("output")->node();
195   }
196
197 public:
198   loco::Graph *graph() { return _graph.get(); }
199
200   loco::Pull *pull_node = nullptr;
201   loco::FeatureEncode *encode_node = nullptr;
202   loco::FeatureDecode *decode_node = nullptr;
203   loco::Push *push_node = nullptr;
204
205 private:
206   std::unique_ptr<loco::Graph> _graph;
207 };
208
209 template <> class GraphTestcase<GraphCode::AvgPool2D> final
210 {
211 public:
212   GraphTestcase()
213   {
214     using namespace loco;
215
216     // Create a sample network
217     _graph = make_graph();
218
219     // Create Graph Input/Output
220     auto graph_input = _graph->inputs()->create();
221     auto graph_output = _graph->outputs()->create();
222
223     graph_input->name("input");
224     graph_output->name("output");
225
226     // Create and connect nodes
227     pull_node = _graph->nodes()->create<Pull>();
228     pull_node->index(0);
229
230     encode_node = _graph->nodes()->create<FeatureEncode>();
231     encode_node->input(pull_node);
232
233     avgpool2d_node = _graph->nodes()->create<AvgPool2D>();
234     avgpool2d_node->ifm(encode_node);
235
236     decode_node = _graph->nodes()->create<FeatureDecode>();
237     decode_node->input(avgpool2d_node);
238
239     push_node = _graph->nodes()->create<loco::Push>();
240     push_node->index(0);
241     push_node->from(decode_node);
242
243     // Create a link between input/output and corresponding nodes
244     loco::link(graph_input, pull_node);
245     loco::link(graph_output, push_node);
246   }
247
248 public:
249   loco::Graph *graph() { return _graph.get(); }
250
251   loco::Pull *pull_node = nullptr;
252   loco::FeatureEncode *encode_node = nullptr;
253   loco::AvgPool2D *avgpool2d_node = nullptr;
254   loco::FeatureDecode *decode_node = nullptr;
255   loco::Push *push_node = nullptr;
256
257 private:
258   std::unique_ptr<loco::Graph> _graph;
259 };
260
261 template <> class GraphTestcase<GraphCode::DepthwiseConv2D> final
262 {
263 public:
264   GraphTestcase()
265   {
266     using namespace loco;
267
268     _graph = make_graph();
269
270     auto graph_builder = make_graph_builder(_graph.get());
271
272     Permutation<Domain::Feature> perm = make_NHWC_perm<Domain::Feature>();
273     Permutation<Domain::DepthwiseFilter> filter_perm = make_HWCM_perm<Domain::DepthwiseFilter>();
274
275     pull_node = graph_builder->push<InputLayer>()->name("input")->node();
276     encode_node = graph_builder->push<FeatureEncodeLayer>()->perm(perm)->node();
277
278     const_node = graph_builder->push<ConstGenLayer>()->node();
279
280     filter_encode_node =
281         graph_builder->push<DepthwiseFilterEncodeLayer>()->perm(filter_perm)->node();
282
283     depthwiseconv2d_node = graph_builder->push<DepthwiseConv2DLayer>()->node();
284
285     decode_node = graph_builder->push<FeatureDecodeLayer>()->perm(perm)->node();
286     push_node = graph_builder->push<OutputLayer>()->name("output")->node();
287   }
288
289 public:
290   loco::Graph *graph() { return _graph.get(); }
291
292   loco::Pull *pull_node = nullptr;
293   loco::FeatureEncode *encode_node = nullptr;
294   loco::ConstGen *const_node = nullptr;
295   loco::DepthwiseFilterEncode *filter_encode_node = nullptr;
296   loco::DepthwiseConv2D *depthwiseconv2d_node = nullptr;
297   loco::FeatureDecode *decode_node = nullptr;
298   loco::Push *push_node = nullptr;
299
300 private:
301   std::unique_ptr<loco::Graph> _graph;
302 };
303
304 template <> class GraphTestcase<GraphCode::TransposedConv2D> final
305 {
306 public:
307   GraphTestcase()
308   {
309     using namespace loco;
310
311     // Prepare permutations
312     Permutation<Domain::Feature> feature_perm = make_NHWC_perm<Domain::Feature>();
313     Permutation<Domain::Filter> filter_perm = make_HWCN_perm<Domain::Filter>();
314
315     // Build graph
316     _graph = make_graph();
317     auto graph_builder = make_graph_builder(_graph.get());
318
319     pull_node = graph_builder->push<InputLayer>()->name("input")->node();
320     encode_node = graph_builder->push<FeatureEncodeLayer>()->perm(feature_perm)->node();
321     const_node = graph_builder->push<ConstGenLayer>()->node();
322     filter_encode_node = graph_builder->push<FilterEncodeLayer>()->perm(filter_perm)->node();
323     tr_conv2d_node = graph_builder->push<TransposedConv2DLayer>()->node();
324     decode_node = graph_builder->push<FeatureDecodeLayer>()->perm(feature_perm)->node();
325     push_node = graph_builder->push<OutputLayer>()->name("output")->node();
326   }
327
328 public:
329   loco::Graph *graph() { return _graph.get(); }
330
331   loco::Pull *pull_node = nullptr;
332   loco::FeatureEncode *encode_node = nullptr;
333   loco::ConstGen *const_node = nullptr;
334   loco::FilterEncode *filter_encode_node = nullptr;
335   loco::TransposedConv2D *tr_conv2d_node = nullptr;
336   loco::FeatureDecode *decode_node = nullptr;
337   loco::Push *push_node = nullptr;
338
339 private:
340   std::unique_ptr<loco::Graph> _graph;
341 };
342
343 template <> class GraphTestcase<GraphCode::MaxPool2D> final
344 {
345 public:
346   GraphTestcase()
347   {
348     using namespace loco;
349
350     // Create a sample network
351     _graph = make_graph();
352
353     // Create Graph Input/Output
354     auto graph_input = _graph->inputs()->create();
355     auto graph_output = _graph->outputs()->create();
356
357     graph_input->name("input");
358     graph_output->name("output");
359
360     // Create and connect nodes
361     pull_node = _graph->nodes()->create<Pull>();
362     pull_node->index(0);
363
364     encode_node = _graph->nodes()->create<FeatureEncode>();
365     encode_node->input(pull_node);
366
367     maxpool2d_node = _graph->nodes()->create<MaxPool2D>();
368     maxpool2d_node->ifm(encode_node);
369
370     decode_node = _graph->nodes()->create<FeatureDecode>();
371     decode_node->input(maxpool2d_node);
372
373     push_node = _graph->nodes()->create<loco::Push>();
374     push_node->index(0);
375     push_node->from(decode_node);
376
377     // Create a link between input/output and corresponding nodes
378     loco::link(graph_input, pull_node);
379     loco::link(graph_output, push_node);
380   }
381
382 public:
383   loco::Graph *graph() { return _graph.get(); }
384
385   loco::Pull *pull_node = nullptr;
386   loco::FeatureEncode *encode_node = nullptr;
387   loco::MaxPool2D *maxpool2d_node = nullptr;
388   loco::FeatureDecode *decode_node = nullptr;
389   loco::Push *push_node = nullptr;
390
391 private:
392   std::unique_ptr<loco::Graph> _graph;
393 };
394
395 template <> class GraphTestcase<GraphCode::TensorConcat> final
396 {
397 public:
398   GraphTestcase()
399   {
400     using namespace loco;
401
402     // Create a sample network
403     _graph = make_graph();
404
405     // Create Graph Input/Output
406     auto graph_lhs = _graph->inputs()->create();
407     auto graph_rhs = _graph->inputs()->create();
408     auto graph_out = _graph->outputs()->create();
409
410     graph_lhs->name("lhs");
411     graph_rhs->name("rhs");
412     graph_out->name("output");
413
414     // Create and connect nodes
415     lhs_node = _graph->nodes()->create<Pull>();
416     lhs_node->index(0);
417
418     rhs_node = _graph->nodes()->create<Pull>();
419     rhs_node->index(1);
420
421     concat_node = _graph->nodes()->create<TensorConcat>();
422     concat_node->lhs(lhs_node);
423     concat_node->rhs(rhs_node);
424
425     push_node = _graph->nodes()->create<loco::Push>();
426     push_node->index(0);
427     push_node->from(concat_node);
428
429     // Create a link between input/output and corresponding nodes
430     loco::link(graph_lhs, lhs_node);
431     loco::link(graph_rhs, rhs_node);
432     loco::link(graph_out, push_node);
433   }
434
435 public:
436   loco::Graph *graph() { return _graph.get(); }
437
438   loco::Pull *lhs_node = nullptr;
439   loco::Pull *rhs_node = nullptr;
440   loco::TensorConcat *concat_node = nullptr;
441   loco::Push *push_node = nullptr;
442
443 private:
444   std::unique_ptr<loco::Graph> _graph;
445 };
446
447 template <> class GraphTestcase<GraphCode::FixedReshape> final
448 {
449 public:
450   GraphTestcase()
451   {
452     _graph = loco::make_graph();
453
454     auto graph_builder = make_graph_builder(_graph.get());
455
456     pull_node = graph_builder->push<InputLayer>()->name("input")->node();
457     reshape_node = graph_builder->push<FixedReshapeLayer>()->node();
458     push_node = graph_builder->push<OutputLayer>()->name("output")->node();
459   }
460
461 public:
462   loco::Graph *graph() { return _graph.get(); }
463
464   loco::Pull *pull_node = nullptr;
465   loco::FixedReshape *reshape_node = nullptr;
466   loco::Push *push_node = nullptr;
467
468 private:
469   std::unique_ptr<loco::Graph> _graph;
470 };
471
472 template <> class GraphTestcase<GraphCode::TensorBroadcast> final
473 {
474 public:
475   GraphTestcase(std::initializer_list<uint32_t> dims)
476   {
477     _graph = loco::make_graph();
478
479     auto graph_builder = make_graph_builder(_graph.get());
480
481     pull_node = graph_builder->push<InputLayer>()->name("input")->shape(dims)->node();
482     broadcast_node = graph_builder->push<TensorBroadcastLayer>()->node();
483     push_node = graph_builder->push<OutputLayer>()->name("output")->node();
484   }
485
486 public:
487   loco::Graph *graph(void) { return _graph.get(); }
488
489   loco::Pull *pull_node = nullptr;
490   loco::TensorBroadcast *broadcast_node = nullptr;
491   loco::Push *push_node = nullptr;
492
493 private:
494   std::unique_ptr<loco::Graph> _graph;
495 };
496
497 template <> class GraphTestcase<GraphCode::TensorTranspose> final
498 {
499 public:
500   GraphTestcase()
501   {
502     using namespace loco;
503
504     // Create a sample network
505     _graph = make_graph();
506
507     // Create Graph Input/Output
508     auto graph_input = _graph->inputs()->create();
509     auto graph_output = _graph->outputs()->create();
510
511     graph_input->name("input");
512     graph_output->name("output");
513
514     // Create and connect nodes
515     pull_node = _graph->nodes()->create<Pull>();
516     pull_node->index(0);
517
518     transpose_node = _graph->nodes()->create<TensorTranspose>();
519     transpose_node->input(pull_node);
520
521     push_node = _graph->nodes()->create<loco::Push>();
522     push_node->index(0);
523     push_node->from(transpose_node);
524
525     // Create a link between input/output and corresponding nodes
526     loco::link(graph_input, pull_node);
527     loco::link(graph_output, push_node);
528   }
529
530 public:
531   loco::Graph *graph() { return _graph.get(); }
532
533   loco::Pull *pull_node = nullptr;
534   loco::TensorTranspose *transpose_node = nullptr;
535   loco::Push *push_node = nullptr;
536
537 private:
538   std::unique_ptr<loco::Graph> _graph;
539 };
540
541 #endif // __GRAPH_TESTCASE_H__