diff --git a/VERSION b/VERSION index 5bcff72f..ff0ca913 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.2.198 +8.2.199 diff --git a/commands/CmdCD.c b/commands/CmdCD.c index dc817c6f..86a258c5 100644 --- a/commands/CmdCD.c +++ b/commands/CmdCD.c @@ -3714,14 +3714,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")) { diff --git a/commands/CmdLQ.c b/commands/CmdLQ.c index 8427fb8d..53f7b928 100644 --- a/commands/CmdLQ.c +++ b/commands/CmdLQ.c @@ -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); } /* diff --git a/database/DBcellsrch.c b/database/DBcellsrch.c index d3eaa667..7e65fdbc 100644 --- a/database/DBcellsrch.c +++ b/database/DBcellsrch.c @@ -1386,6 +1386,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; +} + /* * ---------------------------------------------------------------------------- * @@ -1538,6 +1574,14 @@ struct scaleArg { bool modified; }; +struct moveArg { + int origx; + int origy; + int pnum; + Plane *ptarget; + bool modified; +}; + /* * ---------------------------------------------------------------------------- * @@ -1619,6 +1663,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; +} + /* * ---------------------------------------------------------------------------- * @@ -1804,9 +1916,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 */ @@ -1949,3 +2058,176 @@ 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 the position of all subcell uses. Count all of the tiles in the */ + /* subcell plane, and move those without reference to the actual cells (so */ + /* we don't count the cells multiple times). */ + + lhead = NULL; + (void) TiSrArea((Tile *)NULL, cellDef->cd_planes[PL_CELL], &TiPlaneRect, + dbCellTileEnumFunc, (ClientData) &lhead); + + /* Move each of the tiles in the linked list by (-x, -y) */ + /* Don't move (M)INFINITY on boundary tiles! */ + + lt = lhead; + while (lt != NULL) + { + DBMovePoint(<->tile->ti_ll, origx, origy); + lt = lt->t_next; + } + + /* Free this linked tile structure */ + lt = lhead; + while (lt != NULL) + { + freeMagic((char *)lt); + lt = lt->t_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; +} + diff --git a/database/DBio.c b/database/DBio.c index 0b74ef67..77c6ed5b 100644 --- a/database/DBio.c +++ b/database/DBio.c @@ -1133,7 +1133,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); } diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index fc010154..64578469 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -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 diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 94b2eb53..221483a6 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -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) { diff --git a/extflat/EFbuild.c b/extflat/EFbuild.c index f4ba250b..33e43bc6 100644 --- a/extflat/EFbuild.c +++ b/extflat/EFbuild.c @@ -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; } diff --git a/lef/lefWrite.c b/lef/lefWrite.c index af0cbffd..ad1cab85 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -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; @@ -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 diff --git a/windows/windView.c b/windows/windView.c index eefff34e..eb87d6b9 100644 --- a/windows/windView.c +++ b/windows/windView.c @@ -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); + } +} + + /* * ----------------------------------------------------------------------------