Script branches allow the user to write sequences of CLI commands that can be postponed, waiting for things to happen in the simulator, without breaking the sequential flow of commands. This is typically used to avoid breaking a script into many small sections, each run as a callback using Python.
A simple example of a script branch:
script-branch "script branch description (optional)" { echo "This is a script branch test - going to sleep." board.mb.cpu0.core[0][0].wait-for-step 10 echo "Processor registers after 10 steps:" board.mb.cpu0.core[0][0].print-processor-registers }
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 the processor has reached 10, the branch will wake up and run the next two commands, echo and print-processor-registers.
A big difference between script branches and the main script is that the main script (also called main branch) may be interrupted by the user pressing the stop button or typing Ctrl-C. The script branches are unaffected by such actions and can exist in the background, coexisting with any interactive command line use.
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 some activity occurs that a script branch is waiting for, the branch continues executing once the currently simulated instruction is ready.
The following is a list of the commands related to script branches.
-absolute
is
specified, the branch will instead be suspended until the processor
reaches the specified cycle in the simulation. If -reverse
or
-always is specified, this command is valid when the
simulation is running in reverse.-absolute
is
specified, the branch will instead be suspended until the processor
reaches the specified step in the simulation. If -reverse or
-always is specified, this command is valid when the
simulation is running in reverse.-absolute
is specified, the branch will instead be suspended until the processor
reaches the specified time in the simulation. If -reverse
or
-always is specified, this command is valid when the
simulation is running in reverse.int_register
interface is read.
Only registers that are catchable can be waited on. If -reverse or
-always is specified, this command is valid when the
simulation is running in reverse.int_register
interface is written.
Only registers that catchable can be waited on. If -reverse or
-always is specified, this command is valid when the
simulation is running in reverse.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 "sample script branch" { $foo = 20 board.mb.cpu0.core[0][0].wait-for-step 10 echo "foo is " + $foo } $foo = 15 run
will produce the output foo is 15
while the following script will
print foo is 20
.
script-branch "sample script branch" { local $foo = 20 board.mb.cpu0.core[0][0].wait-for-step 10 echo "foo is " + $foo } $foo = 15 run
The script environment is used to control the simulated system and is not reversed itself when the simulation runs backwards. As a result, it is possible to write scripts that run the simulation both forward and backwards.
By default, the wait-for- script branch commands only wait for events to happen when the simulation is running forward and silently ignore them when reversing. The -reverse and -always flags, provided by most wait-for- commands, can be used to wait for events occurring in only the reverse direction or in both.
Large system configurations can be split up over several cells where each cell runs in its own host thread to speed up simulation. Care must be taken when writing scripts in such sessions. If the simulation is stopped or paused, for example by a breakpoint, other cells than the one where the breakpoint occurred may be ahead or behind in simulated time. The difference in time between cells is limited by the minimum latency setting. The time where cells are stopped may also differ between runs of the same setup. To ensure deterministic behavior, a script stopping a simulation as result of some event should only access the cell where the event occurred. If the script needs to access the full configuration, i.e. also objects in other cells, then all cells have to be synchronized in time. The wait-for-global-time and wait-for-global-sync commands can be used to run until a point where all cells have synchronized.
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 "sample script branch" { wait-for-breakpoint $bp }) ... simics> interrupt-script-branch $id Command 'wait-for-breakpoint' interrupted. Script branch 1 interrupted.
There are a few things related to script branches that are discouraged or not allowed:
text_console_cmp0.con
is used.
script-branch "create checkpoint" { board.console.con.bp-wait-for-string login stop write-configuration login.conf run }
This is one of few exceptions to the rule that script branches should not start or stop the simulation.