Previous - Up - Next

8.1   Script Support in CLI

8.1.1   Variables
The Simics command line has support for string and integer variables. Variables are always prefixed with the $ character. Variables that are not set have a value of 0.

simics> $foo = "some text"
simics> $foo
some text
simics> echo $not_used_before

There is also support for indexed variables (arrays). This is useful in loops for example.

simics> $foo[0] = 10
simics> $foo[1] = 20
simics> echo $foo[0] + $foo[1]

CLI also has support for local variables, described later in this chapter.

8.1.2   Command Return Values
The return value of a command is printed on the console, unless it is used as argument to some other command. Parenthesis () are used to group a command with arguments together, allowing the return value to be used as argument. The return value can also be used as name-space in another command. Variables can be used in the same way.

simics> $address = 0
simics> set $address 20
simics> echo "The Value at address " + $address + " is " + (get $address)
The Value at address 0 is 20

simics> $id = 0
simics> ("cpu" + $id).print-time
processor                 steps             cycles    time [s]
cpu0                          0                  0         0.0

simics> $cpu = cpu0
simics> $cpu.print-time
processor                 steps             cycles    time [s]
cpu0                          0                  0         0.0

Parenthesis can also be used to enter a multi-line command, making it easier to read scripts with nested command invocations. In the text console, the prompt will change to ....... for code spanning more than one line.

simics> (echo 10
.......       + (20 - 5)
.......       + (max 4 7))

8.1.3   Control Flow Commands
The script support in CLI has support for standard if, else and while statements.
simics> $value = 10
simics> if $value > 5 { echo "Larger than five!" }
Larger than five!
The if statement has a return value:
simics> $num_cpus = 2
simics> (if $num_cpus > 1 { "multi" } else { "single" }) + "-pro"

Note: Multi-line if-else statements must have } else { on the same line.

It is also possible to have else followed by another if statement.

simics> if $b == 1 {
.......     echo 10
....... } else if $b == 0 {
.......     echo 20
....... } else {
.......     echo 30
....... }

Loops can be written with the while command.

simics> $loop = 3
simics> while $loop {
.......     echo $loop
.......     $loop -= 1
....... }

In if and while statements, it can be useful to have variables that are local to the scope and thus do not collide with the names of global variables. By adding local before the first assignment of a variable, the variable is made local.

simics> $global = 10
simics> if 1 > 0 {
.......     local $global = 20
.......     echo $global
....... }
....... echo $global
8.1.4   Integer Conversion
In some cases it is useful to interpret an integer as a signed value of a specific bit size, for example when reading four bytes from memory that should be interpreted as a signed 32 bit integer. The signed8, signed16, ..., signed64 commands can be used in to perform the conversion. argument.
simics> phys_mem.set 0 0xffffffff 4
simics> phys_mem.get 0 4
simics> signed32 (phys_mem.get 0 4)
8.1.5   Accessing Configuration Attributes
Simics configuration attributes that are of string and integer type can be accessed directly from CLI using the -> operator.
simics> echo "Will switch cpu every " + (sim->cpu_switch_time) + " cycles"
Will switch cpu every 1000000 cycles

8.1.6   Script Branches   Introduction to Script Branches
Script branches allow the user to write sequences of CLI commands that can wait for Simics haps at anytime without breaking the sequential flow of commands. This is typically used to avoid breaking a script into many small sections, each installed as a hap callback written in Python.

A simple example from a Simics script:

script-branch {
    echo "This is a script branch test - going to sleep."
    cpu0.wait-for-step 10
    echo "Processor registers after 10 steps:"

The example above will execute the first echo command at once, and then go to sleep waiting until the first 10 instructions (steps) have run. When the step counter for cpu0 has reached 10, the branch will wake up and run the next two commands, echo and pregs.

Some commands can not be run while Simics is executing. One example is the write-configuration command. To issue such commands from a script branch, it is possible to stop the execution, issue the command and then resume the simulation. The following is an example that writes a checkpoint when the simulation reaches a login prompt, and then continues running. It assumes that a text-console called con0 is used.

script-branch {
    con0.wait-for-string login
    write-configuration login.conf
}   Waiting for Haps in Script Branches
A common use of script branches is to wait for a hap to occur before continuing the script execution. Most haps have some data associated with them, such as the exception number for the Core_Exception hap used in the example below. This data can be accessed from CLI by telling the wait-for-hap command to save it into a named indexed variable with local scope. See the hap documentation for information on what data is associated with each hap type.
script-branch {
    wait-for-hap Core_Exception info
    echo "Processor " + $info[0] + " got exception " + $info[1]
}   How Script Branches Work

When a script branch is started (using script-branch), it begins executing immediately, and runs until a wait-for-, command is issued. Execution is then resumed in the main script; i.e., there is never any concurrent activity. When a hap, or some other activity, occurs that a script branch is waiting for, the branch continues executing once the currently simulated instruction is ready.

Note: Since only one branch can be active at once, any callback to Python from Simics will execute in the currently active branch, i.e., if a branch installs a callback, it is most likely that it will be called when the main branch is active.   Script Branch Commands
The following is a list of the commands related to script branches.

Create a new script branch and start it.
List all existing, but suspended, branches.
Interrupt a script-branch, causing it to exit.
wait-for-hap hap [object] [index|range-start] [range-end]
Suspend branch waiting for a hap to occur.
wait-for-variable variable
Suspend branch until a specified CLI variable is modified. This can be used for synchronization between script branches.
<processor>.wait-for-cycle cycle
Suspend branch until the specified cycle on the processor has been reached.
<processor>.wait-for-step step
Suspend branch until the specified step on the processor has been reached.
<text-console>.wait-for-string string
Suspend branch until string is printed on the text console.   Variables in Script Branches
Variable references in CLI are evaluated when accessed. This is important to remember when writing script branches, since some commands are executed when the branch has been suspended, and variables may have been changed. To make sure that CLI variables in script branches are untouched by other scripts, they should be made local.

The following example

script-branch {
    $foo = 20
    cpu0.wait-for-step 10
    echo "foo is " + $foo
$foo = 15
will produce the output foo is 15 while the following script will print foo is 20.
script-branch {
    local $foo = 20
    cpu0.wait-for-step 10
    echo "foo is " + $foo
$foo = 15
run   Canceling Script Branches
It is possible to cancel a suspended script branch by interrupting it using the interrupt-script-branch command. Each branch has an ID associated that can be found using list-script-branches, and that is returned by the script-branch command.
$id = (script-branch {
    wait-for-variable trigger


simics> interrupt-script-branch $id
Command 'wait-for-variable' interrupted.
Script branch 1 interrupted.   Script Branch Limitations

There are some limitations to script branches. The first two in the list are enforced by Simics:

Previous - Up - Next