package com.sun.electric.tool.generator.layout; import java.io.Serializable; import java.lang.reflect.Constructor; import java.util.HashMap; import java.util.Iterator; import com.sun.electric.database.hierarchy.Cell; import com.sun.electric.database.prototype.PortProto; import com.sun.electric.database.topology.NodeInst; import com.sun.electric.database.topology.PortInst; import com.sun.electric.database.variable.Variable; import com.sun.electric.technology.ArcProto; import com.sun.electric.technology.DRCTemplate; import com.sun.electric.technology.DRCTemplate.DRCRuleType; import com.sun.electric.technology.Layer; import com.sun.electric.technology.PrimitiveNode; import com.sun.electric.technology.PrimitivePort; import com.sun.electric.technology.Technology; import com.sun.electric.technology.XMLRules; import com.sun.electric.tool.Job; import com.sun.electric.util.math.DBMath; /** The TechType class holds technology dependent information for the layout * generators. Most of the information is available from public static methods. * <p> The TechType class queries the appropriate Technology object to get * references to prototypes commonly used by the layout generators such as the * metal 1 arc proto or the metal 1 pin proto. The Tech class also holds * technology dependant dimensions such as the width of a diffusion contact. * <p> The TechType class serves two purposes. First, it makes it convenient * to access technology dependent information. Second, it hides foundry * specific information that we're not allowed to distribute as open source * software. */ public abstract class TechType implements Serializable { private static class ArcPair implements Serializable { private static final long serialVersionUID = 0; private ArcProto arc1, arc2; public ArcPair(ArcProto a1, ArcProto a2) {arc1=a1; arc2=a2;} @Override public boolean equals(Object o) { if (!(o instanceof ArcPair)) return false; ArcPair ap = (ArcPair)o; if (ap.arc1==arc1 && ap.arc2==arc2) return true; if (ap.arc1==arc2 && ap.arc2==arc1) return true; return false; } @Override public int hashCode() {return arc1.hashCode()*arc2.hashCode();} } private class Transistor { private final PrimitiveNode pn; private PrimitivePort topPoly, bottomPoly, leftDiff, rightDiff; private Transistor(PrimitiveNode pn) { this.pn = pn; Technology.NodeLayer nmos_gate = findNodeLayer(pn, lgate); if (nmos_gate == null) { nmos_gate = findNodeLayer(pn, lp1); } boolean rotate = nmos_gate.getTopEdge().getGridAdder() - nmos_gate.getBottomEdge().getGridAdder() < nmos_gate.getRightEdge().getGridAdder() - nmos_gate.getLeftEdge().getGridAdder(); for (Iterator<PrimitivePort> it = pn.getPrimitivePorts(); it.hasNext(); ) { PrimitivePort pp = it.next(); if (pp.getConnection().getFunction().isPoly()) { if (rotate) { if (pp.getRight().getGridAdder() > 0) { topPoly = pp; } else { bottomPoly = pp; } } else { if (pp.getBottom().getGridAdder() > 0) { topPoly = pp; } else { bottomPoly = pp; } } } else if (pp.getConnection().getFunction().isDiffusion()) { if (rotate) { if (pp.getTop().getGridAdder() > 0) { leftDiff = pp; } else { rightDiff = pp; } } else { if (pp.getRight().getGridAdder() > 0) { rightDiff = pp; } else { leftDiff = pp; } } } } assert topPoly != null && bottomPoly != null && leftDiff != null && rightDiff != null; } } //----------------------------- public data ---------------------------------- private static final Variable.Key ATTR_X = Variable.newKey("ATTR_X"); private static final Variable.Key ATTR_S = Variable.newKey("ATTR_S"); private static final Variable.Key ATTR_SN = Variable.newKey("ATTR_SN"); private static final Variable.Key ATTR_SP = Variable.newKey("ATTR_SP"); private final Technology generic = Technology.findTechnology("generic"); private final Technology technology; private final XMLRules drcRules; private final PrimitiveNode essentialBounds = generic.findNodeProto("Essential-Bounds"); private final PrimitiveNode facetCenter = generic.findNodeProto("Facet-Center"); private final int nbLay; private Layer lgate; private final Layer lp1; private final Layer[] lmets; private final ArcProto[] arcs; private final PrimitiveNode[] vias; private final HashMap<ArcPair,PrimitiveNode> viaMap = new HashMap<ArcPair,PrimitiveNode>(); /** layers * * Poly and metal are considered to be routing layers. In contrast * we assume we never want to route in diffusion or well. This * allows us to assign a unique "height" to each of the routing * layers. Layers at the same height can connect directly. Layers * at adjacent heights can connect using vias. * * For now, well and diffusion don't have heights. */ private final ArcProto pdiff, ndiff, p1, m1, m2, m3, m4, m5, m6, m7, m8, m9, ndiff18, pdiff18, ndiff25, pdiff25, ndiff33, pdiff33; /** layer pins */ private final PrimitiveNode ndpin, pdpin, p1pin, m1pin, m2pin, m3pin, m4pin, m5pin, m6pin, m7pin, m8pin, m9pin; /** vias */ private final PrimitiveNode nwm1, pwm1, nwm1Y, pwm1Y, ndm1, pdm1, p1m1, m1m2, m2m3, m3m4, m4m5, m5m6, m6m7, m7m8, m8m9; /** Transistors */ private final boolean rotateTransistors; private final Transistor nmos, pmos, nmos18, pmos18, nmos25, pmos25, nmos33, pmos33; // nvth, pvth, nvtl, pvtl, nnat, pnat; /** special threshold transistor contacts */ private final PrimitiveNode nmos18contact, pmos18contact, nmos25contact, pmos25contact, nmos33contact, pmos33contact; /** Pure layer nodes for Well and Select */ private final PrimitiveNode nwellNode, pwellNode; /** Layer nodes are sometimes used to patch notches */ private final PrimitiveNode m1Node, m2Node, m3Node, m4Node, m5Node, m6Node, m7Node, m8Node, m9Node, p1Node, pdNode, ndNode, pselNode, nselNode; /** Transistor layer nodes */ private final PrimitiveNode od18Node, od25Node, od33Node, vthNode, vtlNode; //-------------------- Technology dependent dimensions ------------------- protected double // Gilda: gate length depending on foundry gateLength, // Wire offset from center of the poly contact to form a L-shape arc to gate offsetLShapePolyContact, offsetTShapePolyContact, // denote Select spacing rule selectSpace, // surround distance of select from active in transistor selectSurroundDiffInTrans, selectSurroundDiffAlongGateInTrans, // select surround over poly. PP/NP.R.1 in 90nm selectSurround; // RKao my first attempt to embed technology specific dimensions protected double wellSurroundDiff, gateExtendPastMOS, p1Width, p1ToP1Space, gateToGateSpace, gateToDiffContSpace, gateToDiffContSpaceDogBone, selectSurroundDiffInWellContact, // select surround in well contacts selectSurroundDiffInActiveContact, // select surround in active contacts m1MinArea, // min area rules, sq lambda polyContWidth, // width of poly of min size poly contact wellContWidth, // width of diff of min sized well contact diffContWidth, // width of diff of min sized diff contact diffCont_m1Width, // width of m1 of min sized diff contact diffContIncr; // when diff cont increases by diffContIncr, // we get an additional cut //----------------------------- private methods ----------------------------- private static void error(boolean pred, String msg) { Job.error(pred, msg); } private Layer getMetalLayer(int l) { return l <= lmets.length ? lmets[l-1] : null; } private double getSpacing(Layer layer1, Layer layer2) { return drcRules.getSpacingRule(layer1, null, layer2, null, false, -1, -1.0, -1.0).getValue(0); } private ArcProto getArc(int n) { return n>(arcs.length-1) ? null : arcs[n]; } private ArcProto findArc(Layer... layers) { for (Iterator<ArcProto> it = technology.getArcs(); it.hasNext(); ) { ArcProto ap = it.next(); boolean allLayersFound = true; for (Layer layer: layers) { if (ap.indexOf(layer) < 0) { allLayersFound = false; } } if (allLayersFound) { return ap; } } return null; } // private double getArcLayerGridExtend(ArcProto ap, Layer layer1, Layer layer2) { // if (ap == null) { // return Double.NaN; // } // int arcIndex1 = ap.indexOf(layer1); // int arcIndex2 = ap.indexOf(layer2); // if (arcIndex1 < 0 || arcIndex2 < 0) { // return Double.NaN; // } // return DBMath.gridToLambda((ap.getLayerGridExtend(arcIndex1) - ap.getLayerGridExtend(arcIndex2))); // } private PrimitiveNode findPureNode(Layer layer) { return layer != null ? layer.getPureLayerNode() : null; } private Technology.NodeLayer findNodeLayer(PrimitiveNode pn, Layer l) { if (pn == null) { return null; } Technology.NodeLayer[] nls = pn.getNodeLayers(); for (Technology.NodeLayer nl: nls) { if (nl.getLayer() == l) { return nl; } } return null; } private Technology.NodeLayer findMulticut(PrimitiveNode pn) { if (pn == null) { return null; } Technology.NodeLayer[] nls = pn.getNodeLayers(); for (Technology.NodeLayer nl: nls) { if (nl.getRepresentation() == Technology.NodeLayer.MULTICUTBOX) { return nl; } } return null; } private PrimitiveNode getVia(int n) { return n>(vias.length-1) ? null : vias[n]; } /** * get the PrimitiveNode of a particular type that connects to the * complete set of wires given */ private PrimitiveNode findNode(PrimitiveNode.Function type, ArcProto... arcs) { for (Iterator<PrimitiveNode> it=technology.getNodes(); it.hasNext();) { PrimitiveNode pn = it.next(); boolean found = true; if (pn.getFunction() == type) { for (int j=0; j<arcs.length; j++) { if (pn.connectsTo(arcs[j]) == null) { found = false; break; } } if (found) return pn; } } return null; } private Transistor findTransistor(PrimitiveNode.Function type) { PrimitiveNode pn = findNode(type); if (pn == null) { return null; } return new Transistor(pn); } private PrimitiveNode findPin(ArcProto arc) { return arc==null ? null : arc.findPinProto(); } private void putViaMap(ArcProto arc1, ArcProto arc2, PrimitiveNode via) { if (arc1==null || arc2==null || via==null) return; ArcPair ap = new ArcPair(arc1, arc2); error(viaMap.containsKey(ap), "two contacts for same pair of arcs?"); viaMap.put(ap, via); } // initialize map from pair of layers to via that connects them private void initViaMap() { putViaMap(m1, m2, m1m2); putViaMap(m2, m3, m2m3); putViaMap(m3, m4, m3m4); putViaMap(m4, m5, m4m5); putViaMap(m5, m6, m5m6); putViaMap(m6, m7, m6m7); putViaMap(m7, m8, m7m8); putViaMap(m8, m9, m8m9); putViaMap(ndiff, m1, ndm1); putViaMap(pdiff, m1, pdm1); putViaMap(p1, m1, p1m1); } protected TechType(Technology techy) { // This error could happen when there are XML errors while uploading the technologies. error((techy==null), "Null technology in TechType constructor"); // I can't break this into subroutines because most data members are // final. lmets = new Layer[techy.getNumMetals()]; nbLay = 1 + lmets.length; technology = techy; drcRules = technology.getFactoryDesignRules(); //--------------------------- initialize layers ----------------------- arcs = new ArcProto[nbLay]; lp1 = techy.findLayerFromFunction(Layer.Function.POLY1, -1); lgate = techy.findLayerFromFunction(Layer.Function.GATE, -1); arcs[0] = findArc(lp1); for (int i=1; i<nbLay; i++) { Layer lm = techy.findLayerFromFunction(Layer.Function.getMetal(i), -1); lmets[i - 1] = lm; arcs[i] = findArc(lm); error(arcs[i]==null, "No such arc: " + Layer.Function.getMetal(i) + " in technology " + techy.getTechName()); } Layer lnwell = techy.findLayerFromFunction(Layer.Function.WELLN, 0); Layer lpwell = techy.findLayerFromFunction(Layer.Function.WELLP, 0); Layer lnd = techy.findLayerFromFunction(Layer.Function.DIFFN, 0); Layer lpd = techy.findLayerFromFunction(Layer.Function.DIFFP, 0); Layer lnsel = techy.findLayerFromFunction(Layer.Function.IMPLANTN, 0); Layer lpsel = techy.findLayerFromFunction(Layer.Function.IMPLANTP, 0); Layer lod18 = techy.findLayer("OD18"); Layer lod25 = techy.findLayer("OD25"); Layer lod33 = techy.findLayer("OD33"); p1 = getArc(0); m1 = getArc(1); m2 = getArc(2); m3 = getArc(3); m4 = getArc(4); m5 = getArc(5); m6 = getArc(6); m7 = getArc(7); m8 = getArc(8); m9 = getArc(9); ndiff = findArc(lnd); pdiff = findArc(lpd); ndiff18 = findArc(lnd, lod18); pdiff18 = findArc(lpd, lod18); ndiff25 = findArc(lnd, lod25); pdiff25 = findArc(lpd, lod25); ndiff33 = findArc(lnd, lod33); pdiff33 = findArc(lpd, lod33); // Layer Nodes nwellNode = findPureNode(lnwell); pwellNode = findPureNode(lpwell); m1Node = findPureNode(getMetalLayer(1)); m2Node = findPureNode(getMetalLayer(2)); m3Node = findPureNode(getMetalLayer(3)); m4Node = findPureNode(getMetalLayer(4)); m5Node = findPureNode(getMetalLayer(5)); m6Node = findPureNode(getMetalLayer(6)); m7Node = findPureNode(getMetalLayer(7)); m8Node = findPureNode(getMetalLayer(8)); m9Node = findPureNode(getMetalLayer(9)); p1Node = findPureNode(lp1); pdNode = findPureNode(lpd); ndNode = findPureNode(lnd); nselNode = findPureNode(lnsel); pselNode = findPureNode(lpsel); // transistor layers od18Node = findPureNode(lod18); od25Node = findPureNode(lod25); od33Node = findPureNode(lod33); vthNode = null; vtlNode = null; //--------------------------- initialize pins ------------------------- pdpin = findPin(pdiff); ndpin = findPin(ndiff); p1pin = findPin(p1); m1pin = findPin(m1); m2pin = findPin(m2); m3pin = findPin(m3); m4pin = findPin(m4); m5pin = findPin(m5); m6pin = findPin(m6); m7pin = findPin(m7); m8pin = findPin(m8); m9pin = findPin(m9); //--------------------------- initialize vias ------------------------- vias = new PrimitiveNode[nbLay - 1]; for (int i = 0; i < nbLay - 1; i++) { vias[i] = findNode(PrimitiveNode.Function.CONTACT, arcs[i], arcs[i+1]); error(vias[i] == null, "No via for layer: " + arcs[i]); } p1m1 = getVia(0); m1m2 = getVia(1); m2m3 = getVia(2); m3m4 = getVia(3); m4m5 = getVia(4); m5m6 = getVia(5); m6m7 = getVia(6); m7m8 = getVia(7); m8m9 = getVia(8); ndm1 = findNode(PrimitiveNode.Function.CONTACT, ndiff, arcs[1]); pdm1 = findNode(PrimitiveNode.Function.CONTACT, pdiff, arcs[1]); nwm1 = findNode(PrimitiveNode.Function.WELL, arcs[1]);//techy.findNodeProto("Metal-1-N-Well-Con"); pwm1 = findNode(PrimitiveNode.Function.SUBSTRATE, arcs[1]);//techy.findNodeProto("Metal-1-P-Well-Con"); nwm1Y = techy.findNodeProto("Y-Metal-1-N-Well-Con"); pwm1Y = techy.findNodeProto("Y-Metal-1-P-Well-Con"); // initialize special threshold transistor contacts nmos18contact = findNode(PrimitiveNode.Function.CONTACT, ndiff18, arcs[1]); pmos18contact = findNode(PrimitiveNode.Function.CONTACT, pdiff18, arcs[1]); nmos25contact = findNode(PrimitiveNode.Function.CONTACT, ndiff25, arcs[1]); pmos25contact = findNode(PrimitiveNode.Function.CONTACT, pdiff25, arcs[1]); nmos33contact = findNode(PrimitiveNode.Function.CONTACT, ndiff33, arcs[1]); pmos33contact = findNode(PrimitiveNode.Function.CONTACT, pdiff33, arcs[1]); initViaMap(); //------------------------ initialize transistors --------------------- nmos = findTransistor(PrimitiveNode.Function.TRANMOS);//techy.findNodeProto("N-Transistor"); pmos = findTransistor(PrimitiveNode.Function.TRAPMOS);//techy.findNodeProto("P-Transistor"); nmos18 = findTransistor(PrimitiveNode.Function.TRANMOSHV1);//techy.findNodeProto("OD18-N-Transistor"); pmos18 = findTransistor(PrimitiveNode.Function.TRAPMOSHV1);//techy.findNodeProto("OD18-P-Transistor"); nmos25 = findTransistor(PrimitiveNode.Function.TRANMOSHV2);//techy.findNodeProto("OD25-N-Transistor"); pmos25 = findTransistor(PrimitiveNode.Function.TRAPMOSHV2);//techy.findNodeProto("OD25-P-Transistor"); nmos33 = findTransistor(PrimitiveNode.Function.TRANMOSHV3);//techy.findNodeProto("OD33-N-Transistor"); pmos33 = findTransistor(PrimitiveNode.Function.TRAPMOSHV3);//techy.findNodeProto("OD33-P-Transistor"); Technology.NodeLayer nmos_gate = findNodeLayer(nmos.pn, lgate); if (nmos_gate == null) { nmos_gate = findNodeLayer(nmos.pn, lp1); } Technology.NodeLayer nmos_nd = findNodeLayer(nmos.pn, lnd); Technology.NodeLayer nmos_nsel = findNodeLayer(nmos.pn, lnsel); rotateTransistors = nmos_gate.getTopEdge().getGridAdder() - nmos_gate.getBottomEdge().getGridAdder() < nmos_gate.getRightEdge().getGridAdder() - nmos_gate.getLeftEdge().getGridAdder(); double diffExtendAlongMos; if (rotateTransistors) { p1Width = gateLength = DBMath.gridToLambda(nmos_gate.getTopEdge().getGridAdder() - nmos_gate.getBottomEdge().getGridAdder()); gateExtendPastMOS = DBMath.gridToLambda(nmos_gate.getRightEdge().getGridAdder() - nmos_nd.getRightEdge().getGridAdder()); diffExtendAlongMos = DBMath.gridToLambda(nmos_nd.getTopEdge().getGridAdder() - nmos_gate.getTopEdge().getGridAdder()); selectSurroundDiffInTrans = DBMath.gridToLambda(nmos_nsel.getTopEdge().getGridAdder() - nmos_nd.getTopEdge().getGridAdder()); selectSurroundDiffAlongGateInTrans = DBMath.gridToLambda(nmos_nsel.getRightEdge().getGridAdder() - nmos_nd.getRightEdge().getGridAdder()); } else { p1Width = gateLength = DBMath.gridToLambda(nmos_gate.getRightEdge().getGridAdder() - nmos_gate.getLeftEdge().getGridAdder()); gateExtendPastMOS = DBMath.gridToLambda(nmos_gate.getTopEdge().getGridAdder() - nmos_nd.getTopEdge().getGridAdder()); diffExtendAlongMos = DBMath.gridToLambda(nmos_nd.getRightEdge().getGridAdder() - nmos_gate.getRightEdge().getGridAdder()); selectSurroundDiffInTrans = DBMath.gridToLambda(nmos_nsel.getRightEdge().getGridAdder() - nmos_nd.getRightEdge().getGridAdder()); selectSurroundDiffAlongGateInTrans = DBMath.gridToLambda(nmos_nsel.getTopEdge().getGridAdder() - nmos_nd.getTopEdge().getGridAdder()); } wellContWidth = Double.NaN; selectSurroundDiffInWellContact = Double.NaN; wellSurroundDiff = Double.NaN; if (nwm1Y == null) { Technology.NodeLayer nwm1_nwell = findNodeLayer(nwm1, lnwell); Technology.NodeLayer nwm1_nsel = findNodeLayer(nwm1, lnsel); Technology.NodeLayer nwm1_nd = findNodeLayer(nwm1, lnd); if (nwm1_nwell != null && nwm1_nd != null) { wellContWidth = DBMath.gridToLambda(nwm1_nd.getTopEdge().getGridAdder() - nwm1_nd.getBottomEdge().getGridAdder()); selectSurroundDiffInWellContact = DBMath.gridToLambda(nwm1_nsel.getTopEdge().getGridAdder() - nwm1_nd.getTopEdge().getGridAdder()); wellSurroundDiff = DBMath.gridToLambda(nwm1_nwell.getTopEdge().getGridAdder() - nwm1_nd.getTopEdge().getGridAdder()); } } p1ToP1Space = getSpacing(lp1, lp1); gateToGateSpace = Math.max(getSpacing(lgate, lgate), diffExtendAlongMos); selectSpace = getSpacing(lnsel, lnsel); DRCTemplate m1MinAreaRule = drcRules.getMinValue(lmets[0], DRCRuleType.MINAREA); m1MinArea = m1MinAreaRule != null ? m1MinAreaRule.getValue(0) : 0.0; Technology.NodeLayer ndm1_nd = findNodeLayer(ndm1, lnd); Technology.NodeLayer ndm1_nsel = findNodeLayer(ndm1, lnsel); Technology.NodeLayer ndm1_m1 = findNodeLayer(ndm1, lmets[0]); Technology.NodeLayer ndm1_multicut = findMulticut(ndm1); diffContWidth = DBMath.gridToLambda(ndm1_nd.getRightEdge().getGridAdder() - ndm1_nd.getLeftEdge().getGridAdder()); diffCont_m1Width = DBMath.gridToLambda(ndm1_m1.getRightEdge().getGridAdder() - ndm1_m1.getLeftEdge().getGridAdder()); selectSurroundDiffInActiveContact = DBMath.gridToLambda(ndm1_nsel.getRightEdge().getGridAdder() - ndm1_nd.getRightEdge().getGridAdder()); diffContIncr = DBMath.gridToLambda(ndm1_multicut.getGridMulticutSizeX() + ndm1_multicut.getGridMulticutSep1D()); if (drcRules.isAnySpacingRule(ndm1_multicut.getLayer(), lgate)) { gateToDiffContSpace = gateToDiffContSpaceDogBone = DBMath.round(getSpacing(ndm1_multicut.getLayer(), lgate) - 0.5*(diffContWidth - ndm1_multicut.getMulticutSizeX())); } else { gateToDiffContSpace = gateToDiffContSpaceDogBone = 0; } Technology.NodeLayer p1m1_p1 = findNodeLayer(p1m1, lp1); polyContWidth = DBMath.gridToLambda(p1m1_p1.getRightEdge().getGridAdder() - p1m1_p1.getLeftEdge().getGridAdder()); offsetLShapePolyContact = DBMath.gridToLambda(p1m1_p1.getRightEdge().getGridAdder() - p1.getLayerGridExtend(lp1)); offsetTShapePolyContact = DBMath.gridToLambda(p1m1_p1.getRightEdge().getGridAdder() + p1.getLayerGridExtend(lp1)); selectSurround = Double.NaN; } //---------------------------- public classes ----------------------------- /** Hide the differences between technologies. A MosInst's gate is always * vertical. */ public static class MosInst { private final NodeInst mos; private final String leftDiff, rightDiff, topPoly, botPoly; private static void error(boolean pred, String msg) { Job.error(pred, msg); } private MosInst(char np, double x, double y, double width, double length, TechType tech, Cell parent) { Transistor t = np=='n' ? tech.nmos : tech.pmos; this.leftDiff = t.leftDiff.getName(); this.rightDiff = t.rightDiff.getName(); this.topPoly = t.topPoly.getName(); this.botPoly = t.bottomPoly.getName(); if (tech.rotateTransistors) { mos = LayoutLib.newNodeInst(t.pn, x, y, width, length, 90, parent); } else { mos = LayoutLib.newNodeInst(t.pn, x, y, length, width, 0, parent); } } private PortInst getPort(String portNm) { PortInst pi = mos.findPortInst(portNm); error(pi==null, "MosInst can't find port!"); return pi; } public PortInst leftDiff() {return getPort(leftDiff);} public PortInst rightDiff() {return getPort(rightDiff);} public PortInst topPoly() {return getPort(topPoly);} public PortInst botPoly() {return getPort(botPoly);} } //------------------------------ public data ------------------------------ public static TechType getTechType(Technology technology) { if (technology == Technology.getMocmosTechnology()) { return getMOCMOS(); } else if (technology == Technology.getTSMC180Technology()) { return getTSMC180(); } else if (technology == Technology.getCMOS90Technology()) { return getCMOS90(); } else { return new TechTypeWizard(technology); // System.out.println("Invalid TechTypeEnum"); // throw new AssertionError(); } } private static TechType techTypeMoCMOS; public static TechType getMOCMOS() { if (techTypeMoCMOS == null) { techTypeMoCMOS = new TechTypeMoCMOS(); } return techTypeMoCMOS; } private static TechType techTypeTSMC180; public static TechType getTSMC180() { if (techTypeTSMC180 == null) { try { Class tsmc180Class = Class.forName("com.sun.electric.plugins.tsmc.TechTypeTSMC180"); Constructor<TechType> techConstr = tsmc180Class.getConstructor(); techTypeTSMC180 = techConstr.newInstance(); } catch (Exception e) { assert (false); // runtime error } } return techTypeTSMC180; } private static TechType techTypeCMOS90; public static TechType getCMOS90() { if (techTypeCMOS90 == null) { try { Class cmos90Class = Class.forName("com.sun.electric.plugins.tsmc.TechTypeCMOS90"); Constructor<TechType> techConstr = cmos90Class.getConstructor(); techTypeCMOS90 = techConstr.newInstance(); // java.lang.reflect.Field techField = cmos90Class.getDeclaredField("CMOS90"); // cmos90 = (TechType) techField.get(null); } catch (Exception e) { assert (false); // runtime error } } return techTypeCMOS90; } //----------------------------- public methods ---------------------------- public int getNumMetals() { return lmets.length; } public Technology getTechnology() {return technology;} /** layers */ public ArcProto pdiff() {return pdiff;} public ArcProto ndiff() {return ndiff;} public ArcProto p1() {return p1;} public ArcProto m1() {return m1;} public ArcProto m2() {return m2;} public ArcProto m3() {return m3;} public ArcProto m4() {return m4;} public ArcProto m5() {return m5;} public ArcProto m6() {return m6;} public ArcProto m7() {return m7;} public ArcProto m8() {return m8;} public ArcProto m9() {return m9;} public ArcProto ndiff18() {return ndiff18;} public ArcProto pdiff18() {return pdiff18;} public ArcProto ndiff25() {return ndiff25;} public ArcProto pdiff25() {return pdiff25;} public ArcProto ndiff33() {return ndiff33;} public ArcProto pdiff33() {return pdiff33;} /** pins */ public PrimitiveNode ndpin() {return ndpin;} public PrimitiveNode pdpin() {return pdpin;} public PrimitiveNode p1pin() {return p1pin;} public PrimitiveNode m1pin() {return m1pin;} public PrimitiveNode m2pin() {return m2pin;} public PrimitiveNode m3pin() {return m3pin;} public PrimitiveNode m4pin() {return m4pin;} public PrimitiveNode m5pin() {return m5pin;} public PrimitiveNode m6pin() {return m6pin;} public PrimitiveNode m7pin() {return m7pin;} public PrimitiveNode m8pin() {return m8pin;} public PrimitiveNode m9pin() {return m9pin;} /** vias */ public PrimitiveNode nwm1() {return nwm1;} public PrimitiveNode pwm1() {return pwm1;} public PrimitiveNode nwm1Y() {return nwm1Y;} public PrimitiveNode pwm1Y() {return pwm1Y;} public PrimitiveNode ndm1() {return ndm1;} public PrimitiveNode pdm1() {return pdm1;} public PrimitiveNode p1m1() {return p1m1;} public PrimitiveNode m1m2() {return m1m2;} public PrimitiveNode m2m3() {return m2m3;} public PrimitiveNode m3m4() {return m3m4;} public PrimitiveNode m4m5() {return m4m5;} public PrimitiveNode m5m6() {return m5m6;} public PrimitiveNode m6m7() {return m6m7;} public PrimitiveNode m7m8() {return m7m8;} public PrimitiveNode m8m9() {return m8m9;} /** Transistors */ public PrimitiveNode nmos() {return nmos != null ? nmos.pn : null;} public PrimitiveNode pmos() {return pmos != null ? pmos.pn : null;} public PrimitiveNode nmos18() {return nmos18 != null ? nmos18.pn : null;} public PrimitiveNode pmos18() {return pmos18 != null ? pmos18.pn : null;} public PrimitiveNode nmos25() {return nmos25 != null ? nmos25.pn : null;} public PrimitiveNode pmos25() {return pmos25 != null ? pmos25.pn : null;} public PrimitiveNode nmos33() {return nmos33 != null ? nmos33.pn : null;} public PrimitiveNode pmos33() {return pmos33 != null ? pmos33.pn : null;} /** special threshold transistor contacts */ public PrimitiveNode nmos18contact() {return nmos18contact;} public PrimitiveNode pmos18contact() {return pmos18contact;} public PrimitiveNode nmos25contact() {return nmos25contact;} public PrimitiveNode pmos25contact() {return pmos25contact;} public PrimitiveNode nmos33contact() {return nmos33contact;} public PrimitiveNode pmos33contact() {return pmos33contact;} /** Well */ public PrimitiveNode nwell() {return nwellNode;} public PrimitiveNode pwell() {return pwellNode;} /** Layer nodes are sometimes used to patch notches */ public PrimitiveNode m1Node() {return m1Node;} public PrimitiveNode m2Node() {return m2Node;} public PrimitiveNode m3Node() {return m3Node;} public PrimitiveNode m4Node() {return m4Node;} public PrimitiveNode m5Node() {return m5Node;} public PrimitiveNode m6Node() {return m6Node;} public PrimitiveNode m7Node() {return m7Node;} public PrimitiveNode m8Node() {return m8Node;} public PrimitiveNode m9Node() {return m9Node;} public PrimitiveNode p1Node() {return p1Node;} public PrimitiveNode pdNode() {return pdNode;} public PrimitiveNode ndNode() {return ndNode;} public PrimitiveNode pselNode() {return pselNode;} public PrimitiveNode nselNode() {return nselNode;} /** Transistor layer nodes */ public PrimitiveNode od18() {return od18Node;} public PrimitiveNode od25() {return od25Node;} public PrimitiveNode od33() {return od33Node;} public PrimitiveNode vth() {return vthNode;} public PrimitiveNode vtl() {return vtlNode;} /** Essential-Bounds */ public PrimitiveNode essentialBounds() {return essentialBounds;} /** Facet-Center */ public PrimitiveNode facetCenter() {return facetCenter;} public PrimitiveNode getViaFor(ArcProto a1, ArcProto a2) { return viaMap.get(new ArcPair(a1, a2)); } public int layerHeight(ArcProto p) { for (int i = 0; i < nbLay; i++) { if (arcs[i] == p) return i; } error(true, "Can't find layer: " + p); return -1; } public ArcProto closestLayer(PortProto port, ArcProto layer) { int h = layerHeight(layer); for (int dist = 0; dist < nbLay; dist++) { int lookUp = h + dist; int lookDn = h - dist; if (lookUp < nbLay) { ArcProto lay = layerAtHeight(lookUp); if (port.connectsTo(lay)) return lay; } if (lookDn >= 0) { ArcProto lay = layerAtHeight(lookDn); if (port.connectsTo(lay)) return lay; } } error(true, "port can't connect to any layer?!!"); return null; } public ArcProto highestLayer(PortProto port) { for (int h=arcs.length-1; h>=0; h--) { if (port.connectsTo(arcs[h])) return arcs[h]; } error(true, "port can't connect to any layer?!!"); return null; } public ArcProto layerAtHeight(int layHeight) {return arcs[layHeight]; } public PrimitiveNode viaAbove(int layHeight) {return vias[layHeight];} public PrimitiveNode viaBelow(int layHeight) {return vias[layHeight - 1];} /** round to avoid MOCMOS CIF resolution errors */ public double roundToGrid(double x) { return x; } public MosInst newNmosInst(double x, double y, double w, double l, Cell parent) { return new MosInst('n', x, y, w, l, this, parent); } public MosInst newPmosInst(double x, double y, double w, double l, Cell parent) { return new MosInst('p', x, y, w, l, this, parent); } public abstract String name(); public abstract double reservedToLambda(int layer, double nbTracks); /** @return min width of Well */ public double getWellWidth() {return nwm1.getMinSizeRule().getWidth();} /** @return amount that well surrounds diffusion */ public double getWellSurroundDiffInWellContact() {return wellSurroundDiff;} /** @return MOS edge to gate edge */ public double getGateExtendPastMOS() {return gateExtendPastMOS;} /** @return min width of polysilicon 1 */ public double getP1Width() {return p1Width;} /** @return min spacing between polysilicon 1 */ public double getP1ToP1Space() {return p1ToP1Space;} /** @return min spacing between gates of series transistors */ public double getGateToGateSpace() {return gateToGateSpace;} /** @return min spacing between MOS gate and diffusion edge of diff contact */ public double getGateToDiffContSpace() {return gateToDiffContSpace;} /** @return min spacing between MOS gate and diffusion edge of diff contact * when the diffusion width is larger than the gate width */ public double getGateToDiffContSpaceDogBone() {return gateToDiffContSpaceDogBone;} /** @return min width of diffusion surrounding well contact */ public double getWellContWidth() { return wellContWidth; } /** @return min width of diffusion surrounding diff contact */ public double getDiffContWidth() { return diffContWidth; } // SizeOffset so = ndm1().getProtoSizeOffset(); // return (ndm1().getMinSizeRule().getHeight() - so.getHighYOffset() - so.getLowYOffset()); // } /** @return min width of poly contact */ public double getP1M1Width() { return polyContWidth; } // SizeOffset so = p1m1().getProtoSizeOffset(); // return (p1m1().getMinSizeRule().getHeight() - so.getHighYOffset() - so.getLowYOffset()); // } /** @return gate length that depends on foundry */ public double getGateLength() {return gateLength;} /** @return amount that select surrounds diffusion in well? */ public double selectSurroundDiffInWellContact() {return selectSurroundDiffInWellContact;} /** @return amount that select surrounds diffusion in well? */ public double selectSurroundDiffInDiffContact() {return selectSurroundDiffInActiveContact;} /** @return amount that Select surrounds MOS, along gate width dimension */ public double selectSurroundDiffAlongGateInTrans() {return selectSurroundDiffAlongGateInTrans;} /** @return y offset of poly arc connecting poly contact and gate in a L-Shape case */ public double getPolyLShapeOffset() {return offsetLShapePolyContact;} /** @return y offset of poly arc connecting poly contact and gate in a T-Shape case */ public double getPolyTShapeOffset() {return offsetTShapePolyContact;} /** @return select spacing rule */ public double getSelectSpacingRule() {return selectSpace;} /** @return select surround active in transistors but not along the gate */ public double getSelectSurroundDiffInTrans() {return selectSurroundDiffInTrans;} /** @return select surround over poly */ public double getSelectSurroundOverPoly() {return selectSurround;} /** @return minimum metal1 area (sq lambda) */ public double getM1MinArea() {return m1MinArea;} /** @return width of metal-1 in min sized diffusion contact */ public double getDiffCont_m1Width() {return diffCont_m1Width;} /** @return amount diffusion contact grows to accomodate an one additional contact cut */ public double getDiffContIncr() {return diffContIncr;} public Variable.Key getAttrX() {return ATTR_X;} public Variable.Key getAttrS() {return ATTR_S;} public Variable.Key getAttrSP() {return ATTR_SP;} public Variable.Key getAttrSN() {return ATTR_SN;} }