📄 foldedmos.java
字号:
* This constructor is responsible for positioning the internal pieces on * the 0.5 lambda grid. Most significant to the user is the positioning of * the MOS transistors when gateWidth is less than the width of a minimum * sized diffusion contact. In that case this constructor assumes the user * will place the edges of the diffusion contact on grid and moves the MOS * transistors slightly up or down to get the MOS transistor on the same * grid. * * @param type * 'N' or 'P' for NMOS or PMOS * @param x * the middle of the left most diffusion contact * @param y * the "middle" of the FoldedMos. If gateWidth is less than the * width of the minimum sized diffusion contact this will be the * middle of the diffusion contact. Otherwise this is the middle * of the MOS transistor. * @param nbFolds * the number of folds. Each "fold" consists of a left diffusion * contact, nbSeries transistors stacked in series, and a right * diffusion contact. Adjacent folds share diffusion contacts. * @param nbSeries * the number of transistors stacked in series for each fold * @param gateWidth * the width of each gate * @param gateSpace * allows the user to specify the space between diffusion * contacts and gates and between adjacent gates. null means use * the minimum spacing required by the design rules. * @param justifyDiffCont * FoldedMos always makes diffusion contacts a multiple of 5 * lambda wide. If the gateWidth is not a multiple of 5 lambda * wide then this argument specifies how the diffusion contact * should be positioned within the diffusion. The choices are * 'T', or 'B' to move the contact to the top or bottom. * Centering the contact was eliminated because if the transistor * width was .5 + an integer then the diffusion contact edges * would not be on the same .5 lambda grid as any of the edges of * the transistor thereby leading to CIF resolution errors. * @param f * the facet that will contain this FoldedMos * @param tech */ FoldedMos(char type, double x, double y, int nbFolds, int nbSeries, double gateWidth, GateSpace gateSpace, char justifyDiffCont, Cell f, TechType tech) { error(type != 'P' && type != 'N', "FoldedMos: type must be 'P' or 'N': " + type); this.tech = tech; this.gateWidth= gateWidth; physWidth= Math.max(tech.getDiffContWidth(), gateWidth); diffVias= new PortInst[nbFolds + 1]; moss= new MosInst[nbFolds * nbSeries]; internalDiffs= new PortInst[nbFolds * (nbSeries - 1)]; if (gateSpace == null) gateSpace= useMinSp; PrimitiveNode diffCont= isPmos() ? tech.pdm1() : tech.ndm1(); ArcProto diff= isPmos() ? tech.pdiff() : tech.ndiff(); NodeProto difNod= isPmos() ? tech.pdNode() : tech.ndNode(); // double foldPitch = 8 + (nbSeries - 1) * (3 + 2); int diffNdx= 0, mosNdx= 0, internalDiffNdx= 0; // Contact only needs to be multiple of 5 lambda high. Because // diffusion contact is always justified up or down and because it // is always an integral number of lambdas high, it's edges and // center are on the same .5 lambda grid as the transistor edges. double difConIncr= tech.getDiffContIncr(); difContWid= Math.max(tech.getDiffContWidth(), ((int) (gateWidth / difConIncr)) * difConIncr); double difContSlop= Math.max(0, (gateWidth - difContWid) / 2); double difContY= y; switch (justifyDiffCont) { case 'T': difContY+= difContSlop; break; case 'B': difContY-= difContSlop; break; default: error(true, "FoldedMos: justifyDiffCont must be 'T', or 'B'"); } // If the MOS width is less than the minimum width of a diffusion // contact then the diffusion contact determines the boundary of // the transistor. In this case the user will place the top and // bottom of the diffusion contact on a 0.5 lambda grid. // Therefore we need to shift the MOS transistor so that its edges // are also on a 0.5 lambda grid. I will do this by shifting the // MOS transistor down until its bottom edge is on grid. mosY= y; if (gateWidth < tech.getDiffContWidth()) { double mosBotY= y - gateWidth / 2; double misAlign= Math.IEEEremainder(mosBotY, 0.5); mosY-= misAlign; } double extraDiffPolySpace = gateWidth >= tech.getDiffContWidth() ? ( 0. ) : ( tech.getGateToDiffContSpaceDogBone() - tech.getGateToDiffContSpace() ); double viaToMosPitch = tech.getDiffContWidth()/2 + tech.getGateToDiffContSpace() + tech.getGateLength()/2; double mosToMosPitch = tech.getGateLength() + tech.getGateToGateSpace(); PortInst prevPort= null; for (int i= 0;; i++) { // put down diffusion contact PortInst newPort = LayoutLib.newNodeInst(diffCont, x, difContY, LayoutLib.DEF_SIZE, difContWid, 0, f).getOnlyPortInst(); // Add redundant diffusion as a hint of the metal-1 wire size to // use to connect to this diffusion contact. Diffusion contact is // always on grid. LayoutLib.newArcInst(diff, tech.getDiffCont_m1Width(), newPort, newPort); addM1ForMinArea(newPort, difContWid, justifyDiffCont); diffVias[diffNdx++]= newPort; // connect to previous port if (prevPort != null) { newDiffArc(diff, difContY, prevPort, newPort); } prevPort= newPort; if (i >= nbFolds) break; // exit after inserting last diff contact // series transistors for (int j= 0; j < nbSeries; j++) { double extraSp= gateSpace.getExtraSpace( j == 0 ? extraDiffPolySpace : 0, i, nbFolds, j, nbSeries); if (j == 0 && extraSp != 0) { // Fill diff notch from center of diff contact to left end // of MOS. Round up diff node width to multiple of lambda // or else center will be off .5 lambda grid. double w= Math.ceil(extraSp); NodeInst dn= LayoutLib.newNodeInst(difNod, x + w / 2, mosY, w, gateWidth, 0, f); newDiffArc(diff, difContY, prevPort, dn.getOnlyPortInst()); } x+= (j == 0 ? viaToMosPitch : mosToMosPitch) + extraSp; MosInst m= isPmos() ? tech.newPmosInst(x, mosY, gateWidth, tech.getGateLength(), f) : tech.newNmosInst(x, mosY, gateWidth, tech.getGateLength(), f); moss[mosNdx++]= m; newDiffArc(diff, difContY, prevPort, m.leftDiff()); prevPort= m.rightDiff(); if (j != 0) { internalDiffs[internalDiffNdx++]= m.leftDiff(); } } double extraSp= gateSpace.getExtraSpace(extraDiffPolySpace, i, nbFolds, nbSeries, nbSeries); x+= viaToMosPitch + extraSp; if (extraSp != 0) { // fill diff notch from right end of MOS to center of diff cont double w= Math.ceil(extraSp); NodeInst dn= LayoutLib.newNodeInst(difNod, x - w / 2, mosY, w, gateWidth, 0, f); newDiffArc(diff, difContY, prevPort, dn.getOnlyPortInst()); } } } // ----------------------------- public methods ------------------------------ /** return the width of each transistor's gate */ public double getGateWidth() { return gateWidth; } /** * when the gate is narrower than the diffusion contact return the diffusion * contact width, otherwise return the gate width */ public double getPhysWidth() { return physWidth; } /** * Get the Y coordinate of the centers of the MOS transistors. This may be * different from the Y coordinate passed into the constructor. When the MOS * transistor is narrower than the diffusion contact the MOS transistor must * be been shifted up or down to get its edges on grid */ public double getMosCenterY() { return mosY; } /** * The diffusion contact's width increases with the gateWidth but is only * large enough to surround the diffusion contact cuts */ public double getDiffContWidth() { return difContWid; } public int nbSrcDrns() { return diffVias.length; } public PortInst getSrcDrn(int col) { return diffVias[col]; } public int nbGates() { return moss.length; } public PortInst getGate(int mosNdx, char pos) { error(pos != 'T' && pos != 'B', "pos must be 'T' or 'B': " + pos); return pos == 'T' ? moss[mosNdx].topPoly() : moss[mosNdx].botPoly(); } public int nbInternalSrcDrns() { return internalDiffs.length; } /** * "Internal diffusions" are the diffusions between two series transistors. * The user may wish to connect these with "generic:Uinversal" arcs in order * to fool Electric's NCC into paralleling transistor stacks of series * transistors. */ public PortInst getInternalSrcDrn(int col) { return internalDiffs[col]; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -