Compare commits

...

7 Commits

Author SHA1 Message Date
Darryl Miles 1aec37a369
Merge ceedfc1b07 into 246c0ea7a4 2025-10-31 07:33:43 +00:00
R. Timothy Edwards 246c0ea7a4 Extended the "maxwidth" DRC rule to take an optional set of layers
that exclude the maxwidth rule from taking effect.  This is
especially useful for implementing a maxwidth rule on top metal
that does not apply to pads, using the passivation cut layer to
prevent the maxwidth rule from being applied.
2025-10-30 16:39:54 -04:00
R. Timothy Edwards 47778971ee And one more fix to the method, for which I added a variation of
DBNMSrPaintPlane() where if "tile" is non-NULL then "plane" can be
NULL;  the hint tile does not get set but the routine can be called
without knowing the plane other than that the tile is in it somewhere.
2025-10-30 13:18:12 -04:00
R. Timothy Edwards cccd79ab0d One correction to the last commit---The additional check is not
limited to the DRC_REVERSE case but must be done in both the
forward and reverse cases.
2025-10-30 12:37:00 -04:00
R. Timothy Edwards 51b9846120 Made a correction to the DRC error checking on a non-Manhattan
edge.  This was catching geometry unrelated to the error when doing
a spacing check between geometry on different planes.  In the
reverse-edge case, magic needed to run an additional search over
the area on the other side of the original edge that triggered
the rule to effectively clip that corner of the triangle from the
search area.
2025-10-30 12:07:29 -04:00
R. Timothy Edwards 1afd48e840 Corrected an error in which an invalid client name passed to the
"macro" command will crash magic.  This will happen if, for
example, magic is compiled without OpenGL support, in which case
the "wind3d" client does not exist, and parsing the default
macros from the system .magicrc file will cause an immediate
crash.
2025-10-29 09:32:03 -04:00
R. Timothy Edwards 99a5a28a3e Added a drc check to the gencell change procedure, as it appears
that otherwise DRC is not re-checked after a gencell update.  It
is not clear to me why checks are not done otherwise.
2025-10-28 15:10:03 -04:00
8 changed files with 183 additions and 14 deletions

View File

@ -1 +1 @@
8.3.568
8.3.571

View File

@ -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

View File

@ -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++;
}

View File

@ -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;
}

View File

@ -1063,7 +1063,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"},
@ -1584,7 +1584,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
@ -1593,6 +1593,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"
@ -1631,11 +1636,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);
@ -1669,8 +1674,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++)
{
@ -1691,8 +1722,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;
}

View File

@ -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
}

View File

@ -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]);
}