📄 oalefinlayer.cpp
字号:
if (lefLayer->spacingRangeMin(i) <= lefLayer->width()) { continue; } oaInt4 spacing = lefIn.uuToDBU(lefLayer->spacing(i)); oaInt4 width = lefIn.uuToDBU(lefLayer->spacingRangeMin(i)); oaUInt4 w = getRowIndex(table, width); for (oaUInt4 j = 0; j < table.getNumCols(); j++) { table.setValue(w, j, spacing); } } // Set the correct spacing rule type based on the values in the table. // simple spacing values are reduced to an oaIntValue, and width-based-only // spacing values are reduced to a 1D lookup table. oaValue *value = NULL; if (table.getNumRows() == 1 && table.getNumCols() == 1) { value = oaIntValue::create(lefIn.tech(), table.getValue(0, 0)); } else if (table.getNumCols() == 1) { oa1DLookupTbl<oaInt4, oaInt4> table1D(table.getNumRows(), "width", 0, oacSnapDownInterpolateType); table1D.setDefaultValue(table.getDefaultValue()); for (oaUInt4 j = 0; j < table.getNumRows(); j++) { table1D.setHeader(j, table.getRowHeader(j)); table1D.setValue(j, table.getValue(j, 0)); } value = oaInt1DTblValue::create(lefIn.tech(), table1D); } else if (table.getNumRows() && table.getNumCols()) { value = oaInt2DTblValue::create(lefIn.tech(), table); } if (value) { lefIn.setConstraint(lefIn.getFoundryRules(), oacMinSpacing, layer->getNumber(), value); }}voidLefInLayer::parseSpacingInfluence(){ if (lefLayer->hasSpacingNumber()) { oa2DLookupTbl<oaInt4, oaInt4, oaInt4> table(0, 0, "width", "distance", 0, oacSnapDownInterpolateType, oacInclusiveSnapDownInterpolateType); for (oaInt4 i = 0; i < lefLayer->numSpacing(); i++) { if (!lefLayer->hasSpacingRange(i) || !lefLayer->hasSpacingRangeInfluence(i)) { continue; } oaUInt4 width = lefIn.uuToDBU(lefLayer->spacingRangeMin(i)); oaUInt4 length = lefIn.uuToDBU(lefLayer->spacingRangeInfluence(i)); oaUInt4 w = getRowIndex(table, width); oaUInt4 l = getColIndex(table, length); table.setValue(w, l, lefIn.uuToDBU(lefLayer->spacing(i))); } if (table.getNumRows() && table.getNumCols()) { oaValue *value = oaInt2DTblValue::create(lefIn.tech(), table); lefIn.setConstraint(lefIn.getFoundryRules(), oacMinProtrudedProximitySpacing, layer->getNumber(), value); } }}// *****************************************************************************// LefInLayer::parseSpacingTable()// LefInLayer::parseSpacingTableInfluence()//// These functions handle the Spacing Tables (5.5) for this layer.//// Syntax:// [SPACINGTABLE// PARALLELRUNLENGTH {length} ...// {WIDTH width {spacing} ...} ... ;// [SPACINGTABLE// INFLUENCE {WIDTH width WITHIN distance SPACING spacing} ... ;// ]// ]// // The SPACINGTABLE is stored in OA using an oaInt2DTblValue for the// oacMinSpacing constraint in the foundry rules constraint group.//// The SPACINGTABLE INFLUENCE is stored in OA using an oaInt2DTblValue for the// oacMinProximitySpacing constraint in the foundry rules constraint group.// *****************************************************************************voidLefInLayer::parseSpacingTable(){ for (oaInt4 i = 0; i < lefLayer->numSpacingTable(); i++) { lefiSpacingTable *lefSpacing = lefLayer->spacingTable(i); if (lefSpacing->isInfluence()) { continue; } lefiParallel *parallel = lefSpacing->parallel(); oa2DLookupTbl<oaInt4, oaInt4, oaInt4> table(parallel->numWidth(), parallel->numLength(), "width", "length", 0, oacSnapDownInterpolateType, oacInclusiveSnapDownInterpolateType); for (oaInt4 w = 0; w < parallel->numWidth(); w++) { oaUInt4 width = lefIn.uuToDBU(parallel->width(w)); table.setRowHeader(w, width ? width + 1 : 0); for (oaInt4 l = 0; l < parallel->numLength(); l++) { table.setColHeader(l, lefIn.uuToDBU(parallel->length(l))); table.setValue(w, l, lefIn.uuToDBU(parallel->widthSpacing(w, l))); } } oaValue *value = oaInt2DTblValue::create(lefIn.tech(), table); lefIn.setConstraint(lefIn.getFoundryRules(), oacMinSpacing, layer->getNumber(), value); }}voidLefInLayer::parseSpacingTableInfluence(){ for (oaInt4 i = 0; i < lefLayer->numSpacingTable(); i++) { lefiSpacingTable *lefSpacing = lefLayer->spacingTable(i); if (!lefSpacing->isInfluence()) { continue; } lefiInfluence *influence = lefSpacing->influence(); oa2DLookupTbl<oaInt4, oaInt4, oaInt4> table(0, 0, "width", "distance", 0, oacInclusiveSnapDownInterpolateType, oacInclusiveSnapDownInterpolateType); for (oaInt4 j = 0; j < influence->numInfluenceEntry(); j++) { oaUInt4 w = getRowIndex(table, lefIn.uuToDBU(influence->width(j))); oaUInt4 d = getColIndex(table, lefIn.uuToDBU(influence->distance(j))); table.setValue(w, d, lefIn.uuToDBU(influence->spacing(j))); } if (table.getNumRows()) { oaValue *value = oaInt2DTblValue::create(lefIn.tech(), table); lefIn.setConstraint(lefIn.getFoundryRules(), oacMinProximitySpacing, layer->getNumber(), value); } } }// *****************************************************************************// LefInLayer::parseWireExt()// // This function handles the WIREEXTENSION attribute for the current layer.//// Syntax:// [WIREEXTENSION value ; ]// // The WIREEXTENSION value is stored in OA using an oaIntValue for the// oacMinWireExtension constraint in the LEFDefaultRouteSpec constraint group.// *****************************************************************************voidLefInLayer::parseWireExt(){ if (lefLayer->hasWireExtension()) { oaValue *v = oaIntValue::create(lefIn.tech(), lefIn.uuToDBU(lefLayer->wireExtension())); lefIn.setConstraint(lefIn.getDefaultRules(), oacMinWireExtension, layer->getNumber(), v); }}// *****************************************************************************// LefInLayer::parseMinCut()// // This function handles the minimumCut attributes for the specified layer.// Since minimumcut rules are stored on CUT layers in OA, we store them// on metal layers temporarily in LefInLayer::parseMinCutMetal, and this// function moves it onto the current CUT layer...// *****************************************************************************voidLefInLayer::parseMinCut(){ oaPhysicalLayer *layerBelow = layer->getLayerBelow(oacMetalMaterial); if (!layerBelow) { return; } oaLayerConstraintDef *def = oaLayerConstraintDef::get(oacMinNumCut); oaConstraint *c = oaLayerConstraint::find(lefIn.getFoundryRules(), layerBelow->getNumber(), def); if (c) { lefIn.setConstraint(lefIn.getFoundryRules(), oacMinNumCut, layer->getNumber(), c->getValue()->copy()); c->destroy(); } def = oaLayerConstraintDef::get(oacMinProtrusionNumCut); c = oaLayerConstraint::find(lefIn.getFoundryRules(), layerBelow->getNumber(), def); if (c) { oaConstraintParamArray params; c->getParams(params); oaConstraintParamArray params2(3); params2.append(params[0]->copy()); params2.append(params[1]->copy()); params2.append(params[2]->copy()); lefIn.setConstraint(lefIn.getFoundryRules(), oacMinProtrusionNumCut, layer->getNumber(), c->getValue()->copy(), true, ¶ms2); c->destroy(); }}// *****************************************************************************// LefInLayer::parseMinCutMetal()// // This function handles the minimumCut attributes for the specified layer.// MinCut rules are stored only on the cut layers in OA.// Rules for the cut layer above are temporarily stored on the current// metal layer, since the cut layer above does not exist yet.// They are moved to the cut layer by LefInLayer::parseMinCut.//// MINIMUMCUT <numCuts> WIDTH <width> [FROMABOVE | FROMBELOW]// The oacMinNumCut constraint should be set on the cut layer.// (Determined using FROMABOVE, FROMLBEOW).// Because there can be several of these statements the value should be an// oa1DLookupTbl with the lookup (width) value (numcuts).// *****************************************************************************voidLefInLayer::parseMinCutMetal(){ if (!lefLayer->numMinimumcut()) { return; } oaLayer *layerBelow = layer->getLayerBelow(oacCutMaterial); oa1DLookupTbl<oaInt4, oaInt4> tableBelow(0, "width", 1, oacSnapDownInterpolateType, oacSnapDownExtrapolateType, oacSnapDownExtrapolateType); oa1DLookupTbl<oaInt4, oaInt4> tableAbove(0, "width", 1, oacSnapDownInterpolateType, oacSnapDownExtrapolateType, oacSnapDownExtrapolateType); oaConstraint *c; for (oaInt4 i = 0; i < lefLayer->numMinimumcut(); i++) { // Handle the oacMinProtrusionNumCut constraint if (lefLayer->hasMinimumcutNumCuts(i)) { continue; } // Fill the minCut tables oaInt4 width = lefIn.uuToDBU(lefLayer->minimumcutWidth(i)); if (!lefLayer->hasMinimumcutConnection(i) || !strcmp(lefLayer->minimumcutConnection(i), "FROMBELOW")) { for (oaUInt4 j(0); j < tableBelow.getNumItems(); j++) { if ((tableBelow.getValue(j) == lefLayer->minimumcut(i)) && (tableBelow.getHeader(j) < width)) { lefIn.warn(cLayerMinCutRedundant, lefLayer->name(), lefLayer->minimumcut(i), lefLayer->minimumcutWidth(i)); width = tableBelow.getHeader(j); } } tableBelow.setValue(getIndex(tableBelow, width), lefLayer->minimumcut(i)); } if (!lefLayer->hasMinimumcutConnection(i) || !strcmp(lefLayer->minimumcutConnection(i), "FROMABOVE")) { for (oaUInt4 j(0); j < tableAbove.getNumItems(); j++) { if ((tableAbove.getValue(j) == lefLayer->minimumcut(i)) && (tableAbove.getHeader(j) < width)) { lefIn.warn(cLayerMinCutRedundant, lefLayer->name(), lefLayer->minimumcut(i), lefLayer->minimumcutWidth(i)); width = tableAbove.getHeader(j); } } tableAbove.setValue(getIndex(tableAbove, width), lefLayer->minimumcut(i)); } } oaLayerConstraintDef *def = oaLayerConstraintDef::get(oacMinNumCut); if (layerBelow && tableBelow.getNumItems()) { c = oaLayerConstraint::find(lefIn.getFoundryRules(), layerBelow->getNumber(), def); if (c && c->getValue()->getType() == oacInt1DTblValueType) { oa1DLookupTbl<oaInt4, oaInt4> tablePrev(0, "width", 1); ((oaInt1DTblValue *) c->getValue())->get(tablePrev); for (oaUInt4 j(0); j < tablePrev.getNumItems(); j++) { for (oaUInt4 k(0); k < tableBelow.getNumItems(); k++) { if (tablePrev.getValue(j) == tableBelow.getValue(k)) { if (tablePrev.getHeader(j) < tableBelow.getHeader(k)) { tableBelow.setHeader(j, tablePrev.getHeader(k)); } break; } else if (k = tableBelow.getNumItems() - 1) { tableBelow.setValue(getIndex(tableBelow, tablePrev.getHeader(j)), tablePrev.getValue(j)); } } } c->setValue(oaInt1DTblValue::create(lefIn.tech(), tableBelow)); } else { oaValue *v = oaInt1DTblValue::create(lefIn.tech(), tableBelow); c = oaLayerConstraint::create(layerBelow->getNumber(), def, v); oaConstraintGroupMem::create(lefIn.getFoundryRules(), c); } } if (tableAbove.getNumItems()) { oaValue *v = oaInt1DTblValue::create(lefIn.tech(), tableAbove); c = oaLayerConstraint::create(layer->getNumber(), def, v); oaConstraintGroupMem::create(lefIn.getFoundryRules(), c); }}// *****************************************************************************// LefInLayer::parseMinProtrusionCut()// // This function handles the minimumCut attributes for the specified layer.// MinCut rules are stored only on the cut layers in OA.// Rules for the cut layer above are temporarily stored on the current// metal layer, since the cut layer above does not exist yet.// They are moved to the cut layer by LefInLayer::parseMinCut.//// MINIMUMCUT <numCuts> WIDTH <width> [FROMABOVE | FROMBELOW]// LENGTH <length> WITHIN <distance>// The oacMinProtrusionNumCut constraint should be set on the cut layer.// (Determined using FROMABOVE, FROMBELOW).// // OA allows only be one of these per layer. It should be represented as an// oaIntParam constraint with parameters (distance, length, width) and// value (numcuts). If multiple such rules are found in LEF, the most// conservative combination is taken.// *****************************************************************************voidLefInLayer::parseMinProtrusionCut(){ oaLayer *layerBelow = layer->getLayerBelow(oacCutMaterial); for (oaInt4 i = 0; i < lefLayer->numMinimumcut(); i++) { if (!lefLayer->hasMinimumcutNumCuts(i)) { continue; } oaInt4 dist = lefIn.uuToDBU(lefLayer->minimumcutDistance(i)); oaInt4 length = lefIn.uuToDBU(lefLayer->minimumcutLength(i)); oaInt4 width = lefIn.uuToDBU(lefLayer->minimumcutWidth(i)); oaInt4 numCut = lefLayer->minimumcut(i); if (layerBelow && (!lefLayer->hasMinimumcutConnection(i) || !strcmp(lefLayer->minimumcutConnection(i), "FROMBELOW"))) { setMinCutConstraint(layerBelow->getNumber(), dist, length, width, numCut); } if (!lefLayer->hasMinimumcutConnection(i) || !strcmp(lefLayer->minimumcutConnection(i), "FROMABOVE")) { setMinCutConstraint(layer->getNumber(), dist, length, width, numCut); } }}// *****************************************************************************// LefInLayer::parseCutRes()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -