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