Closed deltecent closed 8 months ago
It works just fine for me on my favorite simulators.
It all depends on IF sim_poll_kbd()
is called periodically.
For a simulator without some sort of a console configured and no calibrated timers, the internal timer gratuitously calls sim_poll_kbd()
if nothing else has called it.
I'm wondering why the behavior difference between "SET THROTTLE 250K
and SET THROTTLE 250/1
?
SET THROTTLE 256K
Altair 8800 (Z80) simulator Open SIMH V4.1-0 Current git commit id: 5fba1e75
/Users/patrick/Library/Mobile Documents/com~apple~CloudDocs/open-simh/null.ini-12> SET DEBUG STDOUT
%SIM-INFO: Debug output to "STDOUT"
Debug output to "STDOUT" at Sat Nov 4 14:14:14 2023
Altair 8800 (Z80) simulator Open SIMH V4.1-0 Current git commit id: 5fba1e75
DBG(0)> INT-CLOCK CALIB: sim_start_timer_services(tmr=8) - adjusting calibration real time by 0 ms
DBG(0)> INT-CLOCK CALIB: sim_start_timer_services() - restarting internal timer after 0 instructions
DBG(47596131)> INT-CLOCK CALIB: sim_rtcn_calb(tmr=8) gratuitious keyboard poll after -1685393983 msecs
DBG(47596131)> INT-CLOCK CALIB: sim_rtcn_calb(tmr=8, tickper=100) (delta_rtime=567, delta_vtime=433, base=847917, nxintv=1433, catchups=0, idle=0%, result: 1215065)
DBG(169102631)> INT-CLOCK CALIB: sim_rtcn_calb(tmr=8) gratuitious keyboard poll after 808 msecs
DBG(169102631)> INT-CLOCK CALIB: sim_rtcn_calb(tmr=8, tickper=100) (delta_rtime=808, delta_vtime=500, base=1503793, nxintv=1500, catchups=0, idle=0%, result: 2255689)
DBG(394671531)> INT-CLOCK CALIB: sim_rtcn_calb(tmr=8) gratuitious keyboard poll after 1508 msecs
DBG(394671531)> INT-CLOCK CALIB: sim_rtcn_calb(tmr=8, tickper=100) (delta_rtime=1508, delta_vtime=117, base=1495815, nxintv=1117, catchups=0, idle=0%, result: 1670825)
DBG(395155800)> INT-CLOCK CALIB: sim_rtcn_calb(tmr=8, tickper=100) (delta_rtime=1001, delta_vtime=500, base=2497, nxintv=1500, catchups=0, idle=0%, result: 3745)
DBG(395530300)> INT-CLOCK CALIB: sim_rtcn_calb(tmr=8) gratuitious keyboard poll after 1891 msecs
DBG(395530300)> INT-CLOCK CALIB: sim_rtcn_calb(tmr=8, tickper=100) (delta_rtime=1877, delta_vtime=226, base=1995, nxintv=1226, catchups=0, idle=0%, result: 2445)
DBG(395774800)> INT-CLOCK CALIB: sim_rtcn_calb(tmr=8) gratuitious keyboard poll after 1238 msecs
DBG(395774800)> INT-CLOCK CALIB: sim_rtcn_calb(tmr=8, tickper=100) (delta_rtime=1239, delta_vtime=-13, base=1974, nxintv=987, catchups=0, idle=0%, result: 1948)
DBG(395969600)> INT-CLOCK CALIB: sim_rtcn_calb(tmr=8) gratuitious keyboard poll after 986 msecs
DBG(395969600)> INT-CLOCK CALIB: sim_rtcn_calb(tmr=8, tickper=100) (delta_rtime=986, delta_vtime=1, base=1976, nxintv=1001, catchups=0, idle=0%, result: 1977)
DBG(396167200)> INT-CLOCK CALIB: sim_rtcn_calb(tmr=8) gratuitious keyboard poll after 990 msecs
DBG(396167200)> INT-CLOCK CALIB: sim_rtcn_calb(tmr=8, tickper=100) (delta_rtime=990, delta_vtime=11, base=1997, nxintv=1011, catchups=0, idle=0%, result: 2018)
DBG(396369000)> INT-CLOCK CALIB: sim_rtcn_calb(tmr=8) gratuitious keyboard poll after 1023 msecs
DBG(396369000)> INT-CLOCK CALIB: sim_rtcn_calb(tmr=8, tickper=100) (delta_rtime=1023, delta_vtime=-12, base=1973, nxintv=988, catchups=0, idle=0%, result: 1949)
Simulation stopped, PC: 00000 (JMP 0000h)
Simulation stopped C0Z0M0E0I0 A=00 B=0000 D=0000 H=0000 S=0000 P=0000 JMP 0000h
sim>
SET THROTTLE 250/1
Altair 8800 (Z80) simulator Open SIMH V4.1-0 Current git commit id: 5fba1e75
/Users/patrick/Library/Mobile Documents/com~apple~CloudDocs/open-simh/null.ini-12> SET DEBUG STDOUT
%SIM-INFO: Debug output to "STDOUT"
Debug output to "STDOUT" at Sat Nov 4 14:15:07 2023
Altair 8800 (Z80) simulator Open SIMH V4.1-0 Current git commit id: 5fba1e75
DBG(0)> INT-CLOCK CALIB: sim_start_timer_services(tmr=8) - adjusting calibration real time by 0 ms
DBG(0)> INT-CLOCK CALIB: sim_start_timer_services() - restarting internal timer after 0 instructions
/Users/patrick/Library/Mobile Documents/com~apple~CloudDocs/open-simh/null.ini-15> G 0
SIGTERM received, PC: 00000 (JMP 0000h)
sim>
Actually it appears that ^E "works" even with SET THROTTLE 250/1
. After pressing ^E you just have to wait, on my machine about 3.5 minutes (not seconds). It seems that
if (rtc->ticks < ticksper) /* 1 sec yet? */
return rtc->currd;
in sim_rtcn_calb
is still getting called but it takes ages for rtc->ticks
to reach ticksper
. Only then the call to sim_poll_kbd() happens and ^E is detected. With set INT-CLOCK debug=CALIB
I get after pressing ^E and a long wait
DBG(89639551)> INT-CLOCK CALIB: sim_start_timer_services() - restarting internal timer after 450451 instructions
DBG(134684552)> INT-CLOCK CALIB: sim_rtcn_calb(tmr=8) gratuitious keyboard poll after 1181573 msecs
DBG(134684552)> INT-CLOCK CALIB: gap too big: delta = 237670 - result: 450450
Simulation stopped, PC: 00000 (JMP 0000h)
Actually it appears that ^E "works" even with SET THROTTLE 250/1. After pressing ^E you just have to wait, on my machine about 3.5 minutes (not seconds).
That aligns with my observation that although instructions are executed at the correct rate, service routines are called several times more slowly than they should be when using SET THROTTLE x/t
.
@markpizz writes
For a simulator without some sort of a console configured and no calibrated timers, the internal timer gratuitously calls sim_poll_kbd() if nothing else has called it.
As shown, the gratuitous call happens but it is useless as it does not come within a reasonable period after ^E was pressed (e.g. 5 seconds) but only after minutes. A fix for this defect would be appreciated.
The problem, I believe, is with the internal timer. When SET THROTTLE x/t
is used, it does not appear to get recalibrated to account for the t
ms sleep every x
instructions. I imagine if I could comprehend the code, it would be a simple fix, similar to what happens when THROTTLE is calculated using SET THROTTLE xK
.
Maybe the solution to all this is to learn how to use my own calibrated timer and not rely on the internal timer. I also feel the "gratuitous" keyboard check should be in the sim, not in SCP. The less SCP does that impacts the internal workings of the simulator the better.
The issue appears to be that as soon as the throttle logic starts sleeping the host cpu, all of the timers need to be adjusted to account for the reduced instructions per second due to the injection of a sleep interval. This adjustment happens when SIM THROTTLE 250K
throttle calibration is complete, but doesn't happen if the throttle is forced through SET THROTTLE x/t
. Without the timers being adjusted, they still assume maximum instructions per second rather than the throttled value which causes extreme service dispatch times (including gratuitous keyboard checks).
The following appears to fix it for me.
% git diff sim_timer.c
diff --git a/sim_timer.c b/sim_timer.c
index 4028a687..e909bf7a 100644
--- a/sim_timer.c
+++ b/sim_timer.c
@@ -680,6 +680,7 @@ static void _rtcn_configure_calibrated_clock (int32 newtmr);
static t_bool _sim_coschedule_cancel (UNIT *uptr);
static t_bool _sim_wallclock_cancel (UNIT *uptr);
static t_bool _sim_wallclock_is_active (UNIT *uptr);
+static void _sim_timer_adjust_cal(void);
t_stat sim_timer_show_idle_mode (FILE* st, UNIT* uptr, int32 val, CONST void * desc);
@@ -1753,9 +1754,10 @@ else {
sim_throt_wait = sim_throt_val;
}
}
-if (sim_throt_type == SIM_THROT_SPC) /* Set initial value while correct one is determined */
+if (sim_throt_type == SIM_THROT_SPC) { /* Set initial value while correct one is determined */
sim_throt_cps = (int32)((1000.0 * sim_throt_val) / (double)sim_throt_sleep_time);
-else
+ _sim_timer_adjust_cal();
+} else
sim_throt_cps = sim_precalibrate_ips;
return SCPE_OK;
}
@@ -1960,21 +1962,7 @@ switch (sim_throt_state) {
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Throttle values a_cps = %f, d_cps = %f, wait = %d, sleep = %d ms\n",
a_cps, d_cps, sim_throt_wait, sim_throt_sleep_time);
sim_throt_cps = d_cps; /* save the desired rate */
- /* Run through all timers and adjust the calibration for each */
- /* one that is running to reflect the throttle rate */
- for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
- rtc = &rtcs[tmr];
- if (rtc->hz) { /* running? */
- rtc->currd = (int32)(sim_throt_cps / rtc->hz);/* use throttle calibration */
- rtc->ticks = rtc->hz - 1; /* force clock calibration on next tick */
- rtc->rtime = sim_throt_ms_start - 1000 + 1000/rtc->hz;/* adjust calibration parameters to reflect throttled rate */
- rtc->gtime = sim_throt_inst_start - sim_throt_cps + sim_throt_cps/rtc->hz;
- rtc->nxintv = 1000;
- rtc->based = rtc->currd;
- if (rtc->clock_unit)
- sim_activate_abs (rtc->clock_unit, rtc->currd);/* reschedule next tick */
- }
- }
+ _sim_timer_adjust_cal();
}
break;
@@ -2038,6 +2026,30 @@ sim_activate (uptr, sim_throt_wait); /* reschedule */
return SCPE_OK;
}
+static void _sim_timer_adjust_cal(void)
+{
+ int32 tmr;
+ RTC *rtc = NULL;
+
+ /* Run through all timers and adjust the calibration for each */
+ /* one that is running to reflect the throttle rate */
+ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
+ rtc = &rtcs[tmr];
+
+ if (rtc->hz) { /* running? */
+ rtc->currd = (int32)(sim_throt_cps / rtc->hz);/* use throttle calibration */
+ rtc->ticks = rtc->hz - 1; /* force clock calibration on next tick */
+ rtc->rtime = sim_throt_ms_start - 1000 + 1000/rtc->hz;/* adjust calibration parameters to reflect throttled rate */
+ rtc->gtime = sim_throt_inst_start - sim_throt_cps + sim_throt_cps/rtc->hz;
+ rtc->nxintv = 1000;
+ rtc->based = rtc->currd;
+
+ if (rtc->clock_unit)
+ sim_activate_abs (rtc->clock_unit, rtc->currd);/* reschedule next tick */
+ }
+ }
+}
+
/* Clock assist activites */
t_stat sim_timer_tick_svc (UNIT *uptr)
{
With this change, all of the JAIR's timing loops work during boot:
Altair 8800 (Z80) simulator Open SIMH V4.1-0 Current git commit id: 7539b112+uncommitted-changes
ALTAIR/IMSAI 8080 CPU BOARD BOOT LOADER - Josh Bensadon v2.5 Sep 3, 2018
<D> -SD Card Directory
<R> -RAM Test
<V> -View Load
> .....
BOOT BIOS.HEX, INIT_FAT
Init SD Type#1 ACMD41+MBR S Type06 PBR S VOL=JAIR SYS=FAT16
LOADING FILE BIOS.HEX -EXISTS
FILE SIZE=0x00004AA7
Execute at:DB00
ALTAIR/IMSAI 8080 CPU BOARD - Josh Bensadon v2.6 (Oct 2016)
Init SD Type#1 ACMD41+MBR S Type06 PBR S VOL=JAIR SYS=FAT16
CPMDISKS.TXT -EXISTS
M - Monitor
C - Boot CP/M
1 - Disk A = DISK-A.BIN -EXISTS = 8" SSSD 250K
2 - Disk B = DISK-B.BIN -EXISTS = 8" SSSD 250K
3 - Disk C = DISK-C.BIN -EXISTS = 8" SSSD 250K
4 - Disk D = DISK-D.BIN -EXISTS = 8" SSSD 250K
>c
ALTAIR/IMSAI CPU CARD. 61K CP/M 2.2
WBOOT
a>ls
Name Ext Bytes Name Ext Bytes Name Ext Bytes Name Ext Bytes
ASM COM 8K | ED COM 8K | MOVCPM2 COM 11K | VIEW COM 1K
BIOS ASM 12K | GENMOD COM 2K | NSWP COM 12K | WM COM 11K
CPM48 COM 9K | LOAD COM 2K | PIP COM 8K | WM HLP 3K
CPMM48 COM 9K | LS COM 3K | RLOCBIOSCOM 3K | XMODEM CFG 1K
DDT COM 5K | MBASIC COM 24K | STAT COM 6K | XMODEM COM 8K
DEBLOCK ASM 10K | MON-32K COM 4K | STDBIOS ASM 16K | XSUB COM 1K
DISKDEF LIB 7K | MONV18 COM 5K | SUBMIT COM 2K
DUMP ASM 5K | MONV18 HEX 13K | SURVEY COM 2K
DUMP COM 1K | MOVCPM COM 10K | SYSGEN COM 1K
33 File(s), occupying 223K of 241K total capacity
30 directory entries and 18K bytes remain on A:
a>mbasic
BASIC-80 Rev. 5.21
[CP/M Version]
Copyright 1977-1981 (C) by Microsoft
Created: 28-Jul-81
31800 Bytes free
Ok
Hopefully @markpizz will chime in.
Possibly fixed with #336
When executing
SET THROTTLE x/y
, pressing ^E character on the console does not stop the simulator:the output of "sim> SHOW VERSION" while running the simulator which is having the issue
how you built the simulator or that you're using prebuilt binaries
the simulator configuration file (or commands) which were used when the problem occurred.
When running the following commands, pressing ^E character on the console does stop the simulator:
the expected behavior and the actual behavior
Expected:
Actual:
you may also need to provide specific pointers to data files that may be necessary to demonstrate the problem