Merge branch 'master' into magic-8.2
This commit is contained in:
commit
374c7fda40
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
11
drc/drc.h
11
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();
|
||||
|
|
|
|||
Loading…
Reference in New Issue