1
0
mirror of https://github.com/simh/simh.git synced 2026-01-28 04:48:05 +00:00

Merge branch 'FastAsynchIO' into simhv38-2-rc2

Conflicts:
	PDP11/pdp11_tq.c
	PDP11/pdp11_ts.c
	PDP11/pdp11_xq.h
	VAX/vax780_sbi.c
	VAX/vax_cpu.c
	makefile
	scp.c
	sim_defs.h
	sim_ether.c
	sim_timer.c
This commit is contained in:
Mark Pizzolato
2011-04-15 10:47:35 -07:00
84 changed files with 15748 additions and 714 deletions

102
scp.c
View File

@@ -23,6 +23,11 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
29-Jan-11 MP Adjusted sim_debug to:
- include the simulator timestamp (sim_time)
as part of the prefix for each line of output
- write complete lines at a time (avoid asynch I/O issues).
05-Jan-11 MP Added Asynch I/O support
22-Jan-11 MP Added SET ON, SET NOON, ON, GOTO and RETURN command support
13-Jan-11 MP Added "SHOW SHOW" and "SHOW <dev> SHOW" commands
05-Jan-11 RMS Fixed bug in deposit stride for numeric input (John Dundas)
@@ -253,6 +258,17 @@
else if (sim_switches & SWMASK ('H')) val = 16; \
else val = dft;
/* Asynch I/O support */
#if defined (SIM_ASYNCH_IO)
pthread_mutex_t sim_asynch_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t sim_asynch_wake = PTHREAD_COND_INITIALIZER;
pthread_t sim_asynch_main_threadid;
struct sim_unit *sim_asynch_queue = NULL;
int32 sim_asynch_check;
int32 sim_asynch_latency = 4000; /* 4 usec interrupt latency */
int32 sim_asynch_inst_latency = 20; /* assume 5 mip simulator */
#endif
/* VM interface */
extern char sim_name[];
@@ -657,6 +673,7 @@ for (i = 1; i < argc; i++) { /* loop thru args */
} /* end for */
sim_quiet = sim_switches & SWMASK ('Q'); /* -q means quiet */
AIO_INIT; /* init Asynch I/O */
if (sim_vm_init != NULL) /* call once only */
(*sim_vm_init)();
sim_finit (); /* init fio package */
@@ -742,6 +759,7 @@ sim_set_deboff (0, NULL); /* close debug */
sim_set_logoff (0, NULL); /* close log */
sim_set_notelnet (0, NULL); /* close Telnet */
sim_ttclose (); /* close console */
AIO_CLEANUP; /* Asynch I/O */
return 0;
}
@@ -1766,6 +1784,26 @@ for (uptr = sim_clock_queue; uptr != NULL; uptr = uptr->next) {
fprintf (st, " at %d\n", accum + uptr->time);
accum = accum + uptr->time;
}
#if defined (SIM_ASYNCH_IO)
pthread_mutex_lock (&sim_asynch_lock);
fprintf (st, "asynchronous pending event queue\n");
if (sim_asynch_queue == (void *)-1)
fprintf (st, "Empty\n");
else {
for (uptr = sim_asynch_queue; uptr != (void *)-1; uptr = uptr->a_next) {
if ((dptr = find_dev_from_unit (uptr)) != NULL) {
fprintf (st, " %s", sim_dname (dptr));
if (dptr->numunits > 1) fprintf (st, " unit %d",
(int32) (uptr - dptr->units));
}
else fprintf (st, " Unknown");
fprintf (st, " event delay %d, queue time %d\n", uptr->a_event_time, uptr->a_sim_interval);
}
}
fprintf (st, "asynch latency: %d microseconds\n", sim_asynch_latency);
fprintf (st, "asynch instruction latency: %d instructions\n", sim_asynch_inst_latency);
pthread_mutex_unlock (&sim_asynch_lock);
#endif
return SCPE_OK;
}
@@ -2895,14 +2933,6 @@ r = sim_instr();
sim_is_running = 0; /* flag idle */
sim_ttcmd (); /* restore console */
signal (SIGINT, SIG_DFL); /* cancel WRU */
sim_cancel (&sim_step_unit); /* cancel step timer */
sim_throt_cancel (); /* cancel throttle */
if (sim_clock_queue != NULL) { /* update sim time */
UPDATE_SIM_TIME (sim_clock_queue->time);
}
else {
UPDATE_SIM_TIME (noqueue_time);
}
if (sim_log) /* flush console log */
fflush (sim_log);
if (sim_deb) /* flush debug log */
@@ -2912,12 +2942,24 @@ for (i = 1; (dptr = sim_devices[i]) != NULL; i++) { /* flush attached files
uptr = dptr->units + j;
if ((uptr->flags & UNIT_ATT) && /* attached, */
!(uptr->flags & UNIT_BUF) && /* not buffered, */
(uptr->fileref) && /* real file, */
!(uptr->flags & UNIT_RAW) && /* not raw, */
!(uptr->flags & UNIT_RO)) /* not read only? */
fflush (uptr->fileref);
(uptr->fileref)) /* real file, */
if (uptr->io_flush) /* unit specific flush routine */
uptr->io_flush (uptr);
else
if (!(uptr->flags & UNIT_RAW) && /* not raw, */
!(uptr->flags & UNIT_RO)) /* not read only? */
fflush (uptr->fileref);
}
}
sim_cancel (&sim_step_unit); /* cancel step timer */
sim_throt_cancel (); /* cancel throttle */
AIO_UPDATE_QUEUE;
if (sim_clock_queue != NULL) { /* update sim time */
UPDATE_SIM_TIME (sim_clock_queue->time);
}
else {
UPDATE_SIM_TIME (noqueue_time);
}
#if defined (VMS)
printf ("\n");
#endif
@@ -4457,6 +4499,7 @@ t_stat reason;
if (stop_cpu) /* stop CPU? */
return SCPE_STOP;
AIO_UPDATE_QUEUE;
if (sim_clock_queue == NULL) { /* queue empty? */
UPDATE_SIM_TIME (noqueue_time); /* update sim time */
sim_interval = noqueue_time = NOQUEUE_WAIT; /* flag queue empty */
@@ -4495,8 +4538,7 @@ t_stat sim_activate (UNIT *uptr, int32 event_time)
UNIT *cptr, *prvptr;
int32 accum;
if (event_time < 0)
return SCPE_IERR;
AIO_ACTIVATE (sim_activate, uptr, event_time);
if (sim_is_active (uptr)) /* already active? */
return SCPE_OK;
if (sim_clock_queue == NULL) {
@@ -4540,6 +4582,7 @@ return SCPE_OK;
t_stat sim_activate_abs (UNIT *uptr, int32 event_time)
{
AIO_ACTIVATE (sim_activate_abs, uptr, event_time);
sim_cancel (uptr);
return sim_activate (uptr, event_time);
}
@@ -4557,6 +4600,7 @@ t_stat sim_cancel (UNIT *uptr)
{
UNIT *cptr, *nptr;
AIO_VALIDATE;
if (sim_clock_queue == NULL)
return SCPE_OK;
UPDATE_SIM_TIME (sim_clock_queue->time); /* update sim time */
@@ -4594,6 +4638,7 @@ int32 sim_is_active (UNIT *uptr)
UNIT *cptr;
int32 accum;
AIO_VALIDATE;
accum = 0;
for (cptr = sim_clock_queue; cptr != NULL; cptr = cptr->next) {
if (cptr == sim_clock_queue) {
@@ -5002,7 +5047,7 @@ return SCPE_OK;
/* Debug printout routines, from Dave Hittner */
const char* debug_bstates = "01_^";
const char* debug_fmt = "DBG> %s %s: ";
const char* debug_fmt = "DBG(%.0f)> %s %s: ";
int32 debug_unterm = 0;
/* Finds debug phrase matching bitmask from from device DEBTAB table */
@@ -5032,7 +5077,7 @@ static void sim_debug_prefix (uint32 dbits, DEVICE* dptr)
{
if (!debug_unterm) {
char* debug_type = get_dbg_verb (dbits, dptr);
fprintf(sim_deb, debug_fmt, dptr->name, debug_type);
fprintf(sim_deb, debug_fmt, sim_time, dptr->name, debug_type);
}
}
@@ -5060,7 +5105,7 @@ if (sim_deb && (dptr->dctrl & dbits)) {
#if defined (_WIN32)
#define vsnprintf _vsnprintf
#endif
#if defined (__DECC) && defined (__VMS)
#if defined (__DECC) && defined (__VMS) && defined (__VAX)
#define NO_vsnprintf
#endif
#if defined( NO_vsnprintf)
@@ -5073,9 +5118,12 @@ if (sim_deb && (dptr->dctrl & dbits)) {
set and the bitmask matches the current device debug options.
Extra returns are added for un*x systems, since the output
device is set into 'raw' mode when the cpu is booted,
and the extra returns don't hurt any other systems. */
void sim_debug (uint32 dbits, DEVICE* dptr, const char* fmt, ...)
and the extra returns don't hurt any other systems.
Callers should be calling sim_debug() which is a macro
defined in scp.h which evaluates the action condition before
incurring call overhead. */
void _sim_debug (uint32 dbits, DEVICE* dptr, const char* fmt, ...)
{
if (sim_deb && (dptr->dctrl & dbits)) {
@@ -5084,9 +5132,9 @@ if (sim_deb && (dptr->dctrl & dbits)) {
char *buf = stackbuf;
va_list arglist;
int32 i, j, len;
char* debug_type = get_dbg_verb (dbits, dptr);
buf[bufsize-1] = '\0';
sim_debug_prefix(dbits, dptr); /* print prefix if required */
while (1) { /* format passed string, args */
va_start (arglist, fmt);
@@ -5132,10 +5180,14 @@ if (sim_deb && (dptr->dctrl & dbits)) {
for (i = j = 0; i < len; ++i) {
if ('\n' == buf[i]) {
if (i > j)
fwrite (&buf[j], 1, i-j, sim_deb);
j = i;
fputc('\r', sim_deb);
if (i > j) {
if (debug_unterm)
fprintf (sim_deb, "%.*s\r\n", i-j, &buf[j]);
else /* print prefix when required */
fprintf (sim_deb, "DBG(%.0f)> %s %s: %.*s\r\n", sim_time, dptr->name, debug_type, i-j, &buf[j]);
debug_unterm = 0;
}
j = i + 1;
}
}
if (i > j)