TIMER: Add mechanism to pre-calibrate the instruction execution rate

This commit is contained in:
Mark Pizzolato 2019-05-28 23:56:58 -07:00
parent 48db10994d
commit f75f28aa21
9 changed files with 114 additions and 3 deletions

View file

@ -2347,6 +2347,19 @@ pi_eval (); /* eval pi system */
return;
}
/*
* This sequence of instructions is a mix that hopefully
* represents a resonable instruction set that is a close
* estimate to the normal calibrated result.
*/
static const char *pdp10_clock_precalibrate_commands[] = {
"-m 100 ADDM 0,110",
"-m 101 ADDI 0,1",
"-m 102 JRST 100",
"PC 100",
NULL};
/* Reset routine */
t_stat cpu_reset (DEVICE *dptr)
@ -2368,10 +2381,12 @@ if (M == NULL)
return SCPE_MEM;
sim_vm_pc_value = &pdp10_pc_value;
sim_vm_is_subroutine_call = &cpu_is_pc_a_subroutine_call;
sim_clock_precalibrate_commands = pdp10_clock_precalibrate_commands;
pcq_r = find_reg ("PCQ", NULL, dptr);
if (pcq_r)
pcq_r->qptr = 0;
else return SCPE_IERR;
else
return SCPE_IERR;
sim_brk_types = sim_brk_dflt = SWMASK ('E');
return SCPE_OK;
}

View file

@ -3338,6 +3338,19 @@ else if (CPUT (HAS_STKLR)) { /* register limit? */
return; /* no stack limit */
}
/*
* This sequence of instructions is a mix that mimics
* a resonable instruction set that is a close estimate
* to the normal calibrated result.
*/
static const char *pdp11_clock_precalibrate_commands[] = {
"-m 100 INC 120",
"-m 104 INC 122",
"-m 110 BR 100",
"PC 100",
NULL};
/* Reset routine */
t_stat cpu_reset (DEVICE *dptr)
@ -3365,6 +3378,7 @@ if (M == NULL) { /* First time init */
SWMASK ('W')|SWMASK ('X');
sim_brk_type_desc = cpu_breakpoints;
sim_vm_is_subroutine_call = &cpu_is_pc_a_subroutine_call;
sim_clock_precalibrate_commands = pdp11_clock_precalibrate_commands;
auto_config(NULL, 0); /* do an initial auto configure */
}
pcq_r = find_reg ("PCQ", NULL, dptr);

View file

@ -1371,6 +1371,19 @@ pcq_r->qptr = pcq_p; /* update pc q ptr */
return reason;
} /* end sim_instr */
/*
* This sequence of instructions is a mix that hopefully
* represents a resonable instruction set that is a close
* estimate to the normal calibrated result.
*/
static const char *pdp8_clock_precalibrate_commands[] = {
"-m 100 ISZ 110",
"-m 101 JMP 100",
"-m 102 JMP 100",
"PC 100",
NULL};
/* Reset routine */
t_stat cpu_reset (DEVICE *dptr)
@ -1382,7 +1395,9 @@ UF = UB = gtf = emode = 0;
pcq_r = find_reg ("PCQ", NULL, dptr);
if (pcq_r)
pcq_r->qptr = 0;
else return SCPE_IERR;
else
return SCPE_IERR;
sim_clock_precalibrate_commands = pdp8_clock_precalibrate_commands;
sim_brk_types = SWMASK ('E') | SWMASK('I');
sim_brk_dflt = SWMASK ('E');
return SCPE_OK;

View file

@ -3284,6 +3284,21 @@ void cpu_idle (void)
sim_idle (TMR_CLK, TRUE);
}
/*
* This sequence of instructions is a mix that mimics
* a resonable instruction set that is a close estimate
* to the calibrated result without a direct "loop to
* self" instruction that would halt simulation.
*/
static const char *vax_clock_precalibrate_commands[] = {
"-m 100 INCL 120",
"-m 103 INCL 124",
"-m 106 MULL3 120,124,128",
"-m 10D BRW 100",
"PC 100",
NULL};
/* Reset */
t_stat cpu_reset (DEVICE *dptr)
@ -3299,6 +3314,7 @@ FLUSH_ISTR; /* init I-stream */
if (M == NULL) { /* first time init? */
sim_brk_types = sim_brk_dflt = SWMASK ('E');
sim_vm_is_subroutine_call = cpu_is_pc_a_subroutine_call;
sim_clock_precalibrate_commands = vax_clock_precalibrate_commands;
pcq_r = find_reg ("PCQ", NULL, dptr);
if (pcq_r == NULL)
return SCPE_IERR;

Binary file not shown.

3
scp.c
View file

@ -451,6 +451,8 @@ t_addr (*sim_vm_parse_addr) (DEVICE *dptr, CONST char *cptr, CONST char **tptr)
t_value (*sim_vm_pc_value) (void) = NULL;
t_bool (*sim_vm_is_subroutine_call) (t_addr **ret_addrs) = NULL;
t_bool (*sim_vm_fprint_stopped) (FILE *st, t_stat reason) = NULL;
const char **sim_clock_precalibrate_commands = NULL;
/* Prototypes */
@ -2594,6 +2596,7 @@ if (!sim_quiet) {
printf ("\n");
show_version (stdout, NULL, NULL, 0, NULL);
}
sim_timer_precalibrate_execution_rate ();
show_version (stdnul, NULL, NULL, 1, NULL); /* Quietly set SIM_OSTYPE */
#if defined (HAVE_PCREPOSIX_H)
setenv ("SIM_REGEX_TYPE", "PCREPOSIX", 1); /* Publish regex type */

2
scp.h
View file

@ -420,6 +420,8 @@ extern t_addr (*sim_vm_parse_addr) (DEVICE *dptr, CONST char *cptr, CONST char *
extern t_bool (*sim_vm_fprint_stopped) (FILE *st, t_stat reason);
extern t_value (*sim_vm_pc_value) (void);
extern t_bool (*sim_vm_is_subroutine_call) (t_addr **ret_addrs);
extern const char **sim_clock_precalibrate_commands;
/* Core SCP libraries can potentially have unit test routines.
These defines help implement consistent unit test functionality */

View file

@ -788,6 +788,7 @@ t_stat sim_throt_svc (UNIT *uptr);
t_stat sim_timer_tick_svc (UNIT *uptr);
t_stat sim_timer_stop_svc (UNIT *uptr);
#define DBG_IDL TIMER_DBG_IDLE /* idling */
#define DBG_QUE TIMER_DBG_QUEUE /* queue activities */
#define DBG_MUX TIMER_DBG_MUX /* tmxr queue activities */
@ -3209,3 +3210,47 @@ void sim_set_rom_delay_factor (uint32 delay)
{
sim_rom_delay = delay;
}
/* sim_timer_precalibrate_execution_rate
*
* The point of this routine is to run a bunch of simulator provided
* instructions that don't do anything, but run in an effective loop.
* That loop is run for some 5 million instructions and based on
* the time those 5 million instructions take to execute the effective
* execution rate. That rate is used to avoid the initial 3 to 5
* seconds that normal clock calibration takes.
*
*/
void sim_timer_precalibrate_execution_rate (void)
{
const char **cmd = sim_clock_precalibrate_commands;
uint32 start, end;
double ips_rate;
int32 saved_switches = sim_switches;
int32 tmr;
UNIT precalib_unit = { UDATA (&sim_timer_stop_svc, 0, 0) };
if (cmd == NULL)
return;
sim_run_boot_prep (RU_GO);
while (sim_clock_queue != QUEUE_LIST_END)
sim_cancel (sim_clock_queue);
while (*cmd)
exdep_cmd (EX_D, *(cmd++));
sim_switches = saved_switches;
sim_cancel (&SIM_INTERNAL_UNIT);
sim_activate (&precalib_unit, SIM_INITIAL_IPS);
start = sim_os_msec();
sim_instr();
end = sim_os_msec();
ips_rate = 1000.0 * (SIM_INITIAL_IPS / (double)(end - start));
for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
if (rtc_hz[tmr])
rtc_initd[tmr] = rtc_currd[tmr] = (int32)(ips_rate / rtc_hz[tmr]);
}
reset_all_p (0);
sim_run_boot_prep (RU_GO);
if (sim_switches & SWMASK ('V'))
sim_printf ("Pre-Calibrate execution rate: %s cycles/sec\n", sim_fmt_numeric (ips_rate));
}

View file

@ -76,7 +76,7 @@ int clock_gettime(int clock_id, struct timespec *tp);
#define SIM_NTIMERS 8 /* # timers */
#define SIM_TMAX 500 /* max timer makeup */
#define SIM_INITIAL_IPS 500000 /* uncalibrated assumption */
#define SIM_INITIAL_IPS 5000000 /* uncalibrated assumption */
/* about instructions per second */
#define SIM_IDLE_CAL 10 /* ms to calibrate */
@ -145,6 +145,7 @@ t_stat sim_clock_coschedule_abs (UNIT *uptr, int32 interval);
t_stat sim_clock_coschedule_tmr (UNIT *uptr, int32 tmr, int32 ticks);
t_stat sim_clock_coschedule_tmr_abs (UNIT *uptr, int32 tmr, int32 ticks);
double sim_timer_inst_per_sec (void);
void sim_timer_precalibrate_execution_rate (void);
int32 sim_rtcn_tick_size (int32 tmr);
int32 sim_rtcn_calibrated_tmr (void);
t_bool sim_timer_idle_capable (uint32 *host_ms_sleep_1, uint32 *host_tick_ms);