Commit 199a5e98393ec3151eec2464cf97f23ebb65740f
authorSami Liedes <sliedes@cc.hut.fi>
Tue, 15 Feb 2011 23:21:38 +0000 (01:21 +0200)
committerSami Liedes <sliedes@cc.hut.fi>
Tue, 15 Feb 2011 23:21:38 +0000 (01:21 +0200)
This speeds up cycle timer processing significantly and almost doubles
the speed of the overall simulation.

Signed-off-by: Sami Liedes <sliedes@cc.hut.fi>
2 files changed:
simavr/sim/sim_avr.h
simavr/sim/sim_cycle_timers.c

index 6d205d462ced20ca267e97d260320499b5f04d3c..32426dda5d029655f6c6ab80c7bd7a9e7a33038f 100644 (file)
@@ -156,6 +156,7 @@ typedef struct avr_t {
        // these timers are one shots, then get cleared if the timer function returns zero,
        // they get reset if the callback function returns a new cycle number
        uint32_t        cycle_timer_map;
+       avr_cycle_count_t next_cycle_timer;
        struct {
                avr_cycle_count_t       when;
                avr_cycle_timer_t       timer;
index 57fd0586f81ef2e8ad7a3d8c76ac5c2fb68eddf0..3bafa5c95d2fa95721f163072f613fa0a55fcc94 100644 (file)
@@ -33,6 +33,8 @@ void avr_cycle_timer_register(avr_t * avr, avr_cycle_count_t when, avr_cycle_tim
                return;
        }
        when += avr->cycle;
+       if (when < avr->next_cycle_timer)
+               avr->next_cycle_timer = when;
        for (int i = 0; i < 32; i++)
                if (!(avr->cycle_timer_map & (1 << i))) {
                        avr->cycle_timer[i].timer = timer;
@@ -60,6 +62,9 @@ void avr_cycle_timer_cancel(avr_t * avr, avr_cycle_timer_t timer, void * param)
                        avr->cycle_timer[i].param = NULL;
                        avr->cycle_timer[i].when = 0;
                        avr->cycle_timer_map &= ~(1 << i);
+                       // no need to reset next_cycle_timer; having too small
+                       // a value there only causes some harmless extra
+                       // computation.
                        return;
                }
 }
@@ -92,8 +97,15 @@ avr_cycle_timer_status(avr_t * avr, avr_cycle_timer_t timer, void * param)
  */
 avr_cycle_count_t avr_cycle_timer_process(avr_t * avr)
 {
-       if (!avr->cycle_timer_map)
+       // If we have previously determined that we don't need to fire
+       // cycle timers yet, we can do an early exit
+       if (avr->next_cycle_timer > avr->cycle)
+               return avr->next_cycle_timer - avr->cycle;
+
+       if (!avr->cycle_timer_map) {
+               avr->next_cycle_timer = (avr_cycle_count_t)-1;
                return (avr_cycle_count_t)-1;
+       }
 
        avr_cycle_count_t min = (avr_cycle_count_t)-1;
        uint32_t map = avr->cycle_timer_map;
@@ -120,5 +132,6 @@ avr_cycle_count_t avr_cycle_timer_process(avr_t * avr)
                        min = avr->cycle_timer[bit].when;
                map &= ~(1 << bit);             
        }
+       avr->next_cycle_timer = min;
        return min - avr->cycle;
 }