Modified the handling of "why" strings in the DRC mechanism, so that

DRC records contain an index into a string array instead of containing
a copy of a string.  This is preliminary to changing the way the DRC
error plane is painted, so that the types painted will mark the error
type.  This will (1) allow "drc why" to simply scan the DRC error
plane rather than running the DRC engine, (2) allow DRC errors to be
counted by area rather than by tile, and (3) let the DRC count be the
same whether done by "drc listall why" or "drc count".
This commit is contained in:
Tim Edwards 2020-02-25 13:57:41 -05:00
parent b62efea43d
commit 2beb5ee0e9
7 changed files with 130 additions and 104 deletions

View File

@ -46,7 +46,7 @@ static DRCCookie drcArrayCookie = {
0, 0, 0, 0,
{ 0 }, { 0 },
0, 0, 0,
"This layer can't abut or partially overlap between array elements",
DRC_ARRAY_OVERLAP_TAG,
(DRCCookie *) NULL
};

View File

@ -47,7 +47,7 @@ static DRCCookie drcOverlapCookie = {
0, 0, 0, 0,
{ 0 }, { 0 },
0, 0, 0,
"Can't overlap those layers",
DRC_OVERLAP_TAG,
(DRCCookie *) NULL
};

View File

@ -48,7 +48,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "utils/malloc.h"
#include "utils/utils.h"
extern char *drcWhyDup();
extern int drcCifTile();
extern int areaCifCheck();
extern void drcCheckCifMaxwidth();
@ -169,7 +168,7 @@ drcCifWidth(argc, argv)
char *layername = argv[1];
int scalefactor;
int centidistance = atoi(argv[2]);
char *why = drcWhyDup(argv[3]);
int why = drcWhyCreate(argv[3]);
TileTypeBitMask set, setC, tmp1;
int thislayer = -1;
DRCCookie *dpnew,*dpnext;
@ -228,7 +227,7 @@ drcCifSpacing(argc, argv)
char *argv[];
{
char *adjacency = argv[4];
char *why = drcWhyDup(argv[5]);
int why = drcWhyCreate(argv[5]);
DRCCookie *dpnext, *dpnew;
int needReverse = FALSE;
TileType i, j;
@ -1065,7 +1064,7 @@ drcCifArea(argc, argv)
char *layers = argv[1];
int centiarea = atoi(argv[2]);
int centihorizon = atoi(argv[3]);
char *why = drcWhyDup(argv[4]);
int why = drcWhyCreate(argv[4]);
TileTypeBitMask set, setC, tmp1;
DRCCookie *dpnext, *dpnew;
TileType i, j;
@ -1126,7 +1125,7 @@ drcCifMaxwidth(argc, argv)
char *layers = argv[1];
int centidistance = atoi(argv[2]);
char *bends = argv[3];
char *why = drcWhyDup(argv[4]);
int why = drcWhyCreate(argv[4]);
TileTypeBitMask set, setC, tmp1;
DRCCookie *dpnext, *dpnew;
TileType i, j;

View File

@ -69,9 +69,8 @@ TileType DRCErrorType; /* Type of error tile to paint. */
/* Used by drcPrintError: */
HashTable DRCErrorTable; /* Hash table used to eliminate duplicate
* error strings.
*/
int *DRCErrorList; /* List of DRC error type counts */
HashTable DRCErrorTable; /* Table of DRC errors and geometry */
/* Global variables used by all DRC modules to record statistics.
* For each statistic we keep two values, the count since stats
@ -183,11 +182,12 @@ drcSubstitute (cptr)
DRCCookie * cptr; /* Design rule violated */
{
static char *why_out = NULL;
char *whyptr = cptr->drcc_why, *sptr, *wptr;
char *whyptr, *sptr, *wptr;
int subscnt = 0, whylen;
float oscale, value;
extern float CIFGetOutputScale();
whyptr = DRCCurStyle->DRCWhyList[cptr->drcc_tag];
while ((sptr = strchr(whyptr, '%')) != NULL)
{
subscnt++;
@ -195,7 +195,7 @@ drcSubstitute (cptr)
}
if (subscnt == 0) return whyptr; /* No substitutions */
whyptr = cptr->drcc_why;
whyptr = DRCCurStyle->DRCWhyList[cptr->drcc_tag];
whylen = strlen(whyptr) + 20 * subscnt;
if (why_out != NULL) freeMagic(why_out);
why_out = (char *)mallocMagic(whylen * sizeof(char));
@ -256,7 +256,7 @@ drcSubstitute (cptr)
*
* Side effects:
* DRCErrorCount is incremented. The text associated with
* the error is entered into DRCErrorTable, and, if this is
* the error is entered into DRCErrorList, and, if this is
* the first time that entry has been seen, then the error
* text is printed. If the area parameter is non-NULL, then
* only errors intersecting that area are considered.
@ -279,12 +279,11 @@ drcPrintError (celldef, rect, cptr, scx)
area = &scx->scx_area;
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
DRCErrorCount += 1;
h = HashFind(&DRCErrorTable, cptr->drcc_why);
i = (spointertype) HashGetValue(h);
i = DRCErrorList[cptr->drcc_tag];
if (i == 0)
TxPrintf("%s\n", drcSubstitute(cptr));
i++;
HashSetValue(h, (spointertype)i);
DRCErrorList[cptr->drcc_tag] = i + 1;
}
/* Same routine as above, but output goes to a Tcl list and is appended */
@ -308,8 +307,7 @@ drcListError (celldef, rect, cptr, scx)
area = &scx->scx_area;
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
DRCErrorCount += 1;
h = HashFind(&DRCErrorTable, cptr->drcc_why);
i = (spointertype) HashGetValue(h);
i = DRCErrorList[cptr->drcc_tag];
if (i == 0)
{
Tcl_Obj *lobj;
@ -318,8 +316,7 @@ drcListError (celldef, rect, cptr, scx)
Tcl_NewStringObj(drcSubstitute(cptr), -1));
Tcl_SetObjResult(magicinterp, lobj);
}
i += 1;
HashSetValue(h, (spointertype)i);
DRCErrorList[cptr->drcc_tag] = i + 1;
}
/* Same routine as above, but output for every single error is recorded */
@ -475,11 +472,15 @@ DRCWhy(dolist, use, area)
{
SearchContext scx;
Rect box;
int i;
extern int drcWhyFunc(); /* Forward reference. */
/* Create a hash table to used for eliminating duplicate messages. */
/* Create a hash table to eliminate duplicate messages. */
DRCErrorList = (int *)mallocMagic((DRCCurStyle->DRCWhySize + 1) * sizeof(int));
for (i = 0; i <= DRCCurStyle->DRCWhySize; i++)
DRCErrorList[i] = 0;
HashInit(&DRCErrorTable, 16, HT_STRINGKEYS);
DRCErrorCount = 0;
box = DRCdef->cd_bbox;
@ -494,11 +495,8 @@ DRCWhy(dolist, use, area)
drcWhyFunc(&scx, (pointertype)dolist);
UndoEnable();
/* Delete the hash table now that we're finished (otherwise there
* will be a core leak.
*/
HashKill(&DRCErrorTable);
/* Delete the error list */
freeMagic(DRCErrorList);
/* Redisplay the DRC yank definition in case anyone is looking
* at it.
@ -532,7 +530,7 @@ DRCWhyAll(use, area, fout)
HashEntry *he;
Tcl_Obj *lobj, *robj;
/* Create a hash table to used for eliminating duplicate messages. */
/* Create a hash table for storing all of the results */
HashInit(&DRCErrorTable, 16, HT_STRINGKEYS);
DRCErrorCount = 0;
@ -566,10 +564,7 @@ DRCWhyAll(use, area, fout)
}
Tcl_SetObjResult(magicinterp, robj);
/* Delete the hash table now that we're finished (otherwise there
* will be a core leak.
*/
/* Delete the error table now that we're finished */
HashKill(&DRCErrorTable);
/* Redisplay the DRC yank definition in case anyone is looking

View File

@ -59,7 +59,7 @@ static DRCCookie drcSubcellCookie = {
0, 0, 0, 0,
{ 0 }, { 0 },
0, 0, 0,
"This layer can't abut or partially overlap between subcells",
DRC_SUBCELL_OVERLAP_TAG,
(DRCCookie *) NULL
};

View File

@ -61,6 +61,11 @@ global int DRCRuleOptimization = TRUE;
static int drcRulesSpecified = 0;
static int drcRulesOptimized = 0;
/* Rules with unique names are tagged with a reference number */
/* for use in placing errors into the DRC error plane. */
static int DRCtag = 0;
/*
* Forward declarations.
*/
@ -287,15 +292,8 @@ drcTechFreeStyle()
}
}
/* Clear the DRCWhyList */
while (DRCCurStyle->DRCWhyList != NULL)
{
old = (char *) DRCCurStyle->DRCWhyList;
StrDup(&(DRCCurStyle->DRCWhyList->dwl_string), (char *) NULL);
DRCCurStyle->DRCWhyList = DRCCurStyle->DRCWhyList->dwl_next;
freeMagic(old);
}
/* Clear the Why string list */
freeMagic(DRCCurStyle->DRCWhyList);
freeMagic(DRCCurStyle);
DRCCurStyle = NULL;
@ -329,31 +327,54 @@ drcTechNewStyle()
/*
* ----------------------------------------------------------------------------
* drcWhyDup --
* drcWhyCreate --
*
* Duplicate a shared "why" string using StrDup() and remember it so we can
* free it sometime later, in drcWhyClear().
* Create a hash entry for the DRC "why" string, if it does not already
* exist.
*
* Returns:
* A copy of the given string.
* A pointer to the drcWhy structure containing the string and tag.
*
* Side effects:
* Adds to the DRCWhyList. Calls StrDup().
* Adds to the DRCWhyList if whystring has not been used before.
* Calls StrDup() and increments DRCWhySize. DRCWhyList is allocated
* in blocks of 50 at a time and only expands when filled.
* Temporary hash table DRCErrorTable is used to determine if a
* string entry is unique. It is cleared after the technology file
* has been processed.
* ----------------------------------------------------------------------------
*/
char *
drcWhyDup(why)
char * why;
int
drcWhyCreate(whystring)
char *whystring;
{
struct drcwhylist * new;
HashEntry *he;
new = (struct drcwhylist *) mallocMagic((unsigned) (sizeof *new));
new->dwl_string = StrDup((char **) NULL, why);
new->dwl_next = DRCCurStyle->DRCWhyList;
DRCCurStyle->DRCWhyList = new;
he = HashLookOnly(&DRCErrorTable, whystring);
if (he != NULL)
return (int)((pointertype)HashGetValue(he));
return new->dwl_string;
/* Grow the list in increments of 50 */
if ((DRCCurStyle->DRCWhySize % 50) == 0)
{
int i;
char **newList;
newList = (char **)mallocMagic((DRCCurStyle->DRCWhySize + 51) * sizeof(char *));
for (i = 0; i < DRCCurStyle->DRCWhySize; i++)
newList[i] = DRCCurStyle->DRCWhyList[i];
if (DRCCurStyle->DRCWhySize > 0)
freeMagic((char *)DRCCurStyle->DRCWhyList);
DRCCurStyle->DRCWhyList = newList;
}
DRCCurStyle->DRCWhySize++;
he = HashFind(&DRCErrorTable, whystring);
HashSetValue(he, (char *)((pointertype)DRCCurStyle->DRCWhySize));
DRCCurStyle->DRCWhyList[DRCCurStyle->DRCWhySize] = StrDup((char **)NULL, whystring);
return DRCCurStyle->DRCWhySize;
}
/*
@ -535,12 +556,29 @@ DRCTechStyleInit()
DRCCurStyle->ds_status = TECH_NOT_LOADED;
TTMaskZero(&DRCCurStyle->DRCExactOverlapTypes);
DRCCurStyle->DRCWhyList = NULL;
DRCCurStyle->DRCTechHalo = 0;
DRCCurStyle->DRCScaleFactorN = 1;
DRCCurStyle->DRCScaleFactorD = 1;
DRCCurStyle->DRCStepSize = 0;
DRCCurStyle->DRCFlags = (char)0;
DRCCurStyle->DRCWhySize = 0;
HashInit(&DRCErrorTable, 16, HT_STRINGKEYS);
/* First DRC entry is associated with the statically-allocated */
/* drcArrayCookie and has a tag of DRC_ARRAY_OVERLAP_TAG = 1 */
/* (see DRCarray.c). */
drcWhyCreate("This layer can't abut or partially overlap between array elements");
/* Second DRC entry is associated with the statically-allocated */
/* drcOverlapCookie and has a tag of DRC_OVERLAP_TAG = 2 */
/* (see DRCbasic.c). */
drcWhyCreate("Can't overlap those layers");
/* Third DRC entry is associated with the statically-allocated */
/* drcSubcellCookie and has a tag of DRC_SUBCELL_OVERLAP_TAG = 3 */
/* (see DRCsubcell.c). */
drcWhyCreate("This layer can't abut or partially overlap between subcells");
DRCTechHalo = 0;
@ -872,18 +910,18 @@ DRCTechLine(sectionName, argc, argv)
}
void
drcCifAssign(cookie, dist, next, mask, corner, why, cdist, flags, planeto, planefrom)
drcCifAssign(cookie, dist, next, mask, corner, tag, cdist, flags, planeto, planefrom)
DRCCookie *cookie, *next;
int dist, cdist;
TileTypeBitMask *mask, *corner;
char *why;
int tag;
int flags, planeto, planefrom;
{
(cookie)->drcc_dist = dist;
(cookie)->drcc_next = next;
(cookie)->drcc_mask = *mask;
(cookie)->drcc_corner = *corner;
(cookie)->drcc_why = why;
(cookie)->drcc_tag = tag;
(cookie)->drcc_cdist = cdist;
(cookie)->drcc_flags = flags;
(cookie)->drcc_edgeplane = planefrom;
@ -900,7 +938,7 @@ drcAssign(cookie, dist, next, mask, corner, why, cdist, flags, planeto, planefro
DRCCookie *cookie, *next;
int dist, cdist;
TileTypeBitMask *mask, *corner;
char *why;
int why;
int flags, planeto, planefrom;
{
/* Diagnostic */
@ -1088,7 +1126,7 @@ drcExtend(argc, argv)
char *layers1 = argv[1];
char *layers2 = argv[2];
int distance = atoi(argv[3]);
char *why;
int why;
TileTypeBitMask set1, setC;
DRCCookie *dp, *dpnew, *dptrig;
TileType i, j;
@ -1100,10 +1138,10 @@ drcExtend(argc, argv)
if (!strncmp(argv[4], "exact_", 6))
{
exact = TRUE;
why = drcWhyDup(argv[5]);
why = drcWhyCreate(argv[5]);
}
else
why = drcWhyDup(argv[4]);
why = drcWhyCreate(argv[4]);
ptest = DBTechNoisyNameMask(layers1, &set1);
pMask1 = CoincidentPlanes(&set1, ptest);
@ -1257,7 +1295,7 @@ drcWidth(argc, argv)
{
char *layers = argv[1];
int distance = atoi(argv[2]);
char *why = drcWhyDup(argv[3]);
int why = drcWhyCreate(argv[3]);
TileTypeBitMask set, setC;
PlaneMask pmask, pset, ptest;
DRCCookie *dp, *dpnew;
@ -1342,7 +1380,7 @@ drcArea(argc, argv)
char *layers = argv[1];
int distance = atoi(argv[2]);
int horizon = atoi(argv[3]);
char *why = drcWhyDup(argv[4]);
int why = drcWhyCreate(argv[4]);
TileTypeBitMask set, setC;
DRCCookie *dp, *dpnew;
TileType i, j;
@ -1442,7 +1480,7 @@ drcMaxwidth(argc, argv)
char *layers = argv[1];
int distance = atoi(argv[2]);
char *bends = argv[3];
char *why;
int why;
TileTypeBitMask set, setC;
DRCCookie *dp, *dpnew;
TileType i, j;
@ -1469,7 +1507,7 @@ drcMaxwidth(argc, argv)
bend = 0;
else
bend = DRC_BENDS;
why = drcWhyDup(argv[3]);
why = drcWhyCreate(argv[3]);
}
else
{
@ -1480,7 +1518,7 @@ drcMaxwidth(argc, argv)
TechError("unknown bend option %s\n",bends);
return (0);
}
why = drcWhyDup(argv[4]);
why = drcWhyCreate(argv[4]);
}
for (i = 0; i < DBNumTypes; i++)
@ -1531,7 +1569,7 @@ drcAngles(argc, argv)
{
char *layers = argv[1];
int angles = atoi(argv[2]);
char *why = drcWhyDup(argv[3]);
int why = drcWhyCreate(argv[3]);
TileTypeBitMask set;
DRCCookie *dp, *dpnew;
int plane;
@ -1599,7 +1637,7 @@ drcSpacing3(argc, argv)
char *layers3 = argv[5];
int distance = atoi(argv[3]);
char *adjacency = argv[4];
char *why = drcWhyDup(argv[6]);
int why = drcWhyCreate(argv[6]);
TileTypeBitMask set1, set2, set3;
int plane;
DRCCookie *dp, *dpnew;
@ -2151,7 +2189,7 @@ drcSpacing(argc, argv)
{
char *layers1 = argv[1], *layers2;
char *adjacency;
char *why;
int why;
TileTypeBitMask set1, set2, tmp1, tmp2;
PlaneMask pmask1, pmask2, pmaskA, pmaskB, ptest;
int wwidth, distance, plane, plane2, runlength;
@ -2172,7 +2210,7 @@ drcSpacing(argc, argv)
layers2 = argv[4];
distance = atoi(argv[5]);
adjacency = argv[6];
why = drcWhyDup(argv[7]);
why = drcWhyCreate(argv[7]);
}
else
{
@ -2180,7 +2218,7 @@ drcSpacing(argc, argv)
distance = atoi(argv[4]);
runlength = distance;
adjacency = argv[5];
why = drcWhyDup(argv[6]);
why = drcWhyCreate(argv[6]);
}
/* TxPrintf("Info: DRCtech: widespacing rule for %s width %d:"
" spacing must be %d\n", layers1, wwidth, distance); */
@ -2191,7 +2229,7 @@ drcSpacing(argc, argv)
distance = atoi(argv[3]);
adjacency = argv[4];
wwidth = distance;
why = drcWhyDup(argv[5]);
why = drcWhyCreate(argv[5]);
runlength = distance;
if (argc >= 7)
{
@ -2325,7 +2363,7 @@ drcEdge(argc, argv)
int distance = atoi(argv[3]);
char *okTypes = argv[4], *cornerTypes = argv[5];
int cdist = atoi(argv[6]);
char *why = drcWhyDup(argv[7]);
int why = drcWhyCreate(argv[7]);
bool fourway = (strcmp(argv[0], "edge4way") == 0);
TileTypeBitMask set1, set2, setC, setM;
DRCCookie *dp, *dpnew;
@ -2491,7 +2529,7 @@ drcOverhang(argc, argv)
{
char *layers2 = argv[1], *layers1 = argv[2];
int distance = atoi(argv[3]);
char *why = drcWhyDup(argv[4]);
int why = drcWhyCreate(argv[4]);
TileTypeBitMask set1, set2, setM, setC, setN, set2inv;
DRCCookie *dp, *dpnew, *dptrig;
int plane, plane2;
@ -2627,7 +2665,7 @@ drcRectOnly(argc, argv)
char *argv[];
{
char *layers = argv[1];
char *why = drcWhyDup(argv[2]);
int why = drcWhyCreate(argv[2]);
TileTypeBitMask set1, set2, setC;
PlaneMask pmask, pset, ptest;
DRCCookie *dp, *dpnew;
@ -2727,7 +2765,7 @@ drcSurround(argc, argv)
char *layers1 = argv[1], *layers2 = argv[2];
int distance = atoi(argv[3]);
char *presence = argv[4];
char *why = drcWhyDup(argv[5]);
int why = drcWhyCreate(argv[5]);
TileTypeBitMask set1, set2, setM, invM, setR;
DRCCookie *dp, *dpnew, *dptrig;
int plane1, plane2;
@ -3100,7 +3138,7 @@ drcRectangle(argc, argv)
char *argv[];
{
char *layers = argv[1];
char *why = drcWhyDup(argv[4]);
int why = drcWhyCreate(argv[4]);
TileTypeBitMask types, nottypes;
int maxwidth;
static char *drcRectOpt[4] = {"any", "even", "odd", 0};
@ -3466,6 +3504,9 @@ drcTechFinalStyle(style)
DRCCookie **dpp, **dp2back;
TileType i, j;
/* Done with DRCErrorTable */
HashKill(&DRCErrorTable);
/* If the scale factor is not 1, then divide all distances by */
/* the scale factor, take the ceiling, and save the (negative) */
/* remainder. */
@ -3587,7 +3628,6 @@ drcTechFinalStyle(style)
}
else
{
/* Don't free the shared drcc_why string here! */
freeMagic((char *)dptest);
drcRulesOptimized++;
}
@ -3682,7 +3722,8 @@ drcTechFinalStyle(style)
/* TxPrintf("For edge %s-%s, \"%s\" covers \"%s\"\n",
DBTypeShortName(i), DBTypeShortName(j),
next->drcc_why, dp->drcc_why);
DRCCurStyle->DRCWhyList[next->drcc_tag],
DRCCurStyle->DRCWhyList[dp->drcc_tag]);
*/
dp2back = &(style->DRCRulesTbl[i][j]);
while (*dp2back != dp)
@ -3704,7 +3745,6 @@ drcTechFinalStyle(style)
else
*dp2back = dp->drcc_next;
/* Don't free the shared drcc_why string here! */
freeMagic((char *) dp);
drcRulesOptimized += 1;
}

View File

@ -39,10 +39,15 @@ typedef struct drccookie
int drcc_edgeplane; /* Plane of edge */
int drcc_plane; /* Index of plane on which to check
* legal types. */
char *drcc_why; /* Explanation of error found */
int drcc_tag; /* Tag to explanation of error found */
struct drccookie *drcc_next;
} DRCCookie;
/* These DRC tags in DRCcookie are predefined. */
#define DRC_ARRAY_OVERLAP_TAG 1
#define DRC_OVERLAP_TAG 2
#define DRC_SUBCELL_OVERLAP_TAG 3
/* *This is size "int" because it holds an area for DRC_AREA rules, */
/* and therefore may have twice the bit length of a normal rule distance. */
@ -142,22 +147,6 @@ typedef struct drckeep
char *ds_name;
} DRCKeep;
/*
* DRC "why" strings are potentially referred to hundreds of times by
* DRC cookies in the rule table. Rather than creating hundreds of
* copies of each string, we create just one copy and let all the cookies
* point to that one copy.
*
* Since we can't free these shared "why" strings when we delete a cookie,
* we keep a list of these strings and free them all when convenient.
*/
typedef struct drcwhylist
{
char * dwl_string;
struct drcwhylist * dwl_next;
} drcWhyList;
/*
* Structure defining a DRC style
*/
@ -173,7 +162,8 @@ typedef struct drcstyle
int DRCTechHalo; /* largest action distance of design rules */
int DRCStepSize; /* chunk size for decomposing large areas */
char DRCFlags; /* Option flags */
drcWhyList *DRCWhyList;
char **DRCWhyList; /* Indexed list of "why" text strings */
int DRCWhySize; /* Length of DRCWhyList */
PaintResultType DRCPaintTable[NP][NT][NT];
} DRCStyle;
@ -229,6 +219,7 @@ extern DRCKeep *DRCStyleList; /* List of available DRC styles */
extern DRCStyle *DRCCurStyle; /* Current DRC style in effect */
extern CellDef *DRCdef; /* Current cell being checked for DRC */
extern CellUse *DRCuse, *DRCDummyUse;
extern HashTable DRCErrorTable; /* DRC errors, hashed by name */
/*
* Internal procedures
@ -241,6 +232,7 @@ extern int drcExactOverlapTile();
extern void drcInitRulesTbl();
extern void drcAssign();
extern void drcCifAssign();
extern int drcWhyCreate();
/*
* Exported procedures