imc_extension.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "ImC/imc_kernel.h"
  4. #include "ImC/imc_extension.h"
  5. #include "ImC/imc_api.h"
  6. extern ADC_HandleTypeDef ADC_HANDLER_SBC;
  7. // int loop_pass_estimation_backup[imcMAX_LOOP_IDS] IMC_KERNEL_NVM;
  8. int loop_pass_estimation[imcMAX_LOOP_IDS];
  9. int imc_is_passing_loops_backup IMC_KERNEL_NVM;
  10. int imc_is_passing_loops;
  11. int imc_energy_at_start;
  12. int estimation_backup[2][imcMAX_LOOP_IDS] IMC_KERNEL_NVM;
  13. int imc_energy_estimation_initialized IMC_KERNEL_NVM;
  14. int latest_buffer_index IMC_KERNEL_NVM;
  15. int last_loop_skip_count;
  16. int pass_due_to_low_energy;
  17. #if(imcPRINT_STATS)
  18. int imc_checkpoint_triggered IMC_KERNEL_NVM;
  19. int imc_checkpoint_executed IMC_KERNEL_NVM;
  20. #endif
  21. void imc_recover_estimations() {
  22. memcpy(loop_pass_estimation, estimation_backup[latest_buffer_index], sizeof(int) * imcMAX_LOOP_IDS);
  23. __DSB();
  24. }
  25. void imc_backup_estimations() {
  26. int nextBufferIndex = latest_buffer_index == 0 ? 1 : 0;
  27. memcpy(estimation_backup[nextBufferIndex], loop_pass_estimation, sizeof(int) * imcMAX_LOOP_IDS);
  28. __DSB();
  29. latest_buffer_index = nextBufferIndex;
  30. __DSB();
  31. }
  32. void imc_init_energy_estimation() {
  33. if(!imc_energy_estimation_initialized) {
  34. for(int i=0; i<imcMAX_LOOP_IDS; i++) {
  35. loop_pass_estimation[i] = 1;
  36. }
  37. latest_buffer_index = 0;
  38. imc_backup_estimations();
  39. } else {
  40. imc_recover_estimations();
  41. }
  42. if(imc_energy_estimation_initialized && imc_is_passing_loops_backup != -1) {
  43. int loop_id = imc_is_passing_loops_backup;
  44. int new_estimation = loop_pass_estimation[loop_id] / 2;
  45. loop_pass_estimation[loop_id] = new_estimation;
  46. estimation_backup[latest_buffer_index][loop_id] = new_estimation;
  47. // printf("(recovery) estimation for loop %d is updated to %d\r\n", loop_id, loop_pass_estimation[loop_id]);
  48. }
  49. imc_energy_estimation_initialized = 1;
  50. imc_is_passing_loops_backup = -1;
  51. imc_is_passing_loops = -1;
  52. __DSB();
  53. }
  54. void __imc_unflag_loop_skipping()
  55. {
  56. imc_is_passing_loops_backup = -1;
  57. imc_is_passing_loops = -1;
  58. __DSB();
  59. }
  60. void __imc_finish_loop_skipping() {
  61. int loop_id = imc_is_passing_loops;
  62. if(loop_id == 0) {
  63. printf("imc_is_passing_loop is 0\r\n");
  64. while(1) { __ASM(" nop"); }
  65. }
  66. if(loop_id > 0) {
  67. int volt = measure_voltage(ADC_HANDLER_SBC, EPS_CAP_ID_SBC);
  68. // printf("imc_finish_loop_skipping() called with loopId = %d\r\n", loop_id);
  69. int energy = volt*volt - imcCAP_VOL_LOW*imcCAP_VOL_LOW;
  70. // int ratio = energy * 100 / imcENERGY_TOTAL;
  71. int energy_consumed = imc_energy_at_start - energy;
  72. // int consumed_ratio = energy_consumed * 100 / imcENERGY_TOTAL;
  73. // if(ratio > 5) {
  74. // printf("last loop skip count: %d\r\n", last_loop_skip_count);
  75. int last_skip_is_zero = last_loop_skip_count == 0;
  76. int energy_per_iteration = energy_consumed / last_loop_skip_count;
  77. int underestimated = energy_per_iteration * 10 < energy;
  78. // if(energy_consumed / last_loop_skip_count < 2 * energy) {
  79. if(!last_skip_is_zero && underestimated) {
  80. int current_estimation = loop_pass_estimation[loop_id];
  81. // printf("current estimation for loop_%d: %d\r\n", loop_id, current_estimation);
  82. double inc_factor = 2;
  83. if (current_estimation * inc_factor > (double)INT32_MAX)
  84. {
  85. // printf("remaining energy: %d\r\n", remaining_energy);
  86. current_estimation = INT32_MAX/2-1;
  87. }
  88. else
  89. {
  90. current_estimation = (int)(current_estimation * inc_factor);
  91. // printf("remaining energy: %d\r\n", remaining_energy);
  92. }
  93. if (current_estimation < 1) {
  94. current_estimation = 1;
  95. }
  96. loop_pass_estimation[loop_id] = current_estimation;
  97. // loop_pass_estimation_backup[loop_id] = current_estimation;
  98. portDISABLE_INTERRUPTS();
  99. // printf("estimation for loop %d is updated to %d\r\n", loop_id, current_estimation);
  100. portENABLE_INTERRUPTS();
  101. }
  102. }
  103. imc_is_passing_loops_backup = -1;
  104. imc_is_passing_loops = -1;
  105. __DSB();
  106. }
  107. int __imc_get_loop_pass_count(int loop_id) {
  108. #if(imcENABLE_STATIC_LOOP_PASS_COUNT)
  109. return imcLOOP_PASS_COUNT;
  110. #elif(imcENABLE_ADAPTIVE_LOOP_PASS_COUNT)
  111. int volt = measure_voltage(ADC_HANDLER_SBC, EPS_CAP_ID_SBC);
  112. // if(volt < imcCHECKPOINT_VOLTAGE) {
  113. // imcREQUEST_CHECKPOINT();
  114. // }
  115. int energy = volt*volt - imcCAP_VOL_LOW*imcCAP_VOL_LOW;
  116. int ratio = energy * 100 / imcENERGY_TOTAL;
  117. // float energy_available = (float)(volt*volt - imcCAP_VOL_LOW*imcCAP_VOL_LOW) / imcENERGY_TOTAL;
  118. imc_is_passing_loops = loop_id;
  119. imc_is_passing_loops_backup = loop_id;
  120. __DSB();
  121. imc_energy_at_start = energy;
  122. // printf("write %d to imc_is_passing_loops\r\n", imc_is_passing_loops);
  123. // printf("energy available: %f\r\n", energy_available);
  124. // if(energy_available > 1) return (int)(energy_available / loop_energy_estimation[loop_id]);
  125. // else if(energy_available < 0) return 0;
  126. // else return (int)(energy_available / loop_energy_estimation[loop_id]);
  127. int current_estimation = loop_pass_estimation[loop_id];
  128. if(ratio > 100) {
  129. last_loop_skip_count = current_estimation;
  130. }
  131. else if(ratio < 0) {
  132. last_loop_skip_count = 0;
  133. // imc_sbc_power_off();
  134. // while(1) { __ASM(" nop"); }
  135. // printf("__imc_get_loop_pass_count(%d) called; %d returned\r\n", loop_id, last_loop_skip_count);
  136. }
  137. else {
  138. double r = (double)(ratio) / 100.0;
  139. last_loop_skip_count = (int)((double)current_estimation * r);
  140. // last_loop_skip_count = loop_pass_estimation[loop_id] * ((double)(ratio) / 100.0);
  141. }
  142. // printf("loopId: %d, volt: %d, energy: %d, total: %d, ratio: %d, est:%d, count:%d\r\n", loop_id, volt, energy, imcENERGY_TOTAL, ratio, current_estimation, last_loop_skip_count);
  143. return last_loop_skip_count;
  144. #else
  145. return 0;
  146. #endif
  147. }