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.
This commit is contained in:
Tim Edwards 2018-12-14 11:51:27 -05:00
parent 533017c8c7
commit 6aa0895e6f
1 changed files with 88 additions and 3 deletions

View File

@ -24,6 +24,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#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;