cacheprofile_stat.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. * Copyright (c) 2017 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file
  8. * @brief cpu load statistic
  9. */
  10. #if defined(CONFIG_SOC_SPICACHE_PROFILE)
  11. #include <shell/shell.h>
  12. #include <init.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <spicache.h>
  16. static struct spicache_profile profile_data;
  17. #define RUNNING_CYCLES(end, start) ((uint32_t)((long)(end) - (long)(start)))
  18. /* start flag */
  19. static int cacheprofile_started;
  20. /* cpu load poll interval, unit: ms */
  21. static int cacheprofile_interval;
  22. struct k_delayed_work cacheprofile_stat_work;
  23. void cacheprofile_stat(uint32_t interval);
  24. void spicache_stat_profile_dump(struct spicache_profile *profile)
  25. {
  26. u32_t interval_ms;
  27. u64_t hit_cnt, total;
  28. if (!profile)
  29. return;
  30. interval_ms = k_cyc_to_ns_floor64((profile->end_time - profile->start_time)) / 1000000;
  31. if (profile->spi_id == 0) {
  32. hit_cnt = (u64_t)profile->hit_cnt * 8;
  33. total = hit_cnt + profile->miss_cnt;
  34. if (total != 0){
  35. printk("spi%d cache profile: addr range 0x%08x ~ 0x%08x, profile time %u ms\n",
  36. profile->spi_id, profile->start_addr, profile->end_addr, interval_ms);
  37. printk("range hit: %u,%u miss: %u miss ratio: %u %%%% \n",
  38. (u32_t)(hit_cnt >> 32), (u32_t)hit_cnt,
  39. profile->miss_cnt,
  40. (u32_t)(((u64_t)profile->miss_cnt * 100 * 100) / total));
  41. hit_cnt = (u64_t)profile->total_hit_cnt * 8;
  42. total = hit_cnt + profile->total_miss_cnt;
  43. if (total != 0)
  44. printk("total hit: %u,%u miss: %u miss time ratio: %u %%%% \n",
  45. (u32_t)(hit_cnt >> 32), (u32_t)hit_cnt, profile->total_miss_cnt,
  46. (u32_t)(((u64_t)profile->total_miss_cnt * 34 * 80 / (4 * 100)) / interval_ms));
  47. }
  48. }
  49. }
  50. /*
  51. * cmd: spicache_profile
  52. * start start_addr end_addr
  53. * stop
  54. */
  55. int shell_cmd_spicache_profile(int argc, char *argv[])
  56. {
  57. struct spicache_profile *profile;
  58. int len = strlen(argv[1]);
  59. profile = &profile_data;
  60. if (!strncmp(argv[1], "start", len)) {
  61. if (argc < 5)
  62. return -EINVAL;
  63. memset(profile, 0, sizeof(struct spicache_profile));
  64. profile->start_addr = strtoul(argv[2], NULL, 0);
  65. profile->end_addr = strtoul(argv[3], NULL, 0);
  66. profile->spi_id = strtoul(argv[4], NULL, 0);
  67. printk("Start profile: addr range %08x ~ %08x\n",
  68. profile->start_addr, profile->end_addr);
  69. spicache_profile_start(profile);
  70. } else if (!strncmp(argv[1], "stop", len)) {
  71. printk("Stop profile\n");
  72. spicache_profile_stop(profile);
  73. spicache_stat_profile_dump(profile);
  74. } else {
  75. printk("usage:\n");
  76. printk(" spicache_profile start start_addr end_addr 0/1 \n");
  77. printk(" spicache_profile stop\n");
  78. return -EINVAL;
  79. }
  80. return 0;
  81. }
  82. static void cacheprofile_stat_clear(void)
  83. {
  84. struct spicache_profile *profile;
  85. profile = &profile_data;
  86. unsigned int key;
  87. key = irq_lock();
  88. memset(profile, 0, sizeof(struct spicache_profile));
  89. irq_unlock(key);
  90. }
  91. static void cacheprofile_stat_callback(struct k_work *work)
  92. {
  93. cacheprofile_stat(cacheprofile_interval);
  94. }
  95. void cacheprofile_stat_start(int interval_ms, u32_t start_addr, u32_t end_addr, u32_t step_addr, u32_t profile_id)
  96. {
  97. struct spicache_profile *profile;
  98. profile = &profile_data;
  99. if (!start_addr || !end_addr || !step_addr || !interval_ms || (interval_ms < 500))
  100. return;
  101. if (start_addr >= end_addr || (start_addr + step_addr) >= end_addr)
  102. return;
  103. if (cacheprofile_started)
  104. k_delayed_work_cancel(&cacheprofile_stat_work);
  105. printk("Start profile stat: addr range %08x ~ %08x step %08x interval:%08x ms\n",
  106. start_addr, end_addr, step_addr, interval_ms);
  107. cacheprofile_stat_clear();
  108. cacheprofile_interval = interval_ms;
  109. cacheprofile_started = 1;
  110. profile->start_addr = start_addr;
  111. profile->end_addr = start_addr + step_addr;
  112. profile->limit_addr = end_addr;
  113. profile->spi_id = profile_id;
  114. spicache_profile_start(profile);
  115. k_delayed_work_init(&cacheprofile_stat_work, cacheprofile_stat_callback);
  116. k_delayed_work_submit(&cacheprofile_stat_work, K_MSEC(interval_ms));
  117. }
  118. void cacheprofile_stat_stop(void)
  119. {
  120. k_delayed_work_cancel(&cacheprofile_stat_work);
  121. cacheprofile_started = 0;
  122. }
  123. void cacheprofile_stat(uint32_t interval)
  124. {
  125. u32_t step_addr;
  126. struct spicache_profile *profile;
  127. profile = &profile_data;
  128. spicache_profile_stop(profile);
  129. spicache_stat_profile_dump(profile);
  130. step_addr = profile->end_addr - profile->start_addr;
  131. printk("profile end %x step %x limit %x\n", profile->end_addr, step_addr, \
  132. profile->limit_addr);
  133. if(profile->end_addr + step_addr <= profile->limit_addr){
  134. profile->start_addr = profile->end_addr;
  135. profile->end_addr += step_addr;
  136. spicache_profile_start(profile);
  137. k_delayed_work_submit(&cacheprofile_stat_work, K_MSEC(cacheprofile_interval));
  138. }else{
  139. cacheprofile_stat_stop();
  140. printk("Stop profile\n");
  141. }
  142. }
  143. /*
  144. * cmd: spicache_profile
  145. * start start_addr end_addr
  146. * stop
  147. */
  148. int shell_cmd_spicache_profile_stat(const struct shell *shell,
  149. size_t argc, char **argv)
  150. {
  151. struct spicache_profile *profile;
  152. int len = strlen(argv[1]);
  153. u32_t start_addr, end_addr, step_addr, spi_id, interval_ms;
  154. profile = &profile_data;
  155. if (!strncmp(argv[1], "start", len)) {
  156. printk("argc %d\n", argc);
  157. if (argc < 7)
  158. return -EINVAL;
  159. start_addr = strtoul(argv[2], NULL, 0);
  160. end_addr = strtoul(argv[3], NULL, 0);
  161. step_addr = strtoul(argv[4], NULL, 0);
  162. spi_id = strtoul(argv[5], NULL, 0);
  163. interval_ms = strtoul(argv[6], NULL, 0);
  164. cacheprofile_stat_start(interval_ms, start_addr, end_addr, step_addr, spi_id);
  165. } else if (!strncmp(argv[1], "stop", len)) {
  166. cacheprofile_stat_stop();
  167. } else {
  168. printk("usage:\n");
  169. printk(" spicache_stat start start_addr end_addr step_addr 0/1 interval_ms\n");
  170. printk(" spicache_stat stop\n");
  171. return -EINVAL;
  172. }
  173. return 0;
  174. }
  175. #endif /* CONFIG_SOC_SPICACHE_PROFILE */