ONE - On-device Neural Engine
Loading...
Searching...
No Matches
SVDF.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "OMStatus.h"
18
19#include "core/OMUtils.h"
20#include "core/OMKernelData.h"
21
23
25#include "execute/OMUtils.h"
26
27using namespace onert_micro;
28using namespace onert_micro::core;
29
30namespace
31{
32
33constexpr int inputTensorIdx = 0;
34constexpr int weightsFeatureTensorIdx = 1;
35constexpr int weightsTimeTensorIdx = 2;
36constexpr int biasTensorIdx = 3;
37constexpr int inputActivationStateTensorIdx =
38 4; // This is a variable tensor, and will be modified by this op.
39constexpr int outputTensorIdx = 0;
40
41} // namespace
42
43OMStatus onert_micro::import::configure_kernel_CircleSVDF(const OMConfigureArgs &config_args)
44{
45 // Validate Tensor Inputs (dtype depends on quantization):
46 // [0] = Input, {2, batch_size, input_size}
47 // [1] = Weights Feature, {2, num_filters, input_size}
48 // [2] = Weights Time, {2, num_filters, memory_size}
49 // [3] = Bias (optional), {1, num_units}
50 // [4] = Activation State (variable), {2, batch_size, memory_size * num_filters}
51
52 OMRuntimeContext &runtime_context = config_args.runtime_context;
53 uint16_t op_index = config_args.kernel_index;
54
55 execute::OMRuntimeKernel runtime_kernel;
56 runtime_kernel.readKernel(op_index, runtime_context);
57
58 const circle::Tensor *input = runtime_kernel.inputs[inputTensorIdx];
59 const circle::Tensor *weights_feature = runtime_kernel.inputs[weightsFeatureTensorIdx];
60 const circle::Tensor *weights_time = runtime_kernel.inputs[weightsTimeTensorIdx];
61 const circle::Tensor *bias = runtime_kernel.inputs[biasTensorIdx];
62 const circle::Tensor *activation_state = runtime_kernel.inputs[inputActivationStateTensorIdx];
63
64 const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
65
66 assert(input != nullptr);
67 assert(weights_feature != nullptr);
68 assert(weights_time != nullptr);
69 // bias can be nullptr
70 assert(activation_state != nullptr);
71 assert(output != nullptr);
72
73 OMStatus status = Ok;
74
75 const auto *options = runtime_kernel.first_operator->builtin_options_as_SVDFOptions();
76 status = utils::checkCondition(options != nullptr);
77 if (status != Ok)
78 return status;
79
80 OMRuntimeShape input_shape(input);
81 OMRuntimeShape weights_feature_shape(weights_feature);
82 OMRuntimeShape weights_time_shape(weights_time);
83 OMRuntimeShape activation_state_shape(activation_state);
85
86 // Define input constants based on input tensor definition above:
87 const int rank = options->rank();
88 const int input_size = input_shape.dims(1);
89 const int batch_size = input_shape.dims(0);
90 const int num_filters = weights_feature_shape.dims(0);
91 status = utils::checkCondition(num_filters % rank == 0);
92 if (status != Ok)
93 return status;
94
95 const int num_units = num_filters / rank;
96 const int memory_size = weights_time_shape.dims(1);
97
98 status = utils::checkCondition(input_shape.dimensionsCount() == 2);
99 if (status != Ok)
100 return status;
101 // Validate Tensor Output:
102 // [0] = float/int8_t, {2, batch_size, num_units}
103 status =
104 utils::checkCondition(output_shape.dimensionsCount() == 2 and
105 output_shape.dims(0) == batch_size and output_shape.dims(1) == num_units);
106 if (status != Ok)
107 return status;
108
109 // Validate Weights Feature Input Tensor
110 status = utils::checkCondition(weights_feature_shape.dimensionsCount() == 2 and
111 weights_feature_shape.dims(1) == input_size);
112 if (status != Ok)
113 return status;
114
115 // Validate Weights Time Input Tensor:
116 status = utils::checkCondition(weights_time_shape.dimensionsCount() == 2 and
117 weights_time_shape.dims(0) == num_filters and
118 weights_time_shape.dims(1) == memory_size);
119 if (status != Ok)
120 return status;
121
122 // Validate Optional Bias Input Tensor:
123 if (bias != nullptr)
124 {
125 status = utils::checkCondition(OMRuntimeShape(bias).dims(0) == num_units);
126 if (status != Ok)
127 return status;
128 }
129
130 // Validate Activation State Input Tensor:
131 status = utils::checkCondition(activation_state_shape.dimensionsCount() == 2 and
132 activation_state_shape.dims(0) == batch_size and
133 activation_state_shape.dims(1) == memory_size * num_filters);
134 if (status != Ok)
135 return status;
136
137 if (input->type() == circle::TensorType_FLOAT32)
138 {
139 status = utils::checkCondition(weights_feature->type() == circle::TensorType_FLOAT32 and
140 weights_time->type() == circle::TensorType_FLOAT32 and
141 activation_state->type() == circle::TensorType_FLOAT32 and
142 output->type() == circle::TensorType_FLOAT32);
143 if (status != Ok)
144 return status;
145 if (bias)
146 {
147 status = utils::checkCondition(bias->type() == circle::TensorType_FLOAT32);
148 if (status != Ok)
149 return status;
150 }
151 }
152
153 return status;
154}
int32_t dimensionsCount() const
Definition Tensor.h:106
int32_t dims(int i) const
Definition Tensor.h:108
const circle::Operator * first_operator
OMStatus readKernel(uint16_t op_index, core::OMRuntimeContext &runtime_context)
const circle::Tensor * outputs[maxOutputSize]
const circle::Tensor * inputs[maxInputSize]
const luci_interpreter::RuntimeShape output_shape
constexpr uint32_t outputTensorIdx