I620: Provide optional rate limited I/O for TTY, PTR & ptp

Default behavior is to schedule the inter character I/O based on the
TIME (PTP, PTR) and TTIME (TTY) register variables.  With default values
here I/O completes very quickly.

A user may influence I/O rate behavior to proceed at a particular character
rate per second by using:

    sim> SET CPU CPS=nnn

or equivalently:

    sim> SET CPS=nnn

The resulting I/O completion rate will be independent of host system
processor speed and/or any I/O throttling that may be in effect.  The
above commands set the deferred I/O character completion rate for
all devices that do deferred I/O (PTP, PTR and TTY).

Each deferred I/O device can have its particular character delivery rates
specified with one of these commands:

    sim> deposit PTP CPS xxx
    sim> deposit PTR CPS yyy
    sim> deposit TTY CPS zzz

A CPS register value of 0 indicates that the default cycle based delays
specified by TIME (PTP & PTR) and TTIME (TTY) registers will control
character completion rates.
This commit is contained in:
Mark Pizzolato 2017-06-14 15:44:47 -07:00
parent cb47ea3852
commit 0c4bf36e1e
4 changed files with 16 additions and 11 deletions

View file

@ -2170,7 +2170,7 @@ cpuio_inp = 1;
cpuio_opc = op; cpuio_opc = op;
cpuio_cnt = 0; cpuio_cnt = 0;
if (uptr != NULL) if (uptr != NULL)
sim_activate_after_abs (uptr, 1000000/uptr->wait); DEFIO_ACTIVATE_ABS (uptr);
return SCPE_OK; return SCPE_OK;
} }

View file

@ -240,7 +240,9 @@ enum opcodes {
#define DEV_DEFIO (1 << (DEV_V_UF + 0)) #define DEV_DEFIO (1 << (DEV_V_UF + 0))
#define DEFIO_CPS 50 /* Default Characters per Second */ #define DEFIO_CPS u4 /* Default Characters per Second field */
#define DEFIO_ACTIVATE(uptr) ((uptr)->DEFIO_CPS) ? sim_activate_after (uptr, 1000000/(uptr)->DEFIO_CPS) : sim_activate (uptr, (uptr)->wait)
#define DEFIO_ACTIVATE_ABS(uptr) ((uptr)->DEFIO_CPS) ? sim_activate_after_abs (uptr, 1000000/(uptr)->DEFIO_CPS) : sim_activate_abs (uptr, (uptr)->wait)
/* Function declarations */ /* Function declarations */

View file

@ -74,13 +74,14 @@ t_stat ptp_num (void);
*/ */
UNIT ptr_unit = { UNIT ptr_unit = {
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), DEFIO_CPS UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), SERIAL_OUT_WAIT
}; };
REG ptr_reg[] = { REG ptr_reg[] = {
{ FLDATA (BIN, ptr_mode, 0) }, { FLDATA (BIN, ptr_mode, 0) },
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT }, { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (CPS, ptr_unit.wait, 24), PV_LEFT }, { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
{ DRDATA (CPS, ptr_unit.DEFIO_CPS, 24), PV_LEFT },
{ NULL } { NULL }
}; };
@ -100,13 +101,14 @@ DEVICE ptr_dev = {
*/ */
UNIT ptp_unit = { UNIT ptp_unit = {
UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), DEFIO_CPS UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT
}; };
REG ptp_reg[] = { REG ptp_reg[] = {
{ FLDATA (BIN, ptp_mode, 0) }, { FLDATA (BIN, ptp_mode, 0) },
{ DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (CPS, ptp_unit.wait, 24), PV_LEFT }, { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },
{ DRDATA (CPS, ptr_unit.DEFIO_CPS, 24), PV_LEFT },
{ NULL } { NULL }
}; };
@ -268,7 +270,7 @@ if (cpuio_cnt >= MEMSIZE) { /* over the limit? */
cpuio_clr_inp (uptr); /* done */ cpuio_clr_inp (uptr); /* done */
return STOP_RWRAP; return STOP_RWRAP;
} }
sim_activate_after (uptr, 1000000/uptr->wait); /* sched another xfer */ DEFIO_ACTIVATE (uptr); /* sched another xfer */
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
return SCPE_UNATT; return SCPE_UNATT;
@ -425,7 +427,7 @@ if ((cpuio_opc != OP_DN) && (cpuio_cnt >= MEMSIZE)) { /* wrap, ~dump? */
cpuio_clr_inp (uptr); /* done */ cpuio_clr_inp (uptr); /* done */
return STOP_RWRAP; return STOP_RWRAP;
} }
sim_activate_after (uptr, 1000000/uptr->wait); /* sched another xfer */ DEFIO_ACTIVATE (uptr); /* sched another xfer */
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
return SCPE_UNATT; return SCPE_UNATT;

View file

@ -90,7 +90,7 @@ t_stat tty_set_12digit (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
*/ */
UNIT tty_unit[] = { UNIT tty_unit[] = {
{ UDATA (&tto_svc, 0, 0), DEFIO_CPS }, { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT },
{ UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT } { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT }
}; };
@ -99,7 +99,8 @@ REG tty_reg[] = {
{ FLDATA (FLAG, tti_flag, 0), REG_HRO }, { FLDATA (FLAG, tti_flag, 0), REG_HRO },
{ DRDATA (COL, tto_col, 7) }, { DRDATA (COL, tto_col, 7) },
{ DRDATA (KTIME, tty_unit[UTTI].wait, 24), REG_NZ + PV_LEFT }, { DRDATA (KTIME, tty_unit[UTTI].wait, 24), REG_NZ + PV_LEFT },
{ DRDATA (CPS, tty_unit[UTTO].wait, 24), REG_NZ + PV_LEFT }, { DRDATA (TTIME, tty_unit[UTTO].wait, 24), REG_NZ + PV_LEFT },
{ DRDATA (CPS, tty_unit[UTTO].DEFIO_CPS, 24), REG_NZ + PV_LEFT },
{ NULL } { NULL }
}; };
@ -389,7 +390,7 @@ if ((cpuio_opc != OP_DN) && (cpuio_cnt >= MEMSIZE)) { /* wrap, ~dump? */
cpuio_clr_inp (uptr); /* done */ cpuio_clr_inp (uptr); /* done */
return STOP_RWRAP; return STOP_RWRAP;
} }
sim_activate_after (uptr, 1000000/uptr->wait); /* sched another xfer */ DEFIO_ACTIVATE (uptr); /* sched another xfer */
switch (cpuio_opc) { /* decode op */ switch (cpuio_opc) { /* decode op */