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;
/*
*--------------------------------------------------------------------------
*
@ -121,7 +120,6 @@ ResGetReCell()
ResUse = DBCellNewUse(ResDef, (char *) NULL);
DBSetTrans(ResUse, &GeoIdentityTransform);
ResUse->cu_expandMask = CU_DESCEND_SPECIAL;
}
/*
@ -418,7 +416,6 @@ ResProcessTiles(goodies, origin)
Tile *tile = fix->fp_tile;
if (tile == NULL)
{
tile = ResDef->cd_planes[DBPlane(fix->fp_ttype)]->pl_hint;
GOTOPOINT(tile, &(fix->fp_loc));
if (TiGetTypeExact(tile) != TT_SPACE)
@ -682,7 +679,7 @@ ResExtractNet(startlist, goodies, cellname)
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,
&(ResUse->cu_def->cd_bbox),
@ -771,7 +768,7 @@ ResCleanUpEverything()
resDevice *oldDev;
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++)
{
@ -779,7 +776,6 @@ ResCleanUpEverything()
&(ResUse->cu_def->cd_bbox), &DBAllButSpaceAndDRCBits,
(ClientData)CLIENTDEFAULT, ResRemovePlumbing,
(ClientData)NULL);
}
while (ResNodeList != NULL)
@ -808,12 +804,9 @@ ResCleanUpEverything()
freeMagic((char *)oldDev);
}
}
DBCellClearDef(ResUse->cu_def);
}
/*
*-------------------------------------------------------------------------
*
@ -935,6 +928,7 @@ FindStartTile(goodies, SourcePoint)
t1 = TiGetType(tile);
devptr = ExtCurStyle->exts_device[t1];
/* left */
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp))
{
@ -1019,10 +1013,10 @@ ResGetDevice(pt)
for (pnum = PL_TECHDEPBASE; pnum < DBNumPlanes; pnum++)
{
if (TTMaskIntersect(&ExtCurStyle->exts_deviceMask, &DBPlaneTypes[pnum]) == 0)
{
continue;
}
/*start at hint tile for device plane */
/* Start at hint tile for device plane */
tile = ResUse->cu_def->cd_planes[pnum]->pl_hint;
GOTOPOINT(tile, &workingPoint);
@ -1037,5 +1031,5 @@ ResGetDevice(pt)
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
* is called. It checks for parallel, series, loop, triangle,
* and single conections, and simplifies the network where possible.
* ResDoneWithNode--
* After all connections to node are made, ResDoneWithNode is
* called. It checks for parallel, series, loop, triangle, and
* single conections, and simplifies the network where possible.
*
* Results: none
*
@ -56,10 +57,7 @@ ResDoneWithNode(resptr)
/* are there any resistors? */
if (resptr->rn_re == NULL)
{
return;
}
if (resptr->rn_re == NULL) return;
/* Special handling for geometry option */
@ -106,24 +104,21 @@ ResDoneWithNode(resptr)
break;
}
}
if (status != UNTOUCHED) return; /* resptr may be invalid */
/* Eliminations that can be only if there are no devices connected */
/* to node. Series and dangling connections fall in this group. */
if ((resptr->rn_te == NULL) && (resptr->rn_why != RES_NODE_ORIGIN)
&& (status == UNTOUCHED))
{
status = ResSeriesCheck(resptr);
}
if ((status == UNTOUCHED) && (resptr->rn_why != RES_NODE_ORIGIN))
{
status = ResParallelCheck(resptr);
}
if ((status == UNTOUCHED) && (resptr->rn_why != RES_NODE_ORIGIN))
{
status = ResTriangleCheck(resptr);
}
}
/*
@ -148,13 +143,17 @@ ResFixRes(resptr,resptr2,resptr3,elimResis,newResis)
{
resElement *thisREl;
resptr3->rn_float.rn_area += newResis->rr_value*resptr->rn_float.rn_area/((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));
resptr3->rn_float.rn_area += newResis->rr_value*resptr->rn_float.rn_area
/ ((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;
ASSERT(newResis->rr_value > 0, "series");
newResis->rr_float.rr_area += elimResis->rr_float.rr_area;
#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_tt = elimResis->rr_tt;
@ -220,7 +219,7 @@ ResFixParallel(elimResis,newResis)
*-------------------------------------------------------------------------
*
* 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.
*
@ -269,12 +268,10 @@ ResSeriesCheck(resptr)
{
if (rr1->rr_connection1 == resptr)
{
if (rr2->rr_connection1 == resptr)
{
resptr2 = rr1->rr_connection2;
if (rr1->rr_connection2 ==
rr2->rr_connection2)
if (rr1->rr_connection2 == rr2->rr_connection2)
{
status = LOOP;
ResDeleteResPointer(rr1->rr_connection1, rr1);
@ -287,7 +284,8 @@ ResSeriesCheck(resptr)
ResEliminateResistor(rr1, &ResResList);
ResEliminateResistor(rr2, &ResResList);
ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
}else
}
else
{
status = SERIES;
resptr3 = rr2->rr_connection2;
@ -300,7 +298,8 @@ ResSeriesCheck(resptr)
ResDoneWithNode(resptr2);
}
resptr2 = NULL;
}else
}
else
{
resptr2 = rr1->rr_connection2;
if (rr1->rr_connection2 == rr2->rr_connection1)
@ -316,7 +315,8 @@ ResSeriesCheck(resptr)
ResEliminateResistor(rr1, &ResResList);
ResEliminateResistor(rr2, &ResResList);
ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
}else
}
else
{
status = SERIES;
resptr3 = rr2->rr_connection1;
@ -330,7 +330,8 @@ ResSeriesCheck(resptr)
}
resptr2 = NULL;
}
}else
}
else
{
if (rr2->rr_connection1 == resptr)
{
@ -348,12 +349,12 @@ ResSeriesCheck(resptr)
ResEliminateResistor(rr1, &ResResList);
ResEliminateResistor(rr2, &ResResList);
ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
}else
}
else
{
status = SERIES;
resptr3 = rr2->rr_connection2;
rr1->rr_connection2 =
rr2->rr_connection2;
rr1->rr_connection2 = rr2->rr_connection2;
ResFixRes(resptr, resptr2, resptr3, rr2, rr1);
}
if ((resptr2->rn_status & TRUE) == TRUE)
@ -362,7 +363,8 @@ ResSeriesCheck(resptr)
ResDoneWithNode(resptr2);
}
resptr2 = NULL;
}else
}
else
{
resptr2 = rr1->rr_connection1;
if (rr1->rr_connection1 == rr2->rr_connection1)
@ -378,12 +380,12 @@ ResSeriesCheck(resptr)
ResEliminateResistor(rr1, &ResResList);
ResEliminateResistor(rr2, &ResResList);
ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
}else
}
else
{
status = SERIES;
resptr3 = rr2->rr_connection1;
rr1->rr_connection2 =
rr2->rr_connection1;
rr1->rr_connection2 = rr2->rr_connection1;
ResFixRes(resptr, resptr2, resptr3, rr2, rr1);
}
if ((resptr2->rn_status & TRUE) == TRUE)
@ -399,7 +401,6 @@ ResSeriesCheck(resptr)
return status;
}
/*
*-------------------------------------------------------------------------
*
@ -423,13 +424,13 @@ ResParallelCheck(resptr)
resElement *rcell1, *rcell2;
for (rcell1 = resptr->rn_re;
rcell1->re_nextEl != NULL; rcell1 = rcell1->re_nextEl)
for (rcell1 = resptr->rn_re; rcell1->re_nextEl != NULL;
rcell1 = rcell1->re_nextEl)
{
r1 = rcell1->re_thisEl;
for (rcell2 = rcell1->re_nextEl;
rcell2 != NULL; rcell2 = rcell2->re_nextEl)
for (rcell2 = rcell1->re_nextEl; rcell2 != NULL;
rcell2 = rcell2->re_nextEl)
{
r2 = rcell2->re_thisEl;
@ -483,23 +484,23 @@ ResTriangleCheck(resptr)
resNode *n1, *n2, *n3;
resElement *rcell1, *rcell2, *rcell3, *element;
for (rcell1 = resptr->rn_re;
rcell1->re_nextEl != NULL; rcell1 = rcell1->re_nextEl)
for (rcell1 = resptr->rn_re; rcell1->re_nextEl != NULL;
rcell1 = rcell1->re_nextEl)
{
rr1 = rcell1->re_thisEl;
n1 = (rr1->rr_connection1 == resptr) ? rr1->rr_connection2:
rr1->rr_connection1;
for (rcell2 = rcell1->re_nextEl;
rcell2 != NULL; rcell2 = rcell2->re_nextEl)
for (rcell2 = rcell1->re_nextEl; rcell2 != NULL;
rcell2 = rcell2->re_nextEl)
{
rr2 = rcell2->re_thisEl;
if (TTMaskHasType(ResNoMergeMask + rr1->rr_tt, rr2->rr_tt))
continue;
n2 = (rr2->rr_connection1 == resptr) ? rr2->rr_connection2 :
rr2->rr_connection1;
for (rcell3 = n1->rn_re;
rcell3 != NULL; rcell3 = rcell3->re_nextEl)
for (rcell3 = n1->rn_re; rcell3 != NULL;
rcell3 = rcell3->re_nextEl)
{
rr3 = rcell3->re_thisEl;
if (TTMaskHasType(ResNoMergeMask + rr1->rr_tt, rr3->rr_tt))
@ -517,14 +518,11 @@ ResTriangleCheck(resptr)
{
denom = 1.0 /denom;
/* calculate new values for resistors */
r1 = (((float) rr1->rr_value)*
((float) rr2->rr_value))*denom;
r1 = (((float)rr1->rr_value) * ((float)rr2->rr_value)) * denom;
r2 = (((float) rr2->rr_value)*
((float) rr3->rr_value))*denom;
r2 = (((float)rr2->rr_value) * ((float)rr3->rr_value)) * denom;
r3 = (((float) rr1->rr_value)*
((float) rr3->rr_value))*denom;
r3 = (((float)rr1->rr_value) * ((float)rr3->rr_value)) * denom;
rr1->rr_value = r1 + 0.5;
rr2->rr_value = r2 + 0.5;
@ -540,6 +538,7 @@ ResTriangleCheck(resptr)
rr3->rr_value = 0;
}
n3 = (resNode *)mallocMagic((unsigned)(sizeof(resNode)));
/* Where should the new node be `put'? It */
/* is arbitrarily assigned to the location */
/* occupied by the first node. */
@ -594,21 +593,15 @@ ResTriangleCheck(resptr)
element->re_thisEl = rr3;
n3->rn_re = element;
if ((n1->rn_status & TRUE) == TRUE)
{
n1->rn_status &= ~TRUE;
}
else
{
n1 = NULL;
}
if ((n2->rn_status & TRUE) == TRUE)
{
n2->rn_status &= ~TRUE;
}
else
{
n2 = NULL;
}
ResDoneWithNode(resptr);
if (n1 != NULL) ResDoneWithNode(n1);
if (n2 != NULL) ResDoneWithNode(n2);
@ -637,8 +630,8 @@ ResTriangleCheck(resptr)
void
ResMergeNodes(node1, node2, pendingList, doneList)
resNode *node1,*node2,**pendingList,**doneList;
resNode *node1, *node2;
resNode **pendingList, **doneList;
{
resElement *workingRes, *tRes;
tElement *workingDev, *tDev;
@ -649,6 +642,7 @@ ResMergeNodes(node1,node2,pendingList,doneList)
/* sanity check */
if (node1 == node2) return;
if (node1 == NULL || node2 == NULL)
{
TxError("Attempt to merge NULL node\n");
@ -657,9 +651,7 @@ ResMergeNodes(node1,node2,pendingList,doneList)
/* don't want to merge away startpoint */
if (node2->rn_why & RES_NODE_ORIGIN)
{
node1->rn_why = RES_NODE_ORIGIN;
}
/* set node resistance */
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;
/* combine relevant flags */
node1->rn_status |= (node2->rn_status & RN_MAXTDI);
@ -685,9 +676,7 @@ ResMergeNodes(node1,node2,pendingList,doneList)
{
ResPlug *plug = (ResPlug *) workingDev->te_thist;
if (plug->rpl_node == node2)
{
plug->rpl_node = node1;
}
else
{
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++)
if (workingDev->te_thist->rd_terminals[j] == node2)
{
workingDev->te_thist->rd_terminals[j] = node1;
}
}
tDev = workingDev;
workingDev = workingDev->te_nextt;
tDev->te_nextt = node1->rn_te;
@ -712,6 +699,7 @@ ResMergeNodes(node1,node2,pendingList,doneList)
}
/* append junction lists */
workingJunc = node2->rn_je;
while (workingJunc != NULL)
{
@ -724,10 +712,8 @@ ResMergeNodes(node1,node2,pendingList,doneList)
junk = (tileJunk *) tile->ti_client;
if ((junk->tj_status & RES_TILE_DONE) == FALSE)
{
ResFixBreakPoint(&junk->breakList, node2, node1);
}
}
tJunc->je_thisj->rj_jnode = node1;
workingJunc = workingJunc->je_nextj;
tJunc->je_nextj = node1->rn_je;
@ -749,62 +735,51 @@ ResMergeNodes(node1,node2,pendingList,doneList)
tile =tCon->ce_thisc->cp_tile[i];
junk = (tileJunk *) tile->ti_client;
if ((junk->tj_status & RES_TILE_DONE) == FALSE)
{
ResFixBreakPoint(&junk->breakList, node2, node1);
}
}
}
workingCon = workingCon->ce_nextc;
tCon->ce_nextc = node1->rn_ce;
node1->rn_ce = tCon;
}
/* Moves resistors to new node */
workingRes = node2->rn_re;
while (workingRes != NULL)
{
if (workingRes->re_thisEl->rr_connection1 == node2)
{
workingRes->re_thisEl->rr_connection1 = node1;
}
else if (workingRes->re_thisEl->rr_connection2 == node2)
{
workingRes->re_thisEl->rr_connection2 = node1;
}
else
{
TxError("Resistor not found.\n");
}
tRes = workingRes;
workingRes = workingRes->re_nextEl;
tRes->re_nextEl = node1->rn_re;
node1->rn_re = tRes;
}
if ((node2->rn_status & FINISHED) == FINISHED)
{
ResRemoveFromQueue(node2, doneList);
}
else
{
ResRemoveFromQueue(node2, pendingList);
}
if (node2->rn_client != (ClientData)NULL)
{
freeMagic((char *)node2->rn_client);
node2->rn_client = (ClientData)NULL;
}
{
node2->rn_re = (resElement *)CLIENTDEFAULT;
node2->rn_ce = (cElement *)CLIENTDEFAULT;
node2->rn_je = (jElement *)CLIENTDEFAULT;
node2->rn_te = (tElement *)CLIENTDEFAULT;
node2->rn_more = (resNode *)CLIENTDEFAULT;
node2->rn_less = (resNode *)CLIENTDEFAULT;
}
freeMagic((char *)node2);
}
/*
*-------------------------------------------------------------------------
*
@ -835,12 +810,10 @@ ResDeleteResPointer(node,resistor)
{
notfound = FALSE;
if (rcell1 != NULL)
{
rcell1->re_nextEl = rcell2->re_nextEl;
}else
{
else
node->rn_re = rcell2->re_nextEl;
}
/* Set fields to null just in case there are any stray */
/* pointers to structure. */
rcell2->re_thisEl = NULL;
@ -852,11 +825,9 @@ ResDeleteResPointer(node,resistor)
rcell2 = rcell2->re_nextEl;
}
if (notfound)
{
TxError("Missing rptr at (%d %d).\n",
node->rn_loc.p_x, node->rn_loc.p_y);
}
}
/*
@ -878,19 +849,16 @@ ResEliminateResistor(resistor,homelist)
{
if (resistor->rr_lastResistor == NULL)
{
*homelist = resistor->rr_nextResistor;
}else
{
else
resistor->rr_lastResistor->rr_nextResistor = resistor->rr_nextResistor;
}
if (resistor->rr_nextResistor != NULL)
{
resistor->rr_nextResistor->rr_lastResistor = resistor->rr_lastResistor;
}
/* set everything to null so that any stray pointers will cause */
/* immediate death instead of a slow lingering one. */
resistor->rr_nextResistor = NULL;
resistor->rr_lastResistor = NULL;
resistor->rr_connection1 = NULL;
@ -898,7 +866,6 @@ ResEliminateResistor(resistor,homelist)
freeMagic((char *)resistor);
}
/*
*-------------------------------------------------------------------------
*
@ -960,36 +927,26 @@ ResCleanNode(resptr,junk,homelist1,homelist2)
freeMagic((char *)rcell);
}
if (resptr->rn_less != NULL)
{
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
{
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");
}
}
if (resptr->rn_more != NULL)
{
resptr->rn_more->rn_less = resptr->rn_less;
}
{
resptr->rn_re = (resElement *) CLIENTDEFAULT;
resptr->rn_ce = (cElement *) CLIENTDEFAULT;
resptr->rn_je = (jElement *) CLIENTDEFAULT;
resptr->rn_te = (tElement *) CLIENTDEFAULT;
resptr->rn_more = (resNode *) CLIENTDEFAULT;
resptr->rn_less = (resNode *) CLIENTDEFAULT;
}
freeMagic((char *)resptr);
}
}
@ -1036,28 +993,23 @@ ResFixBreakPoint(sourcelist,origNode,newNode)
if (alreadypresent)
{
if (bp2 == NULL)
{
*sourcelist = bp->br_next;
}else
{
else
bp2->br_next = bp->br_next;
}
bp3 = bp;
bp = bp->br_next;
if (bp3->br_crect != NULL && bp4->br_crect == NULL)
{
bp4->br_crect = bp3->br_crect;
}
freeMagic((char *)bp3);
continue;
}else
{
(bp->br_this = newNode);
}
else
bp->br_this = newNode;
}
bp2 = bp;
bp = bp->br_next;
}
}

View File

@ -171,16 +171,25 @@ ResPrintExtDev(outextfile, devices)
else
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->layout->rd_length * 2,
devices->rs_gattr,
devices->rs_gattr);
if (devices->source != NULL)
fprintf(outextfile, " \"%s\" %d %s",
devices->source->name,
devices->layout->rd_width,
devices->rs_sattr,
devices->rs_sattr);
if (devices->drain != NULL)
fprintf(outextfile, " \"%s\" %d %s",
devices->drain->name,
devices->layout->rd_width,
devices->rs_dattr);
fprintf(outextfile, "\n");
}
}
}

View File

@ -105,7 +105,6 @@ ResFixPoint *ResFixList;
extern void ResSimProcessDrivePoints();
/*
*-------------------------------------------------------------------------
*
@ -133,11 +132,11 @@ ResReadSim(simfile, fetproc, capproc, resproc, attrproc, mergeproc, subproc)
if (fp == NULL)
{
TxError("Cannot open file %s%s\n", simfile, ".sim");
return(1);
return 1;
}
extfile = 0;
/*read in file */
/* Read in file */
while (gettokens(line, fp) != 0)
{
fettype = MINFINITY;
@ -151,34 +150,45 @@ ResReadSim(simfile, fetproc, capproc, resproc, attrproc, mergeproc, subproc)
}
result=0;
break;
case 'e': fettype = DBTechNameType("efet");
case 'e':
fettype = DBTechNameType("efet");
break;
case 'd': fettype = DBTechNameType("dfet");
case 'd':
fettype = DBTechNameType("dfet");
break;
case 'n': fettype = DBTechNameType("nfet");
case 'n':
fettype = DBTechNameType("nfet");
break;
case 'p': fettype = DBTechNameType("pfet");
case 'p':
fettype = DBTechNameType("pfet");
break;
case 'b': fettype = DBTechNameType("bnpn");
case 'b':
fettype = DBTechNameType("bnpn");
break;
case 'C': if (capproc) result = (*capproc)(line);
case 'C':
if (capproc) result = (*capproc)(line);
break;
case 'R': if (resproc)result = (*resproc)(line);
case 'R':
if (resproc) result = (*resproc)(line);
break;
case '=': if (mergeproc)result = (*mergeproc)(line);
case '=':
if (mergeproc) result = (*mergeproc)(line);
break;
case 'A': if (attrproc) result =
(*attrproc)(line[ATTRIBUTENODENAME],
line[ATTRIBUTEVALUE],
simfile, &extfile);
case 'A':
if (attrproc)
result = (*attrproc)(line[ATTRIBUTENODENAME],
line[ATTRIBUTEVALUE], simfile, &extfile);
break;
case 'x': fettype = DBNumTypes;
case 'x':
fettype = DBNumTypes;
break;
case 'D':
case 'c':
case 'r': break;
default: result = 1;
(void)fclose(fp);
case 'r':
break;
default:
result = 1;
fclose(fp);
break;
}
if (fettype == -1)
@ -202,10 +212,10 @@ ResReadSim(simfile, fetproc, capproc, resproc, attrproc, mergeproc, subproc)
if (result != 0)
{
TxError("Error in sim file %s\n", line[0]);
return(1);
return 1;
}
}
(void)fclose(fp);
fclose(fp);
return(result);
}
@ -226,7 +236,6 @@ ResReadSim(simfile, fetproc, capproc, resproc, attrproc, mergeproc, subproc)
int
ResReadNode(nodefile)
char *nodefile;
{
char line[MAXLINE][MAXTOKEN];
FILE *fp, *fopen();
@ -239,7 +248,7 @@ ResReadNode(nodefile)
if (fp == NULL)
{
TxError("Cannot open file %s%s\n", nodefile, ".nodes");
return(1);
return 1;
}
while (gettokens(line,fp) != 0)
{
@ -259,14 +268,15 @@ ResReadNode(nodefile)
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");
(void)fclose(fp);
return(1);
fclose(fp);
return 1;
}
}
(void)fclose(fp);
return(0);
fclose(fp);
return 0;
}
/*
@ -286,7 +296,6 @@ int
gettokens(line, fp)
char line[][MAXTOKEN];
FILE *fp;
{
int i = 0, j = 0;
int c;
@ -296,10 +305,12 @@ gettokens(line,fp)
switch(c)
{
case ' ':
case ' ' : line[i++][j] = '\0';
case ' ' :
line[i++][j] = '\0';
j = 0;
break;
default: line[i][j++] = c;
default:
line[i][j++] = c;
break;
}
}
@ -309,12 +320,10 @@ gettokens(line,fp)
j = 0;
}
for (j = i; j < MAXLINE; j++)
{
line[j][0] = '\0';
}
return(i);
}
return i;
}
/*
*-------------------------------------------------------------------------
@ -359,6 +368,7 @@ ResSimSubckt(line)
ResRDevList = device;
device->layout = NULL;
device->source = device->drain = device->gate = device->subs = NULL;
/* The last argument is the name of the device */
for (i = 1; line[i][0] != '\0'; i++);
@ -471,25 +481,26 @@ ResSimDevice(line, rpersquare, ttype)
static int nowarning = TRUE;
float lambda;
device = (RDev *) mallocMagic((unsigned) (sizeof(RDev)));
if ((line[RDEV_WIDTH][0] == '\0') || (line[RDEV_LENGTH][0] == '\0'))
{
TxError("error in input file:\n");
return(1);
return 1;
}
else
{
device = (RDev *)mallocMagic((unsigned)(sizeof(RDev)));
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");
nowarning = FALSE;
}
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
device->resistance = 0;
}
device->status = FALSE;
device->nextDev = ResRDevList;
@ -502,6 +513,8 @@ ResSimDevice(line, rpersquare, ttype)
device->rs_dattr=RDEV_NOATTR;
device->rs_ttype = ttype;
device->gate = device->source = device->drain = device->subs = NULL;
/* sim attributes look like g=a1,a2 */
/* ext attributes are "a1","a2" */
/* do conversion from one to the other here */
@ -530,10 +543,17 @@ ResSimDevice(line, rpersquare, ttype)
strncpy(newattr, tmpattr, k);
switch (line[i][0])
{
case 'g': device->rs_gattr = newattr; break;
case 's': device->rs_sattr = newattr; break;
case 'd': device->rs_dattr = newattr; break;
default: TxError("Bad fet attribute\n");
case 'g':
device->rs_gattr = newattr;
break;
case 's':
device->rs_sattr = newattr;
break;
case 'd':
device->rs_dattr = newattr;
break;
default:
TxError("Bad fet attribute\n");
break;
}
}
@ -543,10 +563,9 @@ ResSimDevice(line, rpersquare, ttype)
ResSimNewNode(line[SOURCE], SOURCE, device) +
ResSimNewNode(line[DRAIN], DRAIN, device);
return(rvalue);
return rvalue;
}
/*
*-------------------------------------------------------------------------
*
@ -573,7 +592,7 @@ ResSimNewNode(line, type, device)
if (line[0] == '\0')
{
TxError("Missing device connection\n");
return(1);
return 1;
}
entry = HashFind(&ResNodeTable, line);
node = ResInitializeNode(entry);
@ -584,21 +603,25 @@ ResSimNewNode(line, type, device)
tptr->terminal = type;
switch(type)
{
case GATE: device->gate = node;
case GATE:
device->gate = node;
break;
case SOURCE: device->source = node;
case SOURCE:
device->source = node;
break;
case DRAIN: device->drain = node;
case DRAIN:
device->drain = node;
break;
case SUBS: device->subs = node;
case SUBS:
device->subs = node;
break;
default: TxError("Bad Terminal Specifier\n");
default:
TxError("Bad Terminal Specifier\n");
break;
}
return(0);
return 0;
}
/*
*-------------------------------------------------------------------------
*
@ -635,39 +658,38 @@ ResSimCapacitor(line)
if (strcmp(line[COUPLETERMINAL2], "GND") == 0 ||
strcmp(line[COUPLETERMINAL2], "Vdd") == 0)
{
return(0);
return 0;
}
entry2 = HashFind(&ResNodeTable, line[COUPLETERMINAL2]);
node2 = ResInitializeNode(entry2);
node2->capacitance += MagAtof(line[COUPLEVALUE]);
return(0);
return 0;
}
if (strcmp(line[COUPLETERMINAL2], "GND") == 0)
{
node1->capacitance += MagAtof(line[COUPLEVALUE]);
return(0);
return 0;
}
if (strcmp(line[COUPLETERMINAL2], "Vdd") == 0)
{
node1->cap_vdd += MagAtof(line[COUPLEVALUE]);
return(0);
return 0;
}
entry2 = HashFind(&ResNodeTable, line[COUPLETERMINAL2]);
node2 = ResInitializeNode(entry2);
if (strcmp(line[COUPLETERMINAL1], "GND") == 0)
{
node2->capacitance += MagAtof(line[COUPLEVALUE]);
return(0);
return 0;
}
if (strcmp(line[COUPLETERMINAL1], "Vdd") == 0)
{
node2->cap_vdd += MagAtof(line[COUPLEVALUE]);
return(0);
return 0;
}
node1->cap_couple += MagAtof(line[COUPLEVALUE]);
node2->cap_couple += MagAtof(line[COUPLEVALUE]);
return(0);
return 0;
}
@ -688,7 +710,6 @@ ResSimCapacitor(line)
int
ResSimResistor(line)
char line[][MAXTOKEN];
{
HashEntry *entry;
ResSimNode *node;
@ -696,21 +717,19 @@ ResSimResistor(line)
if (line[RESNODENAME][0] == 0)
{
TxError("Bad Resistor\n");
return(1);
return 1;
}
entry = HashFind(&ResNodeTable, line[RESNODENAME]);
node = ResInitializeNode(entry);
if (node->resistance != 0)
{
TxError("Duplicate Resistance Entries\n");
return(1);
return 1;
}
node->resistance = MagAtof(line[NODERESISTANCE]);
return(0);
}
/*
*-------------------------------------------------------------------------
*
@ -741,7 +760,7 @@ ResSimAttribute(aname,avalue,rootname,readextfile)
if (aname[0] == 0)
{
TxError("Bad Resistor\n");
return(1);
return 1;
}
entry = HashFind(&ResNodeTable, aname);
node = ResInitializeNode(entry);
@ -793,7 +812,8 @@ ResSimAttribute(aname,avalue,rootname,readextfile)
else
{
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;
}
}
@ -810,12 +830,11 @@ ResSimAttribute(aname,avalue,rootname,readextfile)
#endif
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)
{
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]);
node = ResInitializeNode(entry);
@ -863,7 +883,6 @@ ResSimProcessDrivePoints(filename)
}
}
/*
*-------------------------------------------------------------------------
*
@ -899,19 +918,20 @@ ResSimProcessFixPoints(filename)
while (gettokens(line, fp) != 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 += 8;
if (*label == ':') label++;
if ((c=strrchr(label, '"')) != NULL) *c = '\0';
else if (*label == '\0');
else
else if (*label != '\0')
{
TxError("Bad res:fix attribute label %s\n",
line[RES_EXT_ATTR_TEXT]);
*label ='\0';
}
thisfix = (ResFixPoint *) mallocMagic((unsigned) (sizeof(ResFixPoint)+strlen(label)));
thisfix = (ResFixPoint *)mallocMagic((unsigned)(sizeof(ResFixPoint)
+ strlen(label)));
thisfix->fp_next = ResFixList;
ResFixList = thisfix;
thisfix->fp_loc.p_x = atoi(line[RES_EXT_ATTR_X]);
@ -962,7 +982,7 @@ ResSimMerge(line)
ptr->nextDev = node->forward->firstDev;
node->forward->firstDev = ptr;
}
return(0);
return 0;
}
/*
@ -1011,5 +1031,5 @@ ResInitializeNode(entry)
{
node = node->forward;
}
return(node);
return node;
}

View File

@ -264,6 +264,17 @@ typedef enum {
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)
: RES_RUN;
@ -979,7 +990,7 @@ ResCheckSimNodes(celldef, resisdata)
t1->drain != t2->source)) break;
/* do parallel combination */
if (cumRes != 0.0 && t2->resistance != 0.0)
if ((cumRes != 0.0) && (t2->resistance != 0.0))
{
cumRes = (cumRes * t2->resistance) /
(cumRes + t2->resistance);
@ -1023,17 +1034,17 @@ ResCheckSimNodes(celldef, resisdata)
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 "
"driving device\n",node->name);
}
if (minRes == FLT_MAX || gparams.rg_devloc == NULL)
if ((minRes == FLT_MAX) || (gparams.rg_devloc == NULL))
{
continue;
}
gparams.rg_bigdevres = (int)minRes * OHMSTOMILLIOHMS;
if (rctol == 0.0 || tol == 0.0)
if ((rctol == 0.0) || (tol == 0.0))
{
ftolerance = 0.0;
rctolerance = 0.0;
@ -1049,7 +1060,7 @@ ResCheckSimNodes(celldef, resisdata)
* resistance? If so, extract net.
*/
if (node->resistance > ftolerance || node->status & FORCE ||
if ((node->resistance > ftolerance) || (node->status & FORCE) ||
(ResOpt_ExtractAll & ResOptionsFlags))
{
ResFixPoint fp;

View File

@ -48,8 +48,6 @@ int resRemoveLoops = FALSE;
extern void ResMoveDevices();
extern void ResAddResistorToList();
/*
*-------------------------------------------------------------------------
*
@ -75,27 +73,26 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
resNode *node, *otherNode, *node1, *node2;
resResistor *resistor1 = NULL, *resistor2 = NULL;
int numdrive = 0, numreceive = 0;
int MarkedReceivers,UnMarkedReceivers,NumberOfDrivers,PendingReceivers;
int MarkedReceivers, UnMarkedReceivers;
int NumberOfDrivers, PendingReceivers;
if (*nodelist == NULL) return;
node = *nodelist;
node->rn_status |= MARKED | FINISHED;
*nodelist = node->rn_more;
if (node->rn_more != NULL)
{
node->rn_more->rn_less = (resNode *) NULL;
}
node->rn_more = *biglist;
if (*biglist != (resNode *) NULL)
{
(*biglist)->rn_less = node;
}
*biglist = node;
/*
Walk though resistors. Mark uninitialized ones and assign them
A direction. Keep track of the number of resistors pointing in
each direction.
* Walk though resistors. Mark uninitialized ones and assign them
* a direction. Keep track of the number of resistors pointing in
* each direction.
*/
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))
{
if (resistor1 == NULL)
{
resistor1 = resisptr->re_thisEl;
}
else
{
resistor2 = resisptr->re_thisEl;
}
numdrive++;
}
else
{
/*
Resistor direction is from node1 to node2. If the resistor
is not marked, mark it and make sure the direction is
set properly.
* Resistor direction is from node1 to node2. If the resistor
* is not marked, mark it and make sure the direction is
* set properly.
*/
if ((resisptr->re_thisEl->rr_status & RES_MARKED) != RES_MARKED)
{
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_status |= RES_MARKED;
}
if (resistor1 == NULL)
{
resistor1 = resisptr->re_thisEl;
}
else
{
resistor2 = resisptr->re_thisEl;
}
numreceive++;
}
}
/*
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
more than 1, delete the current resistor to break the deadlock.
* 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
* more than 1, delete the current resistor to break the deadlock.
*/
if (numreceive == 0 && numdrive == 1 && node->rn_why != RES_NODE_ORIGIN)
{
resistor1->rr_status |= RES_DEADEND;
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;
UnMarkedReceivers = 0;
NumberOfDrivers = 0;
PendingReceivers = 0;
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_connection2->rn_status & MARKED) != MARKED)
if ((resisptr->re_thisEl->rr_connection2->rn_status & MARKED)
!= MARKED)
{
PendingReceivers++;
}
@ -169,23 +165,21 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
resisptr->re_thisEl->rr_value > tolerance)
{
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
{
UnMarkedReceivers++;
}
}
else
{
NumberOfDrivers++;
}
}
/* 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) ||
(UnMarkedReceivers == 0 && MarkedReceivers > 1 && resistor2 == resistor1 && PendingReceivers == 0))
(UnMarkedReceivers == 0 && MarkedReceivers > 1 &&
resistor2 == resistor1 && PendingReceivers == 0))
{
if (otherNode->rn_status & MARKED)
{
@ -194,19 +188,19 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
otherNode->rn_less = NULL;
otherNode->rn_more = *nodelist;
if (*nodelist != NULL)
{
(*nodelist)->rn_less = otherNode;
}
*nodelist = otherNode;
}
return;
}
/*
Break loop here. More than one driver indicates a loop;
remove deadend, allowing drivers to be merged
* Break loop here. More than one driver indicates a loop;
* 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;
@ -222,77 +216,73 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
otherNode->rn_less= NULL;
otherNode->rn_more = *nodelist;
if (*nodelist != NULL)
{
(*nodelist)->rn_less = otherNode;
}
*nodelist = otherNode;
}
ResDoneWithNode(otherNode);
}
}
}
/*
Two resistors in series? Combine them and move devices to
appropriate end.
* Two resistors in series? Combine them and move devices to
* appropriate end.
*/
else if (numdrive+numreceive == 2 &&
(resistor1->rr_value < tolerance && resistor2->rr_value < tolerance))
else if (numdrive+numreceive == 2 && (resistor1->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_connection1 = node;
}
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_connection1 = node;
}
resistor2->rr_status |= RES_MARKED;
node1 = (resistor1->rr_connection1 == node) ? resistor1->rr_connection2 : resistor1->rr_connection1;
node2 = (resistor2->rr_connection1 == node) ? resistor2->rr_connection2 : resistor2->rr_connection1;
node1 = (resistor1->rr_connection1 == node) ? resistor1->rr_connection2 :
resistor1->rr_connection1;
node2 = (resistor2->rr_connection1 == node) ? resistor2->rr_connection2 :
resistor2->rr_connection1;
otherNode = (resistor1->rr_status & RES_DEADEND &&
resistor1->rr_value < tolerance / 2) ||
((resistor2->rr_status & RES_DEADEND) == 0 &&
resistor1->rr_value < resistor2->rr_value) ? node1 : node2;
/*
make one big resistor out of two little ones, eliminating
the current node. Devices connected to this node are
moved to either end depending on their resistance.
* Make one big resistor out of two little ones, eliminating
* the current node. Devices connected to this node are
* moved to either end depending on their resistance.
*/
ResMoveDevices(node,otherNode);
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);
node1->rn_float.rn_area += resistor2->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 /
(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_float.rr_area +=resistor2->rr_float.rr_area;
if (resistor1 == *reslist)
{
*reslist = resistor1->rr_nextResistor;
}
else
{
resistor1->rr_lastResistor->rr_nextResistor = resistor1->rr_nextResistor;
}
if (resistor1->rr_nextResistor != NULL)
{
resistor1->rr_nextResistor->rr_lastResistor = resistor1->rr_lastResistor;
}
ResAddResistorToList(resistor1, reslist);
ResDeleteResPointer(node, resistor1);
ResDeleteResPointer(node, resistor2);
ResDeleteResPointer(node2, resistor2);
if (resistor1->rr_connection1 == node)
{
resistor1->rr_connection1 = node2;
}
else
{
resistor1->rr_connection2 = node2;
}
resisptr = (resElement *)mallocMagic((unsigned)(sizeof(resElement)));
resisptr->re_thisEl = resistor1;
resisptr->re_nextEl = node2->rn_re;
@ -308,9 +298,7 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
node1->rn_less = NULL;
node1->rn_more = *nodelist;
if (*nodelist != NULL)
{
(*nodelist)->rn_less = node1;
}
*nodelist = node1;
}
node2->rn_status &= ~RES_DONE_ONCE;
@ -321,18 +309,16 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
node2->rn_less = NULL;
node2->rn_more = *nodelist;
if (*nodelist != NULL)
{
(*nodelist)->rn_less = node2;
}
*nodelist = node2;
}
ResDoneWithNode(node1);
}
/*
Last resort- keep propagating down the tree. To avoid looping,
mark each node when it is reached. Don't reschedule node if
none of the connections to it have changed since it was marked
* Last resort- keep propagating down the tree. To avoid looping,
* mark each node when it is reached. Don't reschedule node if
* none of the connections to it have changed since it was marked
*/
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)
{
/*
elements with a resistance greater than the
tolerance should only be propagated past once-
loops may occur otherwise.
* Elements with a resistance greater than the
* tolerance should only be propagated past once-
* loops may occur otherwise.
*/
if (resisptr->re_thisEl->rr_status & RES_DONE_ONCE)
{
continue;
}
if (resisptr->re_thisEl->rr_connection2->rn_status & MARKED)
{
/*
mark big resistors so we only process them
once.
* Mark big resistors so we only process them
* once.
*/
if (resisptr->re_thisEl->rr_value > tolerance)
{
resisptr->re_thisEl->rr_status |= RES_DONE_ONCE;
}
resisptr->re_thisEl->rr_connection2->rn_status &= ~MARKED;
ResRemoveFromQueue(resisptr->re_thisEl->rr_connection2, biglist);
resisptr->re_thisEl->rr_connection2->rn_less= NULL;
resisptr->re_thisEl->rr_connection2->rn_more = *nodelist;
if (*nodelist != NULL)
{
(*nodelist)->rn_less = 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 (((ResPlug *)(device))->rpl_node == node1)
{
((ResPlug *)(device))->rpl_node = node2;
}
else
{
TxError("Bad node connection in plug\n");
}
}
else
{
if (device->rd_fet_gate == node1)
{
device->rd_fet_gate = node2;
}
else if (device->rd_fet_source == node1)
{
device->rd_fet_source = node2;
}
else if (device->rd_fet_drain == node1)
{
device->rd_fet_drain = node2;
}
else
{
TxError("Missing Device connection in squish routines at %d, %d\n",node1->rn_loc.p_x,node1->rn_loc.p_y);
}
TxError("Missing Device connection in squish routines"
" at %d, %d\n", node1->rn_loc.p_x, node1->rn_loc.p_y);
}
oldptr->te_nextt = node2->rn_te;
node2->rn_te = oldptr;
@ -439,7 +409,6 @@ ResMoveDevices(node1,node2)
node1->rn_te = NULL;
}
/*
*-------------------------------------------------------------------------
*
@ -468,42 +437,37 @@ ResScrunchNet(reslist,pendingList,biglist,tolerance)
resElement *rcell1;
int c1, c2;
/* sort resistors by size */
/* Sort resistors by size */
current = *reslist;
while (current != NULL)
{
working = current;
current = current->rr_nextResistor;
if (working == *reslist)
{
*reslist = current;
}
else
{
working->rr_lastResistor->rr_nextResistor = current;
}
if (current != NULL)
{
current->rr_lastResistor = working->rr_lastResistor;
}
ResAddResistorToList(working, &locallist);
}
*reslist = locallist;
while (*reslist != NULL && (*reslist)->rr_value < tolerance)
{
current = *reslist;
if (current->rr_nextResistor == NULL)
{
break;
}
working = NULL;
c1 = 0;
c2 = 0;
/* search for next smallest adjoining resistor */
for (rcell1 = current->rr_connection1->rn_re; rcell1 != NULL; rcell1 = rcell1->re_nextEl)
/* Search for next smallest adjoining resistor */
for (rcell1 = current->rr_connection1->rn_re; rcell1 != NULL;
rcell1 = rcell1->re_nextEl)
{
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)
{
@ -544,9 +509,9 @@ ResScrunchNet(reslist,pendingList,biglist,tolerance)
}
}
/*
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,
simply add its area to its node.
* 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,
* simply add its area to its node.
*/
if (c1 != 0 && c2 != 0)
{
@ -558,17 +523,17 @@ ResScrunchNet(reslist,pendingList,biglist,tolerance)
node1->rn_float.rn_area += current->rr_float.rr_area;
}
/*
Move everything from from one end of the ressistor to the
other and eliminate the resistor.
* Move everything from from one end of the ressistor to the
* 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_connection2, current);
working->rr_lastResistor->rr_nextResistor = working->rr_nextResistor;
if (working->rr_nextResistor != NULL)
{
working->rr_nextResistor->rr_lastResistor = working->rr_lastResistor;
}
ResEliminateResistor(current, reslist);
ResAddResistorToList(working, reslist);
if (node2->rn_why & RES_NODE_ORIGIN)
@ -577,25 +542,20 @@ ResScrunchNet(reslist,pendingList,biglist,tolerance)
node1 = node2;
}
else
{
ResMergeNodes(node1,node2,pendingList,biglist);
}
/*
Try further simplification on net using ResDoneWithNode and
ResSimplifyNet.
* Try further simplification on net using ResDoneWithNode and
* ResSimplifyNet.
*/
ResRemoveFromQueue(node1, biglist);
ResAddToQueue(node1, pendingList);
node1->rn_status &= ~(RES_DONE_ONCE | FINISHED);
ResDoneWithNode(node1);
while (*pendingList != NULL)
{
ResSimplifyNet(pendingList,biglist,reslist,tolerance);
}
}
}
/*
*-------------------------------------------------------------------------
@ -620,9 +580,7 @@ ResAddResistorToList(resistor,locallist)
for (local = *locallist; local != NULL; local = local->rr_nextResistor)
{
if (local->rr_value >= resistor->rr_value)
{
break;
}
last = local;
}
if (local != NULL)
@ -630,13 +588,10 @@ ResAddResistorToList(resistor,locallist)
resistor->rr_nextResistor = local;
resistor->rr_lastResistor = local->rr_lastResistor;
if (local->rr_lastResistor == NULL)
{
*locallist = resistor;
}
else
{
local->rr_lastResistor->rr_nextResistor = resistor;
}
local->rr_lastResistor = resistor;
}
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 (rptr = workingNode->rn_re; rptr != NULL; rptr=rptr->re_nextEl)
{
if (rptr->re_thisEl->rr_float.rr_area != 0.0)
{
TxError("Nonnull resistor area\n");
}
/* workingNode->rn_float.rn_area += rptr->re_thisEl->rr_float.rr_area/2; */
}
totalarea += workingNode->rn_float.rn_area;
}
if (totalarea == 0)
@ -700,12 +650,10 @@ ResDistributeCapacitance(nodelist,totalcap)
return;
}
capperarea = FEMTOTOATTO * totalcap / totalarea;
for (workingNode = nodelist; workingNode != NULL; workingNode=workingNode->rn_more)
{
workingNode->rn_float.rn_area *= capperarea;
}
}
/*
*-------------------------------------------------------------------------
@ -734,17 +682,16 @@ ResCalculateChildCapacitance(me)
int t;
ExtDevice *devptr;
if (me->rn_client != (ClientData) NULL) /* we have a loop */
{
return(-1);
}
myC = (RCDelayStuff *) mallocMagic((unsigned) (sizeof(RCDelayStuff)));
me->rn_client = (ClientData) myC;
/* This following assumes that ResDistributeCapacitance has been run */
/* and the the resulting capacitance value is stored in the area field */
myC->rc_Cdownstream = me->rn_float.rn_area;
myC->rc_Tdi = 0.0;
/* get capacitance for all connected gates */
for (tptr = me->rn_te; tptr != NULL; tptr = tptr->te_nextt)
@ -763,9 +710,7 @@ ResCalculateChildCapacitance(me)
if (dev->rd_fet_gate == me)
{
devptr = ExtCurStyle->exts_device[t];
myC->rc_Cdownstream +=
dev->rd_length*
dev->rd_width*
myC->rc_Cdownstream += dev->rd_length * dev->rd_width *
devptr->exts_deviceGateCap +
(dev->rd_width + dev->rd_width) *
devptr->exts_deviceSDCap;
@ -781,16 +726,14 @@ ResCalculateChildCapacitance(me)
{
childcap = ResCalculateChildCapacitance(workingRes->re_thisEl->rr_connection2);
if (childcap == -1)
{
return(-1);
}
myC->rc_Cdownstream += childcap;
}
}
return (myC->rc_Cdownstream);
}
/*
*-------------------------------------------------------------------------
*
@ -817,29 +760,24 @@ ResCalculateTDi(node,resistor,resistorvalue)
ASSERT(rcd != NULL, "ResCalculateTdi");
if (resistor == NULL)
{
rcd->rc_Tdi = rcd->rc_Cdownstream*(float)resistorvalue;
}
else
{
rcd2 = (RCDelayStuff *)resistor->rr_connection1->rn_client;
ASSERT(rcd2 != NULL,"ResCalculateTdi");
rcd->rc_Tdi = rcd->rc_Cdownstream * (float)resistor->rr_value +
rcd2->rc_Tdi;
}
for (workingRes = node->rn_re; workingRes != NULL; workingRes = workingRes->re_nextEl)
{
if (workingRes->re_thisEl->rr_connection1 == node &&
(workingRes->re_thisEl->rr_status & RES_TDI_IGNORE) == 0)
{
ResCalculateTDi(workingRes->re_thisEl->rr_connection2,
workingRes->re_thisEl,
workingRes->re_thisEl->rr_value);
}
}
}
/*
*-------------------------------------------------------------------------
@ -872,16 +810,18 @@ ResPruneTree(node,minTdi,nodelist1,nodelist2,resistorlist)
current = current->re_nextEl;
/* if branch points outward, call routine on subtrees */
if (currentRes->rr_connection1 == node)
{
ResPruneTree(currentRes->rr_connection2, minTdi,nodelist1,nodelist2,resistorlist);
ResPruneTree(currentRes->rr_connection2, minTdi, nodelist1,
nodelist2, resistorlist);
}
}
/* We eliminate this branch if */
/* 1. It is a terminal node, i.e. it is the connected */
/* to only one resistor. */
/* 2. The direction of this resistor is toward the node */
/* (This prevents the root from being eliminated */
/* 3. The time constant TDI is less than the tolerance. */
/* We eliminate this branch if:
* 1. It is a terminal node, i.e. it is the connected
* to only one resistor.
* 2. The direction of this resistor is toward the node
* (This prevents the root from being eliminated
* 3. The time constant TDI is less than the tolerance.
*/
if (node->rn_re != NULL &&
node->rn_re->re_nextEl == NULL &&
node->rn_re->re_thisEl->rr_connection2 == node)
@ -895,12 +835,19 @@ ResPruneTree(node,minTdi,nodelist1,nodelist2,resistorlist)
currentRes = node->rn_re->re_thisEl;
ResDeleteResPointer(currentRes->rr_connection1, 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);
}
}
}
/*
*-------------------------------------------------------------------------
*
*-------------------------------------------------------------------------
*/
int
ResDoSimplify(tolerance, rctol, goodies)
float tolerance;
@ -914,13 +861,10 @@ ResDoSimplify(tolerance,rctol,goodies)
float totalcap;
resResistor *res;
resRemoveLoops = FALSE;
ResSetPathRes();
for (node = ResNodeList; node != NULL; node = node->rn_more)
{
bigres = MAX(bigres,node->rn_noderes);
}
bigres /= OHMSTOMILLIOHMS; /* convert from milliohms to ohms */
goodies->rg_maxres = bigres;
@ -936,11 +880,10 @@ ResDoSimplify(tolerance,rctol,goodies)
(void) ResDistributeCapacitance(ResNodeList,goodies->rg_nodecap);
if ((tolerance > bigres || (ResOptionsFlags &ResOpt_Simplify)==0) &&
(ResOptionsFlags &ResOpt_DoLumpFile)==0)
{
return(0);
}
if (((tolerance > bigres) || ((ResOptionsFlags & ResOpt_Simplify) == 0)) &&
((ResOptionsFlags & ResOpt_DoLumpFile) == 0))
return 0;
res = ResResList;
while (res)
{
@ -975,7 +918,7 @@ ResDoSimplify(tolerance,rctol,goodies)
for (node = ResNodeList; node != NULL; node = node->rn_more)
{
rc = (RCDelayStuff *)node->rn_client;
if (rc && (goodies->rg_Tdi < rc->rc_Tdi))
if ((rc != NULL) && (goodies->rg_Tdi < rc->rc_Tdi))
{
slownode = node;
goodies->rg_Tdi = rc->rc_Tdi;
@ -984,93 +927,85 @@ ResDoSimplify(tolerance,rctol,goodies)
slownode->rn_status |= RN_MAXTDI;
}
else
{
goodies->rg_Tdi = -1;
}
}
else
{
goodies->rg_Tdi = 0;
}
if ((rctol+1) * goodies->rg_bigdevres * goodies->rg_nodecap >
rctol * goodies->rg_Tdi &&
(ResOptionsFlags & ResOpt_Tdi) &&
goodies->rg_Tdi != -1)
{
return(0);
}
return 0;
/* Simplify network; resistors are still in milliohms, so use
millitolerance.
* millitolerance.
*/
if (ResOptionsFlags & ResOpt_Simplify)
{
millitolerance = tolerance * MILLIOHMSPEROHM;
/*
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
remain in the pending 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 remain in the pending list.
*/
for (node = ResNodeList; node != NULL; node = node->rn_more)
{
if (node->rn_noderes == 0)
{
ResOriginNode = node;
}
node->rn_status |= FINISHED;
}
if (ResOriginNode != NULL)
{
/* if Tdi is enabled, prune all branches whose end nodes have */
/* time constants less than the tolerance. */
/* if Tdi is enabled, prune all branches whose end nodes */
/* have time constants less than the tolerance. */
if ((ResOptionsFlags & ResOpt_Tdi) &&
goodies->rg_Tdi != -1 &&
rctol != 0)
{
ResPruneTree(ResOriginNode,
(rctol+1)*goodies->rg_bigdevres*goodies->rg_nodecap/rctol,
ResPruneTree(ResOriginNode, (rctol + 1) *
goodies->rg_bigdevres * goodies->rg_nodecap / rctol,
&ResNodeList, &ResNodeQueue, &ResResList);
}
ResOriginNode->rn_status &= ~MARKED;
if (ResOriginNode->rn_less == NULL)
{
ResNodeList = ResOriginNode->rn_more;
}
else
{
ResOriginNode->rn_less->rn_more = ResOriginNode->rn_more;
}
if (ResOriginNode->rn_more != NULL)
{
ResOriginNode->rn_more->rn_less = ResOriginNode->rn_less;
}
ResOriginNode->rn_more = NULL;
ResOriginNode->rn_less = NULL;
ResNodeQueue = ResOriginNode;
while (ResNodeQueue != NULL)
{
ResSimplifyNet(&ResNodeQueue,&ResNodeList,&ResResList,millitolerance);
}
/*
Call ResScrunchNet to eliminate any remaining under tolerance
resistors.
* Call ResScrunchNet to eliminate any remaining under tolerance
* resistors.
*/
ResScrunchNet(&ResResList,&ResNodeQueue,&ResNodeList,millitolerance);
}
}
return(0);
return 0;
}
/*
*-------------------------------------------------------------------------
*
*-------------------------------------------------------------------------
*/
void
ResSetPathRes()
{
HeapEntry he;
resNode *node;
@ -1105,10 +1040,14 @@ ResSetPathRes()
ASSERT(ResOriginNode != NULL, "ResDoSimplify");
resPathNode(ResOriginNode);
while (HeapRemoveTop(&ResistorHeap,&he))
{
resPathRes((resResistor *)he.he_id);
}
}
/*
*-------------------------------------------------------------------------
*
*-------------------------------------------------------------------------
*/
void
resPathNode(node)
@ -1126,12 +1065,16 @@ resPathNode(node)
if (res->rr_status & RES_HEAP) continue;
if ((node2 = res->rr_node[0]) == node) node2 = res->rr_node[1];
if ((node2->rn_status & FINISHED) == 0)
{
HeapAddInt(&ResistorHeap, node->rn_noderes + res->rr_value,
(char *)res);
}
}
}
/*
*-------------------------------------------------------------------------
*
*-------------------------------------------------------------------------
*/
void
resPathRes(res)

View File

@ -417,11 +417,12 @@ HeapAdd(heap, pKey, id)
{
/* If odd then new entry is the right half of a pair */
cmp = i;
if (i & 1)
if ((i & 1) && (i != 1))
KEY_LE_COND(keyType, list, i, i-1, cmp = i-1);
/* Find parent. If 0 then at the root so quit */
if ((i >>= 1) == 0) return;
KEY_LE_COND(keyType, list, cmp, i, return);
list[0] = list[cmp]; list[cmp] = list[i]; list[i] = list[0];
heapify(heap, cmp);
@ -434,11 +435,12 @@ HeapAdd(heap, pKey, id)
{
/* If odd then new entry is the right half of a pair */
cmp = i;
if (i & 1)
if ((i & 1) && (i != 1))
KEY_GE_COND(keyType, list, i, i-1, cmp = i-1);
/* Find parent. If 0 then at the root so quit */
if ((i >>= 1) == 0) return;
KEY_GE_COND(keyType, list, cmp, i, return);
list[0] = list[cmp]; list[cmp] = list[i]; list[i] = list[0];
heapify(heap, cmp);