Created a method for annotating abstract views with GDS pointers.

This can be done now by reading a LEF file, followed by reading
a GDS file with the "noduplicates" option set.  In addition,
annotation of either the LEF view or a read-only view follows the
same protocol as cell paths in the .mag file, which is to replace
leading path components matching Tcl variables for PDKPATH or
PDKROOT, and replace the home directory path with a tilde.
This commit is contained in:
Tim Edwards 2021-04-22 14:39:34 -04:00
parent a5248a95d3
commit 6bd96a68dc
4 changed files with 168 additions and 124 deletions

View File

@ -1 +1 @@
8.3.156
8.3.157

View File

@ -307,8 +307,8 @@ calmaParseStructure(filename)
if (!calmaReadStringRecord(CALMA_STRNAME, &strname)) goto syntaxerror;
TxPrintf("Reading \"%s\".\n", strname);
if (CalmaReadOnly)
filepos = ftello(calmaInputFile);
/* Used for read-only and annotated LEF views */
filepos = ftello(calmaInputFile);
/* Set up the cell definition */
he = HashFind(&calmaDefInitHash, strname);
@ -350,50 +350,74 @@ calmaParseStructure(filename)
}
}
cifReadCellDef = calmaFindCell(strname, &was_called, &predefined);
if (predefined == TRUE)
{
calmaNextCell();
return TRUE;
bool isAbstract;
/* If the cell was predefined, the "noduplicates" option was
* invoked, and the existing cell is an abstract view, then
* annotate the cell with the GDS file pointers to the cell
* data, and the GDS filename.
*/
DBPropGet(cifReadCellDef, "LEFview", &isAbstract);
if (!isAbstract)
{
calmaNextCell();
return TRUE;
}
calmaSkipTo(CALMA_ENDSTR);
}
DBCellClearDef(cifReadCellDef);
DBCellSetAvail(cifReadCellDef);
HashSetValue(he, cifReadCellDef);
cifCurReadPlanes = cifSubcellPlanes;
cifReadCellDef->cd_flags &= ~CDDEREFERENCE;
/* For read-only cells, set flag in def */
if (CalmaReadOnly)
cifReadCellDef->cd_flags |= CDVENDORGDS;
/* Skip CALMA_STRCLASS or CALMA_STRTYPE */
calmaSkipSet(structs);
/* Initialize the hash table for layer errors */
HashInit(&calmaLayerHash, 32, sizeof (CalmaLayerType) / sizeof (unsigned));
was_initialized = TRUE;
/* Body of structure: a sequence of elements */
osrefs = nsrefs = 0;
npaths = 0;
calmaNonManhattan = 0;
while (calmaParseElement(filename, &nsrefs, &npaths))
else
{
if (SigInterruptPending)
goto done;
if (nsrefs > osrefs && (nsrefs % 100) == 0)
TxPrintf(" %d uses\n", nsrefs);
osrefs = nsrefs;
DBCellClearDef(cifReadCellDef);
DBCellSetAvail(cifReadCellDef);
HashSetValue(he, cifReadCellDef);
cifCurReadPlanes = cifSubcellPlanes;
cifReadCellDef->cd_flags &= ~CDDEREFERENCE;
/* For read-only cells, set flag in def */
if (CalmaReadOnly)
cifReadCellDef->cd_flags |= CDVENDORGDS;
/* Skip CALMA_STRCLASS or CALMA_STRTYPE */
calmaSkipSet(structs);
/* Initialize the hash table for layer errors */
HashInit(&calmaLayerHash, 32, sizeof (CalmaLayerType) / sizeof (unsigned));
was_initialized = TRUE;
/* Body of structure: a sequence of elements */
osrefs = nsrefs = 0;
npaths = 0;
calmaNonManhattan = 0;
while (calmaParseElement(filename, &nsrefs, &npaths))
{
if (SigInterruptPending)
goto done;
if (nsrefs > osrefs && (nsrefs % 100) == 0)
TxPrintf(" %d uses\n", nsrefs);
osrefs = nsrefs;
calmaNonManhattan = 0;
}
}
if (CalmaReadOnly)
if (CalmaReadOnly || predefined)
{
char cstring[1024];
/* Writing the file position into a string is slow, but */
/* it prevents requiring special handling when printing */
/* out the properties. */
char *fpcopy = (char *)mallocMagic(20);
char *fncopy = StrDup(NULL, filename);
char *fncopy;
/* Substitute variable for PDK path or ~ for home directory */
/* the same way that cell references are handled in .mag files. */
DBPathSubstitute(filename, cstring, cifReadCellDef);
fncopy = StrDup(NULL, cstring);
sprintf(fpcopy, "%"DLONG_PREFIX"d", (dlong) filepos);
DBPropPut(cifReadCellDef, "GDS_START", (ClientData)fpcopy);
@ -404,9 +428,11 @@ calmaParseStructure(filename)
DBPropPut(cifReadCellDef, "GDS_FILE", (ClientData)fncopy);
/* Do not lock the cell, or else we can't save the */
/* magic cell with its GDS pointers to disk. . . */
/* cifReadCellDef->cd_flags |= CDNOEDIT; */
if (predefined)
{
if (strname != NULL) freeMagic(strname);
return TRUE;
}
}
/* Check if the cell name matches the pattern list of cells to flatten */

View File

@ -3405,6 +3405,103 @@ dbClearCellFunc(cellUse, cdarg)
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* DBPathSubstitute --
*
* Replace the leading part of a file path string according to the following
* criteria:
*
* 1) If the filename starts with a string equal to the contents of
* Tcl variables PDK_PATH, PDKPATH, PDK_ROOT, or PDKROOT, then
* replace the string with the variable name. The "PATH" names are
* more specific than "ROOT" and so are checked first.
* 2) If the filename starts with a string equal to the contents of
* environment variable HOME, then replace the string with "~".
*
* Results:
* None.
*
* Side Effects:
* Writes into the string "cstring".
*
* ----------------------------------------------------------------------------
*/
void
DBPathSubstitute(pathstart, cstring, cellDef)
char *pathstart;
char *cstring;
CellDef *cellDef;
{
bool subbed = FALSE;
#ifdef MAGIC_WRAPPER
char *tvar;
/* Check for the leading component of the file path being equal to */
/* one of several common variable names for the PDK location, and */
/* if there is a match, then substitute the variable name for the */
/* matching leading path component. */
if (subbed == FALSE)
{
tvar = (char *)Tcl_GetVar(magicinterp, "PDK_PATH", TCL_GLOBAL_ONLY);
if (tvar)
if (!strncmp(pathstart, tvar, strlen(tvar)))
{
sprintf(cstring, "$PDK_PATH%s", pathstart + strlen(tvar));
subbed = TRUE;
}
}
if (subbed == FALSE)
{
tvar = (char *)Tcl_GetVar(magicinterp, "PDKPATH", TCL_GLOBAL_ONLY);
if (tvar)
if (!strncmp(pathstart, tvar, strlen(tvar)))
{
sprintf(cstring, "$PDKPATH%s", pathstart + strlen(tvar));
subbed = TRUE;
}
}
if (subbed == FALSE)
{
tvar = (char *)Tcl_GetVar(magicinterp, "PDK_ROOT", TCL_GLOBAL_ONLY);
if (tvar)
if (!strncmp(pathstart, tvar, strlen(tvar)))
{
sprintf(cstring, "$PDK_ROOT%s", pathstart + strlen(tvar));
subbed = TRUE;
}
}
if (subbed == FALSE)
{
tvar = (char *)Tcl_GetVar(magicinterp, "PDKROOT", TCL_GLOBAL_ONLY);
if (tvar)
if (!strncmp(pathstart, tvar, strlen(tvar)))
{
sprintf(cstring, "$PDKROOT%s", pathstart + strlen(tvar));
subbed = TRUE;
}
}
#endif
if (subbed == FALSE)
{
/* If path starts with home path, then replace with "~" */
/* to make IP semi-portable between home directories */
/* with the same file structure. */
char *homedir = getenv("HOME");
if (!strncmp(cellDef->cd_file, homedir, strlen(homedir))
&& (*(cellDef->cd_file + strlen(homedir)) == '/'))
sprintf(cstring, "~%s", cellDef->cd_file + strlen(homedir));
else
sprintf(cstring, "%s", pathstart);
}
}
/*
* ----------------------------------------------------------------------------
*
@ -3430,8 +3527,7 @@ dbWriteCellFunc(cellUse, cdarg)
struct writeArg *arg = (struct writeArg *) cdarg;
Transform *t;
Rect *b;
bool subbed = FALSE;
char cstring[256], *pathend, *pathstart, *parent;
char cstring[1024], *pathend, *pathstart, *parent;
t = &(cellUse->cu_transform);
b = &(cellUse->cu_def->cd_bbox);
@ -3482,92 +3578,13 @@ dbWriteCellFunc(cellUse, cdarg)
}
else
{
#ifdef MAGIC_WRAPPER
char *tvar;
/* Check for the leading component of the file path being equal to */
/* one of several common variable names for the PDK location, and */
/* if there is a match, then substitute the variable name for the */
/* matching leading path component. */
if (subbed == FALSE)
{
tvar = (char *)Tcl_GetVar(magicinterp, "PDK_PATH", TCL_GLOBAL_ONLY);
if (tvar)
if (!strncmp(pathstart, tvar, strlen(tvar)))
{
sprintf(cstring, "use %s %c%s $PDK_PATH%s\n",
cellUse->cu_def->cd_name,
(cellUse->cu_flags & CU_LOCKED) ? CULOCKCHAR : ' ',
cellUse->cu_id, pathstart + strlen(tvar));
subbed = TRUE;
}
}
if (subbed == FALSE)
{
tvar = (char *)Tcl_GetVar(magicinterp, "PDKPATH", TCL_GLOBAL_ONLY);
if (tvar)
if (!strncmp(pathstart, tvar, strlen(tvar)))
{
sprintf(cstring, "use %s %c%s $PDKPATH%s\n",
cellUse->cu_def->cd_name,
(cellUse->cu_flags & CU_LOCKED) ? CULOCKCHAR : ' ',
cellUse->cu_id, pathstart + strlen(tvar));
subbed = TRUE;
}
}
if (subbed == FALSE)
{
tvar = (char *)Tcl_GetVar(magicinterp, "PDK_ROOT", TCL_GLOBAL_ONLY);
if (tvar)
if (!strncmp(pathstart, tvar, strlen(tvar)))
{
sprintf(cstring, "use %s %c%s $PDK_ROOT%s\n",
cellUse->cu_def->cd_name,
(cellUse->cu_flags & CU_LOCKED) ? CULOCKCHAR : ' ',
cellUse->cu_id, pathstart + strlen(tvar));
subbed = TRUE;
}
}
if (subbed == FALSE)
{
tvar = (char *)Tcl_GetVar(magicinterp, "PDKROOT", TCL_GLOBAL_ONLY);
if (tvar)
if (!strncmp(pathstart, tvar, strlen(tvar)))
{
sprintf(cstring, "use %s %c%s $PDKROOT%s\n",
cellUse->cu_def->cd_name,
(cellUse->cu_flags & CU_LOCKED) ? CULOCKCHAR : ' ',
cellUse->cu_id, pathstart + strlen(tvar));
subbed = TRUE;
}
}
#endif
if (subbed == FALSE)
{
/* If path starts with home path, then replace with "~" */
/* to make IP semi-portable between home directories */
/* with the same file structure. */
char *homedir = getenv("HOME");
if (!strncmp(cellUse->cu_def->cd_file, homedir, strlen(homedir))
&& (*(cellUse->cu_def->cd_file + strlen(homedir)) == '/'))
{
sprintf(cstring, "use %s %c%s ~%s\n", cellUse->cu_def->cd_name,
(cellUse->cu_flags & CU_LOCKED) ? CULOCKCHAR : ' ',
cellUse->cu_id, cellUse->cu_def->cd_file +
strlen(homedir));
}
else
{
sprintf(cstring, "use %s %c%s %s\n", cellUse->cu_def->cd_name,
(cellUse->cu_flags & CU_LOCKED) ? CULOCKCHAR : ' ',
cellUse->cu_id, pathstart);
}
}
sprintf(cstring, "use %s %c%s ", cellUse->cu_def->cd_name,
(cellUse->cu_flags & CU_LOCKED) ? CULOCKCHAR : ' ',
cellUse->cu_id);
DBPathSubstitute(pathstart, cstring + strlen(cstring), cellUse->cu_def);
strcat(cstring, "\n");
}
FPRINTR(arg->wa_file, cstring);
cellUse->cu_def->cd_flags |= CDVISITED;

View File

@ -777,6 +777,7 @@ extern void DBFileRecovery();
extern bool DBWriteBackup();
extern bool DBReadBackup();
extern void DBRemoveBackup();
extern void DBPathSubstitute();
/* Labels */
extern Label *DBPutLabel();