1 /*
2  * lefWrite.c --
3  *
4  * This module incorporates the LEF/DEF format for standard-cell place and
5  * route.
6  *
7  * Version 0.1 (May 1, 2003):  LEF output for cells, to include pointer to
8  * GDS, automatic generation of GDS if not already made, bounding box export,
9  * port export, export of irouter "fence", "magnet", and "rotate" layers
10  * for defining router hints, and generating areas for obstructions and
11  * pin layers.
12  *
13  */
14 
15 #ifndef lint
16 static char rcsid[] __attribute__ ((unused)) = "$Header$";
17 #endif  /* not lint */
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <math.h>   /* for truncf() function */
24 
25 #include "tcltk/tclmagic.h"
26 #include "utils/magic.h"
27 #include "utils/geometry.h"
28 #include "tiles/tile.h"
29 #include "utils/hash.h"
30 #include "database/database.h"
31 #include "extract/extract.h"
32 #include "utils/tech.h"
33 #include "utils/utils.h"
34 #include "utils/malloc.h"
35 #include "utils/stack.h"
36 #include "utils/signals.h"
37 #include "windows/windows.h"
38 #include "dbwind/dbwind.h"
39 #include "graphics/graphics.h"
40 #include "utils/main.h"
41 #include "utils/undo.h"
42 #include "drc/drc.h"
43 #include "cif/cif.h"
44 #include "cif/CIFint.h"
45 #include "lef/lefInt.h"
46 
47 
48 #define FP "%s"
49 #define POINT FP " " FP
50 #define IN0 "  "
51 #define IN1 "    "
52 #define IN2 "      "
53 #define IN3 "        "
54 
55 /* ---------------------------------------------------------------------*/
56 
57 /* Stack of cell definitions */
58 Stack *lefDefStack;
59 
60 /* Keep the database units around for calculations */
61 int LEFdbUnits = 1000;
62 
63 /*
64  * ---------------------------------------------------------------------
65  *
66  * lefPrint --
67  *
68  * Print a measurement value to LEF output in appropriate units.  Since
69  * the minimum LEF database unit is 1/20 nanometer, the number of digits
70  * is adjusted accordingly for the output in units of microns, according
71  * to the grid limit (current grid limit in magic is 1 angstrom, so the
72  * maximum number of digits behind the decimal is 4).
73  *
74  * Results:
75  *	Returns a pointer to a static character string containing the
76  *	formatted value.
77  *
78  * Side effects:
79  *	None.
80  *
81  * ---------------------------------------------------------------------
82  */
83 
84 const char *
lefPrint(char * leffmt,float invalue)85 lefPrint(char *leffmt, float invalue)
86 {
87     float value, r, l;
88 
89     r = (invalue < 0.0) ? -0.5 : 0.5;
90     l = (float)LEFdbUnits;
91 
92     /* Truncate to units or half units to the precision indicated by LEFdbUnits */
93 
94     switch (LEFdbUnits)
95     {
96 	case 100:
97 	    value = (float)(truncf((invalue * l) + r) / l);
98 	    sprintf(leffmt, "%.2f", value);
99 	    break;
100 	case 200:
101 	case 1000:
102 	    value = (float)(truncf((invalue * l) + r) / l);
103 	    sprintf(leffmt, "%.3f", value);
104 	    break;
105 	case 2000:
106 	case 10000:
107 	    value = (float)(truncf((invalue * l) + r) / l);
108 	    sprintf(leffmt, "%.4f", value);
109 	    break;
110 	case 20000:
111 	    value = (float)(truncf((invalue * l) + r) / l);
112 	    sprintf(leffmt, "%.5f", value);
113 	    break;
114 	default:
115 	    value = (float)(truncf((invalue * 100000.) + r) / 100000.);
116 	    sprintf(leffmt, "%.5f", value);
117 	    break;
118     }
119     return leffmt;
120 }
121 
122 /*
123  * ---------------------------------------------------------------------
124  *
125  * lefFileOpen --
126  *
127  * Open the .lef file corresponding to a .mag file.
128  * If def->cd_file is non-NULL, the .lef file is just def->cd_file with
129  * the trailing .mag replaced by .lef.  Otherwise, the .lef file is just
130  * def->cd_name followed by .lef.
131  *
132  * Results:
133  *	Return a pointer to an open FILE, or NULL if the .lef
134  *	file could not be opened in the specified mode.
135  *
136  * Side effects:
137  *	Opens a file.
138  *
139  * ----------------------------------------------------------------------------
140  */
141 
142 FILE *
lefFileOpen(def,file,suffix,mode,prealfile)143 lefFileOpen(def, file, suffix, mode, prealfile)
144     CellDef *def;	/* Cell whose .lef file is to be written.  Should
145 			 * be NULL if file is being opened for reading.
146 			 */
147     char *file;		/* If non-NULL, open 'name'.lef; otherwise,
148 			 * derive filename from 'def' as described
149 			 * above.
150 			 */
151     char *suffix;	/* Either ".lef" for LEF files or ".def" for DEF files */
152     char *mode;		/* Either "r" or "w", the mode in which the LEF/DEF
153 			 * file is to be opened.
154 			 */
155     char **prealfile;	/* If this is non-NULL, it gets set to point to
156 			 * a string holding the name of the LEF/DEF file.
157 			 */
158 {
159     char namebuf[512], *name, *endp, *ends;
160     char *locsuffix;
161     char *pptr;
162     int len;
163     FILE *rfile;
164 
165     if (file)
166 	name = file;
167     else if (def && def->cd_file)
168 	name = def->cd_file;
169     else if (def)
170 	name = def->cd_name;
171     else
172     {
173 	TxError("LEF file open:  No file name or cell given\n");
174 	return NULL;
175     }
176 
177     // Strip off suffix, if there is one
178 
179     ends = strrchr(name, '/');
180     if (ends == NULL)
181 	ends = name;
182     else
183 	ends++;
184 
185     if (endp = strrchr(ends, '.'))
186     {
187 	if (strcmp(endp, suffix))
188 	{
189 	    /* Try once as-is, with the given extension.  That takes care   */
190 	    /* of some less-usual extensions like ".tlef".		    */
191 	    if ((rfile = PaOpen(name, mode, NULL, Path, CellLibPath, prealfile)) != NULL)
192 		return rfile;
193 
194 	    len = endp - name;
195 	    if (len > sizeof namebuf - 1) len = sizeof namebuf - 1;
196 	    (void) strncpy(namebuf, name, len);
197 	    namebuf[len] = '\0';
198 	    name = namebuf;
199 	    locsuffix = suffix;
200 	}
201 	else
202 	    locsuffix = NULL;
203     }
204     else
205 	locsuffix = suffix;
206 
207     /* Try once as-is, and if this fails, try stripping any leading	*/
208     /* path information in case cell is in a read-only directory (mode	*/
209     /* "read" only, and if def is non-NULL).				*/
210 
211     if ((rfile = PaOpen(name, mode, locsuffix, Path, CellLibPath, prealfile)) != NULL)
212 	return rfile;
213 
214     if (def)
215     {
216 	if (name == def->cd_name) return NULL;
217 	name = def->cd_name;
218 	return (PaOpen(name, mode, suffix, Path, CellLibPath, prealfile));
219     }
220     else
221 	return NULL;
222 }
223 
224 
225 /*
226  * ----------------------------------------------------------------------------
227  *
228  * lefWriteHeader --
229  *
230  * This routine generates LEF header output for a cell or cell hierarchy.
231  * Although the LEF/DEF spec does not define a "header" per se, this is
232  * considered to be all LEF output not including the MACRO calls.  The
233  * header, therefore, defines layers, process routing rules, units
234  * (lambda), and so forth.
235  *
236  * Results:
237  *	None.
238  *
239  * Side effects:
240  *	Writes output to the open file "f".
241  *
242  * ----------------------------------------------------------------------------
243  */
244 
245 void
lefWriteHeader(def,f,lefTech,propTable,siteTable)246 lefWriteHeader(def, f, lefTech, propTable, siteTable)
247     CellDef *def;	    /* Def for which to generate LEF output */
248     FILE *f;		    /* Output to this file */
249     bool lefTech;	    /* If TRUE, write layer information */
250     HashTable *propTable;   /* Hash table of property definitions */
251     HashTable *siteTable;   /* Hash table of sites used */
252 {
253     TileType type;
254     HashSearch hs;
255     HashEntry *he;
256     int nprops;
257 
258     TxPrintf("Diagnostic:  Write LEF header for cell %s\n", def->cd_name);
259 
260     /* NOTE:  This routine corresponds to Envisia LEF/DEF Language	*/
261     /* Reference version 5.7 (November 2009).				*/
262 
263     fprintf(f, "VERSION 5.7 ;\n");
264     fprintf(f, IN0 "NOWIREEXTENSIONATPIN ON ;\n");
265     fprintf(f, IN0 "DIVIDERCHAR \"/\" ;\n");
266     fprintf(f, IN0 "BUSBITCHARS \"[]\" ;\n");
267 
268     /* Database units are normally 1000 (magic outputs GDS in nanometers)   */
269     /* but if "gridlimit" is set to something other than 1, then divide it  */
270     /* down (due to LEF format limitations, grid limit can only be 1, 5, or */
271     /* 10).  If the CWF_ANGSTROMS flag is set, then multiply up by ten.	    */
272 
273     LEFdbUnits = 1000;
274     if (CIFCurStyle)
275     {
276 	if (CIFCurStyle->cs_flags & CWF_ANGSTROMS) LEFdbUnits *= 10;
277 	switch (CIFCurStyle->cs_gridLimit)
278 	{
279 	    case 1:
280 	    case 5:
281 	    case 10:
282 		LEFdbUnits /= CIFCurStyle->cs_gridLimit;
283 		break;
284 	    /* Otherwise leave as-is */
285 	}
286     }
287 
288     if (lefTech)
289     {
290 	fprintf(f, "UNITS\n");
291 	fprintf(f, IN0 "DATABASE MICRONS %d ;\n", LEFdbUnits);
292 	fprintf(f, "END UNITS\n");
293 	fprintf(f, "\n");
294     }
295 
296     HashStartSearch(&hs);
297     nprops = 0;
298     while (he = HashNext(propTable, &hs))
299     {
300 	if (nprops == 0) fprintf(f, "PROPERTYDEFINITIONS\n");
301 	nprops++;
302 
303 	/* NOTE: Type (e.g., "STRING") may be kept in hash value.   */
304 	/* This has not been implemented;  only string types are supported */
305 	fprintf(f, IN0 "MACRO %s STRING ;\n", (char *)he->h_key.h_name);
306     }
307     if (nprops > 0) fprintf(f, "END PROPERTYDEFINITIONS\n\n");
308 
309     HashStartSearch(&hs);
310     while (he = HashNext(siteTable, &hs))
311     {
312 	/* Output the SITE as a macro */
313 	CellDef *siteDef;
314 	float scale;
315 	char leffmt[2][10];
316 	bool propfound;
317 	char *propvalue;
318 	Rect boundary;
319 
320 	siteDef = DBCellLookDef((char *)he->h_key.h_name);
321 	if (siteDef)
322 	{
323 	    fprintf(f, "SITE %s\n", siteDef->cd_name);
324 
325 	    propvalue = (char *)DBPropGet(siteDef, "LEFsymmetry", &propfound);
326 	    if (propfound)
327 		fprintf(f, IN0 "SYMMETRY %s ;\n", propvalue);
328 	    else
329 		/* Usually core cells have symmetry Y only. */
330 		fprintf(f, IN0 "SYMMETRY Y ;\n");
331 
332 	    propvalue = (char *)DBPropGet(siteDef, "LEFclass", &propfound);
333 	    if (propfound)
334 		fprintf(f, IN0 "CLASS %s ;\n", propvalue);
335 	    else
336 		/* Needs a class of some kind.  Use CORE as default if not defined */
337 		fprintf(f, IN0 "CLASS CORE ;\n");
338 
339 	    boundary = siteDef->cd_bbox;
340 	    if (siteDef->cd_flags & CDFIXEDBBOX)
341 	    {
342 		propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &propfound);
343 		if (propfound)
344 		    sscanf(propvalue, "%d %d %d %d", &boundary.r_xbot,
345 			    &boundary.r_ybot, &boundary.r_xtop, &boundary.r_ytop);
346 	    }
347 
348 	    scale = CIFGetOutputScale(1000);	/* conversion to microns */
349 	    fprintf(f, IN0 "SIZE " FP " BY " FP " ;\n",
350 		lefPrint(leffmt[0], scale * (float)(boundary.r_xtop - boundary.r_xbot)),
351 		lefPrint(leffmt[1], scale * (float)(boundary.r_ytop - boundary.r_ybot)));
352 
353 	    fprintf(f, "END %s\n\n", siteDef->cd_name);
354 	}
355     }
356 
357     if (!lefTech) return;
358 
359     UndoDisable();
360 
361     /* Layers (minimal information) */
362 
363     if (LefInfo.ht_table != (HashEntry **)NULL)
364     {
365 	HashSearch hs;
366 	HashEntry *he;
367 	lefLayer *lefl;
368 
369 	float oscale = CIFGetOutputScale(1000);	/* lambda->micron conversion */
370 
371 	HashStartSearch(&hs);
372 	while (he = HashNext(&LefInfo, &hs))
373 	{
374 	    lefl = (lefLayer *)HashGetValue(he);
375 	    if (!lefl) continue;
376 
377 	    if (lefl->refCnt > 0)
378 	    {
379 		/* Avoid writing more than one entry per defined layer */
380 	        if (lefl->refCnt > 1) lefl->refCnt = -lefl->refCnt;
381 
382 		/* Ignore obstruction-only layers */
383 		if (lefl->type == -1) continue;
384 
385 		/* Ignore VIA types, report only CUT types here */
386 		else if ((lefl->lefClass == CLASS_VIA)
387 			&& lefl->info.via.cell != NULL) continue;
388 
389 		/* Ignore boundary types */
390 		else if (lefl->lefClass == CLASS_BOUND) continue;
391 
392 		fprintf(f, "LAYER %s\n", lefl->canonName);
393 		if (lefl->lefClass == CLASS_VIA)
394 		{
395 		    int cutarea;
396 		    cutarea = (lefl->info.via.area.r_xtop - lefl->info.via.area.r_xbot);
397 		    cutarea *= (lefl->info.via.area.r_ytop - lefl->info.via.area.r_ybot);
398 		    fprintf(f, IN0 "TYPE CUT ;\n");
399 		    if (cutarea > 0)
400 			fprintf(f, IN0 "CUT AREA %f ;\n",
401 					(float)cutarea * oscale * oscale);
402 		}
403 		else if (lefl->lefClass == CLASS_ROUTE)
404 		{
405 		    fprintf(f, IN0 "TYPE ROUTING ;\n");
406 		    if (lefl->info.route.pitch > 0)
407 			fprintf(f, IN0 "PITCH %f ;\n", (float)(lefl->info.route.pitch)
408 				* oscale);
409 		    if (lefl->info.route.width > 0)
410 			fprintf(f, IN0 "WIDTH %f ;\n", (float)(lefl->info.route.width)
411 				* oscale);
412 		    if (lefl->info.route.spacing > 0)
413 			fprintf(f, IN0 "SPACING %f ;\n", (float)(lefl->info.route.spacing)
414 				* oscale);
415 		    /* No sense in providing direction info unless we know the width */
416 		    if (lefl->info.route.width > 0)
417 			fprintf(f, IN0 "DIRECTION %s ;\n", (lefl->info.route.hdirection)
418 				?  "HORIZONTAL" : "VERTICAL");
419 		}
420 		else if (lefl->lefClass == CLASS_MASTER)
421 		{
422 		    fprintf(f, IN0 "TYPE MASTERSLICE ;\n");
423 		}
424 		else if (lefl->lefClass == CLASS_OVERLAP)
425 		{
426 		    fprintf(f, IN0 "TYPE OVERLAP ;\n");
427 		}
428 		fprintf(f, "END %s\n\n", lefl->canonName);
429 	    }
430 	}
431 
432 	/* Return reference counts to normal */
433 	HashStartSearch(&hs);
434 	while (he = HashNext(&LefInfo, &hs))
435 	{
436 	    lefl = (lefLayer *)HashGetValue(he);
437 	    if (lefl && lefl->refCnt < 0)
438 		lefl->refCnt = -lefl->refCnt;
439 	}
440     }
441 
442     /* Vias (to be completed, presumably) */
443     /* Rules (to be completed, presumably) */
444 
445     UndoEnable();
446 }
447 
448 #define LEF_MODE_PORT		0
449 #define LEF_MODE_OBSTRUCT	1
450 #define LEF_MODE_CONTACT	2
451 #define LEF_MODE_OBS_CONTACT	3
452 
453 typedef struct
454 {
455     FILE	*file;		/* file to write to */
456     TileType	lastType;	/* last type output, so we minimize LAYER
457 				 * statements.
458 				 */
459     CellDef	*lefFlat;	/* Soure CellDef (flattened cell) */
460     CellDef	*lefYank;	/* CellDef to write into */
461     LefMapping  *lefMagicMap;	/* Layer inverse mapping table */
462     TileTypeBitMask rmask;	/* mask of routing layer types */
463     Point	origin;		/* origin of cell */
464     float	oscale;		/* units scale conversion factor */
465     int		pNum;		/* Plane number for tile marking */
466     int		numWrites;	/* Track number of writes to output */
467     bool	needHeader;	/* TRUE if PIN record header needs to be written */
468     int		lefMode;	/* can be LEF_MODE_PORT when searching
469 				 * connections into ports, or
470 				 * LEF_MODE_OBSTRUCT when generating obstruction
471 				 * geometry.  LEF polyons must be manhattan, so
472 				 * if we find a split tile, LEF_MODE_PORT ignores
473 				 * it, and LEF_MODE_OBSTRUCT outputs the whole
474 				 * tile.  LEF_MODE_CONTACT and LEF_MODE_OBS_CONTACT
475 				 * are equivalent modes for handling contacts.
476 				 */
477 } lefClient;
478 
479 /*
480  * ----------------------------------------------------------------------------
481  *
482  * lefEraseGeometry --
483  *
484  *	Remove geometry that has been output from the lefFlat cell so that it
485  *	will be ignored on subsequent output.  This is how pin areas are
486  *	separated from obstruction areas in the output:  Each pin network is
487  *	selected and output, then its geometry is erased from lefFlat.  The
488  *	remaining geometry after all pins have been written are the obstructions.
489  * ----------------------------------------------------------------------------
490  *
491  */
492 
493 int
lefEraseGeometry(tile,cdata)494 lefEraseGeometry(tile, cdata)
495     Tile *tile;
496     ClientData cdata;
497 {
498     lefClient *lefdata = (lefClient *)cdata;
499     CellDef *flatDef = lefdata->lefFlat;
500     Rect area;
501     TileType ttype, otype;
502 
503     TiToRect(tile, &area);
504 
505     otype = TiGetTypeExact(tile);
506     if (IsSplit(tile))
507 	ttype = (otype & TT_SIDE) ? SplitRightType(tile) :
508 			SplitLeftType(tile);
509     else
510 	ttype = otype;
511 
512     /* Erase the tile area out of lefFlat */
513     /* Use DBNMPaintPlane, NOT DBErase().  This erases contacts one	*/
514     /* plane at a time, which normally is bad, but since every plane	*/
515     /* gets erased eventually during "lef write", this is okay.		*/
516     /* DBErase(flatDef, &area, ttype); */
517     DBNMPaintPlane(flatDef->cd_planes[lefdata->pNum], otype, &area,
518 	    DBStdEraseTbl(ttype, lefdata->pNum), NULL);
519 
520     return 0;
521 }
522 
523 /*
524  * ----------------------------------------------------------------------------
525  *
526  * Callback function to find the cell boundary based on the specified
527  * boundary layer type.  Typically this will be a single rectangle on
528  * its own plane, but for completeness, all geometry in the cell is
529  * checked, and the bounding rectangle adjusted to fit that area.
530  *
531  * Return 0 to keep the search going.
532  * ----------------------------------------------------------------------------
533  */
534 
535 int
lefGetBound(tile,cdata)536 lefGetBound(tile, cdata)
537     Tile *tile;
538     ClientData cdata;
539 {
540     Rect *boundary = (Rect *)cdata;
541     Rect area;
542 
543     TiToRect(tile, &area);
544 
545     if (boundary->r_xtop <= boundary->r_xbot)
546 	*boundary = area;
547     else
548 	GeoInclude(&area, boundary);
549     return 0;
550 }
551 
552 /*
553  * ----------------------------------------------------------------------------
554  *
555  * lefAccumulateArea --
556  *
557  * Function called to accumulate the tile area of tiles
558  *
559  * Return 0 to keep the search going.
560  * ----------------------------------------------------------------------------
561  */
562 
563 int
lefAccumulateArea(tile,cdata)564 lefAccumulateArea(tile, cdata)
565     Tile *tile;
566     ClientData cdata;
567 {
568     int *area = (int *)cdata;
569     Rect rarea;
570 
571     TiToRect(tile, &rarea);
572 
573     *area += (rarea.r_xtop - rarea.r_xbot) * (rarea.r_ytop - rarea.r_ybot);
574 
575     return 0;
576 }
577 
578 /*
579  * ----------------------------------------------------------------------------
580  *
581  * lefFindTopmost --
582  *
583  * Function called to find the topmost layer used by a pin network
584  *
585  * Return 0 to keep the search going.
586  * ----------------------------------------------------------------------------
587  */
588 
589 int
lefFindTopmost(tile,cdata)590 lefFindTopmost(tile, cdata)
591     Tile *tile;
592     ClientData cdata;
593 {
594     return 1;	    /* Stop processing on the first tile found */
595 }
596 
597 /*
598  * ----------------------------------------------------------------------------
599  *
600  * lefYankGeometry --
601  *
602  * Function called from lefWriteMacro() that copies geometry from
603  * the cell into a yank buffer cell, one pin connection at a time.
604  * This cell removes contacts so that the following call to lefWriteGeometry
605  * will not be cut up into tiles around contacts.
606  *
607  * Return 0 to keep the search going.
608  * ----------------------------------------------------------------------------
609  */
610 
611 int
lefYankGeometry(tile,cdata)612 lefYankGeometry(tile, cdata)
613     Tile *tile;
614     ClientData cdata;
615 {
616     lefClient *lefdata = (lefClient *)cdata;
617     Rect area;
618     TileType ttype, otype, ptype;
619     LefMapping *lefMagicToLefLayer;
620     TileTypeBitMask sMask;
621     bool iscut;
622 
623     /* Ignore marked tiles */
624     if (tile->ti_client != (ClientData)CLIENTDEFAULT) return 0;
625 
626     otype = TiGetTypeExact(tile);
627     if (IsSplit(tile))
628 	ttype = (otype & TT_SIDE) ? SplitRightType(tile) :
629 			SplitLeftType(tile);
630     else
631 	ttype = otype;
632 
633     /* Output geometry only for defined routing layers	*/
634     /* If we have encountered a contact type, then	*/
635     /* decompose into constituent layers and see if any	*/
636     /* of them are in the route layer masks.		*/
637 
638     if (DBIsContact(ttype))
639     {
640 	DBFullResidueMask(ttype, &sMask);
641 
642 	/* Use the first routing layer that is represented	*/
643 	/* in sMask.  If none, then return.			*/
644 
645 	for (ttype = TT_TECHDEPBASE; ttype < DBNumTypes; ttype++)
646 	    if (TTMaskHasType(&sMask, ttype))
647 		if (TTMaskHasType(&lefdata->rmask, ttype))
648 		    break;
649 
650 	if (ttype == DBNumTypes) return 0;
651 	iscut = TRUE;
652     }
653     else
654     {
655 	if (!TTMaskHasType(&lefdata->rmask, ttype)) return 0;
656 	iscut = FALSE;
657     }
658 
659     TiToRect(tile, &area);
660 
661     while (ttype < DBNumUserLayers)
662     {
663 	lefMagicToLefLayer = lefdata->lefMagicMap;
664 	if (lefMagicToLefLayer[ttype].lefName != NULL)
665 	{
666 	    if (IsSplit(tile))
667 		// Set only the side being yanked
668 		ptype = (otype & (TT_DIAGONAL | TT_SIDE | TT_DIRECTION)) |
669 			((otype & TT_SIDE) ? (ttype << 14) : ttype);
670 	    else
671 		ptype = ttype;
672 
673 	    /* Paint into yank buffer */
674 	    DBNMPaintPlane(lefdata->lefYank->cd_planes[lefdata->pNum],
675 			ptype, &area, DBStdPaintTbl(ttype, lefdata->pNum),
676 			(PaintUndoInfo *)NULL);
677 	}
678 
679 	if (iscut == FALSE) break;
680 
681 	for (++ttype; ttype < DBNumTypes; ttype++)
682 	    if (TTMaskHasType(&sMask, ttype))
683 		if (TTMaskHasType(&lefdata->rmask, ttype))
684 		    break;
685     }
686     return 0;
687 }
688 
689 /*
690  * ----------------------------------------------------------------------------
691  *
692  * lefYankContacts --
693  *
694  * Function similar to lefYankGeometry (see above) that handles contacts.
695  * Contacts are yanked separately so that the tiles around contact cuts
696  * are not broken up into pieces, and the contacts can be handled as cuts.
697  *
698  * Return 0 to keep the search going.
699  * ----------------------------------------------------------------------------
700  */
701 
702 int
lefYankContacts(tile,cdata)703 lefYankContacts(tile, cdata)
704     Tile *tile;
705     ClientData cdata;
706 {
707     lefClient *lefdata = (lefClient *)cdata;
708     Rect area;
709     TileType ttype, ptype, stype;
710     LefMapping *lefMagicToLefLayer;
711     TileTypeBitMask sMask, *lrmask;
712     bool iscut;
713 
714     /* Ignore marked tiles */
715     if (tile->ti_client != (ClientData)CLIENTDEFAULT) return 0;
716 
717     /* Ignore split tiles */
718     if (IsSplit(tile)) return 0;
719 
720     /* Output geometry only for defined contact layers, on their home plane */
721     ttype = TiGetType(tile);
722     if (!DBIsContact(ttype)) return 0;
723 
724     /* If this is a stacked contact, find any residue contact type with	a   */
725     /* home plane on lefdata->pNum.					    */
726 
727     if (ttype >= DBNumUserLayers)
728     {
729 	lrmask = DBResidueMask(ttype);
730 	for (stype = TT_TECHDEPBASE; stype < DBNumUserLayers; stype++)
731 	    if (TTMaskHasType(lrmask, stype))
732 		if (DBPlane(stype) == lefdata->pNum)
733 		{
734 		    ttype = stype;
735 		    break;
736 		}
737 	if (stype == DBNumUserLayers) return 0;	    /* Should not happen */
738     }
739     else
740 	if (DBPlane(ttype) != lefdata->pNum) return 0;
741 
742     /* Ignore non-Manhattan tiles */
743     if (IsSplit(tile)) return 0;
744 
745     TiToRect(tile, &area);
746 
747     lefMagicToLefLayer = lefdata->lefMagicMap;
748     if (lefMagicToLefLayer[ttype].lefInfo != NULL)
749     {
750 	/* Paint into yank buffer */
751 	DBNMPaintPlane(lefdata->lefYank->cd_planes[lefdata->pNum],
752 			ttype, &area, DBStdPaintTbl(ttype, lefdata->pNum),
753 			(PaintUndoInfo *)NULL);
754     }
755     return 0;
756 }
757 
758 /*
759  * ----------------------------------------------------------------------------
760  *
761  * lefWriteGeometry --
762  *
763  * Function called from lefWritemacro() that outputs a RECT
764  * record for each tile called.  Note that LEF does not define
765  * nonmanhattan geometry (see above, comments in lefClient typedef).
766  *
767  * Return 0 to keep the search going.
768  * ----------------------------------------------------------------------------
769  */
770 
771 int
lefWriteGeometry(tile,cdata)772 lefWriteGeometry(tile, cdata)
773     Tile *tile;
774     ClientData cdata;
775 {
776     lefClient *lefdata = (lefClient *)cdata;
777     FILE *f = lefdata->file;
778     float scale = lefdata->oscale;
779     char leffmt[6][16];
780     TileType ttype, otype = TiGetTypeExact(tile);
781     LefMapping *lefMagicToLefLayer = lefdata->lefMagicMap;
782 
783     /* Ignore tiles that have already been output */
784     if (tile->ti_client != (ClientData)CLIENTDEFAULT)
785 	return 0;
786 
787     /* Mark this tile as visited */
788     TiSetClient(tile, (ClientData)1);
789 
790     /* Get layer type */
791     if (IsSplit(tile))
792 	ttype = (otype & TT_SIDE) ? SplitRightType(tile) :
793 			SplitLeftType(tile);
794     else
795 	ttype = otype;
796 
797     /* Unmarked non-contact tiles are created by tile splitting when	*/
798     /* yanking contacts.  These get marked but are otherwise ignored,	*/
799     /* because they are duplicates of areas already output.		*/
800     if (!DBIsContact(ttype))
801 	if (lefdata->lefMode == LEF_MODE_CONTACT ||
802 		    lefdata->lefMode == LEF_MODE_OBS_CONTACT)
803 	    return 0;
804 
805     /* Only LEF routing layer types will be in the yank buffer */
806     if (!TTMaskHasType(&lefdata->rmask, ttype)) return 0;
807 
808     if (lefdata->needHeader)
809     {
810 	/* Reset the tile to not visited and return 1 to    */
811 	/* signal that something is going to be written.    */
812 
813 	TiSetClient(tile, (ClientData)CLIENTDEFAULT);
814 	return 1;
815     }
816 
817     if (lefdata->numWrites == 0)
818     {
819 	if (lefdata->lefMode == LEF_MODE_PORT || lefdata->lefMode == LEF_MODE_CONTACT)
820 	    fprintf(f, IN1 "PORT\n");
821 	else
822 	    fprintf(f, IN0 "OBS\n");
823     }
824     lefdata->numWrites++;
825 
826     if (ttype != lefdata->lastType)
827 	if (lefMagicToLefLayer[ttype].lefName != NULL)
828 	{
829 	    fprintf(f, IN2 "LAYER %s ;\n",
830 				lefMagicToLefLayer[ttype].lefName);
831 	    lefdata->lastType = ttype;
832 	}
833 
834     if (IsSplit(tile))
835 	if (otype & TT_SIDE)
836 	{
837 	    if (otype & TT_DIRECTION)
838 		fprintf(f, IN3 "POLYGON " POINT " " POINT " " POINT " ;\n",
839 			lefPrint(leffmt[0], scale * (float)(LEFT(tile)
840 				    - lefdata->origin.p_x)),
841 			lefPrint(leffmt[1], scale * (float)(TOP(tile)
842 				    - lefdata->origin.p_y)),
843 			lefPrint(leffmt[2], scale * (float)(RIGHT(tile)
844 				    - lefdata->origin.p_x)),
845 			lefPrint(leffmt[3], scale * (float)(TOP(tile)
846 				    - lefdata->origin.p_y)),
847 			lefPrint(leffmt[4], scale * (float)(RIGHT(tile)
848 				    - lefdata->origin.p_x)),
849 			lefPrint(leffmt[5], scale * (float)(BOTTOM(tile)
850 				    - lefdata->origin.p_y)));
851 	    else
852 		fprintf(f, IN3 "POLYGON " POINT " " POINT " " POINT " ;\n",
853 			lefPrint(leffmt[0], scale * (float)(RIGHT(tile)
854 				    - lefdata->origin.p_x)),
855 			lefPrint(leffmt[1], scale * (float)(TOP(tile)
856 				    - lefdata->origin.p_y)),
857 			lefPrint(leffmt[2], scale * (float)(RIGHT(tile)
858 				    - lefdata->origin.p_x)),
859 			lefPrint(leffmt[3], scale * (float)(BOTTOM(tile)
860 				    - lefdata->origin.p_y)),
861 			lefPrint(leffmt[4], scale * (float)(LEFT(tile)
862 				    - lefdata->origin.p_x)),
863 			lefPrint(leffmt[5], scale * (float)(BOTTOM(tile)
864 				    - lefdata->origin.p_y)));
865 	}
866 	else
867 	{
868 	    if (otype & TT_DIRECTION)
869 		fprintf(f, IN3 "POLYGON " POINT " " POINT " " POINT " ;\n",
870 			lefPrint(leffmt[0], scale * (float)(LEFT(tile)
871 				    - lefdata->origin.p_x)),
872 			lefPrint(leffmt[1], scale * (float)(TOP(tile)
873 				    - lefdata->origin.p_y)),
874 			lefPrint(leffmt[2], scale * (float)(RIGHT(tile)
875 				    - lefdata->origin.p_x)),
876 			lefPrint(leffmt[3], scale * (float)(BOTTOM(tile)
877 				    - lefdata->origin.p_y)),
878 			lefPrint(leffmt[4], scale * (float)(LEFT(tile)
879 				    - lefdata->origin.p_x)),
880 			lefPrint(leffmt[5], scale * (float)(BOTTOM(tile)
881 				    - lefdata->origin.p_y)));
882 	    else
883 		fprintf(f, IN3 "POLYGON " POINT " " POINT " " POINT " ;\n",
884 			lefPrint(leffmt[0], scale * (float)(LEFT(tile)
885 				    - lefdata->origin.p_x)),
886 			lefPrint(leffmt[1], scale * (float)(TOP(tile)
887 				    - lefdata->origin.p_y)),
888 			lefPrint(leffmt[2], scale * (float)(RIGHT(tile)
889 				    - lefdata->origin.p_x)),
890 			lefPrint(leffmt[3], scale * (float)(TOP(tile)
891 				    - lefdata->origin.p_y)),
892 			lefPrint(leffmt[4], scale * (float)(LEFT(tile)
893 				    - lefdata->origin.p_x)),
894 			lefPrint(leffmt[5], scale * (float)(BOTTOM(tile)
895 				    - lefdata->origin.p_y)));
896 	}
897     else
898 	fprintf(f, IN3 "RECT " POINT " " POINT " ;\n",
899 		lefPrint(leffmt[0], scale * (float)(LEFT(tile) - lefdata->origin.p_x)),
900 		lefPrint(leffmt[1], scale * (float)(BOTTOM(tile) - lefdata->origin.p_y)),
901 		lefPrint(leffmt[2], scale * (float)(RIGHT(tile) - lefdata->origin.p_x)),
902 		lefPrint(leffmt[3], scale * (float)(TOP(tile) - lefdata->origin.p_y)));
903 
904     return 0;
905 }
906 
907 /*
908  * ----------------------------------------------------------------------------
909  *
910  * MakeLegalLEFSyntax --
911  *
912  *	Follow syntactical rules of the LEF spec.  Most notably, Magic
913  *	node names often contain the hash mark '#', which is illegal
914  *	in LEF output.  Other illegal LEF characters are space, newline,
915  *	semicolon, and for literal names: dash, asterisk, and percent.
916  *	All of the above will be replaced with underscores if found.
917  *
918  * Results:
919  *	Returns an allocated string containing the modified result, or
920  *	else returns the original string pointer.  It is the responsibility
921  *	of the calling function to free the result if it is not equal to
922  *	the argument.
923  *
924  * Side effects:
925  *	Allocated memory.
926  *
927  * ----------------------------------------------------------------------------
928  */
929 
930 char *
MakeLegalLEFSyntax(text)931 MakeLegalLEFSyntax(text)
932     char *text;
933 {
934     static char *badLEFchars = ";# -*$\n";
935     char *cptr, *bptr;
936     char *rstr;
937 
938     for (cptr = text; *cptr != '\0'; cptr++)
939 	for (bptr = badLEFchars; *bptr != '\0'; bptr++)
940 	    if (*cptr == *bptr) break;
941 
942     if (*cptr == '\0' && *bptr == '\0')
943 	return text;
944 
945     rstr = StrDup((char **)NULL, text);
946 
947     for (cptr = rstr; *cptr != '\0'; cptr++)
948 	for (bptr = badLEFchars; bptr != '\0'; bptr++)
949 	    if (*cptr == *bptr)
950 	    {
951 		*cptr = '_';
952 		break;
953 	    }
954 
955     return rstr;
956 }
957 
958 /* Linked list structure for holding PIN PORT geometry areas */
959 
960 typedef struct _labelLinkedList {
961     Label *lll_label;
962     Rect lll_area;
963     struct _labelLinkedList *lll_next;
964 } labelLinkedList;
965 
966 /*
967  * ----------------------------------------------------------------------------
968  *
969  * LefWritePinHeader --
970  *
971  *	Write the PIN record for the LEF macro along with any known properties
972  *	such as CLASS and USE.  Discover the USE POWER or GROUND if it is not
973  *	set as a property and the label name matches the Tcl variables $VDD
974  *	or $GND.
975  *
976  * Returns TRUE if the pin is a power pin, otherwise FALSE.
977  *
978  * ----------------------------------------------------------------------------
979  */
980 
981 bool
LefWritePinHeader(f,lab)982 LefWritePinHeader(f, lab)
983     FILE *f;
984     Label *lab;
985 {
986     bool ispwrrail = FALSE;
987 
988     fprintf(f, IN0 "PIN %s\n", lab->lab_text);
989     if (lab->lab_flags & PORT_CLASS_MASK)
990     {
991 	fprintf(f, IN1 "DIRECTION ");
992 	switch(lab->lab_flags & PORT_CLASS_MASK)
993 	{
994 	    case PORT_CLASS_INPUT:
995 		fprintf(f, "INPUT");
996 		break;
997 	    case PORT_CLASS_OUTPUT:
998 		fprintf(f, "OUTPUT");
999 		break;
1000 	    case PORT_CLASS_TRISTATE:
1001 		fprintf(f, "OUTPUT TRISTATE");
1002 		break;
1003 	    case PORT_CLASS_BIDIRECTIONAL:
1004 		fprintf(f, "INOUT");
1005 		break;
1006 	    case PORT_CLASS_FEEDTHROUGH:
1007 		fprintf(f, "FEEDTHRU");
1008 		break;
1009 	}
1010 	fprintf(f, " ;\n");
1011     }
1012     ispwrrail = FALSE;
1013     if (lab->lab_flags & PORT_USE_MASK)
1014     {
1015 	fprintf(f, IN1 "USE ");
1016 	switch(lab->lab_flags & PORT_USE_MASK)
1017 	{
1018 	    case PORT_USE_SIGNAL:
1019 		fprintf(f, "SIGNAL");
1020 		break;
1021 	    case PORT_USE_ANALOG:
1022 		fprintf(f, "ANALOG");
1023 		break;
1024 	    case PORT_USE_POWER:
1025 		fprintf(f, "POWER");
1026 		ispwrrail = TRUE;
1027 		break;
1028 	    case PORT_USE_GROUND:
1029 		fprintf(f, "GROUND");
1030 		ispwrrail = TRUE;
1031 		break;
1032 	    case PORT_USE_CLOCK:
1033 		fprintf(f, "CLOCK");
1034 		break;
1035 	}
1036 	fprintf(f, " ;\n");
1037     }
1038 #ifdef MAGIC_WRAPPER
1039     else
1040     {
1041 	char *pwr;
1042 
1043 	/* Determine power rails by matching the $VDD and $GND Tcl variables */
1044 
1045 	pwr = (char *)Tcl_GetVar(magicinterp, "VDD", TCL_GLOBAL_ONLY);
1046 	if (pwr && (!strcmp(lab->lab_text, pwr)))
1047 	{
1048 	    ispwrrail = TRUE;
1049 	    fprintf(f, IN1 "USE POWER ;\n");
1050 	}
1051 	pwr = (char *)Tcl_GetVar(magicinterp, "GND", TCL_GLOBAL_ONLY);
1052 	if (pwr && (!strcmp(lab->lab_text, pwr)))
1053 	{
1054 	    ispwrrail = TRUE;
1055 	    fprintf(f, IN1 "USE GROUND ;\n");
1056 	}
1057     }
1058 #endif
1059     if (lab->lab_flags & PORT_SHAPE_MASK)
1060     {
1061 	fprintf(f, IN1 "SHAPE ");
1062 	switch(lab->lab_flags & PORT_SHAPE_MASK)
1063 	{
1064 	    case PORT_SHAPE_ABUT:
1065 		fprintf(f, "ABUTMENT");
1066 		break;
1067 	    case PORT_SHAPE_RING:
1068 		fprintf(f, "RING");
1069 		break;
1070 	    case PORT_SHAPE_THRU:
1071 		fprintf(f, "FEEDTHRU");
1072 		break;
1073 	}
1074 	fprintf(f, " ;\n");
1075     }
1076     return ispwrrail;
1077 }
1078 
1079 /*
1080  * ----------------------------------------------------------------------------
1081  *
1082  * lefWriteMacro --
1083  *
1084  * This routine generates LEF output for a cell in the form of a LEF
1085  * "MACRO" block.  Includes information on cell dimensions, pins,
1086  * ports (physical layout associated with pins), and routing obstructions.
1087  *
1088  * Results:
1089  *	None.
1090  *
1091  * Side effects:
1092  *	Writes output to the open file "f".
1093  *
1094  * ----------------------------------------------------------------------------
1095  */
1096 
1097 void
lefWriteMacro(def,f,scale,setback,pinonly,toplayer,domaster)1098 lefWriteMacro(def, f, scale, setback, pinonly, toplayer, domaster)
1099     CellDef *def;	/* Def for which to generate LEF output */
1100     FILE *f;		/* Output to this file */
1101     float scale;	/* Output distance units conversion factor */
1102     int setback;	/* If >= 0, hide all detail except pins inside setback */
1103     int pinonly;	/* If >= 0, only place pins where labels are defined */
1104     bool toplayer;	/* If TRUE, only output topmost layer of pins */
1105     bool domaster;	/* If TRUE, write masterslice layers */
1106 {
1107     bool propfound, ispwrrail;
1108     char *propvalue, *class = NULL;
1109     Label *lab, *tlab, *reflab;
1110     Rect boundary, labr;
1111     PlaneMask pmask;
1112     SearchContext scx;
1113     CellDef *lefFlatDef;
1114     CellUse lefFlatUse, lefSourceUse;
1115     TileTypeBitMask lmask, boundmask, *lrmask, gatetypemask, difftypemask;
1116     TileType ttype;
1117     lefClient lc;
1118     int idx, pNum, pTop, maxport, curport;
1119     char leffmt[2][10];
1120     char *LEFtext;
1121     HashSearch hs;
1122     HashEntry *he;
1123     labelLinkedList *lll = NULL;
1124 
1125     extern CellDef *SelectDef;
1126 
1127     UndoDisable();
1128 
1129     TxPrintf("Diagnostic:  Writing LEF output for cell %s\n", def->cd_name);
1130 
1131     lefFlatDef = DBCellLookDef("__lefFlat__");
1132     if (lefFlatDef == (CellDef *)NULL)
1133 	lefFlatDef = DBCellNewDef("__lefFlat__");
1134     DBCellSetAvail(lefFlatDef);
1135     lefFlatDef->cd_flags |= CDINTERNAL;
1136 
1137     lefFlatUse.cu_id = StrDup((char **)NULL, "Flattened cell");
1138     lefFlatUse.cu_expandMask = CU_DESCEND_SPECIAL;
1139     lefFlatUse.cu_def = lefFlatDef;
1140     lefFlatUse.cu_parent = (CellDef *)NULL;
1141     lefFlatUse.cu_xlo = 0;
1142     lefFlatUse.cu_ylo = 0;
1143     lefFlatUse.cu_xhi = 0;
1144     lefFlatUse.cu_yhi = 0;
1145     lefFlatUse.cu_xsep = 0;
1146     lefFlatUse.cu_ysep = 0;
1147     lefFlatUse.cu_client = (ClientData)CLIENTDEFAULT;
1148     DBSetTrans(&lefFlatUse, &GeoIdentityTransform);
1149 
1150     lefSourceUse.cu_id = StrDup((char **)NULL, "Source cell");
1151     lefSourceUse.cu_expandMask = CU_DESCEND_ALL;
1152     lefSourceUse.cu_def = def;
1153     lefSourceUse.cu_parent = (CellDef *)NULL;
1154     lefSourceUse.cu_xlo = 0;
1155     lefSourceUse.cu_ylo = 0;
1156     lefSourceUse.cu_xhi = 0;
1157     lefSourceUse.cu_yhi = 0;
1158     lefSourceUse.cu_xsep = 0;
1159     lefSourceUse.cu_ysep = 0;
1160     lefSourceUse.cu_client = (ClientData)CLIENTDEFAULT;
1161     DBSetTrans(&lefSourceUse, &GeoIdentityTransform);
1162 
1163     scx.scx_use = &lefSourceUse;
1164     scx.scx_trans = GeoIdentityTransform;
1165     scx.scx_area = def->cd_bbox;
1166     DBCellCopyAllPaint(&scx, &DBAllButSpaceAndDRCBits, CU_DESCEND_ALL, &lefFlatUse);
1167 
1168     /* Reset scx to point to the flattened use */
1169     scx.scx_use = &lefFlatUse;
1170 
1171     /* Set up client record. */
1172 
1173     lc.file = f;
1174     lc.oscale = scale;
1175     lc.lefMagicMap = defMakeInverseLayerMap(LAYER_MAP_NO_VIAS);
1176     lc.lastType = TT_SPACE;
1177     lc.lefFlat = lefFlatDef;
1178 
1179     TxPrintf("Diagnostic:  Scale value is %f\n", lc.oscale);
1180 
1181     /* Which layers are routing layers are defined in the tech file.	*/
1182 
1183     TTMaskZero(&lc.rmask);
1184     TTMaskZero(&boundmask);
1185     TTMaskZero(&lmask);
1186     pmask = 0;
1187 
1188     /* Any layer which has a port label attached to it should by	*/
1189     /* necessity be considered a routing layer.	 Usually this will not	*/
1190     /* add anything to the mask already created.			*/
1191 
1192     for (lab = def->cd_labels; lab != NULL; lab = lab->lab_next)
1193 	if (lab->lab_flags & PORT_DIR_MASK)
1194 	    TTMaskSetType(&lc.rmask, lab->lab_type);
1195 
1196     HashStartSearch(&hs);
1197     while (he = HashNext(&LefInfo, &hs))
1198     {
1199 	lefLayer *lefl = (lefLayer *)HashGetValue(he);
1200 	if (lefl && (lefl->lefClass == CLASS_ROUTE || lefl->lefClass == CLASS_VIA
1201 		    || (domaster && lefl->lefClass == CLASS_MASTER)))
1202 	{
1203 	    if (lefl->type != -1)
1204 	    {
1205 		TTMaskSetType(&lc.rmask, lefl->type);
1206 		if (DBIsContact(lefl->type))
1207 		{
1208 		    lrmask = DBResidueMask(lefl->type);
1209 		    TTMaskSetMask(&lc.rmask, lrmask);
1210 		}
1211 		if ((lefl->lefClass == CLASS_ROUTE) && (lefl->obsType != -1))
1212 		    TTMaskSetType(&lmask, lefl->type);
1213 	    }
1214 	    if (lefl->obsType != -1)
1215 		TTMaskSetType(&lc.rmask, lefl->obsType);
1216 
1217 	    if (domaster && lefl->lefClass == CLASS_MASTER)
1218 		pmask |= DBTypePlaneMaskTbl[lefl->type];
1219 	}
1220 
1221 	if (lefl && (lefl->lefClass == CLASS_BOUND))
1222 	    if (lefl->type != -1)
1223 		TTMaskSetType(&boundmask, lefl->type);
1224     }
1225 
1226     /* Gate and diff types are determined from the extraction style */
1227     ExtGetGateTypesMask(&gatetypemask);
1228     ExtGetDiffTypesMask(&difftypemask);
1229 
1230     /* NOTE:  This routine corresponds to Envisia LEF/DEF Language	*/
1231     /* Reference version 5.3 (May 31, 2000)				*/
1232 
1233     /* Macro header information (to be completed) */
1234 
1235     fprintf(f, "MACRO %s\n", def->cd_name);
1236 
1237     /* LEF data is stored in the "cd_props" hash table.  If the hash	*/
1238     /* table is NULL or a specific property undefined, then the LEF	*/
1239     /* value takes the default.  Generally, LEF properties which have	*/
1240     /* default values are optional, so in this case we will leave those	*/
1241     /* entries blank.							*/
1242 
1243     propvalue = (char *)DBPropGet(def, "LEFclass", &propfound);
1244     if (propfound)
1245     {
1246 	fprintf(f, IN0 "CLASS %s ;\n", propvalue);
1247 	class = propvalue;
1248     }
1249     else
1250     {
1251 	/* Needs a class of some kind.  Use BLOCK as default if not defined */
1252 	fprintf(f, IN0 "CLASS BLOCK ;\n");
1253     }
1254 
1255     fprintf(f, IN0 "FOREIGN %s ;\n", def->cd_name);
1256 
1257     /* If a boundary class was declared in the LEF section, then use	*/
1258     /* that layer type to define the boundary.  Otherwise, the cell	*/
1259     /* boundary is defined by the magic database.  If the boundary	*/
1260     /* class is used, and the boundary layer corner is not on the	*/
1261     /* origin, then shift all geometry by the difference.		*/
1262 
1263     if (!TTMaskIsZero(&boundmask))
1264     {
1265 	boundary.r_xbot = boundary.r_xtop = 0;
1266 	for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
1267 	    DBSrPaintArea((Tile *)NULL, lefFlatUse.cu_def->cd_planes[pNum],
1268 			&TiPlaneRect, &boundmask, lefGetBound,
1269 			(ClientData)(&boundary));
1270     }
1271     else
1272 	boundary = def->cd_bbox;
1273 
1274     /* If a bounding box has been declared with the FIXED_BBOX property	*/
1275     /* then it takes precedence over def->cd_bbox.			*/
1276 
1277     if (def->cd_flags & CDFIXEDBBOX)
1278     {
1279 	char *propvalue;
1280 	bool found;
1281 
1282 	propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &found);
1283 	if (found)
1284 	    sscanf(propvalue, "%d %d %d %d", &boundary.r_xbot,
1285 		    &boundary.r_ybot, &boundary.r_xtop, &boundary.r_ytop);
1286     }
1287 
1288     /* Check if (boundry less setback) is degenerate.  If so, then	*/
1289     /* there is no effect of the "-hide" option.			*/
1290     if (setback > 0)
1291     {
1292 	if ((boundary.r_xtop - boundary.r_xbot) < (2 * setback)) setback = -1;
1293 	if ((boundary.r_ytop - boundary.r_ybot) < (2 * setback)) setback = -1;
1294     }
1295 
1296     /* Write position and size information */
1297     /* Note:  Using "0.0 - X" prevents fprintf from generating "negative    */
1298     /* zeros" in the output.						    */
1299 
1300     fprintf(f, IN0 "ORIGIN " POINT " ;\n",
1301 		lefPrint(leffmt[0], 0.0 - lc.oscale * (float)boundary.r_xbot),
1302 		lefPrint(leffmt[1], 0.0 - lc.oscale * (float)boundary.r_ybot));
1303 
1304     fprintf(f, IN0 "SIZE " FP " BY " FP " ;\n",
1305 		lefPrint(leffmt[0], lc.oscale * (float)(boundary.r_xtop
1306 				- boundary.r_xbot)),
1307 		lefPrint(leffmt[1], lc.oscale * (float)(boundary.r_ytop
1308 				- boundary.r_ybot)));
1309 
1310     lc.origin.p_x = 0;
1311     lc.origin.p_y = 0;
1312 
1313     propvalue = (char *)DBPropGet(def, "LEFsymmetry", &propfound);
1314     if (propfound)
1315 	fprintf(f, IN0 "SYMMETRY %s ;\n", propvalue);
1316 
1317     propvalue = (char *)DBPropGet(def, "LEFsite", &propfound);
1318     if (propfound)
1319 	fprintf(f, IN0 "SITE %s ;\n", propvalue);
1320 
1321     /* Generate cell for yanking obstructions */
1322 
1323     lc.lefYank = DBCellLookDef("__lefYank__");
1324     if (lc.lefYank == (CellDef *)NULL)
1325     lc.lefYank = DBCellNewDef("__lefYank__");
1326 
1327     DBCellSetAvail(lc.lefYank);
1328     lc.lefYank->cd_flags |= CDINTERNAL;
1329 
1330     /* List of pins (ports) (to be refined?) */
1331 
1332     lc.lefMode = LEF_MODE_PORT;
1333     lc.numWrites = 0;
1334 
1335     /* Determine the maximum port number, then output ports in order */
1336     maxport = -1;
1337     curport = 0;
1338     for (lab = def->cd_labels; lab != NULL; lab = lab->lab_next)
1339 	if (lab->lab_flags & PORT_DIR_MASK)
1340 	{
1341 	    curport++;
1342 	    idx = (int)lab->lab_port;
1343 	    if (idx > maxport)
1344 		maxport = idx;
1345 	}
1346 
1347     if (maxport < 0) lab = def->cd_labels;
1348 
1349     /* Work through pins in port order, if defined, otherwise	*/
1350     /* in order of the label list.				*/
1351 
1352     for (idx = 0; idx < ((maxport < 0) ? curport : maxport + 1); idx++)
1353     {
1354 	if (maxport >= 0)
1355 	{
1356 	    for (lab = def->cd_labels; lab != NULL; lab = lab->lab_next)
1357 		if (lab->lab_flags & PORT_DIR_MASK)
1358 		    if (!(lab->lab_flags & PORT_VISITED))
1359 			if (lab->lab_port == idx)
1360 			    break;
1361 	}
1362 	else
1363 	    while (lab && !(lab->lab_flags & PORT_DIR_MASK)) lab = lab->lab_next;
1364 
1365 	if (lab == NULL) continue;	/* Happens if indexes are skipped */
1366 
1367 	/* Ignore ports which we have already visited (shouldn't happen	*/
1368 	/* unless ports are shorted together).				*/
1369 
1370 	if (lab->lab_flags & PORT_VISITED) continue;
1371 
1372 	/* Query pin geometry for SHAPE (to be done?) */
1373 
1374 	/* Generate port layout geometry using SimSrConnect()		*/
1375 	/* (through the call to SelectNet())				*/
1376 	/*								*/
1377 	/* Selects all electrically-connected material into the		*/
1378 	/* select def.  Output all the layers and geometries of		*/
1379 	/* the select def.						*/
1380 	/*								*/
1381 	/* We use SimSrConnect() and not DBSrConnect() because		*/
1382 	/* SimSrConnect() leaves "marks" (tile->ti_client = 1)		*/
1383 	/* which allows us to later search through all tiles for	*/
1384 	/* anything that is not connected to a port, and generate	*/
1385 	/* an "obstruction" record for it.				*/
1386 	/*								*/
1387 	/* Note: Use DBIsContact() to check if the layer is a VIA.	*/
1388 	/* Presently, I am treating contacts like any other layer.	*/
1389 
1390 	lc.needHeader = TRUE;
1391 	reflab = lab;
1392 
1393 	while (lab != NULL)
1394 	{
1395 	    int antgatearea, antdiffarea;
1396 
1397 	    labr = lab->lab_rect;
1398 
1399 	    /* Deal with degenerate (line or point) labels	*/
1400 	    /* by growing by 1 in each direction.		*/
1401 
1402 	    if (labr.r_xtop - labr.r_xbot == 0)
1403 	    {
1404 		labr.r_xtop++;
1405 		labr.r_xbot--;
1406 	    }
1407 	    if (labr.r_ytop - labr.r_ybot == 0)
1408 	    {
1409 		labr.r_ytop++;
1410 		labr.r_ybot--;
1411 	    }
1412 
1413 	    // Avoid errors caused by labels attached to space or
1414 	    // various technology file issues.
1415 	    TTMaskClearType(&lc.rmask, TT_SPACE);
1416 
1417 	    scx.scx_area = labr;
1418 	    SelectClear();
1419 
1420 	    if (setback == 0)
1421 	    {
1422 		Rect carea;
1423 		labelLinkedList *newlll;
1424 
1425 		if (pinonly == 0)
1426 		    carea = labr;
1427 		else
1428 		{
1429 		    SelectChunk(&scx, lab->lab_type, 0, &carea, FALSE);
1430 		    if (GEO_RECTNULL(&carea)) carea = labr;
1431 		    else if (pinonly > 0)
1432 		    {
1433 			Rect psetback;
1434 			GEO_EXPAND(&boundary, -pinonly, &psetback);
1435 			SelRemoveArea(&psetback, &DBAllButSpaceAndDRCBits, NULL);
1436 		    }
1437 		}
1438 
1439 		/* Note that a sticky label could be placed over multiple   */
1440 		/* tile types, which would cause SelectChunk to fail.  So   */
1441 		/* always paint the label type into the label area in	    */
1442 		/* SelectDef.						    */
1443 
1444 		pNum = DBPlane(lab->lab_type);
1445 		DBPaintPlane(SelectDef->cd_planes[pNum], &carea,
1446 			DBStdPaintTbl(lab->lab_type, pNum), (PaintUndoInfo *) NULL);
1447 
1448 		/* Remember this area since it's going to get erased */
1449 		newlll = (labelLinkedList *)mallocMagic(sizeof(labelLinkedList));
1450 		newlll->lll_label = lab;
1451 		newlll->lll_area = carea;
1452 		newlll->lll_next = lll;
1453 		lll = newlll;
1454 	    }
1455 	    else if (setback > 0)
1456 	    {
1457 		Rect carea;
1458 
1459 		/* For -hide with setback, select the entire net and then   */
1460 		/* remove the part inside the setback area.		    */
1461 
1462 		SelectNet(&scx, lab->lab_type, 0, NULL, FALSE);
1463 		GEO_EXPAND(&boundary, -setback, &carea);
1464 		SelRemoveArea(&carea, &DBAllButSpaceAndDRCBits, NULL);
1465 
1466 		/* Apply any additional setback from the "-pinonly" option */
1467 		if (pinonly > setback)
1468 		{
1469 		    Rect psetback;
1470 		    GEO_EXPAND(&boundary, -pinonly, &psetback);
1471 		    SelRemoveArea(&psetback, &DBAllButSpaceAndDRCBits, NULL);
1472 		}
1473 
1474 		/* Paint over the label area so that labels do not simply   */
1475 		/* disappear by being inside the setback area.		    */
1476 
1477 		pNum = DBPlane(lab->lab_type);
1478 		DBPaintPlane(SelectDef->cd_planes[pNum], &labr,
1479 			DBStdPaintTbl(lab->lab_type, pNum), (PaintUndoInfo *) NULL);
1480 	    }
1481 	    else
1482 	    {
1483 		SelectNet(&scx, lab->lab_type, 0, NULL, FALSE);
1484 
1485 		/* Apply any pin setback */
1486 		if (pinonly >= 0)
1487 		{
1488 		    Rect psetback;
1489 		    GEO_EXPAND(&boundary, -pinonly, &psetback);
1490 		    SelRemoveArea(&psetback, &DBAllButSpaceAndDRCBits, NULL);
1491 
1492 		    /* Paint over the label area so that labels do not simply   */
1493 		    /* disappear by being inside the setback area.		*/
1494 
1495 		    pNum = DBPlane(lab->lab_type);
1496 		    DBPaintPlane(SelectDef->cd_planes[pNum], &labr,
1497 			    DBStdPaintTbl(lab->lab_type, pNum), (PaintUndoInfo *) NULL);
1498 		}
1499 	    }
1500 
1501 	    // Search for gate and diff types and accumulate antenna
1502 	    // areas.  For gates, check for all gate types tied to
1503 	    // devices with MOSFET types (including "msubcircuit", etc.).
1504 	    // For diffusion, use the types declared in the "tiedown"
1505 	    // statement in the extract section of the techfile.
1506 
1507 	    antgatearea = 0;
1508 	    for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
1509 	    {
1510 		DBSrPaintArea((Tile *)NULL, SelectDef->cd_planes[pNum],
1511 			    &TiPlaneRect, &gatetypemask,
1512 			    lefAccumulateArea, (ClientData) &antgatearea);
1513 		// Stop after first plane with geometry to avoid double-counting
1514 		// contacts.
1515 		if (antgatearea > 0) break;
1516 	    }
1517 
1518 	    antdiffarea = 0;
1519 	    for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
1520 	    {
1521 		DBSrPaintArea((Tile *)NULL, SelectDef->cd_planes[pNum],
1522 			    &TiPlaneRect, &difftypemask,
1523 			    lefAccumulateArea, (ClientData) &antdiffarea);
1524 		// Stop after first plane with geometry to avoid double-counting
1525 		// contacts.
1526 		if (antdiffarea > 0) break;
1527 	    }
1528 
1529 	    if (toplayer)
1530 	    {
1531 		for (pTop = DBNumPlanes - 1; pTop >= PL_TECHDEPBASE; pTop--)
1532 		{
1533 		    if (DBSrPaintArea((Tile *)NULL, SelectDef->cd_planes[pTop],
1534 			    &TiPlaneRect, &DBAllButSpaceAndDRCBits,
1535 			    lefFindTopmost, (ClientData)NULL) == 1)
1536 			break;
1537 		}
1538 	    }
1539 
1540 	    // For all geometry in the selection, write LEF records,
1541 	    // and mark the corresponding tiles in lefFlatDef as
1542 	    // visited.
1543 
1544 	    lc.numWrites = 0;
1545 	    lc.lastType = TT_SPACE;
1546 	    for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
1547 	    {
1548 		/* Option to output only the topmost layer of a network	*/
1549 		/* as PIN geometry.  All layers below it are considered	*/
1550 		/* obstructions.  Masterslice layers are considered an	*/
1551 		/* exception, as they are often needed for ensuring	*/
1552 		/* connectivity between power supply and wells.		*/
1553 
1554 		if (toplayer && (pNum != pTop))
1555 		{
1556 		    if (domaster & (pmask != 0))
1557 		    {
1558 			if (!PlaneMaskHasPlane(pmask, pNum))
1559 			    continue;
1560 		    }
1561 		    else continue;
1562 		}
1563 
1564 		lc.pNum = pNum;
1565 		DBSrPaintArea((Tile *)NULL, SelectDef->cd_planes[pNum],
1566 			&TiPlaneRect, &DBAllButSpaceAndDRCBits,
1567 			lefYankGeometry, (ClientData) &lc);
1568 
1569 		while (DBSrPaintArea((Tile *)NULL, lc.lefYank->cd_planes[pNum],
1570 	    		&TiPlaneRect, &lc.rmask,
1571 	    		lefWriteGeometry, (ClientData) &lc) == 1)
1572 		{
1573 		    /* needHeader was set and there was something to write, */
1574 		    /* so write the header and then re-run the search.	    */
1575 
1576 		    ispwrrail = LefWritePinHeader(f, lab);
1577 		    if (ispwrrail == FALSE)
1578 		    {
1579 			if (antgatearea > 0)
1580 			    fprintf(f, IN1 "ANTENNAGATEAREA %f ;\n",
1581 				    lc.oscale * lc.oscale * (float)antgatearea);
1582 			if (antdiffarea > 0)
1583 			    fprintf(f, IN1 "ANTENNADIFFAREA %f ;\n",
1584 				    lc.oscale * lc.oscale * (float)antdiffarea);
1585 		    }
1586 		    lc.needHeader = FALSE;
1587 		}
1588 
1589 		DBSrPaintArea((Tile *)NULL, SelectDef->cd_planes[pNum],
1590 			&TiPlaneRect, &DBAllButSpaceAndDRCBits,
1591 			lefEraseGeometry, (ClientData) &lc);
1592 
1593 		/* Second round yank & write, for contacts only */
1594 
1595 	        lc.lefMode = LEF_MODE_CONTACT;
1596 		DBSrPaintArea((Tile *)NULL, SelectDef->cd_planes[pNum],
1597 			&TiPlaneRect, &DBAllButSpaceAndDRCBits,
1598 			lefYankContacts, (ClientData) &lc);
1599 
1600 		DBSrPaintArea((Tile *)NULL, lc.lefYank->cd_planes[pNum],
1601 	    		&TiPlaneRect, &lc.rmask,
1602 	    		lefWriteGeometry, (ClientData) &lc);
1603 	        lc.lefMode = LEF_MODE_PORT;
1604 	    }
1605 
1606 	    /* Check if any other ports are already contained in this selection.    */
1607 	    /* If so, mark them as visited.  Use lefFindTopmost(), which is just a  */
1608 	    /* routine that stops the search by returning 1 when something is found */
1609 
1610 	    for (tlab = lab->lab_next; tlab != (Label *)NULL; tlab = tlab->lab_next)
1611 		if (tlab->lab_flags & PORT_DIR_MASK)
1612 		    if (!(tlab->lab_flags & PORT_VISITED))
1613 			if (tlab->lab_port == idx)
1614 			{
1615 			    TileTypeBitMask lmask;
1616 			    TTMaskSetOnlyType(&lmask, tlab->lab_type);
1617 			    pNum = DBPlane(tlab->lab_type);
1618 			    if (DBSrPaintArea((Tile *)NULL, lc.lefYank->cd_planes[pNum],
1619 				    &tlab->lab_rect, &lmask,
1620 				    lefFindTopmost, (ClientData)NULL))
1621 				tlab->lab_flags |= PORT_VISITED;
1622 
1623 			    /* For the "toplayer" option, ports on lower layers will not be */
1624 			    /* in the yank buffer but will still be in the selection.	    */
1625 			    else if (toplayer)
1626 				if (DBSrPaintArea((Tile *)NULL, SelectDef->cd_planes[pNum],
1627 					    &tlab->lab_rect, &lmask,
1628 					    lefFindTopmost, (ClientData)NULL))
1629 				    tlab->lab_flags |= PORT_VISITED;
1630 			}
1631 
1632 	    DBCellClearDef(lc.lefYank);
1633 	    lab->lab_flags |= PORT_VISITED;
1634 
1635 	    /* Check if any other unvisited ports belong to this pin */
1636 
1637 	    for (; lab != NULL; lab = lab->lab_next)
1638 		if (lab->lab_flags & PORT_DIR_MASK)
1639 		    if (!(lab->lab_flags & PORT_VISITED))
1640 			if (lab->lab_port == idx)
1641 			    break;
1642 
1643 	    if (lc.numWrites > 0)
1644 		fprintf(f, IN1 "END\n");	/* end of port geometries */
1645 	    lc.numWrites = 0;
1646 	}
1647 
1648 	LEFtext = MakeLegalLEFSyntax(reflab->lab_text);
1649 	if (lc.needHeader == FALSE)
1650 	    fprintf(f, IN0 "END %s\n", reflab->lab_text);	/* end of pin */
1651 	if (LEFtext != reflab->lab_text) freeMagic(LEFtext);
1652 
1653 	if (maxport >= 0)
1654 	{
1655 	    /* Sanity check to see if port number is a duplicate.  ONLY */
1656 	    /* flag this if the other index has a different text, as it	*/
1657 	    /* is perfectly legal to have multiple ports with the same	*/
1658 	    /* name and index.						*/
1659 
1660 	    for (tlab = reflab->lab_next; tlab != NULL; tlab = tlab->lab_next)
1661 	    {
1662 		if (tlab->lab_flags & PORT_DIR_MASK)
1663 		    if (tlab->lab_port == idx)
1664 			if (strcmp(reflab->lab_text, tlab->lab_text))
1665 			{
1666 			    TxError("Index %d is used for ports \"%s\" and \"%s\"\n",
1667 					idx, reflab->lab_text, tlab->lab_text);
1668 			    idx--;
1669 			}
1670 	    }
1671 	}
1672 	else
1673 	    lab = reflab->lab_next;
1674     }
1675 
1676     /* Clear all PORT_VISITED bits in labels */
1677     for (lab = def->cd_labels; lab != NULL; lab = lab->lab_next)
1678 	if (lab->lab_flags & PORT_DIR_MASK)
1679 	    lab->lab_flags &= ~(PORT_VISITED);
1680 
1681     /* List of routing obstructions */
1682 
1683     lc.lefMode = LEF_MODE_OBSTRUCT;
1684     lc.lastType = TT_SPACE;
1685     lc.needHeader = FALSE;
1686 
1687     /* Restrict to routing planes only */
1688 
1689     if (setback >= 0)
1690     {
1691 	/* If details of the cell are to be hidden, then first paint	*/
1692 	/* all route layers with an obstruction rectangle the size of	*/
1693 	/* the cell bounding box.  Then recompute the label chunk	*/
1694 	/* regions used above to write the ports, expand each chunk by	*/
1695 	/* the route metal spacing width, and erase that area from the	*/
1696 	/* obstruction.	 For the obstruction boundary, find the extent	*/
1697 	/* of paint on the layer, not the LEF macro boundary, since	*/
1698 	/* paint may extend beyond the boundary, and sometimes the	*/
1699 	/* boundary may extend beyond the paint.  To be done:  make	*/
1700 	/* sure that every pin has a legal path to the outside of the	*/
1701 	/* cell.  Otherwise, this routine can block internal pins.	*/
1702 
1703 	Rect layerBound;
1704 	labelLinkedList *thislll;
1705 
1706 	for (ttype = TT_TECHDEPBASE; ttype < DBNumTypes; ttype++)
1707 	    if (TTMaskHasType(&lmask, ttype))
1708 	    {
1709 		Rect r;
1710 		layerBound.r_xbot = layerBound.r_xtop = 0;
1711 		for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
1712 		    if (TTMaskHasType(&DBPlaneTypes[pNum], ttype))
1713 		    {
1714 			DBSrPaintArea((Tile *)NULL, lefFlatUse.cu_def->cd_planes[pNum],
1715 				&TiPlaneRect, &DBAllButSpaceAndDRCBits,
1716 				lefGetBound, (ClientData)(&layerBound));
1717 		    }
1718 
1719 		/* Clip layerBound to setback boundary */
1720 		GEO_EXPAND(&boundary, -setback, &r);
1721 		GeoClip(&layerBound, &r);
1722 
1723 		DBPaint(lc.lefYank, &layerBound, ttype);
1724 	    }
1725 
1726 	for (thislll = lll; thislll; thislll = thislll->lll_next)
1727 	{
1728 	    int mspace;
1729 
1730 	    lab = thislll->lll_label;
1731 
1732 	    /* Look for wide spacing rules.  If there are no wide spacing   */
1733 	    /* rules, then fall back on the default spacing rule.	    */
1734 	    mspace = DRCGetDefaultWideLayerSpacing(lab->lab_type, (int)1E6);
1735 	    if (mspace == 0)
1736 		mspace = DRCGetDefaultLayerSpacing(lab->lab_type, lab->lab_type);
1737 
1738 	    thislll->lll_area.r_xbot -= mspace;
1739 	    thislll->lll_area.r_ybot -= mspace;
1740 	    thislll->lll_area.r_xtop += mspace;
1741 	    thislll->lll_area.r_ytop += mspace;
1742 
1743 	    DBErase(lc.lefYank, &thislll->lll_area, lab->lab_type);
1744 	    freeMagic(thislll);
1745 	}
1746 
1747 	if (setback >= 0)
1748 	{
1749 	    /* For -hide with setback, yank everything in the area outside  */
1750 	    /* the setback.						    */
1751 
1752 	    for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
1753 	    {
1754 		Rect r;
1755 		lc.pNum = pNum;
1756 
1757 		r = def->cd_bbox;
1758 		r.r_ytop = boundary.r_ybot + setback;
1759 		DBSrPaintArea((Tile *)NULL, lefFlatDef->cd_planes[pNum],
1760 			&r, &DBAllButSpaceAndDRCBits,
1761 			lefYankGeometry, (ClientData) &lc);
1762 		r = def->cd_bbox;
1763 		r.r_ybot = boundary.r_ytop - setback;
1764 		DBSrPaintArea((Tile *)NULL, lefFlatDef->cd_planes[pNum],
1765 			&r, &DBAllButSpaceAndDRCBits,
1766 			lefYankGeometry, (ClientData) &lc);
1767 		r = def->cd_bbox;
1768 		r.r_ybot = boundary.r_ybot + setback;
1769 		r.r_ytop = boundary.r_ytop - setback;
1770 		r.r_xtop = boundary.r_xbot + setback;
1771 		DBSrPaintArea((Tile *)NULL, lefFlatDef->cd_planes[pNum],
1772 			&r, &DBAllButSpaceAndDRCBits,
1773 			lefYankGeometry, (ClientData) &lc);
1774 		r = def->cd_bbox;
1775 		r.r_ybot = boundary.r_ybot + setback;
1776 		r.r_ytop = boundary.r_ytop - setback;
1777 		r.r_xbot = boundary.r_xtop - setback;
1778 		DBSrPaintArea((Tile *)NULL, lefFlatDef->cd_planes[pNum],
1779 			&r, &DBAllButSpaceAndDRCBits,
1780 			lefYankGeometry, (ClientData) &lc);
1781 	    }
1782 	}
1783     }
1784     else
1785     {
1786 	for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
1787 	{
1788 	    lc.pNum = pNum;
1789 	    DBSrPaintArea((Tile *)NULL, lefFlatDef->cd_planes[pNum],
1790 			&TiPlaneRect, &DBAllButSpaceAndDRCBits,
1791 			lefYankGeometry, (ClientData) &lc);
1792 	}
1793     }
1794 
1795     /* Write all the geometry just generated */
1796 
1797     for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
1798     {
1799 	lc.pNum = pNum;
1800 	DBSrPaintArea((Tile *)NULL, lc.lefYank->cd_planes[pNum],
1801 		&TiPlaneRect, &lc.rmask,
1802 		lefWriteGeometry, (ClientData) &lc);
1803 
1804 	/* Additional yank & write for contacts (although ignore contacts for -hide) */
1805 	if (setback < 0)
1806 	{
1807 	    lc.lefMode = LEF_MODE_OBS_CONTACT;
1808 	    DBSrPaintArea((Tile *)NULL, lefFlatDef->cd_planes[pNum],
1809 			&TiPlaneRect, &DBAllButSpaceAndDRCBits,
1810 			lefYankContacts, (ClientData) &lc);
1811 	    DBSrPaintArea((Tile *)NULL, lc.lefYank->cd_planes[pNum],
1812 			&TiPlaneRect, &lc.rmask,
1813 			lefWriteGeometry, (ClientData) &lc);
1814 	    lc.lefMode = LEF_MODE_OBSTRUCT;
1815 	}
1816 	else if (setback > 0)
1817 	{
1818 	    Rect r;
1819 
1820 	    /* Apply only to area outside setback. */
1821 	    lc.lefMode = LEF_MODE_OBS_CONTACT;
1822 
1823 	    r = def->cd_bbox;
1824 	    r.r_ytop = boundary.r_ybot + setback;
1825 	    DBSrPaintArea((Tile *)NULL, lefFlatDef->cd_planes[pNum],
1826 			&r, &DBAllButSpaceAndDRCBits,
1827 			lefYankContacts, (ClientData) &lc);
1828 	    DBSrPaintArea((Tile *)NULL, lc.lefYank->cd_planes[pNum],
1829 			&r, &lc.rmask, lefWriteGeometry, (ClientData) &lc);
1830 
1831 	    r = def->cd_bbox;
1832 	    r.r_ybot = boundary.r_ytop - setback;
1833 	    DBSrPaintArea((Tile *)NULL, lefFlatDef->cd_planes[pNum],
1834 			&r, &DBAllButSpaceAndDRCBits,
1835 			lefYankContacts, (ClientData) &lc);
1836 	    DBSrPaintArea((Tile *)NULL, lc.lefYank->cd_planes[pNum],
1837 			&r, &lc.rmask, lefWriteGeometry, (ClientData) &lc);
1838 
1839 	    r = def->cd_bbox;
1840 	    r.r_ybot = boundary.r_ybot + setback;
1841 	    r.r_ytop = boundary.r_ytop - setback;
1842 	    r.r_xtop = boundary.r_xbot + setback;
1843 	    DBSrPaintArea((Tile *)NULL, lefFlatDef->cd_planes[pNum],
1844 			&r, &DBAllButSpaceAndDRCBits,
1845 			lefYankContacts, (ClientData) &lc);
1846 	    DBSrPaintArea((Tile *)NULL, lc.lefYank->cd_planes[pNum],
1847 			&r, &lc.rmask, lefWriteGeometry, (ClientData) &lc);
1848 
1849 	    r = def->cd_bbox;
1850 	    r.r_ybot = boundary.r_ybot + setback;
1851 	    r.r_ytop = boundary.r_ytop - setback;
1852 	    r.r_xbot = boundary.r_xtop - setback;
1853 	    DBSrPaintArea((Tile *)NULL, lefFlatDef->cd_planes[pNum],
1854 			&r, &DBAllButSpaceAndDRCBits,
1855 			lefYankContacts, (ClientData) &lc);
1856 	    DBSrPaintArea((Tile *)NULL, lc.lefYank->cd_planes[pNum],
1857 			&r, &lc.rmask, lefWriteGeometry, (ClientData) &lc);
1858 
1859 	    lc.lefMode = LEF_MODE_OBSTRUCT;
1860 	}
1861     }
1862 
1863     if (lc.numWrites > 0)
1864 	fprintf(f, IN0 "END\n");	/* end of obstruction geometries */
1865 
1866     /* If there are any properties saved in LEFproperties, write them out */
1867 
1868     propvalue = (char *)DBPropGet(def, "LEFproperties", &propfound);
1869     if (propfound)
1870     {
1871 	char *delim;
1872 	char *propfind = propvalue;
1873 	bool endfound = FALSE;
1874 
1875 	/* Properties are in space-separated key:value pairs.	*/
1876 	/* The value is in quotes and may contain spaces.	*/
1877 	/* One PROPERTY line is written per key:value pair.	*/
1878 
1879 	while (*propfind != '\0')
1880 	{
1881 	    char dsave;
1882 
1883 	    delim = propfind;
1884 	    while (*delim != ' ' && *delim != '\0') delim++;
1885 	    if (*delim == '\0') break;
1886 	    while (*delim == ' ' && *delim != '\0') delim++;
1887 	    if (*delim == '\0') break;
1888 	    if (*delim == '\"')
1889 	    {
1890 		delim++;
1891 		while (*delim != '\"' && *delim != '\0') delim++;
1892 		if (*delim == '\0') break;
1893 		delim++;
1894 	    }
1895 	    else
1896 		while (*delim != ' ' && *delim != '\0') delim++;
1897 
1898 	    if (*delim == '\0') endfound = TRUE;
1899 	    dsave = *delim;
1900 	    *delim = '\0';
1901 	    fprintf(f, IN0 "PROPERTY %s ;\n", propfind);
1902 	    *delim = dsave;
1903 	    if (endfound) break;
1904 	    while (*delim == ' ' && *delim != '\0') delim++;
1905 	    propfind = delim;
1906 	}
1907     }
1908 
1909     fprintf(f, "END %s\n", def->cd_name);	/* end of macro */
1910 
1911     SigDisableInterrupts();
1912     freeMagic(lc.lefMagicMap);
1913     DBCellClearDef(lc.lefYank);
1914     DBCellClearDef(lefFlatDef);
1915     freeMagic(lefSourceUse.cu_id);
1916     freeMagic(lefFlatUse.cu_id);
1917     SelectClear();
1918     SigEnableInterrupts();
1919 
1920     UndoEnable();
1921 }
1922 
1923 /*
1924  *------------------------------------------------------------
1925  *
1926  * lefGetSites ---
1927  *
1928  *	Pull SITE instances from multiple cells into a list of
1929  *	unique entries to be written to the LEF header of an
1930  *	output LEF file.
1931  *
1932  *------------------------------------------------------------
1933  */
1934 int
lefGetSites(stackItem,i,clientData)1935 lefGetSites(stackItem, i, clientData)
1936     ClientData stackItem;
1937     int i;
1938     ClientData clientData;
1939 {
1940     CellDef *def = (CellDef *)stackItem;
1941     HashTable *lefSiteTbl = (HashTable *)clientData;
1942     HashEntry *he;
1943     bool propfound;
1944     char *propvalue;
1945 
1946     propvalue = (char *)DBPropGet(def, "LEFsite", &propfound);
1947     if (propfound)
1948 	he = HashFind(lefSiteTbl, propvalue);
1949 
1950     return 0;
1951 }
1952 
1953 /*
1954  *------------------------------------------------------------
1955  *
1956  * lefGetProperties ---
1957  *
1958  *	Pull property definitions from multiple cells into
1959  *	a list of unique entries to be written to the
1960  *	PROPERTYDEFINITIONS block in an output LEF file.
1961  *
1962  *------------------------------------------------------------
1963  */
1964 int
lefGetProperties(stackItem,i,clientData)1965 lefGetProperties(stackItem, i, clientData)
1966     ClientData stackItem;
1967     int i;
1968     ClientData clientData;
1969 {
1970     CellDef *def = (CellDef *)stackItem;
1971     HashTable *lefPropTbl = (HashTable *)clientData;
1972     HashEntry *he;
1973     bool propfound;
1974     char *propvalue;
1975 
1976     propvalue = (char *)DBPropGet(def, "LEFproperties", &propfound);
1977     if (propfound)
1978     {
1979 	char *key;
1980 	char *psrch;
1981 	char *value;
1982 
1983 	psrch = propvalue;
1984 	while (*psrch != '\0')
1985 	{
1986 	    key = psrch;
1987 	    while (*psrch != ' ' && *psrch != '\0') psrch++;
1988 	    if (*psrch == '\0') break;
1989 	    *psrch = '\0';
1990 	    he = HashFind(lefPropTbl, key);
1991 
1992 	    /* Potentially to do:  Handle INT and REAL types */
1993 	    /* For now, only STRING properties are handled.  */
1994 
1995 	    *psrch = ' ';
1996 	    psrch++;
1997 	    while (*psrch == ' ' && *psrch != '\0') psrch++;
1998 	    value = psrch;
1999 	    if (*psrch == '\0') break;
2000 	    if (*psrch == '\"')
2001 	    {
2002 		psrch++;
2003 		while (*psrch != '\"' && *psrch != '\0') psrch++;
2004 		if (*psrch == '\0') break;
2005 		psrch++;
2006 	    }
2007 	    else
2008 	    {
2009 		psrch++;
2010 		while (*psrch != ' ' && *psrch != '\0') psrch++;
2011 	    }
2012 	    if (*psrch == '\0') break;
2013 	    psrch++;
2014 	}
2015     }
2016     return 0;
2017 }
2018 
2019 /*
2020  *------------------------------------------------------------
2021  *
2022  * LefWriteAll --
2023  *
2024  *	Write LEF-format output for each cell, beginning with
2025  *	the top-level cell use "rootUse".
2026  *
2027  * Results:
2028  *	None.
2029  *
2030  * Side effects:
2031  *	Writes a .lef file to disk.
2032  *
2033  *------------------------------------------------------------
2034  */
2035 
2036 void
LefWriteAll(rootUse,writeTopCell,lefTech,lefHide,lefPinOnly,lefTopLayer,lefDoMaster,recurse)2037 LefWriteAll(rootUse, writeTopCell, lefTech, lefHide, lefPinOnly, lefTopLayer,
2038 	    lefDoMaster, recurse)
2039     CellUse *rootUse;
2040     bool writeTopCell;
2041     bool lefTech;
2042     int lefHide;
2043     int lefPinOnly;
2044     bool lefTopLayer;
2045     bool lefDoMaster;
2046     bool recurse;
2047 {
2048     HashTable propHashTbl, siteHashTbl;
2049     CellDef *def, *rootdef;
2050     FILE *f;
2051     char *filename;
2052     float scale = CIFGetOutputScale(1000);	/* conversion to microns */
2053 
2054     rootdef = rootUse->cu_def;
2055 
2056     /* Make sure the entire subtree is read in */
2057     if (DBCellReadArea(rootUse, &rootdef->cd_bbox, TRUE))
2058     {
2059 	TxError("Could not read entire subtree of the cell.\n");
2060 	return;
2061     }
2062 
2063     /* Fix up bounding boxes if they've changed */
2064     DBFixMismatch();
2065 
2066     /* Mark all defs as being unvisited */
2067     (void) DBCellSrDefs(0, lefDefInitFunc, (ClientData) 0);
2068 
2069     /* Recursively visit all defs in the tree and push on stack */
2070     /* If "recurse" is false, then only the children of the root use	*/
2071     /* are pushed (this is the default behavior).			*/
2072     lefDefStack = StackNew(100);
2073     if (writeTopCell)
2074 	lefDefPushFunc(rootUse, (bool *)NULL);
2075     DBCellEnum(rootUse->cu_def, lefDefPushFunc, (ClientData)&recurse);
2076 
2077     /* Open the file for output */
2078 
2079     f = lefFileOpen(rootdef, (char *)NULL, ".lef", "w", &filename);
2080 
2081     TxPrintf("Generating LEF output %s for hierarchy rooted at cell %s:\n",
2082 		filename, rootdef->cd_name);
2083 
2084     if (f == NULL)
2085     {
2086 #ifdef MAGIC_WRAPPER
2087 	TxError("Cannot open output file %s (%s).\n", filename,
2088 		strerror(errno));
2089 #else
2090 	TxError("Cannot open output file: ");
2091 	perror(filename);
2092 #endif
2093 	return;
2094     }
2095 
2096     /* For all cells, collect any properties */
2097     HashInit(&propHashTbl, 4, HT_STRINGKEYS);
2098     StackEnum(lefDefStack, lefGetProperties, &propHashTbl);
2099 
2100     /* For all cells, collect any sites */
2101     HashInit(&siteHashTbl, 4, HT_STRINGKEYS);
2102     StackEnum(lefDefStack, lefGetSites, &siteHashTbl);
2103 
2104     /* Now generate LEF output for all the cells we just found */
2105 
2106     lefWriteHeader(rootdef, f, lefTech, &propHashTbl, &siteHashTbl);
2107 
2108     HashKill(&propHashTbl);
2109     HashKill(&siteHashTbl);
2110 
2111     while (def = (CellDef *) StackPop(lefDefStack))
2112     {
2113 	def->cd_client = (ClientData) 0;
2114 	if (!SigInterruptPending)
2115 	    lefWriteMacro(def, f, scale, lefHide, lefPinOnly, lefTopLayer, lefDoMaster);
2116     }
2117 
2118     /* End the LEF file */
2119     fprintf(f, "END LIBRARY\n\n");
2120 
2121     fclose(f);
2122     StackFree(lefDefStack);
2123 }
2124 
2125 /*
2126  * Function to initialize the client data field of all
2127  * cell defs, in preparation for generating LEF output
2128  * for a subtree rooted at a particular def.
2129  */
2130 
2131 int
lefDefInitFunc(def)2132 lefDefInitFunc(def)
2133     CellDef *def;
2134 {
2135     def->cd_client = (ClientData) 0;
2136     return (0);
2137 }
2138 
2139 /*
2140  * Function to push each cell def on lefDefStack
2141  * if it hasn't already been pushed, and then recurse
2142  * on all that def's children.
2143  */
2144 
2145 int
lefDefPushFunc(use,recurse)2146 lefDefPushFunc(use, recurse)
2147     CellUse *use;
2148     bool *recurse;
2149 {
2150     CellDef *def = use->cu_def;
2151 
2152     if (def->cd_client || (def->cd_flags & CDINTERNAL))
2153 	return (0);
2154 
2155     def->cd_client = (ClientData) 1;
2156     StackPush((ClientData) def, lefDefStack);
2157     if (recurse && (*recurse))
2158 	(void) DBCellEnum(def, lefDefPushFunc, (ClientData)recurse);
2159     return (0);
2160 }
2161 
2162 /*
2163  *------------------------------------------------------------
2164  *
2165  * LefWriteCell --
2166  *
2167  *	Write LEF-format output for the indicated cell.
2168  *
2169  * Results:
2170  *	None.
2171  *
2172  * Side effects:
2173  *	Writes a single .lef file to disk.
2174  *
2175  *------------------------------------------------------------
2176  */
2177 
2178 void
LefWriteCell(def,outName,isRoot,lefTech,lefHide,lefPinOnly,lefTopLayer,lefDoMaster)2179 LefWriteCell(def, outName, isRoot, lefTech, lefHide, lefPinOnly, lefTopLayer,
2180 	    lefDoMaster)
2181     CellDef *def;		/* Cell being written */
2182     char *outName;		/* Name of output file, or NULL. */
2183     bool isRoot;		/* Is this the root cell? */
2184     bool lefTech;		/* Output layer information if TRUE */
2185     int  lefHide;		/* Hide detail other than pins if >= 0 */
2186     int  lefPinOnly;		/* Only generate pins on label areas */
2187     bool lefTopLayer;		/* Use only topmost layer of pin if TRUE */
2188     bool lefDoMaster;		/* Write masterslice layers if TRUE */
2189 {
2190     char *filename;
2191     FILE *f;
2192     float scale = CIFGetOutputScale(1000);
2193 
2194     f = lefFileOpen(def, outName, ".lef", "w", &filename);
2195 
2196     TxPrintf("Generating LEF output %s for cell %s:\n", filename, def->cd_name);
2197 
2198     if (f == NULL)
2199     {
2200 #ifdef MAGIC_WRAPPER
2201 	TxError("Cannot open output file %s (%s).\n", filename,
2202 		strerror(errno));
2203 #else
2204 	TxError("Cannot open output file: ");
2205 	perror(filename);
2206 #endif
2207 	return;
2208     }
2209 
2210     if (isRoot)
2211     {
2212 	HashTable propHashTbl, siteHashTbl;
2213 
2214 	HashInit(&propHashTbl, 4, HT_STRINGKEYS);
2215 	lefGetProperties((ClientData)def, 0, (ClientData)&propHashTbl);
2216 	HashInit(&siteHashTbl, 4, HT_STRINGKEYS);
2217 	lefGetSites((ClientData)def, 0, (ClientData)&siteHashTbl);
2218 	lefWriteHeader(def, f, lefTech, &propHashTbl, &siteHashTbl);
2219 	HashKill(&propHashTbl);
2220 	HashKill(&siteHashTbl);
2221     }
2222     lefWriteMacro(def, f, scale, lefHide, lefPinOnly, lefTopLayer, lefDoMaster);
2223 
2224     /* End the LEF file */
2225     fprintf(f, "END LIBRARY\n\n");
2226 
2227     fclose(f);
2228 }
2229 
2230