1 /*
2  * defWrite.c --
3  *
4  * This module incorporates the LEF/DEF format for standard-cell place and
5  * route.
6  *
7  *
8  * Version 0.1 (June 9, 2004):  DEF output for layouts, to include netlist
9  * from the extracted layout.
10  *
11  */
12 
13 #ifndef lint
14 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/lef/defWrite.c,v 1.2 2008/02/10 19:30:21 tim Exp $";
15 #endif  /* not lint */
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <errno.h>
21 
22 #include "tcltk/tclmagic.h"
23 #include "utils/magic.h"
24 #include "utils/geometry.h"
25 #include "tiles/tile.h"
26 #include "utils/hash.h"
27 #include "database/database.h"
28 #include "utils/tech.h"
29 #include "utils/malloc.h"
30 #include "utils/undo.h"
31 #include "cif/cif.h"
32 #include "extflat/extflat.h"
33 #include "lef/lefInt.h"
34 #include "drc/drc.h"		/* for querying width,spacing rules */
35 
36 /*----------------------------------------------------------------------*/
37 /* Structures used by various routines					*/
38 /*----------------------------------------------------------------------*/
39 
40 typedef struct {
41    float	scale;
42    FILE		*f;
43    CellDef	*def;
44 
45    Tile		*tile;		/* Values of the last calculated route */
46    TileType	type;
47    float	x, y, extlen;
48    unsigned char orient;
49 
50    LefMapping	*MagicToLefTbl;
51    int		outcolumn;	/* Current column of output in file */
52    unsigned char specialmode;	/* What nets to write as SPECIALNETS */
53 } DefData;
54 
55 typedef struct {
56    float scale;
57    int total;
58    int plane;
59    TileTypeBitMask *mask;
60    LefMapping *MagicToLefTbl;
61 } CViaData;
62 
63 /*----------------------------------------------------------------------*/
64 
65 char *defGetType();		/* Forward declaration */
66 
67 /*----------------------------------------------------------------------*/
68 
69 
70 /*
71  * ----------------------------------------------------------------------------
72  *
73  * defWriteHeader --
74  *
75  * This routine generates DEF header output for a cell or cell hierarchy.
76  *
77  * Results:
78  *	None.
79  *
80  * Side effects:
81  *	Writes output to the open file "f".
82  *
83  * ----------------------------------------------------------------------------
84  */
85 
86 void
defWriteHeader(def,f,oscale,units)87 defWriteHeader(def, f, oscale, units)
88     CellDef *def;	/* Def for which to generate DEF output */
89     FILE *f;		/* Output to this file */
90     float oscale;
91     int units;		/* Units for UNITS; could be derived from oscale */
92 {
93     TileType type;
94 
95     TxPrintf("Diagnostic:  Write DEF header for cell %s\n", def->cd_name);
96 
97     /* NOTE:  This routine corresponds to Envisia LEF/DEF Language	*/
98     /* Reference version 5.7 (November, 2009)				*/
99 
100     fprintf(f, "VERSION 5.7 ;\n");
101     fprintf(f, "   NAMESCASESENSITIVE ON ;\n");
102     fprintf(f, "   DIVIDERCHAR \"/\" ;\n");
103 
104     /* Declare that buses are denoted with parentheses, since magic	*/
105     /* uses brackets for arrays and instances.				*/
106     fprintf(f, "   BUSBITCHARS \"()\" ;\n");
107 
108     /* Design name, taken from the cell def name */
109     fprintf(f, "   DESIGN %s ;\n", def->cd_name);
110 
111     /* Technology name, taken from the magic tech file.			*/
112     /* (which may not be a good idea. . .  may need a tech definition	*/
113     /* in the tech file "lef" section to specifically name the LEF/DEF	*/
114     /* technology).							*/
115     fprintf(f, "   TECHNOLOGY %s ;\n", DBTechName);
116 
117     /* The DEF scalefactor (conversion to microns) is always 1000	*/
118     /* (nanometers) unless overridden on the command line.		*/
119 
120     fprintf(f, "   UNITS DISTANCE MICRONS %d ;\n", units);
121 
122     /* Die area, taken from the cell def bounding box.			*/
123     fprintf(f, "   DIEAREA ( %.10g %.10g ) ( %.10g %.10g ) ;\n",
124 	(float)def->cd_bbox.r_xbot * oscale,
125 	(float)def->cd_bbox.r_ybot * oscale,
126 	(float)def->cd_bbox.r_xtop * oscale,
127 	(float)def->cd_bbox.r_ytop * oscale);
128 
129     fprintf(f, "\n");
130 }
131 
132 /*
133  *------------------------------------------------------------
134  *
135  * defTransPos --
136  *
137  *	Determine the DEF orientation of a specific magic
138  *	transformation matrix.
139  *
140  * Results:
141  *	The position, in DEF string format ("N" for north, etc.)
142  *	This is a static string
143  *
144  * Side Effects:
145  *	None.
146  *
147  *------------------------------------------------------------
148  */
149 
150 char *
defTransPos(Transform * t)151 defTransPos(Transform *t)
152 {
153     static char *def_orient[] = {
154 	"N", "S", "E", "W", "FN", "FS", "FE", "FW"
155     };
156 
157     bool ew;  /* east-or-west identifier */
158     bool sw;  /* south-or-west identifier */
159     bool flip;
160     int pos = 0;
161 
162     ew = ((t->t_a == 0) && (t->t_e == 0)) ? TRUE : FALSE;
163     if (ew)
164     {
165        flip = ((t->t_b * t->t_d) > 0) ? TRUE : FALSE;
166        sw = (t->t_d > 0) ? TRUE : FALSE;
167     }
168     else
169     {
170        flip = ((t->t_a * t->t_e) < 0) ? TRUE : FALSE;
171        sw = (t->t_e > 0) ? FALSE : TRUE;
172     }
173 
174     if (flip) pos += 4;
175     if (ew) pos += 2;
176     if (sw) pos += 1;
177 
178     return def_orient[pos];
179 }
180 
181 /*
182  *------------------------------------------------------------
183  *
184  * defCountNets --
185  *
186  *	First-pass function to count the number of different
187  *	nets used.  If "allSpecial" is TRUE, consider all
188  *	geometry to be SPECIALNETS.
189  *
190  * Results:
191  *	A NetCount structure holding the regular and special
192  *	net totals upon completion.
193  *
194  * Side Effects:
195  *	None.
196  *
197  *------------------------------------------------------------
198  */
199 
200 NetCount
defCountNets(rootDef,allSpecial)201 defCountNets(rootDef, allSpecial)
202     CellDef *rootDef;
203     bool allSpecial;
204 {
205     NetCount total;
206     int defnodeCount();
207 
208     total.regular = (allSpecial) ? -1 : 0;
209     total.special = 0;
210     total.has_nets = TRUE;
211 
212     TxPrintf("Diagnostic:  Finding all nets in cell %s\n", rootDef->cd_name);
213     TxPrintf("(This can take a while!)\n");
214 
215     /* Read in the extracted file */
216     EFInit();
217 
218     /* There are no arguments for extflat, but we need to call the	*/
219     /* routine to initialize a few things such as the search path.	*/
220     EFArgs(0, NULL, NULL, NULL, NULL);
221 
222     EFScale = 0.0;	/* Allows EFScale to be set to the scale value	*/
223 
224     if (EFReadFile(rootDef->cd_name, TRUE, FALSE, TRUE))
225     {
226 	EFFlatBuild(rootDef->cd_name, EF_FLATNODES | EF_NOFLATSUBCKT);
227         EFVisitNodes(defnodeCount, (ClientData)&total);
228     }
229     else
230     {
231 	TxError("Warning:  Circuit has no .ext file;  no nets written.\n");
232 	TxError("Run extract on this circuit if you want nets in the output.\n");
233 	EFDone();
234 	total.has_nets = FALSE;
235     }
236 
237     if (allSpecial) total.regular = 0;
238     return total;
239 }
240 
241 /* Callback function used by defCountNets */
242 
243 int
defnodeCount(node,res,cap,total)244 defnodeCount(node, res, cap, total)
245     EFNode *node;
246     int res;			/* not used */
247     EFCapValue cap;		/* not used */
248     NetCount *total;
249 {
250     HierName *hierName;
251     char ndn[256];
252     char *cp, clast;
253 
254     /* Ignore power and ground lines, which we will treat	*/
255     /* as SPECIALNETS types.					*/
256 
257     hierName = (HierName *) node->efnode_name->efnn_hier;
258 
259     if (!(hierName->hn_parent))  /* Extra processing of top-level nodes */
260     {
261 	char *pwr;
262 	cp = hierName->hn_name;
263 	clast = *(cp + strlen(cp) - 1);
264 
265 	/* Global nodes are marked as "special nets" */
266 	if (clast == '!')
267 	    node->efnode_flags |= EF_SPECIAL;
268 
269 #ifdef MAGIC_WRAPPER
270 	/* Check if name is defined in array "globals" */
271 	pwr = (char *)Tcl_GetVar2(magicinterp, "globals", cp, TCL_GLOBAL_ONLY);
272 	if (pwr)
273 	{
274 	    /* Diagnostic */
275 	    TxPrintf("Node %s is defined in the \"globals\" array\n");
276 	    node->efnode_flags |= EF_SPECIAL;
277 	}
278 
279 	/* Check against Tcl variables $VDD and $GND */
280 	pwr = (char *)Tcl_GetVar(magicinterp, "VDD", TCL_GLOBAL_ONLY);
281 	if (pwr && (!strcmp(cp, pwr)))
282 	{
283 	    /* Diagnostic */
284 	    TxPrintf("Node %s matches VDD variable definition!\n");
285 	    node->efnode_flags |= EF_SPECIAL;
286 	}
287 
288 	pwr = (char *)Tcl_GetVar(magicinterp, "GND", TCL_GLOBAL_ONLY);
289 	if (pwr && (!strcmp(cp, pwr)))
290 	{
291 	    /* Diagnostic */
292 	    TxPrintf("Node %s matches GND variable definition!\n");
293 	    node->efnode_flags |= EF_SPECIAL;
294 	}
295 
296 	/* If a node has not been marked as SPECIAL, does not connect	*/
297 	/* to a port, and does not have an internally-generated	name,	*/
298 	/* then mark it as "special".					*/
299 	if (!(node->efnode_flags & (EF_SPECIAL | EF_PORT)) &&
300 		(clast != '#'))
301 	    node->efnode_flags |= EF_SPECIAL;
302 #endif
303     }
304 
305     if (total->regular < 0)
306     {
307 	/* "allspecial" options:  all nets written as SPECIALNETS */
308 
309 	if ((node->efnode_flags & EF_SPECIAL) || (node->efnode_flags & EF_PORT))
310 	    total->special++;
311     }
312     else
313     {
314 	/* We only count nodes having a port connection as "regular" nets */
315 
316 	if (node->efnode_flags & EF_SPECIAL)
317 	    total->special++;
318 	else if (node->efnode_flags & EF_PORT)
319 	    total->regular++;
320     }
321 
322     return 0;	/* Keep going. . . */
323 }
324 
325 /*
326  * ----------------------------------------------------------------------------
327  *
328  * defHNsprintf --
329  *
330  * Create a hierarchical node name for the DEF output file..
331  *
332  * Results:
333  *	None.
334  *
335  * Side effects:
336  *	Changes the area pointed to by str
337  *
338  * ----------------------------------------------------------------------------
339  */
340 
341 void
defHNsprintf(str,hierName,divchar)342 defHNsprintf(str, hierName, divchar)
343     char *str;
344     HierName *hierName;
345     char divchar;
346 {
347     bool trimGlob, trimLocal;
348     char *s, *cp, c;
349     char *defHNsprintfPrefix();
350 
351     s = str;
352     if (hierName->hn_parent) str = defHNsprintfPrefix(hierName->hn_parent, str,
353 		divchar);
354 
355     /* Make the name conform to valid LEF/DEF syntax.  This means	*/
356     /* no pound signs or semicolons (which are illegal characters,	*/
357     /* along with space and newline which won't be found in the 	*/
358     /* magic name anyway), or dashes, asterisks, or percent signs	*/
359     /* (which are interpreted as wildcard characters by LEF/DEF).	*/
360 
361     cp = hierName->hn_name;
362     while (c = *cp++)
363     {
364 	switch (c)
365 	{
366 	    case '#':		/* Ignore---this is the final character */
367 				/* in internally-generated node names.	*/
368 		break;
369 	    case ';':
370 	    case '-':
371 	    case '*':
372 	    case '%':
373 		*str++ = '_';
374 		break;
375 	    default:
376 		*str++ = c;
377 		break;
378 	}
379     }
380     *str++ = '\0';
381 }
382 
defHNsprintfPrefix(hierName,str,divchar)383 char *defHNsprintfPrefix(hierName, str, divchar)
384     HierName *hierName;
385     char *str;
386     char divchar;
387 {
388     char *cp, c;
389 
390     if (hierName->hn_parent)
391 	str = defHNsprintfPrefix(hierName->hn_parent, str);
392 
393     cp = hierName->hn_name;
394     while (*str++ = *cp++) ;
395     *(--str) = divchar;
396     return ++str;
397 }
398 
399 
400 /*
401  *------------------------------------------------------------
402  *
403  * nodeDefName ---
404  *
405  *	Determine the node name to write to the DEF file
406  *	for the given hierachical name structure from
407  *	extflat.
408  *
409  *------------------------------------------------------------
410  */
411 
412 char *
nodeDefName(hname)413 nodeDefName(hname)
414     HierName *hname;
415 {
416     EFNodeName *nn;
417     HashEntry *he;
418     EFNode *node;
419     static char nodeName[256];
420 
421     he = EFHNLook(hname, (char *) NULL, "nodeName");
422     if (he == NULL)
423         return "errorNode";
424     nn = (EFNodeName *) HashGetValue(he);
425     node = nn->efnn_node;
426 
427     defHNsprintf(nodeName, node->efnode_name->efnn_hier, '/');
428     return nodeName;
429 }
430 
431 /*
432  *------------------------------------------------------------
433  *
434  * defCheckForBreak --
435  *
436  *	Add the number "addlen" to the column value of
437  *	the output.  If the DEF file output has reached or
438  *	exceeds this value, write a newline character to
439  *	the output and reset the column count.
440  *
441  * Results:
442  *	None.
443  *
444  * Side effects:
445  *	Output to DEF file; resets defdata->outcolumn
446  *
447  *------------------------------------------------------------
448  */
449 
450 #define MAX_DEF_COLUMNS 70
451 
452 void
defCheckForBreak(addlen,defdata)453 defCheckForBreak(addlen, defdata)
454     int addlen;
455     DefData *defdata;
456 {
457     defdata->outcolumn += addlen;
458     if (defdata->outcolumn > MAX_DEF_COLUMNS)
459     {
460 	fprintf(defdata->f, "\n      ");
461 	defdata->outcolumn = 6 + addlen;
462     }
463 }
464 
465 /*
466  *------------------------------------------------------------
467  *
468  * defWriteRouteWidth ---
469  *
470  *	Write the width of a SPECIALNET route to the output.
471  *
472  *------------------------------------------------------------
473  */
474 
475 void
defWriteRouteWidth(defdata,width)476 defWriteRouteWidth(defdata, width)
477     DefData *defdata;
478     int width;
479 {
480     float oscale = defdata->scale;
481     char numstr[12];
482     sprintf(numstr, "%.10g", ((float)width * defdata->scale));
483     defCheckForBreak(strlen(numstr) + 1, defdata);
484     fprintf(defdata->f, "%s ", numstr);
485 }
486 
487 /*
488  *------------------------------------------------------------
489  *
490  * defWriteCoord --
491  *
492  *	Output a coordinate pair in DEF syntax.  We supply the
493  *	point to be written AND the previously written point
494  *	so we can make use of the "*" notation in the DEF point
495  *	format.  If the point to be written is not an extension
496  *	of the previous point, "prevpt" should be NULL.
497  *
498  * Results:
499  *	None.
500  *
501  * Side Effects:
502  *	Output written to the DEF file.
503  *
504  *------------------------------------------------------------
505  */
506 
507 void
defWriteCoord(defdata,x,y,orient)508 defWriteCoord(defdata, x, y, orient)
509     DefData *defdata;
510     float x, y;
511     unsigned char orient;
512 {
513     FILE *f = defdata->f;
514     char numstr[12];
515     int ctot = 4;
516 
517     /* The "12" here is just a fudge factor;  it is not crucial */
518     /* to limit the output to exactly MAX_DEF_COLUMNS, and it 	*/
519     /* is easier to assume that the output of a coordinate	*/
520     /* pair is about 12 characters average rather than try to	*/
521     /* predetermine what the actual output length will be.	*/
522 
523     if ((defdata->outcolumn + 12) > MAX_DEF_COLUMNS)
524     {
525 	fprintf(f, "\n      ");
526 	defdata->outcolumn = 6;
527     }
528 
529     fprintf(f, " ( ");
530     if ((orient == GEO_NORTH) || (orient == GEO_SOUTH))
531     {
532 	fprintf(f, "* ");
533 	ctot += 2;
534     }
535     else
536     {
537 	sprintf(numstr, "%.10g", x);
538 	fprintf(f, "%s ", numstr);
539 	ctot += strlen(numstr) + 1;
540     }
541 
542     if ((orient == GEO_EAST) || (orient == GEO_WEST))
543     {
544 	fprintf(f, "* ");
545 	ctot += 2;
546     }
547     else
548     {
549 	sprintf(numstr, "%.10g", y);
550 	fprintf(f, "%s ", numstr);
551 	ctot += strlen(numstr) + 1;
552     }
553 
554     fprintf(f, ")");
555     defdata->outcolumn += ctot;
556 }
557 
558 /*
559  *------------------------------------------------------------
560  *
561  * defWriteNets --
562  *
563  *	Output the NETS section of a DEF file.  We make use of
564  *	the connectivity search routines used by "getnode" to
565  *	determine unique notes and assign a net name to each.
566  *	Then, we generate the geometry output for each NET
567  *	entry.
568  *
569  * Results:
570  *	None.
571  *
572  * Side Effects:
573  *	Output written to the DEF output file.
574  *
575  *------------------------------------------------------------
576  */
577 
578 void
defWriteNets(f,rootDef,oscale,MagicToLefTable,specialmode)579 defWriteNets(f, rootDef, oscale, MagicToLefTable, specialmode)
580     FILE *f;				/* File to write to */
581     CellDef *rootDef;			/* Cell definition to use */
582     float oscale;			/* Output scale factor */
583     LefMapping *MagicToLefTable;	/* Magic to LEF layer mapping */
584     unsigned char specialmode;		/* What to write as a SPECIALNET */
585 {
586     DefData defdata;
587     int defnodeVisit();
588 
589     defdata.f = f;
590     defdata.scale = oscale;
591     defdata.def = rootDef;
592     defdata.MagicToLefTbl = MagicToLefTable;
593     defdata.outcolumn = 0;
594     defdata.specialmode = specialmode;
595 
596     EFVisitNodes(defnodeVisit, (ClientData)&defdata);
597 }
598 
599 int
defnodeVisit(node,res,cap,defdata)600 defnodeVisit(node, res, cap, defdata)
601     EFNode *node;
602     int res;
603     EFCapValue cap;
604     DefData *defdata;
605 {
606     HierName *hierName;
607     char *ndn;
608     char ndn2[256];
609     FILE *f = defdata->f;
610     CellDef *def = defdata->def;
611     float oscale = defdata->scale;
612     TileTypeBitMask tmask, *rmask;
613     TileType magictype;
614     EFNodeName *thisnn;
615     int defNetGeometryFunc();		/* Forward declaration */
616 
617     /* For regular nets, only count those nodes having port	*/
618     /* connections.  For special nets, only count those nodes	*/
619     /* that were marked with the EF_SPECIAL flag while counting	*/
620     /* nets.							*/
621 
622     if (defdata->specialmode == DO_REGULAR)
623     {
624 	if (!(node->efnode_flags & EF_PORT))
625 	    return 0;
626     }
627     else if (defdata->specialmode == DO_SPECIAL)
628     {
629 	if (!(node->efnode_flags & EF_SPECIAL))
630 	    return 0;
631     }
632     else /* ALL_SPECIAL */
633     {
634 	if (!(node->efnode_flags & EF_PORT) &&
635 		!(node->efnode_flags & EF_SPECIAL))
636 	    return 0;
637     }
638 
639     hierName = (HierName *) node->efnode_name->efnn_hier;
640     ndn = nodeDefName(hierName);
641     defHNsprintf(ndn2, node->efnode_name->efnn_hier, '/');
642     if (strcmp(ndn, ndn2))
643     {
644 	TxError("Node mismatch: %s vs. %s\n", ndn, ndn2);
645     }
646 
647     fprintf(f, "   - %s", ndn);
648     defdata->outcolumn = 5 + strlen(ndn);
649 
650     /* Find all the node names that are port connections. 	*/
651     /* For now, we will just use anything connecting one level	*/
652     /* down in the hierarchy.  This is not definitive, however,	*/
653     /* and we should confirm that the connection is an actual	*/
654     /* port.							*/
655 
656     for (thisnn = node->efnode_name; thisnn != NULL; thisnn = thisnn->efnn_next)
657     {
658 	char locndn[256];
659 	hierName = thisnn->efnn_hier;
660 	if (hierName->hn_parent && !hierName->hn_parent->hn_parent)
661 	{
662 	    /* This is just another kludgy check for a non-port and	*/
663 	    /* will eventually be removed.				*/
664 	    char endc = *(hierName->hn_name + strlen(hierName->hn_name) - 1);
665 	    if (endc != '#')
666 	    {
667 		defHNsprintf(locndn, thisnn->efnn_hier, ' ');
668 		defCheckForBreak(5 + strlen(locndn), defdata);
669 		fprintf(f, " ( %s )", locndn);
670 	    }
671 	}
672     }
673 
674     /* TT_SPACE indicates that a layer name must be the next	*/
675     /* thing to be written to the DEF file.			*/
676     defdata->type = TT_SPACE;
677     defdata->tile = (Tile *)NULL;
678 
679     /* Net geometry (this should be an option!)---	*/
680     /* Use the DBconnect routines to find all geometry	*/
681     /* connected to a specific node.  This is a		*/
682     /* redundant search---we've already done this once	*/
683     /* when extracting the circuit.  But, because the	*/
684     /* DEF file requires a count of nodes up front, we	*/
685     /* would have to do it twice anyway.  In this case,	*/
686     /* we only do it once here, since the results of	*/
687     /* the first pass are picked up from the .ext file.	*/
688 
689     magictype = DBTechNameType(EFLayerNames[node->efnode_type]);
690 
691     /* Note that the type of the node might be defined by the type */
692     /* in the subcircuit itself, so we need to search for any type */
693     /* that might validly connect to it, not just the type itself. */
694     /* TTMaskSetOnlyType(&tmask, magictype); */
695     TTMaskZero(&tmask);
696     TTMaskSetMask(&tmask, &DBConnectTbl[magictype]);
697 
698     /* Avoid attempting to extract an implicit substrate into DEF */
699     if (node->efnode_type == TT_SPACE) return 0;
700 
701     DBSrConnect(def, &node->efnode_loc, &tmask, DBConnectTbl,
702 		&TiPlaneRect, defNetGeometryFunc,
703 		(ClientData)defdata);
704 
705     if (defdata->tile == (Tile *)NULL)
706     {
707 	/* No route layer?  It's possible that something connects to	*/
708 	/* the port location but doesn't overlap.  Try painting the	*/
709 	/* node type in def and trying again.				*/
710 
711 	Rect rport;
712 	SearchContext scx;
713 	int defPortTileFunc();	/* Fwd declaration */
714 
715 	scx.scx_area = node->efnode_loc;
716 	scx.scx_use = def->cd_parents;
717 	scx.scx_trans = GeoIdentityTransform;
718 	DBTreeSrUniqueTiles(&scx, &tmask, 0, defPortTileFunc, (ClientData)&rport);
719 
720 	/* Add the residue types to any contact type */
721 	if (DBIsContact(magictype))
722 	{
723 	    rmask = DBResidueMask(magictype);
724 	    TTMaskSetMask(&tmask, rmask);
725 	    TTMaskSetType(&tmask, magictype);
726 	}
727 	/* Expand the rectangle around the port to overlap any	*/
728 	/* connecting material.					*/
729 	rport.r_xbot--;
730 	rport.r_ybot--;
731 	rport.r_xtop++;
732 	rport.r_ytop++;
733   	DBSrConnect(def, &rport, &tmask, DBConnectTbl, &TiPlaneRect,
734 			defNetGeometryFunc, (ClientData)defdata);
735     }
736 
737     /* Was there a last record pending?  If so, write it. */
738     if (defdata->tile != (Tile *)NULL)
739     {
740 	if (defdata->orient != GEO_CENTER)
741 	    defWriteCoord(defdata, defdata->x, defdata->y, defdata->orient);
742 
743 	defdata->outcolumn = 0;
744     }
745     fprintf(f, " ;\n");
746 
747     return 0; 	/* Keep going */
748 }
749 
750 /* Callback function for DBTreeSrUniqueTiles.  When no routed areas	*/
751 /* were found, we assume that there was no routing material overlapping	*/
752 /* the port.  So, we need to find the area of a tile defining the port	*/
753 /* so we can look for attaching material.				*/
754 
755 int
defPortTileFunc(tile,cx)756 defPortTileFunc(tile, cx)
757     Tile *tile;
758     TreeContext *cx;
759 {
760     SearchContext *scx = cx->tc_scx;
761     Rect *rport = (Rect *)cx->tc_filter->tf_arg;
762     Rect r;
763 
764     TiToRect(tile, &r);
765     GeoTransRect(&scx->scx_trans, &r, rport);
766 
767     /* Diagnostic */
768     /*
769     TxPrintf("Port tile at (%d %d) to (%d %d)\n",
770 		rport->r_xbot, rport->r_ybot,
771 		rport->r_xtop, rport->r_ytop);
772     */
773 
774     return 1;	/* No need to check further */
775 }
776 
777 /* Callback function for writing geometry of the network to	*/
778 /* the DEF file.						*/
779 
780 int
defNetGeometryFunc(tile,plane,defdata)781 defNetGeometryFunc(tile, plane, defdata)
782     Tile *tile;			/* Tile being visited */
783     int plane;			/* Plane of the tile being visited */
784     DefData *defdata;		/* Data passed to this function */
785 {
786     FILE *f = defdata->f;
787     CellDef *def = defdata->def;
788     float oscale = defdata->scale;
789     TileTypeBitMask *rMask, *r2Mask;
790     TileType rtype, r2type, ttype = TiGetType(tile);
791     Rect r;
792     unsigned char orient;
793     bool sameroute = FALSE;
794     int routeWidth, w, h, midlinex2;
795     float x1, y1, x2, y2, extlen;
796     lefLayer *lefType;
797     char *lefName, viaName[24];
798     LefMapping *MagicToLefTable = defdata->MagicToLefTbl;
799 
800     if (ttype == TT_SPACE) return 0;
801     TiToRect(tile, &r);
802 
803     /* Treat contacts here exactly the same way as defCountVias	*/
804 
805     if (DBIsContact(ttype))
806     {
807 	Rect r2;
808 	Tile *tp;
809 
810 	rMask = NULL;
811 	if (ttype >= DBNumUserLayers)
812 	{
813 	    /* Stacked contact types need to be broken into their	*/
814 	    /* constituent types.  Process only if we are on the home	*/
815 	    /* plane of one of the constituent types.			*/
816 
817 	    rMask = DBResidueMask(ttype);
818 	    for (rtype = TT_TECHDEPBASE; rtype < DBNumUserLayers; rtype++)
819 		if (TTMaskHasType(rMask, rtype))
820 		    if (DBPlane(rtype) == plane)
821 		    {
822 			ttype = rtype;
823 			break;
824 		    }
825 	    if (rtype == DBNumUserLayers)
826 		return 0;
827 
828 	}
829 	else
830 	    if (DBPlane(ttype) != plane)
831 		return 0;
832 
833 	/* Boundary search on stacked contact types to include any	*/
834 	/* tile areas belonging to ttype.				*/
835 
836 	for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) /* Top */
837 	{
838 	    r2type = TiGetBottomType(tp);
839 	    if (r2type == ttype)
840 	    {
841 		if (!rMask) return 0;
842 		TiToRect(tp, &r2);
843 		GeoInclude(&r2, &r);
844 	    }
845 	    else if (r2type >= DBNumUserLayers)
846 	    {
847 		r2Mask = DBResidueMask(r2type);
848 		if (TTMaskHasType(r2Mask, ttype))
849 		    return 0;
850 	    }
851 	}
852 
853 	for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) /* Left */
854 	{
855 	    r2type = TiGetRightType(tp);
856 	    if (r2type == ttype)
857 	    {
858 		if (!rMask) return 0;
859 		TiToRect(tp, &r2);
860 		GeoInclude(&r2, &r);
861 	    }
862 	    else if (r2type >= DBNumUserLayers)
863 	    {
864 		r2Mask = DBResidueMask(r2type);
865 		if (TTMaskHasType(r2Mask, ttype))
866 		    return 0;
867 	    }
868 	}
869 
870 	for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) /* Bottom */
871 	{
872 	    r2type = TiGetTopType(tp);
873 	    if (r2type == ttype)
874 	    {
875 		if (!rMask) return 0;
876 		TiToRect(tp, &r2);
877 		GeoInclude(&r2, &r);
878 	    }
879 	    else if (r2type >= DBNumUserLayers)
880 	    {
881 		r2Mask = DBResidueMask(r2type);
882 		if (TTMaskHasType(r2Mask, ttype))
883 		    return 0;
884 	    }
885 	}
886 
887 	for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) /* Right */
888 	{
889 	    r2type = TiGetLeftType(tp);
890 	    if (r2type == ttype)
891 	    {
892 		if (!rMask) return 0;
893 		TiToRect(tp, &r2);
894 		GeoInclude(&r2, &r);
895 	    }
896 	    else if (r2type >= DBNumUserLayers)
897 	    {
898 		r2Mask = DBResidueMask(r2type);
899 		if (TTMaskHasType(r2Mask, ttype))
900 		    return 0;
901 	    }
902 	}
903     }
904 
905     /* Layer names are taken from the LEF database. */
906 
907     lefName = MagicToLefTable[ttype].lefName;
908     if (lefName == NULL) return 0;	/* Do not write types not in LEF definition */
909     lefType = MagicToLefTable[ttype].lefInfo;
910 
911     orient = GEO_EAST;
912     w = r.r_xtop - r.r_xbot;
913     h = r.r_ytop - r.r_ybot;
914     midlinex2 = (r.r_ytop + r.r_ybot);
915 
916     if (defdata->specialmode != DO_REGULAR)
917     {
918 	routeWidth = (h > w) ? w : h;
919 	if ((lefType && lefType->lefClass == CLASS_VIA)
920 			|| (!lefType && DBIsContact(ttype)))
921 	    orient = GEO_CENTER;
922     }
923     else
924     {
925 	routeWidth = 0;
926 	if ((lefType && (lefType->lefClass == CLASS_VIA))
927 			|| (!lefType && DBIsContact(ttype)))
928 	    orient = GEO_CENTER;
929 	else if (lefType)
930 	    routeWidth = lefType->info.route.width;
931 
932 	if (routeWidth == 0)
933 	    routeWidth = DRCGetDefaultLayerWidth(ttype);
934     }
935 
936     if (orient != GEO_CENTER)	/* not a via type */
937     {
938 	if (h != routeWidth)
939 	{
940 	    if ((w == routeWidth) || ((routeWidth == 0) && (h > w)))
941 	    {
942 		orient = GEO_NORTH;
943 		midlinex2 = (r.r_xtop + r.r_xbot);
944 	    }
945 	}
946 
947 	/* Warn if the route is not equal to the default route width--- */
948 	/* This means a regular net should have been a special net.	*/
949 	if ((h != routeWidth) && (w != routeWidth))
950 	{
951 	    /* Diagnostic */
952 	    TxPrintf("Net at (%d, %d) has width %d, default width is %d\n",
953 			r.r_xbot, r.r_ybot,
954 			(h < w) ? h : w, routeWidth);
955 	}
956 
957 	/* Find the route orientation and centerline endpoint coordinates */
958 
959 	if (orient == GEO_EAST)
960 	{
961 	    y1 = (midlinex2 * oscale) / 2;
962 	    y2 = y1;
963 
964 	    x1 = r.r_xbot * oscale;
965 	    x2 = r.r_xtop * oscale;
966 	    if (routeWidth == 0) routeWidth = h;
967 
968 	    extlen = 0;
969 	    if (defdata->specialmode == DO_REGULAR)
970 	    {
971 		x1 = x1 + (routeWidth / 2 * oscale);
972 		x2 = x2 - (routeWidth / 2 * oscale);
973 	    }
974 	}
975 	else	/* vertical orientation */
976 	{
977 	    x1 = (midlinex2 * oscale) / 2;
978 	    x2 = x1;
979 
980 	    y1 = r.r_ybot * oscale;
981 	    y2 = r.r_ytop * oscale;
982 	    if (routeWidth == 0) routeWidth = w;
983 
984 	    extlen = 0;
985 	    if (defdata->specialmode == DO_REGULAR)
986 	    {
987 		y1 = y1 + (routeWidth / 2 * oscale);
988 		y2 = y2 - (routeWidth / 2 * oscale);
989 	    }
990 	}
991     }
992     else	/* Type is a via */
993     {
994 	y1 = y2 = (midlinex2 * oscale) / 2;
995 	x1 = x2 = ((r.r_xtop + r.r_xbot) * oscale) / 2;
996 	extlen = 0;
997     }
998 
999     /* For contact types, find the residues of the contact	*/
1000 
1001     if (orient == GEO_CENTER)
1002     {
1003 	TileType stype;
1004 
1005 	rtype = r2type = TT_SPACE;
1006 	rMask = DBResidueMask(ttype);
1007 	for (stype = TT_TECHDEPBASE; stype < DBNumUserLayers; stype++)
1008 	{
1009 	    if (TTMaskHasType(rMask, stype))
1010 	    {
1011 		if ((stype == defdata->type) || (defdata->tile == (Tile *)NULL))
1012 		   rtype = stype;
1013 		else
1014 		   r2type = stype;
1015 	    }
1016 	}
1017     }
1018 
1019     /* If we previously visited a tile, write out its second	*/
1020     /* coordinate pair, adjusting the position if necessary to	*/
1021     /* make the wire extensions line up correctly.  If they	*/
1022     /* don't line up, we assume a dogleg route and add		*/
1023     /* coordinate pairs as necessary to generate the correct	*/
1024     /* geometry in the DEF output.				*/
1025 
1026     if (defdata->tile)
1027     {
1028 	Rect r2;
1029 	TiToRect(defdata->tile, &r2);
1030 	/* Only consider the endpoint of the previous tile at X2,Y2 */
1031 	/* And the endpoint of the current tile at X1,Y1 */
1032 	if (defdata->orient == GEO_EAST)
1033 	    r2.r_xbot = r2.r_xtop - 1;
1034 	else if (defdata->orient == GEO_NORTH)
1035 	    r2.r_ybot = r2.r_ytop - 1;
1036 
1037 	if (orient == GEO_EAST)
1038 	    r.r_xtop = r.r_xbot + 1;
1039 	else if (orient == GEO_NORTH)
1040 	    r.r_ytop = r.r_ybot + 1;
1041 
1042 	/* "sameroute" is true only if rectangles touch in the		*/
1043 	/* direction of the route.					*/
1044 	/* NOTE:  We should compute this FIRST and use it to determine	*/
1045 	/* the current route direction!					*/
1046 	/* Another hack---for special nets, don't continue routes that	*/
1047 	/* have different widths, even if they're connected in the	*/
1048 	/* direction of travel.  A separate record will be written for	*/
1049 	/* the segment of different width.				*/
1050 
1051 	if (GEO_TOUCH(&r, &r2))
1052 	{
1053 	    if (defdata->orient == GEO_EAST)
1054 	    {
1055 		if ((r.r_xbot == r2.r_xtop) || (r.r_xtop == r2.r_xbot))
1056 		{
1057 		    sameroute = TRUE;
1058 		    if ((defdata->specialmode != DO_REGULAR) &&
1059 				(r.r_ytop != r2.r_ytop || r.r_ybot != r2.r_ybot))
1060 			sameroute = FALSE;
1061 		}
1062 	    }
1063 	    else if (defdata->orient == GEO_NORTH)
1064 	    {
1065 		if ((r.r_ybot == r2.r_ytop) || (r.r_ytop == r2.r_ybot))
1066 		{
1067 		    sameroute = TRUE;
1068 		    if ((defdata->specialmode != DO_REGULAR) &&
1069 				(r.r_xtop != r2.r_xtop || r.r_xbot != r2.r_xbot))
1070 			sameroute = FALSE;
1071 		}
1072 	    }
1073 	    else
1074 		sameroute = TRUE;
1075 	}
1076 
1077 	/* We should NOT continue a route from a via for a special net,	*/
1078 	/* because the spec for this situation is too vaguely defined.	*/
1079 
1080 	if (sameroute && (defdata->specialmode != DO_REGULAR) &&
1081 		defdata->orient == GEO_CENTER)
1082 	    sameroute = FALSE;
1083     }
1084 
1085 
1086     /* Determine if we need to write a NEW (type) record.  We do this	*/
1087     /* if 1) this is the first tile visited (except that we don't	*/
1088     /* write "NEW"), 2) the current tile doesn't touch the last tile	*/
1089     /* visited, or 3) the current type is not equal to the last type.	*/
1090 
1091     if ((!sameroute) || (ttype != defdata->type))
1092     {
1093 	/* This is not a continuation of the last route.  Output	*/
1094 	/* the last route position, and start a NEW record.		*/
1095 
1096 	if ((sameroute) && (ttype != defdata->type) &&
1097 			(orient == GEO_CENTER) &&
1098 			(rtype == defdata->type))
1099 	{
1100 	    /* Adjust previous route to centerpoint of the via.	 If the	*/
1101 	    /* via is not centered on the route, add segments to create	*/
1102 	    /* the proper alignment.					*/
1103 	    if ((defdata->orient == GEO_NORTH) && (x1 == defdata->x))
1104 		defWriteCoord(defdata, defdata->x, y1, defdata->orient);
1105 	    else if ((defdata->orient == GEO_EAST) && (y1 == defdata->y))
1106 		defWriteCoord(defdata, x1, defdata->y, defdata->orient);
1107 	    else if (defdata->orient == GEO_EAST)
1108 	    {
1109 		defWriteCoord(defdata, x1, defdata->y, defdata->orient);
1110 		defWriteCoord(defdata, x1, y1, GEO_NORTH);
1111 	    }
1112 	    else if (defdata->orient == GEO_NORTH)
1113 	    {
1114 		defWriteCoord(defdata, defdata->x, y1, defdata->orient);
1115 		defWriteCoord(defdata, x1, y1, GEO_EAST);
1116 	    }
1117 
1118 	    /* Via type continues route */
1119 	    snprintf(viaName, (size_t)24, "_%.10g_%.10g",
1120 			((float)w * oscale), ((float)h * oscale));
1121 	    defCheckForBreak(strlen(lefName) + strlen(viaName) + 2, defdata);
1122 	    fprintf(f, " %s%s ", lefName, viaName);
1123 	}
1124 	else
1125 	{
1126 	    /* New route segment.  Complete the last route segment. */
1127 	    if (defdata->tile)
1128 	    {
1129 		/* Don't write out a segment for a via */
1130 		if (defdata->orient != GEO_CENTER)
1131 		    defWriteCoord(defdata,
1132 				defdata->x - ((defdata->orient == GEO_EAST) ?
1133 				defdata->extlen : 0),
1134 				defdata->y - ((defdata->orient == GEO_NORTH) ?
1135 				defdata->extlen : 0), defdata->orient);
1136 
1137 		fprintf(f, "\n      NEW ");
1138 		defdata->outcolumn = 10;
1139 	    }
1140 	    else
1141 	    {
1142 		/* First record printed for this node */
1143 		fprintf(f, "\n      + ROUTED ");
1144 		defdata->outcolumn = 15;
1145 	    }
1146 
1147 	    /* This is the first tile segment visited in the	*/
1148 	    /* current type---use GEO_CENTER so that no		*/
1149 	    /* coordinate wildcards ("*") get written.		*/
1150 
1151 	    if (orient == GEO_CENTER)
1152 	    {
1153 		char *rName;
1154 
1155 		/* Type can be zero (space) if the first tile	*/
1156 		/* encountered is a via.  If so, use the 1st	*/
1157 		/* residue of the contact as the route layer	*/
1158 		/* type.					*/
1159 
1160 		rName = defGetType((rtype == TT_SPACE) ? r2type : rtype, NULL,
1161 				LAYER_MAP_VIAS);
1162 
1163 		/* The first layer in a record may not be a via name */
1164 
1165 	        defCheckForBreak(strlen(rName) + 1, defdata);
1166 		fprintf(f, "%s ", rName);
1167 		if (defdata->specialmode != DO_REGULAR)
1168 		    defWriteRouteWidth(defdata, routeWidth);
1169 		defWriteCoord(defdata, x1, y1, GEO_CENTER);
1170 		snprintf(viaName, (size_t)24, "_%.10g_%.10g",
1171 			((float)w * oscale), ((float)h * oscale));
1172 	        defCheckForBreak(strlen(lefName) + strlen(viaName) + 2, defdata);
1173 		fprintf(f, " %s%s ", lefName, viaName);
1174 	    }
1175 	    else
1176 	    {
1177 	        defCheckForBreak(strlen(lefName) + 1, defdata);
1178 		fprintf(f, "%s ", lefName);
1179 		if (defdata->specialmode != DO_REGULAR)
1180 		    defWriteRouteWidth(defdata, routeWidth);
1181 
1182 		/* defWriteCoord(defdata, x1, y1, GEO_CENTER); */
1183 		defWriteCoord(defdata,
1184 			x1 + ((orient == GEO_EAST) ?  extlen : 0),
1185 			y1 + ((orient == GEO_NORTH) ?  extlen : 0),
1186 			GEO_CENTER);
1187 	    }
1188 	}
1189     }
1190     else if (sameroute)
1191     {
1192 	/* Adjust the previous route segment to match the new segment,	*/
1193 	/* and write out the previous route segment record.		*/
1194 	if ((orient == defdata->orient) && (defdata->x != x1) && (defdata->y != x2))
1195 	{
1196 	    /* Dogleg---insert extra segment */
1197 	    defWriteCoord(defdata,
1198 			defdata->x - ((defdata->orient == GEO_EAST) ?
1199 			defdata->extlen : 0),
1200 			defdata->y - ((defdata->orient == GEO_NORTH) ?
1201 			defdata->extlen : 0), defdata->orient);
1202 	    defWriteCoord(defdata, x1 + ((orient == GEO_EAST) ?  extlen : 0),
1203 			y1 + ((orient == GEO_NORTH) ?  extlen : 0), orient);
1204 	}
1205 	else
1206 	{
1207 	    if (defdata->orient == GEO_EAST)
1208 	    {
1209 		if (((defdata->x + defdata->extlen) == x1) ||
1210 			((defdata->x - defdata->extlen) == x1))
1211 		    defWriteCoord(defdata, x1, defdata->y, defdata->orient);
1212 		else
1213 		{
1214 		    /* Don't know how to connect the route segments. */
1215 		    /* End the original route and start a new one. */
1216 		    defWriteCoord(defdata,
1217 				defdata->x - ((defdata->orient == GEO_EAST) ?
1218 				defdata->extlen : 0),
1219 				defdata->y - ((defdata->orient == GEO_NORTH) ?
1220 				defdata->extlen : 0), defdata->orient);
1221 		    fprintf(f, "\n      NEW %s", lefName);
1222 		    defdata->outcolumn = 10 + strlen(lefName);
1223 		    if (defdata->specialmode != DO_REGULAR)
1224 		    {
1225 			fprintf(f, " ");
1226 			defdata->outcolumn++;
1227 			defWriteRouteWidth(defdata, routeWidth);
1228 		    }
1229 		    defWriteCoord(defdata,
1230 				x1 + ((orient == GEO_EAST) ?  extlen : 0),
1231 				y1 + ((orient == GEO_NORTH) ?  extlen : 0),
1232 				GEO_CENTER);
1233 		}
1234 	    }
1235 	    else if (defdata->orient == GEO_NORTH)
1236 	    {
1237 		if (((defdata->y + defdata->extlen) == y1) ||
1238 			((defdata->y - defdata->extlen) == y1))
1239 		    defWriteCoord(defdata, defdata->x, y1, defdata->orient);
1240 		else
1241 		{
1242 		    /* Don't know how to connect the route segments. */
1243 		    /* End the original route and start a new one. */
1244 		    defWriteCoord(defdata,
1245 				defdata->x - ((defdata->orient == GEO_EAST) ?
1246 				defdata->extlen : 0),
1247 				defdata->y - ((defdata->orient == GEO_NORTH) ?
1248 				defdata->extlen : 0), defdata->orient);
1249 		    fprintf(f, "\n      NEW %s", lefName);
1250 		    if (defdata->specialmode != DO_REGULAR) {
1251 			fprintf(f, " ");
1252 			defdata->outcolumn++;
1253 			defWriteRouteWidth(defdata, routeWidth);
1254 		    }
1255 		    defdata->outcolumn = 10 + strlen(lefName);
1256 		    defWriteCoord(defdata,
1257 				x1 + ((orient == GEO_EAST) ?  extlen : 0),
1258 				y1 + ((orient == GEO_NORTH) ?  extlen : 0),
1259 				GEO_CENTER);
1260 		}
1261 	    }
1262 	    else	/* last record was a via */
1263 	    {
1264 		/* Continuing route from via to other connecting layer type */
1265 		/* Bend to meet via center---insert extra segment */
1266 
1267 		if ((orient == GEO_NORTH) && (x1 != defdata->x))
1268 		    defWriteCoord(defdata, x1, defdata->y, GEO_EAST);
1269 
1270 		else if ((orient == GEO_EAST) && (y1 != defdata->y))
1271 		    defWriteCoord(defdata, defdata->x, y1, GEO_NORTH);
1272 	    }
1273 	}
1274     }
1275 
1276     /* After a contact type, the route coordinates may continue in the	*/
1277     /* routing type connected by the contact to the type that was	*/
1278     /* previously seen connected to the contact.			*/
1279 
1280     /* NOTE!  The above comment matches the example on page 203 of the	*/
1281     /* LEF/DEF reference manual.  However, it is obvious that it is	*/
1282     /* logically fallacious.  A via can be declared to be multiple	*/
1283     /* types, and there is no way to know which type continues the	*/
1284     /* route without it being explicitly stated.  Nevertheless, that	*/
1285     /* is the way it's implemented. . .					*/
1286 
1287     if ((orient == GEO_CENTER) && (rtype != TT_SPACE) && (r2type != TT_SPACE))
1288 	defdata->type = r2type;
1289     else if (orient == GEO_CENTER)
1290 	defdata->type = TT_SPACE;
1291     else
1292 	defdata->type = ttype;
1293 
1294     defdata->x = x2;
1295     defdata->y = y2;
1296     defdata->extlen = extlen;
1297     defdata->tile = tile;
1298     defdata->orient = orient;
1299     return 0;	/* Keep going */
1300 }
1301 
1302 /*
1303  *------------------------------------------------------------
1304  *
1305  * defCountVias --
1306  *
1307  *	First-pass function to count the number of different
1308  *	vias used, and retain this information for the netlist
1309  *	output.
1310  *
1311  * Results:
1312  *	The total number of via definitions to be written.
1313  *
1314  * Side Effects:
1315  *	None.
1316  *
1317  *------------------------------------------------------------
1318  */
1319 
1320 int
defCountVias(rootDef,MagicToLefTable,oscale)1321 defCountVias(rootDef, MagicToLefTable, oscale)
1322     CellDef *rootDef;
1323     LefMapping *MagicToLefTable;
1324     float oscale;
1325 {
1326     TileTypeBitMask contactMask, *rmask;
1327     TileType ttype, stype;
1328     int pNum;
1329     CViaData cviadata;
1330     int defCountViaFunc();
1331 
1332     cviadata.scale = oscale;
1333     cviadata.total = 0;
1334     cviadata.MagicToLefTbl = MagicToLefTable;
1335 
1336     for (pNum = PL_SELECTBASE; pNum < DBNumPlanes; pNum++)
1337     {
1338 	cviadata.plane = pNum;
1339 
1340         /* Only search for contacts that are on their *home* plane */
1341 
1342 	TTMaskZero(&contactMask);
1343 	for (ttype = TT_TECHDEPBASE; ttype < DBNumUserLayers; ttype++)
1344 	    if (DBIsContact(ttype) && TTMaskHasType(&DBPlaneTypes[pNum], ttype))
1345 		TTMaskSetType(&contactMask, ttype);
1346 
1347 	/* Also search all stacked types whose residue contact types	*/
1348 	/* are in the mask just generated.				*/
1349 
1350 	for (ttype = DBNumUserLayers; ttype < DBNumTypes; ttype++)
1351 	{
1352 	    if (!DBIsContact(ttype)) continue;
1353 	    rmask = DBResidueMask(ttype);
1354 	    for (stype = TT_TECHDEPBASE; stype < DBNumUserLayers; stype++)
1355 		if (TTMaskHasType(rmask, stype))
1356 		{
1357 		    TTMaskSetType(&contactMask, ttype);
1358 		    break;
1359 		}
1360 	}
1361 	cviadata.mask = &contactMask;
1362 
1363 	DBSrPaintArea((Tile *)NULL, rootDef->cd_planes[pNum],
1364 			&TiPlaneRect, &contactMask,
1365 			defCountViaFunc, (ClientData)&cviadata);
1366     }
1367     return cviadata.total;
1368 }
1369 
1370 /* Callback function used by defCountVias */
1371 
1372 int
defCountViaFunc(tile,cviadata)1373 defCountViaFunc(tile, cviadata)
1374     Tile *tile;
1375     CViaData *cviadata;
1376 {
1377     TileType ttype = TiGetType(tile), ctype, rtype;
1378     TileTypeBitMask *rmask, *rmask2;
1379     Tile *tp;
1380     char *lname, vname[100], *vp;
1381     Rect r, r2;
1382     int w, h, offx, offy;
1383     float oscale = cviadata->scale;
1384     lefLayer *lefl;
1385     HashEntry *he;
1386     LefMapping *MagicToLefTable = cviadata->MagicToLefTbl;
1387 
1388     /* Techfiles are allowed not to declare a LEF entry, in which */
1389     /* case we would need to initialize the hash table.		  */
1390     if (LefInfo.ht_table == (HashEntry **) NULL) LefTechInit();
1391 
1392     /* Find the canonical type */
1393     if (ttype >= DBNumUserLayers)
1394     {
1395 	rmask = DBResidueMask(ttype);
1396 	for (ctype = TT_TECHDEPBASE; ctype < DBNumUserLayers; ctype++)
1397 	    if (TTMaskHasType(rmask, ctype))
1398 		break;
1399 	if (ctype == DBNumUserLayers)
1400 	    return 1;			/* Error condition */
1401     }
1402     else
1403     {
1404 	rmask = NULL;
1405 	ctype = ttype;
1406     }
1407 
1408     /* Generate a via name from the layer name and tile size */
1409 
1410     lname = MagicToLefTable[ctype].lefName;
1411     if (lname == NULL) return 0;    /* Do not output undefined LEF layers */
1412     TiToRect(tile, &r);
1413 
1414     /* Boundary search.  WARNING:  This code is quite naive.  The	*/
1415     /* assumption is that all contacts are rectangular, and therefore	*/
1416     /* any contact area consisting of multiple tiles must be an amalgam	*/
1417     /* of regular and/or stacked types.  This whole thing should be	*/
1418     /* replaced by calls to generate layers via the CIF/Calma code.	*/
1419 
1420     /* Top */
1421     for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp))
1422     {
1423 	rtype = TiGetBottomType(tp);
1424 	if (rtype == ctype)
1425 	{
1426 	    if (!rmask) return 0; /* ignore tile but continue search */
1427 	    TiToRect(tp, &r2);
1428 	    GeoInclude(&r2, &r);
1429 	}
1430 	else if (rtype >= DBNumUserLayers)
1431 	{
1432 	    rmask2 = DBResidueMask(rtype);
1433 	    if (TTMaskHasType(rmask2, ctype))
1434 		return 0;
1435 	}
1436     }
1437 
1438     /* Left */
1439     for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp))
1440     {
1441 	rtype = TiGetRightType(tp);
1442 	if (rtype == ctype)
1443 	{
1444 	    if (!rmask) return 0; /* ignore tile but continue search */
1445 	    TiToRect(tp, &r2);
1446 	    GeoInclude(&r2, &r);
1447 	}
1448 	else if (rtype >= DBNumUserLayers)
1449 	{
1450 	    rmask2 = DBResidueMask(rtype);
1451 	    if (TTMaskHasType(rmask2, ctype))
1452 		return 0;
1453 	}
1454     }
1455 
1456     /* Bottom */
1457     for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp))
1458     {
1459 	rtype = TiGetTopType(tp);
1460 	if (rtype == ctype)
1461 	{
1462 	    if (!rmask) return 0; /* ignore tile but continue search */
1463 	    TiToRect(tp, &r2);
1464 	    GeoInclude(&r2, &r);
1465 	}
1466 	else if (rtype >= DBNumUserLayers)
1467 	{
1468 	    rmask2 = DBResidueMask(rtype);
1469 	    if (TTMaskHasType(rmask2, ctype))
1470 		return 0;
1471 	}
1472     }
1473 
1474     /* Right */
1475     for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp))
1476     {
1477 	rtype = TiGetLeftType(tp);
1478 	if (rtype == ctype)
1479 	{
1480 	    if (!rmask) return 0; /* ignore tile but continue search */
1481 	    TiToRect(tp, &r2);
1482 	    GeoInclude(&r2, &r);
1483 	}
1484 	else if (rtype >= DBNumUserLayers)
1485 	{
1486 	    rmask2 = DBResidueMask(rtype);
1487 	    if (TTMaskHasType(rmask2, ctype))
1488 		return 0;
1489 	}
1490     }
1491 
1492     /* All values for the via rect are in 1/2 lambda to account */
1493     /* for a centerpoint not on the internal grid.		*/
1494 
1495     r.r_xbot <<= 1;
1496     r.r_xtop <<= 1;
1497     r.r_ybot <<= 1;
1498     r.r_ytop <<= 1;
1499 
1500     w = r.r_xtop - r.r_xbot;
1501     h = r.r_ytop - r.r_ybot;
1502     offx = (w >> 1);
1503     offy = (h >> 1);
1504 
1505     /* Center the via area on the origin */
1506     r.r_xbot = -offx;
1507     r.r_ybot = -offy;
1508     r.r_xtop = -offx + w;
1509     r.r_ytop = -offy + h;
1510 
1511     sprintf(vname, "%s_%.10g_%.10g", lname,
1512 			((float)offx * oscale), ((float)offy * oscale));
1513 
1514     he = HashFind(&LefInfo, vname);
1515     lefl = (lefLayer *)HashGetValue(he);
1516     if (lefl == NULL)
1517     {
1518 	cviadata->total++;	/* Increment the count of uses */
1519 	lefl = (lefLayer *)mallocMagic(sizeof(lefLayer));
1520 	lefl->type = ttype;
1521 	lefl->obsType = -1;
1522 	lefl->lefClass = CLASS_VIA;
1523 	lefl->info.via.area = r;
1524 	lefl->info.via.cell = (CellDef *)NULL;
1525 	lefl->info.via.lr = (LinkedRect *)NULL;
1526 	lefl->refCnt = 0;	/* These entries will be removed after writing */
1527 	HashSetValue(he, lefl);
1528 	lefl->canonName = (char *)he->h_key.h_name;
1529     }
1530     return 0;	/* Keep the search going */
1531 }
1532 
1533 /*
1534  *------------------------------------------------------------
1535  *
1536  * defGetType --
1537  *
1538  *	Retrieve the LEF/DEF name of a magic layer from the
1539  *	LefInfo hash table.
1540  *
1541  * Results:
1542  *	The "official" LEF/DEF layer name of the magic type.
1543  *
1544  * Side Effects:
1545  *	If "lefptr" is non-NULL, it is filled with a pointer
1546  *	to the appropriate lefLayer entry, or NULL if there
1547  *	is no corresponding entry.
1548  *------------------------------------------------------------
1549  */
1550 
1551 char *
defGetType(ttype,lefptr,do_vias)1552 defGetType(ttype, lefptr, do_vias)
1553     TileType ttype;
1554     lefLayer **lefptr;
1555     bool do_vias;
1556 {
1557     HashSearch hs;
1558     HashEntry *he;
1559     lefLayer *lefl;
1560     int contact = DBIsContact(ttype) ? CLASS_VIA : CLASS_ROUTE;
1561 
1562     /* Pick up information from the original LefInfo hash table	*/
1563     /* entries created during read-in of the tech file.		*/
1564 
1565     if (LefInfo.ht_table != (HashEntry **) NULL)
1566     {
1567 	HashStartSearch(&hs);
1568 	while (he = HashNext(&LefInfo, &hs))
1569 	{
1570 	    lefl = (lefLayer *)HashGetValue(he);
1571 	    if (lefl && (do_vias == FALSE) && (contact == CLASS_VIA) &&
1572 			(lefl->info.via.lr != NULL))
1573 		continue;	/* Skip VIA definitions if do_vias is FALSE */
1574 
1575 	    if (lefl && ((contact == lefl->lefClass) ||
1576 			((contact == CLASS_ROUTE) && (lefl->lefClass == CLASS_MASTER))))
1577 		if ((lefl->type == ttype) || (lefl->obsType == ttype))
1578 		{
1579 		    if (lefptr) *lefptr = lefl;
1580 		    return lefl->canonName;
1581 		}
1582 	}
1583     }
1584 
1585     /* If we got here, there is no entry;  return NULL. */
1586     if (lefptr) *lefptr = (lefLayer *)NULL;
1587     return NULL;
1588 }
1589 
1590 /*
1591  *------------------------------------------------------------
1592  *
1593  * defWriteVias --
1594  *
1595  *	Output the VIAS section of a DEF file.  We equate magic
1596  *	contact areas with DEF "VIAS".  A separate via entry is
1597  *	generated for each unique geometry.  The exact output
1598  *	is determined from the CIF output rules.
1599  *
1600  * Results:
1601  *	None.
1602  *
1603  * Side Effects:
1604  *	Output written to the DEF output file.
1605  *
1606  *------------------------------------------------------------
1607  */
1608 
1609 void
defWriteVias(f,rootDef,oscale,lefMagicToLefLayer)1610 defWriteVias(f, rootDef, oscale, lefMagicToLefLayer)
1611     FILE *f;				/* File to write to */
1612     CellDef *rootDef;			/* Cell definition to use */
1613     float oscale;			/* Output scale factor */
1614     LefMapping *lefMagicToLefLayer;
1615 {
1616     HashSearch hs;
1617     HashEntry *he;
1618     lefLayer *lefl;
1619     TileTypeBitMask *rMask;
1620     TileType ttype;
1621 
1622     /* Pick up information from the LefInfo hash table	*/
1623     /* created by fucntion defCountVias()		*/
1624 
1625     if (LefInfo.ht_table != (HashEntry **) NULL)
1626     {
1627 	HashStartSearch(&hs);
1628 	while (he = HashNext(&LefInfo, &hs))
1629 	{
1630 	    int size, sep, border;
1631 	    char *us1, *us2;
1632 	    lefl = (lefLayer *)HashGetValue(he);
1633 	    if (!lefl) continue;
1634 
1635 	    /* Only count the generated vias of the type name_sizex_sizey */
1636 
1637 	    if ((us1 = strchr(lefl->canonName, '_')) == NULL ||
1638 	    		(us2 = strrchr(lefl->canonName, '_')) == us1)
1639 		continue;
1640 
1641 	    if (lefl->lefClass == CLASS_VIA)
1642 	    {
1643 		fprintf(f, "   - %s", (char *)lefl->canonName);
1644 
1645 		/* Generate squares for the area as determined	*/
1646 		/* by the cifoutput section of the tech file	*/
1647 
1648 		rMask = DBResidueMask(lefl->type);
1649 		for (ttype = TT_TECHDEPBASE; ttype < DBNumUserLayers; ttype++)
1650 		    if (TTMaskHasType(rMask, ttype))
1651 			fprintf(f, "\n      + RECT %s ( %.10g %.10g ) ( %.10g %.10g )",
1652 				lefMagicToLefLayer[ttype].lefName,
1653 				(float)(lefl->info.via.area.r_xbot) * oscale / 2,
1654 				(float)(lefl->info.via.area.r_ybot) * oscale / 2,
1655 				(float)(lefl->info.via.area.r_xtop) * oscale / 2,
1656 				(float)(lefl->info.via.area.r_ytop) * oscale / 2);
1657 
1658 		/* Handle the contact cuts.	*/
1659 
1660 		if (CIFGetContactSize(lefl->type, &size, &sep, &border))
1661 		{
1662 		    int i, j, nAc, nUp, pitch, left;
1663 		    Rect square, *r = &lefl->info.via.area;
1664 
1665 		    pitch = size + sep;
1666 		    nAc = (r->r_xtop - r->r_xbot + sep - (2 * border)) / pitch;
1667 		    if (nAc == 0)
1668 		    {
1669 			left = (r->r_xbot + r->r_xtop - size) / 2;
1670 			nAc = 1;
1671 			if (left < r->r_xbot)
1672 			{
1673 			    TxError("Warning: via size is %d but area width is %d!\n",
1674 					size, (r->r_xtop - r->r_xbot));
1675 			}
1676 		    }
1677 		    else
1678 			left = (r->r_xbot + r->r_xtop + sep - (nAc * pitch)) / 2;
1679 
1680 		    nUp = (r->r_ytop - r->r_ybot + sep - (2 * border)) / pitch;
1681 		    if (nUp == 0)
1682 		    {
1683 			square.r_ybot = (r->r_ybot + r->r_ytop - size) / 2;
1684 			nUp = 1;
1685 			if (square.r_ybot >= r->r_ybot)
1686 			{
1687 			    TxError("Warning: via size is %d but area height is %d!\n",
1688 					size, (r->r_ytop - r->r_ybot));
1689 			}
1690 		    }
1691 		    else
1692 			square.r_ybot = (r->r_ybot + r->r_ytop + sep - (nUp * pitch)) / 2;
1693 
1694 		    for (i = 0; i < nUp; i++)
1695 		    {
1696 			square.r_ytop = square.r_ybot + size;
1697 			square.r_xbot = left;
1698 			for (j = 0; j < nAc; j++)
1699 			{
1700 			     square.r_xtop = square.r_xbot + size;
1701 
1702 			     fprintf(f, "\n      + RECT %s ( %.10g %.10g )"
1703 					" ( %.10g %.10g )",
1704 					lefMagicToLefLayer[lefl->type].lefName,
1705 					(float)(square.r_xbot) * oscale / 2,
1706 					(float)(square.r_ybot) * oscale / 2,
1707 					(float)(square.r_xtop) * oscale / 2,
1708 					(float)(square.r_ytop) * oscale / 2);
1709 			     square.r_xbot += pitch;
1710 			}
1711 			square.r_ybot += pitch;
1712 		    }
1713 		}
1714 		else
1715 		    /* If we can't find the CIF/GDS parameters for cut	*/
1716 		    /* generation, then output a single rectangle the	*/
1717 		    /* size of the contact tile.			*/
1718 		{
1719 		    fprintf(f, "\n      + RECT %s ( %.10g %.10g ) ( %.10g %.10g )",
1720 			lefMagicToLefLayer[lefl->type].lefName,
1721 			(float)(lefl->info.via.area.r_xbot) * oscale / 2,
1722 			(float)(lefl->info.via.area.r_ybot) * oscale / 2,
1723 			(float)(lefl->info.via.area.r_xtop) * oscale / 2,
1724 			(float)(lefl->info.via.area.r_ytop) * oscale / 2);
1725 	 	}
1726 		fprintf(f, " ;\n");
1727 	    }
1728 	}
1729     }
1730 }
1731 
1732 /*
1733  *------------------------------------------------------------
1734  *
1735  * defCountComponents --
1736  *
1737  *	First-pass function to count the number of cell
1738  *	uses (components) to be written to the DEF output
1739  *	file.
1740  *
1741  * Results:
1742  *	The total number of uses to be written.
1743  *
1744  * Side Effects:
1745  *	None.
1746  *
1747  *------------------------------------------------------------
1748  */
1749 
1750 int
defCountComponents(rootDef)1751 defCountComponents(rootDef)
1752     CellDef *rootDef;
1753 {
1754     pointertype total;
1755     int defCountCompFunc();
1756 
1757     TxPrintf("Diagnostic:  Finding all components of cell %s\n", rootDef->cd_name);
1758 
1759     total = 0;
1760     DBCellEnum(rootDef, defCountCompFunc, (ClientData)&total);
1761     return (int)total;
1762 }
1763 
1764 /* Callback function used by defCountComponents */
1765 
1766 int
defCountCompFunc(cellUse,total)1767 defCountCompFunc(cellUse, total)
1768     CellUse *cellUse;
1769     pointertype *total;
1770 {
1771     /* Ignore any cellUse that does not have an identifier string. */
1772     if (cellUse->cu_id == NULL) return 0;
1773 
1774     /* Make sure that arrays are counted correctly */
1775     int sx = cellUse->cu_xhi - cellUse->cu_xlo + 1;
1776     int sy = cellUse->cu_yhi - cellUse->cu_ylo + 1;
1777     // TxPrintf("Diagnostic: cell %s %d %d\n", cellUse->cu_id, sx, sy);
1778     ASSERT(sx >= 0 && sy >= 0, "Valid array");
1779 
1780     (*total) += sx * sy;	/* Increment the count of uses */
1781 
1782     return 0;	/* Keep the search going */
1783 }
1784 
1785 /*
1786  *------------------------------------------------------------
1787  *
1788  * defCountPins --
1789  *
1790  *	First-pass function to count the number of pins
1791  *	to be written to the DEF output file.
1792  *
1793  * Results:
1794  *	The total number of pins to be written.
1795  *
1796  * Side Effects:
1797  *	None.
1798  *
1799  *------------------------------------------------------------
1800  */
1801 
1802 int
defCountPins(rootDef)1803 defCountPins(rootDef)
1804     CellDef *rootDef;
1805 {
1806     int total;
1807     Label *lab;
1808 
1809     TxPrintf("Diagnostic:  Finding all pins of cell %s\n", rootDef->cd_name);
1810 
1811     total = 0;
1812     for (lab = rootDef->cd_labels; lab; lab = lab->lab_next)
1813 	if (lab->lab_flags & PORT_DIR_MASK)
1814 	    total++;
1815 
1816     return total;
1817 }
1818 
1819 /*
1820  *------------------------------------------------------------
1821  *
1822  * defWritePins --
1823  *
1824  *	Output the PINS section of the DEF file.  This
1825  *	is a listing of all ports, their placement, and
1826  *	name.
1827  *
1828  * Results:
1829  *	None.
1830  *
1831  * Side Effects:
1832  *	Output to the DEF file.
1833  *
1834  *------------------------------------------------------------
1835  */
1836 
1837 void
defWritePins(f,rootDef,oscale)1838 defWritePins(f, rootDef, oscale)
1839     FILE *f;				/* File to write to */
1840     CellDef *rootDef;			/* Cell definition to use */
1841     float oscale;			/* Output scale factor */
1842 {
1843     Label *lab;
1844     int lwidth, lheight;
1845     int dcenterx, dcentery;
1846 
1847     for (lab = rootDef->cd_labels; lab; lab = lab->lab_next)
1848     {
1849 	if (lab->lab_flags & PORT_DIR_MASK)
1850 	{
1851 	    fprintf(f, "   - %s + NET %s\n", lab->lab_text, lab->lab_text);
1852 	    if (lab->lab_flags & PORT_CLASS_MASK)
1853 	    {
1854 		fprintf(f, "     + DIRECTION ");
1855 		switch (lab->lab_flags & PORT_CLASS_MASK)
1856 		{
1857 		    case PORT_CLASS_INPUT:
1858 			fprintf(f, "INPUT");
1859 			break;
1860 		    case PORT_CLASS_OUTPUT:
1861 			fprintf(f, "OUTPUT");
1862 			break;
1863 		    case PORT_CLASS_TRISTATE:
1864 		    case PORT_CLASS_BIDIRECTIONAL:
1865 			fprintf(f, "INOUT");
1866 			break;
1867 		    case PORT_CLASS_FEEDTHROUGH:
1868 			fprintf(f, "FEEDTHRU");
1869 			break;
1870 		}
1871 		fprintf(f, "\n");
1872 	    }
1873 	    if (lab->lab_flags & PORT_USE_MASK)
1874 	    {
1875 		fprintf(f, "     + USE ");
1876 		switch (lab->lab_flags & PORT_USE_MASK)
1877 		{
1878 		    case PORT_USE_SIGNAL:
1879 			fprintf(f, "SIGNAL");
1880 			break;
1881 		    case PORT_USE_ANALOG:
1882 			fprintf(f, "ANALOG");
1883 			break;
1884 		    case PORT_USE_POWER:
1885 			fprintf(f, "POWER");
1886 			break;
1887 		    case PORT_USE_GROUND:
1888 			fprintf(f, "GROUND");
1889 			break;
1890 		    case PORT_USE_CLOCK:
1891 			fprintf(f, "CLOCK");
1892 			break;
1893 		}
1894 		fprintf(f, "\n");
1895 	    }
1896 
1897 	    lwidth = lab->lab_rect.r_xtop - lab->lab_rect.r_xbot;
1898 	    lheight = lab->lab_rect.r_ytop - lab->lab_rect.r_ybot;
1899 
1900 	    dcenterx = lab->lab_rect.r_xtop + lab->lab_rect.r_xbot;
1901 	    dcentery = lab->lab_rect.r_ytop + lab->lab_rect.r_ybot;
1902 
1903 	    fprintf(f, "     + PORT\n");
1904 	    fprintf(f, "        + LAYER %s ( %.10g %.10g ) ( %.10g %.10g )",
1905 		    DBTypeLongNameTbl[lab->lab_type],
1906 		    oscale * (float)(-lwidth) / 2.0, oscale * (float)(-lheight) / 2.0,
1907 		    oscale * (float)lwidth / 2.0, oscale * (float)lheight / 2.0);
1908 	    fprintf(f, "        + PLACED ( %.10g %.10g ) N ;\n",
1909 		    oscale * (float)dcenterx / 2.0, oscale * (float)dcentery / 2.0);
1910 	}
1911     }
1912 }
1913 
1914 /*
1915  *------------------------------------------------------------
1916  *
1917  * defWriteComponents --
1918  *
1919  *	Output the COMPONENTS section of the DEF file.  This
1920  *	is a listing of all cell uses, their placement, and
1921  *	orientation.
1922  *
1923  * Results:
1924  *	None.
1925  *
1926  * Side Effects:
1927  *	Output to the DEF file.
1928  *
1929  *------------------------------------------------------------
1930  */
1931 
1932 void
defWriteComponents(f,rootDef,oscale)1933 defWriteComponents(f, rootDef, oscale)
1934     FILE *f;				/* File to write to */
1935     CellDef *rootDef;			/* Cell definition to use */
1936     float oscale;			/* Output scale factor */
1937 {
1938     DefData defdata;
1939     int defComponentFunc();		/* Forward declaration */
1940 
1941     defdata.f = f;
1942     defdata.scale = oscale;
1943 
1944     DBCellEnum(rootDef, defComponentFunc, (ClientData)&defdata);
1945 }
1946 
1947 /* Callback function used by defWriteComponents for array members */
1948 
1949 int
arrayDefFunc(use,transform,x,y,defdata)1950 arrayDefFunc(use, transform, x, y, defdata)
1951     CellUse *use;		/* CellUse for array element */
1952     Transform *transform;	/* Transform from use to parent */
1953     int x, y;			/* Indices of element */
1954     DefData *defdata;
1955 {
1956     int sx = use->cu_xhi - use->cu_xlo;
1957     int sy = use->cu_yhi - use->cu_ylo;
1958     char idx[32];
1959     Rect box;
1960 
1961     idx[0] = 0;
1962 
1963     if (sy) sprintf(idx, "%d%s", y, sx ? "," : "");
1964     if (sx) sprintf(idx + strlen(idx), "%d", x);
1965 
1966     GeoTransRect(transform, &use->cu_def->cd_bbox, &box);
1967 
1968     fprintf(defdata->f, "   - %s[%s] %s\n      + PLACED ( %.10g %.10g ) %s ;\n",
1969 		use->cu_id, idx, use->cu_def->cd_name,
1970 		(float)box.r_xbot * defdata->scale,
1971 		(float)box.r_ybot * defdata->scale,
1972 		defTransPos(&use->cu_transform));
1973     return 0;
1974 }
1975 
1976 /* Callback function used by defWriteComponents */
1977 
1978 int
defComponentFunc(cellUse,defdata)1979 defComponentFunc(cellUse, defdata)
1980     CellUse *cellUse;
1981     DefData *defdata;
1982 {
1983     FILE *f = defdata->f;
1984     float oscale = defdata->scale;
1985     char *nameroot;
1986 
1987     /* Ignore any cellUse that does not have an identifier string. */
1988     if (cellUse->cu_id == NULL) return 0;
1989 
1990     if (cellUse->cu_xlo != cellUse->cu_xhi || cellUse->cu_ylo != cellUse->cu_yhi) {
1991 	/* expand the array */
1992 	DBArraySr(cellUse, &cellUse->cu_bbox, arrayDefFunc, defdata);
1993 	return 0;
1994     }
1995 
1996     /* In case the cd_name contains a path component (it's not supposed to),	*/
1997     /* remove it.								*/
1998 
1999     nameroot = strrchr(cellUse->cu_def->cd_name, '/');
2000     if (nameroot != NULL)
2001 	nameroot++;
2002     else
2003 	nameroot = cellUse->cu_def->cd_name;
2004 
2005     fprintf(f, "   - %s %s\n      + PLACED ( %.10g %.10g ) %s ;\n",
2006 		cellUse->cu_id, nameroot,
2007 		(float)(cellUse->cu_bbox.r_xbot - cellUse->cu_def->cd_bbox.r_ll.p_x)
2008 		* oscale,
2009 		(float)(cellUse->cu_bbox.r_ybot - cellUse->cu_def->cd_bbox.r_ll.p_y)
2010 		* oscale,
2011 		defTransPos(&cellUse->cu_transform));
2012 
2013     return 0;	/* Keep the search going */
2014 }
2015 
2016 /*
2017  *------------------------------------------------------------
2018  *
2019  * defMakeInverseLayerMap ---
2020  *
2021  *	Generate an array of pointers to lefLayer structures for each
2022  *	magic type so we can do a quick lookup when searching over tiles.
2023  *
2024  * Results:
2025  *	Pointer to the inverse layer map.
2026  *
2027  * Side effects:
2028  *	Memory is allocated for the map structure array.
2029  *
2030  *------------------------------------------------------------
2031  */
2032 
2033 LefMapping *
defMakeInverseLayerMap(do_vias)2034 defMakeInverseLayerMap(do_vias)
2035     bool do_vias;
2036 {
2037     LefMapping *lefMagicToLefLayer;
2038     lefLayer *lefl;
2039     TileType i;
2040     char *lefname;
2041 
2042     lefMagicToLefLayer = (LefMapping *)mallocMagic(DBNumTypes
2043 		* sizeof(LefMapping));
2044     memset(lefMagicToLefLayer, 0, sizeof(LefMapping) * TT_TECHDEPBASE);
2045     for (i = TT_TECHDEPBASE; i < DBNumTypes; i++)
2046     {
2047 	lefname = defGetType(i, &lefl, do_vias);
2048 	lefMagicToLefLayer[i].lefName = lefname;
2049 	lefMagicToLefLayer[i].lefInfo = lefl;
2050     }
2051     return lefMagicToLefLayer;
2052 }
2053 
2054 /*
2055  *------------------------------------------------------------
2056  *
2057  * DefWriteAll --
2058  *
2059  * Results:
2060  *
2061  * Side Effects:
2062  *
2063  *------------------------------------------------------------
2064  */
2065 
2066 /* To do:  routine DefWriteAll().					*/
2067 
2068 /* DEF does not handle hierarchy.  However, we should assume that we	*/
2069 /* want to write out a DEF file for each cell in the hierarchy.  But,	*/
2070 /* we should stop at any cells defining ports, assuming that they are	*/
2071 /* standard cells and not part of the routing.				*/
2072 
2073 /* Maybe there should be a method for specifying that any hierarchy	*/
2074 /* should be flattened when writing to the DEF file output.		*/
2075 
2076 
2077 /*
2078  *------------------------------------------------------------
2079  *
2080  * DefWriteCell --
2081  *
2082  *	Write DEF-format output for the indicated cell.
2083  *
2084  * Results:
2085  *	None.
2086  *
2087  * Side effects:
2088  *	Writes a single .def file to disk.
2089  *
2090  *------------------------------------------------------------
2091  */
2092 
2093 void
DefWriteCell(def,outName,allSpecial,units)2094 DefWriteCell(def, outName, allSpecial, units)
2095     CellDef *def;		/* Cell being written */
2096     char *outName;		/* Name of output file, or NULL. */
2097     bool allSpecial;		/* Treat all nets as SPECIALNETS? */
2098     int units;			/* Force units to this value (default 1000) */
2099 {
2100     char *filename;
2101     FILE *f;
2102     NetCount nets;
2103     int total;
2104     float scale;
2105 
2106     LefMapping *lefMagicToLefLayer;
2107     int i;
2108     lefLayer *lefl;
2109     HashEntry *he;
2110 
2111     /* Note that "1" corresponds to "1000" in the header UNITS line,	*/
2112     /* or units of nanometers.  10 = centimicrons, 1000 = microns.	*/
2113 
2114     scale = CIFGetOutputScale(1000 / units);
2115 
2116     f = lefFileOpen(def, outName, ".def", "w", &filename);
2117 
2118     TxPrintf("Generating DEF output %s for cell %s:\n", filename, def->cd_name);
2119 
2120     if (f == NULL)
2121     {
2122 #ifdef MAGIC_WRAPPER
2123 	TxError("Cannot open output file %s (%s).\n", filename,
2124 		strerror(errno));
2125 #else
2126 	TxError("Cannot open output file: ");
2127 	perror(filename);
2128 #endif
2129 	return;
2130     }
2131 
2132     defWriteHeader(def, f, scale, units);
2133 
2134     lefMagicToLefLayer = defMakeInverseLayerMap(LAYER_MAP_VIAS);
2135 
2136     /* Vias---magic contact areas are reported as vias. */
2137     total = defCountVias(def, lefMagicToLefLayer, scale);
2138     fprintf(f, "VIAS %d ;\n", total);
2139     if (total > 0)
2140 	defWriteVias(f, def, scale, lefMagicToLefLayer);
2141     fprintf(f, "END VIAS\n\n");
2142 
2143     /* Components (i.e., cell uses) */
2144     total = defCountComponents(def);
2145     fprintf(f, "COMPONENTS %d ;\n", total);
2146     if (total > 0)
2147 	defWriteComponents(f, def, scale);
2148     fprintf(f, "END COMPONENTS\n\n");
2149 
2150     /* Pins---assume no pins (for now) */
2151     total = defCountPins(def);
2152     fprintf(f, "PINS %d ;\n", total);
2153     if (total > 0)
2154 	defWritePins(f, def, scale);
2155     fprintf(f, "END PINS\n\n");
2156 
2157     /* Count the number of nets and "special" nets */
2158     nets = defCountNets(def, allSpecial);
2159 
2160     /* "Special" nets---nets matching $GND, $VDD, or $globals(*) 	*/
2161 
2162     fprintf(f, "SPECIALNETS %d ;\n", nets.special);
2163     if (nets.special > 0)
2164 	defWriteNets(f, def, scale, lefMagicToLefLayer, (allSpecial) ?
2165 		ALL_SPECIAL : DO_SPECIAL);
2166     fprintf(f, "END SPECIALNETS\n\n");
2167 
2168     /* "Regular" nets */
2169     fprintf(f, "NETS %d ;\n", nets.regular);
2170     if (nets.regular > 0)
2171 	defWriteNets(f, def, scale, lefMagicToLefLayer, DO_REGULAR);
2172     fprintf(f, "END NETS\n\n");
2173 
2174     if (nets.has_nets) {
2175 	EFFlatDone(NULL);
2176 	EFDone(NULL);
2177     }
2178 
2179     fprintf(f, "END DESIGN\n\n");
2180     fclose(f);
2181 
2182     freeMagic((char *)lefMagicToLefLayer);
2183     lefRemoveGeneratedVias();
2184 }
2185 
2186