test_vector.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. */
  9. #include <rtthread.h>
  10. #include <rthw.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #if defined(RT_USING_UTEST) && defined(ENABLE_VECTOR)
  14. #include <utest.h>
  15. #include <ext_context.h>
  16. void rt_hw_vector_ctx_restore(void *buf);
  17. void rt_hw_vector_ctx_save(void *buf);
  18. /**
  19. * ==============================================================
  20. * TEST FEATURE
  21. * Use libc `memcpy` which employing V extension codes
  22. * to test V extension features
  23. * ==============================================================
  24. */
  25. static char *constant = "hello,it's a nice day and i'm happy to see you\n";
  26. #define ARR_SIZE 4096
  27. static char array[ARR_SIZE];
  28. static void test_feature(void)
  29. {
  30. memcpy(array, constant, sizeof array);
  31. char *src = constant;
  32. char *dst = array;
  33. int error = 0;
  34. for (size_t i = 0; i < ARR_SIZE; i++)
  35. {
  36. if (src[i] != dst[i])
  37. {
  38. error = 1;
  39. break;
  40. }
  41. }
  42. uassert_false(error);
  43. }
  44. /**
  45. * ==============================================================
  46. * TEST CONTEXT SAVING
  47. * Create 2 threads employing V extension, verify V states are
  48. * not modified by each other
  49. * ==============================================================
  50. */
  51. #define TEST_THREAD 2
  52. #define VECTOR_CTX_BYTES (CTX_VECTOR_REG_NR * REGBYTES)
  53. void *ctx_vector[TEST_THREAD * 2];
  54. static rt_sem_t sem;
  55. void dump_frame(void *frame)
  56. {
  57. uint64_t *content = frame;
  58. for (size_t i = 0; i < VECTOR_CTX_BYTES / 8; i++)
  59. {
  60. rt_kprintf("%x ", content[i]);
  61. }
  62. rt_kprintf("\n");
  63. }
  64. static void vector_child(void *param)
  65. {
  66. void **ctx = param;
  67. uint64_t *reg = ctx[0];
  68. uint64_t vtype;
  69. uint64_t vl;
  70. rt_sem_release(sem);
  71. rt_hw_vector_ctx_restore(ctx[0]);
  72. /* STAGE 2, save t2 context */
  73. test_feature();
  74. /**
  75. * @brief vtype & vl will be modified after context saving,
  76. * it's ok because it will be recover after context restoring
  77. * We restore these states manually here.
  78. */
  79. asm volatile("csrr %0, vtype":"=r"(vtype));
  80. asm volatile("csrr %0, vl":"=r"(vl));
  81. rt_hw_vector_ctx_save(ctx[0]);
  82. rt_memcpy(ctx[1], ctx[0], VECTOR_CTX_BYTES);
  83. rt_thread_yield();
  84. asm volatile("vsetvl x0, %0, %1"::"r"(vl), "r"(vtype));
  85. rt_hw_vector_ctx_save(ctx[0]);
  86. uassert_false(rt_memcmp(ctx[1], ctx[0], VECTOR_CTX_BYTES));
  87. }
  88. /**
  89. * @brief Test if context save/restore codes work properly
  90. */
  91. static void test_context()
  92. {
  93. rt_thread_t child;
  94. uint64_t vtype;
  95. uint64_t vl;
  96. for (size_t i = 0; i < TEST_THREAD; i++)
  97. {
  98. ctx_vector[i * 2] = calloc(VECTOR_CTX_BYTES, 1);
  99. ctx_vector[i * 2 + 1] = calloc(VECTOR_CTX_BYTES, 1);
  100. }
  101. rt_hw_vector_ctx_restore(ctx_vector[0]);
  102. child = rt_thread_create("test_vector_child", vector_child, &ctx_vector[2], 4096, 10, 20);
  103. /* STAGE 1, save t1 context */
  104. /* assuming that rt libc memcpy do not use vector instruction */
  105. asm volatile("csrr %0, vtype":"=r"(vtype));
  106. asm volatile("csrr %0, vl":"=r"(vl));
  107. rt_hw_vector_ctx_save(ctx_vector[0]);
  108. rt_memcpy(ctx_vector[1], ctx_vector[0], VECTOR_CTX_BYTES);
  109. rt_thread_startup(child);
  110. rt_sem_take(sem, 0);
  111. /* STAGE 3, verify t1 context */
  112. asm volatile("vsetvl x0, %0, %1"::"r"(vl), "r"(vtype));
  113. rt_hw_vector_ctx_save(ctx_vector[0]);
  114. uassert_false(rt_memcmp(ctx_vector[1], ctx_vector[0], VECTOR_CTX_BYTES));
  115. rt_thread_yield();
  116. }
  117. /**
  118. * ==============================================================
  119. * TEST NO VECTOR raise error and recover
  120. * ==============================================================
  121. */
  122. static void test_no_vector()
  123. {
  124. asm volatile ("li t0, 0x600\n"
  125. "csrc sstatus, t0");
  126. test_feature();
  127. uassert_true(1);
  128. }
  129. static rt_err_t utest_tc_init(void)
  130. {
  131. sem = rt_sem_create("test_ctx", 0, RT_IPC_FLAG_FIFO);
  132. return RT_EOK;
  133. }
  134. static rt_err_t utest_tc_cleanup(void)
  135. {
  136. rt_sem_delete(sem);
  137. return RT_EOK;
  138. }
  139. static void testcase(void)
  140. {
  141. UTEST_UNIT_RUN(test_feature);
  142. UTEST_UNIT_RUN(test_context);
  143. UTEST_UNIT_RUN(test_no_vector);
  144. }
  145. UTEST_TC_EXPORT(testcase, "testcases.libcpu.vector", utest_tc_init, utest_tc_cleanup, 10);
  146. #endif /* RT_USING_UTEST && ENABLE_VECTOR */