2 * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 namespace circleinspect
25 void DumpOperators::run(std::ostream &os, const circle::Model *model)
27 circleinspect::Reader reader(model);
29 const uint32_t subgraph_size = reader.num_subgraph();
31 for (uint32_t g = 0; g < subgraph_size; g++)
33 reader.select_subgraph(g);
34 auto ops = reader.operators();
37 for (uint32_t i = 0; i < ops->Length(); ++i)
39 const auto op = ops->Get(i);
41 auto op_name = reader.opcode_name(op);
43 os << op_name << std::endl;
48 } // namespace circleinspect
53 const circle::Operator *operator_match_output(circleinspect::Reader &reader, const int32_t tensor)
55 auto ops = reader.operators();
57 for (uint32_t i = 0; i < ops->Length(); ++i)
59 const auto op = ops->Get(i);
61 const std::vector<int32_t> &outputs = circleinspect::as_index_vector(op->outputs());
63 for (auto output : outputs)
72 size_t tensor_buffer_size(circleinspect::Reader &reader, const int32_t tensor_id)
74 auto tensors = reader.tensors();
76 if (tensor_id < 0 || tensor_id >= tensors->Length())
78 throw std::runtime_error("Invalid Tensor ID");
81 auto tensor = tensors->Get(tensor_id);
82 auto buffer_id = tensor->buffer();
84 size_t size = reader.buffer_info(buffer_id, nullptr);
91 namespace circleinspect
94 void DumpConv2DWeight::run(std::ostream &os, const circle::Model *model)
96 circleinspect::Reader reader(model);
98 const uint32_t subgraph_size = reader.num_subgraph();
100 for (uint32_t g = 0; g < subgraph_size; g++)
102 reader.select_subgraph(g);
103 auto ops = reader.operators();
105 // dump Conv2D, DepthwiseConv2D and its weight input operator
106 for (uint32_t i = 0; i < ops->Length(); ++i)
108 const auto op = ops->Get(i);
109 auto bc = reader.builtin_code(op);
111 if (bc == circle::BuiltinOperator_CONV_2D || bc == circle::BuiltinOperator_DEPTHWISE_CONV_2D)
113 const std::vector<int32_t> &inputs = circleinspect::as_index_vector(op->inputs());
114 if (inputs.size() < 2)
116 throw std::runtime_error("Operator has invalid input");
118 auto weight_input = inputs[1]; // Tensor ID of weight input
120 const auto op_weight = operator_match_output(reader, weight_input);
121 const auto buffer_size = tensor_buffer_size(reader, weight_input);
123 std::string weight_op_name = "?";
125 if (op_weight == nullptr && buffer_size > 0)
127 weight_op_name = "CONST";
129 else if (op_weight != nullptr)
131 weight_op_name = reader.opcode_name(op_weight);
134 auto op_name = reader.opcode_name(op);
135 os << op_name << "," << weight_op_name << std::endl;
141 } // namespace circleinspect
143 namespace circleinspect
146 void DumpOperatorVersion::run(std::ostream &os, const circle::Model *model)
148 std::map<std::string, int32_t> op_version_map;
150 circleinspect::Reader reader(model);
152 // This assert is subject to be changed later
153 assert(reader.num_subgraph() == 1);
154 reader.select_subgraph(0);
156 auto ops = reader.operators();
158 // Dump operators' version
159 for (uint32_t i = 0; i < ops->Length(); ++i)
161 const auto op = ops->Get(i);
163 auto op_name = reader.opcode_name(op);
164 auto op_version = reader.opcodes().at(op->opcode_index())->version();
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;
171 for (auto op : op_version_map)
173 os << op.first << "," << op.second << std::endl;
177 } // namespace circleinspect