Added an option "gds flatglob [<string>|none]" that allows flattening

of input cells on a per-cellname basis, using glob-style pattern
matching.  This is probably the best way to deal with 3rd-party vendor
GDS with unfortunate practices like dividing devices up among cells in
a hierarchy, even though it comes across as a bit of a hack solution.
This commit is contained in:
Tim Edwards 2020-12-22 14:44:30 -05:00
parent 47f37cc13a
commit bcc7b3d06d
5 changed files with 153 additions and 22 deletions

View File

@ -1 +1 @@
8.3.101
8.3.102

View File

@ -291,6 +291,7 @@ calmaParseStructure(filename)
bool was_called;
bool was_initialized;
bool predefined;
bool do_flatten;
CellDef *def;
/* Make sure this is a structure; if not, let the caller know we're done */
@ -359,9 +360,6 @@ calmaParseStructure(filename)
cifCurReadPlanes = cifSubcellPlanes;
cifReadCellDef->cd_flags &= ~CDDEREFERENCE;
/* Done with strname */
if (strname != NULL) freeMagic(strname);
/* For read-only cells, set flag in def */
if (CalmaReadOnly)
cifReadCellDef->cd_flags |= CDVENDORGDS;
@ -410,7 +408,36 @@ calmaParseStructure(filename)
/* cifReadCellDef->cd_flags |= CDNOEDIT; */
}
/* Make sure it ends with an ENDSTR record */
/* Check if the cell name matches the pattern list of cells to flatten */
do_flatten = FALSE;
if ((CalmaFlattenUsesByName != NULL) && (!was_called) && (nsrefs == 0))
{
int i = 0;
char *pattern;
while (TRUE)
{
pattern = CalmaFlattenUsesByName[i];
if (pattern == NULL) break;
i++;
/* Check pattern against strname */
if (Match(pattern, strname))
{
do_flatten = TRUE;
break;
}
}
}
if (CalmaFlattenUses && (!was_called) && (npaths < CalmaFlattenLimit)
&& (nsrefs == 0))
do_flatten = TRUE;
/* Done with strname */
if (strname != NULL) freeMagic(strname);
/* Make sure the structure ends with an ENDSTR record */
if (!calmaSkipExact(CALMA_ENDSTR)) goto syntaxerror;
/*
@ -418,8 +445,8 @@ calmaParseStructure(filename)
* cell by painting when instanced. But---if this cell was
* instanced before it was defined, then it can't be flattened.
*/
if (CalmaFlattenUses && (!was_called) && (npaths < CalmaFlattenLimit)
&& (nsrefs == 0))
if (do_flatten)
{
/* If CDFLATGDS is already set, may need to remove */
/* existing planes and free memory. */
@ -617,7 +644,7 @@ calmaElementSref(filename)
*/
def = calmaLookCell(sname);
if (!def && (CalmaPostOrder || CalmaFlattenUses))
if (!def && (CalmaPostOrder || CalmaFlattenUses || (CalmaFlattenUsesByName != NULL)))
{
/* Force the GDS parser to read the cell definition in
* post-order. If cellname "sname" is not defined before

View File

@ -63,6 +63,11 @@ bool CalmaFlattenUses = FALSE; /* If TRUE, small cells in the input
* performance when handling contacts
* saved as subcell arrays.
*/
char **CalmaFlattenUsesByName = NULL; /* NULL-terminated list of strings
* to do glob-style pattern matching
* to determine what cells to flatten
* by cellname.
*/
bool CalmaReadOnly = FALSE; /* Set files to read-only and
* retain file position information
* so cells can be written verbatim.

View File

@ -37,6 +37,7 @@ extern bool CalmaMergeTiles;
extern bool CalmaFlattenArrays;
extern bool CalmaNoDRCCheck;
extern bool CalmaFlattenUses;
extern char **CalmaFlattenUsesByName;
extern bool CalmaReadOnly;
extern bool CalmaContactArrays;
extern bool CalmaPostOrder;

View File

@ -94,20 +94,21 @@ bool cmdDumpParseArgs();
#define CALMA_CONTACTS 3
#define CALMA_DRCCHECK 4
#define CALMA_FLATTEN 5
#define CALMA_ORDERING 6
#define CALMA_LABELS 7
#define CALMA_LIBRARY 8
#define CALMA_LOWER 9
#define CALMA_MERGE 10
#define CALMA_NO_STAMP 11
#define CALMA_NO_DUP 12
#define CALMA_READ 13
#define CALMA_READONLY 14
#define CALMA_RESCALE 15
#define CALMA_WARNING 16
#define CALMA_WRITE 17
#define CALMA_POLYS 18
#define CALMA_PATHS 19
#define CALMA_FLATGLOB 6
#define CALMA_ORDERING 7
#define CALMA_LABELS 8
#define CALMA_LIBRARY 9
#define CALMA_LOWER 10
#define CALMA_MERGE 11
#define CALMA_NO_STAMP 12
#define CALMA_NO_DUP 13
#define CALMA_READ 14
#define CALMA_READONLY 15
#define CALMA_RESCALE 16
#define CALMA_WARNING 17
#define CALMA_WRITE 18
#define CALMA_POLYS 19
#define CALMA_PATHS 20
#define CALMA_WARN_HELP CIF_WARN_END /* undefined by CIF module */
@ -136,6 +137,7 @@ CmdCalma(w, cmd)
"contacts [yes|no] optimize output by arraying contacts as subcells",
"drccheck [yes|no] mark all cells as needing DRC checking",
"flatten [yes|no|limit] flatten simple cells (e.g., contacts) on input",
"flatglob [<name>|none] flatten cells by name with glob patterning",
"ordering [on|off] cause cells to be read in post-order",
"labels [yes|no] cause labels to be output when writing GDS-II",
"library [yes|no] do not output the top level, only subcells",
@ -350,6 +352,102 @@ CmdCalma(w, cmd)
CalmaFlattenUses = (option < 4) ? FALSE : TRUE;
return;
case CALMA_FLATGLOB:
if (cmd->tx_argc == 2)
{
if (CalmaFlattenUsesByName != NULL)
{
int i = 0;
char *pattern;
#ifdef MAGIC_WRAPPER
Tcl_Obj *lobj = Tcl_NewListObj(0, NULL);
while (TRUE)
{
pattern = CalmaFlattenUsesByName[i];
if (pattern == NULL) break;
i++;
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewStringObj(pattern, -1));
}
Tcl_SetObjResult(magicinterp, lobj);
#else
TxPrintf("Glob patterns for cells to flatten:\n");
while (TRUE)
{
pattern = CalmaFlattenUsesByName[i];
if (pattern == NULL) break;
i++;
TxPrintf(" \"%s\"\n", pattern);
}
#endif
}
return;
}
else if (cmd->tx_argc != 3)
goto wrongNumArgs;
if (!strcasecmp(cmd->tx_argv[2], "none"))
{
int i = 0;
if (CalmaFlattenUsesByName == (char **)NULL) return;
while (TRUE)
{
char *pattern = CalmaFlattenUsesByName[i];
if (pattern == NULL) break;
freeMagic(pattern);
i++;
}
freeMagic(CalmaFlattenUsesByName);
CalmaFlattenUsesByName = (char **)NULL;
}
else
{
char **newpatterns;
char *pattern;
int i = 0;
if (CalmaFlattenUsesByName == (char **)NULL)
i = 1;
else
{
while (TRUE)
{
pattern = CalmaFlattenUsesByName[i++];
if (pattern == NULL) break;
}
}
newpatterns = (char **)mallocMagic((i + 1) * sizeof(char *));
i = 0;
if (CalmaFlattenUsesByName != (char **)NULL)
{
while (TRUE)
{
pattern = CalmaFlattenUsesByName[i];
if (pattern == NULL) break;
newpatterns[i] = StrDup((char **)NULL, pattern);
i++;
}
}
newpatterns[i++] = StrDup((char **)NULL, cmd->tx_argv[2]);
newpatterns[i] = (char *)NULL;
i = 0;
if (CalmaFlattenUsesByName != (char **)NULL)
{
while (TRUE)
{
pattern = CalmaFlattenUsesByName[i];
if (pattern == NULL) break;
freeMagic(pattern);
i++;
}
freeMagic(CalmaFlattenUsesByName);
}
CalmaFlattenUsesByName = newpatterns;
}
return;
case CALMA_ORDERING:
if (cmd->tx_argc == 2)
{