Compare commits
17 Commits
acdae1efd5
...
fc7aac1ca1
| Author | SHA1 | Date |
|---|---|---|
|
|
fc7aac1ca1 | |
|
|
246c0ea7a4 | |
|
|
47778971ee | |
|
|
cccd79ab0d | |
|
|
51b9846120 | |
|
|
1afd48e840 | |
|
|
99a5a28a3e | |
|
|
0ac4d3a465 | |
|
|
42aa06f8f5 | |
|
|
4d2912a406 | |
|
|
b668b02a1f | |
|
|
6b8f5d1d67 | |
|
|
c977e4cf76 | |
|
|
9327e319da | |
|
|
0e84616af8 | |
|
|
d825f6cafe | |
|
|
388572c1ff |
|
|
@ -117,6 +117,14 @@ DBCellRename(cellname, newname, doforce)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* Cannot rename a cell with the name of an existing cell */
|
||||
entry = HashLookOnly(&dbCellDefTable, newname);
|
||||
if (entry != NULL)
|
||||
{
|
||||
TxError("Cannot rename; cell \"%s\" already exists!\n", newname);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Disallow renaming if the cell has the READONLY flag set, */
|
||||
/* because the cellname must match the name in the GDS */
|
||||
/* file referenced. */
|
||||
|
|
@ -1936,6 +1944,7 @@ DBCellDeleteDef(cellDef)
|
|||
entry = HashFind(&dbCellDefTable, cellDef->cd_name);
|
||||
ASSERT(HashGetValue(entry) == (ClientData) cellDef, "DBCellDeleteDef");
|
||||
HashSetValue(entry, (ClientData) NULL);
|
||||
HashRemove(&dbCellDefTable, cellDef->cd_name);
|
||||
if (cellDef->cd_props)
|
||||
DBPropClearAll(cellDef);
|
||||
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ DBSrPaintNMArea(hintTile, plane, ttype, rect, mask, func, arg)
|
|||
* provide a hint tile in case hintTile == NULL.
|
||||
* The hint tile in the plane is updated to be
|
||||
* the last tile visited in the area
|
||||
* enumeration.
|
||||
* enumeration, if plane is non-NULL.
|
||||
*/
|
||||
TileType ttype; /* Information about the non-manhattan area to
|
||||
* search; zero if area is manhattan.
|
||||
|
|
@ -129,7 +129,7 @@ DBSrPaintNMArea(hintTile, plane, ttype, rect, mask, func, arg)
|
|||
{
|
||||
/* Each iteration enumerates another tile */
|
||||
nm_enum:
|
||||
PlaneSetHint(plane, tp);
|
||||
if (plane != (Plane *)NULL) PlaneSetHint(plane, tp);
|
||||
if (SigInterruptPending)
|
||||
return (1);
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 893 B After Width: | Height: | Size: 991 B |
|
|
@ -36,6 +36,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "utils/signals.h"
|
||||
#include "utils/maxrect.h"
|
||||
#include "utils/malloc.h"
|
||||
#include "textio/textio.h"
|
||||
|
||||
int dbDRCDebug = 0;
|
||||
|
||||
|
|
@ -284,12 +285,53 @@ areaCheck(tile, arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* areaNMReject ---
|
||||
*
|
||||
* Trivial callback function used by areaNMCheck to see if a tile
|
||||
* found in the error area of a reverse non-manhattan check exists
|
||||
* only on the other side of the original check boundary. If it
|
||||
* is found in this search, return 1 to immediately stop the search.
|
||||
*
|
||||
* Results:
|
||||
* Returns 1 if the tile indicated in the ClientData argument was
|
||||
* found in the check area, otherwise return 0 to keep looking.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
areaNMReject(tile, arg)
|
||||
Tile *tile;
|
||||
ClientData *arg;
|
||||
{
|
||||
Tile *checktile = (Tile *)arg;
|
||||
|
||||
if (tile == checktile)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* areaNMCheck ---
|
||||
*
|
||||
* Check for errors in triangular area of a tile
|
||||
* Check for errors in triangular area of a tile.
|
||||
*
|
||||
* Results:
|
||||
* Return 0 always to keep the search going.
|
||||
*
|
||||
* Side effects:
|
||||
* If the tile is not rejected due to being outside of the various
|
||||
* clip areas, then call the function specified in the drcClientData
|
||||
* argument.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
@ -320,6 +362,24 @@ areaNMCheck(tile, arg)
|
|||
if ((rect.r_xbot >= rect.r_xtop) || (rect.r_ybot >= rect.r_ytop))
|
||||
return 0;
|
||||
|
||||
if (arg->dCD_entries & TT_DIAGONAL)
|
||||
{
|
||||
TileTypeBitMask mask;
|
||||
int dinfo = arg->dCD_entries;
|
||||
|
||||
/* In the DRC_REVERSE case, the area being searched extends
|
||||
* behind the edge that triggered the DRC check, but any
|
||||
* tile that is outside that edge should be ignored. This
|
||||
* requires a separate check.
|
||||
*/
|
||||
|
||||
TTMaskSetOnlyType(&mask, TiGetLeftType(tile));
|
||||
TTMaskSetType(&mask, TiGetRightType(tile));
|
||||
if (DBSrPaintNMArea((Tile *)tile, (Plane *)NULL, dinfo, arg->dCD_rlist,
|
||||
&mask, areaNMReject, (ClientData)tile) == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
(*(arg->dCD_function))(arg->dCD_celldef, &rect, arg->dCD_cptr,
|
||||
arg->dCD_clientData);
|
||||
(*(arg->dCD_errors))++;
|
||||
|
|
@ -556,6 +616,20 @@ drcTile (tile, arg)
|
|||
dinfo |= TT_SIDE;
|
||||
}
|
||||
|
||||
/* The area to check is bounded between the diagonals of
|
||||
* tile and errRect (which is the tile area, offset).
|
||||
* Pass errRect and dinfo to areaNMCheck using the
|
||||
* ClientData structure arg->dCD_rlist and arg->dCD_entries,
|
||||
* which are not used by areaNMCheck.
|
||||
*/
|
||||
arg->dCD_rlist = (Rect *)mallocMagic(sizeof(Rect));
|
||||
*(arg->dCD_rlist) = errRect;
|
||||
arg->dCD_entries = dinfo;
|
||||
if (dinfo & TT_SIDE)
|
||||
arg->dCD_entries &= ~TT_SIDE;
|
||||
else
|
||||
arg->dCD_entries |= TT_SIDE;
|
||||
|
||||
/* errRect is the tile area offset by (deltax, deltay) */
|
||||
errRect.r_xbot += deltax;
|
||||
errRect.r_ybot += deltay;
|
||||
|
|
@ -565,6 +639,10 @@ drcTile (tile, arg)
|
|||
DBSrPaintNMArea((Tile *) NULL,
|
||||
arg->dCD_celldef->cd_planes[cptr->drcc_plane], dinfo,
|
||||
&errRect, &tmpMask, areaNMCheck, (ClientData) arg);
|
||||
|
||||
arg->dCD_entries = 0;
|
||||
freeMagic(arg->dCD_rlist);
|
||||
arg->dCD_rlist = (Rect *)NULL;
|
||||
}
|
||||
DRCstatEdges++;
|
||||
}
|
||||
|
|
@ -1135,7 +1213,7 @@ drcTile (tile, arg)
|
|||
lr = &mrd->rlist[i];
|
||||
GeoClip(lr, arg->dCD_clip);
|
||||
if (!GEO_RECTNULL(lr))
|
||||
{
|
||||
{
|
||||
(*(arg->dCD_function)) (arg->dCD_celldef,
|
||||
lr, cptr, arg->dCD_clientData);
|
||||
(*(arg->dCD_errors))++;
|
||||
|
|
|
|||
|
|
@ -203,13 +203,12 @@ DRCCheckThis (celldef, operation, area)
|
|||
/* Insert celldef into list of Defs waiting to be checked, unless */
|
||||
/* it is already there. */
|
||||
|
||||
#if (0)
|
||||
|
||||
/* The switch to copying up DRC errors from non-interacting */
|
||||
/* child cells means that the child cells must be processed */
|
||||
/* first. So this routine changes from prepending the cell */
|
||||
/* to the list to appending it. */
|
||||
|
||||
#if (0)
|
||||
pback = &DRCPendingRoot;
|
||||
p = DRCPendingRoot;
|
||||
|
||||
|
|
@ -230,8 +229,8 @@ DRCCheckThis (celldef, operation, area)
|
|||
}
|
||||
p->dpc_next = DRCPendingRoot;
|
||||
DRCPendingRoot = p;
|
||||
|
||||
#endif
|
||||
|
||||
/* Append new cell to check to the pending list */
|
||||
if (DRCPendingRoot == NULL)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -449,6 +449,31 @@ drcCheckRectSize(starttile, arg, cptr)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
* MaxRectsExclude ---
|
||||
*
|
||||
* Trivial callback function which detects if a type is found
|
||||
* overlapping a Maxrects area.
|
||||
*
|
||||
* Results:
|
||||
* Always return 1 to immediately halt the search.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
MaxRectsExclude(
|
||||
Tile *tile,
|
||||
ClientData clientdata)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -563,10 +588,31 @@ drcCanonicalMaxwidth(starttile, dir, arg, cptr)
|
|||
mrd->maxdist = edgelimit;
|
||||
TTMaskCom2(&wrongtypes, &cptr->drcc_mask);
|
||||
boundorig = *boundrect;
|
||||
DBSrPaintArea(starttile, arg->dCD_celldef->cd_planes[cptr->drcc_plane],
|
||||
DBSrPaintArea(starttile, arg->dCD_celldef->cd_planes[cptr->drcc_edgeplane],
|
||||
&boundorig, &wrongtypes, FindMaxRects, mrd);
|
||||
if (mrd->entries == 0)
|
||||
return NULL;
|
||||
else if (cptr->drcc_plane != cptr->drcc_edgeplane)
|
||||
{
|
||||
/* If the "exclude" option is used, then the maxrect rule will be
|
||||
* ignored for any metal area partially or totally covered by any
|
||||
* type in cptr->drcc_corner on plane cptr->drcc_plane (!=
|
||||
* cptr->drcc_edgeplane).
|
||||
*/
|
||||
for (s = 0; s < mrd->entries; s++)
|
||||
{
|
||||
Rect *r = &(mrd->rlist[s]);
|
||||
if (DBSrPaintArea((Tile *)NULL,
|
||||
arg->dCD_celldef->cd_planes[cptr->drcc_plane],
|
||||
r, &cptr->drcc_corner, MaxRectsExclude, NULL) != 0)
|
||||
{
|
||||
/* Take this area out of consideration */
|
||||
r->r_xtop = r->r_xbot;
|
||||
r->r_ytop = r->r_ybot;
|
||||
}
|
||||
}
|
||||
return (MaxRectsData *)mrd;
|
||||
}
|
||||
else
|
||||
return (MaxRectsData *)mrd;
|
||||
}
|
||||
|
|
|
|||
141
drc/DRCmain.c
141
drc/DRCmain.c
|
|
@ -277,20 +277,50 @@ drcPrintError (celldef, rect, cptr, scx)
|
|||
{
|
||||
HashEntry *h;
|
||||
int i;
|
||||
Rect *area, r;
|
||||
Rect *area;
|
||||
int drcsave = DRCErrorCount;
|
||||
|
||||
/* Forward declaration */
|
||||
void drcWhyFunc(SearchContext *scx, ClientData cdarg);
|
||||
|
||||
ASSERT (cptr != (DRCCookie *) NULL, "drcPrintError");
|
||||
|
||||
area = &scx->scx_area;
|
||||
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
|
||||
|
||||
i = DRCErrorList[cptr->drcc_tag];
|
||||
if (i == 0)
|
||||
TxPrintf("%s\n", drcSubstitute(cptr));
|
||||
if (i >= 0)
|
||||
if (cptr->drcc_tag == DRC_IN_SUBCELL_TAG)
|
||||
{
|
||||
DRCErrorCount += 1;
|
||||
DRCErrorList[cptr->drcc_tag] = i + 1;
|
||||
SearchContext newscx;
|
||||
|
||||
/* Recurse into subcells to find the error being flagged */
|
||||
/* recursive call is drcWhyFunc, clientdata is FALSE */
|
||||
|
||||
newscx.scx_area = *rect;
|
||||
newscx.scx_use = scx->scx_use;
|
||||
newscx.scx_x = scx->scx_use->cu_xlo;
|
||||
newscx.scx_y = scx->scx_use->cu_ylo;
|
||||
newscx.scx_trans = scx->scx_trans;
|
||||
|
||||
DBTreeSrCells(&newscx, 0, drcWhyFunc, (ClientData)FALSE);
|
||||
}
|
||||
/* Hack to avoid printing "no errors found" when recursing on
|
||||
* drcWhyFunc() above. In some cases like run-length rules,
|
||||
* changing the search area can make the error disappear. If
|
||||
* that happens, "See error definition in subcell" will be
|
||||
* printed. The underlying error needs to be fixed, but this
|
||||
* method provides the information the user needs to find the
|
||||
* error.
|
||||
*/
|
||||
if (drcsave == DRCErrorCount)
|
||||
{
|
||||
i = DRCErrorList[cptr->drcc_tag];
|
||||
if (i == 0)
|
||||
TxPrintf("%s\n", drcSubstitute(cptr));
|
||||
if (i >= 0)
|
||||
{
|
||||
DRCErrorCount += 1;
|
||||
DRCErrorList[cptr->drcc_tag] = i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -309,24 +339,47 @@ drcListError (celldef, rect, cptr, scx)
|
|||
HashEntry *h;
|
||||
int i;
|
||||
Rect *area;
|
||||
int drcsave = DRCErrorCount;
|
||||
|
||||
/* Forward declaration */
|
||||
void drcWhyFunc(SearchContext *scx, ClientData cdarg);
|
||||
|
||||
ASSERT (cptr != (DRCCookie *) NULL, "drcListError");
|
||||
|
||||
area = &scx->scx_area;
|
||||
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
|
||||
i = DRCErrorList[cptr->drcc_tag];
|
||||
if (i == 0)
|
||||
|
||||
if (cptr->drcc_tag == DRC_IN_SUBCELL_TAG)
|
||||
{
|
||||
Tcl_Obj *lobj;
|
||||
lobj = Tcl_GetObjResult(magicinterp);
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||
Tcl_NewStringObj(drcSubstitute(cptr), -1));
|
||||
Tcl_SetObjResult(magicinterp, lobj);
|
||||
SearchContext newscx;
|
||||
|
||||
/* Recurse into subcells to find the error being flagged */
|
||||
/* recursive call is drcWhyFunc, clientdata is TRUE */
|
||||
|
||||
newscx.scx_area = *rect;
|
||||
newscx.scx_use = scx->scx_use;
|
||||
newscx.scx_x = scx->scx_use->cu_xlo;
|
||||
newscx.scx_y = scx->scx_use->cu_ylo;
|
||||
newscx.scx_trans = scx->scx_trans;
|
||||
|
||||
DBTreeSrCells(&newscx, 0, drcWhyFunc, (ClientData)TRUE);
|
||||
}
|
||||
if (i >= 0)
|
||||
if (drcsave == DRCErrorCount)
|
||||
{
|
||||
DRCErrorCount += 1;
|
||||
DRCErrorList[cptr->drcc_tag] = i + 1;
|
||||
i = DRCErrorList[cptr->drcc_tag];
|
||||
if (i == 0)
|
||||
{
|
||||
Tcl_Obj *lobj;
|
||||
lobj = Tcl_GetObjResult(magicinterp);
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||
Tcl_NewStringObj(drcSubstitute(cptr), -1));
|
||||
Tcl_SetObjResult(magicinterp, lobj);
|
||||
}
|
||||
if (i >= 0)
|
||||
{
|
||||
DRCErrorCount += 1;
|
||||
DRCErrorList[cptr->drcc_tag] = i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -343,6 +396,10 @@ drcListallError (celldef, rect, cptr, scx)
|
|||
Tcl_Obj *lobj, *pobj;
|
||||
HashEntry *h;
|
||||
Rect *area, r;
|
||||
int drcsave = DRCErrorCount;
|
||||
|
||||
/* Forward declaration */
|
||||
int drcWhyAllFunc(SearchContext *scx, ClientData cdarg);
|
||||
|
||||
ASSERT (cptr != (DRCCookie *) NULL, "drcListallError");
|
||||
|
||||
|
|
@ -350,21 +407,40 @@ drcListallError (celldef, rect, cptr, scx)
|
|||
GeoTransRect(&scx->scx_trans, rect, &r);
|
||||
area = &scx->scx_area;
|
||||
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
|
||||
DRCErrorCount += 1;
|
||||
h = HashFind(&DRCErrorTable, drcSubstitute(cptr));
|
||||
lobj = (Tcl_Obj *) HashGetValue(h);
|
||||
if (lobj == NULL)
|
||||
lobj = Tcl_NewListObj(0, NULL);
|
||||
|
||||
pobj = Tcl_NewListObj(0, NULL);
|
||||
if (cptr->drcc_tag == DRC_IN_SUBCELL_TAG)
|
||||
{
|
||||
SearchContext newscx;
|
||||
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_xbot));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_ybot));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_xtop));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_ytop));
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
|
||||
/* Recurse into subcells to find the error being flagged */
|
||||
/* recursive call is drcWhyAllFunc, clientdata is NULL */
|
||||
|
||||
newscx.scx_area = *rect;
|
||||
newscx.scx_use = scx->scx_use;
|
||||
newscx.scx_x = scx->scx_use->cu_xlo;
|
||||
newscx.scx_y = scx->scx_use->cu_ylo;
|
||||
newscx.scx_trans = scx->scx_trans;
|
||||
|
||||
HashSetValue(h, lobj);
|
||||
DBTreeSrCells(&newscx, 0, drcWhyAllFunc, (ClientData)NULL);
|
||||
}
|
||||
if (drcsave == DRCErrorCount)
|
||||
{
|
||||
DRCErrorCount += 1;
|
||||
h = HashFind(&DRCErrorTable, drcSubstitute(cptr));
|
||||
lobj = (Tcl_Obj *) HashGetValue(h);
|
||||
if (lobj == NULL)
|
||||
lobj = Tcl_NewListObj(0, NULL);
|
||||
|
||||
pobj = Tcl_NewListObj(0, NULL);
|
||||
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_xbot));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_ybot));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_xtop));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_ytop));
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
|
||||
|
||||
HashSetValue(h, lobj);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
@ -737,11 +813,12 @@ drcCheckFunc(scx, cdarg)
|
|||
DBStdPaintTbl(TT_CHECKPAINT, PL_DRC_CHECK),
|
||||
(PaintUndoInfo *) NULL);
|
||||
|
||||
DRCCheckThis(def, TT_CHECKPAINT, (Rect *) NULL);
|
||||
|
||||
/* Search children */
|
||||
/* Search children and apply recursively */
|
||||
(void) DBCellSrArea(scx, drcCheckFunc, (ClientData) NULL);
|
||||
|
||||
/* Then do self */
|
||||
DRCCheckThis(def, TT_CHECKPAINT, (Rect *) NULL);
|
||||
|
||||
/* As a special performance hack, if the complete cell area is
|
||||
* handled here, don't bother to look at any more array elements.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -734,9 +734,9 @@ DRCInteractionCheck(def, area, erasebox, func, cdarg)
|
|||
* square separately.
|
||||
*/
|
||||
|
||||
x = (area->r_xbot/DRCStepSize) * DRCStepSize;
|
||||
x = (area->r_xbot/DRCStepSize) * DRCStepSize - (DRCStepSize / 2);
|
||||
if (x > area->r_xbot) x -= DRCStepSize;
|
||||
y = (area->r_ybot/DRCStepSize) * DRCStepSize;
|
||||
y = (area->r_ybot/DRCStepSize) * DRCStepSize - (DRCStepSize / 2);
|
||||
if (y > area->r_ybot) y -= DRCStepSize;
|
||||
for (square.r_xbot = x; square.r_xbot < area->r_xtop;
|
||||
square.r_xbot += DRCStepSize)
|
||||
|
|
|
|||
|
|
@ -1061,7 +1061,7 @@ DRCTechAddRule(sectionName, argc, argv)
|
|||
"layers area horizon why"},
|
||||
{"off_grid", 4, 4, drcOffGrid,
|
||||
"layers pitch why"},
|
||||
{"maxwidth", 4, 5, drcMaxwidth,
|
||||
{"maxwidth", 4, 6, drcMaxwidth,
|
||||
"layers maxwidth bends why"},
|
||||
{"cifstyle", 2, 2, drcCifSetStyle,
|
||||
"cif_style"},
|
||||
|
|
@ -1582,7 +1582,7 @@ drcOffGrid(argc, argv)
|
|||
* Process a maxwidth rule.
|
||||
* This is of the form:
|
||||
*
|
||||
* maxwidth layers distance [bends] why
|
||||
* maxwidth layers distance [bends] [exclude_layers] why
|
||||
*
|
||||
* This routine was updated 3/6/05 to match the "canonical" definition of
|
||||
* a maxwidth region, which is any rectangle containing <layers> that is
|
||||
|
|
@ -1591,6 +1591,11 @@ drcOffGrid(argc, argv)
|
|||
* (see below) for backwards-compatibility. Otherwise ("bend_ok" or
|
||||
* nothing), the new routine is used.
|
||||
*
|
||||
* exclude_layers is optional and indicates a type or types (which if more
|
||||
* than one must all be on the same plane) that prevent "maxwidth" from
|
||||
* being checked. A common use case is using "glass" (passivation cut) to
|
||||
* exclude top metal on a pad from being checked for maximum metal width.
|
||||
*
|
||||
* maxwidth metal1 389 "metal1 width > 35um must be slotted"
|
||||
* maxwidth pmc 4 bend_illegal "poly contact area must be no wider than 4"
|
||||
* maxwidth trench 4 bend_ok "trench width must be exactly 4"
|
||||
|
|
@ -1629,11 +1634,11 @@ drcMaxwidth(argc, argv)
|
|||
int distance = atoi(argv[2]);
|
||||
char *bends = argv[3];
|
||||
int why;
|
||||
TileTypeBitMask set, setC;
|
||||
TileTypeBitMask set, setC, setE;
|
||||
DRCCookie *dp, *dpnew;
|
||||
TileType i, j;
|
||||
PlaneMask pmask, ptest, pset;
|
||||
int plane;
|
||||
PlaneMask pmask, pmask2, ptest, pset;
|
||||
int plane, plane2;
|
||||
int bend;
|
||||
|
||||
ptest = DBTechNoisyNameMask(layers, &set);
|
||||
|
|
@ -1667,8 +1672,34 @@ drcMaxwidth(argc, argv)
|
|||
TechError("unknown bend option %s\n",bends);
|
||||
return (0);
|
||||
}
|
||||
why = drcWhyCreate(argv[4]);
|
||||
if (argc == 6)
|
||||
why = drcWhyCreate(argv[5]);
|
||||
else
|
||||
why = drcWhyCreate(argv[4]);
|
||||
}
|
||||
if (argc == 6)
|
||||
{
|
||||
ptest = DBTechNoisyNameMask(argv[4], &setE);
|
||||
pmask2 = CoincidentPlanes(&setE, ptest);
|
||||
if (pmask2 == 0)
|
||||
{
|
||||
TechError("All layers for \"maxwidth\" exclude types must "
|
||||
"be on same plane.\n");
|
||||
return (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (plane2 = PL_TECHDEPBASE; plane2 < DBNumPlanes; plane2++)
|
||||
if (PlaneMaskHasPlane(pmask2, plane2))
|
||||
break;
|
||||
|
||||
if (plane2 == plane)
|
||||
TechError("Warning: Exclude types for \"maxwidth\" are on the "
|
||||
"same plane and so cannot be checked.\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
plane2 = -1;
|
||||
|
||||
for (i = 0; i < DBNumTypes; i++)
|
||||
{
|
||||
|
|
@ -1689,8 +1720,12 @@ drcMaxwidth(argc, argv)
|
|||
/* find bucket preceding the new one we wish to insert */
|
||||
dp = drcFindBucket(i, j, distance);
|
||||
dpnew = (DRCCookie *) mallocMagic(sizeof (DRCCookie));
|
||||
drcAssign(dpnew, distance, dp->drcc_next, &set, &set, why,
|
||||
if (plane2 == -1)
|
||||
drcAssign(dpnew, distance, dp->drcc_next, &set, &set, why,
|
||||
distance, DRC_MAXWIDTH | bend, plane, plane);
|
||||
else
|
||||
drcAssign(dpnew, distance, dp->drcc_next, &set, &setE, why,
|
||||
distance, DRC_MAXWIDTH | bend, plane2, plane);
|
||||
|
||||
dp->drcc_next = dpnew;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1116,6 +1116,7 @@ simdevVisit(
|
|||
break;
|
||||
case DEV_MSUBCKT:
|
||||
case DEV_CSUBCKT:
|
||||
case DEV_DSUBCKT:
|
||||
case DEV_RSUBCKT:
|
||||
case DEV_SUBCKT:
|
||||
/* Use the 'x' type in .sim format. This is implemented in the */
|
||||
|
|
|
|||
|
|
@ -2041,7 +2041,7 @@ topVisit(
|
|||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
bool
|
||||
void
|
||||
spcWriteValue(
|
||||
Dev *dev, /* Dev being output */
|
||||
HierName *hierName) /* Hierarchical path down to this dev */
|
||||
|
|
|
|||
|
|
@ -198,9 +198,10 @@ ResReadSim(simfile, fetproc, capproc, resproc, attrproc, mergeproc, subproc)
|
|||
result = 1;
|
||||
break;
|
||||
}
|
||||
if (fettype == -1)
|
||||
if ((fettype != MINFINITY) && (fettype < 0))
|
||||
{
|
||||
TxError("Error in Reading device line of sim file.\n");
|
||||
TxError("Error in Reading device line of sim file: ");
|
||||
TxError("Ambiguous or unknown device.\n");
|
||||
result = 1;
|
||||
}
|
||||
else if (fettype == DBNumTypes)
|
||||
|
|
|
|||
|
|
@ -893,6 +893,7 @@ proc magic::gencell_change {instname gencell_type library parameters} {
|
|||
}
|
||||
|
||||
resumeall
|
||||
drc check ;# force a DRC update if DRC is on.
|
||||
redraw
|
||||
}
|
||||
|
||||
|
|
@ -1153,7 +1154,10 @@ proc magic::add_entry {pname ptext parameters} {
|
|||
|
||||
#----------------------------------------------------------
|
||||
# Default entry callback, without any dependencies. Each
|
||||
# parameter changed
|
||||
# parameter changed causes an update to the dialog. Also
|
||||
# add default callbacks on checkboxes and choice menus,
|
||||
# using a null function which does not get executed, but
|
||||
# the dialog gets updated afterward.
|
||||
#----------------------------------------------------------
|
||||
|
||||
proc magic::add_check_callbacks {gencell_type library} {
|
||||
|
|
@ -1166,6 +1170,12 @@ proc magic::add_check_callbacks {gencell_type library} {
|
|||
bind $w <FocusOut> \
|
||||
"magic::update_dialog {} $pname $gencell_type $library"
|
||||
}
|
||||
if {[regexp {\.params\.body\.area\.edits\.(.+)_sel} $w valid pname]} {
|
||||
magic::add_dependency \{\} $gencell_type $library $pname
|
||||
}
|
||||
if {[regexp {\.params\.body\.area\.edits\.(.+)_chk} $w valid pname]} {
|
||||
magic::add_dependency \{\} $gencell_type $library $pname
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
105
textio/txInput.c
105
textio/txInput.c
|
|
@ -1225,36 +1225,29 @@ TxGetLine(
|
|||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#if defined(SYSV) || defined(CYGWIN)
|
||||
|
||||
void
|
||||
txGetTermState(
|
||||
struct termio *buf)
|
||||
{
|
||||
ioctl( fileno( stdin ), TCGETA, buf);
|
||||
}
|
||||
|
||||
#elif defined (__OpenBSD__) || defined(EMSCRIPTEN)
|
||||
|
||||
void
|
||||
txGetTermState(
|
||||
struct termios *buf)
|
||||
{
|
||||
(void) tcgetattr(fileno(stdin), buf);
|
||||
}
|
||||
|
||||
#if defined(HAVE_TERMIOS_H)
|
||||
struct termios *buf
|
||||
#elif defined(HAVE_TERMIO_H)
|
||||
struct termio *buf
|
||||
#else
|
||||
|
||||
void
|
||||
txGetTermState(
|
||||
txTermState *buf)
|
||||
txTermState *buf
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#if defined(HAVE_TERMIOS_H) /* POSIX */
|
||||
(void) tcgetattr(fileno(stdin), buf);
|
||||
#elif defined(HAVE_TERMIO_H) /* SYSV */
|
||||
ioctl( fileno( stdin ), TCGETA, buf);
|
||||
#else /* fallback to sgtty-style */
|
||||
ASSERT(TxStdinIsatty, "txGetTermState");
|
||||
/* save the current terminal characteristics */
|
||||
(void) ioctl(fileno(stdin), TIOCGETP, (char *) &(buf->tx_i_sgtty) );
|
||||
(void) ioctl(fileno(stdin), TIOCGETC, (char *) &(buf->tx_i_tchars) );
|
||||
#endif
|
||||
}
|
||||
#endif /* SYSV */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -1273,24 +1266,24 @@ txGetTermState(
|
|||
|
||||
void
|
||||
txSetTermState(
|
||||
#if defined(SYSV) || defined(CYGWIN)
|
||||
struct termio *buf
|
||||
#elif defined (__OpenBSD__) || defined(EMSCRIPTEN)
|
||||
#if defined(HAVE_TERMIOS_H)
|
||||
struct termios *buf
|
||||
#elif defined(HAVE_TERMIO_H)
|
||||
struct termio *buf
|
||||
#else
|
||||
txTermState *buf
|
||||
#endif /* SYSV */
|
||||
)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#if defined(SYSV) || defined(CYGWIN)
|
||||
ioctl( fileno(stdin), TCSETAF, buf );
|
||||
#elif defined (__OpenBSD__) || defined(EMSCRIPTEN)
|
||||
#if defined(HAVE_TERMIOS_H) /* POSIX */
|
||||
(void) tcsetattr( fileno(stdin), TCSANOW, buf );
|
||||
#else
|
||||
#elif defined(HAVE_TERMIO_H) /* SYSV */
|
||||
ioctl( fileno(stdin), TCSETAF, buf );
|
||||
#else /* fallback to sgtty-style */
|
||||
/* set the current terminal characteristics */
|
||||
(void) ioctl(fileno(stdin), TIOCSETN, (char *) &(buf->tx_i_sgtty) );
|
||||
(void) ioctl(fileno(stdin), TIOCSETC, (char *) &(buf->tx_i_tchars) );
|
||||
#endif /* SYSV */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1313,37 +1306,36 @@ txSetTermState(
|
|||
|
||||
void
|
||||
txInitTermRec(
|
||||
#if defined(SYSV) || defined(CYGWIN)
|
||||
struct termio *buf
|
||||
#elif defined (__OpenBSD__) || defined(EMSCRIPTEN)
|
||||
#if defined(HAVE_TERMIOS_H)
|
||||
struct termios *buf
|
||||
#elif defined(HAVE_TERMIO_H)
|
||||
struct termio *buf
|
||||
#else
|
||||
txTermState *buf
|
||||
#endif /* SYSV */
|
||||
)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#if defined(SYSV) || defined(CYGWIN) || defined(__OpenBSD__) || defined(EMSCRIPTEN)
|
||||
#if defined(HAVE_TERMIOS_H) || defined(HAVE_TERMIO_H)
|
||||
buf->c_lflag = ISIG; /* raw: no echo and no processing, allow signals */
|
||||
buf->c_cc[ VMIN ] = 1;
|
||||
buf->c_cc[ VTIME ] = 0;
|
||||
#else
|
||||
#else /* sgtty-style interface */
|
||||
/* set things up for us, turn off echo, turn on cbreak, no EOF */
|
||||
buf->tx_i_sgtty.sg_flags |= CBREAK;
|
||||
buf->tx_i_sgtty.sg_flags &= ~ECHO;
|
||||
buf->tx_i_tchars.t_eofc = -1;
|
||||
|
||||
#endif /* SYSV */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if defined(SYSV) || defined(CYGWIN)
|
||||
struct termio closeTermState;
|
||||
#elif defined (__OpenBSD__) || defined(EMSCRIPTEN)
|
||||
#if defined(HAVE_TERMIOS_H)
|
||||
struct termios closeTermState;
|
||||
#elif defined(HAVE_TERMIO_H)
|
||||
struct termio closeTermState;
|
||||
#else
|
||||
static txTermState closeTermState;
|
||||
#endif /* SYSV */
|
||||
#endif
|
||||
|
||||
static bool haveCloseState = FALSE;
|
||||
|
||||
|
|
@ -1366,21 +1358,18 @@ static bool haveCloseState = FALSE;
|
|||
void
|
||||
txSaveTerm(void)
|
||||
{
|
||||
#if defined(SYSV) || defined(CYGWIN)
|
||||
ioctl( fileno( stdin ), TCGETA, &closeTermState);
|
||||
txEraseChar = closeTermState.c_cc[VERASE];
|
||||
txKillChar = closeTermState.c_cc[VKILL];
|
||||
TxEOFChar = closeTermState.c_cc[VEOF];
|
||||
TxInterruptChar = closeTermState.c_cc[VINTR];
|
||||
haveCloseState = TRUE;
|
||||
#elif defined (__OpenBSD__) || defined(EMSCRIPTEN)
|
||||
#if defined(HAVE_TERMIOS_H) || defined(HAVE_TERMIO_H)
|
||||
# if defined(HAVE_TERMIOS_H)
|
||||
(void) tcgetattr( fileno( stdin ), &closeTermState);
|
||||
# else /* HAVE_TERMIO_H */
|
||||
ioctl( fileno( stdin ), TCGETA, &closeTermState);
|
||||
# endif /* HAVE_TERMIOS_H || HAVE_TERMIO_H */
|
||||
txEraseChar = closeTermState.c_cc[VERASE];
|
||||
txKillChar = closeTermState.c_cc[VKILL];
|
||||
TxEOFChar = closeTermState.c_cc[VEOF];
|
||||
TxInterruptChar = closeTermState.c_cc[VINTR];
|
||||
haveCloseState = TRUE;
|
||||
#else
|
||||
#else /* sgtty-style interface */
|
||||
struct ltchars lt;
|
||||
txGetTermState(&closeTermState);
|
||||
(void) ioctl(fileno(stdin), TIOCGLTC, (char *) <);
|
||||
|
|
@ -1393,7 +1382,7 @@ txSaveTerm(void)
|
|||
TxEOFChar = closeTermState.tx_i_tchars.t_eofc;
|
||||
TxInterruptChar = closeTermState.tx_i_tchars.t_intrc;
|
||||
haveCloseState = TRUE;
|
||||
#endif /* SYSV */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1414,13 +1403,13 @@ txSaveTerm(void)
|
|||
void
|
||||
TxSetTerminal(void)
|
||||
{
|
||||
#if defined(SYSV) || defined(CYGWIN)
|
||||
struct termio buf;
|
||||
#elif defined (__OpenBSD__) || defined(EMSCRIPTEN)
|
||||
#if defined(HAVE_TERMIOS_H)
|
||||
struct termios buf;
|
||||
#elif defined(HAVE_TERMIO_H)
|
||||
struct termio buf;
|
||||
#else
|
||||
txTermState buf;
|
||||
#endif /* SYSV */
|
||||
#endif
|
||||
|
||||
#ifdef MAGIC_WRAPPER
|
||||
/* If using Tk console, don't mess with the terminal settings; */
|
||||
|
|
|
|||
|
|
@ -21,44 +21,18 @@
|
|||
#ifndef _MAGIC__UTILS__MAGSGTTY_H
|
||||
#define _MAGIC__UTILS__MAGSGTTY_H
|
||||
|
||||
/* maybe this can be #ifndef HAVE_TERMIO_H */
|
||||
#if !defined(SYSV) && !defined(CYGWIN)
|
||||
|
||||
# ifdef ALPHA
|
||||
# undef MAX
|
||||
# undef MIN
|
||||
#if defined(HAVE_TERMIOS_H) /* POSIX */
|
||||
# include <termios.h>
|
||||
#elif defined(HAVE_TERMIO_H) /* SYSV */
|
||||
# include <termio.h>
|
||||
# include <sys/ioctl.h>
|
||||
#else /* Fallback for older BSD/V7 systems */
|
||||
# if defined(HAVE_SGTTY_H)
|
||||
# include <sgtty.h>
|
||||
# elif defined(HAVE_SYS_IOCTL_COMPAT_H)
|
||||
# include <sys/ioctl_compat.h>
|
||||
# endif
|
||||
|
||||
/* unclear what platform requires this OpenBSD/FreeBSD ? */
|
||||
# ifndef COMPAT_43TTY
|
||||
# define COMPAT_43TTY
|
||||
# endif
|
||||
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
# include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_TERMIOS_H)
|
||||
#include <termios.h>
|
||||
#elif defined(HAVE_SYS_IOCTL_COMPAT_H)
|
||||
/* unclear which platform(s) require <sys/ioctl_compat.h> and the structure
|
||||
* of this file is such that it will try to include it by default, better
|
||||
* to invert the #if and only select this on the known platforms that need
|
||||
* it so that <termios.h> goes by default, which exists on MacOSX, Linux, etc..
|
||||
* many possible solutions to make this work by default:
|
||||
* HAVE_SYS_IOCTL_COMPAT_H ? HAVE_TERMIOS_H ? !defined(linux) at top (MaxOSX is BSD type)
|
||||
*/
|
||||
#include <sys/ioctl_compat.h> /* replaced sgtty.h */
|
||||
#elif defined(HAVE_SGTTY_H)
|
||||
#include <sgtty.h> /* legacy - struct sgttyb{} defn */
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#if defined(HAVE_TERMIO_H)
|
||||
#include <termio.h>
|
||||
#endif
|
||||
|
||||
#endif /* !SYSV && !CYGWIN */
|
||||
|
||||
#endif /* _MAGIC__UTILS__MAGSGTTY_H */
|
||||
|
|
|
|||
|
|
@ -1124,13 +1124,17 @@ windDoMacro(w, cmd, interactive)
|
|||
/* next argument looks like a key, which would indicate */
|
||||
/* an unregistered client as the first argument. A */
|
||||
/* macro retrieved from an unregistered client returns */
|
||||
/* nothing but does not generate an error. */
|
||||
/* nothing but does not generate an error. This allows */
|
||||
/* the default macro set to declare macros for, e.g., the */
|
||||
/* wind3d client and fail quietly if magic was compiled */
|
||||
/* without OpenGL support. */
|
||||
|
||||
if (MacroKey(cmd->tx_argv[argstart], &verbose) == 0)
|
||||
if (MacroKey(cmd->tx_argv[argstart + 1], &verbose) != 0)
|
||||
{
|
||||
wc = 0;
|
||||
argstart++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1139,6 +1143,11 @@ windDoMacro(w, cmd, interactive)
|
|||
|
||||
if (cmd->tx_argc == argstart)
|
||||
{
|
||||
if (wc == (WindClient)0)
|
||||
{
|
||||
TxError("No such client.\n");
|
||||
return;
|
||||
}
|
||||
h = HashLookOnly(&MacroClients, (char *)wc);
|
||||
if (h == NULL)
|
||||
return;
|
||||
|
|
@ -1302,5 +1311,5 @@ windDoMacro(w, cmd, interactive)
|
|||
return;
|
||||
}
|
||||
|
||||
TxError("Usage: %s [macro_name [string] [help_text]]\n", cmd->tx_argv[0]);
|
||||
TxError("Usage: %s [client] [macro_name [string] [help_text]]\n", cmd->tx_argv[0]);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue