(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:
parent
4f5e1aec6b
commit
c001de3d9d
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue