1 
2 #ifndef lint
3 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResUtils.c,v 1.3 2010/06/24 12:37:56 tim Exp $";
4 #endif  /* not lint */
5 
6 #include <stdio.h>
7 #include <string.h>
8 #include <ctype.h>
9 #include <math.h>
10 
11 #include "utils/magic.h"
12 #include "utils/geometry.h"
13 #include "utils/geofast.h"
14 #include "tiles/tile.h"
15 #include "utils/hash.h"
16 #include "database/database.h"
17 #include "utils/malloc.h"
18 #include "textio/textio.h"
19 #include "extract/extract.h"
20 #include "extract/extractInt.h"
21 #include "windows/windows.h"
22 #include "dbwind/dbwind.h"
23 #include "utils/stack.h"
24 #include "utils/tech.h"
25 #include "textio/txcommands.h"
26 #include "resis/resis.h"
27 
28 
29 /*
30  * ---------------------------------------------------------------------------
31  *
32  * ResFirst -- Checks to see if tile is a contact. If it is, allocate a
33  *	contact structure.
34  *
35  *
36  * Results: Always returns NULL (in the form of a Region pointer)
37  *
38  * Side effects:
39  *	Memory is allocated by ResFirst.
40  *	We cons the newly allocated region onto the front of the existing
41  *	region list.
42  *
43  *
44  * -------------------------------------------------------------------------
45  */
46 
47 Region *
ResFirst(tile,arg)48 ResFirst(tile, arg)
49     Tile *tile;
50     FindRegion *arg;
51 {
52     ResContactPoint *reg;
53     TileType t;
54     int i;
55 
56     if (IsSplit(tile))
57     {
58 	t = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
59     }
60     else
61 	t = TiGetType(tile);
62 
63     if (DBIsContact(t))
64     {
65 	reg = (ResContactPoint *) mallocMagic((unsigned) (sizeof(ResContactPoint)));
66 	reg->cp_center.p_x = (LEFT(tile) + RIGHT(tile)) >> 1;
67 	reg->cp_center.p_y = (TOP(tile) + BOTTOM(tile)) >> 1;
68 	reg->cp_status = FALSE;
69 	reg->cp_type = t;
70 	reg->cp_width = RIGHT(tile) - LEFT(tile);
71 	reg->cp_height = TOP(tile) - BOTTOM(tile);
72 	for (i = 0; i < LAYERS_PER_CONTACT; i++)
73 	{
74 	    reg->cp_tile[i] = (Tile *) NULL;
75 	    reg->cp_cnode[i] = (resNode *) NULL;
76 	}
77 	reg->cp_currentcontact = 0;
78 	reg->cp_rect.r_ll.p_x = tile->ti_ll.p_x;
79 	reg->cp_rect.r_ll.p_y = tile->ti_ll.p_y;
80 	reg->cp_rect.r_ur.p_x = RIGHT(tile);
81 	reg->cp_rect.r_ur.p_y = TOP(tile);
82 	reg->cp_contactTile = tile;
83 	/* Prepend it to the region list */
84 	reg->cp_nextcontact = (ResContactPoint *) arg->fra_region;
85 	arg->fra_region = (Region *) reg;
86     }
87     return((Region *) NULL);
88 }
89 
90 /*
91  *--------------------------------------------------------------------------
92  *
93  * resMultiPlaneTerm --
94  *
95  * Callback function to set a junk field
96  *
97  *--------------------------------------------------------------------------
98  */
99 
100 int
resMultiPlaneTerm(Tile * tile,tileJunk * junk2)101 resMultiPlaneTerm(Tile *tile, tileJunk *junk2)
102 {
103     tileJunk *Junk;
104 
105     Junk = resAddField(tile);
106     Junk->tj_status |= RES_TILE_SD;
107     junk2->sourceEdge |= OTHERPLANE;
108     return 0;
109 }
110 
111 /*
112  *--------------------------------------------------------------------------
113  *
114  * resSubstrateTerm --
115  *
116  * Callback function to set a junk field
117  *
118  *--------------------------------------------------------------------------
119  */
120 
121 int
resSubstrateTerm(Tile * tile)122 resSubstrateTerm(Tile *tile)
123 {
124     tileJunk *Junk;
125 
126     Junk = resAddField(tile);
127     Junk->tj_status |= RES_TILE_SUBS;
128     return 0;
129 }
130 
131 /*
132  *--------------------------------------------------------------------------
133  *
134  * ResEach--
135  *
136  * ResEach calls ResFirst unless this is the first contact, in which case it
137  * has alreay been processed
138  *
139  * results: returns 0
140  *
141  * Side Effects: see ResFirst
142  *
143  * -------------------------------------------------------------------------
144  */
145 
146 int
ResEach(tile,pNum,arg)147 ResEach(tile, pNum, arg)
148     Tile	*tile;
149     int		pNum;
150     FindRegion	*arg;
151 {
152 
153     if (((ResContactPoint *)(arg->fra_region))->cp_contactTile != tile)
154     {
155 	ResFirst(tile, arg);
156     }
157     return(0);
158 }
159 
160 /*
161  *-------------------------------------------------------------------------
162  *
163  * ResAddPlumbing-- Each tile is a tileJunk structure associated with it
164  * to keep track of various things used by the extractor. ResAddPlumbing
165  * adds this structure and sets the tile's ClientData field to point to it.
166  * If the tile is a device, then a device structure is also added;
167  * all connected device tiles are enumerated and their deviceList
168  * fields set to the new structure.
169  *
170  * Results: always returns 0
171  *
172  * Side Effects:see above
173  *
174  *-------------------------------------------------------------------------
175  */
176 
177 int
ResAddPlumbing(tile,arg)178 ResAddPlumbing(tile, arg)
179     Tile	*tile;
180     ClientData	*arg;
181 {
182     tileJunk		*Junk, *junk2;
183     static Stack	*resDevStack = NULL;
184     TileType		loctype, t1;
185     Tile		*tp1, *tp2, *source;
186     resDevice		*resDev;
187     ExtDevice		*devptr;
188     TileTypeBitMask	locDevSubsMask;
189 
190     if (resDevStack == NULL)
191      	resDevStack = StackNew(64);
192 
193     if (tile->ti_client == (ClientData) CLIENTDEFAULT)
194     {
195 	if (IsSplit(tile))
196 	    loctype = (SplitSide(tile)) ? SplitRightType(tile) :
197 			SplitLeftType(tile);
198 	else
199 	    loctype = TiGetTypeExact(tile);
200 
201 	devptr = ExtCurStyle->exts_device[loctype];
202      	junk2 = resAddField(tile);
203 	if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), loctype))
204 	{
205 	    int i, nterms, pNum;
206 	    Rect r;
207 
208 	    /* Count SD terminals of the device */
209 	    nterms = 0;
210 	    for (i = 0;; i++)
211 	    {
212 		if (TTMaskIsZero(&(devptr->exts_deviceSDTypes[i]))) break;
213 		nterms++;
214 	    }
215 	    if (nterms < devptr->exts_deviceSDCount)
216 		nterms = devptr->exts_deviceSDCount;
217 
218 	    /* resDev terminals includes device identifier (e.g., gate) and
219 	     * substrate, so add two to nterms.
220 	     */
221 	    nterms += 2;
222 
223    	    resDev = (resDevice *) mallocMagic((unsigned)(sizeof(resDevice)));
224 	    resDev->rd_nterms = nterms;
225 	    resDev->rd_terminals = (resNode **) mallocMagic(nterms * sizeof(resNode *));
226 	    for (i = 0; i != nterms; i++)
227 	    	resDev->rd_terminals[i] = (resNode *) NULL;
228 
229             resDev->rd_tile = tile;
230 	    resDev->rd_inside.r_ll.p_x = LEFT(tile);
231 	    resDev->rd_inside.r_ll.p_y = BOTTOM(tile);
232 	    resDev->rd_inside.r_ur.p_x = RIGHT(tile);
233 	    resDev->rd_inside.r_ur.p_y = TOP(tile);
234 	    resDev->rd_devtype = loctype;
235             resDev->rd_tiles = 0;
236 	    resDev->rd_length = 0;
237 	    resDev->rd_width = 0;
238 	    resDev->rd_perim = 0;
239 	    resDev->rd_area = 0;
240 	    resDev->rd_status = 0;
241             resDev->rd_nextDev = (resDevice *) *arg;
242 	    *arg = (ClientData)resDev;
243 	    junk2->deviceList =  resDev;
244 	    junk2->tj_status |= RES_TILE_DEV;
245 
246 	    for (i = 0; i < nterms - 2; i++)
247 	    {
248 		source = NULL;
249 		/* find diffusion (if present) to be source contact */
250 
251 		/* top */
252 		for (tp2 = RT(tile); RIGHT(tp2) > LEFT(tile); tp2 = BL(tp2))
253 		{
254 		    if TTMaskHasType(&(devptr->exts_deviceSDTypes[i]),
255 				TiGetBottomType(tp2))
256 		    {
257 			junk2->sourceEdge |= TOPEDGE;
258 			source = tp2;
259 			Junk = resAddField(source);
260 			Junk->tj_status |= RES_TILE_SD;
261 			break;
262 		    }
263 		}
264 
265 		/* bottom */
266 		if (source == NULL)
267 		for (tp2 = LB(tile); LEFT(tp2) < RIGHT(tile); tp2 = TR(tp2))
268 		{
269 		    if TTMaskHasType(&(devptr->exts_deviceSDTypes[i]),
270 				TiGetTopType(tp2))
271 		    {
272 			junk2->sourceEdge |= BOTTOMEDGE;
273 			source = tp2;
274 			Junk = resAddField(source);
275 			Junk->tj_status |= RES_TILE_SD;
276 			break;
277 		    }
278 		}
279 
280 		/* right */
281 		if (source == NULL)
282 		for (tp2 = TR(tile); TOP(tp2) > BOTTOM(tile); tp2 = LB(tp2))
283 		{
284 		    if TTMaskHasType(&(devptr->exts_deviceSDTypes[i]),
285 				TiGetLeftType(tp2))
286 		    {
287 			junk2->sourceEdge |= RIGHTEDGE;
288 			source = tp2;
289 			Junk = resAddField(source);
290 			Junk->tj_status |= RES_TILE_SD;
291 			break;
292 		    }
293 		}
294 
295 		/* left */
296 		if (source == NULL)
297 		for (tp2 = BL(tile); BOTTOM(tp2) < TOP(tile); tp2 = RT(tp2))
298 		{
299 		    if TTMaskHasType(&(devptr->exts_deviceSDTypes[i]),
300 				TiGetRightType(tp2))
301 		    {
302 			source = tp2;
303 			Junk = resAddField(source);
304 			Junk->tj_status |= RES_TILE_SD;
305 			junk2->sourceEdge |= LEFTEDGE;
306 			break;
307 		    }
308 		}
309 
310 		/* other plane (in ResUse) */
311 		if (source == NULL)
312 		{
313 		    TiToRect(tile, &r);
314 		    for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
315 		    {
316 			if (TTMaskIntersect(&DBPlaneTypes[pNum],
317 				&(devptr->exts_deviceSDTypes[i])))
318 			    DBSrPaintArea((Tile *)NULL,
319 				    ResUse->cu_def->cd_planes[pNum],
320 				    &r, &(devptr->exts_deviceSDTypes[i]),
321 				    resMultiPlaneTerm, (ClientData)junk2);
322 		    }
323 		}
324 
325 		/* We need to know whether a given diffusion tile connects to
326 		 * the source or to the drain of a device.  A single
327 		 * diffusion tile is marked, and all connecting diffusion tiles
328 		 * are enumerated and called the source.  Any other SD tiles
329 		 * are assumed to be the drain.  BUG: this does not work
330 		 * correctly with multi SD structures.
331 		 */
332 
333 		if (source != (Tile *) NULL)
334 		{
335 		    STACKPUSH((ClientData)source, resDevStack);
336 		}
337 	    }
338 	    while (!StackEmpty(resDevStack))
339 	    {
340 	       	tp1 = (Tile *) STACKPOP(resDevStack);
341 		if (IsSplit(tp1))
342 		{
343 		    t1 = (SplitSide(tp1)) ? SplitRightType(tp1) :
344 				SplitLeftType(tp1);
345 		}
346 		else
347 		    t1 = TiGetTypeExact(tp1);
348 
349 		/* top */
350 		for (tp2 = RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2))
351 		{
352 		    if (TiGetBottomType(tp2) == t1)
353 		    {
354 		        tileJunk *j = resAddField(tp2);
355 			if ((j->tj_status & RES_TILE_SD) == 0)
356 			{
357 			    j->tj_status |= RES_TILE_SD;
358 	            	    STACKPUSH((ClientData)tp2, resDevStack);
359 			}
360 		    }
361 		}
362 		/* bottom */
363 		for (tp2 = LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2))
364 		{
365 		    if (TiGetTopType(tp2) == t1)
366 		    {
367 		        tileJunk *j = resAddField(tp2);
368 			if ((j->tj_status & RES_TILE_SD) == 0)
369 			{
370 			    j->tj_status |= RES_TILE_SD;
371 	            	    STACKPUSH((ClientData)tp2, resDevStack);
372 			}
373 		    }
374 		}
375 		/* right */
376 		for (tp2 = TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2))
377 		{
378 		    if (TiGetLeftType(tp2) == t1)
379 		    {
380 		        tileJunk *j = resAddField(tp2);
381 			if ((j->tj_status & RES_TILE_SD) == 0)
382 			{
383 			    j->tj_status |= RES_TILE_SD;
384 	            	    STACKPUSH((ClientData)tp2, resDevStack);
385 			}
386 		    }
387 		}
388 		/* left */
389 		for (tp2 = BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2))
390 		{
391 		    if (TiGetRightType(tp2) == t1)
392 		    {
393 		        tileJunk *j = resAddField(tp2);
394 			if ((j->tj_status & RES_TILE_SD) == 0)
395 			{
396 			    j->tj_status |= RES_TILE_SD;
397 	            	    STACKPUSH((ClientData)tp2, resDevStack);
398 			}
399 		    }
400 		}
401 	    }
402 
403 	    /* Find device substrate */
404 
405 	    TTMaskZero(&locDevSubsMask);
406 	    TTMaskSetMask(&locDevSubsMask, &(devptr->exts_deviceSubstrateTypes));
407 	    TTMaskClearType(&locDevSubsMask, TT_SPACE);
408 
409 	    TiToRect(tile, &r);
410 	    for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
411 	    {
412 		if (TTMaskIntersect(&DBPlaneTypes[pNum], &locDevSubsMask))
413 		    DBSrPaintArea((Tile *)NULL,
414 				    ResUse->cu_def->cd_planes[pNum],
415 				    &r, &locDevSubsMask,
416 				    resSubstrateTerm, (ClientData)NULL);
417 	    }
418 
419 	    /* find rest of device; search for source edges */
420 
421 	    STACKPUSH((ClientData)tile, resDevStack);
422 	    while (!StackEmpty(resDevStack))
423 	    {
424 	       	tileJunk *j0;
425 
426 		tp1 = (Tile *) STACKPOP(resDevStack);
427 		if (IsSplit(tp1))
428 		{
429 		    t1 = (SplitSide(tp1)) ? SplitRightType(tp1) :
430 				SplitLeftType(tp1);
431 		}
432 		else
433 		    t1 = TiGetTypeExact(tp1);
434 
435 		devptr = ExtCurStyle->exts_device[t1];
436 		j0 = (tileJunk *) tp1->ti_client;
437 		/* top */
438 		for (tp2 = RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2))
439 		{
440 		    if ((TiGetBottomType(tp2) == t1) &&
441 			      (tp2->ti_client == (ClientData) CLIENTDEFAULT))
442 		    {
443      	  		Junk = resAddField(tp2);
444 			STACKPUSH((ClientData)tp2, resDevStack);
445 	       		Junk->deviceList = resDev;
446 	       		Junk->tj_status |= RES_TILE_DEV;
447 
448 		    }
449 	      	    else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
450 				TiGetBottomType(tp2))
451 		    {
452 			Junk = resAddField(tp2);
453 			if (Junk->tj_status & RES_TILE_SD)
454 			       	    j0->sourceEdge |= TOPEDGE;
455 		    }
456 		}
457 		/* bottom */
458 		for (tp2 = LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2))
459 		{
460 		    if ((TiGetTopType(tp2) == t1) &&
461 			      (tp2->ti_client == (ClientData) CLIENTDEFAULT))
462 		    {
463      	  		Junk = resAddField(tp2);
464 			STACKPUSH((ClientData)tp2, resDevStack);
465 	       		Junk->deviceList =  resDev;
466 	       		Junk->tj_status |= RES_TILE_DEV;
467 		    }
468 	      	    else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
469 				TiGetTopType(tp2))
470 		    {
471 			Junk = resAddField(tp2);
472 			if (Junk->tj_status & RES_TILE_SD)
473 			    j0->sourceEdge |= BOTTOMEDGE;
474 		    }
475 		}
476 		/* right */
477 		for (tp2 = TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2))
478 		{
479 		    if ((TiGetLeftType(tp2) == t1) &&
480 			      (tp2->ti_client == (ClientData) CLIENTDEFAULT))
481 		    {
482 			Junk = resAddField(tp2);
483 			STACKPUSH((ClientData)tp2, resDevStack);
484 	       		Junk->deviceList =  resDev;
485 	       		Junk->tj_status |= RES_TILE_DEV;
486 		    }
487 	      	    else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
488 				TiGetLeftType(tp2))
489 		    {
490      	  		Junk = resAddField(tp2);
491 			if (Junk->tj_status & RES_TILE_SD)
492 			    j0->sourceEdge |= RIGHTEDGE;
493 		    }
494 		}
495 		/* left */
496 		for (tp2 = BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2))
497 		{
498 		    if ((TiGetRightType(tp2) == t1) &&
499 			      (tp2->ti_client == (ClientData) CLIENTDEFAULT))
500 		    {
501      	  		Junk = resAddField(tp2);
502 			STACKPUSH((ClientData)tp2, resDevStack);
503 	       		Junk->deviceList =  resDev;
504 	       		Junk->tj_status |= RES_TILE_DEV;
505 		    }
506 	      	    else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
507 				TiGetRightType(tp2))
508 		    {
509      	  		Junk = resAddField(tp2);
510 			if (Junk->tj_status & RES_TILE_SD)
511 			    j0->sourceEdge |= LEFTEDGE;
512 		    }
513 		}
514 	    }
515 
516 	    /* unmark all tiles marked as being part of source */
517 
518 	    if (source != (Tile *) NULL)
519 	    {
520 	        tileJunk *j = (tileJunk *) source->ti_client;
521 
522 		STACKPUSH((ClientData)source, resDevStack);
523 		j->tj_status &= ~RES_TILE_SD;
524 	    }
525 	    while (!StackEmpty(resDevStack))
526 	    {
527 	        tp1 = (Tile *) STACKPOP(resDevStack);
528 		if (IsSplit(tp1))
529 		{
530 		    t1 = (SplitSide(tp1)) ? SplitRightType(tp1) :
531 				SplitLeftType(tp1);
532 		}
533 		else
534 		    t1 = TiGetTypeExact(tp1);
535 
536 		/* top */
537 		for (tp2 = RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2))
538 		{
539 		    tileJunk *j2 = (tileJunk *) tp2->ti_client;
540 		    if (TiGetBottomType(tp2) == t1)
541 		    {
542 			if (j2->tj_status & RES_TILE_SD)
543 			{
544 			    j2->tj_status &= ~RES_TILE_SD;
545 	            	    STACKPUSH((ClientData)tp2, resDevStack);
546 			}
547 		    }
548 		}
549 		/* bottom */
550 		for(tp2 = LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2))
551 		{
552 		    tileJunk *j2 = (tileJunk *) tp2->ti_client;
553 		    if (TiGetTopType(tp2) == t1)
554 		    {
555 			if (j2->tj_status & RES_TILE_SD)
556 			{
557 			    j2->tj_status &= ~RES_TILE_SD;
558 	           	    STACKPUSH((ClientData)tp2, resDevStack);
559 			}
560 		    }
561 		}
562 		/* right */
563 		for (tp2 = TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2))
564 		{
565 		    tileJunk *j2 = (tileJunk *) tp2->ti_client;
566 		    if (TiGetLeftType(tp2) == t1)
567 		    {
568 			if (j2->tj_status & RES_TILE_SD)
569 			{
570 			    j2->tj_status &= ~RES_TILE_SD;
571 	            	    STACKPUSH((ClientData)tp2, resDevStack);
572 			}
573 		    }
574 		}
575 		/* left */
576 		for (tp2 = BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2))
577 		{
578 		    tileJunk *j2 = (tileJunk *) tp2->ti_client;
579 		    if (TiGetRightType(tp2) == t1)
580 		    {
581 			if (j2->tj_status & RES_TILE_SD)
582 			{
583 			    j2->tj_status &= ~RES_TILE_SD;
584 	            	    STACKPUSH((ClientData)tp2, resDevStack);
585 			}
586 		    }
587 		}
588 	    }
589 	}
590     }
591     return(0);
592 }
593 
594 /*
595  *-------------------------------------------------------------------------
596  *
597  * ResRemovePlumbing-- Removes and deallocates all the tileJunk fields.
598  *
599  * Results: returns 0
600  *
601  * Side Effects: frees up memory; resets tile->ti_client fields to CLIENTDEFAULT
602  *
603  *-------------------------------------------------------------------------
604  */
605 
606 int
ResRemovePlumbing(tile,arg)607 ResRemovePlumbing(tile, arg)
608     Tile	*tile;
609     ClientData	*arg;
610 
611 {
612 
613     if (tile->ti_client != (ClientData) CLIENTDEFAULT)
614     {
615 	freeMagic(((char *)(tile->ti_client)));
616 	tile->ti_client = (ClientData) CLIENTDEFAULT;
617     }
618     return(0);
619 }
620 
621 
622 /*
623  *-------------------------------------------------------------------------
624  *
625  * ResPreProcessDevices-- Given a list of all the device tiles and
626  * a list of all the devices, this procedure calculates the width and
627  * length.  The width is set equal to the sum of all edges that touch
628  * diffusion divided by 2. The length is the remaining perimeter divided by
629  * 2*tiles.  The perimeter and area fields of device structures are also
630  * fixed.
631  *
632  * Results: none
633  *
634  * Side Effects: sets length and width of devices. "ResDevTile"
635  * structures are freed.
636  *
637  *-------------------------------------------------------------------------
638  */
639 
640 void
ResPreProcessDevices(TileList,DeviceList,Def)641 ResPreProcessDevices(TileList, DeviceList, Def)
642     ResDevTile		*TileList;
643     resDevice		*DeviceList;
644     CellDef		*Def;
645 {
646     Tile	*tile;
647     ResDevTile	*oldTile;
648     tileJunk	*tstruct;
649     TileType	tt, residue;
650     int		pNum;
651 
652     while (TileList != (ResDevTile *) NULL)
653     {
654 	tt = TileList->type;
655 	if (DBIsContact(tt))
656 	{
657 	    /* Find which residue of the contact is a device. */
658 	    TileTypeBitMask ttresidues;
659 
660 	    DBFullResidueMask(tt, &ttresidues);
661 
662 	    for (residue = TT_TECHDEPBASE; residue < DBNumUserLayers; residue++)
663 	    {
664 		if (TTMaskHasType(&ttresidues, residue))
665 		{
666 		    if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, residue))
667 		    {
668 			pNum = DBPlane(residue);
669 			break;
670 		    }
671 		}
672 	    }
673 	}
674 	else
675 	    pNum = DBPlane(tt);		/* always correct for non-contact types */
676 
677 	tile = (Def->cd_planes[pNum])->pl_hint;
678 	GOTOPOINT(tile, &(TileList->area.r_ll));
679 
680 	tt = TiGetType(tile);
681 	tstruct = (tileJunk *) tile->ti_client;
682 
683 	if ((tstruct == (tileJunk *)CLIENTDEFAULT) ||
684 		    (tstruct->deviceList == NULL) ||
685 		    !TTMaskHasType(&ExtCurStyle->exts_deviceMask, tt))
686 	{
687 	    TxError("Bad Device Location at %d,%d\n",
688 			TileList->area.r_ll.p_x,
689 			TileList->area.r_ll.p_y);
690 	}
691 	else if ((tstruct->tj_status & RES_TILE_MARK) == 0)
692 	{
693 	    resDevice	*rd = tstruct->deviceList;
694 
695 	    tstruct->tj_status |= RES_TILE_MARK;
696 	    rd->rd_perim += TileList->perim;
697 	    rd->rd_length += TileList->overlap;
698 	    rd->rd_area += (TileList->area.r_xtop - TileList->area.r_xbot)
699 			* (TileList->area.r_ytop - TileList->area.r_ybot);
700 	    rd->rd_tiles++;
701 	}
702 	oldTile = TileList;
703 	TileList = TileList->nextDev;
704 	freeMagic((char *)oldTile);
705     }
706 
707     for (; DeviceList != NULL; DeviceList = DeviceList->rd_nextDev)
708     {
709      	int width  = DeviceList->rd_perim;
710 	int length = DeviceList->rd_length;
711 	if (DeviceList->rd_tiles != 0)
712 	{
713 	    if (length)
714 	    {
715 	        DeviceList->rd_length = (float) length /
716 			((float)((DeviceList->rd_tiles) << 1));
717 	        DeviceList->rd_width = (width-length) >> 1;
718 	    }
719 	    else
720 	    {
721 	       	double perimeter = DeviceList->rd_perim;
722 		double area = DeviceList->rd_area;
723 
724 		perimeter /= 4.0;
725 
726 		DeviceList->rd_width = perimeter +
727 			sqrt(perimeter * perimeter-area);
728 		DeviceList->rd_length = (DeviceList->rd_perim
729 			- 2 * DeviceList->rd_width) >> 1;
730 	    }
731 	}
732     }
733 }
734 
735 
736 /*
737  *-------------------------------------------------------------------------
738  *
739  * ResAddToQueue-- adds new nodes to list of nodes requiring processing.
740  *
741  * Side Effects: nodes are added to list (i.e they have their linked list
742  *	pointers modified.)
743  *
744  *-------------------------------------------------------------------------
745  */
746 
747 void
ResAddToQueue(node,list)748 ResAddToQueue(node, list)
749    resNode  *node, **list;
750 {
751    node->rn_more = *list;
752    node->rn_less = NULL;
753    if (*list) (*list)->rn_less = node;
754    *list = node;
755 }
756 
757 /*
758  *-------------------------------------------------------------------------
759  *
760  * ResRemoveFromQueue-- removes node from queue. Complains if it notices
761  *	that the node isn't in the supplied list.
762  *
763  * Results: none
764  *
765  * Side Effects: modifies nodelist
766  *
767  *-------------------------------------------------------------------------
768  */
769 
770 void
ResRemoveFromQueue(node,list)771 ResRemoveFromQueue(node, list)
772     resNode	*node, **list;
773 {
774     if (node->rn_less != NULL)
775     {
776      	node->rn_less->rn_more = node->rn_more;
777     }
778     else
779     {
780      	if (node != (*list))
781 	{
782 	    TxError("Error: Attempt to remove node from wrong list\n");
783 	}
784 	else
785 	{
786 	    *list = node->rn_more;
787 	}
788     }
789     if (node->rn_more != NULL)
790     {
791      	node->rn_more->rn_less = node->rn_less;
792     }
793     node->rn_more = NULL;
794     node->rn_less = NULL;
795 }
796 
797 tileJunk *
resAddField(tile)798 resAddField(tile)
799     Tile    *tile;
800 {
801     tileJunk *Junk;
802     if ((Junk = (tileJunk *)tile->ti_client) == (tileJunk *) CLIENTDEFAULT)
803     {
804      	Junk = (tileJunk *) mallocMagic((unsigned) (sizeof(tileJunk)));
805 	ResJunkInit(Junk);
806 	tile->ti_client = (ClientData) Junk;
807     }
808     return Junk;
809 }
810