Getting Started

1 Introduction

This document provides an introduction to the Intel Simics product and some of its features. Intel Simics is a full-system simulator mainly targeting software development and analysis. To do so, it provides hardware and software inspection, dynamic system configuration, hardware modelling tools, scripting, and a rich set of other features. Unlike many other virtual machine products, the Intel Simics simulator does not focus on being a hardware replacement, although it can be used in that way.

The introduction in this document is in the form of a few short step-by-step tutorials.

1.1 Conventions

1.2 Intel Simics Terminology

This section presents the terminology used throughout Intel Simics documentation.

To simulate a target machine, a configuration must be created. A configuration consists of objects, object hierarchy, properties, and connections between objects.

The default way of creating a configuration is to load a target. For legacy reasons, it is also possible to create configurations by running CLI or Python scripts.

When creating a configuration for a specific target machine, it is often possible to customize properties of the target machine. For targets, the configurable parameters are called target parameters. (see Simics User's Guide).

A simulation session can contain multiple target machines, for example when simulating a network.

For interaction with the target system, the simulator can show graphics consoles and serial consoles.

Figure 1. This is an illustration of some of the key concepts

2 Installation

These are installation steps that should have been followed before running any of the tutorials.

  1. The Intel Simics base package (package number 1000) has been installed.

  2. The QSP-x86 package (package number 2096) has been installed. This package contains a simple x86 system with the qsp-x86/firststeps target which will be used in many examples.

  3. A project directory has been created (referred to as [project] below) which has the QSP-x86 package as an add-on package.

  4. The Grml live full ISO image from the stable 2025.05 release named grml-full-2025.05-amd64.iso has been downloaded and placed in the project directory.

    The direct download link for this image is:
    https://download.grml.org/grml-full-2025.05-amd64.iso. If the download speed is slow, it is also possible to download grml-full-2025.05-amd64.iso from one of the mirrors

For information on how to install the simulator and create a project, see the Installation Guide.

Some tutorials require that the QSP Clear Linux (#4094) package is installed and available as an add-on package in the project. If you don't have this package, reading the tutorials and referenced manuals will still provide an overview on the subject.

3 Launching and Exiting

This section describes how to launch and exit the simulator.

This tutorial assumes that the user has followed the installation steps in the installation section.

The screenshots below were taken on Windows, but the Linux version of the Intel Simics simulator behaves similarly.

3.1 Launch the simulator

  1. First, let’s get a command prompt on the host machine.

    • On a Windows host, use one of the following alternatives:
      • Use the start menu and launch Command Prompt.
      • If Windows Terminal is installed, launch this and start open an instance of the Command Prompt profile.
      • Press the Win + r keys and enter cmd in the popped-up window.
    • On a Linux host, refer to the documentation of your Linux distribution about the instructions how to get access to command prompt.
  2. Once command prompt window is available, navigate to the project directory.

  3. To launch the simulator, and to get its command prompt just run the simics.bat batch file (on Linux, the simics shell script is to be used instead by entering the ./simics command).

    Simics has now been launched.

  4. With the CLI available, we can try running the command list-packages, which lists the packages available to the current project:

There are also launch options available to customize what happens when launching the simulator.

3.2 Exit the Simulator

To quit the simulator just enter the quit command:

3.3 Launch options

Simics has a couple launch options that can be listed with the --help flag:

c:\simics\project>simics.bat --help

Usage: simics [options] [<file>|<target> ...] [--preset <name|file> ...] [<param>=<value> ...]
Common options:

  --batch-mode                quit on error or when returning to prompt
  -e, --execute <command>     execute a CLI command
  -h, --help                  print this help or list all script parameters if
                              used with a file. All other options are ignored
  -l, --list-targets          list available targets
...

These are some of more commonly used options:

3.4 Summary

To sum up, in this section we launched the simulator, tried out a command and exited the simulator.

4 Command Line Interface (CLI)

This section focuses on some practical information related to the use of the CLI. Particularly, the following information is presented:

This section doesn’t cover all available CLI commands, but here are some examples of what can be done with commands:

This tutorial assumes that the user has followed the installation steps in the installation section and knows how to launch the simulator.

4.1 Introduction

As a short introduction to the functionality of the CLI:

4.1.1 CLI Prompts

When launching the simulator (simics.bat on Windows or ./simics on Linux), the CLI is started automatically. The CLI has several prompts, but here are most important.

4.1.2 Keyboard Shortcuts

These are some shortcuts that may be useful:

4.2 Command Line Completion

To simplify interactive use, the CLI implements command line completion, also known as tab completion. The CLI can complete commands, arguments, file names, and some other entities. Let’s see how command line completion works for the load-target command:

We have now used command line completion to load the qsp/firststeps target.

4.3 The help command

The simulator documentation can be accessed in the CLI with the help command. The help command provides access to the documentation for:

To try the command, enter the following command to see the documentation for the load-target command:

simics> help load-target
Command load-target

   Synopsis
      load-target "target" ["namespace"] ["preset"|presets|"preset_yml"]
...

To get the documentation for any command just run the help command specifying the command you are interested in:

simics> help <command-of-interest>

More information on the help command can be obtained by reading the documentation for the help command itself:

simics> help help
Command help

   Alias
      h, man

   Synopsis
      help ["topic"]
...

The help-search command allows to search the documentation for a particular string. Here is a sample usage of the help-search command:

simics> help-search python
The text 'python' appears in the documentation
for the following items:

Command        %
Command        <bp-manager.log>.break
Command        <bp-manager.log>.run-until
Command        <bp-manager.log>.trace
...

4.4 Further Reading

More information about the CLI can be found in Simics User's Guide, section The Command Line Interface.

5 Running the Simulator

This section describes how to:

This tutorial assumes that the user has followed the installation steps in the installation section.

The screenshots below were taken on Windows, but the Linux version of the Intel Simics simulator behaves similarly.

While this section deals with targets, there is also a legacy way of creating target machines using scripts described here.

5.1 Create a Target Machine

Let’s create a target machine by loading the qsp-x86/firststeps target.

  1. Launch the simulator.

  2. Before loading the qsp-x86/firststeps target, let us first verify that this target is available in our project. To list available targets, run list-targets and verify that you see the target qsp-x86/firststeps in the listing:

    It is also possible to list targets without starting an interactive session, by starting the simulator with the -l argument.

    If you don't see qsp-x86/firststeps, you need to make sure that you have installed the QSP-x86 (#2096), and that it is available in the project as an add-on package. Read more about installing the simulator in the installation section.

  3. Now that we have verified that the qsp-x86/firststeps target is available, we will load it:

    simics> load-target target = "qsp-x86/firststeps"
    "firststeps"
    
  4. A few new windows have popped up after a target machine has been created. Initially the consoles are blank, but the below screenshots are taken from a later time in the simulation to show something more interesting.

    • board.mb.sb.com[0] - serial console - Figure 2
      a text terminal window connected to a serial port of the target machine
    • board.mb.gpu.vga - graphics console - Figure 3
      a graphical display window connected to a graphical device of the target machine
    • Target Consoles - Figure 4
      a utility window which allows showing or hiding the target consoles
    Figure 2. A text terminal window connected to a serial port of the target machine
    Figure 3. A graphical display window connected to a graphical device of the target machine
    Figure 4. A target console control window:

5.2 Run and Stop the Simulation

One of the ways to start the simulation of the newly created target machine is to use the run command.

  1. Start the simulation with the run command:

    simics> run
    running> 
    
  2. There may be messages printed in the CLI window:

    These messages are coming from models which, as messages report, may not simulate certain features. Many target models use a pragmatic approach and don’t simulate features which are not relevant for simulated machines, for example, thermal control. So, the messages are usually harmless.

  3. As simulation progresses, the target machine will boot Linux operating system (this can take up to several minutes):

  4. The login to the system is done automatically. After the login, one can interact with the operating system running on the target machine by running commands at the text console window. Here is a sample session when pwd and uname -a Linux commands were executed on the simulated machine after the login:

  5. One can stop simulation, thus pausing a target machine, by running the stop command:

    running> stop
    simics>
    
  6. The target machine is paused now. But it can be resumed by entering the run command:

    simics> run
    running>
    

To see other ways of starting and stopping the simulator, run help with the Execution category:

simics> help Execution
...
run              start execution
run-cycles       start execution
run-seconds      execute for seconds
...

For further information, see the help command section.

6 Hardware Inspection

This section contains some examples of how to inspect processors and devices, when running the qsp-x86/firststeps target machine.

When retrieving a register value for inspection or use in further code, it is better to use one of the commands designed for that purpose:

The command names have the following meanings:

simics> get-device-reg board.mb.nb.bridge.bank.pcie_config.device_id
0x3400
simics> get-device-offset board.mb.nb.bridge.bank.pcie_config offset = 2 size = 2
0x3400

To sum up, we have shown a few simple ways in which the hardware can be inspected. One important point is that the inspection is non-intrusive, any software running on the target machine cannot notice anything of our inspection.

7 Documentation and Help

7.1 Documentation

To access the documentation run the documentation.bat (documentation on Linux) script in your project. The script will index all the documents for the packages associated with your project, and then it will open the documentation in your web browser.

7.2 The Help System

The CLI provides a few commands that assist in exploring large simulated systems, and for exploring the CLI.

Such a command is help. Use it to receive help about almost anything in the simulator that has a name, in particular the commands you have seen in this document, and which you will see in the rest of the Intel Simics documentation.

Another important command is help-search, also known as apropos. It can be used to search the reference documentation for a particular text string.

Both help and apropos limit their search to documentation about everything that is currently loaded in the simulator. This means it is usually best to run them after you have loaded the target system you want to explore.

A simulation in built up by objects. Objects can provide namespaced commands, that is, commands on the format <object-name>.<command-name>. Different kinds of objects provides different namespaced commands. The namespaced command is either registered on an interface or on a class.

Sometimes you know of an interesting namespaced command you want to use, for example the input command, but you don't know which objects provide the command. To find those objects, first use the apropos command to find which kinds of objects that provide the command:

simics> apropos input
The text 'input' appears in the documentation
for the following items:

Command        <bp-manager.con-string>.wait-then-write
Command        <graphcon>.grab-setup
Command        <graphcon>.input
Command        <graphcon>.input-file
Command        <os_awareness>.find
Command        <recorder>.playback-start
Command        <recorder>.recorder-start
Command        <recorder>.recorder-stop
Command        <textcon>.input
...

As an alternative to apropos, which searches all documentation for loaded modules, we can limit the result to only commands by using list-commands:

simics> list-commands substr = input
┌─────────────────────┬───────────────────────────┐
│       Command       │     Short Description     │
├─────────────────────┼───────────────────────────┤
│<graphcon>.input     │send string to a console   │
│<graphcon>.input-file│input a file into a console│
│<textcon>.input      │send input to a console    │
│<textcon>.input-file │input a file into a console│
└─────────────────────┴───────────────────────────┘

The input command is provided by graphcon and textcon. Let's focus on textcon. First we determine if textcon is a interface or a class.

simics> list-interfaces substr = textcon
No match for substr 'textcon'  
simics> list-classes substr = textcon
The following classes are available:
┌───────┬─────────────────┐
│ Class │Short description│
├───────┼─────────────────┤
│textcon│text console     │
└───────┴─────────────────┘

The textcon clearly references a class. Now we can use the list-objects command to find all objects of the textcon class.

simics> list-objects class = textcon
┌────────────────────┬─────────┐
│       Object       │  Class  │
├────────────────────┼─────────┤
│board.serconsole.con│<textcon>│
└────────────────────┴─────────┘

Evidently, the only textcon object in the target system is board.serconsole.con.

From the result of apropos and list-objects we now know that there is a command board.serconsole.con.input:

simics> help board.serconsole.con.input
Command <textcon>.input

   Synopsis
      <textcon>.input "string" [-e]

   Description
      Send string to the text console.
...

The list-objects command, and many other commands can handle the namespace hierarchy of objects. For example, if we know that we were looking for a textcon class hierarchically under board, we would use the namespace argument.

simics> list-objects namespace = board class = textcon
┌────────────────────┬─────────┐
│       Object       │  Class  │
├────────────────────┼─────────┤
│board.serconsole.con│<textcon>│
└────────────────────┴─────────┘

These simple commands go a long way when you want to explore the Intel Simics simulator.

8 Tutorials

These tutorials show how to perform common tasks in the simulator. In the tutorials We use the example target system qsp-x86/firststeps, which is a simple x86 based system running Grml Linux.

8.1 Customizing Targets

In the running the simulator section, we loaded a target which created a configuration with default settings. It is also possible to customize the properties of target machines by setting target parameters.

In this section we demonstrate how to:

8.1.1 Discovering Target Parameters

This section describes how to discover target parameters available for a specific target, in this case the qsp-x86/firststeps target. These are some of possible methods to list target parameters:

8.1.1.1 Discovery using Command Line Completion

To discover available parameters via command line completion, press the tab key twice after entering load-target target = qsp-x86/firststeps:

simics> load-target target = qsp-x86/firststeps <TAB><TAB>
machine:hardware:apic_bus:class =
machine:hardware:consoles:con0:bg_color =
machine:hardware:consoles:con0:create =
machine:hardware:consoles:con0:fg_color =
machine:hardware:consoles:con0:show =

This will list the available target parameters, which is useful for overview and as a convenience when setting parameters.

8.1.1.2 Discovery using the Help System

Another way to list target parameters, and also to show type, description and default value, is to use the help command with target: as prefix:

simics> help "target:qsp-x86/firststeps"
┌───────────────────────────────┬────┬──────────────────────────────┬──────────────────────────────┐
│Name                           │Type│Description                   │Default                       │
├───────────────────────────────┼────┼──────────────────────────────┼──────────────────────────────┤
│machine:hardware:memory_megs   │int │Amount of RAM in the machine, │8192                          │
│                               │    │in MiB. The highest supported │                              │
│                               │    │value is 65536 (64 GiB). More │                              │
│                               │    │than 64 GiB is not supported  │                              │
│                               │    │since the x86QSP1 processor is│                              │
│                               │    │limited to a 36-bit physical  │                              │
│                               │    │address space.                │                              │
...

8.1.1.3 Discovery using params.help

The object params has a help command, which can provide information on targets.

simics> params.help target = "qsp-x86/firststeps"
┌───────────────────────────────┬────┬──────────────────────────────┬──────────────────────────────┐
│Name                           │Type│Description                   │Default                       │
├───────────────────────────────┼────┼──────────────────────────────┼──────────────────────────────┤
│machine:hardware:memory_megs   │int │Amount of RAM in the machine, │8192                          │
│                               │    │in MiB. The highest supported │                              │
│                               │    │value is 65536 (64 GiB). More │                              │
│                               │    │than 64 GiB is not supported  │                              │
│                               │    │since the x86QSP1 processor is│                              │
│                               │    │limited to a 36-bit physical  │                              │
│                               │    │address space.                │                              │

To see a complete description of params.help, type help params.help.

8.1.2 Setting Target Parameters

Let’s create a target machine with 4 cores per physical processor by setting the num_cores parameter to 4. To do that please run the following command:

simics> load-target "qsp-x86/firststeps" machine:hardware:processor:num_cores = 4

To verify that the target indeed has 4 cores, run the list-processors command:

simics> list-processors
┌────────────────────────┬─┬─────────┬────────┐
│        CPU Name        │ │CPU Class│  Freq  │
├────────────────────────┼─┼─────────┼────────┤
│board.mb.cpu0.core[0][0]│*│x86QSP1  │2.00 GHz│
│board.mb.cpu0.core[1][0]│ │x86QSP1  │2.00 GHz│
│board.mb.cpu0.core[2][0]│ │x86QSP1  │2.00 GHz│
│board.mb.cpu0.core[3][0]│ │x86QSP1  │2.00 GHz│
└────────────────────────┴─┴─────────┴────────┘

It is also possible to create a file with customized values of target parameters in a preset file. This is described in Simics User's Guide.

8.2 Logging and Tracing

8.2.1 Logging

Intel Simics hardware models generally output log messages for various kinds of events. The simulator's log system offers a very powerful system for configuring which log messages to see - from which objects, at which level. The result is often large volumes of output. That output can be configured and sent to files for later inspection, as well as used in scripts to stop the simulation, or take other actions when a log message appears.

Here we will show some logging examples when running the qsp-x86/firststeps target machine.

To send all log outputs to a file, use log-setup logfile=<filename>. To overwrite an existing file, the -overwrite flag must be given. To stop output, use the command log-setup -no-log-file.

8.2.2 Tracing

Tracing is a way to observe what is going on during the simulation. The Intel Simics simulator has a Breakpoint Manager that includes functionality for tracing various types of events. This means that messages (in fact, log messages) are printed when an event of the specified occurs. Such a sequence of messages is what is here is known as a trace.

Here we will show some tracing examples.

Several other types of events can also be traced, such as target console string output and hits at specific source code lines.

8.3 Checkpoints (on-disk)

The Intel Simics simulator allows saving the simulation state to disk, thus, the state of all target machines for later use. We call a saved state a checkpoint. Other simulators may refer to a saved state as a snapshot. In Simics a snapshot is also a saved state, but this only exists in-memory during a simulator session.

In this section:

Creating a checkpoint:

  1. launch the simulator and load the qsp-x86/firststeps target:

    simics> load-target qsp-x86/firststeps
    
  2. run the simulation until Linux is booted:

    simics> run
    

  3. stop simulation:

    running> stop
    simics>
    
  4. create a checkpoint by running the write-configuration CLI command and specifying a destination where to store a checkpoint:

    simics> write-configuration target-booted.ckpt
    
  5. quit the simulator:

    simics> quit
    

The target-booted.ckpt directory created on step 5 above contains saved simulation state.

Restoring from a checkpoint:

  1. launch the simulator

  2. restore the checkpoint state with the following command:

    simics> read-configuration target-booted.ckpt
    

  3. the simulation state from the target-booted.ckpt checkpoint has now been restored. We can see a text terminal window of the target machine with Linux prompt. We can resume simulation with the run command:

    simics> run
    running>
    

Useful information about checkpoints can be found in the documentation of the write-configuration and read-configuration commands (the documentation can be obtained from the CLI by running the help command like this: help write-configuration).

8.4 Snapshots (in-memory)

In addition to checkpoints, the Intel Simics simulator can save the state of simulation in memory. We refer to such saved states as snapshots. Snapshots are not preserved after one quits the simulator. Once snapshots have been taken it is possible to jump between them.

In this section:

Creation and use of snapshots:

  1. load the qsp-x86/firststeps target using the load-target command:

    simics> load-target qsp-x86/firststeps
    
  2. start the created target machine:

    simics> run
    running>
    
  3. wait until Linux has booted. When Linux has booted, a text terminal window connected to a serial port of the target machine will look like this:

  1. stop simulation:

    running> stop
    simics>
    
  2. take a snapshot by running the take-snapshot command and specifying a name for the snapshot:

    simics> take-snapshot booted
    

    where "booted" is a name we picked for a snapshot.

  3. resume simulation:

    simics> run
    running>
    
  4. do some changes to the target machine. As an example of such changes, the screenshot below shows how to identify where the cat utility is located, delete it and check that it cannot be found after it has been deleted:

  5. stop simulation:

    running> stop
    simics>
    
  6. restore the simulation state to the one which was saved on step 4:

    simics> restore-snapshot booted
    

    where restore-snapshots is a command to restore the simulation state from a snapshot, and "booted" is the name which we gave to the bookmark created on the step 4.

  7. the text terminal of the simulated machine looks now like it did before we deleted cat utility on step 6:

What will happen now if we will run the simulation after we restored the state from the snapshot? By default, the simulation will just resume from the state of the snapshot. The input and modifications done in step 7 will not occur.

  1. resume simulation by executing the run command and observe on the text terminal windows of the target machine how nothing happens, the console output will remain as after booted in step 3.

  2. stop simulation by executing the stop command.

In order to repeat input one can use a recorder to record input and the replay it after loading a snapshot:

  1. restore the simulation state "booted" again:

    simics> restore-snapshot booted
    
  2. start recording to a file using the start-recording command:

    simics> start-recording file = "myrecording.rec"
    Recording of asynchronous input started
    
  3. resume simulation with the run command:

    simics> run
    running>
    
  4. enter some input to the terminal window, in this case the same input as in the earlier example, step 7:

  5. stop the simulation and then stop the recording with the stop-recording command:

    running> stop
    
    simics> stop-recording
    Recording of asynchronous input stopped
    
  6. restore the simulation state "booted" again:

    simics> restore-snapshot booted
    

  7. replay the recording:

    simics> start-playback file = "myrecording.rec"
    Playback of recorded async input started
    
    simics> run
    running>
    

    The terminal input will be replayed:

    simics> stop
    running>
    

We can see that the same inputs were replayed with the same output as a result.

The existing snapshots can be listed using the list-snapshots command:

simics> list-snapshots

When a snapshot is no longer needed it can be deleted using the delete-snapshot command:

simics> delete-snapshot booted

8.5 Writing Custom Scripts

In addition to interactive use, the Intel Simics simulator can also run scripts with CLI commands and/or Python code. This section provides some examples on how to write custom scripts and run them.

When the situation occurs that the same commands have to be repeated, it is recommended to instead put these in a script.

8.5.1 Create and Run a Script

Here we describe how to create and run a simple script. We will create a script in the project directory and run it.

8.5.1.1 Create the script

Open an editor, and copy/paste/save the below lines to first.simics in the project folder.

echo "Script is running"

8.5.1.2 Run the script

This can be done in two ways:

8.5.2 CLI Script

Let's say we repeatedly input the following lines on the CLI:

$target = "qsp-x86/firststeps"
$run_time = 0.2

echo "Load the target " + $target + " and run " + $run_time + " seconds"
load-target "qsp-x86/firststeps"
run-seconds $run_time
ptime

To speed up the turnaround time, we can put these line in a script, and run this script.

  1. Create the script run-target.simics with the above commands, in the project folder.

  2. Run the script run-target.simics and verify that the output from the last command, ptime is:

    Load the target qsp-x86/firststeps and run 0.2 seconds
    ┌────────────────────────┬─────────┬─────────┬────────┐
    │       Processor        │  Steps  │ Cycles  │Time (s)│
    ├────────────────────────┼─────────┼─────────┼────────┤
    │board.mb.cpu0.core[0][0]│387346147│400000000│   0.200│
    └────────────────────────┴─────────┴─────────┴────────┘
    

8.5.3 Python calling CLI commands

This is an example of a Python script which does essentially the same thing as CLI Script example, and shows different ways of calling CLI commands from Python.

  1. Create the script run-target.py with the below contents:

    import cli
    import simics
    
    target = "qsp-x86/firststeps"
    run_time = 0.2
    
    cli.run_command(f'echo "Load the target {target} and run {run_time} seconds"')
    simics.SIM_load_target(target, None, [], [])
    cli.global_cmds.run_seconds(seconds=run_time)
    cpu = cli.current_cpu_obj()  # get the current CPU object
    print(cpu.cli_cmds.ptime())
    

    The target is loaded by calling the simulator API function simics.SIM_load_target which corresponds to what is done with the load-target command.

  2. Run the script run-target.py and verify that the output is:

    Load the target qsp-x86/firststeps and run 0.2 seconds
    [[<the x86QSP1 'board.mb.cpu0.core[0][0]'>, 387346147, 400000000, 0.2]]
    

    Note that it's the return value of ptime is printed.

In run-target.py two ways of running CLI commands from Python are demonstrated:

The function arguments are documented with the Python help system. Note that the function arguments can be different from the command arguments. For the full command documentation, use the CLI help command.

Examples of viewing help text for the board.log-group command:

Note in the above example:

8.5.4 CLI Script mixed with Python

Here follows another example script, which demonstrates scripting that combines CLI commands and Python:

  1. Create the script mix.simics with the below contents:

    @import cli
    @import conf
    @import simics
    
    @def log_cli_var(name):
        print(f'Log the value of "{name}" from Python')
        contents = cli.simenv[name]
        simics.SIM_log_info(1, conf.sim, 0, f'{name} = {contents}')
    
    $a = 1
    @log_cli_var("a")
    @b = cli.simenv.a + 1
    expect ($a + 1) `b`
    

    In the script the following is demonstrated:

    1. Calling Python code using @.
    2. Access CLI variables from Python using cli.simenv.
    3. Access Python variables from CLI using backticks (`b`).
    4. Using the simulator object sim from Python by prepending conf. to the object name (the sim object is always present).
    5. Calling of the simulator API function simics.SIM_log_info.
  2. Run the script mix.simics and verify that the output is:

    Log the value of "a" from Python
    [sim info] a = 1
    

For further information about CLI, see the Simics User's Guide.

8.6 Virtual disks

This section gives some information about virtual storage devices. Particularly, a few strategies are described for preserving changes done during a simulation session to virtual hard disks and using these changes in other simulation sessions.

Target machines usually have emulated storage devices attached. A typical example of such storage device is a virtual hard disk.

The software running on the target machines reads data from and writes data to virtual hard disks. The actual data is stored in dedicated files on the host system. Such files are usually called image files, disk image files, or, simply, images.

The Intel Simics simulator supports a few image files formats:

Normally, disk image files are opened in a read-only mode. All changes the guest software does to virtual disk's contents are accumulated in memory or in temporary files and are not written directly to disk image files. This means that any changes written to virtual hard disks during a simulation session are lost once a user quits the simulator. There are a few benefits in using disk image files in a read-only mode:

The main drawback, though, is that one needs to take additional steps to preserve changes done to virtual hard disks during a simulation session. Below we describe a few strategies how to preserve changes done to virtual hard disks during a simulation session and use them in other simulation sessions.

8.6.1 Saving virtual disks’ state with save-persistent-state command

The changes done by target software to the contents of virtual hard disks can be saved for later use with the save-persistent-state command. Here is a sample session demonstrating the usage of the command:

  1. launch the simulator and load the qsp-x86/firststeps target:

    simics> load-target qsp-x86/firststeps
    
  2. run the simulation until Linux is booted:

    simics> run
    

  3. create a file on the target system or do some other modification to the file system. As an example, the screenshot below shows how to create the /disk0/test.txt file on the target system by running the command:
    echo 'Hello, world!' > /disk0/test.txt

  4. now, when a file was created, shutdown a target machine by running the shutdown now command on the target machine. This is needed to ensure that a target operating system writes the file on the disk instead of, e.g., caching it in RAM of the simulated machine:

  5. stop simulation by executing the stop command. This step is needed because even though the target machine entered shutdown state, the simulator still continues to advance virtual time:

    running> stop
    simics>
    
  6. save changes done to all virtual disks found in the target machine by running the save-persistent-state command, and as argument, specify the path on the host file system where the state is saved:

    simics> save-persistent-state test_file_created.ckpt
    
  7. quit the simulator:

    simics> quit
    

8.6.2 Restoring virtual disks’ state

The test_file_created.ckpt directory created in the previous section contains all modifications done to all virtual hard disks of the target machine. The modifications are stored in so-called differencing images which are often referred to as diff files in the documentation. These images only hold the differences to another images. A differencing image is useless by itself; it must always be used together with another image.

Let’s run a simulation now to see how the state saved previously can be used. Here is a sample simulation session:

  1. launch the simulator and load the qsp-x86/firststeps target:

    simics> load-target qsp-x86/firststeps
    
  2. use the load-persistent-state command to load any state saved previously. We need to do this step at the very beginning, before the simulation was started, since otherwise the software running on the target will be presented with original state, not the updated one:

    simics> load-persistent-state test_file_created.ckpt
    
  3. run the simulation until Linux is booted:

    simics> run
    

  4. check that the /disk0/test.txt file created during the previous session is present:

Since the contents of disk images are saved incrementally by default, care should be taken when deleting the state saved previously with the save-persistent-state command: such saved state may be referred to by the state saved later.

To sum up, the typical usage scenario for the save-persistent-state and load-persistent-state commands is:

  1. start simulator and load the target qsp-x86/firststeps
  2. use the load-persistent-state command to load, if you already have it, the state saved previously with the save-persistent-state command
  3. start simulation to boot the machine
  4. do any modifications to the target machine
  5. shutdown the target machine
  6. stop simulation
  7. save the state of virtual disks with the save-persistent-state command

Please note that even though the saved states are saved incrementally and thus depend on each other one needs to run the load-persistent-state command only once with the state one wants to load.

Useful information about the save-persistent-state and load-persistent-state commands can be found in their documentation. The documentation can be obtained from CLI by running the help command like this: help save-persistent-state.

8.6.3 Saving a complete disk image

The approach described above may result in multiple saved incremental states which are hard to manage. The Intel Simics simulator allows dumping the contents of a whole virtual disk to a new disk image file. This file can be later used as a new disk image for the target machine.

There are several ways to dump a new disk image from a virtual disk. We will use the save-persistent-state command and its -independent-state flag.

Sample session:

  1. launch the simulator and load the qsp-x86/firststeps target:

    simics> load-target qsp-x86/firststeps
    
  2. (optional) if there is any state saved previously with the save-persistent-state command you want to load, load it with the load-persistent-state command. In this session we load the test_file_created.ckpt state saved in the previous section:

    simics> load-persistent-state test_file_created.ckpt
    
  3. run the simulation until Linux is booted:

    simics> run
    

  4. create a file on the target system or do some other modification to the file system. Since we have already loaded the test_file_created.ckpt state at step 2 above, there is already a /disk0/test.txt on the target machine. As an example, let’s create an additional file called /disk0/test2.txt:

    echo 'Hello, world2!' > /disk0/test2.txt

  5. now, when we are done with all changes we wanted to do, shutdown a target machine by running the shutdown now command on the target machine. This is needed to ensure that target operating system writes the file on the disk instead of, e.g., caching it in RAM of the simulated machine:

  6. stop simulation by executing the stop command. This step is needed because even though the target machine entered shutdown state, the simulator still continues to advance virtual time:

    running> stop
    simics>
    
  7. save disks by running the save-persistent-state command with the -independent-state flag and specifying a destination where on the host system to keep the files. This operation may take some time as disk images are quite large:

    simics> save-persistent-state -independent-state my_independent_state.ickpt
    
  8. quit the simulator:

    simics> quit
    

The my_independent_state.ickpt directory created on step 7 above contains, among other things, disk images of all hard disks of the target machine. The -independent-state flag used with the command ensures that the disk image are not differencing images (or, in other words, diff files) but the complete images which contain the contents of the whole disk.

By inspecting the contents of the my_independent_state.ickpt directory we can find there the board.disk0.hd_image.craff file. This file is the disk image containing the data from the board.disk0 virtual disk object. The next section shows how one can start a target machine with this disk image.

8.6.4 Using own disk image

Target systems often accept target parameters which can be used to specify a disk image for the target machine to use. We will now find out which target parameter to use, and set this to the my_independent_state.ickpt/board.disk0.hd_image.craff image.

  1. launch the simulator without loading a target.

  2. use the params.help command and filter out parameters that contain disk:

    simics> params.help target = "qsp-x86/firststeps" substr = disk
    ┌───────────────────┬────┬────────────────────────┬────────────────────────┐
    │Name               │Type│Description             │Default                 │
    ├───────────────────┼────┼────────────────────────┼────────────────────────┤
    │machine:hardware:  │file│Disk image file for the │^machine:software:linux:│
    │storage:disk0:image│    │machine_name.disk0      │empty_image             │
    │                   │    │virtual                 │                        │
    │                   │    │disk. Files in craff    │                        │
    │                   │    │(Simics own file        │                        │
    │                   │    │format), VHDX, and raw  │                        │
    │                   │    │formats                 │                        │
    │                   │    │are supported.          │                        │
    │                   │    │                        │                        │
    ├───────────────────┼────┼────────────────────────┼────────────────────────┤
    │machine:hardware:  │file│Disk image file for the │^machine:software:linux:│
    │storage:disk1:image│    │machine_name.disk0      │auxiliary_image         │
    │                   │    │virtual                 │                        │
    │                   │    │disk. Files in craff    │                        │
    │                   │    │(Simics own file        │                        │
    │                   │    │format), VHDX, and raw  │                        │
    │                   │    │formats                 │                        │
    │                   │    │are supported.          │                        │
    │                   │    │                        │                        │
    └───────────────────┴────┴────────────────────────┴────────────────────────┘
    
  3. we will use the machine:hardware:storage:disk0:image parameter to set our image:

    simics> $img = my_independent_state.ickpt/board.disk0.hd_image.craff
    simics> load-target qsp-x86/firststeps machine:hardware:storage:disk0:image = $img
    
  4. to check that parameter was correctly assigned, use params.list:

    simics> params.list substr = disk0
    ┌────────────────────────────────────┬────┬───────────────────────────────────────┐
    │Name                                │Type│Value                                  │
    ├────────────────────────────────────┼────┼───────────────────────────────────────┤
    │firststeps:machine:hardware:storage:│file│my_independent_state.ickpt/board.disk0.│
    │disk0:image                         │    │hd_image.craff                         │
    └────────────────────────────────────┴────┴───────────────────────────────────────┘
    
  5. run the simulation until Linux is booted:

    simics> run
    
  6. check that both files are present in /disk0:

8.7 Networking and getting data into the simulated system

There are several situations when it is necessary and/or useful to let the simulated target machine interact with the host system, or even other systems accessible to the host via networking. Probably the most common situation is the need to transfer files between the target and the host.

To summarize the available methods of transferring files between the target system and host machine:

For further information, see:

In the tutorials, it is recommended to start with the preparation section, which will save time by using a checkpoint where Linux has booted.

8.7.1 Preparation

Most tutorials in this section requires a qsp-x86/firststeps target machine where Linux has reached the login prompt, and that the simulation is stopped.

If the checkpoint target-booted.ckpt has been created (see the checkpoints section), it is possible to save time and launch the simulator directly from this checkpoint (Alt 1), otherwise start the qsp-x86/firststeps target (Alt 2).

After having followed the above preparation steps, Linux should have booted and the simulator should have stopped.

8.7.2 Using the Intel Simics Agent

File transfer can be done in several ways. The preferred method is to use the Intel Simics Agent, which is piece of software that must be present on the target machine. The qsp-x86/firststeps target comes with the agent already on disk.

For other targets, if the agent is not present, it must be transferred to the target machine using one of the methods described later. The agent is preferred since it is the fastest and least intrusive method.

The steps required to configure the agent can be summarized as:

  1. in the simulator:
    Start the agent manager. The agent manager is a single global manager in the simulator, used to manage all connections to all agents on all targets. The agent manager is started with the
    start-agent-manager command.

  2. on the target:
    Start the simics-agent on the target.

  3. in the simulator:
    Connect the agent manager with the agent with the <agent_manager>.connect-to-agent command. After connecting, an agent handle will be created, which is a Simics object which can be used access the target.

Here is an example of using the agent for transferring files, using the qsp-x86/firststeps target.

Note that the agent operations are necessarily asynchronous, which is why we must wait for them to finish. However, there is no need to wait after each command; several commands can be queued up before a wait is issued.

In the example, we only started the simulation to allow starting simics-agent in the target machine, and while waiting for agent operations to complete, using <agent_handle>.run-until-job.

An alternative method is to keep the simulation running. With this method, the requested agent operations will start directly, and <agent_handle>.run-until-job or <agent_handle>.status may only be required to await or check completion of the operation. This method (work with a running simulator) can be convenient for interactive work.

The agent can also perform other operations, such as

To see other available commands, run help agent0 or use the tab-completion by typing agent0. followed by two tabs:

agent0 # press tab twice to expand all commands
agent0.agent-poll-interval  agent0.log-group
agent0.agent-quit           agent0.log-level
agent0.agent-restart        agent0.ls
agent0.cd                   agent0.print-file
agent0.change-directory     agent0.print-working-directory
agent0.delete-handle        agent0.pwd
agent0.discard-jobs         agent0.run
agent0.download             agent0.run-until-job
agent0.download-dir         agent0.status
agent0.get-captured-output  agent0.target-time
agent0.info                 agent0.upload
agent0.list-files           agent0.upload-dir
agent0.list-jobs            agent0.wait-for-job

8.7.3 Using disk images

There are other methods for transferring data in and out of the simulation. If the agent is not already present on the target machine, one of them must be used first to copy the agent software.

Here is an example of transferring the agent to the target using USB.

8.7.4 Using the Service Node

Intel Simics simulator is a full system simulator, which can also simulate a network of machines. It includes a feature called the service node which acts like a separate machine on the simulated network, with its own IP address. The service node can expose common useful network services, such as DHCP, DNS, NTP as well as an FTP server that facilitates connecting to the host system and transfer files.

Here is an example of transferring the agent to the target machine over FTP.

With the agent now running on the target machine, we can now proceed as in the earlier section if we want to transfer other files.

8.7.5 Use NAPT network and HTTP

In this section we demonstrate transferring data from the host to the target using regular networking.

Intel Simics simulator can let the target machine connect to any network that the host system has access to. This can be achieved in several ways, where NAPT is the simplest option. The simulator then acts similarly like a regular home router, performing network address translation between the simulated network and the network that the host is connected to. The service node DNS server can also act as a proxy for real DNS.

In this example we only connected to the host itself, but in fact the same technique can be used to connect to any other system that the host can access. Also note that the HTTP server we open on the host will be accessible by any web browser.

8.7.6 Using Port Forwarding and SSH

Using port forwarding, the target can also be accessed from the host, and potentially from any system that can access the host, so this should be used with care. Here is an example of transferring a file to the target from the host over ssh.

This assumes that the host has ssh installed.

In this example we only copied a file, but using port forwarding, we can connect to other network service available on the target, such as web servers.

8.8 Debugging Target Software

The Intel Simics simulator comes with a built-in command line debugger for debugging the target software. This section describes how to get started with the Simics debugger. We start of with and example of debugging a Linux kernel module, then go through

This tutorial assumes that the *QSP Clear Linux (#4094)* package has been installed.

For further information on debugging see Analyzer User's Guide.

To follow the examples in this section it is recommended to launch the simulator the targets/qsp-x86/qsp-clear-linux-pcie-demo.simics script:

simics> run-command-file targets/qsp-x86/qsp-clear-linux-pcie-demo.simics

8.8.1 Example of debugging a kernel module

This example demonstrates how to debug a custom built kernel module. We use the simics-pcie-demo-driver module, which is included in the QSP-x86 package. The example comes with both a kernel module binary and source code for that.

To locate the installation directory with the example files, run the following command:

simics> lookup-file "%simics%/targets/qsp-x86/target-source/simics-pcie-demo-driver"

In this example we use the Linux tracker. This tool, which is part of the OS Awareness feature, allows keeping track of Linux tasks and processes. The tracker can provide symbol mappings of kernel modules to the debugger, which is the feature we will use in this example.

8.8.1.1 Configuring the Linux tracker

This section describes the steps needed to configure the Linux tracker for kernel module debugging.

Create a target machine and start simulation:

simics> run-script targets/qsp-x86/qsp-clear-linux-pcie-demo.simics
simics> run
running>

Let the simulation run until Linux has booted, and the kernel module has been inserted. The simulation is stopped automatically by the script at this point.

Once the system has booted, we can configure the Linux tracker using symbol information for the current kernel. The tracker accepts symbols in two formats.

In this example we will extract kallsyms from the target system and use that as symbols.

simics> matic0.download /proc/kallsyms cl-kallsyms
matic0:job 5 (download kallsyms)
simics> matic0.run-until-job
matic0:job 5 (download kallsyms) finished
simics> machine.software.tracker.detect-parameters symbol-file = cl-kallsyms -load param-file = cl.params kernel-modules = TRUE
[machine.software.tracker.tracker_obj info] Detecting settings using 2 processor(s)
[machine.software.tracker.tracker_obj info] Successfully detected parameters
Saved autodetected parameters to cl.params
simics> machine.software.enable-tracker
OSA control enabled.

The next time we use the Linux tracker with the same kernel we can re-use the same parameters again, by loading the detected parameters using the load-parameters command followed by enable-tracker.

In order for kernel module debugging to work, a path where to find kernel modules on local disk must be set:

simics> machine.software.tracker.set-kernel-modules-path path = "%simics%/targets/qsp-x86/target-source/simics-pcie-demo-driver"

The kernel module binaries on local disk must match the ones running in the target kernel.

8.8.1.2 Adding path maps

The kernel module was built under /root/swbuild, but the source files on local host are located under targets/qsp-x86/target-source. To allow the debugger to find the source files, set the following path map:

simics> add-pathmap-entry /root/swbuild/ "%simics%/targets/qsp-x86/target-source/"

8.8.1.3 Debugging

Enable the debugger:

simics> enable-debugger
Debugger enabled.

Set a breakpoint on a function in the module. This will trigger once the drivers file device gets some input.

simics> bp.source_location.break chari_write -once
Breakpoint 7: 0x7 (planted)

Start the simulation:

simics> run

Then output a string to the file device by writing to it from the Linux shell, using the serial console:

simics@cl-qsp ~ $ sudo bash -c 'echo 01 > /dev/simics_pcie_demo_driver'

The simulation should stop with the following output:

[tcf] Breakpoint 7 on execution in context machine.mb.cpu0.core[0][0]

At this point the current stack frame can be checked using the frame command. We can see that the simulation stopped at chari_write and that the buffer contains "01" as written to the device.

simics> frame
#0 0xffffffffc019359c in chari_write(filep=(struct file *) 0xffff8881f0915a00, buffer=(const char *) 0x10a44d0 "01\n", len=3, offset=(loff_t *) 0xffffc900013dbef0) at /root/swbuild/simics-pcie-demo-driver/simics-pcie-demo-driver.c:365

simics> list
     363  
     364  #ifdef DRIVER_VERBOSE
->   365       pr_info(KBUILD_MODNAME
     366  	        ": chari_write called, with %d characters of input!\n", (int)len);
     367  #endif

Set a breakpoint on line 370 and advance the simulation to that point:

simics> bp.source_line.break filename = "simics-pcie-demo-driver.c" line-number = 370 -once
Breakpoint 8: 0x8 (planted)
simics> run
[tcf] Breakpoint 8 on execution in context machine.mb.cpu0.core[0][0]
chari_write(filep, buffer=(const char *) 0x10a44d0 "01\n", len=3, offset) at /root/swbuild/simics-pcie-demo-driver/simics-pcie-demo-driver.c:370
370	    while(charsleft >= 2) {

Stepping in the code is done with the step-into, step-over and step-out commands.

simics> step-into
chari_write(filep, buffer=(const char *) 0x10a44d0 "01\n", len=3, offset) at /root/swbuild/simics-pcie-demo-driver/simics-pcie-demo-driver.c:372
372	        switch(buffer[0]) {

Note that when step is completed the stack frame and current line will be displayed. As the input was "01" the first switch statement should end up at '0' and the second at '1'.

simics> step-into
373                 case '0': led_no=0; break;
simics> step-into
386             switch(buffer[1]) {
simics> step-into
388                 case '1': brightness=1; break;
simics> step-into
396             hw_update_led_state(led_no,brightness);
simics> step-into
hw_update_led_state(led_no=0, brightness=1)
 at /root/swbuild/simics-pcie-demo-driver/simics-pcie-demo-driver.c:146
    146             if( (led_no<0) || (led_no>5)) {

The program enters another stack frame. Run stack-trace to see the current stack trace:

simics> stack-trace maxdepth = 2
#0 0xffffffffc01931a0 in hw_update_led_state(led_no=0, brightness=1) at /root/swbuild/simics-pcie-demo-driver/simics-pcie-demo-driver.c:146
#1 0xffffffffc019365d in chari_write(filep, buffer=(const char *) 0x10a44d0 "01\n", len=3, offset) at /root/swbuild/simics-pcie-demo-driver/simics-pcie-demo-driver.c:396

Inspect symbols in the current frame with the sym-value and sym-type commands:

simics> sym-value brightness
1
simics> sym-type brightness
int

Change symbol values using the sym-write command:

simics> sym-write brightness 0
brightness = 0

Step out to return to the outer function chari_write:

simics> step-out
chari_write(filep, buffer=(const char *) 0xfaf4d0 "01\n", len=3, offset) at /root/swbuild/simics-pcie-demo-driver/simics-pcie-demo-driver.c:400
400	        buffer    += 2;

Now step to the end of chari_write. The while loop should complete after the first iteration.

simics> step-into
370	    while(charsleft >= 2) {
simics> step-into
403	    return len;

We check the return value len, before returning, and see that the function claims that 3 bytes have been consumed.

simics> sym-value len
3

The kernel module used in this example is compiled with some optimizations, meaning that some variables are optimized out and some code paths can appear strange when stepping.

8.8.2 Setting up and enabling the debugger

The first step in order to use the debugger is to enable it:

simics> enable-debugger

Then symbol files, with debug information, for the target software need to be added in order for debugging to work.

simics> add-symbol-file <binary to debug>
simics> add-symbol-file "%simics%/targets/qsp-x86/images/debug_example"

OS Awareness trackers can provide symbol files to the debugger instead of having to add them using the command.

In case the source files are not present in the same location as they were compiled, a path map is needed for the debugger to locate the source:

simics> add-pathmap-entry <compilation path> <local disk path>

When the debugger is enabled and the simulations stops the current stack frame will be displayed, under the condition that there is a valid symbol file added for the current debug context and address.

simics> add-pathmap-entry /tmp .

8.8.3 Debug Contexts

A debug context represents something that can be debugged, such as:

The debug-context command can be used to see current debug context or specify a different one.

simics> debug-context
dbg0 (the x86QSP1 machine.mb.cpu0.core[0][0])
simics> debug-context object = "machine.mb.cpu0.core[1][0]"
dbg1 (the x86QSP1 machine.mb.cpu0.core[1][0])

To see available debug context, use the list-debug-contexts command, which optionally can take context-query as argument.

simics> list-debug-contexts
Fully Qualified Name        | Fully Qualified Name
----------------------------+---------------------------
/machine                    | /machine/mb.cpu0.mem[0][0]
/machine/mb.cpu0.core[0][0] | /machine/mb.cpu0.mem[1][0]
/machine/mb.cpu0.core[1][0] | 

The context-query argument can be used to match a subset of contexts. To list contexts directly under root:

simics> list-debug-contexts context-query="/*"
Fully Qualified Name
--------------------
/machine

To match specific processor:

simics> list-debug-contexts context-query="/machine/'mb.cpu0.core[1][0]'"
Fully Qualified Name
---------------------------
/machine/mb.cpu0.core[1][0]

A context query is a method to specify a subset of debug contexts, by specifying context properties and what values to match. The default property is name.

The forward slashes in the context names are separators. A query consists of a sequence of parts separated by forward slashes. Two wildcards exist, * and **, where one asterisk is used to match any context and two asterisks matches any sequence of contexts.

Many debugger related commands, such as add-symbol-file and add-pathmap-entry, take context-query as an argument to limit what contexts it applies to. Leaving the argument out, means matching all possible debug contexts.

As example, for a symbol file to only apply for a specific processor then add-symbol-file should be called with the context-query argument to match the processor name.

simics> add-symbol-file context-query="/machine/'mb.cpu0.core[1][0]'" <symbol file>

Extra quotation is added around the processor name. This is needed when the context name contains special characters, such as dots and brackets.

8.8.4 Debugger commands

There are debugger commands available for investigating the current state, most of them start with the sym- prefix. Here follows some examples of debugger commands:

To find out more about these commands, use the help command, for example:

simics> help sym-value
Command sym-value

   Synopsis
      sym-value "expression"
...

8.8.5 Breaking on a source line or function

It is possible to stop the simulation when a specific source line or function is hit. To set a breakpoint on a source line use the following command:

simics> bp.source_line.break filename = foo.c line-number = 10

And in a similar way for a function:

simics> bp.source_location.break foo

After setting such breakpoints, the simulation will stop once the source line foo.c:10 or the function foo is hit.

8.8.6 Debugging Summary

This concludes this tutorial, in which we have learned how to use debugger commands to

8.9 Using Breakpoints

Besides the source code or address breakpoints demonstrated in the debugging section, the Intel Simics simulator provides several other types of breakpoints:

8.9.1 Overview of Breakpoints

These are some examples of breakpoints:

8.9.2 Finding Breakpoint Commands

To list breakpoint related commands, use the help command the Breakpoints category:

simics> help category:Breakpoints
...
<bp-manager.time>.break           set time breakpoint
<bp-manager.time>.run-until       run until specified time
<bp-manager.time>.trace           enable tracing of time points
<bp-manager.time>.wait-for        wait for specified time
...

In the shortened list of break commands above, note that there are different command types:

8.9.3 The Breakpoint Manager

Most breakpoint commands are implemented by the breakpoint manager, which is an object named bp. To list the different breakpoint types that the breakpoint manager implements, use bp.list-types:

simics> bp.list-types
┌───────────────────┬────────────────────────────────────────┐
│     Provider      │            Breakpoint type             │
├───────────────────┼────────────────────────────────────────┤
│bp.bank            │device access                           │
│bp.console_string  │target console string output breakpoints│
│bp.control_register│control register access breakpoints     │
│bp.cycle           │cycle queue breakpoints                 │
│bp.cycle_event     │cycle event breakpoints                 │
│bp.exception       │exception breakpoints                   │
│bp.gfx             │graphics console output breakpoints     │
│bp.hap             │hap occurrence breakpoints              │
│bp.log             │log message breakpoints                 │
│bp.magic           │magic breakpoints                       │
│bp.memory          │memory access breakpoints               │
│bp.notifier        │notifier trigger breakpoints            │
│bp.os_awareness    │OS Awareness breakpoints                │
│bp.source_line     │source code line breakpoints            │
│bp.source_location │source code location breakpoints        │
│bp.step            │step queue breakpoints                  │
│bp.step_event      │step event breakpoints                  │
│bp.time            │virtual time breakpoints                │
└───────────────────┴────────────────────────────────────────┘

A breakpoint created with bp.<type>.break is assigned a breakpoint identity, and this identity can be used to inspect or manipulate that specific breakpoint. These are some common commands:

8.9.4 Breakpoint Examples

Here follows a few examples of how to use breakpoints.

8.9.4.1 Execution Breakpoint

In this example, we set an execution breakpoint on a memory address.

8.9.4.2 Exception Breakpoint

In this example, we will write an illegal instruction, and break on the exception that is raised when executing the illegal instruction.

8.9.4.3 Log Breakpoint

In this example, we will plant a temporary (-once) log breakpoint that triggers when the object board.mb.sb, or one of its child objects, logs an info log that contains the string lower. The selection of child objects is achieved with the -recursive flag.

8.10 Code Coverage of Target Software

The Intel Simics simulator provides a tool for code coverage using binaries with debug information.

This section will describe how to get started with code coverage feature. It will start with an example of code coverage for a kernel module, then provide info about

This tutorial assumes that the *QSP Clear Linux (#4094)* package has been installed.

For further information on code coverage see Analyzer User's Guide.

8.10.1 Code Coverage Example

8.10.1.1 Setup

This section reuses the setup from the debugging section to demonstrate code coverage of a kernel module. The tracker parameters file cl.params, from that example is needed to run this example.

Launch the simulator with the same script as before:

%simics%/targets/qsp-x86/qsp-clear-linux-pcie-demo.simics

Then run the following commands from the previous example:

simics> machine.software.load-parameters cl.params
simics> machine.software.enable-tracker
OSA control enabled.
simics> machine.software.tracker.set-kernel-modules-path path = "%simics%/targets/qsp-x86/target-source/simics-pcie-demo-driver"
simics> add-pathmap-entry "/root/swbuild" "%simics%/targets/qsp-x86/target-source"

8.10.1.2 Collecting Code Coverage

Before starting the simulation, start collecting coverage for all Linux tracker Kernel nodes:

simics> collect-coverage context-query="/**/Kernel/**" name="kernel_module" -running
kernel_module is collecting coverage for /**/Kernel/**

Start the simulation and run until the system is booted and the simulation stops. Note that the simulation is slower when the Linux tracker and code coverage is used.

simics> run
  ...
  Autologin as "simics" was done on "machine.mb.sb.com[0] - serial console".
  Setting new inspection object: machine.mb.cpu0.core[1][0]
simics> 

This script automatically runs insmod when the Linux shell is reached and then stops the simulation.

The output from the serial console should be:

simics@cl-qsp ~ $ sudo insmod simics-pcie-demo-driver.ko
simics@cl-qsp ~ $ 

At this point the driver should be loaded. Output a HTML report for collected coverage up to this point of time:

simics> kernel_module.html-report kernel-module-loaded-html report-name = "Kernel module loaded"
Saving HTML report to: kernel-module-loaded-html
Report contains 29 errors

The errors are because of missing binaries for other kernel modules that the tracker has found. More detailed information about errors can be found in the HTML report.

Before we examine the report, we will input a string to the driver's character device to see how that changes coverage.

Start the simulation:

simics> run

Enter the following in the serial console and wait for the shell to return to prompt:

simics@cl-qsp ~ $ sudo bash -c 'echo 21 > /dev/simics_pcie_demo_driver'

Stop the simulation again:

running> stop

Then output another HTML report, using the same code coverage object:

simics> kernel_module.html-report kernel-module-after-input-html report-name="Kernel module after input"
Saving HTML report to: kernel-module-after-input-html
Report contains 29 errors

Before quitting the simulator, we will save a raw report for use in a later example:

simics> kernel_module.save kernel-module-after-input.raw

Now it is time to examine the two reports. We open the reports kernel-module-loaded-html/index.html and kernel-module-after-input-html/index.html using a web browser.

We should see the following output in the first report:

In the second report we can see that the lines covered increased by one line, when the string "21" was written to the device.

The report shows the number of lines executed and the amount executable, for the whole binary and per source directory. The most interesting directory is simics-pcie-demo-driver. This contains the source of the driver. We can follow the link to see the source files under that directory.

We can follow the links per source file to get detailed information about coverage for a certain source file. That source file pages have the following color codings.

The left column shows the line number of the source file.

In the first report we see for example that hw_update_led_state, on line 136, executed and that the led_no values are inside the expected range. We can see that the assignment of led_offsets was optimized out. For the lines with the pr_err function call we see that only the first line is marked as executable. That is commonly how multi-line function calls will be displayed as only the first line is considered executable.

We can compare the two saved HTML reports to find what extra line was run when we wrote the string "21" to the device driver. The difference is in the chari_write function.

chari_write first switch statement, before writing 21 to device. chari_write second switch statement, before writing 21 to device. chari_write first switch statement, after writing 21 to device.

We see that case '2' has run in the first switch statement. This matches the first character of the input. All other lines in the report are unchanged after the input.

The driver had already received an input "01" in the first report. The script we use is written to test the driver by inputting that value to the device.

There are a lot of unknown addresses under a tab in the HTML report. These correspond to instructions that run where there is no mapping added. In this example every executed address that is not part of a kernel module, such as boot loader and main kernel code, will be unknown.

8.10.2 Setting up code coverage

In order for code coverage to work, symbol files have to be added in the same way as in the debugging section. Either use the add-symbol-file command or configure a tracker to add symbol files for use with code coverage. In the example above the Linux tracker was configured to add symbol files for kernel modules.

8.10.3 Collecting coverage

To start collecting code coverage use the following command:

simics> collect-coverage context-query=<query> name=mycov

This will return a code coverage object which is used for outputting reports. Once collection is started, run the simulation for the desired time to collect code coverage for. Then output a report output. Learn more about controlling the scope of what is collected in the context-queries section.

8.10.4 Outputting reports

The code coverage object returned from collect-coverage has a few commands for outputting reports in different formats.

8.10.5 Combining Code Coverage Reports

The Intel Simics code coverage feature allows combining two or more raw reports into one report. This allows running the same binaries, but with different code paths, to get a full picture of the combined coverage. For example combining code coverage of many tests in a suite.

We will continue the earlier example, were we saved a raw report named kernel-module-after-input.

Relaunch the simulator and repeat the same steps as in the earlier example, with the exception that the string that is passed to the device this time should be "a0".

Run the simulation until the system is booted, the kernel module is inserted and the simulation stops. Then start the simulation again:

simics> run

Enter the following in the serial console:

simics@cl-qsp ~ $ sudo bash -c 'echo a0 > /dev/simics_pcie_demo_driver'\n

Once the Linux shell reaches prompt, stop the simulation:

running> stop

Then add the previous report using the add-report command:

simics> kernel_module.add-report kernel-module-after-input.raw
Adding report from input file: kernel-module-after-input.raw

Before outputting the combined report to HTML we should combine mappings that match the same symbol file, but are loaded at different addresses. Unless the simulation target is fully deterministic, it is likely that the kernel modules are loaded at different addresses on the second run.

simics> kernel_module.stop
simics> kernel_module.combine-mappings
26 mappings were removed

Output a new HTML report with the combined coverage.

simics> kernel_module.html-report kernel-module-combined-html report-name="Kernel module combined"
Saving HTML report to: kernel-module-combined-html</pre>

Check the summary in the report to see that coverage has increased by two lines from when only "21" had been input.

Check the source code coverage of the write_chari function to see that the two switch statements have one more executed line each.


chari_write first switch statement, after combining reports.
chari_write second switch statement, after combining reports.

To increase coverage we can repeat the example with varied inputs.

We can choose to start collecting coverage after the system had been booted to get faster boot time, as driver initialization should be the same between runs. A third option is to launch the simulator with a checkpoint with the booted system and driver loaded, then start collecting at that point.

8.10.6 Code Coverage Summary

That concludes the code coverage tutorial, where we have learned how to

8.11 Instrumentation

The instrumentation framework in the Intel Simics simulator has powerful ways to inspect the simulation. It is built on four core concepts:

At the CLI, it is the tools and filters that are manipulated. To see a list of available tools:

simics> list-instrumentation-tools substr = bank
┌──────────────────────┬──────────────────┬──────────────────────────────┐
│ Tool create command  │    Tool class    │         Description          │
├──────────────────────┼──────────────────┼──────────────────────────────┤
│new-bank-coverage-tool│bank_coverage_tool│register bank coverage tool   │
│new-bank-patch-tool   │bank_patch_tool   │device access miss repair tool│
└──────────────────────┴──────────────────┴──────────────────────────────┘

Here is an example of using instrumentation to compare user and supervisor mode instruction occurrences.

Here is another example of using instrumentation to show exception occurrences.

Source code for instrumentation tools are in

    src/extensions/instruction-histogram
    src/extensions/exception-histogram
    src/extensions/cpu-mode-filter

in the base package.

8.12 Using a cache model

Let us now show a simple example of how to use simple cache model. By default, the Intel Simics simulator does not model any cache system. It uses its own memory system to achieve high speed simulation and modelling a hardware cache model would only slow it down. However, via the instrumentation framework, the flow of memory operations coming from the processor can be captured, and this allows modelling caches.

Here is an example of using instrumentation to connect a simple cache model.

Source code for cache model is in the base package under: src/extensions/simple-cache-tool.

9 Next Steps

This Getting Started document only provides a short introduction of the Simics product and all its capabilities. Other documents describe the Simics functionality in more detail. Simics User's Guide covers the basic feature set of the product. Analyzer User's Guide describes the tools used for software debugging and analysis. Similarly, the Model Builder User's Guide covers model development and configuration for Simics. There are also reference manuals that provide details on commands, interfaces, and API functions.

A Using Legacy Scripts to Create Configurations

This section describes a legacy method creating configurations by using Intel Simics scripts, referred to as scripts in this section for brevity.

Modern configurations are created with targets and are customized using target parameters, but since all models have not been converted, it may be good to know how scripts are used.

To distinguish between legacy scripts and modern targets:

The following tasks are explained:

Intel Simics scripts can accept parameters. There are a few ways to discover which parameters, if any, are accepted by the script:

To discover available parameters via command line completion, press the tab key twice after entering the string: run-command-file targets\qsp-x86\firststeps.simics

simics> run-script targets\qsp-x86\firststeps.simics <TAB><TAB>

As a result, command line completion should show available parameters for the script:

The help command also allows finding out which parameters are accepted by a script as well as to see documentation for the parameters. To discover available parameters for the targets\qsp-x86\firststeps.simics script just run this command:

simics> help targets\qsp-x86\firststeps.simics

As a result, script description will be printed together with a long list of accepted parameters. Here is the beginning of the output:

Let’s create a target machine with 4 cores per physical processor by setting the num_cores parameter to 4. To do that please run the following command:

simics> run-script targets\qsp-x86\firststeps.simics num_cores = 4

To verify that the target indeed has 4 cores, run the list-processors command:

simics> list-processors
┌────────────────────────┬─┬─────────┬────────┐
│        CPU Name        │ │CPU Class│  Freq  │
├────────────────────────┼─┼─────────┼────────┤
│board.mb.cpu0.core[0][0]│*│x86QSP1  │2.00 GHz│
│board.mb.cpu0.core[1][0]│ │x86QSP1  │2.00 GHz│
│board.mb.cpu0.core[2][0]│ │x86QSP1  │2.00 GHz│
│board.mb.cpu0.core[3][0]│ │x86QSP1  │2.00 GHz│
└────────────────────────┴─┴─────────┴────────┘