From 6bae7c25c43e65bdb01688db642b21a61733fb86 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 25 Mar 2020 09:29:16 -0400 Subject: [PATCH 1/5] Enhanced the "lef write -hide" command option to check for metal wide spacing rules; should result in LEF views that can import back into magic without DRC errors. --- drc/DRCtech.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++ lef/lefWrite.c | 22 ++++++++++++++----- 2 files changed, 75 insertions(+), 6 deletions(-) diff --git a/drc/DRCtech.c b/drc/DRCtech.c index 19a906dc..8cde7197 100644 --- a/drc/DRCtech.c +++ b/drc/DRCtech.c @@ -4031,3 +4031,62 @@ DRCGetDefaultLayerSurround(ttype1, ttype2) } return layerSurround; } + +/* + *----------------------------------------------------------------------------- + * DRCGetDefaultLayerWideSpacing --- + * + * Determine a default layer-to-self wide-layer spacing rule from + * the DRC width rules of a layer. + * + * Results: + * The minimum spacing between the specified magic layer type and + * itself, where one of the shapes has width greater than "twidth". + * The result value is in magic internal units. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +int +DRCGetDefaultWideLayerSpacing(ttype, twidth) + TileType ttype; + int twidth; +{ + int routeSpacing = 0; + DRCCookie *cptr; + TileTypeBitMask *set; + bool widerule = FALSE; + + for (cptr = DRCCurStyle->DRCRulesTbl[ttype][TT_SPACE]; cptr != (DRCCookie *) NULL; + cptr = cptr->drcc_next) + { + if (cptr->drcc_flags & DRC_TRIGGER) /* Widespacing rule */ + { + widerule = TRUE; + if (cptr->drcc_dist > twidth) /* Check against rule width */ + return routeSpacing; + } + if (widerule && ((cptr->drcc_flags & DRC_REVERSE) == 0)) /* FORWARD only */ + { + set = &cptr->drcc_mask; + if (!TTMaskHasType(set, ttype)) + if (PlaneMaskHasPlane(DBTypePlaneMaskTbl[ttype], cptr->drcc_plane) && + (cptr->drcc_dist == cptr->drcc_cdist)) + { + routeSpacing = cptr->drcc_dist; + /* Diagnostic */ + /* + TxPrintf("DRC: Layer %s has wide spacing %d to layer %s width %d\n", + DBTypeLongNameTbl[ttype1], routeSpacing, + DBTypeLongNameTbl[ttype2], twidth); + */ + } + } + if (!(cptr->drcc_flags & DRC_TRIGGER)) widerule = FALSE; + } + return routeSpacing; +} + diff --git a/lef/lefWrite.c b/lef/lefWrite.c index 4391d727..93fe30de 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -1103,15 +1103,25 @@ lefWriteMacro(def, f, scale, hide) for (thislll = lll; thislll; thislll = thislll->lll_next) { - int lspace; + int lspacex, lspacey, lwidth; lab = thislll->lll_label; - 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; + /* Look for wide spacing rules. If there are no wide spacing */ + /* rules, then fall back on the default spacing rule. */ + lwidth = thislll->lll_area.r_xtop - thislll->lll_area.r_xbot; + lspacex = DRCGetDefaultWideLayerSpacing(lab->lab_type, lwidth); + if (lspacex == 0) + lspacex = DRCGetDefaultLayerSpacing(lab->lab_type, lab->lab_type); + lwidth = thislll->lll_area.r_ytop - thislll->lll_area.r_ybot; + lspacey = DRCGetDefaultWideLayerSpacing(lab->lab_type, lwidth); + if (lspacey == 0) + lspacey = DRCGetDefaultLayerSpacing(lab->lab_type, lab->lab_type); + + thislll->lll_area.r_xbot -= lspacex; + thislll->lll_area.r_ybot -= lspacey; + thislll->lll_area.r_xtop += lspacex; + thislll->lll_area.r_ytop += lspacey; DBErase(lc.lefYank, &thislll->lll_area, lab->lab_type); freeMagic(thislll); From 195e096d645cc1e0282ee9ea033511e76434d963 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 25 Mar 2020 11:07:54 -0400 Subject: [PATCH 2/5] Modified lefWrite to ensure maximum spacing per all widespacing rules for any gap between a pin touching the cell boundary and the internal obstruction layer. --- VERSION | 2 +- lef/lefWrite.c | 33 +++++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/VERSION b/VERSION index 70e23b87..6635c799 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.2.202 +8.2.203 diff --git a/lef/lefWrite.c b/lef/lefWrite.c index 93fe30de..5c1074e4 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -1103,10 +1103,14 @@ lefWriteMacro(def, f, scale, hide) for (thislll = lll; thislll; thislll = thislll->lll_next) { - int lspacex, lspacey, lwidth; + int lspacex, lspacey, lwidth, mspace; lab = thislll->lll_label; + mspace = DRCGetDefaultWideLayerSpacing(lab->lab_type, 1E6); + if (mspace == 0) + mspace = DRCGetDefaultLayerSpacing(lab->lab_type, lab->lab_type); + /* Look for wide spacing rules. If there are no wide spacing */ /* rules, then fall back on the default spacing rule. */ lwidth = thislll->lll_area.r_xtop - thislll->lll_area.r_xbot; @@ -1118,12 +1122,29 @@ lefWriteMacro(def, f, scale, hide) if (lspacey == 0) lspacey = DRCGetDefaultLayerSpacing(lab->lab_type, lab->lab_type); - thislll->lll_area.r_xbot -= lspacex; - thislll->lll_area.r_ybot -= lspacey; - thislll->lll_area.r_xtop += lspacex; - thislll->lll_area.r_ytop += lspacey; - DBErase(lc.lefYank, &thislll->lll_area, lab->lab_type); + /* Is the label touching the boundary? If so, then use the */ + /* maximum space from the inside edge. */ + if (thislll->lll_area.r_xtop >= boundary.r_xtop) + thislll->lll_area.r_xbot -= mspace; + else + thislll->lll_area.r_xbot -= lspacex; + if (thislll->lll_area.r_ytop >= boundary.r_ytop) + thislll->lll_area.r_ybot -= mspace; + else + thislll->lll_area.r_ybot -= lspacey; + + if (thislll->lll_area.r_xbot <= boundary.r_xbot) + thislll->lll_area.r_xtop += mspace; + else + thislll->lll_area.r_xtop += lspacex; + + if (thislll->lll_area.r_ybot <= boundary.r_ybot) + thislll->lll_area.r_ytop += mspace; + else + thislll->lll_area.r_ytop += lspacey; + + DBErase(lc.lefYank, &thislll->lll_area, lab->lab_type); freeMagic(thislll); } } From c433534f4cbb722e26c2ab3dc54caa9f6e009215 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 25 Mar 2020 12:01:06 -0400 Subject: [PATCH 3/5] Modified GDS read to assign the same port index to incoming port labels with the same text. --- calma/CalmaRdpt.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/calma/CalmaRdpt.c b/calma/CalmaRdpt.c index f0edac74..403192f6 100644 --- a/calma/CalmaRdpt.c +++ b/calma/CalmaRdpt.c @@ -979,13 +979,19 @@ calmaElementText() /* No port information can be encoded in the GDS file, so */ /* assume defaults, and assume that the port order is the */ - /* order in which labels arrive in the GDS stream. */ + /* order in which labels arrive in the GDS stream. If */ + /* ports have the same text, then give them the same index. */ i = -1; for (sl = cifReadCellDef->cd_labels; sl != NULL; sl = sl->lab_next) { idx = sl->lab_flags & PORT_NUM_MASK; if (idx > i) i = idx; + if (!strcmp(sl->lab_text, textbody)) + { + i = (sl->lab_flags & PORT_NUM_MASK) - 1; + break; + } } i++; lab->lab_flags |= (PORT_NUM_MASK & i); From 151f1fb4706429e2cf8e9ae1d6f4a96b4eff3b50 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 25 Mar 2020 12:07:14 -0400 Subject: [PATCH 4/5] Quick fix to last commit. --- calma/CalmaRdpt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/calma/CalmaRdpt.c b/calma/CalmaRdpt.c index 403192f6..40a9e118 100644 --- a/calma/CalmaRdpt.c +++ b/calma/CalmaRdpt.c @@ -987,7 +987,7 @@ calmaElementText() { idx = sl->lab_flags & PORT_NUM_MASK; if (idx > i) i = idx; - if (!strcmp(sl->lab_text, textbody)) + if ((sl != lab) && !strcmp(sl->lab_text, textbody)) { i = (sl->lab_flags & PORT_NUM_MASK) - 1; break; From 521efeb929245e03d69affcc7afd935d301f3275 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 25 Mar 2020 15:21:05 -0400 Subject: [PATCH 5/5] Corrected uninitialized variable problem in lefWrite. --- lef/lefWrite.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lef/lefWrite.c b/lef/lefWrite.c index 5c1074e4..193ab5de 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -836,6 +836,7 @@ lefWriteMacro(def, f, scale, hide) /* List of pins (ports) (to be refined?) */ lc.lefMode = LEF_MODE_PORT; + lc.numWrites = 0; /* Determine the maximum port number, then output ports in order */ maxport = -1;