1 /*
2  * ExtCouple.c --
3  *
4  * Circuit extraction.
5  * Extraction of coupling capacitance.
6  *
7  *     *********************************************************************
8  *     * Copyright (C) 1985, 1990 Regents of the University of California. *
9  *     * Permission to use, copy, modify, and distribute this              *
10  *     * software and its documentation for any purpose and without        *
11  *     * fee is hereby granted, provided that the above copyright          *
12  *     * notice appear in all copies.  The University of California        *
13  *     * makes no representations about the suitability of this            *
14  *     * software for any purpose.  It is provided "as is" without         *
15  *     * express or implied warranty.  Export of this software outside     *
16  *     * of the United States of America may require an export license.    *
17  *     *********************************************************************
18  */
19 
20 #ifndef lint
21 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extract/ExtCouple.c,v 1.2 2010/06/24 12:37:17 tim Exp $";
22 #endif  /* not lint */
23 
24 #include <stdio.h>
25 
26 #include "utils/magic.h"
27 #include "utils/geometry.h"
28 #include "utils/geofast.h"
29 #include "tiles/tile.h"
30 #include "utils/hash.h"
31 #include "database/database.h"
32 #include "extract/extract.h"
33 #include "extract/extractInt.h"
34 
35 /* --------------------- Data local to this file ---------------------- */
36 
37 /* Pointer to hash table currently being updated with coupling capacitance */
38 HashTable *extCoupleHashPtr;
39 
40 /* Clipping area for coupling searches */
41 Rect *extCoupleSearchArea;
42 
43 /* Current list of sidewall capacitance rules */
44 EdgeCap *extCoupleList;
45 EdgeCap *extOverlapList;
46 
47 /* Def being processed */
48 CellDef *extOverlapDef;
49 
50 /* Forward procedure declarations */
51 int extBasicOverlap(), extBasicCouple();
52 int extAddOverlap(), extAddCouple();
53 int extSideLeft(), extSideRight(), extSideBottom(), extSideTop();
54 int extSideOverlap();
55 void extSideCommon();
56 
57 /* Structure to pass on to the coupling and sidewall capacitance	*/
58 /* routines to include the current cell definition and the current	*/
59 /* plane being searched.						*/
60 
61 typedef struct _ecs {
62     CellDef *def;
63     int	     plane;
64 } extCapStruct;
65 
66 /* Structure to pass on two planes to check for coupling and the tile	*/
67 /* which is doing the coupling.						*/
68 
69 typedef struct _ecpls {
70     Tile *tile;
71     int  plane_of_tile;
72     int  plane_checked;
73 } extCoupleStruct;
74 
75 /* Structure to pass on two planes to check for coupling and the	*/
76 /* boundary which initiated the check.					*/
77 
78 typedef struct _esws {
79     Boundary *bp;
80     int  plane_of_boundary;
81     int  plane_checked;
82 } extSidewallStruct;
83 
84 
85 /* --------------------- Debugging stuff ---------------------- */
86 #define CAP_DEBUG	FALSE
87 
extNregAdjustCap(nr,c,str)88 void extNregAdjustCap(nr, c, str)
89     NodeRegion *nr;
90     CapValue c;
91     char *str;
92 {
93     char *name;
94     name = extNodeName((LabRegion *) nr);
95     fprintf(stderr, "CapDebug: %s += %f (%s)\n", name, c, str);
96 }
97 
extAdjustCouple(he,c,str)98 void extAdjustCouple(he, c, str)
99     HashEntry *he;
100     CapValue c;
101     char *str;
102 {
103     char *name1;
104     char *name2;
105     CoupleKey *ck;
106     ck = (CoupleKey *) he->h_key.h_words;
107     name1 = extNodeName((LabRegion *) ck->ck_1);
108     name2 = extNodeName((LabRegion *) ck->ck_2);
109     fprintf(stderr, "CapDebug: %s-%s += %f (%s)\n", name1, name2, c, str);
110 }
111 
112 
113 /*
114  * ----------------------------------------------------------------------------
115  *
116  * extFindCoupling --
117  *
118  * Find the coupling capacitances in the cell def.  Such capacitances
119  * arise from three causes:
120  *
121  *	Overlap.  When two tiles on different planes overlap, they
122  *		  may have a coupling capacitance proportional to
123  *		  their areas.  If this is so, we subtract the substrate
124  *		  capacitance of the overlapped type, and add the overlap
125  *		  capacitance to the coupling hash table.
126  *
127  *	Sidewall. When tiles on the same plane are adjacent, they may
128  *		  have a coupling capacitance proportional to the
129  *		  length of their edges, divided by the distance between
130  *		  them.  In this case, we just add the sidewall coupling
131  *		  capacitance to the hash table.
132  *
133  *	Sidewall
134  *	overlap.  When the edge of a tile on one plane overlaps a tile
135  *		  on a different plane, the two tiles may have a coupling
136  *		  capacitance proportional to the length of the overlapping
137  *		  edge.  In this case we add the coupling capacitance to the
138  *		  hash table.  (We may want to deduct the perimeter capacitance
139  *		  to substrate?).
140  *
141  * Requires that ExtFindRegions has been run on 'def' to label all its
142  * tiles with NodeRegions.  Also requires that the HashTable 'table'
143  * has been initialized by the caller.
144  *
145  * If 'clipArea' is non-NULL, search for overlap capacitance only inside
146  * the area *clipArea.  Search for sidewall capacitance only from tiles
147  * inside *clipArea, although this capacitance may be to tiles outside
148  * *clipArea.
149  *
150  * Results:
151  *	None.
152  *
153  * Side effects:
154  *	When done, the HashTable 'table' will have been filled
155  *	in with an entry for each pair of nodes having coupling
156  *	capacitance.  Each entry will have a two-word key organized
157  *	as an CoupleKey struct, with ck_1 and ck_2 pointing to the
158  *	coupled nodes.  The value of the hash entry will be the
159  *	coupling capacitance between that pair of nodes.
160  *
161  * ----------------------------------------------------------------------------
162  */
163 
164 void
extFindCoupling(def,table,clipArea)165 extFindCoupling(def, table, clipArea)
166     CellDef *def;
167     HashTable *table;
168     Rect *clipArea;
169 {
170     Rect *searchArea;
171     int pNum;
172     extCapStruct ecs;
173 
174     ecs.def = def;
175 
176     extCoupleHashPtr = table;
177     extCoupleSearchArea = clipArea;
178     searchArea = clipArea ? clipArea : &TiPlaneRect;
179     for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
180     {
181 	ecs.plane = pNum;
182 
183 	if (PlaneMaskHasPlane(ExtCurStyle->exts_overlapPlanes, pNum))
184 	    (void) DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum],
185 			searchArea, &ExtCurStyle->exts_overlapTypes[pNum],
186 			extBasicOverlap, (ClientData) &ecs);
187 	if (PlaneMaskHasPlane(ExtCurStyle->exts_sidePlanes, pNum))
188 	    (void) DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum],
189 			searchArea, &ExtCurStyle->exts_sideTypes[pNum],
190 			extBasicCouple, (ClientData) &ecs);
191     }
192 
193 }
194 
195 /*
196  * ----------------------------------------------------------------------------
197  *
198  * extRelocateSubstrateCoupling ---
199  *
200  * Move coupling capacitance to the substrate node from the coupling
201  * cap table onto the source node's cap-to-substrate record.
202  *
203  * ----------------------------------------------------------------------------
204  */
205 
206 void
extRelocateSubstrateCoupling(table,subsnode)207 extRelocateSubstrateCoupling(table, subsnode)
208     HashTable *table;		/* Coupling capacitance hash table */
209     NodeRegion *subsnode;	/* Node record for substrate */
210 {
211     HashEntry *he;
212     CoupleKey *ck;
213     HashSearch hs;
214     CapValue cap;
215     NodeRegion *rtp;
216     NodeRegion *rbp;
217 
218     HashStartSearch(&hs);
219     while (he = HashNext(table, &hs))
220     {
221 	cap = extGetCapValue(he);
222 	if (cap == 0) continue;
223 
224 	ck = (CoupleKey *) he->h_key.h_words;
225 	rtp = (NodeRegion *) ck->ck_1;
226 	rbp = (NodeRegion *) ck->ck_2;
227 
228 	if (rtp == subsnode)
229 	{
230 	    rbp->nreg_cap += cap;
231 	    extSetCapValue(he, (CapValue)0);
232 	}
233 	else if (rbp == subsnode)
234 	{
235 	    rtp->nreg_cap += cap;
236 	    extSetCapValue(he, (CapValue)0);
237 	}
238     }
239 }
240 
241 
242 /*
243  * ----------------------------------------------------------------------------
244  *
245  * extOutputCoupling --
246  *
247  * Output the coupling capacitance table built up by extFindCoupling().
248  * Each entry in the hash table is a capacitance between the pair of
249  * nodes identified by he->h_key, an CoupleKey struct.
250  *
251  * ExtFindRegions and ExtLabelRegions should have been called prior
252  * to this procedure.
253  *
254  * Results:
255  *	None.
256  *
257  * Side effects:
258  *	See the comments above.
259  *
260  * ----------------------------------------------------------------------------
261  */
262 
263 void
extOutputCoupling(table,outFile)264 extOutputCoupling(table, outFile)
265     HashTable *table;	/* Coupling capacitance hash table */
266     FILE *outFile;	/* Output file */
267 {
268     HashEntry *he;
269     CoupleKey *ck;
270     HashSearch hs;
271     char *text;
272     CapValue cap;  /* value of capacitance. */
273 
274     HashStartSearch(&hs);
275     while (he = HashNext(table, &hs))
276     {
277 	cap = extGetCapValue(he) / ExtCurStyle->exts_capScale;
278 	if (cap == 0)
279 	    continue;
280 
281 	ck = (CoupleKey *) he->h_key.h_words;
282 	text = extNodeName((LabRegion *) ck->ck_1);
283 	fprintf(outFile, "cap \"%s\" ", text);
284 	text = extNodeName((LabRegion *) ck->ck_2);
285 	fprintf(outFile, "\"%s\" %lg\n", text, cap);
286     }
287 }
288 
289 /*
290  * ----------------------------------------------------------------------------
291  *
292  * extBasicOverlap --
293  *
294  * Filter function for overlap capacitance.
295  * Called for each tile that might have coupling capacitance
296  * to another node because it overlaps a tile or tiles in that
297  * node.  Causes an area search over the area of 'tile' in all
298  * planes to which 'tile' has overlap capacitance, for any tiles
299  * to which 'tile' has overlap capacitance.
300  *
301  * Results:
302  *	Returns 0 to keep DBSrPaintArea() going.
303  *
304  * Side effects:
305  *	See extAddOverlap().
306  *
307  * ----------------------------------------------------------------------------
308  */
309 
310 int
extBasicOverlap(tile,ecs)311 extBasicOverlap(tile, ecs)
312     Tile *tile;
313     extCapStruct *ecs;
314 {
315     int thisType;
316     int pNum;
317     PlaneMask pMask;
318     TileTypeBitMask *tMask;
319     Rect r;
320     CellDef *def = ecs->def;
321     int thisPlane = ecs->plane;
322     extCoupleStruct ecpls;
323 
324     if (IsSplit(tile))
325 	thisType = (SplitSide(tile)) ? SplitRightType(tile) :
326 		SplitLeftType(tile);
327     else
328 	thisType = TiGetTypeExact(tile);
329 
330     if (DBIsContact(thisType))
331 	thisType = DBPlaneToResidue(thisType, thisPlane);
332 
333     pMask = ExtCurStyle->exts_overlapOtherPlanes[thisType];
334     tMask = &ExtCurStyle->exts_overlapOtherTypes[thisType];
335 
336     TITORECT(tile, &r);
337     extOverlapDef = def;
338     if (extCoupleSearchArea)
339     {
340 	GEOCLIP(&r, extCoupleSearchArea);
341     }
342 
343     ecpls.tile = tile;
344     ecpls.plane_of_tile = thisPlane;
345 
346     for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
347     {
348 	/* Skip if nothing interesting on the other plane */
349 	if (pNum == thisPlane || !PlaneMaskHasPlane(pMask, pNum))
350 	    continue;
351 
352 	ecpls.plane_checked = pNum;
353 	(void) DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum], &r, tMask,
354 		extAddOverlap, (ClientData) &ecpls);
355     }
356 
357     return (0);
358 }
359 
360 /*
361  * ----------------------------------------------------------------------------
362  *
363  * extAddOverlap --
364  *
365  * We are called for each tile that is overlapped by the tile passed to
366  * extBasicOverlap() above (our argument 'tabove').  The intent is that
367  * 'tbelow' actually shields 'tabove' from the substrate, so we should
368  * replace node(tabove)'s capacitance to substrate with a capacitance
369  * to node(tbelow) whose size is proportional to the area of the overlap.
370  *
371  * We check to insure that tabove is not shielded from tbelow by any
372  * intervening material; if it is, we deduct the capacitance between
373  * node(tabove) and node(tbelow) for the area of the overlap.
374  *
375  * Results:
376  *	Returns 0 to keep DBSrPaintArea() going.
377  *
378  * Side effects:
379  *	Updates the HashEntry with key node(tbelow), node(tabove)
380  *	by adding the capacitance of the overlap if node(tbelow)
381  *	and node(tabove) are different, and if they are not totally
382  *	shielded by intervening material.  Also subtracts the capacitance
383  *	to substrate from node(tabove) for the area of the overlap.
384  *	If node(tbelow) and node(tabove) are the same, we do nothing.
385  *
386  * ----------------------------------------------------------------------------
387  */
388 
389 struct overlap
390 {
391     Rect		 o_clip;
392     int			 o_area;
393     PlaneMask		 o_pmask;
394     TileTypeBitMask	 o_tmask;
395 };
396 
397 int
extAddOverlap(tbelow,ecpls)398 extAddOverlap(tbelow, ecpls)
399     Tile *tbelow;
400     extCoupleStruct *ecpls;
401 {
402     int extSubtractOverlap(), extSubtractOverlap2();
403     NodeRegion *rabove, *rbelow;
404     HashEntry *he;
405     struct overlap ov;
406     TileType ta, tb;
407     CoupleKey ck;
408     int pNum;
409     CapValue c;
410     Tile *tabove = ecpls->tile;
411 
412     /* Check if both tiles are connected.  If they are, we don't need   */
413     /* to check for shielding material, and we don't want to add any    */
414     /* coupling capacitance between them.  However, we *do* want to     */
415     /* subtract off any substrate (area) capacitance previously added   */
416     /* (Correction made 4/29/04 by Tim from a tip by Jeff Sondeen).     */
417 
418     rabove = (NodeRegion *) extGetRegion(tabove);
419     rbelow = (NodeRegion *) extGetRegion(tbelow);
420 
421     /* Quick check on validity of tile's ti_client record */
422     if (rbelow == (NodeRegion *)CLIENTDEFAULT) return 0;
423 
424     /* Compute the area of overlap */
425     ov.o_clip.r_xbot = MAX(LEFT(tbelow), LEFT(tabove));
426     ov.o_clip.r_xtop = MIN(RIGHT(tbelow), RIGHT(tabove));
427     ov.o_clip.r_ybot = MAX(BOTTOM(tbelow), BOTTOM(tabove));
428     ov.o_clip.r_ytop = MIN(TOP(tbelow), TOP(tabove));
429     if (extCoupleSearchArea)
430     {
431 	GEOCLIP(&ov.o_clip, extCoupleSearchArea);
432     }
433     ov.o_area = (ov.o_clip.r_ytop - ov.o_clip.r_ybot)
434 	      * (ov.o_clip.r_xtop - ov.o_clip.r_xbot);
435     ta = TiGetType(tabove);
436     tb = TiGetType(tbelow);
437 
438     /* Revert any contacts to their residues */
439 
440     if (DBIsContact(ta))
441 	ta = DBPlaneToResidue(ta, ecpls->plane_of_tile);
442 
443     if (DBIsContact(tb))
444 	tb = DBPlaneToResidue(tb, ecpls->plane_checked);
445 
446     /*
447      * Find whether rabove and rbelow are shielded by intervening material.
448      * Deduct the area shielded from the area of the overlap, so we adjust
449      * the overlap capacitance correspondingly.
450      */
451     if (ov.o_pmask = ExtCurStyle->exts_overlapShieldPlanes[ta][tb])
452     {
453 	ov.o_tmask = ExtCurStyle->exts_overlapShieldTypes[ta][tb];
454 	for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
455 	{
456 	    if (!PlaneMaskHasPlane(ov.o_pmask, pNum)) continue;
457 	    ov.o_pmask &= ~(PlaneNumToMaskBit(pNum));
458 	    if (ov.o_pmask == 0)
459 	    {
460 		(void) DBSrPaintArea((Tile *) NULL,
461 		    extOverlapDef->cd_planes[pNum], &ov.o_clip, &ov.o_tmask,
462 		    extSubtractOverlap, (ClientData) &ov);
463 	    }
464 	    else
465 	    {
466 		(void) DBSrPaintArea((Tile *) NULL,
467 		    extOverlapDef->cd_planes[pNum], &ov.o_clip, &DBAllTypeBits,
468 		    extSubtractOverlap2, (ClientData) &ov);
469 	    }
470 	    break;
471 	}
472     }
473 
474     /* If any capacitance remains, add this record to the table */
475     if (ov.o_area > 0)
476     {
477 	int oa = ExtCurStyle->exts_planeOrder[ecpls->plane_of_tile];
478 	int ob = ExtCurStyle->exts_planeOrder[ecpls->plane_checked];
479 	if (oa > ob)
480 	{
481 	    Tile *tp;
482 	    TileType t, tres;
483 	    TileTypeBitMask *mask;
484 	    int len;
485 	    CapValue cp;
486 	    /*
487 	     * Subtract the substrate capacitance from tabove's region due to
488 	     * the area of the overlap, minus any shielded area.  The shielded
489 	     * areas get handled later, when processing coupling between tabove
490 	     * and the shielding tile.  (Tabove was the overlapping tile, so it
491 	     * is shielded from the substrate by tbelow if the Tabove plane is
492 	     * above the Tbelow plane).
493 	     */
494 	    rabove->nreg_cap -= ExtCurStyle->exts_areaCap[ta] * ov.o_area;
495 	    if (CAP_DEBUG)
496 		extNregAdjustCap(rabove,
497 		    -(ExtCurStyle->exts_areaCap[ta] * ov.o_area),
498 		    "obsolete_overlap");
499 
500 	} else if (CAP_DEBUG)
501 	    extNregAdjustCap(rabove, 0.0,
502 		"obsolete_overlap (skipped, wrong direction)");
503 
504         /* If the regions are the same, skip this part */
505         if (rabove == rbelow) return (0);
506 
507 	/* Find the coupling hash record */
508 	if (rabove < rbelow) ck.ck_1 = rabove, ck.ck_2 = rbelow;
509 	else ck.ck_1 = rbelow, ck.ck_2 = rabove;
510 	he = HashFind(extCoupleHashPtr, (char *) &ck);
511 
512 	/* Add the overlap capacitance to the table */
513 	c = extGetCapValue(he);
514 	c += ExtCurStyle->exts_overlapCap[ta][tb] * ov.o_area;
515 	if (CAP_DEBUG)
516 	    extAdjustCouple(he, ExtCurStyle->exts_overlapCap[ta][tb] *
517 		ov.o_area, "overlap");
518 	extSetCapValue(he, c);
519     }
520     return (0);
521 }
522 
523 int
extSubtractOverlap(tile,ov)524 extSubtractOverlap(tile, ov)
525     Tile *tile;
526     struct overlap *ov;
527 {
528     Rect r;
529     int area;
530 
531     TITORECT(tile, &r);
532     GEOCLIP(&r, &ov->o_clip);
533     area = (r.r_xtop - r.r_xbot) * (r.r_ytop - r.r_ybot);
534     if (area > 0)
535 	ov->o_area -= area;
536 
537     return (0);
538 }
539 
540 int
extSubtractOverlap2(tile,ov)541 extSubtractOverlap2(tile, ov)
542     Tile *tile;
543     struct overlap *ov;
544 {
545     struct overlap ovnew;
546     int area, pNum;
547     Rect r;
548 
549     TITORECT(tile, &r);
550     GEOCLIP(&r, &ov->o_clip);
551     area = (r.r_xtop - r.r_xbot) * (r.r_ytop - r.r_ybot);
552     if (area <= 0)
553 	return (0);
554 
555     /* This tile shields everything below */
556     if (TTMaskHasType(&ov->o_tmask, TiGetType(tile)))
557     {
558 	ov->o_area -= area;
559 	return (0);
560     }
561 
562     /* Tile doesn't shield, so search next plane */
563     ovnew = *ov;
564     ovnew.o_clip = r;
565     for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
566     {
567 	if (!PlaneMaskHasPlane(ovnew.o_pmask, pNum)) continue;
568 	ovnew.o_pmask &= ~(PlaneNumToMaskBit(pNum));
569 	if (ovnew.o_pmask == 0)
570 	{
571 	    (void) DBSrPaintArea((Tile *) NULL,
572 		extOverlapDef->cd_planes[pNum], &ovnew.o_clip, &ovnew.o_tmask,
573 		extSubtractOverlap, (ClientData) &ovnew);
574 	}
575 	else
576 	{
577 	    (void) DBSrPaintArea((Tile *) NULL,
578 		extOverlapDef->cd_planes[pNum], &ovnew.o_clip, &DBAllTypeBits,
579 		extSubtractOverlap2, (ClientData) &ovnew);
580 	}
581 	break;
582     }
583     ov->o_area = ovnew.o_area;
584 
585     return (0);
586 }
587 
588 /*
589  * ----------------------------------------------------------------------------
590  *
591  * extBasicCouple --
592  *
593  * Filter function for sidewall coupling capacitance.
594  * Called for each tile that might have coupling capacitance
595  * to another node because it is near tiles on the same plane,
596  * or because its edge overlaps tiles on a different plane.
597  *
598  * Causes an area search over a halo surrounding each edge of
599  * 'tile' for edges to which each edge has coupling capacitance
600  * on this plane, and a search for tiles on different planes that
601  * this edge overlaps.
602  *
603  * Results:
604  *	Returns 0 to keep DBSrPaintArea() going.
605  *
606  * Side effects:
607  *	See extAddCouple().
608  *
609  * ----------------------------------------------------------------------------
610  */
611 
612 int
extBasicCouple(tile,ecs)613 extBasicCouple(tile, ecs)
614     Tile *tile;
615     extCapStruct *ecs;
616 {
617     (void) extEnumTilePerim(tile, ExtCurStyle->exts_sideEdges[TiGetType(tile)],
618 			ecs->plane, extAddCouple, (ClientData) ecs);
619     return (0);
620 }
621 
622 /*
623  * ----------------------------------------------------------------------------
624  *
625  * extAddCouple --
626  *
627  * Called for each segment along the boundary of the tile bp->b_inside
628  * that might have coupling capacitance with its neighbors.
629  * Causes an area search over a halo surrounding the boundary bp->b_segment
630  * on the side outside bp->b_inside for edges to which this one has coupling
631  * capacitance on this plane, and for tiles overlapping this edge on different
632  * planes.
633  *
634  * Results:
635  *	Returns 0 to keep DBSrPaintArea() going.
636  *
637  * Side effects:
638  *	For each edge (tnear, tfar) we find that has coupling capacitance
639  *	to us, update the HashEntry with key node(bp->b_inside), node(tfar)
640  *	by adding the sidewall capacitance if node(bp->b_inside) and node(tfar)
641  *	are different.  If node(bp->b_inside) and node(tfar) are the same, we
642  *	do nothing.
643  *
644  *	For each tile tp we find on a different plane that overlaps this
645  *	edge, update the HashEntry with key node(bp->b_inside), node(tp)
646  *	by adding the sidewall overlap capacitance.  If node(bp->b_inside)
647  *	and node(tp) are the same, do nothing.
648  *
649  * ----------------------------------------------------------------------------
650  */
651 
652 Rect extSideOverlapSearchArea;
653 
654 int
extAddCouple(bp,ecs)655 extAddCouple(bp, ecs)
656     Boundary *bp;	/* Boundary being considered */
657     extCapStruct *ecs;
658 {
659     TileType tin = TiGetType(bp->b_inside), tout = TiGetType(bp->b_outside);
660     int pNum;
661     PlaneMask pMask;
662     int (*proc)();
663     Boundary bpCopy;
664     Rect r, ovr;
665     CellDef *def = ecs->def;
666     extSidewallStruct esws;
667 
668     /* Revert any edge contacts to their residues */
669     if (DBIsContact(tin))
670 	tin = DBPlaneToResidue(tin, ecs->plane);
671     if (DBIsContact(tout))
672 	tout = DBPlaneToResidue(tout, ecs->plane);
673 
674     extCoupleList = ExtCurStyle->exts_sideCoupleCap[tin][tout];
675     extOverlapList = ExtCurStyle->exts_sideOverlapCap[tin][tout];
676     if (extCoupleList == NULL && extOverlapList == NULL)
677 	return (0);
678 
679     /*
680      * Clip the edge of interest to the area where we're searching
681      * for coupling capacitance, if such an area has been specified.
682      */
683     if (extCoupleSearchArea)
684     {
685 	bpCopy = *bp;
686 	bp = &bpCopy;
687 
688 	GEOCLIP(&bp->b_segment, extCoupleSearchArea);
689 
690 	/* Fixed 2/27/2017 by Tim
691 	 * GEO_RECTNULL should not be applied to boundaries, which are
692 	 * segments and therefore have no area.  This causes the function
693 	 * to always return.
694 	 */
695 	/* if (GEO_RECTNULL(&bp->b_segment)) return (0); */
696 
697 	if ((bp->b_segment.r_ytop <= bp->b_segment.r_ybot) &&
698 		(bp->b_segment.r_xtop <= bp->b_segment.r_xbot))
699 	    return 0;
700     }
701     r = ovr = bp->b_segment;
702 
703     switch (bp->b_direction)
704     {
705 	case BD_LEFT:	/* Along left */
706 	    r.r_xbot -= ExtCurStyle->exts_sideCoupleHalo	;
707 	    ovr.r_xbot -= 1;
708 	    proc = extSideLeft;
709 	    break;
710 	case BD_RIGHT:	/* Along right */
711 	    r.r_xtop += ExtCurStyle->exts_sideCoupleHalo	;
712 	    ovr.r_xtop += 1;
713 	    proc = extSideRight;
714 	    break;
715 	case BD_TOP:	/* Along top */
716 	    r.r_ytop += ExtCurStyle->exts_sideCoupleHalo	;
717 	    ovr.r_ytop += 1;
718 	    proc = extSideTop;
719 	    break;
720 	case BD_BOTTOM:	/* Along bottom */
721 	    r.r_ybot -= ExtCurStyle->exts_sideCoupleHalo	;
722 	    ovr.r_ybot -= 1;
723 	    proc = extSideBottom;
724 	    break;
725     }
726 
727     if (extCoupleList)
728 	(void) DBSrPaintArea((Tile *) NULL, def->cd_planes[ecs->plane],
729 		&r, &ExtCurStyle->exts_sideCoupleOtherEdges[tin][tout],
730 		proc, (ClientData) bp);
731 
732     if (extOverlapList)
733     {
734 	pMask = ExtCurStyle->exts_sideOverlapOtherPlanes[tin][tout];
735 	extSideOverlapSearchArea = ovr;
736 	extOverlapDef = def;
737 
738 	esws.bp = bp;
739 	esws.plane_of_boundary = ecs->plane;
740 
741 	for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
742 	    if (PlaneMaskHasPlane(pMask, pNum))
743 	    {
744 		esws.plane_checked = pNum;
745 		(void) DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum],
746 			&ovr, &ExtCurStyle->exts_sideOverlapOtherTypes[tin][tout],
747 			extSideOverlap, (ClientData) &esws);
748 	    }
749     }
750 
751     return (0);
752 }
753 
754 /*
755  * ----------------------------------------------------------------------------
756  *
757  * extSideOverlap --
758  *
759  * The boundary 'bp' has been found to overlap the tile 'tp', which it
760  * has coupling capacitance to.
761  *
762  * Results:
763  *	Returns 0 to keep DBSrPaintArea() going.
764  *
765  * Side effects:
766  *	Update the coupling capacitance between node(bp->t_inside) and
767  *	node(tp) if the two nodes are different.  Does so by updating
768  *	the value stored in the HashEntry keyed by the two nodes.
769  *
770  * ----------------------------------------------------------------------------
771  */
772 
773 int
extSideOverlap(tp,esws)774 extSideOverlap(tp, esws)
775     Tile *tp;			/* Overlapped tile */
776     extSidewallStruct *esws;	/* Overlapping edge and plane information */
777 {
778     Boundary *bp = esws->bp;	/* Overlapping edge */
779     NodeRegion *rtp = (NodeRegion *) extGetRegion(tp);
780     NodeRegion *rbp = (NodeRegion *) extGetRegion(bp->b_inside);
781     TileType ta, tb;
782     Rect tpr;
783     struct overlap ov;
784     HashEntry *he;
785     EdgeCap *e;
786     int length, areaAccountedFor;
787     CapValue cap;
788     CoupleKey ck;
789 
790     if (bp->b_segment.r_xtop == bp->b_segment.r_xbot)
791     {
792 	length = MIN(bp->b_segment.r_ytop, TOP(tp))
793 	       - MAX(bp->b_segment.r_ybot, BOTTOM(tp));
794     }
795     else
796     {
797 	length = MIN(bp->b_segment.r_xtop, RIGHT(tp))
798 	       - MAX(bp->b_segment.r_xbot, LEFT(tp));
799     }
800 
801     TITORECT(tp, &ov.o_clip);
802     GEOCLIP(&ov.o_clip, &extSideOverlapSearchArea);
803     ov.o_area = length;
804     areaAccountedFor = 0;
805     ASSERT(length == GEO_WIDTH(&ov.o_clip) * GEO_HEIGHT(&ov.o_clip),
806 	"extSideOverlap");
807     ta = TiGetType(bp->b_inside);
808     tb = TiGetType(tp);
809 
810     /* Avoid doing the code below if we're just going to return without */
811     /* changing anything.                                               */
812     if ((tb == TT_SPACE) && (rtp == rbp)) return (0);
813 
814     /* Revert any contacts to their residues */
815     if (DBIsContact(ta))
816 	ta = DBPlaneToResidue(ta, esws->plane_of_boundary);
817     if (DBIsContact(tb))
818 	tb = DBPlaneToResidue(tb, esws->plane_checked);
819 
820     /* Apply each rule, incorporating shielding into the edge length. */
821     cap = (CapValue) 0;
822     for (e = extOverlapList; e; e = e->ec_next)
823     {
824 	/* Only apply rules for the plane in which they are declared */
825 	if (!PlaneMaskHasPlane(e->ec_pmask, esws->plane_checked)) continue;
826 
827 	/* Does this rule "e" include the tile we found? */
828 	if (TTMaskHasType(&e->ec_near, TiGetType(tp)))
829 	{
830 	    /* We have a possible capacitor, but are the tiles shielded from
831 	     * each other part of the way?
832 	     */
833 	    int pNum;
834 	    ov.o_area = length;
835 	    ov.o_pmask = ExtCurStyle->exts_sideOverlapShieldPlanes[ta][tb];
836 	    if (ov.o_pmask)
837 	    {
838 		ov.o_tmask = e->ec_far;  /* Actually shieldtypes. */
839 		for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
840 		{
841 		    /* Each call to DBSrPaintArea has an opportunity to
842 		     * subtract from the area (really length 'cause width=1.
843 		     */
844 		    if (!PlaneMaskHasPlane(ov.o_pmask, pNum)) continue;
845 		    ov.o_pmask &= ~(PlaneNumToMaskBit(pNum));
846 		    if (ov.o_pmask == 0)
847 		    {
848 			(void) DBSrPaintArea((Tile *) NULL,
849 			    extOverlapDef->cd_planes[pNum], &ov.o_clip,
850 			    &ov.o_tmask, extSubtractOverlap, (ClientData) &ov);
851 		    }
852 		    else
853 		    {
854 			(void) DBSrPaintArea((Tile *) NULL,
855 			    extOverlapDef->cd_planes[pNum], &ov.o_clip,
856 			    &DBAllTypeBits,
857 			    extSubtractOverlap2, (ClientData) &ov);
858 		    }
859 		    break;
860 		}
861 	    }
862 	    if (rtp != rbp)
863 		cap += e->ec_cap * ov.o_area;
864 	    areaAccountedFor += ov.o_area;
865 	}
866     }
867 
868     /* Add in the new capacitance. */
869     if (tb == TT_SPACE)
870     {
871 	/* Is tp a space tile?  If so, extGetRegion points to garbage;
872 	 * make terminal 2 point to ground.
873 	 */
874 	rbp->nreg_cap += cap;
875 	if (CAP_DEBUG) extNregAdjustCap(rbp, cap, "sideoverlap_to_subs");
876     }
877     else
878     {
879 	int oa = ExtCurStyle->exts_planeOrder[esws->plane_of_boundary];
880 	int ob = ExtCurStyle->exts_planeOrder[esws->plane_checked];
881 	if (oa > ob)
882 	{
883 	    /* If the overlapped tile is between the substrate and the boundary
884 	     * tile, then we subtract the fringe substrate capacitance
885 	     * from rbp's region due to the area of the sideoverlap, since
886 	     * we now know it is shielded from the substrate.
887 	     */
888 	    CapValue subcap;
889 	    TileType outtype = TiGetType(bp->b_outside);
890 
891 	    /* Decompose contacts into their residues */
892 	    if (DBIsContact(ta))
893 		ta = DBPlaneToResidue(ta, esws->plane_of_boundary);
894 	    if (DBIsContact(outtype))
895 		outtype = DBPlaneToResidue(outtype, esws->plane_of_boundary);
896 
897 	    subcap = (ExtCurStyle->exts_perimCap[ta][outtype] *
898 			MIN(areaAccountedFor, length));
899 	    rbp->nreg_cap -= subcap;
900 	    /* Ignore residual error at ~zero zeptoFarads.  Probably	*/
901 	    /* there should be better handling of round-off here.	*/
902 	    if ((rbp->nreg_cap > -0.001) && (rbp->nreg_cap < 0.001)) rbp->nreg_cap = 0;
903 	    if (CAP_DEBUG)
904 		extNregAdjustCap(rbp, -subcap, "obsolete_perimcap");
905 	} else if (CAP_DEBUG)
906 	    extNregAdjustCap(rbp, 0.0,
907 		"obsolete_perimcap (skipped, wrong direction)");
908 
909 	/* If the nodes are electrically connected, then we don't add	*/
910 	/* any side overlap capacitance to the node.			*/
911 	if (rtp == rbp) return (0);
912 
913 	if (rtp < rbp) ck.ck_1 = rtp, ck.ck_2 = rbp;
914 	    else ck.ck_1 = rbp, ck.ck_2 = rtp;
915 	he = HashFind(extCoupleHashPtr, (char *) &ck);
916 	if (CAP_DEBUG) extAdjustCouple(he, cap, "sideoverlap");
917 	extSetCapValue(he, cap + extGetCapValue(he));
918     }
919     return (0);
920 }
921 
922 /*
923  * ----------------------------------------------------------------------------
924  *
925  * extSideLeft --
926  *
927  * Searching to the left of the boundary 'bp', we found the tile
928  * 'tpfar' which may lie on the far side of an edge to which the
929  * edge bp->b_inside | bp->b_outside has sidewall coupling capacitance.
930  *
931  * Walk along the right-hand side of 'tpfar' searching for such
932  * edges, and recording their capacitance in the hash table
933  * *extCoupleHashPtr.
934  *
935  * Results:
936  *	Returns 0 always.
937  *
938  * Side effects:
939  *	If node(tpfar) exists, and node(bp->b_inside) != node(tpfar),
940  *	search along the inside edge of tpfar (the one closest to
941  *	the boundary bp) for edges having capacitance with bp.  For
942  *	each such edge found, update the entry in *extCoupleHashPtr
943  *	identified by node(bp->b_inside) and node(tpfar) by adding
944  *	the capacitance due to the adjacency of the pair of edges.
945  *
946  * ----------------------------------------------------------------------------
947  */
948 
949 int
extSideLeft(tpfar,bp)950 extSideLeft(tpfar, bp)
951     Tile *tpfar;
952     Boundary *bp;
953 {
954     NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside);
955     NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar);
956     Tile *tpnear;
957 
958     if (rfar != (NodeRegion *) extUnInit && rfar != rinside)
959     {
960 	int sep = bp->b_segment.r_xbot - RIGHT(tpfar);
961 	int limit = MAX(bp->b_segment.r_ybot, BOTTOM(tpfar));
962 	int start = MIN(bp->b_segment.r_ytop, TOP(tpfar));
963 
964 	for (tpnear = TR(tpfar); TOP(tpnear) > limit; tpnear = LB(tpnear))
965 	{
966 	    int overlap = MIN(TOP(tpnear), start) - MAX(BOTTOM(tpnear), limit);
967 
968 	    if (overlap > 0)
969 		extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep);
970 	}
971     }
972 
973     return (0);
974 }
975 
976 /*
977  * ----------------------------------------------------------------------------
978  *
979  * extSideRight --
980  *
981  * Searching to the right of the boundary 'bp', we found the tile
982  * 'tpfar' which may lie on the far side of an edge to which the
983  * edge bp->b_inside | bp->b_outside has sidewall coupling capacitance.
984  *
985  * Walk along the left-hand side of 'tpfar' searching for such
986  * edges, and recording their capacitance in the hash table
987  * *extCoupleHashPtr.
988  *
989  * Results:
990  *	Returns 0 always.
991  *
992  * Side effects:
993  *	See extSideLeft.
994  *
995  * ----------------------------------------------------------------------------
996  */
997 
998 int
extSideRight(tpfar,bp)999 extSideRight(tpfar, bp)
1000     Tile *tpfar;
1001     Boundary *bp;
1002 {
1003     NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside);
1004     NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar);
1005     Tile *tpnear;
1006 
1007     if (rfar != (NodeRegion *) extUnInit && rfar != rinside)
1008     {
1009 	int sep = LEFT(tpfar) - bp->b_segment.r_xtop;
1010 	int limit = MIN(bp->b_segment.r_ytop, TOP(tpfar));
1011 	int start = MAX(bp->b_segment.r_ybot, BOTTOM(tpfar));
1012 
1013 	for (tpnear = BL(tpfar); BOTTOM(tpnear) < limit; tpnear = RT(tpnear))
1014 	{
1015 	    int overlap = MIN(TOP(tpnear), limit) - MAX(BOTTOM(tpnear), start);
1016 
1017 	    if (overlap > 0)
1018 		extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep);
1019 	}
1020     }
1021 
1022     return (0);
1023 }
1024 
1025 /*
1026  * ----------------------------------------------------------------------------
1027  *
1028  * extSideTop --
1029  *
1030  * Searching to the top of the boundary 'bp', we found the tile
1031  * 'tpfar' which may lie on the far side of an edge to which the
1032  * edge bp->b_inside | bp->b_outside has sidewall coupling capacitance.
1033  *
1034  * Walk along the bottom side of 'tpfar' searching for such
1035  * edges, and recording their capacitance in the hash table
1036  * *extCoupleHashPtr.
1037  *
1038  * Results:
1039  *	Returns 0 always.
1040  *
1041  * Side effects:
1042  *	See extSideLeft.
1043  *
1044  * ----------------------------------------------------------------------------
1045  */
1046 
1047 int
extSideTop(tpfar,bp)1048 extSideTop(tpfar, bp)
1049     Tile *tpfar;
1050     Boundary *bp;
1051 {
1052     NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside);
1053     NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar);
1054     Tile *tpnear;
1055 
1056     if (rfar != (NodeRegion *) extUnInit && rfar != rinside)
1057     {
1058 	int sep = BOTTOM(tpfar) - bp->b_segment.r_ytop;
1059 	int limit = MIN(bp->b_segment.r_xtop, RIGHT(tpfar));
1060 	int start = MAX(bp->b_segment.r_xbot, LEFT(tpfar));
1061 
1062 	for (tpnear = LB(tpfar); LEFT(tpnear) < limit; tpnear = TR(tpnear))
1063 	{
1064 	    int overlap = MIN(RIGHT(tpnear), limit) - MAX(LEFT(tpnear), start);
1065 
1066 	    if (overlap > 0)
1067 		extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep);
1068 	}
1069     }
1070 
1071     return (0);
1072 }
1073 
1074 /*
1075  * ----------------------------------------------------------------------------
1076  *
1077  * extSideBottom --
1078  *
1079  * Searching to the bottom of the boundary 'bp', we found the tile
1080  * 'tpfar' which may lie on the far side of an edge to which the
1081  * edge bp->b_inside | bp->b_outside has sidewall coupling capacitance.
1082  *
1083  * Walk along the top side of 'tpfar' searching for such
1084  * edges, and recording their capacitance in the hash table
1085  * *extCoupleHashPtr.
1086  *
1087  * Results:
1088  *	Returns 0 always.
1089  *
1090  * Side effects:
1091  *	See extSideLeft.
1092  *
1093  * ----------------------------------------------------------------------------
1094  */
1095 
1096 int
extSideBottom(tpfar,bp)1097 extSideBottom(tpfar, bp)
1098     Tile *tpfar;
1099     Boundary *bp;
1100 {
1101     NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside);
1102     NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar);
1103     Tile *tpnear;
1104 
1105     if (rfar != (NodeRegion *) extUnInit && rfar != rinside)
1106     {
1107 	int sep = bp->b_segment.r_ybot - TOP(tpfar);
1108 	int limit = MAX(bp->b_segment.r_xbot, LEFT(tpfar));
1109 	int start = MIN(bp->b_segment.r_xtop, RIGHT(tpfar));
1110 
1111 	for (tpnear = RT(tpfar); RIGHT(tpnear) > limit; tpnear = BL(tpnear))
1112 	{
1113 	    int overlap = MIN(RIGHT(tpnear), start) - MAX(LEFT(tpnear), limit);
1114 
1115 	    if (overlap > 0)
1116 		extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep);
1117 	}
1118     }
1119 
1120     return (0);
1121 }
1122 
1123 /*
1124  * ----------------------------------------------------------------------------
1125  *
1126  * extSideCommon --
1127  *
1128  * Perform the actual update to the hash table entry for
1129  * the regions 'rinside' and 'rfar'.  We assume that neither
1130  * 'rinside' nor 'rfar' are extUnInit, and further that they
1131  * are not equal.
1132  *
1133  * Walk along the rules in extCoupleList, applying the appropriate
1134  * amount of capacitance for an edge with tpnear on the close side
1135  * and tpfar on the remote side.
1136  *
1137  * Results:
1138  *	Returns 0 always.
1139  *
1140  * Side effects:
1141  *	See extSideLeft.
1142  *
1143  * ----------------------------------------------------------------------------
1144  */
1145 
1146 void
extSideCommon(rinside,rfar,tpnear,tpfar,overlap,sep)1147 extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep)
1148     NodeRegion *rinside, *rfar;	/* Both must be valid */
1149     Tile *tpnear, *tpfar;	/* Tiles on near and far side of edge */
1150     int overlap, sep;		/* Overlap of this edge with original one,
1151 				 * and distance between the two.
1152 				 */
1153 {
1154     TileType near = TiGetType(tpnear), far = TiGetType(tpfar);
1155     HashEntry *he;
1156     EdgeCap *e;
1157     CoupleKey ck;
1158     CapValue cap;
1159 
1160     if (rinside < rfar) ck.ck_1 = rinside, ck.ck_2 = rfar;
1161     else ck.ck_1 = rfar, ck.ck_2 = rinside;
1162     he = HashFind(extCoupleHashPtr, (char *) &ck);
1163 
1164     cap = extGetCapValue(he);
1165     for (e = extCoupleList; e; e = e->ec_next)
1166 	if (TTMaskHasType(&e->ec_near, near) && TTMaskHasType(&e->ec_far, far)) {
1167 	    cap += (e->ec_cap * overlap) / sep;
1168 	    if (CAP_DEBUG)
1169 		extAdjustCouple(he, (e->ec_cap * overlap) / sep, "sidewall");
1170 	}
1171     extSetCapValue(he, cap);
1172 }
1173