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