123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- /*
- * Timer Service Implementation for SCTUnit
- */
- #include "sc_runner_timed.h"
- /**
- * Implementation of a timer service that uses _virtual_ time to raise time events.
- * It is solely meant for use with sctunit.
- */
- TimedSctUnitRunner::TimedSctUnitRunner(
- StatemachineInterface * statemachine,
- bool event_driven,
- sc_integer cycle_period
- ) :
- statemachine(statemachine),
- event_driven(event_driven),
- cycle_period(event_driven ? -1 : cycle_period),
- current_time_ms(0),
- timer_queue()
- {
- if(!event_driven) {
- SctTimer runCycle(
- cycle_period,
- true,
- 0,
- -1,
- true
- );
- insert_timer(runCycle);
- }
- }
- void TimedSctUnitRunner::proceed_time(sc_integer time_ms)
- {
- sc_integer stop_time_ms = current_time_ms + time_ms;
- bool processed_timer = false;
- do {
-
- // first assume we won't process a timer
- processed_timer = false;
- // and then check if there is a timer to process
- if( ! timer_queue.empty()) {
- SctTimer next = timer_queue.front();
- if(next.abs_time_ms <= stop_time_ms) {
- timer_queue.pop_front();
- current_time_ms = next.abs_time_ms;
- /* Repeat and reinsert timer? */
- if(next.periodic) {
- insert_timer(next);
- }
- if(next.is_runcycle) {
- statemachine->runCycle();
- } else {
- TimedStatemachineInterface * tsi = dynamic_cast<TimedStatemachineInterface*>(statemachine);
- tsi->raiseTimeEvent(next.pt_evid);
- }
- processed_timer = true;
- }
- }
- } while ( processed_timer );
- // As a postcondition the current time is the time after proceeding the specified period.
- current_time_ms = stop_time_ms;
- }
- void TimedSctUnitRunner::proceed_cycles(sc_integer cycles)
- {
- sc_integer elapsed_cycles = 0;
-
- while(elapsed_cycles < cycles) {
- if(timer_queue.empty()) {
- return;
- }
- SctTimer next = timer_queue.front();
-
- timer_queue.pop_front();
-
- current_time_ms = next.abs_time_ms;
-
- std::list<SctTimer>::iterator i_timer;
-
- /* Repeat and reinsert timer? */
- if(next.periodic) {
- insert_timer(next);
- }
-
- if(next.is_runcycle) {
- statemachine->runCycle();
- elapsed_cycles++;
- } else {
- TimedStatemachineInterface * tsi = dynamic_cast<TimedStatemachineInterface*>(statemachine);
- tsi->raiseTimeEvent(next.pt_evid);
- }
- }
- }
- void TimedSctUnitRunner::setTimer(TimedStatemachineInterface* statemachine, sc_eventid event, sc_integer time_ms, sc_boolean isPeriodic)
- {
- SctTimer timer(time_ms, isPeriodic, event, 0, false);
- insert_timer(timer);
- }
- void TimedSctUnitRunner::unsetTimer(TimedStatemachineInterface* statemachine, sc_eventid event)
- {
- std::list<SctTimer>::iterator i_timer = timer_queue.begin();
- while(i_timer != timer_queue.end()) {
- if(i_timer->pt_evid == event) {
- timer_queue.erase(i_timer);
- return;
- }
- i_timer++;
- }
- }
- void TimedSctUnitRunner::cancel()
- {
- std::list<SctTimer>::iterator i_timer = timer_queue.begin();
- while(i_timer != timer_queue.end()) {
- i_timer = timer_queue.erase(i_timer);
- }
- }
- void TimedSctUnitRunner::insert_timer(SctTimer timer)
- {
- timer.abs_time_ms = current_time_ms + timer.rel_time_ms;
-
- std::list<SctTimer>::iterator i_timer;
-
- /* Either the list is empty, so we put the new timer in directly... */
- if(timer_queue.empty()) {
- timer_queue.push_front(timer);
- return;
- }
-
-
- /* Or we put it before some other timer that needs to be raised after this one */
- for(i_timer = timer_queue.begin(); i_timer != timer_queue.end(); i_timer++) {
- if(timer.compare(&(*i_timer)) < 0) {
- timer_queue.insert(i_timer, timer);
- return;
- }
- }
-
- /* Or it gets put into the back of the list. */
- timer_queue.push_back(timer);
- }
- TimedSctUnitRunner::SctTimer::SctTimer(
- sc_integer time_ms,
- bool periodic,
- sc_eventid evid,
- sc_integer priority,
- sc_boolean is_runcycle
- ) :
- rel_time_ms(time_ms),
- abs_time_ms(0),
- periodic(periodic),
- pt_evid(evid),
- priority(priority),
- is_runcycle(is_runcycle)
- {}
- sc_integer TimedSctUnitRunner::SctTimer::compare(SctTimer * other)
- {
- sc_integer result = abs_time_ms - other->abs_time_ms;
- if(result != 0) {
- return result;
- } else {
- // bigger priority needs to be raised first
- result = other->priority - priority;
- return result;
- }
- }
|