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