(1) Corrected an error in generating GDS_FILE properties when

reading GDS files, caused by an unneeded change to pass both
the "original" filename and the actual filename when handling
compressed files---The original filename is unneeded.
(2) Implemented several new methods for parasitic extraction.  The
first is an option offset value to apply to sidewall calculations.
This handles issues where actual wire separation is different
from drawn wire separation, which can be significant for the
1/d calculation of sidewall coupling.  The second method is to
use the recently-added fringe halo to compute the coupling of the
fringe capacitance to nearby wires.  Prior to this change, all
fringe capacitance was applied to surfaces directly under a wire
edge as if the fringe capacitance did not extend outward from the
edge.  Now the capacitance is properly pro-rated for the position
of any overlapped shape inside the fringing field.  Finally, the
third method added is a new search algorithm for finding the
nearest shapes along the length of a boundary.  This is used for
sidewall coupling and fringe shielding, where the nearest shape
dominates the coupling, and any shapes behind are shielded and
may (to first order) be ignored.  Previously, the entire halo
was searched without regard to shapes shielding other shapes
behind, and a recent correction added an ad-hoc search for
blocking shapes that was inefficient and not always correct.
The new method is both efficient and accurate.
This commit is contained in:
Tim Edwards 2022-05-28 10:33:21 -04:00
parent 4f5e1aec6b
commit c001de3d9d
8 changed files with 631 additions and 201 deletions

View File

@ -1 +1 @@
8.3.305
8.3.306

View File

@ -294,11 +294,8 @@ calmaExact()
*/
bool
calmaParseStructure(filename, origname)
calmaParseStructure(filename)
char *filename; /* Name of the GDS file read */
char *origname; /* Original name of the GDS file
* (used with compressed files)
*/
{
static int structs[] = { CALMA_STRCLASS, CALMA_STRTYPE, -1 };
int nbytes, rtype, nsrefs, osrefs, npaths;
@ -449,7 +446,7 @@ calmaParseStructure(filename, origname)
/* Substitute variable for PDK path or ~ for home directory */
/* the same way that cell references are handled in .mag files. */
DBPathSubstitute(origname, cstring, cifReadCellDef);
DBPathSubstitute(filename, cstring, cifReadCellDef);
fncopy = StrDup(NULL, cstring);
sprintf(fpcopy, "%"DLONG_PREFIX"d", (dlong) filepos);
DBPropPut(cifReadCellDef, "GDS_START", (ClientData)fpcopy);

View File

@ -152,12 +152,9 @@ int calmaElementIgnore[] = { CALMA_ELFLAGS, CALMA_PLEX, -1 };
*/
void
CalmaReadFile(file, filename, origname)
CalmaReadFile(file, filename)
FILETYPE file; /* File from which to read Calma */
char *filename; /* The real name of the file read */
char *origname; /* Original name of file read (used for
* compressed files)
*/
{
int k, version;
char *libname = NULL;
@ -237,7 +234,7 @@ CalmaReadFile(file, filename, origname)
if (!calmaParseUnits()) goto done;
/* Main body of GDS-II input */
while (calmaParseStructure(filename, origname))
while (calmaParseStructure(filename))
if (SigInterruptPending)
goto done;
(void) calmaSkipExact(CALMA_ENDLIB);

View File

@ -927,7 +927,7 @@ CmdCalma(w, cmd)
cmd->tx_argv[2], cmd->tx_argv[2], cmd->tx_argv[2]);
return;
}
CalmaReadFile(f, namep, cmd->tx_argv[2]);
CalmaReadFile(f, namep);
(void) FCLOSE(f);
return;
}

File diff suppressed because it is too large Load Diff

View File

@ -111,8 +111,8 @@ static keydesc keyTable[] = {
"defaultsideoverlap", DEFAULTSIDEOVERLAP, 6, 6,
"types plane othertypes otherplane capacitance",
"defaultsidewall", DEFAULTSIDEWALL, 4, 4,
"types plane capacitance",
"defaultsidewall", DEFAULTSIDEWALL, 4, 5,
"types plane capacitance [offset]",
"device", DEVICE, 4, 10,
"device dev-type types options...",
@ -164,8 +164,8 @@ static keydesc keyTable[] = {
"sideoverlap", SIDEOVERLAP, 5, 6,
"intypes outtypes ovtypes capacitance [shieldtypes]",
"sidewall", SIDEWALL, 6, 6,
"intypes outtypes neartypes fartypes capacitance",
"sidewall", SIDEWALL, 6, 7,
"intypes outtypes neartypes fartypes capacitance [offset]",
"step", STEP, 2, 2,
"size",
@ -1374,6 +1374,7 @@ ExtTechSimplePerimCap(argc, argv)
PlaneNumToMaskBit(plane2);
cnew = (EdgeCap *) mallocMagic((unsigned) (sizeof (EdgeCap)));
cnew->ec_cap = capVal;
cnew->ec_offset = 0; /* No offsets on perimeter caps */
cnew->ec_far = shields; /* Types that shield */
cnew->ec_near = subtypes; /* Types we create cap with */
if (plane2 != -1)
@ -1408,7 +1409,8 @@ ExtTechSimplePerimCap(argc, argv)
*/
void
ExtTechSimpleSidewallCap(argv)
ExtTechSimpleSidewallCap(argc, argv)
int argc;
char *argv[];
{
/* Like ExtTechLine, but with near = types2 and far = types1 */
@ -1417,6 +1419,8 @@ ExtTechSimpleSidewallCap(argv)
TileTypeBitMask types1, types2;
CapValue capVal;
EdgeCap *cnew;
int offset;
double doffset;
int plane;
DBTechNoisyNameMask(argv[1], &types1);
@ -1424,6 +1428,17 @@ ExtTechSimpleSidewallCap(argv)
plane = DBTechNoisyNamePlane(argv[2]);
capVal = aToCap(argv[3]);
if (argc == 5)
{
/* Save a value of 1000 * the offset, which will be converted
* appropriately to magic units like exts->sideCoupleHalo.
*/
sscanf(argv[4], "%lg", &doffset);
offset = (int)(0.5 + doffset * 1000.0);
}
else
offset = 0;
// Like perimeter cap, treat only space and space-like types
// TTMaskCom2(&types2, &types1);
TTMaskZero(&types2);
@ -1449,6 +1464,7 @@ ExtTechSimpleSidewallCap(argv)
TTMaskSetMask(&ExtCurStyle->exts_sideCoupleOtherEdges[s][t], &types1);
cnew = (EdgeCap *) mallocMagic((unsigned) (sizeof (EdgeCap)));
cnew->ec_cap = capVal;
cnew->ec_offset = offset;
cnew->ec_near = types2;
cnew->ec_far = types1;
cnew->ec_next = ExtCurStyle->exts_sideCoupleCap[s][t];
@ -1679,6 +1695,7 @@ ExtTechSimpleSideOverlapCap(argv)
PlaneNumToMaskBit(plane2);
cnew = (EdgeCap *) mallocMagic((unsigned) (sizeof (EdgeCap)));
cnew->ec_cap = capVal;
cnew->ec_offset = 0; /* No offsets on overlap caps */
cnew->ec_far = shields; /* Types that shield */
cnew->ec_near = ov; /* Types we create cap with */
cnew->ec_pmask = PlaneNumToMaskBit(plane2);
@ -1846,7 +1863,9 @@ ExtTechLine(sectionName, argc, argv)
ParamList *subcktParams, *newParam;
ExtDevice *devptr;
int refcnt;
int offset;
double dhalo;
double doffset;
bool bad;
if (argc < 1)
@ -2215,7 +2234,7 @@ ExtTechLine(sectionName, argc, argv)
ExtTechSimpleSideOverlapCap(argv);
break;
case DEFAULTSIDEWALL:
ExtTechSimpleSidewallCap(argv);
ExtTechSimpleSidewallCap(argc, argv);
break;
case DEVICE:
@ -2896,6 +2915,7 @@ ExtTechLine(sectionName, argc, argv)
ExtCurStyle->exts_sideOverlapOtherPlanes[s][t] |= pov;
cnew = (EdgeCap *) mallocMagic((unsigned) (sizeof (EdgeCap)));
cnew->ec_cap = capVal;
cnew->ec_offset = 0; /* No offsets on overlap caps */
cnew->ec_far = shield; /* Really types that shield */
cnew->ec_near = ov; /* Really types we create cap with */
cnew->ec_pmask = pov;
@ -2945,6 +2965,13 @@ ExtTechLine(sectionName, argc, argv)
if (TTMaskHasType(&types1, TT_SPACE))
TechError("Can't have space on inside of edge [ignored]\n");
capVal = aToCap(argv[5]);
if (argc == 7)
{
sscanf(argv[6], "%lg", &doffset);
offset = (int)(0.5 + doffset * 1000.0);
}
else
offset = 0;
for (s = TT_TECHDEPBASE; s < DBNumTypes; s++)
{
if (!TTMaskHasType(&types1, s))
@ -2959,6 +2986,7 @@ ExtTechLine(sectionName, argc, argv)
TTMaskSetMask(&ExtCurStyle->exts_sideCoupleOtherEdges[s][t], &far);
cnew = (EdgeCap *) mallocMagic((unsigned) (sizeof (EdgeCap)));
cnew->ec_cap = capVal;
cnew->ec_offset = offset;
cnew->ec_near = near;
cnew->ec_far = far;
cnew->ec_next = ExtCurStyle->exts_sideCoupleCap[s][t];
@ -3451,11 +3479,20 @@ zinit:
// the value needs to be divided by 2 (the factor of
// 2 is made up by the fact that the sidewall is
// independently accumulated on each plate of the
// capacitor)
// capacitor). ALSO: ec_offset was multiplied up by
// 1000 so that micron distances could be saved as
// integer values, so that factor needs to be divided out.
for (ec = style->exts_sideCoupleCap[r][s]; ec != NULL;
ec = ec->ec_next)
{
ec->ec_cap *= 0.5;
if (ec->ec_offset > 0)
{
ec->ec_offset = (int)(((float)ec->ec_offset / dscale) + 0.5);
ec->ec_offset /= 1000;
}
}
}
/* Layer thickness and height are in microns, but are floating-point */
@ -3548,12 +3585,13 @@ ExtTechScale(scalen, scaled)
// per distance, the distance is referred to a separation
// distance in the same units, so the cap never scales.
// for (ec = style->exts_sideCoupleCap[i][j]; ec != NULL;
// ec = ec->ec_next)
// {
// ec->ec_cap *= scalen;
// ec->ec_cap /= scaled;
// }
for (ec = style->exts_sideCoupleCap[i][j]; ec != NULL;
ec = ec->ec_next)
{
// ec->ec_cap *= scalen;
// ec->ec_cap /= scaled;
DBScaleValue(&(ec->ec_offset), scaled, scalen);
}
for (ec = style->exts_sideOverlapCap[i][j]; ec != NULL;
ec = ec->ec_next)
{

View File

@ -67,10 +67,11 @@ extern char *extDevTable[];
#define EXT_DOCOUPLING 0x004 /* Extract coupling capacitance */
#define EXT_DORESISTANCE 0x008 /* Extract resistance */
#define EXT_DOLENGTH 0x010 /* Extract pathlengths */
#define EXT_DOALL 0x01f /* ALL OF THE ABOVE */
#define EXT_DOLOCAL 0x020 /* Write to local directory only */
#define EXT_DOLABELCHECK 0x040 /* Check for connections by label */
#define EXT_DOALIASES 0x080 /* Output all node aliases */
#define EXT_DOFRINGEHALO 0x020 /* Distributed fringe capacitance */
#define EXT_DOALL 0x03f /* ALL OF THE ABOVE */
#define EXT_DOLOCAL 0x040 /* Write to local directory only */
#define EXT_DOLABELCHECK 0x080 /* Check for connections by label */
#define EXT_DOALIASES 0x100 /* Output all node aliases */
extern int ExtOptions; /* Bitmask of above */

View File

@ -442,6 +442,7 @@ typedef struct edgecap
{
struct edgecap *ec_next; /* Next edge capacitance rule in list */
CapValue ec_cap; /* Capacitance (attofarads) */
int ec_offset; /* Offset to apply to separation */
TileTypeBitMask ec_near; /* Types closest to causing edge, or in
* the case of sideOverlaps, the
* types we are overlapping.