1 /*
2 * ExtMain.c --
3 *
4 * Circuit extraction.
5 * Command interface.
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/ExtMain.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
22 #endif /* not lint */
23
24 #include <stdio.h>
25 #include <math.h>
26
27 #include "utils/magic.h"
28 #include "utils/geometry.h"
29 #include "utils/styles.h"
30 #include "tiles/tile.h"
31 #include "utils/hash.h"
32 #include "database/database.h"
33 #include "utils/malloc.h"
34 #include "textio/textio.h"
35 #include "debug/debug.h"
36 #include "extract/extract.h"
37 #include "extract/extractInt.h"
38 #include "utils/signals.h"
39 #include "utils/stack.h"
40 #include "utils/utils.h"
41 #include "windows/windows.h"
42 #include "dbwind/dbwind.h"
43 #include "utils/main.h"
44 #include "utils/undo.h"
45
46 /* Imports from elsewhere in this module */
47 extern FILE *extFileOpen();
48
49 /* ------------------------ Exported variables ------------------------ */
50
51 /*
52 * See extract.h for the bit flags that may be set in the following.
53 * If any are set, the corresponding warnings get generated, leaving
54 * feedback messages. If this word is zero, only errors are
55 * reported.
56 */
57 int ExtDoWarn = EXTWARN_DUP|EXTWARN_FETS;
58 int ExtOptions = EXT_DOALL;
59
60 /* --------------------------- Global data ---------------------------- */
61
62 /* Cumulative yank buffer for hierarchical circuit extraction */
63 CellUse *extYuseCum = NULL;
64 CellDef *extYdefCum = NULL;
65
66 /* Identifier returned by the debug module for circuit extraction */
67 ClientData extDebugID;
68
69 /* Number of errors encountered during extraction */
70 int extNumFatal;
71 int extNumWarnings;
72
73 /* Dummy use pointing to def being extracted */
74 CellUse *extParentUse;
75
76 /* ------------------------ Data local to this file ------------------- */
77
78 /* Stack of defs pending extraction */
79 Stack *extDefStack;
80
81 /* Forward declarations */
82 int extDefInitFunc(), extDefPushFunc();
83 void extParents();
84 void extDefParentFunc();
85 void extDefParentAreaFunc();
86 void extExtractStack();
87
88 bool extContainsGeometry();
89 bool extContainsCellFunc();
90 bool extTimestampMisMatch();
91
92 /*
93 * ----------------------------------------------------------------------------
94 *
95 * ExtInit --
96 *
97 * Initialize the technology-independent part of the extraction module.
98 * This procedure should be called once, after the database module has
99 * been initialized.
100 *
101 * Results:
102 * None.
103 *
104 * Side effects:
105 * Initializes the local variables of the extraction module.
106 * Registers the extractor with the debugging module.
107 *
108 * ----------------------------------------------------------------------------
109 */
110
111 void
ExtInit()112 ExtInit()
113 {
114 int n;
115 static struct
116 {
117 char *di_name;
118 int *di_id;
119 } debugFlags[] = {
120 "areaenum", &extDebAreaEnum,
121 "array", &extDebArray,
122 "hardway", &extDebHardWay,
123 "hiercap", &extDebHierCap,
124 "hierareacap", &extDebHierAreaCap,
125 "label", &extDebLabel,
126 "length", &extDebLength,
127 "neighbor", &extDebNeighbor,
128 "noarray", &extDebNoArray,
129 "nofeedback", &extDebNoFeedback,
130 "nohard", &extDebNoHard,
131 "nosubcell", &extDebNoSubcell,
132 "perimeter", &extDebPerim,
133 "resist", &extDebResist,
134 "visonly", &extDebVisOnly,
135 "yank", &extDebYank,
136 0
137 };
138
139 /* Register ourselves with the debugging module */
140 extDebugID =
141 DebugAddClient("extract", sizeof debugFlags/sizeof debugFlags[0]);
142 for (n = 0; debugFlags[n].di_name; n++)
143 *(debugFlags[n].di_id) =
144 DebugAddFlag(extDebugID, debugFlags[n].di_name);
145
146 /* Create the yank buffer used for hierarchical extraction */
147 DBNewYank("__ext_cumulative", &extYuseCum, &extYdefCum);
148
149 /* Create the dummy use also used in hierarchical extraction */
150 extParentUse = DBCellNewUse(extYdefCum, (char *) NULL);
151 DBSetTrans(extParentUse, &GeoIdentityTransform);
152
153 /* Initialize the hash tables used in ExtLength.c */
154 extLengthInit();
155 }
156
157 /*
158 * ----------------------------------------------------------------------------
159 *
160 * ExtAll --
161 *
162 * Extract the subtree rooted at the CellDef 'rootUse->cu_def'.
163 * Each cell is extracted to a file in the current directory
164 * whose name consists of the last part of the cell's path,
165 * with a .ext suffix.
166 *
167 * Results:
168 * None.
169 *
170 * Side effects:
171 * Creates a number of .ext files and writes to them.
172 * Adds feedback information where errors have occurred.
173 *
174 * ----------------------------------------------------------------------------
175 */
176
177 void
ExtAll(rootUse)178 ExtAll(rootUse)
179 CellUse *rootUse;
180 {
181 /* Make sure the entire subtree is read in */
182 if (DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox, TRUE))
183 {
184 TxError("Failure to read entire subtree of cell.\n");
185 return;
186 }
187
188 /* Fix up bounding boxes if they've changed */
189 DBFixMismatch();
190
191 /* Mark all defs as being unvisited */
192 (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0);
193
194 /* Recursively visit all defs in the tree and push on stack */
195 extDefStack = StackNew(100);
196 (void) extDefPushFunc(rootUse);
197
198 /* Now extract all the cells we just found */
199 extExtractStack(extDefStack, TRUE, rootUse->cu_def);
200 StackFree(extDefStack);
201 }
202
203 /*
204 * Function to initialize the client data field of all
205 * cell defs, in preparation for extracting a subtree
206 * rooted at a particular def.
207 */
208 int
extDefInitFunc(def)209 extDefInitFunc(def)
210 CellDef *def;
211 {
212 def->cd_client = (ClientData) 0;
213 return (0);
214 }
215
216 /*
217 * Function to push each cell def on extDefStack
218 * if it hasn't already been pushed, and then recurse
219 * on all that def's children.
220 */
221 int
extDefPushFunc(use)222 extDefPushFunc(use)
223 CellUse *use;
224 {
225 CellDef *def = use->cu_def;
226
227 if (def->cd_client || (def->cd_flags&CDINTERNAL))
228 return (0);
229
230 def->cd_client = (ClientData) 1;
231 StackPush((ClientData) def, extDefStack);
232 (void) DBCellEnum(def, extDefPushFunc, (ClientData) 0);
233 return (0);
234 }
235
236 /*
237 * ----------------------------------------------------------------------------
238 *
239 * ExtUnique --
240 *
241 * For each cell in the subtree rooted at rootUse->cu_def, make
242 * sure that there are not two different nodes with the same label.
243 * If there are, we generate unique names by appending a numeric
244 * suffix to all but one of the offending labels.
245 * If "option" is 1 (tagged mode), then only labels ending in the
246 * character "#" are forced to be unique. If "option" is 2 ("noports"
247 * mode), then port labels are not forced to be unique. If "option"
248 * is 3 ("notopports" mode), then port labels on the top level are
249 * not forced to be unique. Finally, if the label has been changed
250 * and doesn't end in a '!', we leave feedback.
251 *
252 * Results:
253 * None.
254 *
255 * Side effects:
256 * May modify the label lists of some of the cells rooted
257 * at rootUse->cu_def, and mark the cells as CDMODIFIED.
258 * May also leave feedback.
259 *
260 * ----------------------------------------------------------------------------
261 */
262
263 void
ExtUnique(rootUse,option)264 ExtUnique(rootUse, option)
265 CellUse *rootUse;
266 int option;
267 {
268 CellDef *def;
269 int nwarn;
270 int locoption;
271
272 /* Make sure the entire subtree is read in */
273 if (DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox, TRUE))
274 {
275 TxError("Failure to read entire subtree of cell.\n");
276 return;
277 }
278
279 /* Fix up bounding boxes if they've changed */
280 DBFixMismatch();
281
282 /* Mark all defs as being unvisited */
283 (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0);
284
285 /* Recursively visit all defs in the tree and push on stack */
286 extDefStack = StackNew(100);
287 (void) extDefPushFunc(rootUse);
288
289 /* Now process all the cells we just found */
290 nwarn = 0;
291 while (def = (CellDef *) StackPop(extDefStack))
292 {
293 /* EXT_UNIQ_NOTOPPORTS: Use EXT_UNIQ_ALL on all cells other than the top */
294 if ((option == EXT_UNIQ_NOTOPPORTS) &&
295 (StackLook(extDefStack) != (ClientData)NULL))
296 locoption = EXT_UNIQ_ALL;
297 else
298 locoption = option;
299
300 def->cd_client = (ClientData) 0;
301 if (!SigInterruptPending)
302 nwarn += extUniqueCell(def, option);
303 }
304 StackFree(extDefStack);
305 if (nwarn)
306 TxError("%d uncorrected errors (see the feedback info)\n", nwarn);
307 }
308
309 /*
310 * ----------------------------------------------------------------------------
311 *
312 * ExtParents --
313 * ExtShowParents --
314 *
315 * ExtParents extracts the cell use->cu_def and all its parents.
316 * ExtShowParents merely finds and prints all the parents without
317 * extracting them.
318 *
319 * As in ExtAll, each cell is extracted to a file in the current
320 * directory whose name consists of the last part of the cell's path,
321 * with a .ext suffix.
322 *
323 * Results:
324 * None.
325 *
326 * Side effects:
327 * Creates a number of .ext files and writes to them.
328 * Adds feedback information where errors have occurred.
329 *
330 * ----------------------------------------------------------------------------
331 */
332
333 void
ExtParents(use)334 ExtParents(use)
335 CellUse *use;
336 {
337 extParents(use, TRUE);
338 }
339
340 void
ExtShowParents(use)341 ExtShowParents(use)
342 CellUse *use;
343 {
344 extParents(use, FALSE);
345 }
346
347 void
extParents(use,doExtract)348 extParents(use, doExtract)
349 CellUse *use;
350 bool doExtract; /* If TRUE, we extract; if FALSE, we print */
351 {
352 /* Mark all defs as being unvisited */
353 (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0);
354
355 /* Recursively visit all defs in the tree and push on stack */
356 extDefStack = StackNew(100);
357 extDefParentFunc(use->cu_def);
358
359 /* Now extract all the cells we just found */
360 extExtractStack(extDefStack, doExtract, (CellDef *) NULL);
361 StackFree(extDefStack);
362 }
363
364 /*
365 * Function to visit all the parents of 'def' and push them on
366 * extDefStack. We only push a def if it is unmarked, ie, its
367 * cd_client field is 0. After pushing a def, we mark it by
368 * setting its cd_client field to 1.
369 */
370
371 void
extDefParentFunc(def)372 extDefParentFunc(def)
373 CellDef *def;
374 {
375 CellUse *parent;
376
377 if (def->cd_client || (def->cd_flags&CDINTERNAL))
378 return;
379
380 def->cd_client = (ClientData) 1;
381 StackPush((ClientData) def, extDefStack);
382 for (parent = def->cd_parents; parent; parent = parent->cu_nextuse)
383 if (parent->cu_parent)
384 extDefParentFunc(parent->cu_parent);
385 }
386
387 /*
388 * ----------------------------------------------------------------------------
389 *
390 * ExtParentArea --
391 *
392 * ExtParentArea extracts the cell use->cu_def and each of its
393 * parents that contain geometry touching or overlapping the area
394 * of use->cu_def.
395 *
396 * Results:
397 * None.
398 *
399 * Side effects:
400 * Creates one or more .ext files and writes to them.
401 * Adds feedback information where errors have occurred.
402 *
403 * ----------------------------------------------------------------------------
404 */
405
406 void
ExtParentArea(use,changedArea,doExtract)407 ExtParentArea(use, changedArea, doExtract)
408 CellUse *use; /* Use->cu_def changed; extract its affected parents */
409 Rect *changedArea; /* Area changed in use->cu_def coordinates */
410 bool doExtract; /* If TRUE, we extract; if FALSE, we just print names
411 * of the cells we would extract.
412 */
413 {
414 Rect area;
415
416 /* Mark all defs as being unvisited */
417 (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0);
418
419 /*
420 * Recursively visit all defs in the tree
421 * and push on stack if they contain any geometry
422 * overlapping or touching the area 'changedArea'.
423 */
424 area = *changedArea;
425 area.r_xbot--, area.r_ybot--;
426 area.r_xtop++, area.r_ytop++;
427 extDefStack = StackNew(100);
428 extDefParentAreaFunc(use->cu_def, use->cu_def, (CellUse *) NULL, &area);
429
430 /* Now extract all the cells we just found */
431 extExtractStack(extDefStack, doExtract, (CellDef *) NULL);
432 StackFree(extDefStack);
433 }
434
435 /*
436 * Function to visit all the parents of 'def' and push them on
437 * extDefStack. We only push a def if it is unmarked, ie, its
438 * cd_client field is 0, and if it is either 'baseDef' or it
439 * contains geometry or other subcells in the area 'area'.
440 * We mark each def visited by setting cd_client to 1.
441 */
442
443 void
extDefParentAreaFunc(def,baseDef,allButUse,area)444 extDefParentAreaFunc(def, baseDef, allButUse, area)
445 CellDef *def;
446 CellDef *baseDef;
447 CellUse *allButUse;
448 Rect *area;
449 {
450 int x, y, xoff, yoff;
451 CellUse *parent;
452 Transform t, t2;
453 Rect parArea;
454
455 if (def->cd_client || (def->cd_flags&CDINTERNAL))
456 return;
457
458 if (def == baseDef || extContainsGeometry(def, allButUse, area))
459 {
460 def->cd_client = (ClientData) 1;
461 StackPush((ClientData) def, extDefStack);
462 }
463
464 for (parent = def->cd_parents; parent; parent = parent->cu_nextuse)
465 {
466 if (parent->cu_parent)
467 {
468 for (x = parent->cu_xlo; x <= parent->cu_xhi; x++)
469 {
470 for (y = parent->cu_ylo; y <= parent->cu_yhi; y++)
471 {
472 xoff = (x - parent->cu_xlo) * parent->cu_xsep;
473 yoff = (y - parent->cu_ylo) * parent->cu_ysep;
474 GeoTranslateTrans(&GeoIdentityTransform, xoff, yoff, &t);
475 GeoTransTrans(&t, &parent->cu_transform, &t2);
476 GeoTransRect(&t2, area, &parArea);
477 extDefParentAreaFunc(parent->cu_parent, baseDef,
478 parent, &parArea);
479 }
480 }
481 }
482 }
483 }
484
485 bool
extContainsGeometry(def,allButUse,area)486 extContainsGeometry(def, allButUse, area)
487 CellDef *def;
488 CellUse *allButUse;
489 Rect *area;
490 {
491 int extContainsPaintFunc();
492 bool extContainsCellFunc();
493 int pNum;
494
495 if (DBSrCellPlaneArea(def->cd_cellPlane, area,
496 extContainsCellFunc, (ClientData) allButUse))
497 return (TRUE);
498
499 for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
500 if (DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum],
501 area, &DBAllButSpaceBits,
502 extContainsPaintFunc, (ClientData) NULL))
503 return (TRUE);
504
505 return (FALSE);
506 }
507
508 bool
extContainsCellFunc(use,allButUse)509 extContainsCellFunc(use, allButUse)
510 CellUse *use;
511 CellUse *allButUse;
512 {
513 return (use != allButUse) ? TRUE : FALSE;
514 }
515
516 int
extContainsPaintFunc()517 extContainsPaintFunc()
518 {
519 return (1);
520 }
521
522 /*
523 * ----------------------------------------------------------------------------
524 *
525 * ExtIncremental --
526 *
527 * Starting at 'rootUse', extract all cell defs that have changed.
528 * Right now, we forcibly read in the entire tree before doing the
529 * extraction.
530 *
531 * Results:
532 * None.
533 *
534 * Side effects:
535 * Creates a number of .ext files and writes to them.
536 * Adds feedback information where errors have occurred.
537 *
538 * ----------------------------------------------------------------------------
539 */
540
541 void
ExtIncremental(rootUse)542 ExtIncremental(rootUse)
543 CellUse *rootUse;
544 {
545 /* Make sure the entire subtree is read in */
546 if (DBCellReadArea(rootUse, &rootUse->cu_def->cd_bbox, TRUE))
547 {
548 TxError("Failure to read entire subtree of cell.\n");
549 return;
550 }
551
552 /* Fix up bounding boxes if they've changed */
553 DBFixMismatch();
554
555 /* Update all timestamps */
556 DBUpdateStamps();
557
558 /* Mark all defs as being unvisited */
559 (void) DBCellSrDefs(0, extDefInitFunc, (ClientData) 0);
560
561 /*
562 * Recursively visit all defs in the tree
563 * and push on stack if they need extraction.
564 */
565 extDefStack = StackNew(100);
566 (void) extDefIncrementalFunc(rootUse);
567
568 /* Now extract all the cells we just found */
569 extExtractStack(extDefStack, TRUE, rootUse->cu_def);
570 StackFree(extDefStack);
571 }
572
573 /*
574 * Function to push each cell def on extDefStack if it hasn't
575 * already been pushed and if it needs re-extraction, and then
576 * recurse on all that def's children.
577 */
578
579 int
extDefIncrementalFunc(use)580 extDefIncrementalFunc(use)
581 CellUse *use;
582 {
583 CellDef *def = use->cu_def;
584
585 if (def->cd_client || (def->cd_flags&CDINTERNAL))
586 return (0);
587
588 def->cd_client = (ClientData) 1;
589 if (extTimestampMisMatch(def))
590 StackPush((ClientData) def, extDefStack);
591 (void) DBCellEnum(def, extDefIncrementalFunc, (ClientData) 0);
592 return (0);
593 }
594
595 /*
596 * Function returning TRUE if 'def' needs re-extraction.
597 * This will be the case if either the .ext file for 'def'
598 * does not exist, or if its timestamp fails to match that
599 * recorded in 'def'.
600 */
601
602 bool
extTimestampMisMatch(def)603 extTimestampMisMatch(def)
604 CellDef *def;
605 {
606 char line[256];
607 FILE *extFile;
608 bool ret = TRUE;
609 int stamp;
610 bool doLocal;
611
612 doLocal = (ExtOptions & EXT_DOLOCAL) ? TRUE : FALSE;
613
614 extFile = extFileOpen(def, (char *) NULL, "r", doLocal, (char **) NULL);
615 if (extFile == NULL)
616 return (TRUE);
617
618 if (fgets(line, sizeof line, extFile) == NULL) goto closeit;
619 if (sscanf(line, "timestamp %d", &stamp) != 1) goto closeit;
620 if (def->cd_timestamp != stamp) goto closeit;
621 ret = FALSE;
622
623 closeit:
624 (void) fclose(extFile);
625 return (ret);
626 }
627
628 /* Linked list structure to use to store the substrate plane from each */
629 /* extracted CellDef so that they can be returned to the original after */
630 /* extraction. */
631
632 struct saveList {
633 Plane *sl_plane;
634 CellDef *sl_def;
635 struct saveList *sl_next;
636 };
637
638 /*
639 * ----------------------------------------------------------------------------
640 *
641 * extExtractStack --
642 *
643 * If 'doExtract' is TRUE, call ExtCell for each def on the stack 'stack';
644 * otherwise, print the name of each def on the stack 'stack'.
645 * The root cell of the tree being processed is 'rootDef'; we only
646 * extract pathlength information for this cell.
647 *
648 * Results:
649 * None.
650 *
651 * Side effects:
652 * Leaves 'stack' empty.
653 * Calls ExtCell on each def on the stack if 'doExtract' is TRUE.
654 * Resets cd_client to 0 for each def on the stack.
655 * Prints the total number of errors and warnings.
656 *
657 * ----------------------------------------------------------------------------
658 */
659
660 void
extExtractStack(stack,doExtract,rootDef)661 extExtractStack(stack, doExtract, rootDef)
662 Stack *stack;
663 CellDef *rootDef;
664 {
665 int fatal = 0, warnings = 0;
666 bool first = TRUE;
667 Plane *savePlane;
668 CellDef *def;
669 struct saveList *newsl, *sl = (struct saveList *)NULL;
670
671 while (def = (CellDef *) StackPop(stack))
672 {
673 def->cd_client = (ClientData) 0;
674 if (!SigInterruptPending)
675 {
676 if (doExtract)
677 {
678 savePlane = ExtCell(def, (char *) NULL, (def == rootDef));
679 if (savePlane != NULL)
680 {
681 newsl = (struct saveList *)mallocMagic(sizeof(struct saveList));
682 newsl->sl_plane = savePlane;
683 newsl->sl_def = def;
684 newsl->sl_next = sl;
685 sl = newsl;
686 }
687
688 fatal += extNumFatal;
689 warnings += extNumWarnings;
690 }
691 else
692 {
693 if (!first) TxPrintf(", ");
694 TxPrintf("%s", def->cd_name);
695 TxFlush();
696 first = FALSE;
697 }
698 }
699 }
700
701 /* Replace any modified substrate planes */
702 for (; sl; sl = sl->sl_next)
703 {
704 ExtRevertSubstrate(sl->sl_def, sl->sl_plane);
705 // DBFreePaintPlane(sl->sl_plane);
706 // TiFreePlane(sl->sl_plane);
707
708 freeMagic(sl);
709 }
710
711 if (!doExtract)
712 {
713 TxPrintf("\n");
714 }
715 else
716 {
717 if (fatal > 0)
718 TxError("Total of %d error%s (check feedback entries).\n",
719 fatal, fatal != 1 ? "s" : "");
720 if (warnings > 0)
721 TxError("Total of %d warning%s.\n",
722 warnings, warnings != 1 ? "s" : "");
723 }
724 }
725