📄 varcontext.java
字号:
/** * Get the number of levels of context in this VarContext * @return the number of levels of context in this VarContext */ public int getNumLevels() { int i=0; VarContext acontext = this; while (acontext != VarContext.globalContext) { i++; acontext = acontext.pop(); } return i; } /** Get rid of the variable cache thereby release its storage */ public synchronized void deleteVariableCache() { cache=null; } // ------------------------------ Variable Evaluation ----------------------- /** * Gets the value of Variable @param var. * If variable is Java, uses EvalJavaBsh to evaluate * If variable is TCL, uses ... to evaluate * If variable is Lisp, uses ... to evaluate * otherwise, just returns the Variable's object * @return the evlauated Object. Returns null if the variable * is code and evaluation fails. */ public Object evalVar(Variable var) { return evalVar(var, null); } /** Same as evalVar, except an additional object 'info' * is passed to the evaluator. 'info' may be or contain * additional information necessary for proper evaluation. * Usually info is the NodeInst on which the var exists. * @return the evlauated Object. Returns null if the variable * is code and evaluation fails. */ public Object evalVar(Variable var, Object info) { if (var == null) return null; try { return evalVarRecurse(var, info); } catch (EvalException e) { printException(e, var, this, info); return null; } } public static class EvalException extends Exception { public EvalException() { super(); } public EvalException(String message) { super(message); } public EvalException(String message, Throwable cause) { super(message, cause); } public EvalException(Throwable cause) { super(cause); } } public static void printException(EvalException e, Variable var, VarContext context, Object info) { // If cause is null, this was an error in electric (var lookup etc) if (e.getCause() == null) return; // otherwise, this is an error in the bean shell String msg = "Exception caught evaluating "+var.getCode()+ " var "+var.getTrueName()+(e.getMessage() == null ? "" : ": "+e.getMessage()); if (info instanceof Nodable) { NodeInst ni = ((Nodable)info).getNodeInst(); System.out.println("In Cell "+ni.getParent().describe(false)+", on Node "+ni.describe(false)+": "+msg); } else { System.out.println(msg); } } /** * This is the recursive version of evalVar that may throw an EvalException. * The message of the EvalException states the reason that evaluation failed. * This is made public so code elsewhere that is meant to be used in Attribute's java code * can call this method. This is useful such that the first EvalException encountered is * thrown all the way to the top of the eval caller, rather than getting caught and handled * somewhere inbetween. * @param var the variable to evaluate * @param info an info object that may be needed by the evaluator * @return the variable's object if not code, otherwise an evaluated result object if * evaluation succeeds * @throws EvalException an exception whose message contains the reason evaluation failed */ public Object evalVarRecurse(Variable var, Object info) throws EvalException { CodeExpression ce = var.getCodeExpression(); if (ce == null) return ifNotNumberTryToConvertToNumber(var.getObject()); switch (ce.getCode()) { case JAVA: Object value = fastJavaVarEval(ce, info); // testing code //checkFastValue(value, var, info); if (value==FAST_EVAL_FAILED) { // OK, I give up. Call the darn bean shell. value = EvalJavaBsh.evalJavaBsh.evalVarObject(ce, this, info); synchronized(this) { if (cache!=null) cache.put(ce, info, value); } } return ifNotNumberTryToConvertToNumber(value); case SPICE: Object obj = evalSpice_(ce, true); if (obj instanceof Number) { Number n = (Number)obj; if (n.doubleValue() < 0.001) return TextUtils.formatDoublePostFix(n.doubleValue()); } if (obj instanceof EvalSpice.SimpleEq) { // couldn't parse, just return original return ce.getExpr(); } return obj; case TCL: return ifNotNumberTryToConvertToNumber(ce.getExpr()); default: throw new AssertionError(); } } /** * Evaluate a spice variable * @param var the variable to evaluate * @param recurse false to not recursively evaluate (only if param call is SPICE code). * @return the evaluated string, or null on eval error */ public Object evalSpice(Variable var, boolean recurse) { //if (var.getCode() != TextDescriptor.Code.SPICE) return null; try { return evalSpice_(var.getCodeExpression(), recurse); } catch (EvalException e) { return null; } } /** For replacing @variable */ private static final Pattern pPat = Pattern.compile("P\\(\"(\\w+)\"\\)"); private Object evalSpice_(CodeExpression ce, boolean recurse) throws EvalException { assert ce.getCode() == CodeExpression.Code.SPICE; String expr = EvalJavaBsh.replace(ce.getExpr()); Matcher pMat = pPat.matcher(expr); StringBuffer sb = new StringBuffer(); while (pMat.find()) { Object value = pMat.group(1).substring(5); Variable parentVar = null; Nodable no = getNodable(); if (no != null) parentVar = no.getParameter(Variable.findKey(pMat.group(1))); if (parentVar != null) { // see if param is spice code by looking at instance code boolean isSpiceCode = parentVar.getCode() == CodeExpression.Code.SPICE;// if (no.isCellInstance()) {// Cell c = (Cell)no.getProto();// if (c.contentsView() != null) c = c.contentsView();// Variable protoVar = c.getParameterOrVariable(parentVar.getKey());// if (protoVar != null)// isSpiceCode = protoVar.getCode() == TextDescriptor.Code.SPICE;// } if (recurse || !isSpiceCode) value = pop().evalVarRecurse(parentVar, getNodable()); } pMat.appendReplacement(sb, value.toString()); } pMat.appendTail(sb); EvalSpice sp = new EvalSpice(sb.toString()); return sp.evaluate(); } /** * Lookup Variable one level up the hierarchy and evaluate. * Looks for the var on the most recent NodeInst on the * hierarchy stack. If not found, look for the default * Variable of the same name on the NodeProto. * @param name the name of the variable * @return an object representing the evaluated variable, * or null if no var or default var found. */ protected Object lookupVarEval(String name) throws EvalException { if (ni == null) throwNotFound(name); Variable.Key key = Variable.findKey(name); if (key == null) throwNotFound(name); // Topology.java concludes that all instances of a Cell have // the same transistor sizes if that Cell has no parameters. // Let's see if we can enforce these semantics. A Variable has // a value that is visible in a Cell only if that Variable is // is a "parameter". // RKao Variable var = ni.getParameter(key);// Variable var = ni.getVar(key);//// if (var == null && ni.isCellInstance()) {// // look up default var on prototype// Cell cell = (Cell)ni.getProto();// Cell equiv = cell.getEquivalent();// if (equiv != null) cell = equiv;// var = cell.getVar(key);// } if (var == null) throwNotFound(name); // evaluate var in it's context Object val = this.pop().evalVarRecurse(var, ni); if (val == null) throwNotFound(name); val = ifNotNumberTryToConvertToNumber(val); if (val == null) throwNotFound(name); return val; } // lookupVarFarEval() is deprecated. Topology.java concludes that all instances // of a Cell have the same transistor sizes if that Cell has no parameters. // lookupVarFarEval() violates this assumption. Luckily we believe that no // designs use PAR() or lookupVarFarEval(). I'm commenting out this method to // guarantee that Topology.java always works correctly. RKao// /**// * Lookup Variable on all levels up the hierarchy and evaluate.// * Looks for var on all NodeInsts on the stack, starting// * with the most recent. At each NodeInst, if no Variable// * found, looks for default Variable on NodeProto.// * @param name the name of the variable// * @return evaluated Object, or null if not found// */// protected Object lookupVarFarEval(String name) throws EvalException// {// Variable.Key key = Variable.findKey(name);// if (key == null) throwNotFound(name);//// // look up the entire stack, starting with end// VarContext scan = this;// Object value = null;// while (true)// {// Nodable sni = scan.getNodable();// if (sni == null) break;//// Variable var = sni.getVar(key); // look up var// if (var != null) {// value = scan.pop().evalVarRecurse(var, sni);// break;// }//// // look up default var value on prototype// if (sni.isCellInstance()) {// Cell cell = (Cell)sni.getProto();// Cell equiv = cell.getEquivalent();// if (equiv != null) cell = equiv;// var = cell.getVar(key);// }// if (var != null) {// value = scan.pop().evalVarRecurse(var, sni);// break;// }// scan = scan.prev;// }// if (value == null) throwNotFound(name);//// value = ifNotNumberTryToConvertToNumber(value);// if (value == null) throwNotFound(name);//// return value;// } // ---------------------------------- Utility Methods ---------------------------- /** Return the concatonation of all instances names left to right * from the root to the leaf. Begin with the string with a separator * and place a separator between adjacent instance names. * @param sep the separator string. */ public String getInstPath(String sep) { if (this==globalContext) return ""; String prefix = pop()==globalContext ? "" : pop().getInstPath(sep); Nodable no = getNodable(); if (no==null) { System.out.println("VarContext.getInstPath: context with null NodeInst?"); } String me = no.getName(); if (no instanceof NodeInst) { // nodeInst, we want netlisted name, assume zero index of arrayed node //no = Netlist.getNodableFor((NodeInst)no, 0); Name name = no.getNameKey(); me = name.subname(0).toString(); }// if (me==null) {// //System.out.println("VarContext.getInstPath: NodeInst in VarContext with no name!!!");// me = ni.describe();// } if (prefix.equals("")) return me; return prefix + sep + me; } /** Helper method to convert an Object to a float, if possible. * if not possible, return @param def. */ public static float objectToFloat(Object obj, float def) { if (obj == null) return def; if (obj instanceof Number) return ((Number)obj).floatValue(); try { Number n = TextUtils.parsePostFixNumber(obj.toString()); return n.floatValue(); } catch (NumberFormatException e) {} return def; } /** Helper method to convert an Object to an integer, if possible. * if not possible, return @param def. */ public static int objectToInt(Object obj, int def) { if (obj == null) return def; if (obj instanceof Number) return ((Number)obj).intValue(); try { Number n = TextUtils.parsePostFixNumber(obj.toString()); return n.intValue(); } catch (NumberFormatException e) {} return def; } /** Helper method to convert an Object to a short, if possible. * if not possible, return @param def. */ public static short objectToShort(Object obj, short def) { if (obj == null) return def; if (obj instanceof Number) return ((Number)obj).shortValue(); try { Number n = TextUtils.parsePostFixNumber(obj.toString()); return n.shortValue(); } catch (NumberFormatException e) {} return def; } /** Helper method to convert an Object to a double, if possible. * if not possible, return @param def. */ public static double objectToDouble(Object obj, double def) { if (obj == null) return def; if (obj instanceof Number) return ((Number)obj).doubleValue(); try { Number n = TextUtils.parsePostFixNumber(obj.toString()); return n.doubleValue(); } catch (NumberFormatException e) {} return def; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -