Working with VAR
This example shows how to update the variables inside a VAR block and evaluate an expression.
def var_evaluation(library: de.Library) -> None:
def eval_expression(design: db_uu.Design, expression: str) -> str:
expr_context = de.db.ExpressionContext()
expr_context.setup_hierarchy_for_design(design)
return expr_context.evaluate_expression(expression)
design = db_uu.create_schematic(f"{library.name}:var:schematic")
# Place an instance of VAR
var_inst = design.add_instance(("ads_datacmps", "VAR", "symbol"), (0, 0), name="VAR1", angle=90)
assert var_inst.is_var_instance
with db_uu.Transaction(design) as transaction:
# VAR names are case-sensitive, so
var_inst.vars["X"] = "7.5" # X is different from
var_inst.vars["x"] = "3.0" # x
assert var_inst.vars["X"] == "7.5"
assert var_inst.vars["x"] == "3.0"
# Values can be expressions containing other VAR names
var_inst.vars["Y"] = "X / x"
transaction.commit()
# And the expressions can be evaluated like so:
result = float(eval_expression(design, "Y"))
assert result == 2.5 # 7.5 / 3.0
# ADS has built-in constants like "pi" that can be used in expression evaluation.
# See "VAR (Variables and Equations Component)" in the ADS product documentation for more information.
with db_uu.Transaction(design) as transaction:
var_inst.vars["r"] = "10.0"
var_inst.vars["area"] = "pi * r ** 2"
transaction.commit()
result = float(eval_expression(design, "area"))
import math
assert math.isclose(result, 314.159265, rel_tol=1e-6) # pi * 10.0 ^ 2
design.save_design()
This example shows how to evaluate expressions containing references to VARs higher up in the design hierarchy.
def var_evaluation_in_design_hierarchy(library: de.Library) -> None:
top_design = db_uu.create_schematic(f"{library.name}:top:schematic")
middle_design = db_uu.create_schematic(f"{library.name}:middle:schematic")
bottom_design = db_uu.create_schematic(f"{library.name}:bottom:schematic")
# Place a VAR in bottom_design that references a VAR in middle
var_bottom = bottom_design.add_instance(("ads_datacmps", "VAR", "symbol"), (0, 0), name="VAR_BOTTOM", angle=90)
var_bottom.vars["A"] = "B + 2.0"
# Place a VAR in middle_design that references a VAR in top
var_middle = middle_design.add_instance(("ads_datacmps", "VAR", "symbol"), (0, 0), name="VAR_MIDDLE", angle=90)
var_middle.vars["B"] = "C + 3.0"
# Place a VAR in top_design
var_top = top_design.add_instance(("ads_datacmps", "VAR", "symbol"), (0, 0), name="VAR_TOP", angle=90)
var_top.vars["C"] = "5.0"
# Top has an instance of middle and middle has an instance of bottom
bottom_inst = middle_design.add_instance(bottom_design.design_name, (0, 0), name="bottom")
middle_inst = top_design.add_instance(middle_design.design_name, (0, 0), name="mid")
expr_context = de.db.ExpressionContext()
expr_context.setup_hierarchy_for_design(top_design)
# Push down the hierarchy to the bottom design for evaluation of A
expr_context.push_instance_for_reading(middle_inst)
expr_context.push_instance_for_reading(bottom_inst)
result = float(expr_context.evaluate_expression("A"))
assert result == 10.0 # A = B + 2.0 == C + 3.0 + 2.0 == 5.0 + 3.0 + 2.0 == 10.0
# Pop back up to the hierarchy to evaluate B
expr_context.pop()
result = float(expr_context.evaluate_expression("B"))
assert result == 8.0 # B = C + 3.0 == 5.0 + 3.0 == 8.0
top_design.save_design()
middle_design.save_design()
bottom_design.save_design()
This example shows how to evaluate an expression containing a reference to a VAR lower in the design hierarchy.
def var_evaluation_in_design_hierarchy_global_scope(library: de.Library) -> None:
top_design = db_uu.create_schematic(f"{library.name}:top_global:schematic")
bottom_design = db_uu.create_schematic(f"{library.name}:bottom_global:schematic")
# Place an instance of VAR (Variable and Equations component)
with db_uu.Transaction(bottom_design) as transaction:
var_bottom = bottom_design.add_instance(("ads_datacmps", "VAR", "symbol"), (0, 0), name="VAR1", angle=90)
var_bottom.vars["r"] = "10.0"
var_bottom.vars["area"] = "pi * r ** 2"
del var_bottom.vars["X"]
# To evaluate an expression with a reference to a VAR in a subdesign, the VAR instance must have global scope
var_bottom.set_global_scope()
transaction.commit()
with db_uu.Transaction(top_design) as transaction:
# Add an instance of bottom_design into top_design
top_design.add_instance(bottom_design.design_name, (0, 2), name="bottom", angle=0)
var_top = top_design.add_instance(("ads_datacmps", "VAR", "symbol"), (0, 0), name="VAR2", angle=90)
var_top.vars["perim"] = "2 * pi * r"
transaction.commit()
bottom_design.save_design()
top_design.save_design()
expr_context = de.db.ExpressionContext()
expr_context.setup_hierarchy_for_design(top_design)
result = float(expr_context.evaluate_expression("perim"))
import math
assert math.isclose(result, 62.831853, rel_tol=1e-6) # 2 * pi * 10.0
This example shows some of the errors that can occur when working with VARs.
def var_evaluation_errors(library: de.Library) -> None:
# NOTE: The error messages below are specific to the Simple Evaluator; the Full Evaluator error messages differ
# See the Evaluation section in the Library Configuration Editor in the ADS product documentation for more information
# on the Simple and Full Evaluators
bottom_design = db_uu.create_schematic(f"{library.name}:cell_error_bottom:schematic")
var_bottom = bottom_design.add_instance(("ads_datacmps", "VAR", "symbol"), (1, 0), name="VAR1", angle=90)
# VARs are required to have at least one name/value pair and a new instance of VAR has a default "X" = "1.0"
# It is okay to delete name/value pairs from a VAR but there must always be at least one
try:
del var_bottom.vars["X"]
except RuntimeError as e:
assert str(e) == "VAR instances need to have always at least 1 parameter"
# When evaluating VARs, references to names must be unique within the scope of the design hierarchy
var_bottom2 = bottom_design.add_instance(("ads_datacmps", "VAR", "symbol"), (1, 0), name="VAR2", angle=90)
# To which X does this refer? The one in var_bottom or var_bottom2?
var_bottom2.vars["Y"] = "X + 2"
expr_context = de.db.ExpressionContext()
expr_context.setup_hierarchy_for_design(bottom_design)
try:
# As stated previously, a VAR instance has a name/value pair that defaults to "X" = "1.0",
# but we cannot have two different VARs in a design with the same name
expr_context.evaluate_expression("Y")
except RuntimeError as e:
assert str(e) == "Schematic variable 'X' already defined at level 0"
top = db_uu.create_schematic(f"{library.name}:cell_error_top:schematic")
top.add_instance(bottom_design.design_name, (0, 0), name="design", angle=90)
# To evaluate an expression with a reference to a VAR in a subdesign, the VAR instance must have global scope
var_bottom.vars["A"] = "5.0"
var_top = top.add_instance(("ads_datacmps", "VAR", "symbol"), (0, 2), name="VAR2", angle=90)
var_top.vars["B"] = "A"
expr_context = de.db.ExpressionContext()
expr_context.setup_hierarchy_for_design(top)
try:
expr_context.evaluate_expression("B")
except RuntimeError as e:
assert str(e) == "Error evaluating variable 'B': Error evaluating variable 'A': Variable undefined."
# Not all expressions can be evaluated with the Simple Evaluator, which is the evaluator in automation mode
var_top.vars["Euler"] = "e ** (pi * j)"
if de.running_automation:
try:
expr_context.evaluate_expression("Euler")
except RuntimeError as e:
# See the Evaluation section in the Library Configuration Editor in the ADS product documentation for more information
assert (
str(e)
== "Error evaluating variable 'Euler': Error evaluating variable 'j': Complex numbers are not supported by the Simple Evaluator."
)