A Tutorial

In this topic:

Example 1: Hello World!

Any one who has learnt the 'C' programming language will be familiar with the now celebrated "Hello World" program - possibly the simplest program that can be written. Here we will write and execute a SIMetrix "Hello World" script.

The script is simple:
echo "Hello World!"
To execute and run this script start by selecting the menu File > New > Script this will open the in built script editor. Type:
echo "Hello World!"
Now save the text to a file called hello.sxscr. To execute the script, click on the Run toolbar button or type "hello" at the command line. You should see the message:
Hello World!
Appear in the message window. A script is executed by typing its filename at the command line. If the file has the extension .sxscr the extension may be omitted. You can also assign a key or menu to execute a script. Type at the command line:
DefKey F6 HELLO
Now press the F6 key. The message should appear again. For information on defining menus see User Defined Key and Menu Definitions.

Example 2: An Introduction to Loops

This example adds up all the elements in a vector (or array). To create a vector we will run a simulation on one of the example circuits. The whole process will be put into a script except opening the schematic which we will do manually. (But this can be done from a script as well).

To start with, open the example circuit General/AMP.sxsch. Make sure it is selected to run a transient analysis.

Now select File > New Script. This will open a text editor with the current directory set to the SCRIPT. Type in the following:
Netlist design.net
Run design.net

let sum = 0
for idx=0 to length(vout)-1
let sum = sum + vout[idx]
next idx

echo The sum of all values in vout is {sum}
Save the script to the file name SUM.sxscr. Now type SUM at the command line. A simulation will run and the message:
The sum of all values in vout is -6.1663737561
Should appear in the message window. The exact value given may be different if you have modified the circuit or set up different model libraries. This script introduces four new concepts:
  1. For loops
  2. Braced substitutions ({sum} in the last line)
  3. Vectors (or arrays)
  4. Accessing simulation data
Let's go through this script line by line.

The first two lines carry out the simulation and in fact something similar is done each time a simulation is run using the menu or F9 key. Netlist design.net generates a netlist of the circuit and saves it in a file called design.net. Then Run design.net runs the simulation on the netlist design.net.

The line
let sum = 0
creates and initialises the variable sum which will ultimately hold the final result. The next three lines is a simple for statement. The variable idx is incremented by one each time around the loop starting at zero and ending at length(vout)-1. vout is a variable - actually a vector - which was generated by the simulator and holds the simulated values of the voltage on the VOUT net. This net is marked with a terminal symbol. length(vout) returns the number of elements in vout (1 is subtracted because idx starts at 0). In the line:
let sum = sum + vout[idx]
vout[idx] is an indexed expression which returns element number idx of the vector vout. sum is of course the accumulative total. The final line:
echo The sum of all values in vout is {sum}
contains the braced substitution {sum}. sum is evaluated and the result replaces expression and the braces. See Braced Substitutions for more information.

Example 3: Cross Probing

The standard plotting menus, plot one curve at a time. Here a script is described which repeatedly plots cross-probed curves until the right mouse key is clicked.
let start=1
do while probe()
if start then
plot {netname()}
else
curve {netname()}
endif
let start=0
probe
loop
This script introduces if statements, while statements, functions and the features that allow voltage cross-probing, namely the functions NetName and Probe and the command Probe.
The script repeatedly executes the statements between do while and loop until the probe() function returns 0 (=FALSE). The Probe function changes the cursor shape to an oscilloscope probe but doesn't return until the user presses the left or right mouse key. If the user presses the left key the function returns 1 (=TRUE) and execution continues to the statements inside the loop. If the user presses the right key, the Probe function returns 0 (=FALSE) and the loop is completed and the script terminates. In the next 5 lines:
if start then
plot {netname()}
else
curve {netname()}
endif
the first time around the loop start is equal to 1 and the Plot command is executed. This creates a new graph. Subsequently, start is set to zero and the Curve command is executed which adds new curves to the graph already created.

The argument to the Plot and Curve commands, {netname()} is a braced substitution which we saw in the previous example. The NetName function returns a string which is the name of the nearest net to the cursor at the time the function is executed. The function is executed soon after the user presses the left mouse key so the string returned by NetName will be the net the user is pointing to. The value returned by NetName is a string, but the Plot command requires a numeric expression. By putting netname() in braces the result of evaluating it is substituted as if it were typed in. So if the user pointed at a the net named VOUT, netname() would return 'VOUT' and that would be placed after plot or curve i.e. plot vout would be executed.

The final command
probe
calls the Probe command. This does the same as the Probe function but doesn't return a result. It is needed because both the Probe function and the Probe command return on both up and down clicks of the mouse. The second occurrence of Probe simply waits for the up click of the mouse button.

There are four other functions which are used for cross-probing. These are GetNearestNet, NearestInst, PinName and Branch.

Just one final note. plot {netname()} won't work for vectors whose name contains certain characters such as arithmetic characters e.g. '+' and '-'. These characters get interpreted as their literal meaning and an error usually results. To plot vectors whose names contain these characters, you should use the Vec() function and supply the vector name as a string. E.g.
plot Vec(netname())
Note that there are no curly braces used here. This is because the Vec() function returns a numeric vector containing the actual data to be plotted. The NetName function returns the name of the vector not its actual data.

Example 4: Making a Parts List

This script example displays a list of components in the currently selected schematic with their references and values in the message window.
* mk_bom.txt Display parts list in message window
if NOT SelSchem() then
echo There are no schematics open
exit all
endif

let refs = PropValues('ref', 'ref')

for idx=0 to length(refs)-1

let val = PropValues('value', 'ref', refs[idx])
* check for duplicate ref
if length(val)==1 then
echo {refs[idx]} {val}
else
echo Duplicate reference {refs[idx]}. Ignoring
endif
next idx
The first line:
* do_bom.txt Display parts list in message window
is a comment. Any line beginning with a '*' will be ignored.
The next line:
if NOT SelSchem() then
is the start of an if statement. SelSchem() is a function which returns 1 if there are schematics open and 0 if there are not. if NOT SelSchem() then means 'if there are no schematics open'. This is an initial check that the user has actually opened a schematic.
If there are no schematic open the lines:
echo There are no schematics open
exit all
will be executed. The first line calls the echo command. This echoes to the message window all subsequent text on the same line. The second line is an exit statement. In this case it causes execution to abort and the rest of the script will be ignored.
The next line
endif
terminates the if statement. For every if there must be a matching endif or end if.
Normally, of course, we hope the user has opened a schematic and the remainder of the script will be executed. The next line
let refs = PropValues('ref', 'ref')
calls the let command. This expects an assignment expression which it evaluates. In this case it assigns refs with the result of the a call to the function PropValues. In this example it returns the component reference for all instances (i.e. symbols) on the schematic that have one.
The next line
for idx=0 to length(refs)-1
starts a for loop. The block of statements between this line and the matching next will be repeated with values of idx incrementing by 1 each time around the loop until idx reaches length(refs)-1.The length function returns the number of elements in the refs variable so the loop is repeated for all elements in refs.
The next line is
let val = PropValues('value', 'ref', refs[idx])
This calls the PropValues function again. This time it returns the value of the value property for any instance with the property ref which has the value refs[idx]. Assuming the schematic has been annotated (unique references assigned to all components) the result of this call should be a single value which is assigned to val.
The next 2 lines
if length(val)==1 then
echo {refs[idx]} {val}
The if statement checks that val has length one which means that the reference is unique. If it is then the Echo command is called which displays on the message window all the text following it. In this instance the echo command is followed by two braced substitutions. A braced substitution is an expression enclosed in curly braces '{' and '}'. The braces and the enclosed expression are replaced by the result of evaluating the expression as if it had been typed in. Braced substitutions are a very important feature of the SIMetrix scripting language. Here the result is the component's reference and value are displayed in the message window.
The last part of the for loop is:
else
echo Duplicate reference {refs[idx]}. Ignoring
endif
This is executed if the if expression length(val)==1 is false. This means that there is more than one component with that component reference. A message is output saying that it is being ignored. The final line
next idx
terminates the for loop.