Corrected one array overrun error caused by using the command

"drc printrules".  Implemented a new "drc" command option called
"drc ignore", which can be used to suppress reporting of specific
rules, for both "drc why" and "drc find".  This can help with
finding an error buried among a large number of other errors.
This commit is contained in:
Tim Edwards 2023-06-26 20:47:37 -04:00
parent ca985edbd0
commit 60a378842f
6 changed files with 164 additions and 56 deletions

View File

@ -1 +1 @@
8.3.406
8.3.407

View File

@ -3907,14 +3907,15 @@ cmdDownEnumFunc(selUse, use, transform, area)
#define EUCLIDEAN 7
#define FIND 8
#define DRC_HELP 9
#define DRC_OFF 10
#define DRC_ON 11
#define DRC_STATUS 12
#define DRC_STYLE 13
#define PRINTRULES 14
#define RULESTATS 15
#define STATISTICS 16
#define WHY 17
#define DRC_IGNORE 10
#define DRC_OFF 11
#define DRC_ON 12
#define DRC_STATUS 13
#define DRC_STYLE 14
#define PRINTRULES 15
#define RULESTATS 16
#define STATISTICS 17
#define WHY 18
void
CmdDrc(w, cmd)
@ -3934,6 +3935,7 @@ CmdDrc(w, cmd)
bool incremental;
bool doforall = FALSE;
bool dolist = FALSE;
int drc_start;
int count_total;
DRCCountList *dcl;
int argc = cmd->tx_argc;
@ -3954,6 +3956,7 @@ CmdDrc(w, cmd)
"euclidean on|off enable/disable Euclidean geometry checking",
"find [nth] locate next (or nth) error in the layout",
"help print this help information",
"ignore [<text>|none] do not report on rules with this text",
"off turn off background checker",
"on reenable background checker",
"status report if the drc checker is on or off",
@ -4000,12 +4003,12 @@ CmdDrc(w, cmd)
if ((argc > 2) && (option != PRINTRULES) && (option != FIND)
&& (option != SHOWINT) && (option != DRC_HELP) && (option != EUCLIDEAN)
&& (option != DRC_STEPSIZE) && (option != DRC_HALO) && (option != COUNT)
&& (option != DRC_STYLE))
&& (option != DRC_STYLE) && (option != DRC_IGNORE))
{
badusage:
TxError("Wrong arguments in \"drc %s\" command:\n", argv[1]);
TxError(" :drc %s\n", cmdDrcOption[option]);
TxError("Try \":drc help\" for more help.\n");
TxError(" drc %s\n", cmdDrcOption[option]);
TxError("Try \"drc help\" for more help.\n");
return;
}
}
@ -4173,39 +4176,61 @@ CmdDrc(w, cmd)
drc_nth++;
}
result = DRCFind(rootUse, &rootArea, &area, drc_nth);
if (incremental && (result < 0))
drc_start = -1;
while (TRUE)
{
/* 2nd pass, if we exceeded the total number of errors */
drc_nth = 1;
result = DRCFind(rootUse, &rootArea, &area, drc_nth);
}
/* May need to loop multiple times if some error types
* are being ignored.
*/
if (result > 0)
{
ToolMoveBox(TOOL_BL, &area.r_ll, FALSE, rootDef);
ToolMoveCorner(TOOL_TR, &area.r_ur, FALSE, rootDef);
result = DRCFind(rootUse, &rootArea, &area, drc_nth);
if (incremental && (result < 0))
{
/* 2nd pass, if we exceeded the total number of errors */
drc_nth = 1;
result = DRCFind(rootUse, &rootArea, &area, drc_nth);
}
/* If looping on an incremental DRC error search, and errors
* are being ignored, and there are no non-ignored errors in
* the search area, then quit if we have looped back around
* to the starting point.
*/
if ((drc_start > 0) && (result == drc_start))
break;
if (result > 0)
{
ToolMoveBox(TOOL_BL, &area.r_ll, FALSE, rootDef);
ToolMoveCorner(TOOL_TR, &area.r_ur, FALSE, rootDef);
#ifdef MAGIC_WRAPPER
if (!dolist)
if (!dolist)
#endif
TxPrintf("Error area #%d:\n", result);
DRCWhy(dolist, rootUse, &area);
}
else if (result < 0)
{
TxPrintf("Error area #%d:\n", result);
if (DRCWhy(dolist, rootUse, &area)) break;
drc_nth++;
}
else if (result < 0)
{
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(-1));
if (!dolist)
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(-1));
if (!dolist)
#endif
TxPrintf("There aren't that many errors");
}
else
{
TxPrintf("There aren't that many errors");
break;
}
else
{
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(0));
if (!dolist)
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(0));
if (!dolist)
#endif
TxPrintf("There are no errors in %s.\n", rootDef->cd_name);
TxPrintf("There are no errors in %s.\n", rootDef->cd_name);
break;
}
if (drc_start < 0)
drc_start = result;
}
break;
@ -4262,6 +4287,54 @@ CmdDrc(w, cmd)
}
break;
case DRC_IGNORE:
/* Ignore rules containing the given text, unless the text is "none",
* in which case clear the list of rules to ignore.
*/
if (argc == 2)
{
LinkedIndex *li;
/* Print or list rules being ignored */
li = DRCIgnoreRules;
while (li != NULL)
{
TxPrintf("%s\n", DRCCurStyle->DRCWhyList[li->li_index]);
li = li->li_next;
}
if (DRCIgnoreRules == NULL) TxPrintf("(none)\n");
break;
}
if (argc != 3) goto badusage;
if (!strcasecmp(argv[2], "none"))
{
LinkedIndex *li;
li = DRCIgnoreRules;
while (li != NULL)
{
freeMagic(li);
li = li->li_next;
}
DRCIgnoreRules = (LinkedIndex *)NULL;
}
else
{
int i;
LinkedIndex *newli;
for (i = 1; i < DRCCurStyle->DRCWhySize; i++)
{
if (strstr(DRCCurStyle->DRCWhyList[i], argv[2]) != NULL)
{
newli = (LinkedIndex *)mallocMagic(sizeof(LinkedIndex));
newli->li_index = i;
newli->li_next = DRCIgnoreRules;
DRCIgnoreRules = newli;
}
}
}
break;
case DRC_OFF:
#ifdef MAGIC_WRAPPER
/* Turn on long enough to force a break, then turn off */
@ -4349,7 +4422,8 @@ CmdDrc(w, cmd)
DRCWhyAll(rootUse, &rootArea, NULL);
else
#endif
DRCWhy(dolist, rootUse, &rootArea);
if (!DRCWhy(dolist, rootUse, &rootArea))
TxPrintf("No errors found.\n");
break;
}
return;

View File

@ -41,6 +41,12 @@ Background design rule checker control and status.
<DD> Locate next (or <I>nth</I>) error in current cell
<DT> <B>help</B>
<DD> Print help information
<DT> <B>ignore</B> [<I>text</I>|<B>none</B>]
<DD> Without options, print a list of all rules that are not being
reported. With option <I>text</I>, don't report rules containing
the string <I>text</I>. This is cumulative; additional calls
to "<B>drc ignore</B> <I>text</I>" will add rules to be ignored.
Cancel ignoring rules with "<B>drc ignore none</B>" (the default).
<DT> <B>off</B>
<DD> Turn off background checker
<DT> <B>on</B>

View File

@ -126,6 +126,7 @@ static int drcTotalVRulesHisto[DRC_MAXRULESHISTO];
static int drcTotalHRulesHisto[DRC_MAXRULESHISTO];
#endif /* DRCRULESHISTO */
LinkedIndex *DRCIgnoreRules = NULL;
/*
* ----------------------------------------------------------------------------
@ -282,12 +283,15 @@ drcPrintError (celldef, rect, cptr, scx)
area = &scx->scx_area;
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
DRCErrorCount += 1;
i = DRCErrorList[cptr->drcc_tag];
if (i == 0)
TxPrintf("%s\n", drcSubstitute(cptr));
DRCErrorList[cptr->drcc_tag] = i + 1;
if (i >= 0)
{
DRCErrorCount += 1;
DRCErrorList[cptr->drcc_tag] = i + 1;
}
}
/* Same routine as above, but output goes to a Tcl list and is appended */
@ -310,7 +314,6 @@ drcListError (celldef, rect, cptr, scx)
area = &scx->scx_area;
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
DRCErrorCount += 1;
i = DRCErrorList[cptr->drcc_tag];
if (i == 0)
{
@ -320,7 +323,11 @@ drcListError (celldef, rect, cptr, scx)
Tcl_NewStringObj(drcSubstitute(cptr), -1));
Tcl_SetObjResult(magicinterp, lobj);
}
DRCErrorList[cptr->drcc_tag] = i + 1;
if (i >= 0)
{
DRCErrorCount += 1;
DRCErrorList[cptr->drcc_tag] = i + 1;
}
}
/* Same routine as above, but output for every single error is recorded */
@ -452,7 +459,7 @@ DRCPrintStats()
* about each distinct kind of violation found.
*
* Results:
* None.
* TRUE if errors were found, and FALSE if not.
*
* Side effects:
* None, except that error messages are printed. The given
@ -462,7 +469,7 @@ DRCPrintStats()
* ----------------------------------------------------------------------------
*/
void
bool
DRCWhy(dolist, use, area)
bool dolist; /*
* Generate Tcl list for value
@ -476,8 +483,9 @@ DRCWhy(dolist, use, area)
{
SearchContext scx;
Rect box;
int i;
extern int drcWhyFunc(); /* Forward reference. */
int i, nerrors;
extern void drcWhyFunc(); /* Forward reference. */
LinkedIndex *li;
/* Create a hash table to eliminate duplicate messages. */
@ -485,6 +493,11 @@ DRCWhy(dolist, use, area)
for (i = 0; i <= DRCCurStyle->DRCWhySize; i++)
DRCErrorList[i] = 0;
/* Ignore rules as specified by setting the DRCErrorList entry to */
/* -1, indicating that the error type should be ignored. */
for (li = DRCIgnoreRules; li; li = li->li_next)
DRCErrorList[li->li_index] = -1;
DRCErrorCount = 0;
box = DRCdef->cd_bbox;
@ -510,7 +523,7 @@ DRCWhy(dolist, use, area)
(void) GeoInclude(&DRCdef->cd_bbox, &box);
DBWAreaChanged(DRCdef, &box, DBW_ALLWINDOWS, &DBAllButSpaceBits);
if (DRCErrorCount == 0) TxPrintf("No errors found.\n");
return (DRCErrorCount > 0) ? TRUE : FALSE;
}
#ifdef MAGIC_WRAPPER
@ -595,7 +608,7 @@ DRCWhyAll(use, area, fout)
* searches the subcell recursively.
*
* Results:
* Always returns 0 to keep the search alive.
* Returns the number of errors found by DRCInteractionCheck().
*
* Side effects:
* None.
@ -604,7 +617,7 @@ DRCWhyAll(use, area, fout)
*/
/* ARGSUSED */
int
void
drcWhyFunc(scx, cdarg)
SearchContext *scx; /* Describes current state of search. */
ClientData cdarg; /* Used to hold boolean value "dolist" */
@ -614,9 +627,8 @@ drcWhyFunc(scx, cdarg)
/* Check paint and interactions in this subcell. */
(void) DRCInteractionCheck(def, &scx->scx_area, &scx->scx_area,
DRCInteractionCheck(def, &scx->scx_area, &scx->scx_area,
(dolist) ? drcListError : drcPrintError, (ClientData) scx);
return 0;
}
#ifdef MAGIC_WRAPPER

View File

@ -168,8 +168,9 @@ maskToPrint (mask)
{
int i;
int gotSome = FALSE;
static char printchain[400];
char buffer[20];
static char printchain[512];
char buffer[20], *drcName;
int bufsize = 511;
if (TTMaskIsZero(mask))
return "<none>";
@ -179,9 +180,15 @@ maskToPrint (mask)
for (i = 0; i < DBNumTypes; i++)
if (TTMaskHasType(mask, i))
{
if (gotSome) strcat(printchain, ",");
if (gotSome) strncat(printchain, ",", bufsize--);
else gotSome = TRUE;
strcat(printchain, drcGetName(i, buffer));
strncat(printchain, drcGetName(i, buffer), bufsize);
bufsize -= strlen(buffer);
if (bufsize <= 1)
{
printchain[510] = '|';
break;
}
}
return (printchain);

View File

@ -190,6 +190,13 @@ typedef struct drcstyle
#define DRC_FLAGS_WIDEWIDTH_NONINCLUSIVE 0x01
/* Type definition used to keep a list of DRC rules to ignore */
typedef struct _linkedIndex {
int li_index;
struct _linkedIndex *li_next;
} LinkedIndex;
/* Things shared between DRC functions, but not used by the
* outside world:
*/
@ -230,6 +237,8 @@ extern DRCStyle *DRCCurStyle; /* Current DRC style in effect */
extern CellDef *DRCdef; /* Current cell being checked for DRC */
extern CellUse *DRCuse, *DRCDummyUse;
extern LinkedIndex *DRCIgnoreRules;
/*
* Internal procedures
*/
@ -270,7 +279,7 @@ extern void DRCContinuous();
extern void DRCCheckThis();
extern void DRCRemovePending();
extern void DRCPrintRulesTable();
extern void DRCWhy();
extern bool DRCWhy();
extern void DRCPrintStats();
extern void DRCCheck();
extern DRCCountList *DRCCount();