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_unittest_utils.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),
286 EXPECT_EQ (memcmp (src_data + i + (granularity / 2),
287 dst_data + (granularity / 2) * (i / granularity) + 2048,
297 * @brief Test perform() with layer conversion (QSYMM16)
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;
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);
312 for (int i = 0; i < 4096; i++) {
313 src_data[i] = rand () % INT16_MAX;
317 EXPECT_EQ (converter->perform (), 4096 * 2);
320 for (int i = 0; i < 4096; i += granularity) {
322 memcmp (src_data + i, dst_data + (granularity / 2) * (i / granularity),
325 EXPECT_EQ (memcmp (src_data + i + (granularity / 2),
326 dst_data + (granularity / 2) * (i / granularity) + 2048,
332 converter->setTops (2);
333 EXPECT_EQ (converter->perform (), 4096 * 2);
335 for (int i = 0; i < 4096; i += granularity) {
337 memcmp (src_data + i, dst_data + (granularity / 4) * (i / granularity),
340 EXPECT_EQ (memcmp (src_data + i + (granularity / 4),
341 dst_data + (granularity / 4) * (i / granularity) + 1024,
344 EXPECT_EQ (memcmp (src_data + i + 2 * (granularity / 4),
345 dst_data + (granularity / 4) * (i / granularity) + 2048,
348 EXPECT_EQ (memcmp (src_data + i + 3 * (granularity / 4),
349 dst_data + (granularity / 4) * (i / granularity) + 3072,
359 * @brief Test perform() with negative cases
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};
366 /* invalid parameters */
367 converter->setData (nullptr, nullptr, 4096);
368 EXPECT_EQ (converter->perform (), 0);
370 converter->setData (dummy_data, nullptr, 4096);
371 EXPECT_EQ (converter->perform (), 0);
373 converter->setData (nullptr, dummy_data, 4096);
374 EXPECT_EQ (converter->perform (), 0);
376 converter->setData (dummy_data, dummy_data, 0);
377 EXPECT_EQ (converter->perform (), 0);
379 converter->setData (dummy_data, dummy_data, 4096);
380 converter->setDataDims (nullptr);
381 EXPECT_EQ (converter->perform (), 0);
383 /* still layout/types are not resolved */
384 converter->setDataDims (dummy_dims);
385 EXPECT_EQ (converter->perform (), 0);
391 * @brief Test quantize() with various types (dummy)
393 TEST (ne_core_data_test, dummy_quantize) {
394 data_type npu_types[] = {DATA_TYPE_SRNPU, DATA_TYPE_QASYMM8,
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};
402 void *src_data = malloc (4096);
403 ASSERT_NE (src_data, nullptr);
404 void *dst_data = malloc (4096);
405 if (dst_data == nullptr) {
407 ASSERT_NE (dst_data, nullptr);
411 std::unique_ptr<DataConverter> converter (new DataConverter (true));
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);
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 ();
428 converter.reset (new DataConverter (false));
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);
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 ();
449 * @brief Data conversion from NHWC to TRIV2
451 TEST (ne_core_data_test, layout_conversion_from_nhwc) {
452 std::unique_ptr<DataConverter> converter (new DataConverter (true));
454 uint32_t N = 1, H = 10, W = 10;
455 uint32_t channels[] = {1, 3, 16, 32, 64};
457 for (auto C : channels) {
458 uint32_t data_dims[] = {N, H, W, C};
460 if (C == 1 || C == 3)
463 uint32_t src_size = N * H * W * C;
464 uint8_t *src_data = new uint8_t[src_size];
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];
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);
475 EXPECT_TRUE (converter->checkCapability ());
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;
481 EXPECT_EQ (converter->perform (), src_size);
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));
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]);
504 * @brief Data conversion from TRIV2 to NHWC
506 TEST (ne_core_data_test, layout_conversion_to_nhwc) {
507 std::unique_ptr<DataConverter> converter (new DataConverter (false));
509 uint32_t N = 1, H = 10, W = 100;
510 uint32_t channels[] = {1, 3, 16, 32, 64};
512 for (auto C : channels) {
513 uint32_t data_dims[] = {N, H, W, C};
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];
519 uint32_t dst_size = N * H * W * C;
520 uint8_t *dst_data = new uint8_t[dst_size];
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);
528 EXPECT_TRUE (converter->checkCapability ());
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;
534 EXPECT_EQ (converter->perform (), src_size);
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));
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]);
557 * @brief Data conversion from NCHW to TRIV2
559 TEST (ne_core_data_test, layout_conversion_from_nchw) {
560 std::unique_ptr<DataConverter> converter (new DataConverter (true));
562 uint32_t N = 1, H = 10, W = 10;
563 uint32_t channels[] = {1, 3, 16, 32, 64};
565 for (auto C : channels) {
566 uint32_t data_dims[] = {N, H, W, C};
568 if (C == 1 || C == 3)
571 uint32_t src_size = N * H * W * C;
572 uint8_t *src_data = new uint8_t[src_size];
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];
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);
583 EXPECT_TRUE (converter->checkCapability ());
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;
589 EXPECT_EQ (converter->perform (), src_size);
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));
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]);
612 * @brief Data conversion from TRIV2 to NCHW
614 TEST (ne_core_data_test, layout_conversion_to_nchw) {
615 std::unique_ptr<DataConverter> converter (new DataConverter (false));
617 uint32_t N = 1, H = 10, W = 10;
618 uint32_t channels[] = {1, 3, 16, 32, 64};
620 for (auto C : channels) {
621 uint32_t data_dims[] = {N, H, W, C};
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];
627 uint32_t dst_size = N * H * W * C;
628 uint8_t *dst_data = new uint8_t[dst_size];
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);
636 EXPECT_TRUE (converter->checkCapability ());
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;
642 EXPECT_EQ (converter->perform (), src_size);
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));
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]);
665 * @brief main function for unit test
668 main (int argc, char **argv) {
669 return start_gtest (argc, argv);