public Cell makeVddGndM3Cell(Cell layCell, TechType tech) { Library layLib = layCell.getLibrary(); CellName nm = layCell.getCellName(); String m3Nm = nm.getName() + "_m3{lay}"; Cell m3Cell = Cell.newInstance(layLib, m3Nm); Rectangle2D bounds = layCell.findEssentialBounds(); double minX = bounds.getMinX(); double minY = bounds.getMinY(); double maxX = bounds.getMaxX(); double maxY = bounds.getMaxY(); LayoutLib.newNodeInst(tech.essentialBounds(), minX, minY, DEF_SIZE, DEF_SIZE, 0, m3Cell); LayoutLib.newNodeInst(tech.essentialBounds(), maxX, maxY, DEF_SIZE, DEF_SIZE, 180, m3Cell); for (Integer x : xCoords) { PortInst p1 = LayoutLib.newNodeInst(tech.m3pin(), x, minY, DEF_SIZE, DEF_SIZE, 180, m3Cell) .getOnlyPortInst(); PortInst p2 = LayoutLib.newNodeInst(tech.m3pin(), x, maxY, DEF_SIZE, DEF_SIZE, 180, m3Cell) .getOnlyPortInst(); LayoutLib.newArcInst(tech.m3(), vddGndWidth, p1, p2); } return m3Cell; }
public static Cell makePart(double sz, StdCellParams stdCell) { TechType tech = stdCell.getTechType(); sz = stdCell.roundSize(sz); String nm = "nms1" + (stdCell.getDoubleStrapGate() ? "_strap" : ""); sz = stdCell.checkMinStrength(sz, 1, nm); // Space needed at top of MOS well. // We need more space if we're double strapping poly. double outsideSpace = stdCell.getDoubleStrapGate() ? (2 + 5 + 1.5 // p1_nd_sp + p1m1_wid + p1_p1_sp/2 ) : (wellOverhangDiff); double spaceAvail = nmosTop - (stdCell.getCellBot() + outsideSpace); double totWid = sz * 3; FoldsAndWidth fw = stdCell.calcFoldsAndWidth(spaceAvail, totWid, 1); error(fw == null, "can't make Nms1 this small: " + sz); Cell nms1 = stdCell.findPart(nm, sz); if (nms1 != null) return nms1; nms1 = stdCell.newPart(nm, sz); // leave vertical m1 track for g double gX = 1.5 + 2; // m1_m1_sp/2 + m1_wid/2 LayoutLib.newExport(nms1, "g", PortCharacteristic.IN, tech.m1(), 4, gX, gY); // gnd port overlaps leftmost MOS diffusion contacts double mosX = gX + 2 + 3 + 2; // m1_wid/2 + m1_m1_sp + m1_wid/2 double nmosY = nmosTop - fw.physWid / 2; FoldedMos nmos = new FoldedNmos(mosX, nmosY, fw.nbFolds, 1, fw.gateWid, nms1, tech); // output d m1_wid/2 + m1_m1_sp + m1_wid/2 double dX = StdCellParams.getRightDiffX(nmos) + 2 + 3 + 2; LayoutLib.newExport(nms1, "d", PortCharacteristic.OUT, tech.m1(), 4, dX, dY); // create gnd export and connect to MOS source/drains stdCell.wireVddGnd(nmos, StdCellParams.EVEN, nms1); // connect up input g TrackRouter g = new TrackRouterH(tech.m1(), 3, gY, tech, nms1); g.connect(nms1.findExport("g")); for (int i = 0; i < nmos.nbGates(); i++) g.connect(nmos.getGate(i, 'T')); if (stdCell.getDoubleStrapGate()) { // Connect gates using metal1 along bottom of cell double gndBot = stdCell.getGndY() - stdCell.getGndWidth() / 2; double inLoFromGnd = gndBot - 3 - 2; // -m1_m1_sp -m1_wid/2 double nmosBot = nmosY - fw.physWid / 2; double inLoFromMos = nmosBot - 2 - 2.5; // -nd_p1_sp -p1m1_wid/2 double inLoY = Math.min(inLoFromGnd, inLoFromMos); TrackRouter inLo = new TrackRouterH(tech.m1(), 3, inLoY, tech, nms1); inLo.connect(nms1.findExport("g")); for (int i = 0; i < nmos.nbGates(); i++) { inLo.connect(nmos.getGate(i, 'B')); } } // connect up output d TrackRouter d = new TrackRouterH(tech.m2(), 4, dY, tech, nms1); d.connect(nms1.findExport("d")); for (int i = 1; i < nmos.nbSrcDrns(); i += 2) { d.connect(nmos.getSrcDrn(i)); } // add wells double wellMinX = 0; double wellMaxX = dX + 2 + 1.5; // m1_wid/2 + m1m1_space/2 stdCell.addNmosWell(wellMinX, wellMaxX, nms1); // add essential bounds stdCell.addNstackEssentialBounds(wellMinX, wellMaxX, nms1); // perform Network Consistency Check stdCell.doNCC(nms1, nm + "{sch}"); return nms1; }
private static void error(boolean pred, String msg) { LayoutLib.error(pred, msg); }