diff --git a/arch/sim/Kconfig b/arch/sim/Kconfig index 66ce9b18a40..9c70c1fe948 100644 --- a/arch/sim/Kconfig +++ b/arch/sim/Kconfig @@ -170,6 +170,16 @@ config SIM_WALLTIME_SIGNAL endchoice +config SIM_WALLTIME_RATIO + int "Simulated time ratio in percent relative to real time" + default 100 + range 1 100000 + ---help--- + Set the ratio of simulated time to real time in percent. + 100 means real-time (default). 200 means simulated time advances + twice as fast as real time. 50 means half speed. + This can also be overridden at runtime with --sim-rt-ratio=. + config SIM_LOOP_INTERVAL int "loop interval in ms" default 10 diff --git a/arch/sim/src/sim/posix/sim_hosttime.c b/arch/sim/src/sim/posix/sim_hosttime.c index 03f8ecd1d41..6da74719232 100644 --- a/arch/sim/src/sim/posix/sim_hosttime.c +++ b/arch/sim/src/sim/posix/sim_hosttime.c @@ -41,6 +41,13 @@ ****************************************************************************/ static uint64_t g_start; + +/* Ratio of simulated time to real time in percent. 100 means real-time + * (default). Values > 100 speed up simulated time; values < 100 slow it + * down. Overridable at runtime via --sim-rt-ratio=. + */ + +static int g_time_ratio = CONFIG_SIM_WALLTIME_RATIO; #ifdef __APPLE__ static dispatch_source_t g_timer; @@ -105,7 +112,14 @@ uint64_t host_gettime(bool rtc) clock_gettime(rtc ? CLOCK_REALTIME : CLOCK_MONOTONIC, &tp); current = 1000000000ull * tp.tv_sec + tp.tv_nsec; - return rtc ? current : current - g_start; + if (rtc) + { + return current; + } + + /* Apply time ratio: simulated_time = real_elapsed * ratio / 100 */ + + return ((current - g_start) * g_time_ratio) / 100; } /**************************************************************************** @@ -128,7 +142,31 @@ void host_sleepuntil(uint64_t nsec) now = host_gettime(false); if (nsec > now + 1000) { - usleep((nsec - now) / 1000); + /* nsec is in simulated time; convert back to real duration to sleep */ + + usleep((((nsec - now) * 100) / g_time_ratio) / 1000); + } +} + +/**************************************************************************** + * Name: host_set_timeratio + * + * Description: + * Set the ratio of simulated time to real time in percent. 100 (default) + * means simulated time advances at the same rate as real time. Values + * greater than 100 speed up simulated time; values less than 100 slow it + * down. + * + * Input Parameters: + * ratio - The new time ratio in percent (must be > 0) + * + ****************************************************************************/ + +void host_set_timeratio(int ratio) +{ + if (ratio > 0) + { + g_time_ratio = ratio; } } @@ -148,9 +186,9 @@ void host_sleepuntil(uint64_t nsec) int host_settimer(uint64_t nsec) { - /* Convert to microseconds and set minimum timer to 1 microsecond. */ + /* nsec is in simulated time; convert back to real absolute time. */ - nsec += g_start; + nsec = ((nsec * 100) / g_time_ratio) + g_start; #ifdef __APPLE__ dispatch_time_t start; diff --git a/arch/sim/src/sim/sim_head.c b/arch/sim/src/sim/sim_head.c index ab3def8f691..dc625cd925c 100644 --- a/arch/sim/src/sim/sim_head.c +++ b/arch/sim/src/sim/sim_head.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -164,9 +165,24 @@ noprofile_function const char *__ubsan_default_options(void) int main(int argc, char **argv, char **envp) { + int i; + g_argc = argc; g_argv = argv; + /* Parse simulator-specific options before handing control to NuttX. + * --sim-rt-ratio= Set simulated-to-real time ratio in percent + * (default 100). Values > 100 speed up simulated time; < 100 slow down. + */ + + for (i = 1; i < argc; i++) + { + if (strncmp(argv[i], "--sim-rt-ratio=", 15) == 0) + { + host_set_timeratio(atoi(argv[i] + 15)); + } + } + #ifdef CONFIG_ALLSYMS allsyms_relocate(); #endif diff --git a/arch/sim/src/sim/sim_internal.h b/arch/sim/src/sim/sim_internal.h index 69d4ef27893..3ca70b65e94 100644 --- a/arch/sim/src/sim/sim_internal.h +++ b/arch/sim/src/sim/sim_internal.h @@ -245,6 +245,7 @@ int host_inittimer(void); uint64_t host_gettime(bool rtc); void host_sleep(uint64_t nsec); void host_sleepuntil(uint64_t nsec); +void host_set_timeratio(int ratio); int host_timerirq(void); int host_settimer(uint64_t nsec);