Simics includes a configuration system used to describe the state of the simulated machines.
Simics's configuration system is object-oriented: a simulated machine is represented as a set of objects that interact when the simulated time advances. Typically, processors, memories and devices are modeled as objects. Each object is defined by a number of properties that are called attributes. A processor object, for example, will have an attribute called freq_mhz to define its clock frequency (in MHz).
Simics's configuration system is flexible: it is possible to create and delete objects dynamically, as well as access the attributes of all objects for reading and writing at any time.
Simics's configuration system allows its elements to be saved so that a complete simulated machine state can be written to a set of files. This set of files is called a checkpoint.
This chapter describes the Simics configuration system as well as the different layers built on top of it to handle more specific tasks:
Checkpoints: how a simulated state is saved and restored via checkpointing;
Inspection: how the simulated state can be examined and changed during simulation;
Start Scripts: the components and scripts used to define the initial state of a machine in the examples provided with Simics.
Not all kinds of connections with real network, or with real file systems, will continue to work properly if you pause the simulation for a shorter or lengthier time. This applies to most stateful connections, for example NFS, TCP, etc.
For the same reason, not all kinds of connections with the real world can be saved in a checkpoint and successfully restored at a later time. Hence, make a habit to disconnect such services before pausing the simulation, or before saving a checkpoint.
As mentioned above, Simics's configuration system is object-oriented. A Simics object is instantiated from a Simics class. The core of Simics defines some useful classes, but most of the classes (processors, device models, statistic gathering extensions) are provided by modules that are loaded by the simulator when requested.
For example, the x86-p4 module defines, not surprisingly, the x86-p4 class. Note that a module may define several classes. Since modules advertise the classes they define, Simics can load modules transparently as objects are instantiated.
A class defines attributes that represent both the static and dynamic state of the instantiated objects. The static state includes information that does not change during the simulation (like a version number in a register) while the dynamic state covers the part of the device that are affected by the simulation (registers, internal state, buffers, etc.).
Let us take the example of an x86-p4 processor and have a closer look at how it can be configured using attributes:
x86-p4. Let us call it cpu0freq_mhz can be set to 1500. It defines the processor clock frequency (in MHz)physical_memory can be set to a memory space object, such as phys_mem0. This attribute points to the object that will answer to the memory accesses coming from the processor.As you noticed, attributes may be of various types. A complete description is available in the next section.
Simics's configuration system can save the complete state of a simulation in a portable way. This functionality is known as checkpointing, and the set of files that represent the elements of the systems are called a checkpoint.
Saving and restoring a checkpoint can be done from the command line with the write-configuration and read-configuration commands.
A checkpoint consists of the following files, collected under a directory:
config. This is a text representation of the objects present in the system.Below is a portion of a checkpoint file showing an object. Saved objects are always represented as OBJECT object-name TYPE class-name { attributes }. In this case we have an instance of the DEC21143 class (fast Ethernet LAN controller interfacing the PCI bus) named dec0. The attribute pci_bus is used to connect the device to the PCI bus.
OBJECT dec0 TYPE DEC21143 {
queue: cpu0
component: eth_adapter_cmp0
component_slot: "dec"
object_id: "dec0"
build_id: 0xbb9
pci_bus: pci_bus0
...
}
OBJECT ... TYPE ... {
...
Objects are saved in the main checkpoint file in no specific order.
Simics maintains checkpoint compatibility with older versions, i.e. it is always possible to continue using checkpoints created in a previous version of Simics when upgrading to a new version. Compatibility is always maintained for one major version older than the oldest of the supported API versions. For checkpoints older than that, load the checkpoint with a newer version of Simics and create a new checkpoint.
The opposite is not true. Trying to load a checkpoint created in a newer version of Simics than the local version will typically not work. The same restriction may apply even between minor Simics releases. For example, a checkpoint created with Simics 3.2.2 is not guaranteed to load correctly in the older Simics 3.2.1 release.
The short example of the dec0 description only uses a few types of attribute values: strings, objects, and hexadecimal integers. The possible attribute types are:
"a string\n"0xfce2) or signed decimal (-17) notation.TRUE and FALSE.1.0e-2) or hexadecimal (0x5.a21p-32) style, just like in C.cpu0.("a string", 4711, (1, 2, 3), cpu0){ "master-cpu" : cpu0, "slave-cpu" : cpu1 }. The key should be a string, integer or object, while the value can be of any attribute type. Dictionaries are typically used to save Python dictionaries in a checkpoint. Keys must be unique, although Simics does not enforce this.Each attribute belongs to one of the following categories. Note that only attributes of the first two categories are saved in checkpoints.
Simics implements a special class called image for objects that potentially need to save a huge amount of state, like memories and disks. An image represents a big amount of raw data using pages and compression to minimize disk usage.
To save space and time, images do not necessarily save their entire state every time a checkpoint is written. They can work in several ways:
It is important to understand that when used in incremental mode, images create dependencies between checkpoints. A checkpoint can only be loaded if all previous checkpoints are intact.
As an example, let us have a look at an assumed disk image:
...
}
OBJECT disk0_image TYPE image {
...
files: (("tango1-fedora5.craff", "ro", 0, 0x4c5abc000, 0),
("disk0_image.craff", "ro", 0, 0x4c5abc000, 0))
...
}
...
The checkpointed image is based on the file tango1-fedora5.craff, on top of which is added the file disk0_image.craff that contains the difference between the checkpoint and the initial state.
Files like disk0_image.craff are often called diff files because they contain the difference between the new state and the previous state.
This section contains more in-depth explanations about image handling that you may skip when reading this guide for the first time.
When successive incremental checkpoints are saved, an image object may become dependent on several diff files present in different directories. To keep track of all files, Simics stores in the checkpoint a checkpoint path list that contains the absolute directory paths where image files may be found. Image file names are then saved as %n%\filename where %n% represents the number of the entry in the checkpoint path, counting from zero.
Simics's checkpoint path is different from Simics's search path (see section 2.2.4), although both will be used when looking for image files, as show below.
Independent checkpoints do not affect the checkpoint path.
To summarize, when loading a checkpoint or a new configuration, Simics looks for images in the following way:
If the filename does not contain any path information (like image.craff) or contains a relative path (like test\image.craff), the file is looked up first from the checkpoint directory, then from all the path entries in Simics's search path, in order (see also section 2.2.4 for more information).
[project]\targets\qsp-x86\ and the checkpoint is located in C:\checkpoints, Simics will look for the file test\image.craff in the following places:
C:\checkpoints\test\image.craff[project]\targets\qsp-x86\test\image.craff[project]/targets/qsp-x86/ and the checkpoint is located in /home/joe/checkpoints/, Simics will look for the file test/image.craff in the following places:
/home/joe/checkpoints/test/image.craff[project]/targets/qsp-x86/test/image.craffIf the filename contains a checkpoint path marker (%n%), the marker is translated using Simics's checkpoint path and the file is looked up in the corresponding path.
C:\checkpoints\c1;C:\checkpoints\c2, the file %1%/image.craff will be translated into C:\checkpoints\c2\image.craff./home/joe/c1:/home/joe/c2, the file %1%/image.craff will be translated into /home/joe/c2/image.craff.If the filename contains an absolute path the file path is used as is.
C:\checkpoints\image.craff/home/joe/image.craffThe reason why Simics's search path is involved in the process is that it makes writing new configurations easier. Adding a path to the place where all initial images are located allows you to just specify the image names.
As an alternative to checkpointing, Simics allows you to only save the persistent state of a machine, i.e., data that survive when the machine is powered-down. This typically consists of disk images and flash memory or NVRAM contents. A persistent data checkpoint is handled exactly like any other checkpoint and contains the same file set, but only objects containing persistent data are saved. This persistent data checkpoint can be loaded on top of a corresponding configuration later on.
The commands save-persistent-state and load-persistent-state respectively save and load the persistent data in a configuration.
These commands are often used to save the state and reboot a machine after the disk contents have been modified. Remember that the target OS might have cached disk contents in memory. In order to have a clean disk that can be used at boot, you should synchronize the disk, for example by running init 0 on a Linux target system, or shutting down the operating system, before you issue the save-persistent-state command.
Another option is to use the command enable-writable-persistent-state. It saves a persistent state and also switches all saved files to be writable, so that the images are used in read-write mode, as described in section 2.4.2.3. All changes to the images done during the simulation are then automatically written to these files, without the need to explicitly save the state.
This command can also load a state which already exists, created by this command. It is meant to be used in a Simics script and facilitates easy handling of the persistent states, either creating a new state or loading an existing state.
The states created by enable-writable-persistent-state can be loaded using load-persistent-state, if read-write mode is no longer desired. States created by save-persistent-state are generally not usable by enable-writable-persistent-state, since it may not be possible to make them writable.
Checkpoints are usually created by saving a configuration inside Simics, but it is possible to edit or even create checkpoints yourself. It may even be required to edit file paths in a checkpoint file if it is relocated.
Because a minimal checkpoint only has to include required attributes, creating a checkpoint from scratch works relatively well for small configurations. We suggest you use an existing checkpoint as a starting point if you wish to do that. Note that more advanced layers have been built on top of the configuration system to make the creation of a new machine much easier. Refer to section 2.4.6 for more information.
Modifying checkpoints require some extra care. Adding or removing devices may confuse the operating system, which does not expect devices to appear or disappear while the system is running, and cause it to crash.
Changing the processor frequency may be enough to confuse the operating system. Many operating systems check the CPU frequency at boot time, and base their waiting loops and timing on the value they got. Saving a checkpoint and changing the frequency after boot may affect the simulation and confuse the system. Devices that use processor frequency to trigger events at specific times may also behave strangely when the frequency suddenly changes.
If you want to make an incremental checkpoint independent from all previous checkpoints, for example to distribute it, you can use the small checkpoint-merge program in [simics]\bin from your system command line. It merges the checkpoint with all its ancestors to create a checkpoint that has no dependencies. Specify the checkpoint you want to distribute as the first parameter and the name of the new stand-alone checkpoint as the second. This tool can be used in both Linux and Windows environments.
Note that the merged checkpoint still depends on the base image. This differs from independent checkpoints, which are completely standalone.
Object attributes that are of type integer, string or object are directly accessible at the command line with the notation object->attribute:
# reading the EAX register in an x86 processor
simics> cpu0->eax
0
# writing a new value to EAX
simics> cpu0->eax = 10
simics> cpu0->eax
10
simics>
More information about the command line and scripting is available in chapter 2.3.
Finally, objects and attributes (of all types) are also available when scripting Simics directly in Python. Configuration objects are available under the conf namespace:
# reading the EAX register in an x86 processor
simics> @conf.cpu0.eax
0
# writing a new value to EAX
simics> @conf.cpu0.eax = 10
simics> @conf.cpu0.eax
10
simics>
More information about scripting Simics in Python is available in chapter 2.3.
All machines in [simics]\targets\architecture use components to create configurations. A component is typically the smallest hardware unit that can be used when configuring a real machine, and examples include motherboards, PCI cards, hard disks, and backplanes. Components are usually implemented in Simics using several configuration objects and can also contain subcomponents.
Components are intended to reduce the large configuration space provided by Simics's objects and attributes, by only allowing combinations that match real hardware. This greatly simplifies the creation of different systems by catching many misconfigurations.
Components themselves are also configuration objects in Simics. But to avoid confusion, they will always be referred to as components and the objects implementing the actual functionality will be called objects.
The component is the basic building block in the component system. When a component is created, it is in a non-instantiated state. At this stage only the component itself exists, not the configuration objects that will implement the actual functionality. Once a complete configuration has been created, all included components can be instantiated. When this happens, all objects are created and their attributes are set.
Components are connected to each other with connectors. Each connector has a connector type which tells what kind of connector it is and a direction, which can be up, down, or any. A connector is either required or optional. If it is optional it does not need to be connected to anything. Unless a connector is specified as hotpluggable it cannot be connected or disconnected after the component is instantiated. If a connection is hotpluggable it must be optional.
Connectors can be connected to each other in connections. Each connection connects an up connector with a down connector. A connection can also include an any connector. If an any connector is connected to an up connector it works exactly like a down connector and if it is connected to a down connector it works exactly like an up connector. The connections in the system must not form a cycle. You can think of the components and connections in the system as a directed acyclic graph with the components as the vertices and the connections as the edges.
Each connected subgraph in the set of components is called a component hierarchy.
A component A is said to be above a component B if it can be reached through up connectors in one or more steps from component B. Analogously, component A is said to be below a component B if B is above A.
A root is a component without any components above it. A component's roots are the roots which are above it.
A component where the top_level attribute returns true is a top-level component. It is often a motherboard, backplane or system chassis. It must be a root.
A standalone component is a component without any required connectors. A typical example is a hotplug device, such as a PC Card (PCMCIA) or an Ethernet link.
To instantiate a set of components, each component which is not standalone or top-level must have a top-level component as a root.
Components are also namespaces and can be nested in a namespace hierarchy, which is separate from the component hierarchy. The root of the hierarchy is the global namespace, and this is the only namespace which is not a component. Each configuration object (including components) lives in a namespace. The object is a child of the namespace and the namespace is the parent of the object. The other objects in the namespace are siblings of the object.
Components in Simics are grouped by machine architecture, or by type, into several modules. Before a component can be used in Simics, the corresponding component module has to be loaded. When the component module is loaded, CLI commands for creating components are added to the front end. The most common modules, that are not architecture specific, are memory-comp, pci-comp, std-comp, console-components. To import all modules that are used by the QSP-Simple machine, issue the following commands:
simics> load-module std-comp
simics> load-module memory-comp
simics> load-module console-components
simics> load-module x58-ich10-comp
simics> load-module x86-nehalem-comp
The create-<component> command is used to create non-instantiated components. There is one create command for each component class. The arguments to the create command represent attributes in the component. Standalone components can be created both non-instantiated and instantiated. To create instantiated components, there are new- commands, similar to the create- commands.
The following code creates a non-instantiated 'motherboard_x58_ich10' component , called 'motherboard0'
simics> load-module x58-ich10-comp
simics> create-motherboard-x58-ich10
Created non-instantiated 'motherboard_x58_ich10' component 'motherboard0'
A connector provides a means for a component to connect to other components. Connectors have a defined direction: up, down, or any. The direction is up if it needs an existing hierarchy to connect to; for example, the PCI-bus connector in a PCI device must connect to a PCI slot. A connector has a down direction if it extends the hierarchy downwards; for example, a PCI slot is a connection downward from a board to a PCI device. There are also non-directed connectors, with direction any. You can only connect an up to a down connector or to an any connector, and similar for down connectors. Connectors with the any direction can not be connected together.
Many connectors have to be connected before the component is instantiated, while others can be empty. A standalone component, as described above, may have all connectors empty.
A hotplug connector supports connect and disconnect after instantiation. Other connectors can only be connected, or left unconnected, when the configuration is created and may not be modified after that point. A multi connector supports connections to several other connectors. Creating multi connectors should be avoided, it is often better to dynamically create non-multi connectors when new connectors are needed.
It is not possible to connect instantiated components with non-instantiated ones. The reason is that the instantiated component expects the other to have all objects already created, and need to access some of them to finish the connection.
The info command of a component lists all connectors and some information about them:
simics> motherboard0.info
Information about motherboard0 [class motherboard_x58_ich10]
============================================================
Slots:
dimm[0] : motherboard0.dimm[0]
dimm[1] : motherboard0.dimm[1]
dimm[2] : motherboard0.dimm[2]
dimm[3] : motherboard0.dimm[3]
nb : motherboard0.nb
reset_bus : motherboard0.reset_bus
sb : motherboard0.sb
socket[0] : motherboard0.socket[0]
socket[1] : motherboard0.socket[1]
socket[2] : motherboard0.socket[2]
socket[3] : motherboard0.socket[3]
socket[4] : motherboard0.socket[4]
socket[5] : motherboard0.socket[5]
socket[6] : motherboard0.socket[6]
socket[7] : motherboard0.socket[7]
Connectors:
dimm[0] : mem-bus down
dimm[1] : mem-bus down
dimm[2] : mem-bus down
dimm[3] : mem-bus down
reset_bus : x86-reset-bus down
socket[0] : x86-apic-processor down
socket[1] : x86-apic-processor down
socket[2] : x86-apic-processor down
socket[3] : x86-apic-processor down
socket[4] : x86-apic-processor down
socket[5] : x86-apic-processor down
socket[6] : x86-apic-processor down
socket[7] : x86-apic-processor down
The board has four slots for memory modules, one north bridge, one reset bus, one south bridge, eight sockets. All slots are not listed as hotplug since they have to be inserted when the machine is configured initially.
Since the machine need a cpu, we also add a x86QSP1 processor to our example. A CLI variable is used to hold the name of the processor component.
simics> load-module x86-nehalem-comp
simics> $cpu = (create-processor-x86QSP1 freq_mhz = 2000)
simics> connect motherboard0.socket[0] $cpu.socket
To enable input and output for the simulated machine, the following commands create a serial text console and connect it to the serial[0] connector of the south bridge.
simics> load-module console-components
simics> connect motherboard0.sb.serial[0] (create-txt-console-comp).serial
Since the machine needs some memory to run, we also add a memory module to our example. A CLI variable is used to hold the name of the memory component.
simics> load-module memory-comp
simics> $dimm = (create-simple-memory-module memory_megs = 2048)
simics> connect motherboard0.dimm[0] $dimm.mem_bus
When a component hierarchy has been created, it can be instantiated using the instantiate-components command. This command will look for all non-instantiated top-level components and instantiate all components below them. The instantiate-components command can also be given a specific component as argument. Then only that component will be instantiated, including its hierarchy if it is a top-level component.
simics> instantiate-components
If there are unconnected connectors left that may not be empty, the command will return with an error.
When the instantiation is ready, all object and attributes have been created and initialized. In our example, a text console window should have opened. The hardware of the simulated motherboard is now properly configured, but since no software is loaded, it will not show any output on the console if the machine is started.
The list-components command prints a list of all components in the system. All connectors are included, and information about existing connections between them.
The info namespace command provides static information about a component, such as the slots and a list of connectors.
The status namespace command provides dynamic information about a component, such as attribute values and a list of all current connections. The output from status in the example:
simics> motherboard0.status
Status of motherboard0 [class motherboard_x58_ich10]
====================================================
Setup:
Top component : none
Instantiated : True
Attributes:
acpi : True
bios :
break_on_reboot : False
mac_address : 20:20:20:20:20:20
rtc_time : 2008-06-05 23:52:01
spi_flash :
system_clock : False
system_clock_class : clock
Connections:
dimm[0] : dimm0:mem_bus
socket[0] : processor0:socket
When doing more advanced configuration of a machine, it may be necessary to access configuration objects and their attributes directly. Each object in a component has a slot name that can be used for accessing the object. A list of slot names, and their mappings to actual configuration object names, is available from the output of the component's info command. The next example prints the frequency attribute from the core object.
simics> processor0.core[0][0]->frequency
[20000000, 1]
Accessing objects of non-instantiated components is not possible, since they do not have any associated configuration objects. But it is possible to access the pre_conf_objects of a non-instantiated component from Python. The following example works both for instantiated and non-instantiated components:
simics> @print(conf.processor0.core[0][0].cpuid_stepping)
8
Remember that not all configuration object attributes are available on a pre_conf_object. Only attributes that have been assigned by the component during initialization exists.
The Target Guide for each architecture lists and describes all components that are available.
An object can be identified using more than one name. This section describes the different ways of identifying an object.
All objects have a name that is used when printing log messages, writing checkpoints, in CLI commands, etc. The SIM_object_name function returns this object name. This name will be referred to as the object name in this section, even though an object can have several names for identification.
The object name is the name the object is given when created, or the objects location in the hierarchy.
An object can be given a name when created. The SIM_create_object, SIM_add_configuration, or SIM_set_configuration functions takes the object name as argument. The given name can be a string without dots "foo", a string with dots "cmp0.foo", an empty string "", or None. This section will describe how the given name affects the object name.
An object's hierarchical location is defined by its component and component_slot attributes. The hierarchical location for an object is the name of the component that the object's component attribute points at, and the component's component_slot attribute string, concatenated with a dot. For example, an object that belongs to a component named "cmp0" with the slot name "bar" has the hierarchical location "cmp0.bar".
All objects that reside in a slot in a component have valid component and component_slot attributes. It is the component's responsibility that the attributes are valid. The attributes are set when an object is added to a slot. A name that contains dots is a hierarchical location.
All objects also have an ID. The SIM_object_id function returns the object ID as a string. The object ID is unique, never changes, and will be saved in checkpoints. The object ID will not change even if the object is moved around in the hierarchy or is given a new name.
The object name and object ID are always unique. Creating an object and giving it a name that already exist will generate an error.
If the given name is a hierarchical location, an object will be added to that hierarchical location even if the component and component_slot attributes are not set. Simics will extract the component name and slot name from the given name. This information is then used when looking up the component and adding the object to the slot via the component interface. An object given the name "cmp0.cmp1.foo" belongs to the component "cmp0.cmp1" and has the slot name "foo". Note that the component "cmp1" in this example belongs to the component "cmp0".
An object given a name without dots, e.g., "foo", will get a name that is the hierarchical location of the object if the component and component_slot attributes are valid. Otherwise it will get the name "foo", which means that the object does not reside in any slot in a component. The object will also get an automatically assigned unique object ID, unless legacy_object_id is set. In that case the object name is used as object ID.
An object given a name with dots "cmp0.foo" gets the name "cmp0.foo" or, if it is put in the slot "bar", the name "cmp0.bar", its hierarchical location, and an object ID of the form "obj_XYZ".
An object given an empty name "", or None, will get a hierarchical location as name, if the component and component_slot attributes are valid, otherwise a name of the form "obj_XYZ". The object ID will always be of the form "obj_XYZ", identical to the object name if component and component_slot attributes are invalid.
| Given Name | Name (Slot = None) | Name (Slot = bar) | ID | Name After Move |
|---|---|---|---|---|
| foo | foo | cmp0.bar | obj_XYZ | cmp1.smurf |
| cmp0.foo | cmp0.foo | cmp0.bar | obj_XYZ | cmp1.smurf |
| None | obj_XYZ | cmp0.bar | obj_XYZ | cmp1.smurf |
The given name is the name that the user has provided. Name is the name the object gets when created, depending on if component and component_slot are set: Slot = None when they are not set; Slot = bar when they are set and component_slot is bar. ID is the unique object ID. Name After Move is the name the object gets after being moved to cmp1 to a slot named smurf.
Simics includes many customizable ready-to-run configurations. Because checkpoint files are by definition static, these example configurations are not checkpoint-based, but rather built on components and scripts to generate a working simulated machine.
The example configurations are located in separate directories for each system architecture: [simics]\targets\architecture. Each of these directories contains a number of Simics scripts (i.e., files containing Simics commands):
<machine>-common.simicscommon script uses the corresponding -system.include script to define the hardware, and the -setup.include script for software configuration. The -common.simics scripts may add additional hardware in some cases.These are the files you want to use to start the standard example machines in this directory.
\<machine\> in the script name is either a Linux machine name, or a some other name that defines the hardware/software combination.
<machine>-<feature>-common.simics-common.simics script with a new feature. Many minor features, such as the processor frequency, can be controlled using parameters to the common script, but features that are mutually exclusive are added as separate scripts. Typical examples are scripts that add different diff-files to the same disk image in the system setup.<architecture-variant>-system.include<machine>-setup.includeThe example configurations are designed to work with the disk images distributed with Simics. The machines are described in the Target Guide corresponding to each architecture.
Several machines may be defined for a given architecture, and thus the corresponding architecture directory will contain several machine-common.simics scripts.
There are several ways to customize the examples provided with Simics. They are listed below ordered by how simple they are to use.
Parameters
The machine scripts distributed with Simics can be modified by setting parameters (CLI variables) before the script is actually run. This is the easiest way to change the default configuration. Parameters can typically be used to change properties such as the amount of memory, the number of processors and the primary MAC address. The available parameters are listed in each Target Guide.
Setting parameters before the script is run can be done in two fashions:
Use the startup flag -e. The flag must be repeated for each parameter to set.
An example on Windows:
$ simics.bat -e '$freq_mhz = 2000' -e '$host_name = "target0"' targets/qsp-x86/firststeps.simics
An example on Linux:
$ ./simics -e '$freq_mhz = 2000' -e '$host_name = "target0"' targets/qsp-x86/firststeps.simics
Launch Simics without any script, set the parameters at CLI, and run the CLI command
run-script.
An example identical to the one above:
$ simics.bat
simics> $freq_mhz = 2000
simics> $host_name = "target0"
simics> run-script targets/qsp-x86/firststeps.simics
-common.simics file with a user defined script, the system can be configured more in detail while keeping the machine definition provided by the -system.include file. Similarly the -setup.include can be replaced to configure different software on the same machine.-system.include files use components to create their machine definitions. A complete description of components is provided earlier in this chapter.Below is another example of a simple configuration based on QSP-x86, that uses parameters to configure two machines slightly differently that both run in the same Simics session.
simics> $freq_mhz = 2000
simics> $host_name = "target0"
simics> run-script "%script%/firststeps.simics"
simics> $freq_mhz = 3000
simics> $host_name = "target1"
simics> run-script "%script%/firststeps.simics"
The parameters available for each predefined machine allows the user to do minor modifications. It is also possible to extend the ready-to-run configurations with additional components without creating new machine setups from scratch.
Since the machine setup scripts are located in the read-only master installation of Simics, they should not be modified. User files that add new components should instead be placed in the corresponding [project]\targets\architecture directory.
Here is a short example of how to extend the QSP-x86 to add a SATA disk:
# Add disk2
simics> $disk2 = (create-sata-disk-comp $system.disk2 size = $disk2_size)
simics> connect $system.mb.sb.sata_slot[2] $disk2.sata_slot
simics> instantiate-components
Notice, that script requires you to provide a disk image and a valid disk size. Essentially the script will run another script, firststeps.simics, which will create an instantiated QSP-x86 machine, then a SCSI disk is created and connected to that machine, and finally the new disk is instantiated.
It is possible to add many devices to an instantiated Simics machine in a similar manner. In the case a device must be added to the target machine before instantiation, write a script as described above.