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