blob: d90d62589100d0c54146b9006bcd690d92cfd1cf [file] [log] [blame]
Marat Dukhan1d75a542020-02-03 12:23:01 -08001// Copyright 2020 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 <math.h>
7#include <stddef.h>
8#include <stdint.h>
9#include <stdlib.h>
10
11#include <xnnpack.h>
12#include <xnnpack/allocator.h>
13#include <xnnpack/log.h>
14#include <xnnpack/math.h>
15#include <xnnpack/params.h>
16#include <xnnpack/subgraph.h>
17
18
19enum xnn_status xnn_create_subgraph(
20 uint32_t external_value_ids,
21 uint32_t flags,
22 xnn_subgraph_t* subgraph_out)
23{
24 struct xnn_subgraph* subgraph = NULL;
25 enum xnn_status status = xnn_status_uninitialized;
26
27 if (!xnn_params.initialized) {
28 xnn_log_error("failed to create subgraph: XNNPACK is not initialized");
29 goto error;
30 }
31
32 status = xnn_status_out_of_memory;
33
34 subgraph = xnn_allocate_zero_memory(sizeof(struct xnn_subgraph));
35 if (subgraph == NULL) {
36 xnn_log_error("failed to allocate %zu bytes for subgraph descriptor", sizeof(struct xnn_subgraph));
37 goto error;
38 }
39
40 subgraph->external_value_ids = external_value_ids;
41
42 subgraph->values = xnn_allocate_zero_memory(external_value_ids * sizeof(struct xnn_value));
43 if (subgraph->values == NULL) {
44 xnn_log_error("failed to allocate %zu bytes for subgraph values", external_value_ids * sizeof(struct xnn_value));
45 goto error;
46 }
47 for (size_t i = 0; i < external_value_ids; i++) {
48 subgraph->values[i].id = i;
49 }
50 subgraph->num_values = external_value_ids;
51 subgraph->num_reserved_values = external_value_ids;
52
53 *subgraph_out = subgraph;
54 return xnn_status_success;
55
56error:
57 xnn_delete_subgraph(subgraph);
58 return status;
59}
60
61
62struct xnn_value* xnn_subgraph_new_internal_value(xnn_subgraph_t subgraph)
63{
64 struct xnn_value* values = subgraph->values;
65 const size_t size = subgraph->num_values;
66 const size_t capacity = subgraph->num_reserved_values;
67 if (capacity < size + 1) {
68 const size_t new_capacity = max(min(capacity * 2, capacity + 512), capacity + 64);
69 assert(new_capacity >= size + 1);
70 values = xnn_reallocate_memory(values, new_capacity * sizeof(struct xnn_value));
71 if (values == NULL) {
72 xnn_log_error("failed to allocate %zu bytes for subgraph values",
73 capacity * sizeof(struct xnn_value));
74 return values;
75 }
76
77 memset(values + size, 0, (new_capacity - size) * sizeof(struct xnn_value));
78 subgraph->num_reserved_values = new_capacity;
79 subgraph->values = values;
80 }
81 subgraph->num_values = size + 1;
82 struct xnn_value* new_value = values + size;
83 new_value->id = size;
84 return new_value;
85}
86
87struct xnn_node* xnn_subgraph_new_node(xnn_subgraph_t subgraph)
88{
89 struct xnn_node* nodes = subgraph->nodes;
90 const size_t size = subgraph->num_nodes;
91 const size_t capacity = subgraph->num_reserved_nodes;
92
93 if (capacity < size + 1) {
94 const size_t new_capacity = max(min(capacity * 2, capacity + 512), capacity + 64);
95 assert(new_capacity >= size + 1);
96 nodes = xnn_reallocate_memory(nodes, new_capacity * sizeof(struct xnn_node));
97 if (nodes == NULL) {
98 xnn_log_error("failed to allocate %zu bytes for subgraph nodes",
99 capacity * sizeof(struct xnn_node));
100 return nodes;
101 }
102
103 memset(nodes + size, 0, (new_capacity - size) * sizeof(struct xnn_node));
104 subgraph->num_reserved_nodes = new_capacity;
105 subgraph->nodes = nodes;
106 }
107 subgraph->num_nodes = size + 1;
108 struct xnn_node* new_node = nodes + size;
109 new_node->id = size;
110 return new_node;
111}
112
113enum xnn_status xnn_define_convolution_2d(
114 xnn_subgraph_t subgraph,
115 uint32_t input_padding_top,
116 uint32_t input_padding_right,
117 uint32_t input_padding_bottom,
118 uint32_t input_padding_left,
119 uint32_t kernel_height,
120 uint32_t kernel_width,
121 uint32_t subsampling_height,
122 uint32_t subsampling_width,
123 uint32_t dilation_height,
124 uint32_t dilation_width,
125 uint32_t groups,
126 size_t group_input_channels,
127 size_t group_output_channels,
128 float output_min,
129 float output_max,
130 uint32_t input_id,
131 uint32_t filter_id,
132 uint32_t bias_id,
133 uint32_t output_id,
134 uint32_t flags)
135{
136 if (!xnn_params.initialized) {
137 xnn_log_error("failed to define Convolution operator: XNNPACK is not initialized");
138 return xnn_status_uninitialized;
139 }
140
141 if (kernel_width == 0 || kernel_height == 0) {
142 xnn_log_error(
143 "failed to define Convolution operator with %" PRIu32 "x%" PRIu32 " kernel: kernel dimensions must be non-zero",
144 kernel_width, kernel_height);
145 return xnn_status_invalid_parameter;
146 }
147
148 if (subsampling_width == 0 || subsampling_height == 0) {
149 xnn_log_error(
150 "failed to define Convolution operator with %" PRIu32 "x%" PRIu32 " subsampling: "
151 "subsampling dimensions must be non-zero",
152 subsampling_width, subsampling_height);
153 return xnn_status_invalid_parameter;
154 }
155
156 if (dilation_width == 0 || dilation_height == 0) {
157 xnn_log_error(
158 "failed to define Convolution operator with %" PRIu32 "x%" PRIu32 " dilation: "
159 "dilation dimensions must be non-zero",
160 dilation_width, dilation_height);
161 return xnn_status_invalid_parameter;
162 }
163
164 if (groups == 0) {
165 xnn_log_error(
166 "failed to define Convolution operator with %" PRIu32 " groups: number of groups must be non-zero", groups);
167 return xnn_status_invalid_parameter;
168 }
169
170 if (group_input_channels == 0) {
171 xnn_log_error(
172 "failed to define Convolution operator with %zu input channels per group: "
173 "number of channels must be non-zero",
174 group_input_channels);
175 return xnn_status_invalid_parameter;
176 }
177
178 if (group_output_channels == 0) {
179 xnn_log_error(
180 "failed to define Convolution operator with %zu output channels per group: "
181 "number of channels must be non-zero",
182 group_output_channels);
183 return xnn_status_invalid_parameter;
184 }
185
186 if (isnan(output_min)) {
187 xnn_log_error(
188 "failed to define Convolution operator with NaN output lower bound: lower bound must be non-NaN");
189 return xnn_status_invalid_parameter;
190 }
191
192 if (isnan(output_max)) {
193 xnn_log_error(
194 "failed to define Convolution operator with NaN output upper bound: upper bound must be non-NaN");
195 return xnn_status_invalid_parameter;
196 }
197
198 if (output_min >= output_max) {
199 xnn_log_error(
200 "failed to define Convolution operator with [%.7g, %.7g] output range: "
201 "lower bound must be below upper bound",
202 output_min, output_max);
203 return xnn_status_invalid_parameter;
204 }
205
206 if (input_id >= subgraph->num_values) {
207 xnn_log_error(
208 "failed to define Convolution operator with input ID #%" PRIu32 ": invalid Value ID",
209 input_id);
210 return xnn_status_invalid_parameter;
211 }
212
213 if (filter_id >= subgraph->num_values) {
214 xnn_log_error(
215 "failed to define Convolution operator with filter ID #%" PRIu32 ": invalid Value ID",
216 filter_id);
217 return xnn_status_invalid_parameter;
218 }
219
220 if (bias_id >= subgraph->num_values) {
221 xnn_log_error(
222 "failed to define Convolution operator with bias ID #%" PRIu32 ": invalid Value ID",
223 bias_id);
224 return xnn_status_invalid_parameter;
225 }
226
227 if (output_id >= subgraph->num_values) {
228 xnn_log_error(
229 "failed to define Convolution operator with output ID #%" PRIu32 ": invalid Value ID",
230 output_id);
231 return xnn_status_invalid_parameter;
232 }
233
234 struct xnn_node* node = xnn_subgraph_new_node(subgraph);
235 if (node == NULL) {
236 return xnn_status_out_of_memory;
237 }
238
239 node->type = xnn_node_type_convolution_2d;
240 node->params.convolution_2d.input_padding_top = input_padding_top;
241 node->params.convolution_2d.input_padding_right = input_padding_right;
242 node->params.convolution_2d.input_padding_bottom = input_padding_bottom;
243 node->params.convolution_2d.input_padding_left = input_padding_left;
244 node->params.convolution_2d.kernel_height = kernel_height;
245 node->params.convolution_2d.kernel_width = kernel_width;
246 node->params.convolution_2d.subsampling_height = subsampling_height;
247 node->params.convolution_2d.subsampling_width = subsampling_width;
248 node->params.convolution_2d.dilation_height = dilation_height;
249 node->params.convolution_2d.dilation_width = dilation_width;
250 node->params.convolution_2d.groups = groups;
251 node->params.convolution_2d.group_input_channels = group_input_channels;
252 node->params.convolution_2d.group_output_channels = group_output_channels;
Marat Dukhan54dcb462020-02-10 11:06:12 -0800253 node->activation.output_min = output_min;
254 node->activation.output_max = output_max;
Marat Dukhan1d75a542020-02-03 12:23:01 -0800255 node->num_inputs = 3;
256 node->inputs.raw[0] = input_id;
257 node->inputs.raw[1] = filter_id;
258 node->inputs.raw[2] = bias_id;
259 node->num_outputs = 1;
260 node->outputs.raw[0] = output_id;
261 node->flags = flags;
262
263 return xnn_status_success;
264};
265
266enum xnn_status xnn_define_depthwise_convolution_2d(
267 xnn_subgraph_t subgraph,
268 uint32_t input_padding_top,
269 uint32_t input_padding_right,
270 uint32_t input_padding_bottom,
271 uint32_t input_padding_left,
272 uint32_t kernel_height,
273 uint32_t kernel_width,
274 uint32_t subsampling_height,
275 uint32_t subsampling_width,
276 uint32_t dilation_height,
277 uint32_t dilation_width,
278 uint32_t depth_multiplier,
279 size_t input_channels,
280 float output_min,
281 float output_max,
282 uint32_t input_id,
283 uint32_t filter_id,
284 uint32_t bias_id,
285 uint32_t output_id,
286 uint32_t flags)
287{
288 if (!xnn_params.initialized) {
289 xnn_log_error("failed to define Depthwise Convolution operator: XNNPACK is not initialized");
290 return xnn_status_uninitialized;
291 }
292
293 if (kernel_width == 0 || kernel_height == 0) {
294 xnn_log_error(
295 "failed to define Depthwise Convolution operator with %" PRIu32 "x%" PRIu32 " kernel: kernel dimensions must be non-zero",
296 kernel_width, kernel_height);
297 return xnn_status_invalid_parameter;
298 }
299
300 if (subsampling_width == 0 || subsampling_height == 0) {
301 xnn_log_error(
302 "failed to define Depthwise Convolution operator with %" PRIu32 "x%" PRIu32 " subsampling: "
303 "subsampling dimensions must be non-zero",
304 subsampling_width, subsampling_height);
305 return xnn_status_invalid_parameter;
306 }
307
308 if (dilation_width == 0 || dilation_height == 0) {
309 xnn_log_error(
310 "failed to define Depthwise Convolution operator with %" PRIu32 "x%" PRIu32 " dilation: "
311 "dilation dimensions must be non-zero",
312 dilation_width, dilation_height);
313 return xnn_status_invalid_parameter;
314 }
315
316 if (depth_multiplier == 0) {
317 xnn_log_error(
318 "failed to define Depthwise Convolution operator with %" PRIu32 " depth multiplier: "
319 "depth multiplier must be non-zero",
320 depth_multiplier);
321 return xnn_status_invalid_parameter;
322 }
323
324 if (input_channels == 0) {
325 xnn_log_error(
326 "failed to define Depthwise Convolution operator with %zu input channels: "
327 "number of channels must be non-zero",
328 input_channels);
329 return xnn_status_invalid_parameter;
330 }
331
332 if (isnan(output_min)) {
333 xnn_log_error(
334 "failed to define Depthwise Convolution operator with NaN output lower bound: lower bound must be non-NaN");
335 return xnn_status_invalid_parameter;
336 }
337
338 if (isnan(output_max)) {
339 xnn_log_error(
340 "failed to define Depthwise Convolution operator with NaN output upper bound: upper bound must be non-NaN");
341 return xnn_status_invalid_parameter;
342 }
343
344 if (output_min >= output_max) {
345 xnn_log_error(
346 "failed to define Depthwise Convolution operator with [%.7g, %.7g] output range: "
347 "lower bound must be below upper bound",
348 output_min, output_max);
349 return xnn_status_invalid_parameter;
350 }
351
352 if (input_id >= subgraph->num_values) {
353 xnn_log_error(
354 "failed to define Depthwise Convolution operator with input ID #%" PRIu32 ": invalid Value ID",
355 input_id);
356 return xnn_status_invalid_parameter;
357 }
358
359 if (filter_id >= subgraph->num_values) {
360 xnn_log_error(
361 "failed to define Depthwise Convolution operator with filter ID #%" PRIu32 ": invalid Value ID",
362 filter_id);
363 return xnn_status_invalid_parameter;
364 }
365
366 if (bias_id >= subgraph->num_values) {
367 xnn_log_error(
368 "failed to define Depthwise Convolution operator with bias ID #%" PRIu32 ": invalid Value ID",
369 bias_id);
370 return xnn_status_invalid_parameter;
371 }
372
373 if (output_id >= subgraph->num_values) {
374 xnn_log_error(
375 "failed to define Depthwise Convolution operator with output ID #%" PRIu32 ": invalid Value ID",
376 output_id);
377 return xnn_status_invalid_parameter;
378 }
379
380 struct xnn_node* node = xnn_subgraph_new_node(subgraph);
381 if (node == NULL) {
382 return xnn_status_out_of_memory;
383 }
384
385 node->type = xnn_node_type_depthwise_convolution_2d;
386 node->params.depthwise_convolution_2d.input_padding_top = input_padding_top;
387 node->params.depthwise_convolution_2d.input_padding_right = input_padding_right;
388 node->params.depthwise_convolution_2d.input_padding_bottom = input_padding_bottom;
389 node->params.depthwise_convolution_2d.input_padding_left = input_padding_left;
390 node->params.depthwise_convolution_2d.kernel_height = kernel_height;
391 node->params.depthwise_convolution_2d.kernel_width = kernel_width;
392 node->params.depthwise_convolution_2d.subsampling_height = subsampling_height;
393 node->params.depthwise_convolution_2d.subsampling_width = subsampling_width;
394 node->params.depthwise_convolution_2d.dilation_height = dilation_height;
395 node->params.depthwise_convolution_2d.dilation_width = dilation_width;
396 node->params.depthwise_convolution_2d.depth_multiplier = depth_multiplier;
397 node->params.depthwise_convolution_2d.input_channels = input_channels;
Marat Dukhan54dcb462020-02-10 11:06:12 -0800398 node->activation.output_min = output_min;
399 node->activation.output_max = output_max;
Marat Dukhan1d75a542020-02-03 12:23:01 -0800400 node->num_inputs = 3;
401 node->inputs.raw[0] = input_id;
402 node->inputs.raw[1] = filter_id;
403 node->inputs.raw[2] = bias_id;
404 node->num_outputs = 1;
405 node->outputs.raw[0] = output_id;
406 node->flags = flags;
407
408 return xnn_status_success;
409};
410
Marat Dukhan54dcb462020-02-10 11:06:12 -0800411enum xnn_status xnn_define_add2(
412 xnn_subgraph_t subgraph,
413 float output_min,
414 float output_max,
415 uint32_t input1_id,
416 uint32_t input2_id,
417 uint32_t output_id,
418 uint32_t flags)
419{
420 if (!xnn_params.initialized) {
421 xnn_log_error("failed to define Add2 operator: XNNPACK is not initialized");
422 return xnn_status_uninitialized;
423 }
424
425 if (isnan(output_min)) {
426 xnn_log_error(
427 "failed to define Add2 operator with NaN output lower bound: lower bound must be non-NaN");
428 return xnn_status_invalid_parameter;
429 }
430
431 if (isnan(output_max)) {
432 xnn_log_error(
433 "failed to define Add2 operator with NaN output upper bound: upper bound must be non-NaN");
434 return xnn_status_invalid_parameter;
435 }
436
437 if (output_min >= output_max) {
438 xnn_log_error(
439 "failed to define Add2 operator with [%.7g, %.7g] output range: "
440 "lower bound must be below upper bound",
441 output_min, output_max);
442 return xnn_status_invalid_parameter;
443 }
444
445 if (input1_id >= subgraph->num_values) {
446 xnn_log_error(
447 "failed to define Add2 operator with the first input ID #%" PRIu32 ": invalid Value ID",
448 input1_id);
449 return xnn_status_invalid_parameter;
450 }
451
452 if (input2_id >= subgraph->num_values) {
453 xnn_log_error(
454 "failed to define Add2 operator with the second input ID #%" PRIu32 ": invalid Value ID",
455 input2_id);
456 return xnn_status_invalid_parameter;
457 }
458
459 if (output_id >= subgraph->num_values) {
460 xnn_log_error(
461 "failed to define Add2 operator with output ID #%" PRIu32 ": invalid Value ID",
462 output_id);
463 return xnn_status_invalid_parameter;
464 }
465
466 struct xnn_node* node = xnn_subgraph_new_node(subgraph);
467 if (node == NULL) {
468 return xnn_status_out_of_memory;
469 }
470
471 node->type = xnn_node_type_add2;
472 node->activation.output_min = output_min;
473 node->activation.output_max = output_max;
474 node->num_inputs = 2;
475 node->inputs.raw[0] = input1_id;
476 node->inputs.raw[1] = input2_id;
477 node->num_outputs = 1;
478 node->outputs.raw[0] = output_id;
479 node->flags = flags;
480
481 return xnn_status_success;
482}
483
484enum xnn_status xnn_define_multiply2(
485 xnn_subgraph_t subgraph,
486 float output_min,
487 float output_max,
488 uint32_t input1_id,
489 uint32_t input2_id,
490 uint32_t output_id,
491 uint32_t flags)
492{
493 if (!xnn_params.initialized) {
494 xnn_log_error("failed to define Multiply2 operator: XNNPACK is not initialized");
495 return xnn_status_uninitialized;
496 }
497
498 if (isnan(output_min)) {
499 xnn_log_error(
500 "failed to define Multiply2 operator with NaN output lower bound: lower bound must be non-NaN");
501 return xnn_status_invalid_parameter;
502 }
503
504 if (isnan(output_max)) {
505 xnn_log_error(
506 "failed to define Multiply2 operator with NaN output upper bound: upper bound must be non-NaN");
507 return xnn_status_invalid_parameter;
508 }
509
510 if (output_min >= output_max) {
511 xnn_log_error(
512 "failed to define Multiply2 operator with [%.7g, %.7g] output range: "
513 "lower bound must be below upper bound",
514 output_min, output_max);
515 return xnn_status_invalid_parameter;
516 }
517
518 if (input1_id >= subgraph->num_values) {
519 xnn_log_error(
520 "failed to define Multiply2 operator with the first input ID #%" PRIu32 ": invalid Value ID",
521 input1_id);
522 return xnn_status_invalid_parameter;
523 }
524
525 if (input2_id >= subgraph->num_values) {
526 xnn_log_error(
527 "failed to define Multiply2 operator with the second input ID #%" PRIu32 ": invalid Value ID",
528 input2_id);
529 return xnn_status_invalid_parameter;
530 }
531
532 if (output_id >= subgraph->num_values) {
533 xnn_log_error(
534 "failed to define Multiply2 operator with output ID #%" PRIu32 ": invalid Value ID",
535 output_id);
536 return xnn_status_invalid_parameter;
537 }
538
539 struct xnn_node* node = xnn_subgraph_new_node(subgraph);
540 if (node == NULL) {
541 return xnn_status_out_of_memory;
542 }
543
544 node->type = xnn_node_type_multiply2;
545 node->activation.output_min = output_min;
546 node->activation.output_max = output_max;
547 node->num_inputs = 2;
548 node->inputs.raw[0] = input1_id;
549 node->inputs.raw[1] = input2_id;
550 node->num_outputs = 1;
551 node->outputs.raw[0] = output_id;
552 node->flags = flags;
553
554 return xnn_status_success;
555}
556
Miao Wang3fa1f012020-02-17 22:45:06 +0000557enum xnn_status xnn_define_prelu(
558 xnn_subgraph_t subgraph,
559 uint32_t input_id,
560 uint32_t slope_id,
561 uint32_t output_id,
562 uint32_t flags)
563{
564 if (!xnn_params.initialized) {
565 xnn_log_error("failed to define PReLU operator: XNNPACK is not initialized");
566 return xnn_status_uninitialized;
567 }
568
569 if (input_id >= subgraph->num_values) {
570 xnn_log_error(
571 "failed to define PReLU operator with input ID #%" PRIu32 ": invalid Value ID",
572 input_id);
573 return xnn_status_invalid_parameter;
574 }
575
576 if (slope_id >= subgraph->num_values) {
577 xnn_log_error(
578 "failed to define PReLU operator with slope ID #%" PRIu32 ": invalid Value ID",
579 slope_id);
580 return xnn_status_invalid_parameter;
581 }
582
583 if (output_id >= subgraph->num_values) {
584 xnn_log_error(
585 "failed to define PReLU operator with output ID #%" PRIu32 ": invalid Value ID",
586 output_id);
587 return xnn_status_invalid_parameter;
588 }
589
590 struct xnn_node* node = xnn_subgraph_new_node(subgraph);
591 if (node == NULL) {
592 return xnn_status_out_of_memory;
593 }
594
595 node->type = xnn_node_type_prelu;
596 node->num_inputs = 2;
597 node->inputs.raw[0] = input_id;
598 node->inputs.raw[1] = slope_id;
599 node->num_outputs = 1;
600 node->outputs.raw[0] = output_id;
601 node->flags = flags;
602
603 return xnn_status_success;
604}
605
606enum xnn_status xnn_define_clamp(
607 xnn_subgraph_t subgraph,
608 float output_min,
609 float output_max,
610 uint32_t input_id,
611 uint32_t output_id,
612 uint32_t flags)
613{
614 if (!xnn_params.initialized) {
615 xnn_log_error("failed to define Clamp operator: XNNPACK is not initialized");
616 return xnn_status_uninitialized;
617 }
618
619 if (input_id >= subgraph->num_values) {
620 xnn_log_error(
621 "failed to define Clamp operator with input ID #%" PRIu32 ": invalid Value ID",
622 input_id);
623 return xnn_status_invalid_parameter;
624 }
625
626 if (output_id >= subgraph->num_values) {
627 xnn_log_error(
628 "failed to define Clamp operator with output ID #%" PRIu32 ": invalid Value ID",
629 output_id);
630 return xnn_status_invalid_parameter;
631 }
632
633 struct xnn_node* node = xnn_subgraph_new_node(subgraph);
634 if (node == NULL) {
635 return xnn_status_out_of_memory;
636 }
637
638 node->type = xnn_node_type_clamp;
639 node->activation.output_min = output_min;
640 node->activation.output_max = output_max;
641 node->num_inputs = 1;
642 node->inputs.raw[0] = input_id;
643 node->num_outputs = 1;
644 node->outputs.raw[0] = output_id;
645 node->flags = flags;
646
647 return xnn_status_success;
648}
649
650enum xnn_status xnn_define_hardswish(
651 xnn_subgraph_t subgraph,
652 uint32_t input_id,
653 uint32_t output_id,
654 uint32_t flags)
655{
656 if (!xnn_params.initialized) {
657 xnn_log_error("failed to define HardSwish operator: XNNPACK is not initialized");
658 return xnn_status_uninitialized;
659 }
660
661 if (input_id >= subgraph->num_values) {
662 xnn_log_error(
663 "failed to define HardSwish operator with input ID #%" PRIu32 ": invalid Value ID",
664 input_id);
665 return xnn_status_invalid_parameter;
666 }
667
668 if (output_id >= subgraph->num_values) {
669 xnn_log_error(
670 "failed to define HardSwish operator with output ID #%" PRIu32 ": invalid Value ID",
671 output_id);
672 return xnn_status_invalid_parameter;
673 }
674
675 struct xnn_node* node = xnn_subgraph_new_node(subgraph);
676 if (node == NULL) {
677 return xnn_status_out_of_memory;
678 }
679
680 node->type = xnn_node_type_hardswish;
681 node->num_inputs = 1;
682 node->inputs.raw[0] = input_id;
683 node->num_outputs = 1;
684 node->outputs.raw[0] = output_id;
685 node->flags = flags;
686
687 return xnn_status_success;
688}
689
690enum xnn_status xnn_define_sigmoid(
691 xnn_subgraph_t subgraph,
692 uint32_t input_id,
693 uint32_t output_id,
694 uint32_t flags)
695{
696 if (!xnn_params.initialized) {
697 xnn_log_error("failed to define Sigmoid operator: XNNPACK is not initialized");
698 return xnn_status_uninitialized;
699 }
700
701 if (input_id >= subgraph->num_values) {
702 xnn_log_error(
703 "failed to define Sigmoid operator with input ID #%" PRIu32 ": invalid Value ID",
704 input_id);
705 return xnn_status_invalid_parameter;
706 }
707
708 if (output_id >= subgraph->num_values) {
709 xnn_log_error(
710 "failed to define Sigmoid operator with output ID #%" PRIu32 ": invalid Value ID",
711 output_id);
712 return xnn_status_invalid_parameter;
713 }
714
715 struct xnn_node* node = xnn_subgraph_new_node(subgraph);
716 if (node == NULL) {
717 return xnn_status_out_of_memory;
718 }
719
720 node->type = xnn_node_type_sigmoid;
721 node->num_inputs = 1;
722 node->inputs.raw[0] = input_id;
723 node->num_outputs = 1;
724 node->outputs.raw[0] = output_id;
725 node->flags = flags;
726
727 return xnn_status_success;
728}
729
730enum xnn_status xnn_define_softmax(
731 xnn_subgraph_t subgraph,
732 uint32_t input_id,
733 uint32_t output_id,
734 uint32_t flags)
735{
736 if (!xnn_params.initialized) {
737 xnn_log_error("failed to define SoftMax operator: XNNPACK is not initialized");
738 return xnn_status_uninitialized;
739 }
740
741 if (input_id >= subgraph->num_values) {
742 xnn_log_error(
743 "failed to define SoftMax operator with input ID #%" PRIu32 ": invalid Value ID",
744 input_id);
745 return xnn_status_invalid_parameter;
746 }
747
748 if (output_id >= subgraph->num_values) {
749 xnn_log_error(
750 "failed to define SoftMax operator with output ID #%" PRIu32 ": invalid Value ID",
751 output_id);
752 return xnn_status_invalid_parameter;
753 }
754
755 struct xnn_node* node = xnn_subgraph_new_node(subgraph);
756 if (node == NULL) {
757 return xnn_status_out_of_memory;
758 }
759
760 node->type = xnn_node_type_softmax;
761 node->num_inputs = 1;
762 node->inputs.raw[0] = input_id;
763 node->num_outputs = 1;
764 node->outputs.raw[0] = output_id;
765 node->flags = flags;
766
767 return xnn_status_success;
768}
769
Marat Dukhan1d75a542020-02-03 12:23:01 -0800770enum xnn_status xnn_delete_subgraph(
771 xnn_subgraph_t subgraph)
772{
773 if (subgraph != NULL) {
774 memset(subgraph->nodes, 0, sizeof(struct xnn_node) * subgraph->num_nodes);
775 xnn_release_memory(subgraph->nodes);
776
777 memset(subgraph->values, 0, sizeof(struct xnn_value) * subgraph->num_values);
778 xnn_release_memory(subgraph->values);
779
780 memset(subgraph, 0, sizeof(struct xnn_subgraph));
781 xnn_release_memory(subgraph);
782 }
783 return xnn_status_success;
784}