Using Python to Access IC-CAP Objects and Data Structures

Blog Post created by michea on Oct 31, 2018


IC-CAP comes with a powerful API for accessing internal variables and data structures. In what follows, we will illustrate an example of accessing a Setup's Inputs and Outputs to obtain parameter values for the bias conditions for our custom Python measurement routines using the TableVar object.


What might be a typical approach?
When configuring a source measurement unit (SMU) to define start and stop voltages for a measurement sweep, you might use multiple setup variables stored in the Setup Variables table like this:


Setup Variables in IC-CAP


Then use some Python statements to read the parameter values from the table.


# query setup variables
vg_start = SVar("vgstart").get_val()
vg_stop = SVar("vgstop").get_val()
vg_step = SVar("vgstep").get_val()
vg_pts = SVar("vgpts").get_val().split(".")


But instead, I'm going to show you how to read the measurement configuration values entered in the Measure/Simulate tab and use these values in your Python code.


Measure/Simulate Tab

This allows you to set parameters in the Measure/Simulate tab just like when using the native IC-CAP instrument drivers in normal Measure mode.  Now you can use the built-in IC-CAP user interface to modify the parameters. In using this method, you will have to select the Extract/Optimize tab, select the transform and then click the Execute button to invoke your custom Python transform.




If you have not already setup your Python virtual environment and have IC-CAP installed, please refer to my previous article Measuring Sub-Threshold MOSFET Characteristics Using a Quasi-Static I-V Method.


Depending on whether you are using an older Agilent 4156B/C or a newer Keysight E5270B for your SMU, you may download and open one of the IC-CAP model files included at the end of this post.

  • py_api_demo_5270_v.2.0.mdl
  • py_api_demo_4156_v.2.0.mdl 

The Python code included for the E5270B can be applied to the B1500A with almost no modification as their command sets are very similar. Similarly, the code for the 4156B/C can be used with a 4142B with minor modification because we are using the US42 command mode using Flex commands. 


I recommend saving the *.mdl to C:\Keysight\ICCAP_2018\examples\python.  


Load the IC-CAP Model File


Assuming you saved the model file to the location above, click File/Examples... and select: 



Go to the DUT/Setup called dc/idvg_quasi. Select the Measure/Simulate tab and observe the settings for the Inputs and Outputs. Notice that we have set conditions to make the Id vs. Vg measurement using IC-CAP's built-in drivers. Now select the Setup Variables tab and review the variable table.


Name            Value               Comment
drain           1                   Drain SMU Channel
gate            2                   Gate SMU Channel
source          3                   Source SMU Channel
substrate       4                   Substrate SMU Channel
interface       GPIB0:17::INSTR     VISA instrument resource
visaResponse                        VISA response string
error_status    32,48,128           Status bytes to check for errors
error_command   ERR?,EMG?,ERRX?     Commands to process error events
hold_bias       0.0                 Bias applied during hold time period
hold            0.5                 Hold time before first measurement, in seconds
delay           0.1                 Delay time
step_delay      0.2                 Step delay time


Certain measurement configuration parameters like hold, delay and step delay parameters would normally be set in the Instrument Options of the IC-CAP instrument driver, but because we have not configured an IC-CAP instrument driver, we will read these parameters from the Setup Variables instead.

# add variables for instrument options and other variables
polarity = MVar("POLARITY").get_val() 

# get setup variables



In our previous IC-CAP model file, the bias conditions for the gate sweep, drain, source and substrate values were stored in the Setup Variables table then read from table and assigned to local variables.  In this latest version we have removed these values from the SVars table and will define them in the _init Python transform, as shown below.


Note: You may need to change the SMU channel assignments ('drain', 'gate', 'source', 'substrate') to match the configuration of your instrument. For example, your Drain SMU Channel may be slot 5, not slot 1.


Exploring the _init transform


Select the Extract/Optimize tab and then select the _init transform.


New initialization code has been added to the _init transform relative to previous versions of the example mdl files. In this example, we will use functions provided by IC-CAP to query the settings of the Inputs from the user interface in the Measure/Simulate tab to set the measurement conditions for our quasi-static "Id vs. Vg" MOSFET measurement. 


idvg_quasi Init transform


The following Python local variables in our _init transform will be used to store the measurement parameters from the defined Inputs.

Variable Name   Description
vgstart         Gate sweep start voltage
vgstop          Gate sweep stop voltage
vgstep          Gate step size
vgpts           Gate points
igcompl         Gate current compliance
vdvalue         Drain voltage (constant)
idcompl         Drain current compliance
vsvalue         Source voltage (constant)
iscompl         Source current compliance
vbvalue         Bulk voltage (constant)
ibcompl         Bulk current compliance


We will use these variables the instrument specific SMU commands to programmatically control the quasi-static sweep. 


Setup Object and Methods


Instead of using the IC-CAP function call SVar(“Varname”).get_val(), we will be using the TableVar object provided by IC-CAP's Python environment.  Thanks to the iccap python module, we can programmatically define, manipulate and query DUTs, SetupsTransforms, Inputs and Outputs.  In order to access the TableVar object of the Input and query its values, we will need a reference to its parent Setup object.


Let’s define an object representing the idvg_quasi Setup by name. You will find these two statements in the _run transform.


s = Setup("/py_api_demo_5270/dc/idvg_quasi")
setupName = s.get_fullname()


We can now query this object for its properties (assuming debug = 1)


# query setup
if debug: print "fullname:",s.get_fullname()
if debug: print "name:", s.name
if debug: print "mytype:", s.mytype


Setup query response:

fullname: /py_api/demo/5270/dc/idvg_quasi

name: idvg_quasi

mytype: Setup


With a for loop, we can query the sweeps defined for the Setup.  


# query sweeps with order
if debug:
   for sweepid.range(1,2):
      inputobj = set.get_sweep(sweepid)
      if inputobj == None: break
      print "Sweep ", sweepid, s.get_fullname()

In this case, we have only a 1st order sweep.

Sweep query response:

Sweep 1 /py_api_demo_5270/dc/idvg_quasi


Now, I will show you how to query some of the other parent/child hierarchies so that you get an idea of the type of information that is available to your Python programs.


We can query the setup object for children objects in its hierarchy.


# query child objects and type
if debug:
   print "child objects of Setup:"
   for objchildtype in s.childtypetuple:
      print objchildtype
      for objchild in s.get_child_objects(objchildtype):
         print " ", objchild.name


Child object query response:

child objects of Setup:




































One may query any Setup for these properties and then assign them to local variables for use in your Python code.


Input/Output Objects


We will read the Input values from the IC-CAP TableVar objects and assign them to a Python string variable. Let's start with the Sweep parameters for the vg source.


vg = Input(setupName + "/vg")


The full statement will expand to Input("/py_api_demo_5270/dc/idvg_quasi/vg").  Like the Setup object,  the Input object also provides functions for returning information like full_name, name, and type.


# build full name for the sweep input
sweepName = vg.get_fullname()


Using the Input object vg, we set a variable sweepName for the fullname returned from the Input, we can read each of the vg Input's sweep TableVar parameters including: Compliance, Start, Stop, Step Size and # of Points.


igcompl = TableVar(sweepName + "/Compliance")
vgstart = TableVar(sweepName + "/Start")
vgstop = TableVar(sweepName + "/Stop")
vgstep = TableVar(sweepName + "/Step Size")
vgpts = TableVar(sweepName + "/# of Points")


We now have pointers to the following:




We can now query various properties of our newly created TableVar object.

# query TableVar
if debug: print "fullname :", igcompl.get_fullname()
if debug: print "name :", igcompl.name
if debug: print "mytype :", igcompl.mytype
if debug: print "value :", igcompl.get_val()
if debug: print

# query TableVar
if debug: print "fullname :", vgstart.get_fullname()
if debug: print "name :", vgstart.name
if debug: print "mytype :", vgstart.mytype
if debug: print "value :", vgstart.get_val()
if debug: print


With the debug flag enabled, we obtained the following results in the IC-CAP Output window:

full_name : /py_api_demo_5270/dc/idvg_quasi/vg/Compliance
name : Compliance
mytype : TableVar
value : 0.1

full_name : /py_api_demo_5270/dc/idvg_quasi/vg/Start

name : Start

mytype : TableVar

value : 0.0




Using the TableVarObject.get_val() method, we define local variables and cast the returned string to an appropriate float or integer types for later calculations.


# set gate sweep parameter values
vg_start = float(vgstart.get_val())
vg_stop = float(vgstop.get_val())
vg_step = float(vgstep.get_val())
ig_compl = float(igcompl.get_val())
vg_points = int(vgpts.get_val().split('.')[0])


The type or polarity (NMOS or PMOS) is read from the Model Variable Table as specified in the beginning of the _init transform variables presented above. If its value is PMOS, the values for the gate and drain biases are multiplied by -1, which will appropriately handle the device polarity. 


# get the device polarity from the model variable table
polarity = MVar("POLARITY").get_val()


We can use the value of polarity to invert the sign on Vgs  appropriately for the device type.


if polarity == "PMOS":
   vg_start *= -1
   vg_stop *= -1
   vg_step *= -1


Querying Constant Input Variable Properties


What if the input variable is not swept but is a constant? The Input vd is defined as a CON (constant source type) so the only available properties are the bias value and the compliance.


vd = Input(setupName + "/vd")


The input vd is queried from just like the vg sweep variable.


# build full name for the constant input
constName = vd.get_fullname()


Using the Input object vd we set a variable constName for the fullname returned from the Input, we can read each of the vd Input's TableVar parameters including: Compliance and Value.



idcompl = TableVar(constName + "/Compliance")
vdvalue = TableVar(constName + "/Value")


Again, we may query various properties of our TableVar object. A couple examples are provided as follows.


# query TableVar
if debug: print "fullname :", idcompl.get_fullname()
if debug: print "name :", idcompl.name
if debug: print "mytype :", idcompl.mytype
if debug: print "value :", idcompl.get_val()
if debug: print

# query TableVar
if debug: print "fullname :", vdvalue.get_fullname()
if debug: print "name :", vdvalue.name
if debug: print "mytype :", vdvalue.mytype
if debug: print "value :", vdvalue.get_val()
if debug: print


Executing the code statements above with the debug flag enabled will produce the following in the IC-CAP Output window:


full_name : /py_api_demo_5270/dc/idvg_quasi/vd/Compliance

name : Compliance

type : TableVar

value : 0.1


full_name : /py_api_demo_5270/dc/idvg_quasi/vd/Value

name : Value

mytype : TableVar

value : 3.0


Using the TableVarObject.get_val() method, we define local variables, having cast the returned string to the appropriate float or integer types for later calculations.

# set drain parameter values
id_compl = float(idcompl.get_val())
vd_value = float(vdvalue.get_val())


Again we can use the value of polarity to invert the sign on Vds appropriately for the device type.


if polarity == "PMOS":
   vd_value *= -1


A similar approach is implemented to query the constant type inputs vs and vb. 




With the this modified _init transform, we can now read the bias settings and compliance settings from the Measurement/Simulate tab for the idvg_quasi Setup.




To run this, we will not click the Measure button in Measure/Simulate tab, but instead navigate to the Extract/Optimize tab, select the _run transform and click the Execute button to perform the measurement.


Using these powerful IC-CAP objects and functions from the API, you can easily implement custom measurement and extraction routines to provide familiar usage modalities for your engineers who are familiar with the standard IC-CAP user interface.  I hope the information presented here provides some insight to the internal objects, functions and data types available to you through the Python environment within IC-CAP and will help you in implementing your own custom measurements.  More detailed information on all the information presented here can be found in the IC-CAP Python programming examples or the IC-CAP User's Manual.



IC-CAP 2018 user-manual and documentation

Example model file "py_api_demo.mdl" under Macros

Related Links