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:
parent
ca985edbd0
commit
60a378842f
148
commands/CmdCD.c
148
commands/CmdCD.c
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
11
drc/drc.h
11
drc/drc.h
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Reference in New Issue