home *** CD-ROM | disk | FTP | other *** search
- /* Simulator control program
-
- Copyright (c) 1993, 1994, 1995, 1996, Robert M Supnik,
- Digital Equipment Corporation
- Commercial use prohibited
-
- 13-Apr-95 RMS Added symbolic printouts
- 22-May-95 RMS Added symbolic input
- 11-Dec-95 RMS Fixed ordering bug in save/restore
- 07-Jan-96 RMS Added register buffers in save/restore
- */
-
- #include "sim_defs.h"
- #include <limits.h>
- #include <signal.h>
- #include <ctype.h>
- #define EX_D 0 /* deposit */
- #define EX_E 1 /* examine */
- #define EX_I 2 /* interactive */
- #define SWHIDE (1u << 26) /* enable hiding */
- #define RU_RUN 0 /* run */
- #define RU_GO 1 /* go */
- #define RU_STEP 2 /* step */
- #define RU_CONT 3 /* continue */
- #define RU_BOOT 4 /* boot */
- #define UPDATE_SIM_TIME(x) sim_time = sim_time + (x - sim_interval); \
- x = sim_interval
-
- extern char sim_name[];
- extern DEVICE *sim_devices[];
- extern REG *sim_PC;
- extern char *sim_stop_messages[];
- extern int sim_instr (void);
- extern int sim_load (FILE *ptr);
- extern int sim_emax;
- extern int print_sym (unsigned int addr, unsigned int *val, int flag, int sw);
- extern int parse_sym (char *cptr, unsigned int addr, int flag,
- unsigned int *val);
- extern int ttinit (void);
- extern int ttrunstate (void);
- extern int ttcmdstate (void);
- extern int ttclose (void);
- UNIT *sim_clock_queue = NULL;
- int sim_interval = 0;
- static double sim_time;
- static int noqueue_time;
- volatile int stop_cpu = 0;
- unsigned int *sim_eval = NULL;
-
- #define print_val(a,b,c,d) fprint_val (stdout, (a), (b), (c), (d))
- #define SZ_D(dp) (size_map[((dp) -> dwidth + CHAR_BIT - 1) / CHAR_BIT])
- #define SZ_R(rp) \
- (size_map[((rp) -> width + (rp) -> offset + CHAR_BIT - 1) / CHAR_BIT])
-
- char *get_glyph (char *iptr, char *optr, char mchar);
- int get_switches (char *cptr);
- int get_unum (char *cptr, int radix, unsigned int max, unsigned int *val);
- unsigned int get_rval (REG *rptr, int idx);
- void put_rval (REG *rptr, int idx, unsigned int val, unsigned int mask);
- int fprint_val (FILE *stream, unsigned int val, int rdx, int wid, int fmt);
- char *read_line (char *ptr, int size, FILE *stream);
- DEVICE *find_device (char *ptr, int *iptr);
- DEVICE *find_dev_from_unit (UNIT *uptr);
- REG *find_reg (char *ptr, char **optr, DEVICE *dptr);
- int reset_all (int start_device);
- int attach_unit (UNIT *uptr, char *cptr);
- int detach_all (int start_device);
- int detach_unit (UNIT *uptr);
- int ex_reg (int flag, int sw, REG *rptr);
- int dep_reg (int flag, int sw, char *cptr, REG *rptr);
- int ex_addr (int flag, int sw, unsigned int addr, DEVICE *dptr, UNIT *uptr);
- int dep_addr (int flag, int sw, char *cptr, unsigned int addr, DEVICE *dptr,
- UNIT *uptr);
- int sim_activate (UNIT *uptr, int interval);
- int sim_cancel (UNIT *uptr);
- int sim_is_active (UNIT *uptr);
- int step_svc (UNIT *ptr);
-
- UNIT step_unit = { UDATA (&step_svc, 0, 0) };
- const char *scp_error_messages[] = {
- "Address space exceeded",
- "Unit not attached",
- "I/O error",
- "Checksum error",
- "Format error",
- "Unit not attachable",
- "File open error",
- "Memory exhausted",
- "Invalid argument",
- "Step expired",
- "Unknown command",
- "Read only argument",
- "Command not completed",
- "Simulation stopped",
- "Goodbye",
- "Console input I/O error",
- "Console output I/O error",
- "End of file",
- "Relocation error",
- "No settable parameters",
- "Unit already attached" };
-
- const size_t size_map[] = { sizeof (char),
- sizeof (char), sizeof (short), sizeof (int), sizeof (int),
- sizeof (long), sizeof (long), sizeof (long), sizeof (long) };
-
- int main (int argc, char *argv[])
- {
- char cbuf[CBUFSIZE], gbuf[CBUFSIZE], *cptr;
- int i, stat;
- FILE *fpin;
- int reset_cmd (int flag, char *ptr);
- int exdep_cmd (int flag, char *ptr);
- int load_cmd (int flag, char *ptr);
- int run_cmd (int flag, char *ptr);
- int attach_cmd (int flag, char *ptr);
- int detach_cmd (int flag, char *ptr);
- int save_cmd (int flag, char *ptr);
- int restore_cmd (int flag, char *ptr);
- int exit_cmd (int flag, char *ptr);
- int set_cmd (int flag, char *ptr);
- int show_cmd (int flag, char *ptr);
- int help_cmd (int flag, char *ptr);
-
- static CTAB cmd_table[] = {
- { "RESET", &reset_cmd, 0 },
- { "EXAMINE", &exdep_cmd, EX_E },
- { "IEXAMINE", &exdep_cmd, EX_E+EX_I },
- { "DEPOSIT", &exdep_cmd, EX_D },
- { "IDEPOSIT", &exdep_cmd, EX_D+EX_I },
- { "RUN", &run_cmd, RU_RUN },
- { "GO", &run_cmd, RU_GO },
- { "STEP", &run_cmd, RU_STEP },
- { "CONT", &run_cmd, RU_CONT },
- { "BOOT", &run_cmd, RU_BOOT },
- { "ATTACH", &attach_cmd, 0 },
- { "DETACH", &detach_cmd, 0 },
- { "SAVE", &save_cmd, 0 },
- { "RESTORE", &restore_cmd, 0 },
- { "GET", &restore_cmd, 0 },
- { "LOAD", &load_cmd, 0 },
- { "EXIT", &exit_cmd, 0 },
- { "QUIT", &exit_cmd, 0 },
- { "BYE", &exit_cmd, 0 },
- { "SET", &set_cmd, 0 },
- { "SHOW", &show_cmd, 0 },
- { "HELP", &help_cmd, 0 },
- { NULL, NULL, 0 } };
-
- /* Main command loop */
-
- printf ("\n%s simulator V2.2\n", sim_name);
- if (sim_emax <= 0) sim_emax = 1;
- if ((sim_eval = calloc (sim_emax, sizeof (unsigned int))) == NULL) {
- printf ("Unable to allocate examine buffer\n");
- exit (0); };
- if (ttinit () != SCPE_OK) {
- printf ("Fatal terminal initialization error\n");
- exit (0); }
- stop_cpu = 0;
- sim_interval = 0;
- sim_time = 0;
- noqueue_time = 0;
- sim_clock_queue = NULL;
- reset_all (0);
-
- if ((argc > 1) && (argv[1] != NULL) &&
- ((fpin = fopen (argv[1], "r")) != NULL)) { /* command file? */
- do { cptr = read_line (cbuf, CBUFSIZE, fpin);
- if (cptr == NULL) break; /* exit on eof */
- if (*cptr == 0) continue; /* ignore blank */
- cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */
- for (i = 0; cmd_table[i].name != NULL; i++) {
- if (MATCH_CMD (gbuf, cmd_table[i].name) == 0) {
- stat = cmd_table[i].action (cmd_table[i].arg, cptr);
- break; } }
- if (stat >= SCPE_BASE)
- printf ("%s\n", scp_error_messages[stat - SCPE_BASE]);
- } while (stat != SCPE_EXIT); } /* end if cmd file */
-
- do { printf ("sim> "); /* prompt */
- cptr = read_line (cbuf, CBUFSIZE, stdin); /* read command line */
- stat = SCPE_UNK;
- if (cptr == NULL) continue; /* ignore EOF */
- if (*cptr == 0) continue; /* ignore blank */
- cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */
- for (i = 0; cmd_table[i].name != NULL; i++) {
- if (MATCH_CMD (gbuf, cmd_table[i].name) == 0) {
- stat = cmd_table[i].action (cmd_table[i].arg, cptr);
- break; } }
- if (stat >= SCPE_BASE)
- printf ("%s\n", scp_error_messages[stat - SCPE_BASE]);
- } while (stat != SCPE_EXIT);
-
- detach_all (0);
- ttclose ();
- exit (0);
- }
-
- /* Exit command */
-
- int exit_cmd (int flag, char *cptr)
- {
- return SCPE_EXIT;
- }
-
- /* Help command */
-
- int help_cmd (int flag, char *cptr)
- {
- printf ("r{eset} {ALL|<device>} reset simulator\n");
- printf ("e{xamine} <list> examine memory or registers\n");
- printf ("ie{xamine} <list> interactive examine memory or registers\n");
- printf ("d{eposit} <list> <val> deposit in memory or registers\n");
- printf ("id{eposit} <list> interactive deposit in memory or registers\n");
- printf ("l{oad} <file> load binary file\n");
- printf ("ru{n} {new PC} reset and start simulation\n");
- printf ("go {new PC} start simulation\n");
- printf ("c{ont} continue simulation\n");
- printf ("s{tep} {n} simulate n instructions\n");
- printf ("b(oot) <device>|<unit> bootstrap device\n");
- printf ("at{tach} <unit> <file> attach file to simulated unit\n");
- printf ("det{ach} <unit> detach file from simulated unit\n");
- printf ("sa{ve} <file> save simulator to file\n");
- printf ("rest{ore}|ge{t} <file> restore simulator from file\n");
- printf ("exi{t}|q{uit}|by{e} exit from simulation\n");
- printf ("set <unit> <val> set unit parameter\n");
- printf ("show <device> show device parameters\n");
- printf ("sh{ow} c{onfiguration} show configuration\n");
- printf ("sh{ow} q{ueue} show event queue\n");
- printf ("sh{ow} t{ime} show simulated time\n");
- printf ("h{elp} type this message\n");
- return SCPE_OK;
- }
-
- /* Set command */
-
- int set_cmd (int flag, char *cptr)
- {
- int unitno, r;
- char gbuf[CBUFSIZE];
- DEVICE *dptr;
- UNIT *uptr;
- MTAB *mptr;
-
- cptr = get_glyph (cptr, gbuf, 0); /* get glyph */
- dptr = find_device (gbuf, &unitno); /* find device */
- if ((dptr == NULL) || (*cptr == 0)) return SCPE_ARG; /* argument? */
- cptr = get_glyph (cptr, gbuf, 0); /* get glyph */
- if (*cptr != 0) return SCPE_ARG; /* now eol? */
- uptr = dptr -> units + unitno;
- if (dptr -> modifiers == NULL) return SCPE_NOPARAM; /* any modifiers? */
- for (mptr = dptr -> modifiers; mptr -> mask != 0; mptr++) {
- if ((mptr -> mstring != NULL) &&
- (MATCH_CMD (gbuf, mptr -> mstring) == 0)) {
- if ((mptr -> valid != NULL) &&
- ((r = mptr -> valid (uptr, mptr -> match)) != SCPE_OK))
- return r; /* invalid? */
- uptr -> flags = (uptr -> flags & ~(mptr -> mask)) |
- (mptr -> match & mptr -> mask); /* set new value */
- return SCPE_OK; } }
- return SCPE_ARG; /* no match */
- }
-
- /* Show command */
-
- int show_cmd (int flag, char *cptr)
- {
- int i;
- char gbuf[CBUFSIZE];
- DEVICE *dptr;
- int show_config (int flag, char *ptr);
- int show_queue (int flag, char *ptr);
- int show_time (int flag, char *ptr);
- int show_device (DEVICE *dptr, int flag);
- static CTAB show_table[] = {
- { "CONFIGURATION", &show_config, 0 },
- { "QUEUE", &show_queue, 0 },
- { "TIME", &show_time, 0 },
- { NULL, NULL, 0 } };
-
- cptr = get_glyph (cptr, gbuf, 0); /* get glyph */
- for (i = 0; show_table[i].name != NULL; i++) { /* find command */
- if (MATCH_CMD (gbuf, show_table[i].name) == 0)
- return show_table[i].action (show_table[i].arg, cptr); }
- dptr = find_device (gbuf, NULL); /* find device */
- if (dptr == NULL) return SCPE_ARG;
- return show_device (dptr, dptr != sim_devices[0]);
- }
-
- /* Show processors */
-
- int show_device (DEVICE *dptr, int flag)
- {
- int j;
- UNIT *uptr;
- MTAB *mptr;
-
- printf ("%s", dptr -> name);
- if (dptr -> numunits > 1) printf (", %d units\n", dptr -> numunits);
- for (j = 0; j < dptr -> numunits; j++) {
- uptr = (dptr -> units) + j;
- if (dptr -> numunits > 1) printf (" unit %d", j);
- if (uptr -> flags & UNIT_FIX)
- printf (", %dK%s", uptr -> capac / (flag? 1000: 1024),
- ((dptr -> dwidth / dptr -> aincr) > 8)? "W": "B");
- if (uptr -> flags & UNIT_ATT)
- printf (", attached to %s", uptr -> filename);
- else if (uptr -> flags & UNIT_ATTABLE) printf (", not attached");
- if (dptr -> modifiers != NULL) {
- for (mptr = dptr -> modifiers; mptr -> mask != 0; mptr++) {
- if ((mptr -> pstring != NULL) &&
- ((uptr -> flags & mptr -> mask) == mptr -> match))
- printf (", %s", mptr -> pstring); } }
- printf ("\n"); }
- return SCPE_OK;
- }
-
- int show_config (int flag, char *cptr)
- {
- int i;
- DEVICE *dptr;
-
- printf ("%s simulator configuration\n\n", sim_name);
- for (i = 0; (dptr = sim_devices[i]) != NULL; i++) show_device (dptr, i);
- return SCPE_OK;
- }
-
- int show_queue (int flag, char *cptr)
- {
- DEVICE *dptr;
- UNIT *uptr;
- int accum;
-
- if (sim_clock_queue == NULL) {
- printf ("%s event queue empty, time = %-16.0f\n", sim_name, sim_time);
- return SCPE_OK; }
- printf ("%s event queue status, time = %-16.0f\n", sim_name, sim_time);
- accum = 0;
- for (uptr = sim_clock_queue; uptr != NULL; uptr = uptr -> next) {
- if (uptr == &step_unit) printf (" Step timer");
- else if ((dptr = find_dev_from_unit (uptr)) != NULL) {
- printf (" %s", dptr -> name);
- if (dptr -> numunits > 1) printf (" unit %d",
- uptr - dptr -> units); }
- else printf (" Unknown");
- printf (" at %d\n", accum + uptr -> time);
- accum = accum + uptr -> time; }
- return SCPE_OK;
- }
-
- int show_time (int flag, char *cptr)
- {
- printf ("Time: %-16.0f\n", sim_time);
- return SCPE_OK;
- }
-
- /* Reset command and routines
-
- re[set] reset all devices
- re[set] all reset all devices
- re[set] device reset specific device
- */
-
- int reset_cmd (int flag, char *cptr)
- {
- char gbuf[CBUFSIZE];
- DEVICE *dptr;
-
- if (*cptr == 0) return (reset_all (0)); /* reset(cr) */
- cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
- if (*cptr != 0) return SCPE_ARG; /* now (cr)? */
- if (strcmp (gbuf, "ALL") == 0) return (reset_all (0));
- if ((dptr = find_device (gbuf, NULL)) == NULL) return SCPE_ARG;
- if (dptr -> reset != NULL) return dptr -> reset (dptr);
- else return SCPE_OK;
- }
-
- /* Reset devices start..end
-
- Inputs:
- start = number of starting device
- Outputs:
- status = error status
- */
-
- int reset_all (int start)
- {
- DEVICE *dptr;
- int i;
-
- if ((start < 0) || (start > 1)) return SCPE_ARG;
- for (i = start; (dptr = sim_devices[i]) != NULL; i++) {
- if (dptr -> reset != NULL) dptr -> reset (dptr); }
- return SCPE_OK;
- }
-
- /* Load command
-
- lo[ad] filename load specified file
- */
-
- int load_cmd (int flag, char *cptr)
- {
- FILE *loadfile;
- int reason;
-
- if (*cptr == 0) return SCPE_ARG;
- loadfile = fopen (cptr, "r");
- if (loadfile == NULL) return SCPE_OPENERR;
- reason = sim_load (loadfile);
- fclose (loadfile);
- return reason;
- }
-
- /* Attach command
-
- at[tach] unit file attach specified unit to file
- */
-
- int attach_cmd (int flag, char *cptr)
- {
- char gbuf[CBUFSIZE];
- int unitno;
- DEVICE *dptr;
- UNIT *uptr;
-
- if (*cptr == 0) return SCPE_ARG;
- cptr = get_glyph (cptr, gbuf, 0);
- if (*cptr == 0) return SCPE_ARG;
- if ((dptr = find_device (gbuf, &unitno)) == NULL) return SCPE_ARG;
- uptr = (dptr -> units) + unitno;
- if (dptr -> attach != NULL) return dptr -> attach (uptr, cptr);
- return attach_unit (uptr, cptr);
- }
-
- int attach_unit (UNIT *uptr, char *cptr)
- {
- DEVICE *dptr;
- int reason;
-
- if (!(uptr -> flags & UNIT_ATTABLE)) return SCPE_NOATT;
- if ((dptr = find_dev_from_unit (uptr)) == NULL) return SCPE_NOATT;
- if (uptr -> flags & UNIT_ATT) {
- reason = detach_unit (uptr);
- if (reason != SCPE_OK) return reason; }
- uptr -> filename = calloc (CBUFSIZE, sizeof (char));
- if (uptr -> filename == NULL) return SCPE_MEM;
- strncpy (uptr -> filename, cptr, CBUFSIZE);
- uptr -> fileref = fopen (cptr, "r+");
- if (uptr -> fileref == NULL) {
- uptr -> fileref = fopen (cptr, "w+");
- if (uptr -> fileref == NULL) return SCPE_OPENERR;
- printf ("%s: creating new file\n", dptr -> name); }
- if (uptr -> flags & UNIT_BUFABLE) {
- if ((uptr -> filebuf = calloc (SZ_D (dptr), uptr -> capac)) != NULL) {
- printf ("%s: buffering file in memory\n", dptr -> name);
- uptr -> hwmark = fread (uptr -> filebuf, SZ_D (dptr),
- uptr -> capac, uptr -> fileref);
- uptr -> flags = uptr -> flags | UNIT_BUF; }
- else if (uptr -> flags & UNIT_MUSTBUF) return SCPE_MEM; }
- uptr -> flags = uptr -> flags | UNIT_ATT;
- uptr -> pos = 0;
- return SCPE_OK;
- }
-
- /* Detach command
-
- det[ach] all detach all units
- det[ach] unit detach specified unit
- */
-
- int detach_cmd (int flag, char *cptr)
- {
- char gbuf[CBUFSIZE];
- int unitno;
- DEVICE *dptr;
- UNIT *uptr;
-
- if (*cptr == 0) return SCPE_ARG;
- cptr = get_glyph (cptr, gbuf, 0);
- if (*cptr != 0) return SCPE_ARG;
- if (strcmp (gbuf, "ALL") == 0) return (detach_all (0));
- if ((dptr = find_device (gbuf, &unitno)) == NULL) return SCPE_ARG;
- uptr = (dptr -> units) + unitno;
- if (!(uptr -> flags & UNIT_ATTABLE)) return SCPE_NOATT;
- if (dptr -> detach != NULL) return dptr -> detach (uptr);
- return detach_unit (uptr);
- }
-
- /* Detach devices start..end
-
- Inputs:
- start = number of starting device
- Outputs:
- status = error status
- */
-
- int detach_all (int start)
- {
- int i, j, reason;
- DEVICE *dptr;
- UNIT *uptr;
-
- if ((start < 0) || (start > 1)) return SCPE_ARG;
- for (i = start; (dptr = sim_devices[i]) != NULL; i++) {
- for (j = 0; j < dptr -> numunits; j++) {
- uptr = (dptr -> units) + j;
- if (dptr -> detach != NULL) reason = dptr -> detach (uptr);
- else reason = detach_unit (uptr);
- if (reason != SCPE_OK) return reason; } }
- return SCPE_OK;
- }
-
- int detach_unit (UNIT *uptr)
- {
- DEVICE *dptr;
-
- if (uptr == NULL) return SCPE_ARG;
- if (!(uptr -> flags & UNIT_ATT)) return SCPE_OK;
- if ((dptr = find_dev_from_unit (uptr)) == NULL) return SCPE_OK;
- uptr -> flags = uptr -> flags & ~UNIT_ATT;
- if (uptr -> flags & UNIT_BUF) {
- printf ("%s: writing buffer to file\n", dptr -> name);
- uptr -> flags = uptr -> flags & ~UNIT_BUF;
- rewind (uptr -> fileref);
- fwrite (uptr -> filebuf, SZ_D (dptr), uptr -> hwmark, uptr -> fileref);
- if (ferror (uptr -> fileref)) perror ("I/O error");
- free (uptr -> filebuf);
- uptr -> filebuf = NULL; }
- free (uptr -> filename);
- uptr -> filename = NULL;
- return (fclose (uptr -> fileref) == EOF)? SCPE_IOERR: SCPE_OK;
- }
-
- /* Save command
-
- sa[ve] filename save state to specified file
- */
-
- int save_cmd (int flag, char *cptr)
- {
- FILE *sfile;
- int i, j, k, t, reason, zerocnt, high;
- unsigned int val;
- DEVICE *dptr;
- UNIT *uptr;
- REG *rptr;
-
- #define WRITE_I(xx) fwrite (&(xx), sizeof (int), 1, sfile)
-
- if (*cptr == 0) return SCPE_ARG;
- if ((sfile = fopen (cptr, "w")) == NULL) return SCPE_OPENERR;
- fputs (sim_name, sfile); /* sim name */
- fputc ('\n', sfile);
- fwrite (&sim_time, sizeof (double), 1, sfile); /* sim time */
-
- for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru devices */
- fputs (dptr -> name, sfile); /* device name */
- fputc ('\n', sfile);
- for (j = 0; j < dptr -> numunits; j++) {
- uptr = (dptr -> units) + j;
- t = sim_is_active (uptr);
- WRITE_I (j); /* unit number */
- WRITE_I (t); /* activation time */
- WRITE_I (uptr -> u3); /* unit specific */
- WRITE_I (uptr -> u4);
- if (uptr -> flags & UNIT_ATT) fputs (uptr -> filename, sfile);
- fputc ('\n', sfile);
- if (((uptr -> flags & (UNIT_FIX + UNIT_ATTABLE)) == UNIT_FIX) &&
- (dptr -> examine != NULL) &&
- ((high = uptr -> capac) != 0)) { /* memory-like unit? */
- WRITE_I (high); /* memory limit */
- zerocnt = 0;
- for (k = 0; k < high; k = k + (dptr -> aincr)) {
- reason = dptr -> examine (&val, k, uptr, 0);
- if (reason != SCPE_OK) return reason;
- if (val == 0) zerocnt = zerocnt - 1;
- else { if (zerocnt) WRITE_I (zerocnt);
- zerocnt = 0;
- WRITE_I (val); } }
- if (zerocnt) WRITE_I (zerocnt); }
- else { k = 0;
- WRITE_I (k); } }
- t = -1; WRITE_I (t); /* end units */
- for (rptr = dptr -> registers; /* loop thru regs */
- (rptr != NULL) && (rptr -> name != NULL); rptr++) {
- fputs (rptr -> name, sfile); /* name */
- fputc ('\n', sfile);
- for (k = 0; k < rptr -> depth; k++) { /* loop thru values */
- val = get_rval (rptr, k); /* get value */
- WRITE_I (val); } } /* store */
- fputc ('\n', sfile); } /* end registers */
- fputc ('\n', sfile); /* end devices */
- reason = (ferror (sfile))? SCPE_IOERR: SCPE_OK; /* error during save? */
- fclose (sfile);
- return reason;
- }
-
- /* Restore command
-
- re[store] filename restore state from specified file
- */
-
- int restore_cmd (int flag, char *cptr)
- {
- char buf[CBUFSIZE];
- FILE *rfile;
- int i, j, k, data, reason, unitno, time, high;
- unsigned int val, mask;
- DEVICE *dptr;
- UNIT *uptr;
- REG *rptr;
-
- #define READ_S(xx) if (read_line ((xx), CBUFSIZE, rfile) == NULL) \
- { fclose (rfile); return SCPE_IOERR; }
- #define READ_I(xx) if (fread (&xx, sizeof (int), 1, rfile) <= 0) \
- { fclose (rfile); return SCPE_IOERR; }
-
- if (*cptr == 0) return SCPE_ARG;
- if ((rfile = fopen (cptr, "r")) == NULL) return SCPE_OPENERR;
- READ_S (buf); /* sim name */
- if (strcmp (buf, sim_name)) {
- printf ("Wrong system type: %s\n", buf);
- fclose (rfile);
- return SCPE_OK; }
- fread (&sim_time, sizeof (double), 1, rfile); /* sim time */
-
- for ( ;; ) { /* device loop */
- READ_S (buf); /* read device name */
- if (buf[0] == 0) break; /* last? */
- if ((dptr = find_device (buf, NULL)) == NULL) {
- printf ("Invalid device name: %s\n", buf);
- fclose (rfile);
- return SCPE_INCOMP; }
- for ( ;; ) { /* unit loop */
- READ_I (unitno); /* unit number */
- if (unitno < 0) break;
- if (unitno >= dptr -> numunits) {
- printf ("Invalid unit number %s%d\n", dptr -> name,
- unitno);
- fclose (rfile);
- return SCPE_INCOMP; }
- READ_I (time); /* event time */
- uptr = (dptr -> units) + unitno;
- sim_cancel (uptr);
- if (time > 0) sim_activate (uptr, time - 1);
- READ_I (uptr -> u3); /* device specific */
- READ_I (uptr -> u4);
- READ_S (buf); /* attached file */
- if (buf[0] != 0) {
- reason = attach_unit (uptr, buf);
- if (reason != SCPE_OK) return reason; }
- READ_I (high); /* memory capacity */
- if ((high > 0) && /* validate if > 0 */
- (((uptr -> flags & (UNIT_FIX + UNIT_ATTABLE)) != UNIT_FIX) ||
- (high > uptr -> capac) || (dptr -> deposit == NULL))) {
- printf ("Invalid memory bound: %u\n", high);
- fclose (rfile);
- return SCPE_INCOMP; }
- for (i = 0; i < high; i = i + (dptr -> aincr)) {
- READ_I (data);
- if (data < 0) {
- for (j = data + 1; j < 0; j++) {
- reason = dptr -> deposit (0, i, uptr, 0);
- if (reason != SCPE_OK) return reason;
- i = i + (dptr -> aincr); }
- data = 0; }
- reason = dptr -> deposit (data, i, uptr, 0);
- if (reason != SCPE_OK) return reason; }
- } /* end unit loop */
- for ( ;; ) { /* register loop */
- READ_S (buf); /* read reg name */
- if (buf[0] == 0) break; /* last? */
- if ((rptr = find_reg (buf, NULL, dptr)) == NULL) {
- printf ("Invalid register name: %s\n", buf);
- fclose (rfile);
- return SCPE_INCOMP; }
- mask = (1u << rptr -> width) - 1;
- for (k = 0; k < rptr -> depth; k++) { /* loop thru values */
- READ_I (val); /* read value */
- if (val > mask)
- printf ("Invalid register value: %s\n", buf);
- else put_rval (rptr, k, val, mask); } }
- } /* end device loop */
- fclose (rfile);
- return SCPE_OK;
- }
-
- /* Run, go, cont, step commands
-
- ru[n] [new PC] reset and start simulation
- go [new PC] start simulation
- co[nt] start simulation
- s[tep] [step limit] start simulation for 'limit' instructions
- b[oot] device bootstrap from device and start simulation
- */
-
- int run_cmd (int flag, char *cptr)
- {
- char gbuf[CBUFSIZE];
- int i, j, addr, unitno, r;
- unsigned int step;
- DEVICE *dptr;
- UNIT *uptr;
- void int_handler (int signal);
-
- step = 0;
- if (((flag == RU_RUN) || (flag == RU_GO)) && (*cptr != 0)) { /* run or go */
- cptr = get_glyph (cptr, gbuf, 0); /* get PC, store */
- if ((r = dep_reg (0, 0, gbuf, sim_PC)) != SCPE_OK) return r; }
-
- if (flag == RU_STEP) { /* step */
- if (*cptr == 0) step = 1;
- else { cptr = get_glyph (cptr, gbuf, 0);
- if ((get_unum (gbuf, 10, -1, &step) != SCPE_OK) ||
- (step == 0)) return SCPE_ARG; } }
-
- if (flag == RU_BOOT) { /* boot */
- if (*cptr == 0) return SCPE_ARG;
- cptr = get_glyph (cptr, gbuf, 0);
- if ((dptr = find_device (gbuf, &unitno)) == NULL) return SCPE_ARG;
- if (dptr -> boot == NULL) return SCPE_ARG;
- uptr = dptr -> units + unitno;
- if (!(uptr -> flags & UNIT_ATTABLE)) return SCPE_NOATT;
- if (!(uptr -> flags & UNIT_ATT)) return SCPE_UNATT;
- if ((r = dptr -> boot (unitno)) != SCPE_OK) return r; }
-
- if (*cptr != 0) return SCPE_ARG;
-
- if ((flag == RU_RUN) || (flag == RU_BOOT)) { /* run or boot */
- sim_interval = 0; /* reset queue */
- sim_time = 0;
- noqueue_time = 0;
- sim_clock_queue = NULL;
- reset_all (0); } /* reset devices */
- for (i = 1; (dptr = sim_devices[i]) != NULL; i++) {
- for (j = 0; j < dptr -> numunits; j++) {
- uptr = (dptr -> units) + j;
- if ((uptr -> flags & (UNIT_ATT + UNIT_SEQ)) ==
- (UNIT_ATT + UNIT_SEQ))
- fseek (uptr -> fileref, uptr -> pos, SEEK_SET); } }
- stop_cpu = 0;
- if ((int) signal (SIGINT, int_handler) == -1) { /* set WRU */
- printf ("Simulator interrupt handler setup failed\n");
- return SCPE_OK; }
- if (ttrunstate () != SCPE_OK) { /* set console */
- ttcmdstate ();
- printf ("Simulator terminal setup failed\n");
- return SCPE_OK; }
- if (step) sim_activate (&step_unit, step); /* set step timer */
- r = sim_instr();
-
- ttcmdstate (); /* restore console */
- signal (SIGINT, SIG_DFL); /* cancel WRU */
- sim_cancel (&step_unit); /* cancel step timer */
- if (sim_clock_queue != NULL) { /* update sim time */
- UPDATE_SIM_TIME (sim_clock_queue -> time); }
- else { UPDATE_SIM_TIME (noqueue_time); }
- #ifdef VMS
- printf ("\n");
- #endif
- if (r >= SCPE_BASE) printf ("\n%s, PC: ", scp_error_messages[r - SCPE_BASE]);
- else printf ("\n%s, PC: ", sim_stop_messages[r]);
- print_val (addr = get_rval (sim_PC, 0), sim_PC -> radix,
- sim_PC -> width, sim_PC -> flags & REG_FMT);
- if (((dptr = sim_devices[0]) != NULL) && (dptr -> examine != NULL)) {
- for (i = 0; i < sim_emax; i++) sim_eval[i] = 0;
- for (i = 0, j = addr; i < sim_emax; i++, j = j + dptr -> aincr) {
- if (r = dptr -> examine (&sim_eval[i], j, dptr -> units,
- SWMASK ('V')) != SCPE_OK) break; }
- if ((r == SCPE_OK) || (i > 0)) {
- printf (" (");
- if (print_sym (addr, sim_eval, TRUE, SWMASK('M')) > 0)
- print_val (sim_eval[0], dptr -> dradix,
- dptr -> dwidth, PV_RZRO);
- printf (")"); } }
- printf ("\n");
- return SCPE_OK;
- }
-
- /* Run time routines */
-
- /* Unit service for step timeout, originally scheduled by STEP n command
-
- Return step timeout SCP code, will cause simulation to stop
- */
-
- int step_svc (UNIT *uptr)
- {
- return SCPE_STEP;
- }
-
- /* Signal handler for ^C signal
-
- Set stop simulation flag
- */
-
- void int_handler (int sig)
- {
- stop_cpu = 1;
- return;
- }
-
- /* Examine/deposit commands
-
- ex[amine] [unit] list examine
- de[posit] [unit] list val deposit
- ie[xamine] [unit] list interactive examine
- id[eposit] [unit] list interactive deposit
-
- list list of addresses and registers
- addr[:addr|-addr] address range
- ALL all addresses
- register[:register|-register] register range
- STATE all registers
- */
-
- int exdep_cmd (int flag, char *cptr)
- {
- char gbuf[CBUFSIZE], *gptr, *tptr;
- int sw, reason, unitno;
- unsigned int low, high;
- DEVICE *dptr;
- UNIT *uptr;
- REG *lowr, *highr;
- int exdep_addr_loop (int flag, int sw, char *ptr, unsigned int low,
- unsigned int high, DEVICE *dptr, UNIT *uptr);
- int exdep_reg_loop (int flag, int sw, char *ptr, REG *lptr, REG *hptr);
-
- if (*cptr == 0) return SCPE_ARG; /* err if no args */
- cptr = get_glyph (cptr, gbuf, 0);
- if ((sw = get_switches (gbuf)) != 0) { /* try for switches */
- if ((sw < 0) || (*cptr == 0)) return SCPE_ARG; /* err if no args */
- cptr = get_glyph (cptr, gbuf, 0); } /* if found, advance */
- if ((dptr = find_device (gbuf, &unitno)) != NULL) { /* try for unit */
- if (*cptr == 0) return SCPE_ARG; /* err if no args */
- cptr = get_glyph (cptr, gbuf, 0); } /* if found, advance */
- else { dptr = sim_devices[0]; /* CPU is default */
- unitno = 0; }
- if ((*cptr == 0) == (flag == 0)) return SCPE_ARG; /* eol if needed? */
-
- gptr = gbuf;
- uptr = (dptr -> units) + unitno;
- while (*gptr != 0) {
- errno = 0;
- low = strtoul (gptr, &tptr, dptr -> aradix);
- if ((errno == 0) && (gptr != tptr)) {
- high = low;
- if ((*tptr == '-') || (*tptr == ':')) {
- gptr = tptr + 1;
- errno = 0;
- high = strtoul (gptr, &tptr, dptr -> aradix);
- if (errno || (gptr == tptr)) return SCPE_ARG; }
- if (*tptr == ',') tptr++;
- else if (*tptr != 0) return SCPE_ARG;
- reason = exdep_addr_loop (flag, sw, cptr, low, high,
- dptr, uptr);
- if (reason != SCPE_OK) return reason; }
-
- else if (strncmp (gptr, "ALL", strlen ("ALL")) == 0) {
- tptr = gptr + strlen ("ALL");
- if (*tptr == ',') tptr++;
- else if (*tptr != 0) return SCPE_ARG;
- if ((uptr -> capac == 0) | (flag == EX_E)) return SCPE_ARG;
- high = (uptr -> capac) - (dptr -> aincr);
- reason = exdep_addr_loop (flag, sw, cptr, 0, high, dptr, uptr);
- if (reason != SCPE_OK) return reason; }
-
- else if (strncmp (gptr, "STATE", strlen ("STATE")) == 0) {
- tptr = gptr + strlen ("STATE");
- if (*tptr == ',') tptr++;
- else if (*tptr != 0) return SCPE_ARG;
- if ((lowr = dptr -> registers) == NULL) return SCPE_ARG;
- for (highr = lowr; highr -> name != NULL; highr++) ;
- reason = exdep_reg_loop (flag, sw+SWHIDE, cptr, lowr, --highr);
- if (reason != SCPE_OK) return reason; }
-
- else { lowr = find_reg (gptr, &tptr, dptr);
- if (lowr == NULL) return SCPE_ARG;
- highr = lowr;
- if ((*tptr == '-') || (*tptr == ':')) {
- highr = find_reg (tptr + 1, &tptr, dptr);
- if (highr == NULL) return SCPE_ARG; }
- if (*tptr == ',') tptr++;
- else if (*tptr != 0) return SCPE_ARG;
- reason = exdep_reg_loop (flag, sw, cptr, lowr, highr);
- if (reason != SCPE_OK) return reason; }
-
- gptr = tptr; } /* end while */
- return SCPE_OK;
- }
-
- /* Loop controllers for examine/deposit
-
- exdep_reg_loop examine/deposit range of registers
- exdep_addr_loop examine/deposit range of addresses
- */
-
- int exdep_reg_loop (int flag, int sw, char *cptr, REG *lowr, REG *highr)
- {
- int reason;
- REG *rptr;
-
- if ((lowr == NULL) || (highr == NULL)) return SCPE_ARG;
- if (lowr > highr) return SCPE_ARG;
- for (rptr = lowr; rptr <= highr; rptr++) {
- if ((sw & SWHIDE) && (rptr -> flags & REG_HIDDEN)) continue;
- if (flag != EX_D) {
- reason = ex_reg (flag, sw, rptr);
- if (reason != SCPE_OK) return reason; }
- if (flag != EX_E) {
- reason = dep_reg (flag, sw, cptr, rptr);
- if (reason != SCPE_OK) return reason; } }
- return SCPE_OK;
- }
-
- int exdep_addr_loop (int flag, int sw, char *cptr, unsigned int low,
- unsigned int high, DEVICE *dptr, UNIT *uptr)
- {
- int reason;
- unsigned int i, mask;
-
- reason = 0;
- mask = (1u << dptr -> awidth) - 1;
- if ((low > mask) || (high > mask)) return SCPE_ARG;
- if (low > high) return SCPE_ARG;
- for (i = low; i <= high; i = i + (dptr -> aincr)) {
- if (flag != EX_D) {
- reason = ex_addr (flag, sw, i, dptr, uptr);
- if (reason > SCPE_OK) return reason; }
- if (flag != EX_E) {
- reason = dep_addr (flag, sw, cptr, i, dptr, uptr);
- if (reason > SCPE_OK) return reason; }
- if (reason < SCPE_OK) i = i - (reason * dptr -> aincr); }
- return SCPE_OK;
- }
-
- /* Examine register routine
-
- Inputs:
- flag = type of ex/mod command (ex, iex, idep)
- sw = switches
- rptr = pointer to register descriptor
- Outputs:
- return = error status
- */
-
- int ex_reg (int flag, int sw, REG *rptr)
- {
- unsigned int val;
-
- if (rptr == NULL) return SCPE_ARG;
- printf ("%s: ", rptr -> name);
- if (!(flag & EX_E)) return SCPE_OK;
- val = get_rval (rptr, 0);
- print_val (val, rptr -> radix, rptr -> width, rptr -> flags & REG_FMT);
- if (flag & EX_I) printf (" ");
- else printf ("\n");
- return SCPE_OK;
- }
-
- /* Get register value
-
- Inputs:
- rptr = pointer to register descriptor
- idx = index (SAVE register buffers only)
- Outputs:
- return = register value
- */
-
- unsigned int get_rval (REG *rptr, int idx)
- {
- unsigned int val;
- size_t sz;
-
- sz = SZ_R (rptr);
- if (sz == sizeof (char)) val = *(((unsigned char *) rptr -> loc) + idx);
- else if (sz == sizeof (short)) val = *(((unsigned short *) rptr -> loc) + idx);
- else if (sz == sizeof (int)) val = *(((unsigned int *) rptr -> loc) + idx);
- else if (sz == sizeof (long)) val = *(((unsigned long *) rptr -> loc) + idx);
- val = (val >> rptr -> offset) & ((1u << rptr -> width) - 1);
- return val;
- }
-
- /* Deposit register routine
-
- Inputs:
- flag = type of deposit (normal/interactive)
- sw = switches
- cptr = pointer to input string
- rptr = pointer to register descriptor
- Outputs:
- return = error status
- */
-
- int dep_reg (int flag, int sw, char *cptr, REG *rptr)
- {
- char gbuf[CBUFSIZE];
- unsigned int val, mask;
-
- if ((cptr == NULL) || (rptr == NULL)) return SCPE_ARG;
- if (rptr -> flags & REG_RO) return SCPE_RO;
- if (flag & EX_I) {
- cptr = read_line (gbuf, CBUFSIZE, stdin);
- if (cptr == NULL) return 1; /* force exit */
- if (*cptr == 0) return SCPE_OK; } /* success */
- errno = 0;
- mask = (1u << rptr -> width) - 1;
- if (get_unum (cptr, rptr -> radix, mask, &val) != SCPE_OK) return SCPE_ARG;
- if ((rptr -> flags & REG_NZ) && (val == 0)) return SCPE_ARG;
- put_rval (rptr, 0, val, mask);
- return SCPE_OK;
- }
-
- /* Put register value
-
- Inputs:
- rptr = pointer to register descriptor
- idx = index (RESTORE reg buffers only)
- val = new value
- mask = mask
- Outputs:
- none
- */
-
- void put_rval (REG *rptr, int idx, unsigned int val, unsigned int mask)
- {
- size_t sz;
- #define PUT_RVAL(sz,rp,id,val,msk) \
- *(((unsigned sz *) rp -> loc) + id) = \
- (*(((unsigned sz *) rp -> loc) + id) & \
- ~((msk) << (rp) -> offset)) | ((val) << (rp) -> offset)
-
- sz = SZ_R (rptr);
- if (sz == sizeof (char)) PUT_RVAL (char, rptr, idx, val, mask);
- else if (sz == sizeof (short)) PUT_RVAL (short, rptr, idx, val, mask);
- else if (sz == sizeof (int)) PUT_RVAL (int, rptr, idx, val, mask);
- else if (sz == sizeof (long)) PUT_RVAL (long, rptr, idx, val, mask);
- return;
- }
-
- /* Examine address routine
-
- Inputs:
- flag = type of ex/mod command (ex, iex, idep)
- sw = switches
- addr = address to examine
- dptr = pointer to device
- uptr = pointer to unit
- Outputs:
- return = if >= 0, error status
- if < 0, number of extra words retired
- */
-
- int ex_addr (int flag, int sw, unsigned int addr, DEVICE *dptr, UNIT *uptr)
- {
- unsigned int mask, loc;
- int i, j, reason;
- size_t sz;
-
- if (dptr == NULL) return SCPE_ARG;
- print_val (addr, dptr -> aradix, dptr -> awidth, PV_LEFT);
- printf (": ");
- if (!(flag & EX_E)) return SCPE_OK;
-
- mask = (1u << dptr -> dwidth) - 1;
- for (i = 0; i < sim_emax; i++) sim_eval[i] = 0;
- for (i = 0, j = addr; i < sim_emax; i++, j = j + dptr -> aincr) {
- if (dptr -> examine != NULL) {
- reason = dptr -> examine (&sim_eval[i], j, uptr, sw);
- if (reason != SCPE_OK) break; }
- else { if (!(uptr -> flags & UNIT_ATT)) return SCPE_UNATT;
- if ((uptr -> flags & UNIT_FIX) && (addr >= uptr -> capac)) {
- reason = SCPE_NXM;
- break; }
- sz = SZ_D (dptr);
- loc = j / dptr -> aincr;
- if (uptr -> flags & UNIT_BUF) {
- if (sz == sizeof (char)) sim_eval[i] =
- *(((unsigned char *) uptr -> filebuf) + loc);
- else if (sz == sizeof (short)) sim_eval[i] =
- *(((unsigned short *) uptr -> filebuf) + loc);
- else if (sz == sizeof (int)) sim_eval[i] =
- *(((unsigned int *) uptr -> filebuf) + loc);
- else if (sz == sizeof (long)) sim_eval[i] =
- *(((unsigned long *) uptr -> filebuf) + loc); }
- else { fseek (uptr -> fileref, sz * loc, SEEK_SET);
- fread (&sim_eval[i], sz, 1, uptr -> fileref);
- if ((feof (uptr -> fileref)) &&
- !(uptr -> flags & UNIT_FIX)) {
- reason = SCPE_EOF;
- break; }
- else if (ferror (uptr -> fileref)) {
- clearerr (uptr -> fileref);
- reason = SCPE_IOERR;
- break; } } }
- sim_eval[i] = sim_eval[i] & mask; }
- if ((reason != SCPE_OK) && (i == 0)) return reason;
-
- if ((reason = print_sym (addr, sim_eval, dptr == sim_devices[0], sw)) > 0)
- reason = print_val (sim_eval[0], dptr -> dradix, dptr -> dwidth, PV_RZRO);
- if (flag & EX_I) printf (" ");
- else printf ("\n");
- return reason;
- }
-
- /* Deposit address routine
-
- Inputs:
- flag = type of deposit (normal/interactive)
- sw = switches
- cptr = pointer to input string
- addr = address to examine
- dptr = pointer to device
- uptr = pointer to unit
- Outputs:
- return = if >= 0, error status
- if < 0, number of extra words retired
- */
-
- int dep_addr (int flag, int sw, char *cptr, unsigned int addr,
- DEVICE *dptr, UNIT *uptr)
- {
- unsigned int mask, loc;
- int i, j, count, r, reason;
- size_t sz;
- char *tptr, gbuf[CBUFSIZE];
-
- if (dptr == NULL) return SCPE_ARG;
- if (flag & EX_I) {
- cptr = read_line (gbuf, CBUFSIZE, stdin);
- if (cptr == NULL) return 1; /* force exit */
- if (*cptr == 0) return SCPE_OK; } /* success */
- mask = (1u << dptr -> dwidth) - 1;
-
- if ((reason = parse_sym (cptr, addr, dptr == sim_devices[0], sim_eval)) > 0) {
- if ((reason = get_unum (cptr, dptr -> dradix, mask, sim_eval)) != SCPE_OK)
- return reason; }
- count = 1 - reason;
-
- for (i = 0, j = addr; i < count; i++, j = j + dptr -> aincr) {
- sim_eval[i] = sim_eval[i] & mask;
- if (dptr -> deposit != NULL) {
- r = dptr -> deposit (sim_eval[i], j, uptr, sw);
- if (r != SCPE_OK) return r; }
- else { if (!(uptr -> flags & UNIT_ATT)) return SCPE_UNATT;
- if ((uptr -> flags & UNIT_FIX) && (j >= uptr -> capac))
- return SCPE_NXM;
- sz = SZ_D (dptr);
- loc = j / dptr -> aincr;
- if (uptr -> flags & UNIT_BUF) {
- if (sz == sizeof (char)) *(((unsigned char *)
- uptr -> filebuf) + loc) = sim_eval[i];
- else if (sz == sizeof (short)) *(((unsigned short *)
- uptr -> filebuf) + loc) = sim_eval[i];
- else if (sz == sizeof (int)) *(((unsigned int *)
- uptr -> filebuf) + loc) = sim_eval[i];
- else if (sz == sizeof (long)) *(((unsigned long *)
- uptr -> filebuf) + loc) = sim_eval[i];
- if (loc >= uptr -> hwmark) uptr -> hwmark = loc + 1; }
- else { fseek (uptr -> fileref, sz * loc, SEEK_SET);
- fwrite (sim_eval, sz, 1, uptr -> fileref);
- if (ferror (uptr -> fileref)) {
- clearerr (uptr -> fileref);
- return SCPE_IOERR; } } } }
- return reason;
- }
-
- /* String processing routines
-
- read_line read line
-
- Inputs:
- cptr = pointer to buffer
- size = maximum size
- stream = pointer to input stream
- Outputs:
- optr = pointer to first non-blank character
- NULL if EOF
- */
-
- char *read_line (char *cptr, int size, FILE *stream)
- {
- char *tptr;
-
- cptr = fgets (cptr, size, stream); /* get cmd line */
- if (cptr == NULL) return NULL; /* ignore EOF */
- for (tptr = cptr; tptr < (cptr + size); tptr++) /* remove cr */
- if (*tptr == '\n') *tptr = 0;
- while (isspace (*cptr)) cptr++; /* absorb spaces */
- return cptr;
- }
-
- /* get_glyph get next glyph
-
- Inputs:
- iptr = pointer to input string
- optr = pointer to output string
- mchar = optional end of glyph character
- Outputs
- result = pointer to next character in input string
- */
-
- char *get_glyph (char *iptr, char *optr, char mchar)
- {
- while ((isspace (*iptr) == 0) && (*iptr != 0) && (*iptr != mchar)) {
- if (islower (*iptr)) *optr = toupper (*iptr);
- else *optr = *iptr;
- iptr++; optr++; }
- *optr = 0;
- if (mchar && (*iptr == mchar)) iptr++; /* skip terminator */
- while (isspace (*iptr)) iptr++; /* absorb spaces */
- return iptr;
- }
-
- /* get_yn yes/no question
-
- Inputs:
- cptr = pointer to question
- deflt = default answer
- Outputs:
- result = true if yes, false if no
- */
-
- int get_yn (char *ques, int deflt)
- {
- char cbuf[CBUFSIZE], *cptr;
-
- printf ("%s ", ques);
- cptr = read_line (cbuf, CBUFSIZE, stdin);
- if ((cptr == NULL) || (*cptr == 0)) return deflt;
- if ((*cptr == 'Y') || (*cptr == 'y')) return TRUE;
- return FALSE;
- }
-
- /* get_unum unsigned number
-
- Inputs:
- cptr = pointer to input string
- radix = input radix
- max = maximum acceptable value
- val = pointer to output value
- Outputs:
- status = error status
- */
-
- int get_unum (char *cptr, int radix, unsigned int max, unsigned int *val)
- {
- char *tptr;
-
- errno = 0;
- *val = strtoul (cptr, &tptr, radix);
- if (errno || (cptr == tptr) || (*val > max) || (*tptr != 0)) return SCPE_ARG;
- return SCPE_OK;
- }
-
- /* Find_device find device matching input string
-
- Inputs:
- cptr = pointer to input string
- iptr = pointer to unit number (can be null)
- Outputs:
- result = pointer to device
- *iptr = unit number, if valid
- */
-
- DEVICE *find_device (char *cptr, int *iptr)
- {
- int i, lenn;
- unsigned int unitno;
- char *tptr;
- DEVICE *dptr;
-
- for (i = 0; (dptr = sim_devices[i]) != NULL; i++) {
- lenn = strlen (dptr -> name);
- if (strncmp (cptr, dptr -> name, lenn) != 0) continue;
- cptr = cptr + lenn;
- if (*cptr == 0) unitno = 0;
- else if (get_unum (cptr, 10, dptr -> numunits - 1, &unitno) != SCPE_OK)
- return NULL;
- if (iptr != NULL) *iptr = unitno;
- return sim_devices[i]; }
- return NULL;
- }
-
- /* Find_dev_from_unit find device for unit
-
- Inputs:
- uptr = pointer to unit
- Outputs:
- result = pointer to device
- */
-
- DEVICE *find_dev_from_unit (UNIT *uptr)
- {
- DEVICE *dptr;
- int i,j;
-
- for (i = 0; (dptr = sim_devices[i]) != NULL; i++) {
- for (j = 0; j < dptr -> numunits; j++) {
- if (uptr == (dptr -> units + j)) return dptr; } }
- return NULL;
- }
-
- /* find_reg find register matching input string
-
- Inputs:
- cptr = pointer to input string
- optr = pointer to output pointer (can be null)
- dptr = pointer to device
- Outputs:
- result = pointer to register, NULL if error
- *optr = pointer to next character in input string
- */
-
- REG *find_reg (char *cptr, char **optr, DEVICE *dptr)
- {
- char *tptr;
- REG *rptr;
-
- if ((cptr == NULL) || (dptr == NULL)) return NULL;
- if (dptr -> registers == NULL) return NULL;
- tptr = cptr;
- do { tptr++; } while (isalnum (*tptr) || (*tptr == '_'));
- for (rptr = dptr -> registers; rptr -> name != NULL; rptr++) {
- if (strncmp (cptr, rptr -> name, tptr - cptr) == 0) {
- if (optr != NULL) *optr = tptr;
- return rptr; } }
- return NULL;
- }
-
- /* get_switches get switches from input string
-
- Inputs:
- cptr = pointer to input string
- Outputs:
- sw = switch bit mask
- 0 if no switches, -1 if error
- */
-
- int get_switches (char *cptr)
- {
- int sw;
-
- if (*cptr != '-') return 0;
- sw = 0;
- for (cptr++; (isspace (*cptr) == 0) && (*cptr != 0); cptr++) {
- if (isalpha (*cptr) == 0) return -1;
- sw = sw | SWMASK (*cptr); }
- return sw;
- }
-
- /* General radix printing routine
-
- Inputs:
- stream = stream designator
- val = value to print
- radix = radix to print
- width = width to print
- format = leading zeroes format
- Outputs:
- status = error status
- */
-
- int fprint_val (FILE *stream, unsigned int val, int radix,
- int width, int format)
- {
- #define MAX_WIDTH (CHAR_BIT * sizeof (unsigned int))
- unsigned int mask, digit;
- int d, ndigits;
- double fptest;
- char dbuf[MAX_WIDTH + 1];
-
- for (d = 0; d < MAX_WIDTH; d++) dbuf[d] = (format == PV_RZRO)? '0': ' ';
- dbuf[MAX_WIDTH] = 0;
- d = MAX_WIDTH;
- do { d = d - 1;
- digit = val % (unsigned) radix;
- val = val / (unsigned) radix;
- dbuf[d] = (digit <= 9)? '0' + digit: 'A' + (digit - 10);
- } while ((d > 0) && (val != 0));
-
- if (format != PV_LEFT) {
- mask = (1u << width) - 1;
- fptest = (double) radix;
- ndigits = 1;
- while (fptest < (double) mask) {
- fptest = fptest * (double) radix;
- ndigits = ndigits + 1; }
- if (MAX_WIDTH - ndigits < d) d = MAX_WIDTH - ndigits; }
- if (fputs (&dbuf[d], stream) == EOF) return SCPE_IOERR;
- return SCPE_OK;
- }
-
- /* Event queue routines
-
- sim_activate add entry to event queue
- sim_cancel remove entry from event queue
- sim_process_event process entries on event queue
- sim_is_active see if entry is on event queue
- sim_atime return absolute time for an entry
- sim_gtime return global time
-
- Asynchronous events are set up by queueing a unit data structure
- to the event queue with a timeout (in simulator units, relative
- to the current time). Each simulator 'times' these events by
- counting down interval counter sim_interval. When this reaches
- zero the simulator calls sim_process_event to process the event
- and to see if further events need to be processed, or sim_interval
- reset to count the next one.
-
- The event queue is maintained in clock order; entry timeouts are
- RELATIVE to the time in the previous entry.
-
- Sim_process_event - process event
-
- Inputs:
- none
- Outputs:
- reason reason code returned by any event processor,
- or 0 (SCPE_OK) if no exceptions
- */
-
- int sim_process_event (void)
- {
- UNIT *uptr;
- int reason;
-
- if (stop_cpu) return SCPE_STOP; /* stop CPU? */
- if (sim_clock_queue == NULL) { /* queue empty? */
- UPDATE_SIM_TIME (noqueue_time); /* update sim time */
- sim_interval = noqueue_time = NOQUEUE_WAIT; /* flag queue empty */
- return SCPE_OK; }
- UPDATE_SIM_TIME (sim_clock_queue -> time); /* update sim time */
- do { uptr = sim_clock_queue; /* get first */
- sim_clock_queue = uptr -> next; /* remove first */
- uptr -> next = NULL; /* hygiene */
- uptr -> time = 0;
- if (sim_clock_queue != NULL) sim_interval = sim_clock_queue -> time;
- else sim_interval = noqueue_time = NOQUEUE_WAIT;
- if (uptr -> action != NULL) reason = uptr -> action (uptr);
- else reason = SCPE_OK;
- } while ((reason == SCPE_OK) && (sim_interval == 0));
-
- /* Empty queue forces sim_interval != 0 */
-
- return reason;
- } /* end sim_process */
-
- /* Activate (queue) event
-
- Inputs:
- uptr = pointer to unit
- event_time = relative timeout
- Outputs:
- reason = result (SCPE_OK if ok)
- */
-
- int sim_activate (UNIT *uptr, int event_time)
- {
- UNIT *cptr, *prvptr;
- int accum;
-
- if (event_time < 0) return SCPE_ARG;
- if (sim_is_active (uptr)) return SCPE_OK; /* already active? */
- if (sim_clock_queue == NULL) { UPDATE_SIM_TIME (noqueue_time); }
- else { UPDATE_SIM_TIME (sim_clock_queue -> time); } /* update sim time */
-
- prvptr = NULL;
- accum = 0;
- for (cptr = sim_clock_queue; cptr != NULL; cptr = cptr -> next) {
- if (event_time < accum + cptr -> time) break;
- accum = accum + cptr -> time;
- prvptr = cptr; }
- if (prvptr == NULL) { /* insert at head */
- cptr = uptr -> next = sim_clock_queue;
- sim_clock_queue = uptr; }
- else { cptr = uptr -> next = prvptr -> next; /* insert at prvptr */
- prvptr -> next = uptr; }
- uptr -> time = event_time - accum;
- if (cptr != NULL) cptr -> time = cptr -> time - uptr -> time;
- sim_interval = sim_clock_queue -> time;
- return SCPE_OK;
- }
-
- /* Cancel (dequeue) event
-
- Inputs:
- uptr = pointer to unit
- Outputs:
- reason = result (SCPE_OK if ok)
-
- */
-
- int sim_cancel (UNIT *uptr)
- {
- UNIT *cptr, *nptr;
-
- if (sim_clock_queue == NULL) return SCPE_OK;
- UPDATE_SIM_TIME (sim_clock_queue -> time); /* update sim time */
- nptr = NULL;
- if (sim_clock_queue == uptr) nptr = sim_clock_queue = uptr -> next;
- else { for (cptr = sim_clock_queue; cptr != NULL; cptr = cptr -> next) {
- if (cptr -> next == uptr) {
- nptr = cptr -> next = uptr -> next;
- break; } } } /* end queue scan */
- if (nptr != NULL) nptr -> time = nptr -> time + uptr -> time;
- uptr -> next = NULL; /* hygiene */
- uptr -> time = 0;
- if (sim_clock_queue != NULL) sim_interval = sim_clock_queue -> time;
- else sim_interval = noqueue_time = NOQUEUE_WAIT;
- return SCPE_OK;
- }
-
- /* Test for entry in queue, return activation time
-
- Inputs:
- uptr = pointer to unit
- Outputs:
- result = absolute activation time + 1, 0 if inactive
- */
-
- int sim_is_active (UNIT *uptr)
- {
- UNIT *cptr;
- int accum;
-
- accum = 0;
- for (cptr = sim_clock_queue; cptr != NULL; cptr = cptr -> next) {
- accum = accum + cptr -> time;
- if (cptr == uptr) return accum + 1; }
- return 0;
- }
-
- /* Return global time
-
- Inputs: none
- Outputs:
- time = global time
- */
-
- double sim_gtime (void)
- {
- if (sim_clock_queue == NULL) { UPDATE_SIM_TIME (noqueue_time); }
- else { UPDATE_SIM_TIME (sim_clock_queue -> time); }
- return sim_time;
- }
-