blob: 8a85e7dd9463697bc8326d26ec8cab553753a99e [file] [log] [blame]
telsoa014fcda012018-03-09 14:13:49 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
telsoa014fcda012018-03-09 14:13:49 +00004//
arovir0143095f32018-10-09 18:04:24 +01005
6#include <armnn/test/CreateWorkloadClNeon.hpp>
7
8#include <backends/MemCopyWorkload.hpp>
David Beck0dbe0ee2018-09-24 15:59:27 +01009#include <backends/neon/NeonWorkloadFactory.hpp>
10#include <backends/neon/NeonTensorHandle.hpp>
11#include <backends/neon/workloads/NeonWorkloadUtils.hpp>
12#include <backends/neon/workloads/NeonWorkloads.hpp>
telsoa014fcda012018-03-09 14:13:49 +000013
14BOOST_AUTO_TEST_SUITE(CreateWorkloadNeon)
15
16namespace
17{
18
19bool TestNeonTensorHandleInfo(armnn::INeonTensorHandle* handle, const armnn::TensorInfo& expectedInfo)
20{
21 using namespace armnn::armcomputetensorutils;
22
23 const arm_compute::ITensorInfo* handleInfo = handle->GetTensor().info();
24 const arm_compute::TensorInfo expectedAclInfo = BuildArmComputeTensorInfo(expectedInfo);
25
26 if (handleInfo->data_type() != expectedAclInfo.data_type())
27 {
28 return false;
29 }
30
31 if (handleInfo->num_dimensions() != expectedAclInfo.num_dimensions())
32 {
33 return false;
34 }
35
36 if (handleInfo->quantization_info() != expectedAclInfo.quantization_info())
37 {
38 return false;
39 }
40
41 for (std::size_t d = 0; d < expectedAclInfo.num_dimensions(); ++d)
42 {
43 if (handleInfo->dimension(d) != expectedAclInfo.dimension(d))
44 {
45 return false;
46 }
47 }
48
49 return true;
50}
51
52} // namespace
53
Nattapat Chaimanowongd4b70592018-10-12 11:21:49 +010054template <typename armnn::DataType DataType>
telsoa01c577f2c2018-08-31 09:22:23 +010055static void NeonCreateActivationWorkloadTest()
telsoa014fcda012018-03-09 14:13:49 +000056{
57 Graph graph;
58 NeonWorkloadFactory factory;
Nattapat Chaimanowongd4b70592018-10-12 11:21:49 +010059 auto workload = CreateActivationWorkloadTest<NeonActivationWorkload, DataType>(factory, graph);
telsoa014fcda012018-03-09 14:13:49 +000060
telsoa01c577f2c2018-08-31 09:22:23 +010061 // Checks that inputs/outputs are as we expect them (see definition of CreateActivationWorkloadTest).
telsoa014fcda012018-03-09 14:13:49 +000062 ActivationQueueDescriptor queueDescriptor = workload->GetData();
63 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
64 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
telsoa01c577f2c2018-08-31 09:22:23 +010065 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({1, 1}, DataType)));
66 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({1, 1}, DataType)));
telsoa014fcda012018-03-09 14:13:49 +000067}
68
telsoa01c577f2c2018-08-31 09:22:23 +010069#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
70BOOST_AUTO_TEST_CASE(CreateActivationFloat16Workload)
71{
Nattapat Chaimanowongd4b70592018-10-12 11:21:49 +010072 NeonCreateActivationWorkloadTest<DataType::Float16>();
telsoa01c577f2c2018-08-31 09:22:23 +010073}
74#endif
75
arovir019e53a352018-08-31 15:26:35 +010076BOOST_AUTO_TEST_CASE(CreateActivationFloatWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +010077{
Nattapat Chaimanowongd4b70592018-10-12 11:21:49 +010078 NeonCreateActivationWorkloadTest<DataType::Float32>();
telsoa01c577f2c2018-08-31 09:22:23 +010079}
80
David Beckbc392452018-09-10 14:47:28 +010081template <typename WorkloadType,
82 typename DescriptorType,
83 typename LayerType,
84 armnn::DataType DataType>
85static void NeonCreateArithmethicWorkloadTest()
telsoa014fcda012018-03-09 14:13:49 +000086{
David Beckbc392452018-09-10 14:47:28 +010087 Graph graph;
telsoa014fcda012018-03-09 14:13:49 +000088 NeonWorkloadFactory factory;
David Beckbc392452018-09-10 14:47:28 +010089 auto workload = CreateArithmeticWorkloadTest<WorkloadType, DescriptorType, LayerType, DataType>(factory, graph);
telsoa014fcda012018-03-09 14:13:49 +000090
David Beckbc392452018-09-10 14:47:28 +010091 DescriptorType queueDescriptor = workload->GetData();
telsoa014fcda012018-03-09 14:13:49 +000092 auto inputHandle1 = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
93 auto inputHandle2 = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[1]);
94 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
telsoa01c577f2c2018-08-31 09:22:23 +010095 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle1, TensorInfo({2, 3}, DataType)));
96 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle2, TensorInfo({2, 3}, DataType)));
97 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({2, 3}, DataType)));
telsoa014fcda012018-03-09 14:13:49 +000098}
99
telsoa01c577f2c2018-08-31 09:22:23 +0100100#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
101BOOST_AUTO_TEST_CASE(CreateAdditionFloat16Workload)
102{
David Beckbc392452018-09-10 14:47:28 +0100103 NeonCreateArithmethicWorkloadTest<NeonAdditionFloatWorkload,
104 AdditionQueueDescriptor,
105 AdditionLayer,
106 DataType::Float16>();
telsoa01c577f2c2018-08-31 09:22:23 +0100107}
108#endif
109
arovir019e53a352018-08-31 15:26:35 +0100110BOOST_AUTO_TEST_CASE(CreateAdditionFloatWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +0100111{
David Beckbc392452018-09-10 14:47:28 +0100112 NeonCreateArithmethicWorkloadTest<NeonAdditionFloatWorkload,
113 AdditionQueueDescriptor,
114 AdditionLayer,
115 DataType::Float32>();
116}
117
118#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
119BOOST_AUTO_TEST_CASE(CreateSubtractionFloat16Workload)
120{
121 NeonCreateArithmethicWorkloadTest<NeonSubtractionFloatWorkload,
122 SubtractionQueueDescriptor,
123 SubtractionLayer,
124 DataType::Float16>();
125}
126#endif
127
128BOOST_AUTO_TEST_CASE(CreateSubtractionFloatWorkload)
129{
130 NeonCreateArithmethicWorkloadTest<NeonSubtractionFloatWorkload,
131 SubtractionQueueDescriptor,
132 SubtractionLayer,
133 DataType::Float32>();
134}
135
136#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
137BOOST_AUTO_TEST_CASE(CreateMultiplicationFloat16Workload)
138{
139 NeonCreateArithmethicWorkloadTest<NeonMultiplicationFloatWorkload,
140 MultiplicationQueueDescriptor,
141 MultiplicationLayer,
142 DataType::Float16>();
143}
144#endif
145
146BOOST_AUTO_TEST_CASE(CreateMultiplicationFloatWorkload)
147{
148 NeonCreateArithmethicWorkloadTest<NeonMultiplicationFloatWorkload,
149 MultiplicationQueueDescriptor,
150 MultiplicationLayer,
151 DataType::Float32>();
telsoa01c577f2c2018-08-31 09:22:23 +0100152}
153
154template <typename BatchNormalizationWorkloadType, typename armnn::DataType DataType>
155static void NeonCreateBatchNormalizationWorkloadTest()
telsoa014fcda012018-03-09 14:13:49 +0000156{
157 Graph graph;
158 NeonWorkloadFactory factory;
telsoa01c577f2c2018-08-31 09:22:23 +0100159 auto workload = CreateBatchNormalizationWorkloadTest<BatchNormalizationWorkloadType, DataType>(factory, graph);
telsoa014fcda012018-03-09 14:13:49 +0000160
telsoa01c577f2c2018-08-31 09:22:23 +0100161 // Checks that outputs and inputs are as we expect them (see definition of CreateBatchNormalizationWorkloadTest).
telsoa014fcda012018-03-09 14:13:49 +0000162 BatchNormalizationQueueDescriptor queueDescriptor = workload->GetData();
163 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
164 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
telsoa01c577f2c2018-08-31 09:22:23 +0100165 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({2, 3, 1, 1}, DataType)));
166 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({2, 3, 1, 1}, DataType)));
telsoa014fcda012018-03-09 14:13:49 +0000167}
168
telsoa01c577f2c2018-08-31 09:22:23 +0100169#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
170BOOST_AUTO_TEST_CASE(CreateBatchNormalizationFloat16Workload)
171{
arovir019e53a352018-08-31 15:26:35 +0100172 NeonCreateBatchNormalizationWorkloadTest<NeonBatchNormalizationFloatWorkload, DataType::Float16>();
telsoa01c577f2c2018-08-31 09:22:23 +0100173}
174#endif
175
arovir019e53a352018-08-31 15:26:35 +0100176BOOST_AUTO_TEST_CASE(CreateBatchNormalizationFloatWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +0100177{
arovir019e53a352018-08-31 15:26:35 +0100178 NeonCreateBatchNormalizationWorkloadTest<NeonBatchNormalizationFloatWorkload, DataType::Float32>();
telsoa01c577f2c2018-08-31 09:22:23 +0100179}
180
181template <typename Convolution2dWorkloadType, typename armnn::DataType DataType>
Francis Murtagh0d9d4192018-10-09 16:22:33 +0100182static void NeonCreateConvolution2dWorkloadTest(DataLayout dataLayout = DataLayout::NCHW)
telsoa014fcda012018-03-09 14:13:49 +0000183{
184 Graph graph;
185 NeonWorkloadFactory factory;
telsoa01c577f2c2018-08-31 09:22:23 +0100186 auto workload = CreateConvolution2dWorkloadTest<Convolution2dWorkloadType,
Francis Murtagh0d9d4192018-10-09 16:22:33 +0100187 DataType>(factory, graph, dataLayout);
188
189 TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{2, 3, 8, 16} : TensorShape{2, 8, 16, 3};
190 TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{2, 2, 2, 10} : TensorShape{2, 2, 10, 2};
telsoa014fcda012018-03-09 14:13:49 +0000191
telsoa01c577f2c2018-08-31 09:22:23 +0100192 // Checks that outputs and inputs are as we expect them (see definition of CreateConvolution2dWorkloadTest).
telsoa014fcda012018-03-09 14:13:49 +0000193 Convolution2dQueueDescriptor queueDescriptor = workload->GetData();
194 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
195 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
Francis Murtagh0d9d4192018-10-09 16:22:33 +0100196 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo(inputShape, DataType)));
197 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, DataType)));
telsoa014fcda012018-03-09 14:13:49 +0000198}
199
telsoa01c577f2c2018-08-31 09:22:23 +0100200#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
Francis Murtagh0d9d4192018-10-09 16:22:33 +0100201BOOST_AUTO_TEST_CASE(CreateConvolution2dFloat16NchwWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +0100202{
arovir019e53a352018-08-31 15:26:35 +0100203 NeonCreateConvolution2dWorkloadTest<NeonConvolution2dFloatWorkload, DataType::Float16>();
telsoa01c577f2c2018-08-31 09:22:23 +0100204}
telsoa01c577f2c2018-08-31 09:22:23 +0100205
Francis Murtagh0d9d4192018-10-09 16:22:33 +0100206BOOST_AUTO_TEST_CASE(CreateConvolution2dFloat16NhwcWorkload)
207{
208 NeonCreateConvolution2dWorkloadTest<NeonConvolution2dFloatWorkload, DataType::Float16>(DataLayout::NHWC);
209}
210
211#endif
212BOOST_AUTO_TEST_CASE(CreateConvolution2dFloatNchwWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +0100213{
arovir019e53a352018-08-31 15:26:35 +0100214 NeonCreateConvolution2dWorkloadTest<NeonConvolution2dFloatWorkload, DataType::Float32>();
telsoa01c577f2c2018-08-31 09:22:23 +0100215}
216
Francis Murtagh0d9d4192018-10-09 16:22:33 +0100217BOOST_AUTO_TEST_CASE(CreateConvolution2dFloatNhwcWorkload)
218{
219 NeonCreateConvolution2dWorkloadTest<NeonConvolution2dFloatWorkload, DataType::Float32>(DataLayout::NHWC);
220}
221
telsoa01c577f2c2018-08-31 09:22:23 +0100222template <typename FullyConnectedWorkloadType, typename armnn::DataType DataType>
223static void NeonCreateFullyConnectedWorkloadTest()
telsoa014fcda012018-03-09 14:13:49 +0000224{
225 Graph graph;
226 NeonWorkloadFactory factory;
telsoa01c577f2c2018-08-31 09:22:23 +0100227 auto workload = CreateFullyConnectedWorkloadTest<FullyConnectedWorkloadType,
228 DataType>(factory, graph);
telsoa014fcda012018-03-09 14:13:49 +0000229
telsoa01c577f2c2018-08-31 09:22:23 +0100230 // Checks that outputs and inputs are as we expect them (see definition of CreateFullyConnectedWorkloadTest).
telsoa014fcda012018-03-09 14:13:49 +0000231 FullyConnectedQueueDescriptor queueDescriptor = workload->GetData();
232 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
233 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
telsoa01c577f2c2018-08-31 09:22:23 +0100234 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({3, 1, 4, 5}, DataType)));
235 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({3, 7}, DataType)));
telsoa014fcda012018-03-09 14:13:49 +0000236}
237
telsoa01c577f2c2018-08-31 09:22:23 +0100238#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
239BOOST_AUTO_TEST_CASE(CreateFullyConnectedFloat16Workload)
240{
kevmay01e448be32018-09-26 10:21:55 +0100241 NeonCreateFullyConnectedWorkloadTest<NeonFullyConnectedWorkload, DataType::Float16>();
telsoa01c577f2c2018-08-31 09:22:23 +0100242}
243#endif
244
arovir019e53a352018-08-31 15:26:35 +0100245BOOST_AUTO_TEST_CASE(CreateFullyConnectedFloatWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +0100246{
kevmay01e448be32018-09-26 10:21:55 +0100247 NeonCreateFullyConnectedWorkloadTest<NeonFullyConnectedWorkload, DataType::Float32>();
telsoa01c577f2c2018-08-31 09:22:23 +0100248}
249
telsoa01c577f2c2018-08-31 09:22:23 +0100250template <typename NormalizationWorkloadType, typename armnn::DataType DataType>
narpra0155a97bc2018-10-02 14:35:53 +0100251static void NeonCreateNormalizationWorkloadTest(DataLayout dataLayout)
telsoa014fcda012018-03-09 14:13:49 +0000252{
narpra0155a97bc2018-10-02 14:35:53 +0100253 Graph graph;
telsoa014fcda012018-03-09 14:13:49 +0000254 NeonWorkloadFactory factory;
narpra0155a97bc2018-10-02 14:35:53 +0100255 auto workload = CreateNormalizationWorkloadTest<NormalizationWorkloadType, DataType>(factory, graph, dataLayout);
telsoa014fcda012018-03-09 14:13:49 +0000256
telsoa01c577f2c2018-08-31 09:22:23 +0100257 // Checks that outputs and inputs are as we expect them (see definition of CreateNormalizationWorkloadTest).
telsoa014fcda012018-03-09 14:13:49 +0000258 NormalizationQueueDescriptor queueDescriptor = workload->GetData();
259 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
260 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
telsoa01c577f2c2018-08-31 09:22:23 +0100261 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({3, 5, 5, 1}, DataType)));
262 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({3, 5, 5, 1}, DataType)));
telsoa014fcda012018-03-09 14:13:49 +0000263}
264
telsoa01c577f2c2018-08-31 09:22:23 +0100265#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
narpra0155a97bc2018-10-02 14:35:53 +0100266BOOST_AUTO_TEST_CASE(CreateNormalizationFloat16NchwWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +0100267{
narpra0155a97bc2018-10-02 14:35:53 +0100268 NeonCreateNormalizationWorkloadTest<NeonNormalizationFloatWorkload, DataType::Float16>(DataLayout::NCHW);
269}
270
271BOOST_AUTO_TEST_CASE(CreateNormalizationFloat16NhwcWorkload)
272{
273 NeonCreateNormalizationWorkloadTest<NeonNormalizationFloatWorkload, DataType::Float16>(DataLayout::NHWC);
telsoa01c577f2c2018-08-31 09:22:23 +0100274}
275#endif
276
narpra0155a97bc2018-10-02 14:35:53 +0100277BOOST_AUTO_TEST_CASE(CreateNormalizationFloatNchwWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +0100278{
narpra0155a97bc2018-10-02 14:35:53 +0100279 NeonCreateNormalizationWorkloadTest<NeonNormalizationFloatWorkload, DataType::Float32>(DataLayout::NCHW);
telsoa01c577f2c2018-08-31 09:22:23 +0100280}
281
narpra0155a97bc2018-10-02 14:35:53 +0100282BOOST_AUTO_TEST_CASE(CreateNormalizationFloatNhwcWorkload)
283{
284 NeonCreateNormalizationWorkloadTest<NeonNormalizationFloatWorkload, DataType::Float32>(DataLayout::NHWC);
285}
286
287
telsoa01c577f2c2018-08-31 09:22:23 +0100288template <typename Pooling2dWorkloadType, typename armnn::DataType DataType>
Nina Drozdb48e6862018-10-09 12:09:56 +0100289static void NeonCreatePooling2dWorkloadTest(DataLayout dataLayout = DataLayout::NCHW)
telsoa014fcda012018-03-09 14:13:49 +0000290{
291 Graph graph;
292 NeonWorkloadFactory factory;
telsoa01c577f2c2018-08-31 09:22:23 +0100293 auto workload = CreatePooling2dWorkloadTest<Pooling2dWorkloadType, DataType>
Nina Drozdb48e6862018-10-09 12:09:56 +0100294 (factory, graph, dataLayout);
295
296 TensorShape inputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{3, 2, 5, 5} : TensorShape{3, 5, 5, 2};
297 TensorShape outputShape = (dataLayout == DataLayout::NCHW) ? TensorShape{3, 2, 2, 4} : TensorShape{3, 2, 4, 2};
telsoa014fcda012018-03-09 14:13:49 +0000298
telsoa01c577f2c2018-08-31 09:22:23 +0100299 // Checks that outputs and inputs are as we expect them (see definition of CreatePooling2dWorkloadTest).
telsoa014fcda012018-03-09 14:13:49 +0000300 Pooling2dQueueDescriptor queueDescriptor = workload->GetData();
301 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
302 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
Nina Drozdb48e6862018-10-09 12:09:56 +0100303 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo(inputShape, DataType)));
304 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, DataType)));
telsoa014fcda012018-03-09 14:13:49 +0000305}
306
telsoa01c577f2c2018-08-31 09:22:23 +0100307#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
308BOOST_AUTO_TEST_CASE(CreatePooling2dFloat16Workload)
309{
arovir019e53a352018-08-31 15:26:35 +0100310 NeonCreatePooling2dWorkloadTest<NeonPooling2dFloatWorkload, DataType::Float16>();
telsoa01c577f2c2018-08-31 09:22:23 +0100311}
312#endif
313
Nina Drozdb48e6862018-10-09 12:09:56 +0100314BOOST_AUTO_TEST_CASE(CreatePooling2dFloatNchwWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +0100315{
Nina Drozdb48e6862018-10-09 12:09:56 +0100316 NeonCreatePooling2dWorkloadTest<NeonPooling2dFloatWorkload, DataType::Float32>(DataLayout::NCHW);
telsoa01c577f2c2018-08-31 09:22:23 +0100317}
318
Nina Drozdb48e6862018-10-09 12:09:56 +0100319BOOST_AUTO_TEST_CASE(CreatePooling2dFloatNhwcWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +0100320{
Nina Drozdb48e6862018-10-09 12:09:56 +0100321 NeonCreatePooling2dWorkloadTest<NeonPooling2dFloatWorkload, DataType::Float32>(DataLayout::NHWC);
322}
323
324BOOST_AUTO_TEST_CASE(CreatePooling2dUint8NchwWorkload)
325{
326 NeonCreatePooling2dWorkloadTest<NeonPooling2dUint8Workload, DataType::QuantisedAsymm8>(DataLayout::NCHW);
327}
328
329BOOST_AUTO_TEST_CASE(CreatePooling2dUint8NhwcWorkload)
330{
331 NeonCreatePooling2dWorkloadTest<NeonPooling2dUint8Workload, DataType::QuantisedAsymm8>(DataLayout::NHWC);
telsoa01c577f2c2018-08-31 09:22:23 +0100332}
333
334template <typename ReshapeWorkloadType, typename armnn::DataType DataType>
335static void NeonCreateReshapeWorkloadTest()
telsoa014fcda012018-03-09 14:13:49 +0000336{
337 Graph graph;
338 NeonWorkloadFactory factory;
telsoa01c577f2c2018-08-31 09:22:23 +0100339 auto workload = CreateReshapeWorkloadTest<ReshapeWorkloadType, DataType>(factory, graph);
telsoa014fcda012018-03-09 14:13:49 +0000340
telsoa01c577f2c2018-08-31 09:22:23 +0100341 // Checks that outputs and inputs are as we expect them (see definition of CreateReshapeWorkloadTest).
telsoa014fcda012018-03-09 14:13:49 +0000342 ReshapeQueueDescriptor queueDescriptor = workload->GetData();
343 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
344 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
telsoa01c577f2c2018-08-31 09:22:23 +0100345 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({4, 1}, DataType)));
346 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({1, 4}, DataType)));
telsoa014fcda012018-03-09 14:13:49 +0000347}
348
telsoa01c577f2c2018-08-31 09:22:23 +0100349#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
350BOOST_AUTO_TEST_CASE(CreateReshapeFloat16Workload)
351{
arovir019e53a352018-08-31 15:26:35 +0100352 NeonCreateReshapeWorkloadTest<NeonReshapeFloatWorkload, DataType::Float16>();
telsoa01c577f2c2018-08-31 09:22:23 +0100353}
354#endif
355
arovir019e53a352018-08-31 15:26:35 +0100356BOOST_AUTO_TEST_CASE(CreateReshapeFloatWorkload)
telsoa014fcda012018-03-09 14:13:49 +0000357{
arovir019e53a352018-08-31 15:26:35 +0100358 NeonCreateReshapeWorkloadTest<NeonReshapeFloatWorkload, DataType::Float32>();
telsoa014fcda012018-03-09 14:13:49 +0000359}
360
361BOOST_AUTO_TEST_CASE(CreateReshapeUint8Workload)
362{
telsoa01c577f2c2018-08-31 09:22:23 +0100363 NeonCreateReshapeWorkloadTest<NeonReshapeUint8Workload, DataType::QuantisedAsymm8>();
telsoa014fcda012018-03-09 14:13:49 +0000364}
365
telsoa01c577f2c2018-08-31 09:22:23 +0100366template <typename SoftmaxWorkloadType, typename armnn::DataType DataType>
367static void NeonCreateSoftmaxWorkloadTest()
telsoa014fcda012018-03-09 14:13:49 +0000368{
369 Graph graph;
370 NeonWorkloadFactory factory;
telsoa01c577f2c2018-08-31 09:22:23 +0100371 auto workload = CreateSoftmaxWorkloadTest<SoftmaxWorkloadType, DataType>(factory, graph);
telsoa014fcda012018-03-09 14:13:49 +0000372
telsoa01c577f2c2018-08-31 09:22:23 +0100373 // Checks that outputs and inputs are as we expect them (see definition of CreateSoftmaxWorkloadTest).
telsoa014fcda012018-03-09 14:13:49 +0000374 SoftmaxQueueDescriptor queueDescriptor = workload->GetData();
375 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
376 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
telsoa01c577f2c2018-08-31 09:22:23 +0100377 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({4, 1}, DataType)));
378 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo({4, 1}, DataType)));
379}
380
381#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
382BOOST_AUTO_TEST_CASE(CreateSoftmaxFloat16Workload)
383{
arovir019e53a352018-08-31 15:26:35 +0100384 NeonCreateSoftmaxWorkloadTest<NeonSoftmaxFloatWorkload, DataType::Float16>();
telsoa01c577f2c2018-08-31 09:22:23 +0100385}
386#endif
387
arovir019e53a352018-08-31 15:26:35 +0100388BOOST_AUTO_TEST_CASE(CreateSoftmaxFloatWorkload)
telsoa01c577f2c2018-08-31 09:22:23 +0100389{
arovir019e53a352018-08-31 15:26:35 +0100390 NeonCreateSoftmaxWorkloadTest<NeonSoftmaxFloatWorkload, DataType::Float32>();
telsoa014fcda012018-03-09 14:13:49 +0000391}
392
393BOOST_AUTO_TEST_CASE(CreateSplitterWorkload)
394{
395 Graph graph;
396 NeonWorkloadFactory factory;
arovir019e53a352018-08-31 15:26:35 +0100397 auto workload = CreateSplitterWorkloadTest<NeonSplitterFloatWorkload, DataType::Float32>(factory, graph);
telsoa014fcda012018-03-09 14:13:49 +0000398
telsoa01c577f2c2018-08-31 09:22:23 +0100399 // Checks that outputs are as we expect them (see definition of CreateSplitterWorkloadTest).
telsoa014fcda012018-03-09 14:13:49 +0000400 SplitterQueueDescriptor queueDescriptor = workload->GetData();
401 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
surmeh013537c2c2018-05-18 16:31:43 +0100402 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo({5, 7, 7}, DataType::Float32)));
403
telsoa014fcda012018-03-09 14:13:49 +0000404 auto outputHandle0 = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
surmeh013537c2c2018-05-18 16:31:43 +0100405 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle0, TensorInfo({1, 7, 7}, DataType::Float32)));
406
telsoa014fcda012018-03-09 14:13:49 +0000407 auto outputHandle1 = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[1]);
surmeh013537c2c2018-05-18 16:31:43 +0100408 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle1, TensorInfo({2, 7, 7}, DataType::Float32)));
409
telsoa014fcda012018-03-09 14:13:49 +0000410 auto outputHandle2 = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[2]);
surmeh013537c2c2018-05-18 16:31:43 +0100411 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle2, TensorInfo({2, 7, 7}, DataType::Float32)));
telsoa014fcda012018-03-09 14:13:49 +0000412}
413
414BOOST_AUTO_TEST_CASE(CreateSplitterMerger)
415{
telsoa01c577f2c2018-08-31 09:22:23 +0100416 // Tests that it is possible to decide which output of the splitter layer
417 // should be lined to which input of the merger layer.
418 // We tested that is is possible to specify 0th output
419 // of the splitter to be the 1st input to the merger, and the 1st output of the splitter to be 0th input
telsoa014fcda012018-03-09 14:13:49 +0000420 // of the merger.
421
422 Graph graph;
423 NeonWorkloadFactory factory;
424
425 auto workloads =
arovir019e53a352018-08-31 15:26:35 +0100426 CreateSplitterMergerWorkloadTest<NeonSplitterFloatWorkload, NeonMergerFloatWorkload,
telsoa01c577f2c2018-08-31 09:22:23 +0100427 DataType::Float32>(factory, graph);
telsoa014fcda012018-03-09 14:13:49 +0000428
429 auto wlSplitter = std::move(workloads.first);
430 auto wlMerger = std::move(workloads.second);
431
telsoa01c577f2c2018-08-31 09:22:23 +0100432 //Checks that the index of inputs/outputs matches what we declared on InputDescriptor construction.
telsoa014fcda012018-03-09 14:13:49 +0000433 armnn::INeonTensorHandle* sOut0 = dynamic_cast<armnn::INeonTensorHandle*>(wlSplitter->GetData().m_Outputs[0]);
434 armnn::INeonTensorHandle* sOut1 = dynamic_cast<armnn::INeonTensorHandle*>(wlSplitter->GetData().m_Outputs[1]);
435 armnn::INeonTensorHandle* mIn0 = dynamic_cast<armnn::INeonTensorHandle*>(wlMerger->GetData().m_Inputs[0]);
436 armnn::INeonTensorHandle* mIn1 = dynamic_cast<armnn::INeonTensorHandle*>(wlMerger->GetData().m_Inputs[1]);
437
438 BOOST_TEST(sOut0);
439 BOOST_TEST(sOut1);
440 BOOST_TEST(mIn0);
441 BOOST_TEST(mIn1);
442
443 bool validDataPointers = (sOut0 == mIn1) && (sOut1 == mIn0);
444
445 BOOST_TEST(validDataPointers);
446}
447
448BOOST_AUTO_TEST_CASE(CreateSingleOutputMultipleInputs)
449{
telsoa01c577f2c2018-08-31 09:22:23 +0100450 // Tests that it is possible to assign multiple (two) different layers to each of the outputs of a splitter layer.
451 // We created a splitter with two outputs. That each of those outputs is used by two different activation layers
telsoa014fcda012018-03-09 14:13:49 +0000452
453 Graph graph;
454 NeonWorkloadFactory factory;
arovir019e53a352018-08-31 15:26:35 +0100455 std::unique_ptr<NeonSplitterFloatWorkload> wlSplitter;
Nattapat Chaimanowongd4b70592018-10-12 11:21:49 +0100456 std::unique_ptr<NeonActivationWorkload> wlActiv0_0;
457 std::unique_ptr<NeonActivationWorkload> wlActiv0_1;
458 std::unique_ptr<NeonActivationWorkload> wlActiv1_0;
459 std::unique_ptr<NeonActivationWorkload> wlActiv1_1;
telsoa014fcda012018-03-09 14:13:49 +0000460
arovir019e53a352018-08-31 15:26:35 +0100461 CreateSplitterMultipleInputsOneOutputWorkloadTest<NeonSplitterFloatWorkload,
Nattapat Chaimanowongd4b70592018-10-12 11:21:49 +0100462 NeonActivationWorkload, DataType::Float32>(factory, graph, wlSplitter, wlActiv0_0, wlActiv0_1,
463 wlActiv1_0, wlActiv1_1);
telsoa014fcda012018-03-09 14:13:49 +0000464
465 armnn::INeonTensorHandle* sOut0 = dynamic_cast<armnn::INeonTensorHandle*>(wlSplitter->GetData().m_Outputs[0]);
466 armnn::INeonTensorHandle* sOut1 = dynamic_cast<armnn::INeonTensorHandle*>(wlSplitter->GetData().m_Outputs[1]);
467 armnn::INeonTensorHandle* activ0_0Im = dynamic_cast<armnn::INeonTensorHandle*>(wlActiv0_0->GetData().m_Inputs[0]);
468 armnn::INeonTensorHandle* activ0_1Im = dynamic_cast<armnn::INeonTensorHandle*>(wlActiv0_1->GetData().m_Inputs[0]);
469 armnn::INeonTensorHandle* activ1_0Im = dynamic_cast<armnn::INeonTensorHandle*>(wlActiv1_0->GetData().m_Inputs[0]);
470 armnn::INeonTensorHandle* activ1_1Im = dynamic_cast<armnn::INeonTensorHandle*>(wlActiv1_1->GetData().m_Inputs[0]);
471
472
473 BOOST_TEST(sOut0);
474 BOOST_TEST(sOut1);
475 BOOST_TEST(activ0_0Im);
476 BOOST_TEST(activ0_1Im);
477 BOOST_TEST(activ1_0Im);
478 BOOST_TEST(activ1_1Im);
479
480 bool validDataPointers = (sOut0 == activ0_0Im) && (sOut0 == activ0_1Im) &&
481 (sOut1 == activ1_0Im) && (sOut1 == activ1_1Im);
482
483 BOOST_TEST(validDataPointers);
484}
485
486BOOST_AUTO_TEST_CASE(CreateMemCopyWorkloadsNeon)
487{
488 NeonWorkloadFactory factory;
telsoa01c577f2c2018-08-31 09:22:23 +0100489 CreateMemCopyWorkloads<INeonTensorHandle>(factory);
telsoa014fcda012018-03-09 14:13:49 +0000490}
491
Matteo Martincighbcd3c852018-09-28 14:14:12 +0100492template <typename L2NormalizationWorkloadType, typename armnn::DataType DataType>
493static void NeonCreateL2NormalizationWorkloadTest(DataLayout dataLayout)
494{
Matteo Martincigh2400b6d2018-10-09 18:19:20 +0100495 Graph graph;
496 NeonWorkloadFactory factory;
497 auto workload =
498 CreateL2NormalizationWorkloadTest<L2NormalizationWorkloadType, DataType>(factory, graph, dataLayout);
Matteo Martincighbcd3c852018-09-28 14:14:12 +0100499
500 // Checks that inputs/outputs are as we expect them (see definition of CreateNormalizationWorkloadTest).
501 L2NormalizationQueueDescriptor queueDescriptor = workload->GetData();
502 auto inputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Inputs[0]);
503 auto outputHandle = boost::polymorphic_downcast<INeonTensorHandle*>(queueDescriptor.m_Outputs[0]);
Matteo Martincigh2400b6d2018-10-09 18:19:20 +0100504
505 TensorShape inputShape = (dataLayout == DataLayout::NCHW) ?
506 TensorShape{ 5, 20, 50, 67 } : TensorShape{ 5, 50, 67, 20 };
507 TensorShape outputShape = (dataLayout == DataLayout::NCHW) ?
508 TensorShape{ 5, 20, 50, 67 } : TensorShape{ 5, 50, 67, 20 };
509
510 BOOST_TEST(TestNeonTensorHandleInfo(inputHandle, TensorInfo(inputShape, DataType)));
511 BOOST_TEST(TestNeonTensorHandleInfo(outputHandle, TensorInfo(outputShape, DataType)));
Matteo Martincighbcd3c852018-09-28 14:14:12 +0100512}
513
514#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
515BOOST_AUTO_TEST_CASE(CreateL2NormalizationFloat16NchwWorkload)
516{
517 NeonCreateL2NormalizationWorkloadTest<NeonL2NormalizationFloatWorkload, DataType::Float16>(DataLayout::NCHW);
518}
519
520BOOST_AUTO_TEST_CASE(CreateL2NormalizationFloat16NhwcWorkload)
521{
522 NeonCreateL2NormalizationWorkloadTest<NeonL2NormalizationFloatWorkload, DataType::Float16>(DataLayout::NHWC);
523}
524#endif
525
526BOOST_AUTO_TEST_CASE(CreateL2NormalizationNchwWorkload)
527{
528 NeonCreateL2NormalizationWorkloadTest<NeonL2NormalizationFloatWorkload, DataType::Float32>(DataLayout::NCHW);
529}
530
531BOOST_AUTO_TEST_CASE(CreateL2NormalizationNhwcWorkload)
532{
533 NeonCreateL2NormalizationWorkloadTest<NeonL2NormalizationFloatWorkload, DataType::Float32>(DataLayout::NHWC);
534}
535
telsoa014fcda012018-03-09 14:13:49 +0000536BOOST_AUTO_TEST_SUITE_END()