| // ***************************************************************************** |
| // ***************************************************************************** |
| // Copyright 2014 - 2017, Cadence Design Systems |
| // |
| // This file is part of the Cadence LEF/DEF Open Source |
| // Distribution, Product Version 5.8. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
| // implied. See the License for the specific language governing |
| // permissions and limitations under the License. |
| // |
| // For updates, support, or to become part of the LEF/DEF Community, |
| // check www.openeda.org for details. |
| // |
| // $Author$ |
| // $Revision$ |
| // $Date$ |
| // $State: $ |
| // ***************************************************************************** |
| // ***************************************************************************** |
| |
| #ifdef WIN32 |
| #pragma warning (disable : 4786) |
| #endif |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include <iostream> |
| #include <stdlib.h> |
| |
| #ifndef WIN32 |
| # include <unistd.h> |
| #else |
| # include <windows.h> |
| #endif /* not WIN32 */ |
| #include "lefrReader.hpp" |
| #include "lefwWriter.hpp" |
| #include "lefiDebug.hpp" |
| #include "lefiEncryptInt.hpp" |
| #include "lefiUtil.hpp" |
| |
| char defaultName[128]; |
| char defaultOut[128]; |
| FILE* fout; |
| int printing = 0; // Printing the output. |
| int parse65nm = 0; |
| int parseLef58Type = 0; |
| int isSessionles = 0; |
| |
| // TX_DIR:TRANSLATION ON |
| |
| void dataError() { |
| fprintf(fout, "ERROR: returned user data is not correct!\n"); |
| } |
| |
| |
| void checkType(lefrCallbackType_e c) { |
| if (c >= 0 && c <= lefrLibraryEndCbkType) { |
| // OK |
| } else { |
| fprintf(fout, "ERROR: callback type is out of bounds!\n"); |
| } |
| } |
| |
| |
| char* orientStr(int orient) { |
| switch (orient) { |
| case 0: return ((char*)"N"); |
| case 1: return ((char*)"W"); |
| case 2: return ((char*)"S"); |
| case 3: return ((char*)"E"); |
| case 4: return ((char*)"FN"); |
| case 5: return ((char*)"FW"); |
| case 6: return ((char*)"FS"); |
| case 7: return ((char*)"FE"); |
| }; |
| return ((char*)"BOGUS"); |
| } |
| |
| void lefVia(lefiVia *via) { |
| int i, j; |
| |
| lefrSetCaseSensitivity(1); |
| fprintf(fout, "VIA %s ", via->lefiVia::name()); |
| if (via->lefiVia::hasDefault()) |
| fprintf(fout, "DEFAULT"); |
| else if (via->lefiVia::hasGenerated()) |
| fprintf(fout, "GENERATED"); |
| fprintf(fout, "\n"); |
| if (via->lefiVia::hasTopOfStack()) |
| fprintf(fout, " TOPOFSTACKONLY\n"); |
| if (via->lefiVia::hasForeign()) { |
| fprintf(fout, " FOREIGN %s ", via->lefiVia::foreign()); |
| if (via->lefiVia::hasForeignPnt()) { |
| fprintf(fout, "( %g %g ) ", via->lefiVia::foreignX(), |
| via->lefiVia::foreignY()); |
| if (via->lefiVia::hasForeignOrient()) |
| fprintf(fout, "%s ", orientStr(via->lefiVia::foreignOrient())); |
| } |
| fprintf(fout, ";\n"); |
| } |
| if (via->lefiVia::hasProperties()) { |
| fprintf(fout, " PROPERTY "); |
| for (i = 0; i < via->lefiVia::numProperties(); i++) { |
| fprintf(fout, "%s ", via->lefiVia::propName(i)); |
| if (via->lefiVia::propIsNumber(i)) |
| fprintf(fout, "%g ", via->lefiVia::propNumber(i)); |
| if (via->lefiVia::propIsString(i)) |
| fprintf(fout, "%s ", via->lefiVia::propValue(i)); |
| /* |
| if (i+1 == via->lefiVia::numProperties()) // end of properties |
| fprintf(fout, ";\n"); |
| else // just add new line |
| fprintf(fout, "\n"); |
| */ |
| switch (via->lefiVia::propType(i)) { |
| case 'R': |
| fprintf(fout, "REAL "); |
| break; |
| case 'I': |
| fprintf(fout, "INTEGER "); |
| break; |
| case 'S': |
| fprintf(fout, "STRING "); |
| break; |
| case 'Q': |
| fprintf(fout, "QUOTESTRING "); |
| break; |
| case 'N': |
| fprintf(fout, "NUMBER "); |
| break; |
| } |
| } |
| fprintf(fout, ";\n"); |
| } |
| if (via->lefiVia::hasResistance()) |
| fprintf(fout, " RESISTANCE %g ;\n", via->lefiVia::resistance()); |
| if (via->lefiVia::numLayers() > 0) { |
| for (i = 0; i < via->lefiVia::numLayers(); i++) { |
| fprintf(fout, " LAYER %s\n", via->lefiVia::layerName(i)); |
| for (j = 0; j < via->lefiVia::numRects(i); j++) |
| if (via->lefiVia::rectColorMask(i, j)) { |
| fprintf(fout, " RECT MASK %d ( %f %f ) ( %f %f ) ;\n", |
| via->lefiVia::rectColorMask(i, j), |
| via->lefiVia::xl(i, j), via->lefiVia::yl(i, j), |
| via->lefiVia::xh(i, j), via->lefiVia::yh(i, j)); |
| } else { |
| fprintf(fout, " RECT ( %f %f ) ( %f %f ) ;\n", |
| via->lefiVia::xl(i, j), via->lefiVia::yl(i, j), |
| via->lefiVia::xh(i, j), via->lefiVia::yh(i, j)); |
| } |
| for (j = 0; j < via->lefiVia::numPolygons(i); j++) { |
| struct lefiGeomPolygon poly; |
| poly = via->lefiVia::getPolygon(i, j); |
| if (via->lefiVia::polyColorMask(i, j)) { |
| fprintf(fout, " POLYGON MASK %d", via->lefiVia::polyColorMask(i, j)); |
| } else { |
| fprintf(fout, " POLYGON "); |
| } |
| for (int k = 0; k < poly.numPoints; k++) |
| fprintf(fout, " %g %g ", poly.x[k], poly.y[k]); |
| fprintf(fout, ";\n"); |
| } |
| } |
| } |
| if (via->lefiVia::hasViaRule()) { |
| fprintf(fout, " VIARULE %s ;\n", via->lefiVia::viaRuleName()); |
| fprintf(fout, " CUTSIZE %g %g ;\n", via->lefiVia::xCutSize(), |
| via->lefiVia::yCutSize()); |
| fprintf(fout, " LAYERS %s %s %s ;\n", via->lefiVia::botMetalLayer(), |
| via->lefiVia::cutLayer(), via->lefiVia::topMetalLayer()); |
| fprintf(fout, " CUTSPACING %g %g ;\n", via->lefiVia::xCutSpacing(), |
| via->lefiVia::yCutSpacing()); |
| fprintf(fout, " ENCLOSURE %g %g %g %g ;\n", via->lefiVia::xBotEnc(), |
| via->lefiVia::yBotEnc(), via->lefiVia::xTopEnc(), |
| via->lefiVia::yTopEnc()); |
| if (via->lefiVia::hasRowCol()) |
| fprintf(fout, " ROWCOL %d %d ;\n", via->lefiVia::numCutRows(), |
| via->lefiVia::numCutCols()); |
| if (via->lefiVia::hasOrigin()) |
| fprintf(fout, " ORIGIN %g %g ;\n", via->lefiVia::xOffset(), |
| via->lefiVia::yOffset()); |
| if (via->lefiVia::hasOffset()) |
| fprintf(fout, " OFFSET %g %g %g %g ;\n", via->lefiVia::xBotOffset(), |
| via->lefiVia::yBotOffset(), via->lefiVia::xTopOffset(), |
| via->lefiVia::yTopOffset()); |
| if (via->lefiVia::hasCutPattern()) |
| fprintf(fout, " PATTERN %s ;\n", via->lefiVia::cutPattern()); |
| } |
| fprintf(fout, "END %s\n", via->lefiVia::name()); |
| |
| return; |
| } |
| |
| void lefSpacing(lefiSpacing* spacing) { |
| fprintf(fout, " SAMENET %s %s %g ", spacing->lefiSpacing::name1(), |
| spacing->lefiSpacing::name2(), spacing->lefiSpacing::distance()); |
| if (spacing->lefiSpacing::hasStack()) |
| fprintf(fout, "STACK "); |
| fprintf(fout,";\n"); |
| return; |
| } |
| |
| void lefViaRuleLayer(lefiViaRuleLayer* vLayer) { |
| fprintf(fout, " LAYER %s ;\n", vLayer->lefiViaRuleLayer::name()); |
| if (vLayer->lefiViaRuleLayer::hasDirection()) { |
| if (vLayer->lefiViaRuleLayer::isHorizontal()) |
| fprintf(fout, " DIRECTION HORIZONTAL ;\n"); |
| if (vLayer->lefiViaRuleLayer::isVertical()) |
| fprintf(fout, " DIRECTION VERTICAL ;\n"); |
| } |
| if (vLayer->lefiViaRuleLayer::hasEnclosure()) { |
| fprintf(fout, " ENCLOSURE %g %g ;\n", |
| vLayer->lefiViaRuleLayer::enclosureOverhang1(), |
| vLayer->lefiViaRuleLayer::enclosureOverhang2()); |
| } |
| if (vLayer->lefiViaRuleLayer::hasWidth()) |
| fprintf(fout, " WIDTH %g TO %g ;\n", |
| vLayer->lefiViaRuleLayer::widthMin(), |
| vLayer->lefiViaRuleLayer::widthMax()); |
| if (vLayer->lefiViaRuleLayer::hasResistance()) |
| fprintf(fout, " RESISTANCE %g ;\n", |
| vLayer->lefiViaRuleLayer::resistance()); |
| if (vLayer->lefiViaRuleLayer::hasOverhang()) |
| fprintf(fout, " OVERHANG %g ;\n", |
| vLayer->lefiViaRuleLayer::overhang()); |
| if (vLayer->lefiViaRuleLayer::hasMetalOverhang()) |
| fprintf(fout, " METALOVERHANG %g ;\n", |
| vLayer->lefiViaRuleLayer::metalOverhang()); |
| if (vLayer->lefiViaRuleLayer::hasSpacing()) |
| fprintf(fout, " SPACING %g BY %g ;\n", |
| vLayer->lefiViaRuleLayer::spacingStepX(), |
| vLayer->lefiViaRuleLayer::spacingStepY()); |
| if (vLayer->lefiViaRuleLayer::hasRect()) |
| fprintf(fout, " RECT ( %f %f ) ( %f %f ) ;\n", |
| vLayer->lefiViaRuleLayer::xl(), vLayer->lefiViaRuleLayer::yl(), |
| vLayer->lefiViaRuleLayer::xh(), vLayer->lefiViaRuleLayer::yh()); |
| return; |
| } |
| |
| void prtGeometry(lefiGeometries *geometry) { |
| int numItems = geometry->lefiGeometries::numItems(); |
| int i, j; |
| lefiGeomPath *path; |
| lefiGeomPathIter *pathIter; |
| lefiGeomRect *rect; |
| lefiGeomRectIter *rectIter; |
| lefiGeomPolygon *polygon; |
| lefiGeomPolygonIter *polygonIter; |
| lefiGeomVia *via; |
| lefiGeomViaIter *viaIter; |
| |
| for (i = 0; i < numItems; i++) { |
| switch (geometry->lefiGeometries::itemType(i)) { |
| case lefiGeomClassE: |
| fprintf(fout, "CLASS %s ", |
| geometry->lefiGeometries::getClass(i)); |
| break; |
| case lefiGeomLayerE: |
| fprintf(fout, " LAYER %s ;\n", |
| geometry->lefiGeometries::getLayer(i)); |
| break; |
| case lefiGeomLayerExceptPgNetE: |
| fprintf(fout, " EXCEPTPGNET ;\n"); |
| break; |
| case lefiGeomLayerMinSpacingE: |
| fprintf(fout, " SPACING %g ;\n", |
| geometry->lefiGeometries::getLayerMinSpacing(i)); |
| break; |
| case lefiGeomLayerRuleWidthE: |
| fprintf(fout, " DESIGNRULEWIDTH %g ;\n", |
| geometry->lefiGeometries::getLayerRuleWidth(i)); |
| break; |
| case lefiGeomWidthE: |
| fprintf(fout, " WIDTH %g ;\n", |
| geometry->lefiGeometries::getWidth(i)); |
| break; |
| case lefiGeomPathE: |
| path = geometry->lefiGeometries::getPath(i); |
| if (path->colorMask != 0) { |
| fprintf(fout, " PATH MASK %d ", path->colorMask); |
| } else { |
| fprintf(fout, " PATH "); |
| } |
| for (j = 0; j < path->numPoints; j++) { |
| if (j + 1 == path->numPoints) // last one on the list |
| fprintf(fout, " ( %g %g ) ;\n", path->x[j], path->y[j]); |
| else |
| fprintf(fout, " ( %g %g )\n", path->x[j], path->y[j]); |
| } |
| break; |
| case lefiGeomPathIterE: |
| pathIter = geometry->lefiGeometries::getPathIter(i); |
| if (pathIter->colorMask != 0) { |
| fprintf(fout, " PATH MASK %d ITERATED ", pathIter->colorMask); |
| } else { |
| fprintf(fout, " PATH ITERATED "); |
| } |
| for (j = 0; j < pathIter->numPoints; j++) |
| fprintf(fout, " ( %g %g )\n", pathIter->x[j], |
| pathIter->y[j]); |
| fprintf(fout, " DO %g BY %g STEP %g %g ;\n", pathIter->xStart, |
| pathIter->yStart, pathIter->xStep, pathIter->yStep); |
| break; |
| case lefiGeomRectE: |
| rect = geometry->lefiGeometries::getRect(i); |
| if (rect->colorMask != 0) { |
| fprintf(fout, " RECT MASK %d ( %f %f ) ( %f %f ) ;\n", |
| rect->colorMask, rect->xl, |
| rect->yl, rect->xh, rect->yh); |
| } else { |
| fprintf(fout, " RECT ( %f %f ) ( %f %f ) ;\n", rect->xl, |
| rect->yl, rect->xh, rect->yh); |
| } |
| break; |
| case lefiGeomRectIterE: |
| rectIter = geometry->lefiGeometries::getRectIter(i); |
| if (rectIter->colorMask != 0) { |
| fprintf(fout, " RECT MASK %d ITERATE ( %f %f ) ( %f %f )\n", |
| rectIter->colorMask, |
| rectIter->xl, rectIter->yl, rectIter->xh, rectIter->yh); |
| } else { |
| fprintf(fout, " RECT ITERATE ( %f %f ) ( %f %f )\n", |
| rectIter->xl, rectIter->yl, rectIter->xh, rectIter->yh); |
| } |
| fprintf(fout, " DO %g BY %g STEP %g %g ;\n", |
| rectIter->xStart, rectIter->yStart, rectIter->xStep, |
| rectIter->yStep); |
| break; |
| case lefiGeomPolygonE: |
| polygon = geometry->lefiGeometries::getPolygon(i); |
| if (polygon->colorMask != 0) { |
| fprintf(fout, " POLYGON MASK %d ", polygon->colorMask); |
| } else { |
| fprintf(fout, " POLYGON "); |
| } |
| for (j = 0; j < polygon->numPoints; j++) { |
| if (j + 1 == polygon->numPoints) // last one on the list |
| fprintf(fout, " ( %g %g ) ;\n", polygon->x[j], |
| polygon->y[j]); |
| else |
| fprintf(fout, " ( %g %g )\n", polygon->x[j], |
| polygon->y[j]); |
| } |
| break; |
| case lefiGeomPolygonIterE: |
| polygonIter = geometry->lefiGeometries::getPolygonIter(i); |
| if (polygonIter->colorMask != 0) { |
| fprintf(fout, " POLYGON MASK %d ITERATE ", polygonIter->colorMask); |
| } else { |
| fprintf(fout, " POLYGON ITERATE"); |
| } |
| for (j = 0; j < polygonIter->numPoints; j++) |
| fprintf(fout, " ( %g %g )\n", polygonIter->x[j], |
| polygonIter->y[j]); |
| fprintf(fout, " DO %g BY %g STEP %g %g ;\n", |
| polygonIter->xStart, polygonIter->yStart, |
| polygonIter->xStep, polygonIter->yStep); |
| break; |
| case lefiGeomViaE: |
| via = geometry->lefiGeometries::getVia(i); |
| if (via->topMaskNum != 0 || via->bottomMaskNum != 0 || via->cutMaskNum !=0) { |
| fprintf(fout, " VIA MASK %d%d%d ( %g %g ) %s ;\n", |
| via->topMaskNum, via->cutMaskNum, via->bottomMaskNum, |
| via->x, via->y, |
| via->name); |
| |
| } else { |
| fprintf(fout, " VIA ( %g %g ) %s ;\n", via->x, via->y, |
| via->name); |
| } |
| break; |
| case lefiGeomViaIterE: |
| viaIter = geometry->lefiGeometries::getViaIter(i); |
| if (viaIter->topMaskNum != 0 || viaIter->cutMaskNum != 0 || viaIter->bottomMaskNum != 0) { |
| fprintf(fout, " VIA ITERATE MASK %d%d%d ( %g %g ) %s\n", |
| viaIter->topMaskNum, viaIter->cutMaskNum, viaIter->bottomMaskNum, |
| viaIter->x, |
| viaIter->y, viaIter->name); |
| } else { |
| fprintf(fout, " VIA ITERATE ( %g %g ) %s\n", viaIter->x, |
| viaIter->y, viaIter->name); |
| } |
| fprintf(fout, " DO %g BY %g STEP %g %g ;\n", |
| viaIter->xStart, viaIter->yStart, |
| viaIter->xStep, viaIter->yStep); |
| break; |
| default: |
| fprintf(fout, "BOGUS geometries type.\n"); |
| break; |
| } |
| } |
| } |
| |
| int antennaCB(lefrCallbackType_e c, double value, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| |
| switch (c) { |
| case lefrAntennaInputCbkType: |
| fprintf(fout, "ANTENNAINPUTGATEAREA %g ;\n", value); |
| break; |
| case lefrAntennaInoutCbkType: |
| fprintf(fout, "ANTENNAINOUTDIFFAREA %g ;\n", value); |
| break; |
| case lefrAntennaOutputCbkType: |
| fprintf(fout, "ANTENNAOUTPUTDIFFAREA %g ;\n", value); |
| break; |
| case lefrInputAntennaCbkType: |
| fprintf(fout, "INPUTPINANTENNASIZE %g ;\n", value); |
| break; |
| case lefrOutputAntennaCbkType: |
| fprintf(fout, "OUTPUTPINANTENNASIZE %g ;\n", value); |
| break; |
| case lefrInoutAntennaCbkType: |
| fprintf(fout, "INOUTPINANTENNASIZE %g ;\n", value); |
| break; |
| default: |
| fprintf(fout, "BOGUS antenna type.\n"); |
| break; |
| } |
| return 0; |
| } |
| |
| int arrayBeginCB(lefrCallbackType_e c, const char* name, lefiUserData) { |
| int status; |
| |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| // use the lef writer to write the data out |
| status = lefwStartArray(name); |
| if (status != LEFW_OK) |
| return status; |
| return 0; |
| } |
| |
| int arrayCB(lefrCallbackType_e c, lefiArray* a, lefiUserData) { |
| int status, i, j, defCaps; |
| lefiSitePattern* pattern; |
| lefiTrackPattern* track; |
| lefiGcellPattern* gcell; |
| |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| |
| if (a->lefiArray::numSitePattern() > 0) { |
| for (i = 0; i < a->lefiArray::numSitePattern(); i++) { |
| pattern = a->lefiArray::sitePattern(i); |
| status = lefwArraySite(pattern->lefiSitePattern::name(), |
| pattern->lefiSitePattern::x(), |
| pattern->lefiSitePattern::y(), |
| pattern->lefiSitePattern::orient(), |
| pattern->lefiSitePattern::xStart(), |
| pattern->lefiSitePattern::yStart(), |
| pattern->lefiSitePattern::xStep(), |
| pattern->lefiSitePattern::yStep()); |
| if (status != LEFW_OK) |
| dataError(); |
| } |
| } |
| if (a->lefiArray::numCanPlace() > 0) { |
| for (i = 0; i < a->lefiArray::numCanPlace(); i++) { |
| pattern = a->lefiArray::canPlace(i); |
| status = lefwArrayCanplace(pattern->lefiSitePattern::name(), |
| pattern->lefiSitePattern::x(), |
| pattern->lefiSitePattern::y(), |
| pattern->lefiSitePattern::orient(), |
| pattern->lefiSitePattern::xStart(), |
| pattern->lefiSitePattern::yStart(), |
| pattern->lefiSitePattern::xStep(), |
| pattern->lefiSitePattern::yStep()); |
| if (status != LEFW_OK) |
| dataError(); |
| } |
| } |
| if (a->lefiArray::numCannotOccupy() > 0) { |
| for (i = 0; i < a->lefiArray::numCannotOccupy(); i++) { |
| pattern = a->lefiArray::cannotOccupy(i); |
| status = lefwArrayCannotoccupy(pattern->lefiSitePattern::name(), |
| pattern->lefiSitePattern::x(), |
| pattern->lefiSitePattern::y(), |
| pattern->lefiSitePattern::orient(), |
| pattern->lefiSitePattern::xStart(), |
| pattern->lefiSitePattern::yStart(), |
| pattern->lefiSitePattern::xStep(), |
| pattern->lefiSitePattern::yStep()); |
| if (status != LEFW_OK) |
| dataError(); |
| } |
| } |
| |
| if (a->lefiArray::numTrack() > 0) { |
| for (i = 0; i < a->lefiArray::numTrack(); i++) { |
| track = a->lefiArray::track(i); |
| fprintf(fout, " TRACKS %s, %g DO %d STEP %g\n", |
| track->lefiTrackPattern::name(), |
| track->lefiTrackPattern::start(), |
| track->lefiTrackPattern::numTracks(), |
| track->lefiTrackPattern::space()); |
| if (track->lefiTrackPattern::numLayers() > 0) { |
| fprintf(fout, " LAYER "); |
| for (j = 0; j < track->lefiTrackPattern::numLayers(); j++) |
| fprintf(fout, "%s ", track->lefiTrackPattern::layerName(j)); |
| fprintf(fout, ";\n"); |
| } |
| } |
| } |
| |
| if (a->lefiArray::numGcell() > 0) { |
| for (i = 0; i < a->lefiArray::numGcell(); i++) { |
| gcell = a->lefiArray::gcell(i); |
| fprintf(fout, " GCELLGRID %s, %g DO %d STEP %g\n", |
| gcell->lefiGcellPattern::name(), |
| gcell->lefiGcellPattern::start(), |
| gcell->lefiGcellPattern::numCRs(), |
| gcell->lefiGcellPattern::space()); |
| } |
| } |
| |
| if (a->lefiArray::numFloorPlans() > 0) { |
| for (i = 0; i < a->lefiArray::numFloorPlans(); i++) { |
| status = lefwStartArrayFloorplan(a->lefiArray::floorPlanName(i)); |
| if (status != LEFW_OK) |
| dataError(); |
| for (j = 0; j < a->lefiArray::numSites(i); j++) { |
| pattern = a->lefiArray::site(i, j); |
| status = lefwArrayFloorplan(a->lefiArray::siteType(i, j), |
| pattern->lefiSitePattern::name(), |
| pattern->lefiSitePattern::x(), |
| pattern->lefiSitePattern::y(), |
| pattern->lefiSitePattern::orient(), |
| (int)pattern->lefiSitePattern::xStart(), |
| (int)pattern->lefiSitePattern::yStart(), |
| pattern->lefiSitePattern::xStep(), |
| pattern->lefiSitePattern::yStep()); |
| if (status != LEFW_OK) |
| dataError(); |
| } |
| status = lefwEndArrayFloorplan(a->lefiArray::floorPlanName(i)); |
| if (status != LEFW_OK) |
| dataError(); |
| } |
| } |
| |
| defCaps = a->lefiArray::numDefaultCaps(); |
| if (defCaps > 0) { |
| status = lefwStartArrayDefaultCap(defCaps); |
| if (status != LEFW_OK) |
| dataError(); |
| for (i = 0; i < defCaps; i++) { |
| status = lefwArrayDefaultCap(a->lefiArray::defaultCapMinPins(i), |
| a->lefiArray::defaultCap(i)); |
| if (status != LEFW_OK) |
| dataError(); |
| } |
| status = lefwEndArrayDefaultCap(); |
| if (status != LEFW_OK) |
| dataError(); |
| } |
| return 0; |
| } |
| |
| int arrayEndCB(lefrCallbackType_e c, const char* name, lefiUserData) { |
| int status; |
| |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| // use the lef writer to write the data out |
| status = lefwEndArray(name); |
| if (status != LEFW_OK) |
| return status; |
| return 0; |
| } |
| |
| int busBitCharsCB(lefrCallbackType_e c, const char* busBit, lefiUserData) |
| { |
| int status; |
| |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| // use the lef writer to write out the data |
| status = lefwBusBitChars(busBit); |
| if (status != LEFW_OK) |
| dataError(); |
| return 0; |
| } |
| |
| int caseSensCB(lefrCallbackType_e c, int caseSense, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| |
| if (caseSense == TRUE) |
| fprintf(fout, "NAMESCASESENSITIVE ON ;\n"); |
| else |
| fprintf(fout, "NAMESCASESENSITIVE OFF ;\n"); |
| return 0; |
| } |
| |
| int fixedMaskCB(lefrCallbackType_e c, int fixedMask, lefiUserData) { |
| checkType(c); |
| |
| if (fixedMask == 1) |
| fprintf(fout, "FIXEDMASK ;\n"); |
| return 0; |
| } |
| |
| int clearanceCB(lefrCallbackType_e c, const char* name, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| |
| fprintf(fout, "CLEARANCEMEASURE %s ;\n", name); |
| return 0; |
| } |
| |
| int dividerCB(lefrCallbackType_e c, const char* name, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| |
| fprintf(fout, "DIVIDER %s ;\n", name); |
| return 0; |
| } |
| |
| int noWireExtCB(lefrCallbackType_e c, const char* name, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| |
| fprintf(fout, "NOWIREEXTENSION %s ;\n", name); |
| return 0; |
| } |
| |
| int noiseMarCB(lefrCallbackType_e c, lefiNoiseMargin *, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| return 0; |
| } |
| |
| int edge1CB(lefrCallbackType_e c, double name, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| |
| fprintf(fout, "EDGERATETHRESHOLD1 %g ;\n", name); |
| return 0; |
| } |
| |
| int edge2CB(lefrCallbackType_e c, double name, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| |
| fprintf(fout, "EDGERATETHRESHOLD2 %g ;\n", name); |
| return 0; |
| } |
| |
| int edgeScaleCB(lefrCallbackType_e c, double name, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| |
| fprintf(fout, "EDGERATESCALEFACTORE %g ;\n", name); |
| return 0; |
| } |
| |
| int noiseTableCB(lefrCallbackType_e c, lefiNoiseTable *, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| |
| return 0; |
| } |
| |
| int correctionCB(lefrCallbackType_e c, lefiCorrectionTable *, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| |
| return 0; |
| } |
| |
| int dielectricCB(lefrCallbackType_e c, double dielectric, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| |
| fprintf(fout, "DIELECTRIC %g ;\n", dielectric); |
| return 0; |
| } |
| |
| int irdropBeginCB(lefrCallbackType_e c, void*, lefiUserData){ |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "IRDROP\n"); |
| return 0; |
| } |
| |
| int irdropCB(lefrCallbackType_e c, lefiIRDrop* irdrop, lefiUserData) { |
| int i; |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, " TABLE %s ", irdrop->lefiIRDrop::name()); |
| for (i = 0; i < irdrop->lefiIRDrop::numValues(); i++) |
| fprintf(fout, "%g %g ", irdrop->lefiIRDrop::value1(i), |
| irdrop->lefiIRDrop::value2(i)); |
| fprintf(fout, ";\n"); |
| return 0; |
| } |
| |
| int irdropEndCB(lefrCallbackType_e c, void*, lefiUserData){ |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "END IRDROP\n"); |
| return 0; |
| } |
| |
| int layerCB(lefrCallbackType_e c, lefiLayer* layer, lefiUserData) { |
| int i, j, k; |
| int numPoints, propNum; |
| double *widths, *current; |
| lefiLayerDensity* density; |
| lefiAntennaPWL* pwl; |
| lefiSpacingTable* spTable; |
| lefiInfluence* influence; |
| lefiParallel* parallel; |
| lefiTwoWidths* twoWidths; |
| char pType; |
| int numMinCut, numMinenclosed; |
| lefiAntennaModel* aModel; |
| lefiOrthogonal* ortho; |
| |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| |
| lefrSetCaseSensitivity(0); |
| |
| // Call parse65nmRules for 5.7 syntax in 5.6 |
| if (parse65nm) |
| layer->lefiLayer::parse65nmRules(); |
| |
| // Call parseLef58Type for 5.8 syntax in 5.7 |
| if (parseLef58Type) |
| layer->lefiLayer::parseLEF58Layer(); |
| |
| fprintf(fout, "LAYER %s\n", layer->lefiLayer::name()); |
| if (layer->lefiLayer::hasType()) |
| fprintf(fout, " TYPE %s ;\n", layer->lefiLayer::type()); |
| if (layer->lefiLayer::hasLayerType()) |
| fprintf(fout, " LAYER TYPE %s ;\n", layer->lefiLayer::layerType()); |
| if (layer->lefiLayer::hasMask()) |
| fprintf(fout, " MASK %d ;\n", layer->lefiLayer::mask()); |
| if (layer->lefiLayer::hasPitch()) |
| fprintf(fout, " PITCH %g ;\n", layer->lefiLayer::pitch()); |
| else if (layer->lefiLayer::hasXYPitch()) |
| fprintf(fout, " PITCH %g %g ;\n", layer->lefiLayer::pitchX(), |
| layer->lefiLayer::pitchY()); |
| if (layer->lefiLayer::hasOffset()) |
| fprintf(fout, " OFFSET %g ;\n", layer->lefiLayer::offset()); |
| else if (layer->lefiLayer::hasXYOffset()) |
| fprintf(fout, " OFFSET %g %g ;\n", layer->lefiLayer::offsetX(), |
| layer->lefiLayer::offsetY()); |
| if (layer->lefiLayer::hasDiagPitch()) |
| fprintf(fout, " DIAGPITCH %g ;\n", layer->lefiLayer::diagPitch()); |
| else if (layer->lefiLayer::hasXYDiagPitch()) |
| fprintf(fout, " DIAGPITCH %g %g ;\n", layer->lefiLayer::diagPitchX(), |
| layer->lefiLayer::diagPitchY()); |
| if (layer->lefiLayer::hasDiagWidth()) |
| fprintf(fout, " DIAGWIDTH %g ;\n", layer->lefiLayer::diagWidth()); |
| if (layer->lefiLayer::hasDiagSpacing()) |
| fprintf(fout, " DIAGSPACING %g ;\n", layer->lefiLayer::diagSpacing()); |
| if (layer->lefiLayer::hasWidth()) |
| fprintf(fout, " WIDTH %g ;\n", layer->lefiLayer::width()); |
| if (layer->lefiLayer::hasArea()) |
| fprintf(fout, " AREA %g ;\n", layer->lefiLayer::area()); |
| if (layer->lefiLayer::hasSlotWireWidth()) |
| fprintf(fout, " SLOTWIREWIDTH %g ;\n", layer->lefiLayer::slotWireWidth()); |
| if (layer->lefiLayer::hasSlotWireLength()) |
| fprintf(fout, " SLOTWIRELENGTH %g ;\n", |
| layer->lefiLayer::slotWireLength()); |
| if (layer->lefiLayer::hasSlotWidth()) |
| fprintf(fout, " SLOTWIDTH %g ;\n", layer->lefiLayer::slotWidth()); |
| if (layer->lefiLayer::hasSlotLength()) |
| fprintf(fout, " SLOTLENGTH %g ;\n", layer->lefiLayer::slotLength()); |
| if (layer->lefiLayer::hasMaxAdjacentSlotSpacing()) |
| fprintf(fout, " MAXADJACENTSLOTSPACING %g ;\n", |
| layer->lefiLayer::maxAdjacentSlotSpacing()); |
| if (layer->lefiLayer::hasMaxCoaxialSlotSpacing()) |
| fprintf(fout, " MAXCOAXIALSLOTSPACING %g ;\n", |
| layer->lefiLayer::maxCoaxialSlotSpacing()); |
| if (layer->lefiLayer::hasMaxEdgeSlotSpacing()) |
| fprintf(fout, " MAXEDGESLOTSPACING %g ;\n", |
| layer->lefiLayer::maxEdgeSlotSpacing()); |
| if (layer->lefiLayer::hasMaxFloatingArea()) // 5.7 |
| fprintf(fout, " MAXFLOATINGAREA %g ;\n", |
| layer->lefiLayer::maxFloatingArea()); |
| if (layer->lefiLayer::hasArraySpacing()) { // 5.7 |
| fprintf(fout, " ARRAYSPACING "); |
| if (layer->lefiLayer::hasLongArray()) |
| fprintf(fout, "LONGARRAY "); |
| if (layer->lefiLayer::hasViaWidth()) |
| fprintf(fout, "WIDTH %g ", layer->lefiLayer::viaWidth()); |
| fprintf(fout, "CUTSPACING %g", layer->lefiLayer::cutSpacing()); |
| for (i = 0; i < layer->lefiLayer::numArrayCuts(); i++) |
| fprintf(fout, "\n\tARRAYCUTS %d SPACING %g", |
| layer->lefiLayer::arrayCuts(i), |
| layer->lefiLayer::arraySpacing(i)); |
| fprintf(fout, " ;\n"); |
| } |
| if (layer->lefiLayer::hasSplitWireWidth()) |
| fprintf(fout, " SPLITWIREWIDTH %g ;\n", |
| layer->lefiLayer::splitWireWidth()); |
| if (layer->lefiLayer::hasMinimumDensity()) |
| fprintf(fout, " MINIMUMDENSITY %g ;\n", |
| layer->lefiLayer::minimumDensity()); |
| if (layer->lefiLayer::hasMaximumDensity()) |
| fprintf(fout, " MAXIMUMDENSITY %g ;\n", |
| layer->lefiLayer::maximumDensity()); |
| if (layer->lefiLayer::hasDensityCheckWindow()) |
| fprintf(fout, " DENSITYCHECKWINDOW %g %g ;\n", |
| layer->lefiLayer::densityCheckWindowLength(), |
| layer->lefiLayer::densityCheckWindowWidth()); |
| if (layer->lefiLayer::hasDensityCheckStep()) |
| fprintf(fout, " DENSITYCHECKSTEP %g ;\n", |
| layer->lefiLayer::densityCheckStep()); |
| if (layer->lefiLayer::hasFillActiveSpacing()) |
| fprintf(fout, " FILLACTIVESPACING %g ;\n", |
| layer->lefiLayer::fillActiveSpacing()); |
| // 5.4.1 |
| numMinCut = layer->lefiLayer::numMinimumcut(); |
| if (numMinCut > 0) { |
| for (i = 0; i < numMinCut; i++) { |
| fprintf(fout, " MINIMUMCUT %d WIDTH %g ", |
| layer->lefiLayer::minimumcut(i), |
| layer->lefiLayer::minimumcutWidth(i)); |
| if (layer->lefiLayer::hasMinimumcutWithin(i)) |
| fprintf(fout, "WITHIN %g ", layer->lefiLayer::minimumcutWithin(i)); |
| if (layer->lefiLayer::hasMinimumcutConnection(i)) |
| fprintf(fout, "%s ", layer->lefiLayer::minimumcutConnection(i)); |
| if (layer->lefiLayer::hasMinimumcutNumCuts(i)) |
| fprintf(fout, "LENGTH %g WITHIN %g ", |
| layer->lefiLayer::minimumcutLength(i), |
| layer->lefiLayer::minimumcutDistance(i)); |
| fprintf(fout, ";\n"); |
| } |
| } |
| // 5.4.1 |
| if (layer->lefiLayer::hasMaxwidth()) { |
| fprintf(fout, " MAXWIDTH %g ;\n", layer->lefiLayer::maxwidth()); |
| } |
| // 5.5 |
| if (layer->lefiLayer::hasMinwidth()) { |
| fprintf(fout, " MINWIDTH %g ;\n", layer->lefiLayer::minwidth()); |
| } |
| // 5.5 |
| numMinenclosed = layer->lefiLayer::numMinenclosedarea(); |
| if (numMinenclosed > 0) { |
| for (i = 0; i < numMinenclosed; i++) { |
| fprintf(fout, " MINENCLOSEDAREA %g ", |
| layer->lefiLayer::minenclosedarea(i)); |
| if (layer->lefiLayer::hasMinenclosedareaWidth(i)) |
| fprintf(fout, "MINENCLOSEDAREAWIDTH %g ", |
| layer->lefiLayer::minenclosedareaWidth(i)); |
| fprintf (fout, ";\n"); |
| } |
| } |
| // 5.4.1 & 5.6 |
| if (layer->lefiLayer::hasMinstep()) { |
| for (i = 0; i < layer->lefiLayer::numMinstep(); i++) { |
| fprintf(fout, " MINSTEP %g ", layer->lefiLayer::minstep(i)); |
| if (layer->lefiLayer::hasMinstepType(i)) |
| fprintf(fout, "%s ", layer->lefiLayer::minstepType(i)); |
| if (layer->lefiLayer::hasMinstepLengthsum(i)) |
| fprintf(fout, "LENGTHSUM %g ", |
| layer->lefiLayer::minstepLengthsum(i)); |
| if (layer->lefiLayer::hasMinstepMaxedges(i)) |
| fprintf(fout, "MAXEDGES %d ", layer->lefiLayer::minstepMaxedges(i)); |
| if (layer->lefiLayer::hasMinstepMinAdjLength(i)) |
| fprintf(fout, "MINADJLENGTH %g ", layer->lefiLayer::minstepMinAdjLength(i)); |
| if (layer->lefiLayer::hasMinstepMinBetLength(i)) |
| fprintf(fout, "MINBETLENGTH %g ", layer->lefiLayer::minstepMinBetLength(i)); |
| if (layer->lefiLayer::hasMinstepXSameCorners(i)) |
| fprintf(fout, "XSAMECORNERS"); |
| fprintf(fout, ";\n"); |
| } |
| } |
| // 5.4.1 |
| if (layer->lefiLayer::hasProtrusion()) { |
| fprintf(fout, " PROTRUSIONWIDTH %g LENGTH %g WIDTH %g ;\n", |
| layer->lefiLayer::protrusionWidth1(), |
| layer->lefiLayer::protrusionLength(), |
| layer->lefiLayer::protrusionWidth2()); |
| } |
| if (layer->lefiLayer::hasSpacingNumber()) { |
| for (i = 0; i < layer->lefiLayer::numSpacing(); i++) { |
| fprintf(fout, " SPACING %g ", layer->lefiLayer::spacing(i)); |
| if (layer->lefiLayer::hasSpacingName(i)) |
| fprintf(fout, "LAYER %s ", layer->lefiLayer::spacingName(i)); |
| if (layer->lefiLayer::hasSpacingLayerStack(i)) |
| fprintf(fout, "STACK "); // 5.7 |
| if (layer->lefiLayer::hasSpacingAdjacent(i)) |
| fprintf(fout, "ADJACENTCUTS %d WITHIN %g ", |
| layer->lefiLayer::spacingAdjacentCuts(i), |
| layer->lefiLayer::spacingAdjacentWithin(i)); |
| if (layer->lefiLayer::hasSpacingAdjacentExcept(i)) // 5.7 |
| fprintf(fout, "EXCEPTSAMEPGNET "); |
| if (layer->lefiLayer::hasSpacingCenterToCenter(i)) |
| fprintf(fout, "CENTERTOCENTER "); |
| if (layer->lefiLayer::hasSpacingSamenet(i)) // 5.7 |
| fprintf(fout, "SAMENET "); |
| if (layer->lefiLayer::hasSpacingSamenetPGonly(i)) // 5.7 |
| fprintf(fout, "PGONLY "); |
| if (layer->lefiLayer::hasSpacingArea(i)) // 5.7 |
| fprintf(fout, "AREA %g ", layer->lefiLayer::spacingArea(i)); |
| if (layer->lefiLayer::hasSpacingRange(i)) { |
| fprintf(fout, "RANGE %g %g ", layer->lefiLayer::spacingRangeMin(i), |
| layer->lefiLayer::spacingRangeMax(i)); |
| if (layer->lefiLayer::hasSpacingRangeUseLengthThreshold(i)) |
| fprintf(fout, "USELENGTHTHRESHOLD "); |
| else if (layer->lefiLayer::hasSpacingRangeInfluence(i)) { |
| fprintf(fout, "INFLUENCE %g ", |
| layer->lefiLayer::spacingRangeInfluence(i)); |
| if (layer->lefiLayer::hasSpacingRangeInfluenceRange(i)) |
| fprintf(fout, "RANGE %g %g ", |
| layer->lefiLayer::spacingRangeInfluenceMin(i), |
| layer->lefiLayer::spacingRangeInfluenceMax(i)); |
| } else if (layer->lefiLayer::hasSpacingRangeRange(i)) |
| fprintf(fout, "RANGE %g %g ", |
| layer->lefiLayer::spacingRangeRangeMin(i), |
| layer->lefiLayer::spacingRangeRangeMax(i)); |
| } else if (layer->lefiLayer::hasSpacingLengthThreshold(i)) { |
| fprintf(fout, "LENGTHTHRESHOLD %g ", |
| layer->lefiLayer::spacingLengthThreshold(i)); |
| if (layer->lefiLayer::hasSpacingLengthThresholdRange(i)) |
| fprintf(fout, "RANGE %g %g", |
| layer->lefiLayer::spacingLengthThresholdRangeMin(i), |
| layer->lefiLayer::spacingLengthThresholdRangeMax(i)); |
| } else if (layer->lefiLayer::hasSpacingNotchLength(i)) {// 5.7 |
| fprintf(fout, "NOTCHLENGTH %g", |
| layer->lefiLayer::spacingNotchLength(i)); |
| } else if (layer->lefiLayer::hasSpacingEndOfNotchWidth(i)) // 5.7 |
| fprintf(fout, "ENDOFNOTCHWIDTH %g NOTCHSPACING %g, NOTCHLENGTH %g", |
| layer->lefiLayer::spacingEndOfNotchWidth(i), |
| layer->lefiLayer::spacingEndOfNotchSpacing(i), |
| layer->lefiLayer::spacingEndOfNotchLength(i)); |
| |
| if (layer->lefiLayer::hasSpacingParallelOverlap(i)) // 5.7 |
| fprintf(fout, "PARALLELOVERLAP "); |
| if (layer->lefiLayer::hasSpacingEndOfLine(i)) { // 5.7 |
| fprintf(fout, "ENDOFLINE %g WITHIN %g ", |
| layer->lefiLayer::spacingEolWidth(i), |
| layer->lefiLayer::spacingEolWithin(i)); |
| if (layer->lefiLayer::hasSpacingParellelEdge(i)) { |
| fprintf(fout, "PARALLELEDGE %g WITHIN %g ", |
| layer->lefiLayer::spacingParSpace(i), |
| layer->lefiLayer::spacingParWithin(i)); |
| if (layer->lefiLayer::hasSpacingTwoEdges(i)) { |
| fprintf(fout, "TWOEDGES "); |
| } |
| } |
| } |
| fprintf(fout, ";\n"); |
| } |
| } |
| if (layer->lefiLayer::hasSpacingTableOrtho()) { // 5.7 |
| fprintf(fout, "SPACINGTABLE ORTHOGONAL"); |
| ortho = layer->lefiLayer::orthogonal(); |
| for (i = 0; i < ortho->lefiOrthogonal::numOrthogonal(); i++) { |
| fprintf(fout, "\n WITHIN %g SPACING %g", |
| ortho->lefiOrthogonal::cutWithin(i), |
| ortho->lefiOrthogonal::orthoSpacing(i)); |
| } |
| fprintf(fout, ";\n"); |
| } |
| for (i = 0; i < layer->lefiLayer::numEnclosure(); i++) { |
| fprintf(fout, "ENCLOSURE "); |
| if (layer->lefiLayer::hasEnclosureRule(i)) |
| fprintf(fout, "%s ", layer->lefiLayer::enclosureRule(i)); |
| fprintf(fout, "%g %g ", layer->lefiLayer::enclosureOverhang1(i), |
| layer->lefiLayer::enclosureOverhang2(i)); |
| if (layer->lefiLayer::hasEnclosureWidth(i)) |
| fprintf(fout, "WIDTH %g ", layer->lefiLayer::enclosureMinWidth(i)); |
| if (layer->lefiLayer::hasEnclosureExceptExtraCut(i)) |
| fprintf(fout, "EXCEPTEXTRACUT %g ", |
| layer->lefiLayer::enclosureExceptExtraCut(i)); |
| if (layer->lefiLayer::hasEnclosureMinLength(i)) |
| fprintf(fout, "LENGTH %g ", layer->lefiLayer::enclosureMinLength(i)); |
| fprintf(fout, ";\n"); |
| } |
| for (i = 0; i < layer->lefiLayer::numPreferEnclosure(); i++) { |
| fprintf(fout, "PREFERENCLOSURE "); |
| if (layer->lefiLayer::hasPreferEnclosureRule(i)) |
| fprintf(fout, "%s ", layer->lefiLayer::preferEnclosureRule(i)); |
| fprintf(fout, "%g %g ", layer->lefiLayer::preferEnclosureOverhang1(i), |
| layer->lefiLayer::preferEnclosureOverhang2(i)); |
| if (layer->lefiLayer::hasPreferEnclosureWidth(i)) |
| fprintf(fout, "WIDTH %g ",layer->lefiLayer::preferEnclosureMinWidth(i)); |
| fprintf(fout, ";\n"); |
| } |
| if (layer->lefiLayer::hasResistancePerCut()) |
| fprintf(fout, " RESISTANCE %g ;\n", |
| layer->lefiLayer::resistancePerCut()); |
| if (layer->lefiLayer::hasCurrentDensityPoint()) |
| fprintf(fout, " CURRENTDEN %g ;\n", |
| layer->lefiLayer::currentDensityPoint()); |
| if (layer->lefiLayer::hasCurrentDensityArray()) { |
| layer->lefiLayer::currentDensityArray(&numPoints, &widths, ¤t); |
| for (i = 0; i < numPoints; i++) |
| fprintf(fout, " CURRENTDEN ( %g %g ) ;\n", widths[i], current[i]); |
| } |
| if (layer->lefiLayer::hasDirection()) |
| fprintf(fout, " DIRECTION %s ;\n", layer->lefiLayer::direction()); |
| if (layer->lefiLayer::hasResistance()) |
| fprintf(fout, " RESISTANCE RPERSQ %g ;\n", |
| layer->lefiLayer::resistance()); |
| if (layer->lefiLayer::hasCapacitance()) |
| fprintf(fout, " CAPACITANCE CPERSQDIST %g ;\n", |
| layer->lefiLayer::capacitance()); |
| if (layer->lefiLayer::hasEdgeCap()) |
| fprintf(fout, " EDGECAPACITANCE %g ;\n", layer->lefiLayer::edgeCap()); |
| if (layer->lefiLayer::hasHeight()) |
| fprintf(fout, " TYPE %g ;\n", layer->lefiLayer::height()); |
| if (layer->lefiLayer::hasThickness()) |
| fprintf(fout, " THICKNESS %g ;\n", layer->lefiLayer::thickness()); |
| if (layer->lefiLayer::hasWireExtension()) |
| fprintf(fout, " WIREEXTENSION %g ;\n", layer->lefiLayer::wireExtension()); |
| if (layer->lefiLayer::hasShrinkage()) |
| fprintf(fout, " SHRINKAGE %g ;\n", layer->lefiLayer::shrinkage()); |
| if (layer->lefiLayer::hasCapMultiplier()) |
| fprintf(fout, " CAPMULTIPLIER %g ;\n", layer->lefiLayer::capMultiplier()); |
| if (layer->lefiLayer::hasAntennaArea()) |
| fprintf(fout, " ANTENNAAREAFACTOR %g ;\n", |
| layer->lefiLayer::antennaArea()); |
| if (layer->lefiLayer::hasAntennaLength()) |
| fprintf(fout, " ANTENNALENGTHFACTOR %g ;\n", |
| layer->lefiLayer::antennaLength()); |
| |
| // 5.5 AntennaModel |
| for (i = 0; i < layer->lefiLayer::numAntennaModel(); i++) { |
| aModel = layer->lefiLayer::antennaModel(i); |
| |
| fprintf(fout, " ANTENNAMODEL %s ;\n", |
| aModel->lefiAntennaModel::antennaOxide()); |
| |
| if (aModel->lefiAntennaModel::hasAntennaAreaRatio()) |
| fprintf(fout, " ANTENNAAREARATIO %g ;\n", |
| aModel->lefiAntennaModel::antennaAreaRatio()); |
| if (aModel->lefiAntennaModel::hasAntennaDiffAreaRatio()) |
| fprintf(fout, " ANTENNADIFFAREARATIO %g ;\n", |
| aModel->lefiAntennaModel::antennaDiffAreaRatio()); |
| else if (aModel->lefiAntennaModel::hasAntennaDiffAreaRatioPWL()) { |
| pwl = aModel->lefiAntennaModel::antennaDiffAreaRatioPWL(); |
| fprintf(fout, " ANTENNADIFFAREARATIO PWL ( "); |
| for (j = 0; j < pwl->lefiAntennaPWL::numPWL(); j++) |
| fprintf(fout, "( %g %g ) ", pwl->lefiAntennaPWL::PWLdiffusion(j), |
| pwl->lefiAntennaPWL::PWLratio(j)); |
| fprintf(fout, ") ;\n"); |
| } |
| if (aModel->lefiAntennaModel::hasAntennaCumAreaRatio()) |
| fprintf(fout, " ANTENNACUMAREARATIO %g ;\n", |
| aModel->lefiAntennaModel::antennaCumAreaRatio()); |
| if (aModel->lefiAntennaModel::hasAntennaCumDiffAreaRatio()) |
| fprintf(fout, " ANTENNACUMDIFFAREARATIO %g\n", |
| aModel->lefiAntennaModel::antennaCumDiffAreaRatio()); |
| if (aModel->lefiAntennaModel::hasAntennaCumDiffAreaRatioPWL()) { |
| pwl = aModel->lefiAntennaModel::antennaCumDiffAreaRatioPWL(); |
| fprintf(fout, " ANTENNACUMDIFFAREARATIO PWL ( "); |
| for (j = 0; j < pwl->lefiAntennaPWL::numPWL(); j++) |
| fprintf(fout, "( %g %g ) ", pwl->lefiAntennaPWL::PWLdiffusion(j), |
| pwl->lefiAntennaPWL::PWLratio(j)); |
| fprintf(fout, ") ;\n"); |
| } |
| if (aModel->lefiAntennaModel::hasAntennaAreaFactor()) { |
| fprintf(fout, " ANTENNAAREAFACTOR %g ", |
| aModel->lefiAntennaModel::antennaAreaFactor()); |
| if (aModel->lefiAntennaModel::hasAntennaAreaFactorDUO()) |
| fprintf(fout, " DIFFUSEONLY "); |
| fprintf(fout, ";\n"); |
| } |
| if (aModel->lefiAntennaModel::hasAntennaSideAreaRatio()) |
| fprintf(fout, " ANTENNASIDEAREARATIO %g ;\n", |
| aModel->lefiAntennaModel::antennaSideAreaRatio()); |
| if (aModel->lefiAntennaModel::hasAntennaDiffSideAreaRatio()) |
| fprintf(fout, " ANTENNADIFFSIDEAREARATIO %g\n", |
| aModel->lefiAntennaModel::antennaDiffSideAreaRatio()); |
| else if (aModel->lefiAntennaModel::hasAntennaDiffSideAreaRatioPWL()) { |
| pwl = aModel->lefiAntennaModel::antennaDiffSideAreaRatioPWL(); |
| fprintf(fout, " ANTENNADIFFSIDEAREARATIO PWL ( "); |
| for (j = 0; j < pwl->lefiAntennaPWL::numPWL(); j++) |
| fprintf(fout, "( %g %g ) ", pwl->lefiAntennaPWL::PWLdiffusion(j), |
| pwl->lefiAntennaPWL::PWLratio(j)); |
| fprintf(fout, ") ;\n"); |
| } |
| if (aModel->lefiAntennaModel::hasAntennaCumSideAreaRatio()) |
| fprintf(fout, " ANTENNACUMSIDEAREARATIO %g ;\n", |
| aModel->lefiAntennaModel::antennaCumSideAreaRatio()); |
| if (aModel->lefiAntennaModel::hasAntennaCumDiffSideAreaRatio()) |
| fprintf(fout, " ANTENNACUMDIFFSIDEAREARATIO %g\n", |
| aModel->lefiAntennaModel::antennaCumDiffSideAreaRatio()); |
| else if (aModel->lefiAntennaModel::hasAntennaCumDiffSideAreaRatioPWL()) { |
| pwl = aModel->lefiAntennaModel::antennaCumDiffSideAreaRatioPWL(); |
| fprintf(fout, " ANTENNACUMDIFFSIDEAREARATIO PWL ( "); |
| for (j = 0; j < pwl->lefiAntennaPWL::numPWL(); j++) |
| fprintf(fout, "( %g %g ) ", pwl->lefiAntennaPWL::PWLdiffusion(j), |
| pwl->lefiAntennaPWL::PWLratio(j)); |
| fprintf(fout, ") ;\n"); |
| } |
| if (aModel->lefiAntennaModel::hasAntennaSideAreaFactor()) { |
| fprintf(fout, " ANTENNASIDEAREAFACTOR %g ", |
| aModel->lefiAntennaModel::antennaSideAreaFactor()); |
| if (aModel->lefiAntennaModel::hasAntennaSideAreaFactorDUO()) |
| fprintf(fout, " DIFFUSEONLY "); |
| fprintf(fout, ";\n"); |
| } |
| if (aModel->lefiAntennaModel::hasAntennaCumRoutingPlusCut()) |
| fprintf(fout, " ANTENNACUMROUTINGPLUSCUT ;\n"); |
| if (aModel->lefiAntennaModel::hasAntennaGatePlusDiff()) |
| fprintf(fout, " ANTENNAGATEPLUSDIFF %g ;\n", |
| aModel->lefiAntennaModel::antennaGatePlusDiff()); |
| if (aModel->lefiAntennaModel::hasAntennaAreaMinusDiff()) |
| fprintf(fout, " ANTENNAAREAMINUSDIFF %g ;\n", |
| aModel->lefiAntennaModel::antennaAreaMinusDiff()); |
| if (aModel->lefiAntennaModel::hasAntennaAreaDiffReducePWL()) { |
| pwl = aModel->lefiAntennaModel::antennaAreaDiffReducePWL(); |
| fprintf(fout, " ANTENNAAREADIFFREDUCEPWL ( "); |
| for (j = 0; j < pwl->lefiAntennaPWL::numPWL(); j++) |
| fprintf(fout, "( %g %g ) ", pwl->lefiAntennaPWL::PWLdiffusion(j), |
| pwl->lefiAntennaPWL::PWLratio(j)); |
| fprintf(fout, ") ;\n"); |
| } |
| } |
| |
| if (layer->lefiLayer::numAccurrentDensity()) { |
| for (i = 0; i < layer->lefiLayer::numAccurrentDensity(); i++) { |
| density = layer->lefiLayer::accurrent(i); |
| fprintf(fout, " ACCURRENTDENSITY %s", density->type()); |
| if (density->hasOneEntry()) |
| fprintf(fout, " %g ;\n", density->oneEntry()); |
| else { |
| fprintf(fout, "\n"); |
| if (density->numFrequency()) { |
| fprintf(fout, " FREQUENCY"); |
| for (j = 0; j < density->numFrequency(); j++) |
| fprintf(fout, " %g", density->frequency(j)); |
| fprintf(fout, " ;\n"); |
| } |
| if (density->numCutareas()) { |
| fprintf(fout, " CUTAREA"); |
| for (j = 0; j < density->numCutareas(); j++) |
| fprintf(fout, " %g", density->cutArea(j)); |
| fprintf(fout, " ;\n"); |
| } |
| if (density->numWidths()) { |
| fprintf(fout, " WIDTH"); |
| for (j = 0; j < density->numWidths(); j++) |
| fprintf(fout, " %g", density->width(j)); |
| fprintf(fout, " ;\n"); |
| } |
| if (density->numTableEntries()) { |
| k = 5; |
| fprintf(fout, " TABLEENTRIES"); |
| for (j = 0; j < density->numTableEntries(); j++) |
| if (k > 4) { |
| fprintf(fout, "\n %g", density->tableEntry(j)); |
| k = 1; |
| } else { |
| fprintf(fout, " %g", density->tableEntry(j)); |
| k++; |
| } |
| fprintf(fout, " ;\n"); |
| } |
| } |
| } |
| } |
| if (layer->lefiLayer::numDccurrentDensity()) { |
| for (i = 0; i < layer->lefiLayer::numDccurrentDensity(); i++) { |
| density = layer->lefiLayer::dccurrent(i); |
| fprintf(fout, " DCCURRENTDENSITY %s", density->type()); |
| if (density->hasOneEntry()) |
| fprintf(fout, " %g ;\n", density->oneEntry()); |
| else { |
| fprintf(fout, "\n"); |
| if (density->numCutareas()) { |
| fprintf(fout, " CUTAREA"); |
| for (j = 0; j < density->numCutareas(); j++) |
| fprintf(fout, " %g", density->cutArea(j)); |
| fprintf(fout, " ;\n"); |
| } |
| if (density->numWidths()) { |
| fprintf(fout, " WIDTH"); |
| for (j = 0; j < density->numWidths(); j++) |
| fprintf(fout, " %g", density->width(j)); |
| fprintf(fout, " ;\n"); |
| } |
| if (density->numTableEntries()) { |
| fprintf(fout, " TABLEENTRIES"); |
| for (j = 0; j < density->numTableEntries(); j++) |
| fprintf(fout, " %g", density->tableEntry(j)); |
| fprintf(fout, " ;\n"); |
| } |
| } |
| } |
| } |
| |
| for (i = 0; i < layer->lefiLayer::numSpacingTable(); i++) { |
| spTable = layer->lefiLayer::spacingTable(i); |
| fprintf(fout, " SPACINGTABLE\n"); |
| if (spTable->lefiSpacingTable::isInfluence()) { |
| influence = spTable->lefiSpacingTable::influence(); |
| fprintf(fout, " INFLUENCE"); |
| for (j = 0; j < influence->lefiInfluence::numInfluenceEntry(); j++) { |
| fprintf(fout, "\n WIDTH %g WITHIN %g SPACING %g", |
| influence->lefiInfluence::width(j), |
| influence->lefiInfluence::distance(j), |
| influence->lefiInfluence::spacing(j)); |
| } |
| fprintf(fout, " ;\n"); |
| } else if (spTable->lefiSpacingTable::isParallel()){ |
| parallel = spTable->lefiSpacingTable::parallel(); |
| fprintf(fout, " PARALLELRUNLENGTH"); |
| for (j = 0; j < parallel->lefiParallel::numLength(); j++) { |
| fprintf(fout, " %g", parallel->lefiParallel::length(j)); |
| } |
| for (j = 0; j < parallel->lefiParallel::numWidth(); j++) { |
| fprintf(fout, "\n WIDTH %g", |
| parallel->lefiParallel::width(j)); |
| for (k = 0; k < parallel->lefiParallel::numLength(); k++) { |
| fprintf(fout, " %g", parallel->lefiParallel::widthSpacing(j, k)); |
| } |
| } |
| fprintf(fout, " ;\n"); |
| } else { // 5.7 TWOWIDTHS |
| twoWidths = spTable->lefiSpacingTable::twoWidths(); |
| fprintf(fout, " TWOWIDTHS"); |
| for (j = 0; j < twoWidths->lefiTwoWidths::numWidth(); j++) { |
| fprintf(fout, "\n WIDTH %g ", |
| twoWidths->lefiTwoWidths::width(j)); |
| if (twoWidths->lefiTwoWidths::hasWidthPRL(j)) |
| fprintf(fout, "PRL %g ", twoWidths->lefiTwoWidths::widthPRL(j)); |
| for (k = 0; k < twoWidths->lefiTwoWidths::numWidthSpacing(j); k++) |
| fprintf(fout, "%g ",twoWidths->lefiTwoWidths::widthSpacing(j, k)); |
| } |
| fprintf(fout, " ;\n"); |
| } |
| } |
| |
| propNum = layer->lefiLayer::numProps(); |
| if (propNum > 0) { |
| fprintf(fout, " PROPERTY "); |
| for (i = 0; i < propNum; i++) { |
| // value can either be a string or number |
| fprintf(fout, "%s ", layer->lefiLayer::propName(i)); |
| if (layer->lefiLayer::propIsNumber(i)) |
| fprintf(fout, "%g ", layer->lefiLayer::propNumber(i)); |
| if (layer->lefiLayer::propIsString(i)) |
| fprintf(fout, "%s ", layer->lefiLayer::propValue(i)); |
| pType = layer->lefiLayer::propType(i); |
| switch (pType) { |
| case 'R': fprintf(fout, "REAL "); |
| break; |
| case 'I': fprintf(fout, "INTEGER "); |
| break; |
| case 'S': fprintf(fout, "STRING "); |
| break; |
| case 'Q': fprintf(fout, "QUOTESTRING "); |
| break; |
| case 'N': fprintf(fout, "NUMBER "); |
| break; |
| } |
| } |
| fprintf(fout, ";\n"); |
| } |
| if (layer->lefiLayer::hasDiagMinEdgeLength()) |
| fprintf(fout, " DIAGMINEDGELENGTH %g ;\n", |
| layer->lefiLayer::diagMinEdgeLength()); |
| if (layer->lefiLayer::numMinSize()) { |
| fprintf(fout, " MINSIZE "); |
| for (i = 0; i < layer->lefiLayer::numMinSize(); i++) { |
| fprintf(fout, "%g %g ", layer->lefiLayer::minSizeWidth(i), |
| layer->lefiLayer::minSizeLength(i)); |
| } |
| fprintf(fout, ";\n"); |
| } |
| |
| fprintf(fout, "END %s\n", layer->lefiLayer::name()); |
| |
| // Set it to case sensitive from here on |
| lefrSetCaseSensitivity(1); |
| |
| return 0; |
| } |
| |
| int macroBeginCB(lefrCallbackType_e c, const char* macroName, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "MACRO %s\n", macroName); |
| return 0; |
| } |
| |
| int macroFixedMaskCB(lefrCallbackType_e c, int, |
| lefiUserData) { |
| checkType(c); |
| |
| return 0; |
| } |
| |
| int macroClassTypeCB(lefrCallbackType_e c, const char* macroClassType, |
| lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "MACRO CLASS %s\n", macroClassType); |
| return 0; |
| } |
| |
| int macroOriginCB(lefrCallbackType_e c, lefiNum, |
| lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| // fprintf(fout, " ORIGIN ( %g %g ) ;\n", macroNum.x, macroNum.y); |
| return 0; |
| } |
| |
| int macroSizeCB(lefrCallbackType_e c, lefiNum, |
| lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| // fprintf(fout, " SIZE %g BY %g ;\n", macroNum.x, macroNum.y); |
| return 0; |
| } |
| |
| int macroCB(lefrCallbackType_e c, lefiMacro* macro, lefiUserData) { |
| lefiSitePattern* pattern; |
| int propNum, i, hasPrtSym = 0; |
| |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| if (macro->lefiMacro::hasClass()) |
| fprintf(fout, " CLASS %s ;\n", macro->lefiMacro::macroClass()); |
| if (macro->lefiMacro::isFixedMask()) |
| fprintf(fout, " FIXEDMASK ;\n"); |
| if (macro->lefiMacro::hasEEQ()) |
| fprintf(fout, " EEQ %s ;\n", macro->lefiMacro::EEQ()); |
| if (macro->lefiMacro::hasLEQ()) |
| fprintf(fout, " LEQ %s ;\n", macro->lefiMacro::LEQ()); |
| if (macro->lefiMacro::hasSource()) |
| fprintf(fout, " SOURCE %s ;\n", macro->lefiMacro::source()); |
| if (macro->lefiMacro::hasXSymmetry()) { |
| fprintf(fout, " SYMMETRY X "); |
| hasPrtSym = 1; |
| } |
| if (macro->lefiMacro::hasYSymmetry()) { // print X Y & R90 in one line |
| if (!hasPrtSym) { |
| fprintf(fout, " SYMMETRY Y "); |
| hasPrtSym = 1; |
| } |
| else |
| fprintf(fout, "Y "); |
| } |
| if (macro->lefiMacro::has90Symmetry()) { |
| if (!hasPrtSym) { |
| fprintf(fout, " SYMMETRY R90 "); |
| hasPrtSym = 1; |
| } |
| else |
| fprintf(fout, "R90 "); |
| } |
| if (hasPrtSym) { |
| fprintf (fout, ";\n"); |
| hasPrtSym = 0; |
| } |
| if (macro->lefiMacro::hasSiteName()) |
| fprintf(fout, " SITE %s ;\n", macro->lefiMacro::siteName()); |
| if (macro->lefiMacro::hasSitePattern()) { |
| for (i = 0; i < macro->lefiMacro::numSitePattern(); i++ ) { |
| pattern = macro->lefiMacro::sitePattern(i); |
| if (pattern->lefiSitePattern::hasStepPattern()) { |
| fprintf(fout, " SITE %s %g %g %s DO %g BY %g STEP %g %g ;\n", |
| pattern->lefiSitePattern::name(), pattern->lefiSitePattern::x(), |
| pattern->lefiSitePattern::y(), |
| orientStr(pattern->lefiSitePattern::orient()), |
| pattern->lefiSitePattern::xStart(), |
| pattern->lefiSitePattern::yStart(), |
| pattern->lefiSitePattern::xStep(), |
| pattern->lefiSitePattern::yStep()); |
| } else { |
| fprintf(fout, " SITE %s %g %g %s ;\n", |
| pattern->lefiSitePattern::name(), pattern->lefiSitePattern::x(), |
| pattern->lefiSitePattern::y(), |
| orientStr(pattern->lefiSitePattern::orient())); |
| } |
| } |
| } |
| if (macro->lefiMacro::hasSize()) |
| fprintf(fout, " SIZE %g BY %g ;\n", macro->lefiMacro::sizeX(), |
| macro->lefiMacro::sizeY()); |
| |
| if (macro->lefiMacro::hasForeign()) { |
| for (i = 0; i < macro->lefiMacro::numForeigns(); i++) { |
| fprintf(fout, " FOREIGN %s ", macro->lefiMacro::foreignName(i)); |
| if (macro->lefiMacro::hasForeignPoint(i)) { |
| fprintf(fout, "( %g %g ) ", macro->lefiMacro::foreignX(i), |
| macro->lefiMacro::foreignY(i)); |
| if (macro->lefiMacro::hasForeignOrient(i)) |
| fprintf(fout, "%s ", macro->lefiMacro::foreignOrientStr(i)); |
| } |
| fprintf(fout, ";\n"); |
| } |
| } |
| if (macro->lefiMacro::hasOrigin()) |
| fprintf(fout, " ORIGIN ( %g %g ) ;\n", macro->lefiMacro::originX(), |
| macro->lefiMacro::originY()); |
| if (macro->lefiMacro::hasPower()) |
| fprintf(fout, " POWER %g ;\n", macro->lefiMacro::power()); |
| propNum = macro->lefiMacro::numProperties(); |
| if (propNum > 0) { |
| fprintf(fout, " PROPERTY "); |
| for (i = 0; i < propNum; i++) { |
| // value can either be a string or number |
| if (macro->lefiMacro::propValue(i)) { |
| fprintf(fout, "%s %s ", macro->lefiMacro::propName(i), |
| macro->lefiMacro::propValue(i)); |
| } |
| else |
| fprintf(fout, "%s %g ", macro->lefiMacro::propName(i), |
| macro->lefiMacro::propNum(i)); |
| |
| switch (macro->lefiMacro::propType(i)) { |
| case 'R': fprintf(fout, "REAL "); |
| break; |
| case 'I': fprintf(fout, "INTEGER "); |
| break; |
| case 'S': fprintf(fout, "STRING "); |
| break; |
| case 'Q': fprintf(fout, "QUOTESTRING "); |
| break; |
| case 'N': fprintf(fout, "NUMBER "); |
| break; |
| } |
| } |
| fprintf(fout, ";\n"); |
| } |
| //fprintf(fout, "END %s\n", macro->lefiMacro::name()); |
| return 0; |
| } |
| |
| int macroEndCB(lefrCallbackType_e c, const char* macroName, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "END %s\n", macroName); |
| return 0; |
| } |
| |
| int manufacturingCB(lefrCallbackType_e c, double num, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "MANUFACTURINGGRID %g ;\n", num); |
| return 0; |
| } |
| |
| int maxStackViaCB(lefrCallbackType_e c, lefiMaxStackVia* maxStack, |
| lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "MAXVIASTACK %d ", maxStack->lefiMaxStackVia::maxStackVia()); |
| if (maxStack->lefiMaxStackVia::hasMaxStackViaRange()) |
| fprintf(fout, "RANGE %s %s ", |
| maxStack->lefiMaxStackVia::maxStackViaBottomLayer(), |
| maxStack->lefiMaxStackVia::maxStackViaTopLayer()); |
| fprintf(fout, ";\n"); |
| return 0; |
| } |
| |
| int minFeatureCB(lefrCallbackType_e c, lefiMinFeature* min, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "MINFEATURE %g %g ;\n", min->lefiMinFeature::one(), |
| min->lefiMinFeature::two()); |
| return 0; |
| } |
| |
| int nonDefaultCB(lefrCallbackType_e c, lefiNonDefault* def, lefiUserData) { |
| int i; |
| lefiVia* via; |
| lefiSpacing* spacing; |
| |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "NONDEFAULTRULE %s\n", def->lefiNonDefault::name()); |
| if (def->lefiNonDefault::hasHardspacing()) |
| fprintf(fout, " HARDSPACING ;\n"); |
| for (i = 0; i < def->lefiNonDefault::numLayers(); i++) { |
| fprintf(fout, " LAYER %s\n", def->lefiNonDefault::layerName(i)); |
| if (def->lefiNonDefault::hasLayerWidth(i)) |
| fprintf(fout, " WIDTH %g ;\n", def->lefiNonDefault::layerWidth(i)); |
| if (def->lefiNonDefault::hasLayerSpacing(i)) |
| fprintf(fout, " SPACING %g ;\n", |
| def->lefiNonDefault::layerSpacing(i)); |
| if (def->lefiNonDefault::hasLayerDiagWidth(i)) |
| fprintf(fout, " DIAGWIDTH %g ;\n", |
| def->lefiNonDefault::layerDiagWidth(i)); |
| if (def->lefiNonDefault::hasLayerWireExtension(i)) |
| fprintf(fout, " WIREEXTENSION %g ;\n", |
| def->lefiNonDefault::layerWireExtension(i)); |
| if (def->lefiNonDefault::hasLayerResistance(i)) |
| fprintf(fout, " RESISTANCE RPERSQ %g ;\n", |
| def->lefiNonDefault::layerResistance(i)); |
| if (def->lefiNonDefault::hasLayerCapacitance(i)) |
| fprintf(fout, " CAPACITANCE CPERSQDIST %g ;\n", |
| def->lefiNonDefault::layerCapacitance(i)); |
| if (def->lefiNonDefault::hasLayerEdgeCap(i)) |
| fprintf(fout, " EDGECAPACITANCE %g ;\n", |
| def->lefiNonDefault::layerEdgeCap(i)); |
| fprintf(fout, " END %s\n", def->lefiNonDefault::layerName(i)); |
| } |
| |
| // handle via in nondefaultrule |
| for (i = 0; i < def->lefiNonDefault::numVias(); i++) { |
| via = def->lefiNonDefault::viaRule(i); |
| lefVia(via); |
| } |
| |
| // handle spacing in nondefaultrule |
| for (i = 0; i < def->lefiNonDefault::numSpacingRules(); i++) { |
| spacing = def->lefiNonDefault::spacingRule(i); |
| lefSpacing(spacing); |
| } |
| |
| // handle usevia |
| for (i = 0; i < def->lefiNonDefault::numUseVia(); i++) |
| fprintf(fout, " USEVIA %s ;\n", def->lefiNonDefault::viaName(i)); |
| |
| // handle useviarule |
| for (i = 0; i < def->lefiNonDefault::numUseViaRule(); i++) |
| fprintf(fout, " USEVIARULE %s ;\n", |
| def->lefiNonDefault::viaRuleName(i)); |
| |
| // handle mincuts |
| for (i = 0; i < def->lefiNonDefault::numMinCuts(); i++) { |
| fprintf(fout, " MINCUTS %s %d ;\n", def->lefiNonDefault::cutLayerName(i), |
| def->lefiNonDefault::numCuts(i)); |
| } |
| |
| // handle property in nondefaultrule |
| if (def->lefiNonDefault::numProps() > 0) { |
| fprintf(fout, " PROPERTY "); |
| for (i = 0; i < def->lefiNonDefault::numProps(); i++) { |
| fprintf(fout, "%s ", def->lefiNonDefault::propName(i)); |
| if (def->lefiNonDefault::propIsNumber(i)) |
| fprintf(fout, "%g ", def->lefiNonDefault::propNumber(i)); |
| if (def->lefiNonDefault::propIsString(i)) |
| fprintf(fout, "%s ", def->lefiNonDefault::propValue(i)); |
| switch(def->lefiNonDefault::propType(i)) { |
| case 'R': fprintf(fout, "REAL "); |
| break; |
| case 'I': fprintf(fout, "INTEGER "); |
| break; |
| case 'S': fprintf(fout, "STRING "); |
| break; |
| case 'Q': fprintf(fout, "QUOTESTRING "); |
| break; |
| case 'N': fprintf(fout, "NUMBER "); |
| break; |
| } |
| } |
| fprintf(fout, ";\n"); |
| } |
| fprintf(fout, "END %s ;\n", def->lefiNonDefault::name()); |
| |
| return 0; |
| } |
| |
| int obstructionCB(lefrCallbackType_e c, lefiObstruction* obs, |
| lefiUserData) { |
| lefiGeometries* geometry; |
| |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, " OBS\n"); |
| geometry = obs->lefiObstruction::geometries(); |
| prtGeometry(geometry); |
| fprintf(fout, " END\n"); |
| return 0; |
| } |
| |
| int pinCB(lefrCallbackType_e c, lefiPin* pin, lefiUserData) { |
| int numPorts, i, j; |
| lefiGeometries* geometry; |
| lefiPinAntennaModel* aModel; |
| |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, " PIN %s\n", pin->lefiPin::name()); |
| if (pin->lefiPin::hasForeign()) { |
| for (i = 0; i < pin->lefiPin::numForeigns(); i++) { |
| if (pin->lefiPin::hasForeignOrient(i)) |
| fprintf(fout, " FOREIGN %s STRUCTURE ( %g %g ) %s ;\n", |
| pin->lefiPin::foreignName(i), pin->lefiPin::foreignX(i), |
| pin->lefiPin::foreignY(i), |
| pin->lefiPin::foreignOrientStr(i)); |
| else if (pin->lefiPin::hasForeignPoint(i)) |
| fprintf(fout, " FOREIGN %s STRUCTURE ( %g %g ) ;\n", |
| pin->lefiPin::foreignName(i), pin->lefiPin::foreignX(i), |
| pin->lefiPin::foreignY(i)); |
| else |
| fprintf(fout, " FOREIGN %s ;\n", pin->lefiPin::foreignName(i)); |
| } |
| } |
| if (pin->lefiPin::hasLEQ()) |
| fprintf(fout, " LEQ %s ;\n", pin->lefiPin::LEQ()); |
| if (pin->lefiPin::hasDirection()) |
| fprintf(fout, " DIRECTION %s ;\n", pin->lefiPin::direction()); |
| if (pin->lefiPin::hasUse()) |
| fprintf(fout, " USE %s ;\n", pin->lefiPin::use()); |
| if (pin->lefiPin::hasShape()) |
| fprintf(fout, " SHAPE %s ;\n", pin->lefiPin::shape()); |
| if (pin->lefiPin::hasMustjoin()) |
| fprintf(fout, " MUSTJOIN %s ;\n", pin->lefiPin::mustjoin()); |
| if (pin->lefiPin::hasOutMargin()) |
| fprintf(fout, " OUTPUTNOISEMARGIN %g %g ;\n", |
| pin->lefiPin::outMarginHigh(), pin->lefiPin::outMarginLow()); |
| if (pin->lefiPin::hasOutResistance()) |
| fprintf(fout, " OUTPUTRESISTANCE %g %g ;\n", |
| pin->lefiPin::outResistanceHigh(), |
| pin->lefiPin::outResistanceLow()); |
| if (pin->lefiPin::hasInMargin()) |
| fprintf(fout, " INPUTNOISEMARGIN %g %g ;\n", |
| pin->lefiPin::inMarginHigh(), pin->lefiPin::inMarginLow()); |
| if (pin->lefiPin::hasPower()) |
| fprintf(fout, " POWER %g ;\n", pin->lefiPin::power()); |
| if (pin->lefiPin::hasLeakage()) |
| fprintf(fout, " LEAKAGE %g ;\n", pin->lefiPin::leakage()); |
| if (pin->lefiPin::hasMaxload()) |
| fprintf(fout, " MAXLOAD %g ;\n", pin->lefiPin::maxload()); |
| if (pin->lefiPin::hasCapacitance()) |
| fprintf(fout, " CAPACITANCE %g ;\n", pin->lefiPin::capacitance()); |
| if (pin->lefiPin::hasResistance()) |
| fprintf(fout, " RESISTANCE %g ;\n", pin->lefiPin::resistance()); |
| if (pin->lefiPin::hasPulldownres()) |
| fprintf(fout, " PULLDOWNRES %g ;\n", pin->lefiPin::pulldownres()); |
| if (pin->lefiPin::hasTieoffr()) |
| fprintf(fout, " TIEOFFR %g ;\n", pin->lefiPin::tieoffr()); |
| if (pin->lefiPin::hasVHI()) |
| fprintf(fout, " VHI %g ;\n", pin->lefiPin::VHI()); |
| if (pin->lefiPin::hasVLO()) |
| fprintf(fout, " VLO %g ;\n", pin->lefiPin::VLO()); |
| if (pin->lefiPin::hasRiseVoltage()) |
| fprintf(fout, " RISEVOLTAGETHRESHOLD %g ;\n", |
| pin->lefiPin::riseVoltage()); |
| if (pin->lefiPin::hasFallVoltage()) |
| fprintf(fout, " FALLVOLTAGETHRESHOLD %g ;\n", |
| pin->lefiPin::fallVoltage()); |
| if (pin->lefiPin::hasRiseThresh()) |
| fprintf(fout, " RISETHRESH %g ;\n", pin->lefiPin::riseThresh()); |
| if (pin->lefiPin::hasFallThresh()) |
| fprintf(fout, " FALLTHRESH %g ;\n", pin->lefiPin::fallThresh()); |
| if (pin->lefiPin::hasRiseSatcur()) |
| fprintf(fout, " RISESATCUR %g ;\n", pin->lefiPin::riseSatcur()); |
| if (pin->lefiPin::hasFallSatcur()) |
| fprintf(fout, " FALLSATCUR %g ;\n", pin->lefiPin::fallSatcur()); |
| if (pin->lefiPin::hasRiseSlewLimit()) |
| fprintf(fout, " RISESLEWLIMIT %g ;\n", pin->lefiPin::riseSlewLimit()); |
| if (pin->lefiPin::hasFallSlewLimit()) |
| fprintf(fout, " FALLSLEWLIMIT %g ;\n", pin->lefiPin::fallSlewLimit()); |
| if (pin->lefiPin::hasCurrentSource()) |
| fprintf(fout, " CURRENTSOURCE %s ;\n", pin->lefiPin::currentSource()); |
| if (pin->lefiPin::hasTables()) |
| fprintf(fout, " IV_TABLES %s %s ;\n", pin->lefiPin::tableHighName(), |
| pin->lefiPin::tableLowName()); |
| if (pin->lefiPin::hasTaperRule()) |
| fprintf(fout, " TAPERRULE %s ;\n", pin->lefiPin::taperRule()); |
| if (pin->lefiPin::hasNetExpr()) |
| fprintf(fout, " NETEXPR \"%s\" ;\n", pin->lefiPin::netExpr()); |
| if (pin->lefiPin::hasSupplySensitivity()) |
| fprintf(fout, " SUPPLYSENSITIVITY %s ;\n", |
| pin->lefiPin::supplySensitivity()); |
| if (pin->lefiPin::hasGroundSensitivity()) |
| fprintf(fout, " GROUNDSENSITIVITY %s ;\n", |
| pin->lefiPin::groundSensitivity()); |
| if (pin->lefiPin::hasAntennaSize()) { |
| for (i = 0; i < pin->lefiPin::numAntennaSize(); i++) { |
| fprintf(fout, " ANTENNASIZE %g ", pin->lefiPin::antennaSize(i)); |
| if (pin->lefiPin::antennaSizeLayer(i)) |
| fprintf(fout, "LAYER %s ", pin->lefiPin::antennaSizeLayer(i)); |
| fprintf(fout, ";\n"); |
| } |
| } |
| if (pin->lefiPin::hasAntennaMetalArea()) { |
| for (i = 0; i < pin->lefiPin::numAntennaMetalArea(); i++) { |
| fprintf(fout, " ANTENNAMETALAREA %g ", |
| pin->lefiPin::antennaMetalArea(i)); |
| if (pin->lefiPin::antennaMetalAreaLayer(i)) |
| fprintf(fout, "LAYER %s ", pin->lefiPin::antennaMetalAreaLayer(i)); |
| fprintf(fout, ";\n"); |
| } |
| } |
| if (pin->lefiPin::hasAntennaMetalLength()) { |
| for (i = 0; i < pin->lefiPin::numAntennaMetalLength(); i++) { |
| fprintf(fout, " ANTENNAMETALLENGTH %g ", |
| pin->lefiPin::antennaMetalLength(i)); |
| if (pin->lefiPin::antennaMetalLengthLayer(i)) |
| fprintf(fout, "LAYER %s ", pin->lefiPin::antennaMetalLengthLayer(i)); |
| fprintf(fout, ";\n"); |
| } |
| } |
| |
| if (pin->lefiPin::hasAntennaPartialMetalArea()) { |
| for (i = 0; i < pin->lefiPin::numAntennaPartialMetalArea(); i++) { |
| fprintf(fout, " ANTENNAPARTIALMETALAREA %g ", |
| pin->lefiPin::antennaPartialMetalArea(i)); |
| if (pin->lefiPin::antennaPartialMetalAreaLayer(i)) |
| fprintf(fout, "LAYER %s ", |
| pin->lefiPin::antennaPartialMetalAreaLayer(i)); |
| fprintf(fout, ";\n"); |
| } |
| } |
| |
| if (pin->lefiPin::hasAntennaPartialMetalSideArea()) { |
| for (i = 0; i < pin->lefiPin::numAntennaPartialMetalSideArea(); i++) { |
| fprintf(fout, " ANTENNAPARTIALMETALSIDEAREA %g ", |
| pin->lefiPin::antennaPartialMetalSideArea(i)); |
| if (pin->lefiPin::antennaPartialMetalSideAreaLayer(i)) |
| fprintf(fout, "LAYER %s ", |
| pin->lefiPin::antennaPartialMetalSideAreaLayer(i)); |
| fprintf(fout, ";\n"); |
| } |
| } |
| |
| if (pin->lefiPin::hasAntennaPartialCutArea()) { |
| for (i = 0; i < pin->lefiPin::numAntennaPartialCutArea(); i++) { |
| fprintf(fout, " ANTENNAPARTIALCUTAREA %g ", |
| pin->lefiPin::antennaPartialCutArea(i)); |
| if (pin->lefiPin::antennaPartialCutAreaLayer(i)) |
| fprintf(fout, "LAYER %s ", |
| pin->lefiPin::antennaPartialCutAreaLayer(i)); |
| fprintf(fout, ";\n"); |
| } |
| } |
| |
| if (pin->lefiPin::hasAntennaDiffArea()) { |
| for (i = 0; i < pin->lefiPin::numAntennaDiffArea(); i++) { |
| fprintf(fout, " ANTENNADIFFAREA %g ", |
| pin->lefiPin::antennaDiffArea(i)); |
| if (pin->lefiPin::antennaDiffAreaLayer(i)) |
| fprintf(fout, "LAYER %s ", pin->lefiPin::antennaDiffAreaLayer(i)); |
| fprintf(fout, ";\n"); |
| } |
| } |
| |
| for (j = 0; j < pin->lefiPin::numAntennaModel(); j++) { |
| aModel = pin->lefiPin::antennaModel(j); |
| |
| fprintf(fout, " ANTENNAMODEL %s ;\n", |
| aModel->lefiPinAntennaModel::antennaOxide()); |
| |
| if (aModel->lefiPinAntennaModel::hasAntennaGateArea()) { |
| for (i = 0; i < aModel->lefiPinAntennaModel::numAntennaGateArea(); i++) |
| { |
| fprintf(fout, " ANTENNAGATEAREA %g ", |
| aModel->lefiPinAntennaModel::antennaGateArea(i)); |
| if (aModel->lefiPinAntennaModel::antennaGateAreaLayer(i)) |
| fprintf(fout, "LAYER %s ", |
| aModel->lefiPinAntennaModel::antennaGateAreaLayer(i)); |
| fprintf(fout, ";\n"); |
| } |
| } |
| |
| if (aModel->lefiPinAntennaModel::hasAntennaMaxAreaCar()) { |
| for (i = 0; i < aModel->lefiPinAntennaModel::numAntennaMaxAreaCar(); |
| i++) { |
| fprintf(fout, " ANTENNAMAXAREACAR %g ", |
| aModel->lefiPinAntennaModel::antennaMaxAreaCar(i)); |
| if (aModel->lefiPinAntennaModel::antennaMaxAreaCarLayer(i)) |
| fprintf(fout, "LAYER %s ", |
| aModel->lefiPinAntennaModel::antennaMaxAreaCarLayer(i)); |
| fprintf(fout, ";\n"); |
| } |
| } |
| |
| if (aModel->lefiPinAntennaModel::hasAntennaMaxSideAreaCar()) { |
| for (i = 0; i < aModel->lefiPinAntennaModel::numAntennaMaxSideAreaCar(); |
| i++) { |
| fprintf(fout, " ANTENNAMAXSIDEAREACAR %g ", |
| aModel->lefiPinAntennaModel::antennaMaxSideAreaCar(i)); |
| if (aModel->lefiPinAntennaModel::antennaMaxSideAreaCarLayer(i)) |
| fprintf(fout, "LAYER %s ", |
| aModel->lefiPinAntennaModel::antennaMaxSideAreaCarLayer(i)); |
| fprintf(fout, ";\n"); |
| } |
| } |
| |
| if (aModel->lefiPinAntennaModel::hasAntennaMaxCutCar()) { |
| for (i = 0; i < aModel->lefiPinAntennaModel::numAntennaMaxCutCar(); i++) |
| { |
| fprintf(fout, " ANTENNAMAXCUTCAR %g ", |
| aModel->lefiPinAntennaModel::antennaMaxCutCar(i)); |
| if (aModel->lefiPinAntennaModel::antennaMaxCutCarLayer(i)) |
| fprintf(fout, "LAYER %s ", |
| aModel->lefiPinAntennaModel::antennaMaxCutCarLayer(i)); |
| fprintf(fout, ";\n"); |
| } |
| } |
| } |
| |
| if (pin->lefiPin::numProperties() > 0) { |
| fprintf(fout, " PROPERTY "); |
| for (i = 0; i < pin->lefiPin::numProperties(); i++) { |
| // value can either be a string or number |
| if (pin->lefiPin::propValue(i)) { |
| fprintf(fout, "%s %s ", pin->lefiPin::propName(i), |
| pin->lefiPin::propValue(i)); |
| } |
| else |
| fprintf(fout, "%s %g ", pin->lefiPin::propName(i), |
| pin->lefiPin::propNum(i)); |
| switch (pin->lefiPin::propType(i)) { |
| case 'R': fprintf(fout, "REAL "); |
| break; |
| case 'I': fprintf(fout, "INTEGER "); |
| break; |
| case 'S': fprintf(fout, "STRING "); |
| break; |
| case 'Q': fprintf(fout, "QUOTESTRING "); |
| break; |
| case 'N': fprintf(fout, "NUMBER "); |
| break; |
| } |
| } |
| fprintf(fout, ";\n"); |
| } |
| |
| numPorts = pin->lefiPin::numPorts(); |
| for (i = 0; i < numPorts; i++) { |
| fprintf(fout," PORT\n"); |
| geometry = pin->lefiPin::port(i); |
| prtGeometry(geometry); |
| fprintf(fout, " END\n"); |
| } |
| fprintf(fout, " END %s\n", pin->lefiPin::name()); |
| return 0; |
| } |
| |
| int densityCB(lefrCallbackType_e c, lefiDensity* density, |
| lefiUserData) { |
| |
| struct lefiGeomRect rect; |
| |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, " DENSITY\n"); |
| for (int i = 0; i < density->lefiDensity::numLayer(); i++) { |
| fprintf(fout, " LAYER %s ;\n", density->lefiDensity::layerName(i)); |
| for (int j = 0; j < density->lefiDensity::numRects(i); j++) { |
| rect = density->lefiDensity::getRect(i,j); |
| fprintf(fout, " RECT %g %g %g %g ", rect.xl, rect.yl, rect.xh, |
| rect.yh); |
| fprintf(fout, "%g ;\n", density->lefiDensity::densityValue(i,j)); |
| } |
| } |
| fprintf(fout, " END\n"); |
| return 0; |
| } |
| |
| int propDefBeginCB(lefrCallbackType_e c, void*, lefiUserData) { |
| |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "PROPERTYDEFINITIONS\n"); |
| return 0; |
| } |
| |
| int propDefCB(lefrCallbackType_e c, lefiProp* prop, lefiUserData) { |
| |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, " %s %s", prop->lefiProp::propType(), |
| prop->lefiProp::propName()); |
| switch(prop->lefiProp::dataType()) { |
| case 'I': |
| fprintf(fout, " INTEGER"); |
| break; |
| case 'R': |
| fprintf(fout, " REAL"); |
| break; |
| case 'S': |
| fprintf(fout, " STRING"); |
| break; |
| } |
| if (prop->lefiProp::hasNumber()) |
| fprintf(fout, " %g", prop->lefiProp::number()); |
| if (prop->lefiProp::hasRange()) |
| fprintf(fout, " RANGE %g %g", prop->lefiProp::left(), |
| prop->lefiProp::right()); |
| if (prop->lefiProp::hasString()) |
| fprintf(fout, " %s", prop->lefiProp::string()); |
| fprintf(fout, "\n"); |
| return 0; |
| } |
| |
| int propDefEndCB(lefrCallbackType_e c, void*, lefiUserData) { |
| |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "END PROPERTYDEFINITIONS\n"); |
| return 0; |
| } |
| |
| int siteCB(lefrCallbackType_e c, lefiSite* site, lefiUserData) { |
| int hasPrtSym = 0; |
| int i; |
| |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "SITE %s\n", site->lefiSite::name()); |
| if (site->lefiSite::hasClass()) |
| fprintf(fout, " CLASS %s ;\n", site->lefiSite::siteClass()); |
| if (site->lefiSite::hasXSymmetry()) { |
| fprintf(fout, " SYMMETRY X "); |
| hasPrtSym = 1; |
| } |
| if (site->lefiSite::hasYSymmetry()) { |
| if (hasPrtSym) |
| fprintf(fout, "Y "); |
| else { |
| fprintf(fout, " SYMMETRY Y "); |
| hasPrtSym = 1; |
| } |
| } |
| if (site->lefiSite::has90Symmetry()) { |
| if (hasPrtSym) |
| fprintf(fout, "R90 "); |
| else { |
| fprintf(fout, " SYMMETRY R90 "); |
| hasPrtSym = 1; |
| } |
| } |
| if (hasPrtSym) |
| fprintf(fout, ";\n"); |
| if (site->lefiSite::hasSize()) |
| fprintf(fout, " SIZE %g BY %g ;\n", site->lefiSite::sizeX(), |
| site->lefiSite::sizeY()); |
| |
| if (site->hasRowPattern()) { |
| fprintf(fout, " ROWPATTERN "); |
| for (i = 0; i < site->lefiSite::numSites(); i++) |
| fprintf(fout, " %s %s ", site->lefiSite::siteName(i), |
| site->lefiSite::siteOrientStr(i)); |
| fprintf(fout, ";\n"); |
| } |
| |
| fprintf(fout, "END %s\n", site->lefiSite::name()); |
| return 0; |
| } |
| |
| int spacingBeginCB(lefrCallbackType_e c, void*, lefiUserData){ |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "SPACING\n"); |
| return 0; |
| } |
| |
| int spacingCB(lefrCallbackType_e c, lefiSpacing* spacing, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| lefSpacing(spacing); |
| return 0; |
| } |
| |
| int spacingEndCB(lefrCallbackType_e c, void*, lefiUserData){ |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "END SPACING\n"); |
| return 0; |
| } |
| |
| int timingCB(lefrCallbackType_e c, lefiTiming* timing, lefiUserData) { |
| int i; |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "TIMING\n"); |
| for (i = 0; i < timing->numFromPins(); i++) |
| fprintf(fout, " FROMPIN %s ;\n", timing->fromPin(i)); |
| for (i = 0; i < timing->numToPins(); i++) |
| fprintf(fout, " TOPIN %s ;\n", timing->toPin(i)); |
| fprintf(fout, " RISE SLEW1 %g %g %g %g ;\n", timing->riseSlewOne(), |
| timing->riseSlewTwo(), timing->riseSlewThree(), |
| timing->riseSlewFour()); |
| if (timing->hasRiseSlew2()) |
| fprintf(fout, " RISE SLEW2 %g %g %g ;\n", timing->riseSlewFive(), |
| timing->riseSlewSix(), timing->riseSlewSeven()); |
| if (timing->hasFallSlew()) |
| fprintf(fout, " FALL SLEW1 %g %g %g %g ;\n", timing->fallSlewOne(), |
| timing->fallSlewTwo(), timing->fallSlewThree(), |
| timing->fallSlewFour()); |
| if (timing->hasFallSlew2()) |
| fprintf(fout, " FALL SLEW2 %g %g %g ;\n", timing->fallSlewFive(), |
| timing->fallSlewSix(), timing->riseSlewSeven()); |
| if (timing->hasRiseIntrinsic()) { |
| fprintf(fout, "TIMING RISE INTRINSIC %g %g ;\n", |
| timing->riseIntrinsicOne(), timing->riseIntrinsicTwo()); |
| fprintf(fout, "TIMING RISE VARIABLE %g %g ;\n", |
| timing->riseIntrinsicThree(), timing->riseIntrinsicFour()); |
| } |
| if (timing->hasFallIntrinsic()) { |
| fprintf(fout, "TIMING FALL INTRINSIC %g %g ;\n", |
| timing->fallIntrinsicOne(), timing->fallIntrinsicTwo()); |
| fprintf(fout, "TIMING RISE VARIABLE %g %g ;\n", |
| timing->fallIntrinsicThree(), timing->fallIntrinsicFour()); |
| } |
| if (timing->hasRiseRS()) |
| fprintf(fout, "TIMING RISERS %g %g ;\n", |
| timing->riseRSOne(), timing->riseRSTwo()); |
| if (timing->hasRiseCS()) |
| fprintf(fout, "TIMING RISECS %g %g ;\n", |
| timing->riseCSOne(), timing->riseCSTwo()); |
| if (timing->hasFallRS()) |
| fprintf(fout, "TIMING FALLRS %g %g ;\n", |
| timing->fallRSOne(), timing->fallRSTwo()); |
| if (timing->hasFallCS()) |
| fprintf(fout, "TIMING FALLCS %g %g ;\n", |
| timing->fallCSOne(), timing->fallCSTwo()); |
| if (timing->hasUnateness()) |
| fprintf(fout, "TIMING UNATENESS %s ;\n", timing->unateness()); |
| if (timing->hasRiseAtt1()) |
| fprintf(fout, "TIMING RISESATT1 %g %g ;\n", timing->riseAtt1One(), |
| timing->riseAtt1Two()); |
| if (timing->hasFallAtt1()) |
| fprintf(fout, "TIMING FALLSATT1 %g %g ;\n", timing->fallAtt1One(), |
| timing->fallAtt1Two()); |
| if (timing->hasRiseTo()) |
| fprintf(fout, "TIMING RISET0 %g %g ;\n", timing->riseToOne(), |
| timing->riseToTwo()); |
| if (timing->hasFallTo()) |
| fprintf(fout, "TIMING FALLT0 %g %g ;\n", timing->fallToOne(), |
| timing->fallToTwo()); |
| if (timing->hasSDFonePinTrigger()) |
| fprintf(fout, " %s TABLEDIMENSION %g %g %g ;\n", |
| timing->SDFonePinTriggerType(), timing->SDFtriggerOne(), |
| timing->SDFtriggerTwo(), timing->SDFtriggerThree()); |
| if (timing->hasSDFtwoPinTrigger()) |
| fprintf(fout, " %s %s %s TABLEDIMENSION %g %g %g ;\n", |
| timing->SDFtwoPinTriggerType(), timing->SDFfromTrigger(), |
| timing->SDFtoTrigger(), timing->SDFtriggerOne(), |
| timing->SDFtriggerTwo(), timing->SDFtriggerThree()); |
| fprintf(fout, "END TIMING\n"); |
| return 0; |
| } |
| |
| int unitsCB(lefrCallbackType_e c, lefiUnits* unit, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "UNITS\n"); |
| if (unit->lefiUnits::hasDatabase()) |
| fprintf(fout, " DATABASE %s %g ;\n", unit->lefiUnits::databaseName(), |
| unit->lefiUnits::databaseNumber()); |
| if (unit->lefiUnits::hasCapacitance()) |
| fprintf(fout, " CAPACITANCE PICOFARADS %g ;\n", |
| unit->lefiUnits::capacitance()); |
| if (unit->lefiUnits::hasResistance()) |
| fprintf(fout, " RESISTANCE OHMS %g ;\n", unit->lefiUnits::resistance()); |
| if (unit->lefiUnits::hasPower()) |
| fprintf(fout, " POWER MILLIWATTS %g ;\n", unit->lefiUnits::power()); |
| if (unit->lefiUnits::hasCurrent()) |
| fprintf(fout, " CURRENT MILLIAMPS %g ;\n", unit->lefiUnits::current()); |
| if (unit->lefiUnits::hasVoltage()) |
| fprintf(fout, " VOLTAGE VOLTS %g ;\n", unit->lefiUnits::voltage()); |
| if (unit->lefiUnits::hasFrequency()) |
| fprintf(fout, " FREQUENCY MEGAHERTZ %g ;\n", |
| unit->lefiUnits::frequency()); |
| fprintf(fout, "END UNITS\n"); |
| return 0; |
| } |
| |
| int useMinSpacingCB(lefrCallbackType_e c, lefiUseMinSpacing* spacing, |
| lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "USEMINSPACING %s ", spacing->lefiUseMinSpacing::name()); |
| if (spacing->lefiUseMinSpacing::value()) |
| fprintf(fout, "ON ;\n"); |
| else |
| fprintf(fout, "OFF ;\n"); |
| return 0; |
| } |
| |
| int versionCB(lefrCallbackType_e c, double num, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "VERSION %g ;\n", num); |
| return 0; |
| } |
| |
| int versionStrCB(lefrCallbackType_e c, const char* versionName, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "VERSION %s ;\n", versionName); |
| return 0; |
| } |
| |
| int viaCB(lefrCallbackType_e c, lefiVia* via, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| lefVia(via); |
| return 0; |
| } |
| |
| int viaRuleCB(lefrCallbackType_e c, lefiViaRule* viaRule, lefiUserData) { |
| int numLayers, numVias, i; |
| lefiViaRuleLayer* vLayer; |
| |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "VIARULE %s", viaRule->lefiViaRule::name()); |
| if (viaRule->lefiViaRule::hasGenerate()) |
| fprintf(fout, " GENERATE"); |
| if (viaRule->lefiViaRule::hasDefault()) |
| fprintf(fout, " DEFAULT"); |
| fprintf(fout, "\n"); |
| |
| numLayers = viaRule->lefiViaRule::numLayers(); |
| // if numLayers == 2, it is VIARULE without GENERATE and has via name |
| // if numLayers == 3, it is VIARULE with GENERATE, and the 3rd layer is cut |
| for (i = 0; i < numLayers; i++) { |
| vLayer = viaRule->lefiViaRule::layer(i); |
| lefViaRuleLayer(vLayer); |
| } |
| |
| if (numLayers == 2 && !(viaRule->lefiViaRule::hasGenerate())) { |
| // should have vianames |
| numVias = viaRule->lefiViaRule::numVias(); |
| if (numVias == 0) |
| fprintf(fout, "Should have via names in VIARULE.\n"); |
| else { |
| for (i = 0; i < numVias; i++) |
| fprintf(fout, " VIA %s ;\n", viaRule->lefiViaRule::viaName(i)); |
| } |
| } |
| if (viaRule->lefiViaRule::numProps() > 0) { |
| fprintf(fout, " PROPERTY "); |
| for (i = 0; i < viaRule->lefiViaRule::numProps(); i++) { |
| fprintf(fout, "%s ", viaRule->lefiViaRule::propName(i)); |
| if (viaRule->lefiViaRule::propValue(i)) |
| fprintf(fout, "%s ", viaRule->lefiViaRule::propValue(i)); |
| switch (viaRule->lefiViaRule::propType(i)) { |
| case 'R': fprintf(fout, "REAL "); |
| break; |
| case 'I': fprintf(fout, "INTEGER "); |
| break; |
| case 'S': fprintf(fout, "STRING "); |
| break; |
| case 'Q': fprintf(fout, "QUOTESTRING "); |
| break; |
| case 'N': fprintf(fout, "NUMBER "); |
| break; |
| } |
| } |
| fprintf(fout, ";\n"); |
| } |
| fprintf(fout, "END %s\n", viaRule->lefiViaRule::name()); |
| return 0; |
| } |
| |
| int extensionCB(lefrCallbackType_e c, const char* extsn, lefiUserData) { |
| checkType(c); |
| // lefrSetCaseSensitivity(0); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "BEGINEXT %s ;\n", extsn); |
| // lefrSetCaseSensitivity(1); |
| return 0; |
| } |
| |
| int doneCB(lefrCallbackType_e c, void*, lefiUserData) { |
| checkType(c); |
| // if ((long)ud != userData) dataError(); |
| fprintf(fout, "END LIBRARY\n"); |
| return 0; |
| } |
| |
| void errorCB(const char* msg) { |
| printf ("%s : %s\n", lefrGetUserData(), msg); |
| } |
| |
| void warningCB(const char* msg) { |
| printf ("%s : %s\n", lefrGetUserData(), msg); |
| } |
| |
| void* mallocCB(int size) { |
| return malloc(size); |
| } |
| |
| void* reallocCB(void* name, int size) { |
| return realloc(name, size); |
| } |
| |
| void freeCB(void* name) { |
| free(name); |
| return; |
| } |
| |
| void lineNumberCB(int lineNo) { |
| fprintf(fout, "Parsed %d number of lines!!\n", lineNo); |
| return; |
| } |
| |
| void printWarning(const char *str) |
| { |
| fprintf(stderr, "%s\n", str); |
| } |
| |
| |
| |
| int |
| main(int argc, char** argv) { |
| char* inFile[100]; |
| char* outFile; |
| FILE* f; |
| int res; |
| int noCalls = 0; |
| // long start_mem; |
| int num; |
| int status; |
| int retStr = 0; |
| int numInFile = 0; |
| int fileCt = 0; |
| int relax = 0; |
| const char* version = "N/A"; |
| int setVer = 0; |
| char* userData; |
| int msgCb = 0; |
| int test1 = 0; |
| int test2 = 0; |
| int ccr749853 = 0; |
| int ccr1688946 = 0; |
| int ccr1709089 = 0; |
| int verbose = 0; |
| |
| // start_mem = (long)sbrk(0); |
| |
| userData = strdup ("(lefrw-5100)"); |
| strcpy(defaultName,"lef.in"); |
| strcpy(defaultOut,"list"); |
| inFile[0] = defaultName; |
| outFile = defaultOut; |
| fout = stdout; |
| // userData = 0x01020304; |
| |
| #ifdef WIN32 |
| // Enable two-digit exponent format |
| _set_output_format(_TWO_DIGIT_EXPONENT); |
| #endif |
| |
| argc--; |
| argv++; |
| while (argc--) { |
| |
| if (strcmp(*argv, "-d") == 0) { |
| argv++; |
| argc--; |
| sscanf(*argv, "%d", &num); |
| lefiSetDebug(num, 1); |
| }else if (strcmp(*argv, "-nc") == 0) { |
| noCalls = 1; |
| |
| } else if (strcmp(*argv, "-p") == 0) { |
| printing = 1; |
| |
| } else if (strcmp(*argv, "-m") == 0) { // use the user error/warning CB |
| msgCb = 1; |
| |
| } else if (strcmp(*argv, "-o") == 0) { |
| argv++; |
| argc--; |
| outFile = *argv; |
| if ((fout = fopen(outFile, "w")) == 0) { |
| fprintf(stderr, "ERROR: could not open output file\n"); |
| return 2; |
| } |
| |
| } else if (strcmp(*argv, "-verStr") == 0) { |
| /* New to set the version callback routine to return a string */ |
| /* instead of double. */ |
| retStr = 1; |
| |
| } else if (strcmp(*argv, "-relax") == 0) { |
| relax = 1; |
| |
| } else if (strcmp(*argv, "-65nm") == 0) { |
| parse65nm = 1; |
| |
| } else if (strcmp(*argv, "-lef58") == 0) { |
| parseLef58Type = 1; |
| |
| } else if (strcmp(*argv, "-ver") == 0) { |
| argv++; |
| argc--; |
| setVer = 1; |
| version = *argv; |
| } else if (strcmp(*argv, "-test1") == 0) { |
| test1 = 1; |
| } else if (strcmp(*argv, "-test2") == 0) { |
| test2 = 1; |
| } else if (strcmp(*argv, "-sessionless") == 0) { |
| isSessionles = 1; |
| } else if (strcmp(*argv, "-ccr749853") == 0) { |
| ccr749853 = 1; |
| } else if (strcmp(*argv, "-ccr1688946") == 0) { |
| ccr1688946 = 1; |
| } else if (strcmp(*argv, "-ccr1709089") == 0) { |
| ccr1709089 = 1; |
| } else if (argv[0][0] != '-') { |
| if (numInFile >= 100) { |
| fprintf(stderr, "ERROR: too many input files, max = 3.\n"); |
| return 2; |
| } |
| inFile[numInFile++] = *argv; |
| |
| } else { |
| fprintf(stderr, "ERROR: Illegal command line option: '%s'\n", *argv); |
| return 2; |
| } |
| |
| argv++; |
| } |
| |
| // sets the parser to be case sensitive... |
| // default was supposed to be the case but false... |
| // lefrSetCaseSensitivity(true); |
| if (isSessionles) { |
| lefrSetOpenLogFileAppend(); |
| } |
| |
| lefrInitSession(isSessionles ? 0 : 1); |
| |
| if (noCalls == 0) { |
| lefrSetWarningLogFunction(printWarning); |
| lefrSetAntennaInputCbk(antennaCB); |
| lefrSetAntennaInoutCbk(antennaCB); |
| lefrSetAntennaOutputCbk(antennaCB); |
| lefrSetArrayBeginCbk(arrayBeginCB); |
| lefrSetArrayCbk(arrayCB); |
| lefrSetArrayEndCbk(arrayEndCB); |
| lefrSetBusBitCharsCbk(busBitCharsCB); |
| lefrSetCaseSensitiveCbk(caseSensCB); |
| lefrSetFixedMaskCbk(fixedMaskCB); |
| lefrSetClearanceMeasureCbk(clearanceCB); |
| lefrSetDensityCbk(densityCB); |
| lefrSetDividerCharCbk(dividerCB); |
| lefrSetNoWireExtensionCbk(noWireExtCB); |
| lefrSetNoiseMarginCbk(noiseMarCB); |
| lefrSetEdgeRateThreshold1Cbk(edge1CB); |
| lefrSetEdgeRateThreshold2Cbk(edge2CB); |
| lefrSetEdgeRateScaleFactorCbk(edgeScaleCB); |
| lefrSetExtensionCbk(extensionCB); |
| lefrSetNoiseTableCbk(noiseTableCB); |
| lefrSetCorrectionTableCbk(correctionCB); |
| lefrSetDielectricCbk(dielectricCB); |
| lefrSetIRDropBeginCbk(irdropBeginCB); |
| lefrSetIRDropCbk(irdropCB); |
| lefrSetIRDropEndCbk(irdropEndCB); |
| lefrSetLayerCbk(layerCB); |
| lefrSetLibraryEndCbk(doneCB); |
| lefrSetMacroBeginCbk(macroBeginCB); |
| lefrSetMacroCbk(macroCB); |
| lefrSetMacroClassTypeCbk(macroClassTypeCB); |
| lefrSetMacroOriginCbk(macroOriginCB); |
| lefrSetMacroSizeCbk(macroSizeCB); |
| lefrSetMacroFixedMaskCbk(macroFixedMaskCB); |
| lefrSetMacroEndCbk(macroEndCB); |
| lefrSetManufacturingCbk(manufacturingCB); |
| lefrSetMaxStackViaCbk(maxStackViaCB); |
| lefrSetMinFeatureCbk(minFeatureCB); |
| lefrSetNonDefaultCbk(nonDefaultCB); |
| lefrSetObstructionCbk(obstructionCB); |
| lefrSetPinCbk(pinCB); |
| lefrSetPropBeginCbk(propDefBeginCB); |
| lefrSetPropCbk(propDefCB); |
| lefrSetPropEndCbk(propDefEndCB); |
| lefrSetSiteCbk(siteCB); |
| lefrSetSpacingBeginCbk(spacingBeginCB); |
| lefrSetSpacingCbk(spacingCB); |
| lefrSetSpacingEndCbk(spacingEndCB); |
| lefrSetTimingCbk(timingCB); |
| lefrSetUnitsCbk(unitsCB); |
| lefrSetUseMinSpacingCbk(useMinSpacingCB); |
| lefrSetUserData((void*)3); |
| if (!retStr) |
| lefrSetVersionCbk(versionCB); |
| else |
| lefrSetVersionStrCbk(versionStrCB); |
| lefrSetViaCbk(viaCB); |
| lefrSetViaRuleCbk(viaRuleCB); |
| lefrSetInputAntennaCbk(antennaCB); |
| lefrSetOutputAntennaCbk(antennaCB); |
| lefrSetInoutAntennaCbk(antennaCB); |
| |
| if (msgCb) { |
| lefrSetLogFunction(errorCB); |
| lefrSetWarningLogFunction(warningCB); |
| } |
| |
| lefrSetMallocFunction(mallocCB); |
| lefrSetReallocFunction(reallocCB); |
| lefrSetFreeFunction(freeCB); |
| |
| lefrSetLineNumberFunction(lineNumberCB); |
| lefrSetDeltaNumberLines(50); |
| |
| lefrSetRegisterUnusedCallbacks(); |
| |
| if (relax) |
| lefrSetRelaxMode(); |
| |
| if (setVer) |
| (void)lefrSetVersionValue(version); |
| |
| lefrSetAntennaInoutWarnings(30); |
| lefrSetAntennaInputWarnings(30); |
| lefrSetAntennaOutputWarnings(30); |
| lefrSetArrayWarnings(30); |
| lefrSetCaseSensitiveWarnings(30); |
| lefrSetCorrectionTableWarnings(30); |
| lefrSetDielectricWarnings(30); |
| lefrSetEdgeRateThreshold1Warnings(30); |
| lefrSetEdgeRateThreshold2Warnings(30); |
| lefrSetEdgeRateScaleFactorWarnings(30); |
| lefrSetInoutAntennaWarnings(30); |
| lefrSetInputAntennaWarnings(30); |
| lefrSetIRDropWarnings(30); |
| lefrSetLayerWarnings(30); |
| lefrSetMacroWarnings(30); |
| lefrSetMaxStackViaWarnings(30); |
| lefrSetMinFeatureWarnings(30); |
| lefrSetNoiseMarginWarnings(30); |
| lefrSetNoiseTableWarnings(30); |
| lefrSetNonDefaultWarnings(30); |
| lefrSetNoWireExtensionWarnings(30); |
| lefrSetOutputAntennaWarnings(30); |
| lefrSetPinWarnings(30); |
| lefrSetSiteWarnings(30); |
| lefrSetSpacingWarnings(30); |
| lefrSetTimingWarnings(30); |
| lefrSetUnitsWarnings(30); |
| lefrSetUseMinSpacingWarnings(30); |
| lefrSetViaRuleWarnings(30); |
| lefrSetViaWarnings(30); |
| } |
| |
| (void) lefrSetShiftCase(); // will shift name to uppercase if caseinsensitive |
| // is set to off or not set |
| if (!isSessionles) { |
| lefrSetOpenLogFileAppend(); |
| } |
| |
| if (ccr749853) { |
| lefrSetTotalMsgLimit (5); |
| lefrSetLimitPerMsg (1618, 2); |
| } |
| |
| if (ccr1688946) { |
| lefrRegisterLef58Type("XYZ", "CUT"); |
| lefrRegisterLef58Type("XYZ", "CUT"); |
| } |
| |
| if (test1) { // for special tests |
| for (fileCt = 0; fileCt < numInFile; fileCt++) { |
| lefrReset(); |
| |
| if ((f = fopen(inFile[fileCt],"r")) == 0) { |
| fprintf(stderr,"Couldn't open input file '%s'\n", inFile[fileCt]); |
| return(2); |
| } |
| |
| (void)lefrEnableReadEncrypted(); |
| |
| status = lefwInit(fout); // initialize the lef writer, |
| // need to be called 1st |
| if (status != LEFW_OK) |
| return 1; |
| |
| res = lefrRead(f, inFile[fileCt], (void*)userData); |
| |
| if (res) |
| fprintf(stderr, "Reader returns bad status.\n", inFile[fileCt]); |
| |
| (void)lefrPrintUnusedCallbacks(fout); |
| (void)lefrReleaseNResetMemory(); |
| //(void)lefrUnsetCallbacks(); |
| (void)lefrUnsetLayerCbk(); |
| (void)lefrUnsetNonDefaultCbk(); |
| (void)lefrUnsetViaCbk(); |
| |
| } |
| } |
| else if (test2) { // for special tests |
| // this test is design to test the 3 APIs, lefrDisableParserMsgs, |
| // lefrEnableParserMsgs & lefrEnableAllMsgs |
| // It uses the file ccr566209.lef. This file will parser 3 times |
| // 1st it will have lefrDisableParserMsgs set to both 2007 & 2008 |
| // 2nd will enable 2007 by calling lefrEnableParserMsgs |
| // 3rd enable all msgs by call lefrEnableAllMsgs |
| |
| int nMsgs = 3; |
| int dMsgs[3]; |
| if (numInFile != 1) { |
| fprintf(stderr,"Test 2 mode needs only 1 file\n"); |
| return 2; |
| } |
| |
| for (int idx=0; idx<5; idx++) { |
| if (idx == 0) { // msgs 2005 & 2011 |
| fprintf(stderr,"\nPass 0: Disabling 2007, 2008, 2009\n"); |
| dMsgs[0] = 2007; |
| dMsgs[1] = 2008; |
| dMsgs[2] = 2009; |
| lefrDisableParserMsgs (3, (int*)dMsgs); |
| } else if (idx == 1) { // msgs 2007 & 2005, 2011 did not print because |
| fprintf(stderr,"\nPass 1: Enable 2007\n"); |
| dMsgs[0] = 2007; // lefrUnsetLayerCbk() was called |
| lefrEnableParserMsgs (1, (int*)dMsgs); |
| } else if (idx == 2) { // nothing were printed |
| fprintf(stderr,"\nPass 2: Disable all\n"); |
| lefrDisableAllMsgs(); |
| } else if (idx == 3) { // nothing were printed, lefrDisableParserMsgs |
| fprintf(stderr,"\nPass 3: Enable All\n"); |
| lefrEnableAllMsgs(); |
| } else if (idx == 4) { // msgs 2005 was printed |
| fprintf(stderr,"\nPass 4: Set limit on 2007 up 2\n"); |
| lefrSetLimitPerMsg (2007, 2); |
| } |
| |
| if ((f = fopen(inFile[fileCt],"r")) == 0) { |
| fprintf(stderr,"Couldn't open input file '%s'\n", inFile[fileCt]); |
| return(2); |
| } |
| |
| (void)lefrEnableReadEncrypted(); |
| |
| status = lefwInit(fout); // initialize the lef writer, |
| // need to be called 1st |
| if (status != LEFW_OK) |
| return 1; |
| |
| res = lefrRead(f, inFile[fileCt], (void*)userData); |
| |
| if (res) |
| fprintf(stderr, "Reader returns bad status.\n", inFile[fileCt]); |
| |
| (void)lefrPrintUnusedCallbacks(fout); |
| (void)lefrReleaseNResetMemory(); |
| //(void)lefrUnsetCallbacks(); |
| (void)lefrUnsetLayerCbk(); |
| (void)lefrUnsetNonDefaultCbk(); |
| (void)lefrUnsetViaCbk(); |
| |
| } |
| } else { |
| for (fileCt = 0; fileCt < numInFile; fileCt++) { |
| lefrReset(); |
| |
| if ((f = fopen(inFile[fileCt],"r")) == 0) { |
| fprintf(stderr,"Couldn't open input file '%s'\n", inFile[fileCt]); |
| return(2); |
| } |
| |
| (void)lefrEnableReadEncrypted(); |
| |
| status = lefwInit(fout); // initialize the lef writer, |
| // need to be called 1st |
| if (status != LEFW_OK) |
| return 1; |
| |
| if (ccr1709089) { |
| // CCR 1709089 test. |
| // Non-initialized lefData case. |
| lefrSetLimitPerMsg(10000, 10000); |
| } |
| |
| res = lefrRead(f, inFile[fileCt], (void*)userData); |
| |
| if (ccr1709089) { |
| // CCR 1709089 test. |
| // Initialized lefData case. |
| lefrSetLimitPerMsg(10000, 10000); |
| } |
| |
| if (res) |
| fprintf(stderr, "Reader returns bad status.\n", inFile[fileCt]); |
| |
| (void)lefrPrintUnusedCallbacks(fout); |
| (void)lefrReleaseNResetMemory(); |
| |
| } |
| (void)lefrUnsetCallbacks(); |
| } |
| // Unset all the callbacks |
| void lefrUnsetAntennaInputCbk(); |
| void lefrUnsetAntennaInoutCbk(); |
| void lefrUnsetAntennaOutputCbk(); |
| void lefrUnsetArrayBeginCbk(); |
| void lefrUnsetArrayCbk(); |
| void lefrUnsetArrayEndCbk(); |
| void lefrUnsetBusBitCharsCbk(); |
| void lefrUnsetCaseSensitiveCbk(); |
| void lefrUnsetFixedMaskCbk(); |
| void lefrUnsetClearanceMeasureCbk(); |
| void lefrUnsetCorrectionTableCbk(); |
| void lefrUnsetDensityCbk(); |
| void lefrUnsetDielectricCbk(); |
| void lefrUnsetDividerCharCbk(); |
| void lefrUnsetEdgeRateScaleFactorCbk(); |
| void lefrUnsetEdgeRateThreshold1Cbk(); |
| void lefrUnsetEdgeRateThreshold2Cbk(); |
| void lefrUnsetExtensionCbk(); |
| void lefrUnsetInoutAntennaCbk(); |
| void lefrUnsetInputAntennaCbk(); |
| void lefrUnsetIRDropBeginCbk(); |
| void lefrUnsetIRDropCbk(); |
| void lefrUnsetIRDropEndCbk(); |
| void lefrUnsetLayerCbk(); |
| void lefrUnsetLibraryEndCbk(); |
| void lefrUnsetMacroBeginCbk(); |
| void lefrUnsetMacroCbk(); |
| void lefrUnsetMacroClassTypeCbk(); |
| void lefrUnsetMacroEndCbk(); |
| void lefrUnsetMacroOriginCbk(); |
| void lefrUnsetMacroSizeCbk(); |
| void lefrUnsetManufacturingCbk(); |
| void lefrUnsetMaxStackViaCbk(); |
| void lefrUnsetMinFeatureCbk(); |
| void lefrUnsetNoiseMarginCbk(); |
| void lefrUnsetNoiseTableCbk(); |
| void lefrUnsetNonDefaultCbk(); |
| void lefrUnsetNoWireExtensionCbk(); |
| void lefrUnsetObstructionCbk(); |
| void lefrUnsetOutputAntennaCbk(); |
| void lefrUnsetPinCbk(); |
| void lefrUnsetPropBeginCbk(); |
| void lefrUnsetPropCbk(); |
| void lefrUnsetPropEndCbk(); |
| void lefrUnsetSiteCbk(); |
| void lefrUnsetSpacingBeginCbk(); |
| void lefrUnsetSpacingCbk(); |
| void lefrUnsetSpacingEndCbk(); |
| void lefrUnsetTimingCbk(); |
| void lefrUnsetUseMinSpacingCbk(); |
| void lefrUnsetUnitsCbk(); |
| void lefrUnsetVersionCbk(); |
| void lefrUnsetVersionStrCbk(); |
| void lefrUnsetViaCbk(); |
| void lefrUnsetViaRuleCbk(); |
| |
| fclose(fout); |
| |
| // Release allocated singleton data. |
| lefrClear(); |
| |
| return 0; |
| } |