TIMER: Add mechanism to pre-calibrate the instruction execution rate
This commit is contained in:
parent
48db10994d
commit
f75f28aa21
9 changed files with 114 additions and 3 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
BIN
doc/simh.doc
BIN
doc/simh.doc
Binary file not shown.
3
scp.c
3
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 */
|
||||
|
|
2
scp.h
2
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 */
|
||||
|
|
45
sim_timer.c
45
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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue