1 // Copyright 2019 Google LLC
2 //
3 // This source code is licensed under the BSD-style license found in the
4 // LICENSE file in the root directory of this source tree.
5
6 #include <assert.h>
7 #include <math.h>
8 #include <stddef.h>
9 #include <stdint.h>
10 #include <stdlib.h>
11
12 #include <xnnpack.h>
13 #include <xnnpack/allocator.h>
14 #include <xnnpack/operator.h>
15 #include <xnnpack/log.h>
16 #include <xnnpack/params.h>
17
18
xnn_create_channel_pad_nc_x32(size_t input_channels,size_t pad_before_channels,size_t pad_after_channels,size_t input_stride,size_t output_stride,const void * pad_value,uint32_t flags,xnn_operator_t * channel_pad_op_out)19 enum xnn_status xnn_create_channel_pad_nc_x32(
20 size_t input_channels,
21 size_t pad_before_channels,
22 size_t pad_after_channels,
23 size_t input_stride,
24 size_t output_stride,
25 const void* pad_value,
26 uint32_t flags,
27 xnn_operator_t* channel_pad_op_out)
28 {
29 xnn_operator_t channel_pad_op = NULL;
30 enum xnn_status status = xnn_status_uninitialized;
31
32 if (!xnn_params.initialized) {
33 xnn_log_error("failed to create Channel Pad operator: XNNPACK is not initialized");
34 goto error;
35 }
36
37 status = xnn_status_invalid_parameter;
38
39 if (input_channels == 0) {
40 xnn_log_error(
41 "failed to create Channel Pad operator with %zu input channels: number of channels must be non-zero",
42 input_channels);
43 goto error;
44 }
45
46 if (input_stride < input_channels) {
47 xnn_log_error(
48 "failed to create Channel Pad operator with input element stride of %zu: "
49 "stride must be at least as large as the number of input channels (%zu)",
50 input_stride, input_channels);
51 goto error;
52 }
53
54 const size_t output_channels = pad_before_channels + input_channels + pad_after_channels;
55 if (output_stride < output_channels) {
56 xnn_log_error(
57 "failed to create Channel Pad operator with output element stride of %zu: "
58 "stride must be at least as large as the number of output channels (%zu+%zu+%zu)",
59 output_stride, pad_before_channels, input_channels, pad_after_channels);
60 goto error;
61 }
62
63 status = xnn_status_out_of_memory;
64
65 channel_pad_op = xnn_allocate_zero_simd_memory(sizeof(struct xnn_operator));
66 if (channel_pad_op == NULL) {
67 xnn_log_error("failed to allocate %zu bytes for Channel Pad operator descriptor", sizeof(struct xnn_operator));
68 goto error;
69 }
70
71 channel_pad_op->channels = input_channels;
72 channel_pad_op->pad_before_channels = pad_before_channels;
73 channel_pad_op->pad_after_channels = pad_after_channels;
74 channel_pad_op->input_pixel_stride = input_stride;
75 channel_pad_op->output_pixel_stride = output_stride;
76 channel_pad_op->pad_value = *((const uint32_t*) pad_value);
77
78 channel_pad_op->type = xnn_operator_type_channel_pad_nc_x32;
79 channel_pad_op->ukernel.type = xnn_ukernel_type_pad;
80
81 channel_pad_op->state = xnn_run_state_invalid;
82
83 *channel_pad_op_out = channel_pad_op;
84 return xnn_status_success;
85
86 error:
87 xnn_delete_operator(channel_pad_op);
88 return status;
89 }
90
xnn_setup_channel_pad_nc_x32(xnn_operator_t channel_pad_op,size_t batch_size,const void * input,void * output,pthreadpool_t threadpool)91 enum xnn_status xnn_setup_channel_pad_nc_x32(
92 xnn_operator_t channel_pad_op,
93 size_t batch_size,
94 const void* input,
95 void* output,
96 pthreadpool_t threadpool)
97 {
98 if (channel_pad_op->type != xnn_operator_type_channel_pad_nc_x32) {
99 xnn_log_error("failed to setup Channel Pad (X32) operator: operator type mismatch");
100 return xnn_status_invalid_parameter;
101 }
102 channel_pad_op->state = xnn_run_state_invalid;
103
104 if (!xnn_params.initialized) {
105 xnn_log_error("failed to setup Channel Pad operator: XNNPACK is not initialized");
106 return xnn_status_uninitialized;
107 }
108
109 if (batch_size == 0) {
110 channel_pad_op->state = xnn_run_state_skip;
111 return xnn_status_success;
112 }
113
114 channel_pad_op->batch_size = batch_size;
115 channel_pad_op->input = input;
116 channel_pad_op->output = output;
117
118 channel_pad_op->context.channel_pad = (struct channel_pad_context) {
119 .x = input,
120 .x_stride = channel_pad_op->input_pixel_stride * sizeof(uint32_t),
121 .y = output,
122 .y_stride = channel_pad_op->output_pixel_stride * sizeof(uint32_t),
123 .n = channel_pad_op->channels * sizeof(uint32_t),
124 .l = channel_pad_op->pad_before_channels * sizeof(uint32_t),
125 .r = channel_pad_op->pad_after_channels * sizeof(uint32_t),
126 .c = channel_pad_op->pad_value,
127 .ukernel = xnn_params.x32.pad.ukernel,
128 };
129 channel_pad_op->compute.type = xnn_parallelization_type_1d_tile_1d;
130 channel_pad_op->compute.task_1d_tile_1d =
131 (pthreadpool_task_1d_tile_1d_t) xnn_compute_channel_pad;
132 channel_pad_op->compute.range[0] = batch_size;
133 channel_pad_op->compute.tile[0] = xnn_params.x32.pad.mr;
134 channel_pad_op->state = xnn_run_state_ready;
135
136 return xnn_status_success;
137 }
138