/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: Layer.java
*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
*
* Electric(tm) is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Electric(tm) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Electric(tm); see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, Mass 02111-1307, USA.
*/
package com.sun.electric.technology;
import com.sun.electric.database.EObjectInputStream;
import com.sun.electric.database.EObjectOutputStream;
import com.sun.electric.database.geometry.EGraphics;
import com.sun.electric.database.geometry.Poly;
import com.sun.electric.database.id.LayerId;
import com.sun.electric.database.prototype.PortCharacteristic;
import com.sun.electric.database.text.Setting;
import com.sun.electric.tool.user.UserInterfaceMain;
import com.sun.electric.util.math.DBMath;
import java.awt.Color;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
/**
* The Layer class defines a single layer of material, out of which NodeInst and ArcInst objects are created.
* The Layers are defined by the PrimitiveNode and ArcProto classes, and are used in the generation of geometry.
* In addition, layers have extra information that is used for output and behavior.
*/
public class Layer implements Serializable, Comparable
{
public static final double DEFAULT_THICKNESS = 0; // 3D default thickness
public static final double DEFAULT_DISTANCE = 0; // 3D default distance
/** Describes a P-type layer. */ private static final int PTYPE = 0100;
/** Describes a N-type layer. */ private static final int NTYPE = 0200;
/** Describes a depletion layer. */ private static final int DEPLETION = 0400;
/** Describes a enhancement layer. */ private static final int ENHANCEMENT = 01000;
/** Describes a light doped layer. */ private static final int LIGHT = 02000;
/** Describes a heavy doped layer. */ private static final int HEAVY = 04000;
// /** Describes a pseudo layer. */ private static final int PSEUDO = 010000;
/** Describes a deep layer. */ private static final int DEEP = 010000;
/** Describes a nonelectrical layer (does not carry signals). */ private static final int NONELEC = 020000;
/** Describes a layer that contacts metal (used to identify contacts/vias). */ private static final int CONMETAL = 040000;
/** Describes a layer that contacts polysilicon (used to identify contacts). */ private static final int CONPOLY = 0100000;
/** Describes a layer that contacts diffusion (used to identify contacts). */ private static final int CONDIFF = 0200000;
/** Describes a layer that is native. */ private static final int NATIVE = 0400000;
/** Describes a layer that is VTH or VTL */ private static final int HLVT = 010000000;
/** Describes a layer that is inside transistor. */ private static final int INTRANS = 020000000;
/** Describes a thick layer. */ private static final int THICK = 040000000;
/** Describes a carbon-nanotube Active layer. */ private static final int CARBNANO = 0100000000;
private static final LayerNumbers metalLayers = new LayerNumbers();
private static final LayerNumbers contactLayers = new LayerNumbers();
private static final LayerNumbers polyLayers = new LayerNumbers();
private static List<Function> allFunctions;
/**
* Get Function Set associated to a given Layer
* @param layer
* @return
*/
public static Function.Set getMultiLayersSet(Layer layer)
{
Function.Set thisLayerFunction = (layer.getFunction().isPoly()) ?
new Function.Set(Function.POLY1, Function.GATE) :
new Function.Set(layer);
return thisLayerFunction;
}
private static class LayerNumbers
{
private final ArrayList<Function> list;
private int base;
LayerNumbers()
{
list = new ArrayList<Function>();
base = 0;
}
public void addLayer(Function fun, int level)
{
while (level < base)
{
base--;
list.add(0, null);
}
while (list.size() <= level-base) list.add(null);
Function oldFunction = list.set(level-base, fun);
assert oldFunction == null;
}
public Function get(int level)
{
return list.get(level-base);
}
}
public int compareTo(Object other)
{
String s = toString();
String sOther = other.toString();
return s.compareToIgnoreCase(sOther);
}
/**
* Function is a typesafe enum class that describes the function of a layer.
* Functions are technology-independent and describe the nature of the layer (Metal, Polysilicon, etc.)
*/
public static enum Function
{
/** Describes an unknown layer. */ UNKNOWN ("unknown", 0, 0, 0, 35, 0, 0),
/** Describes a local interconnect metal layer 2. */ METALNEG2 ("metal-2-local", -2, 0, 0, 13, 0, 0),
/** Describes a local interconnect metal layer 1. */ METALNEG1 ("metal-1-local", -1, 0, 0, 15, 0, 0),
/** Describes a metal layer 1. */ METAL1 ("metal-1", 1, 0, 0, 17, 0, 0),
/** Describes a metal layer 2. */ METAL2 ("metal-2", 2, 0, 0, 19, 0, 0),
/** Describes a metal layer 3. */ METAL3 ("metal-3", 3, 0, 0, 21, 0, 0),
/** Describes a metal layer 4. */ METAL4 ("metal-4", 4, 0, 0, 23, 0, 0),
/** Describes a metal layer 5. */ METAL5 ("metal-5", 5, 0, 0, 25, 0, 0),
/** Describes a metal layer 6. */ METAL6 ("metal-6", 6, 0, 0, 27, 0, 0),
/** Describes a metal layer 7. */ METAL7 ("metal-7", 7, 0, 0, 29, 0, 0),
/** Describes a metal layer 8. */ METAL8 ("metal-8", 8, 0, 0, 31, 0, 0),
/** Describes a metal layer 9. */ METAL9 ("metal-9", 9, 0, 0, 33, 0, 0),
/** Describes a metal layer 10. */ METAL10 ("metal-10", 10, 0, 0, 35, 0, 0),
/** Describes a metal layer 11. */ METAL11 ("metal-11", 11, 0, 0, 37, 0, 0),
/** Describes a metal layer 12. */ METAL12 ("metal-12", 12, 0, 0, 39, 0, 0),
/** Describes a polysilicon layer 1. */ POLY1 ("poly-1", 0, 0, 1, 12, 0, 0),
/** Describes a polysilicon layer 2. */ POLY2 ("poly-2", 0, 0, 2, 13, 0, 0),
/** Describes a polysilicon layer 3. */ POLY3 ("poly-3", 0, 0, 3, 14, 0, 0),
/** Describes a polysilicon gate layer. */ GATE ("gate", 0, 0, 0, 15, INTRANS, 0),
/** Describes a diffusion layer. */ DIFF ("diffusion", 0, 0, 0, 11, 0, 0),
/** Describes a P-diffusion layer. */ DIFFP ("p-diffusion", 0, 0, 0, 11, PTYPE, 0),
/** Describes a N-diffusion layer. */ DIFFN ("n-diffusion", 0, 0, 0, 11, NTYPE, 0),
/** Describes a N-diffusion carbon nanotube layer. */ DIFFNCN ("n-diffusion-cn", 0, 0, 0, 11, NTYPE|CARBNANO, 0),
/** Describes a P-diffusion carbon nanotube layer. */ DIFFPCN ("n-diffusion-cn", 0, 0, 0, 11, NTYPE|CARBNANO, 0),
/** Describes an implant layer. */ IMPLANT ("implant", 0, 0, 0, 2, 0, 0),
/** Describes a P-implant layer. */ IMPLANTP ("p-implant", 0, 0, 0, 2, PTYPE, 0),
/** Describes an N-implant layer. */ IMPLANTN ("n-implant", 0, 0, 0, 2, NTYPE, 0),
/** Describes a contact layer 1. */ CONTACT1 ("contact-1", 0, 1, 0, 16, 0, 0),
/** Describes a contact layer 2. */ CONTACT2 ("contact-2", 0, 2, 0, 18, 0, 0),
/** Describes a contact layer 3. */ CONTACT3 ("contact-3", 0, 3, 0, 20, 0, 0),
/** Describes a contact layer 4. */ CONTACT4 ("contact-4", 0, 4, 0, 22, 0, 0),
/** Describes a contact layer 5. */ CONTACT5 ("contact-5", 0, 5, 0, 24, 0, 0),
/** Describes a contact layer 6. */ CONTACT6 ("contact-6", 0, 6, 0, 26, 0, 0),
/** Describes a contact layer 7. */ CONTACT7 ("contact-7", 0, 7, 0, 28, 0, 0),
/** Describes a contact layer 8. */ CONTACT8 ("contact-8", 0, 8, 0, 30, 0, 0),
/** Describes a contact layer 9. */ CONTACT9 ("contact-9", 0, 9, 0, 32, 0, 0),
/** Describes a contact layer 10. */ CONTACT10 ("contact-10", 0,10, 0, 34, 0, 0),
/** Describes a contact layer 11. */ CONTACT11 ("contact-11", 0,11, 0, 36, 0, 0),
/** Describes a contact layer 12. */ CONTACT12 ("contact-12", 0,12, 0, 38, 0, 0),
/** Describes a sinker (diffusion-to-buried plug). */ PLUG ("plug", 0, 0, 0, 40, 0, 0),
/** Describes an overglass layer (passivation). */ OVERGLASS ("overglass", 0, 0, 0, 41, 0, 0),
/** Describes a resistor layer. */ RESISTOR ("resistor", 0, 0, 0, 4, 0, 0),
/** Describes a capacitor layer. */ CAP ("capacitor", 0, 0, 0, 5, 0, 0),
/** Describes a transistor layer. */ TRANSISTOR("transistor", 0, 0, 0, 3, 0, 0),
/** Describes an emitter of bipolar transistor. */ EMITTER ("emitter", 0, 0, 0, 6, 0, 0),
/** Describes a base of bipolar transistor. */ BASE ("base", 0, 0, 0, 7, 0, 0),
/** Describes a collector of bipolar transistor. */ COLLECTOR ("collector", 0, 0, 0, 8, 0, 0),
/** Describes a substrate layer. */ SUBSTRATE ("substrate", 0, 0, 0, 1, 0, 0),
/** Describes a well layer. */ WELL ("well", 0, 0, 0, 0, 0, 0),
/** Describes a P-well layer. */ WELLP ("p-well", 0, 0, 0, 0, PTYPE, 0),
/** Describes a N-well layer. */ WELLN ("n-well", 0, 0, 0, 0, NTYPE, 0),
/** Describes a guard layer. */ GUARD ("guard", 0, 0, 0, 9, 0, 0),
/** Describes an isolation layer (bipolar). */ ISOLATION ("isolation", 0, 0, 0, 10, 0, 0),
/** Describes a bus layer. */ BUS ("bus", 0, 0, 0, 42, 0, 0),
/** Describes an artwork layer. */ ART ("art", 0, 0, 0, 43, 0, 0),
/** Describes a control layer. */ CONTROL ("control", 0, 0, 0, 44, 0, 0),
/** Describes a tileNot layer. */ TILENOT ("tileNot", 0, 0, 0, 45, 0, 0),
/** Describes a dummy polysilicon layer 1 */ DMYPOLY1 ("dmy-poly-1", 0, 0, 0, POLY1.getHeight(), 0, 0),
/** Describes a dummy polysilicon layer 2 */ DMYPOLY2 ("dmy-poly-2", 0, 0, 0, POLY2.getHeight(), 0, 0),
/** Describes a dummy polysilicon layer 3 */ DMYPOLY3 ("dmy-poly-3", 0, 0, 0, POLY3.getHeight(), 0, 0),
/** Describes a dummy diffusion layer */ DMYDIFF ("dmy-diffusion", 0, 0, 0, DIFF.getHeight(), 0, 0),
/** Describes a dummy metal layer 1 */ DMYMETAL1 ("dmy-metal-1", 0, 0, 0, METAL1.getHeight(), 0, 1),
/** Describes a dummy metal layer 2 */ DMYMETAL2 ("dmy-metal-2", 0, 0, 0, METAL2.getHeight(), 0, 2),
/** Describes a dummy metal layer 3 */ DMYMETAL3 ("dmy-metal-3", 0, 0, 0, METAL3.getHeight(), 0, 3),
/** Describes a dummy metal layer 4 */ DMYMETAL4 ("dmy-metal-4", 0, 0, 0, METAL4.getHeight(), 0, 4),
/** Describes a dummy metal layer 5 */ DMYMETAL5 ("dmy-metal-5", 0, 0, 0, METAL5.getHeight(), 0, 5),
/** Describes a dummy metal layer 6 */ DMYMETAL6 ("dmy-metal-6", 0, 0, 0, METAL6.getHeight(), 0, 6),
/** Describes a dummy metal layer 7 */ DMYMETAL7 ("dmy-metal-7", 0, 0, 0, METAL7.getHeight(), 0, 7),
/** Describes a dummy metal layer 8 */ DMYMETAL8 ("dmy-metal-8", 0, 0, 0, METAL8.getHeight(), 0, 8),
/** Describes a dummy metal layer 9 */ DMYMETAL9 ("dmy-metal-9", 0, 0, 0, METAL9.getHeight(), 0, 9),
/** Describes a dummy metal layer 10 */ DMYMETAL10("dmy-metal-10", 0, 0, 0, METAL10.getHeight(), 0, 10),
/** Describes a dummy metal layer 11 */ DMYMETAL11("dmy-metal-11", 0, 0, 0, METAL11.getHeight(), 0, 11),
/** Describes a dummy metal layer 12 */ DMYMETAL12("dmy-metal-12", 0, 0, 0, METAL12.getHeight(), 0, 12),
/** Describes a exclusion polysilicon layer 1 */ DEXCLPOLY1("dexcl-poly-1", 0, 0, 0, POLY1.getHeight(), 0, 0),
/** Describes a exclusion polysilicon layer 2 */ DEXCLPOLY2("dexcl-poly-2", 0, 0, 0, POLY2.getHeight(), 0, 0),
/** Describes a exclusion polysilicon layer 3 */ DEXCLPOLY3("dexcl-poly-3", 0, 0, 0, POLY3.getHeight(), 0, 0),
/** Describes a exclusion diffusion layer */ DEXCLDIFF("dexcl-diffusion", 0, 0, 0, DIFF.getHeight(), 0, 0),
/** Describes a exclusion metal layer 1 */ DEXCLMETAL1("dexcl-metal-1", 0, 0, 0, METAL1.getHeight(), 0, 1),
/** Describes a exclusion metal layer 2 */ DEXCLMETAL2("dexcl-metal-2", 0, 0, 0, METAL2.getHeight(), 0, 2),
/** Describes a exclusion metal layer 3 */ DEXCLMETAL3("dexcl-metal-3", 0, 0, 0, METAL3.getHeight(), 0, 3),
/** Describes a exclusion metal layer 4 */ DEXCLMETAL4("dexcl-metal-4", 0, 0, 0, METAL4.getHeight(), 0, 4),
/** Describes a exclusion metal layer 5 */ DEXCLMETAL5("dexcl-metal-5", 0, 0, 0, METAL5.getHeight(), 0, 5),
/** Describes a exclusion metal layer 6 */ DEXCLMETAL6("dexcl-metal-6", 0, 0, 0, METAL6.getHeight(), 0, 6),
/** Describes a exclusion metal layer 7 */ DEXCLMETAL7("dexcl-metal-7", 0, 0, 0, METAL7.getHeight(), 0, 7),
/** Describes a exclusion metal layer 8 */ DEXCLMETAL8("dexcl-metal-8", 0, 0, 0, METAL8.getHeight(), 0, 8),
/** Describes a exclusion metal layer 9 */ DEXCLMETAL9("dexcl-metal-9", 0, 0, 0, METAL9.getHeight(), 0, 9),
/** Describes a exclusion metal layer 10 */ DEXCLMETAL10("dexcl-metal-10", 0, 0, 0, METAL10.getHeight(), 0, 10),
/** Describes a exclusion metal layer 11 */ DEXCLMETAL11("dexcl-metal-11", 0, 0, 0, METAL11.getHeight(), 0, 11),
/** Describes a exclusion metal layer 12 */ DEXCLMETAL12("dexcl-metal-12", 0, 0, 0, METAL12.getHeight(), 0, 12);
// /** Describes a P-type layer. */ public static final int PTYPE = Layer.PTYPE;
// /** Describes a N-type layer. */ public static final int NTYPE = Layer.NTYPE;
/** Describes a depletion layer. */ public static final int DEPLETION = Layer.DEPLETION;
/** Describes a enhancement layer. */ public static final int ENHANCEMENT = Layer.ENHANCEMENT;
/** Describes a light doped layer. */ public static final int LIGHT = Layer.LIGHT;
/** Describes a heavy doped layer. */ public static final int HEAVY = Layer.HEAVY;
// /** Describes a pseudo layer. */ public static final int PSEUDO = Layer.PSEUDO;
/** Describes a nonelectrical layer (does not carry signals). */ public static final int NONELEC = Layer.NONELEC;
/** Describes a layer that contacts metal (used to identify contacts/vias). */ public static final int CONMETAL = Layer.CONMETAL;
/** Describes a layer that contacts polysilicon (used to identify contacts). */ public static final int CONPOLY = Layer.CONPOLY;
/** Describes a layer that contacts diffusion (used to identify contacts). */ public static final int CONDIFF = Layer.CONDIFF;
/** Describes a layer that is VTH or VTL */ public static final int HLVT = Layer.HLVT;
// /** Describes a layer that is inside transistor. */ public static final int INTRANS = Layer.INTRANS;
/** Describes a thick layer. */ public static final int THICK = Layer.THICK;
/** Describes a native layer. */ public static final int NATIVE = Layer.NATIVE;
/** Describes a deep layer. */ public static final int DEEP = Layer.DEEP;
// /** Describes a carbon-nanotube Active layer. */ public static final int CARBNANO = Layer.CARBNANO;
private final String name;
private final boolean isMetal;
private final boolean isContact;
private final boolean isPoly;
private final int level;
private final int height;
private final int extraBits;
private static final int [] extras = {PTYPE, NTYPE, DEPLETION, ENHANCEMENT, LIGHT, HEAVY, /*PSEUDO,*/ NONELEC, CONMETAL, CONPOLY, CONDIFF, HLVT, INTRANS, THICK, CARBNANO};
static {
allFunctions = Arrays.asList(Function.class.getEnumConstants());
}
private Function(String name, int metalLevel, int contactLevel, int polyLevel, int height, int extraBits, int genericLevel)
{
this.name = name;
this.height = height;
this.extraBits = extraBits;
isMetal = metalLevel != 0;
isContact = contactLevel != 0;
isPoly = polyLevel != 0;
int level = 0;
if (genericLevel != 0) level = genericLevel;
if (isMetal) metalLayers.addLayer(this, level = metalLevel);
if (isContact) contactLayers.addLayer(this, level = contactLevel);
if (isPoly) polyLayers.addLayer(this, level = polyLevel);
this.level = level;
}
// private void addToLayers(ArrayList<Function> layers, int level) {
// this.level = level;
// while (layers.size() <= level) layers.add(null);
// Function oldFunction = layers.set(level, this);
// assert oldFunction == null;
// }
/**
* Returns a printable version of this Function.
* @return a printable version of this Function.
*/
public String toString()
{
String toStr = name;
for(int i=0; i<extras.length; i++)
{
if ((extraBits & extras[i]) == 0) continue;
toStr += "," + getExtraName(extras[i]);
}
return toStr;
}
/**
* Returns the name for this Function.
* @return the name for this Function.
*/
public String getName() { return name; }
/**
* Returns the constant name for this Function.
* Constant names are used when writing Java code, so they must be the same as the actual symbol name.
* @return the constant name for this Function.
*/
public String getConstantName() { return name(); }
/**
* Method to return a list of all Layer Functions.
* @return a list of all Layer Functions.
*/
public static List<Function> getFunctions() { return allFunctions; }
/**
* Method to return an array of the Layer Function "extra bits".
* @return an array of the Layer Function "extra bits".
* Each entry in the array is a single "extra bit", but they can be ORed together to combine them.
*/
public static int [] getFunctionExtras() { return extras; }
/**
* Method to convert an "extra bits" value to a name.
* @param extra the extra bits value (must be a single bit, not an ORed combination).
* @return the name of that extra bit.
*/
public static String getExtraName(int extra)
{
if (extra == PTYPE) return "p-type";
if (extra == NTYPE) return "n-type";
if (extra == DEPLETION) return "depletion";
if (extra == ENHANCEMENT) return "enhancement";
if (extra == LIGHT) return "light";
if (extra == HEAVY) return "heavy";
// if (extra == PSEUDO) return "pseudo";
if (extra == NONELEC) return "nonelectrical";
if (extra == CONMETAL) return "connects-metal";
if (extra == CONPOLY) return "connects-poly";
if (extra == CONDIFF) return "connects-diff";
if (extra == HLVT) return "vt";
if (extra == INTRANS) return "inside-transistor";
if (extra == THICK) return "thick";
if (extra == NATIVE) return "native";
if (extra == DEEP) return "deep";
if (extra == CARBNANO) return "carb-nano";
return "";
}
/**
* Method to convert an "extra bits" value to a constant name.
* Constant names are used when writing Java code, so they must be the same as the actual symbol name.
* @param extra the extra bits value (must be a single bit, not an ORed combination).
* @return the name of that extra bit's constant.
*/
public static String getExtraConstantName(int extra)
{
if (extra == PTYPE) return "PTYPE";
if (extra == NTYPE) return "NTYPE";
if (extra == DEPLETION) return "DEPLETION";
if (extra == ENHANCEMENT) return "ENHANCEMENT";
if (extra == LIGHT) return "LIGHT";
if (extra == HEAVY) return "HEAVY";
// if (extra == PSEUDO) return "PSEUDO";
if (extra == NONELEC) return "NONELEC";
if (extra == CONMETAL) return "CONMETAL";
if (extra == CONPOLY) return "CONPOLY";
if (extra == CONDIFF) return "CONDIFF";
if (extra == HLVT) return "HLVT";
if (extra == INTRANS) return "INTRANS";
if (extra == THICK) return "THICK";
if (extra == NATIVE) return "NATIVE";
if (extra == DEEP) return "DEEP";
if (extra == CARBNANO) return "CN";
return "";
}
/**
* Method to convert an "extra bits" name to its numeric value.
* @param name the name of the bit.
* @return the numeric equivalent of that bit.
*/
public static int parseExtraName(String name)
{
if (name.equalsIgnoreCase("p-type")) return PTYPE;
if (name.equalsIgnoreCase("n-type")) return NTYPE;
if (name.equalsIgnoreCase("depletion")) return DEPLETION;
if (name.equalsIgnoreCase("enhancement")) return ENHANCEMENT;
if (name.equalsIgnoreCase("light")) return LIGHT;
if (name.equalsIgnoreCase("heavy")) return HEAVY;
// if (name.equalsIgnoreCase("pseudo")) return PSEUDO;
if (name.equalsIgnoreCase("nonelectrical")) return NONELEC;
if (name.equalsIgnoreCase("connects-metal")) return CONMETAL;
if (name.equalsIgnoreCase("connects-poly")) return CONPOLY;
if (name.equalsIgnoreCase("connects-diff")) return CONDIFF;
if (name.equalsIgnoreCase("inside-transistor")) return INTRANS;
if (name.equalsIgnoreCase("thick")) return THICK;
if (name.equalsIgnoreCase("vt")) return HLVT;
if (name.equalsIgnoreCase("native")) return NATIVE;
if (name.equalsIgnoreCase("deep")) return DEEP;
if (name.equalsIgnoreCase("carb-nano")) return CARBNANO;
return 0;
}
/**
* Method to get the level of this Layer.
* The level applies to metal and polysilicon functions, and gives the layer number
* (i.e. Metal-2 is level 2).
* @return the level of this Layer.
*/
public int getLevel() { return level; }
/**
* Method to find the Function that corresponds to Metal on a given layer.
* @param level the layer (starting at 1 for Metal-1).
* @return the Function that represents that Metal layer. Null if the given layer level is invalid.
*/
public static Function getMetal(int level)
{
if (level > EGraphics.TRANSPARENT_12)
{
System.out.println("Invalid metal layer level:" + level);
return null;
}
Function func = metalLayers.get(level);
return func;
}
/**
* Method to find the Function that corresponds to Dummy Metal on a given layer.
* @param level the layer (starting at 0 for Metal-1).
* @return the Function that represents that Metal layer. Null if the given layer level is invalid.
*/
public static Function getDummyMetal(int level)
{
if (level > EGraphics.TRANSPARENT_12)
{
System.out.println("Invalid metal layer level:" + level);
return null;
}
switch (level)
{
case 0: return (Layer.Function.DMYMETAL1);
case 1: return (Layer.Function.DMYMETAL2);
case 2: return (Layer.Function.DMYMETAL3);
case 3: return (Layer.Function.DMYMETAL4);
case 4: return (Layer.Function.DMYMETAL5);
case 5: return (Layer.Function.DMYMETAL6);
case 6: return (Layer.Function.DMYMETAL7);
case 7: return (Layer.Function.DMYMETAL8);
case 8: return (Layer.Function.DMYMETAL9);
case 9: return (Layer.Function.DMYMETAL10);
case 10: return (Layer.Function.DMYMETAL11);
case 11: return (Layer.Function.DMYMETAL12);
}
// Should never reach this point
return null;
}
/**
* Method to find the Function that corresponds to Dummy Exclusion Metal on a given layer.
* @param l the layer (starting at 0 for Metal-1).
* @return the Function that represents that Metal layer. Null if the given layer level is invalid.
*/
public static Function getDummyExclMetal(int l)
{
if (l > EGraphics.TRANSPARENT_12)
{
System.out.println("Invalid metal layer level:" + l);
return null;
}
switch (l)
{
case 0: return (Layer.Function.DEXCLMETAL1);
case 1: return (Layer.Function.DEXCLMETAL2);
case 2: return (Layer.Function.DEXCLMETAL3);
case 3: return (Layer.Function.DEXCLMETAL4);
case 4: return (Layer.Function.DEXCLMETAL5);
case 5: return (Layer.Function.DEXCLMETAL6);
case 6: return (Layer.Function.DEXCLMETAL7);
case 7: return (Layer.Function.DEXCLMETAL8);
case 8: return (Layer.Function.DEXCLMETAL9);
case 9: return (Layer.Function.DEXCLMETAL10);
case 10: return (Layer.Function.DEXCLMETAL11);
case 11: return (Layer.Function.DEXCLMETAL12);
}
// Should never reach this point
return null;
}
/**
* Method to find the Function that corresponds to a contact on a given layer.
* @param l the layer (starting at 1 for Contact-1).
* @return the Function that represents that Contact layer. Null if the given layer level is invalid.
*/
public static Function getContact(int l)
{
if (l > EGraphics.TRANSPARENT_12)
{
System.out.println("Invalid via layer level:" + l);
return null;
}
Function func = contactLayers.get(l);
return func;
}
/**
* Method to find the Function that corresponds to Polysilicon on a given layer.
* @param l the layer (starting at 1 for Polysilicon-1).
* @return the Function that represents that Polysilicon layer.
*/
public static Function getPoly(int l)
{
Function func = polyLayers.get(l);
return func;
}
/**
* Method to tell whether this layer function is metal.
* @return true if this layer function is metal.
*/
public boolean isMetal() { return isMetal; }
/**
* Method to tell whether this layer function is diffusion (active).
* @return true if this layer function is diffusion (active).
*/
public boolean isDiff()
{
if (this == DIFF || this == DIFFP || this == DIFFN || this == DIFFNCN || this == DIFFPCN) return true;
return false;
}
/**
* Method to tell whether this layer function is polysilicon.
* @return true if this layer function is polysilicon.
*/
public boolean isPoly() { return isPoly || this == GATE; };
/**
* Method to tell whether this layer function is polysilicon in the gate of a transistor.
* @return true if this layer function is the gate of a transistor.
*/
public boolean isGatePoly()
{
if (isPoly() && (extraBits&INTRANS) != 0) return true;
return false;
}
/**
* Method to tell whether this layer function is a contact.
* @return true if this layer function is contact.
*/
public boolean isContact() { return isContact; }
/**
* Method to tell whether this layer function is a well.
* @return true if this layer function is a well.
*/
public boolean isWell()
{
if (this == WELL || this == WELLP || this == WELLN) return true;
return false;
}
/**
* Method to tell whether this layer function is substrate.
* @return true if this layer function is substrate.
*/
public boolean isSubstrate()
{
if (this == SUBSTRATE ||
this == WELL || this == WELLP || this == WELLN ||
this == IMPLANT || this == IMPLANTN || this == IMPLANTP) return true;
return false;
}
/**
* Method to tell whether this layer function is implant.
* @return true if this layer function is implant.
*/
public boolean isImplant()
{
return (this == IMPLANT || this == IMPLANTN || this == IMPLANTP);
}
/**
* Method to tell whether this layer function is a dummy
* @return true if this layer function is a dummy
*/
public boolean isDummy()
{
return (this == DMYDIFF || this == DMYPOLY1 || this == DMYPOLY2 || this == DMYPOLY3 ||
this == DMYMETAL1 || this == DMYMETAL2 || this == DMYMETAL3 || this == DMYMETAL4 ||
this == DMYMETAL5 || this == DMYMETAL6 || this == DMYMETAL7 || this == DMYMETAL8 ||
this == DMYMETAL9 || this == DMYMETAL10 || this == DMYMETAL11 || this == DMYMETAL12);
}
/**
* Method to tell whether this layer function is a dummy exclusion
* @return true if this layer function is a dummy exclusion
*/
public boolean isDummyExclusion()
{
return (this == DEXCLDIFF || this == DEXCLPOLY1 || this == DEXCLPOLY2 || this == DEXCLPOLY3 ||
this == DEXCLMETAL1 || this == DEXCLMETAL2 || this == DEXCLMETAL3 || this == DEXCLMETAL4 ||
this == DEXCLMETAL5 || this == DEXCLMETAL6 || this == DEXCLMETAL7 || this == DEXCLMETAL8 ||
this == DEXCLMETAL9 || this == DEXCLMETAL10 || this == DEXCLMETAL11 || this == DEXCLMETAL12);
}
/**
* Method to tell whether this layer function is in subset
* of layer functions restricted by specified number
* of metals and polysilicons.
* @param numMetals number of metals in subset.
* @param numPolys number of polysilicons in subset
* @return true if this layer function is in subset.
*/
public boolean isUsed(int numMetals, int numPolys) {
if (isMetal || isContact || isDummyExclusion())
return level <= numMetals;
else if (isPoly)
return level <= numPolys;
else
return true;
}
/**
* Method to tell the distance of this layer function.
* @return the distance of this layer function.
*/
public int getHeight() { return height; }
/**
* A set of Layer.Functions
*/
public static class Set {
final BitSet bits = new BitSet();
int extraBits;
/** Set if all Layer.Functions */
public static final Set ALL = new Set(Function.class.getEnumConstants());
/**
* Constructs Function.Set from a Layer
* @param l Layer
*/
public Set(Layer l)
{
bits.set(l.getFunction().ordinal());
extraBits = l.getFunctionExtras();
}
/**
* Constructs Function.Set from varargs Functions.
* @param funs variable list of Functions.
*/
public Set(Function ... funs) {
for (Function f: funs)
bits.set(f.ordinal());
this.extraBits = NO_FUNCTION_EXTRAS; // same value as Layer.extraFunctions
}
/**
* Constructs Function.Set from a collection of Functions.
* @param funs a Collection of Functions.
*/
public Set(Collection<Function> funs) {
for (Function f: funs)
bits.set(f.ordinal());
this.extraBits = NO_FUNCTION_EXTRAS; // same value as Layer.extraFunctions;
}
public void add(Layer l)
{
bits.set(l.getFunction().ordinal());
extraBits |= l.getFunctionExtras();
}
/**
* Returns true if specified Functions is in this Set.
* @param f Function to test.
* @param extraFunction
* @return true if specified Functions is in this Set.
*/
public boolean contains(Function f, int extraFunction)
{
// Check first if there is a match in the extra bits
int extra = extraBits&extraFunction;
boolean extraBitsM = extraFunction == NO_FUNCTION_EXTRAS || (extra != 0);
return extraBitsM && bits.get(f.ordinal());
}
}
}
/***************************************************************************************************
* Layer Comparators
***************************************************************************************************/
/**
* A comparator object for sorting Layers by their level.
* Created once because it is used often.
*/
public static final LayerSortByFunctionLevel layerSortByFunctionLevel = new LayerSortByFunctionLevel();
/**
* Comparator class for sorting Layers by their name.
*/
public static class LayerSortByFunctionLevel implements Comparator<Layer>
{
/**
* Method to compare two layers by their name.
* @param l1 one layer.
* @param l2 another layer.
* @return an integer indicating their sorting order.
*/
public int compare(Layer l1, Layer l2)
{
int level1 = l1.getFunction().getLevel();
int level2 = l2.getFunction().getLevel();
return level1 - level2;
}
// public static boolean areNeightborLayers(Layer l1, Layer l2)
// {
// int level1 = l1.getFunction().getLevel();
// int level2 = l2.getFunction().getLevel();
// return Math.abs(getNeighborLevel(l1, l2)) <=1;
// }
/**
* Method to determine level of Layer2 with respect to Layer1.
* Positive if Layer2 is above Layer1.
* @param l1 the first Layer.
* @param l2 the second Layer.
* @return realtionship of layers.
*/
public static int getNeighborLevel(Layer l1, Layer l2)
{
int level1 = l1.getFunction().getLevel();
int level2 = l2.getFunction().getLevel();
return level2 - level1;
}
}
/**
* A comparator object for sorting Layers by their name.
* Created once because it is used often.
*/
public static final LayerSortByName layerSortByName = new LayerSortByName();
/**
* Comparator class for sorting Layers by their name.
*/
private static class LayerSortByName implements Comparator<Layer>
{
/**
* Method to compare two layers by their name.
* @param l1 one layer.
* @param l2 another layer.
* @return an integer indicating their sorting order.
*/
public int compare(Layer l1, Layer l2)
{
String s1 = l1.getName();
String s2 = l2.getName();
return s1.compareToIgnoreCase(s2);
}
}
/***************************************************************************************************
* End of Layer Comparators
***************************************************************************************************/
private final LayerId layerId;
private int index = -1; // contains index in technology or -1 for standalone layers
private final Technology tech;
private EGraphics factoryGraphics;
private Function function;
private static final int NO_FUNCTION_EXTRAS = 0;
private int functionExtras;
private final boolean pseudo;
private Setting cifLayerSetting;
private Setting dxfLayerSetting;
// private String gdsLayer;
private Setting skillLayerSetting;
private Setting resistanceSetting;
private Setting capacitanceSetting;
private Setting edgeCapacitanceSetting;
private Setting layer3DThicknessSetting;
private Setting layer3DDistanceSetting;
/** the pseudo layer (if exists) */ private Layer pseudoLayer;
/** the "real" layer (if this one is pseudo) */ private Layer nonPseudoLayer;
/** true if dimmed (drawn darker) undimmed layers are highlighted */ private boolean dimmed;
/** the pure-layer node that contains just this layer */ private PrimitiveNode pureLayerNode;
private Layer(String name, boolean pseudo, Technology tech, EGraphics graphics)
{
layerId = tech.getId().newLayerId(name);
this.tech = tech;
if (graphics == null)
throw new NullPointerException();
this.factoryGraphics = graphics;
this.nonPseudoLayer = this;
this.pseudo = pseudo;
this.dimmed = false;
this.function = Function.UNKNOWN;
}
protected Object writeReplace() { return new LayerKey(this); }
private static class LayerKey extends EObjectInputStream.Key<Layer> {
public LayerKey() {}
private LayerKey(Layer layer) { super(layer); }
@Override
public void writeExternal(EObjectOutputStream out, Layer layer) throws IOException {
out.writeObject(layer.getTechnology());
out.writeInt(layer.getId().chronIndex);
}
@Override
public Layer readExternal(EObjectInputStream in) throws IOException, ClassNotFoundException {
Technology tech = (Technology)in.readObject();
int chronIndex = in.readInt();
Layer layer = tech.getLayerByChronIndex(chronIndex);
if (layer == null)
throw new InvalidObjectException("arc proto not found");
return layer;
}
}
/**
* Method to create a new layer with the given name and graphics.
* @param tech the Technology that this layer belongs to.
* @param name the name of the layer.
* @param graphics the appearance of the layer.
* @return the Layer object.
*/
public static Layer newInstance(Technology tech, String name, EGraphics graphics)
{
if (tech == null) throw new NullPointerException();
int transparent = graphics.getTransparentLayer();
if (transparent != 0) {
Color colorFromMap = tech.getFactoryTransparentLayerColors()[transparent - 1];
if ((colorFromMap.getRGB() & 0xFFFFFF) != graphics.getRGB())
throw new IllegalArgumentException();
}
Layer layer = new Layer(name, false, tech, graphics);
tech.addLayer(layer);
return layer;
}
/**
* Method to create a pseudo-layer for this Layer with a standard name "Pseudo-XXX".
* @return the pseudo-layer.
*/
public Layer makePseudo() {
assert pseudoLayer == null;
String pseudoLayerName = "Pseudo-" + getName();
pseudoLayer = new Layer(pseudoLayerName, true, tech, factoryGraphics);
pseudoLayer.setFunction(function, functionExtras);
pseudoLayer.nonPseudoLayer = this;
return pseudoLayer;
}
/**
* Method to return the Id of this Layer.
* @return the Id of this Layer.
*/
public LayerId getId() { return layerId; }
/**
* Method to return the name of this Layer.
* @return the name of this Layer.
*/
public String getName() { return layerId.name; }
/**
* Method to return the full name of this Layer.
* Full name has format "techName:layerName"
* @return the full name of this Layer.
*/
public String getFullName() { return layerId.fullName; }
/**
* Method to return the index of this Layer.
* The index is 0-based.
* @return the index of this Layer.
*/
public int getIndex() { return index; }
/**
* Method to set the index of this Layer.
* The index is 0-based.
* @param index the index of this Layer.
*/
public void setIndex(int index) { this.index = index; }
/**
* Method to return the Technology of this Layer.
* @return the Technology of this Layer.
*/
public Technology getTechnology() { return tech; }
/**
* Method to set the graphics description of this Layer.
* @param graphics graphics description of this Layer.
*/
public void setGraphics(EGraphics graphics) {
UserInterfaceMain.setGraphicsPreferences(UserInterfaceMain.getGraphicsPreferences().withGraphics(this, graphics));
}
/**
* Method to return the graphics description of this Layer.
* @return the graphics description of this Layer.
*/
public EGraphics getGraphics() { return UserInterfaceMain.getGraphicsPreferences().getGraphics(this); }
/**
* Method to return the graphics description of this Layer by factory default.
* @return the factory graphics description of this Layer.
*/
public EGraphics getFactoryGraphics() { return factoryGraphics; }
/**
* Method to set the Function of this Layer.
* @param function the Function of this Layer.
*/
public void setFunction(Function function)
{
this.function = function;
this.functionExtras = NO_FUNCTION_EXTRAS;
}
/**
* Method to set the Function of this Layer when the function is complex.
* Some layer functions have extra bits of information to describe them.
* For example, P-Type Diffusion has the Function DIFF but the extra bits PTYPE.
* @param function the Function of this Layer.
* @param functionExtras extra bits to describe the Function of this Layer.
*/
public void setFunction(Function function, int functionExtras) {
this.function = function;
int numBits = 0;
for (int i = 0; i < 32; i++) {
if ((functionExtras & (1 << i)) != 0)
numBits++;
}
if (numBits >= 2 &&
functionExtras != (DEPLETION|HEAVY) && functionExtras != (DEPLETION|LIGHT) &&
functionExtras != (ENHANCEMENT|HEAVY) && functionExtras != (ENHANCEMENT|LIGHT) ||
numBits == 1 && Function.getExtraConstantName(functionExtras).length() == 0)
throw new IllegalArgumentException("functionExtras=" + Integer.toHexString(functionExtras));
this.functionExtras = functionExtras;
}
/**
* Method to return the Function of this Layer.
* @return the Function of this Layer.
*/
public Function getFunction() { return function; }
/**
* Method to return the Function "extras" of this Layer.
* The "extras" are a set of modifier bits, such as "p-type".
* @return the Function extras of this Layer.
*/
public int getFunctionExtras() { return functionExtras; }
/**
* Method to set the Pure Layer Node associated with this Layer.
* @param pln the Pure Layer PrimitiveNode to use for this Layer.
*/
public void setPureLayerNode(PrimitiveNode pln) { pureLayerNode = pln; }
/**
* Method to make the Pure Layer Node associated with this Layer.
* @param nodeName the name of the PrimitiveNode.
* Primitive names may not contain unprintable characters, spaces, tabs, a colon (:), semicolon (;) or curly braces ({}).
* @param size the width and the height of the PrimitiveNode.
* @param style the Poly.Type this PrimitiveNode will generate (polygon, cross, etc.).
* @return the Pure Layer PrimitiveNode to use for this Layer.
*/
public PrimitiveNode makePureLayerNode(String nodeName, double size, Poly.Type style, String portName, ArcProto ... connections) {
PrimitiveNode pln = PrimitiveNode.newInstance0(nodeName, tech, size, size,
new Technology.NodeLayer []
{
new Technology.NodeLayer(this, 0, style, Technology.NodeLayer.BOX, Technology.TechPoint.makeFullBox())
});
pln.addPrimitivePorts(new PrimitivePort[]
{
PrimitivePort.newInstance(tech, pln, connections, portName, 0,180, 0, PortCharacteristic.UNKNOWN,
EdgeH.makeLeftEdge(), EdgeV.makeBottomEdge(), EdgeH.makeRightEdge(), EdgeV.makeTopEdge())
}, false);
pln.setFunction(PrimitiveNode.Function.NODE);
pln.setHoldsOutline();
pln.setSpecialType(PrimitiveNode.POLYGONAL);
pureLayerNode = pln;
return pln;
}
/**
* Method to return the Pure Layer Node associated with this Layer.
* @return the Pure Layer Node associated with this Layer.
*/
public PrimitiveNode getPureLayerNode() { return pureLayerNode; }
/**
* Method to tell whether this layer function is non-electrical.
* Non-electrical layers do not carry any signal (for example, artwork, text).
* @return true if this layer function is non-electrical.
*/
public boolean isNonElectrical()
{
return (functionExtras&Function.NONELEC) != 0;
}
/**
* Method to determine if the layer function corresponds to a diffusion layer.
* Used in parasitic calculation
* @return true if this Layer is diffusion.
*/
public boolean isDiffusionLayer()
{
return !isPseudoLayer() && getFunction().isDiff();
}
/**
* Method to determine if the layer corresponds to a VT layer. Used in DRC
* @return true if this layer is a VT layer.
*/
public boolean isVTImplantLayer()
{
return (function.isImplant() && (functionExtras&Layer.Function.HLVT) != 0);
}
/**
* Method to determine if the layer corresponds to a poly cut layer. Used in 3D View
* @return true if this layer is a poly cut layer.
*/
public boolean isPolyCutLayer()
{
return (function.isContact() && (functionExtras&Layer.Function.CONPOLY) != 0);
}
/**
* Method to determine if the layer corresponds to a poly cut layer. Used in 3D View
* @return true if this layer is a poly cut layer.
*/
public boolean isCarbonNanotubeLayer()
{
return (functionExtras&Layer.CARBNANO) != 0;
}
/**
* Method to return true if this is pseudo-Layer.
* Pseudo layers are those used in pins, and have no real geometry.
* @return true if this is pseudo-layer.
*/
public boolean isPseudoLayer() { return pseudo; }
/**
* Method to return the pseudo layer associated with this real-Layer.
* Pseudo layers are those used in pins, and have no real geometry.
* @return the pseudo layer associated with this read-Layer.
* If this layer is hass not pseudo, the null is returned.
*/
public Layer getPseudoLayer() { return pseudoLayer; }
/**
* Method to return the non-pseudo layer associated with this pseudo-Layer.
* Pseudo layers are those used in pins, and have no real geometry.
* @return the non-pseudo layer associated with this pseudo-Layer.
* If this layer is already not pseudo, this layer is returned.
*/
public Layer getNonPseudoLayer() { return nonPseudoLayer; }
private Setting makeLayerSetting(String what, String factory) {
String techName = tech.getTechName();
return getSubNode(what).makeStringSetting(what + "LayerFor" + getName() + "IN" + techName,
Technology.TECH_NODE,
getName(), what + " tab", what + " for layer " + getName() + " in technology " + techName, factory);
}
private Setting makeParasiticSetting(String what, double factory)
{
return getSubNode(what).makeDoubleSetting(what + "ParasiticFor" + getName() + "IN" + tech.getTechName(),
Technology.TECH_NODE,
getName(), "Parasitic tab", "Technology " + tech.getTechName() + ", " + what + " for layer " + getName(), factory);
}
private Setting make3DSetting(String what, double factory)
{
factory = DBMath.round(factory);
return getSubNode(what).makeDoubleSetting(what + "Of" + getName() + "IN" + tech.getTechName(),
Technology.TECH_NODE,
getName(), "3D tab", "Technology " + tech.getTechName() + ", 3D " + what + " for layer " + getName(), factory);
}
private Setting.Group getSubNode(String type) {
return tech.getProjectSettings().node(type);
}
/**
* Method to set the 3D distance and thickness of this Layer.
* @param thickness the thickness of this layer.
* @param distance the distance of this layer above the ground plane (silicon).
* Negative values represent layes in silicon like p++, p well, etc.
*/
public void setFactory3DInfo(double thickness, double distance)
{
assert !isPseudoLayer();
thickness = DBMath.round(thickness);
distance = DBMath.round(distance);
// We don't call setDistance and setThickness directly here due to reflection code.
layer3DDistanceSetting = make3DSetting("Distance", distance);
layer3DThicknessSetting = make3DSetting("Thickness", thickness);
}
/**
* Method to return the distance of this layer, by default.
* The higher the distance value, the farther from the wafer.
* @return the distance of this layer above the ground plane, by default.
*/
public double getDistance() { return layer3DDistanceSetting.getDouble(); }
/**
* Returns project preferences to tell the distance of this layer.
* @return project preferences to tell the distance of this layer.
*/
public Setting getDistanceSetting() { return layer3DDistanceSetting; }
/**
* Method to return the thickness of this layer, by default.
* Layers can have a thickness of 0, which causes them to be rendered flat.
* @return the distance of this layer above the ground plane, by default.
*/
public double getThickness() { return layer3DThicknessSetting.getDouble(); }
/**
* Returns project preferences to tell the thickness of this layer.
* @return project preferences to tell the thickness of this layer.
*/
public Setting getThicknessSetting() { return layer3DThicknessSetting; }
/**
* Method to calculate Z value of the upper part of the layer.
* Note: not called getHeight to avoid confusion
* with getDistance())
* Don't call distance+thickness because those are factory values.
* @return Depth of the layer
*/
public double getDepth() { return DBMath.round(getDistance()+getThickness()); }
/**
* Method to set the factory-default CIF name of this Layer.
* @param cifLayer the factory-default CIF name of this Layer.
*/
public void setFactoryCIFLayer(String cifLayer) {
assert !isPseudoLayer();
cifLayerSetting = makeLayerSetting("CIF", cifLayer);
}
/**
* Method to return the CIF name of this layer.
* @return the CIF name of this layer.
*/
public String getCIFLayer() { return cifLayerSetting.getString(); }
/**
* Returns project preferences to tell the CIF name of this Layer.
* @return project preferences to tell the CIF name of this Layer.
*/
public Setting getCIFLayerSetting() { return cifLayerSetting; }
/**
* Generate key name for GDS value depending on the foundry
* @return
*/
// private String getGDSPrefName(String foundry)
// {
// return ("GDS("+foundry+")");
// }
/**
* Method to set the factory-default GDS name of this Layer.
* @param factoryDefault the factory-default GDS name of this Layer.
* @param foundry
*/
// public void setFactoryGDSLayer(String factoryDefault, String foundry)
// {
// // Getting rid of spaces
// String value = factoryDefault.replaceAll(", ", ",");
// getLayerSetting(getGDSPrefName(foundry), gdsLayerPrefs, value);
// }
/**
* Method to set the GDS name of this Layer.
* @param gdsLayer the GDS name of this Layer.
*/
// public void setGDSLayer(String gdsLayer)
// {
// assert(this.gdsLayer == null);// probing gdsLayer is never used.
// getLayerSetting(getGDSPrefName(tech.getPrefFoundry()), gdsLayerPrefs, this.gdsLayer).setString(gdsLayer);
// }
/**
* Method to return the GDS name of this layer.
* @return the GDS name of this layer.
*/
// public String getGDSLayer()
// {
// assert(gdsLayer == null);// probing gdsLayer is never used.
// return getLayerSetting(getGDSPrefName(tech.getPrefFoundry()), gdsLayerPrefs, gdsLayer).getString();
// }
/**
* Method to set the factory-default DXF name of this Layer.
* @param dxfLayer the factory-default DXF name of this Layer.
*/
public void setFactoryDXFLayer(String dxfLayer) {
assert !isPseudoLayer();
dxfLayerSetting = makeLayerSetting("DXF", dxfLayer);
}
/**
* Method to return the DXF name of this layer.
* @return the DXF name of this layer.
*/
public String getDXFLayer()
{
if (dxfLayerSetting == null) return "";
return dxfLayerSetting.getString();
}
/**
* Returns project preferences to tell the DXF name of this Layer.
* @return project preferences to tell the DXF name of this Layer.
*/
public Setting getDXFLayerSetting() { return dxfLayerSetting; }
/**
* Method to set the factory-default Skill name of this Layer.
* @param skillLayer the factory-default Skill name of this Layer.
*/
public void setFactorySkillLayer(String skillLayer) {
assert !isPseudoLayer();
skillLayerSetting = makeLayerSetting("Skill", skillLayer);
}
/**
* Method to return the Skill name of this layer.
* @return the Skill name of this layer.
*/
public String getSkillLayer() { return skillLayerSetting.getString(); }
/**
* Returns project preferences to tell the Skill name of this Layer.
* @return project preferences to tell the Skill name of this Layer.
*/
public Setting getSkillLayerSetting() { return skillLayerSetting; }
/**
* Method to set the Spice parasitics for this Layer.
* This is typically called only during initialization.
* It does not set the "option" storage, as "setResistance()",
* "setCapacitance()", and ""setEdgeCapacitance()" do.
* @param resistance the resistance of this Layer.
* @param capacitance the capacitance of this Layer.
* @param edgeCapacitance the edge capacitance of this Layer.
*/
public void setFactoryParasitics(double resistance, double capacitance, double edgeCapacitance)
{
assert !isPseudoLayer();
resistanceSetting = makeParasiticSetting("Resistance", resistance);
capacitanceSetting = makeParasiticSetting("Capacitance", capacitance);
edgeCapacitanceSetting = makeParasiticSetting("EdgeCapacitance", edgeCapacitance);
}
// /**
// * Reset this layer's Parasitics to their factory default values
// */
// public void resetToFactoryParasitics()
// {
// double res = resistanceSetting.getDoubleFactoryValue();
// double cap = capacitanceSetting.getDoubleFactoryValue();
// double edgecap = edgeCapacitanceSetting.getDoubleFactoryValue();
// setResistance(res);
// setCapacitance(cap);
// setEdgeCapacitance(edgecap);
// }
/**
* Method to return the resistance for this layer.
* @return the resistance for this layer.
*/
public double getResistance() { return resistanceSetting.getDouble(); }
/**
* Returns project preferences to tell the resistance for this Layer.
* @return project preferences to tell the resistance for this Layer.
*/
public Setting getResistanceSetting() { return resistanceSetting; }
/**
* Method to return the capacitance for this layer.
* @return the capacitance for this layer.
*/
public double getCapacitance() { return capacitanceSetting.getDouble(); }
/**
* Returns project preferences to tell the capacitance for this Layer.
* Returns project preferences to tell the capacitance for this Layer.
*/
public Setting getCapacitanceSetting() { return capacitanceSetting; }
/**
* Method to return the edge capacitance for this layer.
* @return the edge capacitance for this layer.
*/
public double getEdgeCapacitance() { return edgeCapacitanceSetting.getDouble(); }
/**
* Returns project preferences to tell the edge capacitance for this Layer.
* Returns project preferences to tell the edge capacitance for this Layer.
*/
public Setting getEdgeCapacitanceSetting() { return edgeCapacitanceSetting; }
/**
* Method to finish initialization of this Layer.
*/
void finish() {
if (resistanceSetting == null || capacitanceSetting == null || edgeCapacitanceSetting == null) {
setFactoryParasitics(0, 0, 0);
}
if (cifLayerSetting == null) {
setFactoryCIFLayer("");
}
if (dxfLayerSetting == null) {
setFactoryDXFLayer("");
}
if (skillLayerSetting == null) {
setFactorySkillLayer("");
}
if (layer3DThicknessSetting == null || layer3DDistanceSetting == null) {
double thickness = layer3DThicknessSetting != null ? getThickness() : DEFAULT_THICKNESS;
double distance = layer3DDistanceSetting != null ? getDistance() : DEFAULT_DISTANCE;
setFactory3DInfo(thickness, distance);
}
}
/**
* Returns a printable version of this Layer.
* @return a printable version of this Layer.
*/
public String toString()
{
return "Layer " + getName();
}
public void copyState(Layer that) {
assert getName().equals(that.getName());
if (pureLayerNode != null) {
assert pureLayerNode.getId() == that.pureLayerNode.getId();
// pureLayerNode.setDefSize(that.pureLayerNode.getDefWidth(), that.pureLayerNode.getDefHeight());
}
}
void dump(PrintWriter out, Map<Setting,Object> settings) {
final String[] layerBits = {
null, null, null,
null, null, null,
"PTYPE", "NTYPE", "DEPLETION",
"ENHANCEMENT", "LIGHT", "HEAVY",
null, "NONELEC", "CONMETAL",
"CONPOLY", "CONDIFF", null,
null, null, null,
"HLVT", "INTRANS", "THICK"
};
out.print("Layer " + getName() + " " + getFunction().name());
Technology.printlnBits(out, layerBits, getFunctionExtras());
out.print("\t"); Technology.printlnSetting(out, settings, getCIFLayerSetting());
out.print("\t"); Technology.printlnSetting(out, settings, getDXFLayerSetting());
out.print("\t"); Technology.printlnSetting(out, settings, getSkillLayerSetting());
out.print("\t"); Technology.printlnSetting(out, settings, getResistanceSetting());
out.print("\t"); Technology.printlnSetting(out, settings, getCapacitanceSetting());
out.print("\t"); Technology.printlnSetting(out, settings, getEdgeCapacitanceSetting());
// GDS
EGraphics factoryDesc = getFactoryGraphics();
EGraphics desc = factoryDesc;
out.println("\tpatternedOnDisplay=" + desc.isPatternedOnDisplay() + "(" + factoryDesc.isPatternedOnDisplay() + ")");
out.println("\tpatternedOnPrinter=" + desc.isPatternedOnPrinter() + "(" + factoryDesc.isPatternedOnPrinter() + ")");
out.println("\toutlined=" + desc.getOutlined() + "(" + factoryDesc.getOutlined() + ")");
out.println("\ttransparent=" + desc.getTransparentLayer() + "(" + factoryDesc.getTransparentLayer() + ")");
out.println("\tcolor=" + Integer.toHexString(desc.getColor().getRGB()) + "(" + Integer.toHexString(factoryDesc.getRGB()) + ")");
out.println("\topacity=" + desc.getOpacity() + "(" + factoryDesc.getOpacity() + ")");
out.println("\tforeground=" + factoryDesc.getForeground());
int pattern[] = factoryDesc.getPattern();
out.print("\tpattern");
for (int p: pattern)
out.print(" " + Integer.toHexString(p));
out.println();
out.println("\tdistance3D=" + getDistanceSetting().getDoubleFactoryValue());
out.println("\tthickness3D=" + getThicknessSetting().getDoubleFactoryValue());
out.println("\tmode3D=" + factoryDesc.getTransparencyMode());
out.println("\tfactor3D=" + factoryDesc.getTransparencyFactor());
if (getPseudoLayer() != null)
out.println("\tpseudoLayer=" + getPseudoLayer().getName());
}
/**
* Method to create XML version of a Layer.
* @return
*/
Xml.Layer makeXml() {
Xml.Layer l = new Xml.Layer();
l.name = getName();
l.function = getFunction();
l.extraFunction = getFunctionExtras();
l.desc = getFactoryGraphics();
l.height3D = getDistanceSetting().getDoubleFactoryValue();
l.thick3D = getThicknessSetting().getDoubleFactoryValue();
l.cif = (String)getCIFLayerSetting().getFactoryValue();
l.skill = (String)getSkillLayerSetting().getFactoryValue();
l.resistance = getResistanceSetting().getDoubleFactoryValue();
l.capacitance = getCapacitanceSetting().getDoubleFactoryValue();
l.edgeCapacitance = getEdgeCapacitanceSetting().getDoubleFactoryValue();
// if (layer.getPseudoLayer() != null)
// l.pseudoLayer = layer.getPseudoLayer().getName();
if (pureLayerNode != null) {
l.pureLayerNode = new Xml.PureLayerNode();
l.pureLayerNode.name = pureLayerNode.getName();
for (Map.Entry<String,PrimitiveNode> e: tech.getOldNodeNames().entrySet()) {
if (e.getValue() != pureLayerNode) continue;
assert l.pureLayerNode.oldName == null;
l.pureLayerNode.oldName = e.getKey();
}
l.pureLayerNode.style = pureLayerNode.getNodeLayers()[0].getStyle();
l.pureLayerNode.port = pureLayerNode.getPort(0).getName();
l.pureLayerNode.size.addLambda(DBMath.gridToLambda(2*pureLayerNode.getFactoryDefaultGridExtendX()));
for (ArcProto ap: pureLayerNode.getPort(0).getConnections()) {
if (ap.getTechnology() != tech) continue;
l.pureLayerNode.portArcs.add(ap.getName());
}
}
return l;
}
}