diff --git a/VERSION b/VERSION index 0b32410c..8be00eea 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.156 +8.3.157 diff --git a/calma/CalmaRdcl.c b/calma/CalmaRdcl.c index a775d821..9a379599 100644 --- a/calma/CalmaRdcl.c +++ b/calma/CalmaRdcl.c @@ -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 */ diff --git a/database/DBio.c b/database/DBio.c index 2b4747bd..3bbfbec1 100644 --- a/database/DBio.c +++ b/database/DBio.c @@ -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; diff --git a/database/database.h.in b/database/database.h.in index 646882f6..1ef2d9fd 100644 --- a/database/database.h.in +++ b/database/database.h.in @@ -777,6 +777,7 @@ extern void DBFileRecovery(); extern bool DBWriteBackup(); extern bool DBReadBackup(); extern void DBRemoveBackup(); +extern void DBPathSubstitute(); /* Labels */ extern Label *DBPutLabel();