sc_runner.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. * Timer Service Implementation for SCTUnit
  3. */
  4. #include "sc_runner.h"
  5. /**
  6. * Implementation of a timer service that uses _virtual_ time to raise time events.
  7. * It is solely meant for use with sctunit.
  8. */
  9. SctUnitRunner::SctUnitRunner(
  10. StatemachineInterface * statemachine,
  11. bool event_driven,
  12. sc_integer cycle_period
  13. ) :
  14. statemachine(statemachine),
  15. event_driven(event_driven),
  16. cycle_period(event_driven ? -1 : cycle_period),
  17. current_time_ms(0),
  18. timer_queue()
  19. {
  20. if(!event_driven) {
  21. SctTimer runCycle(
  22. cycle_period,
  23. true,
  24. 0,
  25. -1,
  26. true
  27. );
  28. insert_timer(runCycle);
  29. }
  30. }
  31. void SctUnitRunner::proceed_time(sc_integer time_ms)
  32. {
  33. sc_integer stop_time_ms = current_time_ms + time_ms;
  34. bool processed_timer = false;
  35. do {
  36. // first assume we won't process a timer
  37. processed_timer = false;
  38. // and then check if there is a timer to process
  39. if( ! timer_queue.empty()) {
  40. SctTimer next = timer_queue.front();
  41. if(next.abs_time_ms <= stop_time_ms) {
  42. timer_queue.pop_front();
  43. current_time_ms = next.abs_time_ms;
  44. /* Repeat and reinsert timer? */
  45. if(next.periodic) {
  46. insert_timer(next);
  47. }
  48. if(next.is_runcycle) {
  49. statemachine->runCycle();
  50. }
  51. processed_timer = true;
  52. }
  53. }
  54. } while ( processed_timer );
  55. // As a postcondition the current time is the time after proceeding the specified period.
  56. current_time_ms = stop_time_ms;
  57. }
  58. void SctUnitRunner::proceed_cycles(sc_integer cycles)
  59. {
  60. sc_integer elapsed_cycles = 0;
  61. while(elapsed_cycles < cycles) {
  62. if(timer_queue.empty()) {
  63. return;
  64. }
  65. SctTimer next = timer_queue.front();
  66. timer_queue.pop_front();
  67. current_time_ms = next.abs_time_ms;
  68. std::list<SctTimer>::iterator i_timer;
  69. /* Repeat and reinsert timer? */
  70. if(next.periodic) {
  71. insert_timer(next);
  72. }
  73. if(next.is_runcycle) {
  74. statemachine->runCycle();
  75. elapsed_cycles++;
  76. }
  77. }
  78. }
  79. void SctUnitRunner::cancel()
  80. {
  81. std::list<SctTimer>::iterator i_timer = timer_queue.begin();
  82. while(i_timer != timer_queue.end()) {
  83. i_timer = timer_queue.erase(i_timer);
  84. }
  85. }
  86. void SctUnitRunner::insert_timer(SctTimer timer)
  87. {
  88. timer.abs_time_ms = current_time_ms + timer.rel_time_ms;
  89. std::list<SctTimer>::iterator i_timer;
  90. /* Either the list is empty, so we put the new timer in directly... */
  91. if(timer_queue.empty()) {
  92. timer_queue.push_front(timer);
  93. return;
  94. }
  95. /* Or we put it before some other timer that needs to be raised after this one */
  96. for(i_timer = timer_queue.begin(); i_timer != timer_queue.end(); i_timer++) {
  97. if(timer.compare(&(*i_timer)) < 0) {
  98. timer_queue.insert(i_timer, timer);
  99. return;
  100. }
  101. }
  102. /* Or it gets put into the back of the list. */
  103. timer_queue.push_back(timer);
  104. }
  105. SctUnitRunner::SctTimer::SctTimer(
  106. sc_integer time_ms,
  107. bool periodic,
  108. sc_eventid evid,
  109. sc_integer priority,
  110. sc_boolean is_runcycle
  111. ) :
  112. rel_time_ms(time_ms),
  113. abs_time_ms(0),
  114. periodic(periodic),
  115. pt_evid(evid),
  116. priority(priority),
  117. is_runcycle(is_runcycle)
  118. {}
  119. sc_integer SctUnitRunner::SctTimer::compare(SctTimer * other)
  120. {
  121. sc_integer result = abs_time_ms - other->abs_time_ms;
  122. if(result != 0) {
  123. return result;
  124. } else {
  125. // bigger priority needs to be raised first
  126. result = other->priority - priority;
  127. return result;
  128. }
  129. }