📄 oalefinviarule.cpp
字号:
// *****************************************************************************// *****************************************************************************// LefInViaRule.cpp//// Functions to handle LEF VIARULE and LEF VIARULE GENERATE constructs for the// 'lef2oa' translator.//// *****************************************************************************// Except as specified in the OpenAccess terms of use of Cadence or Silicon// Integration Initiative, this material may not be copied, modified,// re-published, uploaded, executed, or distributed in any way, in any medium,// in whole or in part, without prior written permission from Cadence.//// Copyright 2002-2005 Cadence Design Systems, Inc.// All Rights Reserved.//// $Author: nitters $// $Revision: 1.62 $// $Date: 2005/04/19 14:58:52 $// $State: Exp $// *****************************************************************************// *****************************************************************************#include "oaLefDef.h"BEGIN_LEFDEF_NAMESPACE// *****************************************************************************// LefInViaRule::LefInViaRule()// LefInViaRule::~LefInViaRule()//// This is the constructor for the LefInViaRule class. // *****************************************************************************LefInViaRule::LefInViaRule(LefIn &translator): lefIn(translator), viaTable(0, 0, "layer1Width", "layer2Width", NULL){ translator.lefInViaRule = this;}LefInViaRule::~LefInViaRule(){}// *****************************************************************************// LefInViaRule::parse()//// This function creates a new OA viaSpec from the LEF parser datastructure.// *****************************************************************************voidLefInViaRule::parse(lefiViaRule *data){ lefViaRule = data; lefLayer1 = NULL; lefLayer2 = NULL; lefCutLayer = NULL; viaRule = NULL; layer1 = NULL; layer2 = NULL; cutLayer = NULL; colMin = oacNullIndex; colMax = oacNullIndex; rowMin = oacNullIndex; rowMax = oacNullIndex; viaTable.setNumRows(0); viaTable.setNumCols(0); viaTable.setDefaultValue(NULL); parseLayers(); // Find any existing viaDef table viaRule = oaViaSpec::find(layer1, layer2); if (viaRule) { oaViaDef2DTblValue *value = viaRule->getValue(); if (value) { value->get(viaTable); } } oaViaDefArray newArray; parseWidthRanges(); if (lefViaRule->hasGenerate()) { parseGenerate(newArray); } else { parseVias(newArray); } if (!newArray.getNumElements()) { return; } oaViaDefArrayValue *arrayValue = NULL; if (rowMin == oacNullIndex || colMin == oacNullIndex) { // Default (non-width based) value if (viaRule) { arrayValue = viaRule->getDefaultValue(); } oaViaDefArray array; if (arrayValue) { arrayValue->get(array); } for (oaUInt4 i = 0; i < newArray.getNumElements(); i++) { if (array.find(newArray[i]) == oacNullIndex) { array.append(newArray[i]); } } if (arrayValue) { arrayValue->set(array); } else { arrayValue = oaViaDefArrayValue::create(lefIn.tech(), array); if (viaRule) { viaRule->setDefaultValue(arrayValue); } else { viaRule = oaViaSpec::create(layer1, layer2, arrayValue); } } } else { // Add the vias to each row & column in between the min and max ranges for (oaUInt4 row = rowMin; row < rowMax; row++) { for (oaUInt4 col = colMin; col < colMax; col++) { arrayValue = (oaViaDefArrayValue*) viaTable.getValue(row, col); oaViaDefArray array; if (arrayValue) { arrayValue->get(array); } for (oaUInt4 i = 0; i < newArray.getNumElements(); i++) { if (array.find(newArray[i]) == oacNullIndex) { array.append(newArray[i]); } } if (arrayValue) { arrayValue->set(array); } else { arrayValue = oaViaDefArrayValue::create(lefIn.tech(), array); viaTable.setValue(row, col, arrayValue); } } } if (!viaRule || !viaRule->getValue()) { oaViaDef2DTblValue *value = oaViaDef2DTblValue::create(lefIn.tech(), viaTable); if (!viaRule) { viaRule = oaViaSpec::create(layer1, layer2, value); } else { viaRule->setValue(value); } } else { viaRule->getValue()->set(viaTable); } } if (!lefViaRule->hasGenerate()) { parseProperties(); }}// *****************************************************************************// LefInViaRule::parseLayers()//// This function finds the via rule layers in the techDB.// *****************************************************************************voidLefInViaRule::parseLayers(){ layer1 = lefIn.getLayer(lefViaRule->layer(0)->name()); layer2 = lefIn.getLayer(lefViaRule->layer(1)->name()); if (layer2->getMaskNumber() < layer1->getMaskNumber()) { layer1 = layer2; layer2 = lefIn.getLayer(lefViaRule->layer(0)->name()); lefLayer1 = lefViaRule->layer(1); lefLayer2 = lefViaRule->layer(0); } else { lefLayer1 = lefViaRule->layer(0); lefLayer2 = lefViaRule->layer(1); } if (lefViaRule->numLayers() > 2) { lefCutLayer = lefViaRule->layer(2); cutLayer = lefIn.getLayer(lefCutLayer->name()); }}// *****************************************************************************// LefInViaRule::parseGenerate()//// This function creates an OA stdViaDef with the via from the LEF parser// datastructure.// *****************************************************************************voidLefInViaRule::parseGenerate(oaViaDefArray &array){ if(!cutLayer) { if (layer1 == layer2) { // Ignore turn vias return; } else { throw LefDefError(cViaRuleNoCutLayer, lefViaRule->name()); } } oaViaParam viaParams; if (lefLayer1->hasEnclosure() || lefLayer2->hasEnclosure()) { parseEnclosure(viaParams); } else { parseOverhang(viaParams); } viaParams.setCutLayer(cutLayer->getNumber()); parseCutSize(viaParams); parseCutSpacing(viaParams); oaString viaRuleName = lefViaRule->name(); oaViaDef *viaDef = oaViaDef::find(lefIn.tech(), viaRuleName); if (viaDef && viaDef->getType() == oacCustomViaDefType) { viaRuleName += "_rule"; viaDef = NULL; } if (!viaDef) { viaDef = oaStdViaDef::create(lefIn.tech(), viaRuleName, layer1, layer2, viaParams); } else { ((oaStdViaDef*) viaDef)->setParams(viaParams); } parseCutResistance((oaStdViaDef*) viaDef); if (array.find(viaDef) == oacNullIndex) { array.append(viaDef); } if (lefViaRule->hasDefault()) { lefIn.addViaDef(viaDef); }}// *****************************************************************************// LefInViaRule::parseCutResistance()//// This function handles the RESISTANCE attribute for the current viaRule.// It sets the resistancePerCut attribute on the associated viaDef.// Prerequisite : the viaDef has already been created successfully.// *****************************************************************************voidLefInViaRule::parseCutResistance(oaStdViaDef *viaDef){ if (lefCutLayer->hasResistance()) { viaDef->setResistancePerCut(oaFloat(lefCutLayer->resistance())); }}// *****************************************************************************// LefInViaRule::parseOverhang()//// This function handles the OVERHANG attribute for the current viaRule.// It sets the layer2 and layer1 enclosures parameters from the OVERHANG// and DIRECTION attributes.// Note that in LEF both routing layers will have the same enclosure values.// *****************************************************************************voidLefInViaRule::parseOverhang(oaViaParam &viaParams){ oaInt4 enclosureX = 0; oaInt4 enclosureY = 0; if (lefLayer1->hasOverhang() || lefLayer2->hasOverhang()) { if (lefLayer1->hasOverhang()) { if (lefLayer1->isHorizontal()) { enclosureY = lefIn.uuToDBU(lefLayer1->overhang()); } else { enclosureX = lefIn.uuToDBU(lefLayer1->overhang()); } } if (lefLayer2->hasOverhang()) { if (lefLayer2->isHorizontal()) { enclosureY = lefIn.uuToDBU(lefLayer2->overhang()); } else { enclosureX = lefIn.uuToDBU(lefLayer2->overhang()); } } viaParams.setLayer1Enc(oaVector(enclosureX, enclosureY)); viaParams.setLayer2Enc(oaVector(enclosureX, enclosureY)); }}// *****************************************************************************// LefInViaRule::parseEnclosure()//// This function handles the ENCLOSURE attribute for the current viaRule.// *****************************************************************************voidLefInViaRule::parseEnclosure(oaViaParam &viaParams){ if (lefLayer1->hasEnclosure()) { oaInt4 enclosureX(lefIn.uuToDBU(lefLayer1->enclosureOverhang1())); oaInt4 enclosureY(lefIn.uuToDBU(lefLayer1->enclosureOverhang2())); viaParams.setLayer1Enc(oaVector(enclosureX, enclosureY)); } if (lefLayer2->hasEnclosure()) { oaInt4 enclosureX(lefIn.uuToDBU(lefLayer2->enclosureOverhang1())); oaInt4 enclosureY(lefIn.uuToDBU(lefLayer2->enclosureOverhang2())); viaParams.setLayer2Enc(oaVector(enclosureX, enclosureY)); }}// *****************************************************************************// LefInViaRule::parseCutSize()//// This function handles the RECT attribute for the current viaRule.// It sets the cutSize parameter of the specified viaParams.// *****************************************************************************voidLefInViaRule::parseCutSize(oaViaParam &viaParams){ oaInt4 xl = lefIn.uuToDBU(lefCutLayer->xl()); oaInt4 yl = lefIn.uuToDBU(lefCutLayer->yl()); oaInt4 xh = lefIn.uuToDBU(lefCutLayer->xh()); oaInt4 yh = lefIn.uuToDBU(lefCutLayer->yh()); oaInt4 sizeX = abs(xh - xl); oaInt4 sizeY = abs(yh - yl); viaParams.setCutWidth(sizeX); viaParams.setCutHeight(sizeY);}// *****************************************************************************// LefInViaRule::parseCutSpacing()//// This function handles the SPACING attribute for the current viaRule.// It sets the cutSpacing parameter of the specified viaParams.// OA Cut Spacing is edge to edge while LEF spacing is center to center.// *****************************************************************************voidLefInViaRule::parseCutSpacing(oaViaParam &viaParams){ oaInt4 lefSpacingX = lefIn.uuToDBU(lefCutLayer->spacingStepX()); oaInt4 lefSpacingY = lefIn.uuToDBU(lefCutLayer->spacingStepY()); oaInt4 spacingX = lefSpacingX - viaParams.getCutWidth(); oaInt4 spacingY = lefSpacingY - viaParams.getCutHeight(); viaParams.setCutSpacing(oaVector(spacingX, spacingY));}// *****************************************************************************// LefInViaRule::parseWidthRanges()//// This function handles the WIDTH ranges attributes for the current viaRule.// *****************************************************************************voidLefInViaRule::parseWidthRanges(){ if (lefLayer1->hasWidth() && lefLayer2->hasWidth()) { rowMin = getRowIndex(lefIn.uuToDBU(lefLayer1->widthMin())); colMin = getColIndex(lefIn.uuToDBU(lefLayer2->widthMin())); rowMax = getRowIndex(lefIn.uuToDBU(lefLayer1->widthMax()) + 1); colMax = getColIndex(lefIn.uuToDBU(lefLayer2->widthMax()) + 1); }}// *****************************************************************************// LefInViaRule::parseVias()// // This function handles the VIA attributes for the current via rule// *****************************************************************************voidLefInViaRule::parseVias(oaViaDefArray &array){ for (oaInt4 i = 0; i != lefViaRule->numVias(); i++) { oaString viaName(lefViaRule->viaName(i)); oaViaDef *viaDef = oaViaDef::find(lefIn.tech(), viaName); if (!viaDef || (viaDef->getType() == oacStdViaDefType && !lefIn.getOptions()->doUseDefaultStdVias())) { viaName += "_"; viaName += cLefViaDesignName; viaDef = oaViaDef::find(lefIn.tech(), viaName); if (!viaDef) { throw LefDefError(cViaRuleViaNotFound, lefViaRule->name(), (const char*) viaName); } } if (array.find(viaDef) == oacNullIndex) { array.append(viaDef); } }}// *****************************************************************************// LefInViaRule::parseProperties()// // This function handles the PROPERTY attributes for the current via rule// *****************************************************************************voidLefInViaRule::parseProperties(){ LefDefProp *propDef; for (int i = 0; i < lefViaRule->numProps(); i++) { propDef = lefIn.getProp(lefViaRule->propName(i), cLefDefViaRule); lefIn.createProp(propDef, viaRule, lefViaRule->propValue(i)); }}// *****************************************************************************// LefInViaRule::getRowIndex()// LefInViaRule::getColumnIndex()// // This function returns the table index for the specified header/row/column.// If an entry does not exist, it is inserted at the appropriate place, and// all existing data is moved up.// *****************************************************************************oaUInt4LefInViaRule::getRowIndex(oaInt4 row){ oaUInt4 numRows = viaTable.getNumRows(); oaUInt4 index = 0; for (; index < numRows; index++) { if (viaTable.getRowHeader(index) == row) { return index; } if (viaTable.getRowHeader(index) > row) { break; } } viaTable.setNumRows(numRows + 1); for (oaUInt4 i = numRows; i >= index && i > 0; i--) { viaTable.setRowHeader(i, viaTable.getRowHeader(i - 1)); for (oaUInt4 j = 0; j < viaTable.getNumCols(); j++) { viaTable.setValue(i, j, viaTable.getValue(i - 1, j)); } } viaTable.setRowHeader(index, row); for (oaUInt4 i = 0; i < viaTable.getNumCols(); i++) { oaValue *v = index > 0 ? viaTable.getValue(index - 1, i) : NULL; viaTable.setValue(index, i, v ? (oaViaDefArrayValue*) v->copy() : NULL); } return index;}oaUInt4LefInViaRule::getColIndex(oaInt4 column){ oaUInt4 numCols = viaTable.getNumCols(); oaUInt4 index = 0; for (; index < numCols; index++) { if (viaTable.getColHeader(index) == column) { return index; } if (viaTable.getColHeader(index) > column) { break; } } viaTable.setNumCols(numCols + 1); for (oaUInt4 i = numCols; i >= index && i > 0; i--) { viaTable.setColHeader(i, viaTable.getColHeader(i - 1)); for (oaUInt4 j = 0; j < viaTable.getNumRows(); j++) { viaTable.setValue(j, i, viaTable.getValue(j, i - 1)); } } viaTable.setColHeader(index, column); for (oaUInt4 i = 0; i < viaTable.getNumRows(); i++) { oaValue *v = index > 0 ? viaTable.getValue(i, index - 1) : NULL; viaTable.setValue(i, index, v ? (oaViaDefArrayValue*) v->copy() : NULL); } return index;}END_LEFDEF_NAMESPACE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -