diff --git a/VERSION b/VERSION index 608ac6d0..47513574 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.406 +8.3.407 diff --git a/commands/CmdCD.c b/commands/CmdCD.c index a94fad1f..68ffa913 100644 --- a/commands/CmdCD.c +++ b/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 [|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; diff --git a/doc/html/drc.html b/doc/html/drc.html index 615a23ac..a2207ee7 100644 --- a/doc/html/drc.html +++ b/doc/html/drc.html @@ -41,6 +41,12 @@ Background design rule checker control and status.
Locate next (or nth) error in current cell
help
Print help information +
ignore [text|none] +
Without options, print a list of all rules that are not being + reported. With option text, don't report rules containing + the string text. This is cumulative; additional calls + to "drc ignore text" will add rules to be ignored. + Cancel ignoring rules with "drc ignore none" (the default).
off
Turn off background checker
on diff --git a/drc/DRCmain.c b/drc/DRCmain.c index 87441cf8..44a4c5e8 100644 --- a/drc/DRCmain.c +++ b/drc/DRCmain.c @@ -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 diff --git a/drc/DRCprint.c b/drc/DRCprint.c index 8b15d133..f93daaac 100644 --- a/drc/DRCprint.c +++ b/drc/DRCprint.c @@ -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 ""; @@ -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); diff --git a/drc/drc.h b/drc/drc.h index d4d347b9..204e2f8d 100644 --- a/drc/drc.h +++ b/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();