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.NodeProto;
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.PrimitiveNode;
import com.sun.electric.technology.SizeOffset;
import com.sun.electric.technology.Technology;
import com.sun.electric.tool.Job;
/** 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();}
}
//----------------------------- 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 TechTypeEnum techEnum;
private final PrimitiveNode essentialBounds =
generic.findNodeProto("Essential-Bounds");
private final PrimitiveNode facetCenter =
generic.findNodeProto("Facet-Center");
private final int nbLay;
private final ArcProto[] layers;
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 PrimitiveNode 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 nwell, pwell;
/** 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 od18, od25, od33, vth, vtl;
//-------------------- 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,
selectSurroundDiffInActiveContact, // select surround in active contacts
m1MinArea, // min area rules, sq lambda
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 ArcProto getLayer(int n) {
return n>(layers.length-1) ? null : layers[n];
}
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, Technology tech) {
for (Iterator<PrimitiveNode> it=tech.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 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, TechTypeEnum techEnum, String[] layerNms) {
// 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.
nbLay = layerNms.length;
technology = techy;
this.techEnum = techEnum;
//--------------------------- initialize layers -----------------------
layers = new ArcProto[nbLay];
for (int i=0; i<nbLay; i++) {
layers[i] = techy.findArcProto(layerNms[i]);
error(layers[i]==null, "No such layer: " + layerNms[i] + " in technology " + techy.getTechName());
}
p1 = getLayer(0);
m1 = getLayer(1);
m2 = getLayer(2);
m3 = getLayer(3);
m4 = getLayer(4);
m5 = getLayer(5);
m6 = getLayer(6);
m7 = getLayer(7);
m8 = getLayer(8);
m9 = getLayer(9);
pdiff = techy.findArcProto("P-Active");
ndiff = techy.findArcProto("N-Active");
ndiff18 = techy.findArcProto("thick-OD18-N-Active");
pdiff18 = techy.findArcProto("thick-OD18-P-Active");
ndiff25 = techy.findArcProto("thick-OD25-N-Active");
pdiff25 = techy.findArcProto("thick-OD25-P-Active");
ndiff33 = techy.findArcProto("thick-OD33-N-Active");
pdiff33 = techy.findArcProto("thick-OD33-P-Active");
// Layer Nodes
m1Node = techy.findNodeProto("Metal-1-Node");
m2Node = techy.findNodeProto("Metal-2-Node");
m3Node = techy.findNodeProto("Metal-3-Node");
m4Node = techy.findNodeProto("Metal-4-Node");
m5Node = techy.findNodeProto("Metal-5-Node");
m6Node = techy.findNodeProto("Metal-6-Node");
m7Node = techy.findNodeProto("Metal-7-Node");
m8Node = techy.findNodeProto("Metal-8-Node");
m9Node = techy.findNodeProto("Metal-9-Node");
p1Node = techy.findNodeProto("Polysilicon-1-Node");
pdNode = techy.findNodeProto("P-Active-Node");
ndNode = techy.findNodeProto("N-Active-Node");
nselNode = techy.findNodeProto("N-Select-Node");
pselNode = techy.findNodeProto("P-Select-Node");
//--------------------------- 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,
new ArcProto[] {layers[i], layers[i+1]},
techy);
error(vias[i] == null, "No via for layer: " + layerNms[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 = techy.findNodeProto("Metal-1-N-Active-Con");
pdm1 = techy.findNodeProto("Metal-1-P-Active-Con");
nwm1 = techy.findNodeProto("Metal-1-N-Well-Con");
pwm1 = 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 = techy.findNodeProto("thick-OD18-Metal-1-N-Active-Con");
pmos18contact = techy.findNodeProto("thick-OD18-Metal-1-P-Active-Con");
nmos25contact = techy.findNodeProto("thick-OD25-Metal-1-N-Active-Con");
pmos25contact = techy.findNodeProto("thick-OD25-Metal-1-P-Active-Con");
nmos33contact = techy.findNodeProto("thick-OD33-Metal-1-N-Active-Con");
pmos33contact = techy.findNodeProto("thick-OD33-Metal-1-P-Active-Con");
initViaMap();
//------------------------ initialize transistors ---------------------
nmos = techy.findNodeProto("N-Transistor");
pmos = techy.findNodeProto("P-Transistor");
nmos18 = techy.findNodeProto("OD18-N-Transistor");
pmos18 = techy.findNodeProto("OD18-P-Transistor");
nmos25 = techy.findNodeProto("OD25-N-Transistor");
pmos25 = techy.findNodeProto("OD25-P-Transistor");
nmos33 = techy.findNodeProto("OD33-N-Transistor");
pmos33 = techy.findNodeProto("OD33-P-Transistor");
// transistor layers
od18 = techy.findNodeProto("OD18-Node");
od25 = techy.findNodeProto("OD25-Node");
od33 = techy.findNodeProto("OD33-Node");
vth = techy.findNodeProto("VTH-Node");
vtl = techy.findNodeProto("VTL-Node");
//--------------------------- initialize well -------------------------
nwell = techy.findNodeProto("N-Well-Node");
pwell = techy.findNodeProto("P-Well-Node");
}
//---------------------------- 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 xSize, double ySize,
double angle,
String leftDiff, String rightDiff,
String topPoly, String botPoly,
TechType tech,
Cell parent) {
NodeProto npr = np=='n' ? tech.nmos() : tech.pmos();
this.leftDiff = leftDiff;
this.rightDiff = rightDiff;
this.topPoly = topPoly;
this.botPoly = botPoly;
mos = LayoutLib.newNodeInst(npr, x, y, xSize, ySize, angle, 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 static class MosInstV extends MosInst {
public MosInstV(char np, double x, double y, double w, double l,
TechType tech, Cell parent) {
super(np, x, y, l, w, 0,
"diff-left", "diff-right", "poly-top", "poly-bottom",
tech, parent);
}
}
public static class MosInstH extends MosInst {
public MosInstH(char np, double x, double y, double w, double l,
TechType tech, Cell parent) {
super(np, x, y, w, l, 90,
np+"-trans-diff-top", np+"-trans-diff-bottom",
np+"-trans-poly-right", np+"-trans-poly-left",
tech, parent);
}
}
public static class MosInstH1 extends MosInst {
public MosInstH1(char np, double x, double y, double w, double l,
TechType tech, Cell parent) {
super(np, x, y, w, l, 90,
"diff-top", "diff-bottom",
"poly-right", "poly-left",
tech, parent);
}
}
}
//------------------------------ public data ------------------------------
/** These are the Electric technologies understood by the gate layout
* generators */
public static enum TechTypeEnum {MOCMOS, TSMC180, CMOS90;
private TechType type;
public TechType getTechType()
{
loadTechType();
return type;
}
private void loadTechType()
{
if (type != null) return; // loaded
if (this == TechTypeEnum.MOCMOS)
type = new TechTypeMoCMOS(this);
else if (this == TechTypeEnum.TSMC180)
type = getTechTypeTSMC180(this);
else if (this == TechTypeEnum.CMOS90)
type = getTechTypeCMOS90(this);
else {
System.out.println("Invalid TechTypeEnum");
assert(false);
}
}
public static TechTypeEnum getTechTypeEnumFromTechnology(Technology tech)
{
for (TechTypeEnum t : TechTypeEnum.values())
{
// not loaded yet
if (t.type == null)
t.loadTechType();
if (t.type.getTechnology() == tech)
return t;
}
return null;
}
}
private static TechType getTechTypeTSMC180(TechTypeEnum techEnum)
{
TechType tsmc180 = null;
try
{
Class tsmc180Class = Class.forName("com.sun.electric.plugins.tsmc.TechTypeTSMC180");
Constructor<TechType> techConstr = tsmc180Class.getConstructor(TechTypeEnum.class);
tsmc180 = techConstr.newInstance(techEnum);
// java.lang.reflect.Field techField = tsmc180Class.getDeclaredField("TSMC180");
// tsmc180 = (TechType) techField.get(null);
} catch (Exception e)
{
assert(false); // runtime error
}
return tsmc180;
}
private static TechType getTechTypeCMOS90(TechTypeEnum techEnum)
{
TechType cmos90 = null;
try
{
Class cmos90Class = Class.forName("com.sun.electric.plugins.tsmc.TechTypeCMOS90");
Constructor<TechType> techConstr = cmos90Class.getConstructor(TechTypeEnum.class);
cmos90 = techConstr.newInstance(techEnum);
// java.lang.reflect.Field techField = cmos90Class.getDeclaredField("CMOS90");
// cmos90 = (TechType) techField.get(null);
} catch (Exception e)
{
assert(false); // runtime error
}
return cmos90;
}
//----------------------------- public methods ----------------------------
public abstract int getNumMetals();
public Technology getTechnology() {return technology;}
public TechTypeEnum getEnum() {return techEnum; }
/** 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;}
public PrimitiveNode pmos() {return pmos;}
public PrimitiveNode nmos18() {return nmos18;}
public PrimitiveNode pmos18() {return pmos18;}
public PrimitiveNode nmos25() {return nmos25;}
public PrimitiveNode pmos25() {return pmos25;}
public PrimitiveNode nmos33() {return nmos33;}
public PrimitiveNode pmos33() {return pmos33;}
/** 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 nwell;}
public PrimitiveNode pwell() {return pwell;}
/** 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 od18;}
public PrimitiveNode od25() {return od25;}
public PrimitiveNode od33() {return od33;}
public PrimitiveNode vth() {return vth;}
public PrimitiveNode vtl() {return vtl;}
/** 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 (layers[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=layers.length-1; h>=0; h--) {
if (port.connectsTo(layers[h])) return layers[h];
}
error(true, "port can't connect to any layer?!!");
return null;
}
public ArcProto layerAtHeight(int layHeight) {return layers[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 abstract double roundToGrid(double x);
public abstract MosInst newNmosInst(double x, double y,
double w, double l, Cell parent);
public abstract MosInst newPmosInst(double x, double y,
double w, double l, Cell 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 getWellSurroundDiff() {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 diff contact */
public double getDiffContWidth() {
SizeOffset so = ndm1().getProtoSizeOffset();
return (ndm1().getMinSizeRule().getHeight() - so.getHighYOffset() - so.getLowYOffset());
}
/** @return min width of poly contact */
public double getP1M1Width() {
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 selectSurroundDiffInActiveContact() {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;}
}