Imported Upstream version 1.7.0
[platform/core/ml/nnfw.git] / compiler / circle-inspect / src / Dump.cpp
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 #include "Dump.h"
18 #include "Reader.h"
19
20 #include <ostream>
21
22 namespace circleinspect
23 {
24
25 void DumpOperators::run(std::ostream &os, const circle::Model *model)
26 {
27   circleinspect::Reader reader(model);
28
29   const uint32_t subgraph_size = reader.num_subgraph();
30
31   for (uint32_t g = 0; g < subgraph_size; g++)
32   {
33     reader.select_subgraph(g);
34     auto ops = reader.operators();
35
36     // dump operators
37     for (uint32_t i = 0; i < ops->Length(); ++i)
38     {
39       const auto op = ops->Get(i);
40
41       auto op_name = reader.opcode_name(op);
42
43       os << op_name << std::endl;
44     }
45   }
46 }
47
48 } // namespace circleinspect
49
50 namespace
51 {
52
53 const circle::Operator *operator_match_output(circleinspect::Reader &reader, const int32_t tensor)
54 {
55   auto ops = reader.operators();
56
57   for (uint32_t i = 0; i < ops->Length(); ++i)
58   {
59     const auto op = ops->Get(i);
60
61     const std::vector<int32_t> &outputs = circleinspect::as_index_vector(op->outputs());
62
63     for (auto output : outputs)
64     {
65       if (output == tensor)
66         return op;
67     }
68   }
69   return nullptr;
70 }
71
72 size_t tensor_buffer_size(circleinspect::Reader &reader, const int32_t tensor_id)
73 {
74   auto tensors = reader.tensors();
75
76   if (tensor_id < 0 || tensor_id >= tensors->Length())
77   {
78     throw std::runtime_error("Invalid Tensor ID");
79   }
80
81   auto tensor = tensors->Get(tensor_id);
82   auto buffer_id = tensor->buffer();
83
84   size_t size = reader.buffer_info(buffer_id, nullptr);
85
86   return size;
87 }
88
89 } // namespace
90
91 namespace circleinspect
92 {
93
94 void DumpConv2DWeight::run(std::ostream &os, const circle::Model *model)
95 {
96   circleinspect::Reader reader(model);
97
98   const uint32_t subgraph_size = reader.num_subgraph();
99
100   for (uint32_t g = 0; g < subgraph_size; g++)
101   {
102     reader.select_subgraph(g);
103     auto ops = reader.operators();
104
105     // dump Conv2D, DepthwiseConv2D and its weight input operator
106     for (uint32_t i = 0; i < ops->Length(); ++i)
107     {
108       const auto op = ops->Get(i);
109       auto bc = reader.builtin_code(op);
110
111       if (bc == circle::BuiltinOperator_CONV_2D || bc == circle::BuiltinOperator_DEPTHWISE_CONV_2D)
112       {
113         const std::vector<int32_t> &inputs = circleinspect::as_index_vector(op->inputs());
114         if (inputs.size() < 2)
115         {
116           throw std::runtime_error("Operator has invalid input");
117         }
118         auto weight_input = inputs[1]; // Tensor ID of weight input
119
120         const auto op_weight = operator_match_output(reader, weight_input);
121         const auto buffer_size = tensor_buffer_size(reader, weight_input);
122
123         std::string weight_op_name = "?";
124
125         if (op_weight == nullptr && buffer_size > 0)
126         {
127           weight_op_name = "CONST";
128         }
129         else if (op_weight != nullptr)
130         {
131           weight_op_name = reader.opcode_name(op_weight);
132         }
133
134         auto op_name = reader.opcode_name(op);
135         os << op_name << "," << weight_op_name << std::endl;
136       }
137     }
138   }
139 }
140
141 } // namespace circleinspect
142
143 namespace circleinspect
144 {
145
146 void DumpOperatorVersion::run(std::ostream &os, const circle::Model *model)
147 {
148   std::map<std::string, int32_t> op_version_map;
149
150   circleinspect::Reader reader(model);
151
152   // This assert is subject to be changed later
153   assert(reader.num_subgraph() == 1);
154   reader.select_subgraph(0);
155
156   auto ops = reader.operators();
157
158   // Dump operators' version
159   for (uint32_t i = 0; i < ops->Length(); ++i)
160   {
161     const auto op = ops->Get(i);
162
163     auto op_name = reader.opcode_name(op);
164     auto op_version = reader.opcodes().at(op->opcode_index())->version();
165
166     if (op_version_map.find(op_name) == op_version_map.end() ||
167         op_version_map[op_name] < op_version)
168       op_version_map[op_name] = op_version;
169   }
170
171   for (auto op : op_version_map)
172   {
173     os << op.first << "," << op.second << std::endl;
174   }
175 }
176
177 } // namespace circleinspect