1 /*
2 * ExtCell.c --
3 *
4 * Circuit extraction.
5 * Extract a single cell.
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/ExtCell.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 #include <string.h>
27
28 #include "utils/magic.h"
29 #include "utils/geometry.h"
30 #include "utils/styles.h"
31 #include "tiles/tile.h"
32 #include "utils/hash.h"
33 #include "database/database.h"
34 #include "utils/malloc.h"
35 #include "textio/textio.h"
36 #include "debug/debug.h"
37 #include "extract/extract.h"
38 #include "extract/extractInt.h"
39 #include "utils/signals.h"
40 #include "utils/stack.h"
41 #include "utils/utils.h"
42 #include "windows/windows.h"
43 #include "utils/main.h"
44 #include "utils/undo.h"
45
46 /* --------------------------- Global data ---------------------------- */
47
48 /*
49 * Value normally present in ti_client to indicate tiles that have not
50 * been marked with their associated region.
51 */
52 ClientData extUnInit = (ClientData) CLIENTDEFAULT;
53
54
55 /* ------------------------ Data local to this file ------------------- */
56
57 /* Forward declarations */
58 int extOutputUsesFunc();
59 FILE *extFileOpen();
60
61 Plane* extCellFile();
62 void extHeader();
63
64
65 /*
66 * ----------------------------------------------------------------------------
67 *
68 * ExtCell --
69 *
70 * Extract the cell 'def', plus all its interactions with its subcells.
71 * Place the result in the file named 'outName'.
72 *
73 * Results:
74 * None.
75 *
76 * Side effects:
77 * Creates the file 'outName'.ext and writes to it.
78 * May leave feedback information where errors were encountered.
79 * Upon return, extNumFatal contains the number of fatal errors
80 * encountered while extracting 'def', and extNumWarnings contains
81 * the number of warnings.
82 *
83 * ----------------------------------------------------------------------------
84 */
85
86 Plane *
ExtCell(def,outName,doLength)87 ExtCell(def, outName, doLength)
88 CellDef *def; /* Cell being extracted */
89 char *outName; /* Name of output file; if NULL, derive from def name */
90 bool doLength; /* If TRUE, extract pathlengths from drivers to
91 * receivers (the names are stored in ExtLength.c).
92 * Should only be TRUE for the root cell in a
93 * hierarchy.
94 */
95 {
96 char *filename;
97 FILE *f;
98 Plane *savePlane;
99 bool doLocal;
100
101 doLocal = (ExtOptions & EXT_DOLOCAL) ? TRUE : FALSE;
102
103 f = extFileOpen(def, outName, "w", doLocal, &filename);
104
105 TxPrintf("Extracting %s into %s:\n", def->cd_name, filename);
106
107 if (f == NULL)
108 {
109 #ifdef MAGIC_WRAPPER
110 TxError("Cannot open output file.\n");
111 #else
112 TxError("Cannot open output file: ");
113 perror(filename);
114 #endif
115 return NULL;
116 }
117
118 extNumFatal = extNumWarnings = 0;
119 savePlane = extCellFile(def, f, doLength);
120 (void) fclose(f);
121
122 if (extNumFatal > 0 || extNumWarnings > 0)
123 {
124 TxPrintf("%s:", def->cd_name);
125 if (extNumFatal > 0)
126 TxPrintf(" %d fatal error%s",
127 extNumFatal, extNumFatal != 1 ? "s" : "");
128 if (extNumWarnings > 0)
129 TxPrintf(" %d warning%s",
130 extNumWarnings, extNumWarnings != 1 ? "s" : "");
131 TxPrintf("\n");
132 }
133 return savePlane;
134 }
135
136 /*
137 * ----------------------------------------------------------------------------
138 *
139 * extFileOpen --
140 *
141 * Open the .ext file corresponding to a .mag file.
142 * If def->cd_file is non-NULL, the .ext file is just def->cd_file with
143 * the trailing .mag replaced by .ext. Otherwise, the .ext file is just
144 * def->cd_name followed by .ext.
145 *
146 * Results:
147 * Return a pointer to an open FILE, or NULL if the .ext
148 * file could not be opened in the specified mode.
149 *
150 * Side effects:
151 * Opens a file.
152 *
153 * ----------------------------------------------------------------------------
154 */
155
156 FILE *
extFileOpen(def,file,mode,doLocal,prealfile)157 extFileOpen(def, file, mode, doLocal, prealfile)
158 CellDef *def; /* Cell whose .ext file is to be written */
159 char *file; /* If non-NULL, open 'name'.ext; otherwise,
160 * derive filename from 'def' as described
161 * above.
162 */
163 char *mode; /* Either "r" or "w", the mode in which the .ext
164 * file is to be opened.
165 */
166 bool doLocal; /* If true, always write to local directory */
167 char **prealfile; /* If this is non-NULL, it gets set to point to
168 * a string holding the name of the .ext file.
169 */
170 {
171 char namebuf[512], *name, *endp, *ends;
172 int len;
173 FILE *rfile, *testf;
174
175 if (file) name = file;
176 else if (doLocal)
177 name = def->cd_name; /* No path component, so save locally */
178 else if (def->cd_file)
179 {
180 name = def->cd_file;
181 ends = strrchr(def->cd_file, '/');
182 if (ends == NULL) ends = def->cd_file;
183 if (endp = strrchr(ends + 1, '.'))
184 {
185 name = namebuf;
186 len = endp - def->cd_file;
187 if (len > sizeof namebuf - 1) len = sizeof namebuf - 1;
188 (void) strncpy(namebuf, def->cd_file, len);
189 namebuf[len] = '\0';
190 }
191 }
192 else name = def->cd_name;
193
194 /* Try once as-is, and if this fails, try stripping any leading */
195 /* path information in case cell is in a read-only directory. */
196
197 if ((rfile = PaOpen(name, mode, ".ext", Path, CellLibPath, prealfile)) != NULL)
198 return rfile;
199
200 if (!strcmp(mode, "r")) return NULL; /* Not even readable */
201
202 /* Try writing to the cwd IF there is no .mag file by the */
203 /* same name in the cwd that would conflict. */
204
205 name = strrchr(def->cd_name, '/');
206 if (name != NULL)
207 name++;
208 else
209 name = def->cd_name;
210
211 ends = strrchr(def->cd_file, '/');
212 if (ends != NULL)
213 {
214 testf = PaOpen(ends + 1, "r", ".mag", ".", ".", NULL);
215 if (testf)
216 {
217 fclose(testf);
218 return NULL;
219 }
220 }
221 return (PaOpen(name, mode, ".ext", ".", ".", prealfile));
222 }
223
224 /*
225 * ----------------------------------------------------------------------------
226 *
227 * extPrepSubstrate ---
228 *
229 * Prepare a replacement plane for the plane representing the substrate, as
230 * defined in ExtCurStyle->exts_globSubstratePlane. The target CellDef is
231 * searched for types that shield (i.e., isolate) a section of the layout
232 * from the global substrate. The tile type that represents the substrate
233 * is painted into the isolated regions.
234 *
235 * The purpose of this method is to deal with the common methodology in
236 * which the substrate is not represented by any tile type, because no mask
237 * is defined for the substrate. Typically, an entire cell such as a digital
238 * standard cell may be placed on the default substrate or in a deep nwell
239 * region. It is therefore necessary to be able to detect what is underneath
240 * a cell on the plane representing the substrate to determine if the area is
241 * the default substrate or an isolated region. If an isolated region, it
242 * must be painted with a tile type so that the extraction code can tag the
243 * tiles with a Region and assign it a node. This code creates the substrate
244 * paint in the isolated regions for the duration of the extration, then
245 * reverts back to the original plane afterward.
246 *
247 * Results:
248 * Returns a Plane structure that is the original substrate plane from
249 * CellDef "def", with isolated substrate regions filled with the
250 * substrate tile type. If there are no isolated substrate regions,
251 * or if a substrate plane or substrate type is not defined by the
252 * technology, then the routine returns NULL.
253 *
254 * Side effects:
255 * All modifications are limited to the returned plane structure.
256 *
257 * ----------------------------------------------------------------------------
258 */
259
260 Plane *
extPrepSubstrate(def)261 extPrepSubstrate(def)
262 CellDef *def;
263 {
264 SearchContext scx;
265 CellUse dummy;
266 TileType subType;
267 TileTypeBitMask subMask, notSubMask;
268 Plane *subPlane, *savePlane;
269 int pNum;
270
271 /* Determine if substrate copying is required. */
272
273 if (ExtCurStyle->exts_globSubstratePlane == -1) return NULL;
274
275 /* Find a type to use for the substrate, and the mask of all types */
276 /* in the same plane as the substrate that are not connected to the */
277 /* substrate. If there is not a simple type representing the substrate */
278 /* then do not attempt to resolve substrate regions. */
279
280 TTMaskZero(&subMask);
281 TTMaskSetMask(&subMask, &ExtCurStyle->exts_globSubstrateTypes);
282
283 for (subType = TT_TECHDEPBASE; subType < DBNumUserLayers; subType++)
284 if (TTMaskHasType(&subMask, subType))
285 if (DBPlane(subType) == ExtCurStyle->exts_globSubstratePlane)
286 break;
287
288 TTMaskCom2(¬SubMask, &subMask);
289 TTMaskAndMask(¬SubMask, &DBPlaneTypes[ExtCurStyle->exts_globSubstratePlane]);
290
291 if (subType == DBNumUserLayers) return NULL;
292
293 /* Generate the full flattened substrate into ha->ha_cumFlat (which */
294 /* was empty initially). This adds layer geometry for the */
295 /* substrate in the typical case where the substrate may be space */
296 /* (implicitly defined substrate). */
297
298 scx.scx_trans = GeoIdentityTransform;
299 scx.scx_area = def->cd_bbox;
300 scx.scx_use = &dummy;
301 dummy.cu_def = def;
302 dummy.cu_id = NULL;
303
304 subPlane = DBCellGenerateSubstrate(&scx, subType, ¬SubMask,
305 &ExtCurStyle->exts_globSubstrateShieldTypes, def);
306 if (subPlane != NULL)
307 {
308 pNum = ExtCurStyle->exts_globSubstratePlane;
309 savePlane = def->cd_planes[pNum];
310 def->cd_planes[pNum] = subPlane;
311 return savePlane;
312 }
313 else
314 return NULL;
315 }
316
317 /*
318 * ----------------------------------------------------------------------------
319 *
320 * ExtRevertSubstrate ---
321 *
322 * This routine swaps the substrate plane of CellDef "def" with the plane
323 * structure provided in the argument "savePlane". It should be called at
324 * the end of extraction. "savePlane" should be the pointer to the substrate
325 * plane of "def" before it was swapped out for the modified plane created by
326 * the routine "extPrepSubstrate", above. The calling routine is responsible
327 * for knowing if extPrepSubstrate returned NULL in which case there is
328 * nothing to revert.
329 *
330 * Returns:
331 * Nothing.
332 *
333 * Side effects:
334 * The CellDef "def" has its substrate plane swapped out for "savePlane",
335 * and the original substrate plane and its contents are freed.
336 * ----------------------------------------------------------------------------
337 */
338
339
340 void
ExtRevertSubstrate(def,savePlane)341 ExtRevertSubstrate(def, savePlane)
342 CellDef *def;
343 Plane *savePlane;
344 {
345 int pNum;
346 Plane *subPlane;
347
348 pNum = ExtCurStyle->exts_globSubstratePlane;
349 subPlane = def->cd_planes[pNum];
350 def->cd_planes[pNum] = savePlane;
351 DBFreePaintPlane(subPlane);
352 TiFreePlane(subPlane);
353 }
354
355 /*
356 * ----------------------------------------------------------------------------
357 *
358 * extCellFile --
359 *
360 * Internal interface for extracting a single cell.
361 * Extracts it to the open FILE 'f'. Doesn't print
362 * any messages.
363 *
364 * Results:
365 * None.
366 *
367 * Side effects:
368 * May leave feedback information where errors were encountered.
369 * Upon return, extNumFatal has been incremented by the number of
370 * fatal errors encountered while extracting 'def', and extNumWarnings
371 * by the number of warnings.
372 *
373 * ----------------------------------------------------------------------------
374 */
375
376 Plane *
extCellFile(def,f,doLength)377 extCellFile(def, f, doLength)
378 CellDef *def; /* Def to be extracted */
379 FILE *f; /* Output to this file */
380 bool doLength; /* TRUE if we should extract driver-receiver path
381 * length information for this cell (see ExtCell
382 * for more details).
383 */
384 {
385 NodeRegion *reg;
386 Plane *saveSub;
387
388 UndoDisable();
389
390 /* Prep any isolated substrate areas */
391 saveSub = extPrepSubstrate(def);
392
393 /* Output the header: timestamp, technology, calls on cell uses */
394 if (!SigInterruptPending) extHeader(def, f);
395
396 /* Extract the mask information in this cell */
397 reg = (NodeRegion *) NULL;
398 if (!SigInterruptPending) reg = extBasic(def, f);
399
400 /* Do hierarchical extraction */
401 extParentUse->cu_def = def;
402 if (!SigInterruptPending) extSubtree(extParentUse, reg, f);
403 if (!SigInterruptPending) extArray(extParentUse, f);
404
405 /* Clean up from basic extraction */
406 if (reg) ExtFreeLabRegions((LabRegion *) reg);
407 ExtResetTiles(def, extUnInit);
408
409 /* Final pass: extract length information if desired */
410 if (!SigInterruptPending && doLength && (ExtOptions & EXT_DOLENGTH))
411 extLength(extParentUse, f);
412
413 UndoEnable();
414 return saveSub;
415 }
416
417 /*
418 * ----------------------------------------------------------------------------
419 *
420 * extHeader --
421 *
422 * Output header information to the .ext file for a cell.
423 * This information consists of:
424 *
425 * timestamp
426 * extractor version number
427 * technology
428 * scale factors for resistance, capacitance, and lambda
429 * calls on all subcells used by this cell (see extOutputUsesFunc)
430 *
431 * Results:
432 * None.
433 *
434 * Side effects:
435 * Writes to (FILE *) 'f'.
436 *
437 * ----------------------------------------------------------------------------
438 */
439
440 void
extHeader(def,f)441 extHeader(def, f)
442 CellDef *def; /* Cell being extracted */
443 FILE *f; /* Write to this file */
444 {
445 int n;
446 bool propfound;
447 char *propvalue;
448
449 ASSERT(DBTechName != NULL, "extHeader");
450
451 /* Output a timestamp (should be first) */
452 fprintf(f, "timestamp %d\n", def->cd_timestamp);
453
454 /* Output our version number */
455 fprintf(f, "version %s\n", MagicVersion);
456
457 /* Output the technology */
458 fprintf(f, "tech %s\n", DBTechName);
459
460 /* Output the extract style name */
461 fprintf(f, "style %s\n", ExtCurStyle->exts_name);
462
463 /*
464 * Output scaling factors: R C D
465 * R = amount to multiply all resistances in the file by
466 * C = amount to multiply all capacitances by
467 * D = amount to multiply all linear distances by (areas
468 * should be multiplied by D**2).
469 */
470 fprintf(f, "scale %d %d %g\n",
471 ExtCurStyle->exts_resistScale,
472 ExtCurStyle->exts_capScale,
473 ExtCurStyle->exts_unitsPerLambda);
474
475 /* Output the sheet resistivity classes */
476 fprintf(f, "resistclasses");
477 for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++)
478 fprintf(f, " %d", ExtCurStyle->exts_resistByResistClass[n]);
479 fprintf(f, "\n");
480
481 /* Output any parameters defined for this cell that */
482 /* are to be passed to instances of the cell */
483 /* (created by defining property "parameter") */
484
485 propvalue = (char *)DBPropGet(def, "parameter", &propfound);
486 if (propfound)
487 {
488 // Use device parameter table to store the cell def parameters,
489 // but preface name with ":" to avoid any conflict with device
490 // names.
491 fprintf(f, "parameters :%s %s\n", def->cd_name, propvalue);
492 }
493
494 /* Output all calls on subcells */
495 (void) DBCellEnum(def, extOutputUsesFunc, (ClientData) f);
496 }
497
498 /*
499 * ----------------------------------------------------------------------------
500 *
501 * extOutputUsesFunc --
502 *
503 * Filter function, called via DBCellEnum, that outputs all the
504 * cell uses contained in the parent's cell tile planes.
505 *
506 * Results:
507 * Always returns 0, for DBCellEnum to keep going.
508 *
509 * Side effects:
510 * Writes a line for each use encountered to 'outf'.
511 * The line is of the following form:
512 *
513 * use defname useid Ta ... Tf
514 *
515 * where 'defname' is the name of the cell def referenced (cd_name),
516 * 'useid' is its use identifier (cu_id), and Ta ... Tf are the six
517 * components of the transform from coordinates of this use up to
518 * its parent. If the cell is an array, the use id may be followed by:
519 *
520 * [xlo,xhi,xsep][ylo,yhi,ysep]
521 *
522 * The indices are xlo through xhi inclusive, or ylo through yhi
523 * inclusive. The separation between adjacent elements is xsep
524 * or ysep; this is used in computing the transform for a particular
525 * array element. If arraying is not present in a given direction,
526 * the low and high indices are equal and the separation is ignored.
527 *
528 * ----------------------------------------------------------------------------
529 */
530
531 int
extOutputUsesFunc(cu,outf)532 extOutputUsesFunc(cu, outf)
533 CellUse *cu;
534 FILE *outf;
535 {
536 Transform *t = &cu->cu_transform;
537
538 fprintf(outf, "use %s %s", cu->cu_def->cd_name, cu->cu_id);
539 if (cu->cu_xlo != cu->cu_xhi || cu->cu_ylo != cu->cu_yhi)
540 {
541 fprintf(outf, "[%d:%d:%d]",
542 cu->cu_xlo, cu->cu_xhi, cu->cu_xsep);
543 fprintf(outf, "[%d:%d:%d]",
544 cu->cu_ylo, cu->cu_yhi, cu->cu_ysep);
545 }
546
547 /* Output transform to parent */
548 fprintf(outf, " %d %d %d %d %d %d\n",
549 t->t_a, t->t_b, t->t_c, t->t_d, t->t_e, t->t_f);
550
551 return (0);
552 }
553