mirror of
https://github.com/RTimothyEdwards/magic.git
synced 2026-08-29 09:30:46 +02:00
since this is a common artifact of foundry cells and almost always incompatible with magic. Modified the "port" command to allow "port make <index>" on a label where other labels of the same text already have the same index. Removed deprecated documentation and added some missing documentation, such as an explanation of the "ext2spice subcircuit auto" option.
636 lines
19 KiB
C
636 lines
19 KiB
C
/*
|
|
* CalmaRead.c --
|
|
*
|
|
* Input of Calma GDS-II stream format.
|
|
*
|
|
* *********************************************************************
|
|
* * Copyright (C) 1985, 1990 Regents of the University of California. *
|
|
* * Permission to use, copy, modify, and distribute this *
|
|
* * software and its documentation for any purpose and without *
|
|
* * fee is hereby granted, provided that the above copyright *
|
|
* * notice appear in all copies. The University of California *
|
|
* * makes no representations about the suitability of this *
|
|
* * software for any purpose. It is provided "as is" without *
|
|
* * express or implied warranty. Export of this software outside *
|
|
* * of the United States of America may require an export license. *
|
|
* *********************************************************************
|
|
*/
|
|
|
|
#ifndef lint
|
|
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/calma/CalmaRead.c,v 1.3 2010/06/24 12:37:15 tim Exp $";
|
|
#endif /* not lint */
|
|
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
/*
|
|
* C99 compat
|
|
* Mind: tcltk/tclmagic.h must be included prior to all the other headers
|
|
*/
|
|
#include "tcltk/tclmagic.h"
|
|
|
|
#include "utils/magic.h"
|
|
#include "utils/geometry.h"
|
|
#include "tiles/tile.h"
|
|
#include "utils/utils.h"
|
|
#include "utils/hash.h"
|
|
#include "database/database.h"
|
|
#include "database/databaseInt.h"
|
|
#include "utils/malloc.h"
|
|
#include "utils/tech.h"
|
|
#include "cif/cif.h"
|
|
#include "cif/CIFint.h"
|
|
#include "cif/CIFread.h"
|
|
#include "utils/signals.h"
|
|
#include "windows/windows.h"
|
|
#include "dbwind/dbwind.h"
|
|
#include "utils/styles.h"
|
|
#include "textio/textio.h"
|
|
#include "calma/calmaInt.h"
|
|
#include "commands/commands.h" /* for CmdGetRootPoint */
|
|
#include "utils/main.h" /* for EditCellUse */
|
|
#include "utils/undo.h"
|
|
|
|
/* C99 compat */
|
|
#include "calma/calma.h"
|
|
|
|
/* Globals for Calma reading */
|
|
FILETYPE calmaInputFile = NULL; /* Read from this stream */
|
|
FILE *calmaErrorFile = NULL; /* Write error output here */
|
|
unsigned char CalmaSubcellPolygons = CALMA_POLYGON_NONE;
|
|
/* Read non-Manhattan polygons as-is */
|
|
int CalmaPolygonCount;
|
|
bool CalmaSubcellPaths = FALSE; /* Put paths in their own subcells. */
|
|
int CalmaPathCount;
|
|
bool CalmaFlattenUses = FALSE; /* If TRUE, small cells in the input
|
|
* stream are flattened when encountered
|
|
* as uses. This improves magic's
|
|
* 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.
|
|
*/
|
|
float CalmaMagScale = 1.0; /* Scale by which to interpret the MAG
|
|
* record in GDS text records. The
|
|
* default is to treat the value as
|
|
* the text height in microns. This
|
|
* value reinterprets the scale.
|
|
*/
|
|
bool CalmaNoDRCCheck = FALSE; /* If TRUE, don't mark cells as needing
|
|
* a DRC check; they will be assumed
|
|
* DRC clean.
|
|
*/
|
|
bool CalmaPostOrder = FALSE; /* If TRUE, forces the GDS parser to
|
|
* read cells in post-order. It is
|
|
* necessary, e.g., when we need to
|
|
* flatten cells that are contact cuts.
|
|
* Added by Nishit 8/16/2004
|
|
*/
|
|
bool CalmaNoDuplicates = FALSE; /* If TRUE, then if a cell exists in
|
|
* memory with the same name as a cell
|
|
* in the GDS file, then the cell in
|
|
* the GDS file is skipped.
|
|
*/
|
|
bool CalmaUnique = FALSE; /* If TRUE, then if a cell exists in
|
|
* memory with the same name as a cell
|
|
* in the GDS file, then the cell in
|
|
* memory is renamed to a unique
|
|
* identifier with a _N suffix.
|
|
*/
|
|
extern bool CalmaDoLibrary; /* Also used by GDS write */
|
|
|
|
extern void calmaUnexpected(int wanted, int got);
|
|
extern int calmaWriteInitFunc(CellDef *def);
|
|
|
|
/*
|
|
* Scaling.
|
|
* Multiply all coordinates by calmaReadScale1, then divide them
|
|
* by calmaReadScale2 in order to get coordinates in centimicrons.
|
|
*/
|
|
int calmaReadScale1;
|
|
int calmaReadScale2;
|
|
|
|
int calmaTotalErrors;
|
|
|
|
/*
|
|
* Lookahead: calmaLApresent is TRUE when calmaLAnbytes and calmaLArtype
|
|
* are set to the record header of a record we just ungot.
|
|
*/
|
|
bool calmaLApresent; /* TRUE if lookahead input waiting */
|
|
int calmaLAnbytes; /* # bytes in record (from header) */
|
|
int calmaLArtype; /* Record type */
|
|
|
|
/*
|
|
* Hash table for errors, indexed by (layer, datatype).
|
|
* The corresponding entry in this table is created whenever
|
|
* a (layer, datatype) is seen that we don't recognize, so
|
|
* we don't output an error message more than once.
|
|
*/
|
|
HashTable calmaLayerHash;
|
|
|
|
/*
|
|
* Hash table to keep track of all defs that have appeared
|
|
* in this file. Indexed by cell def name.
|
|
*/
|
|
HashTable calmaDefInitHash;
|
|
|
|
/* Common stuff to ignore */
|
|
const int calmaElementIgnore[] = { CALMA_ELFLAGS, CALMA_PLEX, -1 };
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* CalmaReadFile --
|
|
*
|
|
* Read an entire GDS-II stream format library from the open FILE 'file'.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* May modify the contents of cifReadCellDef by painting or adding
|
|
* new uses or labels. May also create new CellDefs.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
CalmaReadFile(
|
|
FILETYPE file, /* File from which to read Calma */
|
|
char *filename) /* The real name of the file read */
|
|
{
|
|
int k, version;
|
|
char *libname = NULL, *libnameptr = NULL;
|
|
MagWindow *mw;
|
|
static const int hdrSkip[] = { CALMA_FORMAT, CALMA_MASK, CALMA_ENDMASKS,
|
|
CALMA_REFLIBS, CALMA_FONTS, CALMA_ATTRTABLE,
|
|
CALMA_STYPTABLE, CALMA_GENERATIONS, -1 };
|
|
static const int skipBeforeLib[] = { CALMA_LIBDIRSIZE, CALMA_SRFNAME,
|
|
CALMA_LIBSECUR, -1 };
|
|
|
|
if (EditCellUse == (CellUse *)NULL)
|
|
{
|
|
TxError("Cannot read GDS: There is no edit cell.\n");
|
|
return;
|
|
}
|
|
|
|
/* We will use full cell names as keys in this hash table */
|
|
CIFReadCellInit(0);
|
|
|
|
if (CIFWarningLevel == CIF_WARN_REDIRECT)
|
|
{
|
|
if (CIFErrorFilename == NULL)
|
|
calmaErrorFile = NULL;
|
|
else
|
|
calmaErrorFile = PaOpen(CIFErrorFilename, "w", (char *)NULL, ".",
|
|
(char *)NULL, (char **)NULL);
|
|
}
|
|
|
|
if (cifCurReadStyle == NULL)
|
|
{
|
|
TxError("Don't know how to read GDS-II:\n");
|
|
TxError("Nothing in \"cifinput\" section of tech file.\n");
|
|
return;
|
|
}
|
|
TxPrintf("Warning: Calma reading is not undoable! I hope that's OK.\n");
|
|
UndoDisable();
|
|
|
|
calmaTotalErrors = 0;
|
|
CalmaPolygonCount = 0;
|
|
CalmaPathCount = 0;
|
|
|
|
/* Reset cd_client pointers (using init function from CalmaWrite.c) */
|
|
/* This is in case a cell already in memory is being referenced; */
|
|
/* it is probably better to avoid those kinds of naming collisions */
|
|
/* though. . . */
|
|
(void) DBCellSrDefs(0, calmaWriteInitFunc, (ClientData) NULL);
|
|
|
|
HashInit(&calmaDefInitHash, 32, 0);
|
|
calmaLApresent = FALSE;
|
|
calmaInputFile = file;
|
|
|
|
/* Read the GDS-II header */
|
|
if (!calmaReadI2Record(CALMA_HEADER, &version)) goto done;
|
|
if (version < 600)
|
|
TxPrintf("Library written using GDS-II Release %d.0\n", version);
|
|
else
|
|
TxPrintf("Library written using GDS-II Release %d.%d\n",
|
|
version / 100, version % 100);
|
|
if (!calmaSkipExact(CALMA_BGNLIB)) goto done;
|
|
calmaSkipSet(skipBeforeLib);
|
|
if (!calmaReadStringRecord(CALMA_LIBNAME, &libname)) goto done;
|
|
|
|
/* Use CalmaDoLibrary similarly for input as for output; if set to */
|
|
/* TRUE, the library name is considered meaningless and discarded; */
|
|
/* the GDS file contents are read into memory but no view is loaded */
|
|
|
|
if (CalmaDoLibrary)
|
|
libnameptr = NULL;
|
|
else
|
|
libnameptr = libname;
|
|
|
|
if ((libnameptr != NULL) && (libname[0] != '\0'))
|
|
{
|
|
bool modified = FALSE;
|
|
char *sptr;
|
|
|
|
/* Avoid generating a magic name with spaces in it. . . */
|
|
/* (added by Mike Godfrey, 7/17/05) */
|
|
|
|
for (k = 0; k < strlen(libname); k++)
|
|
if (libname[k] == ' ')
|
|
{
|
|
libname[k] = '_';
|
|
modified = TRUE;
|
|
}
|
|
|
|
/* Avoid generating a magic name with slashes in it. . . */
|
|
/* (added by Tim, 8/26/2022) */
|
|
|
|
if ((sptr = strrchr(libname, '/')) != NULL)
|
|
{
|
|
libnameptr = sptr + 1;
|
|
modified = TRUE;
|
|
}
|
|
|
|
if (modified)
|
|
TxPrintf("Library name modified to make legal cell name syntax.\n");
|
|
TxPrintf("Library name: %s\n", libnameptr);
|
|
}
|
|
|
|
/* Skip the reflibs, fonts, etc. cruft */
|
|
calmaSkipSet(hdrSkip);
|
|
|
|
/* Set the scale factors */
|
|
if (!calmaParseUnits()) goto done;
|
|
|
|
/* Main body of GDS-II input */
|
|
while (calmaParseStructure(filename))
|
|
if (SigInterruptPending)
|
|
goto done;
|
|
(void) calmaSkipExact(CALMA_ENDLIB);
|
|
|
|
done:
|
|
|
|
/* Added by Nishit, Sept. 2004---Load cell read from GDS */
|
|
/* stream file to the magic layout window. If this fails */
|
|
/* then we do the original action and don't do a load into */
|
|
/* the window. Note that this follows the Magic GDS output */
|
|
/* convention of giving the library the name of the */
|
|
/* top-level cell, so magic-produced GDS can be read back */
|
|
/* with the expected cell appearing in the layout window. */
|
|
|
|
if (libnameptr != NULL)
|
|
{
|
|
mw = CmdGetRootPoint((Point *)NULL, (Rect *)NULL);
|
|
if (mw == NULL)
|
|
windCheckOnlyWindow(&mw, DBWclientID);
|
|
if (mw != NULL)
|
|
{
|
|
if (calmaLookCell(libnameptr) != (CellDef *)NULL)
|
|
DBWloadWindow(mw, libnameptr, 0);
|
|
}
|
|
freeMagic(libname);
|
|
}
|
|
|
|
CIFReadCellCleanup(FILE_CALMA);
|
|
HashKill(&calmaDefInitHash);
|
|
UndoEnable();
|
|
|
|
if (calmaErrorFile != NULL)
|
|
{
|
|
fclose(calmaErrorFile);
|
|
calmaErrorFile = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* calmaParseUnits --
|
|
*
|
|
* Process the CALMA_UNITS record that sets the relationship between
|
|
* user units (stored in the stream file) and centimicrons.
|
|
*
|
|
* Results:
|
|
* TRUE if successful, FALSE if we encountered an error and
|
|
* the caller should abort.
|
|
*
|
|
* Side effects:
|
|
* Consumes input.
|
|
* Sets calmaReadScale1 to the number of centimicrons per user
|
|
* unit, and calmaReadScale2 to 1, unless calmaReadScale1 would be
|
|
* less than 1, in which case we set calmaReadScale1 to 1 and
|
|
* calmaReadScale2 to 1/calmaReadScale1.
|
|
*
|
|
* NOTE:
|
|
* We don't care about user units, only database units. The
|
|
* GDS-II stream specifies the number of meters per database
|
|
* unit, which we use to compute the number of centimicrons
|
|
* per database unit. Since database units are floating point,
|
|
* there is a possibility of roundoff unless the number of
|
|
* centimicrons per user unit is an integer value.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
bool
|
|
calmaParseUnits(void)
|
|
{
|
|
int nbytes, rtype = 0;
|
|
double metersPerDBUnit;
|
|
double userUnitsPerDBUnit;
|
|
double cuPerDBUnit;
|
|
bool compatible;
|
|
|
|
READRH(nbytes, rtype);
|
|
#ifdef lint
|
|
nbytes = nbytes;
|
|
#endif /* lint */
|
|
|
|
if (rtype != CALMA_UNITS)
|
|
{
|
|
calmaUnexpected(CALMA_UNITS, rtype);
|
|
return (FALSE);
|
|
}
|
|
|
|
/* Skip user units per database unit */
|
|
if (!calmaReadR8(&userUnitsPerDBUnit)) return (FALSE);
|
|
|
|
/* Read meters per database unit */
|
|
if (!calmaReadR8(&metersPerDBUnit)) return (FALSE);
|
|
|
|
/* Important! When CalmaReadOnly is TRUE, then this file will have its
|
|
* contents output verbatim. But if the database units don't match,
|
|
* then it will get output at the wrong scale. Setting a magnification
|
|
* factor on the instance when generating output might (?) work. For
|
|
* now, prohibiting a GDS read in read-only mode when the database units
|
|
* don't match. This forces the user either to reconsider the read-only
|
|
* status or to rewrite the GDS at a compatible scalefactor.
|
|
*/
|
|
compatible = TRUE;
|
|
if (CalmaReadOnly == TRUE)
|
|
{
|
|
if (CIFCurStyle->cs_flags & CWF_ANGSTROMS)
|
|
{
|
|
if ((int)(0.5 + metersPerDBUnit * 1e12) != 100)
|
|
{
|
|
CalmaReadError("Incompatible scale factor of %g, must be 1e-10.\n",
|
|
metersPerDBUnit);
|
|
TxError("Cannot read this file in read-only mode.\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((int)(0.5 + metersPerDBUnit * 1e11) != 100)
|
|
{
|
|
CalmaReadError("Incompatible scale factor of %g, must be 1e-9.\n",
|
|
metersPerDBUnit);
|
|
TxError("Cannot read this file in read-only mode.\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef notdef
|
|
TxPrintf("1 database unit equals %e user units\n", userUnitsPerDBUnit);
|
|
TxPrintf("1 database unit equals %e meters\n", metersPerDBUnit);
|
|
TxPrintf("1 user unit equals %e database units\n", 1.0/userUnitsPerDBUnit);
|
|
TxPrintf("1 meter equals %e database units\n", 1.0/metersPerDBUnit);
|
|
#endif /* notdef */
|
|
|
|
/* Meters per database unit (1.0e8 corresponds to traditional centimicrons) */
|
|
cuPerDBUnit = metersPerDBUnit * 1.0e8 * cifCurReadStyle->crs_multiplier;
|
|
|
|
/*
|
|
* Multiply database units by calmaReadScale1, then divide
|
|
* by calmaReadScale2 to get CIF units. The current scheme
|
|
* relies entirely on calmaReadScale1 being an integer.
|
|
*/
|
|
if (cuPerDBUnit >= 1.0)
|
|
{
|
|
calmaReadScale1 = (int)(cuPerDBUnit + 0.5);
|
|
calmaReadScale2 = 1;
|
|
}
|
|
else
|
|
{
|
|
cuPerDBUnit = 1.0 / cuPerDBUnit;
|
|
calmaReadScale1 = 1;
|
|
calmaReadScale2 = (int)(cuPerDBUnit + 0.5);
|
|
}
|
|
#ifdef notdef
|
|
TxPrintf("All units to be scaled by %d/%d\n", calmaReadScale1, calmaReadScale2);
|
|
#endif /* notdef */
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* CalmaReadError --
|
|
*
|
|
* This procedure is called to print out error messages during
|
|
* Calma file reading.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* An error message is printed.
|
|
*
|
|
* Note:
|
|
* You can add more arguments if 10 turns out not to be enough.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
CalmaReadError(const char *format, ...)
|
|
{
|
|
va_list args;
|
|
OFFTYPE filepos;
|
|
|
|
calmaTotalErrors++;
|
|
if (CIFWarningLevel == CIF_WARN_NONE) return;
|
|
|
|
if ((calmaTotalErrors < 100) || (CIFWarningLevel != CIF_WARN_LIMIT))
|
|
{
|
|
filepos = FTELL(calmaInputFile);
|
|
|
|
if (CIFWarningLevel == CIF_WARN_REDIRECT)
|
|
{
|
|
if (calmaErrorFile != NULL)
|
|
{
|
|
fprintf(calmaErrorFile, "Error while reading cell \"%s\" ",
|
|
cifReadCellDef->cd_name);
|
|
fprintf(calmaErrorFile, "(byte position %"DLONG_PREFIX"d): ",
|
|
(dlong)filepos);
|
|
va_start(args, format);
|
|
Vfprintf(calmaErrorFile, format, args);
|
|
va_end(args);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TxError("Error while reading cell \"%s\" ", cifReadCellDef->cd_name);
|
|
TxError("(byte position %"DLONG_PREFIX"d): ", (dlong)filepos);
|
|
va_start(args, format);
|
|
TxErrorV(format, args);
|
|
va_end(args);
|
|
}
|
|
}
|
|
else if ((calmaTotalErrors == 100) && (CIFWarningLevel == CIF_WARN_LIMIT))
|
|
{
|
|
TxError("Error limit set: Remaining errors will not be reported.\n");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* calmaUnexpected --
|
|
*
|
|
* Complain about a record where we expected one kind but got another.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Prints an error message.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
calmaUnexpected(
|
|
int wanted, /* Type of record we wanted */
|
|
int got) /* Type of record we got */
|
|
{
|
|
CalmaReadError("Unexpected record type in input: \n");
|
|
|
|
if (CIFWarningLevel == CIF_WARN_NONE) return;
|
|
if (calmaTotalErrors < 100 || (CIFWarningLevel != CIF_WARN_LIMIT))
|
|
{
|
|
if (CIFWarningLevel == CIF_WARN_REDIRECT)
|
|
{
|
|
if (calmaErrorFile != NULL)
|
|
{
|
|
fprintf(calmaErrorFile," Expected %s record ",
|
|
calmaRecordName(wanted));
|
|
fprintf(calmaErrorFile, "but got %s.\n", calmaRecordName(got));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TxError(" Expected %s record ", calmaRecordName(wanted));
|
|
TxError("but got %s.\n", calmaRecordName(got));
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* calmaRecordName --
|
|
*
|
|
* Return a pointer to the printable name of a CALMA record type.
|
|
*
|
|
* Results:
|
|
* See above.
|
|
*
|
|
* Side effects:
|
|
* May overwrite the string we returned on the previous call.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
const char *
|
|
calmaRecordName(
|
|
int rtype)
|
|
{
|
|
static char numeric[10];
|
|
static const char * const calmaRecordNames[] =
|
|
{
|
|
"HEADER", "BGNLIB", "LIBNAME", "UNITS",
|
|
"ENDLIB", "BGNSTR", "STRNAME", "ENDSTR",
|
|
"BOUNDARY", "PATH", "SREF", "AREF",
|
|
"TEXT", "LAYER", "DATATYPE", "WIDTH",
|
|
"XY", "ENDEL", "SNAME", "COLROW",
|
|
"TEXTNODE", "NODE", "TEXTTYPE", "PRESENTATION",
|
|
"SPACING", "STRING", "STRANS", "MAG",
|
|
"ANGLE", "UINTEGER", "USTRING", "REFLIBS",
|
|
"FONTS", "PATHTYPE", "GENERATIONS", "ATTRTABLE",
|
|
"STYPTABLE", "STRTYPE", "ELFLAGS", "ELKEY",
|
|
"LINKTYPE", "LINKKEYS", "NODETYPE", "PROPATTR",
|
|
"PROPVALUE", "BOX", "BOXTYPE", "PLEX",
|
|
"BGNEXTN", "ENDEXTN", "TAPENUM", "TAPECODE",
|
|
"STRCLASS", "RESERVED", "FORMAT", "MASK",
|
|
"ENDMASKS"
|
|
};
|
|
|
|
if (rtype < 0 || rtype >= CALMA_NUMRECORDTYPES)
|
|
{
|
|
(void) sprintf(numeric, "%d", rtype);
|
|
return (numeric);
|
|
}
|
|
|
|
return (calmaRecordNames[rtype]);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* CalmaTechInit --
|
|
*
|
|
* Prepare for a technology file.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Error checking.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
CalmaTechInit(void)
|
|
{
|
|
ASSERT(sizeof(FourByteInt)==4, "definition in calmaInt.h");
|
|
ASSERT(sizeof(TwoByteInt)==2, "definition in calmaInt.h");
|
|
|
|
/* NOTE: Add "$$*$$" to the default "flatglob" value */
|
|
/* when CalmaContactArrays behaves like the non-arrayed */
|
|
/* function and can be enabled by default. */
|
|
|
|
/* Initialize CalmaFlattenByName to have one entry for */
|
|
/* "*_CDNS_*" to match the name style used by many foundry */
|
|
/* cells and which corresponds to pcells that often split */
|
|
/* layers between cells in ways that magic can't cope with; */
|
|
/* and whose original parameterized functions cannot be */
|
|
/* recovered by magic anyway. When necessary, this default */
|
|
/* can be overridden by the "gds flatglob none" command */
|
|
/* option. */
|
|
|
|
if (CalmaFlattenUsesByName == (char **)NULL)
|
|
{
|
|
CalmaFlattenUsesByName = (char **)mallocMagic(2 * sizeof(char *));
|
|
*CalmaFlattenUsesByName = StrDup((char **)NULL, "*_CDNS_*");
|
|
*(CalmaFlattenUsesByName + 1) = NULL;
|
|
}
|
|
}
|