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.
This commit is contained in:
Tim Edwards 2018-11-16 13:59:17 -05:00
parent eca3ba25b3
commit dd3a92762c
1 changed files with 136 additions and 22 deletions

View File

@ -22,6 +22,7 @@ static char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic-8.0/c
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h> /* for random() */
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
@ -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 */