📄 oalefinmacro.cpp
字号:
// *****************************************************************************// *****************************************************************************// LefInMacro.cpp//// Functions to handle LEF MACRO constructs.//// *****************************************************************************// 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.66 $// $Date: 2005/06/24 12:32:32 $// $State: Exp $// *****************************************************************************// *****************************************************************************#include "oaLefDef.h"BEGIN_LEFDEF_NAMESPACE// *****************************************************************************// LefInMacro::LefInMacro()// LefInMacro::~LefInMacro()//// This is the constructor for the LefInMacro class. // *****************************************************************************LefInMacro::LefInMacro(LefIn &translator): lefIn(translator){ translator.lefInMacro = this;}LefInMacro::~LefInMacro(){}// *****************************************************************************// LefInMacro::init()//// This function resets any data stored on this object.// *****************************************************************************voidLefInMacro::init(){ overlapPoints.setNumElements(0);}// *****************************************************************************// LefInMacro::parse()//// This function handles all MACRO attributes that are specified in the CAT// parser datastructure. It calls a separate function for each attribute.// *****************************************************************************voidLefInMacro::parse(lefiMacro *data){ lefMacro = data; parseClass(); parseSnapBoundary(); parsePRBoundary(); parseForeign(); parseEEQ(); parseSymmetry(); parseSite(); parseProperties();}// *****************************************************************************// LefInMacro::parseForeign()//// This function handles the FOREIGN attribute of the current LEF macro.// *****************************************************************************voidLefInMacro::parseForeign(){ oaInt4 originX = 0; oaInt4 originY = 0; if (lefMacro->hasOrigin()) { originX = lefIn.uuToDBU(lefMacro->originX()); originY = lefIn.uuToDBU(lefMacro->originY()); } oaBoolean shifted = lefIn.design()->getMode() == 'a'; oaDesign *foreignView = NULL; for (int i = 0; i < lefMacro->numForeigns(); i++) { oaInt4 foreignX = 0; oaInt4 foreignY = 0; oaOrient orient = oacR0; if (lefMacro->hasForeignPoint(i)) { foreignX = lefIn.uuToDBU(lefMacro->foreignX(i)); foreignY = lefIn.uuToDBU(lefMacro->foreignY(i)); } if (lefMacro->hasForeignOrient(i)) { orient = lefIn.getOrient(lefMacro->foreignOrient(i)); } // For same name FOREIGN statement, just shift the geometry // Note: we don't handle non-north for this case. if (!strcmp(lefMacro->name(), lefMacro->foreignName(i))) { if (!shifted) { shiftGeometry(oaTransform(foreignX + originX, foreignY + originY)); shifted = true; } continue; } // For non-same name FOREIGN statements, open a layout view, // and instantiate (by name) the FOREIGN cell. oaTransform xform(-foreignX, -foreignY, orient); oaScalarName cellName(lefIn.getNS(), lefMacro->name()); if (!foreignView) { foreignView = oaDesign::open(lefIn.getOptions()->getLibName(), cellName, lefIn.getOptions()->getLayoutName(), oaViewType::get(oacMaskLayout), 'w'); if (!foreignView->getTopBlock()) { oaBlock::create(foreignView); } } cellName.init(lefIn.getNS(), lefMacro->foreignName(i)); oaScalarInst::create(foreignView->getTopBlock(), lefIn.getOptions()->getLibName(), cellName, lefIn.getOptions()->getViewName(), xform); } // If a foreign view was created, add a boolean property indicating this. if (foreignView) { lefIn.setBooleanProp(lefIn.design(), cLefForeignView, true); foreignView->save(); foreignView->purge(); } // If no foreign was specified, shift the geometry to start at 0, 0. if (!shifted) { shiftGeometry(oaTransform(originX, originY)); }}// *****************************************************************************// LefInMacro::parseClass()//// This function stores the cellType information// (given by the MACRO 'CLASS' construct) on the current design.// *****************************************************************************voidLefInMacro::parseClass(){ if (!lefMacro->hasClass()) { if (lefIn.design()->getCellType() == oacNoCellType) { lefIn.design()->setCellType(oacCoreCellType); } return; } oaString macroClass(lefMacro->macroClass()); oaUInt4 sepIndex(macroClass.index(' ')); oaString classStr(macroClass, sepIndex); oaString classOptStr; if (++sepIndex < macroClass.getLength()) { classOptStr = ¯oClass[sepIndex]; } if (classStr == "COVER") { lefIn.design()->setCellType(oacCoverCellType); if (classOptStr == "BUMP") { lefIn.design()->setCellType(oacCoverBumpCellType); } } else if (classStr == "RING") { lefIn.design()->setCellType(oacBlockRingCellType); } else if (classStr == "BLOCK") { lefIn.design()->setCellType(oacBlockCellType); if (classOptStr == "BLACKBOX") { lefIn.design()->setCellType(oacBlockBlackBoxCellType); } else if (classOptStr == "SOFT") { lefIn.design()->setCellType(oacSoftMacroCellType); } } else if (classStr == "PAD") { lefIn.design()->setCellType(oacPadCellType); if (classOptStr == "SPACER") { lefIn.design()->setCellType(oacPadSpacerCellType); } else if (classOptStr == "AREAIO") { lefIn.design()->setCellType(oacPadAreaIOCellType); } } else if (classStr == "CORE") { lefIn.design()->setCellType(oacCoreCellType); if (classOptStr == "SPACER") { lefIn.design()->setCellType(oacCoreSpacerCellType); } else if (classOptStr == "ANTENNACELL") { lefIn.design()->setCellType(oacCoreAntennaCellType); } else if (classOptStr == "WELLTAP") { lefIn.design()->setCellType(oacCoreWellTapCellType); } } else if (classStr == "ENDCAP") { lefIn.design()->setCellType(oacCoreSpacerCellType); if (classOptStr == "TOPLEFT") { lefIn.design()->setCellType(oacCornerCellType); lefIn.setProp(lefIn.design(), cLefCorner, "TOPLEFT"); } else if (classOptStr == "TOPRIGHT") { lefIn.design()->setCellType(oacCornerCellType); lefIn.setProp(lefIn.design(), cLefCorner, "TOPRIGHT"); } else if (classOptStr == "BOTTOMLEFT") { lefIn.design()->setCellType(oacCornerCellType); lefIn.setProp(lefIn.design(), cLefCorner, "BOTTOMLEFT"); } else if (classOptStr == "BOTTOMRIGHT") { lefIn.design()->setCellType(oacCornerCellType); lefIn.setProp(lefIn.design(), cLefCorner, "BOTTOMRIGHT"); } }}// *****************************************************************************// LefInMacro::parseSnapBoundary()//// This function creates a (rectangular) Snap Boundary object with the size// of the current macro.// If origin is not 0 0, lower left point will be offset by -originX, -originY.// *****************************************************************************voidLefInMacro::parseSnapBoundary(){ if (!lefMacro->hasSize()) { return; } oaSnapBoundary *snap = oaSnapBoundary::find(lefIn.topBlock()); if (!snap) { oaUInt4 sizeX(lefIn.uuToDBU(lefMacro->sizeX())); oaUInt4 sizeY(lefIn.uuToDBU(lefMacro->sizeY())); oaInt4 originX = 0; oaInt4 originY = 0; if (lefMacro->hasOrigin()) { originX = lefIn.uuToDBU(lefMacro->originX()); originY = lefIn.uuToDBU(lefMacro->originY()); } oaPointArray bBox(4); bBox.append(oaPoint(-originX, -originY)); bBox.append(oaPoint(-originX, -originY + sizeY)); bBox.append(oaPoint(-originX + sizeX, -originY + sizeY)); bBox.append(oaPoint(-originX + sizeX, -originY)); oaSnapBoundary::create(lefIn.topBlock(), bBox); }}// *****************************************************************************// LefInMacro::parsePRBoundary()//// This function creates a PRBoundary object for the current macro.// If a prBoundary does not exists already (from the overlap layer shapes), it// creates a prBoundary using the same rectangle as snapBoundary.// *****************************************************************************voidLefInMacro::parsePRBoundary(){ oaPRBoundary *prB = oaPRBoundary::find(lefIn.topBlock()); if (prB) { return; } oaPointArray prPoints; if (!overlapPoints.getNumElements()) { oaSnapBoundary *snap = oaSnapBoundary::find(lefIn.topBlock()); if (!snap) { return; } snap->getPoints(prPoints); } else { prPoints = overlapPoints[0]; deleteOverlapPoints(0); oaUInt4 lastNumUsed(0); while (overlapPoints.getNumElements() && (overlapPoints.getNumElements() != lastNumUsed)) { lastNumUsed = overlapPoints.getNumElements(); for (oaUInt4 i = 0; i < overlapPoints.getNumElements(); i++) { oaBox box; overlapPoints[i].getBBox(box); if (prPoints.overlaps(box)) { mergePointArray(prPoints, overlapPoints[i]); deleteOverlapPoints(i--); } } } } if (overlapPoints.getNumElements()) { throw LefDefError(cMacroNonContinuosOverlap, lefMacro->name()); } oaPRBoundary::create(lefIn.topBlock(), prPoints);}// *****************************************************************************// LefInMacro::parseEEQ()//// This function handles the EEQMASTER attribute of the current LEF macro.// A list of processed cells is stored on LefIn, and this function// searches that list to find its EEQ master design.// *****************************************************************************voidLefInMacro::parseEEQ(){ oaString eeq = lefMacro->name(); if (lefMacro->hasEEQ()) { if (!eeqTbl.find(lefMacro->EEQ(), eeq)) { throw LefDefError(cMacroEEQMasterNotFound, lefMacro->name(), lefMacro->EEQ()); } lefIn.topBlock()->setEEQMaster(eeq); } eeqTbl.insert(lefMacro->name(), eeq);}// *****************************************************************************// LefInMacro::parseSymmetry()//// This function handles the SYMMETRY attribute of the current LEF macro.// Here's the mapping from LEF to OA:// X Y R90 oaSymmetry
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -