A number of fixes to the extresist code (as well as style cleanup).
Still tracking down a problem with non-FET devices (e.g., capacitors). So, work in progress. Nothing should be affected outside of extresist.
This commit is contained in:
parent
c22d584ac3
commit
9aa39f820f
|
|
@ -46,7 +46,6 @@ extern ResSimNode *ResInitializeNode();
|
||||||
extern HashTable ResNodeTable;
|
extern HashTable ResNodeTable;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*--------------------------------------------------------------------------
|
*--------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -121,7 +120,6 @@ ResGetReCell()
|
||||||
ResUse = DBCellNewUse(ResDef, (char *) NULL);
|
ResUse = DBCellNewUse(ResDef, (char *) NULL);
|
||||||
DBSetTrans(ResUse, &GeoIdentityTransform);
|
DBSetTrans(ResUse, &GeoIdentityTransform);
|
||||||
ResUse->cu_expandMask = CU_DESCEND_SPECIAL;
|
ResUse->cu_expandMask = CU_DESCEND_SPECIAL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -418,7 +416,6 @@ ResProcessTiles(goodies, origin)
|
||||||
Tile *tile = fix->fp_tile;
|
Tile *tile = fix->fp_tile;
|
||||||
if (tile == NULL)
|
if (tile == NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
tile = ResDef->cd_planes[DBPlane(fix->fp_ttype)]->pl_hint;
|
tile = ResDef->cd_planes[DBPlane(fix->fp_ttype)]->pl_hint;
|
||||||
GOTOPOINT(tile, &(fix->fp_loc));
|
GOTOPOINT(tile, &(fix->fp_loc));
|
||||||
if (TiGetTypeExact(tile) != TT_SPACE)
|
if (TiGetTypeExact(tile) != TT_SPACE)
|
||||||
|
|
@ -682,7 +679,7 @@ ResExtractNet(startlist, goodies, cellname)
|
||||||
|
|
||||||
ExtResetTiles(scx.scx_use->cu_def, extUnInit);
|
ExtResetTiles(scx.scx_use->cu_def, extUnInit);
|
||||||
|
|
||||||
/* find all contacts in design and note their position */
|
/* Find all contacts in design and note their position */
|
||||||
|
|
||||||
ResContactList = (ResContactPoint *)ExtFindRegions(ResUse->cu_def,
|
ResContactList = (ResContactPoint *)ExtFindRegions(ResUse->cu_def,
|
||||||
&(ResUse->cu_def->cd_bbox),
|
&(ResUse->cu_def->cd_bbox),
|
||||||
|
|
@ -771,7 +768,7 @@ ResCleanUpEverything()
|
||||||
resDevice *oldDev;
|
resDevice *oldDev;
|
||||||
ResContactPoint *oldCon;
|
ResContactPoint *oldCon;
|
||||||
|
|
||||||
/* check integrity of internal database. Free up lists. */
|
/* Check integrity of internal database. Free up lists. */
|
||||||
|
|
||||||
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
||||||
{
|
{
|
||||||
|
|
@ -779,7 +776,6 @@ ResCleanUpEverything()
|
||||||
&(ResUse->cu_def->cd_bbox), &DBAllButSpaceAndDRCBits,
|
&(ResUse->cu_def->cd_bbox), &DBAllButSpaceAndDRCBits,
|
||||||
(ClientData)CLIENTDEFAULT, ResRemovePlumbing,
|
(ClientData)CLIENTDEFAULT, ResRemovePlumbing,
|
||||||
(ClientData)NULL);
|
(ClientData)NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (ResNodeList != NULL)
|
while (ResNodeList != NULL)
|
||||||
|
|
@ -808,12 +804,9 @@ ResCleanUpEverything()
|
||||||
freeMagic((char *)oldDev);
|
freeMagic((char *)oldDev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DBCellClearDef(ResUse->cu_def);
|
DBCellClearDef(ResUse->cu_def);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -935,6 +928,7 @@ FindStartTile(goodies, SourcePoint)
|
||||||
t1 = TiGetType(tile);
|
t1 = TiGetType(tile);
|
||||||
|
|
||||||
devptr = ExtCurStyle->exts_device[t1];
|
devptr = ExtCurStyle->exts_device[t1];
|
||||||
|
|
||||||
/* left */
|
/* left */
|
||||||
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp))
|
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp))
|
||||||
{
|
{
|
||||||
|
|
@ -1019,10 +1013,10 @@ ResGetDevice(pt)
|
||||||
for (pnum = PL_TECHDEPBASE; pnum < DBNumPlanes; pnum++)
|
for (pnum = PL_TECHDEPBASE; pnum < DBNumPlanes; pnum++)
|
||||||
{
|
{
|
||||||
if (TTMaskIntersect(&ExtCurStyle->exts_deviceMask, &DBPlaneTypes[pnum]) == 0)
|
if (TTMaskIntersect(&ExtCurStyle->exts_deviceMask, &DBPlaneTypes[pnum]) == 0)
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
/*start at hint tile for device plane */
|
/* Start at hint tile for device plane */
|
||||||
|
|
||||||
tile = ResUse->cu_def->cd_planes[pnum]->pl_hint;
|
tile = ResUse->cu_def->cd_planes[pnum]->pl_hint;
|
||||||
GOTOPOINT(tile, &workingPoint);
|
GOTOPOINT(tile, &workingPoint);
|
||||||
|
|
||||||
|
|
@ -1037,5 +1031,5 @@ ResGetDevice(pt)
|
||||||
return (((tileJunk *)tile->ti_client)->deviceList);
|
return (((tileJunk *)tile->ti_client)->deviceList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (NULL);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
194
resis/ResMerge.c
194
resis/ResMerge.c
|
|
@ -29,9 +29,10 @@ extern void ResFixBreakPoint();
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* ResDoneWithNode--After all connections to node are made, ResDoneWithNode
|
* ResDoneWithNode--
|
||||||
* is called. It checks for parallel, series, loop, triangle,
|
* After all connections to node are made, ResDoneWithNode is
|
||||||
* and single conections, and simplifies the network where possible.
|
* called. It checks for parallel, series, loop, triangle, and
|
||||||
|
* single conections, and simplifies the network where possible.
|
||||||
*
|
*
|
||||||
* Results: none
|
* Results: none
|
||||||
*
|
*
|
||||||
|
|
@ -56,10 +57,7 @@ ResDoneWithNode(resptr)
|
||||||
|
|
||||||
/* are there any resistors? */
|
/* are there any resistors? */
|
||||||
|
|
||||||
if (resptr->rn_re == NULL)
|
if (resptr->rn_re == NULL) return;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Special handling for geometry option */
|
/* Special handling for geometry option */
|
||||||
|
|
||||||
|
|
@ -106,24 +104,21 @@ ResDoneWithNode(resptr)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (status != UNTOUCHED) return; /* resptr may be invalid */
|
||||||
|
|
||||||
/* Eliminations that can be only if there are no devices connected */
|
/* Eliminations that can be only if there are no devices connected */
|
||||||
/* to node. Series and dangling connections fall in this group. */
|
/* to node. Series and dangling connections fall in this group. */
|
||||||
|
|
||||||
if ((resptr->rn_te == NULL) && (resptr->rn_why != RES_NODE_ORIGIN)
|
if ((resptr->rn_te == NULL) && (resptr->rn_why != RES_NODE_ORIGIN)
|
||||||
&& (status == UNTOUCHED))
|
&& (status == UNTOUCHED))
|
||||||
{
|
|
||||||
status = ResSeriesCheck(resptr);
|
status = ResSeriesCheck(resptr);
|
||||||
}
|
|
||||||
if ((status == UNTOUCHED) && (resptr->rn_why != RES_NODE_ORIGIN))
|
if ((status == UNTOUCHED) && (resptr->rn_why != RES_NODE_ORIGIN))
|
||||||
{
|
|
||||||
status = ResParallelCheck(resptr);
|
status = ResParallelCheck(resptr);
|
||||||
}
|
|
||||||
if ((status == UNTOUCHED) && (resptr->rn_why != RES_NODE_ORIGIN))
|
if ((status == UNTOUCHED) && (resptr->rn_why != RES_NODE_ORIGIN))
|
||||||
{
|
|
||||||
status = ResTriangleCheck(resptr);
|
status = ResTriangleCheck(resptr);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -148,13 +143,17 @@ ResFixRes(resptr,resptr2,resptr3,elimResis,newResis)
|
||||||
{
|
{
|
||||||
resElement *thisREl;
|
resElement *thisREl;
|
||||||
|
|
||||||
resptr3->rn_float.rn_area += newResis->rr_value*resptr->rn_float.rn_area/((float)(newResis->rr_value+elimResis->rr_value));
|
resptr3->rn_float.rn_area += newResis->rr_value*resptr->rn_float.rn_area
|
||||||
resptr2->rn_float.rn_area += elimResis->rr_value*resptr->rn_float.rn_area/((float)(newResis->rr_value+elimResis->rr_value));
|
/ ((float)(newResis->rr_value + elimResis->rr_value));
|
||||||
|
resptr2->rn_float.rn_area += elimResis->rr_value*resptr->rn_float.rn_area
|
||||||
|
/ ((float)(newResis->rr_value + elimResis->rr_value));
|
||||||
newResis->rr_value += elimResis->rr_value;
|
newResis->rr_value += elimResis->rr_value;
|
||||||
ASSERT(newResis->rr_value > 0, "series");
|
ASSERT(newResis->rr_value > 0, "series");
|
||||||
newResis->rr_float.rr_area += elimResis->rr_float.rr_area;
|
newResis->rr_float.rr_area += elimResis->rr_float.rr_area;
|
||||||
|
|
||||||
#ifdef ARIEL
|
#ifdef ARIEL
|
||||||
if (elimResis->rr_csArea && elimResis->rr_csArea < newResis->rr_csArea || newResis->rr_csArea == 0)
|
if (elimResis->rr_csArea && elimResis->rr_csArea < newResis->rr_csArea
|
||||||
|
|| newResis->rr_csArea == 0)
|
||||||
{
|
{
|
||||||
newResis->rr_csArea = elimResis->rr_csArea;
|
newResis->rr_csArea = elimResis->rr_csArea;
|
||||||
newResis->rr_tt = elimResis->rr_tt;
|
newResis->rr_tt = elimResis->rr_tt;
|
||||||
|
|
@ -220,7 +219,7 @@ ResFixParallel(elimResis,newResis)
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* ResSeriesCheck -- for nodes with no devices, sees if a series
|
* ResSeriesCheck -- for nodes with no devices, sees if a series
|
||||||
or loop combination is possible.
|
* or loop combination is possible.
|
||||||
*
|
*
|
||||||
* Results: returns SINGLE,LOOP,or SERIES if succesful.
|
* Results: returns SINGLE,LOOP,or SERIES if succesful.
|
||||||
*
|
*
|
||||||
|
|
@ -269,12 +268,10 @@ ResSeriesCheck(resptr)
|
||||||
{
|
{
|
||||||
if (rr1->rr_connection1 == resptr)
|
if (rr1->rr_connection1 == resptr)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (rr2->rr_connection1 == resptr)
|
if (rr2->rr_connection1 == resptr)
|
||||||
{
|
{
|
||||||
resptr2 = rr1->rr_connection2;
|
resptr2 = rr1->rr_connection2;
|
||||||
if (rr1->rr_connection2 ==
|
if (rr1->rr_connection2 == rr2->rr_connection2)
|
||||||
rr2->rr_connection2)
|
|
||||||
{
|
{
|
||||||
status = LOOP;
|
status = LOOP;
|
||||||
ResDeleteResPointer(rr1->rr_connection1, rr1);
|
ResDeleteResPointer(rr1->rr_connection1, rr1);
|
||||||
|
|
@ -287,7 +284,8 @@ ResSeriesCheck(resptr)
|
||||||
ResEliminateResistor(rr1, &ResResList);
|
ResEliminateResistor(rr1, &ResResList);
|
||||||
ResEliminateResistor(rr2, &ResResList);
|
ResEliminateResistor(rr2, &ResResList);
|
||||||
ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
|
ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
|
||||||
}else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
status = SERIES;
|
status = SERIES;
|
||||||
resptr3 = rr2->rr_connection2;
|
resptr3 = rr2->rr_connection2;
|
||||||
|
|
@ -300,7 +298,8 @@ ResSeriesCheck(resptr)
|
||||||
ResDoneWithNode(resptr2);
|
ResDoneWithNode(resptr2);
|
||||||
}
|
}
|
||||||
resptr2 = NULL;
|
resptr2 = NULL;
|
||||||
}else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
resptr2 = rr1->rr_connection2;
|
resptr2 = rr1->rr_connection2;
|
||||||
if (rr1->rr_connection2 == rr2->rr_connection1)
|
if (rr1->rr_connection2 == rr2->rr_connection1)
|
||||||
|
|
@ -316,7 +315,8 @@ ResSeriesCheck(resptr)
|
||||||
ResEliminateResistor(rr1, &ResResList);
|
ResEliminateResistor(rr1, &ResResList);
|
||||||
ResEliminateResistor(rr2, &ResResList);
|
ResEliminateResistor(rr2, &ResResList);
|
||||||
ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
|
ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
|
||||||
}else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
status = SERIES;
|
status = SERIES;
|
||||||
resptr3 = rr2->rr_connection1;
|
resptr3 = rr2->rr_connection1;
|
||||||
|
|
@ -330,7 +330,8 @@ ResSeriesCheck(resptr)
|
||||||
}
|
}
|
||||||
resptr2 = NULL;
|
resptr2 = NULL;
|
||||||
}
|
}
|
||||||
}else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (rr2->rr_connection1 == resptr)
|
if (rr2->rr_connection1 == resptr)
|
||||||
{
|
{
|
||||||
|
|
@ -348,12 +349,12 @@ ResSeriesCheck(resptr)
|
||||||
ResEliminateResistor(rr1, &ResResList);
|
ResEliminateResistor(rr1, &ResResList);
|
||||||
ResEliminateResistor(rr2, &ResResList);
|
ResEliminateResistor(rr2, &ResResList);
|
||||||
ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
|
ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
|
||||||
}else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
status = SERIES;
|
status = SERIES;
|
||||||
resptr3 = rr2->rr_connection2;
|
resptr3 = rr2->rr_connection2;
|
||||||
rr1->rr_connection2 =
|
rr1->rr_connection2 = rr2->rr_connection2;
|
||||||
rr2->rr_connection2;
|
|
||||||
ResFixRes(resptr, resptr2, resptr3, rr2, rr1);
|
ResFixRes(resptr, resptr2, resptr3, rr2, rr1);
|
||||||
}
|
}
|
||||||
if ((resptr2->rn_status & TRUE) == TRUE)
|
if ((resptr2->rn_status & TRUE) == TRUE)
|
||||||
|
|
@ -362,7 +363,8 @@ ResSeriesCheck(resptr)
|
||||||
ResDoneWithNode(resptr2);
|
ResDoneWithNode(resptr2);
|
||||||
}
|
}
|
||||||
resptr2 = NULL;
|
resptr2 = NULL;
|
||||||
}else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
resptr2 = rr1->rr_connection1;
|
resptr2 = rr1->rr_connection1;
|
||||||
if (rr1->rr_connection1 == rr2->rr_connection1)
|
if (rr1->rr_connection1 == rr2->rr_connection1)
|
||||||
|
|
@ -378,12 +380,12 @@ ResSeriesCheck(resptr)
|
||||||
ResEliminateResistor(rr1, &ResResList);
|
ResEliminateResistor(rr1, &ResResList);
|
||||||
ResEliminateResistor(rr2, &ResResList);
|
ResEliminateResistor(rr2, &ResResList);
|
||||||
ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
|
ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
|
||||||
}else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
status = SERIES;
|
status = SERIES;
|
||||||
resptr3 = rr2->rr_connection1;
|
resptr3 = rr2->rr_connection1;
|
||||||
rr1->rr_connection2 =
|
rr1->rr_connection2 = rr2->rr_connection1;
|
||||||
rr2->rr_connection1;
|
|
||||||
ResFixRes(resptr, resptr2, resptr3, rr2, rr1);
|
ResFixRes(resptr, resptr2, resptr3, rr2, rr1);
|
||||||
}
|
}
|
||||||
if ((resptr2->rn_status & TRUE) == TRUE)
|
if ((resptr2->rn_status & TRUE) == TRUE)
|
||||||
|
|
@ -399,7 +401,6 @@ ResSeriesCheck(resptr)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -423,13 +424,13 @@ ResParallelCheck(resptr)
|
||||||
resElement *rcell1, *rcell2;
|
resElement *rcell1, *rcell2;
|
||||||
|
|
||||||
|
|
||||||
for (rcell1 = resptr->rn_re;
|
for (rcell1 = resptr->rn_re; rcell1->re_nextEl != NULL;
|
||||||
rcell1->re_nextEl != NULL; rcell1 = rcell1->re_nextEl)
|
rcell1 = rcell1->re_nextEl)
|
||||||
{
|
{
|
||||||
r1 = rcell1->re_thisEl;
|
r1 = rcell1->re_thisEl;
|
||||||
|
|
||||||
for (rcell2 = rcell1->re_nextEl;
|
for (rcell2 = rcell1->re_nextEl; rcell2 != NULL;
|
||||||
rcell2 != NULL; rcell2 = rcell2->re_nextEl)
|
rcell2 = rcell2->re_nextEl)
|
||||||
|
|
||||||
{
|
{
|
||||||
r2 = rcell2->re_thisEl;
|
r2 = rcell2->re_thisEl;
|
||||||
|
|
@ -483,23 +484,23 @@ ResTriangleCheck(resptr)
|
||||||
resNode *n1, *n2, *n3;
|
resNode *n1, *n2, *n3;
|
||||||
resElement *rcell1, *rcell2, *rcell3, *element;
|
resElement *rcell1, *rcell2, *rcell3, *element;
|
||||||
|
|
||||||
for (rcell1 = resptr->rn_re;
|
for (rcell1 = resptr->rn_re; rcell1->re_nextEl != NULL;
|
||||||
rcell1->re_nextEl != NULL; rcell1 = rcell1->re_nextEl)
|
rcell1 = rcell1->re_nextEl)
|
||||||
{
|
{
|
||||||
rr1 = rcell1->re_thisEl;
|
rr1 = rcell1->re_thisEl;
|
||||||
n1 = (rr1->rr_connection1 == resptr) ? rr1->rr_connection2:
|
n1 = (rr1->rr_connection1 == resptr) ? rr1->rr_connection2:
|
||||||
rr1->rr_connection1;
|
rr1->rr_connection1;
|
||||||
|
|
||||||
for (rcell2 = rcell1->re_nextEl;
|
for (rcell2 = rcell1->re_nextEl; rcell2 != NULL;
|
||||||
rcell2 != NULL; rcell2 = rcell2->re_nextEl)
|
rcell2 = rcell2->re_nextEl)
|
||||||
{
|
{
|
||||||
rr2 = rcell2->re_thisEl;
|
rr2 = rcell2->re_thisEl;
|
||||||
if (TTMaskHasType(ResNoMergeMask + rr1->rr_tt, rr2->rr_tt))
|
if (TTMaskHasType(ResNoMergeMask + rr1->rr_tt, rr2->rr_tt))
|
||||||
continue;
|
continue;
|
||||||
n2 = (rr2->rr_connection1 == resptr) ? rr2->rr_connection2 :
|
n2 = (rr2->rr_connection1 == resptr) ? rr2->rr_connection2 :
|
||||||
rr2->rr_connection1;
|
rr2->rr_connection1;
|
||||||
for (rcell3 = n1->rn_re;
|
for (rcell3 = n1->rn_re; rcell3 != NULL;
|
||||||
rcell3 != NULL; rcell3 = rcell3->re_nextEl)
|
rcell3 = rcell3->re_nextEl)
|
||||||
{
|
{
|
||||||
rr3 = rcell3->re_thisEl;
|
rr3 = rcell3->re_thisEl;
|
||||||
if (TTMaskHasType(ResNoMergeMask + rr1->rr_tt, rr3->rr_tt))
|
if (TTMaskHasType(ResNoMergeMask + rr1->rr_tt, rr3->rr_tt))
|
||||||
|
|
@ -517,14 +518,11 @@ ResTriangleCheck(resptr)
|
||||||
{
|
{
|
||||||
denom = 1.0 /denom;
|
denom = 1.0 /denom;
|
||||||
/* calculate new values for resistors */
|
/* calculate new values for resistors */
|
||||||
r1 = (((float) rr1->rr_value)*
|
r1 = (((float)rr1->rr_value) * ((float)rr2->rr_value)) * denom;
|
||||||
((float) rr2->rr_value))*denom;
|
|
||||||
|
|
||||||
r2 = (((float) rr2->rr_value)*
|
r2 = (((float)rr2->rr_value) * ((float)rr3->rr_value)) * denom;
|
||||||
((float) rr3->rr_value))*denom;
|
|
||||||
|
|
||||||
r3 = (((float) rr1->rr_value)*
|
r3 = (((float)rr1->rr_value) * ((float)rr3->rr_value)) * denom;
|
||||||
((float) rr3->rr_value))*denom;
|
|
||||||
|
|
||||||
rr1->rr_value = r1 + 0.5;
|
rr1->rr_value = r1 + 0.5;
|
||||||
rr2->rr_value = r2 + 0.5;
|
rr2->rr_value = r2 + 0.5;
|
||||||
|
|
@ -540,6 +538,7 @@ ResTriangleCheck(resptr)
|
||||||
rr3->rr_value = 0;
|
rr3->rr_value = 0;
|
||||||
}
|
}
|
||||||
n3 = (resNode *)mallocMagic((unsigned)(sizeof(resNode)));
|
n3 = (resNode *)mallocMagic((unsigned)(sizeof(resNode)));
|
||||||
|
|
||||||
/* Where should the new node be `put'? It */
|
/* Where should the new node be `put'? It */
|
||||||
/* is arbitrarily assigned to the location */
|
/* is arbitrarily assigned to the location */
|
||||||
/* occupied by the first node. */
|
/* occupied by the first node. */
|
||||||
|
|
@ -594,21 +593,15 @@ ResTriangleCheck(resptr)
|
||||||
element->re_thisEl = rr3;
|
element->re_thisEl = rr3;
|
||||||
n3->rn_re = element;
|
n3->rn_re = element;
|
||||||
if ((n1->rn_status & TRUE) == TRUE)
|
if ((n1->rn_status & TRUE) == TRUE)
|
||||||
{
|
|
||||||
n1->rn_status &= ~TRUE;
|
n1->rn_status &= ~TRUE;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
n1 = NULL;
|
n1 = NULL;
|
||||||
}
|
|
||||||
if ((n2->rn_status & TRUE) == TRUE)
|
if ((n2->rn_status & TRUE) == TRUE)
|
||||||
{
|
|
||||||
n2->rn_status &= ~TRUE;
|
n2->rn_status &= ~TRUE;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
n2 = NULL;
|
n2 = NULL;
|
||||||
}
|
|
||||||
ResDoneWithNode(resptr);
|
ResDoneWithNode(resptr);
|
||||||
if (n1 != NULL) ResDoneWithNode(n1);
|
if (n1 != NULL) ResDoneWithNode(n1);
|
||||||
if (n2 != NULL) ResDoneWithNode(n2);
|
if (n2 != NULL) ResDoneWithNode(n2);
|
||||||
|
|
@ -637,8 +630,8 @@ ResTriangleCheck(resptr)
|
||||||
|
|
||||||
void
|
void
|
||||||
ResMergeNodes(node1, node2, pendingList, doneList)
|
ResMergeNodes(node1, node2, pendingList, doneList)
|
||||||
resNode *node1,*node2,**pendingList,**doneList;
|
resNode *node1, *node2;
|
||||||
|
resNode **pendingList, **doneList;
|
||||||
{
|
{
|
||||||
resElement *workingRes, *tRes;
|
resElement *workingRes, *tRes;
|
||||||
tElement *workingDev, *tDev;
|
tElement *workingDev, *tDev;
|
||||||
|
|
@ -649,6 +642,7 @@ ResMergeNodes(node1,node2,pendingList,doneList)
|
||||||
|
|
||||||
/* sanity check */
|
/* sanity check */
|
||||||
if (node1 == node2) return;
|
if (node1 == node2) return;
|
||||||
|
|
||||||
if (node1 == NULL || node2 == NULL)
|
if (node1 == NULL || node2 == NULL)
|
||||||
{
|
{
|
||||||
TxError("Attempt to merge NULL node\n");
|
TxError("Attempt to merge NULL node\n");
|
||||||
|
|
@ -657,9 +651,7 @@ ResMergeNodes(node1,node2,pendingList,doneList)
|
||||||
|
|
||||||
/* don't want to merge away startpoint */
|
/* don't want to merge away startpoint */
|
||||||
if (node2->rn_why & RES_NODE_ORIGIN)
|
if (node2->rn_why & RES_NODE_ORIGIN)
|
||||||
{
|
|
||||||
node1->rn_why = RES_NODE_ORIGIN;
|
node1->rn_why = RES_NODE_ORIGIN;
|
||||||
}
|
|
||||||
|
|
||||||
/* set node resistance */
|
/* set node resistance */
|
||||||
if (node1->rn_noderes > node2->rn_noderes)
|
if (node1->rn_noderes > node2->rn_noderes)
|
||||||
|
|
@ -673,7 +665,6 @@ ResMergeNodes(node1,node2,pendingList,doneList)
|
||||||
}
|
}
|
||||||
node1->rn_float.rn_area += node2->rn_float.rn_area;
|
node1->rn_float.rn_area += node2->rn_float.rn_area;
|
||||||
|
|
||||||
|
|
||||||
/* combine relevant flags */
|
/* combine relevant flags */
|
||||||
node1->rn_status |= (node2->rn_status & RN_MAXTDI);
|
node1->rn_status |= (node2->rn_status & RN_MAXTDI);
|
||||||
|
|
||||||
|
|
@ -685,9 +676,7 @@ ResMergeNodes(node1,node2,pendingList,doneList)
|
||||||
{
|
{
|
||||||
ResPlug *plug = (ResPlug *) workingDev->te_thist;
|
ResPlug *plug = (ResPlug *) workingDev->te_thist;
|
||||||
if (plug->rpl_node == node2)
|
if (plug->rpl_node == node2)
|
||||||
{
|
|
||||||
plug->rpl_node = node1;
|
plug->rpl_node = node1;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TxError("Bad plug node: is (%d %d), should be (%d %d)\n",
|
TxError("Bad plug node: is (%d %d), should be (%d %d)\n",
|
||||||
|
|
@ -701,10 +690,8 @@ ResMergeNodes(node1,node2,pendingList,doneList)
|
||||||
|
|
||||||
for (j = 0; j != workingDev->te_thist->rd_nterms; j++)
|
for (j = 0; j != workingDev->te_thist->rd_nterms; j++)
|
||||||
if (workingDev->te_thist->rd_terminals[j] == node2)
|
if (workingDev->te_thist->rd_terminals[j] == node2)
|
||||||
{
|
|
||||||
workingDev->te_thist->rd_terminals[j] = node1;
|
workingDev->te_thist->rd_terminals[j] = node1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
tDev = workingDev;
|
tDev = workingDev;
|
||||||
workingDev = workingDev->te_nextt;
|
workingDev = workingDev->te_nextt;
|
||||||
tDev->te_nextt = node1->rn_te;
|
tDev->te_nextt = node1->rn_te;
|
||||||
|
|
@ -712,6 +699,7 @@ ResMergeNodes(node1,node2,pendingList,doneList)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* append junction lists */
|
/* append junction lists */
|
||||||
|
|
||||||
workingJunc = node2->rn_je;
|
workingJunc = node2->rn_je;
|
||||||
while (workingJunc != NULL)
|
while (workingJunc != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -724,10 +712,8 @@ ResMergeNodes(node1,node2,pendingList,doneList)
|
||||||
junk = (tileJunk *) tile->ti_client;
|
junk = (tileJunk *) tile->ti_client;
|
||||||
|
|
||||||
if ((junk->tj_status & RES_TILE_DONE) == FALSE)
|
if ((junk->tj_status & RES_TILE_DONE) == FALSE)
|
||||||
{
|
|
||||||
ResFixBreakPoint(&junk->breakList, node2, node1);
|
ResFixBreakPoint(&junk->breakList, node2, node1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
tJunc->je_thisj->rj_jnode = node1;
|
tJunc->je_thisj->rj_jnode = node1;
|
||||||
workingJunc = workingJunc->je_nextj;
|
workingJunc = workingJunc->je_nextj;
|
||||||
tJunc->je_nextj = node1->rn_je;
|
tJunc->je_nextj = node1->rn_je;
|
||||||
|
|
@ -749,62 +735,51 @@ ResMergeNodes(node1,node2,pendingList,doneList)
|
||||||
tile =tCon->ce_thisc->cp_tile[i];
|
tile =tCon->ce_thisc->cp_tile[i];
|
||||||
junk = (tileJunk *) tile->ti_client;
|
junk = (tileJunk *) tile->ti_client;
|
||||||
if ((junk->tj_status & RES_TILE_DONE) == FALSE)
|
if ((junk->tj_status & RES_TILE_DONE) == FALSE)
|
||||||
{
|
|
||||||
ResFixBreakPoint(&junk->breakList, node2, node1);
|
ResFixBreakPoint(&junk->breakList, node2, node1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
workingCon = workingCon->ce_nextc;
|
workingCon = workingCon->ce_nextc;
|
||||||
tCon->ce_nextc = node1->rn_ce;
|
tCon->ce_nextc = node1->rn_ce;
|
||||||
node1->rn_ce = tCon;
|
node1->rn_ce = tCon;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Moves resistors to new node */
|
/* Moves resistors to new node */
|
||||||
|
|
||||||
workingRes = node2->rn_re;
|
workingRes = node2->rn_re;
|
||||||
while (workingRes != NULL)
|
while (workingRes != NULL)
|
||||||
{
|
{
|
||||||
if (workingRes->re_thisEl->rr_connection1 == node2)
|
if (workingRes->re_thisEl->rr_connection1 == node2)
|
||||||
{
|
|
||||||
workingRes->re_thisEl->rr_connection1 = node1;
|
workingRes->re_thisEl->rr_connection1 = node1;
|
||||||
}
|
|
||||||
else if (workingRes->re_thisEl->rr_connection2 == node2)
|
else if (workingRes->re_thisEl->rr_connection2 == node2)
|
||||||
{
|
|
||||||
workingRes->re_thisEl->rr_connection2 = node1;
|
workingRes->re_thisEl->rr_connection2 = node1;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
TxError("Resistor not found.\n");
|
TxError("Resistor not found.\n");
|
||||||
}
|
|
||||||
tRes = workingRes;
|
tRes = workingRes;
|
||||||
workingRes = workingRes->re_nextEl;
|
workingRes = workingRes->re_nextEl;
|
||||||
tRes->re_nextEl = node1->rn_re;
|
tRes->re_nextEl = node1->rn_re;
|
||||||
node1->rn_re = tRes;
|
node1->rn_re = tRes;
|
||||||
}
|
}
|
||||||
if ((node2->rn_status & FINISHED) == FINISHED)
|
if ((node2->rn_status & FINISHED) == FINISHED)
|
||||||
{
|
|
||||||
ResRemoveFromQueue(node2, doneList);
|
ResRemoveFromQueue(node2, doneList);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
ResRemoveFromQueue(node2, pendingList);
|
ResRemoveFromQueue(node2, pendingList);
|
||||||
}
|
|
||||||
if (node2->rn_client != (ClientData)NULL)
|
if (node2->rn_client != (ClientData)NULL)
|
||||||
{
|
{
|
||||||
freeMagic((char *)node2->rn_client);
|
freeMagic((char *)node2->rn_client);
|
||||||
node2->rn_client = (ClientData)NULL;
|
node2->rn_client = (ClientData)NULL;
|
||||||
}
|
}
|
||||||
{
|
|
||||||
node2->rn_re = (resElement *)CLIENTDEFAULT;
|
node2->rn_re = (resElement *)CLIENTDEFAULT;
|
||||||
node2->rn_ce = (cElement *)CLIENTDEFAULT;
|
node2->rn_ce = (cElement *)CLIENTDEFAULT;
|
||||||
node2->rn_je = (jElement *)CLIENTDEFAULT;
|
node2->rn_je = (jElement *)CLIENTDEFAULT;
|
||||||
node2->rn_te = (tElement *)CLIENTDEFAULT;
|
node2->rn_te = (tElement *)CLIENTDEFAULT;
|
||||||
node2->rn_more = (resNode *)CLIENTDEFAULT;
|
node2->rn_more = (resNode *)CLIENTDEFAULT;
|
||||||
node2->rn_less = (resNode *)CLIENTDEFAULT;
|
node2->rn_less = (resNode *)CLIENTDEFAULT;
|
||||||
}
|
|
||||||
freeMagic((char *)node2);
|
freeMagic((char *)node2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -835,12 +810,10 @@ ResDeleteResPointer(node,resistor)
|
||||||
{
|
{
|
||||||
notfound = FALSE;
|
notfound = FALSE;
|
||||||
if (rcell1 != NULL)
|
if (rcell1 != NULL)
|
||||||
{
|
|
||||||
rcell1->re_nextEl = rcell2->re_nextEl;
|
rcell1->re_nextEl = rcell2->re_nextEl;
|
||||||
}else
|
else
|
||||||
{
|
|
||||||
node->rn_re = rcell2->re_nextEl;
|
node->rn_re = rcell2->re_nextEl;
|
||||||
}
|
|
||||||
/* Set fields to null just in case there are any stray */
|
/* Set fields to null just in case there are any stray */
|
||||||
/* pointers to structure. */
|
/* pointers to structure. */
|
||||||
rcell2->re_thisEl = NULL;
|
rcell2->re_thisEl = NULL;
|
||||||
|
|
@ -852,11 +825,9 @@ ResDeleteResPointer(node,resistor)
|
||||||
rcell2 = rcell2->re_nextEl;
|
rcell2 = rcell2->re_nextEl;
|
||||||
}
|
}
|
||||||
if (notfound)
|
if (notfound)
|
||||||
{
|
|
||||||
TxError("Missing rptr at (%d %d).\n",
|
TxError("Missing rptr at (%d %d).\n",
|
||||||
node->rn_loc.p_x, node->rn_loc.p_y);
|
node->rn_loc.p_x, node->rn_loc.p_y);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -878,19 +849,16 @@ ResEliminateResistor(resistor,homelist)
|
||||||
|
|
||||||
{
|
{
|
||||||
if (resistor->rr_lastResistor == NULL)
|
if (resistor->rr_lastResistor == NULL)
|
||||||
{
|
|
||||||
*homelist = resistor->rr_nextResistor;
|
*homelist = resistor->rr_nextResistor;
|
||||||
}else
|
else
|
||||||
{
|
|
||||||
resistor->rr_lastResistor->rr_nextResistor = resistor->rr_nextResistor;
|
resistor->rr_lastResistor->rr_nextResistor = resistor->rr_nextResistor;
|
||||||
}
|
|
||||||
if (resistor->rr_nextResistor != NULL)
|
if (resistor->rr_nextResistor != NULL)
|
||||||
{
|
|
||||||
resistor->rr_nextResistor->rr_lastResistor = resistor->rr_lastResistor;
|
resistor->rr_nextResistor->rr_lastResistor = resistor->rr_lastResistor;
|
||||||
}
|
|
||||||
|
|
||||||
/* set everything to null so that any stray pointers will cause */
|
/* set everything to null so that any stray pointers will cause */
|
||||||
/* immediate death instead of a slow lingering one. */
|
/* immediate death instead of a slow lingering one. */
|
||||||
|
|
||||||
resistor->rr_nextResistor = NULL;
|
resistor->rr_nextResistor = NULL;
|
||||||
resistor->rr_lastResistor = NULL;
|
resistor->rr_lastResistor = NULL;
|
||||||
resistor->rr_connection1 = NULL;
|
resistor->rr_connection1 = NULL;
|
||||||
|
|
@ -898,7 +866,6 @@ ResEliminateResistor(resistor,homelist)
|
||||||
freeMagic((char *)resistor);
|
freeMagic((char *)resistor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -960,36 +927,26 @@ ResCleanNode(resptr,junk,homelist1,homelist2)
|
||||||
freeMagic((char *)rcell);
|
freeMagic((char *)rcell);
|
||||||
}
|
}
|
||||||
if (resptr->rn_less != NULL)
|
if (resptr->rn_less != NULL)
|
||||||
{
|
|
||||||
resptr->rn_less->rn_more = resptr->rn_more;
|
resptr->rn_less->rn_more = resptr->rn_more;
|
||||||
}else
|
|
||||||
{
|
|
||||||
if (*homelist1 == resptr)
|
|
||||||
{
|
|
||||||
*homelist1 = resptr->rn_more;
|
|
||||||
}
|
|
||||||
else if (*homelist2 == resptr)
|
|
||||||
{
|
|
||||||
*homelist2 = resptr->rn_more;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (*homelist1 == resptr)
|
||||||
|
*homelist1 = resptr->rn_more;
|
||||||
|
else if (*homelist2 == resptr)
|
||||||
|
*homelist2 = resptr->rn_more;
|
||||||
|
else
|
||||||
TxError("Error: Attempted to eliminate node from wrong list.\n");
|
TxError("Error: Attempted to eliminate node from wrong list.\n");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (resptr->rn_more != NULL)
|
if (resptr->rn_more != NULL)
|
||||||
{
|
|
||||||
resptr->rn_more->rn_less = resptr->rn_less;
|
resptr->rn_more->rn_less = resptr->rn_less;
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
resptr->rn_re = (resElement *) CLIENTDEFAULT;
|
resptr->rn_re = (resElement *) CLIENTDEFAULT;
|
||||||
resptr->rn_ce = (cElement *) CLIENTDEFAULT;
|
resptr->rn_ce = (cElement *) CLIENTDEFAULT;
|
||||||
resptr->rn_je = (jElement *) CLIENTDEFAULT;
|
resptr->rn_je = (jElement *) CLIENTDEFAULT;
|
||||||
resptr->rn_te = (tElement *) CLIENTDEFAULT;
|
resptr->rn_te = (tElement *) CLIENTDEFAULT;
|
||||||
resptr->rn_more = (resNode *) CLIENTDEFAULT;
|
resptr->rn_more = (resNode *) CLIENTDEFAULT;
|
||||||
resptr->rn_less = (resNode *) CLIENTDEFAULT;
|
resptr->rn_less = (resNode *) CLIENTDEFAULT;
|
||||||
}
|
|
||||||
freeMagic((char *)resptr);
|
freeMagic((char *)resptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1036,28 +993,23 @@ ResFixBreakPoint(sourcelist,origNode,newNode)
|
||||||
if (alreadypresent)
|
if (alreadypresent)
|
||||||
{
|
{
|
||||||
if (bp2 == NULL)
|
if (bp2 == NULL)
|
||||||
{
|
|
||||||
*sourcelist = bp->br_next;
|
*sourcelist = bp->br_next;
|
||||||
}else
|
else
|
||||||
{
|
|
||||||
bp2->br_next = bp->br_next;
|
bp2->br_next = bp->br_next;
|
||||||
}
|
|
||||||
bp3 = bp;
|
bp3 = bp;
|
||||||
bp = bp->br_next;
|
bp = bp->br_next;
|
||||||
|
|
||||||
if (bp3->br_crect != NULL && bp4->br_crect == NULL)
|
if (bp3->br_crect != NULL && bp4->br_crect == NULL)
|
||||||
{
|
|
||||||
bp4->br_crect = bp3->br_crect;
|
bp4->br_crect = bp3->br_crect;
|
||||||
}
|
|
||||||
freeMagic((char *)bp3);
|
freeMagic((char *)bp3);
|
||||||
continue;
|
continue;
|
||||||
}else
|
|
||||||
{
|
|
||||||
(bp->br_this = newNode);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
bp->br_this = newNode;
|
||||||
}
|
}
|
||||||
bp2 = bp;
|
bp2 = bp;
|
||||||
bp = bp->br_next;
|
bp = bp->br_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -171,16 +171,25 @@ ResPrintExtDev(outextfile, devices)
|
||||||
else
|
else
|
||||||
fprintf(outextfile, " \"%s\"", subsName);
|
fprintf(outextfile, " \"%s\"", subsName);
|
||||||
|
|
||||||
fprintf(outextfile, " \"%s\" %d %s \"%s\" %d %s \"%s\" %d %s\n",
|
if (devices->gate != NULL)
|
||||||
|
fprintf(outextfile, " \"%s\" %d %s",
|
||||||
devices->gate->name,
|
devices->gate->name,
|
||||||
devices->layout->rd_length * 2,
|
devices->layout->rd_length * 2,
|
||||||
devices->rs_gattr,
|
devices->rs_gattr);
|
||||||
|
|
||||||
|
if (devices->source != NULL)
|
||||||
|
fprintf(outextfile, " \"%s\" %d %s",
|
||||||
devices->source->name,
|
devices->source->name,
|
||||||
devices->layout->rd_width,
|
devices->layout->rd_width,
|
||||||
devices->rs_sattr,
|
devices->rs_sattr);
|
||||||
|
|
||||||
|
if (devices->drain != NULL)
|
||||||
|
fprintf(outextfile, " \"%s\" %d %s",
|
||||||
devices->drain->name,
|
devices->drain->name,
|
||||||
devices->layout->rd_width,
|
devices->layout->rd_width,
|
||||||
devices->rs_dattr);
|
devices->rs_dattr);
|
||||||
|
|
||||||
|
fprintf(outextfile, "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,6 @@ ResFixPoint *ResFixList;
|
||||||
|
|
||||||
extern void ResSimProcessDrivePoints();
|
extern void ResSimProcessDrivePoints();
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -133,11 +132,11 @@ ResReadSim(simfile, fetproc, capproc, resproc, attrproc, mergeproc, subproc)
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
{
|
{
|
||||||
TxError("Cannot open file %s%s\n", simfile, ".sim");
|
TxError("Cannot open file %s%s\n", simfile, ".sim");
|
||||||
return(1);
|
return 1;
|
||||||
}
|
}
|
||||||
extfile = 0;
|
extfile = 0;
|
||||||
|
|
||||||
/*read in file */
|
/* Read in file */
|
||||||
while (gettokens(line, fp) != 0)
|
while (gettokens(line, fp) != 0)
|
||||||
{
|
{
|
||||||
fettype = MINFINITY;
|
fettype = MINFINITY;
|
||||||
|
|
@ -151,34 +150,45 @@ ResReadSim(simfile, fetproc, capproc, resproc, attrproc, mergeproc, subproc)
|
||||||
}
|
}
|
||||||
result=0;
|
result=0;
|
||||||
break;
|
break;
|
||||||
case 'e': fettype = DBTechNameType("efet");
|
case 'e':
|
||||||
|
fettype = DBTechNameType("efet");
|
||||||
break;
|
break;
|
||||||
case 'd': fettype = DBTechNameType("dfet");
|
case 'd':
|
||||||
|
fettype = DBTechNameType("dfet");
|
||||||
break;
|
break;
|
||||||
case 'n': fettype = DBTechNameType("nfet");
|
case 'n':
|
||||||
|
fettype = DBTechNameType("nfet");
|
||||||
break;
|
break;
|
||||||
case 'p': fettype = DBTechNameType("pfet");
|
case 'p':
|
||||||
|
fettype = DBTechNameType("pfet");
|
||||||
break;
|
break;
|
||||||
case 'b': fettype = DBTechNameType("bnpn");
|
case 'b':
|
||||||
|
fettype = DBTechNameType("bnpn");
|
||||||
break;
|
break;
|
||||||
case 'C': if (capproc) result = (*capproc)(line);
|
case 'C':
|
||||||
|
if (capproc) result = (*capproc)(line);
|
||||||
break;
|
break;
|
||||||
case 'R': if (resproc)result = (*resproc)(line);
|
case 'R':
|
||||||
|
if (resproc) result = (*resproc)(line);
|
||||||
break;
|
break;
|
||||||
case '=': if (mergeproc)result = (*mergeproc)(line);
|
case '=':
|
||||||
|
if (mergeproc) result = (*mergeproc)(line);
|
||||||
break;
|
break;
|
||||||
case 'A': if (attrproc) result =
|
case 'A':
|
||||||
(*attrproc)(line[ATTRIBUTENODENAME],
|
if (attrproc)
|
||||||
line[ATTRIBUTEVALUE],
|
result = (*attrproc)(line[ATTRIBUTENODENAME],
|
||||||
simfile, &extfile);
|
line[ATTRIBUTEVALUE], simfile, &extfile);
|
||||||
break;
|
break;
|
||||||
case 'x': fettype = DBNumTypes;
|
case 'x':
|
||||||
|
fettype = DBNumTypes;
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
case 'c':
|
case 'c':
|
||||||
case 'r': break;
|
case 'r':
|
||||||
default: result = 1;
|
break;
|
||||||
(void)fclose(fp);
|
default:
|
||||||
|
result = 1;
|
||||||
|
fclose(fp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (fettype == -1)
|
if (fettype == -1)
|
||||||
|
|
@ -202,10 +212,10 @@ ResReadSim(simfile, fetproc, capproc, resproc, attrproc, mergeproc, subproc)
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
{
|
{
|
||||||
TxError("Error in sim file %s\n", line[0]);
|
TxError("Error in sim file %s\n", line[0]);
|
||||||
return(1);
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(void)fclose(fp);
|
fclose(fp);
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -226,7 +236,6 @@ ResReadSim(simfile, fetproc, capproc, resproc, attrproc, mergeproc, subproc)
|
||||||
int
|
int
|
||||||
ResReadNode(nodefile)
|
ResReadNode(nodefile)
|
||||||
char *nodefile;
|
char *nodefile;
|
||||||
|
|
||||||
{
|
{
|
||||||
char line[MAXLINE][MAXTOKEN];
|
char line[MAXLINE][MAXTOKEN];
|
||||||
FILE *fp, *fopen();
|
FILE *fp, *fopen();
|
||||||
|
|
@ -239,7 +248,7 @@ ResReadNode(nodefile)
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
{
|
{
|
||||||
TxError("Cannot open file %s%s\n", nodefile, ".nodes");
|
TxError("Cannot open file %s%s\n", nodefile, ".nodes");
|
||||||
return(1);
|
return 1;
|
||||||
}
|
}
|
||||||
while (gettokens(line,fp) != 0)
|
while (gettokens(line,fp) != 0)
|
||||||
{
|
{
|
||||||
|
|
@ -259,14 +268,15 @@ ResReadNode(nodefile)
|
||||||
|
|
||||||
if (node->type == -1)
|
if (node->type == -1)
|
||||||
{
|
{
|
||||||
TxError("Bad tile type name in %s.nodes file for node %s\n",nodefile,node->name);
|
TxError("Bad tile type name in %s.nodes file for node %s\n",
|
||||||
|
nodefile, node->name);
|
||||||
TxError("Did you use the newest version of ext2sim?\n");
|
TxError("Did you use the newest version of ext2sim?\n");
|
||||||
(void)fclose(fp);
|
fclose(fp);
|
||||||
return(1);
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(void)fclose(fp);
|
fclose(fp);
|
||||||
return(0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -286,7 +296,6 @@ int
|
||||||
gettokens(line, fp)
|
gettokens(line, fp)
|
||||||
char line[][MAXTOKEN];
|
char line[][MAXTOKEN];
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
{
|
{
|
||||||
int i = 0, j = 0;
|
int i = 0, j = 0;
|
||||||
int c;
|
int c;
|
||||||
|
|
@ -296,10 +305,12 @@ gettokens(line,fp)
|
||||||
switch(c)
|
switch(c)
|
||||||
{
|
{
|
||||||
case ' ':
|
case ' ':
|
||||||
case ' ' : line[i++][j] = '\0';
|
case ' ' :
|
||||||
|
line[i++][j] = '\0';
|
||||||
j = 0;
|
j = 0;
|
||||||
break;
|
break;
|
||||||
default: line[i][j++] = c;
|
default:
|
||||||
|
line[i][j++] = c;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -309,12 +320,10 @@ gettokens(line,fp)
|
||||||
j = 0;
|
j = 0;
|
||||||
}
|
}
|
||||||
for (j = i; j < MAXLINE; j++)
|
for (j = i; j < MAXLINE; j++)
|
||||||
{
|
|
||||||
line[j][0] = '\0';
|
line[j][0] = '\0';
|
||||||
}
|
|
||||||
return(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
|
|
@ -359,6 +368,7 @@ ResSimSubckt(line)
|
||||||
|
|
||||||
ResRDevList = device;
|
ResRDevList = device;
|
||||||
device->layout = NULL;
|
device->layout = NULL;
|
||||||
|
device->source = device->drain = device->gate = device->subs = NULL;
|
||||||
|
|
||||||
/* The last argument is the name of the device */
|
/* The last argument is the name of the device */
|
||||||
for (i = 1; line[i][0] != '\0'; i++);
|
for (i = 1; line[i][0] != '\0'; i++);
|
||||||
|
|
@ -471,25 +481,26 @@ ResSimDevice(line, rpersquare, ttype)
|
||||||
static int nowarning = TRUE;
|
static int nowarning = TRUE;
|
||||||
float lambda;
|
float lambda;
|
||||||
|
|
||||||
device = (RDev *) mallocMagic((unsigned) (sizeof(RDev)));
|
|
||||||
if ((line[RDEV_WIDTH][0] == '\0') || (line[RDEV_LENGTH][0] == '\0'))
|
if ((line[RDEV_WIDTH][0] == '\0') || (line[RDEV_LENGTH][0] == '\0'))
|
||||||
{
|
{
|
||||||
TxError("error in input file:\n");
|
TxError("error in input file:\n");
|
||||||
return(1);
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
device = (RDev *)mallocMagic((unsigned)(sizeof(RDev)));
|
||||||
if (nowarning && rpersquare == 0)
|
if (nowarning && rpersquare == 0)
|
||||||
{
|
{
|
||||||
TxError("Warning- FET resistance not included or set to zero in technology file-\n");
|
TxError("Warning: FET resistance not included or "
|
||||||
|
"set to zero in technology file-\n");
|
||||||
TxError("All driven nodes will be extracted\n");
|
TxError("All driven nodes will be extracted\n");
|
||||||
nowarning = FALSE;
|
nowarning = FALSE;
|
||||||
}
|
}
|
||||||
if (MagAtof(line[RDEV_WIDTH]) != 0)
|
if (MagAtof(line[RDEV_WIDTH]) != 0)
|
||||||
device->resistance = MagAtof(line[RDEV_LENGTH]) * rpersquare/MagAtof(line[RDEV_WIDTH]);
|
device->resistance = MagAtof(line[RDEV_LENGTH]) * rpersquare /
|
||||||
|
MagAtof(line[RDEV_WIDTH]);
|
||||||
else
|
else
|
||||||
device->resistance = 0;
|
device->resistance = 0;
|
||||||
}
|
|
||||||
device->status = FALSE;
|
device->status = FALSE;
|
||||||
device->nextDev = ResRDevList;
|
device->nextDev = ResRDevList;
|
||||||
|
|
||||||
|
|
@ -502,6 +513,8 @@ ResSimDevice(line, rpersquare, ttype)
|
||||||
device->rs_dattr=RDEV_NOATTR;
|
device->rs_dattr=RDEV_NOATTR;
|
||||||
device->rs_ttype = ttype;
|
device->rs_ttype = ttype;
|
||||||
|
|
||||||
|
device->gate = device->source = device->drain = device->subs = NULL;
|
||||||
|
|
||||||
/* sim attributes look like g=a1,a2 */
|
/* sim attributes look like g=a1,a2 */
|
||||||
/* ext attributes are "a1","a2" */
|
/* ext attributes are "a1","a2" */
|
||||||
/* do conversion from one to the other here */
|
/* do conversion from one to the other here */
|
||||||
|
|
@ -530,10 +543,17 @@ ResSimDevice(line, rpersquare, ttype)
|
||||||
strncpy(newattr, tmpattr, k);
|
strncpy(newattr, tmpattr, k);
|
||||||
switch (line[i][0])
|
switch (line[i][0])
|
||||||
{
|
{
|
||||||
case 'g': device->rs_gattr = newattr; break;
|
case 'g':
|
||||||
case 's': device->rs_sattr = newattr; break;
|
device->rs_gattr = newattr;
|
||||||
case 'd': device->rs_dattr = newattr; break;
|
break;
|
||||||
default: TxError("Bad fet attribute\n");
|
case 's':
|
||||||
|
device->rs_sattr = newattr;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
device->rs_dattr = newattr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TxError("Bad fet attribute\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -543,10 +563,9 @@ ResSimDevice(line, rpersquare, ttype)
|
||||||
ResSimNewNode(line[SOURCE], SOURCE, device) +
|
ResSimNewNode(line[SOURCE], SOURCE, device) +
|
||||||
ResSimNewNode(line[DRAIN], DRAIN, device);
|
ResSimNewNode(line[DRAIN], DRAIN, device);
|
||||||
|
|
||||||
return(rvalue);
|
return rvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -573,7 +592,7 @@ ResSimNewNode(line, type, device)
|
||||||
if (line[0] == '\0')
|
if (line[0] == '\0')
|
||||||
{
|
{
|
||||||
TxError("Missing device connection\n");
|
TxError("Missing device connection\n");
|
||||||
return(1);
|
return 1;
|
||||||
}
|
}
|
||||||
entry = HashFind(&ResNodeTable, line);
|
entry = HashFind(&ResNodeTable, line);
|
||||||
node = ResInitializeNode(entry);
|
node = ResInitializeNode(entry);
|
||||||
|
|
@ -584,21 +603,25 @@ ResSimNewNode(line, type, device)
|
||||||
tptr->terminal = type;
|
tptr->terminal = type;
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case GATE: device->gate = node;
|
case GATE:
|
||||||
|
device->gate = node;
|
||||||
break;
|
break;
|
||||||
case SOURCE: device->source = node;
|
case SOURCE:
|
||||||
|
device->source = node;
|
||||||
break;
|
break;
|
||||||
case DRAIN: device->drain = node;
|
case DRAIN:
|
||||||
|
device->drain = node;
|
||||||
break;
|
break;
|
||||||
case SUBS: device->subs = node;
|
case SUBS:
|
||||||
|
device->subs = node;
|
||||||
break;
|
break;
|
||||||
default: TxError("Bad Terminal Specifier\n");
|
default:
|
||||||
|
TxError("Bad Terminal Specifier\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return(0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -635,39 +658,38 @@ ResSimCapacitor(line)
|
||||||
if (strcmp(line[COUPLETERMINAL2], "GND") == 0 ||
|
if (strcmp(line[COUPLETERMINAL2], "GND") == 0 ||
|
||||||
strcmp(line[COUPLETERMINAL2], "Vdd") == 0)
|
strcmp(line[COUPLETERMINAL2], "Vdd") == 0)
|
||||||
{
|
{
|
||||||
return(0);
|
return 0;
|
||||||
}
|
}
|
||||||
entry2 = HashFind(&ResNodeTable, line[COUPLETERMINAL2]);
|
entry2 = HashFind(&ResNodeTable, line[COUPLETERMINAL2]);
|
||||||
node2 = ResInitializeNode(entry2);
|
node2 = ResInitializeNode(entry2);
|
||||||
node2->capacitance += MagAtof(line[COUPLEVALUE]);
|
node2->capacitance += MagAtof(line[COUPLEVALUE]);
|
||||||
return(0);
|
return 0;
|
||||||
}
|
}
|
||||||
if (strcmp(line[COUPLETERMINAL2], "GND") == 0)
|
if (strcmp(line[COUPLETERMINAL2], "GND") == 0)
|
||||||
{
|
{
|
||||||
node1->capacitance += MagAtof(line[COUPLEVALUE]);
|
node1->capacitance += MagAtof(line[COUPLEVALUE]);
|
||||||
return(0);
|
return 0;
|
||||||
}
|
}
|
||||||
if (strcmp(line[COUPLETERMINAL2], "Vdd") == 0)
|
if (strcmp(line[COUPLETERMINAL2], "Vdd") == 0)
|
||||||
{
|
{
|
||||||
node1->cap_vdd += MagAtof(line[COUPLEVALUE]);
|
node1->cap_vdd += MagAtof(line[COUPLEVALUE]);
|
||||||
return(0);
|
return 0;
|
||||||
}
|
}
|
||||||
entry2 = HashFind(&ResNodeTable, line[COUPLETERMINAL2]);
|
entry2 = HashFind(&ResNodeTable, line[COUPLETERMINAL2]);
|
||||||
node2 = ResInitializeNode(entry2);
|
node2 = ResInitializeNode(entry2);
|
||||||
if (strcmp(line[COUPLETERMINAL1], "GND") == 0)
|
if (strcmp(line[COUPLETERMINAL1], "GND") == 0)
|
||||||
{
|
{
|
||||||
node2->capacitance += MagAtof(line[COUPLEVALUE]);
|
node2->capacitance += MagAtof(line[COUPLEVALUE]);
|
||||||
return(0);
|
return 0;
|
||||||
}
|
}
|
||||||
if (strcmp(line[COUPLETERMINAL1], "Vdd") == 0)
|
if (strcmp(line[COUPLETERMINAL1], "Vdd") == 0)
|
||||||
{
|
{
|
||||||
node2->cap_vdd += MagAtof(line[COUPLEVALUE]);
|
node2->cap_vdd += MagAtof(line[COUPLEVALUE]);
|
||||||
return(0);
|
return 0;
|
||||||
}
|
}
|
||||||
node1->cap_couple += MagAtof(line[COUPLEVALUE]);
|
node1->cap_couple += MagAtof(line[COUPLEVALUE]);
|
||||||
node2->cap_couple += MagAtof(line[COUPLEVALUE]);
|
node2->cap_couple += MagAtof(line[COUPLEVALUE]);
|
||||||
return(0);
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -688,7 +710,6 @@ ResSimCapacitor(line)
|
||||||
int
|
int
|
||||||
ResSimResistor(line)
|
ResSimResistor(line)
|
||||||
char line[][MAXTOKEN];
|
char line[][MAXTOKEN];
|
||||||
|
|
||||||
{
|
{
|
||||||
HashEntry *entry;
|
HashEntry *entry;
|
||||||
ResSimNode *node;
|
ResSimNode *node;
|
||||||
|
|
@ -696,21 +717,19 @@ ResSimResistor(line)
|
||||||
if (line[RESNODENAME][0] == 0)
|
if (line[RESNODENAME][0] == 0)
|
||||||
{
|
{
|
||||||
TxError("Bad Resistor\n");
|
TxError("Bad Resistor\n");
|
||||||
return(1);
|
return 1;
|
||||||
}
|
}
|
||||||
entry = HashFind(&ResNodeTable, line[RESNODENAME]);
|
entry = HashFind(&ResNodeTable, line[RESNODENAME]);
|
||||||
node = ResInitializeNode(entry);
|
node = ResInitializeNode(entry);
|
||||||
if (node->resistance != 0)
|
if (node->resistance != 0)
|
||||||
{
|
{
|
||||||
TxError("Duplicate Resistance Entries\n");
|
TxError("Duplicate Resistance Entries\n");
|
||||||
return(1);
|
return 1;
|
||||||
}
|
}
|
||||||
node->resistance = MagAtof(line[NODERESISTANCE]);
|
node->resistance = MagAtof(line[NODERESISTANCE]);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -741,7 +760,7 @@ ResSimAttribute(aname,avalue,rootname,readextfile)
|
||||||
if (aname[0] == 0)
|
if (aname[0] == 0)
|
||||||
{
|
{
|
||||||
TxError("Bad Resistor\n");
|
TxError("Bad Resistor\n");
|
||||||
return(1);
|
return 1;
|
||||||
}
|
}
|
||||||
entry = HashFind(&ResNodeTable, aname);
|
entry = HashFind(&ResNodeTable, aname);
|
||||||
node = ResInitializeNode(entry);
|
node = ResInitializeNode(entry);
|
||||||
|
|
@ -793,7 +812,8 @@ ResSimAttribute(aname,avalue,rootname,readextfile)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (notwarned)
|
if (notwarned)
|
||||||
TxError("Drivepoint for %s not defined in %s.ext; is it defined in a child cell?\n",node->name,rootname);
|
TxError("Drivepoint for %s not defined in %s.ext; is it "
|
||||||
|
"defined in a child cell?\n", node->name, rootname);
|
||||||
notwarned = FALSE;
|
notwarned = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -810,12 +830,11 @@ ResSimAttribute(aname,avalue,rootname,readextfile)
|
||||||
#endif
|
#endif
|
||||||
if (avalue = strchr(avalue, ','))
|
if (avalue = strchr(avalue, ','))
|
||||||
{
|
{
|
||||||
(void) ResSimAttribute(aname,avalue+1,rootname,readextfile);
|
ResSimAttribute(aname, avalue + 1, rootname, readextfile);
|
||||||
}
|
}
|
||||||
return(0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -853,7 +872,8 @@ ResSimProcessDrivePoints(filename)
|
||||||
while (gettokens(line,fp) != 0)
|
while (gettokens(line,fp) != 0)
|
||||||
{
|
{
|
||||||
if (strncmp(line[RES_EXT_ATTR], "attr", 4) != 0 ||
|
if (strncmp(line[RES_EXT_ATTR], "attr", 4) != 0 ||
|
||||||
strncmp(line[RES_EXT_ATTR_TEXT],"\"res:drive\"",11) != 0) continue;
|
strncmp(line[RES_EXT_ATTR_TEXT], "\"res:drive\"", 11) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
entry = HashFind(&ResNodeTable, line[RES_EXT_ATTR_NAME]);
|
entry = HashFind(&ResNodeTable, line[RES_EXT_ATTR_NAME]);
|
||||||
node = ResInitializeNode(entry);
|
node = ResInitializeNode(entry);
|
||||||
|
|
@ -863,7 +883,6 @@ ResSimProcessDrivePoints(filename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -899,19 +918,20 @@ ResSimProcessFixPoints(filename)
|
||||||
while (gettokens(line, fp) != 0)
|
while (gettokens(line, fp) != 0)
|
||||||
{
|
{
|
||||||
if (strncmp(line[RES_EXT_ATTR], "attr", 4) != 0 ||
|
if (strncmp(line[RES_EXT_ATTR], "attr", 4) != 0 ||
|
||||||
strncmp(line[RES_EXT_ATTR_TEXT],"\"res:fix",8) != 0) continue;
|
strncmp(line[RES_EXT_ATTR_TEXT], "\"res:fix", 8) != 0)
|
||||||
|
continue;
|
||||||
label = line[RES_EXT_ATTR_TEXT];
|
label = line[RES_EXT_ATTR_TEXT];
|
||||||
label += 8;
|
label += 8;
|
||||||
if (*label == ':') label++;
|
if (*label == ':') label++;
|
||||||
if ((c=strrchr(label, '"')) != NULL) *c = '\0';
|
if ((c=strrchr(label, '"')) != NULL) *c = '\0';
|
||||||
else if (*label == '\0');
|
else if (*label != '\0')
|
||||||
else
|
|
||||||
{
|
{
|
||||||
TxError("Bad res:fix attribute label %s\n",
|
TxError("Bad res:fix attribute label %s\n",
|
||||||
line[RES_EXT_ATTR_TEXT]);
|
line[RES_EXT_ATTR_TEXT]);
|
||||||
*label ='\0';
|
*label ='\0';
|
||||||
}
|
}
|
||||||
thisfix = (ResFixPoint *) mallocMagic((unsigned) (sizeof(ResFixPoint)+strlen(label)));
|
thisfix = (ResFixPoint *)mallocMagic((unsigned)(sizeof(ResFixPoint)
|
||||||
|
+ strlen(label)));
|
||||||
thisfix->fp_next = ResFixList;
|
thisfix->fp_next = ResFixList;
|
||||||
ResFixList = thisfix;
|
ResFixList = thisfix;
|
||||||
thisfix->fp_loc.p_x = atoi(line[RES_EXT_ATTR_X]);
|
thisfix->fp_loc.p_x = atoi(line[RES_EXT_ATTR_X]);
|
||||||
|
|
@ -962,7 +982,7 @@ ResSimMerge(line)
|
||||||
ptr->nextDev = node->forward->firstDev;
|
ptr->nextDev = node->forward->firstDev;
|
||||||
node->forward->firstDev = ptr;
|
node->forward->firstDev = ptr;
|
||||||
}
|
}
|
||||||
return(0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1011,5 +1031,5 @@ ResInitializeNode(entry)
|
||||||
{
|
{
|
||||||
node = node->forward;
|
node = node->forward;
|
||||||
}
|
}
|
||||||
return(node);
|
return node;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -264,6 +264,17 @@ typedef enum {
|
||||||
init = 0;
|
init = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize ResGlobalParams */
|
||||||
|
gparams.rg_ttype = TT_SPACE;
|
||||||
|
gparams.rg_Tdi = 0.0;
|
||||||
|
gparams.rg_nodecap = 0.0;
|
||||||
|
gparams.rg_maxres = 0.0;
|
||||||
|
gparams.rg_bigdevres = 0;
|
||||||
|
gparams.rg_tilecount = 0;
|
||||||
|
gparams.rg_status = 0;
|
||||||
|
gparams.rg_devloc = NULL;
|
||||||
|
gparams.rg_name = NULL;
|
||||||
|
|
||||||
option = (cmd->tx_argc > 1) ? Lookup(cmd->tx_argv[1], cmdExtresisCmd)
|
option = (cmd->tx_argc > 1) ? Lookup(cmd->tx_argv[1], cmdExtresisCmd)
|
||||||
: RES_RUN;
|
: RES_RUN;
|
||||||
|
|
||||||
|
|
@ -979,7 +990,7 @@ ResCheckSimNodes(celldef, resisdata)
|
||||||
t1->drain != t2->source)) break;
|
t1->drain != t2->source)) break;
|
||||||
|
|
||||||
/* do parallel combination */
|
/* do parallel combination */
|
||||||
if (cumRes != 0.0 && t2->resistance != 0.0)
|
if ((cumRes != 0.0) && (t2->resistance != 0.0))
|
||||||
{
|
{
|
||||||
cumRes = (cumRes * t2->resistance) /
|
cumRes = (cumRes * t2->resistance) /
|
||||||
(cumRes + t2->resistance);
|
(cumRes + t2->resistance);
|
||||||
|
|
@ -1023,17 +1034,17 @@ ResCheckSimNodes(celldef, resisdata)
|
||||||
gparams.rg_ttype = node->rs_ttype;
|
gparams.rg_ttype = node->rs_ttype;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (gparams.rg_devloc == NULL && node->status & FORCE)
|
if ((gparams.rg_devloc == NULL) && (node->status & FORCE))
|
||||||
{
|
{
|
||||||
TxError("Node %s has force label but no drive point or "
|
TxError("Node %s has force label but no drive point or "
|
||||||
"driving device\n",node->name);
|
"driving device\n",node->name);
|
||||||
}
|
}
|
||||||
if (minRes == FLT_MAX || gparams.rg_devloc == NULL)
|
if ((minRes == FLT_MAX) || (gparams.rg_devloc == NULL))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
gparams.rg_bigdevres = (int)minRes * OHMSTOMILLIOHMS;
|
gparams.rg_bigdevres = (int)minRes * OHMSTOMILLIOHMS;
|
||||||
if (rctol == 0.0 || tol == 0.0)
|
if ((rctol == 0.0) || (tol == 0.0))
|
||||||
{
|
{
|
||||||
ftolerance = 0.0;
|
ftolerance = 0.0;
|
||||||
rctolerance = 0.0;
|
rctolerance = 0.0;
|
||||||
|
|
@ -1049,7 +1060,7 @@ ResCheckSimNodes(celldef, resisdata)
|
||||||
* resistance? If so, extract net.
|
* resistance? If so, extract net.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (node->resistance > ftolerance || node->status & FORCE ||
|
if ((node->resistance > ftolerance) || (node->status & FORCE) ||
|
||||||
(ResOpt_ExtractAll & ResOptionsFlags))
|
(ResOpt_ExtractAll & ResOptionsFlags))
|
||||||
{
|
{
|
||||||
ResFixPoint fp;
|
ResFixPoint fp;
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,6 @@ int resRemoveLoops = FALSE;
|
||||||
extern void ResMoveDevices();
|
extern void ResMoveDevices();
|
||||||
extern void ResAddResistorToList();
|
extern void ResAddResistorToList();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -75,27 +73,26 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
|
||||||
resNode *node, *otherNode, *node1, *node2;
|
resNode *node, *otherNode, *node1, *node2;
|
||||||
resResistor *resistor1 = NULL, *resistor2 = NULL;
|
resResistor *resistor1 = NULL, *resistor2 = NULL;
|
||||||
int numdrive = 0, numreceive = 0;
|
int numdrive = 0, numreceive = 0;
|
||||||
int MarkedReceivers,UnMarkedReceivers,NumberOfDrivers,PendingReceivers;
|
int MarkedReceivers, UnMarkedReceivers;
|
||||||
|
int NumberOfDrivers, PendingReceivers;
|
||||||
|
|
||||||
if (*nodelist == NULL) return;
|
if (*nodelist == NULL) return;
|
||||||
node = *nodelist;
|
node = *nodelist;
|
||||||
node->rn_status |= MARKED | FINISHED;
|
node->rn_status |= MARKED | FINISHED;
|
||||||
*nodelist = node->rn_more;
|
*nodelist = node->rn_more;
|
||||||
if (node->rn_more != NULL)
|
if (node->rn_more != NULL)
|
||||||
{
|
|
||||||
node->rn_more->rn_less = (resNode *) NULL;
|
node->rn_more->rn_less = (resNode *) NULL;
|
||||||
}
|
|
||||||
node->rn_more = *biglist;
|
node->rn_more = *biglist;
|
||||||
if (*biglist != (resNode *) NULL)
|
if (*biglist != (resNode *) NULL)
|
||||||
{
|
|
||||||
(*biglist)->rn_less = node;
|
(*biglist)->rn_less = node;
|
||||||
}
|
|
||||||
*biglist = node;
|
*biglist = node;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Walk though resistors. Mark uninitialized ones and assign them
|
* Walk though resistors. Mark uninitialized ones and assign them
|
||||||
A direction. Keep track of the number of resistors pointing in
|
* a direction. Keep track of the number of resistors pointing in
|
||||||
each direction.
|
* each direction.
|
||||||
*/
|
*/
|
||||||
for (resisptr = node->rn_re; resisptr != NULL; resisptr = resisptr->re_nextEl)
|
for (resisptr = node->rn_re; resisptr != NULL; resisptr = resisptr->re_nextEl)
|
||||||
{
|
{
|
||||||
|
|
@ -103,65 +100,64 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
|
||||||
(resisptr->re_thisEl->rr_connection2 == node))
|
(resisptr->re_thisEl->rr_connection2 == node))
|
||||||
{
|
{
|
||||||
if (resistor1 == NULL)
|
if (resistor1 == NULL)
|
||||||
{
|
|
||||||
resistor1 = resisptr->re_thisEl;
|
resistor1 = resisptr->re_thisEl;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
resistor2 = resisptr->re_thisEl;
|
resistor2 = resisptr->re_thisEl;
|
||||||
}
|
|
||||||
numdrive++;
|
numdrive++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Resistor direction is from node1 to node2. If the resistor
|
* Resistor direction is from node1 to node2. If the resistor
|
||||||
is not marked, mark it and make sure the direction is
|
* is not marked, mark it and make sure the direction is
|
||||||
set properly.
|
* set properly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((resisptr->re_thisEl->rr_status & RES_MARKED) != RES_MARKED)
|
if ((resisptr->re_thisEl->rr_status & RES_MARKED) != RES_MARKED)
|
||||||
{
|
{
|
||||||
if (resisptr->re_thisEl->rr_connection2 == node)
|
if (resisptr->re_thisEl->rr_connection2 == node)
|
||||||
{
|
{
|
||||||
resisptr->re_thisEl->rr_connection2 = resisptr->re_thisEl->rr_connection1;
|
resisptr->re_thisEl->rr_connection2 =
|
||||||
|
resisptr->re_thisEl->rr_connection1;
|
||||||
resisptr->re_thisEl->rr_connection1 = node;
|
resisptr->re_thisEl->rr_connection1 = node;
|
||||||
}
|
}
|
||||||
resisptr->re_thisEl->rr_status |= RES_MARKED;
|
resisptr->re_thisEl->rr_status |= RES_MARKED;
|
||||||
}
|
}
|
||||||
if (resistor1 == NULL)
|
if (resistor1 == NULL)
|
||||||
{
|
|
||||||
resistor1 = resisptr->re_thisEl;
|
resistor1 = resisptr->re_thisEl;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
resistor2 = resisptr->re_thisEl;
|
resistor2 = resisptr->re_thisEl;
|
||||||
}
|
|
||||||
numreceive++;
|
numreceive++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Is the node reached by one resistor? If it is, check the resistor's
|
* Is the node reached by one resistor? If it is, check the resistor's
|
||||||
other end. Check the number of drivers at the other end. If it is
|
* other end. Check the number of drivers at the other end. If it is
|
||||||
more than 1, delete the current resistor to break the deadlock.
|
* more than 1, delete the current resistor to break the deadlock.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (numreceive == 0 && numdrive == 1 && node->rn_why != RES_NODE_ORIGIN)
|
if (numreceive == 0 && numdrive == 1 && node->rn_why != RES_NODE_ORIGIN)
|
||||||
{
|
{
|
||||||
resistor1->rr_status |= RES_DEADEND;
|
resistor1->rr_status |= RES_DEADEND;
|
||||||
if (resistor1->rr_value < tolerance)
|
if (resistor1->rr_value < tolerance)
|
||||||
{
|
{
|
||||||
otherNode = (resistor1->rr_connection1 == node) ? resistor1->rr_connection2 : resistor1->rr_connection1;
|
otherNode = (resistor1->rr_connection1 == node) ?
|
||||||
|
resistor1->rr_connection2 : resistor1->rr_connection1;
|
||||||
MarkedReceivers = 0;
|
MarkedReceivers = 0;
|
||||||
UnMarkedReceivers = 0;
|
UnMarkedReceivers = 0;
|
||||||
NumberOfDrivers = 0;
|
NumberOfDrivers = 0;
|
||||||
PendingReceivers = 0;
|
PendingReceivers = 0;
|
||||||
resistor2 = resistor1;
|
resistor2 = resistor1;
|
||||||
for (resisptr = otherNode->rn_re; resisptr != NULL; resisptr=resisptr->re_nextEl)
|
for (resisptr = otherNode->rn_re; resisptr != NULL;
|
||||||
|
resisptr = resisptr->re_nextEl)
|
||||||
{
|
{
|
||||||
if (resisptr->re_thisEl->rr_connection1 == otherNode)
|
if (resisptr->re_thisEl->rr_connection1 == otherNode)
|
||||||
{
|
{
|
||||||
if ((resisptr->re_thisEl->rr_connection2->rn_status & MARKED) != MARKED)
|
if ((resisptr->re_thisEl->rr_connection2->rn_status & MARKED)
|
||||||
|
!= MARKED)
|
||||||
{
|
{
|
||||||
PendingReceivers++;
|
PendingReceivers++;
|
||||||
}
|
}
|
||||||
|
|
@ -169,23 +165,21 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
|
||||||
resisptr->re_thisEl->rr_value > tolerance)
|
resisptr->re_thisEl->rr_value > tolerance)
|
||||||
{
|
{
|
||||||
MarkedReceivers++;
|
MarkedReceivers++;
|
||||||
resistor2 = (resisptr->re_thisEl->rr_value >= resistor2->rr_value) ? resisptr->re_thisEl : resistor2;
|
resistor2 = (resisptr->re_thisEl->rr_value >=
|
||||||
|
resistor2->rr_value) ? resisptr->re_thisEl : resistor2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
UnMarkedReceivers++;
|
UnMarkedReceivers++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
NumberOfDrivers++;
|
NumberOfDrivers++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
/* other recievers at far end? If so, reschedule other node;
|
/* other recievers at far end? If so, reschedule other node;
|
||||||
deadlock will be settled from that node.
|
* deadlock will be settled from that node.
|
||||||
*/
|
*/
|
||||||
if ((MarkedReceivers+UnMarkedReceivers+NumberOfDrivers == 2) ||
|
if ((MarkedReceivers+UnMarkedReceivers+NumberOfDrivers == 2) ||
|
||||||
(UnMarkedReceivers == 0 && MarkedReceivers > 1 && resistor2 == resistor1 && PendingReceivers == 0))
|
(UnMarkedReceivers == 0 && MarkedReceivers > 1 &&
|
||||||
|
resistor2 == resistor1 && PendingReceivers == 0))
|
||||||
{
|
{
|
||||||
if (otherNode->rn_status & MARKED)
|
if (otherNode->rn_status & MARKED)
|
||||||
{
|
{
|
||||||
|
|
@ -194,19 +188,19 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
|
||||||
otherNode->rn_less = NULL;
|
otherNode->rn_less = NULL;
|
||||||
otherNode->rn_more = *nodelist;
|
otherNode->rn_more = *nodelist;
|
||||||
if (*nodelist != NULL)
|
if (*nodelist != NULL)
|
||||||
{
|
|
||||||
(*nodelist)->rn_less = otherNode;
|
(*nodelist)->rn_less = otherNode;
|
||||||
}
|
|
||||||
*nodelist = otherNode;
|
*nodelist = otherNode;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Break loop here. More than one driver indicates a loop;
|
* Break loop here. More than one driver indicates a loop;
|
||||||
remove deadend, allowing drivers to be merged
|
* remove deadend, allowing drivers to be merged
|
||||||
*/
|
*/
|
||||||
else if (UnMarkedReceivers == 0 && (MarkedReceivers == 1 && NumberOfDrivers > 1 || resistor2 != resistor1))
|
else if (UnMarkedReceivers == 0 && (MarkedReceivers == 1 &&
|
||||||
|
NumberOfDrivers > 1 || resistor2 != resistor1))
|
||||||
|
|
||||||
{
|
{
|
||||||
otherNode->rn_float.rn_area += resistor1->rr_float.rr_area;
|
otherNode->rn_float.rn_area += resistor1->rr_float.rr_area;
|
||||||
|
|
@ -222,77 +216,73 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
|
||||||
otherNode->rn_less= NULL;
|
otherNode->rn_less= NULL;
|
||||||
otherNode->rn_more = *nodelist;
|
otherNode->rn_more = *nodelist;
|
||||||
if (*nodelist != NULL)
|
if (*nodelist != NULL)
|
||||||
{
|
|
||||||
(*nodelist)->rn_less = otherNode;
|
(*nodelist)->rn_less = otherNode;
|
||||||
}
|
|
||||||
*nodelist = otherNode;
|
*nodelist = otherNode;
|
||||||
}
|
}
|
||||||
ResDoneWithNode(otherNode);
|
ResDoneWithNode(otherNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
Two resistors in series? Combine them and move devices to
|
* Two resistors in series? Combine them and move devices to
|
||||||
appropriate end.
|
* appropriate end.
|
||||||
*/
|
*/
|
||||||
else if (numdrive+numreceive == 2 &&
|
else if (numdrive+numreceive == 2 && (resistor1->rr_value < tolerance &&
|
||||||
(resistor1->rr_value < tolerance && resistor2->rr_value < tolerance))
|
resistor2->rr_value < tolerance))
|
||||||
{
|
{
|
||||||
if ((resistor1->rr_status & RES_MARKED) == 0 && (resistor1->rr_connection2 == node))
|
if ((resistor1->rr_status & RES_MARKED) == 0 &&
|
||||||
|
(resistor1->rr_connection2 == node))
|
||||||
{
|
{
|
||||||
resistor1->rr_connection2 = resistor1->rr_connection1;
|
resistor1->rr_connection2 = resistor1->rr_connection1;
|
||||||
resistor1->rr_connection1 = node;
|
resistor1->rr_connection1 = node;
|
||||||
}
|
}
|
||||||
resistor1->rr_status |= RES_MARKED;
|
resistor1->rr_status |= RES_MARKED;
|
||||||
if ((resistor2->rr_status & RES_MARKED) == 0 && (resistor2->rr_connection2 == node))
|
if ((resistor2->rr_status & RES_MARKED) == 0 &&
|
||||||
|
(resistor2->rr_connection2 == node))
|
||||||
{
|
{
|
||||||
resistor2->rr_connection2 = resistor2->rr_connection1;
|
resistor2->rr_connection2 = resistor2->rr_connection1;
|
||||||
resistor2->rr_connection1 = node;
|
resistor2->rr_connection1 = node;
|
||||||
}
|
}
|
||||||
resistor2->rr_status |= RES_MARKED;
|
resistor2->rr_status |= RES_MARKED;
|
||||||
node1 = (resistor1->rr_connection1 == node) ? resistor1->rr_connection2 : resistor1->rr_connection1;
|
node1 = (resistor1->rr_connection1 == node) ? resistor1->rr_connection2 :
|
||||||
node2 = (resistor2->rr_connection1 == node) ? resistor2->rr_connection2 : resistor2->rr_connection1;
|
resistor1->rr_connection1;
|
||||||
|
node2 = (resistor2->rr_connection1 == node) ? resistor2->rr_connection2 :
|
||||||
|
resistor2->rr_connection1;
|
||||||
otherNode = (resistor1->rr_status & RES_DEADEND &&
|
otherNode = (resistor1->rr_status & RES_DEADEND &&
|
||||||
resistor1->rr_value < tolerance / 2) ||
|
resistor1->rr_value < tolerance / 2) ||
|
||||||
((resistor2->rr_status & RES_DEADEND) == 0 &&
|
((resistor2->rr_status & RES_DEADEND) == 0 &&
|
||||||
resistor1->rr_value < resistor2->rr_value) ? node1 : node2;
|
resistor1->rr_value < resistor2->rr_value) ? node1 : node2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
make one big resistor out of two little ones, eliminating
|
* Make one big resistor out of two little ones, eliminating
|
||||||
the current node. Devices connected to this node are
|
* the current node. Devices connected to this node are
|
||||||
moved to either end depending on their resistance.
|
* moved to either end depending on their resistance.
|
||||||
*/
|
*/
|
||||||
ResMoveDevices(node,otherNode);
|
ResMoveDevices(node,otherNode);
|
||||||
otherNode->rn_noderes = MIN(node->rn_noderes, otherNode->rn_noderes);
|
otherNode->rn_noderes = MIN(node->rn_noderes, otherNode->rn_noderes);
|
||||||
node2->rn_float.rn_area += resistor1->rr_value*node->rn_float.rn_area/(resistor1->rr_value+resistor2->rr_value);
|
node2->rn_float.rn_area += resistor1->rr_value * node->rn_float.rn_area /
|
||||||
node1->rn_float.rn_area += resistor2->rr_value*node->rn_float.rn_area/(resistor1->rr_value+resistor2->rr_value);
|
(resistor1->rr_value + resistor2->rr_value);
|
||||||
|
node1->rn_float.rn_area += resistor2->rr_value * node->rn_float.rn_area /
|
||||||
|
(resistor1->rr_value + resistor2->rr_value);
|
||||||
resistor1->rr_value += resistor2->rr_value;
|
resistor1->rr_value += resistor2->rr_value;
|
||||||
resistor1->rr_float.rr_area +=resistor2->rr_float.rr_area;
|
resistor1->rr_float.rr_area +=resistor2->rr_float.rr_area;
|
||||||
if (resistor1 == *reslist)
|
if (resistor1 == *reslist)
|
||||||
{
|
|
||||||
*reslist = resistor1->rr_nextResistor;
|
*reslist = resistor1->rr_nextResistor;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
resistor1->rr_lastResistor->rr_nextResistor = resistor1->rr_nextResistor;
|
resistor1->rr_lastResistor->rr_nextResistor = resistor1->rr_nextResistor;
|
||||||
}
|
|
||||||
if (resistor1->rr_nextResistor != NULL)
|
if (resistor1->rr_nextResistor != NULL)
|
||||||
{
|
|
||||||
resistor1->rr_nextResistor->rr_lastResistor = resistor1->rr_lastResistor;
|
resistor1->rr_nextResistor->rr_lastResistor = resistor1->rr_lastResistor;
|
||||||
}
|
|
||||||
ResAddResistorToList(resistor1, reslist);
|
ResAddResistorToList(resistor1, reslist);
|
||||||
ResDeleteResPointer(node, resistor1);
|
ResDeleteResPointer(node, resistor1);
|
||||||
ResDeleteResPointer(node, resistor2);
|
ResDeleteResPointer(node, resistor2);
|
||||||
ResDeleteResPointer(node2, resistor2);
|
ResDeleteResPointer(node2, resistor2);
|
||||||
if (resistor1->rr_connection1 == node)
|
if (resistor1->rr_connection1 == node)
|
||||||
{
|
|
||||||
resistor1->rr_connection1 = node2;
|
resistor1->rr_connection1 = node2;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
resistor1->rr_connection2 = node2;
|
resistor1->rr_connection2 = node2;
|
||||||
}
|
|
||||||
resisptr = (resElement *)mallocMagic((unsigned)(sizeof(resElement)));
|
resisptr = (resElement *)mallocMagic((unsigned)(sizeof(resElement)));
|
||||||
resisptr->re_thisEl = resistor1;
|
resisptr->re_thisEl = resistor1;
|
||||||
resisptr->re_nextEl = node2->rn_re;
|
resisptr->re_nextEl = node2->rn_re;
|
||||||
|
|
@ -308,9 +298,7 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
|
||||||
node1->rn_less = NULL;
|
node1->rn_less = NULL;
|
||||||
node1->rn_more = *nodelist;
|
node1->rn_more = *nodelist;
|
||||||
if (*nodelist != NULL)
|
if (*nodelist != NULL)
|
||||||
{
|
|
||||||
(*nodelist)->rn_less = node1;
|
(*nodelist)->rn_less = node1;
|
||||||
}
|
|
||||||
*nodelist = node1;
|
*nodelist = node1;
|
||||||
}
|
}
|
||||||
node2->rn_status &= ~RES_DONE_ONCE;
|
node2->rn_status &= ~RES_DONE_ONCE;
|
||||||
|
|
@ -321,18 +309,16 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
|
||||||
node2->rn_less = NULL;
|
node2->rn_less = NULL;
|
||||||
node2->rn_more = *nodelist;
|
node2->rn_more = *nodelist;
|
||||||
if (*nodelist != NULL)
|
if (*nodelist != NULL)
|
||||||
{
|
|
||||||
(*nodelist)->rn_less = node2;
|
(*nodelist)->rn_less = node2;
|
||||||
}
|
|
||||||
*nodelist = node2;
|
*nodelist = node2;
|
||||||
}
|
}
|
||||||
ResDoneWithNode(node1);
|
ResDoneWithNode(node1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Last resort- keep propagating down the tree. To avoid looping,
|
* Last resort- keep propagating down the tree. To avoid looping,
|
||||||
mark each node when it is reached. Don't reschedule node if
|
* mark each node when it is reached. Don't reschedule node if
|
||||||
none of the connections to it have changed since it was marked
|
* none of the connections to it have changed since it was marked
|
||||||
*/
|
*/
|
||||||
else if (numreceive > 0 && (node->rn_status & RES_DONE_ONCE) == 0)
|
else if (numreceive > 0 && (node->rn_status & RES_DONE_ONCE) == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -342,32 +328,29 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
|
||||||
if (resisptr->re_thisEl->rr_connection1 == node)
|
if (resisptr->re_thisEl->rr_connection1 == node)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
elements with a resistance greater than the
|
* Elements with a resistance greater than the
|
||||||
tolerance should only be propagated past once-
|
* tolerance should only be propagated past once-
|
||||||
loops may occur otherwise.
|
* loops may occur otherwise.
|
||||||
*/
|
*/
|
||||||
if (resisptr->re_thisEl->rr_status & RES_DONE_ONCE)
|
if (resisptr->re_thisEl->rr_status & RES_DONE_ONCE)
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
if (resisptr->re_thisEl->rr_connection2->rn_status & MARKED)
|
if (resisptr->re_thisEl->rr_connection2->rn_status & MARKED)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
mark big resistors so we only process them
|
* Mark big resistors so we only process them
|
||||||
once.
|
* once.
|
||||||
*/
|
*/
|
||||||
if (resisptr->re_thisEl->rr_value > tolerance)
|
if (resisptr->re_thisEl->rr_value > tolerance)
|
||||||
{
|
|
||||||
resisptr->re_thisEl->rr_status |= RES_DONE_ONCE;
|
resisptr->re_thisEl->rr_status |= RES_DONE_ONCE;
|
||||||
}
|
|
||||||
resisptr->re_thisEl->rr_connection2->rn_status &= ~MARKED;
|
resisptr->re_thisEl->rr_connection2->rn_status &= ~MARKED;
|
||||||
ResRemoveFromQueue(resisptr->re_thisEl->rr_connection2, biglist);
|
ResRemoveFromQueue(resisptr->re_thisEl->rr_connection2, biglist);
|
||||||
resisptr->re_thisEl->rr_connection2->rn_less= NULL;
|
resisptr->re_thisEl->rr_connection2->rn_less= NULL;
|
||||||
resisptr->re_thisEl->rr_connection2->rn_more = *nodelist;
|
resisptr->re_thisEl->rr_connection2->rn_more = *nodelist;
|
||||||
if (*nodelist != NULL)
|
if (*nodelist != NULL)
|
||||||
{
|
|
||||||
(*nodelist)->rn_less = resisptr->re_thisEl->rr_connection2;
|
(*nodelist)->rn_less = resisptr->re_thisEl->rr_connection2;
|
||||||
}
|
|
||||||
*nodelist = resisptr->re_thisEl->rr_connection2;
|
*nodelist = resisptr->re_thisEl->rr_connection2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -375,8 +358,6 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -406,32 +387,21 @@ ResMoveDevices(node1,node2)
|
||||||
if (device->rd_status & RES_DEV_PLUG)
|
if (device->rd_status & RES_DEV_PLUG)
|
||||||
{
|
{
|
||||||
if (((ResPlug *)(device))->rpl_node == node1)
|
if (((ResPlug *)(device))->rpl_node == node1)
|
||||||
{
|
|
||||||
((ResPlug *)(device))->rpl_node = node2;
|
((ResPlug *)(device))->rpl_node = node2;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
TxError("Bad node connection in plug\n");
|
TxError("Bad node connection in plug\n");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (device->rd_fet_gate == node1)
|
if (device->rd_fet_gate == node1)
|
||||||
{
|
|
||||||
device->rd_fet_gate = node2;
|
device->rd_fet_gate = node2;
|
||||||
}
|
|
||||||
else if (device->rd_fet_source == node1)
|
else if (device->rd_fet_source == node1)
|
||||||
{
|
|
||||||
device->rd_fet_source = node2;
|
device->rd_fet_source = node2;
|
||||||
}
|
|
||||||
else if (device->rd_fet_drain == node1)
|
else if (device->rd_fet_drain == node1)
|
||||||
{
|
|
||||||
device->rd_fet_drain = node2;
|
device->rd_fet_drain = node2;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
TxError("Missing Device connection in squish routines"
|
||||||
TxError("Missing Device connection in squish routines at %d, %d\n",node1->rn_loc.p_x,node1->rn_loc.p_y);
|
" at %d, %d\n", node1->rn_loc.p_x, node1->rn_loc.p_y);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
oldptr->te_nextt = node2->rn_te;
|
oldptr->te_nextt = node2->rn_te;
|
||||||
node2->rn_te = oldptr;
|
node2->rn_te = oldptr;
|
||||||
|
|
@ -439,7 +409,6 @@ ResMoveDevices(node1,node2)
|
||||||
node1->rn_te = NULL;
|
node1->rn_te = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -468,42 +437,37 @@ ResScrunchNet(reslist,pendingList,biglist,tolerance)
|
||||||
resElement *rcell1;
|
resElement *rcell1;
|
||||||
int c1, c2;
|
int c1, c2;
|
||||||
|
|
||||||
/* sort resistors by size */
|
/* Sort resistors by size */
|
||||||
current = *reslist;
|
current = *reslist;
|
||||||
while (current != NULL)
|
while (current != NULL)
|
||||||
{
|
{
|
||||||
working = current;
|
working = current;
|
||||||
current = current->rr_nextResistor;
|
current = current->rr_nextResistor;
|
||||||
if (working == *reslist)
|
if (working == *reslist)
|
||||||
{
|
|
||||||
*reslist = current;
|
*reslist = current;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
working->rr_lastResistor->rr_nextResistor = current;
|
working->rr_lastResistor->rr_nextResistor = current;
|
||||||
}
|
|
||||||
if (current != NULL)
|
if (current != NULL)
|
||||||
{
|
|
||||||
current->rr_lastResistor = working->rr_lastResistor;
|
current->rr_lastResistor = working->rr_lastResistor;
|
||||||
}
|
|
||||||
ResAddResistorToList(working, &locallist);
|
ResAddResistorToList(working, &locallist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
*reslist = locallist;
|
*reslist = locallist;
|
||||||
while (*reslist != NULL && (*reslist)->rr_value < tolerance)
|
while (*reslist != NULL && (*reslist)->rr_value < tolerance)
|
||||||
{
|
{
|
||||||
current = *reslist;
|
current = *reslist;
|
||||||
if (current->rr_nextResistor == NULL)
|
if (current->rr_nextResistor == NULL)
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
working = NULL;
|
working = NULL;
|
||||||
c1 = 0;
|
c1 = 0;
|
||||||
c2 = 0;
|
c2 = 0;
|
||||||
|
|
||||||
/* search for next smallest adjoining resistor */
|
/* Search for next smallest adjoining resistor */
|
||||||
for (rcell1 = current->rr_connection1->rn_re; rcell1 != NULL; rcell1 = rcell1->re_nextEl)
|
for (rcell1 = current->rr_connection1->rn_re; rcell1 != NULL;
|
||||||
|
rcell1 = rcell1->re_nextEl)
|
||||||
{
|
{
|
||||||
if (rcell1->re_thisEl != current)
|
if (rcell1->re_thisEl != current)
|
||||||
{
|
{
|
||||||
|
|
@ -523,7 +487,8 @@ ResScrunchNet(reslist,pendingList,biglist,tolerance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (rcell1 = current->rr_connection2->rn_re; rcell1 != NULL; rcell1 = rcell1->re_nextEl)
|
for (rcell1 = current->rr_connection2->rn_re; rcell1 != NULL;
|
||||||
|
rcell1 = rcell1->re_nextEl)
|
||||||
{
|
{
|
||||||
if (rcell1->re_thisEl != current)
|
if (rcell1->re_thisEl != current)
|
||||||
{
|
{
|
||||||
|
|
@ -544,9 +509,9 @@ ResScrunchNet(reslist,pendingList,biglist,tolerance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
if the current resistor isn't a deadend, add its value and
|
* If the current resistor isn't a deadend, add its value and
|
||||||
area to that of the next smallest one. If it is a deadend,
|
* area to that of the next smallest one. If it is a deadend,
|
||||||
simply add its area to its node.
|
* simply add its area to its node.
|
||||||
*/
|
*/
|
||||||
if (c1 != 0 && c2 != 0)
|
if (c1 != 0 && c2 != 0)
|
||||||
{
|
{
|
||||||
|
|
@ -558,17 +523,17 @@ ResScrunchNet(reslist,pendingList,biglist,tolerance)
|
||||||
node1->rn_float.rn_area += current->rr_float.rr_area;
|
node1->rn_float.rn_area += current->rr_float.rr_area;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
Move everything from from one end of the ressistor to the
|
* Move everything from from one end of the ressistor to the
|
||||||
other and eliminate the resistor.
|
* other and eliminate the resistor.
|
||||||
*/
|
*/
|
||||||
node2 = (current->rr_connection1 == node1) ? current->rr_connection2 : current->rr_connection1;
|
node2 = (current->rr_connection1 == node1) ? current->rr_connection2 :
|
||||||
|
current->rr_connection1;
|
||||||
ResDeleteResPointer(current->rr_connection1, current);
|
ResDeleteResPointer(current->rr_connection1, current);
|
||||||
ResDeleteResPointer(current->rr_connection2, current);
|
ResDeleteResPointer(current->rr_connection2, current);
|
||||||
working->rr_lastResistor->rr_nextResistor = working->rr_nextResistor;
|
working->rr_lastResistor->rr_nextResistor = working->rr_nextResistor;
|
||||||
if (working->rr_nextResistor != NULL)
|
if (working->rr_nextResistor != NULL)
|
||||||
{
|
|
||||||
working->rr_nextResistor->rr_lastResistor = working->rr_lastResistor;
|
working->rr_nextResistor->rr_lastResistor = working->rr_lastResistor;
|
||||||
}
|
|
||||||
ResEliminateResistor(current, reslist);
|
ResEliminateResistor(current, reslist);
|
||||||
ResAddResistorToList(working, reslist);
|
ResAddResistorToList(working, reslist);
|
||||||
if (node2->rn_why & RES_NODE_ORIGIN)
|
if (node2->rn_why & RES_NODE_ORIGIN)
|
||||||
|
|
@ -577,25 +542,20 @@ ResScrunchNet(reslist,pendingList,biglist,tolerance)
|
||||||
node1 = node2;
|
node1 = node2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
ResMergeNodes(node1,node2,pendingList,biglist);
|
ResMergeNodes(node1,node2,pendingList,biglist);
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Try further simplification on net using ResDoneWithNode and
|
* Try further simplification on net using ResDoneWithNode and
|
||||||
ResSimplifyNet.
|
* ResSimplifyNet.
|
||||||
*/
|
*/
|
||||||
ResRemoveFromQueue(node1, biglist);
|
ResRemoveFromQueue(node1, biglist);
|
||||||
ResAddToQueue(node1, pendingList);
|
ResAddToQueue(node1, pendingList);
|
||||||
node1->rn_status &= ~(RES_DONE_ONCE | FINISHED);
|
node1->rn_status &= ~(RES_DONE_ONCE | FINISHED);
|
||||||
ResDoneWithNode(node1);
|
ResDoneWithNode(node1);
|
||||||
while (*pendingList != NULL)
|
while (*pendingList != NULL)
|
||||||
{
|
|
||||||
ResSimplifyNet(pendingList,biglist,reslist,tolerance);
|
ResSimplifyNet(pendingList,biglist,reslist,tolerance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
|
|
@ -620,9 +580,7 @@ ResAddResistorToList(resistor,locallist)
|
||||||
for (local = *locallist; local != NULL; local = local->rr_nextResistor)
|
for (local = *locallist; local != NULL; local = local->rr_nextResistor)
|
||||||
{
|
{
|
||||||
if (local->rr_value >= resistor->rr_value)
|
if (local->rr_value >= resistor->rr_value)
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
last = local;
|
last = local;
|
||||||
}
|
}
|
||||||
if (local != NULL)
|
if (local != NULL)
|
||||||
|
|
@ -630,13 +588,10 @@ ResAddResistorToList(resistor,locallist)
|
||||||
resistor->rr_nextResistor = local;
|
resistor->rr_nextResistor = local;
|
||||||
resistor->rr_lastResistor = local->rr_lastResistor;
|
resistor->rr_lastResistor = local->rr_lastResistor;
|
||||||
if (local->rr_lastResistor == NULL)
|
if (local->rr_lastResistor == NULL)
|
||||||
{
|
|
||||||
*locallist = resistor;
|
*locallist = resistor;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
local->rr_lastResistor->rr_nextResistor = resistor;
|
local->rr_lastResistor->rr_nextResistor = resistor;
|
||||||
}
|
|
||||||
local->rr_lastResistor = resistor;
|
local->rr_lastResistor = resistor;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -656,7 +611,6 @@ ResAddResistorToList(resistor,locallist)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -685,13 +639,9 @@ ResDistributeCapacitance(nodelist,totalcap)
|
||||||
for (workingNode = nodelist; workingNode != NULL; workingNode = workingNode->rn_more)
|
for (workingNode = nodelist; workingNode != NULL; workingNode = workingNode->rn_more)
|
||||||
{
|
{
|
||||||
for (rptr = workingNode->rn_re; rptr != NULL; rptr=rptr->re_nextEl)
|
for (rptr = workingNode->rn_re; rptr != NULL; rptr=rptr->re_nextEl)
|
||||||
{
|
|
||||||
if (rptr->re_thisEl->rr_float.rr_area != 0.0)
|
if (rptr->re_thisEl->rr_float.rr_area != 0.0)
|
||||||
{
|
|
||||||
TxError("Nonnull resistor area\n");
|
TxError("Nonnull resistor area\n");
|
||||||
}
|
|
||||||
/* workingNode->rn_float.rn_area += rptr->re_thisEl->rr_float.rr_area/2; */
|
|
||||||
}
|
|
||||||
totalarea += workingNode->rn_float.rn_area;
|
totalarea += workingNode->rn_float.rn_area;
|
||||||
}
|
}
|
||||||
if (totalarea == 0)
|
if (totalarea == 0)
|
||||||
|
|
@ -700,12 +650,10 @@ ResDistributeCapacitance(nodelist,totalcap)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
capperarea = FEMTOTOATTO * totalcap / totalarea;
|
capperarea = FEMTOTOATTO * totalcap / totalarea;
|
||||||
|
|
||||||
for (workingNode = nodelist; workingNode != NULL; workingNode=workingNode->rn_more)
|
for (workingNode = nodelist; workingNode != NULL; workingNode=workingNode->rn_more)
|
||||||
{
|
|
||||||
workingNode->rn_float.rn_area *= capperarea;
|
workingNode->rn_float.rn_area *= capperarea;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
|
|
@ -734,17 +682,16 @@ ResCalculateChildCapacitance(me)
|
||||||
int t;
|
int t;
|
||||||
ExtDevice *devptr;
|
ExtDevice *devptr;
|
||||||
|
|
||||||
|
|
||||||
if (me->rn_client != (ClientData) NULL) /* we have a loop */
|
if (me->rn_client != (ClientData) NULL) /* we have a loop */
|
||||||
{
|
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
|
||||||
myC = (RCDelayStuff *) mallocMagic((unsigned) (sizeof(RCDelayStuff)));
|
myC = (RCDelayStuff *) mallocMagic((unsigned) (sizeof(RCDelayStuff)));
|
||||||
me->rn_client = (ClientData) myC;
|
me->rn_client = (ClientData) myC;
|
||||||
|
|
||||||
/* This following assumes that ResDistributeCapacitance has been run */
|
/* This following assumes that ResDistributeCapacitance has been run */
|
||||||
/* and the the resulting capacitance value is stored in the area field */
|
/* and the the resulting capacitance value is stored in the area field */
|
||||||
myC->rc_Cdownstream = me->rn_float.rn_area;
|
myC->rc_Cdownstream = me->rn_float.rn_area;
|
||||||
|
myC->rc_Tdi = 0.0;
|
||||||
|
|
||||||
/* get capacitance for all connected gates */
|
/* get capacitance for all connected gates */
|
||||||
for (tptr = me->rn_te; tptr != NULL; tptr = tptr->te_nextt)
|
for (tptr = me->rn_te; tptr != NULL; tptr = tptr->te_nextt)
|
||||||
|
|
@ -763,9 +710,7 @@ ResCalculateChildCapacitance(me)
|
||||||
if (dev->rd_fet_gate == me)
|
if (dev->rd_fet_gate == me)
|
||||||
{
|
{
|
||||||
devptr = ExtCurStyle->exts_device[t];
|
devptr = ExtCurStyle->exts_device[t];
|
||||||
myC->rc_Cdownstream +=
|
myC->rc_Cdownstream += dev->rd_length * dev->rd_width *
|
||||||
dev->rd_length*
|
|
||||||
dev->rd_width*
|
|
||||||
devptr->exts_deviceGateCap +
|
devptr->exts_deviceGateCap +
|
||||||
(dev->rd_width + dev->rd_width) *
|
(dev->rd_width + dev->rd_width) *
|
||||||
devptr->exts_deviceSDCap;
|
devptr->exts_deviceSDCap;
|
||||||
|
|
@ -781,16 +726,14 @@ ResCalculateChildCapacitance(me)
|
||||||
{
|
{
|
||||||
childcap = ResCalculateChildCapacitance(workingRes->re_thisEl->rr_connection2);
|
childcap = ResCalculateChildCapacitance(workingRes->re_thisEl->rr_connection2);
|
||||||
if (childcap == -1)
|
if (childcap == -1)
|
||||||
{
|
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
|
||||||
myC->rc_Cdownstream += childcap;
|
myC->rc_Cdownstream += childcap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (myC->rc_Cdownstream);
|
return (myC->rc_Cdownstream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -817,29 +760,24 @@ ResCalculateTDi(node,resistor,resistorvalue)
|
||||||
|
|
||||||
ASSERT(rcd != NULL, "ResCalculateTdi");
|
ASSERT(rcd != NULL, "ResCalculateTdi");
|
||||||
if (resistor == NULL)
|
if (resistor == NULL)
|
||||||
{
|
|
||||||
rcd->rc_Tdi = rcd->rc_Cdownstream*(float)resistorvalue;
|
rcd->rc_Tdi = rcd->rc_Cdownstream*(float)resistorvalue;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rcd2 = (RCDelayStuff *)resistor->rr_connection1->rn_client;
|
rcd2 = (RCDelayStuff *)resistor->rr_connection1->rn_client;
|
||||||
ASSERT(rcd2 != NULL,"ResCalculateTdi");
|
ASSERT(rcd2 != NULL,"ResCalculateTdi");
|
||||||
rcd->rc_Tdi = rcd->rc_Cdownstream * (float)resistor->rr_value +
|
rcd->rc_Tdi = rcd->rc_Cdownstream * (float)resistor->rr_value +
|
||||||
rcd2->rc_Tdi;
|
rcd2->rc_Tdi;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (workingRes = node->rn_re; workingRes != NULL; workingRes = workingRes->re_nextEl)
|
for (workingRes = node->rn_re; workingRes != NULL; workingRes = workingRes->re_nextEl)
|
||||||
{
|
{
|
||||||
if (workingRes->re_thisEl->rr_connection1 == node &&
|
if (workingRes->re_thisEl->rr_connection1 == node &&
|
||||||
(workingRes->re_thisEl->rr_status & RES_TDI_IGNORE) == 0)
|
(workingRes->re_thisEl->rr_status & RES_TDI_IGNORE) == 0)
|
||||||
{
|
|
||||||
ResCalculateTDi(workingRes->re_thisEl->rr_connection2,
|
ResCalculateTDi(workingRes->re_thisEl->rr_connection2,
|
||||||
workingRes->re_thisEl,
|
workingRes->re_thisEl,
|
||||||
workingRes->re_thisEl->rr_value);
|
workingRes->re_thisEl->rr_value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
|
|
@ -872,16 +810,18 @@ ResPruneTree(node,minTdi,nodelist1,nodelist2,resistorlist)
|
||||||
current = current->re_nextEl;
|
current = current->re_nextEl;
|
||||||
/* if branch points outward, call routine on subtrees */
|
/* if branch points outward, call routine on subtrees */
|
||||||
if (currentRes->rr_connection1 == node)
|
if (currentRes->rr_connection1 == node)
|
||||||
{
|
ResPruneTree(currentRes->rr_connection2, minTdi, nodelist1,
|
||||||
ResPruneTree(currentRes->rr_connection2, minTdi,nodelist1,nodelist2,resistorlist);
|
nodelist2, resistorlist);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
/* We eliminate this branch if */
|
/* We eliminate this branch if:
|
||||||
/* 1. It is a terminal node, i.e. it is the connected */
|
* 1. It is a terminal node, i.e. it is the connected
|
||||||
/* to only one resistor. */
|
* to only one resistor.
|
||||||
/* 2. The direction of this resistor is toward the node */
|
* 2. The direction of this resistor is toward the node
|
||||||
/* (This prevents the root from being eliminated */
|
* (This prevents the root from being eliminated
|
||||||
/* 3. The time constant TDI is less than the tolerance. */
|
* 3. The time constant TDI is less than the tolerance.
|
||||||
|
*/
|
||||||
|
|
||||||
if (node->rn_re != NULL &&
|
if (node->rn_re != NULL &&
|
||||||
node->rn_re->re_nextEl == NULL &&
|
node->rn_re->re_nextEl == NULL &&
|
||||||
node->rn_re->re_thisEl->rr_connection2 == node)
|
node->rn_re->re_thisEl->rr_connection2 == node)
|
||||||
|
|
@ -895,12 +835,19 @@ ResPruneTree(node,minTdi,nodelist1,nodelist2,resistorlist)
|
||||||
currentRes = node->rn_re->re_thisEl;
|
currentRes = node->rn_re->re_thisEl;
|
||||||
ResDeleteResPointer(currentRes->rr_connection1, currentRes);
|
ResDeleteResPointer(currentRes->rr_connection1, currentRes);
|
||||||
ResDeleteResPointer(currentRes->rr_connection2, currentRes);
|
ResDeleteResPointer(currentRes->rr_connection2, currentRes);
|
||||||
ResMergeNodes(currentRes->rr_connection1,currentRes->rr_connection2,nodelist2,nodelist1); /* Patched 7/5/94 */
|
ResMergeNodes(currentRes->rr_connection1, currentRes->rr_connection2,
|
||||||
|
nodelist2, nodelist1);
|
||||||
ResEliminateResistor(currentRes, resistorlist);
|
ResEliminateResistor(currentRes, resistorlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
ResDoSimplify(tolerance, rctol, goodies)
|
ResDoSimplify(tolerance, rctol, goodies)
|
||||||
float tolerance;
|
float tolerance;
|
||||||
|
|
@ -914,13 +861,10 @@ ResDoSimplify(tolerance,rctol,goodies)
|
||||||
float totalcap;
|
float totalcap;
|
||||||
resResistor *res;
|
resResistor *res;
|
||||||
|
|
||||||
|
|
||||||
resRemoveLoops = FALSE;
|
resRemoveLoops = FALSE;
|
||||||
ResSetPathRes();
|
ResSetPathRes();
|
||||||
for (node = ResNodeList; node != NULL; node = node->rn_more)
|
for (node = ResNodeList; node != NULL; node = node->rn_more)
|
||||||
{
|
|
||||||
bigres = MAX(bigres,node->rn_noderes);
|
bigres = MAX(bigres,node->rn_noderes);
|
||||||
}
|
|
||||||
|
|
||||||
bigres /= OHMSTOMILLIOHMS; /* convert from milliohms to ohms */
|
bigres /= OHMSTOMILLIOHMS; /* convert from milliohms to ohms */
|
||||||
goodies->rg_maxres = bigres;
|
goodies->rg_maxres = bigres;
|
||||||
|
|
@ -936,11 +880,10 @@ ResDoSimplify(tolerance,rctol,goodies)
|
||||||
|
|
||||||
(void) ResDistributeCapacitance(ResNodeList,goodies->rg_nodecap);
|
(void) ResDistributeCapacitance(ResNodeList,goodies->rg_nodecap);
|
||||||
|
|
||||||
if ((tolerance > bigres || (ResOptionsFlags &ResOpt_Simplify)==0) &&
|
if (((tolerance > bigres) || ((ResOptionsFlags & ResOpt_Simplify) == 0)) &&
|
||||||
(ResOptionsFlags &ResOpt_DoLumpFile)==0)
|
((ResOptionsFlags & ResOpt_DoLumpFile) == 0))
|
||||||
{
|
return 0;
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
res = ResResList;
|
res = ResResList;
|
||||||
while (res)
|
while (res)
|
||||||
{
|
{
|
||||||
|
|
@ -975,7 +918,7 @@ ResDoSimplify(tolerance,rctol,goodies)
|
||||||
for (node = ResNodeList; node != NULL; node = node->rn_more)
|
for (node = ResNodeList; node != NULL; node = node->rn_more)
|
||||||
{
|
{
|
||||||
rc = (RCDelayStuff *)node->rn_client;
|
rc = (RCDelayStuff *)node->rn_client;
|
||||||
if (rc && (goodies->rg_Tdi < rc->rc_Tdi))
|
if ((rc != NULL) && (goodies->rg_Tdi < rc->rc_Tdi))
|
||||||
{
|
{
|
||||||
slownode = node;
|
slownode = node;
|
||||||
goodies->rg_Tdi = rc->rc_Tdi;
|
goodies->rg_Tdi = rc->rc_Tdi;
|
||||||
|
|
@ -984,93 +927,85 @@ ResDoSimplify(tolerance,rctol,goodies)
|
||||||
slownode->rn_status |= RN_MAXTDI;
|
slownode->rn_status |= RN_MAXTDI;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
goodies->rg_Tdi = -1;
|
goodies->rg_Tdi = -1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
goodies->rg_Tdi = 0;
|
goodies->rg_Tdi = 0;
|
||||||
}
|
|
||||||
if ((rctol+1) * goodies->rg_bigdevres * goodies->rg_nodecap >
|
if ((rctol+1) * goodies->rg_bigdevres * goodies->rg_nodecap >
|
||||||
rctol * goodies->rg_Tdi &&
|
rctol * goodies->rg_Tdi &&
|
||||||
(ResOptionsFlags & ResOpt_Tdi) &&
|
(ResOptionsFlags & ResOpt_Tdi) &&
|
||||||
goodies->rg_Tdi != -1)
|
goodies->rg_Tdi != -1)
|
||||||
{
|
return 0;
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Simplify network; resistors are still in milliohms, so use
|
/* Simplify network; resistors are still in milliohms, so use
|
||||||
millitolerance.
|
* millitolerance.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (ResOptionsFlags & ResOpt_Simplify)
|
if (ResOptionsFlags & ResOpt_Simplify)
|
||||||
{
|
{
|
||||||
|
|
||||||
millitolerance = tolerance * MILLIOHMSPEROHM;
|
millitolerance = tolerance * MILLIOHMSPEROHM;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Start simplification at driver (R=0). Remove it from the done list
|
* Start simplification at driver (R=0). Remove it from the done list
|
||||||
and add it to the pending list. Call ResSimplifyNet as long as nodes
|
* and add it to the pending list. Call ResSimplifyNet as long as
|
||||||
remain in the pending list.
|
* nodes remain in the pending list.
|
||||||
*/
|
*/
|
||||||
for (node = ResNodeList; node != NULL; node = node->rn_more)
|
for (node = ResNodeList; node != NULL; node = node->rn_more)
|
||||||
{
|
{
|
||||||
if (node->rn_noderes == 0)
|
if (node->rn_noderes == 0)
|
||||||
{
|
|
||||||
ResOriginNode = node;
|
ResOriginNode = node;
|
||||||
}
|
|
||||||
node->rn_status |= FINISHED;
|
node->rn_status |= FINISHED;
|
||||||
}
|
}
|
||||||
if (ResOriginNode != NULL)
|
if (ResOriginNode != NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* if Tdi is enabled, prune all branches whose end nodes have */
|
/* if Tdi is enabled, prune all branches whose end nodes */
|
||||||
/* time constants less than the tolerance. */
|
/* have time constants less than the tolerance. */
|
||||||
|
|
||||||
if ((ResOptionsFlags & ResOpt_Tdi) &&
|
if ((ResOptionsFlags & ResOpt_Tdi) &&
|
||||||
goodies->rg_Tdi != -1 &&
|
goodies->rg_Tdi != -1 &&
|
||||||
rctol != 0)
|
rctol != 0)
|
||||||
{
|
{
|
||||||
ResPruneTree(ResOriginNode,
|
ResPruneTree(ResOriginNode, (rctol + 1) *
|
||||||
(rctol+1)*goodies->rg_bigdevres*goodies->rg_nodecap/rctol,
|
goodies->rg_bigdevres * goodies->rg_nodecap / rctol,
|
||||||
&ResNodeList, &ResNodeQueue, &ResResList);
|
&ResNodeList, &ResNodeQueue, &ResResList);
|
||||||
}
|
}
|
||||||
ResOriginNode->rn_status &= ~MARKED;
|
ResOriginNode->rn_status &= ~MARKED;
|
||||||
if (ResOriginNode->rn_less == NULL)
|
if (ResOriginNode->rn_less == NULL)
|
||||||
{
|
|
||||||
ResNodeList = ResOriginNode->rn_more;
|
ResNodeList = ResOriginNode->rn_more;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
ResOriginNode->rn_less->rn_more = ResOriginNode->rn_more;
|
ResOriginNode->rn_less->rn_more = ResOriginNode->rn_more;
|
||||||
}
|
|
||||||
if (ResOriginNode->rn_more != NULL)
|
if (ResOriginNode->rn_more != NULL)
|
||||||
{
|
|
||||||
ResOriginNode->rn_more->rn_less = ResOriginNode->rn_less;
|
ResOriginNode->rn_more->rn_less = ResOriginNode->rn_less;
|
||||||
}
|
|
||||||
ResOriginNode->rn_more = NULL;
|
ResOriginNode->rn_more = NULL;
|
||||||
ResOriginNode->rn_less = NULL;
|
ResOriginNode->rn_less = NULL;
|
||||||
ResNodeQueue = ResOriginNode;
|
ResNodeQueue = ResOriginNode;
|
||||||
while (ResNodeQueue != NULL)
|
while (ResNodeQueue != NULL)
|
||||||
{
|
|
||||||
ResSimplifyNet(&ResNodeQueue,&ResNodeList,&ResResList,millitolerance);
|
ResSimplifyNet(&ResNodeQueue,&ResNodeList,&ResResList,millitolerance);
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Call ResScrunchNet to eliminate any remaining under tolerance
|
* Call ResScrunchNet to eliminate any remaining under tolerance
|
||||||
resistors.
|
* resistors.
|
||||||
*/
|
*/
|
||||||
ResScrunchNet(&ResResList,&ResNodeQueue,&ResNodeList,millitolerance);
|
ResScrunchNet(&ResResList,&ResNodeQueue,&ResNodeList,millitolerance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(0);
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ResSetPathRes()
|
ResSetPathRes()
|
||||||
|
|
||||||
{
|
{
|
||||||
HeapEntry he;
|
HeapEntry he;
|
||||||
resNode *node;
|
resNode *node;
|
||||||
|
|
@ -1105,10 +1040,14 @@ ResSetPathRes()
|
||||||
ASSERT(ResOriginNode != NULL, "ResDoSimplify");
|
ASSERT(ResOriginNode != NULL, "ResDoSimplify");
|
||||||
resPathNode(ResOriginNode);
|
resPathNode(ResOriginNode);
|
||||||
while (HeapRemoveTop(&ResistorHeap,&he))
|
while (HeapRemoveTop(&ResistorHeap,&he))
|
||||||
{
|
|
||||||
resPathRes((resResistor *)he.he_id);
|
resPathRes((resResistor *)he.he_id);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
resPathNode(node)
|
resPathNode(node)
|
||||||
|
|
@ -1126,12 +1065,16 @@ resPathNode(node)
|
||||||
if (res->rr_status & RES_HEAP) continue;
|
if (res->rr_status & RES_HEAP) continue;
|
||||||
if ((node2 = res->rr_node[0]) == node) node2 = res->rr_node[1];
|
if ((node2 = res->rr_node[0]) == node) node2 = res->rr_node[1];
|
||||||
if ((node2->rn_status & FINISHED) == 0)
|
if ((node2->rn_status & FINISHED) == 0)
|
||||||
{
|
|
||||||
HeapAddInt(&ResistorHeap, node->rn_noderes + res->rr_value,
|
HeapAddInt(&ResistorHeap, node->rn_noderes + res->rr_value,
|
||||||
(char *)res);
|
(char *)res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
resPathRes(res)
|
resPathRes(res)
|
||||||
|
|
|
||||||
|
|
@ -417,11 +417,12 @@ HeapAdd(heap, pKey, id)
|
||||||
{
|
{
|
||||||
/* If odd then new entry is the right half of a pair */
|
/* If odd then new entry is the right half of a pair */
|
||||||
cmp = i;
|
cmp = i;
|
||||||
if (i & 1)
|
if ((i & 1) && (i != 1))
|
||||||
KEY_LE_COND(keyType, list, i, i-1, cmp = i-1);
|
KEY_LE_COND(keyType, list, i, i-1, cmp = i-1);
|
||||||
|
|
||||||
/* Find parent. If 0 then at the root so quit */
|
/* Find parent. If 0 then at the root so quit */
|
||||||
if ((i >>= 1) == 0) return;
|
if ((i >>= 1) == 0) return;
|
||||||
|
|
||||||
KEY_LE_COND(keyType, list, cmp, i, return);
|
KEY_LE_COND(keyType, list, cmp, i, return);
|
||||||
list[0] = list[cmp]; list[cmp] = list[i]; list[i] = list[0];
|
list[0] = list[cmp]; list[cmp] = list[i]; list[i] = list[0];
|
||||||
heapify(heap, cmp);
|
heapify(heap, cmp);
|
||||||
|
|
@ -434,11 +435,12 @@ HeapAdd(heap, pKey, id)
|
||||||
{
|
{
|
||||||
/* If odd then new entry is the right half of a pair */
|
/* If odd then new entry is the right half of a pair */
|
||||||
cmp = i;
|
cmp = i;
|
||||||
if (i & 1)
|
if ((i & 1) && (i != 1))
|
||||||
KEY_GE_COND(keyType, list, i, i-1, cmp = i-1);
|
KEY_GE_COND(keyType, list, i, i-1, cmp = i-1);
|
||||||
|
|
||||||
/* Find parent. If 0 then at the root so quit */
|
/* Find parent. If 0 then at the root so quit */
|
||||||
if ((i >>= 1) == 0) return;
|
if ((i >>= 1) == 0) return;
|
||||||
|
|
||||||
KEY_GE_COND(keyType, list, cmp, i, return);
|
KEY_GE_COND(keyType, list, cmp, i, return);
|
||||||
list[0] = list[cmp]; list[cmp] = list[i]; list[i] = list[0];
|
list[0] = list[cmp]; list[cmp] = list[i]; list[i] = list[0];
|
||||||
heapify(heap, cmp);
|
heapify(heap, cmp);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue