Realized a very stupid error in the handling of the "use" lines

when reading in a .mag file.  The routine was not checking for
whether a "use" entry in the file was the first one encountered
or not.  The path is only ever given for the first use of any cell
def, so for any cell after the first, the path should have already
been resolved.  This fix avoids lots of unnecessary error messages
when reading a file in a different directory.  Also, because the
routine now checks for the first use in a file, any error messages
that do occur will only be displayed for the first use, not all of
them.
This commit is contained in:
Tim Edwards 2021-11-20 20:54:51 -05:00
parent f8a45a19bb
commit a6e57093f8
2 changed files with 42 additions and 15 deletions

View File

@ -1 +1 @@
8.3.229
8.3.230

View File

@ -419,6 +419,7 @@ dbCellReadDef(f, cellDef, name, ignoreTech, dereference)
Plane *plane;
Rect r;
int n = 1, d = 1;
HashTable dbUseTable;
/*
* It's very important to disable interrupts during the body of
@ -664,6 +665,7 @@ dbCellReadDef(f, cellDef, name, ignoreTech, dereference)
*/
rp = &r;
UndoDisable();
HashInit(&dbUseTable, 32, HT_STRINGKEYS);
while (TRUE)
{
/*
@ -674,7 +676,8 @@ dbCellReadDef(f, cellDef, name, ignoreTech, dereference)
*/
if (sscanf(line, "<< %s >>", layername) != 1)
{
if (!dbReadUse(cellDef, line, sizeof line, f, n, d, dereference))
if (!dbReadUse(cellDef, line, sizeof line, f, n, d,
dereference, &dbUseTable))
goto badfile;
continue;
}
@ -870,6 +873,7 @@ done:
cellDef->cd_flags |= CDSTAMPSCHANGED|CDGETNEWSTAMP;
}
HashKill(&dbUseTable);
UndoEnable();
/* Disabled 3/16/2021. Let <<checkpaint>> in file force a DRC check */
/* DRCCheckThis(cellDef, TT_CHECKPAINT, (Rect *) NULL); */
@ -1457,7 +1461,7 @@ DBTestOpen(name, fullPath)
*/
bool
dbReadUse(cellDef, line, len, f, scalen, scaled, dereference)
dbReadUse(cellDef, line, len, f, scalen, scaled, dereference, dbUseTable)
CellDef *cellDef; /* Cell whose cells are being read */
char *line; /* Line containing "use ..." */
int len; /* Size of buffer pointed to by line */
@ -1465,6 +1469,7 @@ dbReadUse(cellDef, line, len, f, scalen, scaled, dereference)
int scalen; /* Multiply values in file by this */
int scaled; /* Divide values in file by this */
bool dereference; /* If TRUE, ignore path references */
HashTable *dbUseTable; /* Hash table of instances seen in this file */
{
int xlo, xhi, ylo, yhi, xsep, ysep, childStamp;
int absa, absb, absd, abse, nconv;
@ -1473,7 +1478,7 @@ dbReadUse(cellDef, line, len, f, scalen, scaled, dereference)
CellDef *subCellDef;
Transform t;
Rect r;
bool locked;
bool locked, firstUse;
char *slashptr, *pathptr;
if (strncmp(line, "use", 3) != 0)
@ -1598,6 +1603,13 @@ badTransform:
r.r_ytop /= scaled;
}
/* Flag if this is the first time the cell is used in the file,
* so that we can expect that additional instances will not have
* path information given.
*/
firstUse = (HashLookOnly(dbUseTable, cellname) == NULL) ? TRUE : FALSE;
if (firstUse) HashFind(dbUseTable, cellname);
/*
* Set up cell use.
* If the definition for this use has not been read in,
@ -1614,14 +1626,20 @@ badTransform:
/* Make sure rectangle is non-degenerate */
if (GEO_RECTNULL(&r))
{
TxPrintf("Subcell has degenerate bounding box: %d %d %d %d\n",
r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop);
TxPrintf("Adjusting bounding box of subcell %s of %s",
cellname, cellDef->cd_name);
if (firstUse == TRUE)
{
TxPrintf("Subcell has degenerate bounding box: %d %d %d %d\n",
r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop);
TxPrintf("Adjusting bounding box of subcell %s of %s",
cellname, cellDef->cd_name);
}
if (r.r_xtop <= r.r_xbot) r.r_xtop = r.r_xbot + 1;
if (r.r_ytop <= r.r_ybot) r.r_ytop = r.r_ybot + 1;
TxPrintf(" to %d %d %d %d\n",
r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop);
if (firstUse == TRUE)
{
TxPrintf(" to %d %d %d %d\n",
r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop);
}
}
subCellDef->cd_bbox = r;
subCellDef->cd_extended = r;
@ -1632,9 +1650,12 @@ badTransform:
* Watch out for attempts to create circular structures.
* If this happens, disregard the subcell.
*/
TxPrintf("Subcells are used circularly!\n");
TxPrintf("Ignoring subcell %s of %s.\n", cellname,
cellDef->cd_name);
if (firstUse == TRUE)
{
TxPrintf("Subcells are used circularly!\n");
TxPrintf("Ignoring subcell %s of %s.\n", cellname,
cellDef->cd_name);
}
goto nextLine;
}
@ -1669,7 +1690,13 @@ badTransform:
/* or "~" and cellDef->cd_file has path components, then the path */
/* should be interpreted relative to the path of the parent cell. */
if ((*pathptr == '\0') || ((*pathptr != '/') && (*pathptr != '~')))
/* If there is no pathptr, then the situation is one of these two: */
/* (1) The instance is not the first time the cell was encountered */
/* in the file, or (2) The cell is in the same path as the parent. */
/* Only case (2) needs to be handled. */
if ((firstUse == TRUE) && ((*pathptr == '\0') ||
((*pathptr != '/') && (*pathptr != '~'))))
if ((cellDef->cd_file != NULL) &&
(slashptr = strrchr(cellDef->cd_file, '/')) != NULL)
{
@ -1745,7 +1772,7 @@ badTransform:
}
if ((pathOK == FALSE) && strcmp(subCellDef->cd_file, pathptr)
&& (dereference == FALSE))
&& (dereference == FALSE) && (firstUse == TRUE))
{
TxError("Duplicate cell in %s: Instance of cell %s is from "
"path %s but cell was previously read from %s.\n",