From 6660aba00a898ff4db6c689e35e7fd03b4f9d47d Mon Sep 17 00:00:00 2001 From: Delio Brignoli Date: Fri, 20 Oct 2017 11:22:45 +0200 Subject: [PATCH] modify avr_callback_sleep_raw() to mitigate sim time and wall clock time divergence To avoid simulated time and wall clock time to diverge over time this implementation tries to keep them in sync (roughly) by sleeping for the time required to match the expected sleep deadline in wall clock time. The simulation will burst as fast as the host CPU will allow until the simulated MCU sleeps, at which point avr_callback_sleep_raw() sleeps for the time required to sync wall clock time with simulated MCU time. --- simavr/sim/sim_avr.c | 30 +++++++++++++++++++++++++----- simavr/sim/sim_avr.h | 1 + 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/simavr/sim/sim_avr.c b/simavr/sim/sim_avr.c index 9999a17..6106df6 100644 --- a/simavr/sim/sim_avr.c +++ b/simavr/sim/sim_avr.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "sim_avr.h" #include "sim_core.h" @@ -148,6 +149,10 @@ avr_reset( avr->sreg[i] = 0; avr_interrupt_reset(avr); avr_cycle_timer_reset(avr); + /* Take simulation start time */ + struct timespec tp; + clock_gettime(CLOCK_MONOTONIC_RAW, &tp); + avr->sim_start_time_ns = tp.tv_sec*1E9+tp.tv_nsec; if (avr->reset) avr->reset(avr); avr_io_t * port = avr->io_port; @@ -311,15 +316,30 @@ avr_callback_run_gdb( } +/* +To avoid simulated time and wall clock time to diverge over time +this function tries to keep them in sync (roughly) by sleeping +for the time required to match the expected sleep deadline +in wall clock time. +*/ void avr_callback_sleep_raw( - avr_t * avr, - avr_cycle_count_t howLong) + avr_t *avr, + avr_cycle_count_t how_long) { - uint32_t usec = avr_pending_sleep_usec(avr, howLong); - if (usec > 0) { - usleep(usec); + struct timespec tp; + + /* figure out how long we should wait to match the sleep deadline */ + uint64_t deadline_ns = avr_cycles_to_nsec(avr, avr->cycle + how_long); + clock_gettime(CLOCK_MONOTONIC_RAW, &tp); + uint64_t runtime_ns = (tp.tv_sec*1E9+tp.tv_nsec) - avr->sim_start_time_ns; + if (runtime_ns >= deadline_ns) { + return; } + + uint64_t sleep_us = (deadline_ns - runtime_ns)/1000; + usleep(sleep_us); + return; } void diff --git a/simavr/sim/sim_avr.h b/simavr/sim/sim_avr.h index aedffb2..92459dc 100644 --- a/simavr/sim/sim_avr.h +++ b/simavr/sim/sim_avr.h @@ -201,6 +201,7 @@ typedef struct avr_t { * is passed on to the operating system. */ uint32_t sleep_usec; + uint64_t sim_start_time_ns; // called at init time void (*init)(struct avr_t * avr); -- 2.39.5