Fixed throttling in several ways:
- Sleep for the observed clock tick size while throttling - Recompute the throttling wait once every 10 seconds to account for varying instruction mixes during different phases of a simulator execution or to accommodate the presence of other load on the host system. - Each of the pre-existing throttling modes (Kcps, Mcps, and %) all compute the appropriate throttling interval dynamically. These dynamic computations assume that 100% of the host CPU is dedicated to the current simulator during this computation. This assumption may not always be true and under certain conditions may never provide a way to correctly determine the appropriate throttling wait. An additional throttling mode has been added which allows the simulator operator to explicitly state the desired throttling wait parameters. These are specified by: SET THROT insts/delay where 'insts' is the number of instructions to execute before sleeping for 'delay' milliseconds.
This commit is contained in:
parent
9f1f586714
commit
c38eacd0c8
3 changed files with 77 additions and 19 deletions
3
scp.c
3
scp.c
|
@ -616,7 +616,8 @@ static CTAB cmd_table[] = {
|
|||
"set console NODEBUG disable console debugging\n"
|
||||
"set break <list> set breakpoints\n"
|
||||
"set nobreak <list> clear breakpoints\n"
|
||||
"set throttle x{M|K|%%} set simulation rate\n"
|
||||
"set throttle {x{M|K|%}}|{x/t}\n"
|
||||
" set simulation rate\n"
|
||||
"set nothrottle set simulation rate to maximum\n"
|
||||
"set asynch enable asynchronous I/O\n"
|
||||
"set noasynch disable asynchronous I/O\n"
|
||||
|
|
86
sim_timer.c
86
sim_timer.c
|
@ -23,6 +23,28 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
21-Oct-11 MP Fixed throttling in several ways:
|
||||
- Sleep for the observed clock tick size while throttling
|
||||
- Recompute the throttling wait once every 10 seconds
|
||||
to account for varying instruction mixes during
|
||||
different phases of a simulator execution or to
|
||||
accommodate the presence of other load on the host
|
||||
system.
|
||||
- Each of the pre-existing throttling modes (Kcps,
|
||||
Mcps, and %) all compute the appropriate throttling
|
||||
interval dynamically. These dynamic computations
|
||||
assume that 100% of the host CPU is dedicated to
|
||||
the current simulator during this computation.
|
||||
This assumption may not always be true and under
|
||||
certain conditions may never provide a way to
|
||||
correctly determine the appropriate throttling
|
||||
wait. An additional throttling mode has been added
|
||||
which allows the simulator operator to explicitly
|
||||
state the desired throttling wait parameters.
|
||||
These are specified by:
|
||||
SET THROT insts/delay
|
||||
where 'insts' is the number of instructions to
|
||||
execute before sleeping for 'delay' milliseconds.
|
||||
22-Apr-11 MP Fixed Asynch I/O support to reasonably account cycles
|
||||
when an idle wait is terminated by an external event
|
||||
05-Jan-11 MP Added Asynch I/O support
|
||||
|
@ -67,6 +89,7 @@ static uint32 sim_throt_ms_stop = 0;
|
|||
static uint32 sim_throt_type = 0;
|
||||
static uint32 sim_throt_val = 0;
|
||||
static uint32 sim_throt_state = 0;
|
||||
static uint32 sim_throt_sleep_time = 0;
|
||||
static int32 sim_throt_wait = 0;
|
||||
extern int32 sim_interval, sim_switches;
|
||||
extern FILE *sim_log;
|
||||
|
@ -641,8 +664,11 @@ return SCPE_OK;
|
|||
|
||||
t_stat sim_show_idle (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
if (sim_idle_enab)
|
||||
fprintf (st, "idle enabled, stability wait = %ds, minimum sleep resolution = %dms", sim_idle_stable, sim_idle_rate_ms);
|
||||
if (sim_idle_enab) {
|
||||
fprintf (st, "idle enabled");
|
||||
if (sim_switches & SWMASK ('D'))
|
||||
fprintf (st, ", stability wait = %ds, minimum sleep resolution = %dms", sim_idle_stable, sim_idle_rate_ms);
|
||||
}
|
||||
else fputs ("idle disabled", st);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -652,7 +678,7 @@ return SCPE_OK;
|
|||
t_stat sim_set_throt (int32 arg, char *cptr)
|
||||
{
|
||||
char *tptr, c;
|
||||
t_value val;
|
||||
t_value val, val2;
|
||||
|
||||
if (arg == 0) {
|
||||
if ((cptr != 0) && (*cptr != 0))
|
||||
|
@ -666,8 +692,11 @@ else {
|
|||
val = strtotv (cptr, &tptr, 10);
|
||||
if (cptr == tptr)
|
||||
return SCPE_ARG;
|
||||
sim_throt_sleep_time = sim_idle_rate_ms;
|
||||
c = toupper (*tptr++);
|
||||
if (*tptr != 0)
|
||||
if (c == '/')
|
||||
val2 = strtotv (tptr, &tptr, 10);
|
||||
if ((*tptr != 0) || (val == 0))
|
||||
return SCPE_ARG;
|
||||
if (c == 'M')
|
||||
sim_throt_type = SIM_THROT_MCYC;
|
||||
|
@ -675,6 +704,9 @@ else {
|
|||
sim_throt_type = SIM_THROT_KCYC;
|
||||
else if ((c == '%') && (val > 0) && (val < 100))
|
||||
sim_throt_type = SIM_THROT_PCT;
|
||||
else if ((c == '/') && (val2 != 0)) {
|
||||
sim_throt_type = SIM_THROT_SPC;
|
||||
}
|
||||
else return SCPE_ARG;
|
||||
if (sim_idle_enab) {
|
||||
printf ("Idling disabled\n");
|
||||
|
@ -683,6 +715,14 @@ else {
|
|||
sim_clr_idle (NULL, 0, NULL, NULL);
|
||||
}
|
||||
sim_throt_val = (uint32) val;
|
||||
if (sim_throt_type == SIM_THROT_SPC) {
|
||||
if (val2 >= sim_idle_rate_ms)
|
||||
sim_throt_sleep_time = (uint32) val2;
|
||||
else {
|
||||
sim_throt_sleep_time = (uint32) (val2 * sim_idle_rate_ms);
|
||||
sim_throt_val = (uint32) (val * sim_idle_rate_ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -706,13 +746,17 @@ else {
|
|||
fprintf (st, "Throttle = %d%%\n", sim_throt_val);
|
||||
break;
|
||||
|
||||
case SIM_THROT_SPC:
|
||||
fprintf (st, "Throttle = %d ms every %d cycles\n", sim_throt_sleep_time, sim_throt_val);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf (st, "Throttling disabled\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (sim_switches & SWMASK ('D')) {
|
||||
fprintf (st, "Wait rate = %d ms\n", sim_idle_rate_ms);
|
||||
fprintf (st, "minimum sleep resolution = %d ms\n", sim_idle_rate_ms);
|
||||
if (sim_throt_type != 0)
|
||||
fprintf (st, "Throttle interval = %d cycles\n", sim_throt_wait);
|
||||
}
|
||||
|
@ -725,7 +769,6 @@ void sim_throt_sched (void)
|
|||
sim_throt_state = 0;
|
||||
if (sim_throt_type)
|
||||
sim_activate (&sim_throt_unit, SIM_THROT_WINIT);
|
||||
return;
|
||||
}
|
||||
|
||||
void sim_throt_cancel (void)
|
||||
|
@ -735,11 +778,12 @@ sim_cancel (&sim_throt_unit);
|
|||
|
||||
/* Throttle service
|
||||
|
||||
Throttle service has three distinct states
|
||||
Throttle service has three distinct states used while dynamically
|
||||
determining a throttling interval:
|
||||
|
||||
0 take initial measurement
|
||||
1 take final measurement, calculate wait values
|
||||
2 periodic waits to slow down the CPU
|
||||
0 take initial measurement
|
||||
1 take final measurement, calculate wait values
|
||||
2 periodic waits to slow down the CPU
|
||||
*/
|
||||
|
||||
t_stat sim_throt_svc (UNIT *uptr)
|
||||
|
@ -747,12 +791,16 @@ t_stat sim_throt_svc (UNIT *uptr)
|
|||
uint32 delta_ms;
|
||||
double a_cps, d_cps;
|
||||
|
||||
if (sim_throt_type == SIM_THROT_SPC) { /* Non dynamic? */
|
||||
sim_throt_state = 2; /* force state */
|
||||
sim_throt_wait = sim_throt_val;
|
||||
}
|
||||
switch (sim_throt_state) {
|
||||
|
||||
case 0: /* take initial reading */
|
||||
sim_throt_ms_start = sim_os_msec ();
|
||||
sim_throt_wait = SIM_THROT_WST;
|
||||
sim_throt_state++; /* next state */
|
||||
sim_throt_state = 1; /* next state */
|
||||
break; /* reschedule */
|
||||
|
||||
case 1: /* take final reading */
|
||||
|
@ -774,24 +822,32 @@ switch (sim_throt_state) {
|
|||
d_cps = (double) sim_throt_val * 1000.0;
|
||||
else d_cps = (a_cps * ((double) sim_throt_val)) / 100.0;
|
||||
if (d_cps >= a_cps) {
|
||||
sim_throt_state = 0;
|
||||
sim_throt_sched (); /* start over */
|
||||
return SCPE_OK;
|
||||
}
|
||||
sim_throt_wait = (int32) /* time between waits */
|
||||
((a_cps * d_cps * ((double) sim_idle_rate_ms)) /
|
||||
(1000.0 * (a_cps - d_cps)));
|
||||
if (sim_throt_wait < SIM_THROT_WMIN) { /* not long enough? */
|
||||
sim_throt_state = 0;
|
||||
sim_throt_sched (); /* start over */
|
||||
return SCPE_OK;
|
||||
}
|
||||
sim_throt_state++;
|
||||
sim_throt_ms_start = sim_throt_ms_stop;
|
||||
sim_throt_state = 2;
|
||||
// fprintf (stderr, "Throttle values a_cps = %f, d_cps = %f, wait = %d\n",
|
||||
// a_cps, d_cps, sim_throt_wait);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: /* throttling */
|
||||
sim_os_ms_sleep (1);
|
||||
sim_os_ms_sleep (sim_throt_sleep_time);
|
||||
delta_ms = sim_os_msec () - sim_throt_ms_start;
|
||||
if ((sim_throt_type != SIM_THROT_SPC) && /* when dynamic throttling */
|
||||
(delta_ms >= 10000)) { /* recompute every 10 sec */
|
||||
sim_throt_ms_start = sim_os_msec ();
|
||||
sim_throt_wait = SIM_THROT_WST;
|
||||
sim_throt_state = 1; /* next state */
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,9 +55,10 @@ int clock_gettime(int clock_id, struct timespec *tp);
|
|||
#define SIM_THROT_WMIN 100 /* min wait */
|
||||
#define SIM_THROT_MSMIN 10 /* min for measurement */
|
||||
#define SIM_THROT_NONE 0 /* throttle parameters */
|
||||
#define SIM_THROT_MCYC 1
|
||||
#define SIM_THROT_KCYC 2
|
||||
#define SIM_THROT_PCT 3
|
||||
#define SIM_THROT_MCYC 1 /* MegaCycles Per Sec */
|
||||
#define SIM_THROT_KCYC 2 /* KiloCycles Per Sec */
|
||||
#define SIM_THROT_PCT 3 /* Max Percent of host CPU */
|
||||
#define SIM_THROT_SPC 4 /* Specific periodic Delay */
|
||||
|
||||
t_bool sim_timer_init (void);
|
||||
void sim_timespec_diff (struct timespec *diff, struct timespec *min, struct timespec *sub);
|
||||
|
|
Loading…
Add table
Reference in a new issue