📄 oalefinlayer.cpp
字号:
oacMinAdjacentViaSpacing, layer->getNumber(), v, true, ¶ms); } else { oaLayerConstraintType type = oacMinSpacing; if (lefLayer->hasSpacingCenterToCenter(i)) { type = oacMinCenterToCenterSpacing; } oaValue *v = oaIntValue::create(lefIn.tech(), lefIn.uuToDBU(lefLayer->spacing(i))); lefIn.setConstraint(lefIn.getFoundryRules(), type, layer->getNumber(), v); } } }}// *****************************************************************************// LefInLayer::parseEnclosure()// LefInLayer::parsePreferredEnclosure()// LefInLayer::parseEnclosureMetal()// // These functions handle the ENCLOSURE attributes for the specified layer.//// Syntax:// [ENCLOSURE [ABOVE | BELOW] overhang1 overhang2 [WIDTH minWidth] ;] ...// [PREFERENCLOSURE [ABOVE | BELOW overhang1 overhang2 [WIDTH minWidth] ;] ...// // The ENCLOSURE for cut layers is stored in OA using oaDualIntValue for the// oacMinDualExtension constraint in the foundryRules constraint group, on the// metal layers above and below the cut layer.//// If multiple, width based, rules are present they are grouped together in an// oaoaDualInt1DTblValue, which is indexed by WIDTH.//// Normal ENCLOSURE attributes are mapped to hard constraints, and PREFERRED// ENCLOSURE attributes are mapped to soft constraints in the FoundryRules.// *****************************************************************************voidLefInLayer::parseEnclosure(){ oa1DLookupTbl<oaInt4, oaInt4> firstTableBelow; oa1DLookupTbl<oaInt4, oaInt4> secondTableBelow; oa1DLookupTbl<oaInt4, oaInt4> firstTableAbove; oa1DLookupTbl<oaInt4, oaInt4> secondTableAbove; oaPhysicalLayer *layerBelow = layer->getLayerBelow(oacMetalMaterial); // Retrieve any values already on the layer below. if (layerBelow) { oaValue *v = lefIn.getConstraint(lefIn.getFoundryRules(), oacMinDualExtension, layerBelow->getNumber(), layer->getNumber(), NULL, true, true); if (v && v->getType() == oacDualInt1DTblValueType) { ((oaDualInt1DTblValue*) v)->getFirst(firstTableBelow); ((oaDualInt1DTblValue*) v)->getSecond(secondTableBelow); } } // Add the new values to the tables. for (int i = 0; i < lefLayer->numEnclosure(); i++) { oaUInt4 ext1 = lefIn.uuToDBU(lefLayer->enclosureOverhang1(i)); oaUInt4 ext2 = lefIn.uuToDBU(lefLayer->enclosureOverhang2(i)); oaUInt4 width = 0; if (lefLayer->hasEnclosureWidth(i)) { width = lefIn.uuToDBU(lefLayer->enclosureMinWidth(i)); } if (!lefLayer->hasEnclosureRule(i) || !strcmp(lefLayer->enclosureRule(i), "BELOW")) { oaUInt4 firstIndex = getIndex(firstTableBelow, width); oaUInt4 secondIndex = getIndex(secondTableBelow, width); firstTableBelow.setValue(firstIndex, ext1); secondTableBelow.setValue(secondIndex, ext2); } if (!lefLayer->hasEnclosureRule(i) || !strcmp(lefLayer->enclosureRule(i), "ABOVE")) { oaUInt4 firstIndex = getIndex(firstTableAbove, width); oaUInt4 secondIndex = getIndex(secondTableAbove, width); firstTableAbove.setValue(firstIndex, ext1); secondTableAbove.setValue(secondIndex, ext2); } } // Set the constraint for the layer below if (firstTableBelow.getNumItems() > 0 && layerBelow) { oaValue *value; if (firstTableBelow.getNumItems() == 1) { value = oaDualIntValue::create(lefIn.tech(), firstTableBelow.getValue(0), secondTableBelow.getValue(0)); } else { value = oaDualInt1DTblValue::create(lefIn.tech(), firstTableBelow, secondTableBelow); } lefIn.setConstraint(lefIn.getFoundryRules(), oacMinDualExtension, layerBelow->getNumber(), layer->getNumber(), value); } // Temporarily store the constraint for layerAbove on the first tech layer. oaIter<oaLayer> layerIt(lefIn.tech()->getLayers()); oaLayer *otherLayer = layerIt.getNext(); if (firstTableAbove.getNumItems() > 0 && otherLayer) { oaValue *value; if (firstTableAbove.getNumItems() == 1) { value = oaDualIntValue::create(lefIn.tech(), firstTableAbove.getValue(0), secondTableAbove.getValue(0)); } else { value = oaDualInt1DTblValue::create(lefIn.tech(), firstTableAbove, secondTableAbove); } lefIn.setConstraint(lefIn.getFoundryRules(), oacMinDualExtension, layer->getNumber(), otherLayer->getNumber(), value); }}voidLefInLayer::parsePreferredEnclosure(){ oa1DLookupTbl<oaInt4, oaInt4> firstTableBelow; oa1DLookupTbl<oaInt4, oaInt4> secondTableBelow; oa1DLookupTbl<oaInt4, oaInt4> firstTableAbove; oa1DLookupTbl<oaInt4, oaInt4> secondTableAbove; oaPhysicalLayer *layerBelow = layer->getLayerBelow(oacMetalMaterial); // Retrieve any values already on the layer below. if (layerBelow) { oaValue *v = lefIn.getConstraint(lefIn.getFoundryRules(), oacMinDualExtension, layerBelow->getNumber(), layer->getNumber(), NULL, false, false); if (v && v->getType() == oacDualInt1DTblValueType) { ((oaDualInt1DTblValue*) v)->getFirst(firstTableBelow); ((oaDualInt1DTblValue*) v)->getSecond(secondTableBelow); } } // Add the new values to the tables. for (int i = 0; i < lefLayer->numPreferEnclosure(); i++) { oaUInt4 ext1 = lefIn.uuToDBU(lefLayer->preferEnclosureOverhang1(i)); oaUInt4 ext2 = lefIn.uuToDBU(lefLayer->preferEnclosureOverhang2(i)); oaUInt4 width = 0; if (lefLayer->hasPreferEnclosureWidth(i)) { width = lefIn.uuToDBU(lefLayer->preferEnclosureMinWidth(i)); } if (!lefLayer->hasPreferEnclosureRule(i) || !strcmp(lefLayer->preferEnclosureRule(i), "BELOW")) { oaUInt4 firstIndex = getIndex(firstTableBelow, width); oaUInt4 secondIndex = getIndex(secondTableBelow, width); firstTableBelow.setValue(firstIndex, ext1); secondTableBelow.setValue(secondIndex, ext2); } if (!lefLayer->hasPreferEnclosureRule(i) || !strcmp(lefLayer->preferEnclosureRule(i), "ABOVE")) { oaUInt4 firstIndex = getIndex(firstTableAbove, width); oaUInt4 secondIndex = getIndex(secondTableAbove, width); firstTableAbove.setValue(firstIndex, ext1); secondTableAbove.setValue(secondIndex, ext2); } } // Set the soft constraint for the layer below if (firstTableBelow.getNumItems() > 0 && layerBelow) { oaValue *value; if (firstTableBelow.getNumItems() == 1) { value = oaDualIntValue::create(lefIn.tech(), firstTableBelow.getValue(0), secondTableBelow.getValue(0)); } else { value = oaDualInt1DTblValue::create(lefIn.tech(), firstTableBelow, secondTableBelow); } lefIn.setConstraint(lefIn.getFoundryRules(), oacMinDualExtension, layerBelow->getNumber(), layer->getNumber(), value, false); } // Temporarily store the constraint for layerAbove on the first tech layer. oaIter<oaLayer> layerIt(lefIn.tech()->getLayers()); oaLayer *otherLayer = layerIt.getNext(); if (firstTableAbove.getNumItems() > 0 && otherLayer) { oaValue *value; if (firstTableAbove.getNumItems() == 1) { value = oaDualIntValue::create(lefIn.tech(), firstTableAbove.getValue(0), secondTableAbove.getValue(0)); } else { value = oaDualInt1DTblValue::create(lefIn.tech(), firstTableAbove, secondTableAbove); } lefIn.setConstraint(lefIn.getFoundryRules(), oacMinDualExtension, layer->getNumber(), otherLayer->getNumber(), value, false); }}voidLefInLayer::parseEnclosureMetal(){ oaPhysicalLayer *cutBelow = layer->getLayerBelow(oacCutMaterial); if (!cutBelow) { return; } oaIter<oaLayer> layerIt(lefIn.tech()->getLayers()); oaLayer *otherLayer = layerIt.getNext(); if (!otherLayer) { return; } oaLayerPairConstraintDef *def = oaLayerPairConstraintDef::get(oacMinDualExtension); oaLayerPairConstraint *c; while (c = oaLayerPairConstraint::find(lefIn.getFoundryRules(), cutBelow->getNumber(), otherLayer->getNumber(), def)) { lefIn.setConstraint(lefIn.getFoundryRules(), oacMinDualExtension, layer->getNumber(), cutBelow->getNumber(), c->getValue()->copy(), c->isHard()); c->destroy(); } while (c = oaLayerPairConstraint::find(lefIn.getDefaultRules(), cutBelow->getNumber(), otherLayer->getNumber(), def)) { lefIn.setConstraint(lefIn.getDefaultRules(), oacMinDualExtension, layer->getNumber(), cutBelow->getNumber(), c->getValue()->copy(), c->isHard()); c->destroy(); }}// *****************************************************************************// LefInLayer::parseSpacing()// LefInLayer::parseSpacingInfluence()// // These functions handle the Spacing attributes for the specified layer.//// Syntax:// [SPACING minSpacing// [ RANGE minWidth maxWidth// [ USELENGTHTHRESHOLD// | INFLUENCE value [RANGE stubMinWidth stubMaxWidth]// | RANGE minWidth maxWidth]// | LENGTHTHRESHOLD maxLength [RANGE minWidth maxWidth]// ]// ;] ...//// SPACING rules are stored in OA as an oaIntValue for the oacMinSpacing// constraint in the foundry rules, and the generic (no range)// spacing is also set as the spacing value on the LEFDefaultRouteSpec// constraint group.//// If multiple RANGE (width) based rules are present, the values are grouped// together in an oaInt1DTblValue, which is indexed by width.//// If LENGTHTHRESHOLD spacing rules are present, all SPACING rules are grouped// together in an oaInt2DTblValue, indexed by width and length.// *****************************************************************************voidLefInLayer::parseSpacing(){ if (!lefLayer->hasSpacingNumber()) { return; } oa2DLookupTbl<oaInt4, oaInt4, oaInt4> table(0, 0, "width", "length", 0, oacSnapDownInterpolateType, oacInclusiveSnapDownInterpolateType); // First process the generic spacing value, then all spacing ranges, and // then process the length-threshold values so that the table will inherit // the right spacing values for ranges to which the length-threshold does // not apply. // Simple spacing rules. oaInt4 width = lefIn.getLayerWidth(lefIn.getFoundryRules(), layer->getNumber()); for (oaInt4 i = 0; i < lefLayer->numSpacing(); i++) { if (lefLayer->hasSpacingRangeInfluence(i) || lefLayer->hasSpacingLengthThreshold(i)) { continue; } // This could be an "implicit" generic spacing if the lower limit is // less or equal to the minimum width. if (lefLayer->hasSpacingRange(i) && lefIn.uuToDBU(lefLayer->spacingRangeMin(i)) > width) { continue; } // Store the generic spacing in location 0, 0 of the table, and in the // table's default value. oaInt4 spacing = lefIn.uuToDBU(lefLayer->spacing(i)); oaUInt4 w = getRowIndex(table, 0); oaUInt4 l = getColIndex(table, 0); table.setValue(w, l, spacing); table.setDefaultValue(spacing); } // LENGTHTHRESHOLD spacing rules for (oaInt4 i = 0; i < lefLayer->numSpacing(); i++) { if (lefLayer->hasSpacingLengthThreshold(i)) { oaInt4 spacing = lefIn.uuToDBU(lefLayer->spacing(i)); oaInt4 width = 0; oaUInt4 wm = table.getNumRows(); oaInt4 length = lefIn.uuToDBU(lefLayer->spacingLengthThreshold(i)); // Determine the applicable width range for this spacing value. // We add an extra column for the start of the next range. if (lefLayer->hasSpacingLengthThresholdRange(i)) { width = lefIn.uuToDBU(lefLayer->spacingLengthThresholdRangeMin(i)); oaInt4 widthMax = lefIn.uuToDBU(lefLayer->spacingLengthThresholdRangeMax(i)) + 1; wm = getRowIndex(table, widthMax); } // Store the spacing value in all width entries between the column // for the minimum width (inclusive) and the column for the start // of the next range. oaUInt4 w = getRowIndex(table, width); oaUInt4 l = getColIndex(table, length); for (oaUInt4 j = w; j < wm; j++) { if (l) { table.setValue(j, l - 1, spacing); } else { table.setValue(j, l, spacing); } } } } // RANGE spacing rules with USELENGHTTHRESHOLD // (note: upper limit ignored) for (oaInt4 i = 0; i < lefLayer->numSpacing(); i++) { if (lefLayer->hasSpacingRangeInfluence(i) || lefLayer->hasSpacingLengthThreshold(i) || !lefLayer->hasSpacingRange(i) || !lefLayer->hasSpacingRangeUseLengthThreshold(i)) { continue; } oaInt4 spacing = lefIn.uuToDBU(lefLayer->spacing(i)); oaInt4 width = lefIn.uuToDBU(lefLayer->spacingRangeMin(i)); oaUInt4 w = getRowIndex(table, width); oaUInt4 l = table.getNumCols() - 1; table.setValue(w, l, spacing); } // RANGE spacing rules without USELENGTHTHRESHOLD // (note: upper limit ignored) for (oaInt4 i = 0; i < lefLayer->numSpacing(); i++) { if (lefLayer->hasSpacingRangeInfluence(i) || lefLayer->hasSpacingLengthThreshold(i) || !lefLayer->hasSpacingRange(i) || lefLayer->hasSpacingRangeUseLengthThreshold(i)) { continue; } // Skip implicit default spacing rules here.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -