sc_runner_timed.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. * Timer Service Implementation for SCTUnit
  3. */
  4. #include "sc_runner_timed.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. TimedSctUnitRunner::TimedSctUnitRunner(
  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 TimedSctUnitRunner::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. } else {
  51. TimedStatemachineInterface * tsi = dynamic_cast<TimedStatemachineInterface*>(statemachine);
  52. tsi->raiseTimeEvent(next.pt_evid);
  53. }
  54. processed_timer = true;
  55. }
  56. }
  57. } while ( processed_timer );
  58. // As a postcondition the current time is the time after proceeding the specified period.
  59. current_time_ms = stop_time_ms;
  60. }
  61. void TimedSctUnitRunner::proceed_cycles(sc_integer cycles)
  62. {
  63. sc_integer elapsed_cycles = 0;
  64. while(elapsed_cycles < cycles) {
  65. if(timer_queue.empty()) {
  66. return;
  67. }
  68. SctTimer next = timer_queue.front();
  69. timer_queue.pop_front();
  70. current_time_ms = next.abs_time_ms;
  71. std::list<SctTimer>::iterator i_timer;
  72. /* Repeat and reinsert timer? */
  73. if(next.periodic) {
  74. insert_timer(next);
  75. }
  76. if(next.is_runcycle) {
  77. statemachine->runCycle();
  78. elapsed_cycles++;
  79. } else {
  80. TimedStatemachineInterface * tsi = dynamic_cast<TimedStatemachineInterface*>(statemachine);
  81. tsi->raiseTimeEvent(next.pt_evid);
  82. }
  83. }
  84. }
  85. void TimedSctUnitRunner::setTimer(TimedStatemachineInterface* statemachine, sc_eventid event, sc_integer time_ms, sc_boolean isPeriodic)
  86. {
  87. SctTimer timer(time_ms, isPeriodic, event, 0, false);
  88. insert_timer(timer);
  89. }
  90. void TimedSctUnitRunner::unsetTimer(TimedStatemachineInterface* statemachine, sc_eventid event)
  91. {
  92. std::list<SctTimer>::iterator i_timer = timer_queue.begin();
  93. while(i_timer != timer_queue.end()) {
  94. if(i_timer->pt_evid == event) {
  95. timer_queue.erase(i_timer);
  96. return;
  97. }
  98. i_timer++;
  99. }
  100. }
  101. void TimedSctUnitRunner::cancel()
  102. {
  103. std::list<SctTimer>::iterator i_timer = timer_queue.begin();
  104. while(i_timer != timer_queue.end()) {
  105. i_timer = timer_queue.erase(i_timer);
  106. }
  107. }
  108. void TimedSctUnitRunner::insert_timer(SctTimer timer)
  109. {
  110. timer.abs_time_ms = current_time_ms + timer.rel_time_ms;
  111. std::list<SctTimer>::iterator i_timer;
  112. /* Either the list is empty, so we put the new timer in directly... */
  113. if(timer_queue.empty()) {
  114. timer_queue.push_front(timer);
  115. return;
  116. }
  117. /* Or we put it before some other timer that needs to be raised after this one */
  118. for(i_timer = timer_queue.begin(); i_timer != timer_queue.end(); i_timer++) {
  119. if(timer.compare(&(*i_timer)) < 0) {
  120. timer_queue.insert(i_timer, timer);
  121. return;
  122. }
  123. }
  124. /* Or it gets put into the back of the list. */
  125. timer_queue.push_back(timer);
  126. }
  127. TimedSctUnitRunner::SctTimer::SctTimer(
  128. sc_integer time_ms,
  129. bool periodic,
  130. sc_eventid evid,
  131. sc_integer priority,
  132. sc_boolean is_runcycle
  133. ) :
  134. rel_time_ms(time_ms),
  135. abs_time_ms(0),
  136. periodic(periodic),
  137. pt_evid(evid),
  138. priority(priority),
  139. is_runcycle(is_runcycle)
  140. {}
  141. sc_integer TimedSctUnitRunner::SctTimer::compare(SctTimer * other)
  142. {
  143. sc_integer result = abs_time_ms - other->abs_time_ms;
  144. if(result != 0) {
  145. return result;
  146. } else {
  147. // bigger priority needs to be raised first
  148. result = other->priority - priority;
  149. return result;
  150. }
  151. }