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