1 // 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 <assert.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/params.h>
15 #include <xnnpack/subgraph.h>
16
17
xnn_define_tensor_value(xnn_subgraph_t subgraph,enum xnn_datatype datatype,size_t num_dims,const size_t * dims,const void * data,uint32_t external_id,uint32_t flags,uint32_t * id_out)18 enum xnn_status xnn_define_tensor_value(
19 xnn_subgraph_t subgraph,
20 enum xnn_datatype datatype,
21 size_t num_dims,
22 const size_t* dims,
23 const void* data,
24 uint32_t external_id,
25 uint32_t flags,
26 uint32_t* id_out)
27 {
28 if ((xnn_params.init_flags & XNN_INIT_FLAG_XNNPACK) == 0) {
29 xnn_log_error("failed to create Dense Tensor value: XNNPACK is not initialized");
30 return xnn_status_uninitialized;
31 }
32
33 if (external_id != XNN_INVALID_VALUE_ID && external_id >= subgraph->external_value_ids) {
34 xnn_log_error(
35 "failed to create Dense Tensor value: "
36 "external ID %" PRIu32 " exceeds the number of reserved external IDs in subgraph (%" PRIu32 ")",
37 external_id, subgraph->external_value_ids);
38 return xnn_status_invalid_parameter;
39 }
40
41 if (num_dims > XNN_MAX_TENSOR_DIMS) {
42 xnn_log_error("failed to create Dense Tensor value: num of dimensions exceeds XNNPACK limit (%d)",
43 XNN_MAX_TENSOR_DIMS);
44 return xnn_status_unsupported_parameter;
45 }
46
47 switch (datatype) {
48 case xnn_datatype_fp32:
49 case xnn_datatype_fp16:
50 break;
51 default:
52 xnn_log_error("failed to create Dense Tensor value: invalid data type (%d)", datatype);
53 return xnn_status_unsupported_parameter;
54 }
55
56 struct xnn_value* value = subgraph->values + external_id;
57 if (external_id == XNN_INVALID_VALUE_ID) {
58 value = xnn_subgraph_new_internal_value(subgraph);
59 if (value == NULL) {
60 return xnn_status_out_of_memory;
61 }
62 }
63 value->type = xnn_value_type_dense_tensor;
64 value->datatype = datatype;
65 value->shape.num_dims = num_dims;
66 memcpy(value->shape.dim, dims, num_dims * sizeof(size_t));
67 value->flags = flags;
68 value->data = data;
69
70 *id_out = value->id;
71 return xnn_status_success;
72 }
73
xnn_tensor_get_size(xnn_subgraph_t subgraph,uint32_t value_id)74 size_t xnn_tensor_get_size(
75 xnn_subgraph_t subgraph,
76 uint32_t value_id)
77 {
78 assert(value_id < subgraph->num_values);
79
80 const struct xnn_value* value = subgraph->values + value_id;
81 assert(value->type == xnn_value_type_dense_tensor);
82 assert(value->datatype != xnn_datatype_invalid);
83
84 size_t size = 0;
85 switch (value->datatype) {
86 case xnn_datatype_fp16:
87 size = 2;
88 break;
89 case xnn_datatype_fp32:
90 size = 4;
91 break;
92 case xnn_datatype_invalid:
93 XNN_UNREACHABLE;
94 }
95
96 for (size_t i = 0; i < value->shape.num_dims; i++) {
97 size *= value->shape.dim[i];
98 }
99
100 return size;
101 }
102