HP2100: Latest changes from Dave Bryan.

hp2100_ipl.c:

  - Exposed "ipl_edtdelay" via a REG_HIDDEN register to allow user tuning
    of the EDT delay that works around a race condition in the HP
    2000/Access Time-Shared BASIC system.

  - Corrected typos in comments and strings.

  - Merged SIMH 3.x and 4.x socket calls via conditionals, so that the
    module may be compiled for either version.

hp2100_mux.c:

  - Corrected a typo in the RTS macro definition.

hp2100_sys.c:

  - Added a cast to int for the parameter to "isspace" to avoid a compiler
    warning.

hp2100_bugfixes.txt

  - Added a description of the IPL hidden register fix.
This commit is contained in:
Mark Pizzolato 2015-09-17 05:24:31 -07:00
parent 4baecec0b1
commit 1d6c14be3d
4 changed files with 117 additions and 17 deletions

View file

@ -1,6 +1,6 @@
HP 2100 SIMULATOR BUG FIX WRITEUPS HP 2100 SIMULATOR BUG FIX WRITEUPS
================================== ==================================
Last update: 2015-01-03 Last update: 2015-09-14
1. PROBLEM: Booting from magnetic tape reports "HALT instruction, P: 77756 1. PROBLEM: Booting from magnetic tape reports "HALT instruction, P: 77756
@ -6789,3 +6789,27 @@
modifying the S register directly. modifying the S register directly.
STATUS: Fixed in version 4.0-0. STATUS: Fixed in version 4.0-0.
267. ENHANCEMENT: Add a register to the IPLI device to configure the DMA delay.
VERSION: 3.9-0
OBSERVATION: Occasionally, the 2000 Access terminal multiplexer does not
initialize properly; the problem is more prevalent on multiprocessor
systems.
There is a race condition between the system processor (SP) and the I/O
processor (IOP) during initialization. The problem occurs if the IOP DMA
completion interrupt routine finishes before the SP DMA completion
interrupt routine. As a workaround, the simulator suspends the IOP process
for one millisecond before signaling a DMA completion (EDT) interrupt.
Depending on system loading, this time may be insufficient.
RESOLUTION: Modify "ipli_reg" (hp2100_ipl.c) to add a hidden register,
EDTDELAY, that allows the user to configure the completion delay. The
register value is expressed in milliseconds and defaults to one
millisecond.
STATUS: Fixed in version 4.0-0.

View file

@ -1,6 +1,6 @@
/* hp2100_ipl.c: HP 2000 interprocessor link simulator /* hp2100_ipl.c: HP 2000 interprocessor link simulator
Copyright (c) 2002-2014, Robert M Supnik Copyright (c) 2002-2015, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,10 @@
IPLI, IPLO 12875A interprocessor link IPLI, IPLO 12875A interprocessor link
14-Sep-15 JDB Exposed "ipl_edtdelay" via a REG_HIDDEN to allow user tuning
Corrected typos in comments and strings
05-Jun-15 JDB Merged 3.x and 4.x versions using conditionals
11-Feb-15 MP Revised ipl_detach and ipl_dscln for new sim_close_sock API
30-Dec-14 JDB Added S-register parameters to ibl_copy 30-Dec-14 JDB Added S-register parameters to ibl_copy
12-Dec-12 MP Revised ipl_attach for new socket API 12-Dec-12 MP Revised ipl_attach for new socket API
25-Oct-12 JDB Removed DEV_NET to allow restoration of listening ports 25-Oct-12 JDB Removed DEV_NET to allow restoration of listening ports
@ -72,6 +76,13 @@
#include "hp2100_cpu.h" #include "hp2100_cpu.h"
#include "sim_sock.h" #include "sim_sock.h"
#include "sim_tmxr.h" #include "sim_tmxr.h"
#include "sim_rev.h"
#if (SIM_MAJOR >= 4)
#define sim_close_sock(socket,master) sim_close_sock (socket)
#endif
typedef enum { ipli, iplo } CARD_INDEX; /* card index number */ typedef enum { ipli, iplo } CARD_INDEX; /* card index number */
@ -172,6 +183,7 @@ REG ipli_reg [] = {
{ ORDATA (HOLD, ipl [ipli].hold, 8) }, { ORDATA (HOLD, ipl [ipli].hold, 8) },
{ DRDATA (TIME, ipl_ptime, 24), PV_LEFT }, { DRDATA (TIME, ipl_ptime, 24), PV_LEFT },
{ FLDATA (STOP_IOE, ipl_stopioe, 0) }, { FLDATA (STOP_IOE, ipl_stopioe, 0) },
{ DRDATA (EDTDELAY, ipl_edtdelay, 32), REG_HIDDEN | PV_LEFT },
{ ORDATA (SC, ipli_dib.select_code, 6), REG_HRO }, { ORDATA (SC, ipli_dib.select_code, 6), REG_HRO },
{ ORDATA (DEVNO, ipli_dib.select_code, 6), REG_HRO }, { ORDATA (DEVNO, ipli_dib.select_code, 6), REG_HRO },
{ NULL } { NULL }
@ -256,7 +268,7 @@ DEVICE iplo_dev = {
The STC/CLC normally would cause a second "request device table" command The STC/CLC normally would cause a second "request device table" command
to be recognized by the IOP, except that the IOP DMA setup routine to be recognized by the IOP, except that the IOP DMA setup routine
"DMAXF" (in D61.asm) has specified an end-of-block CLC that holds off the "DMAXF" (in D61.asm) has specified an end-of-block CLC that holds off the
IPL interrupt, and the completion interrupt routine "DMACP" ends with a IPL interrupt, and the completion interrupt routine "DMCMP" ends with a
STC,C that clears the IPL flag. STC,C that clears the IPL flag.
In hardware, the two CPUs are essentially interlocked by the DMA In hardware, the two CPUs are essentially interlocked by the DMA
@ -266,7 +278,7 @@ DEVICE iplo_dev = {
that guarantee does not hold. If the STC/CLC occurs after the STC,C, that guarantee does not hold. If the STC/CLC occurs after the STC,C,
then the IOP starts a second device table DMA transfer, which the SP is then the IOP starts a second device table DMA transfer, which the SP is
not expecting. The IOP never processes the subsequent "start not expecting. The IOP never processes the subsequent "start
timesharing" command, and the muxtiplexer is non-reponsive. timesharing" command, and the multiplexer is non-responsive.
We employ a workaround that decreases the incidence of the problem: DMA We employ a workaround that decreases the incidence of the problem: DMA
output completion interrupts are delayed to allow the other SIMH instance output completion interrupts are delayed to allow the other SIMH instance
@ -276,7 +288,9 @@ DEVICE iplo_dev = {
a data response to the SP. This improves the race condition by delaying a data response to the SP. This improves the race condition by delaying
the IOP until the SP has a chance to receive the last word, recognize its the IOP until the SP has a chance to receive the last word, recognize its
own DMA input completion, drop out of the SFS loop, and execute the own DMA input completion, drop out of the SFS loop, and execute the
STC/CLC. STC/CLC. The delay, "ipl_edtdelay", is initialized to one millisecond
but is exposed via a hidden IPLI register, "EDTDELAY", that allows the
user to lengthen the delay if necessary.
The condition is only improved, and not solved, because "sleep"ing the The condition is only improved, and not solved, because "sleep"ing the
IOP doesn't guarantee that the SP will actually execute. It's possible IOP doesn't guarantee that the SP will actually execute. It's possible
@ -574,10 +588,14 @@ return SCPE_OK;
t_stat ipl_attach (UNIT *uptr, char *cptr) t_stat ipl_attach (UNIT *uptr, char *cptr)
{ {
SOCKET newsock; SOCKET newsock;
uint32 i, t;
char host [CBUFSIZE], port [CBUFSIZE], hostport [2 * CBUFSIZE + 3];
char *tptr = NULL; char *tptr = NULL;
t_stat r; t_stat r;
#if (SIM_MAJOR >= 4)
uint32 i, t;
char host [CBUFSIZE], port [CBUFSIZE], hostport [2 * CBUFSIZE + 3];
t_bool is_active; t_bool is_active;
is_active = (uptr->flags & UNIT_ACTV) == UNIT_ACTV; /* is the connection active? */ is_active = (uptr->flags & UNIT_ACTV) == UNIT_ACTV; /* is the connection active? */
@ -636,6 +654,60 @@ if (tptr == NULL) { /* no memory? */
return SCPE_MEM; return SCPE_MEM;
} }
strcpy (tptr, hostport); /* copy ipaddr:port */ strcpy (tptr, hostport); /* copy ipaddr:port */
#else
uint32 i, t, ipa, ipp, oldf;
r = get_ipaddr (cptr, &ipa, &ipp);
if ((r != SCPE_OK) || (ipp == 0))
return SCPE_ARG;
oldf = uptr->flags;
if (oldf & UNIT_ATT)
ipl_detach (uptr);
if ((sim_switches & SWMASK ('C')) ||
((sim_switches & SIM_SW_REST) && (oldf & UNIT_ACTV))) {
if (ipa == 0)
ipa = 0x7F000001;
newsock = sim_connect_sock (ipa, ipp);
if (newsock == INVALID_SOCKET)
return SCPE_IOERR;
printf ("Connecting to IP address %d.%d.%d.%d, port %d\n",
(ipa >> 24) & 0xff, (ipa >> 16) & 0xff,
(ipa >> 8) & 0xff, ipa & 0xff, ipp);
if (sim_log)
fprintf (sim_log,
"Connecting to IP address %d.%d.%d.%d, port %d\n",
(ipa >> 24) & 0xff, (ipa >> 16) & 0xff,
(ipa >> 8) & 0xff, ipa & 0xff, ipp);
uptr->flags = uptr->flags | UNIT_ACTV;
uptr->LSOCKET = 0;
uptr->DSOCKET = newsock;
}
else {
if (ipa != 0)
return SCPE_ARG;
newsock = sim_master_sock (ipp);
if (newsock == INVALID_SOCKET)
return SCPE_IOERR;
printf ("Listening on port %d\n", ipp);
if (sim_log)
fprintf (sim_log, "Listening on port %d\n", ipp);
uptr->flags = uptr->flags & ~UNIT_ACTV;
uptr->LSOCKET = newsock;
uptr->DSOCKET = 0;
}
uptr->IBUF = uptr->OBUF = 0;
uptr->flags = (uptr->flags | UNIT_ATT) & ~(UNIT_ESTB | UNIT_HOLD);
tptr = (char *) malloc (strlen (cptr) + 1); /* get string buf */
if (tptr == NULL) { /* no memory? */
ipl_detach (uptr); /* close sockets */
return SCPE_MEM;
}
strcpy (tptr, cptr); /* copy ipaddr:port */
#endif
uptr->filename = tptr; /* save */ uptr->filename = tptr; /* save */
sim_activate (uptr, POLL_FIRST); /* activate first poll "immediately" */ sim_activate (uptr, POLL_FIRST); /* activate first poll "immediately" */
if (sim_switches & SWMASK ('W')) { /* wait? */ if (sim_switches & SWMASK ('W')) { /* wait? */
@ -644,7 +716,7 @@ if (sim_switches & SWMASK ('W')) { /* wait? */
if (t) /* established? */ if (t) /* established? */
break; break;
if ((i % 10) == 0) /* status every 10 sec */ if ((i % 10) == 0) /* status every 10 sec */
printf ("Waiting for connnection\n"); printf ("Waiting for connection\n");
sim_os_sleep (1); /* sleep 1 sec */ sim_os_sleep (1); /* sleep 1 sec */
} }
if (t) /* if connected (set by "ipl_check_conn" above) */ if (t) /* if connected (set by "ipl_check_conn" above) */
@ -661,12 +733,12 @@ if (!(uptr->flags & UNIT_ATT)) /* attached? */
return SCPE_OK; return SCPE_OK;
if (uptr->flags & UNIT_ACTV) if (uptr->flags & UNIT_ACTV)
sim_close_sock (uptr->DSOCKET); sim_close_sock (uptr->DSOCKET, 1);
else { else {
if (uptr->flags & UNIT_ESTB) /* if established, */ if (uptr->flags & UNIT_ESTB) /* if established, */
sim_close_sock (uptr->DSOCKET); /* close data socket */ sim_close_sock (uptr->DSOCKET, 0); /* close data socket */
sim_close_sock (uptr->LSOCKET); /* closen listen socket */ sim_close_sock (uptr->LSOCKET, 1); /* closen listen socket */
} }
free (uptr->filename); /* free string */ free (uptr->filename); /* free string */
@ -688,7 +760,7 @@ if (((uptr->flags & UNIT_ATT) == 0) ||
(uptr->flags & UNIT_ACTV) || (uptr->flags & UNIT_ACTV) ||
((uptr->flags & UNIT_ESTB) == 0)) ((uptr->flags & UNIT_ESTB) == 0))
return SCPE_NOFNC; return SCPE_NOFNC;
sim_close_sock (uptr->DSOCKET); sim_close_sock (uptr->DSOCKET, 0);
uptr->DSOCKET = 0; uptr->DSOCKET = 0;
uptr->flags = uptr->flags & ~UNIT_ESTB; uptr->flags = uptr->flags & ~UNIT_ESTB;
return SCPE_OK; return SCPE_OK;
@ -790,7 +862,7 @@ const int32 devi = ipli_dib.select_code;
const int32 devp = ptr_dib.select_code; const int32 devp = ptr_dib.select_code;
if (ibl_copy (ipl_rom, devi, IBL_S_CLR, /* copy the boot ROM to memory and configure */ if (ibl_copy (ipl_rom, devi, IBL_S_CLR, /* copy the boot ROM to memory and configure */
IBL_SET_SC (devi) | devp)) /* the S register accordingly */ IBL_SET_SC (devi) | devp)) /* the S register accordingly */
return SCPE_IERR; /* return an internal error if the copy failed */ return SCPE_IERR; /* return an internal error if the copy failed */
WritePW (PC + MAX_BASE, (~PC + 1) & DMASK); /* fix ups */ WritePW (PC + MAX_BASE, (~PC + 1) & DMASK); /* fix ups */

View file

@ -1,6 +1,6 @@
/* hp2100_mux.c: HP 2100 12920A terminal multiplexor simulator /* hp2100_mux.c: HP 2100 12920A terminal multiplexor simulator
Copyright (c) 2002-2014, Robert M Supnik Copyright (c) 2002-2015, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
MUX,MUXL,MUXM 12920A terminal multiplexor MUX,MUXL,MUXM 12920A terminal multiplexor
29-Jun-15 JDB Corrected typo in RTS macro definition
24-Dec-14 JDB Added casts for explicit downward conversions 24-Dec-14 JDB Added casts for explicit downward conversions
10-Jan-13 MP Added DEV_MUX and additional DEVICE field values 10-Jan-13 MP Added DEV_MUX and additional DEVICE field values
10-Feb-12 JDB Deprecated DEVNO in favor of SC 10-Feb-12 JDB Deprecated DEVNO in favor of SC
@ -221,7 +222,7 @@
#define OTC_SS2 0000002 /* SSn flops */ #define OTC_SS2 0000002 /* SSn flops */
#define OTC_SS1 0000001 #define OTC_SS1 0000001
#define OTC_RW (OTC_ES2|OTC_ES1|OTC_SS2|OTC_SS1) #define OTC_RW (OTC_ES2|OTC_ES1|OTC_SS2|OTC_SS1)
#define RTS OCT_C2 /* C2 = rts */ #define RTS OTC_C2 /* C2 = rts */
#define DTR OTC_C1 /* C1 = dtr */ #define DTR OTC_C1 /* C1 = dtr */
/* LIA, control */ /* LIA, control */

View file

@ -1,6 +1,6 @@
/* hp2100_sys.c: HP 2100 simulator interface /* hp2100_sys.c: HP 2100 simulator interface
Copyright (c) 1993-2014, Robert M. Supnik Copyright (c) 1993-2015, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -23,6 +23,7 @@
used in advertising or otherwise to promote the sale, use or other dealings used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik. in this Software without prior written authorization from Robert M Supnik.
18-Jun-15 JDB Added cast to int for isspace parameter
24-Dec-14 JDB Added casts to t_addr and t_value for 64-bit compatibility 24-Dec-14 JDB Added casts to t_addr and t_value for 64-bit compatibility
Made local routines static Made local routines static
05-Feb-13 JDB Added hp_fprint_stopped to handle HLT instruction message 05-Feb-13 JDB Added hp_fprint_stopped to handle HLT instruction message
@ -430,10 +431,12 @@ static const int32 vtab[] = {
#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) #define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)
#if (SIM_MAJOR >= 4)
/* Use scp.c provided fprintf function */ /* Use scp.c provided fprintf function */
#define fprintf Fprintf #define fprintf Fprintf
#define fputs(_s,f) Fprintf(f,"%s",_s) #define fputs(_s,f) Fprintf(f,"%s",_s)
#define fputc(_c,f) Fprintf(f,"%c",_c) #define fputc(_c,f) Fprintf(f,"%c",_c)
#endif
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
UNIT *uptr, int32 sw) UNIT *uptr, int32 sw)
@ -615,7 +618,7 @@ t_stat r, ret;
char *cptr, gbuf[CBUFSIZE]; char *cptr, gbuf[CBUFSIZE];
cflag = (uptr == NULL) || (uptr == &cpu_unit); cflag = (uptr == NULL) || (uptr == &cpu_unit);
while (isspace (*iptr)) iptr++; /* absorb spaces */ while (isspace ((int) *iptr)) iptr++; /* absorb spaces */
if ((sw & SWMASK ('A')) || ((*iptr == '\'') && iptr++)) { /* ASCII char? */ if ((sw & SWMASK ('A')) || ((*iptr == '\'') && iptr++)) { /* ASCII char? */
if (iptr[0] == 0) return SCPE_ARG; /* must have 1 char */ if (iptr[0] == 0) return SCPE_ARG; /* must have 1 char */
val[0] = (t_value) iptr[0] & 0177; val[0] = (t_value) iptr[0] & 0177;