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(&notSubMask, &subMask);
289     TTMaskAndMask(&notSubMask, &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, &notSubMask,
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