IVGCVSW-3173 Extend reference softmax workload to support qsymm16
[platform/upstream/armnn.git] / src / backends / reference / test / RefCreateWorkloadTests.cpp
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include <test/CreateWorkload.hpp>
7
8 #include <backendsCommon/CpuTensorHandle.hpp>
9 #include <reference/RefWorkloadFactory.hpp>
10 #include <reference/workloads/RefWorkloads.hpp>
11
12 namespace
13 {
14
15 template<typename Workload>
16 void CheckInputOutput(std::unique_ptr<Workload> workload, const TensorInfo& inputInfo, const TensorInfo& outputInfo)
17 {
18     auto queueDescriptor = workload->GetData();
19     auto inputHandle  = boost::polymorphic_downcast<ConstCpuTensorHandle*>(queueDescriptor.m_Inputs[0]);
20     auto outputHandle = boost::polymorphic_downcast<CpuTensorHandle*>(queueDescriptor.m_Outputs[0]);
21     BOOST_TEST((inputHandle->GetTensorInfo() == inputInfo));
22     BOOST_TEST((outputHandle->GetTensorInfo() == outputInfo));
23 }
24
25 template <typename Workload>
26 void CheckInputsOutput(std::unique_ptr<Workload> workload,
27                        const TensorInfo&         inputInfo0,
28                        const TensorInfo&         inputInfo1,
29                        const TensorInfo&         outputInfo)
30 {
31     auto queueDescriptor = workload->GetData();
32     auto inputHandle0     = boost::polymorphic_downcast<ConstCpuTensorHandle*>(queueDescriptor.m_Inputs[0]);
33     auto inputHandle1     = boost::polymorphic_downcast<ConstCpuTensorHandle*>(queueDescriptor.m_Inputs[1]);
34     auto outputHandle    = boost::polymorphic_downcast<CpuTensorHandle*>(queueDescriptor.m_Outputs[0]);
35     BOOST_TEST((inputHandle0->GetTensorInfo() == inputInfo0));
36     BOOST_TEST((inputHandle1->GetTensorInfo() == inputInfo1));
37     BOOST_TEST((outputHandle->GetTensorInfo() == outputInfo));
38 }
39 }
40
41 BOOST_AUTO_TEST_SUITE(CreateWorkloadRef)
42
43 template <typename ActivationWorkloadType, armnn::DataType DataType>
44 static void RefCreateActivationWorkloadTest()
45 {
46     Graph graph;
47     RefWorkloadFactory factory;
48     auto workload = CreateActivationWorkloadTest<ActivationWorkloadType, DataType>(factory, graph);
49
50     // Checks that outputs are as we expect them (see definition of CreateActivationWorkloadTest).
51     CheckInputOutput(std::move(workload),
52         TensorInfo({ 1, 1 }, DataType),
53         TensorInfo({ 1, 1 }, DataType));
54 }
55
56 BOOST_AUTO_TEST_CASE(CreateActivationFloat32Workload)
57 {
58     RefCreateActivationWorkloadTest<RefActivationWorkload, armnn::DataType::Float32>();
59 }
60
61 BOOST_AUTO_TEST_CASE(CreateActivationUint8Workload)
62 {
63     RefCreateActivationWorkloadTest<RefActivationWorkload, armnn::DataType::QuantisedAsymm8>();
64 }
65
66 template <typename WorkloadType,
67           typename DescriptorType,
68           typename LayerType,
69           armnn::DataType DataType>
70 static void RefCreateElementwiseWorkloadTest()
71 {
72     Graph graph;
73     RefWorkloadFactory factory;
74     auto workload = CreateElementwiseWorkloadTest<WorkloadType, DescriptorType, LayerType, DataType>(
75         factory, graph);
76
77     CheckInputsOutput(std::move(workload),
78         TensorInfo({ 2, 3 }, DataType),
79         TensorInfo({ 2, 3 }, DataType),
80         TensorInfo({ 2, 3 }, DataType));
81 }
82
83 BOOST_AUTO_TEST_CASE(CreateAdditionFloatWorkload)
84 {
85     RefCreateElementwiseWorkloadTest<RefAdditionWorkload,
86         AdditionQueueDescriptor,
87         AdditionLayer,
88         armnn::DataType::Float32>();
89 }
90
91 BOOST_AUTO_TEST_CASE(CreateAdditionUint8Workload)
92 {
93     RefCreateElementwiseWorkloadTest<RefAdditionWorkload,
94         AdditionQueueDescriptor,
95         AdditionLayer,
96         armnn::DataType::QuantisedAsymm8>();
97 }
98
99 BOOST_AUTO_TEST_CASE(CreateAdditionInt16Workload)
100 {
101     RefCreateElementwiseWorkloadTest<RefAdditionWorkload,
102         AdditionQueueDescriptor,
103         AdditionLayer,
104         armnn::DataType::QuantisedSymm16>();
105 }
106
107 BOOST_AUTO_TEST_CASE(CreateSubtractionFloatWorkload)
108 {
109     RefCreateElementwiseWorkloadTest<RefSubtractionWorkload,
110         SubtractionQueueDescriptor,
111         SubtractionLayer,
112         armnn::DataType::Float32>();
113 }
114
115 BOOST_AUTO_TEST_CASE(CreateSubtractionUint8Workload)
116 {
117     RefCreateElementwiseWorkloadTest<RefSubtractionWorkload,
118         SubtractionQueueDescriptor,
119         SubtractionLayer,
120         armnn::DataType::QuantisedAsymm8>();
121 }
122
123 BOOST_AUTO_TEST_CASE(CreateSubtractionInt16Workload)
124 {
125     RefCreateElementwiseWorkloadTest<RefSubtractionWorkload,
126         SubtractionQueueDescriptor,
127         SubtractionLayer,
128         armnn::DataType::QuantisedSymm16>();
129 }
130
131 BOOST_AUTO_TEST_CASE(CreateMultiplicationFloatWorkload)
132 {
133     RefCreateElementwiseWorkloadTest<RefMultiplicationWorkload,
134         MultiplicationQueueDescriptor,
135         MultiplicationLayer,
136         armnn::DataType::Float32>();
137 }
138
139 BOOST_AUTO_TEST_CASE(CreateMultiplicationUint8Workload)
140 {
141     RefCreateElementwiseWorkloadTest<RefMultiplicationWorkload,
142         MultiplicationQueueDescriptor,
143         MultiplicationLayer,
144         armnn::DataType::QuantisedAsymm8>();
145 }
146
147 BOOST_AUTO_TEST_CASE(CreateMultiplicationInt16Workload)
148 {
149     RefCreateElementwiseWorkloadTest<RefMultiplicationWorkload,
150         MultiplicationQueueDescriptor,
151         MultiplicationLayer,
152         armnn::DataType::QuantisedSymm16>();
153 }
154
155 BOOST_AUTO_TEST_CASE(CreateDivisionFloatWorkload)
156 {
157     RefCreateElementwiseWorkloadTest<RefDivisionWorkload,
158         DivisionQueueDescriptor,
159         DivisionLayer,
160         armnn::DataType::Float32>();
161 }
162
163 BOOST_AUTO_TEST_CASE(CreateDivisionUint8Workload)
164 {
165     RefCreateElementwiseWorkloadTest<RefDivisionWorkload,
166         DivisionQueueDescriptor,
167         DivisionLayer,
168         armnn::DataType::QuantisedAsymm8>();
169 }
170
171 BOOST_AUTO_TEST_CASE(CreateDivisionInt16Workload)
172 {
173     RefCreateElementwiseWorkloadTest<RefDivisionWorkload,
174         DivisionQueueDescriptor,
175         DivisionLayer,
176         armnn::DataType::QuantisedSymm16>();
177 }
178
179 template <typename BatchNormalizationWorkloadType, armnn::DataType DataType>
180 static void RefCreateBatchNormalizationWorkloadTest(DataLayout dataLayout)
181 {
182     Graph graph;
183     RefWorkloadFactory factory;
184     auto workload =
185             CreateBatchNormalizationWorkloadTest<BatchNormalizationWorkloadType, DataType>(factory, graph, dataLayout);
186
187     TensorShape inputShape;
188     TensorShape outputShape;
189
190     switch (dataLayout)
191     {
192         case DataLayout::NHWC:
193             inputShape  = { 2, 4, 4, 3 };
194             outputShape = { 2, 4, 4, 3 };
195             break;
196         case DataLayout::NCHW:
197         default:
198             inputShape  = { 2, 3, 4, 4 };
199             outputShape = { 2, 3, 4, 4 };
200             break;
201     }
202
203     // Checks that outputs and inputs are as we expect them (see definition of CreateBatchNormalizationWorkloadTest).
204     CheckInputOutput(std::move(workload), TensorInfo(inputShape, DataType), TensorInfo(outputShape, DataType));
205 }
206
207 BOOST_AUTO_TEST_CASE(CreateBatchNormalizationFloat32Workload)
208 {
209     RefCreateBatchNormalizationWorkloadTest<RefBatchNormalizationFloat32Workload,armnn::DataType::Float32>
210             (DataLayout::NCHW);
211 }
212
213 BOOST_AUTO_TEST_CASE(CreateBatchNormalizationFloat32WorkloadNhwc)
214 {
215     RefCreateBatchNormalizationWorkloadTest<RefBatchNormalizationFloat32Workload, armnn::DataType::Float32>
216             (DataLayout::NHWC);
217 }
218
219 BOOST_AUTO_TEST_CASE(CreateBatchNormalizationUint8Workload)
220 {
221     RefCreateBatchNormalizationWorkloadTest<RefBatchNormalizationUint8Workload, armnn::DataType::QuantisedAsymm8>
222             (DataLayout::NCHW);
223 }
224
225 BOOST_AUTO_TEST_CASE(CreateBatchNormalizationUint8WorkloadNhwc)
226 {
227     RefCreateBatchNormalizationWorkloadTest<RefBatchNormalizationUint8Workload, armnn::DataType::QuantisedAsymm8>
228             (DataLayout::NHWC);
229 }
230
231 BOOST_AUTO_TEST_CASE(CreateConvertFp16ToFp32Float32Workload)
232 {
233     Graph                graph;
234     RefWorkloadFactory factory;
235     auto workload = CreateConvertFp16ToFp32WorkloadTest<RefConvertFp16ToFp32Workload>(factory, graph);
236
237     // Checks that outputs and inputs are as we expect them
238     CheckInputOutput(
239         std::move(workload), TensorInfo({1, 3, 2, 3}, DataType::Float16), TensorInfo({1, 3, 2, 3}, DataType::Float32));
240 }
241
242 BOOST_AUTO_TEST_CASE(CreateConvertFp32ToFp16Float16Workload)
243 {
244     Graph                graph;
245     RefWorkloadFactory factory;
246     auto workload = CreateConvertFp32ToFp16WorkloadTest<RefConvertFp32ToFp16Workload>(factory, graph);
247
248     // Checks that outputs and inputs are as we expect them
249     CheckInputOutput(
250         std::move(workload), TensorInfo({1, 3, 2, 3}, DataType::Float32), TensorInfo({1, 3, 2, 3}, DataType::Float16));
251 }
252
253 static void RefCreateConvolution2dWorkloadTest(DataLayout dataLayout = DataLayout::NCHW)
254 {
255     Graph graph;
256     RefWorkloadFactory factory;
257     auto workload = CreateConvolution2dWorkloadTest<RefConvolution2dWorkload, DataType::Float32>
258                     (factory, graph, dataLayout);
259
260     std::initializer_list<unsigned int> inputShape  = (dataLayout == DataLayout::NCHW) ?
261         std::initializer_list<unsigned int>({2, 3, 8, 16}) : std::initializer_list<unsigned int>({2, 8, 16, 3});
262     std::initializer_list<unsigned int> outputShape = (dataLayout == DataLayout::NCHW) ?
263         std::initializer_list<unsigned int>({2, 2, 2, 10}) : std::initializer_list<unsigned int>({2, 2, 10, 2});
264
265     // Checks that outputs and inputs are as we expect them (see definition of CreateConvolution2dWorkloadTest).
266     CheckInputOutput(std::move(workload),
267                      TensorInfo(inputShape, DataType::Float32),
268                      TensorInfo(outputShape, DataType::Float32));
269 }
270
271 BOOST_AUTO_TEST_CASE(CreateConvolution2dFloatNchwWorkload)
272 {
273     RefCreateConvolution2dWorkloadTest(DataLayout::NCHW);
274 }
275
276 BOOST_AUTO_TEST_CASE(CreateConvolution2dFloatNhwcWorkload)
277 {
278     RefCreateConvolution2dWorkloadTest(DataLayout::NHWC);
279 }
280
281 static void RefCreateDepthwiseConvolutionWorkloadTest(DataLayout dataLayout)
282 {
283     Graph graph;
284     RefWorkloadFactory factory;
285     auto workload = CreateDepthwiseConvolution2dWorkloadTest<RefDepthwiseConvolution2dWorkload, DataType::Float32>
286             (factory, graph, dataLayout);
287
288     std::initializer_list<unsigned int> inputShape  = (dataLayout == DataLayout::NCHW)
289                                                       ? std::initializer_list<unsigned int>({ 2, 2, 5, 5 })
290                                                       : std::initializer_list<unsigned int>({ 2, 5, 5, 2 });
291     std::initializer_list<unsigned int> outputShape = (dataLayout == DataLayout::NCHW)
292                                                       ? std::initializer_list<unsigned int>({ 2, 2, 5, 5 })
293                                                       : std::initializer_list<unsigned int>({ 2, 5, 5, 2 });
294     // Checks that inputs/outputs are as we expect them (see definition of CreateDepthwiseConvolution2dWorkloadTest).
295     CheckInputOutput(std::move(workload),
296                      TensorInfo(inputShape, DataType::Float32),
297                      TensorInfo(outputShape, DataType::Float32));
298 }
299
300 BOOST_AUTO_TEST_CASE(CreateDepthwiseConvolutionFloat32NhwcWorkload)
301 {
302     RefCreateDepthwiseConvolutionWorkloadTest(DataLayout::NHWC);
303 }
304
305 template <typename FullyConnectedWorkloadType, armnn::DataType DataType>
306 static void RefCreateFullyConnectedWorkloadTest()
307 {
308     Graph graph;
309     RefWorkloadFactory factory;
310     auto workload = CreateFullyConnectedWorkloadTest<FullyConnectedWorkloadType, DataType>(factory, graph);
311
312     // Checks that outputs and inputs are as we expect them (see definition of CreateFullyConnectedWorkloadTest).
313     float inputsQScale = DataType == armnn::DataType::QuantisedAsymm8 ? 1.0f : 0.0;
314     float outputQScale = DataType == armnn::DataType::QuantisedAsymm8 ? 2.0f : 0.0;
315     CheckInputOutput(std::move(workload),
316         TensorInfo({ 3, 1, 4, 5 }, DataType, inputsQScale),
317         TensorInfo({ 3, 7 }, DataType, outputQScale));
318 }
319
320 BOOST_AUTO_TEST_CASE(CreateFullyConnectedWorkloadFloat32)
321 {
322     RefCreateFullyConnectedWorkloadTest<RefFullyConnectedWorkload, armnn::DataType::Float32>();
323 }
324
325 BOOST_AUTO_TEST_CASE(CreateFullyConnectedWorkloadQuantisedAsymm8)
326 {
327     RefCreateFullyConnectedWorkloadTest<RefFullyConnectedWorkload, armnn::DataType::QuantisedAsymm8>();
328 }
329
330 BOOST_AUTO_TEST_CASE(CreateFullyConnectedWorkloadQuantisedAsymm16)
331 {
332     RefCreateFullyConnectedWorkloadTest<RefFullyConnectedWorkload, armnn::DataType::QuantisedSymm16>();
333 }
334
335 template <typename NormalizationWorkloadType, armnn::DataType DataType>
336 static void RefCreateNormalizationWorkloadTest(DataLayout dataLayout)
337 {
338     Graph graph;
339     RefWorkloadFactory factory;
340     auto workload = CreateNormalizationWorkloadTest<NormalizationWorkloadType, DataType>(factory, graph, dataLayout);
341
342     TensorShape inputShape;
343     TensorShape outputShape;
344
345     switch (dataLayout)
346     {
347         case DataLayout::NHWC:
348             inputShape  = { 3, 1, 5, 5 };
349             outputShape = { 3, 1, 5, 5 };
350             break;
351         case DataLayout::NCHW:
352         default:
353             inputShape  = { 3, 5, 5, 1 };
354             outputShape = { 3, 5, 5, 1 };
355             break;
356     }
357
358     // Checks that outputs and inputs are as we expect them (see definition of CreateNormalizationWorkloadTest).
359     CheckInputOutput(std::move(workload), TensorInfo(inputShape, DataType), TensorInfo(outputShape, DataType));
360 }
361
362 BOOST_AUTO_TEST_CASE(CreateRefNormalizationNchwWorkload)
363 {
364     RefCreateNormalizationWorkloadTest<RefNormalizationFloat32Workload, armnn::DataType::Float32>(DataLayout::NCHW);
365 }
366
367 BOOST_AUTO_TEST_CASE(CreateRefNormalizationNhwcWorkload)
368 {
369     RefCreateNormalizationWorkloadTest<RefNormalizationFloat32Workload, armnn::DataType::Float32>(DataLayout::NHWC);
370 }
371
372 template <typename Pooling2dWorkloadType, armnn::DataType DataType>
373 static void RefCreatePooling2dWorkloadTest(DataLayout dataLayout)
374 {
375     Graph graph;
376     RefWorkloadFactory factory;
377     auto workload = CreatePooling2dWorkloadTest<Pooling2dWorkloadType, DataType>(factory, graph, dataLayout);
378
379     TensorShape inputShape;
380     TensorShape outputShape;
381
382     switch (dataLayout)
383     {
384         case DataLayout::NHWC:
385             inputShape  = { 3, 5, 5, 2 };
386             outputShape = { 3, 2, 4, 2 };
387             break;
388         case DataLayout::NCHW:
389         default:
390             inputShape =  { 3, 2, 5, 5 };
391             outputShape = { 3, 2, 2, 4 };
392     }
393
394     // Checks that outputs and inputs are as we expect them (see definition of CreatePooling2dWorkloadTest).
395     CheckInputOutput(std::move(workload),
396                      TensorInfo(inputShape, DataType),
397                      TensorInfo(outputShape, DataType));
398 }
399
400 BOOST_AUTO_TEST_CASE(CreatePooling2dFloat32Workload)
401 {
402     RefCreatePooling2dWorkloadTest<RefPooling2dFloat32Workload, armnn::DataType::Float32>(DataLayout::NCHW);
403 }
404
405 BOOST_AUTO_TEST_CASE(CreatePooling2dFloat32NhwcWorkload)
406 {
407     RefCreatePooling2dWorkloadTest<RefPooling2dFloat32Workload, armnn::DataType::Float32>(DataLayout::NHWC);
408 }
409
410 BOOST_AUTO_TEST_CASE(CreatePooling2dUint8Workload)
411 {
412     RefCreatePooling2dWorkloadTest<RefPooling2dUint8Workload, armnn::DataType::QuantisedAsymm8>(DataLayout::NCHW);
413 }
414
415 BOOST_AUTO_TEST_CASE(CreatePooling2dUint8NhwcWorkload)
416 {
417     RefCreatePooling2dWorkloadTest<RefPooling2dUint8Workload, armnn::DataType::QuantisedAsymm8>(DataLayout::NHWC);
418 }
419
420 template <typename SoftmaxWorkloadType, armnn::DataType DataType>
421 static void RefCreateSoftmaxWorkloadTest()
422 {
423     Graph graph;
424     RefWorkloadFactory factory;
425     auto workload = CreateSoftmaxWorkloadTest<SoftmaxWorkloadType, DataType>(factory, graph);
426
427     // Checks that outputs and inputs are as we expect them (see definition of CreateSoftmaxWorkloadTest).
428     CheckInputOutput(
429         std::move(workload),
430         TensorInfo({4, 1}, DataType),
431         TensorInfo({4, 1}, DataType));
432 }
433
434 BOOST_AUTO_TEST_CASE(CreateSoftmaxFloat32Workload)
435 {
436     RefCreateSoftmaxWorkloadTest<RefSoftmaxWorkload, armnn::DataType::Float32>();
437 }
438
439 BOOST_AUTO_TEST_CASE(CreateSoftmaxQuantisedAsymm8Workload)
440 {
441     RefCreateSoftmaxWorkloadTest<RefSoftmaxWorkload, armnn::DataType::QuantisedAsymm8>();
442 }
443
444 BOOST_AUTO_TEST_CASE(CreateSoftmaxQuantisedSymm16Workload)
445 {
446     RefCreateSoftmaxWorkloadTest<RefSoftmaxWorkload, armnn::DataType::QuantisedSymm16>();
447 }
448
449 template <typename SplitterWorkloadType, armnn::DataType DataType>
450 static void RefCreateSplitterWorkloadTest()
451 {
452     Graph graph;
453     RefWorkloadFactory factory;
454     auto workload = CreateSplitterWorkloadTest<SplitterWorkloadType, DataType>(factory, graph);
455
456     // Checks that outputs are as we expect them (see definition of CreateSplitterWorkloadTest).
457     SplitterQueueDescriptor queueDescriptor = workload->GetData();
458     auto inputHandle = boost::polymorphic_downcast<ConstCpuTensorHandle*>(queueDescriptor.m_Inputs[0]);
459     BOOST_TEST((inputHandle->GetTensorInfo() == TensorInfo({ 5, 7, 7 }, DataType)));
460
461     auto outputHandle0 = boost::polymorphic_downcast<CpuTensorHandle*>(queueDescriptor.m_Outputs[0]);
462     BOOST_TEST((outputHandle0->GetTensorInfo() == TensorInfo({ 1, 7, 7 }, DataType)));
463
464     auto outputHandle1 = boost::polymorphic_downcast<CpuTensorHandle*>(queueDescriptor.m_Outputs[1]);
465     BOOST_TEST((outputHandle1->GetTensorInfo() == TensorInfo({ 2, 7, 7 }, DataType)));
466
467     auto outputHandle2 = boost::polymorphic_downcast<CpuTensorHandle*>(queueDescriptor.m_Outputs[2]);
468     BOOST_TEST((outputHandle2->GetTensorInfo() == TensorInfo({ 2, 7, 7 }, DataType)));
469 }
470
471 BOOST_AUTO_TEST_CASE(CreateSplitterFloat32Workload)
472 {
473     RefCreateSplitterWorkloadTest<RefSplitterFloat32Workload, armnn::DataType::Float32>();
474 }
475
476 BOOST_AUTO_TEST_CASE(CreateSplitterUint8Workload)
477 {
478     RefCreateSplitterWorkloadTest<RefSplitterUint8Workload, armnn::DataType::QuantisedAsymm8>();
479 }
480
481 template <typename SplitterWorkloadType, typename ConcatWorkloadType, armnn::DataType DataType>
482 static void RefCreateSplitterConcatWorkloadTest()
483 {
484     // Tests that it is possible to decide which output of the splitter layer
485     // should be lined to which input of the concat layer.
486     // We tested that is is possible to specify 0th output
487     // of the splitter to be the 1st input to the concat and the 1st output of the splitter to be 0th input
488     // of the concat.
489
490     Graph graph;
491     RefWorkloadFactory factory;
492     auto workloads = CreateSplitterConcatWorkloadTest<SplitterWorkloadType, ConcatWorkloadType, DataType>
493             (factory, graph);
494
495     auto wlSplitter = std::move(workloads.first);
496     auto wlConcat = std::move(workloads.second);
497
498     //Checks that the index of inputs/outputs matches what we declared on InputDescriptor construction.
499     armnn::CpuTensorHandle* sOut0 = dynamic_cast<armnn::CpuTensorHandle*>(wlSplitter->GetData().m_Outputs[0]);
500     armnn::CpuTensorHandle* sOut1 = dynamic_cast<armnn::CpuTensorHandle*>(wlSplitter->GetData().m_Outputs[1]);
501     armnn::CpuTensorHandle* mIn0 = dynamic_cast<armnn::CpuTensorHandle*>(wlConcat->GetData().m_Inputs[0]);
502     armnn::CpuTensorHandle* mIn1 = dynamic_cast<armnn::CpuTensorHandle*>(wlConcat->GetData().m_Inputs[1]);
503
504     BOOST_TEST(sOut0);
505     BOOST_TEST(sOut1);
506     BOOST_TEST(mIn0);
507     BOOST_TEST(mIn1);
508
509     bool validDataPointers = (sOut0 == mIn1) && (sOut1 == mIn0);
510
511     BOOST_TEST(validDataPointers);
512 }
513
514 BOOST_AUTO_TEST_CASE(CreateSplitterConcatFloat32)
515 {
516     RefCreateSplitterConcatWorkloadTest<RefSplitterFloat32Workload, RefConcatWorkload, DataType::Float32>();
517 }
518
519 BOOST_AUTO_TEST_CASE(CreateSplitterConcatUint8)
520 {
521     RefCreateSplitterConcatWorkloadTest<RefSplitterUint8Workload, RefConcatWorkload, DataType::QuantisedAsymm8>();
522 }
523
524 template <typename SplitterWorkloadType, typename ActivationWorkloadType, armnn::DataType DataType>
525 static void RefCreateSingleOutputMultipleInputsTest()
526 {
527     // Tests that it is possible to assign multiple (two) different layers to each of the outputs of a splitter layer.
528     // We created a splitter with two outputs. That each of those outputs is used by two different activation layers.
529
530     Graph graph;
531     RefWorkloadFactory factory;
532     std::unique_ptr<SplitterWorkloadType> wlSplitter;
533     std::unique_ptr<ActivationWorkloadType> wlActiv0_0;
534     std::unique_ptr<ActivationWorkloadType> wlActiv0_1;
535     std::unique_ptr<ActivationWorkloadType> wlActiv1_0;
536     std::unique_ptr<ActivationWorkloadType> wlActiv1_1;
537
538     CreateSplitterMultipleInputsOneOutputWorkloadTest<SplitterWorkloadType,
539         ActivationWorkloadType, DataType>(factory, graph, wlSplitter, wlActiv0_0, wlActiv0_1, wlActiv1_0, wlActiv1_1);
540
541     armnn::CpuTensorHandle* sOut0 = dynamic_cast<armnn::CpuTensorHandle*>(wlSplitter->GetData().m_Outputs[0]);
542     armnn::CpuTensorHandle* sOut1 = dynamic_cast<armnn::CpuTensorHandle*>(wlSplitter->GetData().m_Outputs[1]);
543     armnn::CpuTensorHandle* activ0_0Im = dynamic_cast<armnn::CpuTensorHandle*>(wlActiv0_0->GetData().m_Inputs[0]);
544     armnn::CpuTensorHandle* activ0_1Im = dynamic_cast<armnn::CpuTensorHandle*>(wlActiv0_1->GetData().m_Inputs[0]);
545     armnn::CpuTensorHandle* activ1_0Im = dynamic_cast<armnn::CpuTensorHandle*>(wlActiv1_0->GetData().m_Inputs[0]);
546     armnn::CpuTensorHandle* activ1_1Im = dynamic_cast<armnn::CpuTensorHandle*>(wlActiv1_1->GetData().m_Inputs[0]);
547
548
549     BOOST_TEST(sOut0);
550     BOOST_TEST(sOut1);
551     BOOST_TEST(activ0_0Im);
552     BOOST_TEST(activ0_1Im);
553     BOOST_TEST(activ1_0Im);
554     BOOST_TEST(activ1_1Im);
555
556     bool validDataPointers = (sOut0 == activ0_0Im) && (sOut0 == activ0_1Im) &&
557                              (sOut1 == activ1_0Im) && (sOut1 == activ1_1Im);
558
559     BOOST_TEST(validDataPointers);
560 }
561
562 BOOST_AUTO_TEST_CASE(CreateSingleOutputMultipleInputsFloat32)
563 {
564     RefCreateSingleOutputMultipleInputsTest<RefSplitterFloat32Workload, RefActivationWorkload,
565         armnn::DataType::Float32>();
566 }
567
568 BOOST_AUTO_TEST_CASE(CreateSingleOutputMultipleInputsUint8)
569 {
570     RefCreateSingleOutputMultipleInputsTest<RefSplitterUint8Workload, RefActivationWorkload,
571         armnn::DataType::QuantisedAsymm8>();
572 }
573
574 template <typename ResizeBilinearWorkloadType, armnn::DataType DataType>
575 static void RefCreateResizeBilinearTest(DataLayout dataLayout)
576 {
577     Graph graph;
578     RefWorkloadFactory factory;
579     auto workload = CreateResizeBilinearWorkloadTest<ResizeBilinearWorkloadType, DataType>(factory, graph, dataLayout);
580
581     TensorShape inputShape;
582     TensorShape outputShape;
583
584     switch (dataLayout)
585     {
586         case DataLayout::NHWC:
587             inputShape  = { 2, 4, 4, 3 };
588             outputShape = { 2, 2, 2, 3 };
589             break;
590         case DataLayout::NCHW:
591         default:
592             inputShape  = { 2, 3, 4, 4 };
593             outputShape = { 2, 3, 2, 2 };
594     }
595
596     // Checks that outputs and inputs are as we expect them (see definition of CreateResizeBilinearWorkloadTest).
597     CheckInputOutput(std::move(workload),
598                      TensorInfo(inputShape, DataType),
599                      TensorInfo(outputShape, DataType));
600 }
601
602 BOOST_AUTO_TEST_CASE(CreateResizeBilinearFloat32)
603 {
604     RefCreateResizeBilinearTest<RefResizeBilinearFloat32Workload, armnn::DataType::Float32>(DataLayout::NCHW);
605 }
606
607 BOOST_AUTO_TEST_CASE(CreateResizeBilinearUint8)
608 {
609     RefCreateResizeBilinearTest<RefResizeBilinearUint8Workload, armnn::DataType::QuantisedAsymm8>(DataLayout::NCHW);
610 }
611
612 BOOST_AUTO_TEST_CASE(CreateResizeBilinearFloat32Nhwc)
613 {
614     RefCreateResizeBilinearTest<RefResizeBilinearFloat32Workload, armnn::DataType::Float32>(DataLayout::NHWC);
615 }
616
617 template <typename L2NormalizationWorkloadType, armnn::DataType DataType>
618 static void RefCreateL2NormalizationTest(DataLayout dataLayout)
619 {
620     Graph graph;
621     RefWorkloadFactory factory;
622     auto workload =
623             CreateL2NormalizationWorkloadTest<L2NormalizationWorkloadType, DataType>(factory, graph, dataLayout);
624
625     TensorShape inputShape;
626     TensorShape outputShape;
627
628     switch (dataLayout)
629     {
630         case DataLayout::NHWC:
631             inputShape  = { 5, 50, 67, 20 };
632             outputShape = { 5, 50, 67, 20 };
633             break;
634         case DataLayout::NCHW:
635         default:
636             inputShape  = { 5, 20, 50, 67 };
637             outputShape = { 5, 20, 50, 67 };
638             break;
639     }
640
641     // Checks that outputs and inputs are as we expect them (see definition of CreateL2NormalizationWorkloadTest).
642     CheckInputOutput(std::move(workload), TensorInfo(inputShape, DataType), TensorInfo(outputShape, DataType));
643 }
644
645 BOOST_AUTO_TEST_CASE(CreateL2NormalizationFloat32)
646 {
647     RefCreateL2NormalizationTest<RefL2NormalizationFloat32Workload, armnn::DataType::Float32>(DataLayout::NCHW);
648 }
649
650 BOOST_AUTO_TEST_CASE(CreateL2NormalizationFloat32Nhwc)
651 {
652     RefCreateL2NormalizationTest<RefL2NormalizationFloat32Workload, armnn::DataType::Float32>(DataLayout::NHWC);
653 }
654
655 template <typename ReshapeWorkloadType, armnn::DataType DataType>
656 static void RefCreateReshapeWorkloadTest()
657 {
658     Graph graph;
659     RefWorkloadFactory factory;
660     auto workload = CreateReshapeWorkloadTest<ReshapeWorkloadType, DataType>(factory, graph);
661
662     // Checks that outputs and inputs are as we expect them (see definition of CreateReshapeWorkloadTest).
663     CheckInputOutput(
664         std::move(workload),
665         TensorInfo({ 4, 1 }, DataType),
666         TensorInfo({ 1, 4 }, DataType));
667 }
668
669 BOOST_AUTO_TEST_CASE(CreateReshapeWorkloadFloat32)
670 {
671     RefCreateReshapeWorkloadTest<RefReshapeWorkload, armnn::DataType::Float32>();
672 }
673
674 BOOST_AUTO_TEST_CASE(CreateReshapeWorkloadQuantisedAsymm8)
675 {
676     RefCreateReshapeWorkloadTest<RefReshapeWorkload, armnn::DataType::QuantisedAsymm8>();
677 }
678
679 BOOST_AUTO_TEST_CASE(CreateReshapeWorkloadQuantisedSymm16)
680 {
681     RefCreateReshapeWorkloadTest<RefReshapeWorkload, armnn::DataType::QuantisedSymm16>();
682 }
683
684 template <typename ConcatWorkloadType, armnn::DataType DataType>
685 static void RefCreateConcatWorkloadTest(const armnn::TensorShape& outputShape,
686                                         unsigned int concatAxis)
687 {
688     Graph graph;
689     RefWorkloadFactory factory;
690     auto workload = CreateConcatWorkloadTest<ConcatWorkloadType, DataType>(factory, graph, outputShape, concatAxis);
691
692     CheckInputsOutput(std::move(workload),
693                       TensorInfo({ 2, 3, 2, 5 }, DataType),
694                       TensorInfo({ 2, 3, 2, 5 }, DataType),
695                       TensorInfo(outputShape, DataType));
696 }
697
698 BOOST_AUTO_TEST_CASE(CreateConcatDim0Float32Workload)
699 {
700     RefCreateConcatWorkloadTest<RefConcatWorkload, armnn::DataType::Float32>({ 4, 3, 2, 5 }, 0);
701 }
702
703 BOOST_AUTO_TEST_CASE(CreateConcatDim0Uint8Workload)
704 {
705     RefCreateConcatWorkloadTest<RefConcatWorkload, armnn::DataType::QuantisedAsymm8>({ 4, 3, 2, 5 }, 0);
706 }
707
708 BOOST_AUTO_TEST_CASE(CreateConcatDim0Uint16Workload)
709 {
710     RefCreateConcatWorkloadTest<RefConcatWorkload, armnn::DataType::QuantisedSymm16>({ 4, 3, 2, 5 }, 0);
711 }
712
713 BOOST_AUTO_TEST_CASE(CreateConcatDim1Float32Workload)
714 {
715     RefCreateConcatWorkloadTest<RefConcatWorkload, armnn::DataType::Float32>({ 2, 6, 2, 5 }, 1);
716 }
717
718 BOOST_AUTO_TEST_CASE(CreateConcatDim1Uint8Workload)
719 {
720     RefCreateConcatWorkloadTest<RefConcatWorkload, armnn::DataType::QuantisedAsymm8>({ 2, 6, 2, 5 }, 1);
721 }
722
723 BOOST_AUTO_TEST_CASE(CreateConcatDim2Float32Workload)
724 {
725     RefCreateConcatWorkloadTest<RefConcatWorkload, armnn::DataType::Float32>({ 2, 3, 4, 5 }, 2);
726 }
727
728 BOOST_AUTO_TEST_CASE(CreateConcatDim2Uint8Workload)
729 {
730     RefCreateConcatWorkloadTest<RefConcatWorkload, armnn::DataType::QuantisedAsymm8>({ 2, 3, 4, 5 }, 2);
731 }
732
733 BOOST_AUTO_TEST_CASE(CreateConcatDim3Float32Workload)
734 {
735     RefCreateConcatWorkloadTest<RefConcatWorkload, armnn::DataType::Float32>({ 2, 3, 2, 10 }, 3);
736 }
737
738 BOOST_AUTO_TEST_CASE(CreateConcatDim3Uint8Workload)
739 {
740     RefCreateConcatWorkloadTest<RefConcatWorkload, armnn::DataType::QuantisedAsymm8>({ 2, 3, 2, 10 }, 3);
741 }
742
743 template <typename ConstantWorkloadType, armnn::DataType DataType>
744 static void RefCreateConstantWorkloadTest(const armnn::TensorShape& outputShape)
745 {
746     armnn::Graph graph;
747     RefWorkloadFactory factory;
748     auto workload = CreateConstantWorkloadTest<ConstantWorkloadType, DataType>(factory, graph, outputShape);
749
750     // Check output is as expected
751     auto queueDescriptor = workload->GetData();
752     auto outputHandle = boost::polymorphic_downcast<CpuTensorHandle*>(queueDescriptor.m_Outputs[0]);
753     BOOST_TEST((outputHandle->GetTensorInfo() == TensorInfo(outputShape, DataType)));
754 }
755
756 BOOST_AUTO_TEST_CASE(CreateConstantUint8Workload)
757 {
758     RefCreateConstantWorkloadTest<RefConstantWorkload, armnn::DataType::QuantisedAsymm8>({ 2, 3, 2, 10 });
759 }
760
761 BOOST_AUTO_TEST_CASE(CreateConstantInt16Workload)
762 {
763     RefCreateConstantWorkloadTest<RefConstantWorkload, armnn::DataType::QuantisedSymm16>({ 2, 3, 2, 10 });
764 }
765
766 BOOST_AUTO_TEST_CASE(CreateConstantFloat32Workload)
767 {
768     RefCreateConstantWorkloadTest<RefConstantWorkload, armnn::DataType::Float32>({ 2, 3, 2, 10 });
769 }
770
771 BOOST_AUTO_TEST_CASE(CreateConstantSigned32Workload)
772 {
773     RefCreateConstantWorkloadTest<RefConstantWorkload, armnn::DataType::Signed32>({ 2, 3, 2, 10 });
774 }
775
776 BOOST_AUTO_TEST_SUITE_END()