📄 stdcellparams.java
字号:
HashMap yCoords = new HashMap(); for (String key : physTracks.keySet();) { int physTrk = physTracks.get(key).intValue(); Double y = new Double(getPhysTrackY(physTrk)); yCoords.put(key, y); } return yCoords; } */ public double getTrackPitch() {return trackPitch;} /** Get the number of NMOS tracks. The indices of NMOS tracks * range from -1 to -nbNmosTracks(). The value 0 is an illegal * index. */ public int nbNmosTracks() { return nmosTracks.size(); } /** Get the number of PMOS tracks. The indices of PMOS tracks * range from 1 to nbPmosTracks(). The value 0 is an illegal * index. */ public int nbPmosTracks() {return pmosTracks.size();} public boolean getSeparateWellTies() {return separateWellTies;} /** Connect well ties to separate exports rather than vdd and gnd */ public void setSeparateWellTies(boolean b) { separateWellTies = b; init(); } public double getNmosWellTieY() {return nmosWellTieY;} public double getPmosWellTieY() {return pmosWellTieY;} public double getNmosWellTieWidth() { return separateWellTies ? trackWidth : gndWidth; } public double getPmosWellTieWidth() { return separateWellTies ? trackWidth : vddWidth; } public String getNmosWellTieName() { return separateWellTies ? "vsb" : gndExportName; } public String getPmosWellTieName() { return separateWellTies ? "vnw" : vddExportName; } public PortCharacteristic getNmosWellTieRole() { return separateWellTies ? PortCharacteristic.IN : gndExportRole; } public PortCharacteristic getPmosWellTieRole() { return separateWellTies ? PortCharacteristic.IN : vddExportRole; } public void setSimpleName(boolean b) {simpleName = b;} public boolean getSimpleName() {return simpleName;} // maximum distance between well contacts public double getWellTiePitch() { double tieToPwellTop = 0 - getNmosWellTieY(); double tieToPwellBot = getNmosWellTieY() - -nmosWellHeight; double tieToPwellTopBot = Math.max(tieToPwellTop, tieToPwellBot); // Right triangle: // hypotenuse is maxWellTieRadius // delta Y is maxGndToWellTopBot // delta X is nmosWellTieDistance double nmosWellTieDistance = Math.sqrt( Math.pow(maxWellTieRadius, 2) - Math.pow(tieToPwellTopBot, 2)); double tieToNwellTop = pmosWellHeight - getPmosWellTieY(); double tieToNwellBot = getPmosWellTieY() - 0; double tieToNwellTopBot = Math.max(tieToNwellTop, tieToNwellBot); double pmosWellTieDistance = Math.sqrt( Math.pow(maxWellTieRadius, 2) - Math.pow(tieToNwellTopBot, 2)); double tiePitch = 2 * Math.min(nmosWellTieDistance, pmosWellTieDistance); // Safety margin: add twice as many ties as necessary return (int) tiePitch/2; } // An "enable" style Nand gate has a weak pullup. This is how much // weaker than normal the PMOS is. public double getEnableGateStrengthRatio() { return enableGateStrengthRatio; } /** round to nearest multiple of 1/2 lambda for MoCMOS, * nearest multiple of 0.2 for CMOS90 */ public double roundGateWidth(double w) { if (is90nm()) { double size = Math.rint(w * 5) / 5; if (size < minGateWid) { System.out.println("Warning: gate width of "+size+" too small, using "+minGateWid); return minGateWid; } return size; } else { return Math.rint(w * 2) / 2; } } /** quantize size. Temporary hack because it doesn't control errors * precisely */ public double roundSize(double s) { if (s == 0) return s; double q = quantizeSize(s);// double e = (s - q) / s;// double qe = Math.rint(e * 100000) / 100000; //System.out.println("desired: "+s+" quantized: "+q+" error: "+qe); return q; //return ((int) (s*10+.5)) / 10.0; } public double roundToGrid(double s) { return ( ((int)(s/gridResolution)) * gridResolution ); } public void setSizeQuantizationError(double err) { error(err >= 1, "quantization error must be less than 1.0"); error(err < 0, "quantization error must be positive"); sizeErr = err; } public double quantizeSize(double desiredSize) { // express desiredSize as (mantisa * 10^exponent) double exponent = Math.floor(Math.log(desiredSize) / Math.log(10)); // 1.0 <= mantissa < 10 double mantissa = desiredSize / Math.pow(10, exponent); double quantMant = sizeErr!=0 ? quantizeMantissa(mantissa) : mantissa; // now round the quantized mantissa to 3 decimal places double roundMant = Math.rint(quantMant * 100) / 100; return Math.pow(10, exponent) * roundMant; } /** Add qualifiers to Cell name to reflect StdCell parameters * "_NH70" for NMOS region height of 70 lambda * "_PH70" for PMOS region height of 70 lambda * "_MW70" for maximum transistor width of 70 lambda */ public String parameterizedName(String nm) { if (!vddExportName.equals("vdd")) nm += "_pwr"; if (simpleName) return nm; return nm +"_NH"+nmosWellHeight+"_PH"+pmosWellHeight +"_MW"+maxMosWidth+"_VY" +vddY+"_GY"+ gndY; } /** Add qualifiers to Cell name to reflect StdCell parameters and part strength * "_NH70" for NMOS region height of 70 lambda * "_PH70" for PMOS region height of 70 lambda * "_MW70" for maximum transistor width of 70 lambda * "_X12.5" for strength of 12.5 * "{lay}" to indicate this is a layout Cell */ public String sizedName(String nm, double sz) { String num = "" + (sz + 1000); // Add leading zeros to size // so Gallery sorts properly. num = num.substring(1); return parameterizedName(nm) + "_X" + num + "{lay}"; } private NodeInst addNmosWell(double loX, double hiX, double y, Cell cell) { NodeInst well = LayoutLib.newNodeInst(tech.pwell(), (loX+hiX)/2, y-nmosWellHeight/2, hiX-loX, nmosWellHeight, 0, cell); well.setHardSelect(); return well; } private NodeInst addPmosWell(double loX, double hiX, double y, Cell cell) { NodeInst well = LayoutLib.newNodeInst(tech.nwell(), (loX+hiX)/2, y+pmosWellHeight/2, hiX-loX, pmosWellHeight, 0, cell); well.setHardSelect(); return well; } public NodeInst addNmosWell(double loX, double hiX, Cell cell) { return addNmosWell(loX, hiX, 0, cell); } public NodeInst addPmosWell(double loX, double hiX, Cell cell) { return addPmosWell(loX, hiX, 0, cell); } /** Given an array of NodeInsts in a row, add wells to both ends of the row to bring the row to minX and maxX. */ public void addWellsForRow( ArrayList<NodeInst> row, double minX, double maxX, Cell cell) { NodeInst first = row.get(row.size() - 1); double rowMinX = first.getBounds().getMinX(); if (rowMinX < minX) { addPmosWell(minX, rowMinX, first.getAnchorCenterY(), cell); addNmosWell(minX, rowMinX, first.getAnchorCenterY(), cell); } NodeInst last = row.get(row.size() - 1); double rowMaxX = last.getBounds().getMaxX(); if (rowMaxX < maxX) { addPmosWell(rowMaxX, maxX, first.getAnchorCenterY(), cell); addNmosWell(rowMaxX, maxX, first.getAnchorCenterY(), cell); } } /** essential bounds for PMOS only cells */ public void addPstackEssentialBounds(double loX, double hiX, Cell cell) { LayoutLib.newNodeInst(tech.essentialBounds(), loX, 0, DEF_SIZE, DEF_SIZE, 180, cell); LayoutLib.newNodeInst(tech.essentialBounds(), hiX, pmosWellHeight, DEF_SIZE, DEF_SIZE, 0, cell); } /** essential bounds for NMOS only cells */ public void addNstackEssentialBounds(double loX, double hiX, Cell cell) { LayoutLib.newNodeInst(tech.essentialBounds(), loX, -nmosWellHeight, DEF_SIZE, DEF_SIZE, 180, cell); LayoutLib.newNodeInst(tech.essentialBounds(), hiX, 0, DEF_SIZE, DEF_SIZE, 0, cell); } /** essential bounds for cells with both NMOS and PMOS */ public void addEssentialBounds(double loX, double hiX, Cell cell) { LayoutLib.newNodeInst(tech.essentialBounds(), loX, -nmosWellHeight, DEF_SIZE, DEF_SIZE, 180, cell); LayoutLib.newNodeInst(tech.essentialBounds(), hiX, pmosWellHeight, DEF_SIZE, DEF_SIZE, 0, cell); } /** Print a warning if strength is less than the minimum allowable. * Always return at least the minimum allowable strength. */ public double checkMinStrength( double specified, double minAllowable, String gateNm) { if (specified<minAllowable) { System.out.println("Can't make: "+gateNm+" this small: X=" +specified+", Using X="+minAllowable +" instead"); } return Math.max(specified, minAllowable); } /** Calculate the number of folds and the width of a MOS * transistor. Given that there is a limited physical height into * which a MOS transistor must fit, divide the total required width: * totWid into fingers. Each finger must have width less than or * equal to spaceAvailWid. * * <p> If it is possible, allocate an even number of fingers so that * the left most and right most diffusion contacts may be connected * to power or ground to reducing the capacitance of the inner * switching diffusion contacts. * @param spaceAvailWid the height in the standard cell that is * available for the diffusion of the MOS transistor. * @param totWid the total electrical width required. * @param groupSz This method creates fingers in multiples of * groupSz. For example, if groupSz is 2, then only even numbers of * fingers are created. This is needed when one FoldedMos is * actually going to be wired up as 2 identical, independent * transistors, for example the 2 PMOS pullups for a 2-input NAND * gate. */ public FoldsAndWidth calcFoldsAndWidth( double spaceAvailWid, double totWid, int groupSz) { if (totWid == 0) return null; double maxAvailWid = Math.min(spaceAvailWid, maxMosWidth); int nbGroups = calcNbGroups(maxAvailWid, totWid, groupSz); double gateWid = roundGateWidth(totWid / groupSz / nbGroups); // If we're unfortunate, rounding up gate width causes gate's width // to exceed space available. if (gateWid > maxAvailWid) { nbGroups = calcNbGroups(maxAvailWid - .5, totWid, groupSz); gateWid = roundGateWidth(totWid / groupSz / nbGroups); } double physWid = Math.max(tech.getDiffContWidth(), gateWid); if (gateWid < minGateWid) return null; return new FoldsAndWidth(nbGroups * groupSz, gateWid, physWid); } /** Fix notch errors between adjacent source/drain regions. * * <p>Mos transistors with source/drain regions that are too close * to each other result in notch errors for diffusion, metal1, * and/or select. Fix these notch errors by running diffusion, * and/or metal1 between the adjacent diffusion regions. * @param moss An array of adjacent FoldedMos transistors arranged * @param fillDiffNotch*/ public void fillDiffAndSelectNotches(FoldedMos[] moss, boolean fillDiffNotch) { error(moss.length == 0, "fillDiffAndSelectNotches: no transistors?"); FoldedMos mos = moss[0]; for (int i = 1; i < moss.length; i++) { PortInst thisPort = moss[i].getSrcDrn(0); PortInst prevPort = moss[i - 1].getSrcDrn(moss[i - 1].nbSrcDrns() - 1); fillDiffAndSelectNotch(prevPort, thisPort, mos, moss[i], fillDiffNotch); } } /** Wire pmos or nmos to vdd or gnd, respectively. Add an export * if there is none. */ public void wireVddGnd(FoldedMos[] moss, SelectSrcDrn select, Cell p) { FoldedMos mos = moss[0]; PortInst leftDiff = mos.getSrcDrn(0); Cell f = leftDiff.getNodeInst().getParent(); double busWid = mos instanceof FoldedPmos ? vddWidth : gndWidth; double busY = mos instanceof FoldedPmos ? vddY : gndY; TrackRouter net = new TrackRouterH(tech.m2(), busWid, busY, tech, p); String exportNm = mos instanceof FoldedPmos ? vddExportName : gndExportName; if (f.findPortProto(exportNm)==null) { // The export doesn't yet exist. Create and export a metal2 pin // aligned with the first diffusion. double x = leftDiff.getBounds().getCenterX(); NodeInst pinProt = LayoutLib.newNodeInst(tech.m2pin(), x, busY, DEF_SIZE, DEF_SIZE, 0, f); PortInst pin = pinProt.getOnlyPortInst(); Export e = Export.newInstance(f, pin, exportNm); PortCharacteristic role = mos instanceof FoldedPmos ? vddExportRole : gndExportRole; e.setCharacteristic(role); // Connect the export to itself using a standard width power or // ground strap. The width of this strap serves as a hint to // Electric as to the width to use to connect to this export at // the next level up. LayoutLib.newArcInst(tech.m2(), busWid, pin, pin); net.connect(pin); } double diffY = LayoutLib.roundCenterY(leftDiff); double notchLoY = Math.min(busY - busWid / 2, diffY); double notchHiY = Math.max(busY + busWid / 2, diffY); PortInst lastDiff = null; for (int i=0; i<moss.length; i++) { for (int j=0; j<moss[i].nbSrcDrns(); j++) { if (select.connectThisOne(i, j)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -