/* * Copyright (c) 2021, 2023 Arm Limited. * * SPDX-License-Identifier: MIT * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "arm_compute/graph/DataLayerVisitor.h" #include "arm_compute/core/Error.h" #include "arm_compute/graph/Graph.h" #include "arm_compute/graph/nodes/Nodes.h" #include "arm_compute/graph/TypePrinter.h" namespace arm_compute { namespace graph { namespace { template void add_convolution_layer_data(DataLayerVisitor::LayerData &layer_data, T &node) { PadStrideInfo ps_info = node.convolution_info(); DataLayout layout = node.output(0)->desc().layout; // Add data layout layer_data["data_layout"] = to_string(layout); // Add padding info std::ostringstream padding; padding << "[" << to_string(ps_info.pad_left()) << "," << to_string(ps_info.pad_top()) << "," << to_string(ps_info.pad_bottom()) << "," << to_string(ps_info.pad_right()) << "]"; layer_data["pad"] = padding.str(); // Add stride info std::ostringstream stride; stride << "[" << to_string(ps_info.stride().first) << "," << to_string(ps_info.stride().second) << "]"; layer_data["stride"] = stride.str(); // Add dilation info // graph api does not support dilation > 1 layer_data["dilation"] = "[1,1]"; // Add bias enabled? // Assumes three inputs (input, weights, bias) std::string bias_enabled = node.input(2) == nullptr ? "0" : "1"; layer_data["bias_enabled"] = bias_enabled; // Change input names for weights / bias (if applicable) // Assumes input(1) is weights and input(2) is bias if (layer_data.count("input_shape1")) { layer_data["weights_shape"] = layer_data["input_shape1"]; layer_data.erase("input_shape1"); } if (layer_data.count("input_shape2")) { layer_data["bias_shape"] = layer_data["input_shape2"]; layer_data.erase("input_shape2"); } } template void add_convolution_layer_method(DataLayerVisitor::LayerData &layer_data, T &node) { std::ostringstream method; method << node.convolution_method(); layer_data["convolution_method"] = method.str(); } template void add_generic_layer_data(DataLayerVisitor::LayerData &layer_data, T &node) { // Loop over each input tensor for (size_t tensor_no = 0; tensor_no < node.num_inputs(); ++tensor_no) { // Add input tensor shapes if (node.input(tensor_no) != nullptr) { layer_data["input_shape" + to_string(tensor_no)] = "[" + to_string(node.input(tensor_no)->desc().shape) + "]"; } } // Add output tensor shape if (node.output(0) != nullptr) { layer_data["output_shape0"] = "[" + to_string(node.output(0)->desc().shape) + "]"; } } } // namespace void DataLayerVisitor::visit(ConvolutionLayerNode &n) { _layer_data.clear(); add_generic_layer_data(_layer_data, n); add_convolution_layer_data(_layer_data, n); add_convolution_layer_method(_layer_data, n); } void DataLayerVisitor::visit(DepthwiseConvolutionLayerNode &n) { _layer_data.clear(); add_generic_layer_data(_layer_data, n); add_convolution_layer_data(_layer_data, n); } void DataLayerVisitor::visit(FusedConvolutionBatchNormalizationNode &n) { _layer_data.clear(); add_generic_layer_data(_layer_data, n); add_convolution_layer_data(_layer_data, n); add_convolution_layer_method(_layer_data, n); } void DataLayerVisitor::visit(FusedDepthwiseConvolutionBatchNormalizationNode &n) { _layer_data.clear(); add_generic_layer_data(_layer_data, n); add_convolution_layer_data(_layer_data, n); } void DataLayerVisitor::visit(OutputNode &n) { _layer_data.clear(); ARM_COMPUTE_UNUSED(n); } void DataLayerVisitor::default_visit(INode &n) { _layer_data.clear(); add_generic_layer_data(_layer_data, n); } const DataLayerVisitor::LayerData &DataLayerVisitor::layer_data() const { return _layer_data; } } // namespace graph } // namespace arm_compute