From dd3a92762c72f78e2c39db2112091768ef8cb60a Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 16 Nov 2018 13:59:17 -0500 Subject: [PATCH] Update for writing files from abstract views. Previous behavior was to prefix all library components read from GDS files pointed to by an abstract view (other than the cell itself) with a prefix. But this does not account for the fact that the same library may be read by other cells. The solution is for every cell in the library, check if there is a cell in magic with the same name which is also an abstract view that points to the same GDS library. Those cells do not get prefixes. At the same time, however, it was discovered that the GDS cellname character limit is set at 32, and so prefixes must be kept short. To keep the prefixes unique, the prefix was changed to a 4 character random alphanumeric sequence, and a warning is issued if any GDS cell exceeds the 32 character limit. --- calma/CalmaWrite.c | 158 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 136 insertions(+), 22 deletions(-) diff --git a/calma/CalmaWrite.c b/calma/CalmaWrite.c index 2ef72893..b80be6f9 100644 --- a/calma/CalmaWrite.c +++ b/calma/CalmaWrite.c @@ -22,6 +22,7 @@ static char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic-8.0/c #include #include +#include /* for random() */ #include #include #include @@ -136,6 +137,11 @@ int calmaPaintScale; int calmaPaintLayerNumber; int calmaPaintLayerType; +/* + * Hash table used to determine which GDS libraries have been output + */ +HashTable calmaLibHash; + /* Imports */ extern time_t time(); @@ -285,6 +291,8 @@ CalmaWrite(rootDef, f) return FALSE; } + HashInit(&calmaLibHash, 32, 0); + /* * Make sure that the entire hierarchy rooted at rootDef is * read into memory and that timestamp mismatches are resolved @@ -334,6 +342,7 @@ CalmaWrite(rootDef, f) */ if (CalmaContactArrays) calmaDelContacts(); + HashFreeKill(&calmaLibHash); return (good); } @@ -345,22 +354,26 @@ CalmaWrite(rootDef, f) * * Parse a structure (cell) from the GDS file. Check the name against the * existing database and modify the name in case of a collision. Then dump - * the entire cell verbatim. + * the entire cell verbatim. The cell gets prefixed with the name "prefix" + * to prevent collisions with other unknown GDS files that may be dumped + * verbatim. * * ---------------------------------------------------------------------------- */ bool -calmaDumpStructure(def, cellstart, outf, calmaDefHash) +calmaDumpStructure(def, cellstart, outf, calmaDefHash, filename) CellDef *def; off_t cellstart; FILE *outf; HashTable *calmaDefHash; + char *filename; { int nbytes, rtype; char *strname = NULL, *newnameptr, newname[CALMANAMELENGTH*2]; - HashEntry *he; + HashEntry *he, *he2; CellDef *edef; + char *prefix; /* Make sure this is a structure; if not, let the caller know we're done */ PEEKRH(nbytes, rtype); @@ -401,17 +414,82 @@ calmaDumpStructure(def, cellstart, outf, calmaDefHash) } else { - /* Modify the cellname by prefixing with the def name */ - newnameptr = mallocMagic(strlen(strname) + strlen(def->cd_name) + 8); - sprintf(newnameptr, "%s_%s", def->cd_name, strname); + /* Check if the cellname is in the magic cell database. */ + /* If so, check if that cell is an abstract view and */ + /* calls the same library. If so, the name does not */ + /* get prefixed. Otherwise, the cell is limited to the */ + /* GDS library being read, and so takes the prefix. */ + + /* Modify the cellname by prefixing with "prefix", which is a */ + /* unique identifier for the library. */ /* Check if the cell is defined in the database */ - edef = DBCellLookDef(newnameptr); + edef = DBCellLookDef(strname); if (edef != NULL) - // To do: Expand upon this, but it's probably overkill - sprintf(newnameptr, "%s_%s[[0]]", def->cd_name, strname); + { + bool isAbstract, isReadOnly; + char *chklibname; + + /* Is view abstract? */ + DBPropGet(edef, "LEFview", &isAbstract); + chklibname = (char *)DBPropGet(edef, "GDS_FILE", &isReadOnly); + + /* Is the library name the same? */ + if (isAbstract && !strcmp(filename, chklibname)) + { + /* Same library, so keep the cellname and mark the cell */ + /* as having been written to GDS. */ + + newnameptr = mallocMagic(strlen(strname) + 1); + sprintf(newnameptr, "%s", strname); + HashSetValue(he, (char *)newnameptr); + + TxPrintf("(1a) Writing \"%s\".\n", strname); + } + else + { + /* Find the unique library prefix and prepend it to the cell name */ + + he2 = HashFind(&calmaLibHash, filename); + if (he2 == NULL) + { + /* Should never happen */ + TxError("Fatal error: Library %s not recorded!\n", filename); + newnameptr = strname; + } + else + { + prefix = (char *)HashGetValue(he2); + newnameptr = mallocMagic(strlen(strname) + strlen(prefix) + 8); + sprintf(newnameptr, "%s_%s", prefix, strname); + + TxPrintf("(1b) Writing \"%s\".\n", newnameptr); + HashSetValue(he, (char *)newnameptr); + } + } + } + else + { + /* Find the unique library prefix and prepend it to the cell name */ + + he2 = HashFind(&calmaLibHash, filename); + if (he2 == NULL) + { + /* Should never happen */ + TxError("Fatal error: Library %s not recorded!\n", filename); + newnameptr = strname; + } + else + { + prefix = (char *)HashGetValue(he2); + newnameptr = mallocMagic(strlen(strname) + strlen(prefix) + 8); + sprintf(newnameptr, "%s_%s", prefix, strname); + + TxPrintf("(1c) Writing \"%s\".\n", newnameptr); + HashSetValue(he, (char *)newnameptr); + } + } calmaOutStringRecord(CALMA_STRNAME, newnameptr, outf); - HashSetValue(he, (char *)newnameptr); } freeMagic(strname); @@ -459,13 +537,14 @@ calmaDumpStructure(def, cellstart, outf, calmaDefHash) /* the same way used for structure definitions. */ newnameptr = (char *)mallocMagic(strlen(strname) + - strlen(def->cd_name) + 8); - sprintf(newnameptr, "%s_%s", def->cd_name, strname); + strlen(prefix) + 8); + sprintf(newnameptr, "%s_%s", prefix, strname); edef = DBCellLookDef(newnameptr); if (edef != NULL) - sprintf(newnameptr, "%s_%s[[0]]", def->cd_name, strname); + sprintf(newnameptr, "%s_%s[[0]]", prefix, strname); HashSetValue(he, (char *)newnameptr); + TxPrintf("(2) Writing \"%s\".\n", newnameptr); calmaOutStringRecord(CALMA_SNAME, newnameptr, outf); } break; @@ -516,15 +595,19 @@ syntaxerror: */ void -calmaFullDump(def, fi, cellstart, outf) +calmaFullDump(def, fi, cellstart, outf, filename) CellDef *def; FILE *fi; off_t cellstart; FILE *outf; + char *filename; { - int version; - char *libname = NULL; + int version, rval, i; + char *libname = NULL, uniqlibname[5]; + char *sptr; HashTable calmaDefHash; + HashEntry *he; + static int hdrSkip[] = { CALMA_FORMAT, CALMA_MASK, CALMA_ENDMASKS, CALMA_REFLIBS, CALMA_FONTS, CALMA_ATTRTABLE, CALMA_STYPTABLE, CALMA_GENERATIONS, CALMA_UNITS, -1 }; @@ -547,8 +630,21 @@ calmaFullDump(def, fi, cellstart, outf) // the input file are compatible with units being used in the output // file. calmaSkipSet(hdrSkip); - - while (calmaDumpStructure(def, cellstart, outf, &calmaDefHash)) + + // Record the GDS library so it will not be processed again. + he = HashFind(&calmaLibHash, filename); + // Generate a SHORT name for this cell (else it is easy to run into the + // GDS 32-character cellname limit). Save it in the hash record. + for (i = 0; i < 4; i++) { + rval = random() % 62; + rval = (rval < 26) ? ('A' + rval) : ((rval < 52) ? ('a' + rval - 26) : + ('0' + rval - 52)); + uniqlibname[i] = (char)(rval & 127); + } + uniqlibname[4] = '\0'; + HashSetValue(he, StrDup(NULL, uniqlibname)); + + while (calmaDumpStructure(def, cellstart, outf, &calmaDefHash, filename)) if (SigInterruptPending) goto done; calmaSkipExact(CALMA_ENDLIB); @@ -622,6 +718,7 @@ calmaProcessDef(def, outf) { char *filename; bool isReadOnly, oldStyle, hasContent, isAbstract; + HashEntry *he; /* Skip if already output */ if ((int) def->cd_client > 0) @@ -665,7 +762,7 @@ calmaProcessDef(def, outf) if (isReadOnly && hasContent) { - char *buffer, *offptr; + char *buffer, *offptr, *retfilename; size_t defsize, numbytes; off_t cellstart, cellend; dlong cval; @@ -674,7 +771,7 @@ calmaProcessDef(def, outf) /* Use PaOpen() so the paths searched are the same as were */ /* searched to find the .mag file that indicated this GDS file. */ - fi = PaOpen(filename, "r", "", Path, CellLibPath, (char **)NULL); + fi = PaOpen(filename, "r", "", Path, CellLibPath, &retfilename); if (fi == NULL) { /* This is a rare error, but if the subcell is inside */ @@ -699,7 +796,15 @@ calmaProcessDef(def, outf) /* not been loaded so naming conflicts may exist. So the file must */ /* be read end-to-end and parsed carefully. */ - calmaFullDump(def, fi, cellstart, outf); + TxPrintf("Checking if library %s was written.\n", retfilename); + he = HashLookOnly(&calmaLibHash, retfilename); + if (he == NULL) + { + TxPrintf("It wasn't. Writing it now.\n"); + calmaFullDump(def, fi, cellstart, outf, retfilename); + } + else + TxPrintf("It was. Skipping.\n"); fclose(fi); def->cd_flags |= CDVENDORGDS; } @@ -2644,7 +2749,16 @@ calmaOutStringRecord(type, str, f) * Output at most CALMANAMELENGTH characters. */ if (len & 01) len++; - if (len > CALMANAMELENGTH) len = CALMANAMELENGTH; + if (len > CALMANAMELENGTH) + { + char csav; + TxError("Warning: Cellname %s truncated ", str); + csav = *(str + 32); + *(str + 32) = '\0'; + TxError("to %32s (GDS format limit)\n", str); + *(str + 32) = csav; + len = CALMANAMELENGTH; + } calmaOutI2(len+4, f); /* Record length */ (void) putc(type, f); /* Record type */ (void) putc(CALMA_ASCII, f); /* Data type */