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:
Mark Pizzolato 2011-10-25 03:52:24 -07:00
parent 9f1f586714
commit c38eacd0c8
3 changed files with 77 additions and 19 deletions

3
scp.c
View file

@ -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"

View file

@ -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;
}

View file

@ -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);