| // ***************************************************************************** |
| // ***************************************************************************** |
| // Copyright 2014 - 2015, 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: $ |
| // ***************************************************************************** |
| // ***************************************************************************** |
| |
| // This program is the diffDef core program. It has all the callback |
| // routines and write it out to a temporary file. |
| |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <ctype.h> |
| #ifndef WIN32 |
| # include <unistd.h> |
| #endif /* not WIN32 */ |
| #include "defrReader.hpp" |
| |
| |
| char defaultName[64]; |
| char defaultOut[64]; |
| static int ignorePE = 0; |
| static int ignoreRN = 0; |
| static int ignoreVN = 0; |
| static int netSeCmp = 0; |
| |
| // Global variables |
| FILE* fout; |
| void *userData; |
| int numObjs; |
| int isSumSet; // to keep track if within SUM |
| int isProp = 0; // for PROPDEF |
| int begOperand; // to keep track for constraint, to print - as the 1st char |
| static double curVer = 5.7; |
| |
| // TX_DIR:TRANSLATION ON |
| |
| void dataError() { |
| fprintf(fout, "ERROR: returned user data is not correct!\n"); |
| } |
| |
| |
| void checkType(defrCallbackType_e c) { |
| if (c >= 0 && c <= defrDesignEndCbkType) { |
| // OK |
| } else { |
| fprintf(fout, "ERROR: callback type is out of bounds!\n"); |
| } |
| } |
| |
| // 05/24/2001 - Wanda da Rosa. PCR 373170 |
| // This function is added due to the rounding between machines are |
| // different. For a 5, solaries will round down while hppa will roundup. |
| // This function will make sure it round up for all the machine |
| double checkDouble(double num) { |
| long tempNum; |
| if ((num > 1000004) || (num < -1000004)) { |
| tempNum = (long)num; |
| if ((tempNum%5) == 0) |
| return num + 3; |
| } |
| return num; |
| } |
| |
| int compMSL(defrCallbackType_e c, defiComponentMaskShiftLayer* co, defiUserData ud) { |
| int i; |
| |
| checkType(c); |
| if (ud != userData) dataError(); |
| |
| if (co->numMaskShiftLayers()) { |
| fprintf(fout, "\nCOMPONENTMASKSHIFT "); |
| |
| for (i = 0; i < co->numMaskShiftLayers(); i++) { |
| fprintf(fout, "%s ", co->maskShiftLayer(i)); |
| } |
| fprintf(fout, ";\n"); |
| } |
| |
| return 0; |
| } |
| |
| |
| // Component |
| int compf(defrCallbackType_e c, defiComponent* co, defiUserData ud) { |
| int i; |
| |
| checkType(c); |
| if (ud != userData) dataError(); |
| // missing GENERATE, FOREIGN |
| fprintf(fout, "COMP %s %s", co->id(), co->name()); |
| if (co->hasNets()) { |
| for (i = 0; i < co->numNets(); i++) |
| fprintf(fout, " %s", co->net(i)); |
| fprintf(fout,"\n"); |
| } else |
| fprintf(fout,"\n"); |
| if (co->isFixed()) |
| fprintf(fout, "COMP %s FIXED ( %d %d ) %s\n", co->id(), |
| co->placementX(), co->placementY(), co->placementOrientStr()); |
| if (co->isCover()) |
| fprintf(fout, "COMP %s COVER ( %d %d ) %s\n", co->id(), |
| co->placementX(), co->placementY(), co->placementOrientStr()); |
| if (co->isPlaced()) |
| fprintf(fout,"COMP %s PLACED ( %d %d ) %s\n", co->id(), |
| co->placementX(), co->placementY(), co->placementOrientStr()); |
| if (co->isUnplaced()) |
| fprintf(fout,"COMP %s UNPLACED\n", co->id()); |
| if (co->hasSource()) |
| fprintf(fout, "COMP %s SOURCE %s\n", co->id(), co->source()); |
| if (co->hasGenerate()) |
| fprintf(fout, "COMP %s GENERATE %s %s\n", co->id(), |
| co->generateName(), co->macroName()); |
| if (co->hasHalo()) { |
| int left, bottom, right, top; |
| (void) co->haloEdges(&left, &bottom, &right, &top); |
| fprintf(fout, "COMP %s HALO", co->id()); |
| if (co->hasHaloSoft()) |
| fprintf(fout, " SOFT"); |
| fprintf(fout, " %d %d %d %d\n", left, bottom, right, top); |
| |
| } |
| if (co->hasRouteHalo()) { |
| fprintf(fout, "COMP %s ROUTEHALO %d %s %s\n", co->id(), |
| co->haloDist(), co->minLayer(), co->maxLayer()); |
| } |
| if (co->hasForeignName()) |
| fprintf(fout, "COMP %s FOREIGN %s %d %d %s\n", co->id(), |
| co->foreignName(), co->foreignX(), co->foreignY(), |
| co->foreignOri()); |
| if (co->hasWeight()) |
| fprintf(fout, "COMP %s WEIGHT %d\n", co->id(), co->weight()); |
| if (co->hasEEQ()) |
| fprintf(fout, "COMP %s EEQMASTER %s\n", co->id(), co->EEQ()); |
| if (co->hasRegionName()) |
| fprintf(fout, "COMP %s REGION %s\n", co->id(), co->regionName()); |
| if (co->hasRegionBounds()) { |
| int *xl, *yl, *xh, *yh; |
| int size; |
| co->regionBounds(&size, &xl, &yl, &xh, &yh); |
| for (i = 0; i < size; i++) { |
| fprintf(fout, "COMP %s REGION ( %d %d ) ( %d %d )\n", co->id(), |
| xl[i], yl[i], xh[i], yh[i]); |
| } |
| } |
| if (co->maskShiftSize()) { |
| fprintf(fout, "MASKSHIFT "); |
| |
| for (int i = co->maskShiftSize()-1; i >= 0; i--) { |
| fprintf(fout, "%d", co->maskShift(i)); |
| } |
| fprintf(fout, "\n"); |
| } |
| if (co->numProps()) { |
| for (i = 0; i < co->numProps(); i++) { |
| fprintf(fout, "COMP %s PROP %s %s ", co->id(), |
| co->propName(i), |
| co->propValue(i)); |
| switch (co->propType(i)) { |
| case 'R': fprintf(fout, "REAL "); |
| break; |
| case 'I': fprintf(fout, "INT "); |
| break; |
| case 'S': fprintf(fout, "STR "); |
| break; |
| case 'Q': fprintf(fout, "QSTR "); |
| break; |
| case 'N': fprintf(fout, "NUM "); |
| break; |
| } |
| fprintf(fout, "\n"); |
| } |
| } |
| |
| --numObjs; |
| return 0; |
| } |
| |
| // Net |
| int netf(defrCallbackType_e c, defiNet* net, defiUserData ud) { |
| // For net and special net. |
| int i, j, k, w, x, y, z, px, py, pz; |
| defiPath* p; |
| defiSubnet* s; |
| int path; |
| defiVpin *vpin; |
| defiShield* noShield; |
| defiWire* wire; |
| int nline; |
| const char* layerName = "N/A"; |
| |
| checkType(c); |
| if (ud != userData) dataError(); |
| if (c != defrNetCbkType) |
| fprintf(fout, "BOGUS NET TYPE "); |
| if (net->pinIsMustJoin(0)) |
| fprintf(fout, "NET MUSTJOIN "); |
| else |
| fprintf(fout, "NET %s ", net->name()); |
| |
| // compName & pinName |
| for (i = 0; i < net->numConnections(); i++) { |
| fprintf(fout, "\nNET %s ( %s %s ) ", net->name(), net->instance(i), |
| net->pin(i)); |
| } |
| |
| if (net->hasNonDefaultRule()) |
| fprintf(fout, "\nNET %s NONDEFAULTRULE %s", net->name(), |
| net->nonDefaultRule()); |
| |
| for (i = 0; i < net->numVpins(); i++) { |
| vpin = net->vpin(i); |
| fprintf(fout, "\nNET %s %s", net->name(), vpin->name()); |
| if (vpin->layer()) |
| fprintf(fout, " %s", vpin->layer()); |
| fprintf(fout, " %d %d %d %d", vpin->xl(), vpin->yl(), vpin->xh(), |
| vpin->yh()); |
| if (vpin->status() != ' ') { |
| switch (vpin->status()) { |
| case 'P': |
| case 'p': |
| fprintf(fout, " PLACED"); |
| break; |
| case 'F': |
| case 'f': |
| fprintf(fout, " FIXED"); |
| break; |
| case 'C': |
| case 'c': |
| fprintf(fout, " COVER"); |
| break; |
| } |
| fprintf(fout, " %d %d", vpin->xLoc(), vpin->yLoc()); |
| if (vpin->orient() != -1) |
| fprintf(fout, " %s", vpin->orientStr()); |
| } |
| } |
| |
| // regularWiring |
| if (net->numWires()) { |
| for (i = 0; i < net->numWires(); i++) { |
| wire = net->wire(i); |
| for (j = 0; j < wire->numPaths(); j++) { |
| p = wire->path(j); |
| p->initTraverse(); |
| fprintf(fout, "\nNET %s %s", net->name(), wire->wireType()); |
| nline = 0; |
| while ((path = (int)p->next()) != DEFIPATH_DONE) { |
| switch (path) { |
| case DEFIPATH_LAYER: |
| if (!netSeCmp) |
| fprintf(fout, " %s", p->getLayer()); |
| layerName = p->getLayer(); |
| px = py = pz = -99; // reset the 1 set of point to 0 |
| break; |
| case DEFIPATH_MASK: |
| fprintf(fout, "MASK %d ", p->getMask()); |
| break; |
| case DEFIPATH_VIAMASK: |
| fprintf(fout, "MASK %d%d%d ", |
| p->getViaTopMask(), |
| p->getViaCutMask(), |
| p->getViaBottomMask()); |
| break; |
| case DEFIPATH_VIA: |
| if (!netSeCmp) { |
| if (!ignoreVN) |
| fprintf(fout, " %s", p->getVia()); |
| } else { |
| if (nline) { |
| if (!ignoreVN) |
| fprintf(fout, "\nNET %s %s ( %d %d ) %s", net->name(), |
| wire->wireType(), px, py, p->getVia()); |
| else |
| fprintf(fout, "\nNET %s %s ( %d %d )", net->name(), |
| wire->wireType(), px, py); |
| } else { |
| if (!ignoreVN) |
| fprintf(fout, " ( %d %d ) %s", px, py, p->getVia()); |
| else |
| fprintf(fout, " ( %d %d )", px, py); |
| } |
| px = py = pz = -99; // reset the 1 set of point to 0 |
| } |
| nline = 1; |
| break; |
| case DEFIPATH_RECT: |
| p->getViaRect(&w, &x, &y, &z); |
| fprintf(fout, "RECT ( %d %d %d %d ) ", w, x, y, z); |
| break; |
| case DEFIPATH_VIRTUALPOINT: |
| p->getVirtualPoint(&x, &y); |
| fprintf(fout, "VIRTUAL ( %d %d ) ", x, y); |
| break; |
| case DEFIPATH_VIAROTATION: |
| fprintf(fout, "%d ",p->getViaRotation()); |
| nline = 1; |
| break; |
| case DEFIPATH_WIDTH: |
| fprintf(fout, " %d ", p->getWidth()); |
| break; |
| case DEFIPATH_POINT: |
| p->getPoint(&x, &y); |
| if (!netSeCmp) { |
| if (!nline) { |
| fprintf(fout, " ( %d %d )", x, y); |
| nline = 1; |
| } else { |
| fprintf(fout, "\nNET %s %s %s ( %d %d )", net->name(), |
| wire->wireType(), layerName, x, y); |
| } |
| } else { |
| if ((px == -99) && (py == -99)) { |
| px = x; |
| py = y; |
| } else { |
| if (nline) |
| fprintf(fout, "\nNET %s %s %s", net->name(), |
| wire->wireType(), layerName); |
| if (px < x) { |
| fprintf (fout, " ( %d %d ) ( %d %d )", px, py, x, y); |
| } else if (px == x) { |
| if (py < y) |
| fprintf (fout, " ( %d %d ) ( %d %d )", |
| px, py, x, y); |
| else |
| fprintf (fout, " ( %d %d ) ( %d %d )", |
| x, y, px, py); |
| } else { // px > x |
| fprintf (fout, " ( %d %d ) ( %d %d )", x, y, px, py); |
| } |
| px = x; |
| py = y; |
| nline = 1; |
| } |
| } |
| break; |
| case DEFIPATH_FLUSHPOINT: |
| p->getFlushPoint(&x, &y, &z); |
| if (!netSeCmp) { |
| if (!nline) { |
| fprintf(fout, " ( %d %d %d )", x, y, z); |
| } else { |
| fprintf(fout, "\nNET %s %s %s ( %d %d %d )", net->name(), |
| wire->wireType(), layerName, x, y, z); |
| } |
| } else { |
| if ((px == -99) && (py == -99) && (pz == -99)) { |
| px = x; |
| py = y; |
| pz = z; |
| } else { |
| if (nline) |
| fprintf(fout, "\nNET %s %s %s", net->name(), |
| wire->wireType(), layerName); |
| if (px < x) { |
| if (pz != -99) |
| fprintf (fout, " ( %d %d %d ) ( %d %d %d )", |
| px, py, pz, x, y, z); |
| else |
| fprintf (fout, " ( %d %d ) ( %d %d %d )", |
| px, py, x, y, z); |
| } else if (px == x) { |
| if (py < y) { |
| if (pz != -99) |
| fprintf (fout, " ( %d %d %d ) ( %d %d %d )", |
| px, py, pz, x, y, z); |
| else |
| fprintf (fout, " ( %d %d ) ( %d %d %d )", |
| px, py, x, y, z); |
| } else { |
| if (pz != -99) |
| fprintf (fout, " ( %d %d %d ) ( %d %d %d )", |
| x, y, z, px, py, pz); |
| else |
| fprintf (fout, " ( %d %d %d ) ( %d %d )", |
| x, y, z, px, py); |
| } |
| } else { // px > x |
| if (pz != -99) |
| fprintf (fout, " ( %d %d %d ) ( %d %d %d )", |
| x, y, z, px, py, pz); |
| else |
| fprintf (fout, " ( %d %d %d ) ( %d %d )", |
| x, y, z, px, py); |
| } |
| px = x; |
| py = y; |
| pz = z; |
| nline = 1; |
| } |
| } |
| break; |
| case DEFIPATH_TAPER: |
| fprintf(fout, " TAPER"); |
| break; |
| case DEFIPATH_TAPERRULE: |
| fprintf(fout, " TAPERRULE %s",p->getTaperRule()); |
| break; |
| } |
| } |
| } |
| } |
| } |
| |
| // shieldnet |
| if (net->numShieldNets()) { |
| for (i = 0; i < net->numShieldNets(); i++) |
| fprintf(fout, "\nNET %s SHIELDNET %s ", net->name(), |
| net->shieldNet(i)); |
| } |
| if (net->numNoShields()) { |
| for (i = 0; i < net->numNoShields(); i++) { |
| noShield = net->noShield(i); |
| for (j = 0; j < noShield->numPaths(); j++) { |
| p = noShield->path(j); |
| p->initTraverse(); |
| fprintf(fout, "\nNET %s NOSHIELD", net->name()); |
| nline = 0; |
| while ((path = (int)p->next()) != DEFIPATH_DONE) { |
| switch (path) { |
| case DEFIPATH_LAYER: |
| fprintf(fout, " %s", p->getLayer()); |
| layerName = p->getLayer(); |
| break; |
| case DEFIPATH_MASK: |
| fprintf(fout, "MASK %d ", p->getMask()); |
| break; |
| case DEFIPATH_VIAMASK: |
| fprintf(fout, "MASK %d%d%d ", |
| p->getViaTopMask(), |
| p->getViaCutMask(), |
| p->getViaBottomMask()); |
| break; |
| case DEFIPATH_VIA: |
| if (!ignoreVN) |
| fprintf(fout, " %s", p->getVia()); |
| nline = 1; |
| break; |
| case DEFIPATH_VIAROTATION: |
| fprintf(fout, " %d", p->getViaRotation()); |
| nline = 1; |
| break; |
| case DEFIPATH_WIDTH: |
| fprintf(fout, " %d", p->getWidth()); |
| break; |
| case DEFIPATH_POINT: |
| p->getPoint(&x, &y); |
| if (!nline) { |
| fprintf(fout, " ( %d %d )", x, y); |
| nline = 1; |
| } else { |
| fprintf(fout, "\nNET %s %s ( %d %d )", |
| net->name(), layerName, x, y); |
| nline = 1; |
| } |
| break; |
| case DEFIPATH_FLUSHPOINT: |
| p->getFlushPoint(&x, &y, &z); |
| if (!nline) { |
| fprintf(fout, " ( %d %d )", x, y); |
| nline = 1; |
| } else { |
| fprintf(fout, "\nNET %s %s ( %d %d )", |
| net->name(), layerName, x, y); |
| nline = 1; |
| } |
| case DEFIPATH_TAPER: |
| fprintf(fout, " TAPER"); |
| break; |
| case DEFIPATH_TAPERRULE: |
| fprintf(fout, " TAPERRULE %s", |
| p->getTaperRule()); |
| break; |
| } |
| } |
| } |
| } |
| } |
| |
| if (net->hasSubnets()) { |
| for (i = 0; i < net->numSubnets(); i++) { |
| s = net->subnet(i); |
| |
| if (s->numConnections()) { |
| for (j = 0; j < s->numConnections(); j++) { |
| if (s->pinIsMustJoin(0)) |
| fprintf(fout, "\nNET MUSTJOIN"); |
| else |
| fprintf(fout, "\nNET %s", s->name()); |
| fprintf(fout, " ( %s %s )", s->instance(j), s->pin(j)); |
| } |
| } |
| |
| for (j = 0; j < s->numWires(); j++) { |
| wire = s->wire(j); |
| if (s->numPaths()) { |
| for (k = 0; k < wire->numPaths(); k++) { |
| int elem; |
| p = wire->path(k); |
| p->initTraverse(); |
| fprintf(fout, "\nNET %s %s", s->name(), wire->wireType()); |
| nline = 0; |
| elem = p->next(); |
| while (elem) { |
| switch (elem) { |
| case DEFIPATH_LAYER: |
| fprintf(fout, " LAYER %s", p->getLayer()); |
| layerName = p->getLayer(); |
| break; |
| case DEFIPATH_MASK: |
| fprintf(fout, "MASK %d ", p->getMask()); |
| break; |
| case DEFIPATH_VIAMASK: |
| fprintf(fout, "MASK %d%d%d ", |
| p->getViaTopMask(), |
| p->getViaCutMask(), |
| p->getViaBottomMask()); |
| break; |
| case DEFIPATH_VIA: |
| if (!ignoreVN) |
| fprintf(fout, " VIA %s", p->getVia()); |
| nline = 1; |
| break; |
| case DEFIPATH_VIAROTATION: |
| fprintf(fout, " VIAROTATION %d", p->getViaRotation()); |
| nline = 1; |
| break; |
| case DEFIPATH_WIDTH: |
| fprintf(fout, " WIDTH %d", p->getWidth()); |
| break; |
| case DEFIPATH_POINT: |
| p->getPoint(&x, &y); |
| if (!nline) { |
| fprintf(fout, " POINT %d %d", x, y); |
| nline = 1; |
| } else { |
| fprintf(fout, "\nNET %s %s %s POINT %d %d", |
| s->name(), wire->wireType(), layerName, x, y); |
| nline = 1; |
| } |
| break; |
| //case DEFIPATH_FLUSHPOINT: |
| //l = 0; |
| //p->getFlushPoint(i1, i2, ext); |
| //while (i1[l] && i2[l] && ext[l]) { |
| //fprintf(fout, "NET %s FLUSHPOINT %d %d %d\n", |
| //s->name(), i1[l], i2[l], ext[l]); |
| //l++; |
| //} |
| //break; |
| case DEFIPATH_TAPERRULE: |
| fprintf(fout, " TAPERRULE %s", p->getTaperRule()); |
| break; |
| case DEFIPATH_SHAPE: |
| fprintf(fout, " SHAPE %s", p->getShape()); |
| break; |
| case DEFIPATH_STYLE: |
| fprintf(fout, " STYLE %d", p->getStyle()); |
| break; |
| } |
| elem = p->next(); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| /* Put the following all in one line */ |
| if (net->hasWeight() || net->hasCap() || net->hasSource() || |
| net->hasPattern() || net->hasOriginal() || net->hasUse()) { |
| fprintf(fout, "\nNET %s ", net->name()); |
| |
| if (net->hasWeight()) |
| fprintf(fout, "WEIGHT %d ", net->weight()); |
| if (net->hasCap()) |
| fprintf(fout, "ESTCAP %g ", checkDouble(net->cap())); |
| if (net->hasSource()) |
| fprintf(fout, "SOURCE %s ", net->source()); |
| if (net->hasFixedbump()) |
| fprintf(fout, "FIXEDBUMP "); |
| if (net->hasFrequency()) |
| fprintf(fout, "FREQUENCY %g ", net->frequency()); |
| if (net->hasPattern()) |
| fprintf(fout, "PATTERN %s ", net->pattern()); |
| if (net->hasOriginal()) |
| fprintf(fout, "ORIGINAL %s ", net->original()); |
| if (net->hasUse()) |
| fprintf(fout, "USE %s ", net->use()); |
| } |
| |
| fprintf (fout, "\n"); |
| --numObjs; |
| return 0; |
| } |
| |
| |
| // Special Net |
| int snetf(defrCallbackType_e c, defiNet* net, defiUserData ud) { |
| // For net and special net. |
| int i, j, x, y, z; |
| char *layerName; |
| double dist, left, right; |
| defiPath *p; |
| defiSubnet *s; |
| int path; |
| defiShield* shield; |
| defiWire *wire; |
| int nline; |
| const char* sNLayerName = "N/A"; |
| int numX, numY, stepX, stepY; |
| |
| checkType(c); |
| if (ud != userData) dataError(); |
| if (c != defrSNetCbkType) |
| fprintf(fout, "BOGUS NET TYPE "); |
| |
| // compName & pinName |
| if (net->numConnections() > 0) { |
| for (i = 0; i < net->numConnections(); i++) |
| fprintf (fout, "SNET %s ( %s %s )\n", net->name(), net->instance(i), |
| net->pin(i)); |
| } |
| |
| if (net->numRectangles()) { // 5.6 |
| |
| for (i = 0; i < net->numRectangles(); i++) { |
| if (curVer >= 5.8 ) { |
| fprintf (fout, "\nSNET %s ", net->name()); |
| if (strcmp(net->rectRouteStatus(i), "") != 0) { |
| fprintf(fout, "%s ", net->rectRouteStatus(i)); |
| if (strcmp(net->rectRouteStatus(i), "SHIELD") == 0) { |
| fprintf(fout, "%s ", net->rectRouteStatusShieldName(i)); |
| } |
| } |
| if (strcmp(net->rectShapeType(i), "") != 0) { |
| fprintf(fout, "SHAPE %s ", net->rectShapeType(i)); |
| } |
| } |
| if (net->rectMask(i)) { |
| fprintf(fout, "MASK %d RECT %s %d %d %d %d", |
| net->rectMask(i), net->rectName(i), |
| net->xl(i), net->yl(i), net->xh(i), |
| net->yh(i)); |
| } else { |
| fprintf(fout, "RECT %s %d %d %d %d", net->name(), |
| net->xl(i), net->yl(i), net->xh(i), |
| net->yh(i)); |
| } |
| } |
| } |
| |
| if (net->numPolygons()) { |
| struct defiPoints points; |
| |
| for (i = 0; i < net->numPolygons(); i++) { |
| fprintf (fout, "\nSNET %s ", net->name()); |
| if (curVer >= 5.8 ) { |
| if (strcmp(net->polyRouteStatus(i), "") != 0) { |
| fprintf(fout, "%s ", net->polyRouteStatus(i)); |
| if (strcmp(net->polyRouteStatus(i), "SHIELD") == 0) { |
| fprintf(fout, "%s ", net->polyRouteStatusShieldName(i)); |
| } |
| } |
| if (strcmp(net->polyShapeType(i), "") != 0) { |
| fprintf(fout, "SHAPE %s ", net->polyShapeType(i)); |
| } |
| } |
| if (net->polyMask(i)) { |
| fprintf(fout, "MASK %d POLYGON % s ", |
| net->polyMask(i), |
| net->polygonName(i)); |
| } else { |
| fprintf(fout, "POLYGON %s", net->polygonName(i)); |
| } |
| |
| points = net->getPolygon(i); |
| for (j = 0; j < points.numPoints; j++) |
| fprintf(fout, " %d %d", points.x[j], points.y[j]); |
| } |
| } |
| |
| if (curVer >= 5.8 && net->numViaSpecs()) { |
| for (i = 0; i < net->numViaSpecs(); i++) { |
| fprintf (fout, "\nSNET %s ", net->name()); |
| if (strcmp(net->viaRouteStatus(i), "") != 0) { |
| fprintf(fout, "%s ", net->viaRouteStatus(i)); |
| if (strcmp(net->viaRouteStatus(i), "SHIELD") == 0) { |
| fprintf(fout, "%s ", net->viaRouteStatusShieldName(i)); |
| } |
| } |
| if (strcmp(net->viaShapeType(i), "") != 0) { |
| fprintf(fout, "SHAPE %s ", net->viaShapeType(i)); |
| } |
| if (net->topMaskNum(i) || net->cutMaskNum(i) || net->bottomMaskNum(i)) { |
| fprintf(fout, "MASK %d%d%d VIA %s ", net->topMaskNum(i), |
| net->cutMaskNum(i), |
| net->bottomMaskNum(i), |
| net->viaName(i)); |
| } else { |
| fprintf(fout, "\n VIA %s ", net->viaName(i)); |
| } |
| fprintf(fout, " %s", net->viaOrientStr(i)); |
| |
| defiPoints points = net->getViaPts(i); |
| |
| for (int j = 0; j < points.numPoints; j++) { |
| fprintf(fout, " %d %d", points.x[j], points.y[j]); |
| } |
| fprintf(fout, ";\n"); |
| } |
| } |
| |
| |
| // specialWiring |
| if (net->numWires()) { |
| for (i = 0; i < net->numWires(); i++) { |
| wire = net->wire(i); |
| for (j = 0; j < wire->numPaths(); j++) { |
| p = wire->path(j); |
| fprintf(fout, "\nSNET %s %s", net->name(), wire->wireType()); |
| nline = 0; |
| p->initTraverse(); |
| while ((path = (int)p->next()) != DEFIPATH_DONE) { |
| switch (path) { |
| case DEFIPATH_LAYER: |
| fprintf(fout, " %s", p->getLayer()); |
| sNLayerName = p->getLayer(); |
| break; |
| case DEFIPATH_MASK: |
| fprintf(fout, "MASK %d ", p->getMask()); |
| break; |
| case DEFIPATH_VIAMASK: |
| fprintf(fout, "MASK %d%d%d ", |
| p->getViaTopMask(), |
| p->getViaCutMask(), |
| p->getViaBottomMask()); |
| break; |
| case DEFIPATH_VIA: |
| if (!ignoreVN) |
| fprintf(fout, " %s", p->getVia()); |
| nline = 1; |
| break; |
| case DEFIPATH_VIAROTATION: |
| fprintf(fout, " %d", p->getViaRotation()); |
| nline = 1; |
| break; |
| case DEFIPATH_VIADATA: |
| p->getViaData(&numX, &numY, &stepX, &stepY); |
| fprintf(fout, " DO %d BY %d STEP %d %d", numX, numY, |
| stepX, stepY); |
| nline = 1; |
| break; |
| case DEFIPATH_WIDTH: |
| fprintf(fout, " %d", p->getWidth()); |
| break; |
| case DEFIPATH_POINT: |
| p->getPoint(&x, &y); |
| if (!nline) { |
| fprintf(fout, " ( %d %d ) ", x, y); |
| nline = 1; |
| } else { |
| fprintf(fout, "\nSNET %s %s %s ( %d %d )", net->name(), |
| wire->wireType(), sNLayerName, x, y); |
| nline = 1; |
| } |
| break; |
| case DEFIPATH_FLUSHPOINT: |
| p->getFlushPoint(&x, &y, &z); |
| fprintf(fout, "( %d %d %d ) ", x, y, z); |
| nline = 1; |
| break; |
| case DEFIPATH_TAPER: |
| fprintf(fout, " TAPER"); |
| break; |
| case DEFIPATH_SHAPE: |
| fprintf(fout, " + SHAPE %s", p->getShape()); |
| break; |
| case DEFIPATH_STYLE: |
| fprintf(fout, " + STYLE %d", p->getStyle()); |
| break; |
| } |
| } |
| } |
| } |
| } |
| |
| if (net->hasSubnets()) { |
| for (i = 0; i < net->numSubnets(); i++) { |
| s = net->subnet(i); |
| if (s->numConnections()) { |
| if (s->pinIsMustJoin(0)) |
| fprintf(fout, "\nSNET %s MUSTJOIN", net->name()); |
| else |
| fprintf(fout, "\nSNET %s", net->name()); |
| for (j = 0; j < s->numConnections(); j++) { |
| fprintf(fout, "( %s %s ) ", s->instance(j), s->pin(j)); |
| } |
| } |
| |
| // regularWiring |
| if (s->numWires()) { |
| for (i = 0; i < s->numWires(); i++) { |
| wire = s->wire(i); |
| for (j = 0; j < wire->numPaths(); j++) { |
| p = wire->path(j); |
| p->initTraverse(); |
| fprintf(fout, "\nSNET %s %s", net->name(), wire->wireType()); |
| nline = 0; |
| while ((path = (int)p->next()) != DEFIPATH_DONE) { |
| switch (path) { |
| case DEFIPATH_LAYER: |
| fprintf(fout, " %s", p->getLayer()); |
| sNLayerName = p->getLayer(); |
| break; |
| case DEFIPATH_VIA: |
| if (!ignoreVN) |
| fprintf(fout, " %s", p->getVia()); |
| break; |
| case DEFIPATH_MASK: |
| fprintf(fout, "MASK %d ", p->getMask()); |
| break; |
| case DEFIPATH_VIAMASK: |
| fprintf(fout, "MASK %d%d%d ", |
| p->getViaTopMask(), |
| p->getViaCutMask(), |
| p->getViaBottomMask()); |
| break; |
| |
| case DEFIPATH_VIAROTATION: |
| fprintf(fout, " %d", p->getViaRotation()); |
| break; |
| case DEFIPATH_WIDTH: |
| fprintf(fout, " %d", p->getWidth()); |
| break; |
| case DEFIPATH_POINT: |
| p->getPoint(&x, &y); |
| if (!nline) { |
| fprintf(fout, "( %d %d ) ", x, y); |
| nline = 1; |
| } else { |
| fprintf(fout, "\nSNET %s %s %s ( %d %d ) ", |
| net->name(), wire->wireType(), sNLayerName, |
| x, y); |
| nline = 1; |
| } |
| break; |
| case DEFIPATH_TAPER: |
| fprintf(fout, " TAPER"); |
| break; |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| if (net->numProps()) { |
| for (i = 0; i < net->numProps(); i++) { |
| fprintf(fout, "\nSNET %s PROP %s %s ", net->name(), |
| net->propName(i), net->propValue(i)); |
| switch (net->propType(i)) { |
| case 'R': fprintf(fout, "REAL "); |
| break; |
| case 'I': fprintf(fout, "INT "); |
| break; |
| case 'S': fprintf(fout, "STR "); |
| break; |
| case 'Q': fprintf(fout, "QSTR "); |
| break; |
| case 'N': fprintf(fout, "NUM "); |
| break; |
| } |
| } |
| } |
| |
| // SHIELD |
| // testing the SHIELD for 5.3 |
| if (net->numShields()) { |
| for (i = 0; i < net->numShields(); i++) { |
| shield = net->shield(i); |
| for (j = 0; j < shield->numPaths(); j++) { |
| p = shield->path(j); |
| fprintf(fout, "\nSNET %s SHIELD %s", net->name(), |
| shield->shieldName()); |
| p->initTraverse(); |
| while ((path = (int)p->next()) != DEFIPATH_DONE) { |
| switch (path) { |
| case DEFIPATH_LAYER: |
| fprintf(fout, " %s", p->getLayer()); |
| sNLayerName = p->getLayer(); |
| break; |
| case DEFIPATH_VIA: |
| if (!ignoreVN) |
| fprintf(fout, " %s", p->getVia()); |
| break; |
| case DEFIPATH_MASK: |
| fprintf(fout, "MASK %d ", p->getMask()); |
| break; |
| case DEFIPATH_VIAMASK: |
| fprintf(fout, "MASK %d%d%d ", |
| p->getViaTopMask(), |
| p->getViaCutMask(), |
| p->getViaBottomMask()); |
| break; |
| case DEFIPATH_VIAROTATION: |
| fprintf(fout, " %d", p->getViaRotation()); |
| break; |
| case DEFIPATH_WIDTH: |
| fprintf(fout, " %d", p->getWidth()); |
| break; |
| case DEFIPATH_POINT: |
| p->getPoint(&x, &y); |
| if (!nline) { |
| fprintf(fout, "( %d %d ) ", x, y); |
| nline = 1; |
| } else { |
| fprintf(fout, "\nSNET %s SHIELD %s %s ( %d %d )", |
| net->name(), shield->shieldName(), sNLayerName, |
| x, y); |
| } |
| break; |
| case DEFIPATH_TAPER: |
| fprintf(fout, " TAPER"); |
| break; |
| } |
| } |
| } |
| } |
| } |
| |
| // layerName width |
| if (net->hasWidthRules()) { |
| fprintf(fout, "\nSNET %s", net->name()); |
| for (i = 0; i < net->numWidthRules(); i++) { |
| net->widthRule(i, &layerName, &dist); |
| fprintf (fout, " WIDTH %s %g ", layerName, checkDouble(dist)); |
| } |
| } |
| |
| // layerName spacing |
| if (net->hasSpacingRules()) { |
| fprintf(fout, "\nSNET %s", net->name()); |
| for (i = 0; i < net->numSpacingRules(); i++) { |
| net->spacingRule(i, &layerName, &dist, &left, &right); |
| if (left == right) |
| fprintf (fout, " SPACING %s %g ", layerName, checkDouble(dist)); |
| else |
| fprintf (fout, " SPACING %s %g RANGE %g %g ", |
| layerName, checkDouble(dist), checkDouble(left), |
| checkDouble(right)); |
| } |
| } |
| |
| if (net->hasVoltage() || net->hasWeight() || net->hasCap() || |
| net->hasSource() || net->hasPattern() || net->hasOriginal() || |
| net->hasUse()) { |
| fprintf(fout, "\nSNET %s", net->name()); |
| if (net->hasVoltage()) |
| fprintf(fout, " VOLTAGE %g", checkDouble(net->voltage())); |
| if (net->hasWeight()) |
| fprintf(fout, " WEIGHT %d", net->weight()); |
| if (net->hasCap()) |
| fprintf(fout, " ESTCAP %g", checkDouble(net->cap())); |
| if (net->hasSource()) |
| fprintf(fout, " SOURCE %s", net->source()); |
| if (net->hasPattern()) |
| fprintf(fout, " PATTERN %s", net->pattern()); |
| if (net->hasOriginal()) |
| fprintf(fout, " ORIGINAL %s", net->original()); |
| if (net->hasUse()) |
| fprintf(fout, " USE %s", net->use()); |
| } |
| |
| fprintf(fout,"\n"); |
| --numObjs; |
| return 0; |
| } |
| |
| int ndr(defrCallbackType_e c, defiNonDefault* nd, defiUserData ud) { |
| // For nondefaultrule |
| int i; |
| |
| checkType(c); |
| if (ud != userData) dataError(); |
| if (c != defrNonDefaultCbkType) |
| fprintf(fout, "BOGUS NONDEFAULTRULE TYPE "); |
| fprintf(fout, "NDR %s", nd->name()); |
| if (nd->hasHardspacing()) |
| fprintf(fout, " HARDSPACING\n"); |
| fprintf(fout, "\n"); |
| for (i = 0; i < nd->numLayers(); i++) { |
| fprintf(fout, "NDR %s LAYER %s", nd->name(), nd->layerName(i)); |
| fprintf(fout, " WIDTH %d", nd->layerWidthVal(i)); |
| if (nd->hasLayerDiagWidth(i)) |
| fprintf(fout, " DIAGWIDTH %d", |
| nd->layerDiagWidthVal(i)); |
| if (nd->hasLayerSpacing(i)) |
| fprintf(fout, " SPACING %d", nd->layerSpacingVal(i)); |
| if (nd->hasLayerWireExt(i)) |
| fprintf(fout, " WIREEXT %d", nd->layerWireExtVal(i)); |
| fprintf(fout, "\n"); |
| } |
| for (i = 0; i < nd->numVias(); i++) |
| fprintf(fout, "NDR %s VIA %s\n", nd->name(), nd->viaName(i)); |
| for (i = 0; i < nd->numViaRules(); i++) |
| fprintf(fout, "NDR %s VIARULE %s\n", nd->name(), nd->viaRuleName(i)); |
| for (i = 0; i < nd->numMinCuts(); i++) |
| fprintf(fout, "NDR %s MINCUTS %s %d\n", nd->name(), nd->cutLayerName(i), |
| nd->numCuts(i)); |
| for (i = 0; i < nd->numProps(); i++) |
| fprintf(fout, "NDR %s PROPERTY %s %s\n", nd->name(), nd->propName(i), |
| nd->propValue(i)); |
| --numObjs; |
| return 0; |
| } |
| |
| // Technology |
| int tname(defrCallbackType_e c, const char* string, defiUserData ud) { |
| checkType(c); |
| if (ud != userData) dataError(); |
| fprintf(fout, "TECHNOLOGY %s\n", string); |
| return 0; |
| } |
| |
| // Design |
| int dname(defrCallbackType_e c, const char* string, defiUserData ud) { |
| checkType(c); |
| if (ud != userData) dataError(); |
| fprintf(fout, "DESIGN %s\n", string); |
| |
| return 0; |
| } |
| |
| |
| char* address(const char* in) { |
| return ((char*)in); |
| } |
| |
| // Assertion or Constraints |
| void operand(defrCallbackType_e c, defiAssertion* a, int ind) { |
| int i, first = 1; |
| char* netName; |
| char* fromInst, * fromPin, * toInst, * toPin; |
| |
| if (a->isSum()) { |
| // Sum in operand, recursively call operand |
| fprintf(fout, "ASSERTIONS/CONSTRAINTS SUM ( "); |
| a->unsetSum(); |
| isSumSet = 1; |
| begOperand = 0; |
| operand (c, a, ind); |
| fprintf(fout, ") "); |
| } else { |
| // operand |
| if (ind >= a->numItems()) { |
| fprintf(fout, "ERROR: when writing out SUM in Constraints.\n"); |
| return; |
| } |
| if (begOperand) { |
| fprintf(fout, "ASSRT/CONSTR "); |
| begOperand = 0; |
| } |
| for (i = ind; i < a->numItems(); i++) { |
| if (a->isNet(i)) { |
| a->net(i, &netName); |
| if (!first) |
| fprintf(fout, ", "); // print , as separator |
| fprintf(fout, "NET %s ", netName); |
| } else if (a->isPath(i)) { |
| a->path(i, &fromInst, &fromPin, &toInst, |
| &toPin); |
| if (!first) |
| fprintf(fout, ", "); |
| fprintf(fout, "PATH %s %s %s %s ", fromInst, fromPin, toInst, |
| toPin); |
| } else if (isSumSet) { |
| // SUM within SUM, reset the flag |
| a->setSum(); |
| operand(c, a, i); |
| } |
| first = 0; |
| } |
| |
| } |
| } |
| |
| // Assertion or Constraints |
| int constraint(defrCallbackType_e c, defiAssertion* a, defiUserData ud) { |
| // Handles both constraints and assertions |
| |
| checkType(c); |
| if (ud != userData) dataError(); |
| if (a->isWiredlogic()) |
| // Wirelogic |
| fprintf(fout, "ASSRT/CONSTR WIREDLOGIC %s + MAXDIST %g\n", |
| a->netName(), checkDouble(a->fallMax())); |
| else { |
| // Call the operand function |
| isSumSet = 0; // reset the global variable |
| begOperand = 1; |
| operand (c, a, 0); |
| // Get the Rise and Fall |
| if (a->hasRiseMax()) |
| fprintf(fout, " RISEMAX %g ", checkDouble(a->riseMax())); |
| if (a->hasFallMax()) |
| fprintf(fout, " FALLMAX %g ", checkDouble(a->fallMax())); |
| if (a->hasRiseMin()) |
| fprintf(fout, " RISEMIN %g ", checkDouble(a->riseMin())); |
| if (a->hasFallMin()) |
| fprintf(fout, " FALLMIN %g ", checkDouble(a->fallMin())); |
| fprintf(fout, "\n"); |
| } |
| --numObjs; |
| return 0; |
| } |
| |
| |
| // Property definitions |
| int prop(defrCallbackType_e c, defiProp* p, defiUserData ud) { |
| checkType(c); |
| if (ud != userData) dataError(); |
| if (strcmp(p->propType(), "design") == 0) |
| fprintf(fout, "PROPDEF DESIGN %s ", p->propName()); |
| else if (strcmp(p->propType(), "net") == 0) |
| fprintf(fout, "PROPDEF NET %s ", p->propName()); |
| else if (strcmp(p->propType(), "component") == 0) |
| fprintf(fout, "PROPDEF COMP %s ", p->propName()); |
| else if (strcmp(p->propType(), "specialnet") == 0) |
| fprintf(fout, "PROPDEF SNET %s ", p->propName()); |
| else if (strcmp(p->propType(), "group") == 0) |
| fprintf(fout, "PROPDEF GROUP %s ", p->propName()); |
| else if (strcmp(p->propType(), "row") == 0) |
| fprintf(fout, "PROPDEF ROW %s ", p->propName()); |
| else if (strcmp(p->propType(), "componentpin") == 0) |
| fprintf(fout, "PROPDEF COMPPIN %s ", p->propName()); |
| else if (strcmp(p->propType(), "region") == 0) |
| fprintf(fout, "PROPDEF REGION %s ", p->propName()); |
| else if (strcmp(p->propType(), "nondefaultrule") == 0) |
| fprintf(fout, "PROPDEF NONDEFAULTRULE %s ", p->propName()); |
| if (p->dataType() == 'I') |
| fprintf(fout, "INT "); |
| if (p->dataType() == 'R') |
| fprintf(fout, "REAL "); |
| if (p->dataType() == 'S') |
| fprintf(fout, "STR "); |
| if (p->dataType() == 'Q') |
| fprintf(fout, "STR "); |
| if (p->hasRange()) { |
| fprintf(fout, "RANGE %g %g ", checkDouble(p->left()), |
| checkDouble(p->right())); |
| } |
| if (p->hasNumber()) |
| fprintf(fout, "%g ", checkDouble(p->number())); |
| if (p->hasString()) |
| fprintf(fout, "\"%s\" ", p->string()); |
| fprintf(fout, "\n"); |
| |
| return 0; |
| } |
| |
| |
| // History |
| int hist(defrCallbackType_e c, const char* h, defiUserData ud) { |
| checkType(c); |
| if (ud != userData) dataError(); |
| fprintf(fout, "HIST %s\n", h); |
| return 0; |
| } |
| |
| |
| // Busbitchars |
| int bbn(defrCallbackType_e c, const char* h, defiUserData ud) { |
| checkType(c); |
| if (ud != userData) dataError(); |
| fprintf(fout, "BUSBITCHARS \"%s\" \n", h); |
| return 0; |
| } |
| |
| |
| // Version |
| int vers(defrCallbackType_e c, double d, defiUserData ud) { |
| checkType(c); |
| if (ud != userData) dataError(); |
| fprintf(fout, "VERSION %g\n", d); |
| |
| curVer = d; |
| return 0; |
| } |
| |
| |
| // Units |
| int units(defrCallbackType_e c, double d, defiUserData ud) { |
| checkType(c); |
| if (ud != userData) dataError(); |
| fprintf(fout, "UNITS DISTANCE MICRONS %g\n", checkDouble(d)); |
| return 0; |
| } |
| |
| |
| // Casesensitive |
| int casesens(defrCallbackType_e c, int d, defiUserData ud) { |
| checkType(c); |
| if (ud != userData) dataError(); |
| if (d == 1) |
| fprintf(fout, "NAMESCASESENSITIVE OFF\n", d); |
| else |
| fprintf(fout, "NAMESCASESENSITIVE ON\n", d); |
| return 0; |
| } |
| |
| |
| // Site, Canplace, Cannotoccupy, Diearea, Pin, Pincap, DefaultCap, |
| // Row, Gcellgrid, Track, Via, Scanchain, IOtiming, Flooplan, |
| // Region, Group, TiminDisable, Pin property |
| int cls(defrCallbackType_e c, void* cl, defiUserData ud) { |
| defiSite* site; // Site and Canplace and CannotOccupy |
| defiBox* box; // DieArea and |
| defiPinCap* pc; |
| defiPin* pin; |
| int i, j, k; |
| defiRow* row; |
| defiTrack* track; |
| defiGcellGrid* gcg; |
| defiVia* via; |
| defiRegion* re; |
| defiGroup* group; |
| defiComponentMaskShiftLayer* maskShiftLayer = NULL; |
| defiScanchain* sc; |
| defiIOTiming* iot; |
| defiFPC* fpc; |
| defiTimingDisable* td; |
| defiPartition* part; |
| defiPinProp* pprop; |
| defiBlockage* block; |
| defiSlot* slot; |
| defiFill* fill; |
| defiStyles* styles; |
| int xl, yl, xh, yh; |
| char *name, *a1, *b1; |
| char **inst, **inPin, **outPin; |
| int *bits; |
| int size; |
| int corner, typ; |
| const char *itemT; |
| char dir; |
| defiPinAntennaModel* aModel; |
| char *tmpPinName = NULL; |
| char *extraPinName = NULL; |
| char *pName = NULL; |
| char *tmpName = NULL; |
| struct defiPoints points; |
| |
| checkType(c); |
| if (ud != userData) dataError(); |
| switch (c) { |
| |
| case defrSiteCbkType : |
| site = (defiSite*)cl; |
| fprintf(fout, "SITE %s %g %g %s ", site->name(), |
| checkDouble(site->x_orig()), checkDouble(site->y_orig()), |
| site->orientStr()); |
| fprintf(fout, "DO %g BY %g STEP %g %g\n", |
| checkDouble(site->x_num()), checkDouble(site->y_num()), |
| checkDouble(site->x_step()), checkDouble(site->y_step())); |
| break; |
| case defrCanplaceCbkType : |
| site = (defiSite*)cl; |
| fprintf(fout, "CANPLACE %s %g %g %s ", site->name(), |
| checkDouble(site->x_orig()), checkDouble(site->y_orig()), |
| site->orientStr()); |
| fprintf(fout, "DO %g BY %g STEP %g %g\n", |
| checkDouble(site->x_num()), checkDouble(site->y_num()), |
| checkDouble(site->x_step()), checkDouble(site->y_step())); |
| break; |
| case defrCannotOccupyCbkType : |
| site = (defiSite*)cl; |
| fprintf(fout, "CANNOTOCCUPY %s %g %g %s ", |
| site->name(), checkDouble(site->x_orig()), |
| checkDouble(site->y_orig()), site->orientStr()); |
| fprintf(fout, "DO %g BY %g STEP %g %g\n", |
| checkDouble(site->x_num()), checkDouble(site->y_num()), |
| checkDouble(site->x_step()), checkDouble(site->y_step())); |
| break; |
| case defrDieAreaCbkType : |
| box = (defiBox*)cl; |
| fprintf(fout, "DIEAREA"); |
| points = box->getPoint(); |
| for (i = 0; i < points.numPoints; i++) |
| fprintf(fout, " %d %d", points.x[i], points.y[i]); |
| fprintf(fout, "\n"); |
| break; |
| case defrPinCapCbkType : |
| pc = (defiPinCap*)cl; |
| fprintf(fout, "DEFCAP MINPINS %d WIRECAP %g\n", pc->pin(), |
| checkDouble(pc->cap())); |
| --numObjs; |
| break; |
| case defrPinCbkType : |
| pin = (defiPin*)cl; |
| pName = strdup((char*)pin->pinName()); // get the pinName |
| // check if there has .extra<n> in the pName and ignorePE |
| // is set to 1 |
| if (ignorePE) { |
| // check if .extra is in the name, if it is, ignore it |
| if ((extraPinName = strstr(pName, ".extra")) == NULL) |
| tmpPinName = pName; |
| else { |
| // make sure name ends with .extraNNN |
| tmpName = extraPinName; |
| extraPinName = extraPinName + 6; |
| *tmpName = '\0'; |
| tmpPinName = pName; |
| if (extraPinName != NULL) { |
| while (*extraPinName != '\0' && *extraPinName != '\n') { |
| if (isdigit(*extraPinName++)) |
| continue; |
| else { // Name does not end only .extraNNN |
| tmpPinName = strdup(pin->pinName()); |
| break; |
| } |
| } |
| } |
| } |
| } else |
| tmpPinName = pName; |
| fprintf(fout, "PIN %s + NET %s ", tmpPinName, |
| pin->netName()); |
| if (pin->hasDirection()) |
| fprintf(fout, "+ DIRECTION %s ", pin->direction()); |
| if (pin->hasUse()) |
| fprintf(fout, "+ USE %s ", pin->use()); |
| if (pin->hasNetExpr()) |
| fprintf(fout, "+ NETEXPR %s", pin->netExpr()); |
| if (pin->hasSupplySensitivity()) |
| fprintf(fout, "+ SUPPLYSENSITIVITY %s ", pin->supplySensitivity()); |
| if (pin->hasGroundSensitivity()) |
| fprintf(fout, "+ GROUNDSENSITIVITY %s ", pin->groundSensitivity()); |
| if (pin->hasLayer()) { |
| for (i = 0; i < pin->numLayer(); i++) { |
| fprintf(fout, "+ LAYER %s ", pin->layer(i)); |
| if (pin->layerMask(i)) |
| fprintf(fout, "MASK %d ", |
| pin->layerMask(i)); |
| if (pin->hasLayerSpacing(i)) |
| fprintf(fout, "SPACING %d ", |
| pin->layerSpacing(i)); |
| if (pin->hasLayerDesignRuleWidth(i)) |
| fprintf(fout, "DESIGNRULEWIDTH %d ", |
| pin->layerDesignRuleWidth(i)); |
| pin->bounds(i, &xl, &yl, &xh, &yh); |
| fprintf(fout, "( %d %d ) ( %d %d ) ", xl, yl, xh, yh); |
| } |
| for (i = 0; i < pin->numPolygons(); i++) { |
| fprintf(fout, "+ POLYGON %s", pin->polygonName(i)); |
| if (pin->polygonMask(i)) |
| fprintf(fout, "MASK %d ", |
| pin->polygonMask(i)); |
| if (pin->hasPolygonSpacing(i)) |
| fprintf(fout, "SPACING %d ", |
| pin->polygonSpacing(i)); |
| if (pin->hasPolygonDesignRuleWidth(i)) |
| fprintf(fout, "DESIGNRULEWIDTH %d ", |
| pin->polygonDesignRuleWidth(i)); |
| points = pin->getPolygon(i); |
| for (k = 0; k < points.numPoints; k++) |
| fprintf(fout, " %d %d", points.x[k], points.y[k]); |
| } |
| for (i = 0; i < pin->numVias(); i++) { |
| if (pin->viaTopMask(i) || pin->viaCutMask(i) || pin->viaBottomMask(i)) { |
| fprintf(fout, "\nVIA %s MASK %d%d%d %d %d ", |
| pin->viaName(i), |
| pin->viaTopMask(i), |
| pin->viaCutMask(i), |
| pin->viaBottomMask(i), |
| pin->viaPtX(i), |
| pin->viaPtY(i)); |
| } else { |
| fprintf(fout, "\nVIA %s %d %d ", pin->viaName(i), |
| pin->viaPtX(i), pin->viaPtY(i)); |
| } |
| } |
| } |
| if (pin->hasPlacement()) { |
| if (pin->isPlaced()) |
| fprintf(fout, " PLACED "); |
| if (pin->isCover()) |
| fprintf(fout, " COVER "); |
| if (pin->isFixed()) |
| fprintf(fout, " FIXED "); |
| fprintf(fout, "( %d %d ) %s ", pin->placementX(), |
| pin->placementY(), pin->orientStr()); |
| } |
| if (pin->hasSpecial()) |
| fprintf(fout, " SPECIAL "); |
| fprintf(fout, "\n"); |
| |
| if (pin->hasPort()) { |
| struct defiPoints points; |
| defiPinPort* port; |
| for (j = 0; j < pin->numPorts(); j++) { |
| fprintf(fout, "PIN %s", tmpPinName); |
| port = pin->pinPort(j); |
| fprintf(fout, " + PORT"); |
| for (i = 0; i < port->numLayer(); i++) { |
| fprintf(fout, "+ LAYER %s", port->layer(i)); |
| if (port->layerMask(i)) |
| fprintf(fout, "MASK %d ", |
| port->layerMask(i)); |
| if (port->hasLayerSpacing(i)) |
| fprintf(fout, " SPACING %d", port->layerSpacing(i)); |
| if (port->hasLayerDesignRuleWidth(i)) |
| fprintf(fout, " DESIGNRULEWIDTH %d", |
| port->layerDesignRuleWidth(i)); |
| port->bounds(i, &xl, &yl, &xh, &yh); |
| fprintf(fout, " %d %d %d %d", xl, yl, xh, yh); |
| } |
| for (i = 0; i < port->numPolygons(); i++) { |
| fprintf(fout, " + POLYGON %s", port->polygonName(i)); |
| if (port->polygonMask(i)) |
| fprintf(fout, "MASK %d ", |
| port->polygonMask(i)); |
| if (port->hasPolygonSpacing(i)) |
| fprintf(fout, " SPACING %d", port->polygonSpacing(i)); |
| if (port->hasPolygonDesignRuleWidth(i)) |
| fprintf(fout, " DESIGNRULEWIDTH %d", |
| port->polygonDesignRuleWidth(i)); |
| points = port->getPolygon(i); |
| for (k = 0; k < points.numPoints; k++) |
| fprintf(fout, " %d %d", points.x[k], points.y[k]); |
| } |
| for (i = 0; i < port->numVias(); i++) { |
| if (port->viaTopMask(i) || port->viaCutMask(i) |
| || port->viaBottomMask(i)) { |
| fprintf(fout, "\n VIA %s MASK %d%d%d ( %d %d ) ", |
| port->viaName(i), |
| port->viaTopMask(i), |
| port->viaCutMask(i), |
| port->viaBottomMask(i), |
| port->viaPtX(i), |
| port->viaPtY(i)); |
| } else { |
| fprintf(fout, " VIA %s ( %d %d ) ", port->viaName(i), |
| port->viaPtX(i), port->viaPtY(i)); |
| } |
| } |
| if (port->hasPlacement()) { |
| if (port->isPlaced()) { |
| fprintf(fout, " + PLACED"); |
| fprintf(fout, " %d %d %d ", port->placementX(), |
| port->placementY(), port->orient()); |
| } |
| if (port->isCover()) { |
| fprintf(fout, " + COVER"); |
| fprintf(fout, " %d %d %d ", port->placementX(), |
| port->placementY(), port->orient()); |
| } |
| if (port->isFixed()) { |
| fprintf(fout, " + FIXED"); |
| fprintf(fout, " %d %d %d", port->placementX(), |
| port->placementY(), port->orient()); |
| } |
| } |
| fprintf(fout,"\n"); |
| } |
| } |
| if (pin->hasAPinPartialMetalArea()) { |
| fprintf(fout, "PIN %s + NET %s ", tmpPinName, |
| pin->netName()); |
| for (i = 0; i < pin->numAPinPartialMetalArea(); i++) { |
| fprintf(fout, " ANTPINPARTIALMETALAREA %d ", |
| pin->APinPartialMetalArea(i)); |
| if (*(pin->APinPartialMetalAreaLayer(i))) |
| fprintf(fout, " %s ", pin->APinPartialMetalAreaLayer(i)); |
| } |
| fprintf(fout, "\n"); |
| } |
| if (pin->hasAPinPartialMetalSideArea()) { |
| fprintf(fout, "PIN %s + NET %s ", tmpPinName, |
| pin->netName()); |
| for (i = 0; i < pin->numAPinPartialMetalSideArea(); i++) { |
| fprintf(fout, "ANTPINPARTIALMETALSIDEAREA %d", |
| pin->APinPartialMetalSideArea(i)); |
| if (*(pin->APinPartialMetalSideAreaLayer(i))) |
| fprintf(fout, " %s", pin->APinPartialMetalSideAreaLayer(i)); |
| } |
| fprintf(fout, "\n"); |
| } |
| if (pin->hasAPinPartialCutArea()) { |
| fprintf(fout, "PIN %s + NET %s ", tmpPinName, |
| pin->netName()); |
| for (i = 0; i < pin->numAPinPartialCutArea(); i++) { |
| fprintf(fout, "ANTPINPARTIALCUTAREA %d", |
| pin->APinPartialCutArea(i)); |
| if (*(pin->APinPartialCutAreaLayer(i))) |
| fprintf(fout, " %s", pin->APinPartialCutAreaLayer(i)); |
| } |
| fprintf(fout, "\n"); |
| } |
| if (pin->hasAPinDiffArea()) { |
| fprintf(fout, "PIN %s + NET %s ", tmpPinName, |
| pin->netName()); |
| for (i = 0; i < pin->numAPinDiffArea(); i++) { |
| fprintf(fout, "ANTPINDIFFAREA %d", pin->APinDiffArea(i)); |
| if (*(pin->APinDiffAreaLayer(i))) |
| fprintf(fout, " %s", pin->APinDiffAreaLayer(i)); |
| } |
| fprintf(fout, "\n"); |
| } |
| |
| for (j = 0; j < pin->numAntennaModel(); j++) { |
| aModel = pin->antennaModel(j); |
| |
| if (aModel->hasAPinGateArea()) { |
| fprintf(fout, "PIN %s + NET %s %s ", tmpPinName, |
| pin->netName(), aModel->antennaOxide()); |
| for (i = 0; i < aModel->numAPinGateArea(); |
| i++) { |
| fprintf(fout, "ANTPINGATEAREA %d", aModel->APinGateArea(i)); |
| if (*(aModel->APinGateAreaLayer(i))) |
| fprintf(fout, " %s", aModel->APinGateAreaLayer(i)); |
| } |
| fprintf(fout, "\n"); |
| } |
| if (aModel->hasAPinMaxAreaCar()) { |
| fprintf(fout, "PIN %s + NET %s %s ", tmpPinName, |
| pin->netName(), aModel->antennaOxide()); |
| for (i = 0; i < |
| aModel->numAPinMaxAreaCar(); i++) { |
| fprintf(fout, "ANTPINMAXAREACAR %d", |
| aModel->APinMaxAreaCar(i)); |
| if (*(aModel->APinMaxAreaCarLayer(i))) |
| fprintf(fout, " %s", aModel->APinMaxAreaCarLayer(i)); |
| } |
| fprintf(fout, "\n"); |
| } |
| if (aModel->hasAPinMaxSideAreaCar()) { |
| fprintf(fout, "PIN %s + NET %s %s ", tmpPinName, |
| pin->netName(), aModel->antennaOxide()); |
| for (i = 0; |
| i < aModel->numAPinMaxSideAreaCar(); |
| i++) { |
| fprintf(fout, "ANTPINMAXSIDEAREACAR %d", |
| aModel->APinMaxSideAreaCar(i)); |
| if (*(aModel->APinMaxSideAreaCarLayer(i))) |
| fprintf(fout, " %s", aModel->APinMaxSideAreaCarLayer(i)); |
| } |
| fprintf(fout, "\n"); |
| } |
| if (aModel->hasAPinMaxCutCar()) { |
| fprintf(fout, "PIN %s + NET %s %s ", tmpPinName, |
| pin->netName(), aModel->antennaOxide()); |
| for (i = 0; i < aModel->numAPinMaxCutCar(); |
| i++) { |
| fprintf(fout, "ANTPINMAXCUTCAR %d", |
| aModel->APinMaxCutCar(i)); |
| if (*(aModel->APinMaxCutCarLayer(i))) |
| fprintf(fout, " %s", aModel->APinMaxCutCarLayer(i)); |
| } |
| fprintf(fout, "\n"); |
| } |
| } |
| if (tmpPinName) |
| free(tmpPinName); |
| --numObjs; |
| break; |
| case defrDefaultCapCbkType : |
| i = (long)cl; |
| fprintf(fout, "DEFAULTCAP %d\n", i); |
| numObjs = i; |
| break; |
| case defrRowCbkType : |
| row = (defiRow*)cl; |
| if (ignoreRN) // PCR 716759, if flag is set don't bother with name |
| fprintf(fout, "ROW %s %g %g %d", |
| row->macro(), checkDouble(row->x()), checkDouble(row->y()), |
| row->orient()); |
| else |
| fprintf(fout, "ROW %s %s %g %g %d", row->name(), |
| row->macro(), checkDouble(row->x()), checkDouble(row->y()), |
| row->orient()); |
| if (row->hasDo()) { |
| fprintf(fout, " DO %g BY %g", |
| checkDouble(row->xNum()), checkDouble(row->yNum())); |
| if (row->hasDoStep()) |
| fprintf(fout, " STEP %g %g\n", |
| checkDouble(row->xStep()), checkDouble(row->yStep())); |
| } |
| fprintf(fout, "\n"); |
| if (row->numProps() > 0) { |
| if (ignoreRN) { |
| for (i = 0; i < row->numProps(); i++) |
| fprintf(fout, "ROW PROP %s %s\n", |
| row->propName(i), row->propValue(i)); |
| } else { |
| for (i = 0; i < row->numProps(); i++) |
| fprintf(fout, "ROW %s PROP %s %s\n", row->name(), |
| row->propName(i), row->propValue(i)); |
| } |
| } |
| break; |
| case defrTrackCbkType : |
| track = (defiTrack*)cl; |
| /*if (track->firstTrackMask()) { |
| if (track->sameMask()) { |
| fprintf(fout, "TRACKS %s %g DO %g STEP %g MASK %d SAMEMASK LAYER ", |
| track->macro(), track->x(), |
| track->xNum(), track->xStep(), |
| track->firstTrackMask()); |
| } else { |
| fprintf(fout, "TRACKS %s %g DO %g STEP %g MASK %d LAYER ", |
| track->macro(), track->x(), |
| track->xNum(), track->xStep(), |
| track->firstTrackMask()); |
| } |
| } else { |
| fprintf(fout, "TRACKS %s %g DO %g STEP %g LAYER ", |
| track->macro(), track->x(), |
| track->xNum(), track->xStep()); |
| } */ |
| for (i = 0; i < track->numLayers(); i++) { |
| if (track->firstTrackMask()) { |
| if (track->sameMask()) { |
| fprintf(fout, "TRACKS %s %g DO %g STEP %g MASK %d SAMEMASK LAYER %s\n", |
| track->macro(), track->x(), |
| track->xNum(), track->xStep(), |
| track->firstTrackMask(), track->layer(i)); |
| } else { |
| fprintf(fout, "TRACKS %s %g DO %g STEP %g MASK %d LAYER %s\n", |
| track->macro(), track->x(), |
| track->xNum(), track->xStep(), |
| track->firstTrackMask(), |
| track->layer(i)); |
| } |
| } else { |
| fprintf(fout, "TRACKS %s %g DO %g STEP %g LAYER %s\n", |
| track->macro(), track->x(), |
| track->xNum(), track->xStep(), |
| track->layer(i)); |
| } |
| } |
| break; |
| case defrGcellGridCbkType : |
| gcg = (defiGcellGrid*)cl; |
| fprintf(fout, "GCELLGRID %s %d DO %d STEP %g\n", |
| gcg->macro(), gcg->x(), |
| gcg->xNum(), |
| checkDouble(gcg->xStep())); |
| break; |
| case defrViaCbkType : |
| via = (defiVia*)cl; |
| fprintf(fout, "VIA %s ", via->name()); |
| if (via->hasPattern()) |
| fprintf(fout, " PATTERNNAME %s\n", via->pattern()); |
| else |
| fprintf(fout, "\n"); |
| for (i = 0; i < via->numLayers(); i++) { |
| via->layer(i, &name, &xl, &yl, &xh, &yh); |
| int rectMask = via->rectMask(i); |
| |
| if (rectMask) { |
| fprintf(fout, "VIA %s RECT %s MASK %d ( %d %d ) ( %d %d ) \n", |
| via->name(), name, rectMask, xl, yl, xh, yh); |
| } else { |
| fprintf(fout, "VIA %s RECT %s ( %d %d ) ( %d %d ) \n", via->name(), |
| name, xl, yl, xh, yh); |
| } |
| } |
| // POLYGON |
| if (via->numPolygons()) { |
| struct defiPoints points; |
| for (i = 0; i < via->numPolygons(); i++) { |
| int polyMask = via->polyMask(i); |
| |
| if (polyMask) { |
| fprintf(fout, "\n POLYGON %s MASK %d ", |
| via->polygonName(i), polyMask); |
| } else { |
| fprintf(fout, "\n POLYGON %s ", via->polygonName(i)); |
| } |
| points = via->getPolygon(i); |
| for (j = 0; j < points.numPoints; j++) |
| fprintf(fout, "%d %d ", points.x[j], points.y[j]); |
| } |
| fprintf(fout, " \n"); |
| } |
| |
| if (via->hasViaRule()) { |
| char *vrn, *bl, *cl, *tl; |
| int xs, ys, xcs, ycs, xbe, ybe, xte, yte; |
| int cr, cc, xo, yo, xbo, ybo, xto, yto; |
| (void)via->viaRule(&vrn, &xs, &ys, &bl, &cl, &tl, &xcs, |
| &ycs, &xbe, &ybe, &xte, &yte); |
| fprintf(fout, "VIA %s VIARULE %s CUTSIZE %d %d LAYERS %s %s %s", |
| via->name(), vrn, xs, ys, bl, cl, tl); |
| fprintf(fout, " CUTSPACING %d %d ENCLOSURE %d %d %d %d", xcs, ycs, |
| xbe, ybe, xte, yte); |
| if (via->hasRowCol()) { |
| (void)via->rowCol(&cr, &cc); |
| fprintf(fout, " ROWCOL %d %d", cr, cc); |
| } |
| if (via->hasOrigin()) { |
| (void)via->origin(&xo, &yo); |
| fprintf(fout, " ORIGIN %d %d", xo, yo); |
| } |
| if (via->hasOffset()) { |
| (void)via->offset(&xbo, &ybo, &xto, &yto); |
| fprintf(fout, " OFFSET %d %d %d %d", xbo, ybo, xto, yto); |
| } |
| if (via->hasCutPattern()) |
| fprintf(fout, " PATTERN %s", via->cutPattern()); |
| fprintf(fout, "\n"); |
| } |
| --numObjs; |
| break; |
| case defrRegionCbkType : |
| re = (defiRegion*)cl; |
| for (i = 0; i < re->numRectangles(); i++) |
| fprintf(fout, "REGION %s ( %d %d ) ( %d %d )\n",re->name(), |
| re->xl(i), re->yl(i), re->xh(i), re->yh(i)); |
| if (re->hasType()) |
| fprintf(fout, "REGION %s TYPE %s\n",re->name(), re->type()); |
| --numObjs; |
| break; |
| case defrGroupCbkType : |
| group = (defiGroup*)cl; |
| fprintf(fout, "GROUP %s ", group->name()); |
| if (group->hasMaxX() | group->hasMaxY() |
| | group->hasPerim()) { |
| fprintf(fout, "SOFT "); |
| if (group->hasPerim()) |
| fprintf(fout, "MAXHALFPERIMETER %d ", |
| group->perim()); |
| if (group->hasMaxX()) |
| fprintf(fout, "MAXX %d ", group->maxX()); |
| if (group->hasMaxY()) |
| fprintf(fout, "MAXY %d ", group->maxY()); |
| } |
| if (group->hasRegionName()) |
| fprintf(fout, "REGION %s ", group->regionName()); |
| if (group->hasRegionBox()) { |
| int *gxl, *gyl, *gxh, *gyh; |
| int size; |
| group->regionRects(&size, &gxl, &gyl, &gxh, &gyh); |
| for (i = 0; i < size; i++) |
| fprintf(fout, "REGION (%d %d) (%d %d) ", gxl[i], gyl[i], |
| gxh[i], gyh[i]); |
| } |
| fprintf(fout, "\n"); |
| --numObjs; |
| break; |
| case defrComponentMaskShiftLayerCbkType : |
| fprintf(fout, "COMPONENTMASKSHIFT "); |
| |
| for (i = 0; i < maskShiftLayer->numMaskShiftLayers(); i++) { |
| fprintf(fout, "%s ", maskShiftLayer->maskShiftLayer(i)); |
| } |
| fprintf(fout, ";\n"); |
| break; |
| case defrScanchainCbkType : |
| sc = (defiScanchain*)cl; |
| fprintf(fout, "SCANCHAINS %s", sc->name()); |
| if (sc->hasStart()) { |
| sc->start(&a1, &b1); |
| fprintf(fout, " START %s %s", sc->name(), a1, b1); |
| } |
| if (sc->hasStop()) { |
| sc->stop(&a1, &b1); |
| fprintf(fout, " STOP %s %s", sc->name(), a1, b1); |
| } |
| if (sc->hasCommonInPin() || |
| sc->hasCommonOutPin()) { |
| fprintf(fout, " COMMONSCANPINS ", sc->name()); |
| if (sc->hasCommonInPin()) |
| fprintf(fout, " ( IN %s )", sc->commonInPin()); |
| if (sc->hasCommonOutPin()) |
| fprintf(fout, " ( OUT %s )",sc->commonOutPin()); |
| } |
| fprintf(fout, "\n"); |
| if (sc->hasFloating()) { |
| sc->floating(&size, &inst, &inPin, &outPin, &bits); |
| for (i = 0; i < size; i++) { |
| fprintf(fout, "SCANCHAINS %s FLOATING %s", sc->name(), inst[i]); |
| if (inPin[i]) |
| fprintf(fout, " IN %s", inPin[i]); |
| if (outPin[i]) |
| fprintf(fout, " OUT %s", outPin[i]); |
| if (bits[i] != -1) |
| fprintf(fout, " BITS %d", bits[i]); |
| fprintf(fout, "\n"); |
| } |
| } |
| |
| if (sc->hasOrdered()) { |
| for (i = 0; i < sc->numOrderedLists(); i++) { |
| sc->ordered(i, &size, &inst, &inPin, &outPin, &bits); |
| for (j = 0; j < size; j++) { |
| fprintf(fout, "SCANCHAINS %s ORDERED %s", sc->name(), |
| inst[j]); |
| if (inPin[j]) |
| fprintf(fout, " IN %s", inPin[j]); |
| if (outPin[j]) |
| fprintf(fout, " OUT %s", outPin[j]); |
| if (bits[j] != -1) |
| fprintf(fout, " BITS %d", bits[j]); |
| fprintf(fout, "\n"); |
| } |
| } |
| } |
| |
| if (sc->hasPartition()) { |
| fprintf(fout, "SCANCHAINS %s PARTITION %s", sc->name(), |
| sc->partitionName()); |
| if (sc->hasPartitionMaxBits()) |
| fprintf(fout, " MAXBITS %d", sc->partitionMaxBits()); |
| } |
| fprintf(fout, "\n"); |
| --numObjs; |
| break; |
| case defrIOTimingCbkType : |
| iot = (defiIOTiming*)cl; |
| fprintf(fout, "IOTIMING ( %s %s )\n", iot->inst(), iot->pin()); |
| if (iot->hasSlewRise()) |
| fprintf(fout, "IOTIMING %s RISE SLEWRATE %g %g\n", iot->inst(), |
| checkDouble(iot->slewRiseMin()), |
| checkDouble(iot->slewRiseMax())); |
| if (iot->hasSlewFall()) |
| fprintf(fout, "IOTIMING %s FALL SLEWRATE %g %g\n", iot->inst(), |
| checkDouble(iot->slewFallMin()), |
| checkDouble(iot->slewFallMax())); |
| if (iot->hasVariableRise()) |
| fprintf(fout, "IOTIMING %s RISE VARIABLE %g %g\n", iot->inst(), |
| checkDouble(iot->variableRiseMin()), |
| checkDouble(iot->variableRiseMax())); |
| if (iot->hasVariableFall()) |
| fprintf(fout, "IOTIMING %s FALL VARIABLE %g %g\n", iot->inst(), |
| checkDouble(iot->variableFallMin()), |
| checkDouble(iot->variableFallMax())); |
| if (iot->hasCapacitance()) |
| fprintf(fout, "IOTIMING %s CAPACITANCE %g\n", iot->inst(), |
| checkDouble(iot->capacitance())); |
| if (iot->hasDriveCell()) { |
| fprintf(fout, "IOTIMING %s DRIVECELL %s ", iot->inst(), |
| iot->driveCell()); |
| if (iot->hasFrom()) |
| fprintf(fout, " FROMPIN %s ", |
| iot->from()); |
| if (iot->hasTo()) |
| fprintf(fout, " TOPIN %s ", |
| iot->to()); |
| if (iot->hasParallel()) |
| fprintf(fout, "PARALLEL %g", checkDouble(iot->parallel())); |
| fprintf(fout, "\n"); |
| } |
| --numObjs; |
| break; |
| case defrFPCCbkType : |
| fpc = (defiFPC*)cl; |
| fprintf(fout, "FLOORPLAN %s ", fpc->name()); |
| if (fpc->isVertical()) |
| fprintf(fout, "VERTICAL "); |
| if (fpc->isHorizontal()) |
| fprintf(fout, "HORIZONTAL "); |
| if (fpc->hasAlign()) |
| fprintf(fout, "ALIGN "); |
| if (fpc->hasMax()) |
| fprintf(fout, "%g ", checkDouble(fpc->alignMax())); |
| if (fpc->hasMin()) |
| fprintf(fout, "%g ", checkDouble(fpc->alignMin())); |
| if (fpc->hasEqual()) |
| fprintf(fout, "%g ", checkDouble(fpc->equal())); |
| for (i = 0; i < fpc->numParts(); i++) { |
| fpc->getPart(i, &corner, &typ, &name); |
| if (corner == 'B') |
| fprintf(fout, "BOTTOMLEFT "); |
| else |
| fprintf(fout, "TOPRIGHT "); |
| if (typ == 'R') |
| fprintf(fout, "ROWS %s ", name); |
| else |
| fprintf(fout, "COMPS %s ", name); |
| } |
| fprintf(fout, "\n"); |
| --numObjs; |
| break; |
| case defrTimingDisableCbkType : |
| td = (defiTimingDisable*)cl; |
| if (td->hasFromTo()) fprintf(fout, "TIMINGDISABLE FROMPIN %s %s ", td->fromInst(), td->fromPin(), td->toInst(), td->toPin()); if (td->hasThru()) |
| fprintf(fout, " THRUPIN %s %s ", td->thruInst(), td->thruPin()); |
| if (td->hasMacroFromTo()) |
| fprintf(fout, " MACRO %s FROMPIN %s %s ", td->macroName(), |
| td->fromPin(), td->toPin()); |
| if (td->hasMacroThru()) |
| fprintf(fout, " MACRO %s THRUPIN %s %s ", td->macroName(), |
| td->fromPin()); |
| fprintf(fout, "\n"); |
| break; |
| case defrPartitionCbkType : |
| part = (defiPartition*)cl; |
| fprintf(fout, "PARTITION %s ", part->name()); |
| if (part->isSetupRise() | part->isSetupFall() | part->isHoldRise() | |
| part->isHoldFall()) { |
| // has turnoff |
| fprintf(fout, "TURNOFF "); |
| if (part->isSetupRise()) |
| fprintf(fout, "SETUPRISE "); |
| if (part->isSetupFall()) |
| fprintf(fout, "SETUPFALL "); |
| if (part->isHoldRise()) |
| fprintf(fout, "HOLDRISE "); |
| if (part->isHoldFall()) |
| fprintf(fout, "HOLDFALL "); |
| } |
| itemT = part->itemType(); |
| dir = part->direction(); |
| if (strcmp(itemT, "CLOCK") == 0) { |
| if (dir == 'T') // toclockpin |
| fprintf(fout, " TOCLOCKPIN %s %s ", part->instName(), |
| part->pinName()); |
| if (dir == 'F') // fromclockpin |
| fprintf(fout, " FROMCLOCKPIN %s %s ", part->instName(), |
| part->pinName()); |
| if (part->hasMin()) |
| fprintf(fout, "MIN %g %g ", |
| checkDouble(part->partitionMin()), |
| checkDouble(part->partitionMax())); |
| if (part->hasMax()) |
| fprintf(fout, "MAX %g %g ", |
| checkDouble(part->partitionMin()), |
| checkDouble(part->partitionMax())); |
| fprintf(fout, "PINS "); |
| for (i = 0; i < part->numPins(); i++) |
| fprintf(fout, "%s ", part->pin(i)); |
| } else if (strcmp(itemT, "IO") == 0) { |
| if (dir == 'T') // toiopin |
| fprintf(fout, " TOIOPIN %s %s ", part->instName(), |
| part->pinName()); |
| if (dir == 'F') // fromiopin |
| fprintf(fout, " FROMIOPIN %s %s ", part->instName(), |
| part->pinName()); |
| } else if (strcmp(itemT, "COMP") == 0) { |
| if (dir == 'T') // tocomppin |
| fprintf(fout, " TOCOMPPIN %s %s ", part->instName(), |
| part->pinName()); |
| if (dir == 'F') // fromcomppin |
| fprintf(fout, " FROMCOMPPIN %s %s ", part->instName(), |
| part->pinName()); |
| } |
| fprintf(fout, "\n"); |
| --numObjs; |
| break; |
| |
| case defrPinPropCbkType : |
| pprop = (defiPinProp*)cl; |
| if (pprop->isPin()) |
| fprintf(fout, "PINPROP PIN %s ", pprop->pinName()); |
| else |
| fprintf(fout, "PINPROP %s %s ", pprop->instName(), |
| pprop->pinName()); |
| fprintf(fout, "\n"); |
| if (pprop->numProps() > 0) { |
| for (i = 0; i < pprop->numProps(); i++) { |
| fprintf(fout, "PINPROP PIN %s PROP %s %s\n", |
| pprop->pinName(), pprop->propName(i), |
| pprop->propValue(i)); |
| } |
| } |
| --numObjs; |
| break; |
| |
| case defrBlockageCbkType : |
| block = (defiBlockage*)cl; |
| if (block->hasLayer()) { |
| fprintf(fout, "BLOCKAGE LAYER %s", block->layerName()); |
| if (block->hasComponent()) |
| fprintf(fout, " COMP %s", block->layerComponentName()); |
| if (block->hasSlots()) |
| fprintf(fout, " SLOTS"); |
| if (block->hasFills()) |
| fprintf(fout, " FILLS"); |
| if (block->hasPushdown()) |
| fprintf(fout, " PUSHDOWN"); |
| if (block->hasExceptpgnet()) |
| fprintf(fout, " EXCEPTPGNET"); |
| if (block->hasMask()) |
| fprintf(fout, " MASK %d", block->mask()); |
| if (block->hasSpacing()) |
| fprintf(fout, " SPACING %d", |
| block->minSpacing()); |
| if (block->hasDesignRuleWidth()) |
| fprintf(fout, " DESIGNRULEWIDTH %d", block->designRuleWidth()); |
| fprintf(fout, "\n"); |
| for (i = 0; i < block->numRectangles(); i++) { |
| fprintf(fout, "BLOCKAGE LAYER %s RECT %d %d %d %d\n", |
| block->layerName(), block->xl(i), block->yl(i), |
| block->xh(i), block->yh(i)); |
| } |
| for (i = 0; i < block->numPolygons(); i++) { |
| fprintf(fout, "BLOCKAGE LAYER %s POLYGON", block->layerName()); |
| points = block->getPolygon(i); |
| for (j = 0; j < points.numPoints; j++) |
| fprintf(fout, "%d %d ", points.x[j], points.y[j]); |
| fprintf(fout, "\n"); |
| } |
| } |
| else if (block->hasPlacement()) { |
| fprintf(fout, "BLOCKAGE PLACEMENT"); |
| if (block->hasSoft()) |
| fprintf(fout, " SOFT"); |
| if (block->hasPartial()) |
| fprintf(fout, " PARTIAL %g", block->placementMaxDensity()); |
| if (block->hasComponent()) |
| fprintf(fout, " COMP %s", block->layerComponentName()); |
| if (block->hasPushdown()) |
| fprintf(fout, " PUSHDOWN"); |
| fprintf(fout, "\n"); |
| for (i = 0; i < block->numRectangles(); i++) { |
| fprintf(fout, "BLOCKAGE PLACEMENT RECT %d %d %d %d\n", |
| block->xl(i), block->yl(i), |
| block->xh(i), block->yh(i)); |
| } |
| } |
| --numObjs; |
| break; |
| |
| case defrSlotCbkType : |
| slot = (defiSlot*)cl; |
| for (i = 0; i < slot->numRectangles(); i++) { |
| fprintf(fout, "SLOT LAYER %s", slot->layerName()); |
| fprintf(fout, " RECT %d %d %d %d\n", |
| slot->xl(i), slot->yl(i), |
| slot->xh(i), slot->yh(i)); |
| } |
| for (i = 0; i < slot->numPolygons(); i++) { |
| fprintf(fout, "SLOT LAYER %s POLYGON"); |
| points = slot->getPolygon(i); |
| for (j = 0; j < points.numPoints; j++) |
| fprintf(fout, " %d %d", points.x[j], points.y[j]); |
| fprintf(fout, "\n"); |
| } |
| --numObjs; |
| break; |
| |
| case defrFillCbkType : |
| fill = (defiFill*)cl; |
| for (i = 0; i < fill->numRectangles(); i++) { |
| fprintf(fout, "FILL LAYER %s", fill->layerName()); |
| if (fill->layerMask()) { |
| fprintf(fout, " MASK %d", fill->layerMask()); |
| } |
| if (fill->hasLayerOpc()) |
| fprintf(fout, " OPC"); |
| fprintf(fout, " RECT %d %d %d %d\n", |
| fill->xl(i), fill->yl(i), |
| fill->xh(i), fill->yh(i)); |
| } |
| for (i = 0; i < fill->numPolygons(); i++) { |
| fprintf(fout, "FILL LAYER %s POLYGON", fill->layerName()); |
| points = fill->getPolygon(i); |
| for (j = 0; j < points.numPoints; j++) |
| fprintf(fout, " %d %d", points.x[j], points.y[j]); |
| fprintf(fout, "\n"); |
| } |
| if (fill->hasVia()) { |
| fprintf(fout, "FILL VIA %s", fill->viaName()); |
| if (fill->viaTopMask() || fill->viaCutMask() |
| || fill->viaBottomMask()) { |
| fprintf(fout, " MASK %d%d%d", |
| fill->viaTopMask(), |
| fill->viaCutMask(), |
| fill->viaBottomMask()); |
| } |
| if (fill->hasViaOpc()) |
| fprintf(fout, " OPC\n"); |
| for (i = 0; i < fill->numViaPts(); i++) { |
| points = fill->getViaPts(i); |
| for (j = 0; j < points.numPoints; j++) |
| fprintf(fout, " %d %d", points.x[j], points.y[j]); |
| } |
| fprintf(fout, "\n"); |
| } |
| --numObjs; |
| break; |
| |
| case defrStylesCbkType : |
| struct defiPoints points; |
| styles = (defiStyles*)cl; |
| fprintf(fout, "STYLE %d", styles->style()); |
| points = styles->getPolygon(); |
| for (j = 0; j < points.numPoints; j++) |
| fprintf(fout, " %d %d", points.x[j], points.y[j]); |
| fprintf(fout, "\n"); |
| --numObjs; |
| break; |
| |
| default: fprintf(fout, "BOGUS callback to cls.\n"); return 1; |
| } |
| return 0; |
| } |
| |
| |
| int dn(defrCallbackType_e c, const char* h, defiUserData ud) { |
| checkType(c); |
| if (ud != userData) dataError(); |
| fprintf(fout, "DIVIDERCHAR \"%s\" \n",h); |
| return 0; |
| } |
| |
| |
| int ext(defrCallbackType_e t, const char* c, defiUserData ud) { |
| char* name; |
| |
| checkType(t); |
| if (ud != userData) dataError(); |
| |
| switch (t) { |
| case defrNetExtCbkType : name = address("net"); break; |
| case defrComponentExtCbkType : name = address("component"); break; |
| case defrPinExtCbkType : name = address("pin"); break; |
| case defrViaExtCbkType : name = address("via"); break; |
| case defrNetConnectionExtCbkType : name = address("net connection"); break; |
| case defrGroupExtCbkType : name = address("group"); break; |
| case defrScanChainExtCbkType : name = address("scanchain"); break; |
| case defrIoTimingsExtCbkType : name = address("io timing"); break; |
| case defrPartitionsExtCbkType : name = address("partition"); break; |
| default: name = address("BOGUS"); return 1; |
| } |
| fprintf(fout, "EXTENSION %s %s\n", name, c); |
| return 0; |
| } |
| |
| //======== |
| |
| int diffDefReadFile(char* inFile, char* outFile, char* ignorePinExtra, |
| char* ignoreRowName, char* ignoreViaName, char* netSegComp) { |
| FILE* f; |
| int res; |
| |
| userData = (void*)0x01020304; |
| defrInit(); |
| |
| defrSetDesignCbk(dname); |
| defrSetTechnologyCbk(tname); |
| defrSetPropCbk(prop); |
| defrSetNetCbk(netf); |
| defrSetSNetCbk(snetf); |
| defrSetComponentMaskShiftLayerCbk(compMSL); |
| defrSetComponentCbk(compf); |
| defrSetAddPathToNet(); |
| defrSetHistoryCbk(hist); |
| defrSetConstraintCbk(constraint); |
| defrSetAssertionCbk(constraint); |
| defrSetDividerCbk(dn); |
| defrSetBusBitCbk(bbn); |
| defrSetNonDefaultCbk(ndr); |
| |
| // All of the extensions point to the same function. |
| defrSetNetExtCbk(ext); |
| defrSetComponentExtCbk(ext); |
| defrSetPinExtCbk(ext); |
| defrSetViaExtCbk(ext); |
| defrSetNetConnectionExtCbk(ext); |
| defrSetGroupExtCbk(ext); |
| defrSetScanChainExtCbk(ext); |
| defrSetIoTimingsExtCbk(ext); |
| defrSetPartitionsExtCbk(ext); |
| |
| defrSetUnitsCbk(units); |
| defrSetVersionCbk(vers); |
| defrSetCaseSensitiveCbk(casesens); |
| |
| // The following calls are an example of using one function "cls" |
| // to be the callback for many DIFFERENT types of constructs. |
| // We have to cast the function type to meet the requirements |
| // of each different set function. |
| defrSetSiteCbk((defrSiteCbkFnType)cls); |
| defrSetCanplaceCbk((defrSiteCbkFnType)cls); |
| defrSetCannotOccupyCbk((defrSiteCbkFnType)cls); |
| defrSetDieAreaCbk((defrBoxCbkFnType)cls); |
| defrSetPinCapCbk((defrPinCapCbkFnType)cls); |
| defrSetPinCbk((defrPinCbkFnType)cls); |
| defrSetPinPropCbk((defrPinPropCbkFnType)cls); |
| defrSetDefaultCapCbk((defrIntegerCbkFnType)cls); |
| defrSetRowCbk((defrRowCbkFnType)cls); |
| defrSetTrackCbk((defrTrackCbkFnType)cls); |
| defrSetGcellGridCbk((defrGcellGridCbkFnType)cls); |
| defrSetViaCbk((defrViaCbkFnType)cls); |
| defrSetRegionCbk((defrRegionCbkFnType)cls); |
| defrSetGroupCbk((defrGroupCbkFnType)cls); |
| defrSetScanchainCbk((defrScanchainCbkFnType)cls); |
| defrSetIOTimingCbk((defrIOTimingCbkFnType)cls); |
| defrSetFPCCbk((defrFPCCbkFnType)cls); |
| defrSetTimingDisableCbk((defrTimingDisableCbkFnType)cls); |
| defrSetPartitionCbk((defrPartitionCbkFnType)cls); |
| defrSetBlockageCbk((defrBlockageCbkFnType)cls); |
| defrSetSlotCbk((defrSlotCbkFnType)cls); |
| defrSetFillCbk((defrFillCbkFnType)cls); |
| |
| if (strcmp(ignorePinExtra, "0") != 0) |
| ignorePE = 1; |
| |
| if (strcmp(ignoreRowName, "0") != 0) |
| ignoreRN = 1; |
| |
| if (strcmp(ignoreViaName, "0") != 0) |
| ignoreVN = 1; |
| |
| if (strcmp(netSegComp, "0") != 0) |
| netSeCmp = 1; |
| |
| if ((f = fopen(inFile,"r")) == 0) { |
| fprintf(stderr,"Couldn't open input file '%s'\n", inFile); |
| return(2); |
| } |
| |
| if ((fout = fopen(outFile, "w")) == 0) { |
| fprintf(stderr, "Couldn't open output file '%s'\n", outFile); |
| fclose(f); |
| return(2); |
| } |
| |
| res = defrRead(f, inFile, userData, 1); |
| |
| fclose(f); |
| fclose(fout); |
| |
| return 0; |
| } |