[Valgrind] Remove valgrind warnings.
[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_test_utils_gtest.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), granularity / 2),
284         0);
285     EXPECT_EQ (memcmp (src_data + i + (granularity / 2),
286                        dst_data + (granularity / 2) * (i / granularity) + 2048, granularity / 2),
287                0);
288   }
289
290   delete[] src_data;
291   delete[] dst_data;
292 }
293
294 /**
295  * @brief Test perform() with layer conversion (QSYMM16)
296  */
297 TEST (ne_core_data_test, perform_layer_conversion_symm16) {
298   std::unique_ptr<DataConverter> converter (new DataConverter (true));
299   int16_t *src_data = new int16_t[4096];
300   int16_t *dst_data = new int16_t[4096];
301   uint32_t data_dims[] = {1, 8, 8, 64};
302   uint32_t granularity = DATA_GRANULARITY;
303
304   converter->setData (src_data, dst_data, 4096 * 2);
305   converter->setDataDims (data_dims);
306   converter->setDataLayout (DATA_LAYOUT_NHWC, DATA_LAYOUT_TRIV2);
307   converter->setDataType (DATA_TYPE_QSYMM16, DATA_TYPE_QSYMM16);
308
309   /* fill any data */
310   for (int i = 0; i < 4096; i++) {
311     src_data[i] = rand () % INT16_MAX;
312     dst_data[i] = 0;
313   }
314
315   EXPECT_EQ (converter->perform (), 4096 * 2);
316
317   /* check values */
318   for (int i = 0; i < 4096; i += granularity) {
319     EXPECT_EQ (
320         memcmp (src_data + i, dst_data + (granularity / 2) * (i / granularity), granularity / 2),
321         0);
322     EXPECT_EQ (memcmp (src_data + i + (granularity / 2),
323                        dst_data + (granularity / 2) * (i / granularity) + 2048, granularity / 2),
324                0);
325   }
326
327   /* 2-TOPS */
328   converter->setTops (2);
329   EXPECT_EQ (converter->perform (), 4096 * 2);
330
331   for (int i = 0; i < 4096; i += granularity) {
332     EXPECT_EQ (
333         memcmp (src_data + i, dst_data + (granularity / 4) * (i / granularity), granularity / 4),
334         0);
335     EXPECT_EQ (memcmp (src_data + i + (granularity / 4),
336                        dst_data + (granularity / 4) * (i / granularity) + 1024, granularity / 4),
337                0);
338     EXPECT_EQ (memcmp (src_data + i + 2 * (granularity / 4),
339                        dst_data + (granularity / 4) * (i / granularity) + 2048, granularity / 4),
340                0);
341     EXPECT_EQ (memcmp (src_data + i + 3 * (granularity / 4),
342                        dst_data + (granularity / 4) * (i / granularity) + 3072, granularity / 4),
343                0);
344   }
345
346   delete[] src_data;
347   delete[] dst_data;
348 }
349
350 /**
351  * @brief Test perform() with negative cases
352  */
353 TEST (ne_core_data_test, perform_n) {
354   std::unique_ptr<DataConverter> converter (new DataConverter (true));
355   char *dummy_data = new char[4096];
356   uint32_t dummy_dims[] = {1, 1, 1, 4096};
357
358   /* invalid parameters */
359   converter->setData (nullptr, nullptr, 4096);
360   EXPECT_EQ (converter->perform (), 0);
361
362   converter->setData (dummy_data, nullptr, 4096);
363   EXPECT_EQ (converter->perform (), 0);
364
365   converter->setData (nullptr, dummy_data, 4096);
366   EXPECT_EQ (converter->perform (), 0);
367
368   converter->setData (dummy_data, dummy_data, 0);
369   EXPECT_EQ (converter->perform (), 0);
370
371   converter->setData (dummy_data, dummy_data, 4096);
372   converter->setDataDims (nullptr);
373   EXPECT_EQ (converter->perform (), 0);
374
375   /* still layout/types are not resolved */
376   converter->setDataDims (dummy_dims);
377   EXPECT_EQ (converter->perform (), 0);
378
379   delete[] dummy_data;
380 }
381
382 /**
383  * @brief Test quantize() with various types (dummy)
384  */
385 TEST (ne_core_data_test, dummy_quantize) {
386   data_type npu_types[] = {DATA_TYPE_SRNPU, DATA_TYPE_QASYMM8, DATA_TYPE_QSYMM16};
387   data_type std_types[] = {DATA_TYPE_INT8,    DATA_TYPE_UINT8,  DATA_TYPE_INT16, DATA_TYPE_UINT16,
388                            DATA_TYPE_INT32,   DATA_TYPE_UINT32, DATA_TYPE_INT64, DATA_TYPE_UINT64,
389                            DATA_TYPE_FLOAT32, DATA_TYPE_FLOAT64};
390   uint32_t data_dims[] = {1, 1, 1, 1024};
391
392   void *src_data = calloc (1, 4096);
393   ASSERT_NE (src_data, nullptr);
394   void *dst_data = calloc (1, 4096);
395   if (dst_data == nullptr) {
396     free (src_data);
397     ASSERT_NE (dst_data, nullptr);
398   }
399
400   /* std to npu */
401   std::unique_ptr<DataConverter> converter (new DataConverter (true));
402
403   converter->setDataLayout (DATA_LAYOUT_TRIV2, DATA_LAYOUT_TRIV2);
404   converter->setDataDims (data_dims);
405   converter->setTops (2);
406   converter->setQuantZero (127);
407   converter->setQuantScale (1.0);
408
409   for (auto &s : std_types) {
410     converter->setData (src_data, dst_data, get_data_size (s));
411     for (auto &n : npu_types) {
412       converter->setDataType (s, n);
413       converter->perform ();
414     }
415   }
416
417   /* npu to std */
418   converter.reset (new DataConverter (false));
419
420   converter->setDataLayout (DATA_LAYOUT_TRIV2, DATA_LAYOUT_TRIV2);
421   converter->setDataDims (data_dims);
422   converter->setTops (2);
423   converter->setQuantZero (127);
424   converter->setQuantScale (1.0);
425
426   for (auto &n : npu_types) {
427     converter->setData (src_data, dst_data, get_data_size (n));
428     for (auto &s : std_types) {
429       converter->setDataType (n, s);
430       converter->perform ();
431     }
432   }
433
434   free (src_data);
435   free (dst_data);
436 }
437
438 /**
439  * @brief Data conversion from NHWC to TRIV2
440  */
441 TEST (ne_core_data_test, layout_conversion_from_nhwc) {
442   std::unique_ptr<DataConverter> converter (new DataConverter (true));
443
444   uint32_t N = 1, H = 10, W = 10;
445   uint32_t channels[] = {1, 3, 16, 32, 64};
446
447   for (auto C : channels) {
448     uint32_t data_dims[] = {N, H, W, C};
449     uint32_t MPA_L = 32;
450     if (C == 1 || C == 3)
451       MPA_L = C;
452
453     uint32_t src_size = N * H * W * C;
454     uint8_t *src_data = new uint8_t[src_size];
455
456     uint32_t dst_size = N * H * W * (((C + MPA_L - 1) / MPA_L) * MPA_L);
457     uint8_t *dst_data = new uint8_t[dst_size];
458
459     converter->setTops (2);
460     converter->setData (src_data, dst_data, src_size);
461     converter->setDataDims (data_dims);
462     converter->setDataLayout (DATA_LAYOUT_NHWC, DATA_LAYOUT_TRIV2);
463     converter->setDataType (DATA_TYPE_QASYMM8, DATA_TYPE_QASYMM8);
464
465     EXPECT_TRUE (converter->checkCapability ());
466
467     /* fill any data */
468     for (int i = 0; i < src_size; i++) src_data[i] = i;
469     for (int i = 0; i < dst_size; i++) dst_data[i] = 0;
470
471     EXPECT_EQ (converter->perform (), src_size);
472
473     uint32_t std_offset;
474     uint32_t npu_offset;
475     for (int n = 0; n < N; n++) {
476       for (int h = 0; h < H; h++) {
477         for (int w = 0; w < W; w++) {
478           for (int c = 0; c < C; c++) {
479             std_offset = c + C * (w + W * (h + n * H));
480             npu_offset = c % MPA_L + MPA_L * (w + W * (h + (n + c / MPA_L) * H));
481             EXPECT_EQ (src_data[std_offset], dst_data[npu_offset]);
482           }
483         }
484       }
485     }
486
487     delete[] src_data;
488     delete[] dst_data;
489   }
490 }
491
492 /**
493  * @brief Data conversion from TRIV2 to NHWC
494  */
495 TEST (ne_core_data_test, layout_conversion_to_nhwc) {
496   std::unique_ptr<DataConverter> converter (new DataConverter (false));
497
498   uint32_t N = 1, H = 10, W = 100;
499   uint32_t channels[] = {1, 3, 16, 32, 64};
500
501   for (auto C : channels) {
502     uint32_t data_dims[] = {N, H, W, C};
503     uint32_t MPA_L = 32;
504
505     uint32_t src_size = N * H * W * (((C + MPA_L - 1) / MPA_L) * MPA_L);
506     uint8_t *src_data = new uint8_t[src_size];
507
508     uint32_t dst_size = N * H * W * C;
509     uint8_t *dst_data = new uint8_t[dst_size];
510
511     converter->setTops (2);
512     converter->setData (src_data, dst_data, src_size);
513     converter->setDataDims (data_dims);
514     converter->setDataLayout (DATA_LAYOUT_TRIV2, DATA_LAYOUT_NHWC);
515     converter->setDataType (DATA_TYPE_QASYMM8, DATA_TYPE_QASYMM8);
516
517     EXPECT_TRUE (converter->checkCapability ());
518
519     /* fill any data */
520     for (int i = 0; i < src_size; i++) src_data[i] = i;
521     for (int i = 0; i < dst_size; i++) dst_data[i] = 0;
522
523     EXPECT_EQ (converter->perform (), src_size);
524
525     uint32_t std_offset;
526     uint32_t npu_offset;
527     for (int n = 0; n < N; n++) {
528       for (int h = 0; h < H; h++) {
529         for (int w = 0; w < W; w++) {
530           for (int c = 0; c < C; c++) {
531             std_offset = c + C * (w + W * (h + n * H));
532             npu_offset = (c % MPA_L) + MPA_L * (w + W * (h + (n + c / MPA_L) * H));
533             EXPECT_EQ (src_data[npu_offset], dst_data[std_offset]);
534           }
535         }
536       }
537     }
538
539     delete[] src_data;
540     delete[] dst_data;
541   }
542 }
543
544 /**
545  * @brief Data conversion from NCHW to TRIV2
546  */
547 TEST (ne_core_data_test, layout_conversion_from_nchw) {
548   std::unique_ptr<DataConverter> converter (new DataConverter (true));
549
550   uint32_t N = 1, H = 10, W = 10;
551   uint32_t channels[] = {1, 3, 16, 32, 64};
552
553   for (auto C : channels) {
554     uint32_t data_dims[] = {N, H, W, C};
555     uint32_t MPA_L = 32;
556     if (C == 1 || C == 3)
557       MPA_L = C;
558
559     uint32_t src_size = N * H * W * C;
560     uint8_t *src_data = new uint8_t[src_size];
561
562     uint32_t dst_size = N * H * W * (((C + MPA_L - 1) / MPA_L) * MPA_L);
563     uint8_t *dst_data = new uint8_t[dst_size];
564
565     converter->setTops (2);
566     converter->setData (src_data, dst_data, src_size);
567     converter->setDataDims (data_dims);
568     converter->setDataLayout (DATA_LAYOUT_NCHW, DATA_LAYOUT_TRIV2);
569     converter->setDataType (DATA_TYPE_QASYMM8, DATA_TYPE_QASYMM8);
570
571     EXPECT_TRUE (converter->checkCapability ());
572
573     /* fill any data */
574     for (int i = 0; i < src_size; i++) src_data[i] = i;
575     for (int i = 0; i < dst_size; i++) dst_data[i] = 0;
576
577     EXPECT_EQ (converter->perform (), src_size);
578
579     uint32_t std_offset;
580     uint32_t npu_offset;
581     for (int n = 0; n < N; n++) {
582       for (int c = 0; c < C; c++) {
583         for (int h = 0; h < H; h++) {
584           for (int w = 0; w < W; w++) {
585             std_offset = w + W * (h + H * (c + n * C));
586             npu_offset = (c % MPA_L) + MPA_L * (w + W * (h + (n + c / MPA_L) * H));
587             EXPECT_EQ (src_data[std_offset], dst_data[npu_offset]);
588           }
589         }
590       }
591     }
592
593     delete[] src_data;
594     delete[] dst_data;
595   }
596 }
597
598 /**
599  * @brief Data conversion from TRIV2 to NCHW
600  */
601 TEST (ne_core_data_test, layout_conversion_to_nchw) {
602   std::unique_ptr<DataConverter> converter (new DataConverter (false));
603
604   uint32_t N = 1, H = 10, W = 10;
605   uint32_t channels[] = {1, 3, 16, 32, 64};
606
607   for (auto C : channels) {
608     uint32_t data_dims[] = {N, H, W, C};
609     uint32_t MPA_L = 32;
610
611     uint32_t src_size = N * H * W * (((C + MPA_L - 1) / MPA_L) * MPA_L);
612     uint8_t *src_data = new uint8_t[src_size];
613
614     uint32_t dst_size = N * H * W * C;
615     uint8_t *dst_data = new uint8_t[dst_size];
616
617     converter->setTops (2);
618     converter->setData (src_data, dst_data, src_size);
619     converter->setDataDims (data_dims);
620     converter->setDataLayout (DATA_LAYOUT_TRIV2, DATA_LAYOUT_NCHW);
621     converter->setDataType (DATA_TYPE_QASYMM8, DATA_TYPE_QASYMM8);
622
623     EXPECT_TRUE (converter->checkCapability ());
624
625     /* fill any data */
626     for (int i = 0; i < src_size; i++) src_data[i] = i;
627     for (int i = 0; i < dst_size; i++) dst_data[i] = 0;
628
629     EXPECT_EQ (converter->perform (), src_size);
630
631     uint32_t std_offset;
632     uint32_t npu_offset;
633     for (int n = 0; n < N; n++) {
634       for (int c = 0; c < C; c++) {
635         for (int h = 0; h < H; h++) {
636           for (int w = 0; w < W; w++) {
637             std_offset = w + W * (h + H * (c + n * C));
638             npu_offset = (c % MPA_L) + MPA_L * (w + W * (h + (n + c / MPA_L) * H));
639             EXPECT_EQ (src_data[npu_offset], dst_data[std_offset]);
640           }
641         }
642       }
643     }
644
645     delete[] src_data;
646     delete[] dst_data;
647   }
648 }
649
650 /**
651  * @brief main function for unit test
652  */
653 int
654 main (int argc, char **argv) {
655   return start_gtest (argc, argv);
656 }