main.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. #include <stdio.h>
  2. #include "nuclei_sdk_soc.h"
  3. #if !defined(__riscv_atomic)
  4. #error "RVA(atomic) extension is required for SMP"
  5. #endif
  6. #if !defined(SMP_CPU_CNT)
  7. #error "SMP_CPU_CNT macro is not defined, please set SMP_CPU_CNT to integer value > 1"
  8. #endif
  9. typedef struct {
  10. uint32_t state;
  11. } spinlock;
  12. spinlock lock;
  13. volatile uint32_t lock_ready = 0;
  14. volatile uint32_t cpu_count = 0;
  15. volatile uint32_t finished = 0;
  16. // comment SPINLOCK_CAS to use AMOSWAP as spinlock
  17. #define SPINLOCK_CAS
  18. __STATIC_FORCEINLINE void spinlock_init(spinlock *lock)
  19. {
  20. lock->state = 0;
  21. }
  22. __STATIC_FORCEINLINE void spinlock_lock(spinlock *lock)
  23. {
  24. uint32_t old;
  25. uint32_t backoff = 10;
  26. do {
  27. #ifndef SPINLOCK_CAS
  28. // Use amoswap as spinlock
  29. old = __AMOSWAP_W((&(lock->state)), 1);
  30. #else
  31. // use lr.w & sc.w to do CAS as spinlock
  32. old = __CAS_W((&(lock->state)), 0, 1);
  33. #endif
  34. if (old == 0) {
  35. break;
  36. }
  37. for (volatile int i = 0; i < backoff; i ++) {
  38. __NOP();
  39. }
  40. backoff += 10;
  41. } while (1);
  42. }
  43. __STATIC_FORCEINLINE void spinlock_unlock(spinlock *lock)
  44. {
  45. lock->state = 0;
  46. }
  47. int boot_hart_main(unsigned long hartid);
  48. int other_harts_main(unsigned long hartid);
  49. int main(void);
  50. /* Reimplementation of smp_main for multi-harts */
  51. int smp_main(void)
  52. {
  53. return main();
  54. }
  55. int main(void)
  56. {
  57. int ret;
  58. // get hart id in current cluster
  59. unsigned long hartid = __get_hart_id();
  60. if (hartid == BOOT_HARTID) { // boot hart
  61. spinlock_init(&lock);
  62. lock_ready = 1;
  63. finished = 0;
  64. __SMP_RWMB();
  65. ret = boot_hart_main(hartid);
  66. } else { // other harts
  67. // wait for lock initialized
  68. while (lock_ready == 0);
  69. ret = other_harts_main(hartid);
  70. }
  71. return ret;
  72. }
  73. int boot_hart_main(unsigned long hartid)
  74. {
  75. volatile unsigned long waitcnt = 0;
  76. spinlock_lock(&lock);
  77. printf("Hello world from hart %lu\n", hartid);
  78. cpu_count += 1;
  79. spinlock_unlock(&lock);
  80. // wait for all harts boot and print hello
  81. while (cpu_count < SMP_CPU_CNT) {
  82. waitcnt ++;
  83. __NOP();
  84. // The waitcnt compare value need to be adjust according
  85. // to cpu frequency
  86. if (waitcnt >= SystemCoreClock) {
  87. break;
  88. }
  89. }
  90. if (cpu_count == SMP_CPU_CNT) {
  91. printf("All harts boot successfully!\n");
  92. finished = 1;
  93. return 0;
  94. } else {
  95. printf("Some harts boot failed, only %d/%d booted!\n", cpu_count, SMP_CPU_CNT);
  96. return -1;
  97. }
  98. }
  99. int other_harts_main(unsigned long hartid)
  100. {
  101. spinlock_lock(&lock);
  102. printf("Hello world from hart %lu\n", hartid);
  103. cpu_count += 1;
  104. spinlock_unlock(&lock);
  105. // wait for all harts boot and print hello
  106. while (cpu_count < SMP_CPU_CNT);
  107. // wait for boot hart to set finished flag
  108. while (finished == 0);
  109. return 0;
  110. }