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