Commit 3c5e1ae3f560ba1568da247f4e835206ff12a264
authorbsekisser <squirmyworms@embarqmail.com>
Tue, 9 Sep 2014 21:53:56 +0000 (17:53 -0400)
committerbsekisser <squirmyworms@embarqmail.com>
Mon, 15 Sep 2014 20:22:24 +0000 (16:22 -0400)
 with per interval limiting.

Average cycle times drop by about upwards of 50-60+ cycles per emulated cycle,
dependant on usage.

sim_avr.h: struct avr_t changed.
added members run_cycle_count and run_cycle_limit.
run_cycle_count is number of cycles till next cycle timer.
run_cycle_limit is maximum number of cycles to run per interval.

sim_core.c: avr_run_one
* run_one_again label added at top.
* clause added at end which loops to run_one_again given that the core
is still in a cpu_Running state, run_cycle_count is greater than
cycles, and no interrups are pending.

sim_cycle_timers.c:
* static avr_cycle_timer_return_sleep_run_cycles_limited() added.
run_cycle_count is bounded to run_cycle_limit.
returns sleep count unbounded, preserving original behavior.

* static avr_cycle_timer_reset_sleep_run_cycles_limited() added.
sets new run_cycle_count based on present list of cycle timers.

* avr_cycle_timer_reset() changed.
run_cycle_count and run_cycle_limit is set to default values.

* avr_cycle_timer_register() changed.
* avr_cycle_timer_cancel() changed.
* avr_cycle_timer_process() changed.
call the relevant function to set/maintain run_cycle_count.

modified:   simavr/sim/sim_avr.c
modified:   simavr/sim/sim_avr.h
modified:   simavr/sim/sim_cycle_timers.c

3 files changed:
simavr/sim/sim_avr.h
simavr/sim/sim_core.c
simavr/sim/sim_cycle_timers.c

index 07985e1a918fce087f89262cd10e4b9dc16106ba..7b95bd55741136b3237596eec7fd11b3aebcf8bc 100644 (file)
@@ -162,6 +162,11 @@ typedef struct avr_t {
        // like, sleeping.
        avr_cycle_count_t       cycle;          // current cycle
 
+       // these next two allow the core to freely run between cycle timers and also allows
+       // for a maximum run cycle limit... run_cycle_count is set during cycle timer processing.
+       avr_cycle_count_t       run_cycle_count;        // cycles to run before next timer
+       avr_cycle_count_t       run_cycle_limit;        // maximum run cycle interval limit
+
        /**
         * Sleep requests are accumulated in sleep_usec until the minimum sleep value
         * is reached, at which point sleep_usec is cleared and the sleep request
index f740aa58db1bdae87f3199044fe86fe6a5f4413b..c4e7b3ecd810b61d47a43d31c6f4752157996b64 100644 (file)
@@ -581,6 +581,7 @@ static inline int _avr_is_instruction_32_bits(avr_t * avr, avr_flashaddr_t pc)
  */
 avr_flashaddr_t avr_run_one(avr_t * avr)
 {
+run_one_again:
 #if CONFIG_SIMAVR_TRACE
        /*
         * this traces spurious reset or bad jumps
@@ -1402,6 +1403,16 @@ avr_flashaddr_t avr_run_one(avr_t * avr)
 
        }
        avr->cycle += cycle;
+       
+       if( (avr->state == cpu_Running) && 
+               (avr->run_cycle_count > cycle) && 
+               !(avr->sreg[S_I] && avr_has_pending_interrupts(avr)) )
+       {
+               avr->run_cycle_count -= cycle;
+               avr->pc = new_pc;
+               goto run_one_again;
+       }
+       
        return new_pc;
 }
 
index 1064dc5ded186dda6d50d896ed3d4a8f736bd6f1..93cf26549dc8f2f724169489a676cc39aa387d14 100644 (file)
@@ -46,6 +46,8 @@
                } \
        }
 
+#define DEFAULT_SLEEP_CYCLES 1000
+
 void
 avr_cycle_timer_reset(
                struct avr_t * avr)
@@ -57,6 +59,41 @@ avr_cycle_timer_reset(
                avr_cycle_timer_slot_p t = &pool->timer_slots[i];
                QUEUE(pool->timer_free, t);
        }
+       avr->run_cycle_count = 1;
+       avr->run_cycle_limit = 1;
+}
+
+static avr_cycle_count_t
+avr_cycle_timer_return_sleep_run_cycles_limited(
+       avr_t *avr,
+       avr_cycle_count_t sleep_cycle_count)
+{
+       // run_cycle_count is bound to run_cycle_limit but NOT less than 1 cycle...
+       //      this is not an error!..  unless you like deadlock.
+       avr_cycle_count_t run_cycle_count = ((avr->run_cycle_limit >= sleep_cycle_count) ?
+               sleep_cycle_count : avr->run_cycle_limit);
+       avr->run_cycle_count = run_cycle_count ? run_cycle_count : 1;
+
+       // sleep cycles are returned unbounded thus preserving original behavior.
+       return(sleep_cycle_count);
+}
+
+static void
+avr_cycle_timer_reset_sleep_run_cycles_limited(
+       avr_t *avr)
+{
+       avr_cycle_timer_pool_t * pool = &avr->cycle_timers;
+       avr_cycle_count_t sleep_cycle_count = DEFAULT_SLEEP_CYCLES;
+
+       if(pool->timer) {
+               if(pool->timer->when > avr->cycle) {
+                       sleep_cycle_count = pool->timer->when - avr->cycle;
+               } else {
+                       sleep_cycle_count = 0;
+               }
+       }
+
+       avr_cycle_timer_return_sleep_run_cycles_limited(avr, sleep_cycle_count);
 }
 
 // no sanity checks checking here, on purpose
@@ -112,6 +149,7 @@ avr_cycle_timer_register(
                return;
        }
        avr_cycle_timer_insert(avr, when, timer, param);
+       avr_cycle_timer_reset_sleep_run_cycles_limited(avr);
 }
 
 void
@@ -143,6 +181,7 @@ avr_cycle_timer_cancel(
                last = t;
                t = t->next;
        }
+       avr_cycle_timer_reset_sleep_run_cycles_limited(avr);
 }
 
 /*
@@ -179,15 +218,12 @@ avr_cycle_timer_process(
 {
        avr_cycle_timer_pool_t * pool = &avr->cycle_timers;
 
-       if (!pool->timer)
-               return (avr_cycle_count_t)1000;
-
-       do {
+       if (pool->timer) do {
                avr_cycle_timer_slot_p t = pool->timer;
                avr_cycle_count_t when = t->when;
 
                if (when > avr->cycle)
-                       return t->when - avr->cycle;
+                       return avr_cycle_timer_return_sleep_run_cycles_limited(avr, when - avr->cycle);
 
                // detach from active timers
                pool->timer = t->next;
@@ -206,5 +242,8 @@ avr_cycle_timer_process(
                QUEUE(pool->timer_free, t);
        } while (pool->timer);
 
-       return (avr_cycle_count_t)1000;
+       // original behavior was to return 1000 cycles when no timers were present...
+       // run_cycles are bound to at least one cycle but no more than requested limit...
+       //      value passed here is returned unbounded, thus preserving original behavior.
+       return avr_cycle_timer_return_sleep_run_cycles_limited(avr, DEFAULT_SLEEP_CYCLES);
 }