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:
Tim Edwards 2021-05-25 22:41:52 -04:00
parent c22d584ac3
commit 9aa39f820f
7 changed files with 2271 additions and 2340 deletions

View File

@ -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;
} }

View File

@ -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;
} }
} }

View File

@ -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");
} }
} }
} }

View File

@ -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;
} }

View File

@ -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;

View File

@ -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)

View File

@ -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);