From 6aa0895e6fbce703534a357722f4e41720db9d74 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 14 Dec 2018 11:51:27 -0500 Subject: [PATCH] Created a method for distance substitutions in DRC "why" strings in DRC rules. The substitutions are specified by "%d" for the main rule distance, "%c" for the corner rule distance (sometimes interpreted differently; e.g., as width in the widespacing rule), and "%a" for rule area (e.g., maxarea rule). In addition to simplifying the process of writing rule violation strings, the benefits are twofold: (1) The output is in meaningful physical units, but in the case of SCMOS technology, will scale properly depending on the selected GDS output style, and in the case of all technologies, will scale properly with internal grid division; and (2) when using lambda, but where rules are given in vendor minimum dimensions, the rules will be based on the lambda rule approximation (that is, distances will be rounded to the nearest lambda but reported in microns). Behavior is unchanged from previous versions for "why" strings not using the defined substitution sequences. --- drc/DRCmain.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 3 deletions(-) diff --git a/drc/DRCmain.c b/drc/DRCmain.c index a9c879f0..58f91a32 100644 --- a/drc/DRCmain.c +++ b/drc/DRCmain.c @@ -24,6 +24,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include #include +#include #include "tcltk/tclmagic.h" #include "utils/magic.h" @@ -158,6 +159,90 @@ drcPaintError(celldef, rect, cptr, plane) DRCErrorCount += 1; } +/* + * ---------------------------------------------------------------------------- + * drcSubstitute --- + * + * Check for substitution sequences in the DRC "why" string in the DRCCookie + * record passed in cptr, and make the appropriate substitutions. Return + * the modified string. + * + * Currently supported: + * %d encodes the rule distance. Output is given in microns + * %c encodes the rule corner distance. Output is given in microns. + * %a encodes the rule distance as area. Output is given in microns squared. + * + * To do: Add flag bits to the drcc_flags field to indicate what type of + * rule this is (easier than decoding it from context), and add a substitution + * sequence "%s" to build the entire "why" string from the relevant rule data. + * ---------------------------------------------------------------------------- + */ + +char * +drcSubstitute (cptr) + DRCCookie * cptr; /* Design rule violated */ +{ + static char *why_out = NULL; + char *whyptr = cptr->drcc_why, *sptr, *wptr; + int subscnt = 0, whylen; + float oscale, value; + extern float CIFGetOutputScale(); + + while ((sptr = strchr(whyptr, '%')) != NULL) + { + subscnt++; + whyptr = sptr + 1; + } + if (subscnt == 0) return whyptr; /* No substitutions */ + + whyptr = cptr->drcc_why; + whylen = strlen(whyptr) + 20 * subscnt; + if (why_out != NULL) freeMagic(why_out); + why_out = (char *)mallocMagic(whylen * sizeof(char)); + strcpy(why_out, whyptr); + + oscale = CIFGetOutputScale(1000); /* 1000 for conversion to um */ + wptr = why_out; + + while ((sptr = strchr(whyptr, '%')) != NULL) + { + /* copy up to sptr */ + strncpy(wptr, whyptr, (int)(sptr - whyptr)); + wptr += (sptr - whyptr); + + switch (*(sptr + 1)) + { + case 'd': + /* Replace with "dist" value in microns */ + value = (float)cptr->drcc_dist * oscale; + snprintf(wptr, 20, "%01.3gum", value); + wptr += strlen(wptr); + break; + case 'c': + /* Replace with "cdist" value in microns */ + value = (float)cptr->drcc_cdist * oscale; + snprintf(wptr, 20, "%01.3gum", value); + wptr += strlen(wptr); + break; + case 'a': + /* Replace with "dist" value in microns squared */ + value = (float)cptr->drcc_dist * oscale * oscale; + snprintf(wptr, 20, "%01.4gum^2", value); + wptr += strlen(wptr); + break; + default: + /* Any other character after '%', treat as literal */ + wptr += 2; + break; + } + whyptr = sptr + 2; + } + /* copy remainder of string (including trailing null) */ + strncpy(wptr, whyptr, strlen(whyptr) + 1); + + return why_out; +} + /* * ---------------------------------------------------------------------------- @@ -197,8 +282,8 @@ drcPrintError (celldef, rect, cptr, scx) h = HashFind(&DRCErrorTable, cptr->drcc_why); i = (spointertype) HashGetValue(h); if (i == 0) - TxPrintf("%s\n", cptr->drcc_why); - i += 1; + TxPrintf("%s\n", drcSubstitute(cptr)); + i++; HashSetValue(h, (spointertype)i); } @@ -230,7 +315,7 @@ drcListError (celldef, rect, cptr, scx) Tcl_Obj *lobj; lobj = Tcl_GetObjResult(magicinterp); Tcl_ListObjAppendElement(magicinterp, lobj, - Tcl_NewStringObj(cptr->drcc_why, -1)); + Tcl_NewStringObj(drcSubstitute(cptr), -1)); Tcl_SetObjResult(magicinterp, lobj); } i += 1;