Merge branch 'master' of https://github.com/RTimothyEdwards/magic into spice_hier

This commit is contained in:
Dan Moore 2021-02-06 07:45:57 -08:00
commit bbe256e77d
78 changed files with 5342 additions and 2810 deletions

View File

@ -1,5 +0,0 @@
[filter "header"]
smudge = ./.git-expand-header %f
clean = sed -e's/\\$Header:[^$]*\\$/\\$Header\\$/g'
[diff "gds"]
textconv = hexdump -v -C

4
.gitignore vendored
View File

@ -21,9 +21,13 @@ scmos/scmos-sub.tech
scmos/scmos-tm.tech
scmos/scmos.tech
scmos/scmosWR.tech
scmos/nmos.tech
tcltk/magic.sh
tcltk/magic.tcl
tcltk/magicdnull
tcltk/magicexec
tcltk/ext2spice.sh
tcltk/ext2sim.sh
magic/tclmagic.dylib
tcltk/magicdnull.dSYM/
tcltk/magicexec.dSYM/

View File

@ -1 +1 @@
8.3.82
8.3.124

View File

@ -290,6 +290,8 @@ calmaParseStructure(filename)
off_t filepos;
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 */
@ -299,6 +301,7 @@ calmaParseStructure(filename)
/* Read the structure name */
was_initialized = FALSE;
predefined = FALSE;
if (!calmaSkipExact(CALMA_BGNSTR)) goto syntaxerror;
if (!calmaReadStringRecord(CALMA_STRNAME, &strname)) goto syntaxerror;
TxPrintf("Reading \"%s\".\n", strname);
@ -345,16 +348,18 @@ calmaParseStructure(filename)
freeMagic(newname);
}
}
cifReadCellDef = calmaFindCell(strname, &was_called);
cifReadCellDef = calmaFindCell(strname, &was_called, &predefined);
if (predefined == TRUE)
{
calmaNextCell();
return TRUE;
}
DBCellClearDef(cifReadCellDef);
DBCellSetAvail(cifReadCellDef);
HashSetValue(he, cifReadCellDef);
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;
@ -403,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))
{
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;
/*
@ -411,13 +445,13 @@ 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. */
if ((cifReadCellDef->cd_client != (ClientData)CLIENTDEFAULT) &&
if ((cifReadCellDef->cd_client != (ClientData)0) &&
(cifReadCellDef->cd_flags & CDFLATGDS))
{
Plane **cifplanes = (Plane **)cifReadCellDef->cd_client;
@ -432,7 +466,7 @@ calmaParseStructure(filename)
}
}
freeMagic((char *)cifReadCellDef->cd_client);
cifReadCellDef->cd_client = (ClientData)CLIENTDEFAULT;
cifReadCellDef->cd_client = (ClientData)0;
}
TxPrintf("Saving contents of cell %s\n", cifReadCellDef->cd_name);
@ -610,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
@ -659,14 +693,14 @@ calmaElementSref(filename)
scalen = 1;
scaled = cifCurReadStyle->crs_multiplier / crsMultiplier;
}
CIFScalePlanes(scalen, scaled, cifCurReadPlanes);
CIFScalePlanes(scaled, scalen, cifCurReadPlanes);
}
}
else
{
TxPrintf("Cell definition %s does not exist!\n", sname);
fseek(calmaInputFile, originalFilePos, SEEK_SET);
def = calmaFindCell(sname, NULL);
def = calmaFindCell(sname, NULL, NULL);
/* Cell flags set to "dereferenced" in case there is no */
/* definition in the GDS file. If there is a definition */
/* made after the instance, then the flag will be cleared. */
@ -674,7 +708,7 @@ calmaElementSref(filename)
}
}
if (!def) def = calmaFindCell(sname, NULL);
if (!def) def = calmaFindCell(sname, NULL, NULL);
if (DBIsAncestor(def, cifReadCellDef))
{
@ -917,8 +951,7 @@ calmaElementSref(filename)
for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++)
{
if ((def->cd_client != (ClientData)CLIENTDEFAULT) &&
(gdsplanes[pNum] != NULL))
if ((def->cd_client != (ClientData)0) && (gdsplanes[pNum] != NULL))
{
gdsCopyRec.plane = cifCurReadPlanes[pNum];
if (isArray)
@ -1032,13 +1065,16 @@ gdsCopyPaintFunc(tile, gdsCopyRec)
*/
CellDef *
calmaFindCell(name, was_called)
calmaFindCell(name, was_called, predefined)
char *name; /* Name of desired cell */
bool *was_called; /* If this cell is in the hash table, then it
* was instanced before it was defined. We
* need to know this so as to avoid flattening
* the cell if requested.
*/
bool *predefined; /* If this cell was in memory before the GDS
* file was read, then this flag gets set.
*/
{
HashEntry *h;
@ -1060,6 +1096,16 @@ calmaFindCell(name, was_called)
*/
DBReComputeBbox(def);
}
else
{
TxPrintf("Warning: cell %s already existed before reading GDS!\n",
name);
if (CalmaNoDuplicates)
{
if (predefined) *predefined = TRUE;
TxPrintf("Using pre-existing cell definition\n");
}
}
HashSetValue(h, def);
if (was_called) *was_called = FALSE;
}

View File

@ -98,8 +98,8 @@ calmaInputRescale(n, d)
{
/* Scale the GDS planes in this cell's cd_client record */
Plane **gdsplanes = (Plane **)def->cd_client;
/* Should not happen, but punt if client record is not set */
if (def->cd_client != (ClientData)CLIENTDEFAULT)
/* Should not happen, but punt if client record is not set; */
if (def->cd_client != (ClientData)0)
CIFScalePlanes(n, d, gdsplanes);
}
}

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.
@ -77,7 +82,13 @@ bool CalmaPostOrder = FALSE; /* If TRUE, forces the GDS parser 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.
*/
extern void calmaUnexpected();
extern int calmaWriteInitFunc();
bool calmaParseUnits();
@ -172,6 +183,12 @@ CalmaReadFile(file, filename)
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;
@ -368,7 +385,7 @@ CalmaReadError(format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
{
fprintf(calmaErrorFile, "Error while reading cell \"%s\" ",
cifReadCellDef->cd_name);
fprintf(calmaErrorFile, "(byte position %"DLONG_PREFIX"ld): ",
fprintf(calmaErrorFile, "(byte position %"DLONG_PREFIX"d): ",
(dlong)filepos);
fprintf(calmaErrorFile, format, a1, a2, a3, a4, a5, a6, a7,
a8, a9, a10);

View File

@ -53,11 +53,13 @@ static char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic-8.0/c
#include "utils/stack.h"
/* Exports */
bool CalmaDoLibrary = FALSE; /* If TRUE, do not output the top level */
bool CalmaDoLabels = TRUE; /* If FALSE, don't output labels with GDS-II */
bool CalmaDoLower = TRUE; /* If TRUE, allow lowercase labels. */
bool CalmaFlattenArrays = FALSE; /* If TRUE, output arrays as individual uses */
bool CalmaAddendum = FALSE; /* If TRUE, do not output readonly cell defs */
bool CalmaDoLibrary = FALSE; /* If TRUE, do not output the top level */
bool CalmaDoLabels = TRUE; /* If FALSE, don't output labels with GDS-II */
bool CalmaDoLower = TRUE; /* If TRUE, allow lowercase labels. */
bool CalmaFlattenArrays = FALSE; /* If TRUE, output arrays as individual uses */
bool CalmaAddendum = FALSE; /* If TRUE, do not output readonly cell defs */
bool CalmaNoDateStamp = FALSE; /* If TRUE, output zero for creation date stamp */
bool CalmaAllowUndefined = FALSE; /* If TRUE, allow calls to undefined cells */
/* Experimental stuff---not thoroughly tested (as of Sept. 2007)! */
bool CalmaContactArrays = FALSE; /* If TRUE, output contacts as subcell arrays */
@ -304,7 +306,12 @@ CalmaWrite(rootDef, f)
*/
dummy.cu_def = rootDef;
DBCellReadArea(&dummy, &rootDef->cd_bbox);
if (DBCellReadArea(&dummy, &rootDef->cd_bbox, !CalmaAllowUndefined))
{
TxError("Failure to read entire subtree of the cell.\n");
return FALSE;
}
DBFixMismatch();
/*
@ -396,7 +403,10 @@ calmaDumpStructure(def, outf, calmaDefHash, filename)
/* Output structure begin */
calmaOutRH(28, CALMA_BGNSTR, CALMA_I2, outf);
calmaOutDate(def->cd_timestamp, outf);
if (CalmaNoDateStamp)
calmaOutDate(time((time_t *) 0), outf);
else
calmaOutDate(def->cd_timestamp, outf);
calmaOutDate(time((time_t *) 0), outf);
/* Find the structure's unique prefix, in case structure calls subcells */
@ -799,15 +809,19 @@ calmaProcessDef(def, outf, do_library)
if (isReadOnly && hasContent && CalmaAddendum) return (0);
/* Give some feedback to the user */
TxPrintf(" Writing cell %s\n", def->cd_name);
/*
* Output the definitions for any of our descendants that have
* not already been output. Numbers are assigned to the subcells
* as they are output.
* as they are output. If the cell will get a "full dump" (by
* having GDS_START but no GDS_END), then do not output any subcells,
* as they are expected to be in the referenced GDS file.
*/
(void) DBCellEnum(def, calmaProcessUse, (ClientData) outf);
if (!hasContent || hasGDSEnd)
if (DBCellEnum(def, calmaProcessUse, (ClientData) outf) != 0)
return 1;
/* Give some feedback to the user */
TxPrintf(" Generating output for cell %s\n", def->cd_name);
if (isReadOnly && hasContent)
{
@ -826,14 +840,22 @@ calmaProcessDef(def, outf, do_library)
/* This is a rare error, but if the subcell is inside */
/* another vendor GDS, it would not normally be output. */
DBPropGet(def->cd_parents->cu_parent, "GDS_FILE", &isReadOnly);
if (!isReadOnly || isAbstract)
TxError("Calma output error: Can't find GDS file \"%s\" "
"for vendor cell \"%s\". Using magic's "
"internal definition\n", filename,
def->cd_name);
DBPropGet((def->cd_parents->cu_parent == NULL) ? def :
def->cd_parents->cu_parent, "GDS_FILE", &isReadOnly);
if (isReadOnly)
{
def->cd_flags |= CDVENDORGDS;
return 0; /* Ignore without raising an error */
}
TxError("Calma output error: Can't find GDS file \"%s\" "
"for vendor cell \"%s\". It will not be output.\n",
filename, def->cd_name);
if (CalmaAllowUndefined)
return 0;
else
return 1;
}
else if (isAbstract || (!hasGDSEnd))
{
@ -867,7 +889,10 @@ calmaProcessDef(def, outf, do_library)
/* Output structure header */
calmaOutRH(28, CALMA_BGNSTR, CALMA_I2, outf);
calmaOutDate(def->cd_timestamp, outf);
if (CalmaNoDateStamp)
calmaOutDate(time((time_t *) 0), outf);
else
calmaOutDate(def->cd_timestamp, outf);
calmaOutDate(time((time_t *) 0), outf);
/* Name structure the same as the magic cellname */
@ -922,7 +947,7 @@ calmaProcessDef(def, outf, do_library)
if (!do_library)
calmaOutFunc(def, outf, &TiPlaneRect);
return (0);
return 0;
}
@ -964,7 +989,10 @@ calmaOutFunc(def, f, cliprect)
/* Output structure begin */
calmaOutRH(28, CALMA_BGNSTR, CALMA_I2, f);
calmaOutDate(def->cd_timestamp, f);
if (CalmaNoDateStamp)
calmaOutDate(time((time_t *) 0), f);
else
calmaOutDate(def->cd_timestamp, f);
calmaOutDate(time((time_t *) 0), f);
/* Output structure name */
@ -2693,7 +2721,10 @@ calmaOutHeader(rootDef, f)
/* Beginning of library */
calmaOutRH(28, CALMA_BGNLIB, CALMA_I2, f);
calmaOutDate(rootDef->cd_timestamp, f);
if (CalmaNoDateStamp)
calmaOutDate(time((time_t *) 0), f);
else
calmaOutDate(rootDef->cd_timestamp, f);
calmaOutDate(time((time_t *) 0), f);
/* Library name (name of root cell) */

View File

@ -31,13 +31,17 @@ extern bool CalmaDoLabels;
extern bool CalmaDoLibrary;
extern bool CalmaDoLower;
extern bool CalmaAddendum;
extern bool CalmaNoDuplicates;
extern bool CalmaNoDateStamp;
extern bool CalmaMergeTiles;
extern bool CalmaFlattenArrays;
extern bool CalmaNoDRCCheck;
extern bool CalmaFlattenUses;
extern char **CalmaFlattenUsesByName;
extern bool CalmaReadOnly;
extern bool CalmaContactArrays;
extern bool CalmaPostOrder;
extern bool CalmaAllowUndefined;
/* Externally-visible procedures: */
extern bool CalmaWrite();

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#endif /* not lint */
#include <stdio.h>
#include <string.h>
#include "tcltk/tclmagic.h"
#include "utils/magic.h"
@ -201,6 +202,193 @@ cifHierCleanup()
SigEnableInterrupts();
}
/*
* ----------------------------------------------------------------------------
*
* cifMaskHints --
*
* Copy a mask hint into a target cell by adding it to the
* property list of the target cell. If the target cell already
* has the same mask hint key, then the mask hint value is
* appended to the property in the target cell def.
*
* Returns:
* 0 to keep the search going.
*
* Side effects:
* Modifies properties of the target cell def.
*
* ----------------------------------------------------------------------------
*/
int
cifMaskHints(name, value, targetDef)
char *name;
char *value;
CellDef *targetDef;
{
char *propvalue, *newval;
bool propfound;
if (!strncmp(name, "MASKHINTS_", 10))
{
/* Check if name exists already in the flattened cell */
propvalue = (char *)DBPropGet(targetDef, name, &propfound);
if (propfound)
{
/* Append value to the property */
newval = mallocMagic(strlen(value) + strlen(propvalue) + 2);
sprintf(newval, "%s %s", propvalue, value);
}
else
newval = StrDup((char **)NULL, value);
DBPropPut(targetDef, name, newval);
}
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* CIFCopyMaskHints --
*
* Callback function to copy mask hints from one cell into another.
*
* Results:
* None.
*
* Side effects:
* May modify properties in the target cell.
*
* ----------------------------------------------------------------------------
*/
void
CIFCopyMaskHints(sourceDef, targetDef)
CellDef *sourceDef;
CellDef *targetDef;
{
DBPropEnum(sourceDef, cifMaskHints, targetDef);
}
/* Structure used by cifFlatMaskHints, below */
typedef struct _maskHintsData
{
Transform *mh_trans;
CellDef *mh_def;
} MaskHintsData;
/*
* ----------------------------------------------------------------------------
*
* cifFlatMaskHints --
*
* Copy a mask hint into a flattened cell by transforming it into the
* coordinate system of the flattened cell, and adding it to the
* property list of the flattened cell.
*
* Returns:
* 0 to keep the search going.
*
* Side effects:
* Modifies properties of the cell def passed in MaskHintsData.
*
* ----------------------------------------------------------------------------
*/
int
cifFlatMaskHints(name, value, mhd)
char *name;
char *value;
MaskHintsData *mhd;
{
Rect r, newr;
char *vptr, *newval, *lastval, *propvalue;
bool propfound;
int lastlen;
if (!strncmp(name, "MASKHINTS_", 10))
{
newval = (char *)NULL;
vptr = value;
while (*vptr != '\0')
{
if (sscanf(vptr, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
&r.r_xtop, &r.r_ytop) == 4)
{
/* Transform rectangle to top level coordinates */
GeoTransRect(mhd->mh_trans, &r, &newr);
lastval = newval;
lastlen = (lastval) ? strlen(lastval) : 0;
newval = mallocMagic(40 + lastlen);
if (lastval)
strcpy(newval, lastval);
else
*newval = '\0';
sprintf(newval + lastlen, "%s%d %d %d %d", (lastval) ? " " : "",
newr.r_xbot, newr.r_ybot, newr.r_xtop, newr.r_ytop);
if (lastval) freeMagic(lastval);
/* Parse through the four values and check if there's more */
while (*vptr && !isspace(*vptr)) vptr++;
while (*vptr && isspace(*vptr)) vptr++;
while (*vptr && !isspace(*vptr)) vptr++;
while (*vptr && isspace(*vptr)) vptr++;
while (*vptr && !isspace(*vptr)) vptr++;
while (*vptr && isspace(*vptr)) vptr++;
while (*vptr && !isspace(*vptr)) vptr++;
while (*vptr && isspace(*vptr)) vptr++;
}
}
/* Check if name exists already in the flattened cell */
propvalue = (char *)DBPropGet(mhd->mh_def, name, &propfound);
if (propfound)
{
/* Append newval to the property */
lastval = newval;
newval = mallocMagic(strlen(lastval) + strlen(propvalue) + 2);
sprintf(newval, "%s %s", propvalue, lastval);
freeMagic(lastval);
}
DBPropPut(mhd->mh_def, name, newval);
}
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* cifHierCopyMaskHints --
*
* Callback function to copy mask hints from a subcell into a flattened
* cell, which is passed in the clientData record.
*
* Results:
* Always returns 0 to keep the search alive.
*
* Side effects:
* May modify properties in the flattened cell.
*
* ----------------------------------------------------------------------------
*/
int
cifHierCopyMaskHints(scx, clientData)
SearchContext *scx;
ClientData clientData;
{
MaskHintsData mhd;
mhd.mh_trans = &scx->scx_trans;
mhd.mh_def = (CellDef *)clientData;
DBPropEnum(scx->scx_use->cu_def, cifFlatMaskHints, &mhd);
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -245,9 +433,8 @@ cifHierCopyFunc(tile, cxp)
if (cxp->tc_scx->scx_use->cu_def->cd_flags & CDVENDORGDS)
{
if (!CIFCurStyle)
return 0;
else if (!(CIFCurStyle->cs_flags & CWF_SEE_VENDOR))
return 0;
if (!(CIFCurStyle->cs_flags & CWF_SEE_NO_VENDOR))
return 0;
}
/* Ignore space tiles, since they won't do anything anyway. */
@ -320,6 +507,11 @@ cifHierCellFunc(scx)
(void) DBTreeSrTiles(&newscx, &CIFCurStyle->cs_yankLayers, 0,
cifHierCopyFunc, (ClientData) CIFComponentDef);
/* Flatten mask hints in the area of interest */
CIFCopyMaskHints(scx->scx_use->cu_def, CIFComponentDef);
DBTreeSrCells(&newscx, 0, cifHierCopyMaskHints,
(ClientData)CIFComponentDef);
/* Set CIFErrorDef to NULL to ignore errors here... these will
* get reported anyway when the cell is CIF'ed non-hierarchically,
* so there's no point in making a second report here.
@ -421,6 +613,44 @@ cifHierCheckFunc(tile, plane)
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* cifHierTempCheckFunc --
*
* This function is like cifHierCheckFunc() (see above), but is used
* for "templayers", where any parent/child disagreement should be
* considered a non-issue as far as output is concerned. Only the
* actual mask layer will report any problems.
*
* Results:
* Always returns 0 to keep the search alive.
*
* Side effects:
* Error messages may be output.
*
* ----------------------------------------------------------------------------
*/
int
cifHierTempCheckFunc(tile, plane)
Tile *tile; /* Tile containing CIF. */
Plane *plane; /* Plane to check against and modify. */
{
Rect area;
TiToRect(tile, &area);
if (IsSplit(tile))
DBNMPaintPlane(plane, TiGetTypeExact(tile), &area, CIFEraseTable,
(PaintUndoInfo *) NULL);
else
DBPaintPlane(plane, &area, CIFEraseTable, (PaintUndoInfo *) NULL);
CIFTileOps++;
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -490,9 +720,14 @@ cifCheckAndErase(style)
{
CIFErrorLayer = i;
if (CIFComponentPlanes[i] == NULL) continue;
(void) DBSrPaintArea((Tile *) NULL, CIFComponentPlanes[i],
&TiPlaneRect, &CIFSolidBits, cifHierCheckFunc,
(ClientData) CIFTotalPlanes[i]);
if (CIFCurStyle->cs_layers[i]->cl_flags & CIF_TEMP)
(void) DBSrPaintArea((Tile *) NULL, CIFComponentPlanes[i],
&TiPlaneRect, &CIFSolidBits, cifHierTempCheckFunc,
(ClientData) CIFTotalPlanes[i]);
else
(void) DBSrPaintArea((Tile *) NULL, CIFComponentPlanes[i],
&TiPlaneRect, &CIFSolidBits, cifHierCheckFunc,
(ClientData) CIFTotalPlanes[i]);
}
}
@ -595,6 +830,11 @@ CIFGenSubcells(def, area, output)
GEO_EXPAND(&interaction, CIFCurStyle->cs_radius, &scx.scx_area);
(void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0,
cifHierCopyFunc, (ClientData) CIFTotalDef);
/* Flatten mask hints in the area of interest */
CIFCopyMaskHints(def, CIFTotalDef);
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
(ClientData)CIFTotalDef);
CIFErrorDef = def;
CIFGen(CIFTotalDef, def, &interaction, CIFTotalPlanes,
&CIFCurStyle->cs_hierLayers, TRUE, TRUE, TRUE,
@ -720,10 +960,16 @@ cifHierElementFunc(use, transform, x, y, checkArea)
scx.scx_use = use;
(void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0,
cifHierCopyFunc, (ClientData) CIFTotalDef);
CIFCopyMaskHints(use->cu_def, CIFTotalDef);
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
(ClientData)CIFTotalDef);
DBCellClearDef(CIFComponentDef);
(void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0,
cifHierCopyFunc, (ClientData) CIFComponentDef);
CIFCopyMaskHints(use->cu_def, CIFComponentDef);
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
(ClientData)CIFComponentDef);
CIFErrorDef = (CellDef *) NULL;
CIFGen(CIFComponentDef, use->cu_def, checkArea, CIFComponentPlanes,

View File

@ -142,6 +142,7 @@ typedef struct cifop
* CIFOP_CLOSE - Added 11/25/19---close up areas smaller than indicated
* CIFOP_BRIDGE - Added 6/11/20---Bridge across catecorner gaps
* CIFOP_BRIDGELIM - Added 27/07/20---Bridge across catecorner gaps, but with limiting layers
* CIFOP_MASKHINTS - Added 12/14/20---Add geometry from cell properties, if any.
*/
#define CIFOP_AND 1
@ -166,6 +167,7 @@ typedef struct cifop
#define CIFOP_CLOSE 20
#define CIFOP_BRIDGE 21
#define CIFOP_BRIDGELIM 22
#define CIFOP_MASKHINTS 23
/* Added by Tim 10/21/2004 */
@ -224,12 +226,9 @@ typedef struct
*
* CIF_TEMP: Means that this is a temporary layer used to build
* up CIF information. It isn't output in the CIF file.
* CIF_BBOX_TOP: Indicates that the bounding box rectangle should
* only be generated if the cell is a top-level cell.
*/
#define CIF_TEMP 1
#define CIF_BBOX_TOP 2
/* The following data structure describes a complete set of CIF
* layers. The number of CIF layers (MAXCIFLAYERS) must not be
@ -307,8 +306,8 @@ typedef struct cifstyle
#define CWF_GROW_SLIVERS 0x02
#define CWF_ANGSTROMS 0x04
#define CWF_GROW_EUCLIDEAN 0x08
#define CWF_SEE_VENDOR 0x10 /* Override vendor GDS flag in cells */
#define CWF_NO_ERRORS 0x20 /* Do not generate error msgs and fdbk */
#define CWF_SEE_NO_VENDOR 0x10 /* Hide magic's GDS from vendor cells */
#define CWF_NO_ERRORS 0x20 /* Do not generate error msgs and fdbk */
#define CWF_STRING_LIMIT 0x40 /* Use older Calma format character limit */
/* procedures */
@ -321,7 +320,9 @@ extern void CIFClearPlanes();
extern Plane *CIFGenLayer();
extern void CIFInitCells();
extern int cifHierCopyFunc();
extern int cifHierCopyMaskHints();
extern void CIFLoadStyle();
extern void CIFCopyMaskHints();
/* Shared variables and structures: */

View File

@ -259,7 +259,8 @@ CIFSetStyle(name)
* print out the valid styles.
*/
{
CIFKeep *style, *match;
CIFKeep *style, *match, *exactmatch;
bool ambiguous = FALSE;
int length;
if (name == NULL) return;
@ -269,18 +270,25 @@ CIFSetStyle(name)
for (style = CIFStyleList; style != NULL; style = style->cs_next)
{
if (strncmp(name, style->cs_name, length) == 0)
if (!strcmp(name, style->cs_name)) {
match = style;
ambiguous = FALSE;
break;
}
else if (!strncmp(name, style->cs_name, length))
{
if (match != NULL)
{
TxError("CIF output style \"%s\" is ambiguous.\n", name);
CIFPrintStyle(FALSE, TRUE, TRUE);
return;
}
if (match != NULL) ambiguous = TRUE;
match = style;
}
}
if (ambiguous)
{
TxError("CIF output style \"%s\" is ambiguous.\n", name);
CIFPrintStyle(FALSE, TRUE, TRUE);
return;
}
if (match != NULL)
{
CIFLoadStyle(match->cs_name);

View File

@ -386,8 +386,10 @@ CIFInputRescale(n, d)
}
}
CIFScalePlanes(n, d, cifEditCellPlanes);
if (cifEditCellPlanes != cifSubcellPlanes)
CIFScalePlanes(n, d, cifCurReadPlanes);
if (cifCurReadPlanes != cifEditCellPlanes)
CIFScalePlanes(n, d, cifEditCellPlanes);
if (cifEditCellPlanes != cifSubcellPlanes && cifCurReadPlanes != cifSubcellPlanes)
CIFScalePlanes(n, d, cifSubcellPlanes);
CIFReadWarning("CIF style %s: units rescaled by factor of %d / %d\n",
@ -603,13 +605,13 @@ CIFPaintCurrent(filetype)
Plane **parray;
extern char *(cifReadLayers[MAXCIFRLAYERS]);
/* NOTE: There should be no need to check for cd_client
* here as cd_client should not be CLIENTDEFAULT if CDFLATGDS
* is set in flags. This condition has occurred, though, and
* needs to be debugged.
/* NOTE: The condition cd_client == 0 when CDFLATGDS
* indicates that the cell was already in memory when the
* GDS was read. This condition should be properly caught
* and handled.
*/
if ((cifReadCellDef->cd_flags & CDFLATGDS) &&
(cifReadCellDef->cd_client != (ClientData)CLIENTDEFAULT))
(cifReadCellDef->cd_client != (ClientData)0))
parray = (Plane **)cifReadCellDef->cd_client;
else
{
@ -1499,7 +1501,7 @@ CIFReadCellCleanup(filetype)
UndoDisable();
/* cifplanes should be valid, but don't crash magic if not */
if (cifplanes != (Plane **)CLIENTDEFAULT)
if (cifplanes != (Plane **)0)
{
for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++)
@ -1512,7 +1514,7 @@ CIFReadCellCleanup(filetype)
}
freeMagic((char *)def->cd_client);
}
def->cd_client = (ClientData)CLIENTDEFAULT;
def->cd_client = (ClientData)0;
#if 0
/* If the CDFLATTENED flag was not set, then this geometry */

View File

@ -21,6 +21,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#endif /* not lint */
#include <stdio.h>
#include "tcltk/tclmagic.h"
#include "utils/magic.h"
#include "utils/geometry.h"
#include "tiles/tile.h"
@ -162,6 +163,10 @@ CIFPaintLayer(rootDef, area, cifLayer, magicLayer, paintDef)
scx.scx_trans = GeoIdentityTransform;
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
cifHierCopyFunc, (ClientData) CIFComponentDef);
CIFCopyMaskHints(rootDef, CIFComponentDef);
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
(ClientData)CIFComponentDef);
oldCount = DBWFeedbackCount;
CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE, FALSE,
@ -278,6 +283,10 @@ CIFSeeLayer(rootDef, area, layer)
scx.scx_trans = GeoIdentityTransform;
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
cifHierCopyFunc, (ClientData) CIFComponentDef);
CIFCopyMaskHints(rootDef, CIFComponentDef);
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
(ClientData)CIFComponentDef);
oldCount = DBWFeedbackCount;
CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE,
FALSE, (ClientData)NULL);
@ -414,10 +423,11 @@ typedef struct {
} coverstats;
void
CIFCoverageLayer(rootDef, area, layer)
CIFCoverageLayer(rootDef, area, layer, dolist)
CellDef *rootDef; /* Def in which to compute CIF coverage */
Rect *area; /* Area in which to compute coverage */
char *layer; /* CIF layer for coverage computation. */
bool dolist; /* If TRUE, report only the value, in decimal */
{
coverstats cstats;
int i, scale;
@ -443,6 +453,10 @@ CIFCoverageLayer(rootDef, area, layer)
scx.scx_trans = GeoIdentityTransform;
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
cifHierCopyFunc, (ClientData) CIFComponentDef);
CIFCopyMaskHints(rootDef, CIFComponentDef);
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
(ClientData)CIFComponentDef);
CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE,
FALSE, (ClientData)NULL);
DBCellClearDef(CIFComponentDef);
@ -470,12 +484,26 @@ CIFCoverageLayer(rootDef, area, layer)
atotal = (long long)(cstats.bounds.r_xtop - cstats.bounds.r_xbot);
atotal *= (long long)(cstats.bounds.r_ytop - cstats.bounds.r_ybot);
TxPrintf("%s Area = %lld CIF units^2\n", doBox ? "Cursor Box" :
if (dolist)
{
#ifdef MAGIC_WRAPPER
Tcl_Obj *pobj;
pobj = Tcl_NewDoubleObj((double)fcover);
Tcl_SetObjResult(magicinterp, pobj);
#else
TxPrintf("%g\n", fcover);
#endif
}
else
{
TxPrintf("%s Area = %lld CIF units^2\n", doBox ? "Cursor Box" :
"Cell", btotal);
TxPrintf("Layer Bounding Area = %lld CIF units^2\n", atotal);
TxPrintf("Layer Total Area = %lld CIF units^2\n", cstats.coverage);
TxPrintf("Coverage in %s = %1.1f%%\n", doBox ? "box" :
TxPrintf("Layer Bounding Area = %lld CIF units^2\n", atotal);
TxPrintf("Layer Total Area = %lld CIF units^2\n", cstats.coverage);
TxPrintf("Coverage in %s = %1.1f%%\n", doBox ? "box" :
"cell", 100.0 * fcover);
}
}
int

View File

@ -991,8 +991,8 @@ CIFTechLine(sectionName, argc, argv)
CIFCurStyle->cs_flags |= CWF_PERMISSIVE_LABELS;
else if (strcmp(argv[i], "grow-euclidean") == 0)
CIFCurStyle->cs_flags |= CWF_GROW_EUCLIDEAN;
else if (strcmp(argv[i], "see-vendor") == 0)
CIFCurStyle->cs_flags |= CWF_SEE_VENDOR;
else if (strcmp(argv[i], "see-no-vendor") == 0)
CIFCurStyle->cs_flags |= CWF_SEE_NO_VENDOR;
else if (strcmp(argv[i], "no-errors") == 0)
CIFCurStyle->cs_flags |= CWF_NO_ERRORS;
else if (strcmp(argv[i], "string-limit") == 0)
@ -1054,6 +1054,8 @@ CIFTechLine(sectionName, argc, argv)
newOp->co_opcode = CIFOP_MAXRECT;
else if (strcmp(argv[0], "boundary") == 0)
newOp->co_opcode = CIFOP_BOUNDARY;
else if (strcmp(argv[0], "mask-hints") == 0)
newOp->co_opcode = CIFOP_MASKHINTS;
else if (strcmp(argv[0], "close") == 0)
newOp->co_opcode = CIFOP_CLOSE;
else if (strcmp(argv[0], "bridge") == 0)
@ -1247,6 +1249,11 @@ bloatCheck:
&newOp->co_cifMask, FALSE);
break;
case CIFOP_MASKHINTS:
if (argc != 2) goto wrongNumArgs;
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
break;
case CIFOP_MAXRECT:
if (argc == 2)
{
@ -1537,10 +1544,12 @@ cifComputeRadii(layer, des)
for (op = layer->cl_ops; op != NULL; op = op->co_next)
{
/* BBOX and NET operators should never be used hierarchically */
/* so ignore any grow/shrink operators that come after them. */
/* BBOX, NET, and MASKHINTS operators should never be used */
/* hierarchically so ignore any grow/shrink operators that */
/* come after them. */
if (op->co_opcode == CIFOP_BBOX || op->co_opcode == CIFOP_NET)
if (op->co_opcode == CIFOP_BBOX || op->co_opcode == CIFOP_NET ||
op->co_opcode == CIFOP_MASKHINTS)
break;
/* If CIF layers are used, switch to the max of current
@ -1565,11 +1574,11 @@ cifComputeRadii(layer, des)
switch (op->co_opcode)
{
case CIFOP_AND: break;
case CIFOP_ANDNOT: break;
case CIFOP_OR: break;
case CIFOP_AND:
case CIFOP_ANDNOT:
case CIFOP_OR:
case CIFOP_MASKHINTS:
break;
case CIFOP_GROW:
case CIFOP_GROWMIN:
@ -1850,13 +1859,15 @@ CIFTechFinal()
/* Presence of op->co_opcode in CIFOP_OR indicates a copy */
/* of the SquaresData pointer from a following operator */
/* CIFOP_BBOX and CIFOP_MAXRECT uses the co_client field */
/* as a flag field, while CIFOP_NET uses it for a string. */
/* as a flag field, while CIFOP_NET and CIFOP_MASKHINTS */
/* uses it for a string. */
else
{
switch (op->co_opcode)
{
case CIFOP_OR:
case CIFOP_BBOX:
case CIFOP_MASKHINTS:
case CIFOP_BOUNDARY:
case CIFOP_MAXRECT:
case CIFOP_NET:
@ -2388,6 +2399,7 @@ CIFTechOutputScale(n, d)
case CIFOP_OR:
case CIFOP_BBOX:
case CIFOP_BOUNDARY:
case CIFOP_MASKHINTS:
case CIFOP_MAXRECT:
case CIFOP_NET:
break;
@ -2425,7 +2437,7 @@ CIFTechOutputScale(n, d)
/* Reduce the scale and all distances by the greatest common */
/* factor of everything. */
/* fprintf(stderr, "All CIF units divisible by %d\n", lexpand); */
/* fprintf(stderr, "All CIF units divisible by %d\n", lexpand); */
/* fflush(stderr); */
lgcf = FindGCF(ostyle->cs_scaleFactor, ostyle->cs_expander);
@ -2502,9 +2514,10 @@ CIFTechOutputScale(n, d)
bridge->br_width /= lexpand;
break;
default:
/* op->co_opcode in CIFOP_OR is a pointer copy */
/* and in CIFOP_BBOX and CIFOP_MAXRECT is a */
/* flag, and in CIFOP_NET is a string. */
/* op->co_opcode in CIFOP_OR is a pointer copy, */
/* in CIFOP_BBOX and CIFOP_MAXRECT is a flag, */
/* and in CIFOP_NET and CIFOP_MASKHINTS is a */
/* string. */
break;
}
}

View File

@ -132,14 +132,18 @@ CIFWrite(rootDef, f)
*/
dummy.cu_def = rootDef;
DBCellReadArea(&dummy, &rootDef->cd_bbox);
if (DBCellReadArea(&dummy, &rootDef->cd_bbox, TRUE))
{
TxError("Failure to read in entire subtree of the cell.\n");
return (FALSE);
}
DBFixMismatch();
if (CIFCurStyle->cs_reducer == 0)
{
TxError("The current CIF output style can only be used for writing\n");
TxError("Calma output. Try picking another output style.\n");
return (TRUE);
return (FALSE);
}
/*

View File

@ -94,18 +94,22 @@ 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_READ 11
#define CALMA_READONLY 12
#define CALMA_RESCALE 13
#define CALMA_WARNING 14
#define CALMA_WRITE 15
#define CALMA_POLYS 16
#define CALMA_PATHS 17
#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_UNDEFINED 21
#define CALMA_WARN_HELP CIF_WARN_END /* undefined by CIF module */
@ -122,7 +126,9 @@ CmdCalma(w, cmd)
extern int CalmaFlattenLimit;
static char *gdsExts[] = {".gds", ".gds2", ".strm", "", NULL};
static char *cmdCalmaYesNo[] = { "no", "false", "off", "yes", "true", "on", 0 };
static char *cmdCalmaYesNo[] = {
"no", "false", "off", "0", "yes", "true", "on", "1", 0 };
static char *cmdCalmaAllowDisallow[] = {"disallow", "0", "allow", "1", 0};
static char *cmdCalmaWarnOptions[] = { "default", "none", "align",
"limit", "redirect", "help", 0 };
static char *cmdCalmaOption[] =
@ -133,11 +139,14 @@ 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",
"lower [yes|no] allow both upper and lower case in labels",
"merge [yes|no] merge tiles into polygons in the output",
"noduplicates [yes|no] do not read cells that exist before reading GDS",
"nodatestamp [yes|no] write a zero value creation date stamp",
"read file read Calma GDS-II format from \"file\"\n"
" into edit cell",
"readonly [yes|no] set cell as read-only and generate output from GDS file",
@ -149,6 +158,8 @@ CmdCalma(w, cmd)
" put non-Manhattan polygons into subcells",
"path subcells [yes|no]\n"
" put wire paths into individual subcells",
"undefined [allow|disallow]\n"
" [dis]allow writing of GDS with calls to undefined cells",
NULL
};
@ -220,15 +231,16 @@ CmdCalma(w, cmd)
else if (cmd->tx_argc != 3)
{
wrongNumArgs:
TxError("Wrong number of arguments in \"gds\" command.");
TxError(" Try \":gds help\" for help.\n");
TxError("Wrong number of arguments in \"%s\" command.",
cmd->tx_argv[0]);
TxError(" Try \":%s help\" for help.\n", cmd->tx_argv[0]);
return;
}
option = Lookup(cmd->tx_argv[2], cmdCalmaYesNo);
if (option < 0)
goto wrongNumArgs;
CalmaDoLabels = (option < 3) ? FALSE : TRUE;
CalmaDoLabels = (option < 4) ? FALSE : TRUE;
return;
case CALMA_LIBRARY:
@ -248,7 +260,7 @@ CmdCalma(w, cmd)
option = Lookup(cmd->tx_argv[2], cmdCalmaYesNo);
if (option < 0)
goto wrongNumArgs;
CalmaDoLibrary = (option < 3) ? FALSE : TRUE;
CalmaDoLibrary = (option < 4) ? FALSE : TRUE;
return;
case CALMA_ADDENDUM:
@ -268,7 +280,27 @@ CmdCalma(w, cmd)
option = Lookup(cmd->tx_argv[2], cmdCalmaYesNo);
if (option < 0)
goto wrongNumArgs;
CalmaAddendum = (option < 3) ? FALSE : TRUE;
CalmaAddendum = (option < 4) ? FALSE : TRUE;
return;
case CALMA_UNDEFINED:
if (cmd->tx_argc == 2)
{
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewBooleanObj(CalmaAllowUndefined));
#else
TxPrintf("Writing of GDS file with undefined cells is %sallowed.\n",
(CalmaAllowUndefined) ? "" : "dis");
#endif
return;
}
else if (cmd->tx_argc != 3)
goto wrongNumArgs;
option = Lookup(cmd->tx_argv[2], cmdCalmaAllowDisallow);
if (option < 0)
goto wrongNumArgs;
CalmaAllowUndefined = (option < 2) ? FALSE : TRUE;
return;
case CALMA_CONTACTS:
@ -290,7 +322,7 @@ CmdCalma(w, cmd)
option = Lookup(cmd->tx_argv[2], cmdCalmaYesNo);
if (option < 0)
goto wrongNumArgs;
CalmaContactArrays = (option < 3) ? FALSE : TRUE;
CalmaContactArrays = (option < 4) ? FALSE : TRUE;
return;
case CALMA_DRCCHECK:
@ -310,7 +342,7 @@ CmdCalma(w, cmd)
option = Lookup(cmd->tx_argv[2], cmdCalmaYesNo);
if (option < 0)
goto wrongNumArgs;
CalmaNoDRCCheck = (option < 3) ? TRUE : FALSE;
CalmaNoDRCCheck = (option < 4) ? TRUE : FALSE;
return;
case CALMA_FLATTEN:
@ -341,7 +373,103 @@ CmdCalma(w, cmd)
goto wrongNumArgs;
}
else
CalmaFlattenUses = (option < 3) ? FALSE : TRUE;
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:
@ -364,7 +492,7 @@ CmdCalma(w, cmd)
option = Lookup(cmd->tx_argv[2], cmdCalmaYesNo);
if (option < 0)
goto wrongNumArgs;
CalmaPostOrder = (option < 3) ? FALSE : TRUE;
CalmaPostOrder = (option < 4) ? FALSE : TRUE;
return;
case CALMA_ARRAYS:
@ -384,7 +512,7 @@ CmdCalma(w, cmd)
option = Lookup(cmd->tx_argv[2], cmdCalmaYesNo);
if (option < 0)
goto wrongNumArgs;
CalmaFlattenArrays = (option < 3) ? FALSE : TRUE;
CalmaFlattenArrays = (option < 4) ? FALSE : TRUE;
return;
case CALMA_LOWER:
@ -404,7 +532,7 @@ CmdCalma(w, cmd)
option = Lookup(cmd->tx_argv[2], cmdCalmaYesNo);
if (option < 0)
goto wrongNumArgs;
CalmaDoLower = (option < 3) ? FALSE : TRUE;
CalmaDoLower = (option < 4) ? FALSE : TRUE;
return;
case CALMA_MERGE:
@ -426,7 +554,7 @@ CmdCalma(w, cmd)
option = Lookup(cmd->tx_argv[2], cmdCalmaYesNo);
if (option < 0)
goto wrongNumArgs;
CalmaMergeTiles = (option < 3) ? FALSE : TRUE;
CalmaMergeTiles = (option < 4) ? FALSE : TRUE;
return;
case CALMA_POLYS:
@ -448,7 +576,47 @@ CmdCalma(w, cmd)
option = Lookup(cmd->tx_argv[3], cmdCalmaYesNo);
if (option < 0)
goto wrongNumArgs;
CalmaSubcellPolygons = (option < 3) ? FALSE : TRUE;
CalmaSubcellPolygons = (option < 4) ? FALSE : TRUE;
return;
case CALMA_NO_DUP:
if (cmd->tx_argc == 2)
{
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewBooleanObj(CalmaNoDuplicates));
#else
TxPrintf("Cell defs that exist before reading GDS will not be paresd.\n",
(CalmaNoDuplicates) ? "not " : "");
#endif
return;
}
else if (cmd->tx_argc != 3)
goto wrongNumArgs;
option = Lookup(cmd->tx_argv[2], cmdCalmaYesNo);
if (option < 0)
goto wrongNumArgs;
CalmaNoDuplicates = (option < 4) ? FALSE : TRUE;
return;
case CALMA_NO_STAMP:
if (cmd->tx_argc == 2)
{
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewBooleanObj(CalmaNoDateStamp));
#else
TxPrintf("Structures will contain a %s header creation date stamp.\n",
(CalmaNoDateStamp) ? "zero" : "valid");
#endif
return;
}
else if (cmd->tx_argc != 3)
goto wrongNumArgs;
option = Lookup(cmd->tx_argv[2], cmdCalmaYesNo);
if (option < 0)
goto wrongNumArgs;
CalmaNoDateStamp = (option < 4) ? FALSE : TRUE;
return;
case CALMA_PATHS:
@ -470,7 +638,7 @@ CmdCalma(w, cmd)
option = Lookup(cmd->tx_argv[3], cmdCalmaYesNo);
if (option < 0)
goto wrongNumArgs;
CalmaSubcellPaths = (option < 3) ? FALSE : TRUE;
CalmaSubcellPaths = (option < 4) ? FALSE : TRUE;
return;
case CALMA_READONLY:
@ -490,7 +658,7 @@ CmdCalma(w, cmd)
option = Lookup(cmd->tx_argv[2], cmdCalmaYesNo);
if (option < 0)
goto wrongNumArgs;
CalmaReadOnly = (option < 3) ? FALSE : TRUE;
CalmaReadOnly = (option < 4) ? FALSE : TRUE;
return;
case CALMA_RESCALE:
@ -510,7 +678,7 @@ CmdCalma(w, cmd)
option = Lookup(cmd->tx_argv[2], cmdCalmaYesNo);
if (option < 0)
goto wrongNumArgs;
CIFRescaleAllow = (option < 3) ? FALSE : TRUE;
CIFRescaleAllow = (option < 4) ? FALSE : TRUE;
if (!CIFRescaleAllow)
CIFWarningLevel = CIF_WARN_LIMIT;
return;
@ -667,8 +835,10 @@ CmdCellname(w, cmd)
"window list top-level cell of a layout window",
"create create a new cell definition",
"delete delete the named cell definition",
"dereference reload the named cell from the search paths",
"filepath list the full path of the file for the cell",
"flags list option flags of the indicated cell definition",
"timestamp list the cell timestamp",
"lock lock the named cell (prevent changes to cell use)",
"unlock unlock the named cell (allow changes to cell use)",
"property list or set cell definition properties",
@ -681,10 +851,11 @@ CmdCellname(w, cmd)
};
typedef enum { IDX_CHILDREN, IDX_PARENTS, IDX_EXISTS, IDX_SELF,
IDX_INSTANCE, IDX_CHILDINST, IDX_CELLDEF, IDX_ALLCELLS,
IDX_TOPCELLS, IDX_IN_WINDOW, IDX_CREATE,
IDX_DELETE, IDX_FILEPATH, IDX_FLAGS, IDX_LOCK, IDX_UNLOCK,
IDX_PROPERTY, IDX_ABUTMENT, IDX_ORIENTATION, IDX_RENAME,
IDX_READWRITE, IDX_MODIFIED } optionType;
IDX_TOPCELLS, IDX_IN_WINDOW, IDX_CREATE, IDX_DELETE,
IDX_DEREFERENCE, IDX_FILEPATH, IDX_FLAGS, IDX_TIMESTAMP,
IDX_LOCK, IDX_UNLOCK, IDX_PROPERTY, IDX_ABUTMENT,
IDX_ORIENTATION, IDX_RENAME, IDX_READWRITE,
IDX_MODIFIED } optionType;
if (strstr(cmd->tx_argv[0], "in"))
is_cellname = FALSE;
@ -721,8 +892,9 @@ CmdCellname(w, cmd)
if (option < 0) goto badusage;
if ((locargc > 3) && (option != IDX_RENAME) && (option != IDX_DELETE) &&
(option != IDX_READWRITE) && (option != IDX_PROPERTY) &&
(option != IDX_FILEPATH) && (option != IDX_ORIENTATION))
(option != IDX_DEREFERENCE) && (option != IDX_READWRITE) &&
(option != IDX_PROPERTY) && (option != IDX_FILEPATH) &&
(option != IDX_ORIENTATION) && (option != IDX_TIMESTAMP))
goto badusage;
if ((locargc > 4) && (option != IDX_PROPERTY))
@ -768,6 +940,7 @@ CmdCellname(w, cmd)
return;
case IDX_IN_WINDOW: case IDX_READWRITE: case IDX_FLAGS:
case IDX_PROPERTY: case IDX_FILEPATH: case IDX_MODIFIED:
case IDX_DEREFERENCE: case IDX_TIMESTAMP:
TxError("Function unimplemented for instances.\n");
return;
case IDX_DELETE:
@ -845,6 +1018,30 @@ CmdCellname(w, cmd)
TxError("Delete cell command missing cellname\n");
break;
case IDX_DEREFERENCE:
/* Unload the cell definition and re-read with search paths */
if (locargc == 3)
{
void cmdFlushCell();
if (cellname == NULL)
cellDef = EditRootDef;
else
cellDef = DBCellLookDef(cellname);
/* Reload cell with dereferencing */
if (cellDef == NULL)
{
TxError("No such cell \"%s\"\n", cellname);
break;
}
cmdFlushCell(cellDef, TRUE);
SelectClear();
}
else
TxError("Dereference cell command missing cellname\n");
break;
case IDX_READWRITE:
if (cellname == NULL)
cellDef = EditRootDef;
@ -994,6 +1191,35 @@ CmdCellname(w, cmd)
}
break;
case IDX_TIMESTAMP:
if (cellname == NULL)
cellDef = EditRootDef;
else
cellDef = DBCellLookDef(cellname);
if (cellDef == (CellDef *) NULL)
{
TxError("Unknown cell %s\n", cellname);
break;
}
if ((locargc == 3) || (locargc == 2 && cellname == NULL))
{
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(cellDef->cd_timestamp));
#else
TxPrintf("Timestamp for cell %s = %d\n", cellname, cellDef->cd_timestamp);
#endif
}
else if (locargc == 4 || (locargc == 3 && cellname == NULL))
{
int timestamp = atoi(cmd->tx_argv[2 + ((cellname == NULL) ? 0 : 1)]);
if (timestamp != cellDef->cd_timestamp)
{
cellDef->cd_timestamp = timestamp;
cellDef->cd_flags &= ~CDGETNEWSTAMP;
}
}
break;
case IDX_FLAGS:
if (cellname == NULL)
cellDef = EditRootDef;
@ -1133,6 +1359,7 @@ CmdCif(w, cmd)
bool doforall = FALSE;
float curscale;
int argc = cmd->tx_argc;
int argshift;
char **argv = cmd->tx_argv;
static char *cmdCifWarnOptions[] = { "default", "none", "align",
@ -1288,10 +1515,10 @@ CmdCif(w, cmd)
TxError("Box requested but no cursor box exists\n");
return;
}
CIFCoverageLayer(rootDef, &box, argv[2]);
CIFCoverageLayer(rootDef, &box, argv[2], dolist);
}
else if (argc == 3)
CIFCoverageLayer(rootDef, &rootDef->cd_bbox, argv[2]);
CIFCoverageLayer(rootDef, &rootDef->cd_bbox, argv[2], dolist);
else
goto wrongNumArgs;
@ -3454,7 +3681,7 @@ CmdDrc(w, cmd)
}
#ifdef MAGIC_WRAPPER
if (count_total >= 0)
if ((count_total >= 0) || (!dolist))
{
if (dolist)
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(count_total));

View File

@ -951,7 +951,7 @@ CmdExtract(w, cmd)
"style [stylename] set current extraction parameter style",
"unique [option] generate unique names when different nodes\n\
have the same name",
"warn [ [no] option] enable/disable reporting of non-fatal errors",
"warn [ [no] option] enable/disable reporting of non-serious errors",
NULL
};

View File

@ -726,6 +726,45 @@ usage:
TxError("Usage: findbox [zoom]\n");
}
/*
* ----------------------------------------------------------------------------
*
* cmdFindLabelFunc --
*
* Callback function from CmdFindLabel. Return 1 to stop the search on the
* Nth instance of the label named "label", where N is passed through the
* client data as lsr_occur.
*
* The client data record lsr_rect is left pointing to the label location
* when the Nth label instance is found.
*
* ----------------------------------------------------------------------------
*/
typedef struct _labsearchrec
{
Rect lsr_rect;
int lsr_occur;
} LabSearchRec;
int cmdFindLabelFunc(rect, name, label, cdarg)
Rect *rect;
char *name;
Label *label;
LabSearchRec *cdarg;
{
if (cdarg->lsr_occur == 0)
{
cdarg->lsr_rect = *rect;
return 1;
}
else
cdarg->lsr_occur--;
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -747,16 +786,6 @@ usage:
* ----------------------------------------------------------------------------
*/
int cmdFindLabelFunc(rect, name, label, cdarg)
Rect *rect;
char *name;
Label *label;
Rect *cdarg;
{
*cdarg = *rect;
return 1;
}
void
CmdFindLabel(w, cmd)
MagWindow *w;
@ -764,17 +793,30 @@ CmdFindLabel(w, cmd)
{
CellDef *boxDef;
CellUse *labUse;
Rect box, cmdFindLabelRect;
Rect box;
char *labname;
int found;
int found, occur, plainargs;
bool doglob = FALSE; /* csh-style glob matching (see utils/match.c) */
LabSearchRec lsr;
int dbListLabels(); /* forward declaration */
if ((cmd->tx_argc == 3) && !strncmp(cmd->tx_argv[1], "-glob", 5))
plainargs = cmd->tx_argc;
if ((plainargs > 2) && !strncmp(cmd->tx_argv[1], "-glob", 5))
{
plainargs--;
doglob = TRUE;
else if (cmd->tx_argc != 2)
}
if ((plainargs != 2) && (plainargs != 3))
goto usage;
occur = 0;
if (plainargs == 3)
{
char *occurstr = cmd->tx_argv[plainargs - 1];
if (StrIsInt(occurstr))
occur = atoi(occurstr);
}
if (w == NULL)
{
TxError("Point to a window first.\n");
@ -794,7 +836,7 @@ CmdFindLabel(w, cmd)
return;
};
labname = (cmd->tx_argc == 3) ? cmd->tx_argv[2] : cmd->tx_argv[1];
labname = cmd->tx_argv[1 + (doglob) ? 1 : 0];
labUse = EditCellUse;
if (labUse == NULL) labUse = (CellUse *)w->w_surfaceID;
@ -815,15 +857,17 @@ CmdFindLabel(w, cmd)
{
/* Exact-match label search (corrected by Nishit, 10/14/04) */
lsr.lsr_occur = occur;
found = DBSrLabelLoc(labUse, labname, cmdFindLabelFunc,
(ClientData) &cmdFindLabelRect);
(ClientData) &lsr);
if (found) {
if (cmdFindLabelRect.r_xbot == cmdFindLabelRect.r_xtop)
cmdFindLabelRect.r_xtop++;
if (cmdFindLabelRect.r_ybot == cmdFindLabelRect.r_ytop)
cmdFindLabelRect.r_ytop++;
ToolMoveBox(TOOL_BL,&cmdFindLabelRect.r_ll,FALSE,labUse->cu_def);
ToolMoveCorner(TOOL_TR,&cmdFindLabelRect.r_ur,FALSE,labUse->cu_def);
if (lsr.lsr_rect.r_xbot == lsr.lsr_rect.r_xtop)
lsr.lsr_rect.r_xtop++;
if (lsr.lsr_rect.r_ybot == lsr.lsr_rect.r_ytop)
lsr.lsr_rect.r_ytop++;
ToolMoveBox(TOOL_BL, &lsr.lsr_rect.r_ll, FALSE, labUse->cu_def);
ToolMoveCorner(TOOL_TR, &lsr.lsr_rect.r_ur, FALSE, labUse->cu_def);
} else {
TxError("Couldn't find label %s\n", labname);
}
@ -869,10 +913,12 @@ dbListLabels(scx, label, tpath, cdarg)
* Implement the "flush" command.
* Throw away all changes made within magic to the specified cell,
* and re-read it from disk. If no cell is specified, the default
* is the current edit cell.
* is the current edit cell. If "-dereference" is specified as an
* option, then re-read the cell from the search path instead of
* the file path that has been associated with the cell.
*
* Usage:
* flush [cellname]
* flush [cellname] [-dereference]
*
* Results:
* None.
@ -893,10 +939,17 @@ CmdFlush(w, cmd)
int action;
static char *actionNames[] = { "no", "yes", 0 };
char *prompt;
bool dereference = FALSE;
if (!strncmp(cmd->tx_argv[cmd->tx_argc - 1], "-deref", 6))
{
dereference = TRUE;
cmd->tx_argc--;
}
if (cmd->tx_argc > 2)
{
TxError("Usage: flush [cellname]\n");
TxError("Usage: flush [cellname] [dereference]\n");
return;
}
@ -926,7 +979,7 @@ CmdFlush(w, cmd)
return;
}
cmdFlushCell(def);
cmdFlushCell(def, dereference);
SelectClear();
TxPrintf("[Flushed]\n");
}
@ -1565,8 +1618,8 @@ CmdFindNetProc(nodename, use, rect, warn_not_found)
/* go to that point (transformed to the top level of the design */
/* hierarchy). */
/* see extract/extractInt.h for the format of the node, found in */
/* extMakeNodeNumPrint(), which is a macro, not a subroutine. */
/* see extract/extBasic.c for the format of the node, found */
/* in extMakeNodeNumPrint(). */
locvalid = FALSE;
if ((xstr = strchr(s, '_')) != NULL)
@ -1816,6 +1869,9 @@ flatCopyAllLabels(scx, lab, tpath, targetUse)
char labelname[1024];
char *n, *f, c;
/* Ignore null labels */
if (*lab->lab_text == '\0') return 0;
def = targetUse->cu_def;
if (!GEO_LABEL_IN_AREA(&lab->lab_rect, &(scx->scx_area))) return 0;
GeoTransRect(&scx->scx_trans, &lab->lab_rect, &labTargetRect);
@ -1876,7 +1932,7 @@ CmdFlatten(w, cmd)
TxCommand *cmd;
{
int rval, xMask;
bool dolabels, toplabels, invert;
bool dolabels, dobox, toplabels, invert;
char *destname;
CellDef *newdef;
CellUse *newuse;
@ -1887,6 +1943,7 @@ CmdFlatten(w, cmd)
xMask = CU_DESCEND_ALL;
dolabels = TRUE;
toplabels = FALSE;
dobox = FALSE;
rval = 0;
if (cmd->tx_argc > 2)
@ -1912,6 +1969,9 @@ CmdFlatten(w, cmd)
{
switch(cmd->tx_argv[i][3])
{
case 'b':
dobox = (invert) ? FALSE : TRUE;
break;
case 'l':
dolabels = (invert) ? FALSE : TRUE;
break;
@ -1926,7 +1986,7 @@ CmdFlatten(w, cmd)
break;
default:
TxError("options are: -nolabels, -nosubcircuits "
"-novendor, -dotoplabels\n");
"-novendor, -dotoplabels, -dobox\n");
break;
}
}
@ -1953,7 +2013,6 @@ CmdFlatten(w, cmd)
(void) StrDup(&(newuse->cu_id), "Flattened cell");
DBSetTrans(newuse, &GeoIdentityTransform);
newuse->cu_expandMask = CU_DESCEND_SPECIAL;
UndoDisable();
flatDestUse = newuse;
if (EditCellUse)
@ -1961,9 +2020,28 @@ CmdFlatten(w, cmd)
else
scx.scx_use = (CellUse *)w->w_surfaceID;
scx.scx_area = scx.scx_use->cu_def->cd_bbox;
if (dobox)
{
CellDef *boxDef;
if (!ToolGetBox(&boxDef, &scx.scx_area))
{
TxError("Put the box in a window first.\n");
return;
}
else if (boxDef != scx.scx_use->cu_def)
{
TxError("The box is not in the edit cell!\n");
return;
}
}
else
scx.scx_area = scx.scx_use->cu_def->cd_bbox;
scx.scx_trans = GeoIdentityTransform;
UndoDisable();
DBCellCopyAllPaint(&scx, &DBAllButSpaceAndDRCBits, xMask, flatDestUse);
if (dolabels)
FlatCopyAllLabels(&scx, &DBAllTypeBits, xMask, flatDestUse);
@ -1980,5 +2058,3 @@ CmdFlatten(w, cmd)
UndoEnable();
}

View File

@ -309,6 +309,10 @@ CmdLabel(w, cmd)
CmdLabelProc(p, font, size, rotate, offx, offy, pos, sticky, type);
}
#define LOAD_NOWINDOW 0
#define LOAD_DEREFERENCE 1
#define LOAD_FORCE 2
#define LOAD_QUIET 3
/*
* ----------------------------------------------------------------------------
@ -318,7 +322,7 @@ CmdLabel(w, cmd)
* Implement the "load" command.
*
* Usage:
* load [name [scaled n [d]]] [-force] [-nowindow] [-dereference]
* load [name [scaled n [d]]] [-force] [-nowindow] [-dereference] [-quiet]
*
* If name is supplied, then the window containing the point tool is
* remapped so as to edit the cell with the given name.
@ -354,29 +358,52 @@ CmdLoad(w, cmd)
{
int n = 1;
int d = 1;
int option;
int locargc = cmd->tx_argc;
bool ignoreTech = FALSE;
bool noWindow = FALSE;
bool dereference = FALSE;
bool beQuiet = FALSE;
bool saveVerbose;
int keepGoing(); /* forward declaration */
extern bool DBVerbose; /* from DBio.c */
saveVerbose = DBVerbose;
static char *cmdLoadOption[] =
{
"-nowindow load file but do not display in the layout window",
"-dereference use search paths and ignore embedded cell paths in file",
"-force load file even if tech in header does not match",
"-quiet no alert if file does not exist",
NULL
};
while (cmd->tx_argv[locargc - 1][0] == '-')
{
option = Lookup(cmd->tx_argv[locargc - 1], cmdLoadOption);
switch (option)
{
case LOAD_NOWINDOW:
noWindow = TRUE;
break;
case LOAD_DEREFERENCE:
dereference = TRUE;
break;
case LOAD_FORCE:
ignoreTech = TRUE;
break;
case LOAD_QUIET:
beQuiet = TRUE;
break;
default:
TxError("No such option \"%s\".\n", cmd->tx_argv[locargc - 1]);
}
locargc--;
}
if (locargc > 2)
{
if (!strncmp(cmd->tx_argv[locargc - 1], "-nowindow", 8))
{
locargc--;
noWindow = TRUE;
}
if (!strncmp(cmd->tx_argv[locargc - 1], "-deref", 5))
{
locargc--;
dereference = TRUE;
}
if (!strncmp(cmd->tx_argv[locargc - 1], "-force", 6))
{
locargc--;
ignoreTech = TRUE;
}
if ((locargc >= 4) && !strncmp(cmd->tx_argv[2], "scale", 5) &&
StrIsInt(cmd->tx_argv[3]))
{
@ -397,7 +424,7 @@ CmdLoad(w, cmd)
else if (!ignoreTech && !noWindow && !dereference)
{
TxError("Usage: %s name [scaled n [d]] [-force] "
"[-nowindow] [-dereference]\n",
"[-nowindow] [-dereference] [-quiet]\n",
cmd->tx_argv[0]);
return;
}
@ -422,8 +449,10 @@ CmdLoad(w, cmd)
*(cmd->tx_argv[1] + strlen(cmd->tx_argv[1]) - 1) = '\0';
}
#endif
DBVerbose = !beQuiet;
DBWloadWindow((noWindow == TRUE) ? NULL : w, cmd->tx_argv[1],
ignoreTech, FALSE, dereference);
DBVerbose = saveVerbose;
if ((n > 1) || (d > 1))
{
@ -456,7 +485,12 @@ CmdLoad(w, cmd)
ReduceFraction(&DBLambda[0], &DBLambda[1]);
}
}
else DBWloadWindow(w, (char *) NULL, TRUE, FALSE, FALSE);
else
{
DBVerbose = !beQuiet;
DBWloadWindow(w, (char *) NULL, TRUE, FALSE, FALSE);
DBVerbose = saveVerbose;
}
}
/*
@ -1298,7 +1332,7 @@ CmdPort(w, cmd)
char **msg;
int argstart;
int i, refidx, idx, pos, type, option, argc;
unsigned short dirmask;
unsigned int dirmask;
bool found;
bool nonEdit = FALSE;
Label *lab, *sl;

View File

@ -24,6 +24,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "tcltk/tclmagic.h"
#include "utils/magic.h"
@ -53,6 +54,61 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
extern void DisplayWindow();
/*
* ----------------------------------------------------------------------------
*
* CmdRandom
*
* Generate a random integer or set the random seed. This is mainly
* used for seeding the random number generator for the GDS write
* routine when GDS write is assigning a random prefix to ensure
* uniqueness of names in a GDS library read from a file instead of
* generated from the database.
*
* Results:
* None.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
void
CmdRandom(w, cmd)
MagWindow *w;
TxCommand *cmd;
{
int value;
if (cmd->tx_argc == 1)
{
/* Return a random number */
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(random()));
#else
TxPrintf("%d", random());
#endif
}
else if ((cmd->tx_argc >= 2) && (!strcmp(cmd->tx_argv[1], "seed")))
{
if (cmd->tx_argc == 3)
{
value = atoi(cmd->tx_argv[2]);
}
else
{
value = (int)time(NULL);
}
srandom(value);
}
else
{
TxPrintf("usage: random [seed [<value>]]\n");
return;
}
}
#if !defined(NO_SIM_MODULE) && defined(RSIM_MODULE)
/*

View File

@ -285,12 +285,15 @@ CmdInit()
*/
void
cmdFlushCell(def)
cmdFlushCell(def, force_deref)
CellDef *def;
bool force_deref;
{
CellUse *parentUse;
bool dereference;
if (def == NULL) return;
/* Disallow flushing a cell that contains the edit cell as a child */
if (EditCellUse && (EditCellUse->cu_parent == def))
{
@ -300,6 +303,15 @@ cmdFlushCell(def)
}
UndoFlush();
if (force_deref)
{
/* Force dereferencing */
def->cd_flags |= CDDEREFERENCE;
freeMagic(def->cd_file);
def->cd_file = NULL;
}
DBWAreaChanged(def, &def->cd_bbox, DBW_ALLWINDOWS,
(TileTypeBitMask *) NULL);
for (parentUse = def->cd_parents; parentUse != NULL;

View File

@ -1818,7 +1818,7 @@ cmdWriteallFunc(def, cmd)
cmdSaveCell(def, (char *) NULL, FALSE, TRUE);
break;
case 1: /* Flush */
cmdFlushCell(def);
cmdFlushCell(def, FALSE);
break;
case 2: /* Skip */
break;

View File

@ -48,7 +48,7 @@ static PaintResultType (*dbCurPaintTbl)[NT][NT] = DBPaintResultTbl;
* such as the design-rule checker that need to use, for example,
* DBPaintPlaneMark instead of the standard version.
*/
static void (*dbCurPaintPlane)() = DBPaintPlaneWrapper;
static int (*dbCurPaintPlane)() = DBPaintPlaneWrapper;
/* Structure passed to DBTreeSrTiles() */
struct copyAllArg
@ -56,6 +56,7 @@ struct copyAllArg
TileTypeBitMask *caa_mask; /* Mask of tile types to be copied */
Rect caa_rect; /* Clipping rect in target coords */
CellUse *caa_targetUse; /* Use to which tiles are copied */
void (*caa_func)(); /* Callback function for off-grid points */
Rect *caa_bbox; /* Bbox of material copied (in
* targetUse coords). Used only when
* copying cells.
@ -96,7 +97,7 @@ struct copyLabelArg
* ----------------------------------------------------------------------------
*/
void
int
DBPaintPlaneWrapper(def, pNum, type, area, undo)
CellDef *def;
int pNum;
@ -106,12 +107,14 @@ DBPaintPlaneWrapper(def, pNum, type, area, undo)
{
TileType loctype = type & TT_LEFTMASK;
Rect expand;
int result;
undo->pu_pNum = pNum;
DBNMPaintPlane(def->cd_planes[pNum], type, area,
result = DBNMPaintPlane(def->cd_planes[pNum], type, area,
dbCurPaintTbl[pNum][loctype], undo);
GEO_EXPAND(area, 1, &expand);
DBMergeNMTiles(def->cd_planes[pNum], &expand, undo);
return result;
}
/*
@ -126,7 +129,7 @@ DBPaintPlaneWrapper(def, pNum, type, area, undo)
* ----------------------------------------------------------------------------
*/
void
int
DBPaintPlaneMark(def, pNum, type, area, undo)
CellDef *def;
int pNum;
@ -137,7 +140,7 @@ DBPaintPlaneMark(def, pNum, type, area, undo)
TileType loctype = type & TT_LEFTMASK;
undo->pu_pNum = pNum;
DBNMPaintPlane0(def->cd_planes[pNum], type, area,
return DBNMPaintPlane0(def->cd_planes[pNum], type, area,
dbCurPaintTbl[pNum][loctype], undo, (unsigned char)PAINT_MARK);
}
@ -147,7 +150,7 @@ DBPaintPlaneMark(def, pNum, type, area, undo)
* ----------------------------------------------------------------------------
*/
void
int
DBPaintPlaneXor(def, pNum, type, area, undo)
CellDef *def;
int pNum;
@ -158,7 +161,7 @@ DBPaintPlaneXor(def, pNum, type, area, undo)
TileType loctype = type & TT_LEFTMASK;
undo->pu_pNum = pNum;
DBNMPaintPlane0(def->cd_planes[pNum], type, area,
return DBNMPaintPlane0(def->cd_planes[pNum], type, area,
dbCurPaintTbl[pNum][loctype], undo, (unsigned char)PAINT_XOR);
}
@ -175,7 +178,7 @@ DBPaintPlaneXor(def, pNum, type, area, undo)
* ----------------------------------------------------------------------------
*/
void
int
DBPaintPlaneActive(def, pNum, type, area, undo)
CellDef *def;
int pNum;
@ -200,11 +203,13 @@ DBPaintPlaneActive(def, pNum, type, area, undo)
DBPaintPlaneWrapper(def, pNum, t | (type &
(TT_SIDE | TT_DIRECTION | TT_DIAGONAL)),
area, undo);
return;
return 0;
}
}
if (TTMaskHasType(&DBActiveLayerBits, loctype))
DBPaintPlaneWrapper(def, pNum, type, area, undo);
return DBPaintPlaneWrapper(def, pNum, type, area, undo);
else
return 0;
}
/*
@ -241,6 +246,7 @@ DBCellCopyManhattanPaint(scx, mask, xMask, targetUse)
arg.caa_mask = mask;
arg.caa_targetUse = targetUse;
arg.caa_func = NULL;
GEOTRANSRECT(&scx->scx_trans, &scx->scx_area, &arg.caa_rect);
(void) DBTreeSrTiles(scx, mask, xMask, dbCopyManhattanPaint, (ClientData) &arg);
@ -281,6 +287,52 @@ DBCellCopyAllPaint(scx, mask, xMask, targetUse)
arg.caa_mask = mask;
arg.caa_targetUse = targetUse;
arg.caa_func = NULL;
GEOTRANSRECT(&scx->scx_trans, &scx->scx_area, &arg.caa_rect);
/* Add any stacking types for the search (but not to mask passed as arg!) */
locMask = *mask;
DBMaskAddStacking(&locMask);
DBTreeSrTiles(scx, &locMask, xMask, dbCopyAllPaint, (ClientData) &arg);
}
/*
*-----------------------------------------------------------------------------
*
* DBCellCheckCopyAllPaint --
*
* Copy paint from the tree rooted at scx->scx_use to the paint planes
* of targetUse, transforming according to the transform in scx.
* Only the types specified by typeMask are copied.
*
* Results:
* None.
*
* Side effects:
* Updates the paint planes in targetUse.
*
*-----------------------------------------------------------------------------
*/
void
DBCellCheckCopyAllPaint(scx, mask, xMask, targetUse, func)
SearchContext *scx; /* Describes root cell to search, area to
* copy, transform from root cell to coords
* of targetUse.
*/
TileTypeBitMask *mask; /* Types of tiles to be yanked/stuffed */
int xMask; /* Expansion state mask to be used in search */
CellUse *targetUse; /* Cell into which material is to be stuffed */
void (*func)(); /* Function to call on tile split error */
{
TileTypeBitMask locMask;
struct copyAllArg arg;
int dbCopyAllPaint();
arg.caa_mask = mask;
arg.caa_targetUse = targetUse;
arg.caa_func = func;
GEOTRANSRECT(&scx->scx_trans, &scx->scx_area, &arg.caa_rect);
/* Add any stacking types for the search (but not to mask passed as arg!) */
@ -441,7 +493,7 @@ DBCellCopyPaint(scx, mask, xMask, targetUse)
for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
if (PlaneMaskHasPlane(planeMask, pNum))
{
cxp.tc_plane = pNum; /* not used? */
cxp.tc_plane = pNum;
(void) DBSrPaintArea((Tile *) NULL,
scx->scx_use->cu_def->cd_planes[pNum], &scx->scx_area,
mask, dbCopyAllPaint, (ClientData) &cxp);
@ -590,6 +642,7 @@ dbCopyAllPaint(tile, cxp)
CellDef *def;
TileType type = TiGetTypeExact(tile);
int pNum = cxp->tc_plane;
int result;
TileTypeBitMask *typeMask;
/*
@ -752,7 +805,12 @@ topbottom:
splitdone:
(*dbCurPaintPlane)(def, pNum, dinfo | type, &targetRect, &ui);
result = (*dbCurPaintPlane)(def, pNum, dinfo | type, &targetRect, &ui);
if ((result != 0) && (arg->caa_func != NULL))
{
/* result == 1 used exclusively for DRC off-grid error flagging */
DRCOffGridError(&targetRect);
}
return (0);
}
@ -1013,11 +1071,11 @@ DBNewPaintTable(newTable))[NT][NT]
* ----------------------------------------------------------------------------
*/
VoidProc
IntProc
DBNewPaintPlane(newProc)
void (*newProc)(); /* Address of new procedure */
int (*newProc)(); /* Address of new procedure */
{
void (*oldProc)() = dbCurPaintPlane;
int (*oldProc)() = dbCurPaintPlane;
dbCurPaintPlane = newProc;
return (oldProc);
}

View File

@ -21,6 +21,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#endif /* not lint */
#include <stdio.h>
#include <string.h>
#include "utils/magic.h"
#include "utils/malloc.h"
@ -767,6 +768,9 @@ cleanup:
* remaining elements of the current array are skipped, but the
* search is not aborted.
*
* NOTE: Unlike DBTreeSrTiles and DBTreeSrLabels, the function is not
* applied to the top level cell, only to descendents.
*
* Each element of an array is returned separately.
*
* Results:
@ -847,9 +851,8 @@ dbTreeCellSrFunc(scx, fp)
if ((fp->tf_xmask == CU_DESCEND_NO_LOCK) && (use->cu_flags & CU_LOCKED))
return 2;
else if ((!DBDescendSubcell(use, fp->tf_xmask)) ||
(fp->tf_xmask == CU_DESCEND_ALL))
result = (*fp->tf_func)(scx, fp->tf_arg);
else if (!DBDescendSubcell(use, fp->tf_xmask))
return (*fp->tf_func)(scx, fp->tf_arg);
else
{
if ((use->cu_def->cd_flags & CDAVAILABLE) == 0)
@ -858,9 +861,15 @@ dbTreeCellSrFunc(scx, fp)
if (!DBCellRead(use->cu_def, (char *) NULL, TRUE, dereference, NULL))
return 0;
}
result = DBCellSrArea(scx, dbTreeCellSrFunc, (ClientData) fp);
}
return result;
if (fp->tf_xmask == CU_DESCEND_ALL)
{
result = (*fp->tf_func)(scx, fp->tf_arg);
if (result != 0) return result;
}
/* Run recursively on children in search area */
return DBCellSrArea(scx, dbTreeCellSrFunc, (ClientData) fp);
}
/*
@ -1775,6 +1784,149 @@ DBSrCellUses(cellDef, func, arg)
return retval;
}
/* Structure used by dbScaleProp() and dbMoveProp() */
typedef struct _cellpropstruct {
Point cps_point;
CellDef *cps_def;
} CellPropStruct;
/*
* ----------------------------------------------------------------------------
*
* dbScaleProp --
*
* Callback function for dbScaleCell. Finds properties that represent
* internal geometry (FIXED_BBOX and MASKHINTS_*) and scale the values
* by the numerator / denominator values passed as a pointer to a Point
* structure, where p_x is the numerator value and p_y is the denominator
* value.
*
* ----------------------------------------------------------------------------
*/
int dbScaleProp(name, value, cps)
char *name;
char *value;
CellPropStruct *cps;
{
int scalen, scaled;
char *newvalue, *vptr;
Rect r;
if (!strcmp(name, "FIXED_BBOX"))
{
if (sscanf(value, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
&r.r_xtop, &r.r_ytop) == 4)
{
/* Scale numerator held in point X value, */
/* scale denominator held in point Y value */
scalen = cps->cps_point.p_x;
scaled = cps->cps_point.p_y;
DBScalePoint(&r.r_ll, scalen, scaled);
DBScalePoint(&r.r_ur, scalen, scaled);
newvalue = (char *)mallocMagic(40);
sprintf(newvalue, "%d %d %d %d", r.r_xbot, r.r_ybot,
r.r_xtop, r.r_ytop);
DBPropPut(cps->cps_def, name, newvalue);
}
}
else if (!strncmp(name, "MASKHINTS_", 10))
{
char *vptr, *lastval;
int lastlen;
newvalue = (char *)NULL;
vptr = value;
while (*vptr != '\0')
{
if (sscanf(vptr, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
&r.r_xtop, &r.r_ytop) == 4)
{
/* Scale numerator held in point X value, */
/* scale denominator held in point Y value */
scalen = cps->cps_point.p_x;
scaled = cps->cps_point.p_y;
DBScalePoint(&r.r_ll, scalen, scaled);
DBScalePoint(&r.r_ur, scalen, scaled);
lastval = newvalue;
lastlen = (lastval) ? strlen(lastval) : 0;
newvalue = mallocMagic(40 + lastlen);
if (lastval)
strcpy(newvalue, lastval);
else
*newvalue = '\0';
sprintf(newvalue + lastlen, "%s%d %d %d %d", (lastval) ? " " : "",
r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop);
if (lastval) freeMagic(lastval);
/* Parse through the four values and check if there's more */
while (*vptr && !isspace(*vptr)) vptr++;
while (*vptr && isspace(*vptr)) vptr++;
while (*vptr && !isspace(*vptr)) vptr++;
while (*vptr && isspace(*vptr)) vptr++;
while (*vptr && !isspace(*vptr)) vptr++;
while (*vptr && isspace(*vptr)) vptr++;
while (*vptr && !isspace(*vptr)) vptr++;
while (*vptr && isspace(*vptr)) vptr++;
}
else break;
}
if (newvalue)
DBPropPut(cps->cps_def, name, newvalue);
}
return 0; /* Keep enumerating through properties */
}
/*
* ----------------------------------------------------------------------------
*
* dbMoveProp --
*
* Callback function for ??. Finds properties that represent
* internal geometry (FIXED_BBOX and MASKHINTS_*) and modifies the values
* by the X, Y values passed as a pointer to a Point structure in ClientData.
*
* ----------------------------------------------------------------------------
*/
int dbMoveProp(name, value, cps)
char *name;
char *value;
CellPropStruct *cps;
{
int origx, origy;
char *newvalue;
Rect r;
if (!strcmp(name, "FIXED_BBOX") || !strncmp(name, "MASKHINTS_", 10))
{
if (sscanf(value, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
&r.r_xtop, &r.r_ytop) == 4)
{
origx = cps->cps_point.p_x;
origy = cps->cps_point.p_y;
DBMovePoint(&r.r_ll, origx, origy);
DBMovePoint(&r.r_ur, origx, origy);
newvalue = (char *)mallocMagic(40);
sprintf(newvalue, "%d %d %d %d", r.r_xbot, r.r_ybot,
r.r_xtop, r.r_ytop);
DBPropPut(cps->cps_def, name, newvalue);
}
}
return 0; /* Keep enumerating through properties */
}
/*
* ----------------------------------------------------------------------------
*
@ -1799,6 +1951,7 @@ dbScaleCell(cellDef, scalen, scaled)
LinkedCellUse *luhead, *lu;
Plane *newplane;
BPlane *cellPlane, *cellPlaneOrig;
CellPropStruct cps;
/* DBCellEnum() attempts to read unavailable celldefs. We don't */
/* want to do that here, so check CDAVAILABLE flag first. */
@ -1936,6 +2089,18 @@ donecell:
}
}
}
/* Check all properties for ones with keys beginning with "MASKHINTS_"
* or the key "FIXED_BBOX", and scale them by the same amount as all
* the geometry.
*/
cps.cps_point.p_x = scalen;
cps.cps_point.p_y = scaled;
cps.cps_def = cellDef;
DBPropEnum(cellDef, dbScaleProp, &cps);
return 0;
}
@ -2023,6 +2188,7 @@ DBMoveCell(cellDef, origx, origy)
LinkedCellUse *luhead, *lu;
Plane *newplane;
BPlane *cellPlane, *cellPlaneOrig;
CellPropStruct cps;
/* Unlike dbScaleCell(), this routine is only run on valid edit defs */
@ -2120,31 +2286,15 @@ donecell:
DBMovePoint(&cellDef->cd_extended.r_ll, origx, origy);
DBMovePoint(&cellDef->cd_extended.r_ur, origx, origy);
/* If the cell is an abstract view with a fixed bounding box, then */
/* adjust the bounding box property to match the new scale. */
/* Check all properties for ones with keys beginning with "MASKHINTS_"
* or the key "FIXED_BBOX", and move them by the same amount as all
* the geometry.
*/
if ((cellDef->cd_flags & CDFIXEDBBOX) != 0)
{
Rect r;
bool found;
char *propval;
propval = (char *)DBPropGet(cellDef, "FIXED_BBOX", &found);
if (found)
{
if (sscanf(propval, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
&r.r_xtop, &r.r_ytop) == 4)
{
DBMovePoint(&r.r_ll, origx, origy);
DBMovePoint(&r.r_ur, origx, origy);
propval = (char *)mallocMagic(40);
sprintf(propval, "%d %d %d %d", r.r_xbot, r.r_ybot,
r.r_xtop, r.r_ytop);
DBPropPut(cellDef, "FIXED_BBOX", propval);
}
}
}
cps.cps_point.p_x = origx;
cps.cps_point.p_y = origy;
cps.cps_def = cellDef;
DBPropEnum(cellDef, dbMoveProp, &cps);
return 0;
}

View File

@ -275,7 +275,8 @@ dbUnexpandFunc(scx, arg)
* the given rectangle.
*
* Results:
* None.
* If "halt_on_error" is TRUE, then return 1 if any subcell could not
* be read. Otherwise, return 0.
*
* Side effects:
* May make new cells known to the database. Sets the CDAVAILABLE
@ -284,10 +285,11 @@ dbUnexpandFunc(scx, arg)
* ----------------------------------------------------------------------------
*/
void
DBCellReadArea(rootUse, rootRect)
int
DBCellReadArea(rootUse, rootRect, halt_on_error)
CellUse *rootUse; /* Root cell use from which search begins */
Rect *rootRect; /* Area to be read, in root coordinates */
bool halt_on_error; /* If TRUE, failure to find a cell causes a halt */
{
int dbReadAreaFunc();
SearchContext scontext;
@ -295,30 +297,39 @@ DBCellReadArea(rootUse, rootRect)
scontext.scx_use = rootUse;
scontext.scx_trans = GeoIdentityTransform;
scontext.scx_area = *rootRect;
(void) dbReadAreaFunc(&scontext);
if (dbReadAreaFunc(&scontext, halt_on_error) == 1)
return 1;
return 0;
}
int
dbReadAreaFunc(scx)
dbReadAreaFunc(scx, halt_on_error)
SearchContext *scx; /* Pointer to context specifying
* the cell use to be read in, and
* an area to be recursively read in
* coordinates of the cell use's def.
*/
bool halt_on_error; /* If TURE, failure to find a cell causes a halt */
{
CellDef *def = scx->scx_use->cu_def;
if ((def->cd_flags & CDAVAILABLE) == 0)
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
(void) DBCellRead(def, (char *) NULL, TRUE, dereference, NULL);
if (DBCellRead(def, (char *)NULL, TRUE, dereference, NULL) == FALSE)
if (halt_on_error)
return 1;
/* Note: we don't have to invoke DBReComputeBbox here because
* if the bbox changed then there was a timestamp mismatch and
* the timestamp code will take care of the bounding box later.
*/
}
(void) DBCellSrArea(scx, dbReadAreaFunc, (ClientData) NULL);
if (DBCellSrArea(scx, dbReadAreaFunc, (ClientData)halt_on_error))
if (halt_on_error)
return 1;
/* Be clever about handling arrays: if the search area covers this
* whole definition, then there's no need to look at any other
@ -328,5 +339,6 @@ dbReadAreaFunc(scx)
if (GEO_SURROUND(&scx->scx_area, &scx->scx_use->cu_def->cd_bbox))
return 2;
return 0;
}

View File

@ -45,6 +45,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include <paths.h>
#endif
#include "tcltk/tclmagic.h"
#include "utils/magic.h"
#include "utils/geometry.h"
#include "tiles/tile.h"
@ -898,7 +899,7 @@ DBReadBackup(name)
*
* DBCellRead --
*
* This is the wrapper for DBCellReadDef. The routine has been divided into
* This is the wrapper for dbCellReadDef. The routine has been divided into
* parts so that a single backup file can be made and recovered, and in
* preparation for allowing certain cell definitions to be in-lined into the
* output file (such as polygonXXXXX cells generated by the gds read-in).
@ -989,6 +990,11 @@ DBCellRead(cellDef, name, ignoreTech, dereference, errptr)
* CDAVAILABLE, with the CDNOTFOUND bit clear, if we
* were successful.
*
* Notes:
* Global variable DBVerbose determines whether or not error
* messages are generated by this routine. This can be controlled
* by "load -quiet".
*
* ----------------------------------------------------------------------------
*/
@ -1061,15 +1067,20 @@ dbReadOpen(cellDef, name, setFileName, errptr)
/* somewhere else in the search paths. */
if (pptr != NULL) *pptr = '.';
TxError("Warning: Parent cell lists instance of \"%s\" at bad file "
"path %s.\n", cellDef->cd_name, cellDef->cd_file);
if (DBVerbose)
TxError("Warning: Parent cell lists instance of \"%s\" at "
"bad file path %s.\n",
cellDef->cd_name, cellDef->cd_file);
/* Write the new path to cd_file or else magic will */
/* generate another error later. */
StrDup(&cellDef->cd_file, filename);
TxError("The cell exists in the search paths at %s.\n", filename);
TxError("The discovered version will be used.\n");
if (DBVerbose)
{
TxError("The cell exists in the search paths at %s.\n", filename);
TxError("The discovered version will be used.\n");
}
}
}
@ -1090,17 +1101,24 @@ dbReadOpen(cellDef, name, setFileName, errptr)
return ((FILE *) NULL);
if (name != (char *) NULL)
TxError("File %s%s couldn't be read\n", name, DBSuffix);
{
if (DBVerbose)
TxError("File %s%s couldn't be read\n", name, DBSuffix);
}
else if (cellDef->cd_file != (char *) NULL)
TxError("File %s couldn't be read\n", cellDef->cd_file);
{
if (DBVerbose)
TxError("File %s couldn't be read\n", cellDef->cd_file);
}
else {
TxError("Cell %s couldn't be read\n", cellDef->cd_name);
if (DBVerbose)
TxError("Cell %s couldn't be read\n", cellDef->cd_name);
realname = (char *) mallocMagic((unsigned) (strlen(cellDef->cd_name)
+ strlen(DBSuffix) + 1));
(void) sprintf(realname, "%s%s", cellDef->cd_name, DBSuffix);
StrDup(&cellDef->cd_file, realname);
}
if (errptr) TxError("%s\n", strerror(*errptr));
if (errptr && DBVerbose) TxError("%s\n", strerror(*errptr));
cellDef->cd_flags |= CDNOTFOUND;
return ((FILE *) NULL);
@ -1373,7 +1391,7 @@ badTransform:
else if (DBIsAncestor(subCellDef, cellDef))
{
/*
* Watchout for attempts to create circular structures.
* Watch out for attempts to create circular structures.
* If this happens, disregard the subcell.
*/
TxPrintf("Subcells are used circularly!\n");
@ -1382,6 +1400,33 @@ badTransform:
goto nextLine;
}
#ifdef MAGIC_WRAPPER
/* If path starts with '$' then check for a possible Tcl variable */
/* replacement. */
if (*pathptr == '$')
{
char *varstart, *varend, savechar, *tvar;
varstart = pathptr + 1;
if (*varstart == '{') varstart++;
varend = varstart + 1;
while (*varend != '\0' && *varend != '}' && *varend != '/'
&& *varend != '\n' && *varend != ' ') varend++;
savechar = *varend;
*varend = '\0';
tvar = (char *)Tcl_GetVar(magicinterp, varstart, TCL_GLOBAL_ONLY);
*varend = savechar;
if (savechar == '}') varend++;
if (tvar)
{
memmove(pathptr + strlen(tvar), varend, strlen(varend) + 1);
memmove(pathptr, tvar, strlen(tvar));
}
}
#endif
/* Relative path handling: If path does not have a leading "/" */
/* or "~" and cellDef->cd_file has path components, then the path */
/* should be interpreted relative to the path of the parent cell. */
@ -2902,7 +2947,8 @@ DBCellWrite(cellDef, fileName)
{
bool dereference = (cellDef->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
/* Re-aquire the lock on the new file by opening it. */
DBCellRead(cellDef, NULL, TRUE, dereference, NULL);
if (DBCellRead(cellDef, NULL, TRUE, dereference, NULL) == FALSE)
return FALSE;
}
#endif
@ -3146,6 +3192,7 @@ dbWriteCellFunc(cellUse, cdarg)
struct writeArg *arg = (struct writeArg *) cdarg;
Transform *t;
Rect *b;
bool subbed = FALSE;
char cstring[256], *pathend, *pathstart, *parent;
t = &(cellUse->cu_transform);
@ -3197,25 +3244,90 @@ dbWriteCellFunc(cellUse, cdarg)
}
else
{
/* If path starts with home path, then replace with "~" */
/* to make IP semi-portable between home directories */
/* with the same file structure. */
#ifdef MAGIC_WRAPPER
char *tvar;
char *homedir = getenv("HOME");
/* 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 (!strncmp(cellUse->cu_def->cd_file, homedir, strlen(homedir))
&& (*(cellUse->cu_def->cd_file + strlen(homedir)) == '/'))
if (subbed == FALSE)
{
sprintf(cstring, "use %s %c%s ~%s\n", cellUse->cu_def->cd_name,
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,
}
else
{
sprintf(cstring, "use %s %c%s %s\n", cellUse->cu_def->cd_name,
(cellUse->cu_flags & CU_LOCKED) ? CULOCKCHAR : ' ',
cellUse->cu_id, pathstart);
}
}
}
FPRINTR(arg->wa_file, cstring);

View File

@ -215,7 +215,7 @@ dbJoinUndo(tile, splitx, undo)
* 'undo' can be NULL.
*
* Results:
* None.
* Always return 0.
*
* Side effects:
* Modifies the database plane that contains the given tile.
@ -236,7 +236,7 @@ dbJoinUndo(tile, splitx, undo)
* ----------------------------------------------------------------------------
*/
void
int
DBPaintPlane0(plane, area, resultTbl, undo, method)
Plane *plane; /* Plane whose paint is to be modified */
Rect *area; /* Area to be changed */
@ -262,7 +262,7 @@ DBPaintPlane0(plane, area, resultTbl, undo, method)
bool haschanged;
if (area->r_xtop <= area->r_xbot || area->r_ytop <= area->r_ybot)
return;
return 0;
/*
* The following is a modified version of the area enumeration
@ -697,6 +697,7 @@ enum2:
done2:
plane->pl_hint = tile;
return 0;
}
/*
@ -1442,7 +1443,7 @@ typedef struct
* paint quadrangular (clipped triangle) areas.
*
* Results:
* None.
* 0 on success, 1 on error splitting a non-manhattan tile
*
* Side Effects:
* Plane is painted with a diagonal. The plane may be hacked up
@ -1452,7 +1453,7 @@ typedef struct
* ----------------------------------------------------------------------------
*/
void
int
DBNMPaintPlane0(plane, exacttype, area, resultTbl, undo, method)
Plane *plane; /* Plane whose paint is to be modified */
TileType exacttype; /* diagonal info for tile to be changed */
@ -1478,6 +1479,7 @@ DBNMPaintPlane0(plane, exacttype, area, resultTbl, undo, method)
int xc, yc, width, height;
dlong xref, yref; /* xref, yref can easily exceed 32 bits */
int resstate;
int result = 0;
if (exacttype & TT_DIAGONAL)
{
@ -1532,7 +1534,7 @@ DBNMPaintPlane0(plane, exacttype, area, resultTbl, undo, method)
if (resultTbl[oldType] == oldType)
{
freeMagic((char *) lr);
return;
return 0;
}
}
@ -1544,7 +1546,7 @@ DBNMPaintPlane0(plane, exacttype, area, resultTbl, undo, method)
if (newType == oldType)
{
freeMagic((char *) lr);
return;
return 0;
}
/* Watch for the worst-case scenario of attempting to */
@ -1560,9 +1562,9 @@ DBNMPaintPlane0(plane, exacttype, area, resultTbl, undo, method)
{
if ((width == 1) || (height == 1))
{
DBPaintPlane(plane, &(lr->r_r), resultTbl, undo);
result = DBPaintPlane(plane, &(lr->r_r), resultTbl, undo);
freeMagic((char *) lr);
return;
return 1; /* Flag the error by returning 1 */
}
/* lr->r_r is drawn & quartered */
@ -1605,7 +1607,7 @@ DBNMPaintPlane0(plane, exacttype, area, resultTbl, undo, method)
if (newType & TT_DIAGONAL)
{
DBPaintPlane(plane, &(lr->r_r), DBSpecialPaintTbl,
result = DBPaintPlane(plane, &(lr->r_r), DBSpecialPaintTbl,
(PaintUndoInfo *)NULL);
tile = plane->pl_hint;
GOTOPOINT(tile, &(lr->r_r.r_ll));
@ -1620,14 +1622,14 @@ DBNMPaintPlane0(plane, exacttype, area, resultTbl, undo, method)
{
PaintResultType tempTbl;
tempTbl = newType;
DBPaintPlane0(plane, &(lr->r_r), &tempTbl, undo, method);
result = DBPaintPlane0(plane, &(lr->r_r), &tempTbl,
undo, method);
}
else
DBPaintPlane(plane, &(lr->r_r), resultTbl, undo);
result = DBPaintPlane(plane, &(lr->r_r), resultTbl, undo);
freeMagic((char *) lr);
/* goto nmmerge; */
return;
return result;
}
}
@ -1755,11 +1757,12 @@ paintrect:
if (resstate == RES_DIAG)
{
/* Recursive call to self on sub-area */
DBNMPaintPlane0(plane, exacttype, &(lr->r_r), resultTbl, undo, method);
result |= DBNMPaintPlane0(plane, exacttype, &(lr->r_r), resultTbl,
undo, method);
}
else if ((resstate == RES_LEFT && !dinfo.side) ||
(resstate == RES_RIGHT && dinfo.side)) {
DBPaintPlane(plane, &(lr->r_r), resultTbl, undo);
result |= DBPaintPlane(plane, &(lr->r_r), resultTbl, undo);
}
/* else: Rectangle does not contain type and should be ignored. */
nextrect:
@ -1774,8 +1777,10 @@ nextrect:
}
}
else
DBPaintPlane0(plane, area, resultTbl, undo, (method == PAINT_MARK) ?
result = DBPaintPlane0(plane, area, resultTbl, undo, (method == PAINT_MARK) ?
method : PAINT_NORMAL);
return result;
}
/*
@ -2547,7 +2552,7 @@ dbMergeType(tile, newType, plane, mergeFlags, undo, client)
* ----------------------------------------------------------------------------
*/
void
int
DBPaintPlaneVert(plane, area, resultTbl, undo)
Plane *plane; /* Plane whose paint is to be modified */
Rect *area; /* Area to be changed */

View File

@ -34,7 +34,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
/* ----------------------------------------------------------------------------
*
*DBPropPut --
* DBPropPut --
*
* Put a property onto a celldef.
*
@ -57,8 +57,15 @@ DBPropPut(cellDef, name, value)
HashEntry *entry;
char *oldvalue;
/* Honor the NOEDIT flag */
if (cellDef->cd_flags & CDNOEDIT) return;
/* Honor the NOEDIT flag. Note that the caller always assumes that */
/* the value would be saved in the hash table, so if it is not */
/* being used, then it must be freed here. */
if (cellDef->cd_flags & CDNOEDIT)
{
freeMagic((char *)value);
return;
}
if (cellDef->cd_props == (ClientData) NULL)
{

View File

@ -204,9 +204,57 @@ DBTechSetVersion(sectionName, argc, argv)
}
return TRUE;
}
if (strcmp(argv[0], "requires") == 0)
{
/* Version requirement check. If the techfile has "requires" followed
* by a magic version number in the form [magic-]<major>.<minor>.<revision>,
* then the version of magic is checked against this, and the tech
* loading will fail if there is a version incompatibility.
*/
int major, minor, rev;
int rmajor, rminor, rrev;
bool goodversion = FALSE;
char *vstring;
vstring = argv[1];
while ((*vstring != '\0') && !isdigit(*vstring)) vstring++;
major = minor = rev = 0;
rmajor = rminor = rrev = 0;
if (sscanf(vstring, "%d.%d.%d", &rmajor, &rminor, &rrev) == 0)
{
TechError("Badly formed magic version string, should be major.minor.rev\n");
return FALSE;
}
sscanf(MagicVersion, "%d.%d", &major, &minor);
sscanf(MagicRevision, "%d", &rev);
if (major > rmajor)
goodversion = TRUE;
else if (major == rmajor)
{
if (minor > rminor)
goodversion = TRUE;
else if (minor == rminor)
{
if (rev >= rrev)
goodversion = TRUE;
}
}
if (goodversion == FALSE)
{
TechError("Error: Magic version %d.%d.%d is required by this "
"techfile, but this version of magic is %d.%d.%d.\n",
rmajor, rminor, rrev, major, minor, rev);
return FALSE;
}
return TRUE;
}
usage:
TechError("Badly formed version line\nUsage: {version text}|{description text}\n");
TechError("Badly formed version line\n"
"Usage: {version text}|{description text}|{requires text}\n");
return FALSE;
}

View File

@ -265,42 +265,46 @@ typedef struct label
* Label flags bit fields
*/
#define PORT_NUM_MASK 0x0fff /* Mask of port number (up to 4096) */
#define PORT_NUM_MASK 0x003fff /* Mask of port number (up to 16384) */
#define PORT_DIR_MASK 0xf000 /* Mask of all port directions */
#define PORT_DIR_NORTH 0x1000 /* Port allows connection to north */
#define PORT_DIR_EAST 0x2000 /* Port allows connection to east */
#define PORT_DIR_SOUTH 0x4000 /* Port allows connection to south */
#define PORT_DIR_WEST 0x8000 /* Port allows connection to west */
#define PORT_DIR_MASK 0x03c000 /* Mask of all port directions */
#define PORT_DIR_NORTH 0x004000 /* Port allows connection to north */
#define PORT_DIR_EAST 0x008000 /* Port allows connection to east */
#define PORT_DIR_SOUTH 0x010000 /* Port allows connection to south */
#define PORT_DIR_WEST 0x020000 /* Port allows connection to west */
#define PORT_CLASS_MASK 0x70000 /* Mask of all port classes */
#define PORT_CLASS_DEFAULT 0x00000 /* Port takes default class */
#define PORT_CLASS_INPUT 0x10000 /* Port is a digital input */
#define PORT_CLASS_OUTPUT 0x20000 /* Port is a digital output */
#define PORT_CLASS_TRISTATE 0x30000 /* Port is a tri-state output */
#define PORT_CLASS_BIDIRECTIONAL 0x40000 /* Port is analog or digital */
/* bidirectional */
#define PORT_CLASS_FEEDTHROUGH 0x50000 /* Port touches no active */
/* devices */
#define PORT_CLASS_MASK 0x1c0000 /* Mask of all port classes */
#define PORT_CLASS_DEFAULT 0x000000 /* Port takes default class */
#define PORT_CLASS_INPUT 0x040000 /* Port is a digital input */
#define PORT_CLASS_OUTPUT 0x080000 /* Port is a digital output */
#define PORT_CLASS_TRISTATE 0x0c0000 /* Port is a tri-state output */
#define PORT_CLASS_BIDIRECTIONAL 0x100000 /* Port is analog or digital */
/* bidirectional */
#define PORT_CLASS_FEEDTHROUGH 0x140000 /* Port touches no active */
/* devices */
#define PORT_USE_MASK 0x0700000 /* Mask of all port uses */
#define PORT_USE_DEFAULT 0x0000000 /* Port takes default use */
#define PORT_USE_SIGNAL 0x0100000 /* Port is a digital signal */
#define PORT_USE_ANALOG 0x0200000 /* Port is an analog signal */
#define PORT_USE_POWER 0x0300000 /* Port is a power rail */
#define PORT_USE_GROUND 0x0400000 /* Port is a ground rail */
#define PORT_USE_CLOCK 0x0500000 /* Port is a digital clock */
/* signal */
#define PORT_SHAPE_MASK 0x1800000 /* Mask of all port shapes */
#define PORT_SHAPE_DEFAULT 0x0000000 /* Port takes default shape */
#define PORT_SHAPE_ABUT 0x0800000 /* Port is an abutment shape */
#define PORT_SHAPE_RING 0x1000000 /* Port is a ring shape */
#define PORT_SHAPE_THRU 0x1800000 /* Port is a feedthrough shape */
#define PORT_VISITED 0x2000000 /* Bit for checking if a port */
#define PORT_USE_MASK 0x03c00000 /* Mask of all port uses */
#define PORT_USE_DEFAULT 0x00000000 /* Port takes default use */
#define PORT_USE_SIGNAL 0x00400000 /* Port is a digital signal */
#define PORT_USE_ANALOG 0x00800000 /* Port is an analog signal */
#define PORT_USE_POWER 0x00c00000 /* Port is a power rail */
#define PORT_USE_GROUND 0x01000000 /* Port is a ground rail */
#define PORT_USE_CLOCK 0x01400000 /* Port is a digital clock */
#define PORT_USE_RESET 0x01800000 /* Port is a digital reset */
#define PORT_USE_SCAN 0x01c00000 /* Port is a digital scan */
#define PORT_USE_TIEOFF 0x02000000 /* Port is a tie-off */
#define PORT_SHAPE_MASK 0x0c000000 /* Mask of all port shapes */
#define PORT_SHAPE_DEFAULT 0x00000000 /* Port takes default shape */
#define PORT_SHAPE_ABUT 0x04000000 /* Port is an abutment shape */
#define PORT_SHAPE_RING 0x08000000 /* Port is a ring shape */
#define PORT_SHAPE_THRU 0x0c000000 /* Port is a feedthrough shape */
#define PORT_VISITED 0x10000000 /* Bit for checking if a port */
/* has been previously visited. */
#define LABEL_STICKY 0x4000000 /* Label does not change layers */
#define LABEL_GENERATE 0x8000000 /* Auto-generated label */
#define LABEL_STICKY 0x20000000 /* Label does not change layers */
#define LABEL_GENERATE 0x40000000 /* Auto-generated label */
/*
* Macros for dealing with label rectangles.
@ -652,7 +656,7 @@ typedef struct treeFilter
#define TF_LABEL_ATTACH_CORNER 0x3C /* Mask of the four types above */
/* To do: Make the tpath entries dynamically allocated */
#define FLATTERMSIZE 1024 /* Used for generating flattened labels */
#define FLATTERMSIZE 4096 /* Used for generating flattened labels */
/* -------------- Undo information passed to DBPaintPlane ------------- */
@ -692,13 +696,13 @@ typedef struct
extern void DBPaint();
extern void DBErase();
extern int DBSrPaintArea();
extern void DBPaintPlane0();
extern void DBPaintPlaneActive();
extern void DBPaintPlaneWrapper();
extern void DBPaintPlaneMark();
extern void DBPaintPlaneXor();
extern void DBPaintPlaneByProc();
extern void DBPaintPlaneMergeOnce();
extern int DBPaintPlane0();
extern int DBPaintPlaneActive();
extern int DBPaintPlaneWrapper();
extern int DBPaintPlaneMark();
extern int DBPaintPlaneXor();
extern int DBPaintPlaneByProc();
extern int DBPaintPlaneMergeOnce();
extern void DBPaintMask();
extern void DBEraseMask();
extern void DBClearPaintPlane();
@ -708,7 +712,7 @@ extern void DBUnlockContact();
#define DBPaintPlane(a, b, c, d) DBPaintPlane0(a, b, c, d, PAINT_NORMAL)
#define DBMergeNMTiles(a, b, c) DBMergeNMTiles0(a, b, c, FALSE)
extern void DBNMPaintPlane0();
extern int DBNMPaintPlane0();
#define DBNMPaintPlane(a, b, c, d, e) DBNMPaintPlane0(a, b, c, d, e, PAINT_NORMAL)
/* I/O */
@ -716,7 +720,7 @@ extern bool DBCellRead();
extern bool DBTestOpen();
extern char *DBGetTech();
extern bool DBCellWrite();
extern void DBCellReadArea();
extern int DBCellReadArea();
extern void DBFileRecovery();
extern bool DBWriteBackup();
extern bool DBReadBackup();
@ -812,6 +816,7 @@ extern char *DBPrintUseId();
/* Massive copying */
extern void DBCellCopyPaint();
extern void DBCellCopyAllPaint();
extern void DBCellCheckCopyAllPaint();
extern void DBCellCopyLabels();
extern void DBCellCopyAllLabels();
extern void DBCellCopyCells();
@ -841,8 +846,8 @@ extern void DBEnumerateTypes();
extern Plane *DBNewPlane();
extern PaintResultType (*DBNewPaintTable())[TT_MAXTYPES][TT_MAXTYPES];
typedef void (*VoidProc)();
VoidProc DBNewPaintPlane();
typedef int (*IntProc)();
IntProc DBNewPaintPlane();
/* Diagnostic */
extern void DBTechPrintTypes();

View File

@ -49,7 +49,7 @@ extern void CmdGetcell(), CmdGrid(), CmdIdentify();
extern void CmdLabel(), CmdLoad();
extern void CmdMove(), CmdNetlist(), CmdOrient(), CmdPaint(), CmdPath();
extern void CmdPlow(), CmdPolygon(), CmdPort(), CmdProperty();
extern void CmdSave(), CmdScaleGrid(), CmdSee();
extern void CmdRandom(), CmdSave(), CmdScaleGrid(), CmdSee();
extern void CmdSelect(), CmdSetLabel(), CmdSideways();
extern void CmdShell(), CmdSnap();
extern void CmdStretch(), CmdStraighten();
@ -407,6 +407,9 @@ DBWInitCommands()
WindAddCommand(DBWclientID,
"rotate [+/-][deg] rotate selection and box (counter)clockwise",
CmdClockwise, FALSE); /* "rotate" is alias for "clockwise" */
WindAddCommand(DBWclientID,
"random [seed [value]] generate random number or set random seed",
CmdRandom, FALSE);
WindAddCommand(DBWclientID,
"save [filename] save edit cell on disk",
CmdSave, FALSE);

View File

@ -620,6 +620,16 @@ drcTile (tile, arg)
drcCheckRectSize(tile, arg, cptr);
continue;
}
/* Off-grid checks apply only to edge */
if (cptr->drcc_flags & DRC_OFFGRID)
{
errRect.r_ytop = edgeTop;
errRect.r_ybot = edgeBot;
errRect.r_xtop = errRect.r_xbot = edgeX;
arg->dCD_cptr = cptr;
drcCheckOffGrid(&errRect, arg, cptr);
continue;
}
result = 0;
arg->dCD_radial = 0;
@ -983,13 +993,22 @@ checkbottom:
}
continue;
}
else if (cptr->drcc_flags & (DRC_AREA | DRC_RECTSIZE
| DRC_MAXWIDTH))
else if (cptr->drcc_flags & (DRC_AREA | DRC_RECTSIZE | DRC_MAXWIDTH))
{
/* only have to do these checks in one direction */
if (trigpending) cptr = cptr->drcc_next;
continue;
}
/* Off-grid checks apply only to edge */
if (cptr->drcc_flags & DRC_OFFGRID)
{
errRect.r_xtop = edgeRight;
errRect.r_xbot = edgeLeft;
errRect.r_ytop = errRect.r_ybot = edgeY;
arg->dCD_cptr = cptr;
drcCheckOffGrid(&errRect, arg, cptr);
continue;
}
result = 0;
arg->dCD_radial = 0;

View File

@ -197,12 +197,7 @@ DRCCheckThis (celldef, operation, area)
* of CellDefs waiting for DRC
*/
/* Ignore internal GDS cells. */
/* Note that this rescinds the former behavior of ignoring DRC on */
/* vendor and read-only cells. Such cells will be flattened in */
/* interaction areas and show errors anyway, so not showing errors */
/* in the cell is just confusing. */
/* Ignore internal cells. */
if (celldef->cd_flags & CDINTERNAL) return;
/* Insert celldef into list of Defs waiting to be checked, unless */

View File

@ -70,6 +70,50 @@ drcCheckAngles(tile, arg, cptr)
}
}
/*
*-------------------------------------------------------------------------
*
* drcCheckOffGrid- checks to see that an edge is on the specified
* grid pitch.
*
* Results: none
*
* Side Effects: may cause errors to be painted.
*
*-------------------------------------------------------------------------
*/
void
drcCheckOffGrid(edgeRect, arg, cptr)
Rect *edgeRect;
struct drcClientData *arg;
DRCCookie *cptr;
{
Rect rect;
int gtest;
if (cptr->drcc_dist <= 1) return; /* No error by definition */
rect = *edgeRect;
GeoClip(&rect, arg->dCD_clip);
/* Expand rect to nearest pitch */
gtest = (rect.r_xbot / cptr->drcc_dist) * cptr->drcc_dist;
if (gtest < rect.r_xbot) rect.r_xbot = gtest;
gtest = (rect.r_xtop / cptr->drcc_dist) * cptr->drcc_dist;
if (gtest > rect.r_xtop) rect.r_xtop = gtest;
gtest = (rect.r_ybot / cptr->drcc_dist) * cptr->drcc_dist;
if (gtest < rect.r_ybot) rect.r_ybot = gtest;
gtest = (rect.r_ytop / cptr->drcc_dist) * cptr->drcc_dist;
if (gtest > rect.r_ytop) rect.r_ytop = gtest;
if (!GEO_RECTNULL(&rect)) {
(*(arg->dCD_function)) (arg->dCD_celldef, &rect,
arg->dCD_cptr, arg->dCD_clientData);
(*(arg->dCD_errors))++;
}
}
/*
*-------------------------------------------------------------------------
*
@ -144,10 +188,6 @@ drcCheckArea(starttile,arg,cptr)
if (!GEO_RECTNULL(&rect)) {
(*(arg->dCD_function)) (arg->dCD_celldef, &rect,
arg->dCD_cptr, arg->dCD_clientData);
/***
DBWAreaChanged(arg->dCD_celldef,&rect, DBW_ALLWINDOWS,
&DBAllButSpaceBits);
***/
(*(arg->dCD_errors))++;
}
}

View File

@ -664,7 +664,11 @@ DRCCheck(use, area)
SearchContext scx;
extern int drcCheckFunc(); /* Forward reference. */
DBCellReadArea(use, area);
if (DBCellReadArea(use, area, TRUE))
{
TxError("Failure to read in entire subtree of cell.\n");
return;
}
scx.scx_use = use;
scx.scx_x = use->cu_xlo;
@ -702,8 +706,8 @@ drcCheckFunc(scx, cdarg)
DRCCheckThis(def, TT_CHECKPAINT, (Rect *) NULL);
/* New behavior: Don't search children, instead propagate errors up. */
/* (void) DBCellSrArea(scx, drcCheckFunc, (ClientData) NULL); */
/* Search children */
(void) DBCellSrArea(scx, drcCheckFunc, (ClientData) NULL);
/* As a special performance hack, if the complete cell area is
* handled here, don't bother to look at any more array elements.

View File

@ -74,7 +74,22 @@ static DRCCookie drcInSubCookie = {
(DRCCookie *) NULL
};
/* The following DRC cookie is used when flattening non-Manhattan
* shapes results in a non-integer coordinate. Because the non-
* integer coordinate cannot be represented in magic, the position
* is flagged as a DRC error.
*/
static DRCCookie drcOffGridCookie = {
0, 0, 0, 0,
{ 0 }, { 0 },
0, 0, 0,
DRC_OFFGRID_TAG,
(DRCCookie *) NULL
};
extern int DRCErrorType;
extern CellDef *DRCErrorDef;
/*
* ----------------------------------------------------------------------------
@ -604,6 +619,37 @@ drcExactOverlapTile(tile, cxp)
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* DRCOffGridError ---
*
* Function to call when a call to DBCellCheckCopyAllPaint() flags an error
* indicating that a subcell overlap of non-Manhattan geometry resolves to
* an off-grid intersection point. Note that this is different from the
* DRC off-grid check, which checks for geometry that does not match the
* manufacturing grid pitch. This checks for the case of geometry that
* is finer than the underlying database grid, which can only happen for
* two non-Manhattan shapes interacting between two different cells, and
* can only be caught during the process of flattening the cell contents.
*
* Results:
* None.
*
* Side effects:
* Creates a DRC error or prints the DRC error message, depending on
* the value of drcSubFunc.
*
* ----------------------------------------------------------------------------
*/
void
DRCOffGridError(rect)
Rect *rect; /* Area of error */
{
(*drcSubFunc)(DRCErrorDef, rect, &drcOffGridCookie, drcSubClientData);
}
/*
* ----------------------------------------------------------------------------
*
@ -809,7 +855,8 @@ DRCInteractionCheck(def, area, erasebox, func, cdarg)
savedPaintTable = DBNewPaintTable(DRCCurStyle->DRCPaintTable);
savedPaintPlane = DBNewPaintPlane(DBPaintPlaneMark);
(void) DBCellCopyAllPaint(&scx, &DBAllButSpaceBits, 0, DRCuse);
(void) DBCellCheckCopyAllPaint(&scx, &DBAllButSpaceBits, 0,
DRCuse, func);
(void) DBNewPaintTable(savedPaintTable);
(void) DBNewPaintPlane(savedPaintPlane);

View File

@ -73,7 +73,7 @@ static int DRCtag = 0;
int drcWidth(), drcSpacing(), drcEdge(), drcNoOverlap();
int drcExactOverlap(), drcExtend();
int drcSurround(), drcRectOnly(), drcOverhang();
int drcStepSize(), drcOption();
int drcStepSize(), drcOption(), drcOffGrid();
int drcMaxwidth(), drcArea(), drcRectangle(), drcAngles();
int drcCifSetStyle(), drcCifWidth(), drcCifSpacing();
int drcCifMaxwidth(), drcCifArea();
@ -587,6 +587,11 @@ DRCTechStyleInit()
/* (see DRCsubcell.c). */
drcWhyCreate("See error definition in the subcell");
/* Fifth DRC entry is associated with the statically-allocated */
/* drcOffGridCookie and has a tag of DRC_OFFGRID_TAG = 5 */
/* (see DRCsubcell.c). */
drcWhyCreate("This position does not align with the manufacturing grid");
DRCTechHalo = 0;
/* Put a dummy rule at the beginning of the rules table for each entry */
@ -922,7 +927,8 @@ drcCifAssign(cookie, dist, next, mask, corner, tag, cdist, flags, planeto, plane
int dist, cdist;
TileTypeBitMask *mask, *corner;
int tag;
int flags, planeto, planefrom;
unsigned short flags;
int planeto, planefrom;
{
(cookie)->drcc_dist = dist;
(cookie)->drcc_next = next;
@ -946,7 +952,8 @@ drcAssign(cookie, dist, next, mask, corner, why, cdist, flags, planeto, planefro
int dist, cdist;
TileTypeBitMask *mask, *corner;
int why;
int flags, planeto, planefrom;
unsigned short flags;
int planeto, planefrom;
{
/* Diagnostic */
if (planeto >= DBNumPlanes)
@ -1040,6 +1047,8 @@ DRCTechAddRule(sectionName, argc, argv)
"layers1 width layers2 separation adjacency why",
"area", 5, 5, drcArea,
"layers area horizon why",
"off_grid", 4, 4, drcOffGrid,
"layers pitch why",
"maxwidth", 4, 5, drcMaxwidth,
"layers maxwidth bends why",
"cifstyle", 2, 2, drcCifSetStyle,
@ -1434,6 +1443,85 @@ drcArea(argc, argv)
return (horizon);
}
/*
* ----------------------------------------------------------------------------
*
* drcOffGrid --
*
* Process an off-grid rule.
* This is of the form:
*
* off_grid layers pitch why
*
* e.g,
*
* off_grid m1 5 "metal shapes must be on %d grid"
*
* "pitch" is the grid pitch that shapes must be aligned to.
*
* Results:
* Returns pitch (the halo for detecting off-grid errors).
*
* Side effects:
* Updates the DRC technology variables.
*
* ----------------------------------------------------------------------------
*/
int
drcOffGrid(argc, argv)
int argc;
char *argv[];
{
char *layers = argv[1];
int pitch = atoi(argv[2]);
int why = drcWhyCreate(argv[3]);
TileTypeBitMask set, setC;
DRCCookie *dp, *dpnew;
TileType i, j;
PlaneMask pset;
int plane;
DBTechNoisyNameMask(layers, &set);
TTMaskCom2(&setC, &set);
for (i = 0; i < DBNumTypes; i++)
{
for (j = 0; j < DBNumTypes; j++)
{
if (i == j) continue;
/*
* Must have types in 'set' for at least 'distance'
* to the right of any edge between a type in '~set'
* and a type in 'set'.
*/
if (pset = (DBTypesOnSamePlane(i, j)))
{
if (TTMaskHasType(&setC, i) && TTMaskHasType(&set, j))
{
plane = LowestMaskBit(pset);
/* find bucket preceding the new one we wish to insert */
dp = drcFindBucket(i, j, pitch);
dpnew = (DRCCookie *) mallocMagic(sizeof (DRCCookie));
drcAssign(dpnew, pitch, dp->drcc_next, &set, &set, why,
0, DRC_OFFGRID|DRC_FORWARD, plane, plane);
dp->drcc_next = dpnew;
/* opposite edge also needs to be checked */
dp = drcFindBucket(j, i, pitch);
dpnew = (DRCCookie *) mallocMagic(sizeof (DRCCookie));
drcAssign(dpnew, pitch, dp->drcc_next, &set, &set, why,
0, DRC_OFFGRID|DRC_REVERSE, plane, plane);
dp->drcc_next = dpnew;
}
}
}
}
return (pitch);
}
/*
* ----------------------------------------------------------------------------
*

View File

@ -48,6 +48,7 @@ typedef struct drccookie
#define DRC_OVERLAP_TAG 2
#define DRC_SUBCELL_OVERLAP_TAG 3
#define DRC_IN_SUBCELL_TAG 4
#define DRC_OFFGRID_TAG 5
/* *This is size "int" because it holds an area for DRC_AREA rules, */
/* and therefore may have twice the bit length of a normal rule distance. */
@ -63,20 +64,22 @@ typedef struct drccookie
* edge processing.
*/
#define DRC_FORWARD 0x00
#define DRC_REVERSE 0x01
#define DRC_BOTHCORNERS 0x02
#define DRC_TRIGGER 0x04
#define DRC_BENDS 0x08
#define DRC_OUTSIDE 0x08 // Note: Shared with DRC_BENDS
#define DRC_AREA 0x10
#define DRC_MAXWIDTH 0x20
#define DRC_RECTSIZE 0x40
#define DRC_ANGLES 0x80
#define DRC_NONSTANDARD (DRC_AREA|DRC_MAXWIDTH|DRC_RECTSIZE|DRC_ANGLES)
#define DRC_FORWARD 0x000
#define DRC_REVERSE 0x001
#define DRC_BOTHCORNERS 0x002
#define DRC_TRIGGER 0x004
#define DRC_BENDS 0x008
#define DRC_OUTSIDE 0x010
#define DRC_AREA 0x020
#define DRC_OFFGRID 0x040
#define DRC_MAXWIDTH 0x080
#define DRC_RECTSIZE 0x100
#define DRC_ANGLES 0x200
#define DRC_NONSTANDARD (DRC_AREA|DRC_MAXWIDTH|DRC_RECTSIZE\
|DRC_ANGLES|DRC_OFFGRID)
/* More flags for indicating what the rule type represents */
#define DRC_CIFRULE 0x100
#define DRC_CIFRULE 0x400
#define DRC_PENDING 0
#define DRC_UNPROCESSED CLIENTDEFAULT
@ -165,7 +168,7 @@ typedef struct drcstyle
int DRCScaleFactorD; /* Multiply dist by this to get magic units */
int DRCTechHalo; /* largest action distance of design rules */
int DRCStepSize; /* chunk size for decomposing large areas */
char DRCFlags; /* Option flags */
unsigned short DRCFlags; /* Option flags */
char **DRCWhyList; /* Indexed list of "why" text strings */
int DRCWhySize; /* Length of DRCWhyList */
PaintResultType DRCPaintTable[NP][NT][NT];
@ -271,6 +274,7 @@ extern int DRCFind();
extern void DRCCatchUp();
extern bool DRCFindInteractions();
extern int DRCBasicCheck();
extern void DRCOffGridError();
extern void DRCPrintStyle();
extern void DRCSetStyle();

View File

@ -350,6 +350,13 @@ esOutputHierResistor(hc, dev, scale, term1, term2, has_model, l, w, dscale)
/* term1=gate term2=source by the above code. */
/* extracted units are Ohms; output is in Ohms */
if ((term1->dterm_node == NULL) || (term2->dterm_node == NULL))
{
TxError("Error: Resistor %s missing terminal node!\n",
EFDevTypes[dev->dev_type]);
return;
}
spcdevOutNode(hc->hc_hierName, term1->dterm_node->efnode_name->efnn_hier,
"res_top", esSpiceF);
spcdevOutNode(hc->hc_hierName, term2->dterm_node->efnode_name->efnn_hier,
@ -405,6 +412,7 @@ subcktHierVisit(use, hierName, is_top)
EFNode *snode;
EFNodeName *nodeName;
bool hasports = FALSE;
bool isStub;
/* Avoid generating records for circuits that have no ports. */
/* These are already absorbed into the parent. All other */
@ -431,6 +439,13 @@ subcktHierVisit(use, hierName, is_top)
break;
}
/* Same considerations as at line 1831 for determining if the cell */
/* has been folded into the parent and should not be output. */
isStub = ((def->def_flags & DEF_ABSTRACT) && esDoBlackBox) ? TRUE : FALSE;
if ((!is_top) && (def->def_flags & DEF_NODEVICES) && (!isStub))
return 0;
if (hasports || is_top)
return subcktVisit(use, hierName, is_top);
else if (def->def_flags & DEF_NODEVICES)
@ -1557,6 +1572,7 @@ devDistJunctHierVisit(hc, dev, scale)
* for each connection to it. Note that this generates an arbitrary
* port order for each cell. To have a specific port order, it is
* necessary to generate ports for each cell.
*
* ----------------------------------------------------------------------------
*/
@ -1570,6 +1586,7 @@ esMakePorts(hc, cdata)
Use *use;
HashEntry *he;
EFNodeName *nn;
char *name, *portname, *tptr, *aptr, *locname;
int j;

View File

@ -1635,6 +1635,11 @@ subcktUndef(use, hierName, is_top)
* subcircuit, and implicit substrate connections should not be
* output.
*
* NOTE: The cookie-cutter method for extraction can result in multiple
* connections to the same port if the net spans multiple extraction regions.
* Because of this, it is necessary to make sure that the same port name is
* not output twice.
*
* ----------------------------------------------------------------------------
*/
@ -1646,13 +1651,16 @@ topVisit(def, doStub)
EFNode *snode, *basenode;
EFNodeName *sname, *nodeName;
HashSearch hs;
HashEntry *he;
HashEntry *he, *hep;
HashTable portNameTable;
int portorder, portmax, tchars;
DevParam *plist, *pptr;
char *instname;
char *subcktname;
char *pname;
HashInit(&portNameTable, 32, HT_STRINGKEYS);
/* SPICE subcircuit names must begin with A-Z. This will also be */
/* enforced when writing X subcircuit calls. */
subcktname = def->def_name;
@ -1698,19 +1706,25 @@ topVisit(def, doStub)
if (snode->efnode_flags & EF_PORT)
{
pname = nodeSpiceName(snode->efnode_name->efnn_hier, &basenode);
if (basenode->efnode_name->efnn_port < 0)
if (HashLookOnly(&portNameTable, pname) == NULL)
{
if (tchars > 80)
hep = HashFind(&portNameTable, pname);
if (basenode->efnode_name->efnn_port < 0)
{
/* Line continuation */
fprintf(esSpiceF, "\n+");
tchars = 1;
if (tchars > 80)
{
/* Line continuation */
fprintf(esSpiceF, "\n+");
tchars = 1;
}
fprintf(esSpiceF, " %s", pname);
tchars += strlen(pname) + 1;
basenode->efnode_name->efnn_port = portorder++;
}
fprintf(esSpiceF, " %s", pname);
tchars += strlen(pname) + 1;
basenode->efnode_name->efnn_port = portorder++;
snode->efnode_name->efnn_port = basenode->efnode_name->efnn_port;
HashSetValue(hep,
(ClientData)(pointertype)snode->efnode_name->efnn_port);
}
snode->efnode_name->efnn_port = basenode->efnode_name->efnn_port;
}
}
}
@ -1757,8 +1771,24 @@ topVisit(def, doStub)
}
else
pname = nodeSpiceName(snode->efnode_name->efnn_hier, NULL);
fprintf(esSpiceF, " %s", pname);
tchars += strlen(pname) + 1;
if (HashLookOnly(&portNameTable, pname) == NULL)
{
hep = HashFind(&portNameTable, pname);
HashSetValue(hep,
(ClientData)(pointertype)nodeName->efnn_port);
fprintf(esSpiceF, " %s", pname);
tchars += strlen(pname) + 1;
}
else
{
// Node that was unassigned has been found to be
// a repeat (see NOTE at top), so make sure its
// port number is set correctly.
hep = HashFind(&portNameTable, pname);
nodeName->efnn_port = (int)(pointertype)HashGetValue(hep);
}
break;
}
else if (portidx < 0)
@ -1779,6 +1809,7 @@ topVisit(def, doStub)
portorder++;
}
}
HashKill(&portNameTable);
/* Add all implicitly-defined local substrate node names */

View File

@ -397,6 +397,7 @@ efHierDevKilled(hc, dev, prefix)
for (n = 0; n < dev->dev_nterm; n++)
{
if (dev->dev_terms[n].dterm_node == NULL) continue;
suffix = dev->dev_terms[n].dterm_node->efnode_name->efnn_hier;
he = HashLookOnly(&efNodeHashTable, (char *)suffix);
if (he && (nn = (EFNodeName *) HashGetValue(he))

View File

@ -286,6 +286,7 @@ extern Def *EFRootDef();
/* HierName manipulation */
extern HierName *efHNFromUse();
extern char *efHNToStrFunc();
extern bool EFHNBest();
/* Functions for hashing of HierNames */
extern int efHNCompare();

View File

@ -66,7 +66,7 @@ bool efDevKilled();
* (*subProc)(use, hierName, is_top)
* Use *use;
* HierName *hierName;
* Boolean is_top;
* bool is_top;
* {
* }
*

View File

@ -606,7 +606,12 @@ extArrayInterFunc(use, trans, x, y, ha)
extHierConnections(ha, extArrayPrimary, oneFlat);
/* Process substrate connection */
extHierSubstrate(ha, use, x, y);
if (use->cu_xlo == use->cu_xhi)
extHierSubstrate(ha, use, -1, y);
else if (use->cu_ylo == use->cu_yhi)
extHierSubstrate(ha, use, x, -1);
else
extHierSubstrate(ha, use, x, y);
ha->ha_cumFlat.et_nodes = (NodeRegion *) NULL;
if (ExtOptions & EXT_DOADJUST)

View File

@ -67,7 +67,8 @@ char *extDevTable[] = {"fet", "mosfet", "asymmetric", "bjt", "devres",
* used to compute the resistance of each node. Each is
* indexed by sheet resistivity class.
*/
int extResistPerim[NT], extResistArea[NT];
int extResistPerim[NT];
dlong extResistArea[NT];
/*
* The following structure is used in extracting transistors.
@ -575,7 +576,8 @@ void
extSetResist(reg)
NodeRegion *reg;
{
int n, perim, area;
int n, perim;
dlong area;
float s, fperim, v;
for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++)
@ -704,7 +706,7 @@ extOutputNodes(nodeList, outFile)
/* Output its area and perimeter for each resistivity class */
for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++)
fprintf(outFile, " %d %d", reg->nreg_pa[n].pa_area,
fprintf(outFile, " %"DLONG_PREFIX"d %d", reg->nreg_pa[n].pa_area,
reg->nreg_pa[n].pa_perim);
(void) putc('\n', outFile);
@ -738,6 +740,139 @@ extOutputNodes(nodeList, outFile)
}
}
/*
* ---------------------------------------------------------------------
*
* extSubsName --
*
* Return the name of the substrate node, if the node belongs to
* the substrate region and a global substrate node name has been
* specified by the tech file. If the substrate node name is a
* Tcl variable name, then perform the variable substitution.
*
* Results:
* Pointer to a character string.
*
* Side Effects:
* None.
*
* ---------------------------------------------------------------------
*/
char *
extSubsName(node)
LabRegion *node;
{
char *subsName;
/* If the techfile specifies a global name for the substrate, use */
/* that in preference to the default "p_x_y#" name. Use this name */
/* only to substitute for nodes with tiles at -(infinity). */
if (ExtCurStyle->exts_globSubstrateName != NULL)
{
if (node->lreg_ll.p_x <= (MINFINITY + 3))
{
if (ExtCurStyle->exts_globSubstrateName[0] == '$' &&
ExtCurStyle->exts_globSubstrateName[1] != '$')
{
// If subsName is a Tcl variable (begins with "$"), make the
// variable substitution, if one exists. Ignore double-$.
// If the variable is undefined in the interpreter, then
// strip the "$" from the front as this is not legal in most
// netlist formats.
char *varsub = (char *)Tcl_GetVar(magicinterp,
&ExtCurStyle->exts_globSubstrateName[1],
TCL_GLOBAL_ONLY);
return (varsub != NULL) ? varsub : ExtCurStyle->exts_globSubstrateName
+ 1;
}
else
return ExtCurStyle->exts_globSubstrateName;
}
else return NULL;
}
return NULL;
}
/*
* ----------------------------------------------------------------------------
*
* extMakeNodeNumPrint --
*
* Construct a node name from the plane number "plane" and lower left Point
* "coord", and place it in the string "buf" (which must be large enough).
*
* Results:
* None.
*
* Side Effects:
* Fills in string "buf".
*
* ----------------------------------------------------------------------------
*/
void
extMakeNodeNumPrint(buf, lreg)
char *buf;
LabRegion *lreg;
{
int plane = lreg->lreg_pnum;
Point *p = &lreg->lreg_ll;
char *subsName;
subsName = extSubsName(lreg);
if (subsName != NULL)
strcpy(buf, subsName);
else
sprintf(buf, "%s_%s%d_%s%d#",
DBPlaneShortName(plane),
(p->p_x < 0) ? "n": "", abs(p->p_x),
(p->p_y < 0) ? "n": "", abs(p->p_y));
}
/*
* ----------------------------------------------------------------------------
*
* extNodeName --
*
* Given a pointer to a LabRegion, return a pointer to a string
* that can be printed as the name of the node. If the LabRegion
* has a list of attached labels, use one of the labels; otherwise,
* use its node number.
*
* Results:
* Returns a pointer to a string. If the node had a label, this
* is a pointer to the lab_text field of the first label on the
* label list for the node; otherwise, it is a pointer to a static
* buffer into which we have printed the node number.
*
* Side effects:
* May overwrite the static buffer used to hold the printable
* version of a node number.
*
* ----------------------------------------------------------------------------
*/
char *
extNodeName(node)
LabRegion *node;
{
static char namebuf[256]; /* Big enough to hold a generated nodename */
LabelList *ll;
if (node == (LabRegion *) NULL || SigInterruptPending)
return ("(none)");
for (ll = node->lreg_labels; ll; ll = ll->ll_next)
if (extLabType(ll->ll_label->lab_text, LABTYPE_NAME))
return (ll->ll_label->lab_text);
extMakeNodeNumPrint(namebuf, node);
return (namebuf);
}
/*
* ----------------------------------------------------------------------------
*
@ -805,8 +940,7 @@ extFindDuplicateLabels(def, nreg)
{
r.r_ll = r.r_ur = ll2->ll_label->lab_rect.r_ll;
r.r_xbot--, r.r_ybot--, r.r_xtop++, r.r_ytop++;
extMakeNodeNumPrint(name,
np2->nreg_pnum, np2->nreg_ll);
extMakeNodeNumPrint(name, np2);
(void) sprintf(message, badmesg, text, name);
DBWFeedbackAdd(&r, message, def,
1, STYLE_PALEHIGHLIGHTS);
@ -825,69 +959,6 @@ extFindDuplicateLabels(def, nreg)
HashKill(&labelHash);
}
/*
* ----------------------------------------------------------------------------
*
* extNodeName --
*
* Given a pointer to a LabRegion, return a pointer to a string
* that can be printed as the name of the node. If the LabRegion
* has a list of attached labels, use one of the labels; otherwise,
* use its node number.
*
* Results:
* Returns a pointer to a string. If the node had a label, this
* is a pointer to the lab_text field of the first label on the
* label list for the node; otherwise, it is a pointer to a static
* buffer into which we have printed the node number.
*
* Side effects:
* May overwrite the static buffer used to hold the printable
* version of a node number.
*
* ----------------------------------------------------------------------------
*/
char *
extNodeName(node)
LabRegion *node;
{
static char namebuf[256]; /* Big enough to hold a generated nodename */
LabelList *ll;
if (node == (LabRegion *) NULL || SigInterruptPending)
return ("(none)");
for (ll = node->lreg_labels; ll; ll = ll->ll_next)
if (extLabType(ll->ll_label->lab_text, LABTYPE_NAME))
return (ll->ll_label->lab_text);
/* If the techfile specifies a global name for the substrate, use */
/* that in preference to the default "p_x_y#" name. */
if (((NodeRegion *)node == glob_subsnode) || ((NodeRegion *)node == temp_subsnode))
{
if (ExtCurStyle->exts_globSubstrateName != NULL)
{
if (ExtCurStyle->exts_globSubstrateName[0] == '$' &&
ExtCurStyle->exts_globSubstrateName[1] != '$')
{
// If subsName is a Tcl variable (begins with "$"), make the
// variable substitution, if one exists. Ignore double-$.
char *varsub = (char *)Tcl_GetVar(magicinterp,
&ExtCurStyle->exts_globSubstrateName[1],
TCL_GLOBAL_ONLY);
return (varsub != NULL) ? varsub : ExtCurStyle->exts_globSubstrateName;
}
else
return ExtCurStyle->exts_globSubstrateName;
}
}
extMakeNodeNumPrint(namebuf, node->lreg_pnum, node->lreg_ll);
return (namebuf);
}
/*
* ---------------------------------------------------------------------
*
@ -1730,10 +1801,6 @@ extOutputDevices(def, transList, outFile)
if (TTMaskIsZero(tmask)) {
if (termcount < nsd) {
ExtDevice *devcheck;
/* See if there is another matching device record with */
/* a different number of terminals, and try again. */
devcheck = extDevFindMatch(devptr, t);
if (devcheck != NULL) devptr = devcheck;
/* Not finding another device record just means that */
/* terminals are tied together on the same net, such as */
@ -1741,11 +1808,37 @@ extOutputDevices(def, transList, outFile)
}
break; /* End of SD terminals */
}
else if (!TTMaskIntersect(tmask, &DBPlaneTypes[reg->treg_pnum]))
else if (!TTMaskIntersect(tmask, &DBPlaneTypes[reg->treg_pnum])
|| (TTMaskHasType(tmask, TT_SPACE)))
{
node = NULL;
/* First try to find a region under the device */
extTransFindSubs(reg->treg_tile, t, tmask, def, &node, NULL);
if (node == NULL) {
if ((node == NULL) && (TTMaskHasType(tmask, TT_SPACE))) {
/* Device node is possibly the substrate. But: Note */
/* that TT_SPACE in the mask covers all planes, and it */
/* is not possible to specify TT_SPACE in a single */
/* plane. So it is necessary to check for any */
/* shielding types that block the substrate. */
if (!TTMaskIsZero(&ExtCurStyle->exts_globSubstrateShieldTypes))
{
extTransFindSubs(reg->treg_tile, t,
&ExtCurStyle->exts_globSubstrateShieldTypes,
def, &node, NULL);
}
if ((glob_subsnode == NULL) || (node != NULL)) {
/* See if there is another matching device record */
/* with a different terminal type, and try again. */
devptr = extDevFindMatch(devptr, t);
break;
}
else if ((node == NULL) && (glob_subsnode != NULL))
node = glob_subsnode;
}
else if (node == NULL) {
/* See if there is another matching device record */
/* with a different terminal type, and try again. */
devptr = extDevFindMatch(devptr, t);
@ -1754,17 +1847,6 @@ extOutputDevices(def, transList, outFile)
extTransRec.tr_devmatch |= (MATCH_TERM << termcount);
extTransRec.tr_termnode[termcount] = node;
}
else if (TTMaskHasType(tmask, TT_SPACE)) {
/* Device node is specified as being the substrate */
if (glob_subsnode == NULL) {
/* See if there is another matching device record */
/* with a different terminal type, and try again. */
devptr = extDevFindMatch(devptr, t);
break;
}
extTransRec.tr_devmatch |= (MATCH_TERM << termcount);
extTransRec.tr_termnode[termcount] = glob_subsnode;
}
else {
/* Determine if there is another matching device record */
/* that has fewer required terminals. */
@ -3093,8 +3175,9 @@ extSpecialPerimFunc(bp, sense)
break;
if (thisterm >= extTransRec.tr_nterm)
{
if (toutside == TT_SPACE)
TxError("Internal Error in Transistor Perimeter Boundary Search!\n");
/* This is not necessarily an error; e.g., happens for */
/* a device like a diode with TT_SPACE in the source/ */
/* drain list. */
return 1;
}
}
@ -3759,7 +3842,8 @@ extNodeAreaFunc(tile, arg)
Tile *tile;
FindRegion *arg;
{
int tilePlaneNum, pNum, len, area, resistClass, n, nclasses;
int tilePlaneNum, pNum, len, resistClass, n, nclasses;
dlong area;
PlaneMask pMask;
CapValue capval;
TileTypeBitMask *mask, *resMask;
@ -3855,9 +3939,9 @@ extNodeAreaFunc(tile, arg)
{
TITORECT(tile, &r);
GEOCLIP(&r, extNodeClipArea);
area = (r.r_xtop - r.r_xbot) * (r.r_ytop - r.r_ybot);
area = (dlong)(r.r_xtop - r.r_xbot) * (dlong)(r.r_ytop - r.r_ybot);
}
else area = TILEAREA(tile);
else area = (dlong)(TOP(tile) - BOTTOM(tile)) * (dlong)(RIGHT(tile) - LEFT(tile));
if (IsSplit(tile)) area /= 2; /* Split tiles are 1/2 area! */

View File

@ -406,22 +406,7 @@ extHardGenerateLabel(scx, reg, arg)
Rect r;
Point p;
// Modification 9/9/2014 by Tim:
// Convert the treg_ll value up to top-level coordinates.
// Otherwise you end up with a node that is apparently in
// "canonical coordinates", but if you try to find the
// location of the node using the name, you'll end up in
// a random place. It also allows the low-probability
// but possible conflict between this node and another with
// the same name in the parent cell.
//
// Reverted 10/30/2014: Apparently this causes worse
// problems.
//
// GeoTransPoint(&scx->scx_trans, &reg->treg_ll, &r.r_ll);
// extMakeNodeNumPrint(gen, reg->treg_pnum, r.r_ll);
extMakeNodeNumPrint(gen, reg->treg_pnum, reg->treg_ll);
extMakeNodeNumPrint(gen, (LabRegion *)reg);
prefixlen = tpath->tp_next - tpath->tp_first;
len = strlen(gen) + prefixlen;

View File

@ -51,7 +51,7 @@ extern FILE *extFileOpen();
/*
* See extract.h for the bit flags that may be set in the following.
* If any are set, the corresponding warnings get generated, leaving
* feedback messages. If this word is zero, only fatal errors are
* feedback messages. If this word is zero, only errors are
* reported.
*/
int ExtDoWarn = EXTWARN_DUP|EXTWARN_FETS;
@ -179,7 +179,11 @@ ExtAll(rootUse)
CellUse *rootUse;
{
/* Make sure the entire subtree is read in */
DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox);
if (DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox, TRUE))
{
TxError("Failure to read entire subtree of cell.\n");
return;
}
/* Fix up bounding boxes if they've changed */
DBFixMismatch();
@ -264,7 +268,11 @@ ExtUnique(rootUse, option)
int nwarn;
/* Make sure the entire subtree is read in */
DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox);
if (DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox, TRUE))
{
TxError("Failure to read entire subtree of cell.\n");
return;
}
/* Fix up bounding boxes if they've changed */
DBFixMismatch();
@ -526,7 +534,11 @@ ExtIncremental(rootUse)
CellUse *rootUse;
{
/* Make sure the entire subtree is read in */
DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox);
if (DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox, TRUE))
{
TxError("Failure to read entire subtree of cell.\n");
return;
}
/* Fix up bounding boxes if they've changed */
DBFixMismatch();
@ -663,7 +675,7 @@ extExtractStack(stack, doExtract, rootDef)
else
{
if (fatal > 0)
TxError("Total of %d fatal error%s.\n",
TxError("Total of %d error%s (check feedback entries).\n",
fatal, fatal != 1 ? "s" : "");
if (warnings > 0)
TxError("Total of %d warning%s.\n",

View File

@ -2202,10 +2202,13 @@ ExtTechLine(sectionName, argc, argv)
termtypes[1] = DBZeroTypeBits; /* Make it symmetric */
else if (!TTMaskIsZero(&termtypes[2]))
{
class = DEV_ASYMMETRIC;
TechError("Device mosfet %s has overlapping drain"
" and source types!\n", transName);
/* Should this device be disabled? */
}
else
class = DEV_ASYMMETRIC;
termtypes[2] = DBZeroTypeBits;
if (strcmp(argv[6], "None"))
DBTechNoisyNameMask(argv[6], &subsTypes); /* substrate */
@ -2213,7 +2216,6 @@ ExtTechLine(sectionName, argc, argv)
if (argc > 8) gscap = aToCap(argv[8]);
if (argc > 9) gccap = aToCap(argv[9]);
nterm = 2;
class = DEV_ASYMMETRIC;
}
else
{

View File

@ -169,7 +169,11 @@ ExtTimes(rootUse, f)
HashEntry *he;
/* Make sure this cell is read in */
DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox);
if (DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox, TRUE))
{
TxError("Failure to read entire subtree of cell.\n");
return;
}
/* Initialize cumulative statistics */
extCumInit(&cumFetsPerSecPaint);
@ -1020,7 +1024,11 @@ ExtInterCount(rootUse, halo, f)
double inter;
/* Make sure this cell is read in */
DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox);
if (DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox, TRUE))
{
TxError("Failure to read entire subtree of cell.\n");
return;
}
/* Initialize cumulative statistics */
extCumInit(&cumPercentInteraction);

View File

@ -177,6 +177,7 @@ extMakeUnique(def, ll, lreg, lregList, labelHash, option)
int nsuffix, nwarn;
Label saveLab, *lab;
Rect r;
int flags;
/*
* Make a pass through all labels for all nodes.
@ -207,7 +208,7 @@ extMakeUnique(def, ll, lreg, lregList, labelHash, option)
nwarn++;
r.r_ll = r.r_ur = ll2->ll_label->lab_rect.r_ll;
GEO_EXPAND(&r, 1, &r);
extMakeNodeNumPrint(name, lp2->lreg_pnum, lp2->lreg_ll);
extMakeNodeNumPrint(name, lp2);
(void) sprintf(message, badmesg, text, name);
DBWFeedbackAdd(&r, message, def, 1, STYLE_MEDIUMHIGHLIGHTS);
}
@ -258,13 +259,32 @@ makeUnique:
nsuffix++;
}
/* If the label is a port, then the port needs a unique ID */
/* for the unique name. */
flags = ll2->ll_label->lab_flags;
if (flags & PORT_DIR_MASK) {
int idx;
int portno = -1;
/* Find the last port index used in the cell def */
for (lab = def->cd_labels; lab != NULL; lab = lab->lab_next)
{
idx = lab->lab_flags & PORT_NUM_MASK;
if (idx > portno) portno = idx;
}
portno++;
flags &= ~PORT_NUM_MASK;
flags |= portno;
}
lab = ll2->ll_label;
saveLab = *lab;
DBRemoveLabel(def, lab);
(void) DBPutFontLabel(def, &saveLab.lab_rect,
saveLab.lab_font, saveLab.lab_size, saveLab.lab_rotate,
&saveLab.lab_offset, saveLab.lab_just, name2,
saveLab.lab_type, saveLab.lab_flags);
saveLab.lab_type, flags);
ll2->ll_label = (Label *) NULL;
}

View File

@ -182,7 +182,7 @@ typedef struct lreg
typedef struct
{
int pa_perim;
int pa_area;
dlong pa_area;
} PerimArea;
typedef struct nreg
@ -239,28 +239,6 @@ typedef struct {
CapValue subcap_adjust;
} SubCapAdjust;
/*
* The following constructs a node name from the plane number 'n'
* and lower left Point l, and places it in the string 's' (which must
* be large enough).
*/
#define extMakeNodeNumPrint(buf, plane, coord) \
(void) sprintf((buf), "%s_%s%d_%s%d#", DBPlaneShortName(plane), \
((coord).p_x < 0) ? "n": "", abs((coord).p_x), \
((coord).p_y < 0) ? "n": "", abs((coord).p_y))
/* Old way: cryptic numbers, but a bit shorter
*
* #define extMakeNodeNumPrint(s, n, l) \
* (void) sprintf((s), "%d_%d_%d#", (n), extCoord((l).p_x), extCoord((l).p_y))
*
* The following is used to map the full coordinate space into
* the positive integers, for constructing internally generated
* node names.
*
* #define extCoord(x) (((x) < 0) ? (1 - ((x) << 1)) : ((x) << 1))
*/
/*
* Argument passed to filter functions for finding regions.
*/
@ -1076,6 +1054,7 @@ extern NodeRegion *extFindNodes();
extern ExtTree *extHierNewOne();
extern int extNbrPushFunc();
extern TileType extGetDevType();
extern void extMakeNodeNumPrint();
/* --------------------- Miscellaneous globals ------------------------ */

View File

@ -164,7 +164,7 @@ GAGenChans(chanType, area, f)
Rect *area;
FILE *f;
{
extern void DBPaintPlane0(), DBPaintPlaneVert();
extern int DBPaintPlane0(), DBPaintPlaneVert();
int gaSplitFunc(), gaSplitOut();
static CellDef *genDef = (CellDef *) NULL;
static CellUse *genUse = (CellUse *) NULL;
@ -201,7 +201,7 @@ GAGenChans(chanType, area, f)
}
/* Make sure everything in 'area' is read */
(void) DBCellReadArea(EditCellUse, area);
(void) DBCellReadArea(EditCellUse, area, FALSE);
DBFixMismatch();
/* Start with a clean slate */

View File

@ -281,5 +281,8 @@ nullSetDisplay(dispType, outFileName, mouseFileName)
GrScreenRect.r_xtop = 511;
GrScreenRect.r_ytop = 483;
/* Set GrDisplayStatus to force graphics updates to be suspended */
GrDisplayStatus = DISPLAY_SUSPEND;
return TRUE;
}

View File

@ -527,6 +527,7 @@ GrTkInit(dispType)
TxPrintf("None of TrueColor 15, 16 or 24, or PseudoColor 8 found. "
"Cannot initialize DISPLAY %s\n", getenv("DISPLAY"));
XFree(grvisual_get);
GrClosePtr = NULL;
MainExit(1);
}
else

View File

@ -683,7 +683,7 @@ DefReadNets(f, rootDef, sname, oscale, special, dolabels, total)
NULL
};
defLayerMap = defMakeInverseLayerMap();
defLayerMap = defMakeInverseLayerMap(LAYER_MAP_VIAS);
while ((token = LefNextToken(f, TRUE)) != NULL)
{
@ -942,6 +942,7 @@ DefReadPins(f, rootDef, sname, oscale, total)
int keyword, subkey, values, flags;
int processed = 0;
int pinDir = PORT_CLASS_DEFAULT;
int pinUse = PORT_USE_DEFAULT;
int pinNum = 0;
TileType curlayer = -1;
Rect *currect, topRect;
@ -978,6 +979,19 @@ DefReadPins(f, rootDef, sname, oscale, total)
NULL
};
static char *pin_uses[] = {
"DEFAULT",
"SIGNAL",
"POWER",
"GROUND",
"CLOCK",
"RESET",
"ANALOG",
"SCAN",
"TIEOFF",
NULL
};
static int lef_class_to_bitmask[] = {
PORT_CLASS_DEFAULT,
PORT_CLASS_INPUT,
@ -987,6 +1001,20 @@ DefReadPins(f, rootDef, sname, oscale, total)
PORT_CLASS_FEEDTHROUGH
};
static int lef_use_to_bitmask[] = {
PORT_USE_DEFAULT,
PORT_USE_SIGNAL,
PORT_USE_POWER,
PORT_USE_GROUND,
PORT_USE_CLOCK,
PORT_USE_RESET,
PORT_USE_ANALOG,
PORT_USE_SCAN,
PORT_USE_TIEOFF
};
flags = 0;
while ((token = LefNextToken(f, TRUE)) != NULL)
{
keyword = Lookup(token, pin_keys);
@ -1058,6 +1086,13 @@ DefReadPins(f, rootDef, sname, oscale, total)
hasports = TRUE;
break;
case DEF_PINS_PROP_USE:
token = LefNextToken(f, TRUE);
subkey = Lookup(token, pin_uses);
if (subkey < 0)
LefError(DEF_ERROR, "Unknown pin use \"%s\"\n", token);
else
pinUse = lef_use_to_bitmask[subkey];
break;
case DEF_PINS_PROP_NET:
/* Get the net name, but ignore it */
token = LefNextToken(f, TRUE);
@ -1066,7 +1101,7 @@ DefReadPins(f, rootDef, sname, oscale, total)
token = LefNextToken(f, TRUE);
subkey = Lookup(token, pin_classes);
if (subkey < 0)
LefError(DEF_ERROR, "Unknown pin class\n");
LefError(DEF_ERROR, "Unknown pin class \"%s\"\n", token);
else
pinDir = lef_class_to_bitmask[subkey];
break;
@ -1086,7 +1121,7 @@ DefReadPins(f, rootDef, sname, oscale, total)
GeoTransRect(&t, currect, &topRect);
DBPaint(rootDef, &topRect, curlayer);
DBPutLabel(rootDef, &topRect, -1, pinname, curlayer,
pinNum | pinDir | flags);
pinNum | pinDir | pinUse | flags);
pending = FALSE;
pinNum++;
}
@ -1109,7 +1144,7 @@ DefReadPins(f, rootDef, sname, oscale, total)
GeoTransRect(&t, currect, &topRect);
DBPaint(rootDef, &topRect, curlayer);
DBPutLabel(rootDef, &topRect, -1, pinname, curlayer,
pinNum | pinDir | flags);
pinNum | pinDir | pinUse | flags);
pinNum++;
}
break;
@ -1666,7 +1701,7 @@ enum def_sections {DEF_VERSION = 0, DEF_NAMESCASESENSITIVE,
DEF_HISTORY, DEF_DIEAREA, DEF_COMPONENTS, DEF_VIAS,
DEF_PINS, DEF_PINPROPERTIES, DEF_SPECIALNETS,
DEF_NETS, DEF_IOTIMINGS, DEF_SCANCHAINS,
DEF_CONSTRAINTS, DEF_GROUPS, DEF_EXTENSION,
DEF_CONSTRAINTS, DEF_GROUPS, DEF_EXTENSION, DEF_BLOCKAGES,
DEF_END};
void
@ -1708,6 +1743,7 @@ DefRead(inName, dolabels)
"CONSTRAINTS",
"GROUPS",
"BEGINEXT",
"BLOCKAGES",
"END",
NULL
};
@ -1873,6 +1909,9 @@ DefRead(inName, dolabels)
case DEF_EXTENSION:
LefSkipSection(f, sections[DEF_EXTENSION]);
break;
case DEF_BLOCKAGES:
LefSkipSection(f, sections[DEF_BLOCKAGES]);
break;
case DEF_END:
if (!LefParseEndStatement(token, "DESIGN"))
{

View File

@ -1143,7 +1143,8 @@ defNetGeometryFunc(tile, plane, defdata)
/* residue of the contact as the route layer */
/* type. */
rName = defGetType((rtype == TT_SPACE) ? r2type : rtype, NULL);
rName = defGetType((rtype == TT_SPACE) ? r2type : rtype, NULL,
LAYER_MAP_VIAS);
/* The first layer in a record may not be a via name */
@ -1534,9 +1535,10 @@ defCountViaFunc(tile, cviadata)
*/
char *
defGetType(ttype, lefptr)
defGetType(ttype, lefptr, do_vias)
TileType ttype;
lefLayer **lefptr;
bool do_vias;
{
HashSearch hs;
HashEntry *he;
@ -1552,6 +1554,10 @@ defGetType(ttype, lefptr)
while (he = HashNext(&LefInfo, &hs))
{
lefl = (lefLayer *)HashGetValue(he);
if (lefl && (do_vias == FALSE) && (contact == CLASS_VIA) &&
(lefl->info.via.lr != NULL))
continue; /* Skip VIA definitions if do_vias is FALSE */
if (lefl && ((contact == lefl->lefClass) ||
((contact == CLASS_ROUTE) && (lefl->lefClass == CLASS_MASTER))))
if ((lefl->type == ttype) || (lefl->obsType == ttype))
@ -1870,7 +1876,8 @@ defComponentFunc(cellUse, defdata)
*/
LefMapping *
defMakeInverseLayerMap()
defMakeInverseLayerMap(do_vias)
bool do_vias;
{
LefMapping *lefMagicToLefLayer;
lefLayer *lefl;
@ -1882,7 +1889,7 @@ defMakeInverseLayerMap()
memset(lefMagicToLefLayer, 0, sizeof(LefMapping) * TT_TECHDEPBASE);
for (i = TT_TECHDEPBASE; i < DBNumTypes; i++)
{
lefname = defGetType(i, &lefl);
lefname = defGetType(i, &lefl, do_vias);
lefMagicToLefLayer[i].lefName = lefname;
lefMagicToLefLayer[i].lefInfo = lefl;
}
@ -1969,7 +1976,7 @@ DefWriteCell(def, outName, allSpecial, units)
defWriteHeader(def, f, scale, units);
lefMagicToLefLayer = defMakeInverseLayerMap();
lefMagicToLefLayer = defMakeInverseLayerMap(LAYER_MAP_VIAS);
/* Vias---magic contact areas are reported as vias. */
total = defCountVias(def, lefMagicToLefLayer, scale);

View File

@ -113,7 +113,7 @@ CmdLef(w, cmd)
{
"read [filename] read a LEF file filename[.lef]\n"
" read [filename] -import read a LEF file; import cells from .mag files\n"
" read [filename] -annotate read a LEF file for cell annotation only."
" read [filename] -annotate read a LEF file for cell annotation only.",
"write [filename] [-tech] write LEF for current cell\n"
" write [filename] -hide hide all details other than ports\n"
" write [filename] -hide <d> hide details in area set back distance <d>",
@ -129,7 +129,7 @@ CmdLef(w, cmd)
static char *cmdDefOption[] =
{
"read [filename] read a DEF file filename[.def]",
"write [cell] [-allspecial] write DEF for current or indicated cell\n",
"write [cell] [-allspecial] write DEF for current or indicated cell\n"
"write -labels label every net in NETS with the net name",
"writeall (use \"flatten -nosubckt\" + \"def"
" write\" instead)",

View File

@ -35,6 +35,10 @@ typedef struct
#define DO_SPECIAL 1
#define ALL_SPECIAL 2 /* treat all nets as SPECIALNETS */
/* Used with defMakeInverseLayerMap() */
#define LAYER_MAP_NO_VIAS FALSE
#define LAYER_MAP_VIAS TRUE
/* For a linked list of rectangular areas, use the LinkedRect structure */
/* defined in utils/geometry.h. */

View File

@ -1385,6 +1385,7 @@ LefReadPin(lefMacro, f, pinname, pinNum, oscale, is_imported)
int pinUse = PORT_USE_DEFAULT;
int pinShape = PORT_SHAPE_DEFAULT;
Label *firstlab;
bool firstport = TRUE;
static char *pin_keys[] = {
"DIRECTION",
@ -1636,13 +1637,14 @@ LefReadPin(lefMacro, f, pinname, pinNum, oscale, is_imported)
if (needRect)
{
if (lab == NULL)
if ((lab == NULL) && (firstport == TRUE))
DBEraseLabelsByContent(lefMacro, NULL, -1, testpin);
LefReadPort(lefMacro, f, testpin, pinNum, pinDir, pinUse,
pinShape, oscale, lab);
}
else
LefSkipSection(f, NULL);
firstport = FALSE;
}
else
LefReadPort(lefMacro, f, testpin, pinNum, pinDir, pinUse,

View File

@ -1171,7 +1171,7 @@ lefWriteMacro(def, f, scale, setback, toplayer, domaster)
lc.file = f;
lc.oscale = scale;
lc.lefMagicMap = defMakeInverseLayerMap();
lc.lefMagicMap = defMakeInverseLayerMap(LAYER_MAP_NO_VIAS);
lc.lastType = TT_SPACE;
lc.lefFlat = lefFlatDef;
@ -1674,7 +1674,7 @@ lefWriteMacro(def, f, scale, setback, toplayer, domaster)
freeMagic(thislll);
}
if (setback > 0)
if (setback >= 0)
{
/* For -hide with setback, yank everything in the area outside */
/* the setback. */
@ -1982,7 +1982,11 @@ LefWriteAll(rootUse, writeTopCell, lefTech, lefHide, lefTopLayer, lefDoMaster, r
rootdef = rootUse->cu_def;
/* Make sure the entire subtree is read in */
DBCellReadArea(rootUse, &rootdef->cd_bbox);
if (DBCellReadArea(rootUse, &rootdef->cd_bbox, TRUE))
{
TxError("Could not read entire subtree of the cell.\n");
return;
}
/* Fix up bounding boxes if they've changed */
DBFixMismatch();

View File

@ -167,6 +167,8 @@ macro XK_KP_Prior "move ne 1"
# Scroll wheel bindings
macro XK_Pointer_Button4 "scroll u .05 w"
macro XK_Pointer_Button5 "scroll d .05 w"
macro Shift_XK_Pointer_Button4 "scroll l .05 w"
macro Shift_XK_Pointer_Button5 "scroll r .05 w"
# Quick macro function keys for scmos tech (X11 versions only)
macro XK_F1 "paint ndiff"
macro XK_F2 "paint pdiff"

View File

@ -26,6 +26,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>

View File

@ -24,7 +24,7 @@ FILES = mos.7bit.dstyle mos.7bit.std.cmap \
mos.7bit.mraster_dstyle mos.7bit.mraster.cmap \
mos.OpenGL.dstyle mos.OpenGL.std.cmap
TECHFILES = minimum.tech gdsquery.tech scmos.tech scmos-tm.tech \
scmos-sub.tech scmosWR.tech
scmos-sub.tech scmosWR.tech nmos.tech
CIFin = cif_template/objs/CIFin
CIFout = cif_template/objs/CIFout
@ -87,6 +87,9 @@ minimum.tech: minimum.tech.in
gdsquery.tech: gdsquery.tech.in
$(SC_PP) gdsquery.tech.in > gdsquery.tech
nmos.tech: nmos.tech.in
$(CP) nmos.tech.in nmos.tech
$(CIFin):
$(CIFout):
$(ICIFin):

473
scmos/nmos.tech.in Normal file
View File

@ -0,0 +1,473 @@
#
# nmos.tech --
#
# Defines the MOSIS 4.0 micron NMOS technology for Magic. Some
# of the characteristics of this technology are:
#
# 1. 1 level of metal.
# 2. Buried contacts.
# 3. No butting contacts.
#
# Copyright (C) 1985 Regents of the University of California
# All rights reserved.
#
# sccsid @(#)nmos.tech 3.73 MAGIC (Berkeley) 11/22/85
#
tech
format 35
nmos
end
version
version 0
description "MOSIS 4.0 micron NMOS"
requires magic-8.3.0
end
planes
active,diff,poly_diff
metal
end
types
active polysilicon,poly,red
active diffusion,diff,green
metal metal,blue
active poly_metal_contact,pmc
active diff_metal_contact,dmc
active enhancement_fet,efet
active depletion_fet,dfet
active depletion_capacitor,dcap
active buried_contact,bc
metal glass_contact,glass
end
styles
styletype mos
polysilicon 1
diffusion 2
metal 20
enhancement_fet 6
enhancement_fet 7
depletion_fet 6
depletion_fet 10
depletion_capacitor 6
depletion_capacitor 11
buried_contact 6
buried_contact 33
poly_metal_contact 1
poly_metal_contact 20
poly_metal_contact 32
diff_metal_contact 2
diff_metal_contact 20
diff_metal_contact 32
glass_contact 20
glass_contact 34
error_s 42
error_p 42
error_ps 42
# Hint layers
magnet 39
fence 38
rotate 37
end
contact
pmc poly metal
dmc diff metal
end
aliases
allDiff diff,dmc,bc,efet,dfet,dcap
allPoly poly,pmc,bc,efet,dfet,dcap
tran efet,dfet
allMetal metal,pmc,dmc,glass
spP (space,poly,pmc)/a
sdD (space,diff,dmc)/a
notDmc space,metal,pmc,glass
notPmc space,metal,dmc,glass
allButFet (space,diff,poly,dmc,pmc,bc)/a
allpdTypes (space,diff,poly,dmc,pmc,bc,dfet,dcap,efet)/a
end
compose
# The following rule allows transistors to be built up of poly and diff */
compose efet poly diff
# The following rules allow poly or diff to be erased from fets or bcs */
decompose dfet poly diff
decompose dcap poly diff
decompose bc poly diff
# The following lets us erase metal from a glass_contact to get space */
erase glass metal space
end
#
# Electrical connectivity. Each tile in the group on the left
# is considered to be connected to each tile in the group on
# the right. Tiles within the groups are not necessarily
# connected to each other.
#
connect
poly pmc,efet,dfet,dcap,bc
diff bc,dmc
efet pmc,dmc,bc,dfet,dcap
dfet pmc,dmc,bc,dcap
dcap pmc,dmc,bc
pmc dmc,bc
dmc bc
metal glass,pmc,dmc
glass pmc,dmc
end
# Information used to generate CIF files. The only tricky business
# is to merge necks between adjacent implants or buried windows.
# The grow-shrink does this. Also, note that labels on Magic layers
# get attached to the first CIF layer containing that Magic layer
# in an "or" or "bloat-or" statement. This makes order important
# (for example, we want transistor labels to attach to the poly gate).
#
cifoutput
style lambda=2
scalefactor 200 100
layer NP poly,pmc,efet,dfet,dcap,bc
labels poly,efet,dfet,dcap,bc
calma 1 1
layer ND diff,dmc,efet,dfet,dcap,bc
labels diff
calma 2 1
layer NM metal,pmc,dmc,glass
labels metal,pmc,dmc,glass
calma 3 1
layer NI
bloat-or dfet,dcap * 200 diff,bc 400
grow 100
shrink 100
calma 4 1
layer NC dmc
squares 400
calma 5 1
layer NC pmc
squares 400
calma 6 1
layer NG glass
calma 7 1
layer NB
bloat-or bc * 200 diff,dmc 400 dfet 0
grow 100
shrink 100
calma 8 1
end
# Information on how to read CIF files. Read in all the CIF layers,
# then perform geometric operations to get the Magic layers. The
# order in which the Magic layers are generated is important!
#
cifinput
style lambda=2
scalefactor 200
layer poly NP
labels NP
layer diff ND
labels ND
layer metal NM
labels NM
layer efet NP
and ND
layer dfet NI
and NP
and ND
layer pmc NC
grow 200
and NM
and NP
layer dmc NC
grow 200
and NM
and ND
# Buried contacts must be generated after transistors, since they
# override transistors.
#
layer bc NB
and NP
and ND
layer glass NG
end
mzrouter
style irouter
layer metal 32 32 256 1
layer poly 64 64 256 1
contact pmc metal poly 1024
end
#
# DRC information
# Width, spacing and edge rules are "compiled" into rules table entries.
#
# width: types in the mask, taken collectively, must have the given width
#
# spacing: types in mask1 must be separated by distance from types in mask2
#
# edge: explict entries for the rules table --
# LHS RHS distance types allowed on RHS corner mask reason
#
# All combinations of single elements of the LHS and RHS masks
# are used to form a rule.
#
drc
width allDiff 2 "Diffusion width must be at least 2"
width dmc 4 "Metal_diff contact width must be at least 4"
width allPoly 2 "Polysilicon width must be at least 2"
width pmc 4 "Metal_poly contact width must be at least 4"
width bc 2 "Buried contact width must be at least 2"
width efet 2 "Enhancement FET width must be at least 2"
width dfet 2 "Depletion FET width must be at least 2"
width dcap 2 "Depletion capacitor width must be at least 2"
width allMetal 3 "Metal width must be at least 3"
spacing allDiff allDiff 3 touching_ok \
"Diff-diff separation must be at least 3"
spacing allPoly allPoly 2 touching_ok \
"Poly-poly separation must be at least 2"
spacing tran pmc,dmc 1 touching_illegal \
"Transistor-contact separation must be at least 1"
spacing efet dfet,dcap 3 touching_illegal \
"Enhancement-depletion transistor separation must be at least 3"
spacing allMetal allMetal 3 touching_ok \
"Metal-metal separation must be at least 3"
#
# Diff and poly cannot be adjacent, except at corners where
# the intermediate material is "bc", "efet", "dfet", or "dcap".
# Thus, there is no need for rules with RHS equal to "Bef".
# But corner extension applies if the intermediate material is "s".
# For this reason, the first edge rule CANNOT be rewritten as
# "edge diff pP 1 0 pP 1".
#
edge diff spP 1 (space)/a spP 1 \
"Diff-poly separation must be at least 1"
edge poly sdD 1 (space)/a sdD 1 \
"Diff-poly separation must be at least 1"
#
# Allow dmc and pmc to be adjacent since they are electrically shorted.
#
edge dmc (space,poly)/a 1 (space)/a (space,poly)/a 1 \
"Diff-poly separation must be at least 1"
edge pmc (space,diff)/a 1 (space)/a (space,diff)/a 1 \
"Diff-poly separation must be at least 1"
#
# Don't let pmc and dmc have convex shapes, since this may interfere
# with the via-generation process. The corner check in the rules
# below does this. Also don't let contacts overlap between cells
# unless they do so exactly.
#
edge4way dmc notDmc 1 notDmc notDmc,dmc 1 \
"Diffusion-metal contacts must be rectangular"
edge4way pmc notPmc 1 notPmc notPmc,pmc 1 \
"Poly-metal contacts must be rectangular"
exact_overlap pmc,dmc
#
# Transistors cannot touch space, except in corners.
# The corner mask is set to 0 to prevent checking there.
#
edge tran (space)/a 1 0 0 0 \
"Transistor overhang is missing"
edge (space)/a tran 1 0 0 0 \
"Transistor overhang is missing"
#
# Buried contacts must be 3 lambda from efets in all cases,
# and 4 lambda in some. Depends on the orientation of the
# buried contact implant. The 4x3 corner checks ON BOTH
# SIDES solve the problem. Buried contacts may abut
# depletion transistors, but only if the transistors are
# fairly long (otherwise, a misalignment in the buried
# window mask may make a huge difference in the transistor's
# effective length).
#
spacing bc efet 3 touching_illegal \
"Buried contact-transistor separation must be at least 3"
spacing bc dfet 3 touching_ok \
"Buried contact-transistor separation must be at least 3"
edge4way bc diff,dmc 4 allButFet allpdTypes 3 \
"Buried contact-transistor separation must be at least 4 on diff side"
edge4way bc dfet 4 dfet 0 0 \
"Transistors next to buried contacts must be at least 4 long"
#
# WARNING: The above rules don't take care of poly approaching
# the buried contact on the diffusion side. Unfortunately, the
# only fix is a rule that is ridiculously conservative. So
# for now, buyer beware!
#
#
# 3 by 2 shape of buried contact next to dfet.
# No corner check.
#
edge4way dfet bc 3 bc 0 0 \
"Buried contact next to depletion transistor must be at least 3x2"
#
# Poly and diffusion must overhang transistors by 2.
#
# Corner checks are necessary for L or S shaped transistors.
#
# Don't worry about dfet -- buried_contact boundaries here.
#
edge4way tran poly 2 poly,pmc poly 2 \
"Polysilicon must overhang transistor by at least 2"
edge4way tran diff 2 diff,dmc diff 2 \
"Diffusion must overhang transistor by at least 2"
# Cannot change transistors as a result of cell overlaps */
no_overlap efet,dfet efet,dfet
end
#
# Parameters for circuit extraction.
# A type may appear both as a node and as a transistor. When it
# appears as a node, we are describing the gate, and when it appears
# as a transistor, we are describing the channel.
#
extract
style default
# scale factor: output units (centimicrons) per lambda */
lambda 200
# chunk size for hierarchical extraction, in lambda */
step 100
planeorder active 0
planeorder metal 1
# sheet resistivity milli-ohms per square */
resist diff,dmc/poly 10000
resist poly,pmc/poly,efet,dfet,bc 30000
resist metal,glass 30
# area capacitance atto-farads/lambda**2 */
areacap poly,efet,dfet 200
areacap metal,glass 120
areacap diff 400
areacap bc 600
areacap dmc/poly 520
areacap pmc/poly 320
# sidewall capacitance atto-farads/lambda */
perimc diff,dmc/poly,bc space,dfet,efet 200
# transistors terms #terms name substr gs-cap gc-cap */
fet efet diff 2 efet GND! 0 0
fet dfet diff,bc 2 dfet GND! 0 0
fet dcap diff,bc 1 dcap GND! 0 0
# End of style "default" */
end
# Information for the wiring interface */
wiring
contact pmc 4 metal 0 poly 0
contact dmc 4 metal 0 diff 0
contact bc 2 poly 0 diff 0
end
# Information to control the router */
router
layer1 metal 3 metal,pmc/metal,dmc/metal,glass 3
layer2 poly 2 poly,efet,dfet,dcap,pmc,bc 2 diff,dmc 1
contacts pmc 4
gridspacing 7
end
# Information for plowing */
plowing
fixed efet,dfet,dcap,bc,glass
covered efet,dfet,dcap,bc
drag efet,dfet,dcap,bc
end
plot
style versatec
# Same as Gremlin stipple 9: */
dfet,dcap \
07c0 0f80 1f00 3e00 \
7c00 f800 f001 e003 \
c007 800f 001f 003e \
00c7 00f8 01f0 03e0
# Same as Gremlin stipple 10: */
efet,dcap \
1f00 0f80 07c0 03e0 \
01f0 00f8 007c 003e \
001f 800f c007 e003 \
f001 f800 7c00 3e00
# Same as Gremlin stipple 11: */
bc \
c3c3 c3c3 0000 0000 \
0000 0000 c3c3 c3c3 \
c3c3 c3c3 0000 0000 \
0000 0000 c3c3 c3c3
# Same as Gremlin stipple 12: */
glass \
0040 0080 0100 0200 \
0400 0800 1000 2000 \
4000 8000 0001 0002 \
0004 0008 0010 0020
# Same as Gremlin stipple 17: */
diff,dmc/active,efet,dfet,dcap,bc \
0000 4242 6666 0000 \
0000 2424 6666 0000 \
0000 4242 6666 0000 \
0000 2424 6666 0000
# Same as Gremlin stipple 19: */
poly,pmc/active,efet,dfet,dcap,bc \
0808 0400 0202 0101 \
8080 4000 2020 1010 \
0808 0004 0202 0101 \
8080 0040 2020 1010
# Same as Gremlin stipple 22: */
metal,dmc/metal,pmc/metal,glass \
8080 0000 0000 0000 \
0808 0000 0000 0000 \
8080 0000 0000 0000 \
0808 0000 0000 0000
# Same as Gremlin stipple 23: */
glass \
0000 0000 1c1c 3e3e \
3636 3e3e 1c1c 0000 \
0000 0000 1c1c 3e3e \
3636 3e3e 1c1c 0000
pmc,dmc X
bc B
style gremlin
dfet,dcap 9
efet,dcap 10
bc 11
glass 12
diff,dmc/active,efet,dfet,dcap,bc 17
poly,pmc/active,efet,dfet,dcap,bc 19
metal,dmc,pmc,glass 22
pmc,dmc X
bc B
end

1294
scripts/config.guess vendored Executable file → Normal file

File diff suppressed because it is too large Load Diff

2649
scripts/config.sub vendored Executable file → Normal file

File diff suppressed because it is too large Load Diff

16
scripts/configure vendored
View File

@ -626,8 +626,6 @@ INSTALL_TARGET
ALL_TARGET
OA_LIBS
OA
MAGIC_REVISION
MAGIC_VERSION
MSED
MCPP
LD_RUN_PATH
@ -2597,17 +2595,6 @@ test -n "$target_alias" &&
PACKAGE=magic
MAGIC_VERSION=`cat ../VERSION | cut -d. -f1-2`
MAGIC_REVISION=`cat ../VERSION | cut -d. -f3`
cat >>confdefs.h <<_ACEOF
#define MAGIC_VERSION "${MAGIC_VERSION}"
_ACEOF
cat >>confdefs.h <<_ACEOF
#define MAGIC_REVISION "${MAGIC_REVISION}"
_ACEOF
ALL_TARGET="standard"
INSTALL_TARGET="install-magic"
@ -8227,9 +8214,6 @@ fi

View File

@ -11,11 +11,6 @@ AC_CANONICAL_SYSTEM
dnl pass the version string on the the makefiles
PACKAGE=magic
MAGIC_VERSION=`cat ../VERSION | cut -d. -f1-2`
MAGIC_REVISION=`cat ../VERSION | cut -d. -f3`
AC_DEFINE_UNQUOTED(MAGIC_VERSION, "${MAGIC_VERSION}")
AC_DEFINE_UNQUOTED(MAGIC_REVISION, "${MAGIC_REVISION}")
dnl Override default target when compiling under TCL
ALL_TARGET="standard"
INSTALL_TARGET="install-magic"
@ -407,6 +402,8 @@ AC_ARG_WITH(tcllibs, [ --with-tcllibs=DIR Find Tcl library in DIR],
magic_with_tcl_libraries=$withval)
AC_ARG_WITH(tklibs, [ --with-tklibs=DIR Find Tk library in DIR],
magic_with_tk_libraries=$withval)
AC_ARG_WITH(wish, [ --with-wish=EXE Use wish binary at EXE],
magic_with_wish_binary=$withval)
# -----------------------------------------------------------------------
# Find the Tcl build configuration file "tclConfig.sh"
@ -709,33 +706,37 @@ if test $usingTcl ; then
# Find the version of "wish" that corresponds to TCL_EXEC_PREFIX
# We really ought to run "ldd" to confirm that the linked libraries match.
AC_MSG_CHECKING([for wish executable])
for dir in \
${TK_EXEC_PREFIX}/bin \
${TK_EXEC_PREFIX}
do
for wishexe in \
wish-X11 \
wish \
wish${TK_VERSION} \
wish.exe \
wish${TK_VERSION}.exe
if text "x${magic_with_wish_binary}" = "x" ; then
AC_MSG_CHECKING([for wish executable])
for dir in \
${TK_EXEC_PREFIX}/bin \
${TK_EXEC_PREFIX}
do
if test -r "$dir/$wishexe" ; then
WISH_EXE=$dir/$wishexe
for wishexe in \
wish-X11 \
wish \
wish${TK_VERSION} \
wish.exe \
wish${TK_VERSION}.exe
do
if test -r "$dir/$wishexe" ; then
WISH_EXE=$dir/$wishexe
break
fi
done
if test "x${WISH_EXE}" != "x" ; then
break
fi
done
if test "x${WISH_EXE}" != "x" ; then
break
if test "x${WISH_EXE}" = "x" ; then
echo "Warning: Can't find executable for \"wish\". You may have to"
echo "manually set the value for WISH_EXE in the magic startup script."
AC_MSG_RESULT(no)
else
AC_MSG_RESULT([${WISH_EXE}])
fi
done
if test "x${WISH_EXE}" = "x" ; then
echo "Warning: Can't find executable for \"wish\". You may have to"
echo "manually set the value for WISH_EXE in the magic startup script."
AC_MSG_RESULT(no)
else
AC_MSG_RESULT([${WISH_EXE}])
WISH_EXE=${magic_with_wish_binary}
fi
# Find the version of "tclsh" that corresponds to TCL_EXEC_PREFIX
@ -1800,9 +1801,6 @@ AC_SUBST(LD_RUN_PATH)
AC_SUBST(MCPP)
AC_SUBST(MSED)
AC_SUBST(MAGIC_VERSION)
AC_SUBST(MAGIC_REVISION)
AC_SUBST(OA)
AC_SUBST(OA_LIBS)

View File

@ -68,15 +68,15 @@ LIB_SPECS = @LIB_SPECS@
LIB_SPECS_NOSTUB = @LIB_SPECS_NOSTUB@
WISH_EXE = @WISH_EXE@
TCL_LIB_DIR = @TCL_LIB_DIR@
MAGIC_VERSION = @MAGIC_VERSION@
MAGIC_REVISION = @MAGIC_REVISION@
MAGIC_VERSION = `cat ../VERSION | cut -d. -f1-2`
MAGIC_REVISION = `cat ../VERSION | cut -d. -f3`
CC = @CC@
CPP = @CPP@
CXX = @CXX@
CPPFLAGS = -I. -I${MAGICDIR} @CPPFLAGS@
DFLAGS = @extra_defs@ @stub_defs@ @DEFS@ -DGCORE=\"@GCORE@\"
DFLAGS = @extra_defs@ @stub_defs@ @DEFS@ -DMAGIC_VERSION=\"${MAGIC_VERSION}\" -DMAGIC_REVISION=\"${MAGIC_REVISION}\" -DGCORE=\"@GCORE@\"
DFLAGS += -DSHDLIB_EXT=\"@SHDLIB_EXT@\" -DNDEBUG
DFLAGS_NOSTUB = @extra_defs@ @DEFS@ -DGCORE=\"@GCORE@\"
DFLAGS_NOSTUB += -DSHDLIB_EXT=\"@SHDLIB_EXT@\" -DNDEBUG

View File

@ -5,6 +5,7 @@
MODULE = tcltk
MAGICDIR = ..
SRCS = tclmagic.c
OBJS = $(subst .c,.o,${SRCS})
include ${MAGICDIR}/defs.mak
@ -58,11 +59,10 @@ magicdnull: magicdnull.c ${MAGICDIR}/defs.mak
-o magicdnull ${LD_RUN_PATH} ${LIB_SPECS_NOSTUB} ${LIBS} \
${GR_LIBS}
magic.tcl: magic.tcl.in ${MAGICDIR}/defs.mak
sed -e /TCL_DIR/s%TCL_DIR%${TCLDIR}%g \
-e /MAGIC_VERSION/s%MAGIC_VERSION%${MAGIC_VERSION}%g \
magic.tcl: magic.tcl.in ${MAGICDIR}/defs.mak ${MAGICDIR}/VERSION
sed -e /MAGIC_VERSION/s%MAGIC_VERSION%${MAGIC_VERSION}%g \
-e /MAGIC_REVISION/s%MAGIC_REVISION%${MAGIC_REVISION}%g \
-e /SHDLIB_EXT/s%SHDLIB_EXT%${SHDLIB_EXT}%g magic.tcl.in > magic.tcl
magic.tcl.in > magic.tcl
magic.sh: magic.sh.in ${MAGICDIR}/defs.mak
sed -e /TCL_DIR/s%TCL_DIR%${TCLDIR}%g \
@ -70,10 +70,12 @@ magic.sh: magic.sh.in ${MAGICDIR}/defs.mak
-e /WISH_EXE/s%WISH_EXE%${WISH_EXE}%g magic.sh.in > magic.sh
ext2spice.sh: ext2spice.sh.in ${MAGICDIR}/defs.mak
sed -e /TCL_DIR/s%TCL_DIR%${TCLDIR}%g ext2spice.sh.in > ext2spice.sh
sed -e /TCL_DIR/s%TCL_DIR%${TCLDIR}%g \
ext2spice.sh.in > ext2spice.sh
ext2sim.sh: ext2sim.sh.in ${MAGICDIR}/defs.mak
sed -e /TCL_DIR/s%TCL_DIR%${TCLDIR}%g ext2sim.sh.in > ext2sim.sh
sed -e /TCL_DIR/s%TCL_DIR%${TCLDIR}%g \
ext2sim.sh.in > ext2sim.sh
$(DESTDIR)${INSTALL_TCLDIR}/%: %
${RM} $(DESTDIR)${INSTALL_TCLDIR}/$*
@ -94,4 +96,7 @@ $(DESTDIR)${INSTALL_BINDIR}/ext2sim.sh: ext2sim.sh
${CP} ext2sim.sh $(DESTDIR)${INSTALL_BINDIR}/ext2sim
(cd $(DESTDIR)${INSTALL_BINDIR}; chmod 0755 ext2sim)
# An additional dependency on the VERSION file
${OBJS}: ${MAGICDIR}/VERSION
include ${MAGICDIR}/rules.mak

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
#
# Standalone script for ext2sim, for Tcl-based magic 8.0
#
@ -14,8 +14,12 @@ for i in $@; do
*) esargs="$esargs $i" ;;
esac
done
TCL_MAG_DIR=${CAD_ROOT}/magic/tcl
if [ "${TCL_MAG_DIR}" = "/magic/tcl" ]; then
TCL_MAG_DIR=TCL_DIR
fi
#
eval TCL_DIR/magicdnull -dnull -noconsole -nowrapper $mgargs <<EOF
eval ${TCL_MAG_DIR}/magicdnull -dnull -noconsole -nowrapper $mgargs <<EOF
drc off
box 0 0 0 0
ext2sim $esargs

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
#
# Standalone script for ext2spice, for Tcl-based magic 8.0
#
@ -14,8 +14,12 @@ for i in $@; do
*) esargs="$esargs $i" ;;
esac
done
TCL_MAG_DIR=${CAD_ROOT}/magic/tcl
if [ "${TCL_MAG_DIR}" = "/magic/tcl" ]; then
TCL_MAG_DIR=TCL_DIR
fi
#
eval TCL_DIR/magicdnull -dnull -noconsole -nowrapper $mgargs <<EOF
eval ${TCL_MAG_DIR}/magicdnull -dnull -noconsole -nowrapper $mgargs <<EOF
drc off
box 0 0 0 0
ext2spice $esargs

View File

@ -11,6 +11,10 @@
# Parse for the argument "-c[onsole]". If it exists, run magic
# with the TkCon console. Strip this argument from the argument list.
TCL_MAG_DIR=${CAD_ROOT}/magic/tcl
if [ "${TCL_MAG_DIR}" = "/magic/tcl" ]; then
TCL_MAG_DIR=TCL_DIR
fi
TKCON=true
DNULL=
MAGIC_WISH=WISH_EXE
@ -37,12 +41,12 @@ done
if [ $TKCON ]; then
if [ $DNULL ]; then
exec TCL_DIR/tkcon.tcl -eval "source TCL_DIR/console.tcl" \
-slave "set argc $#; set argv [list $*]; source TCL_DIR/magic.tcl"
exec $TCL_MAG_DIR/tkcon.tcl -eval "source $TCL_MAG_DIR/console.tcl" \
-slave "set argc $#; set argv [list $*]; source $TCL_MAG_DIR/magic.tcl"
else
exec TCL_DIR/tkcon.tcl -eval "source TCL_DIR/console.tcl" \
exec $TCL_MAG_DIR/tkcon.tcl -eval "source $TCL_MAG_DIR/console.tcl" \
-slave "package require Tk; set argc $#; set argv [list $arglist]; \
source TCL_DIR/magic.tcl"
source $TCL_MAG_DIR/magic.tcl"
fi
else
@ -57,8 +61,8 @@ else
# only, efficient for running in batch mode).
#
if [ $DNULL ]; then
exec TCL_DIR/magicdnull -nowrapper "$@"
exec $TCL_MAG_DIR/magicdnull -nowrapper "$@"
else
exec TCL_DIR/magicexec -- "$@"
exec $TCL_MAG_DIR/magicexec -- "$@"
fi
fi

View File

@ -1,19 +1,20 @@
# Wishrc startup for ToolScript (magic)
#
# For installation: Put this file and also magicwrap.so into
# directory TCL_DIR, and set the "load" line below
# to point to the location of magicwrap.so. Also see comments
# in shell script "magic.sh".
# the same directory. Also see comments in shell script "magic.sh".
global Opts
# If we called magic via the non-console script, then we want to reset
# the environment variable HOME to its original value.
variable MAGIC_TCL_DIR [file dirname [file normalize [info script]]]
variable CAD_ROOT_DEFAULT [file normalize [file join $MAGIC_TCL_DIR ../..]]
if {${tcl_version} >= 8.6} {
load -lazy TCL_DIR/tclmagicSHDLIB_EXT
load -lazy [file join $MAGIC_TCL_DIR tclmagic[info sharedlibextension]]
} else {
load TCL_DIR/tclmagicSHDLIB_EXT
load [file join $MAGIC_TCL_DIR tclmagic[info sharedlibextension]]
}
# It is important to make sure no magic commands overlap with Tcl built-in
@ -30,8 +31,8 @@ proc pushnamespace { name } {
foreach v $y {
regsub -all {\*} $v {\\*} i
set x [namespace tail $i]
if {[lsearch $z $x] < 0} {
namespace import $i
if {[lsearch $z $x] < 0} {
namespace import $i
}
}
}
@ -124,7 +125,7 @@ proc xcircuit { args } {
# execute script in the scope of magic, because its variable space is
# not modularized.
set argv $args
set argc [llength $args]
set argc [llength $args]
uplevel #0 source $xcircscript
}
}
@ -143,7 +144,7 @@ proc netgen { args } {
puts stderr "\"source <path>/netgen.tcl\"."
} else {
set argv $args
set argc [llength $args]
set argc [llength $args]
uplevel #0 source $netgenscript
}
}
@ -151,7 +152,7 @@ proc netgen { args } {
# Add the "echo" command
proc echo {args} {
puts stdout $args
puts stdout $args
}
# Parse argument list for "-c[onsole]" and "-now[rapper]".

View File

@ -1191,7 +1191,7 @@ int
Tclmagic_Init(interp)
Tcl_Interp *interp;
{
char *cadroot;
const char *cadroot;
/* Sanity check! */
if (interp == NULL) return TCL_ERROR;
@ -1221,12 +1221,18 @@ Tclmagic_Init(interp)
Tcl_Eval(interp, "lappend auto_path " TCL_DIR );
/* Set $CAD_ROOT as a Tcl variable */
/* Get $CAD_ROOT from a Tcl variable, if it exists, and if not, then */
/* set CAD_ROOT from the environment variable of the same name, if */
/* it exists, and finally fall back on the CAD_DIR set at compile */
/* time. */
cadroot = getenv("CAD_ROOT");
if (cadroot == NULL) cadroot = CAD_DIR;
Tcl_SetVar(interp, "CAD_ROOT", cadroot, TCL_GLOBAL_ONLY);
cadroot = Tcl_GetVar(interp, "CAD_ROOT", TCL_GLOBAL_ONLY);
if (cadroot == NULL)
{
cadroot = (const char *)getenv("CAD_ROOT");
if (cadroot == NULL) cadroot = CAD_DIR;
Tcl_SetVar(interp, "CAD_ROOT", cadroot, TCL_GLOBAL_ONLY);
}
Tcl_PkgProvide(interp, "Tclmagic", MAGIC_VERSION);
return TCL_OK;

View File

@ -119,7 +119,7 @@ PaExpand(psource, pdest, size)
{
char *ps, *pd;
struct passwd *passwd, *getpwnam();
char expandName[100], *string, *newEntry;
char expandName[512], *string, *newEntry;
HashEntry *h;
int i, length;
@ -135,7 +135,7 @@ PaExpand(psource, pdest, size)
*pd = *++ps;
if (isspace(*pd) || (*pd=='\0') || (*pd=='/') || (*pd==':'))
break;
if (i < 99) pd++;
if (i < 511) pd++;
}
*pd = '\0';
@ -196,7 +196,7 @@ PaExpand(psource, pdest, size)
*pd = *++ps;
if (isspace(*pd) || (*pd=='\0') || (*pd=='/') || (*pd==':'))
break;
if (i < 99) pd++;
if ((i < 511) && (*pd != '{') && (*pd != '}')) pd++;
}
saveChar = *pd;
*pd = '\0';
@ -226,7 +226,11 @@ PaExpand(psource, pdest, size)
if (string == NULL)
{
/* Check for CAD_ROOT = CAD_DIR, the only internal variable */
/* recognized (this is passed down from the Makefile) */
/* recognized (this is passed down from the Makefile). */
/* Note that in the MAGIC_WRAPPER version, CAD_ROOT was set */
/* as a Tcl variable in tcltk/tclmagic.c, such that if */
/* expandName == "CAD_ROOT", then string should not be NULL */
/* here. */
if (!strcmp(expandName, "CAD_ROOT"))
string = CAD_DIR;

View File

@ -272,9 +272,12 @@ changePlanesFunc(cellDef, arg)
/* Old planes to be subtracted */
for (pNum = DBNumPlanes; pNum < oldnumplanes; pNum++)
{
DBFreePaintPlane(cellDef->cd_planes[pNum]);
TiFreePlane(cellDef->cd_planes[pNum]);
cellDef->cd_planes[pNum] = (Plane *) NULL;
if (cellDef->cd_planes[pNum] != NULL)
{
DBFreePaintPlane(cellDef->cd_planes[pNum]);
TiFreePlane(cellDef->cd_planes[pNum]);
cellDef->cd_planes[pNum] = (Plane *) NULL;
}
}
}
return 0;