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