1 /* CIFmain.c -
2  *
3  *	This file contains global information for the CIF module,
4  *	such as performance statistics.
5  *
6  *     *********************************************************************
7  *     * Copyright (C) 1985, 1990 Regents of the University of California. *
8  *     * Permission to use, copy, modify, and distribute this              *
9  *     * software and its documentation for any purpose and without        *
10  *     * fee is hereby granted, provided that the above copyright          *
11  *     * notice appear in all copies.  The University of California        *
12  *     * makes no representations about the suitability of this            *
13  *     * software for any purpose.  It is provided "as is" without         *
14  *     * express or implied warranty.  Export of this software outside     *
15  *     * of the United States of America may require an export license.    *
16  *     *********************************************************************
17  */
18 
19 #ifndef lint
20 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFmain.c,v 1.3 2009/01/15 15:44:34 tim Exp $";
21 #endif  /* not lint */
22 
23 #include <stdio.h>
24 #include <string.h>
25 
26 #include "tcltk/tclmagic.h"
27 #include "utils/magic.h"
28 #include "utils/geometry.h"
29 #include "tiles/tile.h"
30 #include "utils/hash.h"
31 #include "database/database.h"
32 #include "cif/CIFint.h"
33 #include "textio/textio.h"
34 #include "windows/windows.h"
35 #include "dbwind/dbwind.h"
36 #include "utils/styles.h"
37 
38 /* The following points to a list of all the CIF output styles
39  * currently understood:
40  */
41 
42 CIFKeep *CIFStyleList;
43 
44 /* The current style being used for CIF output: */
45 
46 CIFStyle *CIFCurStyle = NULL;
47 
48 /* The following are statistics gathered at various points in
49  * CIF processing.  There are two versions of each statistic:
50  * a total number, and the number since stats were last printed.
51  */
52 
53 int CIFTileOps = 0;		/* Total tiles touched in geometrical
54 				 * operations.
55 				 */
56 int CIFHierTileOps = 0;		/* Tiles touched in geometrical operations
57 				 * as part of hierarchical processing.
58 				 */
59 int CIFRects = 0;		/* Total CIF rectangles output. */
60 int CIFHierRects = 0;		/* Rectangles stemming from interactions. */
61 
62 static int cifTotalTileOps = 0;
63 static int cifTotalHierTileOps = 0;
64 static int cifTotalRects = 0;
65 static int cifTotalHierRects = 0;
66 
67 /* This file provides several procedures for dealing with errors during
68  * the CIF generation process.  Low-level CIF artwork-manipulation
69  * procedures call CIFError without knowing what cell CIF is being
70  * generated for, or what layer is being generated.  Higher-level
71  * routines are responsible for recording that information in the
72  * variables below so that CIFError can output meaningful diagnostics
73  * using the feedback mechanism.
74  */
75 
76 global CellDef *CIFErrorDef;	/* Definition in which to record errors. */
77 global int CIFErrorLayer;	/* Index of CIF layer associated with errors.*/
78 
79 
80 /*
81  * ----------------------------------------------------------------------------
82  *
83  * CIFPrintStats --
84  *
85  * 	This procedure prints out CIF statistics including both
86  *	total values and counts since the last printing.
87  *
88  * Results:
89  *	None.
90  *
91  * Side effects:
92  *	Several messages are printed.
93  *
94  * ----------------------------------------------------------------------------
95  */
96 
97 void
CIFPrintStats()98 CIFPrintStats()
99 {
100     TxPrintf("CIF statistics (recent/total):\n");
101     cifTotalTileOps += CIFTileOps;
102     TxPrintf("    Geometrical tile operations: %d/%d\n",
103 	CIFTileOps, cifTotalTileOps);
104     CIFTileOps = 0;
105     cifTotalHierTileOps += CIFHierTileOps;
106     TxPrintf("    Tile operations for hierarchy: %d/%d\n",
107 	CIFHierTileOps, cifTotalHierTileOps);
108     CIFHierTileOps = 0;
109     cifTotalRects += CIFRects;
110     TxPrintf("    CIF rectangles output: %d/%d\n",
111 	CIFRects, cifTotalRects);
112     CIFRects = 0;
113     cifTotalHierRects += CIFHierRects;
114     TxPrintf("    CIF rectangles due to hierarchical interactions: %d/%d\n",
115 	CIFHierRects, cifTotalHierRects);
116     CIFHierRects = 0;
117 }
118 
119 /*
120  * ----------------------------------------------------------------------------
121  *
122  * CIFGetOutputScale --
123  *
124  *	This routine is given here so that the CIF output scale can be
125  *	accessed from the "commands" directory source without declaring
126  *	external references to CIF global variables.
127  *
128  * Results:
129  *	Internal units-to-(nanometers * convert) conversion factor (float).
130  *	Use convert = 1000 for centimicrons-to-microns conversion
131  *
132  * Side effects:
133  *	None.
134  *
135  * ----------------------------------------------------------------------------
136  */
137 
138 float
CIFGetOutputScale(convert)139 CIFGetOutputScale(convert)
140    int convert;
141 {
142     if (CIFCurStyle == NULL) return 1.0;
143 
144     return ((float)(10 * CIFCurStyle->cs_scaleFactor) /
145 		(float)(CIFCurStyle->cs_expander * convert));
146 }
147 
148 /*
149  * ----------------------------------------------------------------------------
150  *
151  * CIFGetScale --
152  *
153  *  Same as the above routine, but provides the scalefactor to get CIF
154  *  units from centimicrons (which generally means just returning the
155  *  expander value to show if units have been declared in nanometers or
156  *  angstroms).
157  *
158  * ----------------------------------------------------------------------------
159  */
160 
161 float
CIFGetScale(convert)162 CIFGetScale(convert)
163    int convert;
164 {
165     if (CIFCurStyle == NULL) return 1.0;
166 
167     return (1.0 / (float)(CIFCurStyle->cs_expander * convert));
168 }
169 
170 /*
171  * ----------------------------------------------------------------------------
172  *
173  * CIFPrintStyle --
174  *
175  * 	This procedure prints the current CIF output style or list
176  *	of known styles.
177  *
178  * Results:
179  *	None.
180  *
181  * Side effects:
182  *	Output.
183  *
184  * ----------------------------------------------------------------------------
185  */
186 
187 void
CIFPrintStyle(dolist,doforall,docurrent)188 CIFPrintStyle(dolist, doforall, docurrent)
189     bool dolist;		/* Return as a list if true */
190     bool doforall;		/* Print all known styles if true */
191     bool docurrent;		/* Print current style if true */
192 {
193     CIFKeep *style;
194 
195     if (docurrent)
196     {
197 	if (CIFCurStyle == NULL)
198 	    TxError("Error: No style is set\n");
199 	else
200 	{
201 	    if (!dolist) TxPrintf("The current style is \"");
202 #ifdef MAGIC_WRAPPER
203 	    if (dolist)
204 		Tcl_SetResult(magicinterp, CIFCurStyle->cs_name, NULL);
205 	    else
206 #endif
207 	    TxPrintf("%s",  CIFCurStyle->cs_name);
208 	    if (!dolist) TxPrintf("\".\n");
209 	}
210     }
211 
212     if (doforall)
213     {
214 	if (!dolist) TxPrintf("The CIF output styles are: ");
215 
216 	for (style = CIFStyleList; style != NULL; style = style->cs_next)
217 	{
218 	    if (dolist)
219 	    {
220 #ifdef MAGIC_WRAPPER
221 		Tcl_AppendElement(magicinterp, style->cs_name);
222 #else
223 		if (style != CIFStyleList) TxPrintf(" ");
224 		TxPrintf("%s", style->cs_name);
225 #endif
226 	    }
227 	    else
228 	    {
229 		if (style != CIFStyleList) TxPrintf(", ");
230 		TxPrintf("%s", style->cs_name);
231 	    }
232 	}
233 	if (!dolist) TxPrintf(".\n");
234     }
235 }
236 
237 
238 /*
239  * ----------------------------------------------------------------------------
240  *
241  * CIFSetStyle --
242  *
243  * 	This procedure changes the current CIF output style to the one
244  *	named by the parameter.
245  *
246  * Results:
247  *	None.
248  *
249  * Side effects:
250  *	The current CIF style is changed.  If the name doesn't match,
251  *	or is ambiguous, then a list of all CIF styles is output.
252  *
253  * ----------------------------------------------------------------------------
254  */
255 
256 void
CIFSetStyle(name)257 CIFSetStyle(name)
258     char *name;			/* Name of the new style.  If NULL, just
259 				 * print out the valid styles.
260 				 */
261 {
262     CIFKeep *style, *match, *exactmatch;
263     bool ambiguous = FALSE;
264     int length;
265 
266     if (name == NULL) return;
267 
268     match = NULL;
269     length = strlen(name);
270 
271     for (style = CIFStyleList; style != NULL; style = style->cs_next)
272     {
273 	if (!strcmp(name, style->cs_name)) {
274 	    match = style;
275 	    ambiguous = FALSE;
276 	    break;
277 	}
278 	else if (!strncmp(name, style->cs_name, length))
279 	{
280 	    if (match != NULL) ambiguous = TRUE;
281 	    match = style;
282 	}
283     }
284 
285     if (ambiguous)
286     {
287 	TxError("CIF output style \"%s\" is ambiguous.\n", name);
288 	CIFPrintStyle(FALSE, TRUE, TRUE);
289 	return;
290     }
291 
292     if (match != NULL)
293     {
294 	CIFLoadStyle(match->cs_name);
295 	TxPrintf("CIF output style is now \"%s\"\n", name);
296 	return;
297     }
298 
299     TxError("\"%s\" is not one of the CIF output styles Magic knows.\n", name);
300     CIFPrintStyle(FALSE, TRUE, TRUE);
301 }
302 
303 /*
304  * ----------------------------------------------------------------------------
305  *
306  * CIFNameToMask --
307  *
308  * 	Finds the CIF planes for a given name.
309  *
310  * Results:
311  *	Returns TRUE on success, or FALSE if "name" failed to match any layers.
312  *
313  * Side effects:
314  *	If there's no match, then an error message is output.
315  *	The sets 'result' to be all types containing the CIF layer named
316  *	"name".  The current CIF style is used for the lookup. If "depend"
317  *	is non-NULL, then it is filled with the mask of all layers on which
318  *	the named layer depends.
319  * ----------------------------------------------------------------------------
320  */
321 
322 bool
CIFNameToMask(name,result,depend)323 CIFNameToMask(name, result, depend)
324     char *name;
325     TileTypeBitMask *result;
326     TileTypeBitMask *depend;
327 {
328     int i, j;
329     CIFOp *op;
330     CIFLayer *cl;
331 
332     if (!CIFCurStyle)
333     {
334 	TxError("No CIF output style set!\n");
335 	return FALSE;
336     }
337 
338     TTMaskZero(result);
339     for (i = 0; i < CIFCurStyle->cs_nLayers; i++)
340 	if (strcmp(name, CIFCurStyle->cs_layers[i]->cl_name) == 0)
341 	    TTMaskSetType(result, i);
342 
343     if (!TTMaskEqual(result, &DBZeroTypeBits))
344     {
345 	/* This loop depends on the fact that templayers must	*/
346 	/* be declared in order of dependency;  that is, you	*/
347 	/* can't use a layer before it is declared.  Thus, the	*/
348 	/* dependent layers will always be filled in from layer	*/
349 	/* i back to zero.					*/
350 
351 	if (depend)
352  	{
353 	    TTMaskZero(depend);
354 	    TTMaskSetMask(depend, result);
355 	    for (j = CIFCurStyle->cs_nLayers - 1; j >= 0; j--)
356 		if (TTMaskHasType(depend, j))
357 		{
358 		    cl = CIFCurStyle->cs_layers[j];
359 		    for (op = cl->cl_ops; op != NULL; op = op->co_next)
360 		    {
361 			TTMaskSetMask(depend, &op->co_cifMask);
362 
363 			/* Bloat layers may depend on CIF layers    */
364 			/* Currently supported only with bloat-all  */
365 
366 			if (op->co_opcode == CIFOP_BLOATALL)
367 			{
368 		            BloatData *bloats = (BloatData *)op->co_client;
369 			    TileType ttype;
370 
371 			    if (bloats->bl_plane < 0)	 /* Use CIF types */
372 		                for (ttype = 0; ttype < TT_MAXTYPES; ttype++)
373 		                    if (bloats->bl_distance[ttype] > 0)
374 					TTMaskSetType(depend, ttype);
375 			}
376 		    }
377 		}
378 	}
379 	return TRUE;
380     }
381 
382     TxError("CIF name \"%s\" doesn't exist in style \"%s\".\n", name,
383 	CIFCurStyle->cs_name);
384     TxError("The valid CIF layer names are: ");
385     for (i = 0; i < CIFCurStyle->cs_nLayers; i++)
386     {
387 	if (i == 0)
388 	    TxError("%s", CIFCurStyle->cs_layers[i]->cl_name);
389 	else
390 	    TxError(", %s", CIFCurStyle->cs_layers[i]->cl_name);
391     }
392     TxError(".\n");
393     return FALSE;
394 }
395 
396 /*
397  * ----------------------------------------------------------------------------
398  *
399  * CIFError --
400  *
401  * 	This procedure is called by low-level CIF generation routines
402  *	when a problem is encountered in generating CIF.  This procedure
403  *	notes the problem using the feedback mechanism.
404  *
405  * Results:
406  *	None.
407  *
408  * Side effects:
409  *	Feedback information is added.  The caller must have set CIFErrorDef
410  *	to point to the cell definition that area refers to.  If CIFErrorDef
411  *	is NULL, then errors are ignored.
412  *
413  * ----------------------------------------------------------------------------
414  */
415 
416 void
CIFError(area,message)417 CIFError(area, message)
418     Rect *area;			/* Place in CIFErrorDef where there was a
419 				 * problem in generating CIFErrorLayer.
420 				 */
421     char *message;		/* Short note about what went wrong. */
422 {
423     char msg[200];
424 
425     if (CIFCurStyle->cs_flags & CWF_NO_ERRORS) return;
426 
427     if (CIFErrorDef == (NULL)) return;
428     (void) sprintf(msg, "CIF error in cell %s, layer %s: %s",
429 	CIFErrorDef->cd_name, CIFCurStyle->cs_layers[CIFErrorLayer]->cl_name,
430 	message);
431     DBWFeedbackAdd(area, msg, CIFErrorDef, CIFCurStyle->cs_scaleFactor,
432 	STYLE_PALEHIGHLIGHTS);
433 }
434 
435 /*
436  * ----------------------------------------------------------------------------
437  *
438  * CIFOutputScaleFactor --
439  *
440  * 	Returns current conversion factor between CIF units and
441  *	Magic units.
442  *
443  * Results:
444  *	The return value is the number of centimicrons per Magic
445  *	unit in the current CIF output style.  If there is no
446  *	known CIF output style, 1 is returned.
447  *
448  * Side effects:
449  *	None.
450  *
451  * ----------------------------------------------------------------------------
452  */
453 
454 int
CIFOutputScaleFactor()455 CIFOutputScaleFactor()
456 {
457     if (CIFCurStyle == NULL) return 1;
458     return CIFCurStyle->cs_scaleFactor;
459 }
460