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:
parent
00afa58bc4
commit
0251c08d12
1 changed files with 115 additions and 9 deletions
|
@ -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 */
|
||||
|
|
Loading…
Add table
Reference in a new issue