1 // *****************************************************************************
2 // *****************************************************************************
3 // Copyright 2012 - 2015, Cadence Design Systems
4 //
5 // This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source
6 // Distribution,  Product Version 5.8.
7 //
8 // Licensed under the Apache License, Version 2.0 (the "License");
9 //    you may not use this file except in compliance with the License.
10 //    You may obtain a copy of the License at
11 //
12 //        http://www.apache.org/licenses/LICENSE-2.0
13 //
14 //    Unless required by applicable law or agreed to in writing, software
15 //    distributed under the License is distributed on an "AS IS" BASIS,
16 //    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
17 //    implied. See the License for the specific language governing
18 //    permissions and limitations under the License.
19 //
20 // For updates, support, or to become part of the LEF/DEF Community,
21 // check www.openeda.org for details.
22 //
23 //  $Author$
24 //  $Revision$
25 //  $Date$
26 //  $State:  $
27 // *****************************************************************************
28 // *****************************************************************************
29 
30 // This program is the diffLef core program.  It has all the callback
31 // routines and write it out to a temporary file
32 
33 #include <stdio.h>
34 #include <string.h>
35 #ifndef WIN32
36 #   include <unistd.h>
37 #endif /* not WIN32 */
38 #include "lefrReader.hpp"
39 #include "lefwWriter.hpp"
40 #include "lefiDebug.hpp"
41 
42 char    defaultName[128];
43 char    defaultOut[128];
44 FILE*   fout;
45 int     printing = 0;     // Printing the output.
46 void*   userData;
47 
48 // TX_DIR:TRANSLATION ON
49 
dataError()50 void dataError() {
51   fprintf(fout, "ERROR: returned user data is not correct!\n");
52 }
53 
54 
checkType(lefrCallbackType_e c)55 void checkType(lefrCallbackType_e c) {
56   if (c >= 0 && c <= lefrLibraryEndCbkType) {
57     // OK
58   } else {
59     fprintf(fout, "ERROR: callback type is out of bounds!\n");
60   }
61 }
62 
63 // 05/24/2001 - Wanda da Rosa.  PCR 373170
64 // This function is added due to the rounding between machines are
65 // different.  For a 5, solaries will round down while hppa will roundup.
66 // This function will make sure it round up for all the machine
chkNum(double num)67 double chkNum(double num) {
68   long tempNum;
69   if ((num > 1000004) || (num < -1000004)) {
70      tempNum = (long)num;
71      if ((tempNum%5) == 0)
72         return num + 3;
73   }
74   return num;
75 }
76 
77 // Print Via
lefVia(lefiVia * via,char * inName)78 void lefVia(lefiVia* via, char* inName) {
79   int i, j;
80 
81   fprintf(fout, "%s %s", inName, via->name());
82   if (via->hasDefault())
83      fprintf(fout, " DEFAULT");
84   if (via->hasGenerated())
85      fprintf(fout, " GENERATED");
86   if (via->hasTopOfStack())
87      fprintf(fout, " TOPOFSTACKONLY");
88   if (via->hasForeign()) {
89      fprintf(fout, " FOREIGN %s", via->foreign());
90      if (via->hasForeignPnt()) {
91         fprintf(fout, " ( %g %g )", chkNum(via->foreignX()),
92                 chkNum(via->foreignY()));
93         if (via->hasForeignOrient())
94            fprintf(fout, " %s", lefiOrientStr(via->foreignOrient()));
95      }
96   }
97   fprintf(fout, "\n");
98   if (via->hasProperties()) {
99      for (i = 0; i < via->numProperties(); i++) {
100         fprintf(fout, "%s %s PROP", inName, via->name());
101         fprintf(fout, " %s", via->propName(i));
102         if (via->propIsNumber(i))
103            fprintf(fout, " %g", chkNum(via->propNumber(i)));
104         if (via->propIsString(i))
105            fprintf(fout, " %s", via->propValue(i));
106         fprintf(fout, "\n");
107      }
108   }
109   if (via->hasViaRule()) {
110      fprintf(fout, "%s %s %g %g %s %s %s %g %g %g %g %g %g", via->name(),
111              via->viaRuleName(), via->xCutSize(), via->yCutSize(),
112              via->botMetalLayer(),  via->cutLayer(), via->topMetalLayer(),
113              via->xCutSpacing(), via->yCutSpacing(), via->xBotEnc(),
114              via->yBotEnc(), via->xTopEnc(), via->yTopEnc());
115      if (via->hasRowCol())
116         fprintf(fout, " %d %d", via->numCutRows(), via->numCutCols());
117      if (via->hasOrigin())
118         fprintf(fout, " %g %g", via->xOffset(), via->yOffset());
119      if (via->hasOffset())
120         fprintf(fout, " %g %g %g %g", via->xBotOffset(), via->yBotOffset(),
121                 via->xTopOffset(), via->yTopOffset());
122      if (via->hasCutPattern())
123         fprintf(fout, " %s", via->cutPattern());
124      fprintf(fout, "\n");
125   }
126   if (via->hasResistance())
127      fprintf(fout, "%s %s RESISTANCE %g\n",inName, via->name(),
128              chkNum(via->resistance()));
129   if (via->numLayers() > 0) {
130      for (i = 0; i < via->numLayers(); i++) {
131         fprintf(fout, "%s %s LAYER %s\n", inName, via->name(),
132                 via->layerName(i));
133         for (j = 0; j < via->numRects(i); j++) {
134 	   if (via->rectColorMask(i, j)) {
135 		fprintf(fout, "%s %s RECT MASK % d ( %g %g ) ( %g %g )\n",
136 			inName, via->name(), via->rectColorMask(i, j),
137 			chkNum(via->xl(i, j)), chkNum(via->yl(i, j)),
138 			chkNum(via->xh(i, j)), chkNum(via->yh(i, j)));
139            } else {
140 		fprintf(fout, "%s %s RECT ( %g %g ) ( %g %g )\n", inName,
141 			via->name(),
142 			chkNum(via->xl(i, j)), chkNum(via->yl(i, j)),
143 			chkNum(via->xh(i, j)), chkNum(via->yh(i, j)));
144 	    }
145 	}
146         for (j = 0; j < via->numPolygons(i); j++) {
147            struct lefiGeomPolygon poly;
148            poly = via->getPolygon(i, j);
149 	   if (via->polyColorMask(i, j)) {
150                fprintf(fout, "%s %s POLYGON MASK %d", inName, via->name(),
151 		       via->polyColorMask(i, j));
152            } else {
153 	       fprintf(fout, "%s %s POLYGON", inName, via->name());
154 	   }
155            for (int k = 0; k < poly.numPoints; k++)
156               fprintf(fout, " %g %g", poly.x[k], poly.y[k]);
157            fprintf(fout, "\n");
158         }
159      }
160   }
161   return;
162 }
163 
164 // Print Spacing
lefSpacing(lefiSpacing * spacing,char * inName)165 void lefSpacing(lefiSpacing* spacing, char *inName) {
166   fprintf(fout, "%s SAMENET %s %s %g ", inName, spacing->name1(),
167           spacing->name2(), chkNum(spacing->distance()));
168   if (spacing->hasStack())
169      fprintf(fout, " STACK");
170   fprintf(fout,"\n");
171   return;
172 }
173 
174 // Print Via Rule Layer
lefViaRuleLayer(lefiViaRuleLayer * vLayer,char * viaName)175 void lefViaRuleLayer(lefiViaRuleLayer* vLayer, char* viaName) {
176   fprintf(fout, "VIARULE %s LAYER %s", viaName, vLayer->name());
177   if (vLayer->hasDirection()) {
178      if (vLayer->isHorizontal())
179         fprintf(fout, " DIRECTION HORIZONTAL");
180      if (vLayer->isVertical())
181         fprintf(fout, " DIRECTION VERTICAL");
182   }
183   if (vLayer->hasEnclosure())
184      fprintf(fout, " ENCLOSURE %g %g\n", chkNum(vLayer->enclosureOverhang1()),
185              chkNum(vLayer->enclosureOverhang2()));
186   if (vLayer->hasWidth())
187      fprintf(fout, " WIDTH %g TO %g", chkNum(vLayer->widthMin()),
188                    chkNum(vLayer->widthMax()));
189   if (vLayer->hasResistance())
190      fprintf(fout, " RESISTANCE %g", chkNum(vLayer->resistance()));
191   if (vLayer->hasOverhang())
192      fprintf(fout, " OVERHANG %g", chkNum(vLayer->overhang()));
193   if (vLayer->hasMetalOverhang())
194      fprintf(fout, " METALOVERHANG %g", chkNum(vLayer->metalOverhang()));
195   if (vLayer->hasSpacing())
196      fprintf(fout, " SPACING %g BY %g", chkNum(vLayer->spacingStepX()),
197              chkNum(vLayer->spacingStepY()));
198   if (vLayer->hasRect())
199      fprintf(fout, " RECT ( %g %g ) ( %g %g )", chkNum(vLayer->xl()),
200              chkNum(vLayer->yl()), chkNum(vLayer->xh()), chkNum(vLayer->yh()));
201   fprintf(fout, "\n");
202   return;
203 }
204 
205 // Print Geometry
prtGeometry(lefiGeometries * geometry,char * inName)206 void prtGeometry(lefiGeometries* geometry, char* inName) {
207   int                   numItems = geometry->numItems();
208   int                   i, j;
209   lefiGeomPath*         path;
210   lefiGeomPathIter*     pathIter;
211   lefiGeomRect*         rect;
212   lefiGeomRectIter*     rectIter;
213   lefiGeomPolygon*      polygon;
214   lefiGeomPolygonIter*  polygonIter;
215   lefiGeomVia*          via;
216   lefiGeomViaIter*      viaIter;
217 
218   for (i = 0; i < numItems; i++) {
219      switch (geometry->itemType(i)) {
220         case  lefiGeomClassE:
221              fprintf(fout, "%s CLASS %s\n", inName, geometry->getClass(i));
222              break;
223         case lefiGeomLayerE:
224              fprintf(fout, "%s LAYER %s\n", inName, geometry->getLayer(i));
225              break;
226         case lefiGeomLayerMinSpacingE:
227              fprintf(fout, "%s SPACING %g\n", inName,
228                      chkNum(geometry->getLayerMinSpacing(i)));
229              break;
230         case lefiGeomLayerExceptPgNetE:
231              fprintf(fout, "%s EXCEPTPGNET\n", inName);
232              break;
233         case lefiGeomLayerRuleWidthE:
234              fprintf(fout, "%s DESIGNRULEWIDTH %g\n", inName,
235                      chkNum(geometry->getLayerRuleWidth(i)));
236              break;
237         case lefiGeomWidthE:
238              fprintf(fout, "%s WIDTH %g\n", inName,
239                      chkNum(geometry->getWidth(i)));
240              break;
241         case lefiGeomPathE:
242              path = geometry->getPath(i);
243 	     if (path->colorMask != 0) {
244                 fprintf(fout, "%s PATH MASK %d ", inName, path->colorMask);
245              } else {
246 		fprintf(fout, "%s PATH ", inName);
247              }
248 
249              for (j = 0; j < path->numPoints; j++) {
250                 if (j+1 == path->numPoints) // last one on the list
251                    fprintf(fout, " ( %g %g )\n", chkNum(path->x[j]),
252                            chkNum(path->y[j]));
253                 else
254                    fprintf(fout, " ( %g %g )", chkNum(path->x[j]),
255                            chkNum(path->y[j]));
256              }
257              break;
258         case lefiGeomPathIterE:
259              pathIter = geometry->getPathIter(i);
260 	     if (pathIter->colorMask != 0) {
261                 fprintf(fout, "%s PATH MASK %d ITERATED ", inName,
262 			pathIter->colorMask);
263             } else {
264 		fprintf(fout, "%s PATH ITERATED ", inName);
265 	    }
266              for (j = 0; j < pathIter->numPoints; j++)
267                 fprintf(fout, " ( %g %g )", chkNum(pathIter->x[j]),
268                         chkNum(pathIter->y[j]));
269              fprintf(fout, " DO %g BY %g STEP %g %g\n",
270                      chkNum(pathIter->xStart), chkNum(pathIter->yStart),
271                      chkNum(pathIter->xStep), chkNum(pathIter->yStep));
272              break;
273         case lefiGeomRectE:
274              rect = geometry->getRect(i);
275 	     if (rect->colorMask != 0) {
276 		 fprintf(fout, "%s RECT MASK %d ( %g %g ) ( %g %g )\n",
277 			 inName, rect->colorMask,
278 			 chkNum(rect->xl), chkNum(rect->yl),
279 			 chkNum(rect->xh), chkNum(rect->yh));
280 	     } else {
281 		fprintf(fout, "%s RECT ( %g %g ) ( %g %g )\n", inName,
282 			chkNum(rect->xl), chkNum(rect->yl),
283 			chkNum(rect->xh), chkNum(rect->yh));
284 	     }
285              break;
286         case lefiGeomRectIterE:
287              rectIter = geometry->getRectIter(i);
288 	     if (rectIter->colorMask != 0) {
289 		 fprintf(fout, "%s RECT MASK %d ITERATE ( %g %g ) ( %g %g )",
290 			 inName, rectIter->colorMask,
291 			 chkNum(rectIter->xl), chkNum(rectIter->yl),
292 			 chkNum(rectIter->xh), chkNum(rectIter->yh));
293 	     } else {
294 		 fprintf(fout, "%s RECT ITERATE ( %g %g ) ( %g %g )", inName,
295 			 chkNum(rectIter->xl), chkNum(rectIter->yl),
296                          chkNum(rectIter->xh), chkNum(rectIter->yh));
297 	     }
298              fprintf(fout, " DO %g BY %g STEP %g %g ;\n",
299                      chkNum(rectIter->xStart), chkNum(rectIter->yStart),
300                      chkNum(rectIter->xStep), chkNum(rectIter->yStep));
301              break;
302         case lefiGeomPolygonE:
303              polygon = geometry->getPolygon(i);
304 	     if (polygon->colorMask != 0) {
305 		 fprintf(fout, "%s POLYGON MASK %d ", inName, polygon->colorMask);
306 	     } else {
307 		 fprintf(fout, "%s POLYGON ", inName);
308 	     }
309              for (j = 0; j < polygon->numPoints; j++) {
310                 if (j+1 == polygon->numPoints) // last one on the list
311                    fprintf(fout, " ( %g %g )\n", chkNum(polygon->x[j]),
312                            chkNum(polygon->y[j]));
313                 else
314                    fprintf(fout, " ( %g %g )", chkNum(polygon->x[j]),
315                            chkNum(polygon->y[j]));
316              }
317              break;
318         case lefiGeomPolygonIterE:
319              polygonIter = geometry->getPolygonIter(i);
320 	     if (polygonIter->colorMask != 0) {
321 		 fprintf(fout, "%s POLYGON MASK %d ITERATE", inName,
322 			 polygonIter->colorMask);
323 	     } else {
324 		 fprintf(fout, "%s POLYGON ITERATE", inName);
325 	     }
326              for (j = 0; j < polygonIter->numPoints; j++)
327                    fprintf(fout, " ( %g %g )", chkNum(polygonIter->x[j]),
328                            chkNum(polygonIter->y[j]));
329              fprintf(fout, " DO %g BY %g STEP %g %g\n",
330                      chkNum(polygonIter->xStart), chkNum(polygonIter->yStart),
331                      chkNum(polygonIter->xStep), chkNum(polygonIter->yStep));
332              break;
333         case lefiGeomViaE:
334              via = geometry->getVia(i);
335 	     if (via->topMaskNum != 0 || via->bottomMaskNum != 0 || via->cutMaskNum !=0) {
336 		fprintf(fout, "%s VIA MASK %d%d%d ( %g %g ) %s\n", inName,
337 			via->topMaskNum, via->cutMaskNum, via->bottomMaskNum,
338 			chkNum(via->x),
339 			chkNum(via->y), via->name);
340 	     } else {
341 		fprintf(fout, "%s VIA ( %g %g ) %s\n", inName, chkNum(via->x),
342 			chkNum(via->y), via->name);
343 	     }
344              break;
345         case lefiGeomViaIterE:
346              viaIter = geometry->getViaIter(i);
347 	     if (viaIter->topMaskNum != 0 || viaIter->cutMaskNum != 0 || viaIter->bottomMaskNum != 0) {
348 		fprintf(fout, "%s VIA ITERATE MASK %d%d%d ( %g %g ) %s", inName,
349 			viaIter->topMaskNum, viaIter->cutMaskNum,
350 			viaIter->bottomMaskNum,
351 			chkNum(viaIter->x), chkNum(viaIter->y), viaIter->name);
352 	     } else {
353 		fprintf(fout, "%s VIA ITERATE ( %g %g ) %s", inName,
354 			chkNum(viaIter->x), chkNum(viaIter->y), viaIter->name);
355 	     }
356              fprintf(fout, " DO %g BY %g STEP %g %g\n",
357                      chkNum(viaIter->xStart), chkNum(viaIter->yStart),
358                      chkNum(viaIter->xStep), chkNum(viaIter->yStep));
359              break;
360         default:
361              fprintf(fout, "BOGUS geometries type.\n");
362              break;
363      }
364   }
365 }
366 
367 // Antenna
antennaCB(lefrCallbackType_e c,double value,lefiUserData ud)368 int antennaCB(lefrCallbackType_e c, double value, lefiUserData ud) {
369   checkType(c);
370   if (ud != userData) dataError();
371 
372   switch (c) {
373         case lefrAntennaInputCbkType:
374              fprintf(fout, "ANTINPUTGATEAREA %g\n", chkNum(value));
375              break;
376         case lefrAntennaInoutCbkType:
377              fprintf(fout, "ANTINOUTDIFFAREA %g\n", chkNum(value));
378              break;
379         case lefrAntennaOutputCbkType:
380              fprintf(fout, "ANTOUTPUTDIFFAREA %g\n", chkNum(value));
381              break;
382         case lefrInputAntennaCbkType:
383              fprintf(fout, "INPUTPINANTENNASIZE %g\n", chkNum(value));
384              break;
385         case lefrOutputAntennaCbkType:
386              fprintf(fout, "OUTPUTPINANTENNASIZE %g\n", chkNum(value));
387              break;
388         case lefrInoutAntennaCbkType:
389              fprintf(fout, "INOUTPINANTENNASIZE %g\n", chkNum(value));
390              break;
391         default:
392              break;
393   }
394   return 0;
395 }
396 
397 // Array
arrayCB(lefrCallbackType_e c,lefiArray * a,lefiUserData ud)398 int arrayCB(lefrCallbackType_e c, lefiArray* a, lefiUserData ud) {
399   int              i, j, defCaps;
400   lefiSitePattern* pattern;
401   lefiTrackPattern* track;
402   lefiGcellPattern* gcell;
403 
404   checkType(c);
405   if (ud != userData) dataError();
406 
407   if (a->numSitePattern() > 0) {
408      for (i = 0; i < a->numSitePattern(); i++) {
409         pattern = a->sitePattern(i);
410         fprintf(fout, "ARRAY %s SITE %s %g %g %s DO %g BY %g STEP %g %g\n",
411                a->name(), pattern->name(), chkNum(pattern->x()),
412                chkNum(pattern->y()), lefiOrientStr(pattern->orient()),
413                chkNum(pattern->xStart()), chkNum(pattern->yStart()),
414                chkNum(pattern->xStep()), chkNum(pattern->yStep()));
415      }
416   }
417   if (a->numCanPlace() > 0) {
418      for (i = 0; i < a->numCanPlace(); i++) {
419         pattern = a->canPlace(i);
420         fprintf(fout, "ARRAY %s CANPLACE %s %g %g %s DO %g BY %g STEP %g %g\n",
421                a->name(), pattern->name(), chkNum(pattern->x()),
422                chkNum(pattern->y()), lefiOrientStr(pattern->orient()),
423                chkNum(pattern->xStart()), chkNum(pattern->yStart()),
424                chkNum(pattern->xStep()), chkNum(pattern->yStep()));
425      }
426   }
427   if (a->numCannotOccupy() > 0) {
428      for (i = 0; i < a->numCannotOccupy(); i++) {
429         pattern = a->cannotOccupy(i);
430         fprintf(fout, "ARRAY %s CANNOTOCCUPY %s %g %g %s DO %g BY %g STEP %g %g\n",
431                a->name(), pattern->name(), chkNum(pattern->x()),
432                chkNum(pattern->y()), lefiOrientStr(pattern->orient()),
433                chkNum(pattern->xStart()), chkNum(pattern->yStart()),
434                chkNum(pattern->xStep()), chkNum(pattern->yStep()));
435      }
436   }
437 
438   if (a->numTrack() > 0) {
439      for (i = 0; i < a->numTrack(); i++) {
440         track = a->track(i);
441         // 11/22/99 - Wanda da Rosa, PCR 283781.  Merge the track with
442         // layer names.  This way, if user split the layer into different
443         // line, the diff program won't generate extra lines.
444         if (track->numLayers() == 0) {
445            fprintf(fout, "ARRAY %s TRACKS %s, %g DO %d STEP %g\n", a->name(),
446                    track->name(), chkNum(track->start()), track->numTracks(),
447                    chkNum(track->space()));
448         } else {
449            fprintf(fout, "ARRAY %s TRACKS %s, %g DO %d STEP %g ", a->name(),
450                    track->name(), chkNum(track->start()), track->numTracks(),
451                    chkNum(track->space()));
452            for (j = 0; j < track->numLayers(); j++)
453               fprintf(fout, "%s ", track->layerName(j));
454            fprintf(fout, ";\n");
455         }
456      }
457   }
458 
459   if (a->numGcell() > 0) {
460      for (i = 0; i < a->numGcell(); i++) {
461         gcell = a->gcell(i);
462         fprintf(fout, "ARRAY %s GCELLGRID %s, %g DO %d STEP %g\n", a->name(),
463                 gcell->name(), chkNum(gcell->start()), gcell->numCRs(),
464                 chkNum(gcell->space()));
465      }
466   }
467 
468   if (a->numFloorPlans() > 0) {
469      for (i = 0; i < a->numFloorPlans(); i++) {
470         for (j = 0; j < a->numSites(i); j++) {
471            pattern = a->site(i, j);
472            fprintf(fout,
473                "ARRAY %s FLOORPLAN %s %s %s %g %g %s DO %d BY %d STEP %g %g\n",
474                a->name(), a->floorPlanName(i), a->siteType(i, j),
475                pattern->name(), chkNum(pattern->x()), chkNum(pattern->y()),
476                lefiOrientStr(pattern->orient()), pattern->xStart(),
477                pattern->yStart(), chkNum(pattern->xStep()),
478                chkNum(pattern->yStep()));
479         }
480      }
481   }
482 
483   defCaps = a->numDefaultCaps();
484   if (defCaps > 0) {
485      for (i = 0; i < defCaps; i++)
486         fprintf(fout, "ARRAY %s DEFAULTCAP %d MINPINS %g WIRECAP %g\n",
487                 a->name(), defCaps, chkNum(a->defaultCapMinPins(i)),
488                 chkNum(a->defaultCap(i)));
489   }
490   return 0;
491 }
492 
493 // Busbitchar
busBitCharsCB(lefrCallbackType_e c,const char * busBit,lefiUserData ud)494 int busBitCharsCB(lefrCallbackType_e c, const char* busBit, lefiUserData ud)
495 {
496   checkType(c);
497   if (ud != userData) dataError();
498   // use the lef writer to write out the data
499   fprintf(fout, "BUSBITCHARS %s\n", busBit);
500   return 0;
501 }
502 
503 // CaseSensitive
caseSensCB(lefrCallbackType_e c,int caseSense,lefiUserData ud)504 int caseSensCB(lefrCallbackType_e c, int caseSense, lefiUserData ud) {
505   checkType(c);
506   if (ud != userData) dataError();
507 
508   if (caseSense == TRUE)
509      fprintf(fout, "NAMESCASESENSITIVE ON\n");
510   else
511      fprintf(fout, "NAMESCASESENSITIVE OFF\n");
512   return 0;
513 }
514 
515 // FixedMask
fixedMaskCB(lefrCallbackType_e c,int fixedMask,lefiUserData ud)516 int fixedMaskCB(lefrCallbackType_e c, int fixedMask, lefiUserData ud) {
517     checkType(c);
518     if (ud != userData) dataError();
519 
520     if (fixedMask == 1)
521         fprintf(fout, "FIXEDMASK ;\n");
522     return 0;
523 }
524 
525 // Crearance
clearanceCB(lefrCallbackType_e c,const char * name,lefiUserData ud)526 int clearanceCB(lefrCallbackType_e c, const char* name, lefiUserData ud) {
527   checkType(c);
528   if (ud != userData) dataError();
529 
530   fprintf(fout, "CLEARANCEMEASURE %s\n", name);
531   return 0;
532 }
533 
534 // Crosstalk correcttable
correctTableCB(lefrCallbackType_e c,lefiCorrectionTable * table,lefiUserData ud)535 int correctTableCB(lefrCallbackType_e c, lefiCorrectionTable* table,
536                    lefiUserData ud) {
537   int                      i, j, k, l;
538   lefiCorrectionEdge       *edge;
539   lefiCorrectionResistance *resist;
540   lefiCorrectionVictim     *victim;
541 
542   checkType(c);
543   if (ud != userData) dataError();
544 
545   fprintf(fout, "CROSSTALK CORRECTIONTABLE %d\n", table->num());
546   for (i = 0; i < table->numEdges(); i++) {
547      edge = table->edge(i);
548      // resistances
549      if (edge->numResistances()) {
550         for (j = 0; j < edge->numResistances(); j++) {
551            resist = edge->resistance(j);
552            fprintf(fout, "CROSSTALK CORRECTIONTABLE %d RESISTANCE %g\n",
553                    table->num(), chkNum(resist->num(j)));
554            // victims
555            for (k = 0; k < resist->numVictims(); k++) {
556               victim = resist->victim(k);
557               if (victim->length() > 0)
558                  fprintf(fout,
559                     "CROSSTALK CORRECTIONTABLE %d RESISTANCE %g VICTIMLEN %g\n",
560                          table->num(), chkNum(resist->num(j)),
561                          chkNum(victim->length()));
562                  for (l = 0; l < victim->numCorrections(); l++)
563                     fprintf(fout,
564                     "CROSSTALK CORRECTIONTABLE %d RESISTANCE %g VICTIM GTH %g CORRECTIONFACTOR %g\n",
565                        table->num(), chkNum(resist->num(j)),
566                        chkNum(victim->length()), chkNum(victim->correction(l)));
567            }
568         }
569      }
570   }
571   return 0;
572 }
573 
574 // Dielectric
dielectricCB(lefrCallbackType_e c,double dielectric,lefiUserData ud)575 int dielectricCB(lefrCallbackType_e c, double dielectric, lefiUserData ud) {
576   checkType(c);
577   if (ud != userData) dataError();
578 
579   fprintf(fout, "DIELECTRIC %g\n", chkNum(dielectric));
580   return 0;
581 }
582 
583 // Divider
dividerCB(lefrCallbackType_e c,const char * divideChar,lefiUserData ud)584 int dividerCB(lefrCallbackType_e c, const char* divideChar, lefiUserData ud) {
585   checkType(c);
586   if (ud != userData) dataError();
587   fprintf(fout, "DIVIDER %s\n", divideChar);
588   return 0;
589 }
590 
591 // Crosstalk edgeRate
edgeRateCB(lefrCallbackType_e c,double rate,lefiUserData ud)592 int edgeRateCB(lefrCallbackType_e c, double rate, lefiUserData ud) {
593   checkType(c);
594   if (ud != userData) dataError();
595   fprintf(fout, "CROSSTALK EDGERATESCALEFACTOR %g\n", chkNum(rate));
596   return 0;
597 }
598 
599 // Callback routine for edgeratethreshold1
edgeRate1CB(lefrCallbackType_e c,double rate,lefiUserData ud)600 int edgeRate1CB(lefrCallbackType_e c, double rate, lefiUserData ud) {
601   checkType(c);
602   if (ud != userData) dataError();
603   fprintf(fout, "CROSSTALK EDGERATETHRESHOLD1 %g\n", chkNum(rate));
604   return 0;
605 }
606 
607 // Callback routine for edgeratethreshold2
edgeRate2CB(lefrCallbackType_e c,double rate,lefiUserData ud)608 int edgeRate2CB(lefrCallbackType_e c, double rate, lefiUserData ud) {
609   checkType(c);
610   if (ud != userData) dataError();
611   fprintf(fout, "CROSSTALK EDGERATETHRESHOLD2 %g\n", chkNum(rate));
612   return 0;
613 }
614 
615 // InputAntenna
inputAntCB(lefrCallbackType_e c,double antenna,lefiUserData ud)616 int inputAntCB(lefrCallbackType_e c, double antenna, lefiUserData ud) {
617   checkType(c);
618   if (ud != userData) dataError();
619   fprintf(fout, "INPUTINANTENNASIZE %g\n", chkNum(antenna));
620   return 0;
621 }
622 
623 // OutputAntenna
outputAntCB(lefrCallbackType_e c,double antenna,lefiUserData ud)624 int outputAntCB(lefrCallbackType_e c, double antenna, lefiUserData ud) {
625   checkType(c);
626   if (ud != userData) dataError();
627   fprintf(fout, "OUTPUTINANTENNASIZE %g\n", chkNum(antenna));
628   return 0;
629 }
630 
631 
632 // InOutAntenna
inoutAntCB(lefrCallbackType_e c,double antenna,lefiUserData ud)633 int inoutAntCB(lefrCallbackType_e c, double antenna, lefiUserData ud) {
634   checkType(c);
635   if (ud != userData) dataError();
636   fprintf(fout, "INOUTPUTINANTENNASIZE %g\n", chkNum(antenna));
637   return 0;
638 }
639 
640 // Irdrop
irdropCB(lefrCallbackType_e c,lefiIRDrop * irdrop,lefiUserData ud)641 int irdropCB(lefrCallbackType_e c, lefiIRDrop* irdrop, lefiUserData ud) {
642   int i;
643   checkType(c);
644   if (ud != userData) dataError();
645   fprintf(fout, "IRDROP TABLE %s ", irdrop->name());
646   for (i = 0; i < irdrop->numValues(); i++)
647      fprintf(fout, "%g %g ", chkNum(irdrop->value1(i)),
648              chkNum(irdrop->value2(i)));
649   fprintf(fout, "\n");
650   return 0;
651 }
652 
653 // Layer
layerCB(lefrCallbackType_e c,lefiLayer * layer,lefiUserData ud)654 int layerCB(lefrCallbackType_e c, lefiLayer* layer, lefiUserData ud) {
655   int                 i, j, k;
656   double              *widths, *current;
657   lefiLayerDensity*   density;
658   char                pType;
659   int                 numPoints, propNum;
660   lefiAntennaPWL*     pwl;
661   int                 needHeading;
662   int                 numMinCut, numMinenclosed;
663   lefiSpacingTable*   spTable;
664   lefiInfluence*      influence;
665   lefiParallel*       parallel;
666   lefiTwoWidths*      twoWidths;
667   lefiAntennaModel*   aModel;
668   lefiOrthogonal*     ortho;
669 
670   checkType(c);
671   if (ud != userData) dataError();
672   if (layer->hasType())
673      fprintf(fout, "LAYER %s TYPE %s\n", layer->name(), layer->type());
674   if (layer->hasMask())
675      fprintf(fout, "LAYER %s MASK %d\n", layer->name(), layer->mask());
676   if (layer->hasPitch())
677      fprintf(fout, "LAYER %s PITCH %g\n", layer->name(), chkNum(layer->pitch()));
678   else if (layer->hasXYPitch())
679      fprintf(fout, "LAYER %s PITCH %g %g\n", layer->name(),
680              chkNum(layer->pitchX()), chkNum(layer->pitchY()));
681   if (layer->hasOffset())
682      fprintf(fout, "LAYER %s OFFSET %g\n", layer->name(),
683              chkNum(layer->offset()));
684   else if (layer->hasXYOffset())
685      fprintf(fout, "LAYER %s OFFSET %g %g\n", layer->name(),
686              chkNum(layer->offsetX()), chkNum(layer->offsetY()));
687   if (layer->hasDiagPitch())
688      fprintf(fout, "LAYER %s DIAGPITCH %g\n", layer->name(),
689              chkNum(layer->diagPitch()));
690   else if (layer->hasXYDiagPitch())
691      fprintf(fout, "LAYER %s DIAGPITCH %g %g\n", layer->name(),
692              chkNum(layer->diagPitchX()), chkNum(layer->diagPitchY()));
693   if (layer->hasDiagWidth())
694      fprintf(fout, "LAYER %s DIAGWIDTH %g\n", layer->name(),
695              chkNum(layer->diagWidth()));
696   if (layer->hasDiagSpacing())
697      fprintf(fout, "LAYER %s DIAGSPACING %g\n", layer->name(),
698              chkNum(layer->diagSpacing()));
699   if (layer->hasDiagMinEdgeLength())
700      fprintf(fout, "LAYER %s DIAGMINEDGELENGTH %g\n", layer->name(),
701              chkNum(layer->diagMinEdgeLength()));
702   if (layer->hasWidth())
703      fprintf(fout, "LAYER %s WIDTH %g\n", layer->name(),
704              chkNum(layer->width()));
705   if (layer->hasArea())
706      fprintf(fout, "LAYER %s AREA %g\n", layer->name(),
707              chkNum(layer->area()));
708   if (layer->numMinSize()) {
709      fprintf(fout, "LAYER %s MINSIZE", layer->name());
710      for (i = 0; i < layer->numMinSize(); i++)
711         fprintf(fout, " %g %g", layer->minSizeWidth(i),
712                                 layer->minSizeLength(i));
713      fprintf(fout, "\n");
714   }
715   if (layer->hasSlotWireWidth())
716      fprintf(fout, "LAYER %s SLOTWIREWIDTH %g\n", layer->name(),
717              chkNum(layer->slotWireWidth()));
718   if (layer->hasSlotWireLength())
719      fprintf(fout, "LAYER %s SLOTWIRELENGTH %g\n", layer->name(),
720              chkNum(layer->slotWireLength()));
721   if (layer->hasSlotWidth())
722      fprintf(fout, "LAYER %s SLOTWIDTH %g\n", layer->name(),
723              chkNum(layer->slotWidth()));
724   if (layer->hasSlotLength())
725      fprintf(fout, "LAYER %s SLOTLENGTH %g\n", layer->name(),
726              chkNum(layer->slotLength()));
727   if (layer->hasMaxAdjacentSlotSpacing())
728      fprintf(fout, "LAYER %s MAXADJACENTSLOTSPACING %g\n", layer->name(),
729              chkNum(layer->maxAdjacentSlotSpacing()));
730   if (layer->hasMaxCoaxialSlotSpacing())
731      fprintf(fout, "LAYER %s MAXCOAXIALSLOTSPACING %g\n", layer->name(),
732              chkNum(layer->maxCoaxialSlotSpacing()));
733   if (layer->hasMaxEdgeSlotSpacing())
734      fprintf(fout, "LAYER %s MAXEDGESLOTSPACING %g\n", layer->name(),
735              chkNum(layer->maxEdgeSlotSpacing()));
736   if (layer->hasArraySpacing()) {
737      fprintf(fout, "LAYER %s ARRAYSPACING", layer->name());
738      if (layer->hasLongArray())
739         fprintf(fout, " LONGARRAY");
740      if (layer->hasViaWidth())
741         fprintf(fout, " WIDTH %g", chkNum(layer->viaWidth()));
742      fprintf(fout, " CUTSPACING %g", chkNum(layer->cutSpacing()));
743      fprintf(fout, "\n");
744      for (i = 1; i < layer->numArrayCuts(); i++) {
745         fprintf(fout, "LAYER %s ARRAYCUTS %i SPACING %g\n", layer->name(),
746                 layer->arrayCuts(i),
747                 layer->arraySpacing(i));
748      }
749   }
750   if (layer->hasSplitWireWidth())
751      fprintf(fout, "LAYER %s SPLITWIREWIDTH %g\n", layer->name(),
752              chkNum(layer->splitWireWidth()));
753   if (layer->hasMinimumDensity())
754      fprintf(fout, "LAYER %s MINIMUMDENSITY %g\n", layer->name(),
755              chkNum(layer->minimumDensity()));
756   if (layer->hasMaximumDensity())
757      fprintf(fout, "LAYER %s MAXIMUMDENSITY %g\n", layer->name(),
758              chkNum(layer->maximumDensity()));
759   if (layer->hasDensityCheckWindow())
760      fprintf(fout, "LAYER %s DENSITYCHECKWINDOW %g %g\n", layer->name(),
761              chkNum(layer->densityCheckWindowLength()),
762              chkNum(layer->densityCheckWindowWidth()));
763   if (layer->hasDensityCheckStep())
764      fprintf(fout, "LAYER %s DENSITYCHECKSTEP %g\n", layer->name(),
765              chkNum(layer->densityCheckStep()));
766   if (layer->hasFillActiveSpacing())
767      fprintf(fout, "LAYER %s FILLACTIVESPACING %g\n", layer->name(),
768              chkNum(layer->fillActiveSpacing()));
769   numMinCut = layer->numMinimumcut();    // 5.4.1
770   if (numMinCut > 0) {
771      for (i = 0; i < numMinCut; i++) {
772          fprintf(fout, "LAYER %s MINIMUMCUT %d WIDTH %g", layer->name(),
773               layer->minimumcut(i),
774               layer->minimumcutWidth(i));
775          if (layer->hasMinimumcutWithin(i))
776             fprintf(fout, " WITHIN %g", layer->minimumcutWithin(i));
777          if (layer->hasMinimumcutConnection(i))
778             fprintf(fout, " %s", layer->minimumcutConnection(i));
779          if (layer->hasMinimumcutNumCuts(i))
780             fprintf(fout, " LENGTH %g WITHIN %g",
781             layer->minimumcutLength(i),
782             layer->minimumcutDistance(i));
783          fprintf(fout, "\n");
784      }
785   }
786   if (layer->hasMaxwidth())              // 5.4.1
787      fprintf(fout, "LAYER %s MAXWIDTH %g\n", layer->name(), layer->maxwidth());
788   if (layer->hasMinwidth())              // 5.5
789      fprintf(fout, "LAYER %s MINWIDTH %g\n", layer->name(), layer->minwidth());
790   numMinenclosed = layer->numMinenclosedarea();
791   if (numMinenclosed > 0) {
792      for (i = 0; i < numMinenclosed; i++) {  // 5.5, made it multiples
793         fprintf(fout, "LAYER %s MINENCLOSEDAREA %g", layer->name(),
794                layer->minenclosedarea(i));
795         if (layer->hasMinenclosedareaWidth(i))
796            fprintf(fout, " MINENCLOSEDAREAWIDTH %g",
797                    layer->minenclosedareaWidth(i));
798         fprintf(fout,"\n");
799      }
800   }
801   if (layer->hasMinstep()) {               // 5.4.1 & 5.6
802      for (i = 0; i < layer->numMinstep(); i++) {
803         fprintf(fout, "LAYER %s MINSTEP %g", layer->name(),
804                 layer->minstep(i));
805         if (layer->hasMinstepType(i))
806            fprintf(fout, " %s", layer->minstepType(i));
807         if (layer->hasMinstepLengthsum(i))
808            fprintf(fout, " LENGTHSUM %g", layer->minstepLengthsum(i));
809         if (layer->hasMinstepMaxedges(i))
810            fprintf(fout, " MAXEDGES %d", layer->minstepMaxedges(i));
811         fprintf(fout, "\n");
812      }
813   }
814   if (layer->hasProtrusion())            // 5.4.1
815      fprintf(fout, "LAYER %s PROTRUSIONWIDTH %g LENGTH %g WIDTH %g\n",
816              layer->name(), layer->protrusionWidth1(),
817              layer->protrusionLength(), layer->protrusionWidth2());
818   if (layer->hasSpacingNumber()) {
819      for (i = 0; i < layer->numSpacing(); i++) {
820         fprintf(fout, "LAYER %s SPACING %g", layer->name(),
821                 chkNum(layer->spacing(i)));
822         if (layer->spacingName(i))
823            fprintf(fout, " LAYER %s", layer->spacingName(i));
824         if (layer->hasSpacingLayerStack(i))
825            fprintf(fout, " STACK");
826         fprintf(fout,"\n");
827         if (layer->hasSpacingAdjacent(i))
828            fprintf(fout, "LAYER %s ADJACENTCUTS %d WITHIN %g\n", layer->name(),
829                    layer->spacingAdjacentCuts(i),
830                    chkNum(layer->spacingAdjacentWithin(i)));
831         if (layer->hasSpacingAdjacentExcept(i))
832            fprintf(fout, "LAYER %s EXCEPTSAMEPGNET\n", layer->name());
833         if (layer->hasSpacingCenterToCenter(i))
834            fprintf(fout, "LAYER %s CENTERTOCENTER\n", layer->name());
835         if (layer->hasSpacingSamenet(i)) {
836            fprintf(fout, "LAYER %s SAMENET", layer->name());
837            if (layer->hasSpacingSamenetPGonly(i))
838               fprintf(fout, " PGONLY\n");
839            else
840               fprintf(fout, "\n");
841         }
842         if (layer->hasSpacingArea(i))
843            fprintf(fout, "LAYER %s AREA %g\n", layer->name(),
844                   chkNum(layer->spacingArea(i)));
845         if (layer->hasSpacingRange(i)) {
846            fprintf(fout, "LAYER %s RANGE %g %g", layer->name(),
847                    chkNum(layer->spacingRangeMin(i)),
848                    chkNum(layer->spacingRangeMax(i)));
849            if (layer->hasSpacingRangeUseLengthThreshold(i))
850               fprintf(fout, "USELENGTHTHRESHOLD ");
851           else if (layer->hasSpacingRangeInfluence(i)) {
852               fprintf(fout, "INFLUENCE %g ",
853                  layer->spacingRangeInfluence(i));
854               if (layer->hasSpacingRangeInfluenceRange(i))
855                  fprintf(fout, "RANGE %g %g ",
856                     layer->spacingRangeInfluenceMin(i),
857                     layer->spacingRangeInfluenceMax(i));
858            } else if (layer->hasSpacingRangeRange(i))
859                fprintf(fout, "RANGE %g %g ",
860                  layer->spacingRangeRangeMin(i),
861                  layer->spacingRangeRangeMax(i));
862            fprintf(fout,"\n");
863         }
864         else if (layer->hasSpacingLengthThreshold(i)) {
865            fprintf(fout, "LAYER %s LENGTHTHRESHOLD %g\n", layer->name(),
866                    chkNum(layer->spacingLengthThreshold(i)));
867            if (layer->hasSpacingLengthThresholdRange(i))
868               fprintf(fout, "RANGE %g %g",
869                  layer->spacingLengthThresholdRangeMin(i),
870                  layer->spacingLengthThresholdRangeMax(i));
871            fprintf(fout,"\n");
872         }
873         else if (layer->hasSpacingNotchLength(i)) {
874            fprintf(fout, "LAYER %s NOTCHLENGTH %g\n", layer->name(),
875                    chkNum(layer->spacingNotchLength(i)));
876         }
877         else if (layer->hasSpacingEndOfNotchWidth(i)) {
878            fprintf(fout, "LAYER %s ENDOFNOTCHWIDTH %g NOTCHSPACING %g, NOTCHLENGTH %g\n",
879                    layer->name(),
880                    chkNum(layer->spacingEndOfNotchWidth(i)),
881                    chkNum(layer->spacingEndOfNotchSpacing(i)),
882                    chkNum(layer->spacingEndOfNotchLength(i)));
883         }
884         if (layer->hasSpacingParallelOverlap(i))
885            fprintf(fout, "LAYER %s PARALLELOVERLAP\n", layer->name());
886         if (layer->hasSpacingEndOfLine(i)) {
887            fprintf(fout, "LAYER %s ENDOFLINE %g WITHIN %g ", layer->name(),
888               chkNum(layer->spacingEolWidth(i)),
889               chkNum(layer->spacingEolWithin(i)));
890            if (layer->hasSpacingParellelEdge(i)) {
891               fprintf(fout, "PARALLELEDGE %g WITHIN %g ",
892                  chkNum(layer->spacingParSpace(i)),
893                  chkNum(layer->spacingParWithin(i)));
894               if (layer->hasSpacingTwoEdges(i)) {
895                  fprintf(fout, "TWOEDGES ");
896               }
897            }
898            fprintf(fout,"\n");
899         }
900      }
901   }
902   if (layer->hasSpacingTableOrtho()) {
903      fprintf(fout, "LAYER %s SPACINGTABLE ORTHOGONAL\n", layer->name());
904      ortho = layer->orthogonal();
905      for (i = 0; i < ortho->numOrthogonal(); i++) {
906         fprintf(fout, "LAYER %s SPACINGTABLE ORTHOGONAL WITHIN %g SPACING %g\n",
907                 layer->name(), ortho->cutWithin(i),
908                 ortho->orthoSpacing(i));
909      }
910      fprintf(fout, ";\n");
911   }
912   if (layer->numEnclosure() > 0) {
913      fprintf(fout, "LAYER %s ENCLOSURE", layer->name());
914      for (i = 0; i < layer->numEnclosure(); i++) {
915         if (layer->hasEnclosureRule(i))
916            fprintf(fout, " %s", layer->enclosureRule(i));
917         fprintf(fout, " %g %g", layer->enclosureOverhang1(i),
918                                 layer->enclosureOverhang2(i));
919         if (layer->hasEnclosureWidth(i))
920            fprintf(fout, " WIDTH %g", layer->enclosureMinWidth(i));
921         if (layer->hasEnclosureExceptExtraCut(i))
922            fprintf(fout, " EXCEPTEXTRACUT %g",
923                    layer->enclosureExceptExtraCut(i));
924         if (layer->hasEnclosureMinLength(i))
925            fprintf(fout, " LENGTH %g", layer->enclosureMinLength(i));
926         fprintf(fout, "\n");
927      }
928   }
929   if (layer->numPreferEnclosure() > 0) {
930      fprintf(fout, "LAYER %s PREFERENCLOSURE", layer->name());
931      for (i = 0; i < layer->numPreferEnclosure(); i++) {
932         if (layer->hasPreferEnclosureRule(i))
933            fprintf(fout, "%s ", layer->preferEnclosureRule(i));
934         fprintf(fout, "%g %g ", layer->preferEnclosureOverhang1(i),
935                                 layer->preferEnclosureOverhang2(i));
936         if (layer->hasPreferEnclosureWidth(i))
937            fprintf(fout, "WIDTH %g ",layer->preferEnclosureMinWidth(i));
938         fprintf(fout, "\n");
939      }
940   }
941   if (layer->hasResistancePerCut())
942      fprintf(fout, "LAYER %s RESISTANCE %g\n", layer->name(),
943              chkNum(layer->resistancePerCut()));
944   if (layer->hasCurrentDensityPoint())
945      fprintf(fout, "LAYER %s CURRENTDEN %g\n", layer->name(),
946              chkNum(layer->currentDensityPoint()));
947   if (layer->hasCurrentDensityArray()) {
948      layer->currentDensityArray(&numPoints, &widths, &current);
949      for (i = 0; i < numPoints; i++)
950          fprintf(fout, "LAYER %s CURRENTDEN ( %g %g )\n", layer->name(),
951                  chkNum(widths[i]), chkNum(current[i]));
952   }
953   if (layer->hasDirection())
954      fprintf(fout, "LAYER %s DIRECTION %s\n", layer->name(),
955              layer->direction());
956   if (layer->hasResistance())
957      fprintf(fout, "LAYER %s RESISTANCE RPERSQ %g\n", layer->name(),
958              chkNum(layer->resistance()));
959   if (layer->hasCapacitance())
960      fprintf(fout, "LAYER %s CAPACITANCE CPERSQDIST %g\n", layer->name(),
961              chkNum(layer->capacitance()));
962   if (layer->hasHeight())
963      fprintf(fout, "LAYER %s HEIGHT %g\n", layer->name(), chkNum(layer->height()));
964   if (layer->hasThickness())
965      fprintf(fout, "LAYER %s THICKNESS %g\n", layer->name(),
966              chkNum(layer->thickness()));
967   if (layer->hasWireExtension())
968      fprintf(fout, "LAYER %s WIREEXTENSION %g\n", layer->name(),
969              chkNum(layer->wireExtension()));
970   if (layer->hasShrinkage())
971      fprintf(fout, "LAYER %s SHRINKAGE %g\n", layer->name(),
972              chkNum(layer->shrinkage()));
973   if (layer->hasCapMultiplier())
974      fprintf(fout, "LAYER %s CAPMULTIPLIER %g\n", layer->name(),
975              chkNum(layer->capMultiplier()));
976   if (layer->hasEdgeCap())
977      fprintf(fout, "LAYER %s EDGECAPACITANCE %g\n", layer->name(),
978              chkNum(layer->edgeCap()));
979   if (layer->hasAntennaArea())
980      fprintf(fout, "LAYER %s ANTAREAFACTOR %g\n", layer->name(),
981              chkNum(layer->antennaArea()));
982   if (layer->hasAntennaLength())
983      fprintf(fout, "LAYER %s ANTLENGTHFACTOR %g\n", layer->name(),
984              chkNum(layer->antennaLength()));
985   for (j = 0; j < layer->numAntennaModel(); j++) { // 5.5
986      aModel = layer->antennaModel(j);
987 
988      if (aModel->hasAntennaAreaRatio())
989         fprintf(fout, "LAYER %s %s ANTAREARATIO %g\n", layer->name(),
990                 aModel->antennaOxide(),
991                 chkNum(aModel->antennaAreaRatio()));
992      if (aModel->hasAntennaDiffAreaRatio())
993         fprintf(fout, "LAYER %s %s ANTDIFFAREARATIO %g\n", layer->name(),
994                 aModel->antennaOxide(),
995                 chkNum(aModel->antennaDiffAreaRatio()));
996      else if (aModel->hasAntennaDiffAreaRatioPWL()) {
997         pwl = aModel->antennaDiffAreaRatioPWL();
998         fprintf(fout, "LAYER %s %s ANTDIFFAREARATIO PWL", layer->name(),
999                 aModel->antennaOxide());
1000         for (i = 0; i < pwl->numPWL(); i++)
1001            fprintf(fout, " %g %g", chkNum(pwl->PWLdiffusion(i)),
1002                    chkNum(pwl->PWLratio(i)));
1003         fprintf(fout, "\n");
1004      }
1005      if (aModel->hasAntennaCumAreaRatio())
1006         fprintf(fout, "LAYER %s %s ANTCUMAREARATIO %g\n", layer->name(),
1007                 aModel->antennaOxide(),
1008                 chkNum(aModel->antennaCumAreaRatio()));
1009      if (aModel->hasAntennaCumDiffAreaRatio())
1010         fprintf(fout, "LAYER %s %s ANTCUMDIFFAREARATIO %g\n", layer->name(),
1011                 aModel->antennaOxide(),
1012                 chkNum(aModel->antennaCumDiffAreaRatio()));
1013      else if (aModel->hasAntennaCumDiffAreaRatioPWL()) {
1014         pwl = aModel->antennaCumDiffAreaRatioPWL();
1015         fprintf(fout, "LAYER %s %s ANTCUMDIFFAREARATIO PWL", layer->name(),
1016                 aModel->antennaOxide());
1017         for (i = 0; i < pwl->numPWL(); i++)
1018            fprintf(fout, " %g %g", chkNum(pwl->PWLdiffusion(i)),
1019                    chkNum(pwl->PWLratio(i)));
1020         fprintf(fout, "\n");
1021      }
1022      if (aModel->hasAntennaAreaFactor()) {
1023         fprintf(fout, "LAYER %s %s ANTAREAFACTOR %g", layer->name(),
1024                 aModel->antennaOxide(),
1025                 chkNum(aModel->antennaAreaFactor()));
1026         if (aModel->hasAntennaAreaFactorDUO())
1027            fprintf(fout, "  DIFFUSEONLY");
1028         fprintf(fout, "\n");
1029      }
1030      if (aModel->hasAntennaSideAreaRatio())
1031         fprintf(fout, "LAYER %s %s ANTSIDEAREARATIO %g\n", layer->name(),
1032                 aModel->antennaOxide(),
1033                 chkNum(aModel->antennaSideAreaRatio()));
1034      if (aModel->hasAntennaDiffSideAreaRatio())
1035         fprintf(fout, "LAYER %s %s ANTDIFFSIDEAREARATIO %g\n", layer->name(),
1036                 aModel->antennaOxide(),
1037                 chkNum(aModel->antennaDiffSideAreaRatio()));
1038      else if (aModel->hasAntennaDiffSideAreaRatioPWL()) {
1039         pwl = aModel->antennaDiffSideAreaRatioPWL();
1040         fprintf(fout, "LAYER %s %s ANTDIFFSIDEAREARATIO PWL", layer->name(),
1041                 aModel->antennaOxide());
1042         for (i = 0; i < pwl->numPWL(); i++)
1043            fprintf(fout, " %g %g", chkNum(pwl->PWLdiffusion(i)),
1044                    chkNum(pwl->PWLratio(i)));
1045         fprintf(fout, "\n");
1046      }
1047      if (aModel->hasAntennaCumSideAreaRatio())
1048         fprintf(fout, "LAYER %s %s ANTCUMSIDEAREARATIO %g\n", layer->name(),
1049                 aModel->antennaOxide(),
1050                 chkNum(aModel->antennaCumSideAreaRatio()));
1051      if (aModel->hasAntennaCumDiffSideAreaRatio())
1052         fprintf(fout, "LAYER %s %s ANTCUMDIFFSIDEAREARATIO %g\n", layer->name(),
1053                 aModel->antennaOxide(),
1054                 chkNum(aModel->antennaCumDiffSideAreaRatio()));
1055      else if (aModel->hasAntennaCumDiffSideAreaRatioPWL()) {
1056         pwl = aModel->antennaCumDiffSideAreaRatioPWL();
1057         fprintf(fout, "LAYER %s %s ANTCUMDIFFSIDEAREARATIO PWL", layer->name(),
1058                 aModel->antennaOxide());
1059         for (i = 0; i < pwl->numPWL(); i++)
1060            fprintf(fout, "%g %g ", chkNum(pwl->PWLdiffusion(i)),
1061                    chkNum(pwl->PWLratio(i)));
1062         fprintf(fout, "\n");
1063      }
1064      if (aModel->hasAntennaSideAreaFactor()) {
1065         fprintf(fout, "  ANTSIDEAREAFACTOR %g ",
1066                 chkNum(aModel->antennaSideAreaFactor()));
1067         if (aModel->hasAntennaSideAreaFactorDUO())
1068            fprintf(fout, "  DIFFUSEONLY ");
1069         fprintf(fout, "\n");
1070      }
1071   }
1072 
1073   if (layer->numAccurrentDensity()) {
1074      for (i = 0; i < layer->numAccurrentDensity(); i++) {
1075          density = layer->accurrent(i);
1076          fprintf(fout, "LAYER %s ACCURRENTDENSITY %s", layer->name(),
1077                  density->type());
1078          needHeading = 0;
1079          if (density->hasOneEntry())
1080              fprintf(fout, " %g\n", chkNum(density->oneEntry()));
1081          else {
1082              if (density->numFrequency()) {
1083 /*
1084                 if (needHeading) {
1085                    fprintf(fout, "LAYER %s ACCURRENTDENSITY %s", layer->name(),
1086                    density->type());
1087                 }
1088 */
1089                 fprintf(fout, " FREQUENCY");
1090                 for (j = 0; j < density->numFrequency(); j++)
1091                    fprintf(fout, " %g", chkNum(density->frequency(j)));
1092                 fprintf(fout, "\n");
1093                 needHeading = 1;
1094              }
1095              if (density->numWidths()) {
1096                 if (needHeading) {
1097                    fprintf(fout, "LAYER %s ACCURRENTDENSITY %s", layer->name(),
1098                    density->type());
1099                 }
1100                 fprintf(fout, " WIDTH");
1101                 for (j = 0; j < density->numWidths(); j++)
1102                    fprintf(fout, " %g", chkNum(density->width(j)));
1103                 fprintf(fout, "\n");
1104                 needHeading = 1;
1105              }
1106              if (density->numTableEntries()) {
1107                 if (needHeading) {
1108                    fprintf(fout, "LAYER %s ACCURRENTDENSITY %s", layer->name(),
1109                    density->type());
1110                    k = 0;
1111                 }
1112                 else k = 5;
1113                 fprintf(fout, " TABLEENTRIES");
1114                 for (j = 0; j < density->numTableEntries(); j++) {
1115                    if (k > 4) {
1116                       fprintf(fout,
1117                           "\nLAYER %s ACCURRENTDENSITY %s TABLEENTRIES %g",
1118                           layer->name(), density->type(),
1119                           chkNum(density->tableEntry(j)));
1120                       k = 1;
1121                    } else {
1122                       fprintf(fout, " %g", chkNum(density->tableEntry(j)));
1123                       k++;
1124                    }
1125                 }
1126                 fprintf(fout, "\n");
1127                 needHeading = 1;
1128              }
1129          }
1130      }
1131   }
1132   if (layer->numDccurrentDensity()) {
1133      for (i = 0; i < layer->numDccurrentDensity(); i++) {
1134          density = layer->dccurrent(i);
1135          fprintf(fout, "LAYER %s DCCURRENTDENSITY %s", layer->name(),
1136                  density->type());
1137          needHeading = 0;
1138          if (density->hasOneEntry())
1139              fprintf(fout, " %g\n", chkNum(density->oneEntry()));
1140          else {
1141              if (density->numCutareas()) {
1142 /*
1143                 if (needHeading) {
1144                    fprintf(fout, "LAYER %s DCCURRENTDENSITY %s", layer->name(),
1145                    density->type());
1146                 }
1147 */
1148                 fprintf(fout, " CUTAREA");
1149                 for (j = 0; j < density->numCutareas(); j++)
1150                    fprintf(fout, " %g", chkNum(density->cutArea(j)));
1151                 fprintf(fout, "\n");
1152                 needHeading = 1;
1153              }
1154              if (density->numWidths()) {
1155                 if (needHeading) {
1156                    fprintf(fout, "LAYER %s DCCURRENTDENSITY %s", layer->name(),
1157                    density->type());
1158                 }
1159                 fprintf(fout, " WIDTH");
1160                 for (j = 0; j < density->numWidths(); j++)
1161                    fprintf(fout, " %g", chkNum(density->width(j)));
1162                 fprintf(fout, "\n");
1163                 needHeading = 1;
1164              }
1165              if (density->numTableEntries()) {
1166                 if (needHeading) {
1167                    fprintf(fout, "LAYER %s DCCURRENTDENSITY %s", layer->name(),
1168                    density->type());
1169                 }
1170                 fprintf(fout, " TABLEENTRIES");
1171                 for (j = 0; j < density->numTableEntries(); j++)
1172                    fprintf(fout, " %g", chkNum(density->tableEntry(j)));
1173                 fprintf(fout, "\n");
1174                 needHeading = 1;
1175              }
1176          }
1177      }
1178   }
1179 
1180   for (i = 0; i < layer->numSpacingTable(); i++) {
1181      spTable = layer->spacingTable(i);
1182      if (spTable->isInfluence()) {
1183         influence = spTable->influence();
1184         for (j = 0; j < influence->numInfluenceEntry(); j++) {
1185            fprintf(fout, "LAYER %s SPACINGTABLE INFLUENCE WIDTH %g WITHIN %g SPACING %g\n",
1186                    layer->name(), influence->width(j), influence->distance(j),
1187                    influence->spacing(j));
1188         }
1189      } else if (spTable->isParallel()) {
1190         parallel = spTable->parallel();
1191         fprintf(fout, "LAYER %s SPACINGTABLE PARALLELRUNLENGTH", layer->name());
1192         for (j = 0; j < parallel->numLength(); j++) {
1193            fprintf(fout, " %g", parallel->length(j));
1194         }
1195         fprintf(fout, "\n");
1196         for (j = 0; j < parallel->numWidth(); j++) {
1197            fprintf(fout, "LAYER %s SPACINGTABLE PARALLELRUNLENGTH WIDTH %g",
1198                    layer->name(), parallel->width(j));
1199            for (k = 0; k < parallel->numLength(); k++) {
1200               fprintf(fout, " %g", parallel->widthSpacing(j, k));
1201            }
1202         }
1203         fprintf(fout, "\n");
1204      } else {
1205         twoWidths = spTable->twoWidths();
1206         for (j = 0; j < twoWidths->numWidth(); j++) {
1207            fprintf(fout, "LAYER %s TWOWIDTHS", layer->name());
1208            fprintf(fout, " WIDTH %g", twoWidths->width(j));
1209            if (twoWidths->hasWidthPRL(j))
1210               fprintf(fout, " PRL %g", twoWidths->widthPRL(j));
1211            for (k = 0; k < twoWidths->numWidthSpacing(j); k++)
1212               fprintf(fout, " %g",twoWidths->widthSpacing(j, k));
1213            fprintf(fout, "\n");
1214         }
1215      }
1216   }
1217   propNum = layer->numProps();
1218   if (propNum > 0) {
1219      for (i = 0; i < propNum; i++) {
1220         fprintf(fout, "LAYER %s PROP ", layer->name());
1221         // value can either be a string or number
1222         fprintf(fout, "%s %s ", layer->propName(i),
1223                 layer->propValue(i));
1224         pType = layer->propType(i);
1225         switch (pType) {
1226            case 'R': fprintf(fout, "REAL");
1227                      break;
1228            case 'I': fprintf(fout, "INTEGER");
1229                      break;
1230            case 'S': fprintf(fout, "STRING");
1231                      break;
1232            case 'Q': fprintf(fout, "QUOTESTRING");
1233                      break;
1234            case 'N': fprintf(fout, "NUMBER");
1235                      break;
1236         }
1237         fprintf(fout, "\n");
1238      }
1239   }
1240 
1241   return 0;
1242 }
1243 
1244 // Macro
macroCB(lefrCallbackType_e c,lefiMacro * macro,lefiUserData ud)1245 int macroCB(lefrCallbackType_e c, lefiMacro* macro, lefiUserData ud) {
1246   lefiSitePattern* pattern;
1247   int              propNum, i, hasPrtSym = 0;
1248 
1249   checkType(c);
1250   if (ud != userData) dataError();
1251   fprintf(fout, "MACRO %s", macro->name());
1252   if (macro->hasClass())
1253      fprintf(fout, " CLASS %s", macro->macroClass());
1254   if (macro->isFixedMask())
1255      fprintf(fout, " FIXEDMASK ");
1256   if (macro->hasEEQ())
1257      fprintf(fout, " EEQ %s", macro->EEQ());
1258   if (macro->hasLEQ())
1259      fprintf(fout, " LEQ %s", macro->LEQ());
1260   if (macro->hasSource())
1261      fprintf(fout, " SOURCE %s", macro->source());
1262   if (macro->hasXSymmetry()) {
1263      fprintf(fout, " SYMMETRY X ");
1264      hasPrtSym = 1;
1265   }
1266   if (macro->hasYSymmetry()) {   // print X Y & R90 in one line
1267      if (!hasPrtSym) {
1268         fprintf(fout, "  SYMMETRY Y ");
1269         hasPrtSym = 1;
1270      }
1271      else
1272         fprintf(fout, "Y ");
1273   }
1274   if (macro->has90Symmetry()) {
1275      if (!hasPrtSym) {
1276         fprintf(fout, "  SYMMETRY R90 ");
1277         hasPrtSym = 1;
1278      }
1279      else
1280         fprintf(fout, "R90 ");
1281   }
1282   fprintf (fout, "\n");
1283   if (macro->hasSiteName())
1284      fprintf(fout, "MACRO %s SITE %s\n", macro->name(), macro->siteName());
1285   if (macro->hasSitePattern()) {
1286      for (i = 0; i < macro->numSitePattern(); i++ ) {
1287         pattern = macro->sitePattern(i);
1288         if (pattern->hasStepPattern())
1289            fprintf(fout, "MACRO %s SITE %s %g %g %d DO %g BY %g STEP %g %g\n",
1290                  macro->name(), pattern->name(), chkNum(pattern->x()),
1291                  chkNum(pattern->y()), pattern->orient(),
1292                  chkNum(pattern->xStart()), chkNum(pattern->yStart()),
1293                  chkNum(pattern->xStep()), chkNum(pattern->yStep()));
1294         else
1295            fprintf(fout, "MACRO %s SITE %s %g %g %d\n",
1296                  macro->name(), pattern->name(), chkNum(pattern->x()),
1297                  chkNum(pattern->y()), pattern->orient());
1298      }
1299   }
1300   if (macro->hasSize())
1301      fprintf(fout, "MACRO %s SIZE %g BY %g\n", macro->name(),
1302              chkNum(macro->sizeX()), chkNum(macro->sizeY()));
1303   if (macro->hasForeign()) {
1304      for (i = 0; i < macro->numForeigns(); i++) {
1305         fprintf(fout, "MACRO %s FOREIGN %s", macro->name(),
1306                 macro->foreignName(i));
1307         if (macro->hasForeignPoint(i)) {
1308            fprintf(fout, " ( %g %g )", chkNum(macro->foreignX(i)),
1309                    chkNum(macro->foreignY(i)));
1310            if (macro->hasForeignOrient(i))
1311               fprintf(fout, " %s", lefiOrientStr(macro->foreignOrient(i)));
1312         }
1313         fprintf(fout, "\n");
1314      }
1315   }
1316   if (macro->hasOrigin())
1317      fprintf(fout, "MACRO %s ORIGIN ( %g %g )\n", macro->name(),
1318              chkNum(macro->originX()), chkNum(macro->originY()));
1319   if (macro->hasPower())
1320      fprintf(fout, "MACRO %s POWER %g\n", macro->name(), chkNum(macro->power()));
1321   propNum = macro->numProperties();
1322   if (propNum > 0) {
1323      for (i = 0; i < propNum; i++) {
1324         fprintf(fout, "MACRO %s PROP", macro->name());
1325         // value can either be a string or number
1326         if (macro->propValue(i)) {
1327            fprintf(fout, " %s %s\n", macro->propName(i), macro->propValue(i));
1328         }
1329         else
1330            fprintf(fout, " %s %g\n", macro->propName(i),
1331                    chkNum(macro->propNum(i)));
1332      }
1333   }
1334   return 0;
1335 }
1336 
1337 // Manufacturinggrid
manufacturingCB(lefrCallbackType_e c,double num,lefiUserData ud)1338 int manufacturingCB(lefrCallbackType_e c, double num, lefiUserData ud) {
1339   checkType(c);
1340   if (ud != userData) dataError();
1341   fprintf(fout, "MANUFACTURINGGRID %g\n", chkNum(num));
1342   return 0;
1343 }
1344 
1345 // Maxviastack
maxStackViaCB(lefrCallbackType_e c,lefiMaxStackVia * maxStack,lefiUserData ud)1346 int maxStackViaCB(lefrCallbackType_e c, lefiMaxStackVia* maxStack,
1347   lefiUserData ud) {
1348   checkType(c);
1349   if (ud != userData) dataError();
1350   fprintf(fout, "MAXVIASTACK %d", maxStack->maxStackVia());
1351   if (maxStack->hasMaxStackViaRange())
1352      fprintf(fout, " RANGE %s %s",
1353              maxStack->maxStackViaBottomLayer(),
1354              maxStack->maxStackViaTopLayer());
1355   fprintf(fout, "\n");
1356   return 0;
1357 }
1358 
1359 // Minfeature
minFeatureCB(lefrCallbackType_e c,lefiMinFeature * min,lefiUserData ud)1360 int minFeatureCB(lefrCallbackType_e c, lefiMinFeature* min, lefiUserData ud) {
1361   checkType(c);
1362   if (ud != userData) dataError();
1363   fprintf(fout, "MINFEATURE %g %g\n", chkNum(min->one()), chkNum(min->two()));
1364   return 0;
1365 }
1366 
1367 // Universalnoisemargin
noiseMarginCB(lefrCallbackType_e c,lefiNoiseMargin * margin,lefiUserData ud)1368 int noiseMarginCB(lefrCallbackType_e c, lefiNoiseMargin* margin,
1369                   lefiUserData ud) {
1370   checkType(c);
1371   if (ud != userData) dataError();
1372   fprintf(fout, "UNIVERSALNOISEMARGIN %g %g\n", chkNum(margin->high),
1373           chkNum(margin->low));
1374   return 0;
1375 }
1376 
1377 // NoiseTable
noiseTableCB(lefrCallbackType_e c,lefiNoiseTable * table,lefiUserData ud)1378 int noiseTableCB(lefrCallbackType_e c, lefiNoiseTable* table, lefiUserData ud) {
1379   int                 i, j, k, l;
1380   lefiNoiseEdge       *edge;
1381   lefiNoiseResistance *resist;
1382   lefiNoiseVictim     *victim;
1383 
1384   checkType(c);
1385   if (ud != userData) dataError();
1386   fprintf(fout, "CROSSTALK NOISETABLE %d\n", table->num());
1387   if (table->numEdges() > 0) {
1388      for (i = 0; i < table->numEdges(); i++) {
1389         edge = table->edge(i);
1390         // resistances
1391         if (edge->numResistances()) {
1392            for (j = 0; j < edge->numResistances(); j++) {
1393               resist = edge->resistance(j);
1394               fprintf(fout, "NOISETABLE %d RESISTANCE %g\n",
1395                       table->num(), chkNum(resist->num(j)));
1396               // victims
1397               for (k = 0; k < resist->numVictims(); k++) {
1398                  victim = resist->victim(k);
1399                  if (victim->length() > 0)
1400                     fprintf(fout, "CROSSTALK NOISETABLE %d RESISTANCE %g VICTIMLENGTH % g\n",
1401                             table->num(), chkNum(resist->num(j)),
1402                             chkNum(victim->length()));
1403                     for (l = 0; l < victim->numNoises(); l++)
1404                        fprintf(fout, "CROSSTALK NOISETABLE %d RESISTANCE %g VICTIMLENGT %g NOISEFACTOR %g\n",
1405                           table->num(), chkNum(resist->num(j)),
1406                           chkNum(victim->length()), chkNum(victim->noise(l)));
1407               }
1408            }
1409         }
1410      }
1411   }
1412   return 0;
1413 }
1414 
1415 // Nondefault
nonDefaultCB(lefrCallbackType_e c,lefiNonDefault * def,lefiUserData ud)1416 int nonDefaultCB(lefrCallbackType_e c, lefiNonDefault* def, lefiUserData ud) {
1417   int          i;
1418   lefiVia*     via;
1419   lefiSpacing* spacing;
1420   char         defName[1024];
1421 
1422   checkType(c);
1423   if (ud != userData) dataError();
1424   if (def->hasHardspacing())
1425      fprintf(fout, "NONDEFAULTRULE HARDSPACING\n");
1426   for (i = 0; i < def->numLayers(); i++) {
1427      fprintf(fout, "NONDEFAULTRULE %s LAYER %s", def->name(),
1428              def->layerName(i));
1429      if (def->hasLayerWidth(i))
1430         fprintf(fout, " WIDTH %g", chkNum(def->layerWidth(i)));
1431      if (def->hasLayerDiagWidth(i))
1432         fprintf(fout, " DIAGWIDTH %g", chkNum(def->layerDiagWidth(i)));
1433      if (def->hasLayerSpacing(i))
1434         fprintf(fout, " SPACING %g", chkNum(def->layerSpacing(i)));
1435      if (def->hasLayerWireExtension(i))
1436         fprintf(fout, " WIREEXTENSION %g", chkNum(def->layerWireExtension(i)));
1437      if (def->hasLayerResistance(i))
1438         fprintf(fout, " RESISTANCE RPERSQ %g", chkNum(def->layerResistance(i)));
1439      if (def->hasLayerCapacitance(i))
1440         fprintf(fout, " CAPACITANCE CPERSQDIST %g",
1441                 chkNum(def->layerCapacitance(i)));
1442      if (def->hasLayerEdgeCap(i))
1443         fprintf(fout, " EDGECAPACITANCE %g", chkNum(def->layerEdgeCap(i)));
1444      fprintf(fout, "\n");
1445   }
1446 
1447   sprintf(defName, "NONDEFAULTRULE %s VIA", def->name());
1448   // handle via in nondefaultrule
1449   for (i = 0; i < def->numVias(); i++) {
1450      via = def->viaRule(i);
1451      lefVia(via, defName);
1452   }
1453 
1454   sprintf(defName, "NONDEFAULTRULE %s SPACING", def->name());
1455   // handle spacing in nondefaultrule
1456   for (i = 0; i < def->numSpacingRules(); i++) {
1457      spacing = def->spacingRule(i);
1458      lefSpacing(spacing, defName);
1459   }
1460 
1461   if (def->numUseVia() > 0) {
1462      fprintf(fout, "NONDEFAULTRULE %s USEVIA", def->name());
1463      // handle spacing in nondefaultrule
1464      for (i = 0; i < def->numUseVia(); i++)
1465         fprintf(fout, " %s", def->viaName(i));
1466      fprintf(fout, "\n");
1467   }
1468 
1469   if (def->numUseViaRule() > 0) {
1470      fprintf(fout, "NONDEFAULTRULE %s USEVIARULE", def->name());
1471      // handle spacing in nondefaultrule
1472      for (i = 0; i < def->numUseViaRule(); i++)
1473         fprintf(fout, " %s", def->viaRuleName(i));
1474      fprintf(fout, "\n");
1475   }
1476 
1477   if (def->numMinCuts() > 0) {
1478      fprintf(fout, "NONDEFAULTRULE %s MINCUTS", def->name());
1479      // handle spacing in nondefaultrule
1480      for (i = 0; i < def->numMinCuts(); i++)
1481         fprintf(fout, " %s %d", def->cutLayerName(i), def->numCuts(i));
1482      fprintf(fout, "\n");
1483   }
1484 
1485   return 0;
1486 }
1487 
1488 // Nowireextension
noWireExtCB(lefrCallbackType_e c,const char * wireExt,lefiUserData ud)1489 int noWireExtCB(lefrCallbackType_e c, const char* wireExt, lefiUserData ud) {
1490   checkType(c);
1491   if (ud != userData) dataError();
1492   fprintf(fout, "NOWIREEXTENSION %s\n", wireExt);
1493   return 0;
1494 }
1495 
1496 // Obstruction
obstructionCB(lefrCallbackType_e c,lefiObstruction * obs,lefiUserData ud)1497 int obstructionCB(lefrCallbackType_e c, lefiObstruction* obs,
1498                   lefiUserData ud) {
1499   lefiGeometries* geometry;
1500 
1501   checkType(c);
1502   if (ud != userData) dataError();
1503   geometry = obs->geometries();
1504   prtGeometry(geometry, (char*)"OBS");
1505   return 0;
1506 }
1507 
1508 // Pin
pinCB(lefrCallbackType_e c,lefiPin * pin,lefiUserData ud)1509 int pinCB(lefrCallbackType_e c, lefiPin* pin, lefiUserData ud) {
1510   int                  numPorts, i, j;
1511   lefiGeometries*      geometry;
1512   lefiPinAntennaModel* aModel;
1513 
1514   checkType(c);
1515   if (ud != userData) dataError();
1516   if (pin->hasForeign()) {
1517      if (pin->hasForeignOrient())
1518         fprintf(fout, "PIN %s FOREIGN %s STRUCTURE %g %g %s\n", pin->name(),
1519                 pin->foreignName(), chkNum(pin->foreignX()),
1520                 chkNum(pin->foreignY()), lefiOrientStr(pin->foreignOrient()));
1521      else if (pin->hasForeignPoint())
1522         fprintf(fout, "PIN %s FOREIGN %s STRUCTURE %g %g", pin->name(),
1523                 pin->foreignName(), chkNum(pin->foreignX()),
1524                 chkNum(pin->foreignY()));
1525      else
1526         fprintf(fout, "PIN %s FOREIGN %s\n", pin->name(), pin->foreignName());
1527   }
1528   if (pin->hasLEQ())
1529      fprintf(fout, "PIN %s LEQ %s\n", pin->name(), pin->LEQ());
1530   if (pin->hasDirection())
1531      fprintf(fout, "PIN %s DIRECTION %s\n", pin->name(), pin->direction());
1532   if (pin->hasUse())
1533      fprintf(fout, "PIN %s USE %s\n", pin->name(), pin->use());
1534   if (pin->hasShape())
1535      fprintf(fout, "PIN %s SHAPE %s\n", pin->name(), pin->shape());
1536   if (pin->hasMustjoin())
1537      fprintf(fout, "PIN %s MUSTJOIN %s\n", pin->name(), pin->mustjoin());
1538   if (pin->hasOutMargin())
1539      fprintf(fout, "PIN %s OUTPUTNOISEMARGIN %g %g\n", pin->name(),
1540              chkNum(pin->outMarginHigh()), chkNum(pin->outMarginLow()));
1541   if (pin->hasOutResistance())
1542      fprintf(fout, "PIN %s OUTPUTRESISTANCE %g %g\n", pin->name(),
1543              chkNum(pin->outResistanceHigh()), chkNum(pin->outResistanceLow()));
1544   if (pin->hasInMargin())
1545      fprintf(fout, "PIN %s INPUTNOISEMARGIN %g %g\n", pin->name(),
1546              chkNum(pin->inMarginHigh()), chkNum(pin->inMarginLow()));
1547   if (pin->hasPower())
1548      fprintf(fout, "PIN %s POWER %g\n", pin->name(), chkNum(pin->power()));
1549   if (pin->hasLeakage())
1550      fprintf(fout, "PIN %s LEAKAGE %g\n", pin->name(), chkNum(pin->leakage()));
1551   if (pin->hasMaxload())
1552      fprintf(fout, "PIN %s MAXLOAD %g\n", pin->name(), chkNum(pin->maxload()));
1553   if (pin->hasCapacitance())
1554      fprintf(fout, "PIN %s CAPACITANCE %g\n", pin->name(),
1555              chkNum(pin->capacitance()));
1556   if (pin->hasResistance())
1557      fprintf(fout, "PIN %s RESISTANCE %g\n", pin->name(),
1558              chkNum(pin->resistance()));
1559   if (pin->hasPulldownres())
1560      fprintf(fout, "PIN %s PULLDOWNRES %g\n", pin->name(),
1561              chkNum(pin->pulldownres()));
1562   if (pin->hasTieoffr())
1563      fprintf(fout, "PIN %s TIEOFFR %g\n", pin->name(), chkNum(pin->tieoffr()));
1564   if (pin->hasVHI())
1565      fprintf(fout, "PIN %s VHI %g\n", pin->name(), chkNum(pin->VHI()));
1566   if (pin->hasVLO())
1567      fprintf(fout, "PIN %s VLO %g\n", pin->name(), chkNum(pin->VLO()));
1568   if (pin->hasRiseVoltage())
1569      fprintf(fout, "PIN %s RISEVOLTAGETHRESHOLD %g\n", pin->name(),
1570              chkNum(pin->riseVoltage()));
1571   if (pin->hasFallVoltage())
1572      fprintf(fout, "PIN %s FALLVOLTAGETHRESHOLD %g\n", pin->name(),
1573              chkNum(pin->fallVoltage()));
1574   if (pin->hasRiseThresh())
1575      fprintf(fout, "PIN %s RISETHRESH %g\n", pin->name(),
1576              chkNum(pin->riseThresh()));
1577   if (pin->hasFallThresh())
1578      fprintf(fout, "PIN %s FALLTHRESH %g\n", pin->name(),
1579              chkNum(pin->fallThresh()));
1580   if (pin->hasRiseSatcur())
1581      fprintf(fout, "PIN %s RISESATCUR %g\n", pin->name(),
1582              chkNum(pin->riseSatcur()));
1583   if (pin->hasFallSatcur())
1584      fprintf(fout, "PIN %s FALLSATCUR %g\n", pin->name(),
1585              chkNum(pin->fallSatcur()));
1586   if (pin->hasRiseSlewLimit())
1587      fprintf(fout, "PIN %s RISESLEWLIMIT %g\n", pin->name(),
1588              chkNum(pin->riseSlewLimit()));
1589   if (pin->hasFallSlewLimit())
1590      fprintf(fout, "PIN %s FALLSLEWLIMIT %g\n", pin->name(),
1591              chkNum(pin->fallSlewLimit()));
1592   if (pin->hasCurrentSource())
1593      fprintf(fout, "PIN %s CURRENTSOURCE %s\n", pin->name(),
1594              pin->currentSource());
1595   if (pin->hasTables())
1596      fprintf(fout, "PIN %s IV_TABLES %s %s\n", pin->name(),
1597              pin->tableHighName(), pin->tableLowName());
1598   if (pin->hasTaperRule())
1599      fprintf(fout, "PIN %s TAPERRULE %s\n", pin->name(), pin->taperRule());
1600   if (pin->hasNetExpr())
1601      fprintf(fout, "PIN %s NETEXPR %s\n",pin->name(),  pin->netExpr());
1602   if (pin->hasSupplySensitivity())
1603      fprintf(fout, "PIN %s SUPPLYSENSITIVITY %s\n", pin->name(),
1604              pin->supplySensitivity());
1605   if (pin->hasGroundSensitivity())
1606      fprintf(fout, "PIN %s GROUNDSENSITIVITY %s\n", pin->name(),
1607              pin->groundSensitivity());
1608   if (pin->hasAntennaSize()) {
1609      for (i = 0; i < pin->numAntennaSize(); i++) {
1610         fprintf(fout, "PIN %s ANTSIZE %g", pin->name(),
1611            chkNum(pin->antennaSize(i)));
1612         if (pin->antennaSizeLayer(i))
1613            fprintf(fout, " LAYER %s\n", pin->antennaSizeLayer(i));
1614         else
1615            fprintf(fout, "\n");
1616      }
1617   }
1618   if (pin->hasAntennaMetalArea()) {
1619      for (i = 0; i < pin->numAntennaMetalArea(); i++) {
1620         fprintf(fout, "PIN %s ANTMETALAREA %g", pin->name(),
1621            chkNum(pin->antennaMetalArea(i)));
1622         if (pin->antennaMetalAreaLayer(i))
1623            fprintf(fout, " LAYER %s\n", pin->antennaMetalAreaLayer(i));
1624         else
1625            fprintf(fout, "\n");
1626      }
1627   }
1628   if (pin->hasAntennaMetalLength()) {
1629      for (i = 0; i < pin->numAntennaMetalLength(); i++) {
1630         fprintf(fout, "PIN %s ANTMETALLENGTH %g", pin->name(),
1631            chkNum(pin->antennaMetalLength(i)));
1632         if (pin->antennaMetalLengthLayer(i))
1633            fprintf(fout, " LAYER %s\n", pin->antennaMetalLengthLayer(i));
1634         else
1635            fprintf(fout, "\n");
1636      }
1637   }
1638   if (pin->hasAntennaPartialMetalArea()) {
1639      for (i = 0; i < pin->numAntennaPartialMetalArea(); i++) {
1640         fprintf(fout, "PIN %s ANTPARTIALMETALAREA %g", pin->name(),
1641                 chkNum(pin->antennaPartialMetalArea(i)));
1642         if (pin->antennaPartialMetalAreaLayer(i))
1643            fprintf(fout, " LAYER %s",
1644                    pin->antennaPartialMetalAreaLayer(i));
1645         fprintf(fout, "\n");
1646      }
1647   }
1648   if (pin->hasAntennaPartialMetalSideArea()) {
1649      for (i = 0; i < pin->numAntennaPartialMetalSideArea(); i++) {
1650         fprintf(fout, "PIN %s ANTPARTIALMETALSIDEAREA %g", pin->name(),
1651                 chkNum(pin->antennaPartialMetalSideArea(i)));
1652         if (pin->antennaPartialMetalSideAreaLayer(i))
1653            fprintf(fout, " LAYER %s ",
1654                    pin->antennaPartialMetalSideAreaLayer(i));
1655         fprintf(fout, "\n");
1656      }
1657   }
1658   if (pin->hasAntennaPartialCutArea()) {
1659      for (i = 0; i < pin->numAntennaPartialCutArea(); i++) {
1660         fprintf(fout, "PIN %s ANTPARTIALCUTAREA %g", pin->name(),
1661                 chkNum(pin->antennaPartialCutArea(i)));
1662         if (pin->antennaPartialCutAreaLayer(i))
1663            fprintf(fout, " LAYER %s ",
1664                    pin->antennaPartialCutAreaLayer(i));
1665         fprintf(fout, "\n");
1666      }
1667   }
1668   if (pin->hasAntennaDiffArea()) {
1669      for (i = 0; i < pin->numAntennaDiffArea(); i++) {
1670         fprintf(fout, "PIN %s ANTDIFFAREA %g", pin->name(),
1671                 chkNum(pin->antennaDiffArea(i)));
1672         if (pin->antennaDiffAreaLayer(i))
1673            fprintf(fout, " LAYER %s ", pin->antennaDiffAreaLayer(i));
1674         fprintf(fout, "\n");
1675      }
1676   }
1677 
1678   for (j = 0; j < pin->numAntennaModel(); j++) {
1679      aModel = pin->antennaModel(j);
1680 
1681      if (aModel->hasAntennaGateArea()) {
1682         for (i = 0; i < aModel->numAntennaGateArea(); i++)
1683         {
1684            fprintf(fout, "PIN %s %s ANTGATEAREA %g", pin->name(),
1685                    aModel->antennaOxide(),
1686                    chkNum(aModel->antennaGateArea(i)));
1687            if (aModel->antennaGateAreaLayer(i))
1688               fprintf(fout, " LAYER %s ",
1689                       aModel->antennaGateAreaLayer(i));
1690            fprintf(fout, "\n");
1691         }
1692      }
1693      if (aModel->hasAntennaMaxAreaCar()) {
1694         for (i = 0; i < aModel->numAntennaMaxAreaCar();
1695              i++) {
1696            fprintf(fout, "PIN %s %s ANTMAXAREACAR %g", pin->name(),
1697                    aModel->antennaOxide(),
1698                    chkNum(aModel->antennaMaxAreaCar(i)));
1699            if (aModel->antennaMaxAreaCarLayer(i))
1700               fprintf(fout, " LAYER %s ",
1701                       aModel->antennaMaxAreaCarLayer(i));
1702            fprintf(fout, "\n");
1703         }
1704      }
1705      if (aModel->hasAntennaMaxSideAreaCar()) {
1706         for (i = 0; i < aModel->numAntennaMaxSideAreaCar();
1707              i++) {
1708            fprintf(fout, "PIN %s %s ANTMAXAREACAR %g", pin->name(),
1709                  aModel->antennaOxide(),
1710                  chkNum(aModel->antennaMaxSideAreaCar(i)));
1711            if (aModel->antennaMaxSideAreaCarLayer(i))
1712               fprintf(fout, " LAYER %s ",
1713                     aModel->antennaMaxSideAreaCarLayer(i));
1714            fprintf(fout, "\n");
1715         }
1716      }
1717      if (aModel->hasAntennaMaxCutCar()) {
1718         for (i = 0; i < aModel->numAntennaMaxCutCar(); i++)
1719         {
1720            fprintf(fout, "PIN %s %s ANTMAXCUTCAR %g", pin->name(),
1721                    aModel->antennaOxide(),
1722                    chkNum(aModel->antennaMaxCutCar(i)));
1723            if (aModel->antennaMaxCutCarLayer(i))
1724               fprintf(fout, " LAYER %s ",
1725                       aModel->antennaMaxCutCarLayer(i));
1726            fprintf(fout, "\n");
1727         }
1728      }
1729   }
1730 
1731   if (pin->numProperties() > 0) {
1732      for (i = 0; i < pin->numProperties(); i++) {
1733         fprintf(fout, "PIN %s PROP ", pin->name());
1734         // value can either be a string or number
1735         if (pin->propValue(i)) {
1736            fprintf(fout, "%s %s\n", pin->propName(i), pin->propValue(i));
1737         }
1738         else
1739            fprintf(fout, "%s %g\n", pin->propName(i), chkNum(pin->propNum(i)));
1740      }
1741   }
1742 
1743   numPorts = pin->numPorts();
1744 
1745   char pinName[1024];
1746 
1747   for (i = 0; i < numPorts; i++) {
1748      sprintf(pinName, "PIN %s PORT", pin->name());
1749      geometry = pin->port(i);
1750      prtGeometry(geometry, pinName);
1751   }
1752   return 0;
1753 }
1754 
densityCB(lefrCallbackType_e c,lefiDensity * density,lefiUserData ud)1755 int densityCB(lefrCallbackType_e c, lefiDensity* density,
1756                   lefiUserData ud) {
1757   struct lefiGeomRect rect;
1758 
1759   checkType(c);
1760   if (ud != userData) dataError();
1761   for (int i = 0; i < density->numLayer(); i++) {
1762     for (int j = 0; j < density->numRects(i); j++) {
1763       rect = density->getRect(i,j);
1764       fprintf(fout, "DENSITY LAYER %s RECT %g %g %g %g %g\n",
1765               density->layerName(i), rect.xl, rect.yl, rect.xh, rect.yh,
1766               density->densityValue(i,j));
1767     }
1768   }
1769   return 0;
1770 }
1771 
1772 // Property definition
propDefCB(lefrCallbackType_e c,lefiProp * prop,lefiUserData ud)1773 int propDefCB(lefrCallbackType_e c, lefiProp* prop, lefiUserData ud) {
1774   checkType(c);
1775   if (ud != userData) dataError();
1776   fprintf(fout, "PROPDEF %s %s",
1777           prop->propType(), prop->propName());
1778   if (prop->hasRange())
1779      fprintf(fout, " RANGE %g %g", chkNum(prop->left()), chkNum(prop->right()));
1780   if (prop->hasNumber())
1781      fprintf(fout, " NUMBER %g", chkNum(prop->number()));
1782   switch (prop->dataType()) {
1783       case 'I':
1784            fprintf(fout, " TYPE I");
1785            break;
1786       case 'R':
1787            fprintf(fout, " TYPE R");
1788            break;
1789       case 'S':
1790            fprintf(fout, " TYPE S");
1791            break;
1792       case 'Q':
1793            fprintf(fout, " TYPE Q");
1794            break;
1795       case 'N':
1796            fprintf(fout, " TYPE N");
1797            break;
1798   }
1799   fprintf(fout, "\n");
1800   return 0;
1801 }
1802 
1803 // Site
siteCB(lefrCallbackType_e c,lefiSite * site,lefiUserData ud)1804 int siteCB(lefrCallbackType_e c, lefiSite* site, lefiUserData ud) {
1805   int hasPrtSym = 0;
1806   int i;
1807 
1808   checkType(c);
1809   if (ud != userData) dataError();
1810   fprintf(fout, "SITE %s", site->name());
1811   if (site->hasClass())
1812      fprintf(fout, " CLASS %s", site->siteClass());
1813   if (site->hasXSymmetry()) {
1814      fprintf(fout, " SYMMETRY X ");
1815      hasPrtSym = 1;
1816   }
1817   if (site->hasYSymmetry()) {
1818      if (hasPrtSym)
1819         fprintf(fout, "Y ");
1820      else {
1821         fprintf(fout, " SYMMETRY Y ");
1822         hasPrtSym = 1;
1823      }
1824   }
1825   if (site->has90Symmetry()) {
1826      if (hasPrtSym)
1827         fprintf(fout, "R90 ");
1828      else {
1829         fprintf(fout, " SYMMETRY R90 ");
1830         hasPrtSym = 1;
1831      }
1832   }
1833   if (site->hasSize())
1834      fprintf(fout, " SIZE %g BY %g", chkNum(site->sizeX()),
1835              chkNum(site->sizeY()));
1836   fprintf(fout, "\n");
1837   if (site->hasRowPattern()) {    // 5.6, a line for ea rowpattern for sorting
1838      for (i = 0; i < site->numSites(); i++)
1839         fprintf(fout, "SITE %s ROWPATTERN %s %s\n", site->name(),
1840                 site->siteName(i), site->siteOrientStr(i));
1841   }
1842 
1843   return 0;
1844 }
1845 
1846 // Spacing
spacingCB(lefrCallbackType_e c,lefiSpacing * spacing,lefiUserData ud)1847 int spacingCB(lefrCallbackType_e c, lefiSpacing* spacing, lefiUserData ud) {
1848   checkType(c);
1849   if (ud != userData) dataError();
1850   lefSpacing(spacing, (char*)"SPACING");
1851   return 0;
1852 }
1853 
1854 // Timing
timingCB(lefrCallbackType_e c,lefiTiming * timing,lefiUserData ud)1855 int timingCB(lefrCallbackType_e c, lefiTiming* timing, lefiUserData ud) {
1856   int i;
1857   checkType(c);
1858   if (ud != userData) dataError();
1859   for (i = 0; i < timing->numFromPins(); i++)
1860      fprintf(fout, "TIMING FROMPIN %s\n", timing->fromPin(i));
1861   for (i = 0; i < timing->numToPins(); i++)
1862      fprintf(fout, "TIMING TOPIN %s\n", timing->toPin(i));
1863      fprintf(fout, "TIMING RISE SLEW1 %g %g %g %g\n",
1864              chkNum(timing->riseSlewOne()), chkNum(timing->riseSlewTwo()),
1865              chkNum(timing->riseSlewThree()), chkNum(timing->riseSlewFour()));
1866   if (timing->hasRiseSlew2())
1867      fprintf(fout, "TIMING RISE SLEW2 %g %g %g\n",
1868              chkNum(timing->riseSlewFive()), chkNum(timing->riseSlewSix()),
1869              chkNum(timing->riseSlewSeven()));
1870   if (timing->hasFallSlew())
1871      fprintf(fout, "TIMING FALL SLEW1 %g %g %g %g\n",
1872              chkNum(timing->fallSlewOne()), chkNum(timing->fallSlewTwo()),
1873              chkNum(timing->fallSlewThree()), chkNum(timing->fallSlewFour()));
1874   if (timing->hasFallSlew2())
1875      fprintf(fout, "TIMING FALL SLEW2 %g %g %g\n",
1876              chkNum(timing->fallSlewFive()), chkNum(timing->fallSlewSix()),
1877              chkNum(timing->riseSlewSeven()));
1878   if (timing->hasRiseIntrinsic()) {
1879      fprintf(fout, "TIMING RISE INTRINSIC %g %g\n",
1880              chkNum(timing->riseIntrinsicOne()),
1881              chkNum(timing->riseIntrinsicTwo()));
1882      fprintf(fout, "TIMING RISE VARIABLE %g %g\n",
1883              chkNum(timing->riseIntrinsicThree()),
1884              chkNum(timing->riseIntrinsicFour()));
1885   }
1886   if (timing->hasFallIntrinsic()) {
1887      fprintf(fout, "TIMING FALL INTRINSIC %g %g\n",
1888              chkNum(timing->fallIntrinsicOne()),
1889              chkNum(timing->fallIntrinsicTwo()));
1890      fprintf(fout, "TIMING RISE VARIABLE %g %g\n",
1891              chkNum(timing->fallIntrinsicThree()),
1892              chkNum(timing->fallIntrinsicFour()));
1893   }
1894   if (timing->hasRiseRS())
1895      fprintf(fout, "TIMING RISERS %g %g\n",
1896              chkNum(timing->riseRSOne()), chkNum(timing->riseRSTwo()));
1897      if (timing->hasRiseCS())
1898      fprintf(fout, "TIMING RISECS %g %g\n",
1899              chkNum(timing->riseCSOne()), chkNum(timing->riseCSTwo()));
1900   if (timing->hasFallRS())
1901      fprintf(fout, "TIMING FALLRS %g %g\n",
1902              chkNum(timing->fallRSOne()), chkNum(timing->fallRSTwo()));
1903   if (timing->hasFallCS())
1904      fprintf(fout, "TIMING FALLCS %g %g\n",
1905              chkNum(timing->fallCSOne()), chkNum(timing->fallCSTwo()));
1906   if (timing->hasUnateness())
1907      fprintf(fout, "TIMING UNATENESS %s\n", timing->unateness());
1908   if (timing->hasRiseAtt1())
1909      fprintf(fout, "TIMING RISESATT1 %g %g\n", chkNum(timing->riseAtt1One()),
1910              chkNum(timing->riseAtt1Two()));
1911   if (timing->hasFallAtt1())
1912      fprintf(fout, "TIMING FALLSATT1 %g %g\n", chkNum(timing->fallAtt1One()),
1913              chkNum(timing->fallAtt1Two()));
1914   if (timing->hasRiseTo())
1915      fprintf(fout, "TIMING RISET0 %g %g\n", chkNum(timing->riseToOne()),
1916              chkNum(timing->riseToTwo()));
1917   if (timing->hasFallTo())
1918      fprintf(fout, "TIMING FALLT0 %g %g\n", chkNum(timing->fallToOne()),
1919              chkNum(timing->fallToTwo()));
1920   return 0;
1921 }
1922 
1923 // Units
unitsCB(lefrCallbackType_e c,lefiUnits * unit,lefiUserData ud)1924 int unitsCB(lefrCallbackType_e c, lefiUnits* unit, lefiUserData ud) {
1925   checkType(c);
1926   if (ud != userData) dataError();
1927   if (unit->hasDatabase())
1928      fprintf(fout, "UNITS DATABASE %s %g\n", unit->databaseName(),
1929              chkNum(unit->databaseNumber()));
1930   if (unit->hasCapacitance())
1931      fprintf(fout, "UNITS CAPACITANCE PICOFARADS %g\n",
1932              chkNum(unit->capacitance()));
1933   if (unit->hasResistance())
1934      fprintf(fout, "UNITS RESISTANCE OHMS %g\n", chkNum(unit->resistance()));
1935   if (unit->hasPower())
1936      fprintf(fout, "UNITS POWER MILLIWATTS %g\n", chkNum(unit->power()));
1937   if (unit->hasCurrent())
1938      fprintf(fout, "UNITS CURRENT MILLIAMPS %g\n", chkNum(unit->current()));
1939   if (unit->hasVoltage())
1940      fprintf(fout, "UNITS VOLTAGE VOLTS %g\n", chkNum(unit->voltage()));
1941   if (unit->hasFrequency())
1942      fprintf(fout, "UNITS FREQUENCY MEGAHERTZ %g\n", chkNum(unit->frequency()));
1943   return 0;
1944 }
1945 
1946 // UseMinSpacing
useMinSpacingCB(lefrCallbackType_e c,lefiUseMinSpacing * spacing,lefiUserData ud)1947 int useMinSpacingCB(lefrCallbackType_e c, lefiUseMinSpacing* spacing,
1948                     lefiUserData ud) {
1949   checkType(c);
1950   if (ud != userData) dataError();
1951   fprintf(fout, "USEMINSPACING %s ", spacing->name());
1952   if (spacing->value())
1953       fprintf(fout, "USEMINSPACING ON\n");
1954   else
1955       fprintf(fout, "USEMINSPACING OFF\n");
1956   return 0;
1957 }
1958 
1959 // Version
versionCB(lefrCallbackType_e c,double num,lefiUserData ud)1960 int versionCB(lefrCallbackType_e c, double num, lefiUserData ud) {
1961   checkType(c);
1962   if (ud != userData) dataError();
1963   fprintf(fout, "VERSION %g\n", num);
1964   return 0;
1965 }
1966 
1967 // Via
viaCB(lefrCallbackType_e c,lefiVia * via,lefiUserData ud)1968 int viaCB(lefrCallbackType_e c, lefiVia* via, lefiUserData ud) {
1969   checkType(c);
1970   if (ud != userData) dataError();
1971   lefVia(via, (char*)"VIA");
1972   return 0;
1973 }
1974 
1975 // Viarule
viaRuleCB(lefrCallbackType_e c,lefiViaRule * viaRule,lefiUserData ud)1976 int viaRuleCB(lefrCallbackType_e c, lefiViaRule* viaRule, lefiUserData ud) {
1977   int               numLayers, numVias, i;
1978   lefiViaRuleLayer* vLayer;
1979 
1980   checkType(c);
1981   if (ud != userData) dataError();
1982   fprintf(fout, "VIARULE %s", viaRule->name());
1983   if (viaRule->hasGenerate())
1984      fprintf(fout, " GENERATE");
1985   if (viaRule->hasDefault())
1986      fprintf(fout, " DEFAULT");
1987   fprintf(fout, "\n");
1988 
1989   numLayers = viaRule->numLayers();
1990   // if numLayers == 2, it is VIARULE without GENERATE and has via name
1991   // if numLayers == 3, it is VIARULE with GENERATE, and the 3rd layer is cut
1992   for (i = 0; i < numLayers; i++) {
1993      vLayer = viaRule->layer(i);
1994      lefViaRuleLayer(vLayer, viaRule->name());
1995   }
1996 
1997   if (numLayers == 2) {    // should have vianames
1998      numVias = viaRule->numVias();
1999      if (numVias == 0)
2000         fprintf(fout, "Should have via names in VIARULE.\n");
2001      else {
2002         for (i = 0; i < numVias; i++)
2003            fprintf(fout, "VIARULE %s  VIA %s ;\n", viaRule->name(),
2004                    viaRule->viaName(i));
2005      }
2006   }
2007   if (viaRule->numProps() > 0) {
2008      for (i = 0; i < viaRule->numProps(); i++) {
2009         fprintf(fout, "VIARULE %s PROP %s ", viaRule->name(),
2010                 viaRule->propName(i));
2011         if (viaRule->propValue(i))
2012            fprintf(fout, "%s ", viaRule->propValue(i));
2013         switch (viaRule->propType(i)) {
2014            case 'R': fprintf(fout, "REAL ");
2015                      break;
2016            case 'I': fprintf(fout, "INTEGER ");
2017                      break;
2018            case 'S': fprintf(fout, "STRING ");
2019                      break;
2020            case 'Q': fprintf(fout, "QUOTESTRING ");
2021                      break;
2022            case 'N': fprintf(fout, "NUMBER ");
2023                      break;
2024         fprintf(fout, "\n");
2025         }
2026      }
2027   }
2028   return 0;
2029 }
2030 
2031 //========
2032 
diffLefReadFile(char * inFile,char * outFile)2033 int diffLefReadFile(char* inFile, char* outFile) {
2034   FILE* f;
2035   int   res;
2036 
2037   userData = (void*)0x01020304;
2038   lefrInit();
2039 
2040   // Fix of CCR 758312
2041   lefrSetRelaxMode();
2042 
2043   lefrSetAntennaInputCbk(antennaCB);
2044   lefrSetAntennaInoutCbk(antennaCB);
2045   lefrSetAntennaOutputCbk(antennaCB);
2046   lefrSetArrayCbk(arrayCB);
2047   lefrSetBusBitCharsCbk(busBitCharsCB);
2048   lefrSetCaseSensitiveCbk(caseSensCB);
2049   lefrSetFixedMaskCbk(fixedMaskCB);
2050   lefrSetClearanceMeasureCbk(clearanceCB);
2051   lefrSetCorrectionTableCbk(correctTableCB);
2052   lefrSetDensityCbk(densityCB);
2053   lefrSetDielectricCbk(dielectricCB);
2054   lefrSetDividerCharCbk(dividerCB);
2055   lefrSetEdgeRateScaleFactorCbk(edgeRateCB);
2056   lefrSetEdgeRateThreshold1Cbk(edgeRate1CB);
2057   lefrSetEdgeRateThreshold2Cbk(edgeRate2CB);
2058   lefrSetInputAntennaCbk(inputAntCB);
2059   lefrSetOutputAntennaCbk(outputAntCB);
2060   lefrSetInoutAntennaCbk(inoutAntCB);
2061   lefrSetIRDropCbk(irdropCB);
2062   lefrSetLayerCbk(layerCB);
2063   lefrSetMacroCbk(macroCB);
2064   lefrSetManufacturingCbk(manufacturingCB);
2065   lefrSetMaxStackViaCbk(maxStackViaCB);
2066   lefrSetMinFeatureCbk(minFeatureCB);
2067   lefrSetNoiseMarginCbk(noiseMarginCB);
2068   lefrSetNoiseTableCbk(noiseTableCB);
2069   lefrSetNonDefaultCbk(nonDefaultCB);
2070   lefrSetNoWireExtensionCbk(noWireExtCB);
2071   lefrSetObstructionCbk(obstructionCB);
2072   lefrSetPinCbk(pinCB);
2073   lefrSetPropCbk(propDefCB);
2074   lefrSetSiteCbk(siteCB);
2075   lefrSetSpacingCbk(spacingCB);
2076   lefrSetTimingCbk(timingCB);
2077   lefrSetUnitsCbk(unitsCB);
2078   lefrSetUseMinSpacingCbk(useMinSpacingCB);
2079   lefrSetUserData((void*)3);
2080   lefrSetVersionCbk(versionCB);
2081   lefrSetViaCbk(viaCB);
2082   lefrSetViaRuleCbk(viaRuleCB);
2083 
2084   if ((f = fopen(inFile,"r")) == 0) {
2085     fprintf(stderr,"Couldn't open input file '%s'\n", inFile);
2086     return(2);
2087   }
2088 
2089   if ((fout = fopen(outFile,"w")) == 0) {
2090     fprintf(stderr,"Couldn't open output file '%s'\n", outFile);
2091     fclose(f);
2092     return(2);
2093   }
2094 
2095   res = lefrRead(f, inFile, userData);
2096 
2097   fclose(f);
2098   fclose(fout);
2099 
2100   return 0;
2101 }
2102