diff --git a/PDP10/pdp10_cpu.c b/PDP10/pdp10_cpu.c index 9262f11b..30b8bb50 100644 --- a/PDP10/pdp10_cpu.c +++ b/PDP10/pdp10_cpu.c @@ -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; } diff --git a/PDP11/pdp11_cpu.c b/PDP11/pdp11_cpu.c index 293995fb..19525e55 100644 --- a/PDP11/pdp11_cpu.c +++ b/PDP11/pdp11_cpu.c @@ -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); diff --git a/PDP8/pdp8_cpu.c b/PDP8/pdp8_cpu.c index aca02045..30782b78 100644 --- a/PDP8/pdp8_cpu.c +++ b/PDP8/pdp8_cpu.c @@ -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; diff --git a/VAX/vax_cpu.c b/VAX/vax_cpu.c index 73058c86..df29b086 100644 --- a/VAX/vax_cpu.c +++ b/VAX/vax_cpu.c @@ -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; diff --git a/doc/simh.doc b/doc/simh.doc index 96c4c1b9..43dd3652 100644 Binary files a/doc/simh.doc and b/doc/simh.doc differ diff --git a/scp.c b/scp.c index 7781648a..3523cacf 100644 --- a/scp.c +++ b/scp.c @@ -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 */ diff --git a/scp.h b/scp.h index d9c5cc5f..c335e8a8 100644 --- a/scp.h +++ b/scp.h @@ -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 */ diff --git a/sim_timer.c b/sim_timer.c index ce6e8ed3..39d9f617 100644 --- a/sim_timer.c +++ b/sim_timer.c @@ -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)); +} diff --git a/sim_timer.h b/sim_timer.h index 59226fef..0ec85b89 100644 --- a/sim_timer.h +++ b/sim_timer.h @@ -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);