Adding Instances to a Design

This example adds instances of components to a design and then adds that design as an instance to another design

# Copyright Keysight Technologies 2023 - 2023
import os

from keysight.ads import ael, de
from keysight.ads.de import ArcOrientation, GenPolyline, PointF, db_uu
from keysight.ads.de.experimental import generate_symbol as gs


def create_lpf_circuit_workspace_design_and_simulate() -> None:
    # This workspace will reside in the user's home directory under workspaces/Instances_example_wrk
    home_dir = os.environ["HOME"]
    workspace_path = os.path.join(home_dir, "workspaces/Instances_example_wrk")

    # Ensure there is no open workspace
    if de.workspace_is_open():
        de.close_workspace()
    # Create the workspace
    de.create_workspace(workspace_path)
    workspace = de.open_workspace(workspace_path)
    # Create the library
    de.create_new_library("LPF_lib", os.path.join(workspace_path, "LPF_lib"))
    # And add it to the workspace
    workspace.add_library("LPF_lib", os.path.join(workspace_path, "LPF_lib"), de.LibraryMode.SHARED)
    # Create an empty schematic
    schematic_lpf = db_uu.create_schematic("LPF_lib:LPF:schematic")
    assert schematic_lpf is not None
    # And write out the design
    # By creating and committing a transaction, we force a connectivitiy check on the design
    transaction = de.db.Transaction(schematic_lpf, "Create schematic")
    create_an_ideal_lpf_circuit(schematic_lpf)
    transaction.commit()
    schematic_lpf.save_design()

    # Generate a symbol for the design
    symbol_lpf = create_symbol_for_ideal_lpf_circuit(schematic_lpf)

    # Create a new design in a new cell
    schematic_sp = db_uu.create_schematic("LPF_lib:LPF_SP:schematic")
    assert schematic_sp is not None
    # Designs may be referenced in multiple ways, such as with a CellviewRef
    cvr = de.CellviewRef(view=symbol_lpf.view)
    assert cvr is not None
    # Write out the new design
    transaction = de.db.Transaction(schematic_sp, "Create schematic")
    add_subcircuit_to_design_and_create_lpf_circuit(schematic_sp, cvr)
    transaction.commit()
    schematic_sp.save_design()

    # qthelp://ads.2024/doc/appguide/Designing_a_Simple_Low_Pass_Filter.html
    # TODO: Specify hierarchy policy
    # TODO: Perform schematic simulation
    # TODO: Add Parameters Sweep/Values
    # TODO: Simulate


def create_an_ideal_lpf_circuit(design: db_uu.Design) -> None:
    # ensure the design is empty
    design.clear_design()
    # ads_device:drawing for schematic, cond for layout
    layer_id = db_uu.LayerId(231 if design.is_schematic is True else 1)

    # Add an input pin to the design
    net = design.find_or_add_net("P1")
    term = design.add_term(net, "P1", db_uu.TermType.INPUT)
    dot = design.add_dot(layer_id, (0.0, 0.0))
    # Pin angle may be passed into the constructor, or
    pin = design.add_pin(term, dot, angle=0.0)
    # The pin angle may be modified after being placed
    pin.angle = 180.0
    # And when setting the pin angle this way, update the annotation position, if desired
    pin.update_pin_annotation(False)
    assert pin.term.name == "P1"

    # Add an output pin to the design
    net = design.find_or_add_net("P2")
    term = design.add_term(net, "P2", db_uu.TermType.OUTPUT)
    dot = design.add_dot(layer_id, (5.0, 0.0))
    pin = design.add_pin(term, dot)
    assert pin.term.name == "P2"

    # Add a couple instances of an inductor to the design
    # An instance may be referred by using the Library, Cell, and View name directly
    inductor = design.add_instance(de.LCVName("ads_rflib", "L", "symbol"), (0.750, 0.0), name="L1", angle=0.0)
    assert inductor is not None and inductor.name == "L1"
    # Or an instance may be referred by using a CellviewRef
    cell_view_ref = de.CellviewRef("ads_rflib", "L", "symbol")
    inductor = design.add_instance(cell_view_ref, (3.250, 0.0), name="L2", angle=0.0)
    assert inductor is not None and inductor.name == "L2"
    # Add a capacitor to the design at a -90 degree angle
    capacitor = design.add_instance(de.LCVName("ads_rflib", "C", "symbol"), (2.50, -1.25), name="C1", angle=-90.0)
    assert capacitor is not None and capacitor.name == "C1"
    # Add a ground to the design at a -90 degree angle
    ground = design.add_instance(de.LCVName("ads_rflib", "GROUND", "symbol"), (2.50, -2.25), name="GND", angle=-90.0)
    assert ground is not None and ground.name == "GND"
    # Wire them up
    # P1 to L1
    design.add_wire([(0.0, 0.0), (0.750, 0.0)])
    # L1 to L2
    design.add_wire([(1.750, 0.0), (3.250, 0.0)])
    # L2 to P2
    design.add_wire([(4.250, 0.0), (5.0, 0.0)])
    # C1 to L1 and L2
    design.add_wire([(2.50, 0.0), (2.50, -1.250)])


def create_symbol_for_ideal_lpf_circuit(schematic_lpf: db_uu.Design) -> db_uu.Design:
    symbol_lpf = db_uu.create_symbol("LPF_lib:LPF:symbol")
    # Create the symbol in LPF using SymbolGenerator
    symbol_generator = gs.SymbolGenerator(symbol_lpf, schematic_lpf, 0.25, 0.25)
    symbol_generator.is_dual_symbol_type = True
    symbol_generator.should_replace = True
    symbol_generator.pin_shape = "square"
    symbol_generator.generate_symbol()
    points_l = [(0.3, 0.2), (0.5, 0)]
    polyline_l = GenPolyline(points_l)
    polyline_l.set_segment_as_arc(0, PointF(0.375, 0), ArcOrientation.CLOCKWISE)
    symbol_layer_id = ael.call.db_get_layerid_for_symbol_body(symbol_lpf)
    symbol_lpf.add_line(symbol_layer_id, polyline_l.outline)
    points_r = [(0.7, -0.2), (0.5, 0)]
    polyline_r = GenPolyline(points_r)
    polyline_r.set_segment_as_arc(0, PointF(0.625, 0), ArcOrientation.CLOCKWISE)
    symbol_lpf.add_line(symbol_layer_id, polyline_r.outline)
    symbol_lpf.add_text(symbol_layer_id, "Input", (0.3, 0.125), "Ariel for CAE", 0.069, db_uu.TextAlignment.LOWER_LEFT)
    symbol_lpf.add_text(
        symbol_layer_id, "Output", (0.7, -0.125), "Ariel for CAE", 0.069, db_uu.TextAlignment.UPPER_RIGHT
    )
    symbol_lpf.save_design()
    return symbol_lpf


def add_subcircuit_to_design_and_create_lpf_circuit(design: db_uu.Design, sub_circuit: de.CellviewRef) -> None:
    # Add an instance of sub_circuit to design
    design.add_instance(sub_circuit, (2.50, 0.0))
    # Add some terms
    design.add_instance(de.LCVName("ads_simulation", "Term", "symbol"), (0.0, 0.0), name="Term1", angle=-90.0)
    design.add_instance(de.LCVName("ads_simulation", "Term", "symbol"), (6.0, 0.0), name="Term2", angle=-90.0)
    # Add some ground
    design.add_instance(de.LCVName("ads_rflib", "GROUND", "symbol"), (0.0, -1.0), name="GND1", angle=-90.0)
    design.add_instance(de.LCVName("ads_rflib", "GROUND", "symbol"), (6.0, -1.0), name="GND2", angle=-90.0)
    # Add an S-Param
    design.add_instance(de.LCVName("ads_simulation", "S_Param", "symbol"), (0.0, -3.0), name="S_Param", angle=0.0)
    # Wire up the terms to the sub_circuit
    design.add_wire([(0.0, 0.0), (2.50, 0.0)])
    design.add_wire([(3.50, 0.0), (6.0, 0.0)])
On this page