1 /*
2 * ExtSubtree.c --
3 *
4 * Circuit extraction.
5 * Extracts interactions between subtrees of a parent and the
6 * parent itself. Does not handle extraction of interactions
7 * arising between elements of the same array; those are handled
8 * by the procedures in ExtArray.c
9 *
10 * The procedures in this file are not re-entrant.
11 *
12 * *********************************************************************
13 * * Copyright (C) 1985, 1990 Regents of the University of California. *
14 * * Permission to use, copy, modify, and distribute this *
15 * * software and its documentation for any purpose and without *
16 * * fee is hereby granted, provided that the above copyright *
17 * * notice appear in all copies. The University of California *
18 * * makes no representations about the suitability of this *
19 * * software for any purpose. It is provided "as is" without *
20 * * express or implied warranty. Export of this software outside *
21 * * of the United States of America may require an export license. *
22 * *********************************************************************
23 */
24
25 #ifndef lint
26 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/extract/ExtSubtree.c,v 1.3 2010/06/24 12:37:17 tim Exp $";
27 #endif /* not lint */
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <sys/time.h>
32
33 #include "tcltk/tclmagic.h"
34 #include "utils/magic.h"
35 #include "tcltk/tclmagic.h"
36 #include "utils/geometry.h"
37 #include "utils/geofast.h"
38 #include "tiles/tile.h"
39 #include "utils/hash.h"
40 #include "database/database.h"
41 #include "utils/malloc.h"
42 #include "textio/textio.h"
43 #include "debug/debug.h"
44 #include "extract/extract.h"
45 #include "extract/extractInt.h"
46 #include "graphics/graphics.h"
47 #include "utils/signals.h"
48 #include "windows/windows.h"
49 #include "dbwind/dbwind.h"
50 #include "utils/styles.h"
51
52 #ifdef exactinteractions
53 /*
54 * If "exactinteractions" is defined, we use an experimental algorithm
55 * for finding exact interaction areas. Currently it doesn't work too
56 * well, so we leave it turned off.
57 */
58 int ExtInterBloat = 10;
59 #endif /* exactinteractions */
60
61 /* Imports from elsewhere in this module */
62 extern int extHierYankFunc();
63 extern LabRegion *extSubtreeHardNode();
64 extern Node *extHierNewNode();
65 extern ExtTree *extHierNewOne();
66
67 /* Global data incremented by extSubtree() */
68 int extSubtreeTotalArea; /* Total area of cell */
69 int extSubtreeInteractionArea; /* Total area of all interactions, counting the
70 * entire area of the interaction each time.
71 */
72 int extSubtreeClippedArea; /* Total area of all interactions, counting only
73 * the area that lies inside each chunk, so no
74 * area is counted more than once.
75 */
76
77 /* Local data */
78
79 /* TRUE if processing the first subtree in an interaction area */
80 bool extFirstPass;
81
82 /* Points to list of subtrees in an interaction area */
83 ExtTree *extSubList = (ExtTree *) NULL;
84
85 /* Forward declarations of filter functions */
86 char *extSubtreeTileToNode();
87 int extSubtreeFunc();
88 int extSubstrateFunc();
89 int extConnFindFunc();
90 int extSubtreeHardUseFunc();
91 int extHardProc();
92 int extSubtreeCopyPlane();
93 int extSubtreeShrinkPlane();
94 void extSubtreeInteraction();
95 void extSubtreeAdjustInit();
96 void extSubtreeOutputCoupling();
97 void extSubtreeHardSearch();
98
99 /*
100 * ----------------------------------------------------------------------------
101 *
102 * extClearUseFlags --
103 *
104 * Callback function to clear the CU_SUB_EXTRACTED flag from each child
105 * use of a CellDef.
106 *
107 * ----------------------------------------------------------------------------
108 */
109
110 int
extClearUseFlags(use,clientData)111 extClearUseFlags(use, clientData)
112 CellUse *use;
113 ClientData clientData;
114 {
115 use->cu_flags &= ~CU_SUB_EXTRACTED;
116 return 0;
117 }
118
119
120 /*
121 * ----------------------------------------------------------------------------
122 *
123 * extSubtree --
124 *
125 * Do the hierarchical part of extracting the cell 'parentUse->cu_def'.
126 * This consists of finding all connections either between geometry in the
127 * parent and geometry in a subcell, or between geometry in two overlapping
128 * or adjacent subcells.
129 *
130 * This procedure only finds interaction areas, where subcells are close
131 * to each other or to mask information, and then calls extSubtreeInteraction()
132 * to do the real work. See the comments there for more details.
133 *
134 * Results:
135 * None.
136 *
137 * Side effects:
138 * Outputs connections and adjustments to the file 'f'.
139 * There are two kinds of records:
140 *
141 * merge node1 node2 deltaC deltaP1 deltaA1 deltaP2 deltaA2 ...
142 * cap node1 node2 deltaC
143 *
144 * The first merges node1 and node2, adjusts the substrate capacitance
145 * by adding deltaC (usually negative), and the node perimeter and area
146 * for each resistive layer n by deltaPn deltaAn.
147 *
148 * The second adjusts the coupling capacitance between node1 and node2
149 * by deltaC, which may be positive or negative.
150 *
151 * ----------------------------------------------------------------------------
152 */
153
154 #define RECTAREA(r) (((r)->r_xtop-(r)->r_xbot) * ((r)->r_ytop-(r)->r_ybot))
155
156 void
extSubtree(parentUse,reg,f)157 extSubtree(parentUse, reg, f)
158 CellUse *parentUse;
159 NodeRegion *reg; /* Node regions of the parent cell */
160 FILE *f;
161 {
162 int extSubtreeInterFunc();
163 CellDef *def = parentUse->cu_def;
164 int halo = ExtCurStyle->exts_sideCoupleHalo + 1;
165 HierExtractArg ha;
166 Rect r, rlab, rbloat, *b;
167 Label *lab;
168 bool result;
169 int cuts, totcuts;
170 float pdone, plast;
171 SearchContext scx;
172
173 /* Use the display timer to force a 5-second progress check */
174 GrDisplayStatus = DISPLAY_IN_PROGRESS;
175 SigSetTimer(5); /* Print at 5-second intervals */
176
177 if ((ExtOptions & (EXT_DOCOUPLING|EXT_DOADJUST))
178 != (EXT_DOCOUPLING|EXT_DOADJUST))
179 halo = 1;
180
181 /*
182 * The cumulative buffer is initially empty. It will be built up
183 * for each interaction area, and then cleared before processing
184 * the next one.
185 *
186 * The connection hash table is initialized here but doesn't get
187 * cleared until the end. It is responsible for changes to the
188 * node structure over the entire cell 'def'.
189 */
190 extSubtreeTotalArea += RECTAREA(&def->cd_bbox);
191 ha.ha_outf = f;
192 ha.ha_parentUse = parentUse;
193 ha.ha_parentReg = reg;
194 ha.ha_nodename = extSubtreeTileToNode;
195 ha.ha_cumFlat.et_use = extYuseCum;
196 HashInit(&ha.ha_connHash, 32, 0);
197
198 #ifndef exactinteractions
199 /*
200 * Cookie-cutter up def into pieces ExtCurStyle->exts_stepSize by
201 * ExtCurStyle->exts_stepSize.
202 * Find all interaction areas (within halo units distance, where
203 * halo has been set above to reflect the maximum distance for
204 * sidewall coupling capacitance).
205 */
206 b = &def->cd_bbox;
207
208 /* Monitor progress, for large designs, and allow display refresh at intervals */
209
210 totcuts = (b->r_ytop - b->r_ybot + ExtCurStyle->exts_stepSize - 1)
211 / ExtCurStyle->exts_stepSize;
212 totcuts *= ((b->r_xtop - b->r_xbot + ExtCurStyle->exts_stepSize - 1)
213 / ExtCurStyle->exts_stepSize);
214 cuts = 0;
215 pdone = 0.0;
216 plast = 0.0;
217
218 for (r.r_ybot = b->r_ybot; r.r_ybot < b->r_ytop; r.r_ybot = r.r_ytop)
219 {
220 r.r_ytop = r.r_ybot + ExtCurStyle->exts_stepSize;
221 for (r.r_xbot = b->r_xbot; r.r_xbot < b->r_xtop; r.r_xbot = r.r_xtop)
222 {
223 r.r_xtop = r.r_xbot + ExtCurStyle->exts_stepSize;
224 if (SigInterruptPending)
225 goto done;
226 rbloat = r;
227 rbloat.r_xbot -= halo, rbloat.r_ybot -= halo;
228 rbloat.r_xtop += halo, rbloat.r_ytop += halo;
229 result = DRCFindInteractions(def, &rbloat, halo, &ha.ha_interArea);
230
231 // Check area for labels. Expand interaction area to include
232 // the labels. This catches labels that are not attached to
233 // any geometry in the cell and therefore do not get flagged by
234 // DRCFindInteractions().
235
236 for (lab = def->cd_labels; lab; lab = lab->lab_next)
237 if (GEO_OVERLAP(&lab->lab_rect, &r) || GEO_TOUCH(&lab->lab_rect, &r)) {
238 // Clip the label area to the area of rbloat
239 rlab = lab->lab_rect;
240 GEOCLIP(&rlab, &rbloat);
241 if (!result) {
242 // If result == FALSE then ha.ha_interArea is invalid.
243 ha.ha_interArea = rlab;
244 result = TRUE;
245 }
246 else
247 result |= GeoIncludeAll(&rlab, &ha.ha_interArea);
248 }
249
250 if (result)
251 {
252 ha.ha_clipArea = ha.ha_interArea;
253 GEOCLIP(&ha.ha_clipArea, &r);
254 extSubtreeInteractionArea += RECTAREA(&ha.ha_interArea);
255 extSubtreeClippedArea += RECTAREA(&ha.ha_clipArea);
256 extSubtreeInteraction(&ha);
257 }
258 else
259 {
260 /* Make sure substrate connections have been handled */
261 /* even if there were no other interactions found. */
262
263 ha.ha_clipArea = r;
264 scx.scx_trans = GeoIdentityTransform;
265 scx.scx_area = r;
266 scx.scx_use = ha.ha_parentUse;
267 DBCellSrArea(&scx, extSubstrateFunc, (ClientData)&ha);
268 }
269
270 cuts++;
271 pdone = 100.0 * ((float)cuts / (float)totcuts);
272 if ((((pdone - plast) > 5.0) || (cuts == totcuts)) && (cuts > 1)) {
273 /* Only print something if the 5-second timer has expired */
274 if (GrDisplayStatus == DISPLAY_BREAK_PENDING)
275 {
276 TxPrintf("Completed %d%%\n", (int)(pdone + 0.5));
277 plast = pdone;
278 TxFlushOut();
279
280 GrDisplayStatus = DISPLAY_IN_PROGRESS;
281 SigSetTimer(5);
282 }
283
284 #ifdef MAGIC_WRAPPER
285 /* We need to let Tk paint the console display */
286 while (Tcl_DoOneEvent(TCL_DONT_WAIT) != 0);
287 #endif
288 }
289 }
290 }
291 #else /* exactinteractions */
292 {
293 static Plane *interPlane = NULL, *bloatPlane = NULL;
294
295 /*
296 * Experimental code to find exact interaction areas.
297 * Currently, this both takes longer to find interactions
298 * and longer to process them than the cookie-cutter
299 * approach above, but maybe it can be turned into a
300 * scheme that is faster.
301 */
302 if (interPlane == (Plane *) NULL)
303 interPlane = DBNewPlane((ClientData) TT_SPACE);
304 if (bloatPlane == (Plane *) NULL)
305 bloatPlane = DBNewPlane((ClientData) TT_SPACE);
306 ExtFindInteractions(def, halo, ExtInterBloat, interPlane);
307 if (ExtInterBloat)
308 {
309 /* Shrink back down */
310 (void) DBSrPaintArea((Tile *) NULL, interPlane,
311 &TiPlaneRect, &DBAllButSpaceBits,
312 extSubtreeCopyPlane, (ClientData) bloatPlane);
313 (void) DBSrPaintArea((Tile *) NULL, bloatPlane,
314 &TiPlaneRect, &DBSpaceBits,
315 extSubtreeShrinkPlane, (ClientData) interPlane);
316 DBClearPaintPlane(bloatPlane);
317 }
318 (void) DBSrPaintArea((Tile *) NULL, interPlane,
319 &TiPlaneRect, &DBAllButSpaceBits,
320 extSubtreeInterFunc, (ClientData) &ha);
321 DBClearPaintPlane(interPlane);
322 }
323 #endif /* exactinteractions */
324
325 done:
326 /* Output connections and node adjustments */
327 extOutputConns(&ha.ha_connHash, f);
328 HashKill(&ha.ha_connHash);
329 GrDisplayStatus = DISPLAY_IDLE;
330 SigRemoveTimer();
331
332 /* Clear the CU_SUB_EXTRACTED flag from all children instances */
333 DBCellEnum(def, extClearUseFlags, (ClientData)NULL);
334 }
335
336 #ifdef exactinteractions
337 int
extSubtreeCopyPlane(tile,plane)338 extSubtreeCopyPlane(tile, plane)
339 Tile *tile;
340 Plane *plane;
341 {
342 Rect r;
343
344 TITORECT(tile, &r);
345 (void) DBPaintPlane(plane, &r, DBStdWriteTbl(TT_ERROR_P),
346 (PaintUndoInfo *) NULL);
347 return (0);
348 }
349
350 int
extSubtreeShrinkPlane(tile,plane)351 extSubtreeShrinkPlane(tile, plane)
352 Tile *tile;
353 Plane *plane;
354 {
355 Rect r;
356
357 TITORECT(tile, &r);
358 r.r_xbot -= ExtInterBloat; r.r_ybot -= ExtInterBloat;
359 r.r_xtop += ExtInterBloat; r.r_ytop += ExtInterBloat;
360 GEOCLIP(&r, &TiPlaneRect);
361 (void) DBPaintPlane(plane, &r, DBStdWriteTbl(TT_SPACE),
362 (PaintUndoInfo *) NULL);
363 return (0);
364 }
365
366 int
extSubtreeInterFunc(tile,ha)367 extSubtreeInterFunc(tile, ha)
368 Tile *tile;
369 HierExtractArg *ha;
370 {
371 TITORECT(tile, &ha->ha_interArea);
372 ha->ha_clipArea = ha->ha_interArea;
373 extSubtreeInteractionArea += RECTAREA(&ha->ha_interArea);
374 extSubtreeClippedArea += RECTAREA(&ha->ha_clipArea);
375 extSubtreeInteraction(ha);
376 return (0);
377 }
378 #endif /* exactinteractions */
379
380 /*
381 * ----------------------------------------------------------------------------
382 *
383 * extSubtreeInteraction --
384 *
385 * Having found an interaction area, we process it.
386 * The def being extracted is ha->ha_parentUse->cu_def.
387 *
388 * Clipping:
389 * The cookie-cutter piece we were looking at for the interaction is
390 * ha->ha_clipArea, and the interaction area actually found is
391 * ha->ha_interArea. It is possible that ha->ha_interArea extends
392 * outside of ha->ha_clipArea; if this is the case, all area and
393 * perimeter outside of ha->ha_clipArea are ignored when making
394 * adjustments. When computing sidewall coupling capacitance,
395 * we search for an initial tile only inside ha->ha_clipArea.
396 *
397 * Algorithm:
398 * Extracting an interaction area consists of two passes.
399 *
400 * The first pass will build the connection table ha->ha_connHash,
401 * but leave the adjustment for each connection as zero. At the
402 * end of the first pass, extSubList is a list of ExtTrees containing
403 * each flattened subtree in the area of the interaction (including
404 * the parent geometry), and ha->ha_cumFlat contains everything
405 * flattened.
406 *
407 * The second pass will make the adjustments in ha->ha_connHash, and
408 * will build the table et_coupleHash in ha->ha_cumFlat. All of
409 * the table ha->ha_connHash will be output, but only those entries
410 * in et_coupleHash with non-zero capacitance adjustment (either
411 * positive or negative) will get output.
412 *
413 * Results:
414 * None.
415 *
416 * Side effects:
417 * Adds more information to ha->ha_connHash and
418 * ha->ha_cumFlat.et_coupleHash.
419 *
420 * ----------------------------------------------------------------------------
421 */
422
423 void
extSubtreeInteraction(ha)424 extSubtreeInteraction(ha)
425 HierExtractArg *ha; /* Context for hierarchical extraction */
426 {
427 CellDef *oneDef, *cumDef = ha->ha_cumFlat.et_use->cu_def;
428 ExtTree *oneFlat, *nextFlat;
429 NodeRegion *reg;
430 SearchContext scx;
431
432 scx.scx_trans = GeoIdentityTransform;
433 scx.scx_area = ha->ha_interArea;
434 scx.scx_use = ha->ha_parentUse;
435
436 /* Copy parent paint into ha->ha_cumFlat */
437 DBCellCopyPaint(&scx, &DBAllButSpaceBits, 0, ha->ha_cumFlat.et_use);
438
439 /*
440 * First element on the subtree list will be parent mask info.
441 * Extract nodes and capacitors. Node names come from parent.
442 */
443 oneFlat = extHierNewOne();
444 oneDef = oneFlat->et_use->cu_def;
445 DBCellCopyPaint(&scx, &DBAllButSpaceBits, 0, oneFlat->et_use);
446
447 oneFlat->et_nodes = extFindNodes(oneDef, &ha->ha_clipArea, FALSE);
448 if ((ExtOptions & (EXT_DOCOUPLING|EXT_DOADJUST))
449 == (EXT_DOCOUPLING|EXT_DOADJUST))
450 {
451 HashInit(&oneFlat->et_coupleHash, 32, HashSize(sizeof (CoupleKey)));
452 extFindCoupling(oneDef, &oneFlat->et_coupleHash, &ha->ha_clipArea);
453 }
454 oneFlat->et_lookNames = ha->ha_parentUse->cu_def;
455 oneFlat->et_realuse = (CellUse *) NULL;
456 extSubList = oneFlat;
457
458 /*
459 * Cumulative yank buffer names also come from parent.
460 * Since we only mark nodes for use in naming on the first
461 * pass, there's no need to extract nodes in ha_cumFlat
462 * until we process the first subcell in extSubtreeFunc.
463 */
464 ha->ha_cumFlat.et_nodes = (NodeRegion *) NULL;
465 ha->ha_cumFlat.et_lookNames = ha->ha_parentUse->cu_def;
466 extFirstPass = TRUE;
467
468 /*
469 * Process each subcell in the interaction area exactly once.
470 * After processing each subcell, we reset ha->ha_cumFlat.et_nodes
471 * to NULL.
472 */
473 (void) DBCellSrArea(&scx, extSubtreeFunc, (ClientData) ha);
474
475 if (ExtOptions & EXT_DOADJUST)
476 {
477 /*
478 * Re-extract ha->ha_cumFlat, this time getting node capacitance,
479 * perimeter, and area, and coupling capacitances between nodes.
480 * Assign labels from cumDef's label list.
481 * Don't reset ha_lookNames, since we still need to be able to
482 * refer to nodes in the parent.
483 */
484 ha->ha_cumFlat.et_nodes = extFindNodes(cumDef, &ha->ha_clipArea, FALSE);
485 ExtLabelRegions(cumDef, ExtCurStyle->exts_nodeConn,
486 &(ha->ha_cumFlat.et_nodes), &ha->ha_clipArea);
487 if (ExtOptions & EXT_DOCOUPLING)
488 {
489 HashInit(&ha->ha_cumFlat.et_coupleHash, 32,
490 HashSize(sizeof(CoupleKey)));
491 extFindCoupling(cumDef, &ha->ha_cumFlat.et_coupleHash,
492 &ha->ha_clipArea);
493 }
494
495 /* Process all adjustments */
496 ha->ha_subUse = (CellUse *) NULL;
497 extSubtreeAdjustInit(ha);
498 for (oneFlat = extSubList; oneFlat; oneFlat = oneFlat->et_next)
499 extHierAdjustments(ha, &ha->ha_cumFlat, oneFlat, &ha->ha_cumFlat);
500
501 #if 0
502 /*
503 * Output adjustments to substrate capacitance that are not
504 * output anywhere else. Nodes that connect down into the
505 * hierarchy are part of ha_connHash and have adjustments
506 * that are printed in the "merge" statement. Nodes not in
507 * the current cell are not considered. Anything left over
508 * has its adjusted value output.
509 */
510
511 /* Disabled (9/28/2021)---This does not work as advertised. */
512
513 for (reg = ha->ha_parentReg; reg; reg = reg->nreg_next)
514 {
515 Rect r;
516 NodeRegion *treg;
517 CapValue finC;
518 char *text;
519
520 r.r_ll = reg->nreg_ll;
521 r.r_xtop = r.r_xbot + 1;
522 r.r_ytop = r.r_ybot + 1;
523
524 /* Use the tile position of the parent region to find the
525 * equivalent region in cumDef. Then compare the substrate
526 * cap and output the difference.
527 */
528
529 if (DBSrPaintArea((Tile *)NULL, cumDef->cd_planes[reg->nreg_pnum],
530 &r, &DBAllButSpaceBits, extConnFindFunc,
531 (ClientData) &treg))
532 {
533 text = extNodeName(reg);
534 // Output the adjustment made to the substrate cap
535 // (should be negative). Ignore adjustments of zero
536 finC = (treg->nreg_cap - reg->nreg_cap) /
537 ExtCurStyle->exts_capScale;
538 if (finC < -1.0E-6)
539 fprintf(ha->ha_outf, "subcap \"%s\" %lg\n", text, finC);
540 }
541 }
542 #endif
543
544 /*
545 * Output adjustments to coupling capacitance.
546 * The names output for coupling capacitors are those on the
547 * label list for each node in the cumulative buffer.
548 */
549 if (ExtOptions & EXT_DOCOUPLING)
550 {
551 extSubtreeOutputCoupling(ha);
552 extCapHashKill(&ha->ha_cumFlat.et_coupleHash);
553 }
554 }
555
556 /* Free the subtrees (this must happen after all adjustments are made) */
557 for (oneFlat = extSubList; oneFlat; oneFlat = nextFlat)
558 nextFlat = oneFlat->et_next, extHierFreeOne(oneFlat);
559 extSubList = (ExtTree *) NULL;
560
561 /*
562 * Done with the cumulative yank buffer for this interaction.
563 * Free the list of nodes, the list of hierarchical labels
564 * built when we yanked this def, and then erase all the paint
565 * in the buffer.
566 */
567 if (ha->ha_cumFlat.et_nodes)
568 ExtFreeLabRegions((LabRegion *) ha->ha_cumFlat.et_nodes);
569 ha->ha_cumFlat.et_nodes = (NodeRegion *) NULL;
570 extHierFreeLabels(cumDef);
571 DBCellClearDef(cumDef);
572 }
573
574 /*
575 * ----------------------------------------------------------------------------
576 *
577 * extSubtreeAdjustInit --
578 *
579 * Initialize the node capacitance, perimeter, and area values in
580 * all the Nodes in the HashTable ha->ha_connHash. The initial
581 * values come from the NodeRegions in ha->ha_cumFlat.et_nodes,
582 * which correspond to extracting the entire flattened interaction
583 * area. We add these values to any already existing from a previous
584 * interaction area in case there were any nodes that span the boundary
585 * between two interaction areas. We will then call extHierAdjustments
586 * to subtract away the extracted values in each of the individually
587 * flattened subtrees.
588 *
589 * Results:
590 * None.
591 *
592 * Side effects:
593 * See above.
594 *
595 * Design notes:
596 * We only need to update perimeter, area, or substrate capacitance
597 * when nodes from different subtrees abut or overlap, i.e., connect.
598 * These nodes have already been recorded in the table ha->ha_connHash
599 * by extHierConnections(), so all we have to do is find the appropriate
600 * entries in this table.
601 *
602 * Each NodeRegion in ha->ha_cumFlat contains a list of labels with
603 * it. The first label in each list is guaranteed to correspond to
604 * an entry in the table ha->ha_connHash if this node is a participant
605 * in a connection, so we pass this label to HashFind to obtain the
606 * appropriate Node.
607 *
608 * ----------------------------------------------------------------------------
609 */
610
611 void
extSubtreeAdjustInit(ha)612 extSubtreeAdjustInit(ha)
613 HierExtractArg *ha;
614 {
615 NodeRegion *np;
616 NodeName *nn;
617 int n;
618 HashEntry *he;
619 char *name;
620
621 /*
622 * Initialize the capacitance, perimeter, and area values
623 * in the Nodes in the hash table ha->ha_connHash.
624 */
625 for (np = ha->ha_cumFlat.et_nodes; np; np = np->nreg_next)
626 {
627 if ((name = extNodeName((LabRegion *) np))
628 && (he = HashLookOnly(&ha->ha_connHash, name))
629 && (nn = (NodeName *) HashGetValue(he)))
630 {
631 nn->nn_node->node_cap += np->nreg_cap;
632 for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++)
633 {
634 nn->nn_node->node_pa[n].pa_perim += np->nreg_pa[n].pa_perim;
635 nn->nn_node->node_pa[n].pa_area += np->nreg_pa[n].pa_area;
636 }
637 }
638 }
639 }
640
641 /*
642 * ----------------------------------------------------------------------------
643 *
644 * extSubtreeOutputCoupling --
645 *
646 * Output the coupling capacitance table built up by extFindCoupling().
647 * Each entry in the hash table is a capacitance between the pair of
648 * nodes identified by he->h_key, an CoupleKey struct. Writes to the
649 * FILE ha->ha_outf.
650 *
651 * Because it is possible that the coupled nodes aren't already named,
652 * we have to call extSubtreeTileToNode() to find their actual names.
653 *
654 * Results:
655 * None.
656 *
657 * Side effects:
658 * See the comments above.
659 *
660 * ----------------------------------------------------------------------------
661 */
662
663 void
extSubtreeOutputCoupling(ha)664 extSubtreeOutputCoupling(ha)
665 HierExtractArg *ha;
666 {
667 CapValue cap;
668 CoupleKey *ck;
669 HashEntry *he;
670 Tile *tp;
671 HashSearch hs;
672 char *name;
673
674 HashStartSearch(&hs);
675 while (he = HashNext(&ha->ha_cumFlat.et_coupleHash, &hs))
676 {
677 cap = extGetCapValue(he) / ExtCurStyle->exts_capScale;
678 if (cap == 0)
679 continue;
680
681 ck = (CoupleKey *) he->h_key.h_words;
682
683 tp = extNodeToTile(ck->ck_1, &ha->ha_cumFlat);
684 name = extSubtreeTileToNode(tp, ck->ck_1->nreg_pnum, &ha->ha_cumFlat, ha, TRUE);
685 fprintf(ha->ha_outf, "cap \"%s\" ", name);
686
687 tp = extNodeToTile(ck->ck_2, &ha->ha_cumFlat);
688 name = extSubtreeTileToNode(tp, ck->ck_2->nreg_pnum, &ha->ha_cumFlat, ha, TRUE);
689 fprintf(ha->ha_outf, "\"%s\" %lg\n", name, cap);
690 }
691 }
692
693 /*
694 * ----------------------------------------------------------------------------
695 *
696 * extSubtreeFunc --
697 *
698 * Called once for each cell use that is a child of the parent def
699 * being extracted. Yanks the subtree into a new ExtTree. Extract
700 * connections between this subtree and ha->ha_cumFlat, then paint
701 * the subtree into the cumulative buffer ha->ha_cumFlat and prepend
702 * the subtree to extSubList.
703 *
704 * Results:
705 * Always returns 2, to avoid further elements in arrays.
706 *
707 * Side effects:
708 * Leaves ha->ha_cumFlat unextracted (all LabRegions free,
709 * and ha->ha_cumFlat.et_nodes set to NULL).
710 * See extHierConnections().
711 *
712 * ----------------------------------------------------------------------------
713 */
714
715 int
extSubtreeFunc(scx,ha)716 extSubtreeFunc(scx, ha)
717 SearchContext *scx;
718 HierExtractArg *ha;
719 {
720 CellUse *cumUse = ha->ha_cumFlat.et_use;
721 CellUse *use = scx->scx_use;
722 CellDef *oneDef;
723 SearchContext newscx;
724 ExtTree *oneFlat;
725 HierYank hy;
726 int x, y;
727
728 /* Allocate a new ExtTree to hold the flattened, extracted subtree */
729 oneFlat = extHierNewOne();
730 oneFlat->et_realuse = use;
731
732 /* Record information for finding node names the hard way later */
733 ha->ha_subUse = use;
734
735 /*
736 * Yank all array elements of this subcell that lie in the interaction
737 * area. Transform to parent coordinates. Prefix is true, meaning that
738 * we should prefix each hierarchical name with the subcell use it
739 * belongs to.
740 */
741 ha->ha_subArea = use->cu_bbox;
742 GEOCLIP(&ha->ha_subArea, &ha->ha_interArea);
743 hy.hy_area = &ha->ha_subArea;
744 hy.hy_target = oneFlat->et_use;
745 hy.hy_prefix = TRUE;
746
747 (void) DBArraySr(use, &ha->ha_subArea, extHierYankFunc, (ClientData) &hy);
748
749 /*
750 * Extract node capacitance, perimeter, area, and coupling capacitance
751 * for this subtree. Labels come from the hierarchical labels yanked
752 * above, but may have additional labels added when we find names the
753 * hard way.
754 */
755 oneDef = oneFlat->et_use->cu_def;
756 oneFlat->et_nodes = extFindNodes(oneDef, &ha->ha_clipArea, FALSE);
757 ExtLabelRegions(oneDef, ExtCurStyle->exts_nodeConn,
758 &(oneFlat->et_nodes), &ha->ha_clipArea);
759 if ((ExtOptions & (EXT_DOCOUPLING|EXT_DOADJUST))
760 == (EXT_DOCOUPLING|EXT_DOADJUST))
761 extFindCoupling(oneDef, &oneFlat->et_coupleHash, &ha->ha_clipArea);
762
763 /*
764 * If this is not the first subcell we're processing, mark ha_cumFlat's
765 * tiles with LabRegions. We don't mark it the first time through,
766 * since then ha_cumFlat contains only the parent mask geometry and
767 * node names will be found by looking in ha_lookNames.
768 */
769 if (extFirstPass)
770 {
771 extFirstPass = FALSE;
772
773 // On the first pass, run through et_lookName's label list.
774 // Copy any sticky labels to cumUse->cu_def, so that the labels
775 // can be found even when there is no geometry underneath in
776 // the parent cell.
777
778 CellDef *cumDef = ha->ha_cumFlat.et_lookNames;
779
780 if (cumDef != NULL)
781 {
782 Label *lab, *newlab;
783 unsigned int n;
784
785 for (lab = cumDef->cd_labels; lab ; lab = lab->lab_next)
786 {
787 if (!(lab->lab_flags & LABEL_STICKY)) continue;
788
789 n = sizeof (Label) + strlen(lab->lab_text)
790 - sizeof lab->lab_text + 1;
791
792 newlab = (Label *)mallocMagic(n);
793 newlab->lab_type = lab->lab_type;
794 newlab->lab_rect = lab->lab_rect;
795 newlab->lab_flags = lab->lab_flags;
796 newlab->lab_port = lab->lab_port;
797 strcpy(newlab->lab_text, lab->lab_text);
798
799 newlab->lab_next = cumUse->cu_def->cd_labels;
800 cumUse->cu_def->cd_labels = newlab;
801 }
802 }
803 }
804 else
805 {
806 /*
807 * We don't care about the lreg_ll or lreg_pNum for these
808 * nodes (we're only interested in the label list associated
809 * with each node), so we don't pass extHierLabEach() to
810 * ExtFindRegions().
811 */
812 ha->ha_cumFlat.et_nodes =
813 (NodeRegion *) ExtFindRegions(cumUse->cu_def, &TiPlaneRect,
814 &ExtCurStyle->exts_activeTypes,
815 ExtCurStyle->exts_nodeConn,
816 extUnInit, extHierLabFirst, (int (*)()) NULL);
817 ExtLabelRegions(cumUse->cu_def, ExtCurStyle->exts_nodeConn,
818 &(ha->ha_cumFlat.et_nodes), &TiPlaneRect);
819 }
820
821 /* Process connections; this updates ha->ha_connHash */
822 extHierConnections(ha, &ha->ha_cumFlat, oneFlat);
823
824 /* Process substrate connection. All substrates should be */
825 /* connected together in the cell def, so in the case of an */
826 /* array, just make sure that the first array entry is */
827 /* connected. */
828
829 if (use->cu_xhi == use->cu_xlo && use->cu_yhi == use->cu_ylo)
830 extHierSubstrate(ha, use, -1, -1);
831 else if (use->cu_xhi == use->cu_xlo && use->cu_yhi > use->cu_ylo)
832 {
833 for (y = use->cu_ylo; y <= use->cu_yhi; y++)
834 extHierSubstrate(ha, use, -1, y);
835 }
836 else if (use->cu_xhi > use->cu_xlo && use->cu_yhi == use->cu_ylo)
837 {
838 for (x = use->cu_xlo; x <= use->cu_xhi; x++)
839 extHierSubstrate(ha, use, x, -1);
840 }
841 else
842 {
843 for (x = use->cu_xlo; x <= use->cu_xhi; x++)
844 for (y = use->cu_ylo; y <= use->cu_yhi; y++)
845 extHierSubstrate(ha, use, x, y);
846 }
847 /* Mark substrate as having been extracted for this use. */
848 use->cu_flags |= CU_SUB_EXTRACTED;
849
850 /* Free the cumulative node list we extracted above */
851 if (ha->ha_cumFlat.et_nodes)
852 {
853 ExtResetTiles(cumUse->cu_def, extUnInit);
854 ExtFreeLabRegions((LabRegion *) ha->ha_cumFlat.et_nodes);
855 ha->ha_cumFlat.et_nodes = (NodeRegion *) NULL;
856 }
857
858 /*
859 * Paint the subtree buffer on top of the cumulative buffer.
860 * Copy the labels that were yanked along with the subtree into
861 * the cumulative buffer as well.
862 */
863 newscx.scx_use = oneFlat->et_use;
864 newscx.scx_area = ha->ha_subArea;
865 newscx.scx_trans = GeoIdentityTransform;
866 DBCellCopyPaint(&newscx, &DBAllButSpaceBits, 0, cumUse);
867 extHierCopyLabels(oneFlat->et_use->cu_def, cumUse->cu_def);
868
869 /* Prepend this tree to the list of trees we've processed so far */
870 oneFlat->et_next = extSubList;
871 extSubList = oneFlat;
872
873 return (2);
874 }
875
876
877 /*
878 * ----------------------------------------------------------------------------
879 *
880 * extSubstrateFunc
881 *
882 * This contains just the part of extSubtreeFunc() dealing with the
883 * substrate, so that substrate extraction can occur in cells not
884 * otherwise having extraction interactions, without incurring the
885 * overhead of all the other items handled by extHierSubtreeFunc().
886 *
887 * Results:
888 * Always returns 2, to avoid further elements in arrays.
889 *
890 * ----------------------------------------------------------------------------
891 */
892
893 int
extSubstrateFunc(scx,ha)894 extSubstrateFunc(scx, ha)
895 SearchContext *scx;
896 HierExtractArg *ha;
897 {
898 CellUse *use = scx->scx_use;
899 int x, y;
900
901 /* Record information for finding node names the hard way */
902 ha->ha_subUse = use;
903 ha->ha_subArea = use->cu_bbox;
904 GEOCLIP(&ha->ha_subArea, &ha->ha_interArea);
905
906 /* Process substrate connection. All substrates should be */
907 /* connected together in the cell def, so in the case of an */
908 /* array, just make sure that the first array entry is */
909 /* connected. */
910
911 if (use->cu_xhi == use->cu_xlo && use->cu_yhi == use->cu_ylo)
912 extHierSubstrate(ha, use, -1, -1);
913 else if (use->cu_xhi == use->cu_xlo && use->cu_yhi > use->cu_ylo)
914 {
915 for (y = use->cu_ylo; y <= use->cu_yhi; y++)
916 extHierSubstrate(ha, use, -1, y);
917 }
918 else if (use->cu_xhi > use->cu_xlo && use->cu_yhi == use->cu_ylo)
919 {
920 for (x = use->cu_xlo; x <= use->cu_xhi; x++)
921 extHierSubstrate(ha, use, x, -1);
922 }
923 else
924 {
925 for (x = use->cu_xlo; x <= use->cu_xhi; x++)
926 for (y = use->cu_ylo; y <= use->cu_yhi; y++)
927 extHierSubstrate(ha, use, x, y);
928 }
929 use->cu_flags |= CU_SUB_EXTRACTED;
930 return (2);
931 }
932
933
934 /*
935 * ----------------------------------------------------------------------------
936 *
937 * extSubtreeTileToNode --
938 *
939 * Map from a Tile in a given yank buffer 'et' to the name of the node
940 * containing that tile.
941 *
942 * The node associated with a tile can be determined in one of the
943 * following ways:
944 *
945 * (1) Look for a label on the list of the Region pointed to by the
946 * tile planes of the yank buffer. If no label was found, then
947 * try (2).
948 *
949 * (2) If et->et_lookNames is non-NULL, see if the tile overlaps a
950 * connected tile on the same plane of the def et->et_lookNames.
951 *
952 * (3) Call extSubtreeHardNode() to do a painful extraction of a label.
953 * See the comments in extSubtreeHardNode() for a description of
954 * the algorithm used. Only do this if doHard is TRUE.
955 *
956 * Results:
957 * Returns a pointer to the name of the node containing
958 * the tile. If no node name was found, and doHard was
959 * TRUE, return the string "(none)"; if doHard was FALSE,
960 * return NULL.
961 *
962 * Side effects:
963 * The string returned is allocated from a static buffer, so
964 * subsequent calls to extSubtreeTileToNode() will overwrite
965 * the results returned in previous calls.
966 *
967 * Records an error with the feedback package if no node name
968 * could be found and doHard was TRUE.
969 *
970 * ----------------------------------------------------------------------------
971 */
972
973 char *
extSubtreeTileToNode(tp,pNum,et,ha,doHard)974 extSubtreeTileToNode(tp, pNum, et, ha, doHard)
975 Tile *tp; /* Tile whose node name is to be found */
976 int pNum; /* Plane of the tile */
977 ExtTree *et; /* Yank buffer to search */
978 HierExtractArg *ha; /* Extraction context */
979 bool doHard; /* If TRUE, we look up this node's name the hard way
980 * if we can't find it any other way; otherwise, we
981 * return NULL if we can't find the node's name.
982 */
983 {
984 static char warningStr[] =
985 "Warning: node labels should be inside overlap area";
986 static char errorStr[] =
987 "Cannot find the name of this node (probable extractor error)";
988 CellDef *parentDef = ha->ha_parentUse->cu_def;
989 LabRegion *reg;
990 Label *lab;
991 Rect r;
992 TileType ttype;
993
994 /* If there is a label list, use it */
995 if (extHasRegion(tp, extUnInit))
996 {
997 reg = (LabRegion *) extGetRegion(tp);
998 if (reg->lreg_labels)
999 return (extNodeName(reg));
1000 }
1001
1002 /*
1003 * If there is any node at all in the cell et->et_lookNames,
1004 * use it. The node doesn't have to have a label list.
1005 */
1006 TITORECT(tp, &r);
1007 if (et->et_lookNames)
1008 {
1009 /*
1010 * Make sure we've got a valid tile -- interactions with interrupts
1011 * can cause problems.
1012 */
1013 if (IsSplit(tp))
1014 {
1015 if (SplitSide(tp))
1016 ttype = SplitRightType(tp);
1017 else
1018 ttype = SplitLeftType(tp);
1019 }
1020 else
1021 ttype = TiGetTypeExact(tp);
1022
1023 if (pNum >= PL_PAINTBASE)
1024 {
1025 if (IsSplit(tp))
1026 {
1027 if (DBSrPaintNMArea((Tile *) NULL,
1028 et->et_lookNames->cd_planes[pNum],
1029 TiGetTypeExact(tp), &r, &DBAllButSpaceBits,
1030 extConnFindFunc, (ClientData) ®))
1031 {
1032 if (SigInterruptPending)
1033 return ("(none)");
1034 return (extNodeName(reg));
1035 }
1036 }
1037 else
1038 {
1039 if (DBSrPaintArea((Tile *) NULL,
1040 et->et_lookNames->cd_planes[pNum], &r,
1041 &DBAllButSpaceBits, extConnFindFunc, (ClientData) ®))
1042 {
1043 if (SigInterruptPending)
1044 return ("(none)");
1045 return (extNodeName(reg));
1046 }
1047 }
1048 }
1049 }
1050
1051 /* We have to do it the hard way */
1052 if (!doHard) return ((char *) NULL);
1053 if (extHasRegion(tp, extUnInit)
1054 && (reg = extSubtreeHardNode(tp, pNum, et, ha)))
1055 {
1056 if (ExtDoWarn & EXTWARN_LABELS)
1057 {
1058 DBWFeedbackAdd(&r, warningStr, parentDef, 1, STYLE_PALEHIGHLIGHTS);
1059 extNumWarnings++;
1060 }
1061 return (extNodeName(reg));
1062 }
1063
1064 extNumFatal++;
1065 if (!DebugIsSet(extDebugID, extDebNoFeedback))
1066 DBWFeedbackAdd(&r, errorStr, parentDef, 1, STYLE_MEDIUMHIGHLIGHTS);
1067 return ("(none)");
1068 }
1069
1070 /*
1071 * ----------------------------------------------------------------------------
1072 * extConnFindFunc --
1073 *
1074 * Called when searching the area of a tile in the def et->et_lookNames
1075 * by extSubtreeTileToNode() above.
1076 *
1077 * Results:
1078 * If we find a tile that has been marked with a node,
1079 * return 1; otherwise, return 0.
1080 *
1081 * Side effects:
1082 * Sets *preg to the node found if we returned 1; otherwise,
1083 * leaves *preg alone.
1084 * ----------------------------------------------------------------------------
1085 */
1086
1087 int
extConnFindFunc(tp,preg)1088 extConnFindFunc(tp, preg)
1089 Tile *tp;
1090 LabRegion **preg;
1091 {
1092 if (extHasRegion(tp, extUnInit))
1093 {
1094 *preg = (LabRegion *) extGetRegion(tp);
1095 return (1);
1096 }
1097
1098 return (0);
1099 }
1100
1101 /*
1102 * ----------------------------------------------------------------------------
1103 *
1104 * extSubtreeHardNode --
1105 *
1106 * Find a node name for the electrical node containing the tile 'tp'
1107 * the hard way. We assume tp->ti_client points to a LabRegion that
1108 * had no labels associated with it; if we succeed, we leave this
1109 * LabRegion pointing to a newly allocated LabelList and Label.
1110 *
1111 * Results:
1112 * Returns a pointer to LabRegion for the node to which the tile
1113 * 'tp' belongs. Returns NULL if no region could be found.
1114 *
1115 * Side effects:
1116 * See above.
1117 *
1118 * Algorithm:
1119 * For each subcell of the parent that could have contributed
1120 * to the yank buffer in question, search the original tree
1121 * for geometry in the area of the tile 'tp'. For each cell
1122 * we find, we trace out just those nodes lying in the area
1123 * of the overlap, and then do a label assignment for those
1124 * nodes. As soon as we find a label, we're done. Otherwise,
1125 * we reset this def back the way we found it and continue on
1126 * to the next cell in our search.
1127 *
1128 * ----------------------------------------------------------------------------
1129 */
1130
1131 LabRegion *
extSubtreeHardNode(tp,pNum,et,ha)1132 extSubtreeHardNode(tp, pNum, et, ha)
1133 Tile *tp;
1134 int pNum;
1135 ExtTree *et;
1136 HierExtractArg *ha;
1137 {
1138 LabRegion *lreg = (LabRegion *) extGetRegion(tp);
1139 CellDef *def = et->et_use->cu_def;
1140 TileType ttype;
1141 char labelBuf[4096];
1142 LabelList *ll;
1143 HardWay arg;
1144
1145 ASSERT(lreg->lreg_labels == NULL, "extSubtreeHardNode");
1146
1147 if (IsSplit(tp))
1148 {
1149 if (SplitSide(tp))
1150 ttype = SplitRightType(tp);
1151 else
1152 ttype = SplitLeftType(tp);
1153 }
1154 else
1155 ttype = TiGetTypeExact(tp);
1156
1157 arg.hw_ha = ha;
1158 arg.hw_label = (Label *) NULL;
1159 arg.hw_mask = DBPlaneTypes[pNum];
1160 TTMaskAndMask(&arg.hw_mask, &DBConnectTbl[ttype]);
1161 arg.hw_tpath.tp_last = &labelBuf[sizeof labelBuf - 3];
1162 arg.hw_tpath.tp_first = arg.hw_tpath.tp_next = labelBuf;
1163 arg.hw_prefix = TRUE;
1164 TITORECT(tp, &arg.hw_area);
1165
1166 /*
1167 * Try to find a label in the area.
1168 * If we can't find a label, we make one up based on the
1169 * automatically generated node name in a child cell that
1170 * contains paint in this node.
1171 */
1172 labelBuf[0] = '\0';
1173 arg.hw_autogen = FALSE;
1174 extSubtreeHardSearch(et, &arg);
1175 if (arg.hw_label == NULL)
1176 {
1177 labelBuf[0] = '\0';
1178 arg.hw_autogen = TRUE;
1179 extSubtreeHardSearch(et, &arg);
1180 }
1181
1182 /*
1183 * If we succeeded (we always should), we now have a label.
1184 * Make the single LabelList for the region 'lreg' point to
1185 * this label, and prepend it to the list for 'def'.
1186 */
1187 if (arg.hw_label)
1188 {
1189 ll = (LabelList *) mallocMagic((unsigned) (sizeof (LabelList)));
1190 lreg->lreg_labels = ll;
1191 ll->ll_next = (LabelList *) NULL;
1192 ll->ll_label = arg.hw_label;
1193 arg.hw_label->lab_next = def->cd_labels;
1194 def->cd_labels = arg.hw_label;
1195 return (lreg);
1196 }
1197
1198 return ((LabRegion *) NULL);
1199 }
1200
1201 /*
1202 * ----------------------------------------------------------------------------
1203 * extSubtreeHardSearch --
1204 *
1205 * Do the actual work of deciding which subtrees to search
1206 * for extSubtreeHardNode above. We apply the procedure
1207 * extHardProc() at each subcell.
1208 * ----------------------------------------------------------------------------
1209 */
1210
1211 void
extSubtreeHardSearch(et,arg)1212 extSubtreeHardSearch(et, arg)
1213 ExtTree *et;
1214 HardWay *arg;
1215 {
1216 HierExtractArg *ha = arg->hw_ha;
1217 ExtTree *oneFlat;
1218
1219 arg->hw_proc = extHardProc;
1220 if (et == &ha->ha_cumFlat)
1221 {
1222 /*
1223 * Recursively search all children of parent up to, but not
1224 * including, ha->ha_subUse. Don't search parent paint.
1225 */
1226 for (oneFlat = extSubList; oneFlat; oneFlat = oneFlat->et_next)
1227 {
1228 if (oneFlat->et_realuse)
1229 {
1230 if (DBArraySr(oneFlat->et_realuse, &arg->hw_area,
1231 extSubtreeHardUseFunc, (ClientData) arg))
1232 {
1233 break;
1234 }
1235 }
1236 }
1237 }
1238 else
1239 {
1240 /* Recursively search only the elements of ha->ha_subUse */
1241 (void) DBArraySr(ha->ha_subUse, &arg->hw_area,
1242 extSubtreeHardUseFunc, (ClientData) arg);
1243 }
1244 }
1245
1246 /*
1247 * ----------------------------------------------------------------------------
1248 * extSubtreeHardUseFunc --
1249 *
1250 * When searching a subtree, this is called once for each element
1251 * in the array that is the root of the subtree.
1252 *
1253 * Results:
1254 * Returns 1 if we have successfully found a label, 0 if not
1255 * (return value of arg->hw_proc).
1256 *
1257 * Side effects:
1258 * Calls (*arg->hw_proc)().
1259 * ----------------------------------------------------------------------------
1260 */
1261
1262 int
extSubtreeHardUseFunc(use,trans,x,y,arg)1263 extSubtreeHardUseFunc(use, trans, x, y, arg)
1264 CellUse *use; /* Use that is the root of the subtree being searched */
1265 Transform *trans; /* Transform from coordinates of use->cu_def to those
1266 * in use->cu_parent, for the array element (x, y).
1267 */
1268 int x, y; /* Indices of this array element */
1269 HardWay *arg; /* Context passed down to filter functions */
1270 {
1271 SearchContext scx;
1272 Transform tinv;
1273
1274 scx.scx_use = use;
1275 scx.scx_trans = *trans;
1276 scx.scx_x = x;
1277 scx.scx_y = y;
1278 GEOINVERTTRANS(trans, &tinv);
1279 GEOTRANSRECT(&tinv, &arg->hw_area, &scx.scx_area);
1280 return ((*arg->hw_proc)(&scx, arg));
1281 }
1282