📄 stdcellparams.java
字号:
NodeProto diffNode = mosLeft instanceof FoldedPmos ? tech.pdNode() : tech.ndNode(); double prevX = LayoutLib.roundCenterX(prevPort); double thisX = LayoutLib.roundCenterX(thisPort); double dist = thisX - prevX; // If they overlap perfectly or if they're so far apart there's no // select notch then no notches of any kind are possible. if (dist == 0 || (dist >= selectOverhangsDiffCont * 2 + tech.getSelectSpacingRule())) return; // Fill a notch with diffusion. // // I can't fill notches using a diffusion arc because the span in // the Y coordinate of the port of the diffusion contact may not // include the center of such an arc. This occurs for MOS // transistors with a single contact cut. // // I therefore fill the notch using a diffusion node. double mosY = mosLeft.getMosCenterY(); double mosRightY = mosRight.getMosCenterY(); // if they are not aligned along Y, the extra select node might not cover top transistor. if (!DBMath.areEquals(mosY, mosRightY)) { double activePlusSelect = diffWid/2 + tech.getSelectSurroundDiffInTrans(); double topY = -activePlusSelect, bottomY = activePlusSelect; double sign = 1; if (mosY > mosRightY) { topY += mosY; bottomY += mosRightY; sign = -1; } else { topY += mosRightY; bottomY += mosY; } double diff = DBMath.round(topY - bottomY); if (DBMath.isGreaterThan(diff, 0)) { // round diff to multiple of min precision otherwise diff/2 (or node center will generate DRC errors)// double minRe = f.getTechnology().getResolution()*2; double minRe = getGridResolution()*2; if (minRe > 0 && DBMath.hasRemainder(diff, minRe)) { diff += getGridResolution(); // to ceil correctlu otherwise it could leave a notch diff = ((int)(Math.ceil(diff/minRe))) * minRe; } diffWid += diff; mosY += DBMath.round(sign * diff/2); } } double a = mosLeft.getDiffContWidth(); double b = mosLeft.getGateWidth(); Rectangle2D diffNodeBnd = LayoutLib.calculateNodeInst(diffNode, thisX-dist/2, mosY, dist, diffWid); if (fillDiffNotch) { NodeInst dFill = LayoutLib.newNodeInst(diffNode, diffNodeBnd, 0, f); double contY = LayoutLib.roundCenterY(thisPort); // contact is always on grid LayoutLib.newArcInst(diffArc, DEF_SIZE, thisPort, thisX, contY, dFill.getOnlyPortInst(), LayoutLib.roundCenterX(dFill.getOnlyPortInst()), contY); // Never place wide arcs directly onto the FoldedMos // diffusion-metal1 contacts because they become bad width hints. if (dist < m1OverhangsDiffCont * 2 + m1Space) { // m1 is 1 lambda narrower than diffusion contact width double m1Wid = mosLeft.getDiffContWidth() - 1; NodeInst mFill = LayoutLib.newNodeInst(tech.m1Node(), thisX-dist/2, contY, dist, m1Wid, 0, f); LayoutLib.newArcInst(tech.m1(), DEF_SIZE, thisPort, mFill.getOnlyPortInst()); } } // Rounding values to avoid out-of-grid values double roundedPosY = DBMath.round(diffNodeBnd.getY() - diffNodeBnd.getHeight()/2); Rectangle2D selectRec = new Rectangle2D.Double(diffNodeBnd.getX() - dist/2, roundedPosY, diffNodeBnd.getWidth(), diffNodeBnd.getHeight()); double selectDiff = (a - b);// if (DBMath.isGreaterThan(selectDiff, 0)) addSelAroundDiff(diffNode, selectRec, selectDiff, f); } private static FoldedMos getRightMos(Object a) { if (a instanceof FoldedMos) return (FoldedMos) a; error(!(a instanceof FoldedMos[]), "not FoldedMos or FoldedMos[]"); FoldedMos[] moss = (FoldedMos[]) a; return moss[moss.length - 1]; } private static String trkMsg(Object key, Cell schem) { return "Track assignment for export: " + key + " in Cell: " + schem.getName() + ".\n "; } //----------------------------- public constants -------------------------- /** This class allows the user to specify which source/drains * wireVddGnd() should connect to power or ground. Most users will * be happy with the predefined instances: ODD or EVEN. */ public interface SelectSrcDrn { public boolean connectThisOne(int mosNdx, int srcDrnNdx); } public static final SelectSrcDrn EVEN = new SelectSrcDrn() { public boolean connectThisOne(int mosNdx, int srcDrnNdx) { return srcDrnNdx % 2 == 0; } }; public static final SelectSrcDrn ODD = new SelectSrcDrn() { public boolean connectThisOne(int mosNdx, int srcDrnNdx) { return srcDrnNdx % 2 == 1; } }; //------------------------ public methods -------------------------------------- //------------------------------------------------------------------------------ // Allow user to customize standard cell characteristics // /** Attach the well ties to special busses rather than to Vdd and Gnd. */ public void setDoubleStrapGate(boolean val) { doubleStrapGate = val; } /** GasP generators use exhaustive search for gate placement */ public void setExhaustivePlace(boolean val) { exhaustivePlace = val; } /** Set number of permuations GasP placer should try before giving * up. */ public void setNbPlacerPerms(int i) { nbPlacerPerms = i; } /** Units of lambda */ public void setNmosWellHeight(double h) { nmosWellHeight = h; init(); } /** Units of lambda */ public void setPmosWellHeight(double h) { pmosWellHeight = h; init(); } /** Set the maximum width of a each MOS finger. Units of lambda */ public void setMaxMosWidth(double wid) { maxMosWidth = wid; } /** Set the starting offset from 0 of the pmos tracks */ public void setPmosTrackOffset(double offset) { pmosTrackOffset = offset; init(); } /** Set the starting offset from 0 of the nmos tracks */ public void setNmosTrackOffset(double offset) { nmosTrackOffset = offset; init(); } /** Set the track width */ public void setTrackWidth(double width) { trackWidth = width; init(); } /** Set the width of the Vdd track */ public void setVddWidth(double width) { vddWidth = width; init(); } /** Set the width of the Gnd track */ public void setGndWidth(double width) { gndWidth = width; init(); } public void setM1TrackWidth(double width) { m1TrackWidth = width; } public double getM1TrackWidth() { return m1TrackWidth; } public void setM2TrackWidth(double width) { m2TrackWidth = width; } public double getM2TrackWidth() { return m2TrackWidth; } public double getDRCRingSpacing() { return drcRingSpace; } public double getM1TrackAboveVDD() { double trackX; if (is90nm()) { // vddTop + m1_m1_sp + m1_wid/2 + m1_xcon_extension trackX = getVddY() + getVddWidth()/2 + 2.4 + getM1TrackWidth()/2 + 2.8; } else { // vddTop + m1_m1_sp + m1_wid/2 trackX = getVddY() + getVddWidth()/2 + 3 + 2; } return trackX; } public double getM1TrackBelowGnd() { double trackX; double gndBot = getGndY() - getGndWidth()/2; if (is90nm()) { // gndBot - m1_m1_sp - m1_wid/2 - m1_xcon_extension trackX = gndBot - 2.4 - getM1TrackWidth()/2 - 2.8; } else { // gndBot - m1_m1_sp - m1_wid/2 trackX = gndBot - getM1TrackWidth() - 2; } return trackX; } public double getWellOverhangDiff() { if (is90nm()) return 8; else return 6; } public double getGridResolution() { return gridResolution; } /** Get the fold pitch for folded transistor, given the number of series transistors */ public double getFoldPitch(int nbSeries) { if (is90nm()) return (8 + (nbSeries - 1) * (3 + 2)); else return (8 + (nbSeries - 1) * (3 + 2)); } /** Turn on Network Consistency Checking after each gate is generated. *<p> This just checks topology and ignores sizes. */ public void enableNCC(String libName) { schemLib = Library.findLibrary(libName); error(schemLib==null, "Please open the PurpleFour Library"); } public void setVddExportName(String vddNm) {vddExportName=vddNm;} public String getVddExportName() {return vddExportName;} public void setGndExportName(String gndNm) {gndExportName=gndNm;} public String getGndExportName() {return gndExportName;} public void setVddExportRole(PortCharacteristic vddRole) { vddExportRole = vddRole; } public PortCharacteristic getVddExportRole() { return vddExportRole; } public void setGndExportRole(PortCharacteristic gndRole) { gndExportRole = gndRole; } public PortCharacteristic getGndExportRole() { return gndExportRole; } //------------------------------------------------------------------------------ // Utilities for gate generators public StdCellParams(TechType.TechTypeEnum techEnum) { if (techEnum == TechType.TechTypeEnum.CMOS90) initCMOS90(); else if (techEnum == TechType.TechTypeEnum.MOCMOS || techEnum == TechType.TechTypeEnum.TSMC180) initMoCMOS(); else { error(true, "Standard Cell Params does not understand technology "+techEnum); } this.tech = techEnum.getTechType(); } void setOutputLibrary(Library lib) { this.layoutLib = lib; } Library getOutputLibrary() { return layoutLib; } public TechType getTechType() { return tech; } public double getNmosWellHeight() { return nmosWellHeight; } public double getPmosWellHeight() { return pmosWellHeight; } public boolean getDoubleStrapGate() { return doubleStrapGate; } public boolean getExhaustivePlace() { return exhaustivePlace; } public int getNbPlacerPerms() { return nbPlacerPerms; } public double getCellBot() { return -nmosWellHeight; } public double getCellTop() { return pmosWellHeight; } public double getGndY() { return gndY; } public void setGndY(double y) { gndY = y; init(); } public double getVddY() { return vddY; } public void setVddY(double y) { vddY = y; init(); } public double getGndWidth() { return gndWidth; } public double getVddWidth() { return vddWidth; } /** Gets the Y coordinate of the ith available track. Available * tracks exclude Vdd, Gnd, and reserved tracks. */ public double getTrackY(int i) { error(i==0, "StdCellParams.getTrackY: 0 is an illegal track index"); return i>0 ? pmosTracks.get(i - 1).doubleValue() : nmosTracks.get(-i - 1).doubleValue(); } /** A physical track number enumerates all tracks regardless of * whether the track is blocked. The value 0 is illegal. Tracks 1 * and higher are PMOS tracks. Tracks -1 and lower are NMOS * tracks */ public double getPhysTrackY(int i) { error(i==0, "StdCellParams.getPhysTrackY: 0 is illegal track index"); return i>0 ? trackPitch/2 + (i-1)*trackPitch : -trackPitch/2 + (i+1)*trackPitch; } /* public HashMap physTracksToYCoords(HashMap physTracks) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -