ArmNN
 20.02
NeonCreateWorkloadTests.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
7 
10 
12 
17 
18 BOOST_AUTO_TEST_SUITE(CreateWorkloadNeon)
19 
20 namespace
21 {
22 
23 boost::test_tools::predicate_result CompareIAclTensorHandleShape(IAclTensorHandle* tensorHandle,
24  std::initializer_list<unsigned int> expectedDimensions)
25 {
26  return CompareTensorHandleShape<IAclTensorHandle>(tensorHandle, expectedDimensions);
27 }
28 
29 bool TestNeonTensorHandleInfo(armnn::IAclTensorHandle* handle, const armnn::TensorInfo& expectedInfo)
30 {
31  using namespace armnn::armcomputetensorutils;
32 
33  const arm_compute::ITensorInfo* handleInfo = handle->GetTensor().info();
34  const arm_compute::TensorInfo expectedAclInfo = BuildArmComputeTensorInfo(expectedInfo);
35 
36  if (handleInfo->data_type() != expectedAclInfo.data_type())
37  {
38  return false;
39  }
40 
41  if (handleInfo->num_dimensions() != expectedAclInfo.num_dimensions())
42  {
43  return false;
44  }
45 
46  if (handleInfo->quantization_info() != expectedAclInfo.quantization_info())
47  {
48  return false;
49  }
50 
51  for (std::size_t d = 0; d < expectedAclInfo.num_dimensions(); ++d)
52  {
53  if (handleInfo->dimension(d) != expectedAclInfo.dimension(d))
54  {
55  return false;
56  }
57  }
58 
59  return true;
60 }
61 
62 } // namespace
63 
64 template <typename armnn::DataType DataType>
65 static void NeonCreateActivationWorkloadTest()
66 {
67  Graph graph;
68  NeonWorkloadFactory factory =
69  NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
70 
71  auto workload = CreateActivationWorkloadTest<NeonActivationWorkload, DataType>(factory, graph);
72 
73  // Checks that inputs/outputs are as we expect them (see definition of CreateActivationWorkloadTest).
74  ActivationQueueDescriptor queueDescriptor = workload->GetData();
75  auto inputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[0]);
76  auto outputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[0]);
77  BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({1, 1}, DataType)));
78  BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({1, 1}, DataType)));
79 }
80 
81 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
82 BOOST_AUTO_TEST_CASE(CreateActivationFloat16Workload)
83 {
84  NeonCreateActivationWorkloadTest<DataType::Float16>();
85 }
86 #endif
87 
88 BOOST_AUTO_TEST_CASE(CreateActivationFloatWorkload)
89 {
90  NeonCreateActivationWorkloadTest<DataType::Float32>();
91 }
92 
93 template <typename WorkloadType,
94  typename DescriptorType,
95  typename LayerType,
97 static void NeonCreateElementwiseWorkloadTest()
98 {
99  Graph graph;
100  NeonWorkloadFactory factory =
101  NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
102 
103  auto workload = CreateElementwiseWorkloadTest<WorkloadType, DescriptorType, LayerType, DataType>(factory, graph);
104 
105  DescriptorType queueDescriptor = workload->GetData();
106  auto inputHandle1 = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[0]);
107  auto inputHandle2 = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[1]);
108  auto outputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[0]);
109  BOOST_TEST(TestNeonTensorHandleInfo(inputHandle1, TensorInfo({2, 3}, DataType)));
110  BOOST_TEST(TestNeonTensorHandleInfo(inputHandle2, TensorInfo({2, 3}, DataType)));
111  BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({2, 3}, DataType)));
112 }
113 
114 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
115 BOOST_AUTO_TEST_CASE(CreateAdditionFloat16Workload)
116 {
117  NeonCreateElementwiseWorkloadTest<NeonAdditionWorkload,
121 }
122 #endif
123 
124 BOOST_AUTO_TEST_CASE(CreateAdditionFloatWorkload)
125 {
126  NeonCreateElementwiseWorkloadTest<NeonAdditionWorkload,
130 }
131 
132 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
133 BOOST_AUTO_TEST_CASE(CreateSubtractionFloat16Workload)
134 {
135  NeonCreateElementwiseWorkloadTest<NeonSubtractionWorkload,
139 }
140 #endif
141 
142 BOOST_AUTO_TEST_CASE(CreateSubtractionFloatWorkload)
143 {
144  NeonCreateElementwiseWorkloadTest<NeonSubtractionWorkload,
148 }
149 
150 BOOST_AUTO_TEST_CASE(CreateSubtractionUint8Workload)
151 {
152  NeonCreateElementwiseWorkloadTest<NeonSubtractionWorkload,
156 }
157 
158 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
159 BOOST_AUTO_TEST_CASE(CreateMultiplicationFloat16Workload)
160 {
161  NeonCreateElementwiseWorkloadTest<NeonMultiplicationWorkload,
165 }
166 #endif
167 
168 BOOST_AUTO_TEST_CASE(CreateMultiplicationFloatWorkload)
169 {
170  NeonCreateElementwiseWorkloadTest<NeonMultiplicationWorkload,
174 }
175 
176 BOOST_AUTO_TEST_CASE(CreateMultiplicationUint8Workload)
177 {
178  NeonCreateElementwiseWorkloadTest<NeonMultiplicationWorkload,
182 }
183 
184 BOOST_AUTO_TEST_CASE(CreateDivisionFloatWorkloadTest)
185 {
186  NeonCreateElementwiseWorkloadTest<NeonDivisionWorkload,
190 }
191 
192 template <typename BatchNormalizationWorkloadType, typename armnn::DataType DataType>
193 static void NeonCreateBatchNormalizationWorkloadTest(DataLayout dataLayout)
194 {
195  Graph graph;
196  NeonWorkloadFactory factory =
197  NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
198 
199  auto workload = CreateBatchNormalizationWorkloadTest<BatchNormalizationWorkloadType, DataType>
200  (factory, graph, dataLayout);
201 
202  // Checks that outputs and inputs are as we expect them (see definition of CreateBatchNormalizationWorkloadTest).
203  BatchNormalizationQueueDescriptor queueDescriptor = workload->GetData();
204  auto inputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[0]);
205  auto outputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[0]);
206 
207  TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{2, 3, 4, 4} : TensorShape{2, 4, 4, 3};
208  TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{2, 3, 4, 4} : TensorShape{2, 4, 4, 3};
209 
210  BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo(inputShape, DataType)));
211  BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, DataType)));
212 }
213 
214 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
215 BOOST_AUTO_TEST_CASE(CreateBatchNormalizationFloat16NchwWorkload)
216 {
217  NeonCreateBatchNormalizationWorkloadTest<NeonBatchNormalizationWorkload, DataType::Float16>(DataLayout::NCHW);
218 }
219 
220 BOOST_AUTO_TEST_CASE(CreateBatchNormalizationFloat16NhwcWorkload)
221 {
222  NeonCreateBatchNormalizationWorkloadTest<NeonBatchNormalizationWorkload, DataType::Float16>(DataLayout::NHWC);
223 }
224 #endif
225 
226 BOOST_AUTO_TEST_CASE(CreateBatchNormalizationFloatNchwWorkload)
227 {
228  NeonCreateBatchNormalizationWorkloadTest<NeonBatchNormalizationWorkload, DataType::Float32>(DataLayout::NCHW);
229 }
230 
231 BOOST_AUTO_TEST_CASE(CreateBatchNormalizationFloatNhwcWorkload)
232 {
233  NeonCreateBatchNormalizationWorkloadTest<NeonBatchNormalizationWorkload, DataType::Float32>(DataLayout::NHWC);
234 }
235 
236 template <typename armnn::DataType DataType>
237 static void NeonCreateConvolution2dWorkloadTest(DataLayout dataLayout = DataLayout::NCHW)
238 {
239  Graph graph;
240  NeonWorkloadFactory factory =
241  NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
242 
243  auto workload = CreateConvolution2dWorkloadTest<NeonConvolution2dWorkload, DataType>(factory, graph, dataLayout);
244 
245  TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{2, 3, 8, 16} : TensorShape{2, 8, 16, 3};
246  TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{2, 2, 2, 10} : TensorShape{2, 2, 10, 2};
247 
248  // Checks that outputs and inputs are as we expect them (see definition of CreateConvolution2dWorkloadTest).
249  Convolution2dQueueDescriptor queueDescriptor = workload->GetData();
250  auto inputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[0]);
251  auto outputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[0]);
252  BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo(inputShape, DataType)));
253  BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, DataType)));
254 }
255 
256 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
257 BOOST_AUTO_TEST_CASE(CreateConvolution2dFloat16NchwWorkload)
258 {
259  NeonCreateConvolution2dWorkloadTest<DataType::Float16>();
260 }
261 
262 BOOST_AUTO_TEST_CASE(CreateConvolution2dFloat16NhwcWorkload)
263 {
264  NeonCreateConvolution2dWorkloadTest<DataType::Float16>(DataLayout::NHWC);
265 }
266 
267 #endif
268 BOOST_AUTO_TEST_CASE(CreateConvolution2dFloatNchwWorkload)
269 {
270  NeonCreateConvolution2dWorkloadTest<DataType::Float32>();
271 }
272 
273 BOOST_AUTO_TEST_CASE(CreateConvolution2dFloatNhwcWorkload)
274 {
275  NeonCreateConvolution2dWorkloadTest<DataType::Float32>(DataLayout::NHWC);
276 }
277 
278 template <typename armnn::DataType DataType>
279 static void NeonCreateDepthWiseConvolutionWorkloadTest(DataLayout dataLayout)
280 {
281  Graph graph;
282  NeonWorkloadFactory factory =
283  NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
284 
285  auto workload = CreateDepthwiseConvolution2dWorkloadTest<NeonDepthwiseConvolutionWorkload,
286  DataType>(factory, graph, dataLayout);
287 
288  // Checks that inputs/outputs are as we expect them (see definition of CreateNormalizationWorkloadTest).
289  DepthwiseConvolution2dQueueDescriptor queueDescriptor = workload->GetData();
290  auto inputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[0]);
291  auto outputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[0]);
292 
293  TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? std::initializer_list<unsigned int>({ 2, 2, 5, 5 })
294  : std::initializer_list<unsigned int>({ 2, 5, 5, 2 });
295  TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? std::initializer_list<unsigned int>({ 2, 2, 5, 5 })
296  : std::initializer_list<unsigned int>({ 2, 5, 5, 2 });
297 
298  BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo(inputShape, DataType)));
299  BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, DataType)));
300 }
301 
302 BOOST_AUTO_TEST_CASE(CreateDepthWiseConvolution2dFloat32NhwcWorkload)
303 {
304  NeonCreateDepthWiseConvolutionWorkloadTest<DataType::Float32>(DataLayout::NHWC);
305 }
306 
307 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
308 BOOST_AUTO_TEST_CASE(CreateDepthWiseConvolution2dFloat16NhwcWorkload)
309 {
310  NeonCreateDepthWiseConvolutionWorkloadTest<DataType::Float16>(DataLayout::NHWC);
311 }
312 #endif
313 
314 template <typename FullyConnectedWorkloadType, typename armnn::DataType DataType>
315 static void NeonCreateFullyConnectedWorkloadTest()
316 {
317  Graph graph;
318  NeonWorkloadFactory factory =
319  NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
320 
321  auto workload = CreateFullyConnectedWorkloadTest<FullyConnectedWorkloadType, DataType>(factory, graph);
322 
323  // Checks that outputs and inputs are as we expect them (see definition of CreateFullyConnectedWorkloadTest).
324  FullyConnectedQueueDescriptor queueDescriptor = workload->GetData();
325  auto inputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[0]);
326  auto outputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[0]);
327  BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({3, 1, 4, 5}, DataType)));
328  BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({3, 7}, DataType)));
329 }
330 
331 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
332 BOOST_AUTO_TEST_CASE(CreateFullyConnectedFloat16Workload)
333 {
334  NeonCreateFullyConnectedWorkloadTest<NeonFullyConnectedWorkload, DataType::Float16>();
335 }
336 #endif
337 
338 BOOST_AUTO_TEST_CASE(CreateFullyConnectedFloatWorkload)
339 {
340  NeonCreateFullyConnectedWorkloadTest<NeonFullyConnectedWorkload, DataType::Float32>();
341 }
342 
343 template <typename NormalizationWorkloadType, typename armnn::DataType DataType>
344 static void NeonCreateNormalizationWorkloadTest(DataLayout dataLayout)
345 {
346  Graph graph;
347  NeonWorkloadFactory factory =
348  NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
349 
350  auto workload = CreateNormalizationWorkloadTest<NormalizationWorkloadType, DataType>(factory, graph, dataLayout);
351 
352  // Checks that outputs and inputs are as we expect them (see definition of CreateNormalizationWorkloadTest).
353  NormalizationQueueDescriptor queueDescriptor = workload->GetData();
354  auto inputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[0]);
355  auto outputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[0]);
356 
357  TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{3, 5, 5, 1} : TensorShape{3, 1, 5, 5};
358  TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{3, 5, 5, 1} : TensorShape{3, 1, 5, 5};
359 
360  BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo(inputShape, DataType)));
361  BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, DataType)));
362 }
363 
364 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
365 BOOST_AUTO_TEST_CASE(CreateNormalizationFloat16NchwWorkload)
366 {
367  NeonCreateNormalizationWorkloadTest<NeonNormalizationFloatWorkload, DataType::Float16>(DataLayout::NCHW);
368 }
369 
370 BOOST_AUTO_TEST_CASE(CreateNormalizationFloat16NhwcWorkload)
371 {
372  NeonCreateNormalizationWorkloadTest<NeonNormalizationFloatWorkload, DataType::Float16>(DataLayout::NHWC);
373 }
374 #endif
375 
376 BOOST_AUTO_TEST_CASE(CreateNormalizationFloatNchwWorkload)
377 {
378  NeonCreateNormalizationWorkloadTest<NeonNormalizationFloatWorkload, DataType::Float32>(DataLayout::NCHW);
379 }
380 
381 BOOST_AUTO_TEST_CASE(CreateNormalizationFloatNhwcWorkload)
382 {
383  NeonCreateNormalizationWorkloadTest<NeonNormalizationFloatWorkload, DataType::Float32>(DataLayout::NHWC);
384 }
385 
386 
387 template <typename armnn::DataType DataType>
388 static void NeonCreatePooling2dWorkloadTest(DataLayout dataLayout = DataLayout::NCHW)
389 {
390  Graph graph;
391  NeonWorkloadFactory factory =
392  NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
393 
394  auto workload = CreatePooling2dWorkloadTest<NeonPooling2dWorkload, DataType>(factory, graph, dataLayout);
395 
396  TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{3, 2, 5, 5} : TensorShape{3, 5, 5, 2};
397  TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{3, 2, 2, 4} : TensorShape{3, 2, 4, 2};
398 
399  // Checks that outputs and inputs are as we expect them (see definition of CreatePooling2dWorkloadTest).
400  Pooling2dQueueDescriptor queueDescriptor = workload->GetData();
401  auto inputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[0]);
402  auto outputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[0]);
403  BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo(inputShape, DataType)));
404  BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, DataType)));
405 }
406 
407 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
408 BOOST_AUTO_TEST_CASE(CreatePooling2dFloat16Workload)
409 {
410  NeonCreatePooling2dWorkloadTest<DataType::Float16>();
411 }
412 #endif
413 
414 BOOST_AUTO_TEST_CASE(CreatePooling2dFloatNchwWorkload)
415 {
416  NeonCreatePooling2dWorkloadTest<DataType::Float32>(DataLayout::NCHW);
417 }
418 
419 BOOST_AUTO_TEST_CASE(CreatePooling2dFloatNhwcWorkload)
420 {
421  NeonCreatePooling2dWorkloadTest<DataType::Float32>(DataLayout::NHWC);
422 }
423 
424 BOOST_AUTO_TEST_CASE(CreatePooling2dUint8NchwWorkload)
425 {
426  NeonCreatePooling2dWorkloadTest<DataType::QAsymmU8>(DataLayout::NCHW);
427 }
428 
429 BOOST_AUTO_TEST_CASE(CreatePooling2dUint8NhwcWorkload)
430 {
431  NeonCreatePooling2dWorkloadTest<DataType::QAsymmU8>(DataLayout::NHWC);
432 }
433 
434 static void NeonCreatePreluWorkloadTest(const armnn::TensorShape& inputShape,
435  const armnn::TensorShape& alphaShape,
436  const armnn::TensorShape& outputShape,
437  armnn::DataType dataType)
438 {
439  Graph graph;
440  NeonWorkloadFactory factory =
441  NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
442 
443  auto workload = CreatePreluWorkloadTest<NeonPreluWorkload>(factory,
444  graph,
445  inputShape,
446  alphaShape,
447  outputShape,
448  dataType);
449 
450  // Checks that outputs and inputs are as we expect them (see definition of CreateReshapeWorkloadTest).
451  PreluQueueDescriptor queueDescriptor = workload->GetData();
452  auto inputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[0]);
453  auto alphaHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[1]);
454  auto outputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[0]);
455  BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo(inputShape, dataType)));
456  BOOST_TEST(TestNeonTensorHandleInfo(alphaHandle, TensorInfo(alphaShape, dataType)));
457  BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, dataType)));
458 }
459 
460 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
461  BOOST_AUTO_TEST_CASE(CreatePreluFloat16Workload)
462 {
463  NeonCreatePreluWorkloadTest({ 1, 4, 1, 2 }, { 5, 4, 3, 1 }, { 5, 4, 3, 2 }, DataType::Float16);
464 }
465 #endif
466 
467 BOOST_AUTO_TEST_CASE(CreatePreluFloatWorkload)
468 {
469  NeonCreatePreluWorkloadTest({ 1, 4, 1, 2 }, { 5, 4, 3, 1 }, { 5, 4, 3, 2 }, DataType::Float32);
470 }
471 
472 BOOST_AUTO_TEST_CASE(CreatePreluUint8Workload)
473 {
474  NeonCreatePreluWorkloadTest({ 1, 4, 1, 2 }, { 5, 4, 3, 1 }, { 5, 4, 3, 2 }, DataType::QAsymmU8);
475 }
476 
477 template <typename armnn::DataType DataType>
478 static void NeonCreateReshapeWorkloadTest()
479 {
480  Graph graph;
481  NeonWorkloadFactory factory =
482  NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
483 
484  auto workload = CreateReshapeWorkloadTest<NeonReshapeWorkload, DataType>(factory, graph);
485 
486  // Checks that outputs and inputs are as we expect them (see definition of CreateReshapeWorkloadTest).
487  ReshapeQueueDescriptor queueDescriptor = workload->GetData();
488  auto inputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[0]);
489  auto outputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[0]);
490  BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({4, 1}, DataType)));
491  BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({1, 4}, DataType)));
492 }
493 
494 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
495 BOOST_AUTO_TEST_CASE(CreateReshapeFloat16Workload)
496 {
497  NeonCreateReshapeWorkloadTest<DataType::Float16>();
498 }
499 #endif
500 
501 BOOST_AUTO_TEST_CASE(CreateReshapeFloatWorkload)
502 {
503  NeonCreateReshapeWorkloadTest<DataType::Float32>();
504 }
505 
506 BOOST_AUTO_TEST_CASE(CreateReshapeUint8Workload)
507 {
508  NeonCreateReshapeWorkloadTest<DataType::QAsymmU8>();
509 }
510 
511 template <typename ResizeWorkloadType, armnn::DataType DataType>
512 static void NeonCreateResizeWorkloadTest(DataLayout dataLayout)
513 {
514  Graph graph;
515  NeonWorkloadFactory factory =
516  NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
517  auto workload = CreateResizeBilinearWorkloadTest<ResizeWorkloadType, DataType>(factory, graph, dataLayout);
518 
519  auto queueDescriptor = workload->GetData();
520 
521  auto inputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[0]);
522  auto outputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[0]);
523 
524  switch (dataLayout)
525  {
526  case DataLayout::NHWC:
527  BOOST_TEST(CompareIAclTensorHandleShape(inputHandle, { 2, 4, 4, 3 }));
528  BOOST_TEST(CompareIAclTensorHandleShape(outputHandle, { 2, 2, 2, 3 }));
529  break;
530  case DataLayout::NCHW:
531  default:
532  BOOST_TEST(CompareIAclTensorHandleShape(inputHandle, { 2, 3, 4, 4 }));
533  BOOST_TEST(CompareIAclTensorHandleShape(outputHandle, { 2, 3, 2, 2 }));
534  }
535 }
536 
537 BOOST_AUTO_TEST_CASE(CreateResizeFloat32NchwWorkload)
538 {
539  NeonCreateResizeWorkloadTest<NeonResizeWorkload, armnn::DataType::Float32>(DataLayout::NCHW);
540 }
541 
542 BOOST_AUTO_TEST_CASE(CreateResizeUint8NchwWorkload)
543 {
544  NeonCreateResizeWorkloadTest<NeonResizeWorkload, armnn::DataType::QAsymmU8>(DataLayout::NCHW);
545 }
546 
547 BOOST_AUTO_TEST_CASE(CreateResizeFloat32NhwcWorkload)
548 {
549  NeonCreateResizeWorkloadTest<NeonResizeWorkload, armnn::DataType::Float32>(DataLayout::NHWC);
550 }
551 
552 BOOST_AUTO_TEST_CASE(CreateResizeUint8NhwcWorkload)
553 {
554  NeonCreateResizeWorkloadTest<NeonResizeWorkload, armnn::DataType::QAsymmU8>(DataLayout::NHWC);
555 }
556 
557 template <typename SoftmaxWorkloadType, typename armnn::DataType DataType>
558 static void NeonCreateSoftmaxWorkloadTest()
559 {
560  Graph graph;
561  NeonWorkloadFactory factory =
562  NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
563 
564  auto workload = CreateSoftmaxWorkloadTest<SoftmaxWorkloadType, DataType>(factory, graph);
565 
566  // Checks that outputs and inputs are as we expect them (see definition of CreateSoftmaxWorkloadTest).
567  SoftmaxQueueDescriptor queueDescriptor = workload->GetData();
568  auto inputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[0]);
569  auto outputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[0]);
570  BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({4, 1}, DataType)));
571  BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({4, 1}, DataType)));
572 }
573 
574 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
575 BOOST_AUTO_TEST_CASE(CreateSoftmaxFloat16Workload)
576 {
577  NeonCreateSoftmaxWorkloadTest<NeonSoftmaxFloatWorkload, DataType::Float16>();
578 }
579 #endif
580 
581 BOOST_AUTO_TEST_CASE(CreateSoftmaxFloatWorkload)
582 {
583  NeonCreateSoftmaxWorkloadTest<NeonSoftmaxFloatWorkload, DataType::Float32>();
584 }
585 
586 template <typename SpaceToDepthWorkloadType, typename armnn::DataType DataType>
587 static void NeonSpaceToDepthWorkloadTest()
588 {
589  Graph graph;
590  NeonWorkloadFactory factory =
591  NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
592 
593  auto workload = CreateSpaceToDepthWorkloadTest<SpaceToDepthWorkloadType, DataType>(factory, graph);
594 
595  SpaceToDepthQueueDescriptor queueDescriptor = workload->GetData();
596  auto inputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[0]);
597  auto outputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[0]);
598 
599  BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({ 1, 2, 2, 1 }, DataType)));
600  BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({ 1, 1, 1, 4 }, DataType)));
601 }
602 
603 BOOST_AUTO_TEST_CASE(CreateSpaceToDepthFloat32Workload)
604 {
605  NeonSpaceToDepthWorkloadTest<NeonSpaceToDepthWorkload, armnn::DataType::Float32>();
606 }
607 
608 BOOST_AUTO_TEST_CASE(CreateSpaceToDepthFloat16Workload)
609 {
610  NeonSpaceToDepthWorkloadTest<NeonSpaceToDepthWorkload, armnn::DataType::Float16>();
611 }
612 
613 BOOST_AUTO_TEST_CASE(CreateSpaceToDepthQAsymm8Workload)
614 {
615  NeonSpaceToDepthWorkloadTest<NeonSpaceToDepthWorkload, armnn::DataType::QAsymmU8>();
616 }
617 
618 BOOST_AUTO_TEST_CASE(CreateSpaceToDepthQSymm16Workload)
619 {
620  NeonSpaceToDepthWorkloadTest<NeonSpaceToDepthWorkload, armnn::DataType::QSymmS16>();
621 }
622 
623 BOOST_AUTO_TEST_CASE(CreateSplitterWorkload)
624 {
625  Graph graph;
626  NeonWorkloadFactory factory =
627  NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
628 
629  auto workload = CreateSplitterWorkloadTest<NeonSplitterWorkload, DataType::Float32>(factory, graph);
630 
631  // Checks that outputs are as we expect them (see definition of CreateSplitterWorkloadTest).
632  SplitterQueueDescriptor queueDescriptor = workload->GetData();
633  auto inputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[0]);
634  BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({5, 7, 7}, DataType::Float32)));
635 
636  auto outputHandle0 = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[0]);
637  BOOST_TEST(TestNeonTensorHandleInfo(outputHandle0, TensorInfo({1, 7, 7}, DataType::Float32)));
638 
639  auto outputHandle1 = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[1]);
640  BOOST_TEST(TestNeonTensorHandleInfo(outputHandle1, TensorInfo({2, 7, 7}, DataType::Float32)));
641 
642  auto outputHandle2 = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[2]);
643  BOOST_TEST(TestNeonTensorHandleInfo(outputHandle2, TensorInfo({2, 7, 7}, DataType::Float32)));
644 }
645 
646 BOOST_AUTO_TEST_CASE(CreateSplitterConcat)
647 {
648  // Tests that it is possible to decide which output of the splitter layer
649  // should be lined to which input of the concat layer.
650  // We tested that is is possible to specify 0th output
651  // of the splitter to be the 1st input to the concat, and the 1st output of the splitter to be 0th input
652  // of the concat.
653 
654  Graph graph;
655  NeonWorkloadFactory factory =
656  NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
657 
658  auto workloads =
659  CreateSplitterConcatWorkloadTest<NeonSplitterWorkload, NeonConcatWorkload,
660  DataType::Float32>(factory, graph);
661 
662  auto wlSplitter = std::move(workloads.first);
663  auto wlConcat = std::move(workloads.second);
664 
665  //Checks that the index of inputs/outputs matches what we declared on InputDescriptor construction.
666  armnn::IAclTensorHandle* sOut0 = dynamic_cast<armnn::IAclTensorHandle*>(wlSplitter->GetData().m_Outputs[0]);
667  armnn::IAclTensorHandle* sOut1 = dynamic_cast<armnn::IAclTensorHandle*>(wlSplitter->GetData().m_Outputs[1]);
668  armnn::IAclTensorHandle* mIn0 = dynamic_cast<armnn::IAclTensorHandle*>(wlConcat->GetData().m_Inputs[0]);
669  armnn::IAclTensorHandle* mIn1 = dynamic_cast<armnn::IAclTensorHandle*>(wlConcat->GetData().m_Inputs[1]);
670 
671  BOOST_TEST(sOut0);
672  BOOST_TEST(sOut1);
673  BOOST_TEST(mIn0);
674  BOOST_TEST(mIn1);
675 
676  bool validDataPointers = (sOut0 == mIn1) && (sOut1 == mIn0);
677 
678  BOOST_TEST(validDataPointers);
679 }
680 
681 BOOST_AUTO_TEST_CASE(CreateSingleOutputMultipleInputs)
682 {
683  // Tests that it is possible to assign multiple (two) different layers to each of the outputs of a splitter layer.
684  // We created a splitter with two outputs. That each of those outputs is used by two different activation layers
685 
686  Graph graph;
687  NeonWorkloadFactory factory =
688  NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
689 
690  std::unique_ptr<NeonSplitterWorkload> wlSplitter;
691  std::unique_ptr<NeonActivationWorkload> wlActiv0_0;
692  std::unique_ptr<NeonActivationWorkload> wlActiv0_1;
693  std::unique_ptr<NeonActivationWorkload> wlActiv1_0;
694  std::unique_ptr<NeonActivationWorkload> wlActiv1_1;
695 
696  CreateSplitterMultipleInputsOneOutputWorkloadTest<NeonSplitterWorkload,
697  NeonActivationWorkload, DataType::Float32>(factory, graph, wlSplitter, wlActiv0_0, wlActiv0_1,
698  wlActiv1_0, wlActiv1_1);
699 
700  armnn::IAclTensorHandle* sOut0 = dynamic_cast<armnn::IAclTensorHandle*>(wlSplitter->GetData().m_Outputs[0]);
701  armnn::IAclTensorHandle* sOut1 = dynamic_cast<armnn::IAclTensorHandle*>(wlSplitter->GetData().m_Outputs[1]);
702  armnn::IAclTensorHandle* activ0_0Im = dynamic_cast<armnn::IAclTensorHandle*>(wlActiv0_0->GetData().m_Inputs[0]);
703  armnn::IAclTensorHandle* activ0_1Im = dynamic_cast<armnn::IAclTensorHandle*>(wlActiv0_1->GetData().m_Inputs[0]);
704  armnn::IAclTensorHandle* activ1_0Im = dynamic_cast<armnn::IAclTensorHandle*>(wlActiv1_0->GetData().m_Inputs[0]);
705  armnn::IAclTensorHandle* activ1_1Im = dynamic_cast<armnn::IAclTensorHandle*>(wlActiv1_1->GetData().m_Inputs[0]);
706 
707 
708  BOOST_TEST(sOut0);
709  BOOST_TEST(sOut1);
710  BOOST_TEST(activ0_0Im);
711  BOOST_TEST(activ0_1Im);
712  BOOST_TEST(activ1_0Im);
713  BOOST_TEST(activ1_1Im);
714 
715  bool validDataPointers = (sOut0 == activ0_0Im) && (sOut0 == activ0_1Im) &&
716  (sOut1 == activ1_0Im) && (sOut1 == activ1_1Im);
717 
718  BOOST_TEST(validDataPointers);
719 }
720 
721 #if defined(ARMNNREF_ENABLED)
722 
723 // This test unit needs the reference backend, it's not available if the reference backend is not built
724 
725 BOOST_AUTO_TEST_CASE(CreateMemCopyWorkloadsNeon)
726 {
727  NeonWorkloadFactory factory =
728  NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
729  CreateMemCopyWorkloads<IAclTensorHandle>(factory);
730 }
731 
732 #endif
733 
734 template <typename L2NormalizationWorkloadType, typename armnn::DataType DataType>
735 static void NeonCreateL2NormalizationWorkloadTest(DataLayout dataLayout)
736 {
737  Graph graph;
738  NeonWorkloadFactory factory =
739  NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
740 
741  auto workload =
742  CreateL2NormalizationWorkloadTest<L2NormalizationWorkloadType, DataType>(factory, graph, dataLayout);
743 
744  // Checks that inputs/outputs are as we expect them (see definition of CreateNormalizationWorkloadTest).
745  L2NormalizationQueueDescriptor queueDescriptor = workload->GetData();
746  auto inputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[0]);
747  auto outputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[0]);
748 
749  TensorShape inputShape = (dataLayout == DataLayout::NCHW) ?
750  TensorShape{ 5, 20, 50, 67 } : TensorShape{ 5, 50, 67, 20 };
751  TensorShape outputShape = (dataLayout == DataLayout::NCHW) ?
752  TensorShape{ 5, 20, 50, 67 } : TensorShape{ 5, 50, 67, 20 };
753 
754  BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo(inputShape, DataType)));
755  BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, DataType)));
756 }
757 
758 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
759 BOOST_AUTO_TEST_CASE(CreateL2NormalizationFloat16NchwWorkload)
760 {
761  NeonCreateL2NormalizationWorkloadTest<NeonL2NormalizationFloatWorkload, DataType::Float16>(DataLayout::NCHW);
762 }
763 
764 BOOST_AUTO_TEST_CASE(CreateL2NormalizationFloat16NhwcWorkload)
765 {
766  NeonCreateL2NormalizationWorkloadTest<NeonL2NormalizationFloatWorkload, DataType::Float16>(DataLayout::NHWC);
767 }
768 #endif
769 
770 BOOST_AUTO_TEST_CASE(CreateL2NormalizationNchwWorkload)
771 {
772  NeonCreateL2NormalizationWorkloadTest<NeonL2NormalizationFloatWorkload, DataType::Float32>(DataLayout::NCHW);
773 }
774 
775 BOOST_AUTO_TEST_CASE(CreateL2NormalizationNhwcWorkload)
776 {
777  NeonCreateL2NormalizationWorkloadTest<NeonL2NormalizationFloatWorkload, DataType::Float32>(DataLayout::NHWC);
778 }
779 
780 template <typename LstmWorkloadType>
781 static void NeonCreateLstmWorkloadTest()
782 {
783  Graph graph;
784  NeonWorkloadFactory factory =
785  NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
786 
787  auto workload = CreateLstmWorkloadTest<LstmWorkloadType>(factory, graph);
788 
789  LstmQueueDescriptor queueDescriptor = workload->GetData();
790 
791  auto inputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[0]);
792  auto outputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[1]);
793 
794  BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({ 2, 2 }, DataType::Float32)));
795  BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({ 2, 4 }, DataType::Float32)));
796 }
797 
798 BOOST_AUTO_TEST_CASE(CreateLSTMWorkloadFloatWorkload)
799 {
800  NeonCreateLstmWorkloadTest<NeonLstmFloatWorkload>();
801 }
802 
803 template <typename ConcatWorkloadType, armnn::DataType DataType>
804 static void NeonCreateConcatWorkloadTest(std::initializer_list<unsigned int> outputShape,
805  unsigned int concatAxis)
806 {
807  Graph graph;
808  NeonWorkloadFactory factory =
809  NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
810 
811  auto workload = CreateConcatWorkloadTest<ConcatWorkloadType, DataType>(factory, graph, outputShape, concatAxis);
812 
813  ConcatQueueDescriptor queueDescriptor = workload->GetData();
814  auto inputHandle0 = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[0]);
815  auto inputHandle1 = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[1]);
816  auto outputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[0]);
817 
818  BOOST_TEST(TestNeonTensorHandleInfo(inputHandle0, TensorInfo({ 2, 3, 2, 5 }, DataType)));
819  BOOST_TEST(TestNeonTensorHandleInfo(inputHandle1, TensorInfo({ 2, 3, 2, 5 }, DataType)));
820  BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, DataType)));
821 }
822 
823 BOOST_AUTO_TEST_CASE(CreateConcatDim0Float32Workload)
824 {
825  NeonCreateConcatWorkloadTest<NeonConcatWorkload, armnn::DataType::Float32>({ 4, 3, 2, 5 }, 0);
826 }
827 
828 BOOST_AUTO_TEST_CASE(CreateConcatDim1Float32Workload)
829 {
830  NeonCreateConcatWorkloadTest<NeonConcatWorkload, armnn::DataType::Float32>({ 2, 6, 2, 5 }, 1);
831 }
832 
833 BOOST_AUTO_TEST_CASE(CreateConcatDim3Float32Workload)
834 {
835  NeonCreateConcatWorkloadTest<NeonConcatWorkload, armnn::DataType::Float32>({ 2, 3, 2, 10 }, 3);
836 }
837 
838 BOOST_AUTO_TEST_CASE(CreateConcatDim0Uint8Workload)
839 {
840  NeonCreateConcatWorkloadTest<NeonConcatWorkload, armnn::DataType::QAsymmU8>({ 4, 3, 2, 5 }, 0);
841 }
842 
843 BOOST_AUTO_TEST_CASE(CreateConcatDim1Uint8Workload)
844 {
845  NeonCreateConcatWorkloadTest<NeonConcatWorkload, armnn::DataType::QAsymmU8>({ 2, 6, 2, 5 }, 1);
846 }
847 
848 BOOST_AUTO_TEST_CASE(CreateConcatDim3Uint8Workload)
849 {
850  NeonCreateConcatWorkloadTest<NeonConcatWorkload, armnn::DataType::QAsymmU8>({ 2, 3, 2, 10 }, 3);
851 }
852 
853 template <armnn::DataType DataType>
854 static void NeonCreateStackWorkloadTest(const std::initializer_list<unsigned int>& inputShape,
855  const std::initializer_list<unsigned int>& outputShape,
856  unsigned int axis,
857  unsigned int numInputs)
858 {
859  armnn::Graph graph;
860  NeonWorkloadFactory factory =
861  NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
862 
863  auto workload = CreateStackWorkloadTest<NeonStackWorkload, DataType>(factory,
864  graph,
865  TensorShape(inputShape),
866  TensorShape(outputShape),
867  axis,
868  numInputs);
869 
870  // Check inputs and output are as expected
871  StackQueueDescriptor queueDescriptor = workload->GetData();
872  for (unsigned int i = 0; i < numInputs; ++i)
873  {
874  auto inputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[i]);
875  BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo(inputShape, DataType)));
876  }
877  auto outputHandle = boost::polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[0]);
878  BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, DataType)));
879 }
880 
881 BOOST_AUTO_TEST_CASE(CreateStackFloat32Workload)
882 {
883  NeonCreateStackWorkloadTest<armnn::DataType::Float32>({ 3, 4, 5 }, { 3, 4, 2, 5 }, 2, 2);
884 }
885 
886 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
887 BOOST_AUTO_TEST_CASE(CreateStackFloat16Workload)
888 {
889  NeonCreateStackWorkloadTest<armnn::DataType::Float16>({ 3, 4, 5 }, { 3, 4, 2, 5 }, 2, 2);
890 }
891 #endif
892 
893 BOOST_AUTO_TEST_CASE(CreateStackUint8Workload)
894 {
895  NeonCreateStackWorkloadTest<armnn::DataType::QAsymmU8>({ 3, 4, 5 }, { 3, 4, 2, 5 }, 2, 2);
896 }
897 
898 template <typename QuantizedLstmWorkloadType>
899 static void NeonCreateQuantizedLstmWorkloadTest()
900 {
902 
903  Graph graph;
904  NeonWorkloadFactory factory = NeonWorkloadFactoryHelper::GetFactory(NeonWorkloadFactoryHelper::GetMemoryManager());
905 
906  auto workload = CreateQuantizedLstmWorkloadTest<QuantizedLstmWorkloadType>(factory, graph);
907 
908  QuantizedLstmQueueDescriptor queueDescriptor = workload->GetData();
909 
910  IAclTensorHandle* inputHandle = polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[0]);
911  BOOST_TEST((inputHandle->GetShape() == TensorShape({2, 2})));
912  BOOST_TEST((inputHandle->GetDataType() == arm_compute::DataType::QASYMM8));
913 
914  IAclTensorHandle* cellStateInHandle = polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[1]);
915  BOOST_TEST((cellStateInHandle->GetShape() == TensorShape({2, 4})));
916  BOOST_TEST((cellStateInHandle->GetDataType() == arm_compute::DataType::QSYMM16));
917 
918  IAclTensorHandle* outputStateInHandle = polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Inputs[2]);
919  BOOST_TEST((outputStateInHandle->GetShape() == TensorShape({2, 4})));
920  BOOST_TEST((outputStateInHandle->GetDataType() == arm_compute::DataType::QASYMM8));
921 
922  IAclTensorHandle* cellStateOutHandle = polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[0]);
923  BOOST_TEST((cellStateOutHandle->GetShape() == TensorShape({2, 4})));
924  BOOST_TEST((cellStateOutHandle->GetDataType() == arm_compute::DataType::QSYMM16));
925 
926  IAclTensorHandle* outputStateOutHandle = polymorphic_downcast<IAclTensorHandle*>(queueDescriptor.m_Outputs[1]);
927  BOOST_TEST((outputStateOutHandle->GetShape() == TensorShape({2, 4})));
928  BOOST_TEST((outputStateOutHandle->GetDataType() == arm_compute::DataType::QASYMM8));
929 }
930 
931 BOOST_AUTO_TEST_CASE(CreateQuantizedLstmWorkload)
932 {
933  NeonCreateQuantizedLstmWorkloadTest<NeonQuantizedLstmWorkload>();
934 }
935 
BOOST_AUTO_TEST_SUITE(TensorflowLiteParser)
DestType polymorphic_downcast(SourceType value)
virtual arm_compute::ITensor & GetTensor()=0
DataLayout
Definition: Types.hpp:49
virtual arm_compute::DataType GetDataType() const =0
DataType
Definition: Types.hpp:32
BOOST_AUTO_TEST_CASE(CheckConvolution2dLayer)
virtual TensorShape GetShape() const =0
Get the number of elements for each dimension ordered from slowest iterating dimension to fastest ite...
This layer represents an addition operation.
BOOST_AUTO_TEST_SUITE_END()
This layer represents a subtraction operation.
std::vector< ITensorHandle * > m_Outputs
This layer represents a division operation.
std::vector< ITensorHandle * > m_Inputs
This layer represents a multiplication operation.