diff --git a/VERSION b/VERSION index c0768957..6022050e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.2.186 +8.2.187 diff --git a/commands/CmdCD.c b/commands/CmdCD.c index 5babc7c2..d91da3a6 100644 --- a/commands/CmdCD.c +++ b/commands/CmdCD.c @@ -3182,6 +3182,7 @@ CmdDrc(w, cmd) bool doforall = FALSE; bool dolist = FALSE; int count_total; + DRCCountList *dcl; int argc = cmd->tx_argc; char **argv = cmd->tx_argv; #ifdef MAGIC_WRAPPER @@ -3196,7 +3197,7 @@ CmdDrc(w, cmd) "*stepsize [d] change DRC step size to d units", "catchup run checker and wait for it to complete", "check recheck area under box in all cells", - "count count error tiles in each cell under box", + "count [total] count error tiles in each cell under box", "euclidean on|off enable/disable Euclidean geometry checking", "find [nth] locate next (or nth) error in the layout", "help print this help information", @@ -3304,6 +3305,14 @@ CmdDrc(w, cmd) break; case COUNT: + count_total = -1; + if (argc == 3) + if (!strncmp(argv[2], "total", 5)) + count_total = 0; + +#ifdef MAGIC_WRAPPER + if (count_total == -1) lobj = Tcl_NewListObj(0, NULL); +#endif if ((window = w) == NULL) { window = ToolGetBoxWindow(&rootArea, (int *) NULL); @@ -3313,44 +3322,61 @@ CmdDrc(w, cmd) rootArea = w->w_surfaceArea; rootUse = (CellUse *) window->w_surfaceID; - count_total = DRCCount(rootUse, &rootArea); - -#ifdef MAGIC_WRAPPER - if (dolist) - { - lobj = Tcl_NewListObj(0, NULL); - Tcl_ListObjAppendElement(magicinterp, lobj, - Tcl_NewStringObj(rootUse->cu_def->cd_name, -1)); - Tcl_ListObjAppendElement(magicinterp, lobj, - Tcl_NewIntObj(count_total)); - } - else + dcl = DRCCount(rootUse, &rootArea); + while (dcl != NULL) { + if (count_total >= 0) + count_total += dcl->dcl_count; + else + { +#ifdef MAGIC_WRAPPER + if (dolist) + { + Tcl_Obj *pobj = Tcl_NewListObj(0, NULL); + Tcl_ListObjAppendElement(magicinterp, pobj, + Tcl_NewStringObj(dcl->dcl_def->cd_name, -1)); + Tcl_ListObjAppendElement(magicinterp, pobj, + Tcl_NewIntObj(dcl->dcl_count)); + Tcl_ListObjAppendElement(magicinterp, lobj, pobj); + } + else + { #endif - - if (count_total > 1) - TxPrintf("Cell %s has %d error tiles.\n", - rootUse->cu_def->cd_name, count_total); - else if (count_total == 1) - TxPrintf("Cell %s has just one error tile.\n", - rootUse->cu_def->cd_name); + if (dcl->dcl_count > 1) + TxPrintf("Cell %s has %d error tiles.\n", + dcl->dcl_def->cd_name, dcl->dcl_count); + else if (dcl->dcl_count == 1) + TxPrintf("Cell %s has just one error tile.\n", + dcl->dcl_def->cd_name); +#ifdef MAGIC_WRAPPER + } +#endif + } + freeMagic((char *)dcl); + dcl = dcl->dcl_next; + } #ifdef MAGIC_WRAPPER - } -#endif - -#ifdef MAGIC_WRAPPER - if (doforall) - Tcl_SetObjResult(magicinterp, lobj); - else if (count_total >= 0) + if (count_total >= 0) { if (dolist) Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(count_total)); else - TxPrintf("Total DRC errors found: %d\n", count_total); + { + if ((DRCBackGround != DRC_SET_OFF) && (count_total == -1)) + count_total = 0; + if (count_total >= 0) + TxPrintf("Total DRC errors found: %d\n", count_total); + } } + else if (dolist) + Tcl_SetObjResult(magicinterp, lobj); + #else - TxPrintf("Total DRC errors found: %d\n", count_total); + if ((DRCBackGround != DRC_SET_OFF) && (count_total == -1)) + count_total = 0; + if (count_gotal >= 0) + TxPrintf("Total DRC errors found: %d\n", count_total); #endif break; diff --git a/drc/DRCmain.c b/drc/DRCmain.c index 72d9c456..2b365224 100644 --- a/drc/DRCmain.c +++ b/drc/DRCmain.c @@ -747,31 +747,97 @@ drcCheckFunc(scx, cdarg) * ---------------------------------------------------------------------------- */ -int +DRCCountList * DRCCount(use, area) CellUse *use; /* Top-level use of hierarchy. */ Rect *area; /* Area in which violations are counted. */ { + DRCCountList *dcl, *newdcl; + HashTable dupTable; + HashEntry *he; + HashSearch hs; int count; SearchContext scx; CellDef *def; - extern int drcCountFunc2(); + extern int drcCountFunc(); + + /* Use a hash table to make sure that we don't output information + * for any cell more than once. + */ + + HashInit(&dupTable, 16, HT_WORDKEYS); scx.scx_use = use; scx.scx_x = use->cu_xlo; scx.scx_y = use->cu_ylo; scx.scx_area = *area; scx.scx_trans = GeoIdentityTransform; + (void) drcCountFunc(&scx, &dupTable); - def = use->cu_def; + /* Create the list from the hash table */ + + dcl = NULL; + if (dupTable.ht_table != (HashEntry **) NULL) + { + HashStartSearch(&hs); + while ((he = HashNext(&dupTable, &hs)) != (HashEntry *)NULL) + { + count = (spointertype)HashGetValue(he); + if (count > 1) + { + newdcl = (DRCCountList *)mallocMagic(sizeof(DRCCountList)); + newdcl->dcl_count = count - 1; + newdcl->dcl_def = (CellDef *)he->h_key.h_ptr; + newdcl->dcl_next = dcl; + dcl = newdcl; + } + } + } + HashKill(&dupTable); + return dcl; +} + +int +drcCountFunc(scx, dupTable) + SearchContext *scx; + HashTable *dupTable; /* Passed as client data, used to + * avoid searching any cell twice. + */ +{ + int count; + HashEntry *h; + CellDef *def; + extern int drcCountFunc2(); + + /* If we've already seen this cell definition before, then skip it + * now. + */ + + def = scx->scx_use->cu_def; + h = HashFind(dupTable, (char *)def); + if (HashGetValue(h) != 0) goto done; + HashSetValue(h, 1); /* Count errors in this cell definition by scanning the error plane. */ count = 0; (void) DBSrPaintArea((Tile *) NULL, def->cd_planes[PL_DRC_ERROR], &def->cd_bbox, &DBAllButSpaceBits, drcCountFunc2, (ClientData)(&count)); + HashSetValue(h, (spointertype)count + 1); - return count; + /* Ignore children that have not been loaded---we will only report */ + /* errors that can be seen. This avoids immediately loading and */ + /* drc processing large layouts simply because we asked for an */ + /* error count. When the cell is loaded, drc will be checked */ + /* anyway, and the count can be updated in response to that check. */ + + if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0) return 0; + + /* As a special performance hack, if the complete cell area is + * handled here, don't bother to look at any more array elements. + */ + done: if (GEO_SURROUND(&scx->scx_area, &def->cd_bbox)) return 2; + else return 0; } int diff --git a/drc/drc.h b/drc/drc.h index 99bf0d28..6f3e98c6 100644 --- a/drc/drc.h +++ b/drc/drc.h @@ -125,6 +125,15 @@ typedef struct drcpendingcookie struct drcpendingcookie *dpc_next; } DRCPendingCookie; +/* Structure used to pass back lists of cell definitions and error tile counts */ + +typedef struct drccountlist +{ + CellDef *dcl_def; + int dcl_count; + struct drccountlist *dcl_next; +} DRCCountList; + /* Structure used to keep information about the current DRC style */ typedef struct drckeep @@ -258,7 +267,7 @@ extern void DRCPrintRulesTable(); extern void DRCWhy(); extern void DRCPrintStats(); extern void DRCCheck(); -extern int DRCCount(); +extern DRCCountList *DRCCount(); extern int DRCFind(); extern void DRCCatchUp(); extern bool DRCFindInteractions();