1 
2 #ifndef lint
3 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResMerge.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
4 #endif  /* not lint */
5 
6 #include <stdio.h>
7 
8 #include "utils/magic.h"
9 #include "utils/geometry.h"
10 #include "utils/geofast.h"
11 #include "tiles/tile.h"
12 #include "utils/hash.h"
13 #include "database/database.h"
14 #include "utils/malloc.h"
15 #include "textio/textio.h"
16 #include "extract/extractInt.h"
17 #include "resis/resis.h"
18 
19 TileTypeBitMask	ResNoMergeMask[NT];
20 
21 /* Forward declarations */
22 
23 extern void ResMergeNodes();
24 extern void ResDeleteResPointer();
25 extern void ResEliminateResistor();
26 extern void ResCleanNode();
27 extern void ResFixBreakPoint();
28 
29 
30 /*
31  *-------------------------------------------------------------------------
32  *
33  * ResDoneWithNode--
34  *   After all connections to node are made, ResDoneWithNode is
35  *   called. It checks for parallel, series, loop, triangle, and
36  *   single conections, and simplifies the network where possible.
37  *
38  * Results: none
39  *
40  * Side Effects: deletes resistors and/or nodes.
41  *
42  *-------------------------------------------------------------------------
43  */
44 
45 void
ResDoneWithNode(resptr)46 ResDoneWithNode(resptr)
47     resNode *resptr;
48 
49 {
50     int		status;
51     resNode	*resptr2;
52     resElement	*rcell1;
53     resResistor	*rr1;
54 
55     resptr2 = NULL;
56     resptr->rn_status |= TRUE;
57     status = UNTOUCHED;
58 
59     /* are there any resistors? */
60 
61     if (resptr->rn_re == NULL) return;
62 
63     /* Special handling for geometry option */
64 
65     if (ResOptionsFlags & ResOpt_Geometry) return;
66 
67     /* Eliminate resistors with connections to one terminal and */
68     /* resistors with value 0.					*/
69 
70     for (rcell1 = resptr->rn_re; rcell1 != NULL; rcell1 = rcell1->re_nextEl)
71     {
72      	rr1 = rcell1->re_thisEl;
73 	if (rr1->rr_connection1 == rr1->rr_connection2)
74 	{
75 	    ResDeleteResPointer(resptr, rr1);
76 	    ResDeleteResPointer(resptr, rr1);
77 	    resptr->rn_float.rn_area += rr1->rr_float.rr_area;
78 	    ResEliminateResistor(rr1, &ResResList);
79 	    status = LOOP;
80 	    ResDoneWithNode(resptr);
81 	    break;
82 
83 	}
84 	else if (rr1->rr_value == 0)
85 	{
86 	    ResDeleteResPointer(rr1->rr_connection1, rr1);
87 	    ResDeleteResPointer(rr1->rr_connection2, rr1);
88 	    if (rr1->rr_connection1 == resptr)
89 		resptr2 = rr1->rr_connection2;
90 	    else
91 		resptr2 = rr1->rr_connection1;
92 
93 	    ResMergeNodes(resptr2, resptr, &ResNodeQueue, &ResNodeList);
94 	    resptr2->rn_float.rn_area += rr1->rr_float.rr_area;
95 	    ResEliminateResistor(rr1, &ResResList);
96 	    if ((resptr2->rn_status & TRUE) == TRUE)
97 	    {
98 		resptr2->rn_status &= ~TRUE;
99 		ResDoneWithNode(resptr2);
100 	    }
101 	    resptr2 = NULL;
102 	    status = SINGLE;
103 	    break;
104 	}
105     }
106     if (status != UNTOUCHED) return;  /* resptr may be invalid */
107 
108     /* Eliminations that can be only if there are no devices connected */
109     /* to node.  Series and dangling connections fall in this group.	*/
110 
111     if ((resptr->rn_te == NULL) && (resptr->rn_why != RES_NODE_ORIGIN)
112 		&& (status == UNTOUCHED))
113      	status = ResSeriesCheck(resptr);
114 
115     if ((status == UNTOUCHED) && (resptr->rn_why != RES_NODE_ORIGIN))
116 	status = ResParallelCheck(resptr);
117 
118     if ((status == UNTOUCHED) && (resptr->rn_why != RES_NODE_ORIGIN))
119 	status = ResTriangleCheck(resptr);
120 }
121 
122 
123 /*
124  *------------------------------------------------------------------------
125  *
126  * ResFixRes--
127  *
128  * Results: none
129  *
130  * Side Effects: ResFixRes combines two resistors in series.  the second
131  * Resistor is eliminated.  Resptr is the node that is "cut out" of the
132  * network.
133  *
134  *------------------------------------------------------------------------
135  */
136 
137 void
ResFixRes(resptr,resptr2,resptr3,elimResis,newResis)138 ResFixRes(resptr, resptr2, resptr3, elimResis, newResis)
139     resNode *resptr, *resptr2, *resptr3;
140     resResistor *elimResis, *newResis;
141 
142 {
143     resElement  *thisREl;
144 
145     resptr3->rn_float.rn_area += newResis->rr_value * resptr->rn_float.rn_area
146 		/ ((float)(newResis->rr_value + elimResis->rr_value));
147     resptr2->rn_float.rn_area += elimResis->rr_value * resptr->rn_float.rn_area
148 		/ ((float)(newResis->rr_value + elimResis->rr_value));
149     newResis->rr_value += elimResis->rr_value;
150     ASSERT(newResis->rr_value > 0, "series");
151     newResis->rr_float.rr_area += elimResis->rr_float.rr_area;
152 
153 #ifdef ARIEL
154     if (elimResis->rr_csArea && elimResis->rr_csArea < newResis->rr_csArea
155 		|| newResis->rr_csArea == 0)
156     {
157      	newResis->rr_csArea = elimResis->rr_csArea;
158 	newResis->rr_tt = elimResis->rr_tt;
159     }
160 #endif
161     for (thisREl = resptr3->rn_re; (thisREl != NULL); thisREl = thisREl->re_nextEl)
162     {
163      	if (thisREl->re_thisEl == elimResis)
164 	{
165 	    (thisREl->re_thisEl = newResis);
166 	    break;
167 	}
168 
169     }
170     if (thisREl == NULL) TxError("Resistor not found in duo\n");
171     ResDeleteResPointer(resptr, elimResis);
172     ResDeleteResPointer(resptr, newResis);
173     ResEliminateResistor(elimResis, &ResResList);
174     ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
175 }
176 
177 /*
178  *------------------------------------------------------------------------
179  *
180  * ResFixParallel--
181  *
182  * Results: none
183  *
184  * Side Effects: ResFixParallel combines two resistors in parallel. T
185  *  	The second  Resistor is eliminated.
186  *
187  *
188  *------------------------------------------------------------------------
189  */
190 
191 void
ResFixParallel(elimResis,newResis)192 ResFixParallel(elimResis, newResis)
193     resResistor *elimResis, *newResis;
194 
195 {
196     if ((newResis->rr_value + elimResis->rr_value) != 0)
197     {
198         newResis->rr_value = (((float) newResis->rr_value) *
199 	  			((float)elimResis->rr_value)) /
200      		            	((float)(newResis->rr_value +
201 				 elimResis->rr_value));
202 	ASSERT(newResis->rr_value >= 0, "parallel");
203     }
204     else
205     {
206      	newResis->rr_value = 0;
207     }
208     newResis->rr_float.rr_area += elimResis->rr_float.rr_area;
209 #ifdef ARIEL
210     newResis->rr_csArea += elimResis->rr_csArea;
211 #endif
212     ResDeleteResPointer(elimResis->rr_connection1, elimResis);
213     ResDeleteResPointer(elimResis->rr_connection2, elimResis);
214     ResEliminateResistor(elimResis, &ResResList);
215 }
216 
217 /*
218  *-------------------------------------------------------------------------
219  *
220  * ResSeriesCheck -- for nodes with no devices, sees if a series
221  *	or loop combination is possible.
222  *
223  * Results: returns SINGLE,LOOP,or SERIES if succesful.
224  *
225  * Side Effects: may delete some nodes and resistors.
226  *
227  *-------------------------------------------------------------------------
228  */
229 
230 int
ResSeriesCheck(resptr)231 ResSeriesCheck(resptr)
232     resNode	*resptr;
233 
234 {
235     resResistor	*rr1,*rr2;
236     resNode	*resptr2, *resptr3;
237     int		status = UNTOUCHED;
238     resElement	*res_next;
239 
240     rr1 = resptr->rn_re->re_thisEl;
241     res_next = resptr->rn_re->re_nextEl;
242 
243     if (res_next == NULL)
244     /* node with only one connection */
245     {
246 	resptr2 = (rr1->rr_connection1 == resptr) ? rr1->rr_connection2:
247 	  					    rr1->rr_connection1;
248 
249 	ResDeleteResPointer(rr1->rr_connection1, rr1);
250 	ResDeleteResPointer(rr1->rr_connection2, rr1);
251 	resptr2->rn_float.rn_area += rr1->rr_float.rr_area +
252 	  				resptr->rn_float.rn_area;
253 	ResEliminateResistor(rr1, &ResResList);
254 	ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
255 	status = SINGLE;
256 	if (resptr2->rn_status & TRUE)
257 	{
258 	    resptr2->rn_status &= ~TRUE;
259 	    ResDoneWithNode(resptr2);
260 	}
261 	resptr2 = NULL;
262     }
263     else if (res_next->re_nextEl == NULL)
264     {
265 	rr2 = res_next->re_thisEl;
266 	if (!TTMaskHasType(ResNoMergeMask + rr1->rr_tt, rr2->rr_tt))
267 	{
268 	    if (rr1->rr_connection1 == resptr)
269 	    {
270 		if (rr2->rr_connection1 == resptr)
271 		{
272 		    resptr2 = rr1->rr_connection2;
273 		    if (rr1->rr_connection2 == rr2->rr_connection2)
274 		    {
275 			status = LOOP;
276 			ResDeleteResPointer(rr1->rr_connection1, rr1);
277 			ResDeleteResPointer(rr1->rr_connection2, rr1);
278 			ResDeleteResPointer(rr2->rr_connection1, rr2);
279 			ResDeleteResPointer(rr2->rr_connection2, rr2);
280 			resptr2->rn_float.rn_area += rr1->rr_float.rr_area
281 					+ rr2->rr_float.rr_area
282 					+ resptr->rn_float.rn_area;
283 			ResEliminateResistor(rr1, &ResResList);
284 			ResEliminateResistor(rr2, &ResResList);
285 			ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
286 		    }
287 		    else
288 		    {
289 			status = SERIES;
290 			resptr3 = rr2->rr_connection2;
291 			rr1->rr_connection1 = rr2->rr_connection2;
292 			ResFixRes(resptr, resptr2, resptr3, rr2, rr1);
293 		    }
294 		    if ((resptr2->rn_status & TRUE) == TRUE)
295 		    {
296 			resptr2->rn_status &= ~TRUE;
297 			ResDoneWithNode(resptr2);
298 		    }
299 		    resptr2 = NULL;
300 		}
301 		else
302 		{
303   		    resptr2 = rr1->rr_connection2;
304 		    if (rr1->rr_connection2 == rr2->rr_connection1)
305 		    {
306 			status = LOOP;
307 			ResDeleteResPointer(rr1->rr_connection1, rr1);
308 			ResDeleteResPointer(rr1->rr_connection2, rr1);
309 			ResDeleteResPointer(rr2->rr_connection1, rr2);
310 			ResDeleteResPointer(rr2->rr_connection2, rr2);
311 	        	resptr2->rn_float.rn_area += rr1->rr_float.rr_area
312 					+ rr2->rr_float.rr_area
313 					+ resptr->rn_float.rn_area;
314 			ResEliminateResistor(rr1, &ResResList);
315 			ResEliminateResistor(rr2, &ResResList);
316 			ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
317 		    }
318 		    else
319 		    {
320 			status = SERIES;
321 			resptr3 = rr2->rr_connection1;
322 			rr1->rr_connection1 = rr2->rr_connection1;
323 			ResFixRes(resptr, resptr2, resptr3, rr2, rr1);
324 		    }
325 		    if ((resptr2->rn_status & TRUE) == TRUE)
326 		    {
327 			resptr2->rn_status &= ~TRUE;
328 			ResDoneWithNode(resptr2);
329 		    }
330 		    resptr2 = NULL;
331 		}
332 	    }
333 	    else
334 	    {
335 		if (rr2->rr_connection1 == resptr)
336 		{
337 		    resptr2 = rr1->rr_connection1;
338 		    if (rr1->rr_connection1 == rr2->rr_connection2)
339 		    {
340 			status = LOOP;
341 			ResDeleteResPointer(rr1->rr_connection1, rr1);
342 			ResDeleteResPointer(rr1->rr_connection2, rr1);
343 			ResDeleteResPointer(rr2->rr_connection1, rr2);
344 			ResDeleteResPointer(rr2->rr_connection2, rr2);
345 	        	resptr2->rn_float.rn_area += rr1->rr_float.rr_area
346 					+ rr2->rr_float.rr_area
347 					+ resptr->rn_float.rn_area;
348 			ResEliminateResistor(rr1, &ResResList);
349 			ResEliminateResistor(rr2, &ResResList);
350 			ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
351 		    }
352 		    else
353 		    {
354 			status = SERIES;
355 			resptr3 = rr2->rr_connection2;
356 			rr1->rr_connection2 = rr2->rr_connection2;
357 			ResFixRes(resptr, resptr2, resptr3, rr2, rr1);
358 		    }
359 		    if ((resptr2->rn_status & TRUE) == TRUE)
360 		    {
361 			resptr2->rn_status &= ~TRUE;
362 			ResDoneWithNode(resptr2);
363 		    }
364 		    resptr2 = NULL;
365 		}
366 		else
367 		{
368 		    resptr2 = rr1->rr_connection1;
369 		    if (rr1->rr_connection1 == rr2->rr_connection1)
370 		    {
371 			status = LOOP;
372 			ResDeleteResPointer(rr1->rr_connection1, rr1);
373 			ResDeleteResPointer(rr1->rr_connection2, rr1);
374 			ResDeleteResPointer(rr2->rr_connection1, rr2);
375 			ResDeleteResPointer(rr2->rr_connection2, rr2);
376 	        	resptr2->rn_float.rn_area += rr1->rr_float.rr_area
377 					+ rr2->rr_float.rr_area
378 					+ resptr->rn_float.rn_area;
379 			ResEliminateResistor(rr1, &ResResList);
380 			ResEliminateResistor(rr2, &ResResList);
381 			ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
382 		    }
383 		    else
384 		    {
385 			status = SERIES;
386 			resptr3 = rr2->rr_connection1;
387 			rr1->rr_connection2 = rr2->rr_connection1;
388 			ResFixRes(resptr, resptr2, resptr3, rr2, rr1);
389 		    }
390 		    if ((resptr2->rn_status & TRUE) == TRUE)
391 		    {
392 			resptr2->rn_status &= ~TRUE;
393 			ResDoneWithNode(resptr2);
394 		    }
395 		    resptr2 = NULL;
396 		}
397 	    }
398 	}
399     }
400     return status;
401 }
402 
403 /*
404  *-------------------------------------------------------------------------
405  *
406  * ResParallelCheck -- tries to do parallel combinations of devices.
407  *
408  * Results: returns PARALLEL if successful
409  *
410  * Side Effects: may delete resistors and nodes.
411  *
412  *-------------------------------------------------------------------------
413  */
414 
415 int
ResParallelCheck(resptr)416 ResParallelCheck(resptr)
417     resNode	*resptr;
418 
419 {
420     resResistor	*r1,*r2;
421     resNode	*resptr2,*resptr3;
422     int		status = UNTOUCHED;
423     resElement	*rcell1, *rcell2;
424 
425 
426     for (rcell1 = resptr->rn_re; rcell1->re_nextEl != NULL;
427 		    rcell1 = rcell1->re_nextEl)
428     {
429 	r1 = rcell1->re_thisEl;
430 
431 	for (rcell2 = rcell1->re_nextEl; rcell2 != NULL;
432 		    rcell2 = rcell2->re_nextEl)
433 
434 	{
435 	    r2 = rcell2->re_thisEl;
436 	    if (TTMaskHasType(ResNoMergeMask+r1->rr_tt, r2->rr_tt)) continue;
437 	    if (((r1->rr_connection1 == r2->rr_connection1) &&
438 	            (r1->rr_connection2 == r2->rr_connection2))||
439 	            ((r1->rr_connection1 == r2->rr_connection2) &&
440 	            (r1->rr_connection2 == r2->rr_connection1)))
441 	    {
442 	        resptr3 = (r1->rr_connection1 == resptr) ?
443 		     		r1->rr_connection2 :  r1->rr_connection1;
444 		ResFixParallel(r1, r2);
445 	        status = PARALLEL;
446 		resptr2 = NULL;
447 		if (resptr3->rn_status & TRUE)
448 		{
449 		    resptr2 = resptr3;
450 		    resptr2->rn_status &= ~TRUE;
451 		}
452 		ResDoneWithNode(resptr);
453 		if (resptr2 != NULL) ResDoneWithNode(resptr2);
454 	        break;
455 	    }
456 	}
457 	if (status == PARALLEL) break;
458     }
459     return status;
460 }
461 
462 
463 /*
464  *-------------------------------------------------------------------------
465  *
466  * ResTriangleCheck -- looks for places to do the traingle-to-Y conversion.
467  *
468  * Results: returns TRIANGLE if successful.
469  *
470  * Side Effects: may allocate a new node.
471  *
472  *-------------------------------------------------------------------------
473  */
474 
475 int
ResTriangleCheck(resptr)476 ResTriangleCheck(resptr)
477     resNode	*resptr;
478 
479 {
480     resResistor	*rr1, *rr2, *rr3;
481     int		status = UNTOUCHED;
482     float	r1, r2, r3, denom;
483     resNode	*n1, *n2, *n3;
484     resElement	*rcell1, *rcell2, *rcell3, *element;
485 
486     for (rcell1 = resptr->rn_re; rcell1->re_nextEl != NULL;
487 		rcell1 = rcell1->re_nextEl)
488     {
489         rr1 = rcell1->re_thisEl;
490 	n1 = (rr1->rr_connection1 == resptr) ? rr1->rr_connection2:
491 	  		       rr1->rr_connection1;
492 
493         for (rcell2 = rcell1->re_nextEl; rcell2 != NULL;
494 		    rcell2 = rcell2->re_nextEl)
495 	{
496 	    rr2 = rcell2->re_thisEl;
497 	    if (TTMaskHasType(ResNoMergeMask + rr1->rr_tt, rr2->rr_tt))
498 		continue;
499 	    n2 = (rr2->rr_connection1 == resptr) ? rr2->rr_connection2 :
500 	       					    rr2->rr_connection1;
501 	    for (rcell3 = n1->rn_re; rcell3 != NULL;
502 			rcell3 = rcell3->re_nextEl)
503 	    {
504 		rr3 = rcell3->re_thisEl;
505 		if (TTMaskHasType(ResNoMergeMask + rr1->rr_tt, rr3->rr_tt))
506 		    continue;
507 		if (TTMaskHasType(ResNoMergeMask + rr2->rr_tt, rr3->rr_tt))
508 		    continue;
509 
510 		if (((rr3->rr_connection1 != n1) ||
511 		        (rr3->rr_connection2 != n2)) &&
512 		        ((rr3->rr_connection2 != n1) ||
513 		        (rr3->rr_connection1 != n2))) continue;
514 
515 		status = TRIANGLE;
516 		if ((denom = rr1->rr_value + rr2->rr_value + rr3->rr_value) != 0.0)
517 		{
518 		    denom = 1.0  /denom;
519 		    /* calculate new values for resistors */
520 		    r1 = (((float)rr1->rr_value) * ((float)rr2->rr_value)) * denom;
521 
522 		    r2 = (((float)rr2->rr_value) * ((float)rr3->rr_value)) * denom;
523 
524 		    r3 = (((float)rr1->rr_value) * ((float)rr3->rr_value)) * denom;
525 
526 		    rr1->rr_value = r1 + 0.5;
527 		    rr2->rr_value = r2 + 0.5;
528 		    rr3->rr_value = r3 + 0.5;
529 		    ASSERT(rr1->rr_value >= 0, "Triangle");
530 		    ASSERT(rr2->rr_value >= 0, "Triangle");
531 		    ASSERT(rr3->rr_value >= 0, "Triangle");
532 		}
533 	        else
534 		{
535 		    rr1->rr_value = 0;
536 		    rr2->rr_value = 0;
537 		    rr3->rr_value = 0;
538 	        }
539 		n3 = (resNode *)mallocMagic((unsigned)(sizeof(resNode)));
540 
541 	      	/* Where should the new node be put?  It    */
542 	        /* is arbitrarily assigned to the location  */
543 		/* occupied by the first node.		    */
544 
545 		InitializeNode(n3, resptr->rn_loc.p_x, resptr->rn_loc.p_y, TRIANGLE);
546 		n3->rn_status = FINISHED | TRUE | MARKED;
547 
548 		n3->rn_less = NULL;
549 		n3->rn_more = ResNodeList;
550 		ResNodeList->rn_less = n3;
551 		ResNodeList = n3;
552 		if (resptr == rr1->rr_connection1)
553 		{
554 		    ResDeleteResPointer(rr1->rr_connection2, rr1);
555 		    rr1->rr_connection2 = n3;
556 		}
557 		else
558 		{
559 		    ResDeleteResPointer(rr1->rr_connection1, rr1);
560 		    rr1->rr_connection1 = n3;
561 		}
562 		if (n2 == rr2->rr_connection1)
563 		{
564 		    ResDeleteResPointer(rr2->rr_connection2, rr2);
565 		    rr2->rr_connection2 = n3;
566 		}
567 		else
568 		{
569 		    ResDeleteResPointer(rr2->rr_connection1, rr2);
570 		    rr2->rr_connection1 = n3;
571 		}
572 		if (n1 == rr3->rr_connection1)
573 		{
574 		    ResDeleteResPointer(rr3->rr_connection2, rr3);
575 		    rr3->rr_connection2 = n3;
576 		}
577 		else
578 		{
579 		    ResDeleteResPointer(rr3->rr_connection1, rr3);
580 		    rr3->rr_connection1 = n3;
581 		}
582 		element = (resElement *)mallocMagic((unsigned)(sizeof(resElement)));
583 		element->re_nextEl = NULL;
584 		element->re_thisEl = rr1;
585 		n3->rn_re = element;
586 		element = (resElement *)mallocMagic((unsigned)(sizeof(resElement)));
587 		element->re_nextEl = n3->rn_re;
588 		element->re_thisEl = rr2;
589 		n3->rn_re = element;
590 		element = (resElement *)mallocMagic((unsigned)(sizeof(resElement)));
591 		element->re_nextEl = n3->rn_re;
592 		element->re_thisEl = rr3;
593 		n3->rn_re = element;
594 	      	if ((n1->rn_status & TRUE) == TRUE)
595 		    n1->rn_status &= ~TRUE;
596 		else
597 		    n1 = NULL;
598 
599 		if ((n2->rn_status & TRUE) == TRUE)
600 		    n2->rn_status &= ~TRUE;
601 		else
602 		    n2 = NULL;
603 
604 		ResDoneWithNode(resptr);
605 		if (n1 != NULL) ResDoneWithNode(n1);
606 		if (n2 != NULL) ResDoneWithNode(n2);
607 		break;
608 	    }
609 	    if (status == TRIANGLE) break;
610 	}
611 	if (status == TRIANGLE) break;
612     }
613     return status;
614 }
615 
616 /*
617  *--------------------------------------------------------------------------
618  *
619  * ResMergeNodes--
620  *
621  * results: none
622  *
623  * side effects: appends all the cElement, jElement, tElement and
624  *       resElement structures from node 2 onto node 1.  Node 2 is
625  *	 then eliminated.
626  *
627  *---------------------------------------------------------------------------
628  */
629 
630 void
ResMergeNodes(node1,node2,pendingList,doneList)631 ResMergeNodes(node1, node2, pendingList, doneList)
632     resNode *node1, *node2;
633     resNode **pendingList, **doneList;
634 {
635     resElement	*workingRes, *tRes;
636     tElement	*workingDev, *tDev;
637     jElement	*workingJunc, *tJunc;
638     cElement	*workingCon, *tCon;
639     Tile	*tile;
640     int		i;
641 
642     /* sanity check */
643     if (node1 == node2) return;
644 
645     if (node1 == NULL || node2 == NULL)
646     {
647       	TxError("Attempt to merge NULL node\n");
648 	return;
649     }
650 
651     /* don't want to merge away startpoint */
652     if (node2->rn_why & RES_NODE_ORIGIN)
653       	node1->rn_why = RES_NODE_ORIGIN;
654 
655     /* set node resistance */
656     if (node1->rn_noderes > node2->rn_noderes)
657     {
658 	node1->rn_noderes = node2->rn_noderes;
659 	if ((node1->rn_status & FINISHED) != FINISHED)
660 	{
661 	    ResRemoveFromQueue(node1, pendingList);
662 	    ResAddToQueue(node1, pendingList);
663 	}
664     }
665     node1->rn_float.rn_area += node2->rn_float.rn_area;
666 
667     /* combine relevant flags */
668     node1->rn_status |= (node2->rn_status & RN_MAXTDI);
669 
670     /* merge device lists */
671     workingDev = node2->rn_te;
672     while (workingDev != NULL)
673     {
674       	if (workingDev->te_thist->rd_status & RES_DEV_PLUG)
675 	{
676 	    ResPlug *plug = (ResPlug *) workingDev->te_thist;
677 	    if (plug->rpl_node == node2)
678 	       	plug->rpl_node = node1;
679 	    else
680 	    {
681 	       	TxError("Bad plug node: is (%d %d), should be (%d %d)\n",
682 		    	    plug->rpl_node->rn_loc, node2->rn_loc);
683 	       	plug->rpl_node = NULL;
684 	    }
685 	}
686 	else
687 	{
688 	    int j;
689 
690 	    for (j = 0; j != workingDev->te_thist->rd_nterms; j++)
691 		if (workingDev->te_thist->rd_terminals[j] == node2)
692 	   	    workingDev->te_thist->rd_terminals[j] = node1;
693 	 }
694 	 tDev = workingDev;
695 	 workingDev = workingDev->te_nextt;
696 	 tDev->te_nextt = node1->rn_te;
697 	 node1->rn_te = tDev;
698     }
699 
700     /* append junction lists */
701 
702     workingJunc = node2->rn_je;
703     while (workingJunc != NULL)
704     {
705 	tJunc = workingJunc;
706 	for (i = 0; i < TILES_PER_JUNCTION; i++)
707 	{
708 	    tileJunk *junk;
709 
710 	    tile = tJunc->je_thisj->rj_Tile[i];
711 	    junk = (tileJunk *) tile->ti_client;
712 
713 	    if ((junk->tj_status & RES_TILE_DONE) == FALSE)
714 		ResFixBreakPoint(&junk->breakList, node2, node1);
715 	}
716         tJunc->je_thisj->rj_jnode = node1;
717 	workingJunc = workingJunc->je_nextj;
718 	tJunc->je_nextj = node1->rn_je;
719 	node1->rn_je = tJunc;
720      }
721 
722      /* Append connection lists */
723      workingCon = node2->rn_ce;
724      while (workingCon != NULL)
725      {
726 	tCon = workingCon;
727 	for (i = 0; i < workingCon->ce_thisc->cp_currentcontact; i++)
728 	{
729 	    if (workingCon->ce_thisc->cp_cnode[i] == node2)
730 	    {
731 	        tileJunk *junk;
732 
733 		workingCon->ce_thisc->cp_cnode[i] = node1;
734 	        tile =tCon->ce_thisc->cp_tile[i];
735 		junk = (tileJunk *) tile->ti_client;
736 	   	if ((junk->tj_status & RES_TILE_DONE) == FALSE)
737 		    ResFixBreakPoint(&junk->breakList, node2, node1);
738 	    }
739 	}
740 	workingCon = workingCon->ce_nextc;
741 	tCon->ce_nextc = node1->rn_ce;
742 	node1->rn_ce = tCon;
743     }
744 
745     /* Moves resistors to new node  */
746 
747     workingRes = node2->rn_re;
748     while (workingRes != NULL)
749     {
750 	if (workingRes->re_thisEl->rr_connection1 == node2)
751 	    workingRes->re_thisEl->rr_connection1 = node1;
752       	else if (workingRes->re_thisEl->rr_connection2 == node2)
753 	    workingRes->re_thisEl->rr_connection2 = node1;
754 	else
755 	    TxError("Resistor not found.\n");
756 
757 	tRes = workingRes;
758 	workingRes = workingRes->re_nextEl;
759 	tRes->re_nextEl = node1->rn_re;
760 	node1->rn_re = tRes;
761     }
762     if ((node2->rn_status & FINISHED) == FINISHED)
763       	ResRemoveFromQueue(node2, doneList);
764     else
765       	ResRemoveFromQueue(node2, pendingList);
766 
767     if (node2->rn_client != (ClientData)NULL)
768     {
769 	freeMagic((char *)node2->rn_client);
770 	node2->rn_client = (ClientData)NULL;
771     }
772 
773     node2->rn_re = (resElement *)CLIENTDEFAULT;
774     node2->rn_ce = (cElement   *)CLIENTDEFAULT;
775     node2->rn_je = (jElement   *)CLIENTDEFAULT;
776     node2->rn_te = (tElement   *)CLIENTDEFAULT;
777     node2->rn_more = (resNode  *)CLIENTDEFAULT;
778     node2->rn_less = (resNode  *)CLIENTDEFAULT;
779     freeMagic((char *)node2);
780 }
781 
782 /*
783  *-------------------------------------------------------------------------
784  *
785  * ResDeleteResPointer-- Deletes the pointer from a node to a resistor.
786  *	Used when a resistor is deleted.
787  *
788  * Results:none
789  *
790  * Side Effects: Modifies a node's resistor list.
791  *
792  *-------------------------------------------------------------------------
793  */
794 
795 void
ResDeleteResPointer(node,resistor)796 ResDeleteResPointer(node,resistor)
797     resNode	*node;
798     resResistor	*resistor;
799 
800 {
801     resElement	*rcell1, *rcell2;
802     int		notfound = TRUE;
803 
804     rcell1 = NULL;
805     rcell2 = node->rn_re;
806     while (rcell2 != NULL)
807     {
808      	if (rcell2->re_thisEl == resistor)
809 	{
810 	    notfound = FALSE;
811 	    if (rcell1 != NULL)
812 	       	rcell1->re_nextEl = rcell2->re_nextEl;
813 	    else
814 	       	node->rn_re = rcell2->re_nextEl;
815 
816 	    /* Set fields to null just in case there are any stray  */
817 	    /* pointers to structure.				    */
818 	    rcell2->re_thisEl = NULL;
819 	    rcell2->re_nextEl = NULL;
820 	    freeMagic((char *)rcell2);
821 	    break;
822 	}
823 	rcell1 = rcell2;
824 	rcell2 = rcell2->re_nextEl;
825     }
826     if (notfound)
827      	TxError("Missing rptr at (%d %d).\n",
828 	  		node->rn_loc.p_x, node->rn_loc.p_y);
829 }
830 
831 
832 /*
833  *-------------------------------------------------------------------------
834  *
835  * ResEliminateResistor--
836  *
837  * Results:none
838  *
839  * Side Effects: Deletes a resistor. Does not delete pointers from nodes to
840  *	resistor.
841  *
842  *-------------------------------------------------------------------------
843  */
844 
845 void
ResEliminateResistor(resistor,homelist)846 ResEliminateResistor(resistor, homelist)
847     resResistor *resistor, **homelist;
848 
849 {
850     if (resistor->rr_lastResistor == NULL)
851      	*homelist = resistor->rr_nextResistor;
852     else
853      	resistor->rr_lastResistor->rr_nextResistor = resistor->rr_nextResistor;
854 
855     if (resistor->rr_nextResistor != NULL)
856      	resistor->rr_nextResistor->rr_lastResistor = resistor->rr_lastResistor;
857 
858     /* set everything to null so that any stray pointers will cause */
859     /* immediate death instead of a slow lingering one.		    */
860 
861     resistor->rr_nextResistor = NULL;
862     resistor->rr_lastResistor = NULL;
863     resistor->rr_connection1 = NULL;
864     resistor->rr_connection2 = NULL;
865     freeMagic((char *)resistor);
866 }
867 
868 /*
869  *-------------------------------------------------------------------------
870  *
871  * ResCleanNode--removes the linked lists of junctions and contacts after
872  *		they are no longer needed. If the 'junk' option is used,
873  *		the node is eradicated.
874  *
875  * Results:
876  *	None.
877  *
878  * Side Effects: frees memory
879  *
880  *-------------------------------------------------------------------------
881  */
882 
883 void
ResCleanNode(resptr,junk,homelist1,homelist2)884 ResCleanNode(resptr, junk, homelist1, homelist2)
885     resNode *resptr;
886     int	    junk;
887     resNode **homelist1;
888     resNode **homelist2;
889 {
890     resElement *rcell;
891     cElement *ccell;
892     jElement *jcell;
893     tElement *tcell;
894 
895     /* free up contact and junction lists */
896     while (resptr->rn_ce != NULL)
897     {
898 	ccell = resptr->rn_ce;
899 	resptr->rn_ce = resptr->rn_ce->ce_nextc;
900 	freeMagic((char *)ccell);
901     }
902     while (resptr->rn_je != NULL)
903     {
904 	jcell = resptr->rn_je;
905 	resptr->rn_je = resptr->rn_je->je_nextj;
906 	freeMagic((char *)jcell->je_thisj);
907 	freeMagic((char *)jcell);
908     }
909     if (junk == TRUE)
910     {
911 	if (resptr->rn_client != (ClientData)NULL)
912 	{
913 	    freeMagic((char *)resptr->rn_client);
914 	    resptr->rn_client = (ClientData)NULL;
915 	}
916 	while (resptr->rn_te != NULL)
917         {
918 	    tcell = resptr->rn_te;
919 	    resptr->rn_te = resptr->rn_te->te_nextt;
920 	    freeMagic((char *)tcell);
921         }
922         while (resptr->rn_re != NULL)
923         {
924 	    rcell = resptr->rn_re;
925 	    resptr->rn_re = resptr->rn_re->re_nextEl;
926 	    freeMagic((char *)rcell);
927         }
928 	if (resptr->rn_less != NULL)
929 	    resptr->rn_less->rn_more = resptr->rn_more;
930 	else
931 	{
932 	    if (*homelist1 == resptr)
933 	        *homelist1 = resptr->rn_more;
934 	    else if (*homelist2 == resptr)
935 	        *homelist2 = resptr->rn_more;
936 	    else
937 	       	TxError("Error: Attempted to eliminate node from wrong list.\n");
938 	}
939 	if (resptr->rn_more != NULL)
940 	    resptr->rn_more->rn_less = resptr->rn_less;
941 
942 	resptr->rn_re = (resElement *) CLIENTDEFAULT;
943 	resptr->rn_ce = (cElement   *) CLIENTDEFAULT;
944 	resptr->rn_je = (jElement   *) CLIENTDEFAULT;
945 	resptr->rn_te = (tElement   *) CLIENTDEFAULT;
946 	resptr->rn_more = (resNode   *) CLIENTDEFAULT;
947 	resptr->rn_less = (resNode   *) CLIENTDEFAULT;
948 
949 	freeMagic((char *)resptr);
950     }
951 }
952 
953 
954 /*
955  *-------------------------------------------------------------------------
956  *
957  * ResFixBreakPoint--moves breakpoints from one node to another, checking
958  *     first to see whether the target node already has the breakpoint.
959  *     Used when nodes are merged.
960  *
961  * Results: none
962  *
963  * Side Effects: may free up memory if breakpoint is already present.
964  *
965  *-------------------------------------------------------------------------
966  */
967 
968 void
ResFixBreakPoint(sourcelist,origNode,newNode)969 ResFixBreakPoint(sourcelist, origNode, newNode)
970     Breakpoint	**sourcelist;
971     resNode	*origNode, *newNode;
972 
973 {
974     Breakpoint	*bp, *bp2, *bp3, *bp4;
975     int		alreadypresent;
976 
977     alreadypresent = FALSE;
978     for (bp4 = *sourcelist; bp4 != NULL; bp4 = bp4->br_next)
979     {
980 	if (bp4->br_this == newNode)
981 	{
982 	    alreadypresent = TRUE;
983 	    break;
984 	}
985     }
986     bp2 = NULL;
987     bp = *sourcelist;
988     while (bp != NULL)
989     {
990      	if (bp->br_this == origNode)
991 	{
992 	    if (alreadypresent)
993 	    {
994 	       	if (bp2 == NULL)
995 		    *sourcelist = bp->br_next;
996 		else
997 		    bp2->br_next = bp->br_next;
998 
999 		bp3 = bp;
1000 		bp = bp->br_next;
1001 
1002 		if (bp3->br_crect != NULL &&  bp4->br_crect == NULL)
1003 		    bp4->br_crect = bp3->br_crect;
1004 
1005 		freeMagic((char *)bp3);
1006 		continue;
1007 	    }
1008 	    else
1009 	       	bp->br_this = newNode;
1010 	}
1011 	bp2 = bp;
1012 	bp = bp->br_next;
1013     }
1014 }
1015