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
43namespace onert_micro
44{
45namespace import
46{
47
49{
50 // Validate Tensor Inputs (dtype depends on quantization):
51 // [0] = Input, {2, batch_size, input_size}
52 // [1] = Weights Feature, {2, num_filters, input_size}
53 // [2] = Weights Time, {2, num_filters, memory_size}
54 // [3] = Bias (optional), {1, num_units}
55 // [4] = Activation State (variable), {2, batch_size, memory_size * num_filters}
56
57 OMRuntimeContext &runtime_context = config_args.runtime_context;
58 uint16_t op_index = config_args.kernel_index;
59
60 execute::OMRuntimeKernel runtime_kernel;
61 runtime_kernel.readKernel(op_index, runtime_context);
62
63 const circle::Tensor *input = runtime_kernel.inputs[inputTensorIdx];
64 const circle::Tensor *weights_feature = runtime_kernel.inputs[weightsFeatureTensorIdx];
65 const circle::Tensor *weights_time = runtime_kernel.inputs[weightsTimeTensorIdx];
66 const circle::Tensor *bias = runtime_kernel.inputs[biasTensorIdx];
67 const circle::Tensor *activation_state = runtime_kernel.inputs[inputActivationStateTensorIdx];
68
69 const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
70
71 assert(input != nullptr);
72 assert(weights_feature != nullptr);
73 assert(weights_time != nullptr);
74 // bias can be nullptr
75 assert(activation_state != nullptr);
76 assert(output != nullptr);
77
78 OMStatus status = Ok;
79
80 const auto *options = runtime_kernel.first_operator->builtin_options_as_SVDFOptions();
81 status = utils::checkCondition(options != nullptr);
82 if (status != Ok)
83 return status;
84
85 OMRuntimeShape input_shape(input);
86 OMRuntimeShape weights_feature_shape(weights_feature);
87 OMRuntimeShape weights_time_shape(weights_time);
88 OMRuntimeShape activation_state_shape(activation_state);
90
91 // Define input constants based on input tensor definition above:
92 const int rank = options->rank();
93 const int input_size = input_shape.dims(1);
94 const int batch_size = input_shape.dims(0);
95 const int num_filters = weights_feature_shape.dims(0);
96 status = utils::checkCondition(num_filters % rank == 0);
97 if (status != Ok)
98 return status;
99
100 const int num_units = num_filters / rank;
101 const int memory_size = weights_time_shape.dims(1);
102
103 status = utils::checkCondition(input_shape.dimensionsCount() == 2);
104 if (status != Ok)
105 return status;
106 // Validate Tensor Output:
107 // [0] = float/int8_t, {2, batch_size, num_units}
108 status =
109 utils::checkCondition(output_shape.dimensionsCount() == 2 and
110 output_shape.dims(0) == batch_size and output_shape.dims(1) == num_units);
111 if (status != Ok)
112 return status;
113
114 // Validate Weights Feature Input Tensor
115 status = utils::checkCondition(weights_feature_shape.dimensionsCount() == 2 and
116 weights_feature_shape.dims(1) == input_size);
117 if (status != Ok)
118 return status;
119
120 // Validate Weights Time Input Tensor:
121 status = utils::checkCondition(weights_time_shape.dimensionsCount() == 2 and
122 weights_time_shape.dims(0) == num_filters and
123 weights_time_shape.dims(1) == memory_size);
124 if (status != Ok)
125 return status;
126
127 // Validate Optional Bias Input Tensor:
128 if (bias != nullptr)
129 {
130 status = utils::checkCondition(OMRuntimeShape(bias).dims(0) == num_units);
131 if (status != Ok)
132 return status;
133 }
134
135 // Validate Activation State Input Tensor:
136 status = utils::checkCondition(activation_state_shape.dimensionsCount() == 2 and
137 activation_state_shape.dims(0) == batch_size and
138 activation_state_shape.dims(1) == memory_size * num_filters);
139 if (status != Ok)
140 return status;
141
142 if (input->type() == circle::TensorType_FLOAT32)
143 {
144 status = utils::checkCondition(weights_feature->type() == circle::TensorType_FLOAT32 and
145 weights_time->type() == circle::TensorType_FLOAT32 and
146 activation_state->type() == circle::TensorType_FLOAT32 and
147 output->type() == circle::TensorType_FLOAT32);
148 if (status != Ok)
149 return status;
150 if (bias)
151 {
152 status = utils::checkCondition(bias->type() == circle::TensorType_FLOAT32);
153 if (status != Ok)
154 return status;
155 }
156 }
157
158 return status;
159}
160
161} // namespace import
162} // namespace onert_micro
int32_t dimensionsCount() const
Definition Tensor.h:106
int32_t dims(int i) const
Definition Tensor.h:108
size_t dimensionsCount() const noexcept
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
OMStatus configure_kernel_CircleSVDF(const OMConfigureArgs &config_args)
Definition SVDF.cpp:48
core::OMRuntimeContext & runtime_context