1 /*
2 * CalmaRead.c --
3 *
4 * Input of Calma GDS-II stream format.
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/calma/CalmaRead.c,v 1.3 2010/06/24 12:37:15 tim Exp $";
21 #endif /* not lint */
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27
28 #include <netinet/in.h>
29
30 #include "utils/magic.h"
31 #include "utils/geometry.h"
32 #include "tiles/tile.h"
33 #include "utils/utils.h"
34 #include "utils/hash.h"
35 #include "database/database.h"
36 #include "database/databaseInt.h"
37 #include "utils/malloc.h"
38 #include "utils/tech.h"
39 #include "cif/cif.h"
40 #include "cif/CIFint.h"
41 #include "cif/CIFread.h"
42 #include "utils/signals.h"
43 #include "windows/windows.h"
44 #include "dbwind/dbwind.h"
45 #include "utils/styles.h"
46 #include "textio/textio.h"
47 #include "calma/calmaInt.h"
48 #include "commands/commands.h" /* for CmdGetRootPoint */
49 #include "utils/main.h" /* for EditCellUse */
50 #include "utils/undo.h"
51
52 /* Globals for Calma reading */
53 FILE *calmaInputFile = NULL; /* Read from this stream */
54 FILE *calmaErrorFile = NULL; /* Write error output here */
55 bool CalmaSubcellPolygons = FALSE; /* Put non-Manhattan polygons
56 * in their own subcells.
57 */
58 int CalmaPolygonCount;
59 bool CalmaSubcellPaths = FALSE; /* Put paths in their own subcells. */
60 int CalmaPathCount;
61 bool CalmaFlattenUses = FALSE; /* If TRUE, small cells in the input
62 * stream are flattened when encountered
63 * as uses. This improves magic's
64 * performance when handling contacts
65 * saved as subcell arrays.
66 */
67 char **CalmaFlattenUsesByName = NULL; /* NULL-terminated list of strings
68 * to do glob-style pattern matching
69 * to determine what cells to flatten
70 * by cellname.
71 */
72 bool CalmaReadOnly = FALSE; /* Set files to read-only and
73 * retain file position information
74 * so cells can be written verbatim.
75 */
76 bool CalmaNoDRCCheck = FALSE; /* If TRUE, don't mark cells as needing
77 * a DRC check; they will be assumed
78 * DRC clean.
79 */
80 bool CalmaPostOrder = FALSE; /* If TRUE, forces the GDS parser to
81 * read cells in post-order. It is
82 * necessary, e.g., when we need to
83 * flatten cells that are contact cuts.
84 * Added by Nishit 8/16/2004
85 */
86 bool CalmaNoDuplicates = FALSE; /* If TRUE, then if a cell exists in
87 * memory with the same name as a cell
88 * in the GDS file, then the cell in
89 * the GDS file is skipped.
90 */
91 bool CalmaUnique = FALSE; /* If TRUE, then if a cell exists in
92 * memory with the same name as a cell
93 * in the GDS file, then the cell in
94 * memory is renamed to a unique
95 * identifier with a _N suffix.
96 */
97 extern void calmaUnexpected();
98 extern int calmaWriteInitFunc();
99
100 bool calmaParseUnits();
101
102 /*
103 * Scaling.
104 * Multiply all coordinates by calmaReadScale1, then divide them
105 * by calmaReadScale2 in order to get coordinates in centimicrons.
106 */
107 int calmaReadScale1;
108 int calmaReadScale2;
109
110 int calmaTotalErrors;
111
112 /*
113 * Lookahead: calmaLApresent is TRUE when calmaLAnbytes and calmaLArtype
114 * are set to the record header of a record we just ungot.
115 */
116 bool calmaLApresent; /* TRUE if lookahead input waiting */
117 int calmaLAnbytes; /* # bytes in record (from header) */
118 int calmaLArtype; /* Record type */
119
120 /*
121 * Hash table for errors, indexed by (layer, datatype).
122 * The corresponding entry in this table is created whenever
123 * a (layer, datatype) is seen that we don't recognize, so
124 * we don't output an error message more than once.
125 */
126 HashTable calmaLayerHash;
127
128 /*
129 * Hash table to keep track of all defs that have appeared
130 * in this file. Indexed by cell def name.
131 */
132 HashTable calmaDefInitHash;
133
134 /* Common stuff to ignore */
135 int calmaElementIgnore[] = { CALMA_ELFLAGS, CALMA_PLEX, -1 };
136
137 /*
138 * ----------------------------------------------------------------------------
139 *
140 * CalmaReadFile --
141 *
142 * Read an entire GDS-II stream format library from the open FILE 'file'.
143 *
144 * Results:
145 * None.
146 *
147 * Side effects:
148 * May modify the contents of cifReadCellDef by painting or adding
149 * new uses or labels. May also create new CellDefs.
150 *
151 * ----------------------------------------------------------------------------
152 */
153
154 void
CalmaReadFile(file,filename)155 CalmaReadFile(file, filename)
156 FILE *file; /* File from which to read Calma */
157 char *filename; /* The real name of the file read */
158 {
159 int k, version;
160 char *libname = NULL;
161 MagWindow *mw;
162 static int hdrSkip[] = { CALMA_FORMAT, CALMA_MASK, CALMA_ENDMASKS,
163 CALMA_REFLIBS, CALMA_FONTS, CALMA_ATTRTABLE,
164 CALMA_STYPTABLE, CALMA_GENERATIONS, -1 };
165 static int skipBeforeLib[] = { CALMA_LIBDIRSIZE, CALMA_SRFNAME,
166 CALMA_LIBSECUR, -1 };
167
168 if (EditCellUse == (CellUse *)NULL)
169 {
170 TxError("Cannot read GDS: There is no edit cell.\n");
171 return;
172 }
173
174 /* We will use full cell names as keys in this hash table */
175 CIFReadCellInit(0);
176
177 if (CIFWarningLevel == CIF_WARN_REDIRECT)
178 {
179 if (CIFErrorFilename == NULL)
180 calmaErrorFile = NULL;
181 else
182 calmaErrorFile = PaOpen(CIFErrorFilename, "w", (char *)NULL, ".",
183 (char *)NULL, (char **)NULL);
184 }
185
186 if (cifCurReadStyle == NULL)
187 {
188 TxError("Don't know how to read GDS-II:\n");
189 TxError("Nothing in \"cifinput\" section of tech file.\n");
190 return;
191 }
192 TxPrintf("Warning: Calma reading is not undoable! I hope that's OK.\n");
193 UndoDisable();
194
195 calmaTotalErrors = 0;
196 CalmaPolygonCount = 0;
197 CalmaPathCount = 0;
198
199 /* Reset cd_client pointers (using init function from CalmaWrite.c) */
200 /* This is in case a cell already in memory is being referenced; */
201 /* it is probably better to avoid those kinds of naming collisions */
202 /* though. . . */
203 (void) DBCellSrDefs(0, calmaWriteInitFunc, (ClientData) NULL);
204
205 HashInit(&calmaDefInitHash, 32, 0);
206 calmaLApresent = FALSE;
207 calmaInputFile = file;
208
209 /* Read the GDS-II header */
210 if (!calmaReadI2Record(CALMA_HEADER, &version)) goto done;
211 if (version < 600)
212 TxPrintf("Library written using GDS-II Release %d.0\n", version);
213 else
214 TxPrintf("Library written using GDS-II Release %d.%d\n",
215 version / 100, version % 100);
216 if (!calmaSkipExact(CALMA_BGNLIB)) goto done;
217 calmaSkipSet(skipBeforeLib);
218 if (!calmaReadStringRecord(CALMA_LIBNAME, &libname)) goto done;
219 if ((libname != NULL) && (libname[0] != '\0'))
220 {
221 /* Avoid generating a magic name with spaces in it. . . */
222 /* (added by Mike Godfrey, 7/17/05) */
223
224 for (k = 0; k < strlen(libname); k++)
225 if (libname[k] == ' ')
226 libname[k] = '_';
227 TxPrintf("Library name: %s\n", libname);
228 }
229
230 /* Skip the reflibs, fonts, etc. cruft */
231 calmaSkipSet(hdrSkip);
232
233 /* Set the scale factors */
234 if (!calmaParseUnits()) goto done;
235
236 /* Main body of GDS-II input */
237 while (calmaParseStructure(filename))
238 if (SigInterruptPending)
239 goto done;
240 (void) calmaSkipExact(CALMA_ENDLIB);
241
242 done:
243
244 /* Added by Nishit, Sept. 2004---Load cell read from GDS */
245 /* stream file to the magic layout window. If this fails */
246 /* then we do the original action and don't do a load into */
247 /* the window. Note that this follows the Magic GDS output */
248 /* convention of giving the library the name of the */
249 /* top-level cell, so magic-produced GDS can be read back */
250 /* with the expected cell appearing in the layout window. */
251
252 if (libname != NULL)
253 {
254 mw = CmdGetRootPoint((Point *)NULL, (Rect *)NULL);
255 if (mw == NULL)
256 windCheckOnlyWindow(&mw, DBWclientID);
257 if (mw != NULL)
258 {
259 if (calmaLookCell(libname, NULL) != (CellDef *)NULL)
260 DBWloadWindow(mw, libname, 0);
261 }
262 freeMagic(libname);
263 }
264
265 CIFReadCellCleanup(FILE_CALMA);
266 HashKill(&calmaDefInitHash);
267 UndoEnable();
268
269 if (calmaErrorFile != NULL) fclose(calmaErrorFile);
270 }
271
272 /*
273 * ----------------------------------------------------------------------------
274 *
275 * calmaParseUnits --
276 *
277 * Process the CALMA_UNITS record that sets the relationship between
278 * user units (stored in the stream file) and centimicrons.
279 *
280 * Results:
281 * TRUE if successful, FALSE if we encountered an error and
282 * the caller should abort.
283 *
284 * Side effects:
285 * Consumes input.
286 * Sets calmaReadScale1 to the number of centimicrons per user
287 * unit, and calmaReadScale2 to 1, unless calmaReadScale1 would be
288 * less than 1, in which case we set calmaReadScale1 to 1 and
289 * calmaReadScale2 to 1/calmaReadScale1.
290 *
291 * NOTE:
292 * We don't care about user units, only database units. The
293 * GDS-II stream specifies the number of meters per database
294 * unit, which we use to compute the number of centimicrons
295 * per database unit. Since database units are floating point,
296 * there is a possibility of roundoff unless the number of
297 * centimicrons per user unit is an integer value.
298 *
299 * ----------------------------------------------------------------------------
300 */
301
302 bool
calmaParseUnits()303 calmaParseUnits()
304 {
305 int nbytes, rtype;
306 double metersPerDBUnit;
307 double userUnitsPerDBUnit;
308 double cuPerDBUnit;
309
310 READRH(nbytes, rtype);
311 #ifdef lint
312 nbytes = nbytes;
313 #endif /* lint */
314
315 if (rtype != CALMA_UNITS)
316 {
317 calmaUnexpected(CALMA_UNITS, rtype);
318 return (FALSE);
319 }
320
321 /* Skip user units per database unit */
322 if (!calmaReadR8(&userUnitsPerDBUnit)) return (FALSE);
323
324 /* Read meters per database unit */
325 if (!calmaReadR8(&metersPerDBUnit)) return (FALSE);
326
327 #ifdef notdef
328 TxPrintf("1 database unit equals %e user units\n", userUnitsPerDBUnit);
329 TxPrintf("1 database unit equals %e meters\n", metersPerDBUnit);
330 TxPrintf("1 user unit equals %e database units\n", 1.0/userUnitsPerDBUnit);
331 TxPrintf("1 meter equals %e database units\n", 1.0/metersPerDBUnit);
332 #endif /* notdef */
333
334 /* Meters per database unit (1.0e8 corresponds to traditional centimicrons) */
335 cuPerDBUnit = metersPerDBUnit * 1.0e8 * cifCurReadStyle->crs_multiplier;
336
337 /*
338 * Multiply database units by calmaReadScale1, then divide
339 * by calmaReadScale2 to get CIF units. The current scheme
340 * relies entirely on calmaReadScale1 being an integer.
341 */
342 if (cuPerDBUnit >= 1.0)
343 {
344 calmaReadScale1 = (int)(cuPerDBUnit + 0.5);
345 calmaReadScale2 = 1;
346 }
347 else
348 {
349 cuPerDBUnit = 1.0 / cuPerDBUnit;
350 calmaReadScale1 = 1;
351 calmaReadScale2 = (int)(cuPerDBUnit + 0.5);
352 }
353 #ifdef notdef
354 TxPrintf("All units to be scaled by %d/%d\n", calmaReadScale1, calmaReadScale2);
355 #endif /* notdef */
356
357 return (TRUE);
358 }
359
360 /*
361 * ----------------------------------------------------------------------------
362 *
363 * CalmaReadError --
364 *
365 * This procedure is called to print out error messages during
366 * Calma file reading.
367 *
368 * Results:
369 * None.
370 *
371 * Side effects:
372 * An error message is printed.
373 *
374 * Note:
375 * You can add more arguments if 10 turns out not to be enough.
376 *
377 * ----------------------------------------------------------------------------
378 */
379
380 void
381 /*VARARGS1*/
CalmaReadError(format,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)382 CalmaReadError(format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
383 char *format;
384 char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9, *a10;
385 {
386 off_t filepos;
387
388 calmaTotalErrors++;
389 if (CIFWarningLevel == CIF_WARN_NONE) return;
390
391 if ((calmaTotalErrors < 100) || (CIFWarningLevel != CIF_WARN_LIMIT))
392 {
393 filepos = ftello(calmaInputFile);
394
395 if (CIFWarningLevel == CIF_WARN_REDIRECT)
396 {
397 if (calmaErrorFile != NULL)
398 {
399 fprintf(calmaErrorFile, "Error while reading cell \"%s\" ",
400 cifReadCellDef->cd_name);
401 fprintf(calmaErrorFile, "(byte position %"DLONG_PREFIX"d): ",
402 (dlong)filepos);
403 fprintf(calmaErrorFile, format, a1, a2, a3, a4, a5, a6, a7,
404 a8, a9, a10);
405 }
406 }
407 else
408 {
409 TxError("Error while reading cell \"%s\" ", cifReadCellDef->cd_name);
410 TxError("(byte position %"DLONG_PREFIX"d): ", (dlong)filepos);
411 TxError(format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
412 }
413 }
414 else if ((calmaTotalErrors == 100) && (CIFWarningLevel == CIF_WARN_LIMIT))
415 {
416 TxError("Error limit set: Remaining errors will not be reported.\n");
417 }
418 }
419
420 /*
421 * ----------------------------------------------------------------------------
422 *
423 * calmaUnexpected --
424 *
425 * Complain about a record where we expected one kind but got another.
426 *
427 * Results:
428 * None.
429 *
430 * Side effects:
431 * Prints an error message.
432 *
433 * ----------------------------------------------------------------------------
434 */
435
436 void
calmaUnexpected(wanted,got)437 calmaUnexpected(wanted, got)
438 int wanted; /* Type of record we wanted */
439 int got; /* Type of record we got */
440 {
441 CalmaReadError("Unexpected record type in input: \n");
442
443 if (CIFWarningLevel == CIF_WARN_NONE) return;
444 if (calmaTotalErrors < 100 || (CIFWarningLevel != CIF_WARN_LIMIT))
445 {
446 if (CIFWarningLevel == CIF_WARN_REDIRECT)
447 {
448 if (calmaErrorFile != NULL)
449 {
450 fprintf(calmaErrorFile," Expected %s record ",
451 calmaRecordName(wanted));
452 fprintf(calmaErrorFile, "but got %s.\n", calmaRecordName(got));
453 }
454 }
455 else
456 {
457 TxError(" Expected %s record ", calmaRecordName(wanted));
458 TxError("but got %s.\n", calmaRecordName(got));
459 }
460 }
461 }
462
463 /*
464 * ----------------------------------------------------------------------------
465 *
466 * calmaRecordName --
467 *
468 * Return a pointer to the printable name of a CALMA record type.
469 *
470 * Results:
471 * See above.
472 *
473 * Side effects:
474 * May overwrite the string we returned on the previous call.
475 *
476 * ----------------------------------------------------------------------------
477 */
478
479 char *
calmaRecordName(rtype)480 calmaRecordName(rtype)
481 int rtype;
482 {
483 static char numeric[10];
484 static char *calmaRecordNames[] =
485 {
486 "HEADER", "BGNLIB", "LIBNAME", "UNITS",
487 "ENDLIB", "BGNSTR", "STRNAME", "ENDSTR",
488 "BOUNDARY", "PATH", "SREF", "AREF",
489 "TEXT", "LAYER", "DATATYPE", "WIDTH",
490 "XY", "ENDEL", "SNAME", "COLROW",
491 "TEXTNODE", "NODE", "TEXTTYPE", "PRESENTATION",
492 "SPACING", "STRING", "STRANS", "MAG",
493 "ANGLE", "UINTEGER", "USTRING", "REFLIBS",
494 "FONTS", "PATHTYPE", "GENERATIONS", "ATTRTABLE",
495 "STYPTABLE", "STRTYPE", "ELFLAGS", "ELKEY",
496 "LINKTYPE", "LINKKEYS", "NODETYPE", "PROPATTR",
497 "PROPVALUE", "BOX", "BOXTYPE", "PLEX",
498 "BGNEXTN", "ENDEXTN", "TAPENUM", "TAPECODE",
499 "STRCLASS", "RESERVED", "FORMAT", "MASK",
500 "ENDMASKS"
501 };
502
503 if (rtype < 0 || rtype >= CALMA_NUMRECORDTYPES)
504 {
505 (void) sprintf(numeric, "%d", rtype);
506 return (numeric);
507 }
508
509 return (calmaRecordNames[rtype]);
510 }
511
512 /*
513 * ----------------------------------------------------------------------------
514 *
515 * CalmaTechInit --
516 *
517 * Prepare for a technology file.
518 *
519 * Results:
520 * None.
521 *
522 * Side effects:
523 * Error checking.
524 *
525 * ----------------------------------------------------------------------------
526 */
527
528 void
CalmaTechInit()529 CalmaTechInit()
530 {
531 ASSERT(sizeof(FourByteInt)==4, "definition in calmaInt.h");
532 ASSERT(sizeof(TwoByteInt)==2, "definition in calmaInt.h");
533 }
534