📄 capcell.java
字号:
package com.sun.electric.tool.generator.layout.fill;import com.sun.electric.database.geometry.EPoint;import com.sun.electric.database.hierarchy.Cell;import com.sun.electric.database.hierarchy.Export;import com.sun.electric.database.hierarchy.Library;import com.sun.electric.database.topology.NodeInst;import com.sun.electric.database.topology.PortInst;import com.sun.electric.tool.generator.layout.LayoutLib;import com.sun.electric.tool.generator.layout.Tech;import com.sun.electric.tool.generator.layout.TechType;// ------------------------------------ CapCell -------------------------------/** CapCell is built assuming horizontal metal 1 straps. I deal with the * possible 90 degree rotation by creating a NodeInst of this Cell rotated * by -90 degrees. */public abstract class CapCell{ protected int gndNum, vddNum; protected Cell cell; abstract public int numVdd(); abstract public int numGnd(); abstract public double getVddWidth(); abstract public double getGndWidth(); public Cell getCell() {return cell;}}// ------------------------------------ CapCellMosis -------------------------------class CapCellMosis extends CapCell{ /** All the fields in ProtoPlan assume that metal1 runs horizontally * since that is how we build CapCell */ private static class ProtoPlan{ private final double MAX_MOS_WIDTH = 40; private final double SEL_WIDTH_OF_NDM1; private final double SEL_TO_MOS; public final double protoWidth, protoHeight; public final double vddWidth = 9; public final double gndWidth = 4; public final double vddGndSpace = 3; // 4 in CMOS90 -> to change public final double gateWidth; public final int numMosX; public final double mosPitchX; public final double leftWellContX; public final double gateLength; public final int numMosY; public final double mosPitchY; public final double botWellContY; public ProtoPlan(CapFloorplan instPlan, TechType tech) { SEL_WIDTH_OF_NDM1 = tech.getDiffContWidth() + tech.selectSurroundDiffInActiveContact()*2; SEL_TO_MOS = tech.selectSurroundDiffAlongGateInTrans(); protoWidth = instPlan.horizontal ? instPlan.cellWidth : instPlan.cellHeight; protoHeight = instPlan.horizontal ? instPlan.cellHeight : instPlan.cellWidth; // compute number of MOS's bottom to top mosPitchY = gndWidth + 2*vddGndSpace + vddWidth; gateLength = mosPitchY - gndWidth - 2; numMosY = (int) Math.floor((protoHeight-tech.getWellWidth())/mosPitchY); botWellContY = - numMosY * mosPitchY / 2; // min distance from left Cell edge to center of leftmost diffusion // contact. double cellEdgeToDiffContCenter = tech.getWellSurroundDiff() + tech.getDiffContWidth()/2; // min distance from left Cell Edge to center of leftmost poly // contact. double polyContWidth = Math.floor(gateLength / tech.getP1M1Width()) * tech.getP1M1Width(); double cellEdgeToPolyContCenter = tech.getP1ToP1Space()/2 + polyContWidth/2; // diffusion and poly contact centers line up double cellEdgeToContCenter = Math.max(cellEdgeToDiffContCenter, cellEdgeToPolyContCenter); // compute number of MOS's left to right //double availForCap = protoWidth - 2*(SEL_TO_CELL_EDGE + SEL_WIDTH_OF_NDM1/2); double availForCap = protoWidth - 2*cellEdgeToContCenter; double numMosD = availForCap / (MAX_MOS_WIDTH + SEL_WIDTH_OF_NDM1 + 2*SEL_TO_MOS); numMosX = (int) Math.ceil(numMosD); LayoutLib.error((numMosX < 1), "not enough space for cap cell. Increase template size."); double mosWidth1 = availForCap/numMosX - SEL_WIDTH_OF_NDM1 - 2*SEL_TO_MOS; // round down mos Width to integral number of lambdas gateWidth = Math.floor(mosWidth1); mosPitchX = gateWidth + SEL_WIDTH_OF_NDM1 + 2*SEL_TO_MOS; leftWellContX = - numMosX * mosPitchX / 2; } } private final double POLY_CONT_WIDTH = 10; private final String TOP_DIFF = "n-trans-diff-top"; private final String BOT_DIFF = "n-trans-diff-bottom"; private final String LEFT_POLY = "n-trans-poly-left"; private final String RIGHT_POLY = "n-trans-poly-right"; private final ProtoPlan plan; private final TechType tech; /** Interleave well contacts with diffusion contacts left to right. Begin * and end with well contacts */ private PortInst[] diffCont(double y, ProtoPlan plan, Cell cell) { PortInst[] conts = new PortInst[plan.numMosX]; double x = - plan.numMosX * plan.mosPitchX / 2; PortInst wellCont = LayoutLib.newNodeInst(tech.pwm1(), x, y, G.DEF_SIZE, G.DEF_SIZE, 0, cell ).getOnlyPortInst(); Export e = Export.newInstance(cell, wellCont, FillCell.GND_NAME+"_"+gndNum++); e.setCharacteristic(FillCell.GND_CHARACTERISTIC); for (int i=0; i<plan.numMosX; i++) { x += plan.mosPitchX/2; conts[i] = LayoutLib.newNodeInst(tech.ndm1(), x, y, plan.gateWidth, 5, 0, cell).getOnlyPortInst(); LayoutLib.newArcInst(tech.m1(), plan.gndWidth, wellCont, conts[i]); x += plan.mosPitchX/2; wellCont = LayoutLib.newNodeInst(tech.pwm1(), x, y, G.DEF_SIZE, G.DEF_SIZE, 0, cell ).getOnlyPortInst(); LayoutLib.newArcInst(tech.m1(), plan.gndWidth, conts[i], wellCont); } // bring metal to cell left and right edges to prevent notches x = -plan.protoWidth/2 + plan.gndWidth/2; PortInst pi; pi = LayoutLib.newNodeInst(tech.m1pin(), x, y, G.DEF_SIZE, G.DEF_SIZE, 0, cell).getOnlyPortInst(); LayoutLib.newArcInst(tech.m1(), plan.gndWidth, pi, conts[0]); x = plan.protoWidth/2 - plan.gndWidth/2; pi = LayoutLib.newNodeInst(tech.m1pin(), x, y, G.DEF_SIZE, G.DEF_SIZE, 0, cell).getOnlyPortInst(); LayoutLib.newArcInst(tech.m1(), plan.gndWidth, pi, conts[conts.length-1]); return conts; } /** Interleave gate contacts and MOS transistors left to right. Begin * and end with gate contacts. */ private void mos(PortInst[] botDiffs, PortInst[] topDiffs, double y, ProtoPlan plan, Cell cell) { final double POLY_CONT_HEIGHT = plan.vddWidth + 1; double x = plan.leftWellContX; PortInst poly = LayoutLib.newNodeInst(tech.p1m1(), x, y, POLY_CONT_WIDTH, POLY_CONT_HEIGHT, 0, cell ).getOnlyPortInst(); PortInst leftCont = poly; Export e = Export.newInstance(cell, poly, FillCell.VDD_NAME+"_"+vddNum++); e.setCharacteristic(FillCell.VDD_CHARACTERISTIC); for (int i=0; i<plan.numMosX; i++) { x += plan.mosPitchX/2; NodeInst mos = LayoutLib.newNodeInst(tech.nmos(), x, y, plan.gateWidth, plan.gateLength, 0, cell); G.noExtendArc(tech.p1(), POLY_CONT_HEIGHT, poly, mos.findPortInst(LEFT_POLY)); x += plan.mosPitchX/2; PortInst polyR = LayoutLib.newNodeInst(tech.p1m1(), x, y, POLY_CONT_WIDTH, POLY_CONT_HEIGHT, 0, cell ).getOnlyPortInst(); G.noExtendArc(tech.m1(), plan.vddWidth, poly, polyR); poly = polyR; G.noExtendArc(tech.p1(), POLY_CONT_HEIGHT, poly, mos.findPortInst(RIGHT_POLY)); botDiffs[i] = mos.findPortInst(BOT_DIFF); topDiffs[i] = mos.findPortInst(TOP_DIFF); } PortInst rightCont = poly; // bring metal to cell left and right edges to prevent notches x = -plan.protoWidth/2 + plan.vddWidth/2; PortInst pi; pi = LayoutLib.newNodeInst(tech.m1pin(), x, y, G.DEF_SIZE, G.DEF_SIZE, 0, cell).getOnlyPortInst(); LayoutLib.newArcInst(tech.m1(), plan.vddWidth, pi, leftCont); x = plan.protoWidth/2 - plan.vddWidth/2; pi = LayoutLib.newNodeInst(tech.m1pin(), x, y, G.DEF_SIZE, G.DEF_SIZE, 0, cell).getOnlyPortInst(); LayoutLib.newArcInst(tech.m1(), plan.vddWidth, pi, rightCont); } double roundToHalfLambda(double x) { return Math.rint(x * 2) / 2; } // The height of a MOS diff contact is 1/2 lambda. Therefore, using the // center for diffusion arcs always generates CIF resolution errors private void newDiffArc(PortInst p1, PortInst p2) { EPoint p1P = p1.getCenter(); double x = p1P.getX(); // LayoutLib.roundCenterX(p1); double y1 = roundToHalfLambda(p1P.getY()); // LayoutLib.roundCenterY(p1)); double y2 = roundToHalfLambda(LayoutLib.roundCenterY(p2)); LayoutLib.newArcInst(tech.ndiff(), LayoutLib.DEF_SIZE, p1, x, y1, p2, x, y2); } private void connectDiffs(PortInst[] a, PortInst[] b) { for (int i=0; i<a.length; i++) { //LayoutLib.newArcInst(tech.ndiff, G.DEF_SIZE, a[i], b[i]); newDiffArc(a[i], b[i]); } } /** @Deprecated */ public CapCellMosis(Library lib, CapFloorplan instPlan) { this(lib, instPlan, Tech.getTechType()); } public CapCellMosis(Library lib, CapFloorplan instPlan, TechType tech) { this.plan = new ProtoPlan(instPlan, tech); this.tech = tech; PortInst[] botDiffs = new PortInst[plan.numMosX]; PortInst[] topDiffs = new PortInst[plan.numMosX]; cell = Cell.newInstance(lib, "fillCap{lay}"); double y = plan.botWellContY; PortInst[] lastCont = diffCont(y, plan, cell); for (int i=0; i<plan.numMosY; i++) { y += plan.mosPitchY/2; mos(botDiffs, topDiffs, y, plan, cell); connectDiffs(lastCont, botDiffs); y += plan.mosPitchY/2; lastCont = diffCont(y, plan, cell); connectDiffs(topDiffs, lastCont); } // Cover the sucker with well to eliminate notch errors LayoutLib.newNodeInst(tech.pwell(), 0, 0, plan.protoWidth, plan.protoHeight, 0, cell); } @Override public int numVdd() {return plan.numMosY;} @Override public int numGnd() {return plan.numMosY+1;} @Override public double getVddWidth() {return plan.vddWidth;} @Override public double getGndWidth() {return plan.gndWidth;}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -