xref: /aosp_15_r20/external/ComputeLibrary/tests/validation/NEON/LSTMLayerQuantized.cpp (revision c217d954acce2dbc11938adb493fc0abd69584f3)
1 /*
2  * Copyright (c) 2019-2021 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #include "arm_compute/runtime/NEON/functions/NELSTMLayerQuantized.h"
25 
26 #include "tests/NEON/Accessor.h"
27 #include "tests/PaddingCalculator.h"
28 #include "tests/Utils.h"
29 #include "tests/datasets/LSTMLayerDataset.h"
30 #include "tests/framework/Asserts.h"
31 #include "tests/framework/Macros.h"
32 #include "tests/framework/datasets/Datasets.h"
33 #include "tests/validation/Validation.h"
34 
35 #include <vector>
36 
37 namespace arm_compute
38 {
39 namespace test
40 {
41 namespace validation
42 {
43 namespace
44 {
45 template <typename T>
fill_tensor(Tensor & tensor,const std::vector<T> & v)46 inline void fill_tensor(Tensor &tensor, const std::vector<T> &v)
47 {
48     // Import memory accounting for padding
49     TensorShape t_shape = tensor.info()->tensor_shape();
50     Window      window;
51     window.use_tensor_dimensions(t_shape);
52     Iterator out(&tensor, window);
53     execute_window_loop(window, [&](const Coordinates & id)
54     {
55         *reinterpret_cast<T *>(out.ptr()) = v[coord2index(t_shape, id)];
56     },
57     out);
58 }
59 
60 template <typename T>
fill_tensor(SimpleTensor<T> & tensor,const std::vector<T> & v)61 inline void fill_tensor(SimpleTensor<T> &tensor, const std::vector<T> &v)
62 {
63     std::memcpy(tensor.data(), v.data(), sizeof(T) * v.size());
64 }
65 
66 /** Tolerance for quantized asymmetric operations */
67 #if defined(__aarch64__)
68 constexpr AbsoluteTolerance<int16_t> tolerance_qsymm16(0);
69 #else  // defined(__aarch64__)
70 constexpr AbsoluteTolerance<int16_t> tolerance_qsymm16(1);
71 #endif // defined(__aarch64__)
72 
73 } // namespace
74 
75 TEST_SUITE(NEON)
TEST_SUITE(LSTMLayerQuantized)76 TEST_SUITE(LSTMLayerQuantized)
77 
78 // *INDENT-OFF*
79 // clang-format off
80 TEST_SUITE(IntegrationTestCase)
81 TEST_SUITE(MultSmallerEq1)
82 TEST_CASE(RunSmall, framework::DatasetMode::PRECOMMIT)
83 {
84     const int batch_size  = 2;
85     const int input_size  = 2;
86     const int output_size = 4;
87 
88 
89     QuantizationInfo qasymm(1.f / 128.f, 128);
90     QuantizationInfo qweights(1.f / 128.f, 128);
91     QuantizationInfo qsymm_3(8.f / 32768.f, 0);
92     QuantizationInfo qsymm_4(16.f / 32768.f, 0);
93 
94     TensorShape input_shape{ input_size, batch_size };
95     TensorShape input_weights_shape{ input_size, output_size };
96     TensorShape recurrent_weights_shape{ output_size, output_size };
97     TensorShape output_shape{ output_size, batch_size};
98     TensorShape bias_shape{ output_size };
99 
100     auto input_to_input_weights      = create_tensor<Tensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
101     auto input_to_forget_weights     = create_tensor<Tensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
102     auto input_to_cell_weights       = create_tensor<Tensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
103     auto input_to_output_weights     = create_tensor<Tensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
104     auto recurrent_to_input_weights  = create_tensor<Tensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
105     auto recurrent_to_forget_weights = create_tensor<Tensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
106     auto recurrent_to_cell_weights   = create_tensor<Tensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
107     auto recurrent_to_output_weights = create_tensor<Tensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
108     auto input_gate_bias             = create_tensor<Tensor>(bias_shape, DataType::S32);
109     auto forget_gate_bias            = create_tensor<Tensor>(bias_shape, DataType::S32);
110     auto cell_gate_bias              = create_tensor<Tensor>(bias_shape, DataType::S32);
111     auto output_gate_bias            = create_tensor<Tensor>(bias_shape, DataType::S32);
112 
113     // LSTM input
114     auto input = create_tensor<Tensor>(input_shape, DataType::QASYMM8, 1, qasymm);
115 
116     // LSTM output state
117     auto output_state = create_tensor<Tensor>(output_shape, DataType::QASYMM8, 1, qasymm);
118 
119     // LSTM cell state
120     auto cell_state = create_tensor<Tensor>(output_shape, DataType::QSYMM16, 1, qsymm_4);
121 
122     NELSTMLayerQuantized lstmq;
123 
124     lstmq.configure(&input, &input_to_input_weights, &input_to_forget_weights, &input_to_cell_weights, &input_to_output_weights,
125                     &recurrent_to_input_weights, &recurrent_to_forget_weights, &recurrent_to_cell_weights, &recurrent_to_output_weights,
126                     &input_gate_bias, &forget_gate_bias, &cell_gate_bias, &output_gate_bias, &cell_state, &output_state, &cell_state, &output_state);
127 
128     input.allocator()->allocate();
129     input_to_input_weights.allocator()->allocate();
130     input_to_forget_weights.allocator()->allocate();
131     input_to_cell_weights.allocator()->allocate();
132     input_to_output_weights.allocator()->allocate();
133     recurrent_to_input_weights.allocator()->allocate();
134     recurrent_to_forget_weights.allocator()->allocate();
135     recurrent_to_cell_weights.allocator()->allocate();
136     recurrent_to_output_weights.allocator()->allocate();
137     input_gate_bias.allocator()->allocate();
138     forget_gate_bias.allocator()->allocate();
139     cell_gate_bias.allocator()->allocate();
140     output_gate_bias.allocator()->allocate();
141     cell_state.allocator()->allocate();
142     output_state.allocator()->allocate();
143 
144     // Fill weights and biases
145     fill_tensor(input_to_input_weights, std::vector<uint8_t>{ 47,  168,
146                                                               66,  239,
147                                                                6,   42,
148                                                              237,  236 });
149 
150     fill_tensor(input_to_forget_weights, std::vector<uint8_t> { 204,  193,
151                                                                 148,  59,
152                                                                 113,  17,
153                                                                  66, 197 });
154 
155     fill_tensor(input_to_cell_weights, std::vector<uint8_t> { 172,  101,
156                                                               184, 209,
157                                                               165,  82,
158                                                               108, 209 });
159 
160     fill_tensor(input_to_output_weights, std::vector<uint8_t> { 203, 244,
161                                                                 219, 114,
162                                                                 130,  16,
163                                                                 163, 222 });
164 
165     fill_tensor(recurrent_to_input_weights, std::vector<uint8_t> { 162, 168,  7,  95,
166                                                                     91, 155, 108, 216,
167                                                                    255, 100,  48, 188,
168                                                                     58,  37, 186, 147 });
169 
170     fill_tensor(recurrent_to_forget_weights, std::vector<uint8_t> {  46,  58,  47, 170,
171                                                                     246,  96,  12,  99,
172                                                                      68,  23, 186, 161,
173                                                                     237, 164,  89,   6 });
174 
175     fill_tensor(recurrent_to_cell_weights, std::vector<uint8_t> { 234,  99,   71, 206,
176                                                                   205, 159,   64, 253,
177                                                                   191, 148,  116,   8,
178                                                                   209, 136,   59, 138 });
179 
180     fill_tensor(recurrent_to_output_weights, std::vector<uint8_t> {  23, 241, 137, 36,
181                                                                     206,   5, 227, 56,
182                                                                     254, 176, 231, 47,
183                                                                      18, 201, 161, 11 });
184 
185     fill_tensor(input_gate_bias, std::vector<int>  {-103038,   30525,  115255, -38154 });
186     fill_tensor(forget_gate_bias, std::vector<int> { -23428,  126970,  116806,  46307 });
187     fill_tensor(cell_gate_bias, std::vector<int>   { 128006,   69949,  -42808,  42568 });
188     fill_tensor(output_gate_bias, std::vector<int> { -67066,  -53607,   47233,  7300  });
189 
190     SimpleTensor<uint8_t> expected_output(output_shape, DataType::QASYMM8, 1, qasymm);
191 
192     // Initialize state
193     fill_tensor(output_state, std::vector<uint8_t> { 128, 128, 128, 128,
194                                                      128, 128, 128, 128 });
195     fill_tensor(cell_state, std::vector<int16_t> { 0, 0, 0, 0,
196                                                    0, 0, 0, 0 });
197 
198     // First input
199     fill_tensor(input, std::vector<uint8_t> { 106,  193,
200                                               155,  150 });
201 
202     fill_tensor(expected_output, std::vector<uint8_t> { 128, 130,  36, 134,
203                                                         128, 131,  35, 133 });
204 
205     lstmq.run();
206     validate(Accessor(output_state), expected_output, tolerance_qsymm16);
207 
208     // Second input
209     fill_tensor(expected_output, std::vector<uint8_t> { 128, 129, 12, 137,
210                                                         128, 131, 10, 136 });
211     lstmq.run();
212     validate(Accessor(output_state), expected_output, tolerance_qsymm16);
213 
214     // Third input
215     fill_tensor(expected_output, std::vector<uint8_t> { 128, 129, 8, 140,
216                                                         128, 130, 6, 138 });
217     lstmq.run();
218     validate(Accessor(output_state), expected_output, tolerance_qsymm16);
219 }
220 
TEST_CASE(RunLarge,framework::DatasetMode::PRECOMMIT)221 TEST_CASE(RunLarge, framework::DatasetMode::PRECOMMIT)
222 {
223     const int batch_size  = 16;
224     const int input_size  = 8;
225     const int output_size = 8;
226 
227 
228     QuantizationInfo qasymm(1.f / 128.f, 128);
229     QuantizationInfo qweights(1.f / 128.f, 128);
230     QuantizationInfo qsymm_3(8.f / 32768.f, 0);
231     QuantizationInfo qsymm_4(16.f / 32768.f, 0);
232 
233     TensorShape input_shape{ input_size, batch_size };
234     TensorShape input_weights_shape{ input_size, output_size };
235     TensorShape recurrent_weights_shape{ output_size, output_size };
236     TensorShape output_shape{ output_size, batch_size};
237     TensorShape bias_shape{ output_size };
238 
239     auto input_to_input_weights      = create_tensor<Tensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
240     auto input_to_forget_weights     = create_tensor<Tensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
241     auto input_to_cell_weights       = create_tensor<Tensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
242     auto input_to_output_weights     = create_tensor<Tensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
243     auto recurrent_to_input_weights  = create_tensor<Tensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
244     auto recurrent_to_forget_weights = create_tensor<Tensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
245     auto recurrent_to_cell_weights   = create_tensor<Tensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
246     auto recurrent_to_output_weights = create_tensor<Tensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
247     auto input_gate_bias             = create_tensor<Tensor>(bias_shape, DataType::S32);
248     auto forget_gate_bias            = create_tensor<Tensor>(bias_shape, DataType::S32);
249     auto cell_gate_bias              = create_tensor<Tensor>(bias_shape, DataType::S32);
250     auto output_gate_bias            = create_tensor<Tensor>(bias_shape, DataType::S32);
251 
252     // LSTM input
253     auto input = create_tensor<Tensor>(input_shape, DataType::QASYMM8, 1, qasymm);
254 
255     // LSTM output state
256     auto output_state = create_tensor<Tensor>(output_shape, DataType::QASYMM8, 1, qasymm);
257 
258     // LSTM cell state
259     auto cell_state = create_tensor<Tensor>(output_shape, DataType::QSYMM16, 1, qsymm_4);
260 
261     NELSTMLayerQuantized lstmq;
262 
263     lstmq.configure(&input, &input_to_input_weights, &input_to_forget_weights, &input_to_cell_weights, &input_to_output_weights,
264                     &recurrent_to_input_weights, &recurrent_to_forget_weights, &recurrent_to_cell_weights, &recurrent_to_output_weights,
265                     &input_gate_bias, &forget_gate_bias, &cell_gate_bias, &output_gate_bias, &cell_state, &output_state, &cell_state, &output_state);
266 
267     input.allocator()->allocate();
268     input_to_input_weights.allocator()->allocate();
269     input_to_forget_weights.allocator()->allocate();
270     input_to_cell_weights.allocator()->allocate();
271     input_to_output_weights.allocator()->allocate();
272     recurrent_to_input_weights.allocator()->allocate();
273     recurrent_to_forget_weights.allocator()->allocate();
274     recurrent_to_cell_weights.allocator()->allocate();
275     recurrent_to_output_weights.allocator()->allocate();
276     input_gate_bias.allocator()->allocate();
277     forget_gate_bias.allocator()->allocate();
278     cell_gate_bias.allocator()->allocate();
279     output_gate_bias.allocator()->allocate();
280     cell_state.allocator()->allocate();
281     output_state.allocator()->allocate();
282 
283     // Fill weights and biases
284     fill_tensor(input_to_input_weights, std::vector<uint8_t>{ 141,  89, 200, 180,  46,  50,  87, 128,
285                                                               149, 227, 177, 187, 212, 229,  54, 111,
286                                                               131, 116,   3,  58, 196,  26, 131, 255,
287                                                                22, 106, 216,  69, 239,  12, 232, 207,
288                                                               184,  56, 236, 172,  28, 143, 161, 124,
289                                                               255,  33, 197, 122,  47, 197,  26, 229,
290                                                                91,  79,  11, 160,  26,  80, 100,  36,
291                                                               248, 186,  97,  61, 125,  46,  14, 100, });
292 
293     fill_tensor(input_to_forget_weights, std::vector<uint8_t> { 237, 165, 141, 249,  72, 116, 36 , 115,
294                                                                 234, 213,  85,  84,  59,  62, 150, 246,
295                                                                 182, 102, 158, 214, 182, 183,  94,  11,
296                                                                 158, 192,  92, 189, 160, 219, 206, 249,
297                                                                  88, 213, 193, 244, 151,  72, 129,  49,
298                                                                 239,  83, 106,   9, 169, 187, 125, 171,
299                                                                  32, 141, 126,  92,  13,  36, 224, 150,
300                                                                 187, 250, 178, 169,  89, 214,  91, 173 });
301 
302     fill_tensor(input_to_cell_weights, std::vector<uint8_t> {  93, 103, 226, 139, 185, 252, 129, 171,
303                                                               159,  32,  25, 175, 224, 183, 165,  35,
304                                                               207,  69, 238, 228, 149, 214,  79,   6,
305                                                                 5,  66, 102,  14,  19, 111,  36, 143,
306                                                                22,  85,  13,  78, 236, 121, 122,  77,
307                                                               249,  39,  88,  12, 205, 143,  93, 240,
308                                                               167,  89, 188,  50,  73,  69, 201, 251,
309                                                                59,  32, 203, 184, 139, 191, 199,  74});
310 
311     fill_tensor(input_to_output_weights, std::vector<uint8_t> { 205,   7,  95, 104, 252, 143, 226,  73,
312                                                                 229, 114, 152, 171, 221, 153,  73, 229,
313                                                                 153, 165, 223, 239, 100,  38, 172, 211,
314                                                                 226, 133, 239, 207, 116, 230, 170, 100,
315                                                                 241,  95, 171, 124,  63, 115,  32, 127,
316                                                                 141, 239,  53, 193, 201,  53, 104, 178,
317                                                                 186, 212, 167, 107, 226, 230,  71, 213,
318                                                                 148, 217,  19, 248, 233, 195, 183, 156 });
319 
320     fill_tensor(recurrent_to_input_weights, std::vector<uint8_t> { 147, 112, 140, 103,   3, 255,  17,  49,
321                                                                     84, 112, 144, 213, 138, 142, 112,  66,
322                                                                    117,  30, 101,  35,  25, 132, 211, 229,
323                                                                    183, 208, 102,  16,  38,  85, 101, 152,
324                                                                    226,  83, 132,  22, 161, 110, 157, 129,
325                                                                    184,  63, 168,  42, 220, 126, 209, 157,
326                                                                      5,  88, 243,  83, 249,  19, 226, 209,
327                                                                    173,  96, 185,  77, 146, 227, 238, 136 });
328 
329 
330     fill_tensor(recurrent_to_forget_weights, std::vector<uint8_t> {  52, 132,  92, 200, 213,  32, 213,  37,
331                                                                     116, 142, 116, 180,   4, 172, 158, 143,
332                                                                     110,  40,  99,  28, 221, 153, 133,   2,
333                                                                     247, 144, 198, 100,  20,  15, 221, 196,
334                                                                     159, 178, 188, 151, 171,  15,  25, 217,
335                                                                     178, 109, 110, 118, 128,  39, 232, 234,
336                                                                     184, 214, 177,  13,  56,   6,  28, 252,
337                                                                      89, 187, 242,  59, 146, 111, 132, 129});
338 
339     fill_tensor(recurrent_to_cell_weights, std::vector<uint8_t> {  70,  44, 137,  29,  36, 127,   1, 241,
340                                                                    26, 241, 142, 114,  67, 181,  49,  57,
341                                                                   131, 152, 175,  77,  23,  63,  37, 124,
342                                                                   150, 113,  95, 103, 110, 201,  69,  97,
343                                                                   196, 242,  62, 214,  66,  19,  45, 135,
344                                                                    22, 168, 149, 104,  77, 101,  36,  68,
345                                                                   170, 116, 222, 100, 109,   1, 154,  18,
346                                                                   133, 215, 105,  93,  31,  57, 231, 112 });
347 
348 
349     fill_tensor(recurrent_to_output_weights, std::vector<uint8_t> { 45 ,  181 ,  220 ,  219 ,   49  ,  63 ,   49  , 129,
350                                                                      7 ,  166 ,  104 ,  114 ,   83  ,  40 ,    1  , 195,
351                                                                    245 ,  142 ,   82 ,  232 ,  104  , 245 ,   82  , 196,
352                                                                    111 ,   56 ,  156 ,    9 ,  141  , 240 ,  180  , 148,
353                                                                    247 ,  198 ,  234 ,  137 ,   13  , 210 ,  161  , 192,
354                                                                    196 ,   59 ,  233 ,  184 ,  142  , 187 ,  140  , 166,
355                                                                      2 ,   95 ,  152 ,   46 ,   71  ,  46 ,  113  ,  32,
356                                                                    175 ,  229 ,   86 ,   87 ,   62  ,  93 ,   74  , 130});
357 
358     fill_tensor(input_gate_bias, std::vector<int>  {  -40040, -106916,  -92315,  -79123,   45160, -17954,   50962, -63758 });
359     fill_tensor(forget_gate_bias, std::vector<int> { -128514,    8463,  -57831,  116977,  106547, -28132, -124557,  44941 });
360     fill_tensor(cell_gate_bias, std::vector<int>   { 88388  ,  123601, -116148,  -13022,   21619,  48926,   57523,  39332 });
361     fill_tensor(output_gate_bias, std::vector<int> {  59485 ,  -33070,   21386, -100633, -115959, 125768,  -56407,  24897 });
362 
363     SimpleTensor<uint8_t> expected_output(output_shape, DataType::QASYMM8, 1, qasymm);
364 
365     // Initialize state
366     fill_tensor(output_state, std::vector<uint8_t> { 128, 128, 128, 128, 128, 128, 128, 128,
367                                                      128, 128, 128, 128, 128, 128, 128, 128,
368                                                      128, 128, 128, 128, 128, 128, 128, 128,
369                                                      128, 128, 128, 128, 128, 128, 128, 128,
370                                                      128, 128, 128, 128, 128, 128, 128, 128,
371                                                      128, 128, 128, 128, 128, 128, 128, 128,
372                                                      128, 128, 128, 128, 128, 128, 128, 128,
373                                                      128, 128, 128, 128, 128, 128, 128, 128,
374                                                      128, 128, 128, 128, 128, 128, 128, 128,
375                                                      128, 128, 128, 128, 128, 128, 128, 128,
376                                                      128, 128, 128, 128, 128, 128, 128, 128,
377                                                      128, 128, 128, 128, 128, 128, 128, 128,
378                                                      128, 128, 128, 128, 128, 128, 128, 128,
379                                                      128, 128, 128, 128, 128, 128, 128, 128,
380                                                      128, 128, 128, 128, 128, 128, 128, 128,
381                                                      128, 128, 128, 128, 128, 128, 128, 128 });
382 
383     fill_tensor(cell_state, std::vector<int16_t> { 0, 0, 0, 0, 0, 0, 0, 0,
384                                                    0, 0, 0, 0, 0, 0, 0, 0,
385                                                    0, 0, 0, 0, 0, 0, 0, 0,
386                                                    0, 0, 0, 0, 0, 0, 0, 0,
387                                                    0, 0, 0, 0, 0, 0, 0, 0,
388                                                    0, 0, 0, 0, 0, 0, 0, 0,
389                                                    0, 0, 0, 0, 0, 0, 0, 0,
390                                                    0, 0, 0, 0, 0, 0, 0, 0,
391                                                    0, 0, 0, 0, 0, 0, 0, 0,
392                                                    0, 0, 0, 0, 0, 0, 0, 0,
393                                                    0, 0, 0, 0, 0, 0, 0, 0,
394                                                    0, 0, 0, 0, 0, 0, 0, 0,
395                                                    0, 0, 0, 0, 0, 0, 0, 0,
396                                                    0, 0, 0, 0, 0, 0, 0, 0,
397                                                    0, 0, 0, 0, 0, 0, 0, 0,
398                                                    0, 0, 0, 0, 0, 0, 0, 0});
399 
400     // First input
401     fill_tensor(input, std::vector<uint8_t> { 247,  203, 159, 131, 182, 114, 207, 195,
402                                               48 ,  61 , 154,  16,  80, 101, 116, 255,
403                                               50 , 115 ,  45, 186,  75, 212,  98,  48,
404                                               88 , 146 ,  24, 143, 218, 174, 203, 200,
405                                              239 ,  16 ,  66, 136, 234,  54,  94,  51,
406                                              101 , 128 , 220, 213, 164,  82, 137, 255,
407                                               70 , 165 , 234, 220,  66,  35, 183, 206,
408                                               39 ,  57 , 180, 202,  23, 172, 224, 109,
409                                              102 , 215 , 186,  82, 215, 147,  85, 187,
410                                               96 , 249 ,  59, 116, 150,  44, 167, 128,
411                                               34 , 217 , 148, 193, 243,  38, 250, 208,
412                                              112 , 130 , 208,  29,  16, 122,  20,  92,
413                                               24 ,  72 , 104,  29, 150, 233, 151,  19,
414                                              158 , 192 , 254,  70,  73, 142, 106, 152,
415                                                3 ,  61 ,  24, 135, 212,   9,  80, 234,
416                                              147 , 246 ,  83, 249,  49,  14,  68,  50});
417 
418     fill_tensor(expected_output, std::vector<uint8_t> {131, 128,  128,  128,  128,  180,  129,  133,
419                                                        136, 128,  126,  128,  128,  173,  135,  130,
420                                                        160, 128,  128,  128,  128,  138,  132,  129,
421                                                        131, 128,  127,  128,  128,  169,  129,  131,
422                                                        133, 128,  128,  128,  128,  182,  130,  129,
423                                                        131, 128,  128,  128,  128,  163,  129,  130,
424                                                        131, 128,  128,  128,  128,  149,  132,  129,
425                                                        143, 128,  127,  128,  128,  150,  134,  131,
426                                                        134, 128,  128,  128,  128,  167,  130,  130,
427                                                        131, 128,  128,  128,  128,  152,  132,  129,
428                                                        128, 128,  128,  128,  128,  169,  130,  130,
429                                                        173, 128,  128,  128,  128,  148,  139,  130,
430                                                        152, 128,  128,  128,  128,  168,  139,  132,
431                                                        147, 128,  128,  128,  128,  161,  131,  132,
432                                                        130, 128,  128,  128,  128,  159,  134,  128,
433                                                        140, 128,  128,  128,  128,  133,  132,  128 });
434 
435     lstmq.run();
436     validate(Accessor(output_state), expected_output, tolerance_qsymm16);
437 
438     // Second input
439     fill_tensor(expected_output, std::vector<uint8_t> { 130,   128,   128,   128,   128,   205,   129,   137,
440                                                         135,   128,   127,   128,   128,   190,   137,   132,
441                                                         160,   128,   128,   128,   128,   142,   133,   131,
442                                                         130,   128,   128,   128,   128,   185,   129,   133,
443                                                         132,   128,   128,   128,   128,   198,   131,   130,
444                                                         130,   128,   128,   128,   128,   178,   130,   131,
445                                                         131,   128,   128,   128,   128,   158,   132,   131,
446                                                         142,   128,   127,   128,   128,   158,   135,   134,
447                                                         133,   128,   128,   128,   128,   178,   131,   132,
448                                                         131,   128,   128,   128,   128,   160,   132,   130,
449                                                         128,   128,   128,   128,   128,   190,   131,   131,
450                                                         170,   128,   128,   128,   128,   157,   142,   131,
451                                                         149,   128,   128,   128,   128,   178,   142,   135,
452                                                         145,   128,   128,   128,   129,   173,   132,   135,
453                                                         129,   128,   128,   128,   128,   171,   134,   129,
454                                                         140,   128,   128,   128,   128,   135,   132,   129});
455     lstmq.run();
456     validate(Accessor(output_state), expected_output, tolerance_qsymm16);
457 }
458 TEST_SUITE_END() // MultSmallerEq1
459 
TEST_SUITE(MultGreater1)460 TEST_SUITE(MultGreater1)
461 TEST_CASE(RunSmall, framework::DatasetMode::PRECOMMIT)
462 {
463     //Input sequence length is 1
464     const int batch_size  = 2;
465     const int input_size  = 2;
466     const int output_size = 4;
467 
468     QuantizationInfo qasymm(1.f / 128.f, 128);
469     QuantizationInfo qweights(1.f / 16.f, 16);
470     QuantizationInfo qsymm_3(8.f / 32768.f, 0);
471     QuantizationInfo qsymm_4(16.f / 32768.f, 0);
472 
473     TensorShape input_shape{ input_size, batch_size };
474     TensorShape input_weights_shape{ input_size, output_size };
475     TensorShape recurrent_weights_shape{ output_size, output_size };
476     TensorShape output_shape{ output_size, batch_size};
477     TensorShape bias_shape{ output_size };
478 
479     auto input_to_input_weights      = create_tensor<Tensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
480     auto input_to_forget_weights     = create_tensor<Tensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
481     auto input_to_cell_weights       = create_tensor<Tensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
482     auto input_to_output_weights     = create_tensor<Tensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
483     auto recurrent_to_input_weights  = create_tensor<Tensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
484     auto recurrent_to_forget_weights = create_tensor<Tensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
485     auto recurrent_to_cell_weights   = create_tensor<Tensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
486     auto recurrent_to_output_weights = create_tensor<Tensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
487     auto input_gate_bias             = create_tensor<Tensor>(bias_shape, DataType::S32);
488     auto forget_gate_bias            = create_tensor<Tensor>(bias_shape, DataType::S32);
489     auto cell_gate_bias              = create_tensor<Tensor>(bias_shape, DataType::S32);
490     auto output_gate_bias            = create_tensor<Tensor>(bias_shape, DataType::S32);
491 
492     // LSTM input
493     auto input = create_tensor<Tensor>(input_shape, DataType::QASYMM8, 1, qasymm);
494 
495     // LSTM output state
496     auto output_state = create_tensor<Tensor>(output_shape, DataType::QASYMM8, 1, qasymm);
497 
498     // LSTM cell state
499     auto cell_state = create_tensor<Tensor>(output_shape, DataType::QSYMM16, 1, qsymm_4);
500 
501     NELSTMLayerQuantized lstmq;
502 
503     lstmq.configure(&input, &input_to_input_weights, &input_to_forget_weights, &input_to_cell_weights, &input_to_output_weights,
504                     &recurrent_to_input_weights, &recurrent_to_forget_weights, &recurrent_to_cell_weights, &recurrent_to_output_weights,
505                     &input_gate_bias, &forget_gate_bias, &cell_gate_bias, &output_gate_bias, &cell_state, &output_state, &cell_state, &output_state);
506 
507     input.allocator()->allocate();
508     input_to_input_weights.allocator()->allocate();
509     input_to_forget_weights.allocator()->allocate();
510     input_to_cell_weights.allocator()->allocate();
511     input_to_output_weights.allocator()->allocate();
512     recurrent_to_input_weights.allocator()->allocate();
513     recurrent_to_forget_weights.allocator()->allocate();
514     recurrent_to_cell_weights.allocator()->allocate();
515     recurrent_to_output_weights.allocator()->allocate();
516     input_gate_bias.allocator()->allocate();
517     forget_gate_bias.allocator()->allocate();
518     cell_gate_bias.allocator()->allocate();
519     output_gate_bias.allocator()->allocate();
520     cell_state.allocator()->allocate();
521     output_state.allocator()->allocate();
522 
523     // Fill weights and biases
524     fill_tensor(input_to_input_weights, std::vector<uint8_t>{ 122,  130,
525                                                               124,  134,
526                                                                120,   122,
527                                                              134,  134 });
528 
529     fill_tensor(input_to_forget_weights, std::vector<uint8_t> { 204,  193,
530                                                                 148,  59,
531                                                                 113,  17,
532                                                                  66, 197 });
533 
534     fill_tensor(input_to_cell_weights, std::vector<uint8_t> { 172,  101,
535                                                               184, 209,
536                                                               165,  82,
537                                                               108, 209 });
538 
539     fill_tensor(input_to_output_weights, std::vector<uint8_t> { 203, 244,
540                                                                 219, 114,
541                                                                 130,  16,
542                                                                 163, 222 });
543 
544     fill_tensor(recurrent_to_input_weights, std::vector<uint8_t> { 162, 168,  7,  95,
545                                                                     91, 155, 108, 216,
546                                                                    255, 100,  48, 188,
547                                                                     58,  37, 186, 147 });
548 
549     fill_tensor(recurrent_to_forget_weights, std::vector<uint8_t> {  46,  58,  47, 170,
550                                                                     246,  96,  12,  99,
551                                                                      68,  23, 186, 161,
552                                                                     237, 164,  89,   6 });
553 
554     fill_tensor(recurrent_to_cell_weights, std::vector<uint8_t> { 234,  99,   71, 206,
555                                                                   205, 159,   64, 253,
556                                                                   191, 148,  116,   8,
557                                                                   209, 136,   59, 138 });
558 
559     fill_tensor(recurrent_to_output_weights, std::vector<uint8_t> {  23, 241, 137, 36,
560                                                                     206,   5, 227, 56,
561                                                                     254, 176, 231, 47,
562                                                                      18, 201, 161, 11 });
563 
564     fill_tensor(input_gate_bias, std::vector<int>  {-103038,   30525,  115255, -38154 });
565     fill_tensor(forget_gate_bias, std::vector<int> { -23428,  126970,  116806,  46307 });
566     fill_tensor(cell_gate_bias, std::vector<int>   { 128006,   69949,  -42808,  42568 });
567     fill_tensor(output_gate_bias, std::vector<int> { -67066,  -53607,   47233,  7300  });
568 
569     SimpleTensor<uint8_t> expected_output(output_shape, DataType::QASYMM8, 1, qasymm);
570 
571     // Initialize state
572     fill_tensor(output_state, std::vector<uint8_t> { 128, 128, 128, 128,
573                                                      128, 128, 128, 128 });
574     fill_tensor(cell_state, std::vector<int16_t> { 0, 0, 0, 0,
575                                                    0, 0, 0, 0 });
576 
577     // First input
578     fill_tensor(input, std::vector<uint8_t> { 106,  193,
579                                               155,  150 });
580 
581     fill_tensor(expected_output, std::vector<uint8_t> { 128, 128,  31, 128,
582                                                         128, 128,  31, 128 });
583 
584     lstmq.run();
585     validate(Accessor(output_state), expected_output);
586 
587     // Second input
588     fill_tensor(expected_output, std::vector<uint8_t> { 128, 128, 5, 128,
589                                                         128, 128, 5, 128 });
590     lstmq.run();
591     validate(Accessor(output_state), expected_output);
592 
593     // Third input
594     fill_tensor(expected_output, std::vector<uint8_t> { 128, 128, 1, 128,
595                                                         128, 128, 1, 128, });
596     lstmq.run();
597     validate(Accessor(output_state), expected_output);
598 }
599 TEST_SUITE_END() // MultGreater1
600 TEST_SUITE_END() // IntegrationTestCase
601 // clang-format on
602 // *INDENT-ON*
603 
604 TEST_SUITE_END() // LSTMLayerQuantized
605 TEST_SUITE_END() // Neon
606 } // namespace validation
607 } // namespace test
608 } // namespace arm_compute
609