![JAR search and dependency download from the Maven repository](/logo.png)
com.sun.electric.database.variable.Variable Maven / Gradle / Ivy
/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: Variable.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.database.variable;
import com.sun.electric.database.IdMapper;
import com.sun.electric.database.geometry.EPoint;
import com.sun.electric.database.id.ArcProtoId;
import com.sun.electric.database.id.CellId;
import com.sun.electric.database.id.ExportId;
import com.sun.electric.database.id.IdReader;
import com.sun.electric.database.id.IdWriter;
import com.sun.electric.database.id.LibId;
import com.sun.electric.database.id.PrimitiveNodeId;
import com.sun.electric.database.id.TechId;
import com.sun.electric.database.text.TextUtils;
import com.sun.electric.tool.Tool;
import java.io.IOException;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;
/**
* The Variable immutable class defines a single attribute-value pair that can be attached to any ElectricObject.
*
* This immutable class is thread-safe.
*/
public class Variable implements Serializable {
/**
* The Key class caches Variable names.
*/
public static class Key implements Comparable {
private final String name;
/**
* Method to create a new Key object with the specified name.
* @param name the name of the Variable.
* @throws NullPointerException if name is null.
*/
private Key(String name) {
if (name == null) {
throw new NullPointerException();
}
this.name = name;
}
/**
* Method to return the name of this Key object.
* @return the name of this Key object.
*/
public String getName() {
return name;
}
/**
* Method to return if this Variable.Key is a User Attribute.
* @return true if this Variable.Key is an attribute, false otherwise.
*/
public boolean isAttribute() {
return false;
}
/**
* Compares Variable Keys by their names.
* @param that the other Variable Key.
* @return a comparison between the Variable Keys.
*/
@Override
public int compareTo(Key that) {
return TextUtils.STRING_NUMBER_ORDER.compare(name, that.name);
}
/**
* Returns a printable version of this Key.
* @return a printable version of this Key.
*/
@Override
public String toString() {
return name;
}
/**
* Print statistics about Variable Keys.
*/
public static void printStatistics() {
long keyLength = 0;
for (Key key : varKeys.values()) {
keyLength += key.getName().length();
}
// int canonicCount = 0;
// long canonicLength = 0;
// for (String canonic : varCanonicKeys.keySet()) {
// Key key = varCanonicKeys.get(canonic);
// if (key != null && key.getName() == canonic) {
// continue;
// }
// canonicCount++;
// canonicLength += canonic.length();
// }
System.out.println(varKeys.size() + " variable keys with " + keyLength + " chars.");
// + " Canonic " + varCanonicKeys.size() + " entries " + canonicCount + " strings with " + canonicLength + " chars.");
}
}
/**
* The Key class caches attribute Variable names.
*/
public static class AttrKey extends Key {
AttrKey(String name) {
super(name);
}
/**
* Method to return if this Variable.Key is a User Attribute.
* @return true if this Variable.Key is an attribute, false otherwise.
*/
@Override
public boolean isAttribute() {
return true;
}
}
/** a list of all variable keys */
private static final HashMap varKeys = new HashMap();
// /** all variable keys addressed by lower case name */
// private static final HashMap varCanonicKeys = new HashMap();
/**
* Method to return the Key object for a given Variable name.
* Variable Key objects are caches of the actual string name of the Variable.
* @return the Key object for a given Variable name.
*/
public static synchronized Key findKey(String name) {
Key key = varKeys.get(name);
if (key != null) {
return key;
}
// if (varKeys.containsKey(name)) {
// return null;
// }
// name = name.intern();
// varKeys.put(name, null);
// String canonicName = TextUtils.canonicString(name);
// key = varCanonicKeys.get(canonicName);
// if (key != null) {
// String msg = "WARNING: Variable \"" + name + "\" not found though variable \"" + key.getName() + "\" exists";
// ActivityLogger.logMessage(msg);
// System.out.println(msg);
// }
return null;
}
/**
* Method to find or create the Key object for a given Variable name.
* Variable Key objects are caches of the actual string name of the Variable.
* @param name given Variable name.
* @return the Key object for a given Variable name.
*/
public static synchronized Key newKey(String name) {
Key key = varKeys.get(name);
if (key != null) {
return key;
}
name = name.intern();
key = name.startsWith("ATTR_") ? new AttrKey(name) : new Key(name);
varKeys.put(name, key);
// String canonicName = TextUtils.canonicString(name);
// Key key2 = varCanonicKeys.get(canonicName);
// if (key2 != null && parent != null) {
// // find examples of these two variables
// String ex = null;
// for (Library lib : Library.getVisibleLibraries()) {
// if (ex == null) {
// ex = findVariable(lib, key2);
// }
// for (Iterator cIt = lib.getCells(); cIt.hasNext();) {
// Cell cell = cIt.next();
// if (ex == null) {
// ex = findVariable(cell, key2);
// }
// for (Iterator nIt = cell.getNodes(); nIt.hasNext();) {
// NodeInst ni = nIt.next();
// if (ex == null) {
// ex = findVariable(ni, key2);
// }
// }
// for (Iterator aIt = cell.getArcs(); aIt.hasNext();) {
// ArcInst ai = aIt.next();
// if (ex == null) {
// ex = findVariable(ai, key2);
// }
// }
// for (Iterator eIt = cell.getExports(); eIt.hasNext();) {
// Export e = eIt.next();
// if (ex == null) {
// ex = findVariable(e, key2);
// }
// }
// }
// }
// String msg = "WARNING: Variables with similar names are used: \"" + name + "\"";
// if (parent != null) {
// msg += " (on " + getObjectName(parent) + ")";
// }
// msg += " and \"" + key2.getName() + "\"";
// if (ex != null) {
// msg += " (on " + ex + ")";
// }
// ActivityLogger.logMessage(msg);
// System.out.println(msg);
// } else {
// varCanonicKeys.put(canonicName.intern(), key);
// }
return key;
}
// private static String findVariable(ElectricObject eObj, Key key) {
// for (Iterator it = eObj.getParametersAndVariables(); it.hasNext();) {
// Variable var = it.next();
// if (var.getKey() == key) {
// return getObjectName(eObj);
// }
// }
// return null;
// }
//
// private static String getObjectName(ElectricObject eObj) {
// if (eObj instanceof Library) {
// return "Library " + ((Library) eObj).getName();
// }
// if (eObj instanceof Cell) {
// return "Cell " + ((Cell) eObj).describe(false);
// }
// if (eObj instanceof Export) {
// return "Export " + ((Export) eObj).getName() + " in Cell " + ((Export) eObj).getParent().describe(false);
// }
// if (eObj instanceof NodeInst) {
// return "Node " + ((NodeInst) eObj).describe(false) + " in Cell " + ((NodeInst) eObj).getParent().describe(false);
// }
// if (eObj instanceof ArcInst) {
// return "Arc " + ((ArcInst) eObj).describe(false) + " in Cell " + ((ArcInst) eObj).getParent().describe(false);
// }
// return eObj.toString();
// }
/** empty array of Variables. */
public static final Variable[] NULL_ARRAY = {};
/** type if value. */
private final static byte ARRAY = 1;
private final static byte LIBRARY = 2;
private final static byte CELL = 4;
private final static byte EXPORT = 6;
private final static byte STRING = 8;
private final static byte CODE = 10;
private final static byte DOUBLE = 12;
private final static byte FLOAT = 14;
private final static byte LONG = 16;
private final static byte INTEGER = 18;
private final static byte SHORT = 20;
private final static byte BYTE = 22;
private final static byte BOOLEAN = 24;
private final static byte EPOINT = 26;
private final static byte TOOL = 28;
private final static byte TECHNOLOGY = 30;
private final static byte PRIM_NODE = 32;
private final static byte ARC_PROTO = 34;
/** Valid type of value. */
private static final HashMap validClasses = new HashMap();
static {
validClasses.put(LibId.class, Byte.valueOf(LIBRARY));
validClasses.put(CellId.class, Byte.valueOf(CELL));
validClasses.put(ExportId.class, Byte.valueOf(EXPORT));
validClasses.put(String.class, Byte.valueOf(STRING));
validClasses.put(CodeExpression.class, Byte.valueOf(CODE));
validClasses.put(Double.class, Byte.valueOf(DOUBLE));
validClasses.put(Float.class, Byte.valueOf(FLOAT));
validClasses.put(Long.class, Byte.valueOf(LONG));
validClasses.put(Integer.class, Byte.valueOf(INTEGER));
validClasses.put(Short.class, Byte.valueOf(SHORT));
validClasses.put(Byte.class, Byte.valueOf(BYTE));
validClasses.put(Boolean.class, Byte.valueOf(BOOLEAN));
validClasses.put(EPoint.class, Byte.valueOf(EPOINT));
validClasses.put(Tool.class, Byte.valueOf(TOOL));
validClasses.put(TechId.class, Byte.valueOf(TECHNOLOGY));
validClasses.put(PrimitiveNodeId.class, Byte.valueOf(PRIM_NODE));
validClasses.put(ArcProtoId.class, Byte.valueOf(ARC_PROTO));
}
/** key of this Variable. */
private final Key key;
/** Value of this Variable. */
private final Object value;
/** Text descriptor of this Variable. */
private final TextDescriptor descriptor;
private final byte type;
/**
* Constructor of Variable.
* @param key key of this Variable.
* @param descriptor text descriptor of this Variable.
* @param value value of this Variable.
* @param type type of the value
*/
private Variable(Key key, Object value, TextDescriptor descriptor, byte type) {
this.key = key;
this.value = value;
this.descriptor = descriptor;
this.type = type;
check(true, true);
}
/**
* Returns new Variable.
* @param key key of this Variable.
* @param value value of this Variable.
* @param descriptor text descriptor of this Variable.
* @return new Variable object.
* @throws NullPointerException if key, descriptor or value is null.
* @throws IllegalArgumentException if value has invalid type
*/
public static Variable newInstance(Variable.Key key, Object value, TextDescriptor descriptor) {
if (key == null) {
throw new NullPointerException("key");
}
if (descriptor == null) {
throw new NullPointerException("descriptor");
}
if (!key.isAttribute()) {
descriptor = descriptor.withParam(false);
}
byte type = getObjectType(value);
if ((type & ARRAY) != 0) {
value = ((Object[]) value).clone();
}
return new Variable(key, value, descriptor, type);
}
/**
* Returns Object of specified Code derived from specified Object
* If code is not NONE, the new Object will be of type CodeExpression.
* If code is NONE and the specified Object was CodeExpression,
* the new Object will be a String with expression text.
* @param value specified Object
* @param code code of new Object.
* @return Object of specified Code derived from specified Object
*/
public static Object withCode(Object value, CodeExpression.Code code) {
if (code == CodeExpression.Code.NONE) {
return value instanceof CodeExpression ? value.toString() : value;
}
if (value instanceof CodeExpression && ((CodeExpression) value).getCode() == code) {
return value;
}
String expr;
if (value instanceof Object[]) {
StringBuilder sb = new StringBuilder();
for (Object o : (Object[]) value) {
if (o == null) {
continue;
}
if (sb.length() > 0) {
sb.append(' ');
}
sb.append(o.toString());
}
expr = sb.toString();
} else {
expr = value.toString();
}
return CodeExpression.valueOf(expr, code);
}
/**
* Checks invariant of this Variable.
* @param paramAllowed true if paramerer flag is allowed on this Variable
* @param inheritAllowed true if inherit flag is allowed on this Variable
* @throws AssertionError or NullPointerException if invariant is broken.
*/
public void check(boolean paramAllowed, boolean inheritAllowed) {
assert key != null;
assert value != null;
assert type == getObjectType(value);
assert descriptor != null;
if (descriptor.isParam()) {
assert paramAllowed && isAttribute();
}
if (descriptor.isInherit()) {
assert inheritAllowed;
}
}
private static byte getObjectType(Object value) {
byte type;
if (value instanceof Object[]) {
Byte typeByte = validClasses.get(value.getClass().getComponentType());
if (typeByte == null) {
throw new IllegalArgumentException(value.getClass().toString());
}
type = (byte) (typeByte.byteValue() | ARRAY);
if (!validValue(type, value)) {
throw new IllegalArgumentException(value.toString());
}
} else {
Byte typeByte = validClasses.get(value.getClass());
if (typeByte == null) {
throw new IllegalArgumentException(value.getClass().toString());
}
type = typeByte.byteValue();
}
return type;
}
private static boolean validValue(byte type, Object value) {
if ((type & ARRAY) == 0) {
return value != null;
}
type = (byte) (type & ~ARRAY);
if (type == CODE) {
return false;
}
Object[] valueArr = (Object[]) value;
if (type >= STRING && type <= BOOLEAN) {
for (Object o : valueArr) {
if (o == null) {
return false;
}
}
}
return true;
}
/**
* Returns true if the value is array,
* @return true if the value is array,
*/
public boolean isArray() {
return (type & ARRAY) != 0;
}
/**
* Get the number of entries stored in this Variable.
* For non-arrayed Variables, this is 1.
* @return the number of entries stored in this Variable.
*/
public int getLength() {
return (type & ARRAY) != 0 ? ((Object[]) value).length : 1;
}
/**
* Returns thread-independent value of this Variable.
* @return thread-independent value of this variable.
*/
public Object getObject() {
return (type & ARRAY) != 0 ? ((Object[]) value).clone() : value;
}
/**
* Write this Variable to IdWriter.
* @param writer where to write.
*/
public void write(IdWriter writer) throws IOException {
writer.writeVariableKey(key);
writer.writeTextDescriptor(descriptor);
writeObject(writer, value, type);
}
/**
* Write Object to IdWriter.
* Object must be a valid value of Variable
* @param writer where to write.
* @param obj
*/
public static void writeObject(IdWriter writer, Object obj) throws IOException {
writeObject(writer, obj, getObjectType(obj));
}
private static void writeObject(IdWriter writer, Object obj, byte type) throws IOException {
writer.writeByte(type);
if (obj instanceof Object[]) {
Object[] array = (Object[]) obj;
writer.writeInt(array.length);
for (Object o : array) {
writer.writeBoolean(o != null);
if (o != null) {
writeObj(writer, o, type);
}
}
} else {
writeObj(writer, obj, type);
}
}
private static void writeObj(IdWriter writer, Object obj, byte type) throws IOException {
switch (type & ~ARRAY) {
case LIBRARY:
writer.writeLibId((LibId) obj);
break;
case CELL:
writer.writeNodeProtoId((CellId) obj);
break;
case EXPORT:
writer.writePortProtoId((ExportId) obj);
break;
case STRING:
writer.writeString((String) obj);
break;
case CODE:
((CodeExpression) obj).write(writer);
break;
case DOUBLE:
writer.writeDouble(((Double) obj).doubleValue());
break;
case FLOAT:
writer.writeFloat(((Float) obj).floatValue());
break;
case LONG:
writer.writeLong(((Long) obj).longValue());
break;
case INTEGER:
writer.writeInt(((Integer) obj).intValue());
break;
case SHORT:
writer.writeShort(((Short) obj).shortValue());
break;
case BYTE:
writer.writeByte(((Byte) obj).byteValue());
break;
case BOOLEAN:
writer.writeBoolean(((Boolean) obj).booleanValue());
break;
case EPOINT:
writer.writePoint((EPoint) obj);
break;
case TOOL:
writer.writeTool((Tool) obj);
break;
case TECHNOLOGY:
writer.writeTechId((TechId) obj);
break;
case PRIM_NODE:
writer.writeNodeProtoId((PrimitiveNodeId) obj);
break;
case ARC_PROTO:
writer.writeArcProtoId((ArcProtoId) obj);
break;
}
}
/**
* Read Variable from IdReader.
* @param reader from to read.
* @return Variable read
*/
public static Variable read(IdReader reader) throws IOException {
Variable.Key varKey = reader.readVariableKey();
TextDescriptor td = reader.readTextDescriptor();
Object value = readObject(reader);
return Variable.newInstance(varKey, value, td);
}
/**
* Read Object from IdReader. Object will be a valid value of Variable
* @param reader from to read
* @return Object read
*/
public static Object readObject(IdReader reader) throws IOException {
int type = reader.readByte();
Object value;
if ((type & ARRAY) != 0) {
int length = reader.readInt();
type &= ~ARRAY;
Object[] array;
switch (type) {
case LIBRARY:
array = new LibId[length];
break;
case CELL:
array = new CellId[length];
break;
case EXPORT:
array = new ExportId[length];
break;
case STRING:
array = new String[length];
break;
case DOUBLE:
array = new Double[length];
break;
case FLOAT:
array = new Float[length];
break;
case LONG:
array = new Long[length];
break;
case INTEGER:
array = new Integer[length];
break;
case SHORT:
array = new Short[length];
break;
case BYTE:
array = new Byte[length];
break;
case BOOLEAN:
array = new Boolean[length];
break;
case EPOINT:
array = new EPoint[length];
break;
case TOOL:
array = new Tool[length];
break;
case TECHNOLOGY:
array = new TechId[length];
break;
case PRIM_NODE:
array = new PrimitiveNodeId[length];
break;
case ARC_PROTO:
array = new ArcProtoId[length];
break;
case CODE:
default:
throw new IOException("type");
}
for (int i = 0; i < length; i++) {
boolean hasElem = reader.readBoolean();
if (hasElem) {
array[i] = readObj(reader, type);
}
}
value = array;
} else {
value = readObj(reader, type);
}
return value;
}
private static Object readObj(IdReader reader, int type) throws IOException {
switch (type) {
case LIBRARY:
return reader.readLibId();
case CELL:
return reader.readNodeProtoId();
case EXPORT:
return reader.readPortProtoId();
case STRING:
return reader.readString();
case CODE:
return CodeExpression.read(reader);
case DOUBLE:
return Double.valueOf(reader.readDouble());
case FLOAT:
return Float.valueOf(reader.readFloat());
case LONG:
return Long.valueOf(reader.readLong());
case INTEGER:
return Integer.valueOf(reader.readInt());
case SHORT:
return Short.valueOf(reader.readShort());
case BYTE:
return Byte.valueOf(reader.readByte());
case BOOLEAN:
return Boolean.valueOf(reader.readBoolean());
case EPOINT:
return reader.readPoint();
case TOOL:
return reader.readTool();
case TECHNOLOGY:
return reader.readTechId();
case PRIM_NODE:
return reader.readNodeProtoId();
case ARC_PROTO:
return reader.readArcProtoId();
default:
throw new IllegalArgumentException();
}
}
/**
* Returns Variable which differs from this Variable by key.
* @param key key of new Variable.
* @return Variable which differs from this Variable by key.
* @throws NullPointerException if key is null.
*/
public Variable withVarKey(Variable.Key key) {
if (this.key == key) {
return this;
}
return newInstance(key, this.value, this.descriptor);
}
/**
* Returns Variable which differs from this Variable by value.
* @param value value of new Variable.
* @return Variable which differs from this Variable by value.
* @throws NullPointerException if value is null.
* @throws IllegalArgumentException if value has invalid type
*/
public Variable withObject(Object value) {
if (this.value.equals(value)) {
return this;
}
if ((type & ARRAY) != 0 && value instanceof Object[]
&& Arrays.equals((Object[]) this.value, (Object[]) value)
&& this.value.getClass().getComponentType() == value.getClass().getComponentType()) {
return this;
}
return newInstance(this.key, value, this.descriptor);
}
/**
* Returns Variable which differs from this Variable by text value.
* If this Variable is Code Varibale its Code type is preserved
* @param text text value of new Variable.
* @return Variable which differs from this Variable by value.
* @throws NullPointerException if value is null.
* @throws IllegalArgumentException if value has invalid type
*/
public Variable withText(String text) {
if (value instanceof CodeExpression) {
CodeExpression ce = (CodeExpression) value;
if (ce.getExpr().equals(text)) {
return this;
}
return new Variable(this.key, CodeExpression.valueOf(text, ce.getCode()), this.descriptor, this.type);
}
if (value.equals(text)) {
return this;
}
return new Variable(this.key, text, this.descriptor, STRING);
}
/**
* Returns Variable which differs from this Variable by code.
* @param code code of new Variable.
* @return Variable which differs from this Variable by code
*/
public Variable withCode(CodeExpression.Code code) {
if (getCode() == code) {
return this;
}
return withObject(withCode(value, code));
}
/**
* Returns Variable which differs from this Variable by renamed Ids.
* @param idMapper a mapper from old Ids to new Ids.
* @return Variable which differs from this Variable by renamed Ids.
*/
public Variable withRenamedIds(IdMapper idMapper) {
Object newValue = withRenamedIds(idMapper, value, type);
return newValue != value ? withObject(newValue) : this;
}
private static Object withRenamedIds(IdMapper idMapper, Object value, byte type) {
Object newValue = value;
switch (type) {
case LIBRARY:
newValue = idMapper.get((LibId) value);
break;
case CELL:
newValue = idMapper.get((CellId) value);
break;
case EXPORT:
newValue = idMapper.get((ExportId) value);
break;
case LIBRARY | ARRAY:
LibId[] libIds = (LibId[]) value;
for (int i = 0; i < libIds.length; i++) {
if (libIds[i] == null) {
continue;
}
LibId libId = idMapper.get(libIds[i]);
if (libId != libIds[i]) {
libIds[i] = libId;
newValue = libIds;
}
}
break;
case CELL | ARRAY:
CellId[] cellIds = (CellId[]) value;
for (int i = 0; i < cellIds.length; i++) {
if (cellIds[i] == null) {
continue;
}
CellId cellId = idMapper.get(cellIds[i]);
if (cellId != cellIds[i]) {
cellIds[i] = cellId;
newValue = cellIds;
}
}
break;
case EXPORT | ARRAY:
ExportId[] exportIds = (ExportId[]) value;
for (int i = 0; i < exportIds.length; i++) {
if (exportIds[i] == null) {
continue;
}
ExportId exportId = idMapper.get(exportIds[i]);
if (exportId != exportIds[i]) {
exportIds[i] = exportId;
newValue = exportIds;
}
}
break;
}
return newValue;
}
/**
* Returns thread-independent element of array value of this Variable.
* @param index index of array
* @return element of array value.
* @throws ArrayIndexOutOfBoundsException if index is scalar of value is out of bounds.
*/
public Object getObject(int index) {
if ((type & ARRAY) == 0) {
throw new ArrayIndexOutOfBoundsException(index);
}
return ((Object[]) value)[index];
}
/**
* Method to return the Variable Key associated with this Variable.
* @return the Variable Key associated with this variable.
*/
public Key getKey() {
return key;
}
/**
* Method to convert the standard Variable names to more readable strings.
* @param name the actual Variable name.
* @return a better name for it (returns the same name if no better one exists).
*/
public static String betterVariableName(String name) {
// handle standard variable names
if (name.equals("ARC_name")) {
return "Arc Name";
}
if (name.equals("ARC_radius")) {
return "Arc Radius";
}
if (name.equals("ART_color")) {
return "Color";
}
if (name.equals("ART_degrees")) {
return "Number of Degrees";
}
if (name.equals("ART_message")) {
return "Annotation text";
}
if (name.equals("NET_ncc_match")) {
return "NCC equivalence";
}
if (name.equals("NET_ncc_forcedassociation")) {
return "NCC association";
}
if (name.equals("NODE_name")) {
return "Node Name";
}
if (name.equals("SCHEM_capacitance")) {
return "Capacitance";
}
if (name.equals("SCHEM_diode")) {
return "Diode Size";
}
if (name.equals("SCHEM_global_name")) {
return "Global Signal Name";
}
if (name.equals("SCHEM_inductance")) {
return "Inductance";
}
if (name.equals("SCHEM_resistance")) {
return "Resistance";
}
if (name.equals("SIM_fall_delay")) {
return "Fall Delay";
}
if (name.equals("SIM_fasthenry_group_name")) {
return "FastHenry Group";
}
if (name.equals("SIM_rise_delay")) {
return "Rise Delay";
}
if (name.equals("SIM_spice_card")) {
return "SPICE code";
}
if (name.equals("SIM_spice_declaration")) {
return "SPICE declaration";
}
if (name.equals("SIM_spice_model")) {
return "SPICE model";
}
if (name.equals("SIM_verilog_wire_type")) {
return "Verilog Wire type";
}
if (name.equals("SIM_weak_node")) {
return "Transistor Strength";
}
if (name.equals("transistor_width")) {
return "Transistor Width";
}
if (name.equals("VERILOG_code")) {
return "Verilog code";
}
if (name.equals("VERILOG_declaration")) {
return "Verilog declaration";
}
if (name.equals("VERILOG_parameter")) {
return "Verilog parameter";
}
if (name.equals("VERILOG_external_code")) {
return "Verilog external code";
}
return null;
}
/**
* Method to return the "true" name for this Variable.
* The method removes the "ATTR_" and "ATTRP_" prefixes.
* @return the "true" name for this Variable.
*/
public String getTrueName() {
String name = getKey().getName();
if (name.startsWith("ATTR_")) {
return name.substring(5);
}
if (name.startsWith("ATTRP_")) {
int i = name.lastIndexOf('_');
return name.substring(i);
}
return name;
}
/**
* Method to return a description of this Variable.
* @return a description of this Variable.
*/
public String describe(VarContext context, Object eobj) {
return describe(-1, context, eobj);
}
/**
* Return a description of this Variable without any context
* or helper object info
*/
public String describe(int aindex) {
return describe(aindex, VarContext.globalContext, null);
}
/**
* Method to return a String describing this Variable.
* @param aindex if negative, print the entire array.
* @param context the VarContext for this Variable.
* @param eobj the Object on which this Variable resides.
* @return a String desribing this Variable.
*/
public String describe(int aindex, VarContext context, Object eobj) {
TextDescriptor.Unit units = getUnit();
StringBuffer returnVal = new StringBuffer();
TextDescriptor.DispPos dispPos = getDispPart();
if (isCode()) {
// special case for code: it is a string, the type applies to the result
if (context == null) {
context = VarContext.globalContext;
}
Object val = null;
try {
val = context.evalVarRecurse(this, eobj);
} catch (VarContext.EvalException e) {
VarContext.printException(e, this, context, eobj);
val = e.getMessage();
}
if (val == null) {
val = "?";
}
returnVal.append(makeStringVar(val, units));
} else {
returnVal.append(getPureValue(aindex));
}
if (dispPos == TextDescriptor.DispPos.NAMEVALUE && (aindex < 0 || getLength() == 1)) {
return this.getTrueName() + "=" + returnVal;
}
return returnVal.toString();
}
/**
* Method to convert this Variable to a String without any evaluation of code.
* @param aindex if negative, print the entire array.
* @return a String desribing this Variable.
*/
public String getPureValue(int aindex) {
TextDescriptor.Unit units = getUnit();
StringBuilder returnVal = new StringBuilder();
Object thisAddr = getObject();
if (thisAddr instanceof Object[]) {
// compute the array length
Object[] addrArray = (Object[]) thisAddr;
int len = addrArray.length;
// if asking for a single entry, get it
if (aindex >= 0) {
// normal array indexing
if (aindex < len) {
returnVal.append(makeStringVar(addrArray[aindex], units));
}
} else {
// in an array, quote strings
if (len > 1) {
returnVal.append("[");
}
for (int i = 0; i < len; i++) {
if (i != 0) {
returnVal.append(",");
}
returnVal.append(makeStringVar(addrArray[i], units));
}
if (len > 1) {
returnVal.append("]");
}
}
} else {
returnVal.append(makeStringVar(thisAddr, units));
}
return returnVal.toString();
}
/**
* Method to convert object "addr" to a string, given a set of units.
* For completion of the method, the units should be treated as in "makeStringVar()".
*/
private String makeStringVar(Object addr, TextDescriptor.Unit units) {
// if (addr instanceof Integer)
// {
// return ((Integer)addr).toString();
// }
if (addr instanceof Float) {
return TextUtils.makeUnits(((Float) addr).floatValue(), units);
}
if (addr instanceof Double) {
return TextUtils.makeUnits(((Double) addr).doubleValue(), units);
}
// if (addr instanceof Short)
// return ((Short)addr).toString();
// if (addr instanceof Byte)
// return ((Byte)addr).toString();
// if (addr instanceof String)
// return (String)addr;
if (addr instanceof Object[]) {
StringBuffer buf = new StringBuffer();
buf.append("[");
Object[] objects = (Object[]) addr;
for (int i = 0; i < objects.length; i++) {
if (objects[i] != null) {
buf.append(makeStringVar(objects[i], units));
}
buf.append(", ");
}
buf.replace(buf.length() - 2, buf.length(), "]");
return buf.toString();
}
return addr.toString();
}
/**
* This function is to compare Variable elements. Initiative CrossLibCopy
* @param obj Object to compare to
* @param buffer To store comparison messages in case of failure
* @return True if objects represent same PortInst
*/
public boolean compare(Object obj, StringBuffer buffer) {
if (this == obj) {
return (true);
}
// Better if compare classes? but it will crash with obj=null
if (obj == null || getClass() != obj.getClass()) {
return (false);
}
Variable var = (Variable) obj;
boolean check = var.getTextDescriptor().equals(getTextDescriptor());
if (!check && buffer != null) {
buffer.append("No same variables detected in " + var + " and " + this + "\n");
}
return (check);
}
@Override
public int hashCode() {
return key.hashCode();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Variable)) {
return false;
}
Variable that = (Variable) o;
if (this.key != that.key || this.descriptor != that.descriptor) {
return false;
}
if (this.type != that.type) {
return false;
}
if ((this.type & ARRAY) == 0) {
return this.value.equals(that.value);
}
return Arrays.equals((Object[]) this.value, (Object[]) that.value);
}
/**
* Returns a printable version of this Variable.
* @return a printable version of this Variable.
*/
@Override
public String toString() {
return key.getName();
}
/**
* Method to return the TextDescriptor on this Variable.
* The TextDescriptor gives information for displaying the Variable.
* @return the TextDescriptor on this Variable.
*/
public TextDescriptor getTextDescriptor() {
return descriptor;
}
/**
* Returns Variable which differs from this Variable by TextDescriptor.
* The TextDescriptor gives information for displaying the Variable.
* @param descriptor the new TextDescriptor on this Variable.
* @return Variable which differs from this Variable by TextDescriptor.
*/
public Variable withTextDescriptor(TextDescriptor descriptor) {
if (!isAttribute()) {
descriptor = descriptor.withParam(false);
}
if (this.descriptor == descriptor) {
return this;
}
return new Variable(this.key, this.value, descriptor, this.type);
}
/**
* Returns Variable which differs from this Variable by displayable flag.
* Displayable Variables are shown with the object.
* @param state true, if new Variable is displayable.
* @return Variable which differs from this Variable by displayable flag.
*/
public Variable withDisplay(boolean state) {
return withTextDescriptor(getTextDescriptor().withDisplay(state));
}
/**
* Method to return true if this Variable is displayable.
* @return true if this Variable is displayable.
*/
public boolean isDisplay() {
return descriptor.isDisplay();
}
/**
* Returns CodeExpression of this Variable, it it is code variable.
* Returns null otherwise
* @return CodeExprssion of this Variable or null
*/
public CodeExpression getCodeExpression() {
return value instanceof CodeExpression ? (CodeExpression) value : null;
}
/**
* Determine what code type this variable has, if any
* @return the code type
*/
public CodeExpression.Code getCode() {
CodeExpression ce = getCodeExpression();
return ce != null ? ce.getCode() : CodeExpression.Code.NONE;
}
/**
* Method to return true if this Variable is Java.
* Java Variables contain Java code that is evaluated in order to produce a value.
* @return true if this Variable is Java.
*/
public boolean isJava() {
CodeExpression ce = getCodeExpression();
return ce != null && ce.isJava();
}
/**
* Method to tell whether this Variable is any code.
* @return true if this Variable is any code.
*/
public boolean isCode() {
return value instanceof CodeExpression;
}
/**
* Method to return if this is Variable is a User Attribute.
* @return true if this Variable is an attribute, false otherwise.
*/
public boolean isAttribute() {
return getKey().isAttribute();
}
// TextDescriptor
/**
* Method to return the color index of the Variable's TextDescriptor.
* Color indices are more general than colors, because they can handle
* transparent layers, C-Electric-style opaque layers, and full color values.
* Methods in "EGraphics" manipulate color indices.
* @return the color index of the Variables's TextDescriptor.
*/
public int getColorIndex() {
return descriptor.getColorIndex();
}
/**
* Returns Variable which differs from this Variable by colorIndex.
* Color indices are more general than colors, because they can handle
* transparent layers, C-Electric-style opaque layers, and full color values.
* Methods in "EGraphics" manipulate color indices.
* @param colorIndex color index of new Variable.
* @return Variable which differs from this Variable by colorIndex.
*/
public Variable withColorIndex(int colorIndex) {
return withTextDescriptor(getTextDescriptor().withColorIndex(colorIndex));
}
/**
* Method to return the text position of the Variable's TextDescriptor.
* The text position describes the "anchor point" of the text,
* which is the point on the text that is attached to the object and does not move.
* @return the text position of the Variable's TextDescriptor.
*/
public TextDescriptor.Position getPos() {
return descriptor.getPos();
}
/**
* Returns Variable which differs from this Variable by position.
* The text position describes the "anchor point" of the text,
* which is the point on the text that is attached to the object and does not move.
* @param p the text position of new Variable.
* @return Variable which differs from this Variable by position.
* @throws NullPointerException if p is null.
*/
public Variable withPos(TextDescriptor.Position p) {
return withTextDescriptor(getTextDescriptor().withPos(p));
}
/**
* Method to return the text size of the text in the Variable's TextDescriptor.
* This is a Size object that can describe either absolute text (in points)
* or relative text (in quarter units).
* @return the text size of the text in the Variable's TextDescriptor.
*/
public TextDescriptor.Size getSize() {
return descriptor.getSize();
}
/**
* Method to find the true size in points for the Variable's TextDescriptor in a given EditWindow0.
* If the TextDescriptor is already Absolute (in points) nothing needs to be done.
* Otherwise, the scale of the EditWindow0 is used to determine the acutal point size.
* @param wnd the EditWindow0 in which drawing will occur.
* @return the point size of the text described by the Variable's TextDescriptor.
*/
public double getTrueSize(EditWindow0 wnd) {
return descriptor.getTrueSize(wnd);
}
/**
* Returns Variable which differs from this Variable by text size.
* New size is absolute size (in points).
* The size must be between 1 and 63 points.
* @param s the point size of new Variable.
* @return Variable which differs from this Variable by text size.
*/
public Variable withAbsSize(int s) {
return withTextDescriptor(getTextDescriptor().withAbsSize(s));
}
/**
* Returns Variable which differs from this Variable by text size.
* New size is a relative size (in units).
* The size must be between 0.25 and 127.75 grid units (in .25 increments).
* @param s the unit size of new Variable.
* @return Variable which differs from this Variable by text size.
*/
public Variable withRelSize(double s) {
return withTextDescriptor(getTextDescriptor().withRelSize(s));
}
/**
* Method to return the text font of the Variable's TextDescriptor.
* @return the text font of the Variable's TextDescriptor.
*/
public int getFace() {
return descriptor.getFace();
}
/**
* Returns Variable which differs from this Variable by text font.
* @param f the text font of new Variable.
* @return Variable which differs from this Variable by text font.
*/
public Variable withFace(int f) {
return withTextDescriptor(getTextDescriptor().withFace(f));
}
/**
* Method to return the text rotation of the Variable's TextDescriptor.
* There are only 4 rotations: 0, 90 degrees, 180 degrees, and 270 degrees.
* @return the text rotation of the Variable's TextDescriptor.
*/
public TextDescriptor.Rotation getRotation() {
return descriptor.getRotation();
}
/**
* Returns Variable which differs from this Variable by rotation.
* There are only 4 rotations: 0, 90 degrees, 180 degrees, and 270 degrees.
* @param r the text rotation of new Variable.
* @return Variable which differs from this Variable by rotation.
*/
public Variable withRotation(TextDescriptor.Rotation r) {
return withTextDescriptor(getTextDescriptor().withRotation(r));
}
/**
* Method to return the text display part of the Variable's TextDescriptor.
* @return the text display part of the Variable's TextDescriptor.
*/
public TextDescriptor.DispPos getDispPart() {
return descriptor.getDispPart();
}
/**
* Returns Variable which differs from this Variable by dislay part.
* @param dispPos the text display part of new Variable.
* @return Variable which differs from this Variable by dislay part.
* @throws NullPointerException if dispPos is null
*/
public Variable withDispPart(TextDescriptor.DispPos dispPos) {
return withTextDescriptor(getTextDescriptor().withDispPart(dispPos));
}
/**
* Method to return true if the text in the Variable's TextDescriptor is italic.
* @return true if the text in the Variable's TextDescriptor is italic.
*/
public boolean isItalic() {
return descriptor.isItalic();
}
/**
* Returns Variable which differs from this Variable by italic flag.
* @param state true if text of new Variable is italic.
* @return Variable which differs from this Variable by italic flag.
*/
public Variable withItalic(boolean state) {
return withTextDescriptor(getTextDescriptor().withItalic(state));
}
/**
* Method to return true if the text in the Variable's TextDescriptor is bold.
* @return true if the text in the Variable's TextDescriptor is bold.
*/
public boolean isBold() {
return descriptor.isBold();
}
/**
* Returns Variable which differs from this Variable by bold flag.
* @param state true if text of new Variable is bold.
* @return Variable which differs from this Variable by bold flag.
*/
public Variable withBold(boolean state) {
return withTextDescriptor(getTextDescriptor().withBold(state));
}
/**
* Method to return true if the text in the Variable's TextDescriptor is underlined.
* @return true if the text in the Variable's TextDescriptor is underlined.
*/
public boolean isUnderline() {
return descriptor.isUnderline();
}
/**
* Returns Variable which differs from this Variable by underline flag.
* @param state true text of new Variable is underlined.
* @return Variable which differs from this Variable by underline flag.
*/
public Variable withUnderline(boolean state) {
return withTextDescriptor(getTextDescriptor().withUnderline(state));
}
/**
* Method to return true if the text in the Variable's TextDescriptor is interior.
* Interior text is not seen at higher levels of the hierarchy.
* @return true if the text in the Variable's TextDescriptor is interior.
*/
public boolean isInterior() {
return descriptor.isInterior();
}
/**
* Returns Variable which differs from this Variable by interior flag.
* Interior text is not seen at higher levels of the hierarchy.
* @param state true if text with new Variable is interior.
* @return Variable which differs from this Variable by interior flag.
*/
public Variable withInterior(boolean state) {
return withTextDescriptor(getTextDescriptor().withInterior(state));
}
/**
* Method to return true if the text in the Variable's TextDescriptor is inheritable.
* Inheritable variables copy their contents from prototype to instance.
* Only Variables on NodeProto and PortProto objects can be inheritable.
* When a NodeInst is created, any inheritable Variables on its NodeProto are automatically
* created on that NodeInst.
* @return true if the text in the Variable's TextDescriptor is inheritable.
*/
public boolean isInherit() {
return descriptor.isInherit();
}
/**
* Returns Variable which differs from this Variable by inheritable flag.
* Inheritable variables copy their contents from prototype to instance.
* Only Variables on NodeProto and PortProto objects can be inheritable.
* When a NodeInst is created, any inheritable Variables on its NodeProto are automatically
* created on that NodeInst.
* @param state true if new Variable is inheritable.
* @return Variable which differs from this Variable by inheritable flag.
*/
public Variable withInherit(boolean state) {
return withTextDescriptor(getTextDescriptor().withInherit(state));
}
/**
* Returns Variable which deffers from this Variable by parameter flag.
* Parameters are those Variables that have values on instances which are
* passed down the hierarchy into the contents.
* Parameters can only exist on Cell objects.
* @param state true if new Variable is parameter.
* @return Variable which deffers from this Variable by parameter flag.
*/
public Variable withParam(boolean state) {
return withTextDescriptor(getTextDescriptor().withParam(state));
}
/**
* Method to return the X offset of the text in the Variable's TextDescriptor.
* @return the X offset of the text in the Variable's TextDescriptor.
*/
public double getXOff() {
return descriptor.getXOff();
}
/**
* Method to return the Y offset of the text in the Variable's TextDescriptor.
* @return the Y offset of the text in the Variable's TextDescriptor.
*/
public double getYOff() {
return descriptor.getYOff();
}
/**
* Returns Variable which differs from this Variable by
* X and Y offsets of the text in the Variable's TextDescriptor.
* The values are scaled by 4, so a value of 3 indicates a shift of 0.75 and a value of 4 shifts by 1.
* @param xd the X offset of the text in new Variable's TextDescriptor.
* @param yd the Y offset of the text in new Variable's TextDescriptor.
* @return Variable which differs from this Variable by
* X and Y offsets of the text in the Variable's TextDescriptor.
*/
public Variable withOff(double xd, double yd) {
return withTextDescriptor(getTextDescriptor().withOff(xd, yd));
}
/**
* Method to return the Unit of the Variable's TextDescriptor.
* Unit describes the type of real-world unit to apply to the value.
* For example, if this value is in volts, the Unit tells whether the value
* is volts, millivolts, microvolts, etc.
* @return the Unit of the Variable's TextDescriptor.
*/
public TextDescriptor.Unit getUnit() {
return descriptor.getUnit();
}
/**
* Returns Variable which differs from this Variable by unit.
* Unit describe the type of real-world unit to apply to the value.
* For example, if this value is in volts, the Unit tells whether the value
* is volts, millivolts, microvolts, etc.
* @param u the Unit of new Variable.
* @return Variable which differs from this Variable by unit.
*/
public Variable withUnit(TextDescriptor.Unit u) {
return withTextDescriptor(getTextDescriptor().withUnit(u));
}
}
|