[Data] Support data layout conversion between NCHW and TRIV2
[platform/adaptation/npu/trix-engine.git] / tests / unittests / ne_core_data_test.cc
1 /**
2  * Proprietary
3  * Copyright (C) 2021 Samsung Electronics
4  * Copyright (C) 2021 Dongju Chae <dongju.chae@samsung.com>
5  */
6 /**
7  * @file ne_core_data_test.cc
8  * @date 17 Feb 2021
9  * @brief UnitTests to test functionality of data converter
10  * @author Dongju Chae <dongju.chae@samsung.com>
11  * @bug No known bugs except for NYI items
12  */
13
14 #include <ne-data.h>
15 #include <ne-model.h>
16 #include "ne_unittest_utils.h"
17
18 #include <npubinfmt.h>
19 #include <cstdlib>
20
21 /**
22  * @brief Test checkCapability()
23  */
24 TEST (ne_core_data_test, check_capability) {
25   std::unique_ptr<DataConverter> converter (new DataConverter (true));
26   converter->setDataType (DATA_TYPE_QASYMM8, DATA_TYPE_QASYMM8);
27
28   converter->setDataLayout (DATA_LAYOUT_NHWC, DATA_LAYOUT_TRIV2);
29   EXPECT_TRUE (converter->checkCapability ());
30
31   converter->setDataLayout (DATA_LAYOUT_TRIV2, DATA_LAYOUT_NHWC);
32   EXPECT_TRUE (converter->checkCapability ());
33 }
34
35 /**
36  * @brief Test checkCapability() with negative cases
37  */
38 TEST (ne_core_data_test, check_capability_n) {
39   std::unique_ptr<DataConverter> converter (new DataConverter (true));
40
41   /* layouts are not resolved yet */
42   converter->setDataLayout (DATA_LAYOUT_MODEL, DATA_LAYOUT_MODEL);
43   EXPECT_FALSE (converter->checkCapability ());
44
45   /* types are not resolved yet */
46   converter->setDataLayout (DATA_LAYOUT_NHWC, DATA_LAYOUT_TRIV2);
47   converter->setDataType (DATA_TYPE_MODEL, DATA_TYPE_MODEL);
48   EXPECT_FALSE (converter->checkCapability ());
49
50   /* some layouts are not supported */
51   converter->setDataType (DATA_TYPE_QASYMM8, DATA_TYPE_QASYMM8);
52   converter->setDataLayout (DATA_LAYOUT_TRIV, DATA_LAYOUT_TRIV2);
53   EXPECT_FALSE (converter->checkCapability ());
54 }
55
56 /**
57  * @brief Test perform() with quantization (QASYMM8)
58  */
59 TEST (ne_core_data_test, perform_quantization_asymm8) {
60   std::unique_ptr<DataConverter> converter (new DataConverter (true));
61   uint16_t *src_data = new uint16_t[4096];
62   uint8_t *dst_data = new uint8_t[4096];
63   uint32_t data_dims[] = {1, 8, 8, 64};
64   uint32_t zero = 127;
65   float scale = 127.0;
66   double max = 255.0;
67   double min = 0.0;
68
69   converter->setData (src_data, dst_data, 4096 * 2);
70   converter->setDataDims (data_dims);
71   converter->setDataLayout (DATA_LAYOUT_TRIV2, DATA_LAYOUT_TRIV2);
72   converter->setDataType (DATA_TYPE_UINT16, DATA_TYPE_QASYMM8);
73   converter->setQuantZero (zero);
74   converter->setQuantScale (scale);
75
76   /* fill any data */
77   for (int i = 0; i < 4096; i++) {
78     src_data[i] = rand () % UINT16_MAX;
79     dst_data[i] = 0;
80   }
81
82   EXPECT_EQ (converter->perform (), 4096 * 2);
83
84   /* check quantized value */
85   for (int i = 0; i < 4096; i++) {
86     double val = src_data[i];
87     val = val / scale;
88     val += zero;
89     val = (val > max) ? max : val;
90     val = (val < min) ? min : val;
91     EXPECT_EQ (dst_data[i], (uint8_t) val);
92   }
93
94   delete[] src_data;
95   delete[] dst_data;
96 }
97
98 /**
99  * @brief Test perform() with quantization (QSYMM16)
100  */
101 TEST (ne_core_data_test, perform_quantization_symm16) {
102   std::unique_ptr<DataConverter> converter (new DataConverter (true));
103   uint32_t *src_data = new uint32_t[4096];
104   int16_t *dst_data = new int16_t[4096];
105   uint32_t data_dims[] = {1, 8, 8, 64};
106   uint32_t zero = 0;
107   float scale = 127.0;
108   double max = 32767.0;
109   double min = -32768.0;
110
111   converter->setData (src_data, dst_data, 4096 * 4);
112   converter->setDataDims (data_dims);
113   converter->setDataLayout (DATA_LAYOUT_TRIV2, DATA_LAYOUT_TRIV2);
114   converter->setDataType (DATA_TYPE_UINT32, DATA_TYPE_QSYMM16);
115   converter->setQuantZero (zero);
116   converter->setQuantScale (scale);
117
118   /* fill any data */
119   for (int i = 0; i < 4096; i++) {
120     src_data[i] = rand () % UINT32_MAX;
121     dst_data[i] = 0;
122   }
123
124   EXPECT_EQ (converter->perform (), 4096 * 4);
125
126   /* check quantized value */
127   for (int i = 0; i < 4096; i++) {
128     double val = src_data[i];
129     val = val / scale;
130     val += zero;
131     val = (val > max) ? max : val;
132     val = (val < min) ? min : val;
133     EXPECT_EQ (dst_data[i], (int16_t) val);
134   }
135
136   delete[] src_data;
137   delete[] dst_data;
138 }
139
140 /**
141  * @brief Test perform() with quantization (negative)
142  */
143 TEST (ne_core_data_test, perform_quantization_n) {
144   std::unique_ptr<DataConverter> converter (new DataConverter (true));
145   uint32_t *src_data = new uint32_t[4096];
146   int16_t *dst_data = new int16_t[4096];
147   uint32_t data_dims[] = {1, 8, 8, 64};
148   uint32_t zero = 0;
149   float scale = 0.0;
150
151   converter->setData (src_data, dst_data, 4096 * 4);
152   converter->setDataDims (data_dims);
153   converter->setDataLayout (DATA_LAYOUT_TRIV2, DATA_LAYOUT_TRIV2);
154   converter->setDataType (DATA_TYPE_UINT32, DATA_TYPE_QSYMM16);
155   converter->setQuantZero (zero);
156   converter->setQuantScale (scale);
157
158   /* fill any data */
159   for (int i = 0; i < 4096; i++) {
160     src_data[i] = rand () % UINT32_MAX;
161     dst_data[i] = 0;
162   }
163
164   EXPECT_EQ (converter->perform (), 4096 * 4);
165
166   /* failed to quantize */
167   for (int i = 0; i < 4096; i++) {
168     EXPECT_EQ (dst_data[i], 0);
169   }
170
171   delete[] src_data;
172   delete[] dst_data;
173 }
174
175 /**
176  * @brief Test perform() with dequantization (QASYMM8)
177  */
178 TEST (ne_core_data_test, perform_dequantization_asymm8) {
179   std::unique_ptr<DataConverter> converter (new DataConverter (false));
180   uint8_t *src_data = new uint8_t[4096];
181   uint16_t *dst_data = new uint16_t[4096];
182   uint32_t data_dims[] = {1, 8, 8, 64};
183   uint32_t zero = 127;
184   float scale = 127.0;
185
186   converter->setData (src_data, dst_data, 4096);
187   converter->setDataDims (data_dims);
188   converter->setDataLayout (DATA_LAYOUT_TRIV2, DATA_LAYOUT_TRIV2);
189   converter->setDataType (DATA_TYPE_QASYMM8, DATA_TYPE_UINT16);
190   converter->setQuantZero (zero);
191   converter->setQuantScale (scale);
192
193   /* fill any data */
194   for (int i = 0; i < 4096; i++) {
195     src_data[i] = rand () % UINT8_MAX;
196     dst_data[i] = 0;
197   }
198
199   EXPECT_EQ (converter->perform (), 4096);
200
201   /* check dequantized value */
202   for (int i = 0; i < 4096; i++) {
203     double val = src_data[i];
204     val -= zero;
205     val *= scale;
206     EXPECT_EQ (dst_data[i], (uint16_t) val);
207   }
208
209   delete[] src_data;
210   delete[] dst_data;
211 }
212
213 /**
214  * @brief Test perform() with dequantization (QSYMM16)
215  */
216 TEST (ne_core_data_test, perform_dequantization_symm16) {
217   std::unique_ptr<DataConverter> converter (new DataConverter (false));
218   int16_t *src_data = new int16_t[4096];
219   uint32_t *dst_data = new uint32_t[4096];
220   uint32_t data_dims[] = {1, 8, 8, 64};
221   uint32_t zero = 0;
222   float scale = 127.0;
223
224   converter->setData (src_data, dst_data, 4096 * 2);
225   converter->setDataDims (data_dims);
226   converter->setDataLayout (DATA_LAYOUT_TRIV2, DATA_LAYOUT_TRIV2);
227   converter->setDataType (DATA_TYPE_QSYMM16, DATA_TYPE_UINT32);
228   converter->setQuantZero (zero);
229   converter->setQuantScale (scale);
230
231   /* fill any data */
232   for (int i = 0; i < 4096; i++) {
233     src_data[i] = rand () % INT16_MAX;
234     dst_data[i] = 0;
235   }
236
237   EXPECT_EQ (converter->perform (), 4096 * 2);
238
239   /* check dequantized value */
240   for (int i = 0; i < 4096; i++) {
241     double val = src_data[i];
242     val -= zero;
243     val *= scale;
244     EXPECT_EQ (dst_data[i], (int32_t) val);
245   }
246
247   delete[] src_data;
248   delete[] dst_data;
249 }
250
251 /**
252  * @brief Test perform() with layer conversion (QASYMM8)
253  */
254 TEST (ne_core_data_test, perform_layer_conversion_asymm8) {
255   std::unique_ptr<DataConverter> converter (new DataConverter (true));
256   uint8_t *src_data = new uint8_t[4096];
257   uint8_t *dst_data = new uint8_t[4096];
258   uint32_t data_dims[] = {1, 8, 8, 64};
259   uint32_t granularity = DATA_GRANULARITY;
260
261   converter->setData (src_data, dst_data, 4096);
262   converter->setDataDims (data_dims);
263   converter->setDataLayout (DATA_LAYOUT_NHWC, DATA_LAYOUT_TRIV2);
264   converter->setDataType (DATA_TYPE_QASYMM8, DATA_TYPE_QASYMM8);
265
266   /* fill any data */
267   for (int i = 0; i < 4096; i++) {
268     src_data[i] = rand () % UINT8_MAX;
269     dst_data[i] = 0;
270   }
271
272   EXPECT_EQ (converter->perform (), 4096);
273
274   /* check values */
275   EXPECT_EQ (memcmp (src_data, dst_data, 4096), 0);
276
277   /* 2-TOPS */
278   converter->setTops (2);
279   EXPECT_EQ (converter->perform (), 4096);
280
281   for (int i = 0; i < 4096; i += granularity) {
282     EXPECT_EQ (
283         memcmp (src_data + i, dst_data + (granularity / 2) * (i / granularity),
284                 granularity / 2),
285         0);
286     EXPECT_EQ (memcmp (src_data + i + (granularity / 2),
287                        dst_data + (granularity / 2) * (i / granularity) + 2048,
288                        granularity / 2),
289                0);
290   }
291
292   delete[] src_data;
293   delete[] dst_data;
294 }
295
296 /**
297  * @brief Test perform() with layer conversion (QSYMM16)
298  */
299 TEST (ne_core_data_test, perform_layer_conversion_symm16) {
300   std::unique_ptr<DataConverter> converter (new DataConverter (true));
301   int16_t *src_data = new int16_t[4096];
302   int16_t *dst_data = new int16_t[4096];
303   uint32_t data_dims[] = {1, 8, 8, 64};
304   uint32_t granularity = DATA_GRANULARITY;
305
306   converter->setData (src_data, dst_data, 4096 * 2);
307   converter->setDataDims (data_dims);
308   converter->setDataLayout (DATA_LAYOUT_NHWC, DATA_LAYOUT_TRIV2);
309   converter->setDataType (DATA_TYPE_QSYMM16, DATA_TYPE_QSYMM16);
310
311   /* fill any data */
312   for (int i = 0; i < 4096; i++) {
313     src_data[i] = rand () % INT16_MAX;
314     dst_data[i] = 0;
315   }
316
317   EXPECT_EQ (converter->perform (), 4096 * 2);
318
319   /* check values */
320   for (int i = 0; i < 4096; i += granularity) {
321     EXPECT_EQ (
322         memcmp (src_data + i, dst_data + (granularity / 2) * (i / granularity),
323                 granularity / 2),
324         0);
325     EXPECT_EQ (memcmp (src_data + i + (granularity / 2),
326                        dst_data + (granularity / 2) * (i / granularity) + 2048,
327                        granularity / 2),
328                0);
329   }
330
331   /* 2-TOPS */
332   converter->setTops (2);
333   EXPECT_EQ (converter->perform (), 4096 * 2);
334
335   for (int i = 0; i < 4096; i += granularity) {
336     EXPECT_EQ (
337         memcmp (src_data + i, dst_data + (granularity / 4) * (i / granularity),
338                 granularity / 4),
339         0);
340     EXPECT_EQ (memcmp (src_data + i + (granularity / 4),
341                        dst_data + (granularity / 4) * (i / granularity) + 1024,
342                        granularity / 4),
343                0);
344     EXPECT_EQ (memcmp (src_data + i + 2 * (granularity / 4),
345                        dst_data + (granularity / 4) * (i / granularity) + 2048,
346                        granularity / 4),
347                0);
348     EXPECT_EQ (memcmp (src_data + i + 3 * (granularity / 4),
349                        dst_data + (granularity / 4) * (i / granularity) + 3072,
350                        granularity / 4),
351                0);
352   }
353
354   delete[] src_data;
355   delete[] dst_data;
356 }
357
358 /**
359  * @brief Test perform() with negative cases
360  */
361 TEST (ne_core_data_test, perform_n) {
362   std::unique_ptr<DataConverter> converter (new DataConverter (true));
363   char *dummy_data = new char[4096];
364   uint32_t dummy_dims[] = {1, 1, 1, 4096};
365
366   /* invalid parameters */
367   converter->setData (nullptr, nullptr, 4096);
368   EXPECT_EQ (converter->perform (), 0);
369
370   converter->setData (dummy_data, nullptr, 4096);
371   EXPECT_EQ (converter->perform (), 0);
372
373   converter->setData (nullptr, dummy_data, 4096);
374   EXPECT_EQ (converter->perform (), 0);
375
376   converter->setData (dummy_data, dummy_data, 0);
377   EXPECT_EQ (converter->perform (), 0);
378
379   converter->setData (dummy_data, dummy_data, 4096);
380   converter->setDataDims (nullptr);
381   EXPECT_EQ (converter->perform (), 0);
382
383   /* still layout/types are not resolved */
384   converter->setDataDims (dummy_dims);
385   EXPECT_EQ (converter->perform (), 0);
386
387   delete[] dummy_data;
388 }
389
390 /**
391  * @brief Test quantize() with various types (dummy)
392  */
393 TEST (ne_core_data_test, dummy_quantize) {
394   data_type npu_types[] = {DATA_TYPE_SRNPU, DATA_TYPE_QASYMM8,
395                            DATA_TYPE_QSYMM16};
396   data_type std_types[] = {
397       DATA_TYPE_INT8,    DATA_TYPE_UINT8,  DATA_TYPE_INT16, DATA_TYPE_UINT16,
398       DATA_TYPE_INT32,   DATA_TYPE_UINT32, DATA_TYPE_INT64, DATA_TYPE_UINT64,
399       DATA_TYPE_FLOAT32, DATA_TYPE_FLOAT64};
400   uint32_t data_dims[] = {1, 1, 1, 1024};
401
402   void *src_data = malloc (4096);
403   ASSERT_NE (src_data, nullptr);
404   void *dst_data = malloc (4096);
405   if (dst_data == nullptr) {
406     free (src_data);
407     ASSERT_NE (dst_data, nullptr);
408   }
409
410   /* std to npu */
411   std::unique_ptr<DataConverter> converter (new DataConverter (true));
412
413   converter->setDataLayout (DATA_LAYOUT_TRIV2, DATA_LAYOUT_TRIV2);
414   converter->setDataDims (data_dims);
415   converter->setTops (2);
416   converter->setQuantZero (127);
417   converter->setQuantScale (1.0);
418
419   for (auto &s : std_types) {
420     converter->setData (src_data, dst_data, get_data_size (s));
421     for (auto &n : npu_types) {
422       converter->setDataType (s, n);
423       converter->perform ();
424     }
425   }
426
427   /* npu to std */
428   converter.reset (new DataConverter (false));
429
430   converter->setDataLayout (DATA_LAYOUT_TRIV2, DATA_LAYOUT_TRIV2);
431   converter->setDataDims (data_dims);
432   converter->setTops (2);
433   converter->setQuantZero (127);
434   converter->setQuantScale (1.0);
435
436   for (auto &n : npu_types) {
437     converter->setData (src_data, dst_data, get_data_size (n));
438     for (auto &s : std_types) {
439       converter->setDataType (n, s);
440       converter->perform ();
441     }
442   }
443
444   free (src_data);
445   free (dst_data);
446 }
447
448 /**
449  * @brief Data conversion from NHWC to TRIV2
450  */
451 TEST (ne_core_data_test, layout_conversion_from_nhwc) {
452   std::unique_ptr<DataConverter> converter (new DataConverter (true));
453
454   uint32_t N = 1, H = 10, W = 10;
455   uint32_t channels[] = {1, 3, 16, 32, 64};
456
457   for (auto C : channels) {
458     uint32_t data_dims[] = {N, H, W, C};
459     uint32_t MPA_L = 32;
460     if (C == 1 || C == 3)
461       MPA_L = C;
462
463     uint32_t src_size = N * H * W * C;
464     uint8_t *src_data = new uint8_t[src_size];
465
466     uint32_t dst_size = N * H * W * (((C + MPA_L - 1) / MPA_L) * MPA_L);
467     uint8_t *dst_data = new uint8_t[dst_size];
468
469     converter->setTops (2);
470     converter->setData (src_data, dst_data, src_size);
471     converter->setDataDims (data_dims);
472     converter->setDataLayout (DATA_LAYOUT_NHWC, DATA_LAYOUT_TRIV2);
473     converter->setDataType (DATA_TYPE_QASYMM8, DATA_TYPE_QASYMM8);
474
475     EXPECT_TRUE (converter->checkCapability ());
476
477     /* fill any data */
478     for (int i = 0; i < src_size; i++) src_data[i] = i;
479     for (int i = 0; i < dst_size; i++) dst_data[i] = 0;
480
481     EXPECT_EQ (converter->perform (), src_size);
482
483     uint32_t std_offset;
484     uint32_t npu_offset;
485     for (int n = 0; n < N; n++) {
486       for (int h = 0; h < H; h++) {
487         for (int w = 0; w < W; w++) {
488           for (int c = 0; c < C; c++) {
489             std_offset = c + C * (w + W * (h + n * H));
490             npu_offset =
491                 c % MPA_L + MPA_L * (w + W * (h + (n + c / MPA_L) * H));
492             EXPECT_EQ (src_data[std_offset], dst_data[npu_offset]);
493           }
494         }
495       }
496     }
497
498     delete[] src_data;
499     delete[] dst_data;
500   }
501 }
502
503 /**
504  * @brief Data conversion from TRIV2 to NHWC
505  */
506 TEST (ne_core_data_test, layout_conversion_to_nhwc) {
507   std::unique_ptr<DataConverter> converter (new DataConverter (false));
508
509   uint32_t N = 1, H = 10, W = 100;
510   uint32_t channels[] = {1, 3, 16, 32, 64};
511
512   for (auto C : channels) {
513     uint32_t data_dims[] = {N, H, W, C};
514     uint32_t MPA_L = 32;
515
516     uint32_t src_size = N * H * W * (((C + MPA_L - 1) / MPA_L) * MPA_L);
517     uint8_t *src_data = new uint8_t[src_size];
518
519     uint32_t dst_size = N * H * W * C;
520     uint8_t *dst_data = new uint8_t[dst_size];
521
522     converter->setTops (2);
523     converter->setData (src_data, dst_data, src_size);
524     converter->setDataDims (data_dims);
525     converter->setDataLayout (DATA_LAYOUT_TRIV2, DATA_LAYOUT_NHWC);
526     converter->setDataType (DATA_TYPE_QASYMM8, DATA_TYPE_QASYMM8);
527
528     EXPECT_TRUE (converter->checkCapability ());
529
530     /* fill any data */
531     for (int i = 0; i < src_size; i++) src_data[i] = i;
532     for (int i = 0; i < dst_size; i++) dst_data[i] = 0;
533
534     EXPECT_EQ (converter->perform (), src_size);
535
536     uint32_t std_offset;
537     uint32_t npu_offset;
538     for (int n = 0; n < N; n++) {
539       for (int h = 0; h < H; h++) {
540         for (int w = 0; w < W; w++) {
541           for (int c = 0; c < C; c++) {
542             std_offset = c + C * (w + W * (h + n * H));
543             npu_offset =
544                 (c % MPA_L) + MPA_L * (w + W * (h + (n + c / MPA_L) * H));
545             EXPECT_EQ (src_data[npu_offset], dst_data[std_offset]);
546           }
547         }
548       }
549     }
550
551     delete[] src_data;
552     delete[] dst_data;
553   }
554 }
555
556 /**
557  * @brief Data conversion from NCHW to TRIV2
558  */
559 TEST (ne_core_data_test, layout_conversion_from_nchw) {
560   std::unique_ptr<DataConverter> converter (new DataConverter (true));
561
562   uint32_t N = 1, H = 10, W = 10;
563   uint32_t channels[] = {1, 3, 16, 32, 64};
564
565   for (auto C : channels) {
566     uint32_t data_dims[] = {N, H, W, C};
567     uint32_t MPA_L = 32;
568     if (C == 1 || C == 3)
569       MPA_L = C;
570
571     uint32_t src_size = N * H * W * C;
572     uint8_t *src_data = new uint8_t[src_size];
573
574     uint32_t dst_size = N * H * W * (((C + MPA_L - 1) / MPA_L) * MPA_L);
575     uint8_t *dst_data = new uint8_t[dst_size];
576
577     converter->setTops (2);
578     converter->setData (src_data, dst_data, src_size);
579     converter->setDataDims (data_dims);
580     converter->setDataLayout (DATA_LAYOUT_NCHW, DATA_LAYOUT_TRIV2);
581     converter->setDataType (DATA_TYPE_QASYMM8, DATA_TYPE_QASYMM8);
582
583     EXPECT_TRUE (converter->checkCapability ());
584
585     /* fill any data */
586     for (int i = 0; i < src_size; i++) src_data[i] = i;
587     for (int i = 0; i < dst_size; i++) dst_data[i] = 0;
588
589     EXPECT_EQ (converter->perform (), src_size);
590
591     uint32_t std_offset;
592     uint32_t npu_offset;
593     for (int n = 0; n < N; n++) {
594       for (int c = 0; c < C; c++) {
595         for (int h = 0; h < H; h++) {
596           for (int w = 0; w < W; w++) {
597             std_offset = w + W * (h + H * (c + n * C));
598             npu_offset =
599                 (c % MPA_L) + MPA_L * (w + W * (h + (n + c / MPA_L) * H));
600             EXPECT_EQ (src_data[std_offset], dst_data[npu_offset]);
601           }
602         }
603       }
604     }
605
606     delete[] src_data;
607     delete[] dst_data;
608   }
609 }
610
611 /**
612  * @brief Data conversion from TRIV2 to NCHW
613  */
614 TEST (ne_core_data_test, layout_conversion_to_nchw) {
615   std::unique_ptr<DataConverter> converter (new DataConverter (false));
616
617   uint32_t N = 1, H = 10, W = 10;
618   uint32_t channels[] = {1, 3, 16, 32, 64};
619
620   for (auto C : channels) {
621     uint32_t data_dims[] = {N, H, W, C};
622     uint32_t MPA_L = 32;
623
624     uint32_t src_size = N * H * W * (((C + MPA_L - 1) / MPA_L) * MPA_L);
625     uint8_t *src_data = new uint8_t[src_size];
626
627     uint32_t dst_size = N * H * W * C;
628     uint8_t *dst_data = new uint8_t[dst_size];
629
630     converter->setTops (2);
631     converter->setData (src_data, dst_data, src_size);
632     converter->setDataDims (data_dims);
633     converter->setDataLayout (DATA_LAYOUT_TRIV2, DATA_LAYOUT_NCHW);
634     converter->setDataType (DATA_TYPE_QASYMM8, DATA_TYPE_QASYMM8);
635
636     EXPECT_TRUE (converter->checkCapability ());
637
638     /* fill any data */
639     for (int i = 0; i < src_size; i++) src_data[i] = i;
640     for (int i = 0; i < dst_size; i++) dst_data[i] = 0;
641
642     EXPECT_EQ (converter->perform (), src_size);
643
644     uint32_t std_offset;
645     uint32_t npu_offset;
646     for (int n = 0; n < N; n++) {
647       for (int c = 0; c < C; c++) {
648         for (int h = 0; h < H; h++) {
649           for (int w = 0; w < W; w++) {
650             std_offset = w + W * (h + H * (c + n * C));
651             npu_offset =
652                 (c % MPA_L) + MPA_L * (w + W * (h + (n + c / MPA_L) * H));
653             EXPECT_EQ (src_data[npu_offset], dst_data[std_offset]);
654           }
655         }
656       }
657     }
658
659     delete[] src_data;
660     delete[] dst_data;
661   }
662 }
663
664 /**
665  * @brief main function for unit test
666  */
667 int
668 main (int argc, char **argv) {
669   return start_gtest (argc, argv);
670 }