pdp11_vh.c: - Added debugging support to trace register, interrupt

and data traffic (SET VH DEBUG[=REG;INT;XMT;RCV])
                 -  Added SET LOG and SET NOLOG support for logging mux
                    traffic
                 -  Fixed SET VH LINES=n to correctly adjust the number
                    of lines available to be 8, 16, 24, or 32.
                 -  Fixed performance issue avoiding redundant polling in unit
                    service routine (removed 75% of polling overhead)

pdp11_dz.c:      -  Added debugging support to trace register, interrupt
                    and data traffic (SET VH DEBUG[=REG;INT;XMT;RCV])
This commit is contained in:
Mark Pizzolato 2011-06-03 09:27:27 -07:00
parent 338ad5147b
commit 89a27e0816
2 changed files with 1173 additions and 1017 deletions

View file

@ -160,6 +160,20 @@ int32 dz_auto = 0; /* autodiscon enabled */
TMLN dz_ldsc[DZ_MUXES * DZ_LINES] = { 0 }; /* line descriptors */
TMXR dz_desc = { DZ_MUXES * DZ_LINES, 0, 0, dz_ldsc }; /* mux descriptor */
/* debugging bitmaps */
#define DBG_REG 0x0001 /* trace read/write registers */
#define DBG_INT 0x0002 /* display transfer requests */
#define DBG_XMT TMXR_DBG_XMT /* display Transmitted Data */
#define DBG_RCV TMXR_DBG_RCV /* display Received Data */
DEBTAB dz_debug[] = {
{"REG", DBG_REG},
{"INT", DBG_INT},
{"XMT", DBG_XMT},
{"RCV", DBG_RCV},
{0}
};
DEVICE dz_dev;
t_stat dz_rd (int32 *data, int32 PA, int32 access);
t_stat dz_wr (int32 data, int32 PA, int32 access);
@ -249,9 +263,16 @@ DEVICE dz_dev = {
1, DEV_RDX, 8, 1, DEV_RDX, 8,
&tmxr_ex, &tmxr_dep, &dz_reset,
NULL, &dz_attach, &dz_detach,
&dz_dib, DEV_FLTA | DEV_DISABLE | DEV_NET | DEV_UBUS | DEV_QBUS
&dz_dib, DEV_FLTA | DEV_DISABLE | DEV_NET | DEV_UBUS | DEV_QBUS | DEV_DEBUG,
0, dz_debug
};
/* Register names for Debug tracing */
static char *dz_rd_regs[] =
{"CSR ", "RBUF", "TCR ", "MSR " };
static char *dz_wr_regs[] =
{"CSR ", "LPR ", "TCR ", "TDR "};
/* IO dispatch routines, I/O addresses 177601x0 - 177601x7 */
t_stat dz_rd (int32 *data, int32 PA, int32 access)
@ -289,6 +310,8 @@ switch ((PA >> 1) & 03) { /* case on PA<2:1> */
break;
}
sim_debug(DBG_REG, &dz_dev, "dz_rd(PA=0x%08X [%s], access=%d, data=0x%X)\n", PA, dz_rd_regs[(PA >> 1) & 03], access, *data);
return SCPE_OK;
}
@ -298,6 +321,8 @@ int32 dz = ((PA - dz_dib.ba) >> 3) & DZ_MNOMASK; /* get mux num */
int32 i, c, line;
TMLN *lp;
sim_debug(DBG_REG, &dz_dev, "dz_wr(PA=0x%08X [%s], access=%d, data=0x%X)\n", PA, dz_wr_regs[(PA >> 1) & 03], access, data);
switch ((PA >> 1) & 03) { /* case on PA<2:1> */
case 00: /* CSR */
@ -517,6 +542,7 @@ int32 dz;
for (dz = 0; dz < DZ_MUXES; dz++) { /* find 1st mux */
if (dz_rxi & (1 << dz)) {
sim_debug(DBG_INT, &dz_dev, "dz_rzinta(dz=%d)\n", dz);
dz_clr_rxint (dz); /* clear intr */
return (dz_dib.vec + (dz * 010)); /* return vector */
}
@ -546,6 +572,7 @@ int32 dz;
for (dz = 0; dz < DZ_MUXES; dz++) { /* find 1st mux */
if (dz_txi & (1 << dz)) {
sim_debug(DBG_INT, &dz_dev, "dz_txinta(dz=%d)\n", dz);
dz_clr_txint (dz); /* clear intr */
return (dz_dib.vec + 4 + (dz * 010)); /* return vector */
}

View file

@ -26,6 +26,13 @@
vh DHQ11 asynch multiplexor for SIMH
02-Jun-11 MP Added debugging support to trace register, interrupt
and data traffic (SET VH DEBUG[=REG;INT;XMT;RCV])
Added SET LOG and SET NOLOG support for logging mux
traffic
Fixed SET VH LINES=n to correctly adjust the number
of lines available to be 8, 16, 24, or 32.
Fixed performance issue avoiding redundant polling
03-Jan-10 JAD Eliminate gcc warnings
19-Nov-08 RMS Revised for common TMXR show routines
18-Jun-07 RMS Added UNIT_IDLE flag
@ -82,7 +89,6 @@ extern int32 cpu_opt;
extern int32 tmxr_poll, clk_tps;
/* convert ms to SIMH time units based on tmxr_poll polls per second */
#define MS2SIMH(ms) (((ms) * clk_tps) / 1000)
extern FILE *sim_log;
#ifndef VH_MUXES
#define VH_MUXES (4)
@ -284,6 +290,20 @@ static TMLN vh_ldsc[VH_MUXES * VH_LINES] = { { 0 } };
static TMXR vh_desc = { VH_MUXES * VH_LINES, 0, 0, vh_ldsc };
static TMLX vh_parm[VH_MUXES * VH_LINES] = { { 0 } };
/* debugging bitmaps */
#define DBG_REG 0x0001 /* trace read/write registers */
#define DBG_INT 0x0002 /* display transfer requests */
#define DBG_XMT TMXR_DBG_XMT /* display Transmitted Data */
#define DBG_RCV TMXR_DBG_RCV /* display Received Data */
DEBTAB vh_debug[] = {
{"REG", DBG_REG},
{"INT", DBG_INT},
{"XMT", DBG_XMT},
{"RCV", DBG_RCV},
{0}
};
/* Forward references */
static t_stat vh_rd (int32 *data, int32 PA, int32 access);
static t_stat vh_wr (int32 data, int32 PA, int32 access);
@ -294,11 +314,15 @@ static t_stat vh_clear (int32 vh, t_bool flag);
static t_stat vh_reset (DEVICE *dptr);
static t_stat vh_attach (UNIT *uptr, char *cptr);
static t_stat vh_detach (UNIT *uptr);
static t_stat vh_show_debug (FILE *st, UNIT *uptr, int32 val, void *desc);
static t_stat vh_show_detail (FILE *st, UNIT *uptr, int32 val, void *desc);
static t_stat vh_show_rbuf (FILE *st, UNIT *uptr, int32 val, void *desc);
static t_stat vh_show_txq (FILE *st, UNIT *uptr, int32 val, void *desc);
static t_stat vh_putc (int32 vh, TMLX *lp, int32 chan, int32 data);
static void doDMA (int32 vh, int32 chan);
static t_stat vh_setnl (UNIT *uptr, int32 val, char *cptr, void *desc);
static t_stat vh_set_log (UNIT *uptr, int32 val, char *cptr, void *desc);
static t_stat vh_set_nolog (UNIT *uptr, int32 val, char *cptr, void *desc);
static t_stat vh_show_log (FILE *st, UNIT *uptr, int32 val, void *desc);
int32 tmxr_send_buffered_data (TMLN *lp);
@ -317,9 +341,6 @@ static DIB vh_dib = {
static UNIT vh_unit[VH_MUXES] = {
{ UDATA (&vh_svc, UNIT_IDLE|UNIT_ATTABLE, 0) },
{ UDATA (&vh_svc, UNIT_IDLE|UNIT_ATTABLE, 0) },
{ UDATA (&vh_svc, UNIT_IDLE|UNIT_ATTABLE, 0) },
{ UDATA (&vh_svc, UNIT_IDLE|UNIT_ATTABLE, 0) },
};
static const REG vh_reg[] = {
@ -344,23 +365,28 @@ static const MTAB vh_mod[] = {
&set_vec, &show_vec_mux, (void *) &vh_desc },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "AUTOCONFIGURE",
&set_addr_flt, NULL, NULL },
/* this one is dangerous, don't use yet */
{ MTAB_XTD|MTAB_VDV, 0, "LINES", "LINES",
NULL, &tmxr_show_lines, (void *) &vh_desc },
&vh_setnl, &tmxr_show_lines, (void *) &vh_desc },
{ UNIT_ATT, UNIT_ATT, "summary", NULL,
NULL, &tmxr_show_summ, (void *) &vh_desc },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL,
{ MTAB_XTD|MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL,
NULL, &tmxr_show_cstat, (void *) &vh_desc },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL,
{ MTAB_XTD|MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL,
NULL, &tmxr_show_cstat, (void *) &vh_desc },
{ MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT",
{ MTAB_XTD|MTAB_VDV, 1, NULL, "DISCONNECT",
&tmxr_dscln, NULL, &vh_desc },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "DEBUG", NULL,
NULL, &vh_show_debug, NULL },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "RBUF", NULL,
{ MTAB_XTD|MTAB_VDV | MTAB_NMO, 0, "DETAIL", NULL,
NULL, &vh_show_detail, NULL },
{ MTAB_XTD|MTAB_VDV | MTAB_NMO, 0, "RBUF", NULL,
NULL, &vh_show_rbuf, NULL },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "TXQ", NULL,
{ MTAB_XTD|MTAB_VDV | MTAB_NMO, 0, "TXQ", NULL,
NULL, &vh_show_txq, NULL },
{ MTAB_XTD|MTAB_VDV | MTAB_NC, 0, NULL, "LOG",
&vh_set_log, NULL, &vh_desc },
{ MTAB_XTD|MTAB_VDV | MTAB_NC, 0, NULL, "NOLOG",
&vh_set_nolog, NULL, &vh_desc },
{ MTAB_XTD|MTAB_VDV | MTAB_NMO, 0, "LOG", NULL,
NULL, &vh_show_log, &vh_desc },
{ 0 }
};
@ -381,10 +407,21 @@ DEVICE vh_dev = {
NULL, /* boot routine */
&vh_attach, /* attach routine */
&vh_detach, /* detach routine */
(void *)&vh_dib, /* context */
DEV_FLTA | DEV_DISABLE | DEV_DIS |DEV_NET | DEV_QBUS | DEV_UBUS, /* flags */
(void *)&vh_dib,/* context */
DEV_FLTA | DEV_DISABLE | DEV_DIS |DEV_NET | DEV_QBUS | DEV_UBUS | DEV_DEBUG, /* flags */
0, vh_debug
};
/* Register names for Debug tracing */
static char *vh_rd_dhv_regs[] =
{"CSR ", "RBUF ", "LPR ", "STAT ", "LNCTRL", "TBFAD1", "TBFAD2", "TBFCNT" };
static char *vh_wr_dhv_regs[] =
{"CSR ", "TXCHAR", "LPR ", "STAT ", "LNCTRL", "TBFAD1", "TBFAD2", "TBFCNT" };
static char *vh_rd_dhu_regs[] =
{"CSR ", "RBUF ", "LPR ", "FIFOSZ", "LNCTRL", "TBFAD1", "TBFAD2", "TBFCNT" };
static char *vh_wr_dhu_regs[] =
{"CSR ", "RXTIMR", "LPR ", "FIFODT", "LNCTRL", "TBFAD1", "TBFAD2", "TBFCNT" };
/* Interrupt routines */
static void vh_clr_rxint ( int32 vh )
@ -408,8 +445,9 @@ static int32 vh_rxinta (void)
{
int32 vh;
for (vh = 0; vh < VH_MUXES; vh++) {
for (vh = 0; vh < vh_desc.lines/VH_LINES; vh++) {
if (vh_rxi & (1 << vh)) {
sim_debug(DBG_INT, &vh_dev, "vh_rzinta(vh=%d)\n", vh);
vh_clr_rxint (vh);
return (vh_dib.vec + (vh * 010));
}
@ -438,8 +476,9 @@ static int32 vh_txinta (void)
{
int32 vh;
for (vh = 0; vh < VH_MUXES; vh++) {
for (vh = 0; vh < vh_desc.lines/VH_LINES; vh++) {
if (vh_txi & (1 << vh)) {
sim_debug(DBG_INT, &vh_dev, "vh_txinta(vh=%d)\n", vh);
vh_clr_txint (vh);
return (vh_dib.vec + 4 + (vh * 010));
}
@ -772,6 +811,10 @@ fprintf (stderr, "\rtqln %d\n", 64 - tmxr_tqln (lp->tmln));
/* can't happen */
break;
}
sim_debug(DBG_REG, &vh_dev, "vh_rd(PA=0x%08X [%s], access=%d, data=0x%X)\n", PA,
((vh_unit[vh].flags & UNIT_MODEDHU) ? vh_rd_dhu_regs : vh_rd_dhv_regs)[(PA >> 1) & 07], access, data);
return (SCPE_OK);
}
@ -782,6 +825,9 @@ static t_stat vh_wr ( int32 data,
int32 vh = ((PA - vh_dib.ba) >> 4) & VH_MNOMASK, line;
TMLX *lp;
sim_debug(DBG_REG, &vh_dev, "vh_wr(PA=0x%08X [%s], access=%d, data=0x%X)\n", PA,
((vh_unit[vh].flags & UNIT_MODEDHU) ? vh_wr_dhu_regs : vh_wr_dhv_regs)[(PA >> 1) & 07], access, data);
switch ((PA >> 1) & 7) {
case 0: /* CSR, but no read-modify-write */
if (access == WRITEB)
@ -791,6 +837,7 @@ static t_stat vh_wr ( int32 data,
if (data & CSR_MASTER_RESET) {
if ((vh_unit[vh].flags & UNIT_MODEDHU) && (data & CSR_SKIP))
data &= ~CSR_MASTER_RESET;
if (vh == 0) /* Only start unit service on the first unit. Units are polled there */
sim_activate (&vh_unit[vh], clk_cosched (tmxr_poll));
/* vh_mcount[vh] = 72; */ /* 1.2 seconds */
vh_mcount[vh] = MS2SIMH (1200); /* 1.2 seconds */
@ -1083,7 +1130,7 @@ static t_stat vh_svc ( UNIT *uptr )
int32 vh, newln, i;
/* scan all muxes for countdown reset */
for (vh = 0; vh < VH_MUXES; vh++) {
for (vh = 0; vh < vh_desc.lines/VH_LINES; vh++) {
if (vh_csr[vh] & CSR_MASTER_RESET) {
if (vh_mcount[vh] != 0)
vh_mcount[vh] -= 1;
@ -1109,17 +1156,17 @@ static t_stat vh_svc ( UNIT *uptr )
/* BUG: should check for overflow above */
}
/* scan all muxes, lines for DMA to complete; start every 3.12ms */
for (vh = 0; vh < VH_MUXES; vh++) {
for (vh = 0; vh < vh_desc.lines/VH_LINES; vh++) {
for (i = 0; i < VH_LINES; i++)
doDMA (vh, i);
}
/* interrupt driven in a real DHQ */
tmxr_poll_rx (&vh_desc);
for (vh = 0; vh < VH_MUXES; vh++)
for (vh = 0; vh < vh_desc.lines/VH_LINES; vh++)
vh_getc (vh);
tmxr_poll_tx (&vh_desc);
/* scan all DHU-mode muxes for RX FIFO timeout */
for (vh = 0; vh < VH_MUXES; vh++) {
for (vh = 0; vh < vh_desc.lines/VH_LINES; vh++) {
if (vh_unit[vh].flags & UNIT_MODEDHU) {
if (vh_timeo[vh] && (vh_csr[vh] & CSR_RXIE)) {
vh_timeo[vh] -= 1;
@ -1234,9 +1281,9 @@ static t_stat vh_reset ( DEVICE *dptr )
{
int32 i;
for (i = 0; i < (VH_MUXES * VH_LINES); i++)
for (i = 0; i < vh_desc.lines; i++)
vh_parm[i].tmln = &vh_ldsc[i];
for (i = 0; i < VH_MUXES; i++) {
for (i = 0; i < vh_desc.lines/VH_LINES; i++) {
#if defined (VM_PDP11)
/* if Unibus, force DHU mode */
if (UNIBUS)
@ -1247,9 +1294,8 @@ static t_stat vh_reset ( DEVICE *dptr )
vh_rxi = vh_txi = 0;
CLR_INT (VHRX);
CLR_INT (VHTX);
for (i = 0; i < VH_MUXES; i++)
sim_cancel (&vh_unit[i]);
return (auto_config (dptr->name, (dptr->flags & DEV_DIS) ? 0 : VH_MUXES));
sim_cancel (&vh_unit[0]);
return (auto_config (dptr->name, (dptr->flags & DEV_DIS) ? 0 : vh_desc.lines/VH_LINES));
}
@ -1266,7 +1312,7 @@ static t_stat vh_detach ( UNIT *uptr )
return (tmxr_detach (&vh_desc, uptr));
}
static void debug_line ( FILE *st,
static void vh_detail_line ( FILE *st,
int32 vh,
int32 chan )
{
@ -1283,7 +1329,7 @@ static void debug_line ( FILE *st,
lp->tmln->rcve, lp->tmln->xmte);
}
static t_stat vh_show_debug ( FILE *st,
static t_stat vh_show_detail ( FILE *st,
UNIT *uptr,
int32 val,
void *desc )
@ -1291,14 +1337,14 @@ static t_stat vh_show_debug ( FILE *st,
int32 i, j;
fprintf (st, "VH:\trxi %d, txi %d\n", vh_rxi, vh_txi);
for (i = 0; i < VH_MUXES; i++) {
for (i = 0; i < vh_desc.lines/VH_LINES; i++) {
fprintf (st, "VH%d:\tmode %s, crit %d\n", i,
vh_unit[i].flags & UNIT_MODEDHU ? "DHU" : "DHV",
vh_crit & (1 << i));
fprintf (st, "\tCSR %06o, mcount %d, rbuf_idx %d, txq_idx %d\n",
vh_csr[i], vh_mcount[i], rbuf_idx[i], txq_idx[i]);
for (j = 0; j < VH_LINES; j++)
debug_line (st, i, j);
vh_detail_line (st, i, j);
}
return (SCPE_OK);
}
@ -1327,3 +1373,86 @@ static t_stat vh_show_txq ( FILE *st,
return (SCPE_OK);
}
/* SET LINES processor */
static t_stat vh_setnl (UNIT *uptr, int32 val, char *cptr, void *desc)
{
int32 newln, i, t, ndev;
t_stat r;
if (cptr == NULL)
return SCPE_ARG;
newln = (int32) get_uint (cptr, 10, (VH_MUXES * VH_LINES), &r);
if ((r != SCPE_OK) || (newln == vh_desc.lines))
return r;
if ((newln == 0) || (newln % VH_LINES))
return SCPE_ARG;
if (newln < vh_desc.lines) {
for (i = newln, t = 0; i < vh_desc.lines; i++)
t = t | vh_ldsc[i].conn;
if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE))
return SCPE_OK;
for (i = newln; i < vh_desc.lines; i++) {
if (vh_ldsc[i].conn) {
tmxr_linemsg (&vh_ldsc[i], "\r\nOperator disconnected line\r\n");
tmxr_reset_ln (&vh_ldsc[i]); /* reset line */
}
if ((i % VH_LINES) == (VH_LINES - 1))
vh_clear (i / VH_LINES, TRUE); /* reset mux */
}
}
vh_dib.lnt = (newln / VH_LINES) * IOLN_VH; /* set length */
vh_desc.lines = newln;
ndev = ((vh_dev.flags & DEV_DIS)? 0: (vh_desc.lines / VH_LINES));
vh_dev.numunits = (newln / VH_LINES);
return auto_config (vh_dev.name, ndev); /* auto config */
}
/* SET LOG processor */
static t_stat vh_set_log (UNIT *uptr, int32 val, char *cptr, void *desc)
{
char *tptr;
t_stat r;
int32 ln;
if (cptr == NULL)
return SCPE_ARG;
tptr = strchr (cptr, '=');
if ((tptr == NULL) || (*tptr == 0))
return SCPE_ARG;
*tptr++ = 0;
ln = (int32) get_uint (cptr, 10, (VH_MUXES * VH_LINES), &r);
if ((r != SCPE_OK) || (ln >= vh_desc.lines))
return SCPE_ARG;
return tmxr_set_log (NULL, ln, tptr, desc);
}
/* SET NOLOG processor */
static t_stat vh_set_nolog (UNIT *uptr, int32 val, char *cptr, void *desc)
{
t_stat r;
int32 ln;
if (cptr == NULL)
return SCPE_ARG;
ln = (int32) get_uint (cptr, 10, (VH_MUXES * VH_LINES), &r);
if ((r != SCPE_OK) || (ln >= vh_desc.lines))
return SCPE_ARG;
return tmxr_set_nolog (NULL, ln, NULL, desc);
}
/* SHOW LOG processor */
static t_stat vh_show_log (FILE *st, UNIT *uptr, int32 val, void *desc)
{
int32 i;
for (i = 0; i < vh_desc.lines; i++) {
fprintf (st, "line %d: ", i);
tmxr_show_log (st, NULL, i, desc);
fprintf (st, "\n");
}
return SCPE_OK;
}