3 * Copyright (C) 2021 Samsung Electronics
4 * Copyright (C) 2021 Dongju Chae <dongju.chae@samsung.com>
7 * @file ne_core_data_test.cc
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
16 #include <ne_test_utils_gtest.h>
18 #include <npubinfmt.h>
22 * @brief Test checkCapability()
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);
28 converter->setDataLayout (DATA_LAYOUT_NHWC, DATA_LAYOUT_TRIV2);
29 EXPECT_TRUE (converter->checkCapability ());
31 converter->setDataLayout (DATA_LAYOUT_TRIV2, DATA_LAYOUT_NHWC);
32 EXPECT_TRUE (converter->checkCapability ());
36 * @brief Test checkCapability() with negative cases
38 TEST (ne_core_data_test, check_capability_n) {
39 std::unique_ptr<DataConverter> converter (new DataConverter (true));
41 /* layouts are not resolved yet */
42 converter->setDataLayout (DATA_LAYOUT_MODEL, DATA_LAYOUT_MODEL);
43 EXPECT_FALSE (converter->checkCapability ());
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 ());
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 ());
57 * @brief Test perform() with quantization (QASYMM8)
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};
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);
77 for (int i = 0; i < 4096; i++) {
78 src_data[i] = rand () % UINT16_MAX;
82 EXPECT_EQ (converter->perform (), 4096 * 2);
84 /* check quantized value */
85 for (int i = 0; i < 4096; i++) {
86 double val = src_data[i];
89 val = (val > max) ? max : val;
90 val = (val < min) ? min : val;
91 EXPECT_EQ (dst_data[i], (uint8_t) val);
99 * @brief Test perform() with quantization (QSYMM16)
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};
108 double max = 32767.0;
109 double min = -32768.0;
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);
119 for (int i = 0; i < 4096; i++) {
120 src_data[i] = rand () % UINT32_MAX;
124 EXPECT_EQ (converter->perform (), 4096 * 4);
126 /* check quantized value */
127 for (int i = 0; i < 4096; i++) {
128 double val = src_data[i];
131 val = (val > max) ? max : val;
132 val = (val < min) ? min : val;
133 EXPECT_EQ (dst_data[i], (int16_t) val);
141 * @brief Test perform() with quantization (negative)
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};
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);
159 for (int i = 0; i < 4096; i++) {
160 src_data[i] = rand () % UINT32_MAX;
164 EXPECT_EQ (converter->perform (), 4096 * 4);
166 /* failed to quantize */
167 for (int i = 0; i < 4096; i++) {
168 EXPECT_EQ (dst_data[i], 0);
176 * @brief Test perform() with dequantization (QASYMM8)
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};
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);
194 for (int i = 0; i < 4096; i++) {
195 src_data[i] = rand () % UINT8_MAX;
199 EXPECT_EQ (converter->perform (), 4096);
201 /* check dequantized value */
202 for (int i = 0; i < 4096; i++) {
203 double val = src_data[i];
206 EXPECT_EQ (dst_data[i], (uint16_t) val);
214 * @brief Test perform() with dequantization (QSYMM16)
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};
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);
232 for (int i = 0; i < 4096; i++) {
233 src_data[i] = rand () % INT16_MAX;
237 EXPECT_EQ (converter->perform (), 4096 * 2);
239 /* check dequantized value */
240 for (int i = 0; i < 4096; i++) {
241 double val = src_data[i];
244 EXPECT_EQ (dst_data[i], (int32_t) val);
252 * @brief Test perform() with layer conversion (QASYMM8)
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;
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);
267 for (int i = 0; i < 4096; i++) {
268 src_data[i] = rand () % UINT8_MAX;
272 EXPECT_EQ (converter->perform (), 4096);
275 EXPECT_EQ (memcmp (src_data, dst_data, 4096), 0);
278 converter->setTops (2);
279 EXPECT_EQ (converter->perform (), 4096);
281 for (int i = 0; i < 4096; i += granularity) {
283 memcmp (src_data + i, dst_data + (granularity / 2) * (i / granularity), granularity / 2),
285 EXPECT_EQ (memcmp (src_data + i + (granularity / 2),
286 dst_data + (granularity / 2) * (i / granularity) + 2048, granularity / 2),
295 * @brief Test perform() with layer conversion (QSYMM16)
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;
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);
310 for (int i = 0; i < 4096; i++) {
311 src_data[i] = rand () % INT16_MAX;
315 EXPECT_EQ (converter->perform (), 4096 * 2);
318 for (int i = 0; i < 4096; i += granularity) {
320 memcmp (src_data + i, dst_data + (granularity / 2) * (i / granularity), granularity / 2),
322 EXPECT_EQ (memcmp (src_data + i + (granularity / 2),
323 dst_data + (granularity / 2) * (i / granularity) + 2048, granularity / 2),
328 converter->setTops (2);
329 EXPECT_EQ (converter->perform (), 4096 * 2);
331 for (int i = 0; i < 4096; i += granularity) {
333 memcmp (src_data + i, dst_data + (granularity / 4) * (i / granularity), granularity / 4),
335 EXPECT_EQ (memcmp (src_data + i + (granularity / 4),
336 dst_data + (granularity / 4) * (i / granularity) + 1024, granularity / 4),
338 EXPECT_EQ (memcmp (src_data + i + 2 * (granularity / 4),
339 dst_data + (granularity / 4) * (i / granularity) + 2048, granularity / 4),
341 EXPECT_EQ (memcmp (src_data + i + 3 * (granularity / 4),
342 dst_data + (granularity / 4) * (i / granularity) + 3072, granularity / 4),
351 * @brief Test perform() with negative cases
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};
358 /* invalid parameters */
359 converter->setData (nullptr, nullptr, 4096);
360 EXPECT_EQ (converter->perform (), 0);
362 converter->setData (dummy_data, nullptr, 4096);
363 EXPECT_EQ (converter->perform (), 0);
365 converter->setData (nullptr, dummy_data, 4096);
366 EXPECT_EQ (converter->perform (), 0);
368 converter->setData (dummy_data, dummy_data, 0);
369 EXPECT_EQ (converter->perform (), 0);
371 converter->setData (dummy_data, dummy_data, 4096);
372 converter->setDataDims (nullptr);
373 EXPECT_EQ (converter->perform (), 0);
375 /* still layout/types are not resolved */
376 converter->setDataDims (dummy_dims);
377 EXPECT_EQ (converter->perform (), 0);
383 * @brief Test quantize() with various types (dummy)
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};
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) {
397 ASSERT_NE (dst_data, nullptr);
401 std::unique_ptr<DataConverter> converter (new DataConverter (true));
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);
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 ();
418 converter.reset (new DataConverter (false));
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);
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 ();
439 * @brief Data conversion from NHWC to TRIV2
441 TEST (ne_core_data_test, layout_conversion_from_nhwc) {
442 std::unique_ptr<DataConverter> converter (new DataConverter (true));
444 uint32_t N = 1, H = 10, W = 10;
445 uint32_t channels[] = {1, 3, 16, 32, 64};
447 for (auto C : channels) {
448 uint32_t data_dims[] = {N, H, W, C};
450 if (C == 1 || C == 3)
453 uint32_t src_size = N * H * W * C;
454 uint8_t *src_data = new uint8_t[src_size];
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];
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);
465 EXPECT_TRUE (converter->checkCapability ());
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;
471 EXPECT_EQ (converter->perform (), src_size);
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]);
493 * @brief Data conversion from TRIV2 to NHWC
495 TEST (ne_core_data_test, layout_conversion_to_nhwc) {
496 std::unique_ptr<DataConverter> converter (new DataConverter (false));
498 uint32_t N = 1, H = 10, W = 100;
499 uint32_t channels[] = {1, 3, 16, 32, 64};
501 for (auto C : channels) {
502 uint32_t data_dims[] = {N, H, W, C};
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];
508 uint32_t dst_size = N * H * W * C;
509 uint8_t *dst_data = new uint8_t[dst_size];
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);
517 EXPECT_TRUE (converter->checkCapability ());
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;
523 EXPECT_EQ (converter->perform (), src_size);
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]);
545 * @brief Data conversion from NCHW to TRIV2
547 TEST (ne_core_data_test, layout_conversion_from_nchw) {
548 std::unique_ptr<DataConverter> converter (new DataConverter (true));
550 uint32_t N = 1, H = 10, W = 10;
551 uint32_t channels[] = {1, 3, 16, 32, 64};
553 for (auto C : channels) {
554 uint32_t data_dims[] = {N, H, W, C};
556 if (C == 1 || C == 3)
559 uint32_t src_size = N * H * W * C;
560 uint8_t *src_data = new uint8_t[src_size];
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];
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);
571 EXPECT_TRUE (converter->checkCapability ());
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;
577 EXPECT_EQ (converter->perform (), src_size);
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]);
599 * @brief Data conversion from TRIV2 to NCHW
601 TEST (ne_core_data_test, layout_conversion_to_nchw) {
602 std::unique_ptr<DataConverter> converter (new DataConverter (false));
604 uint32_t N = 1, H = 10, W = 10;
605 uint32_t channels[] = {1, 3, 16, 32, 64};
607 for (auto C : channels) {
608 uint32_t data_dims[] = {N, H, W, C};
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];
614 uint32_t dst_size = N * H * W * C;
615 uint8_t *dst_data = new uint8_t[dst_size];
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);
623 EXPECT_TRUE (converter->checkCapability ());
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;
629 EXPECT_EQ (converter->perform (), src_size);
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]);
651 * @brief main function for unit test
654 main (int argc, char **argv) {
655 return start_gtest (argc, argv);