| 368 | } |
| 369 | |
| 370 | NodeID GraphBuilder::add_depthwise_convolution_node(Graph &g, |
| 371 | NodeParams params, |
| 372 | NodeIdxPair input, |
| 373 | Size2D kernel_spatial_extend, |
| 374 | PadStrideInfo conv_info, |
| 375 | int depth_multiplier, |
| 376 | DepthwiseConvolutionMethod method, |
| 377 | ITensorAccessorUPtr weights_accessor, |
| 378 | ITensorAccessorUPtr bias_accessor, |
| 379 | const QuantizationInfo &quant_info, |
| 380 | const QuantizationInfo &out_quant_info) |
| 381 | { |
| 382 | check_nodeidx_pair(input, g); |
| 383 | ARM_COMPUTE_ERROR_ON((kernel_spatial_extend.width == 0) || (kernel_spatial_extend.height == 0)); |
| 384 | |
| 385 | bool has_bias = (bias_accessor != nullptr); |
| 386 | |
| 387 | // Get input tensor descriptor |
| 388 | const TensorDescriptor input_tensor_desc = get_tensor_descriptor(g, g.node(input.node_id)->outputs()[0]); |
| 389 | const DataLayout input_data_layout = input_tensor_desc.layout; |
| 390 | |
| 391 | // Create weights node |
| 392 | TensorDescriptor w_desc = input_tensor_desc; |
| 393 | w_desc.shape.set(get_dimension_idx(input_data_layout, DataLayoutDimension::WIDTH), kernel_spatial_extend.width); |
| 394 | w_desc.shape.set(get_dimension_idx(input_data_layout, DataLayoutDimension::HEIGHT), kernel_spatial_extend.height); |
| 395 | w_desc.shape.set(get_dimension_idx(input_data_layout, DataLayoutDimension::CHANNEL), |
| 396 | get_dimension_size(input_tensor_desc, DataLayoutDimension::CHANNEL) * depth_multiplier); |
| 397 | if (!quant_info.empty()) |
| 398 | { |
| 399 | w_desc.quant_info = quant_info; |
| 400 | } |
| 401 | |
| 402 | NodeID w_nid = add_const_node_with_name(g, params, "Weights", w_desc, std::move(weights_accessor)); |
| 403 | |
| 404 | // Create bias nodes |
| 405 | NodeID b_nid = EmptyNodeID; |
| 406 | if (has_bias) |
| 407 | { |
| 408 | TensorDescriptor b_desc = input_tensor_desc; |
| 409 | b_desc.shape = |
| 410 | TensorShape(get_dimension_size(input_tensor_desc, DataLayoutDimension::CHANNEL) * depth_multiplier); |
| 411 | |
| 412 | if (is_data_type_quantized_asymmetric(b_desc.data_type)) |
| 413 | { |
| 414 | b_desc.data_type = DataType::S32; |
| 415 | } |
| 416 | |
| 417 | b_nid = add_const_node_with_name(g, params, "Bias", b_desc, std::move(bias_accessor)); |
| 418 | } |
| 419 | |
| 420 | // Create convolution node and connect |
| 421 | NodeID conv_nid = g.add_node<DepthwiseConvolutionLayerNode>(conv_info, depth_multiplier, method, out_quant_info); |
| 422 | g.add_connection(input.node_id, input.index, conv_nid, 0); |
| 423 | g.add_connection(w_nid, 0, conv_nid, 1); |
| 424 | if (has_bias) |
| 425 | { |
| 426 | g.add_connection(b_nid, 0, conv_nid, 2); |
| 427 | } |
nothing calls this directly
no test coverage detected