diff --git a/VERSION b/VERSION index d96b2377..98a9e086 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.615 +8.3.616 diff --git a/database/DBcellcopy.c b/database/DBcellcopy.c index 3ccb8b0d..6c905650 100644 --- a/database/DBcellcopy.c +++ b/database/DBcellcopy.c @@ -358,6 +358,7 @@ struct propUseDefStruct { CellDef *puds_source; CellDef *puds_dest; Transform *puds_trans; /* Transform from source use to dest */ + Rect *puds_area; /* Clip area in source coordinates */ }; /* @@ -387,11 +388,12 @@ dbCopyMaskHintsFunc(key, proprec, puds) { CellDef *dest = puds->puds_dest; Transform *trans = puds->puds_trans; + Rect *clip = puds->puds_area; PropertyRecord *parentproprec, *newproprec; char *parentprop, *newvalue, *vptr; Rect r, rnew; bool propfound; - int i; + int i, j; if (!strncmp(key, "MASKHINTS_", 10)) { @@ -407,29 +409,33 @@ dbCopyMaskHintsFunc(key, proprec, puds) (proprec->prop_len + parentproprec->prop_len - 2) * sizeof(int)); newproprec->prop_type = PROPERTY_TYPE_DIMENSION; - newproprec->prop_len = proprec->prop_len + parentproprec->prop_len; + newproprec->prop_len = parentproprec->prop_len; } else { newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) + (proprec->prop_len - 2) * sizeof(int)); newproprec->prop_type = PROPERTY_TYPE_DIMENSION; - newproprec->prop_len = proprec->prop_len; + newproprec->prop_len = 0; } - for (i = 0; i < proprec->prop_len; i += 4) + for (i = 0, j = 0; i < proprec->prop_len; i += 4) { r.r_xbot = proprec->prop_value.prop_integer[i]; r.r_ybot = proprec->prop_value.prop_integer[i + 1]; r.r_xtop = proprec->prop_value.prop_integer[i + 2]; r.r_ytop = proprec->prop_value.prop_integer[i + 3]; - - GeoTransRect(trans, &r, &rnew); - - newproprec->prop_value.prop_integer[i] = rnew.r_xbot; - newproprec->prop_value.prop_integer[i + 1] = rnew.r_ybot; - newproprec->prop_value.prop_integer[i + 2] = rnew.r_xtop; - newproprec->prop_value.prop_integer[i + 3] = rnew.r_ytop; + GeoClip(&r, clip); + if (!GEO_RECTNULL(&r)) + { + GeoTransRect(trans, &r, &rnew); + newproprec->prop_value.prop_integer[j] = rnew.r_xbot; + newproprec->prop_value.prop_integer[j + 1] = rnew.r_ybot; + newproprec->prop_value.prop_integer[j + 2] = rnew.r_xtop; + newproprec->prop_value.prop_integer[j + 3] = rnew.r_ytop; + newproprec->prop_len += 4; + j += 4; + } } if (propfound) @@ -474,6 +480,7 @@ DBCellCopyMaskHints(child, parent, transform) puds.puds_source = child->cu_def; puds.puds_dest = parent; puds.puds_trans = transform; + puds.puds_area = (Rect *)&TiPlaneRect; DBPropEnum(child->cu_def, dbCopyMaskHintsFunc, (ClientData)&puds); } @@ -507,6 +514,7 @@ dbFlatCopyMaskHintsFunc(scx, def) puds.puds_source = scx->scx_use->cu_def; puds.puds_dest = def; puds.puds_trans = &scx->scx_trans; + puds.puds_area = &scx->scx_area; DBPropEnum(use->cu_def, dbCopyMaskHintsFunc, (ClientData)&puds); diff --git a/drc/DRCarray.c b/drc/DRCarray.c index 4e48926a..766fc76f 100644 --- a/drc/DRCarray.c +++ b/drc/DRCarray.c @@ -45,7 +45,7 @@ extern int drcArrayYankFunc(), drcArrayOverlapFunc(); static DRCCookie drcArrayCookie = { 0, 0, 0, 0, { {0} }, { {0} }, - 0, 0, 0, + 0, DRC_EXCEPTION_NONE, 0, 0, DRC_ARRAY_OVERLAP_TAG, (DRCCookie *) NULL }; diff --git a/drc/DRCbasic.c b/drc/DRCbasic.c index a7fb088b..521f4170 100644 --- a/drc/DRCbasic.c +++ b/drc/DRCbasic.c @@ -48,7 +48,7 @@ int dbDRCDebug = 0; static DRCCookie drcOverlapCookie = { 0, 0, 0, 0, { {0} }, { {0} }, - 0, 0, 0, + 0, DRC_EXCEPTION_NONE, 0, 0, DRC_OVERLAP_TAG, (DRCCookie *) NULL }; @@ -727,6 +727,59 @@ drcTile (tile, dinfo, arg) for (cptr = DRCCurStyle->DRCRulesTbl[to][tt]; cptr != (DRCCookie *) NULL; cptr = cptr->drcc_next) { + /* Handle rule exceptions and exemptions */ + if (cptr->drcc_exception != (char)DRC_EXCEPTION_NONE) + { + PropertyRecord *proprec; + bool propfound, isinside; + char *name; + char idx = cptr->drcc_exception; + if (idx < 0) idx = -idx - 1; + name = DRCCurStyle->DRCExceptionList[idx]; + + /* Is there any exception area defined? */ + proprec = DBPropGet(arg->dCD_celldef, name, &propfound); + + /* Quickest case: Rule is an exception but there are no + * exception areas. + */ + if ((!propfound) && (cptr->drcc_exception >= 0)) + continue; + + /* If an exception area exists, is the error edge inside? */ + if (propfound) + { + int i; + Rect r, redge; + + redge.r_xbot = redge.r_xtop = edgeX; + redge.r_ybot = edgeBot; + redge.r_ytop = edgeTop; + isinside = FALSE; + for (i = 0; i < proprec->prop_len; i += 4) + { + if ((i + 4) > proprec->prop_len) break; + r.r_xbot = proprec->prop_value.prop_integer[i]; + r.r_ybot = proprec->prop_value.prop_integer[i + 1]; + r.r_xtop = proprec->prop_value.prop_integer[i + 2]; + r.r_ytop = proprec->prop_value.prop_integer[i + 3]; + + if (GEO_OVERLAP(&redge, &r)) + { + isinside = TRUE; + break; + } + } + } + + /* Exemption rules are ignored if the edge is inside + * an exception area. Exception rules are ignored if + * the edge is outside an exception area. + */ + if (isinside && (cptr->drcc_exception < 0)) continue; + if (!isinside && (cptr->drcc_exception >= 0)) continue; + } + /* DRC_ANGLES_90 and DRC_SPLITTILE rules are handled by */ /* the code above for non-Manhattan shapes and do not */ /* need to be processed again. */ @@ -1136,6 +1189,59 @@ drcTile (tile, dinfo, arg) for (cptr = DRCCurStyle->DRCRulesTbl[to][tt]; cptr != (DRCCookie *) NULL; cptr = cptr->drcc_next) { + /* Handle rule exceptions and exemptions */ + if (cptr->drcc_exception != (char)DRC_EXCEPTION_NONE) + { + PropertyRecord *proprec; + bool propfound, isinside; + char *name; + char idx = cptr->drcc_exception; + if (idx < 0) idx = -idx - 1; + name = DRCCurStyle->DRCExceptionList[idx]; + + /* Is there any exception area defined? */ + proprec = DBPropGet(arg->dCD_celldef, name, &propfound); + + /* Quickest case: Rule is an exception but there are no + * exception areas. + */ + if ((!propfound) && (cptr->drcc_exception >= 0)) + continue; + + /* If an exception area exists, is the error edge inside? */ + if (propfound) + { + int i; + Rect r, redge; + + redge.r_ybot = redge.r_ytop = edgeY; + redge.r_xbot = edgeLeft; + redge.r_xtop = edgeRight; + isinside = FALSE; + for (i = 0; i < proprec->prop_len; i += 4) + { + if ((i + 4) > proprec->prop_len) break; + r.r_xbot = proprec->prop_value.prop_integer[i]; + r.r_ybot = proprec->prop_value.prop_integer[i + 1]; + r.r_xtop = proprec->prop_value.prop_integer[i + 2]; + r.r_ytop = proprec->prop_value.prop_integer[i + 3]; + + if (GEO_OVERLAP(&redge, &r)) + { + isinside = TRUE; + break; + } + } + } + + /* Exemption rules are ignored if the edge is inside + * an exception area. Exception rules are ignored if + * the edge is outside an exception area. + */ + if (isinside && (cptr->drcc_exception < 0)) continue; + if (!isinside && (cptr->drcc_exception >= 0)) continue; + } + /* DRC_ANGLES_90 and DRC_SPLITTILE rules are handled by */ /* the code above for non-Manhattan shapes and do not */ /* need to be processed again. */ diff --git a/drc/DRCsubcell.c b/drc/DRCsubcell.c index 73030298..3df40ad7 100644 --- a/drc/DRCsubcell.c +++ b/drc/DRCsubcell.c @@ -52,7 +52,7 @@ static ClientData drcSubClientData; /* To be passed to error function. */ static DRCCookie drcSubcellCookie = { 0, 0, 0, 0, { {0} }, { {0} }, - 0, 0, 0, + 0, DRC_EXCEPTION_NONE, 0, 0, DRC_SUBCELL_OVERLAP_TAG, (DRCCookie *) NULL }; @@ -65,7 +65,7 @@ static DRCCookie drcSubcellCookie = { static DRCCookie drcInSubCookie = { 0, 0, 0, 0, { {0} }, { {0} }, - 0, 0, 0, + 0, DRC_EXCEPTION_NONE, 0, 0, DRC_IN_SUBCELL_TAG, (DRCCookie *) NULL }; @@ -79,7 +79,7 @@ static DRCCookie drcInSubCookie = { static DRCCookie drcOffGridCookie = { 0, 0, 0, 0, { {0} }, { {0} }, - 0, 0, 0, + 0, DRC_EXCEPTION_NONE, 0, 0, DRC_OFFGRID_TAG, (DRCCookie *) NULL }; diff --git a/drc/DRCtech.c b/drc/DRCtech.c index 278e0542..d396a999 100644 --- a/drc/DRCtech.c +++ b/drc/DRCtech.c @@ -72,6 +72,12 @@ static int drcRulesOptimized = 0; static int DRCtag = 0; +/* Keep track of what rule exemption or exception is in effect + * while reading the DRC tech file section. + */ + +static char drcCurException = (char)DRC_EXCEPTION_NONE; + /* * Forward declarations. */ @@ -79,6 +85,7 @@ int drcWidth(), drcSpacing(), drcEdge(), drcNoOverlap(); int drcExactOverlap(), drcExtend(); int drcSurround(), drcRectOnly(), drcOverhang(); int drcStepSize(), drcOption(), drcOffGrid(); +int drcException(), drcExemption(); int drcMaxwidth(), drcArea(), drcRectangle(), drcAngles(); int drcCifSetStyle(), drcCifWidth(), drcCifSpacing(); int drcCifMaxwidth(), drcCifArea(); @@ -301,6 +308,12 @@ drcTechFreeStyle() /* Clear the Why string list */ freeMagic(DRCCurStyle->DRCWhyList); + /* Clear the exception list */ + for (i = 0; i < DRCCurStyle->DRCExceptionSize; i++) + freeMagic(DRCCurStyle->DRCExceptionList[i]); + if (DRCCurStyle->DRCExceptionList != (char **)NULL) + freeMagic(DRCCurStyle->DRCExceptionList); + freeMagic(DRCCurStyle); DRCCurStyle = NULL; } @@ -384,6 +397,60 @@ drcWhyCreate(whystring) return DRCCurStyle->DRCWhySize; } +/* + * ---------------------------------------------------------------------------- + * drcExceptionCreate -- + * + * Create an entry for a DRC rule exception/exemption type, if it does + * not already exist. + * + * Results: + * The index of the exception (which is a signed character). + * + * Side effects: + * Adds to the DRCExceptionList if "name" has not been used before. + * Calls StrDup() and increments DRCExceptionSize. + * + * ---------------------------------------------------------------------------- + */ + +char +drcExceptionCreate(name) + char *name; +{ + int i; + char **newlist; + + /* NOTE: DRCExceptionList has "MASKHINTS_" prepended to the names */ + for (i = 0; i < DRCCurStyle->DRCExceptionSize; i++) + if (!strcmp(name, DRCCurStyle->DRCExceptionList[i] + 10)) + return (char)i; + + if (i > 127) + { + /* I would be shocked if this code ever got executed. */ + TxError("Error: Too many rule exceptions! Limit is 127.\n"); + return (char)DRC_EXCEPTION_NONE; + } + + /* Create a new list that is one entry longer than the old list. + * This is not elegant but there will never be more than a handful + * of exceptions in a rule deck. + */ + newlist = (char **)mallocMagic((i + 1) * sizeof(char *)); + for (i = 0; i < DRCCurStyle->DRCExceptionSize; i++) + newlist[i] = DRCCurStyle->DRCExceptionList[i]; + + /* The rule deck does not have the "MASKHINTS_" prefix on the name */ + newlist[i] = (char *)mallocMagic(strlen(name) + 11); + sprintf(newlist[i], "MASKHINTS_%s", name); + DRCCurStyle->DRCExceptionSize++; + if (DRCCurStyle->DRCExceptionList != (char **)NULL) + freeMagic(DRCCurStyle->DRCExceptionList); + DRCCurStyle->DRCExceptionList = newlist; + return (char)i; +} + /* * ---------------------------------------------------------------------------- * @@ -571,6 +638,8 @@ DRCTechStyleInit() DRCCurStyle->DRCStepSize = 0; DRCCurStyle->DRCFlags = (char)0; DRCCurStyle->DRCWhySize = 0; + DRCCurStyle->DRCExceptionList = (char **)NULL; + DRCCurStyle->DRCExceptionSize = 0; HashInit(&DRCWhyErrorTable, 16, HT_STRINGKEYS); @@ -663,6 +732,7 @@ DRCTechStyleInit() } drcCifInit(); + drcCurException = (char)DRC_EXCEPTION_NONE; } /* @@ -955,6 +1025,7 @@ drcCifAssign(cookie, dist, next, mask, corner, tag, cdist, flags, planeto, plane (cookie)->drcc_plane = planeto; (cookie)->drcc_mod = 0; (cookie)->drcc_cmod = 0; + (cookie)->drcc_exception = drcCurException; } // This is like drcCifAssign, but checks for bad plane numbers in planeto and @@ -1031,50 +1102,37 @@ DRCTechAddRule(sectionName, argc, argv) int (*rk_proc)(); /* Procedure implementing this keyword */ const char *rk_err; /* Error message */ } ruleKeys[] = { - {"angles", 4, 4, drcAngles, - "layers 45|90 why"}, + {"angles", 4, 4, drcAngles, "layers 45|90 why"}, {"edge", 8, 10, drcEdge, "layers1 layers2 distance okTypes cornerTypes cornerDistance [option] why [plane]"}, {"edge4way", 8, 10, drcEdge, "layers1 layers2 distance okTypes cornerTypes cornerDistance [option] why [plane]"}, - {"exact_overlap", 2, 2, drcExactOverlap, - "layers"}, + {"exact_overlap", 2, 2, drcExactOverlap, "layers"}, + {"exception", 2, 2, drcException, "name"}, + {"exemption", 2, 2, drcExemption, "name"}, {"extend", 5, 6, drcExtend, "layers1 layers2 distance [option] why"}, - {"no_overlap", 3, 3, drcNoOverlap, - "layers1 layers2"}, - {"option", 2, 2, drcOption, - "option_name option_value"}, - {"overhang", 5, 5, drcOverhang, - "layers1 layers2 distance why"}, - {"rect_only", 3, 3, drcRectOnly, - "layers why"}, + {"no_overlap", 3, 3, drcNoOverlap, "layers1 layers2"}, + {"option", 2, 2, drcOption, "option_name option_value"}, + {"overhang", 5, 5, drcOverhang, "layers1 layers2 distance why"}, + {"rect_only", 3, 3, drcRectOnly, "layers why"}, {"spacing", 6, 7, drcSpacing, "layers1 layers2 separation [layers3] adjacency why"}, - {"stepsize", 2, 2, drcStepSize, - "step_size"}, + {"stepsize", 2, 2, drcStepSize, "step_size"}, {"surround", 6, 7, drcSurround, "layers1 layers2 distance presence why"}, - {"width", 4, 5, drcWidth, - "layers width why"}, + {"width", 4, 5, drcWidth, "layers width why"}, {"widespacing", 7, 8, drcSpacing, "layers1 width layers2 separation adjacency why"}, - {"area", 5, 5, drcArea, - "layers area horizon why"}, - {"off_grid", 4, 4, drcOffGrid, - "layers pitch why"}, - {"maxwidth", 4, 6, drcMaxwidth, - "layers maxwidth bends why"}, - {"cifstyle", 2, 2, drcCifSetStyle, - "cif_style"}, - {"cifwidth", 4, 4, drcCifWidth, - "layers width why"}, + {"area", 5, 5, drcArea, "layers area horizon why"}, + {"off_grid", 4, 4, drcOffGrid, "layers pitch why"}, + {"maxwidth", 4, 6, drcMaxwidth, "layers maxwidth bends why"}, + {"cifstyle", 2, 2, drcCifSetStyle, "cif_style"}, + {"cifwidth", 4, 4, drcCifWidth, "layers width why"}, {"cifspacing", 6, 6, drcCifSpacing, "layers1 layers2 separation adjacency why"}, - {"cifarea", 5, 5, drcCifArea, - "layers area horizon why"}, - {"cifmaxwidth", 5, 5, drcCifMaxwidth, - "layers maxwidth bends why"}, + {"cifarea", 5, 5, drcCifArea, "layers area horizon why"}, + {"cifmaxwidth", 5, 5, drcCifMaxwidth, "layers maxwidth bends why"}, {"rectangle", 5, 5, drcRectangle, "layers maxwidth [even|odd|any] why"}, {0} @@ -3634,6 +3692,83 @@ drcRectangle(argc, argv) return maxwidth; } +/* + * ---------------------------------------------------------------------------- + * + * drcException, drcExemption -- + * + * Process a DRC exception declaration + * This is of the form: + * + * exception exception_name|none + * or + * exemption exemption_name|none + * + * e.g, + * + * exception SRAM + * exemption SRAM + * + * The exception_name or exemption_name is the suffix part of a MASKHINTS_* + * property name; e.g., the name SRAM corresponds to a property called + * MASKHINTS_SRAM. This declaration is followed by a block of DRC rules + * that are subject to the exception or the exemption. An exception is the + * opposite of an exemption: If a rule is excepted, then the rule applies + * within areas delineated by bounding boxes defined by the + * MASKHINTS_ property. If a rule is exempted, then the + * rule applies only outside of areas delineated by bounding boxes defined + * by the MASKHINTS_ property. The block of rules subject + * to the exemption or exception ends with another exception or exemption + * declaration. If the following rules are not to be excepted or exempted + * at all, then use "exception none" or "exemption none". + * + * Results: + * Returns 0. + * + * Side effects: + * Updates drcCurException. drcCurException is zero or positive for + * exceptions and negative for exemptions. The index can be + * recovered from a negative value by negating it and subtracting 1. + * + * ---------------------------------------------------------------------------- + */ + +int +drcException(argc, argv) + int argc; + char *argv[]; +{ + int i; + + if (DRCCurStyle == NULL) return 0; + + /* Assume that argc must be 2 because the parser insists upon it */ + + if (!strcmp(argv[1], "none")) + drcCurException = (char)DRC_EXCEPTION_NONE; + else + drcCurException = drcExceptionCreate(argv[1]); + return (0); +} + +int +drcExemption(argc, argv) + int argc; + char *argv[]; +{ + int i; + + if (DRCCurStyle == NULL) return 0; + + /* Assume that argc must be 2 because the parser insists upon it */ + + if (!strcmp(argv[1], "none")) + drcCurException = (char)DRC_EXCEPTION_NONE; + else + drcCurException = -(drcExceptionCreate(argv[1])) - 1; + return (0); +} + /* * ---------------------------------------------------------------------------- * @@ -4119,6 +4254,7 @@ drcTechFinalStyle(style) if (dp->drcc_dist > next->drcc_dist) continue; if (dp->drcc_cdist > next->drcc_cdist) continue; if (dp->drcc_plane != next->drcc_plane) continue; + if (dp->drcc_exception != next->drcc_exception) continue; if (dp->drcc_flags & DRC_REVERSE) { if (!(next->drcc_flags & DRC_REVERSE)) continue; diff --git a/drc/drc.h b/drc/drc.h index 346fab7c..59f6d423 100644 --- a/drc/drc.h +++ b/drc/drc.h @@ -36,6 +36,7 @@ typedef struct drccookie TileTypeBitMask drcc_mask; /* Legal types on RHS */ TileTypeBitMask drcc_corner; /* Types that trigger corner check */ unsigned short drcc_flags; /* Miscellaneous flags, see below. */ + char drcc_exception; /* Index to list of exceptions */ int drcc_edgeplane; /* Plane of edge */ int drcc_plane; /* Index of plane on which to check * legal types. */ @@ -91,6 +92,9 @@ typedef struct drccookie #define DRC_UNPROCESSED CLIENTDEFAULT #define DRC_PROCESSED 1 +/* drcc_exception defaults to -128 (0x80) meaning no exceptions/exemptions */ +#define DRC_EXCEPTION_NONE (char)0x80 + /* * Background DRC (DRC Idle proc) for Tcl-based Magic */ @@ -177,6 +181,8 @@ typedef struct drcstyle unsigned short DRCFlags; /* Option flags */ char **DRCWhyList; /* Indexed list of "why" text strings */ int DRCWhySize; /* Length of DRCWhyList */ + char **DRCExceptionList; /* Indexed list of DRC exceptions */ + int DRCExceptionSize; /* Length of DRCExceptionList */ PaintResultType DRCPaintTable[NP][NT][NT]; } DRCStyle;