PDP11/VAX: Detect vector conflicts, SHOW IOSPACE and SHOW DEVICE improvements

From Timothe Litt:
  - Detect vector conflicts, SHOW IOSPACE
  - Detect conflicting vector assignments.
  - Correct show iospace display of high vector for multi-unit devices
  - Display vectors in DEV_RDX in show iospace
  - Ignore disabled devices when searching for conflict.
  - Improve device conflict reporting, Report both devices when address conflict is detected.

From Mark Pizzolato:
  - Added optional alternate radix output display for device address and vector values
    displayed by SHOW DEVICE.
    -H and -O switches select hex or octal output in addition to the default radix displayed
    by the normal simulator.
This commit is contained in:
Mark Pizzolato 2013-11-22 07:03:15 -08:00
parent 00afa58bc4
commit 0251c08d12

View file

@ -107,6 +107,7 @@ t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc)
{
DEVICE *dptr;
DIB *dibp;
uint32 radix = DEV_RDX;
if (uptr == NULL)
return SCPE_IERR;
@ -116,11 +117,25 @@ if (dptr == NULL)
dibp = (DIB *) dptr->ctxt;
if ((dibp == NULL) || (dibp->ba <= IOPAGEBASE))
return SCPE_IERR;
if (sim_switches & SWMASK ('H'))
radix = 16;
if (sim_switches & SWMASK ('O'))
radix = 8;
fprintf (st, "address=");
fprint_val (st, (t_value) dibp->ba, DEV_RDX, 32, PV_LEFT);
if (radix != DEV_RDX) {
fprintf (st, "(");
fprint_val (st, (t_value) dibp->ba, radix, 32, PV_LEFT);
fprintf (st, ")");
}
if (dibp->lnt > 1) {
fprintf (st, "-");
fprint_val (st, (t_value) dibp->ba + dibp->lnt - 1, DEV_RDX, 32, PV_LEFT);
if (radix != DEV_RDX) {
fprintf (st, "(");
fprint_val (st, (t_value) dibp->ba + dibp->lnt - 1, radix, 32, PV_LEFT);
fprintf (st, ")");
}
}
if (dibp->ba < IOPAGEBASE + AUTO_CSRBASE + AUTO_CSRMAX)
fprintf (st, "*");
@ -178,7 +193,7 @@ t_stat show_vec (FILE *st, UNIT *uptr, int32 arg, void *desc)
{
DEVICE *dptr;
DIB *dibp;
uint32 vec, numvec;
uint32 vec, numvec, radix = DEV_RDX;
if (uptr == NULL)
return SCPE_IERR;
@ -188,6 +203,10 @@ if (dptr == NULL)
dibp = (DIB *) dptr->ctxt;
if (dibp == NULL)
return SCPE_IERR;
if (sim_switches & SWMASK ('H'))
radix = 16;
if (sim_switches & SWMASK ('O'))
radix = 8;
vec = dibp->vec;
if (arg)
numvec = arg;
@ -197,9 +216,19 @@ if (vec == 0)
else {
fprintf (st, "vector=");
fprint_val (st, (t_value) vec, DEV_RDX, 16, PV_LEFT);
if (radix != DEV_RDX) {
fprintf (st, "(");
fprint_val (st, (t_value) vec, radix, 16, PV_LEFT);
fprintf (st, ")");
}
if (numvec > 1) {
fprintf (st, "-");
fprint_val (st, (t_value) vec + (4 * (numvec - 1)), DEV_RDX, 16, PV_LEFT);
if (radix != DEV_RDX) {
fprintf (st, "(");
fprint_val (st, (t_value) vec + (4 * (numvec - 1)), radix, 16, PV_LEFT);
fprintf (st, ")");
}
}
}
if (vec >= VEC_Q + AUTO_VECBASE)
@ -242,12 +271,58 @@ return;
t_stat build_ubus_tab (DEVICE *dptr, DIB *dibp)
{
int32 i, idx, vec, ilvl, ibit;
int32 i, idx, vec, hivec, ilvl, ibit;
DEVICE *cdptr;
size_t j;
char *cdname;
if ((dptr == NULL) || (dibp == NULL)) /* validate args */
return SCPE_IERR;
if (dibp->vnum > VEC_DEVMAX)
return SCPE_IERR;
vec = dibp->vec;
/* hivec & cdhivec are first vector AFTER device */
hivec = vec + (dibp->vnum * 4 * (dibp->ulnt? dibp->lnt/dibp->ulnt:
(dptr->numunits? dptr->numunits: 1)));
/* Check for vector conflict with any other enabled device.
* Skip vector checks if device (currently) doesn't have a vector assigned.
* Also skip if power-up reset to allow for auto-configure.
*/
if (vec && !(sim_switches & SWMASK ('P'))) {
for (j = 0; vec && (cdptr = sim_devices[j]) != NULL; j++) {
DIB *cdibp = (DIB *)(cdptr->ctxt);
int32 cdvec, cdhivec;
if (!cdibp || (cdptr->flags & DEV_DIS)) {
continue;
}
cdvec = cdibp->vec;
cdhivec = cdvec + (cdibp->vnum * 4 *
(cdibp->ulnt? cdibp->lnt/cdibp->ulnt:
(cdptr->numunits? cdptr->numunits: 1)));
if (cdptr == dptr || !cdvec || !dibp->vnum) {
continue;
}
if (hivec <= cdvec || vec >= cdhivec) {
continue;
}
cdname = cdptr? sim_dname(cdptr): NULL;
if (!cdname) {
cdname = "CPU";
}
printf ("Device %s interrupt vector conflict with %s at ",
sim_dname (dptr), cdname);
fprint_val (stdout, (t_value) dibp->vec, DEV_RDX, 32, PV_LEFT);
printf ("\n");
if (sim_log) {
fprintf (sim_log, "Device %s interrupt vector conflict with %s at ",
sim_dname (dptr), cdname);
fprint_val (sim_log, (t_value) dibp->vec, DEV_RDX, 32, PV_LEFT);
fprintf (sim_log, "\n");
}
return SCPE_STOP;
}
}
/* Interrupt slot assignment and conflict check. */
for (i = 0; i < dibp->vnum; i++) { /* loop thru vec */
idx = dibp->vloc + i; /* vector index */
vec = dibp->vec? (dibp->vec + (i * 4)): 0; /* vector addr */
@ -269,17 +344,39 @@ for (i = 0; i < dibp->vnum; i++) { /* loop thru vec */
else if (vec)
int_vec[ilvl][ibit] = vec;
}
/* Register I/O space address and check for conflicts */
for (i = 0; i < (int32) dibp->lnt; i = i + 2) { /* create entries */
idx = ((dibp->ba + i) & IOPAGEMASK) >> 1; /* index into disp */
if ((iodispR[idx] && dibp->rd && /* conflict? */
(iodispR[idx] != dibp->rd)) ||
(iodispW[idx] && dibp->wr &&
(iodispW[idx] != dibp->wr))) {
printf ("Device %s address conflict at \n", sim_dname (dptr));
for (j = 0; (cdptr = sim_devices[j]) != NULL; j++) { /* Find conflicting device */
DIB *cdibp = (DIB *)(cdptr->ctxt);
if ((cdptr->flags & DEV_DIS) || !cdibp || cdibp == dibp) {
continue;
}
if ((iodispR[idx] && dibp->rd &&
(iodispR[idx] != dibp->rd) &&
(cdibp->rd == iodispR[idx])) ||
(iodispW[idx] && dibp->wr &&
(iodispW[idx] != dibp->wr) &&
(cdibp->wr == iodispW[idx]))) {
break;
}
}
cdname = cdptr? sim_dname(cdptr): NULL;
if (!cdname) {
cdname = "CPU";
}
printf ("Device %s address conflict with %s at ", sim_dname (dptr), cdname);
fprint_val (stdout, (t_value) dibp->ba, DEV_RDX, 32, PV_LEFT);
printf ("\n");
if (sim_log) {
fprintf (sim_log, "Device %s address conflict at \n", sim_dname (dptr));
fprintf (sim_log, "Device %s address conflict with %s at ", sim_dname (dptr),
cdname);
fprint_val (sim_log, (t_value) dibp->ba, DEV_RDX, 32, PV_LEFT);
fprintf (sim_log, "\n");
}
return SCPE_STOP;
}
@ -304,6 +401,12 @@ int32 maxvec, vecwid;
int32 brbase = 0;
char valbuf[40];
#if defined DEV_RDX && DEV_RDX == 16
#define VEC_FMT "X"
#else
#define VEC_FMT "o"
#endif
if (build_dib_tab ()) /* build IO page */
return SCPE_OK;
@ -339,7 +442,7 @@ for (i = 0, dibp = NULL; i < (IOPAGESIZE >> 1); i++) { /* loop thru entries */
} /* end if */
} /* end for i */
maxaddr = fprint_val (NULL, (t_value) dibp->ba, DEV_RDX, 32, PV_LEFT);
sprintf (valbuf, "%03o", maxvec);
sprintf (valbuf, "%03" VEC_FMT, maxvec);
vecwid = maxvec = (int32) strlen (valbuf);
if (vecwid < 3)
vecwid = 3;
@ -402,9 +505,11 @@ for (i = 0, dibp = NULL; i < (IOPAGESIZE >> 1); i++) { /* loop thru entries */
if (dibp->vec == 0)
fprintf (st, "%*s", ((vecwid*2)+1+1), " ");
else {
fprintf (st, "%0*o", vecwid, dibp->vec);
fprintf (st, "%0*" VEC_FMT, vecwid, dibp->vec);
if (dibp->vnum > 1)
fprintf (st, "-%0*o", vecwid, dibp->vec + (4 * (dibp->vnum - 1)));
fprintf (st, "-%0*" VEC_FMT, vecwid, dibp->vec + (4 *
(dibp->ulnt? dibp->lnt/dibp->ulnt:
(dptr? dptr->numunits: 1)) * dibp->vnum) - 4);
else
fprintf (st, " %*s", vecwid, " ");
fprintf (st, "%1s", (dibp->vnum >= AUTO_VECBASE)? "*": " ");
@ -419,6 +524,7 @@ for (i = 0, dibp = NULL; i < (IOPAGESIZE >> 1); i++) { /* loop thru entries */
} /* end if */
} /* end for i */
return SCPE_OK;
#undef VEC_FMT
}
/* Autoconfiguration
@ -544,10 +650,10 @@ AUTO_CON auto_tab[] = {/*c #v am vm fxa fxv */
{ { NULL }, 1, 3, 0, 8,
{015000, 015040, 015100, 015140, }}, /* DV11 */
{ { NULL }, 1, 2, 8, 8 }, /* LK11A */
{ { "DMC0", "DMC1", "DMC2", "DMC3" },
{ { "DMC" },
1, 2, 8, 8 }, /* DMC11 */
{ { "DZ" }, 1, 2, 8, 8 }, /* DZ11 */
{ { "KMC" }, 1, 2, 8, 8 }, /* KMC11 */
{ { "KDP" }, 1, 2, 8, 8 }, /* KMC11 */
{ { NULL }, 1, 2, 8, 8 }, /* LPP11 */
{ { NULL }, 1, 2, 8, 8 }, /* VMV21 */
{ { NULL }, 1, 2, 16, 8 }, /* VMV31 */