Workspace Elements

Workspace

An ADS Workspace is a directory on disk, where all design work must be done.

It is used to store and organize the design work in a Library:Cell:View hierarchical structure. Additionally, it contains simulation results, data display files, and other data files.

# import the design environment package
from keysight.ads import de
# Creating a new workspace
workspace: de.Workspace = de.create_workspace('path_to_workspace')
# A newly created workspace is not open by default, and be can opened by:
workspace.open()
# Or, for an existing workspace:
workspace: de.Workspace = de.open_workspace('path_to_workspace')

Only one workspace may be open at a time. You can obtain the currently opened workspace by calling get_active_workspace().

from keysight.ads import de
# Check if there is an open workspace and retrieve it
if de.workspace_is_open():
    workspace: de.Workspace = de.get_active_workspace()

A workspace defines a library mapping of OpenAccess libraries. Each entry in the mapping associates a library name, like mylib, with a library directory, like ./mylib, as well as its access mode, such as LibraryMode.READ_ONLY. The library mapping is contained in a file, typically named lib.defs, in the workspace directory.

Library

An ADS Library is a directory, formatted as an OpenAccess library. A library contains a set of cells plus some configuration shared across the cells. All types of designs are contained in a library. A library does not have to physically reside in the workspace directory. It is common to have one or more library directories inside the workspace directory. However, a workspace can also refer to libraries in other locations.

Libraries have a unique name and path and help prevent name collisions with PDKs and other system libraries; they help to organize designs that share a common technology.

Creating a library using ADS Python is straightforward:

from keysight.ads import de
# Create a new library named "mylib"
# Often, "path_to_library" is a path contained in a workspace directory
# and carries the same name as the library
library: de.Library = de.create_new_library("mylib", "path_to_library")

When a library definition file is loaded, each of the libraries defined in the file are opened and every referenced library definition file is loaded. While workspaces cannot be added to other workspaces, libraries from other workspaces can. To add a library to the definition file, use the add_library() method.

from keysight.ads import de
# Given a workspace, add "library_name", located at "path_to_library"
# as a read-only library to the workspace
workspace.add_library("library_name", "path_to_library", de.LibraryMode.READ_ONLY)

Libraries can be opened in one of three different modes:

  • SHARED: The library is opened for reading and writing, using lock files

    to prevent multiple users from modifying a given design in the library at the same time. An error is thrown if a user attempts to open a design that is already open by another user or process.

  • NON_SHARED: The library is opened for reading and writing without using lock files.

    In this mode, no error is given if two users or processes open a particular design at the same time.

  • READ_ONLY: The library is opened for reading only. Design modifications cannot be saved

    in this mode.

By default, libraries are opened as READ_ONLY.

All designs stored in a library inherit the technology of the library and will need to be created or attached to the library.

from keysight.ads import de
# Setup a basic technology for schematic and layout views of the library
# Typically you'll want to specify the substrate interfaces, layers, materials, etc.
# yourself, or copy them from another library
library.setup_schematic_tech()
library.create_layout_tech_std_ads("mil", 1000, True)

Cell

A Cell` is an object that contains cellviews (such as schematic views, layout views, and symbol views) and other files relevant to the design (such as itemdef.py, which specifies the model for your component). Cells are contained within libraries and are represented as directories on disk under the library.

A cell will be automatically created the first time you create a design in a library for a cell that does not already exist. For example, if you wish to create a new schematic in a new cell, called “mycell”, in the library “mylib”, you can do so as follows:

from keysight.ads import de
# Create a new schematic design in a view called "schematic", in a cell called "mycell",
# in a library called "mylib"
design: de.db_uu.Design = de.db_uu.create_schematic("myLib:mycell:schematic")
assert design.cell.cell_name == "mycell"

# Cells can also be created directly without an initial design by passing
# in the library and cell name
# Create a new cell called "mycell1" in a library called "mylib"
cell: de.Cell = de.Cell.create(myLib, "mycell1")
assert cell.cell_name == "mycell1"

View

A View represents a specific aspect or representation of a cell. For example, a view can be a schematic view, a layout view, a symbol view, etc. Views are contained within cells and are represented as directories on disk underneath the cell directory. Not all views are design views; such as a Verilog view.

Similar to cells, views will be automatically created the first time you create a design in a cell for a view that does not already exist. For example, if you wish to create a schematic view, you can do so as follows:

from keysight.ads import de
# Create a new schematic design in a view called "schematic", in a cell called "mycell",
# in a library called "mylib"
design: de.db_uu.Design = de.db_uu.create_schematic("myLib:mycell:schematic")
assert design.cell.cell_name == "mycell"

# Alternatively, you can create a view directly from a cell
cell: de.Cell = de.Cell.create(myLib, "mycell1")
# Create a view of the schematic type named my_schematic
view: de.View = cell.create_view("my_schematic", "schematic")

assert view.view_name == "my_schematic"
# Not all views are design views, but a schematic view is
assert view.is_design_view and view.is_schematic_view
# Given a design view, you can obtain the associated design by using the design initializer
# and setting the named parameter view to the view object
design: de.db_uu.Design = de.db_uu.Design(view=view)

Iterating through all the cells and views in a library can be done as follows:

from keysight.ads import de
# Assumes the library "myLib" is already open
library: de.Library = de.get_open_library("myLib")
for cell in library.cells:
    print(f"cell name: {cell.cell_name}")
    for view in cell.views:
        print(f"view name: {view.view_name}")

Design

A Design in ADS is an instance of a design view. The ADS Python API separates designs and associated design objects into two major categories, differentiated by the unit specification of the design, user units (db_uu) and database units (dbu).

Every design will be one of the two types and the other type can be easily obtained by calling either in_user_units or in_database_units on an instance of a design. Any object or element contained in a design will be of the same unit type as the design.

User units are the unit type that the user sees while interacting with GUI and are floating point values. Database units are the unit type when storing the design in the database and are integer values. You can determine the factor between the two units by calling uu_to_dbu_factor or dbu_to_uu_factor on an instance of a design. Additionally, Any point can be converted between the two units by calling uu_to_dbu or dbu_to_uu.

Schematic and symbol designs have a uu_to_dbu_factor of 160 (dbu_to_uu_factor of 0.00625) and cannot be modified. Layout designs have a resolution that is determined by the technology of the library.

Typically, when working with designs, the user unit type is used.

from keysight.ads import de
# Create a design
design: de.db_uu.Design = de.db_uu.create_layout("myLib:mycell:layout")
# The dbu_to_uu_factor of this layout design is determined by the setting in the technology
# in the library. If, for example, you have configured the technology to have 1000 dbu per uu,
# then the dbu_to_uu_factor will be 0.001
assert design.dbu_to_uu_factor == 0.001
# The uu_to_dbu_factor will be 1000
assert design.uu_to_dbu_factor == 1000

# Regardless of the technology settings, schematic and symbol designs have a fixed factor
# of 160 dbu per uu and cannot be modified.
design: de.db_uu.Design = de.db_uu.create_schematic("myLib:mycell:schematic")
assert design.dbu_to_uu_factor == 0.00625
assert design.uu_to_dbu_factor == 160

Instance

An Instance represents an instance of a design that is included as part of another design. The design containing the instance is referred to as the parent design; the design being instantiated is referred to as the master design. Instances can be used to create hierarchical designs, where the master design of an instance can contain instances of other master designs, continuing for as many levels of hierarchy as needed to complete the overall design.

Adding instances to a design can be done by calling the add_instance method on a design object and are specified by the library, cell, and view.

from keysight.ads import de

design: de.db_uu.Design = de.db_uu.create_schematic("myLib:mycell:schematic")

# Create an instance of a resistor symbol and place it in the schematic at (0, 0)
cellview: de.CellviewRef = de.CellviewRef("ads_rflib", "R", "symbol")
instance: de.db_uu.Instance = design.add_instance(cellview, (0, 0), name="R1")

# Iterating over the parameters of an instance
for param in instance.parameters:
    # The __repr__ of the parameter will return the name and value
    print(param)

# When modifying the value of a parameter, put the modification under a transaction
# and invoke the parameter changed callback
with de.db.Transaction(design) as transaction:
    instance.parameters["R"].value = "100 Ohm"
    # Some components, custom ones or ones provided by ADS, may have a callback that
    # responds to parameter changes.
    # You can invoke this callback by calling invoke_item_parameter_changed_callback
    instance.invoke_item_parameter_changed_callback("R")
    transaction.commit()

# You can obtain the model definition (also known as an item or component definition)
# of the instance
model_del: de.db.ModelDef = instance.model_def
# The model definition
On this page