Merge branch 'master' into bplane

Conflicts:
	VERSION

Merged recent changes from master back into bplane, as the efficiency of
bplane for doing extraction on large layouts is unquestionably better.
Fixed the implementation of DBMoveCell() for bplane.  Corrected an error
in the bplane version of dbScaleCell() that enumerates cell uses but
does not free the list.
This commit is contained in:
Tim Edwards 2020-03-22 14:07:25 -04:00
commit ff0ba7f89d
31 changed files with 527 additions and 169 deletions

View File

@ -1048,7 +1048,7 @@ calmaFindCell(name, was_called)
def = DBCellLookDef(name);
if (def == NULL)
{
def = DBCellNewDef(name, (char *) NULL);
def = DBCellNewDef(name);
/*
* Tricky point: call DBReComputeBbox here to make SURE

View File

@ -1416,7 +1416,7 @@ calmaGetContactCell(type, lookOnly)
def = DBCellLookDef(contactCellName);
if ((def == (CellDef *) NULL) && (lookOnly == FALSE))
{
def = DBCellNewDef(contactCellName, (char *) NULL);
def = DBCellNewDef(contactCellName);
def->cd_flags &= ~(CDMODIFIED|CDGETNEWSTAMP);
def->cd_flags |= CDAVAILABLE;
}

View File

@ -112,7 +112,7 @@ CIFInitCells()
CIFTotalDef = DBCellLookDef("__CIF__");
if (CIFTotalDef == (CellDef *) NULL)
{
CIFTotalDef = DBCellNewDef ("__CIF__",(char *) NULL);
CIFTotalDef = DBCellNewDef("__CIF__");
ASSERT(CIFTotalDef != (CellDef *) NULL, "cifMakeCell");
DBCellSetAvail(CIFTotalDef);
CIFTotalDef->cd_flags |= CDINTERNAL;
@ -124,7 +124,7 @@ CIFInitCells()
CIFComponentDef = DBCellLookDef("__CIF2__");
if (CIFComponentDef == (CellDef *) NULL)
{
CIFComponentDef = DBCellNewDef ("__CIF2__",(char *) NULL);
CIFComponentDef = DBCellNewDef("__CIF2__");
ASSERT(CIFComponentDef != (CellDef *) NULL, "cifMakeCell");
DBCellSetAvail(CIFComponentDef);
CIFComponentDef->cd_flags |= CDINTERNAL;

View File

@ -273,7 +273,7 @@ cifFindCell(cifNum)
def = DBCellLookDef(name);
if (def == NULL)
{
def = DBCellNewDef(name, (char *) NULL);
def = DBCellNewDef(name);
/* Tricky point: call DBReComputeBbox here to make SURE
* that the cell has a valid bounding box. Otherwise,

View File

@ -896,14 +896,12 @@ CmdCellname(w, cmd)
{
char *fullpath;
fullpath = (char *)mallocMagic(strlen(filepath) +
strlen(cellDef->cd_name) + 6);
sprintf(fullpath, "%s/%s.mag", filepath, cellDef->cd_name);
strlen(cellDef->cd_name) + 2);
sprintf(fullpath, "%s/%s", filepath, cellDef->cd_name);
if (cellDef->cd_file != NULL)
{
freeMagic(cellDef->cd_file);
cellDef->cd_file = NULL;
}
cellDef->cd_file = fullpath;
}
}
@ -945,7 +943,7 @@ CmdCellname(w, cmd)
newDef = DBCellLookDef(cellname);
if (newDef == (CellDef *) NULL)
{
newDef = DBCellNewDef(cellname, (char *) NULL);
newDef = DBCellNewDef(cellname);
DBCellSetAvail(newDef);
}
break;
@ -1442,7 +1440,7 @@ CmdCif(w, cmd)
paintDef = DBCellLookDef(argv[4]);
if (paintDef == (CellDef *)NULL)
{
paintDef = DBCellNewDef(argv[4], (char *)NULL);
paintDef = DBCellNewDef(argv[4]);
DBCellSetAvail(paintDef);
}
}
@ -3699,8 +3697,7 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
if ((cellnameptr = strrchr(cmd->tx_argv[1], '/')) != NULL)
{
cellnameptr++;
/* Allocate extra space for cellname in case it needs an extension */
fullpathname = (char *)mallocMagic(strlen(cmd->tx_argv[1]) + 10);
fullpathname = (char *)mallocMagic(strlen(cmd->tx_argv[1]) + 2);
strcpy(fullpathname, cmd->tx_argv[1]);
}
else
@ -3714,14 +3711,6 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
if ((clen > 4) && !strcmp(cellnameptr + clen - 4, ".mag"))
*(cellnameptr + clen - 4) = '\0';
/* However, if this is a full path, then the full path name must have .mag */
if (fullpathname != NULL)
{
clen = strlen(fullpathname);
if ((clen <= 4) || strcmp(fullpathname + clen - 4, ".mag"))
strcat(cellnameptr, ".mag");
}
/* Check for illegal characters in the cellname */
if (CmdIllegalChars(cellnameptr, "", "Cell name"))
{
@ -3731,7 +3720,7 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
def = DBCellLookDef(cellnameptr);
if (def == (CellDef *) NULL)
def = DBCellNewDef(cellnameptr, (char *) NULL);
def = DBCellNewDef(cellnameptr);
if (fullpathname != NULL)
{
@ -3757,7 +3746,7 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
uniqchar++;
}
TxError("Renaming cell to \"%s\" to avoid conflict.", newcellname);
def = DBCellNewDef(cellnameptr, (char *)NULL);
def = DBCellNewDef(cellnameptr);
def->cd_file = StrDup(&def->cd_file, fullpathname);
freeMagic(newcellname);
}
@ -3785,7 +3774,7 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
dummy->cu_expandMask = CU_DESCEND_SPECIAL;
if (DBIsAncestor(def, EditCellUse->cu_def))
{
TxError("The edit cell is already a desecendant of \"%s\",\n",
TxError("The edit cell is already a descendant of \"%s\",\n",
cmd->tx_argv[1]);
TxError(" which means that you're trying to create a circular\n");
TxError(" structure. This isn't legal.\n");

View File

@ -878,7 +878,8 @@ cmdExpandFunc(use, windowMask)
#define DOCAPACITANCE 2
#define DOCOUPLING 3
#define DOLENGTH 4
#define DORESISTANCE 5
#define DOLOCAL 5
#define DORESISTANCE 6
#define LENCLEAR 0
#define LENDRIVER 1
@ -900,6 +901,7 @@ CmdExtract(w, cmd)
CellDef *selectedDef;
bool dolist = FALSE;
bool doforall = FALSE;
bool doLocal = FALSE;
int argc = cmd->tx_argc;
char **argv = cmd->tx_argv;
@ -918,6 +920,7 @@ CmdExtract(w, cmd)
"capacitance extract substrate capacitance",
"coupling extract coupling capacitance",
"length compute driver-receiver pathlengths",
"local put all generated files in the current directory",
"resistance estimate resistance",
NULL
};
@ -1136,6 +1139,7 @@ CmdExtract(w, cmd)
TxPrintf("%s capacitance\n", OPTSET(EXT_DOCAPACITANCE));
TxPrintf("%s coupling\n", OPTSET(EXT_DOCOUPLING));
TxPrintf("%s length\n", OPTSET(EXT_DOLENGTH));
TxPrintf("%s local\n", OPTSET(EXT_DOLOCAL));
TxPrintf("%s resistance\n", OPTSET(EXT_DORESISTANCE));
return;
#undef OPTSET
@ -1163,6 +1167,7 @@ CmdExtract(w, cmd)
case DOCAPACITANCE: option = EXT_DOCAPACITANCE; break;
case DOCOUPLING: option = EXT_DOCOUPLING; break;
case DOLENGTH: option = EXT_DOLENGTH; break;
case DOLOCAL: option = EXT_DOLOCAL; break;
case DORESISTANCE: option = EXT_DORESISTANCE; break;
}
if (no) ExtOptions &= ~option;

View File

@ -1944,7 +1944,7 @@ CmdFlatten(w, cmd)
TxError("%s already exists\n",destname);
return;
}
newdef = DBCellNewDef(destname, (char *) NULL);
newdef = DBCellNewDef(destname);
ASSERT(newdef, "CmdFlatten");
DBCellSetAvail(newdef);
newuse = DBCellNewUse(newdef, (char *) NULL);

View File

@ -480,8 +480,8 @@ keepGoing(use, clientdata)
* Implement the "move" command.
*
* Usage:
* move [direction [amount]]
* move to x y
* move [origin] [direction [amount]]
* move [origin] to x y
*
* Results:
* None.
@ -502,12 +502,13 @@ CmdMove(w, cmd)
Point rootPoint, editPoint;
CellDef *rootDef;
int argpos;
bool doOrigin = FALSE;
if (cmd->tx_argc > 4)
{
badUsage:
TxError("Usage: %s [direction [amount]]\n", cmd->tx_argv[0]);
TxError(" or: %s to x y\n", cmd->tx_argv[0]);
TxError("Usage: %s [origin] [direction [amount]]\n", cmd->tx_argv[0]);
TxError(" or: %s [origin] to x y\n", cmd->tx_argv[0]);
return;
}
@ -518,18 +519,26 @@ CmdMove(w, cmd)
if (!ToolGetEditBox((Rect *)NULL)) return;
if (strcmp(cmd->tx_argv[1], "to") == 0)
argpos = 1;
if (strcmp(cmd->tx_argv[1], "origin") == 0)
{
doOrigin = TRUE;
argpos++;
}
if (strcmp(cmd->tx_argv[argpos], "to") == 0)
{
if (cmd->tx_argc != 4)
goto badUsage;
editPoint.p_x = cmdParseCoord(w, cmd->tx_argv[2], FALSE, TRUE);
editPoint.p_y = cmdParseCoord(w, cmd->tx_argv[3], FALSE, FALSE);
editPoint.p_x = cmdParseCoord(w, cmd->tx_argv[argpos + 1], FALSE, TRUE);
editPoint.p_y = cmdParseCoord(w, cmd->tx_argv[argpos + 2], FALSE, FALSE);
GeoTransPoint(&EditToRootTransform, &editPoint, &rootPoint);
goto moveToPoint;
}
indx = GeoNameToPos(cmd->tx_argv[1], FALSE, FALSE);
argpos = (indx < 0) ? 1 : 2;
indx = GeoNameToPos(cmd->tx_argv[argpos], FALSE, FALSE);
if (indx >= 0) argpos++;
if (cmd->tx_argc >= 3)
{
@ -605,8 +614,9 @@ CmdMove(w, cmd)
* but is retained for backward compatibility.
*/
if (ToolGetBox(&rootDef, &rootBox) && ((rootDef == SelectRootDef)
|| (SelectRootDef == NULL)))
if (ToolGetBox(&rootDef, &rootBox) &&
((rootDef == SelectRootDef) || (SelectRootDef == NULL))
&& (doOrigin == FALSE))
{
GeoTransRect(&t, &rootBox, &newBox);
DBWSetBox(rootDef, &newBox);
@ -640,11 +650,41 @@ moveToPoint:
}
GeoTransTranslate(rootPoint.p_x - rootBox.r_xbot,
rootPoint.p_y - rootBox.r_ybot, &GeoIdentityTransform, &t);
GeoTransRect(&t, &rootBox, &newBox);
DBWSetBox(rootDef, &newBox);
if (doOrigin == FALSE)
{
GeoTransRect(&t, &rootBox, &newBox);
DBWSetBox(rootDef, &newBox);
}
}
SelectTransform(&t);
if (doOrigin)
{
DBMoveCell(rootDef, t.t_c, t.t_f);
/* Adjust box to maintain relative position */
if (ToolGetBox(&rootDef, &rootBox) &&
((rootDef == SelectRootDef) || (SelectRootDef == NULL)))
{
t.t_c = -t.t_c;
t.t_f = -t.t_f;
GeoTransRect(&t, &rootBox, &newBox);
DBWSetBox(rootDef, &newBox);
t.t_c = -t.t_c;
t.t_f = -t.t_f;
}
/* Adjust all window viewing positions and redraw */
WindTranslate(t.t_c, t.t_f);
/* This is harsh. Might work to change all distance measures */
/* in the undo record, but this is simple and direct. */
UndoFlush();
}
else
SelectTransform(&t);
}
/*

View File

@ -153,8 +153,11 @@ CmdSave(w, cmd)
DBUpdateStamps();
if (cmd->tx_argc == 2)
{
char *fileName;
if (CmdIllegalChars(cmd->tx_argv[1], "[],", "Cell name"))
return;
cmdSaveCell(locDef, cmd->tx_argv[1], FALSE, TRUE);
}
else cmdSaveCell(locDef, (char *) NULL, FALSE, TRUE);
@ -842,6 +845,8 @@ CmdSelect(w, cmd)
option = SEL_DEFAULT;
else
{
char *fileName;
option = Lookup(optionArgs[0], cmdSelectOption);
if (option < 0 && cmd->tx_argc != 2)
{

View File

@ -33,6 +33,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "database/database.h"
#include "tiles/tile.h"
#include "utils/hash.h"
#include "utils/malloc.h"
#include "windows/windows.h"
#include "dbwind/dbwind.h"
#include "utils/main.h"
@ -589,6 +590,8 @@ cmdSaveCell(cellDef, newName, noninteractive, tryRename)
* place where it was saved.
*/
{
char *fileName = newName;
/* Eliminate the phony labels added for use by rsim */
#ifndef NO_SIM_MODULE
SimEraseLabels();
@ -604,41 +607,41 @@ cmdSaveCell(cellDef, newName, noninteractive, tryRename)
{
if (newName == NULL)
TxPrintf("Must specify name for cell %s.\n", UNNAMED);
newName = cmdCheckNewName(cellDef, newName, TRUE, noninteractive);
if (newName == NULL) return;
fileName = cmdCheckNewName(cellDef, newName, TRUE, noninteractive);
if (fileName == NULL) return;
}
else if (newName != NULL)
{
newName = cmdCheckNewName(cellDef, newName, TRUE, noninteractive);
if (newName == NULL) return;
fileName = cmdCheckNewName(cellDef, newName, TRUE, noninteractive);
if (fileName == NULL) return;
}
else
{
if (cellDef->cd_file == NULL)
{
newName = cmdCheckNewName(cellDef, cellDef->cd_name,
fileName = cmdCheckNewName(cellDef, cellDef->cd_name,
TRUE, noninteractive);
if (newName == NULL) return;
if (fileName == NULL) return;
}
}
DBUpdateStamps();
if (!DBCellWrite(cellDef, newName))
if (!DBCellWrite(cellDef, fileName))
{
TxError("Could not write file. Cell not written.\n");
return;
goto cleanup;
}
if (!tryRename || (newName == NULL) || (strcmp(cellDef->cd_name, newName) == 0))
return;
if (!tryRename || (fileName == NULL) || (strcmp(cellDef->cd_name, fileName) == 0))
goto cleanup;
/* Rename the cell */
if (!DBCellRenameDef(cellDef, newName))
if (!DBCellRenameDef(cellDef, fileName))
{
/* This should never happen */
TxError("Magic error: there is already a cell named \"%s\"\n",
newName);
return;
fileName);
goto cleanup;
}
if (EditCellUse && (cellDef == EditCellUse->cu_def))
@ -660,6 +663,11 @@ cmdSaveCell(cellDef, newName, noninteractive, tryRename)
(void) WindSearch(DBWclientID, (ClientData) NULL, (Rect *) NULL,
cmdSaveWindSet, (ClientData) cellDef);
}
cleanup:
if ((fileName != newName) && (fileName != cellDef->cd_name))
freeMagic(fileName);
return;
}
/*
@ -694,38 +702,44 @@ cmdCheckNewName(def, newName, tryRename, noninteractive)
bool tryRename;
bool noninteractive;
{
static char newname[256];
static char *yesno[] = { "no", "yes", 0 };
char *filename;
char *prompt;
char *returnname;
int code;
FILE *f;
returnname = newName;
again:
if (newName == NULL)
if (returnname == NULL)
{
if (noninteractive) {
TxError("Can't write file named '%s'\n", def->cd_name);
return NULL;
};
TxPrintf("File for cell %s: [hit return to abort save] ", def->cd_name);
if (TxGetLine(newname, sizeof newname) == NULL || newname[0] == '\0')
returnname = (char *)mallocMagic(1024 * sizeof(char));
if (TxGetLine(returnname, sizeof returnname) == NULL || returnname[0] == '\0')
{
TxPrintf("Cell not saved.\n");
freeMagic(returnname);
return ((char *) NULL);
}
if (CmdIllegalChars(newname, "[],", "Cell name"))
if (CmdIllegalChars(returnname, "[],", "Cell name"))
{
freeMagic(returnname);
goto again;
newName = newname;
}
}
/* Remove any ".mag" file extension from the name */
else if (!strcmp(newName + strlen(newName) - 4, ".mag"))
*(newName + strlen(newName) - 4) = '\0';
if (!strcmp(returnname + strlen(returnname) - 4, ".mag"))
*(returnname + strlen(returnname) - 4) = '\0';
if (strcmp(newName, def->cd_name) != 0)
if (strcmp(returnname, def->cd_name) != 0)
{
if (f = PaOpen(newName, "r", DBSuffix, ".", (char *) NULL, &filename))
if (f = PaOpen(returnname, "r", DBSuffix, ".", (char *) NULL, &filename))
{
(void) fclose(f);
if (noninteractive) {
@ -740,23 +754,24 @@ again:
if (code == 0)
{
/* No -- don't overwrite */
newName = NULL;
if (returnname != newName) freeMagic(returnname);
returnname = NULL;
goto again;
}
}
}
if (tryRename && DBCellLookDef(newName) != NULL)
if (tryRename && DBCellLookDef(returnname) != NULL)
{
TxError("Can't rename cell '%s' to '%s' because that cell already exists.\n",
def->cd_name, newName);
def->cd_name, returnname);
if (returnname != newName) freeMagic(returnname);
if (noninteractive) return NULL;
newName = NULL;
returnname = NULL;
goto again;
}
}
return (newName);
return (returnname);
}
/*

View File

@ -1245,14 +1245,12 @@ DBCellLookDef(cellName)
*/
CellDef *
DBCellNewDef(cellName, cellFileName)
DBCellNewDef(cellName)
char *cellName; /* Name by which the cell is known */
char *cellFileName; /* Name of disk file in which the cell
* should be kept when written out.
*/
{
CellDef *cellDef;
HashEntry *entry;
char *dotptr;
if (cellName == (char *) NULL)
cellName = UNNAMED;
@ -1264,10 +1262,12 @@ DBCellNewDef(cellName, cellFileName)
cellDef = DBCellDefAlloc();
HashSetValue(entry, (ClientData) cellDef);
cellDef->cd_name = StrDup((char **) NULL, cellName);
if (cellFileName == (char *) NULL)
cellDef->cd_file = cellFileName;
else
cellDef->cd_file = StrDup((char **) NULL, cellFileName);
/* Strip any .mag extension off of the cell name */
dotptr = strrchr(cellDef->cd_name, '.');
if (dotptr && !strcmp(dotptr, ".mag")) *dotptr = '\0';
cellDef->cd_file = NULL;
return (cellDef);
}
@ -2083,7 +2083,7 @@ DBNewYank(yname, pyuse, pydef)
*pydef = DBCellLookDef(yname);
if (*pydef == (CellDef *) NULL)
{
*pydef = DBCellNewDef (yname,(char *) NULL);
*pydef = DBCellNewDef(yname);
ASSERT(*pydef != (CellDef *) NULL, "DBNewYank");
DBCellSetAvail(*pydef);
(*pydef)->cd_flags |= CDINTERNAL;

View File

@ -1361,6 +1361,42 @@ typedef struct LCU1 /* A linked celluse record */
struct LCU1 *cu_next; /* Pointer to another linked celluse record */
} LinkedCellUse;
/*
* ----------------------------------------------------------------------------
*
* DBMovePoint ---
*
* Move a point by a position (origx, origy). Ignore positions which
* are marked as (M)INFINITY.
*
* Results:
* TRUE if the point was moved (point position was not infinite)
*
* Side effects:
* Point structure pointed to by the first argument is repositioned.
*
* ----------------------------------------------------------------------------
*/
bool
DBMovePoint(p, origx, origy)
Point *p;
int origx, origy;
{
int result = FALSE;
if ((p->p_x < (INFINITY - 2)) && (p->p_x > (MINFINITY + 2)))
{
p->p_x -= origx;
result = TRUE;
}
if ((p->p_y < (INFINITY + 2)) && (p->p_y > (MINFINITY + 2)))
{
p->p_y -= origy;
result = TRUE;
}
return result;
}
/*
* ----------------------------------------------------------------------------
*
@ -1513,6 +1549,14 @@ struct scaleArg {
bool modified;
};
struct moveArg {
int origx;
int origy;
int pnum;
Plane *ptarget;
bool modified;
};
/*
* ----------------------------------------------------------------------------
*
@ -1594,6 +1638,74 @@ dbTileScaleFunc(tile, scvals)
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* dbMovePlane --
*
* Relocation procedure called on a single plane. Copies paint into the
* new plane at a delta position (-origx, -origy)
*
* ----------------------------------------------------------------------------
*/
bool
dbMovePlane(oldplane, newplane, pnum, origx, origy)
Plane *oldplane, *newplane;
int pnum;
int origx, origy;
{
int dbTileMoveFunc(); /* forward declaration */
struct moveArg arg;
arg.origx = origx;
arg.origy = origy;
arg.ptarget = newplane;
arg.pnum = pnum;
arg.modified = FALSE;
(void) DBSrPaintArea((Tile *) NULL, oldplane, &TiPlaneRect,
&DBAllButSpaceBits, dbTileMoveFunc, (ClientData) &arg);
return arg.modified;
}
/*
* ----------------------------------------------------------------------------
*
* dbTileMoveFunc --
*
* Repositioning procedure called on each tile being copied from one plane
* to another. Delta position (-origx, -origy) is stored inside the struct
* moveArg before calling.
*
* ----------------------------------------------------------------------------
*/
int
dbTileMoveFunc(tile, mvvals)
Tile *tile;
struct moveArg *mvvals;
{
TileType type;
Rect targetRect;
TileType exact;
TiToRect(tile, &targetRect);
mvvals->modified = TRUE;
DBMovePoint(&targetRect.r_ll, mvvals->origx, mvvals->origy);
DBMovePoint(&targetRect.r_ur, mvvals->origx, mvvals->origy);
type = TiGetTypeExact(tile);
exact = type;
if (IsSplit(tile))
type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
DBNMPaintPlane(mvvals->ptarget, exact, &targetRect,
DBStdPaintTbl(type, mvvals->pnum),
(PaintUndoInfo *)NULL);
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -1737,14 +1849,6 @@ dbScaleCell(cellDef, scalen, scaled)
lu = lu->cu_next;
}
/* Scale the position of all subcell uses. Count all of the cells in the */
/* subcell plane, and scale those without reference to the actual cells (so */
/* we don't count the cells multiple times). */
lhead = NULL;
(void) DBSrCellPlaneArea(cellDef->cd_cellPlane, &TiPlaneRect,
dbCellUseEnumFunc, (ClientData) &lhead);
/* Scale all of the paint tiles in this cell by creating a new plane */
/* and copying all tiles into the new plane at scaled dimensions. */
@ -1761,9 +1865,6 @@ dbScaleCell(cellDef, scalen, scaled)
cellDef->cd_planes[pNum] = newplane;
}
/* Check consistency of several global pointers */
/* WARNING: This list may not be complete! */
/* Also scale the position of all labels. */
/* If labels are the rendered-font type, scale the size as well */
@ -1879,3 +1980,150 @@ dbCellUseEnumFunc(cellUse, arg)
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* DBMoveCell --
*
* Reposition a cell to a different origin. This routine is equivalent to
* unexpanding all contents of a cell, selecting everything, and issuing a
* move command. However, for very large layouts this becomes memory- and
* compute- intensive. The process of reorienting an entire layout to a
* new position can be done much more efficiently. This routine is
* essentially a copy of dbScaleCell() but changes only position and not
* scale.
*
* ----------------------------------------------------------------------------
*/
int
DBMoveCell(cellDef, origx, origy)
CellDef *cellDef; /* Pointer to CellDef to be saved. This def might
* be an internal buffer; if so, we ignore it.
*/
int origx, origy; /* Internal unit coordinates which will become the new origin */
{
int dbCellTileEnumFunc(), dbCellUseEnumFunc();
Label *lab;
int pNum;
LinkedTile *lhead, *lt;
LinkedCellUse *luhead, *lu;
Plane *newplane;
/* Unlike dbScaleCell(), this routine is only run on valid edit defs */
cellDef->cd_flags |= CDBOXESCHANGED;
/* Enumerate all unique cell uses, and move their position in the */
/* bounding box and transform. */
luhead = NULL;
(void) DBCellEnum(cellDef, dbCellUseEnumFunc, (ClientData) &luhead);
lu = luhead;
while (lu != NULL)
{
CellUse *use;
Rect *bbox;
use = lu->cellUse;
bbox = &use->cu_bbox;
/* TxPrintf("CellUse: BBox is ll (%d, %d), transform [%d %d %d %d %d %d]\n",
bbox->r_xbot, bbox->r_ybot,
use->cu_transform.t_a, use->cu_transform.t_b, use->cu_transform.t_c,
use->cu_transform.t_d, use->cu_transform.t_e, use->cu_transform.t_f); */
DBMovePoint(&bbox->r_ll, origx, origy);
DBMovePoint(&bbox->r_ur, origx, origy);
bbox = &use->cu_extended;
DBMovePoint(&bbox->r_ll, origx, origy);
DBMovePoint(&bbox->r_ur, origx, origy);
use->cu_transform.t_c -= origx;
use->cu_transform.t_f -= origy;
lu = lu->cu_next;
}
/* Free this linked cellUse structure */
lu = luhead;
while (lu != NULL)
{
freeMagic((char *)lu);
lu = lu->cu_next;
}
/* Move all of the paint tiles in this cell by creating a new plane */
/* and copying all tiles into the new plane at the new position. */
for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
{
if (cellDef->cd_planes[pNum] == NULL) continue;
newplane = DBNewPlane((ClientData) TT_SPACE);
DBClearPaintPlane(newplane);
if (dbMovePlane(cellDef->cd_planes[pNum], newplane, pNum,
origx, origy, FALSE))
cellDef->cd_flags |= (CDMODIFIED | CDGETNEWSTAMP);
DBFreePaintPlane(cellDef->cd_planes[pNum]);
TiFreePlane(cellDef->cd_planes[pNum]);
cellDef->cd_planes[pNum] = newplane;
}
/* Also move the position of all labels. */
if (cellDef->cd_labels)
{
for (lab = cellDef->cd_labels; lab; lab = lab->lab_next)
{
DBMovePoint(&lab->lab_rect.r_ll, origx, origy);
DBMovePoint(&lab->lab_rect.r_ur, origx, origy);
if (lab->lab_font >= 0)
{
DBMovePoint(&lab->lab_bbox.r_ll, origx, origy);
DBMovePoint(&lab->lab_bbox.r_ur, origx, origy);
}
}
}
donecell:
/* The cellDef bounding box gets moved to match the new position. */
DBMovePoint(&cellDef->cd_bbox.r_ll, origx, origy);
DBMovePoint(&cellDef->cd_bbox.r_ur, origx, origy);
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. */
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);
}
}
}
return 0;
}

View File

@ -859,7 +859,7 @@ DBReadBackup(name)
cellDef = DBCellLookDef(rootname);
if (cellDef == (CellDef *)NULL)
cellDef = DBCellNewDef(rootname, (char *)NULL);
cellDef = DBCellNewDef(rootname);
cellDef->cd_flags &= ~CDNOTFOUND;
cellDef->cd_flags |= CDAVAILABLE;
@ -1054,23 +1054,22 @@ dbReadOpen(cellDef, name, setFileName, errptr)
if (f != NULL)
{
if (pptr != NULL) *pptr = '.';
/* NOTE: May not want to present this as an error, as */
/* it is a common technique to read files from, say, a */
/* LEF file but not save them locally, and then expect */
/* that the layout views will be picked up from */
/* 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);
TxError("The cell exists in the search paths at %s.\n", filename);
TxError("The discovered version will be used.\n");
/* Write the new path to cd_file or else magic will */
/* generate another error later. */
cellDef->cd_file = 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");
}
}
@ -1133,7 +1132,14 @@ dbReadOpen(cellDef, name, setFileName, errptr)
cellDef->cd_flags &= ~CDNOTFOUND;
#endif
if (setFileName)
{
/* Remove any ".mag" file extension */
char *pptr = strrchr(filename, '.');
if (pptr != NULL)
if (!strcmp(pptr, DBSuffix)) *pptr = '\0';
(void) StrDup(&cellDef->cd_file, filename);
}
cellDef->cd_flags |= CDAVAILABLE;
return (f);
}
@ -1346,7 +1352,7 @@ badTransform:
subCellDef = DBCellLookDef(cellname);
if (subCellDef == (CellDef *) NULL)
{
subCellDef = DBCellNewDef(cellname, (char *)NULL);
subCellDef = DBCellNewDef(cellname);
subCellDef->cd_timestamp = childStamp;
/* Make sure rectangle is non-degenerate */
@ -2715,29 +2721,25 @@ DBCellWrite(cellDef, fileName)
/*
* Figure out the name of the file we will eventually write.
*/
if (fileName)
if (!fileName)
{
realname = (char *) mallocMagic(strlen(fileName) + strlen(DBSuffix) + 1);
(void) sprintf(realname, "%s%s", fileName, DBSuffix);
if (cellDef->cd_file)
fileName = cellDef->cd_file;
else if (cellDef->cd_name)
fileName = cellDef->cd_name;
else
return FALSE;
}
/* Bug fix: 7/17/99, Michael D. Godfrey: Forces */
/* cd_name and cd_file to ALWAYS be the same, otherwise ugly */
/* surprises can occur after saving a file as a different */
/* filename. */
/* Bug fix: 7/17/99, Michael D. Godfrey: Forces */
/* cd_name and cd_file to ALWAYS be the same, otherwise ugly */
/* surprises can occur after saving a file as a different */
/* filename. */
cellDef->cd_file = StrDup(&cellDef->cd_file, realname);
}
else if (cellDef->cd_file)
{
realname = StrDup((char **) NULL, cellDef->cd_file);
}
else if (cellDef->cd_name)
{
realname = (char *) mallocMagic((unsigned) (strlen(cellDef->cd_name)
+ strlen(DBSuffix) + 1));
(void) sprintf(realname, "%s%s", cellDef->cd_name, DBSuffix);
}
else return (FALSE);
cellDef->cd_file = StrDup(&cellDef->cd_file, fileName);
realname = (char *) mallocMagic(strlen(fileName) + strlen(DBSuffix) + 1);
(void) sprintf(realname, "%s%s", fileName, DBSuffix);
/*
* Expand the filename, removing the leading ~, if any.

View File

@ -328,7 +328,7 @@ DBWloadWindow(window, name, ignoreTech, expand, dereference)
newEditDef = DBCellLookDef(UNNAMED);
if (newEditDef == (CellDef *) NULL)
{
newEditDef = DBCellNewDef(UNNAMED, (char *) NULL);
newEditDef = DBCellNewDef(UNNAMED);
DBCellSetAvail(newEditDef);
}
}
@ -397,7 +397,7 @@ DBWloadWindow(window, name, ignoreTech, expand, dereference)
}
}
if (newEditDef == (CellDef *) NULL)
newEditDef = DBCellNewDef(rootname, (char *) NULL);
newEditDef = DBCellNewDef(rootname);
if (dereference) newEditDef->cd_flags |= CDDEREFERENCE;
@ -431,7 +431,7 @@ DBWloadWindow(window, name, ignoreTech, expand, dereference)
newEditDef = DBCellLookDef(UNNAMED);
if (newEditDef == (CellDef *) NULL)
{
newEditDef = DBCellNewDef(UNNAMED, (char *) NULL);
newEditDef = DBCellNewDef(UNNAMED);
DBCellSetAvail(newEditDef);
}
}

View File

@ -345,7 +345,7 @@ DRCInit()
DRCdef = DBCellLookDef(DRCYANK);
if (DRCdef == (CellDef *) NULL)
{
DRCdef = DBCellNewDef (DRCYANK,(char *) NULL);
DRCdef = DBCellNewDef(DRCYANK);
ASSERT(DRCdef != (CellDef *) NULL, "DRCInit");
DBCellSetAvail(DRCdef);
DRCdef->cd_flags |= CDINTERNAL;

View File

@ -1619,7 +1619,7 @@ esMakePorts(hc, cdata)
nn = (EFNodeName *) HashGetValue(he);
}
if (!(nn->efnn_node->efnode_flags & EF_PORT))
if (nn->efnn_node && !(nn->efnn_node->efnode_flags & EF_PORT))
{
nn->efnn_node->efnode_flags |= EF_PORT;
nn->efnn_port = -1; // Will be sorted later

View File

@ -1668,7 +1668,7 @@ topVisit(def, doStub)
sname = (EFNodeName *) HashGetValue(he);
if (sname == NULL) continue;
snode = sname->efnn_node;
if (!(snode->efnode_flags & EF_PORT)) continue;
if ((!snode) || (!(snode->efnode_flags & EF_PORT))) continue;
for (nodeName = sname; nodeName != NULL; nodeName = nodeName->efnn_next)
{
portorder = nodeName->efnn_port;
@ -1729,7 +1729,7 @@ topVisit(def, doStub)
if (sname == NULL) continue; /* Should not happen */
snode = sname->efnn_node;
if (!(snode->efnode_flags & EF_PORT)) continue;
if ((!snode) || (!(snode->efnode_flags & EF_PORT))) continue;
for (nodeName = sname; nodeName != NULL; nodeName = nodeName->efnn_next)
{
@ -1787,7 +1787,7 @@ topVisit(def, doStub)
if (sname == NULL) continue;
snode = sname->efnn_node;
if (snode->efnode_flags & EF_SUBS_PORT)
if (snode && (snode->efnode_flags & EF_SUBS_PORT))
{
if (snode->efnode_name->efnn_port < 0)
{

View File

@ -466,6 +466,8 @@ efBuildEquiv(def, nodeName1, nodeName2)
if (efWarn)
efReadError("Merged nodes %s and %s\n", nodeName1, nodeName2);
efNodeMerge(&nn1->efnn_node, &nn2->efnn_node);
if (nn1->efnn_port > 0) nn2->efnn_port = nn1->efnn_port;
else if (nn2->efnn_port > 0) nn1->efnn_port = nn2->efnn_port;
}
return;
}

View File

@ -95,8 +95,11 @@ ExtCell(def, outName, doLength)
{
char *filename;
FILE *f;
bool doLocal;
f = extFileOpen(def, outName, "w", &filename);
doLocal = (ExtOptions & EXT_DOLOCAL) ? TRUE : FALSE;
f = extFileOpen(def, outName, "w", doLocal, &filename);
TxPrintf("Extracting %s into %s:\n", def->cd_name, filename);
@ -149,7 +152,7 @@ ExtCell(def, outName, doLength)
*/
FILE *
extFileOpen(def, file, mode, prealfile)
extFileOpen(def, file, mode, doLocal, prealfile)
CellDef *def; /* Cell whose .ext file is to be written */
char *file; /* If non-NULL, open 'name'.ext; otherwise,
* derive filename from 'def' as described
@ -158,6 +161,7 @@ extFileOpen(def, file, mode, prealfile)
char *mode; /* Either "r" or "w", the mode in which the .ext
* file is to be opened.
*/
bool doLocal; /* If true, always write to local directory */
char **prealfile; /* If this is non-NULL, it gets set to point to
* a string holding the name of the .ext file.
*/
@ -167,6 +171,8 @@ extFileOpen(def, file, mode, prealfile)
FILE *rfile, *testf;
if (file) name = file;
else if (doLocal)
name = def->cd_name; /* No path component, so save locally */
else if (def->cd_file)
{
name = def->cd_file;

View File

@ -626,7 +626,6 @@ closeit:
void
extExtractStack(stack, doExtract, rootDef)
Stack *stack;
bool doExtract;
CellDef *rootDef;
{
int fatal = 0, warnings = 0;

View File

@ -66,6 +66,7 @@ extern char *extDevTable[];
#define EXT_DORESISTANCE 0x08 /* Extract resistance */
#define EXT_DOLENGTH 0x10 /* Extract pathlengths */
#define EXT_DOALL 0x1f /* ALL OF THE ABOVE */
#define EXT_DOLOCAL 0x20 /* Write to local directory only */
extern int ExtOptions; /* Bitmask of above */

View File

@ -1220,6 +1220,9 @@ DefReadVias(f, sname, oscale, total)
LefEstimate(processed++, total, "vias");
/* If not otherwise specified, rows and columns default to 1 */
rows = cols = 1;
/* Get via name */
token = LefNextToken(f, TRUE);
if (sscanf(token, "%2047s", vianame) != 1)
@ -1538,7 +1541,7 @@ DefReadComponents(f, rootDef, sname, oscale, total)
/* Before giving up, assume that this cell has a */
/* magic .mag layout file. */
defMacro = DBCellNewDef(token, (char *)NULL);
defMacro = DBCellNewDef(token);
defMacro->cd_flags &= ~CDNOTFOUND;
dereference = (defMacro->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(defMacro, (char *)NULL, TRUE, dereference, NULL))

View File

@ -572,7 +572,7 @@ lefFindCell(name)
def = DBCellLookDef(name);
if (def == NULL)
{
def = DBCellNewDef(name, (char *)NULL);
def = DBCellNewDef(name);
DBReComputeBbox(def);
}
HashSetValue(h, def);

View File

@ -618,6 +618,14 @@ MakeLegalLEFSyntax(text)
return rstr;
}
/* Linked list structure for holding PIN PORT geometry areas */
typedef struct _labelLinkedList {
Label *lll_label;
Rect lll_area;
struct _labelLinkedList *lll_next;
} labelLinkedList;
/*
* ----------------------------------------------------------------------------
*
@ -657,6 +665,7 @@ lefWriteMacro(def, f, scale, hide)
char *LEFtext;
HashSearch hs;
HashEntry *he;
labelLinkedList *lll = NULL;
extern CellDef *SelectDef;
@ -666,7 +675,7 @@ lefWriteMacro(def, f, scale, hide)
lefFlatDef = DBCellLookDef("__lefFlat__");
if (lefFlatDef == (CellDef *)NULL)
lefFlatDef = DBCellNewDef("__lefFlat__", (char *)NULL);
lefFlatDef = DBCellNewDef("__lefFlat__");
DBCellSetAvail(lefFlatDef);
lefFlatDef->cd_flags |= CDINTERNAL;
@ -819,7 +828,7 @@ lefWriteMacro(def, f, scale, hide)
lc.lefYank = DBCellLookDef("__lefYank__");
if (lc.lefYank == (CellDef *)NULL)
lc.lefYank = DBCellNewDef("__lefYank__", (char *)NULL);
lc.lefYank = DBCellNewDef("__lefYank__");
DBCellSetAvail(lc.lefYank);
lc.lefYank->cd_flags |= CDINTERNAL;
@ -959,7 +968,11 @@ lefWriteMacro(def, f, scale, hide)
if (hide)
{
SelectChunk(&scx, lab->lab_type, 0, NULL, FALSE);
Rect carea;
labelLinkedList *newlll;
SelectChunk(&scx, lab->lab_type, 0, &carea, FALSE);
if (GEO_RECTNULL(&carea)) carea = lab->lab_rect;
/* Note that a sticky label could be placed over multiple */
/* tile types, which would cause SelectChunk to fail. So */
@ -967,8 +980,15 @@ lefWriteMacro(def, f, scale, hide)
/* SelectDef. */
pNum = DBPlane(lab->lab_type);
DBPaintPlane(SelectDef->cd_planes[pNum], &lab->lab_rect,
DBPaintPlane(SelectDef->cd_planes[pNum], &carea,
DBStdPaintTbl(lab->lab_type, pNum), (PaintUndoInfo *) NULL);
/* Remember this area since it's going to get erased */
newlll = (labelLinkedList *)mallocMagic(sizeof(labelLinkedList));
newlll->lll_label = lab;
newlll->lll_area = carea;
newlll->lll_next = lll;
lll = newlll;
}
else
SelectNet(&scx, lab->lab_type, 0, NULL, FALSE);
@ -1064,6 +1084,7 @@ lefWriteMacro(def, f, scale, hide)
/* cell. Otherwise, this routine can block internal pins. */
Rect layerBound;
labelLinkedList *thislll;
for (ttype = TT_TECHDEPBASE; ttype < DBNumTypes; ttype++)
if (TTMaskHasType(&lmask, ttype))
@ -1080,39 +1101,20 @@ lefWriteMacro(def, f, scale, hide)
DBPaint(lc.lefYank, &layerBound, ttype);
}
scx.scx_use = &lefSourceUse;
for (lab = def->cd_labels; lab != NULL; lab = lab->lab_next)
for (thislll = lll; thislll; thislll = thislll->lll_next)
{
Rect carea;
int lspace;
labr = lab->lab_rect;
lab = thislll->lll_label;
/* Force label area to be non-degenerate */
if (labr.r_xbot >= labr.r_xtop)
{
labr.r_xbot--;
labr.r_xtop++;
}
if (labr.r_ybot >= labr.r_ytop)
{
labr.r_ybot--;
labr.r_ytop++;
}
if (lab->lab_flags & PORT_DIR_MASK)
{
scx.scx_area = labr;
SelectClear();
SelectChunk(&scx, lab->lab_type, 0, &carea, FALSE);
if (GEO_RECTNULL(&carea)) carea = lab->lab_rect;
lspace = DRCGetDefaultLayerSpacing(lab->lab_type, lab->lab_type);
carea.r_xbot -= lspace;
carea.r_ybot -= lspace;
carea.r_xtop += lspace;
carea.r_ytop += lspace;
DBErase(lc.lefYank, &carea, lab->lab_type);
}
lspace = DRCGetDefaultLayerSpacing(lab->lab_type, lab->lab_type);
thislll->lll_area.r_xbot -= lspace;
thislll->lll_area.r_ybot -= lspace;
thislll->lll_area.r_xtop += lspace;
thislll->lll_area.r_ytop += lspace;
DBErase(lc.lefYank, &thislll->lll_area, lab->lab_type);
freeMagic(thislll);
}
}
else

View File

@ -235,7 +235,7 @@ nmGetShowCell()
nmscShowDef = DBCellLookDef("__SHOW__");
if (nmscShowDef == NULL)
{
nmscShowDef = DBCellNewDef("__SHOW__", (char *) NULL);
nmscShowDef = DBCellNewDef("__SHOW__");
ASSERT (nmscShowDef != (CellDef *) NULL, "nmGetShowCell");
DBCellSetAvail(nmscShowDef);
nmscShowDef->cd_flags |= CDINTERNAL;

View File

@ -113,7 +113,7 @@ ResGetReCell()
ResDef = DBCellLookDef("__RESIS__");
if (ResDef == NULL)
{
ResDef = DBCellNewDef("__RESIS__", (char *) NULL);
ResDef = DBCellNewDef("__RESIS__");
ASSERT (ResDef != (CellDef *) NULL, "ResGetReCell");
DBCellSetAvail(ResDef);
ResDef->cd_flags |= CDINTERNAL;

View File

@ -273,7 +273,7 @@ RtrFindChannelDef()
/* Create our target cell */
if ((def = DBCellLookDef("__CHANNEL__")) == (CellDef *) NULL)
{
def = DBCellNewDef("__CHANNEL__", (char *) NULL);
def = DBCellNewDef("__CHANNEL__");
DBCellSetAvail(def);
def->cd_flags |= CDINTERNAL;
}

View File

@ -108,7 +108,7 @@ SelectInit()
SelectDef = DBCellLookDef("__SELECT__");
if (SelectDef == (CellDef *) NULL)
{
SelectDef = DBCellNewDef("__SELECT__",(char *) NULL);
SelectDef = DBCellNewDef("__SELECT__");
ASSERT(SelectDef != (CellDef *) NULL, "SelectInit");
DBCellSetAvail(SelectDef);
SelectDef->cd_flags |= CDINTERNAL;
@ -122,7 +122,7 @@ SelectInit()
Select2Def = DBCellLookDef("__SELECT2__");
if (Select2Def == (CellDef *) NULL)
{
Select2Def = DBCellNewDef("__SELECT2__",(char *) NULL);
Select2Def = DBCellNewDef("__SELECT2__");
ASSERT(Select2Def != (CellDef *) NULL, "SelectInit");
DBCellSetAvail(Select2Def);
Select2Def->cd_flags |= CDINTERNAL;

View File

@ -15,7 +15,7 @@ for i in $@; do
esac
done
#
eval /usr/local/lib/magic/tcl/magicdnull -dnull -noconsole -nowrapper $mgargs <<EOF
eval /home/tim/cad/lib/magic/tcl/magicdnull -dnull -noconsole -nowrapper $mgargs <<EOF
drc off
box 0 0 0 0
ext2sim $esargs

View File

@ -15,7 +15,7 @@ for i in $@; do
esac
done
#
eval /usr/local/lib/magic/tcl/magicdnull -dnull -noconsole -nowrapper $mgargs <<EOF
eval /home/tim/cad/lib/magic/tcl/magicdnull -dnull -noconsole -nowrapper $mgargs <<EOF
drc off
box 0 0 0 0
ext2spice $esargs

View File

@ -289,6 +289,47 @@ WindScale(scalen, scaled)
}
}
/*
* ----------------------------------------------------------------------------
*
* WindTranslate --
*
* Move the viewing windows by the given delta position. Because
* this is done in conjunction with repositioning the geometry
* ("move origin" command), we don't preserve the center position
* like WindZoom() does. The net effect is that the image in the
* window doesn't appear to change.
*
* Results:
* None.
*
* Side effects:
* All windows will be now view a different portion of the client's area.
*
* ----------------------------------------------------------------------------
*/
void
WindTranslate(origx, origy)
int origx, origy;
{
extern void DBMovePoint();
MagWindow *w2;
Rect newArea;
for (w2 = windTopWindow; w2 != NULL; w2 = w2->w_nextWindow)
{
newArea.r_xbot = w2->w_surfaceArea.r_xbot;
newArea.r_xtop = w2->w_surfaceArea.r_xtop;
newArea.r_ybot = w2->w_surfaceArea.r_ybot;
newArea.r_ytop = w2->w_surfaceArea.r_ytop;
DBMovePoint(&newArea.r_ll, origx, origy);
DBMovePoint(&newArea.r_ur, origx, origy);
WindMove(w2, &newArea);
}
}
/*
* ----------------------------------------------------------------------------