This chapter provides a checklist for use when developing models of devices and systems for Simics. The intention is to help developers with creating high quality models that work well in Simics, including future versions, that behave in a way that Simics users expect models to, and that can be used together with other device models easily.
This section describes important generic items that should be taken into consideration when working with Simics. This applies if one is writing device models, components or general functionality to extend Simics.
GE-01 — Checkpointing
Device models and other Simics extensions must support checkpointing. All state associated with the modeled machine should be included in the checkpoint. The simulation session is not checkpointed. Simply loading a machine, taking a checkpoint without having advanced the simulation and restarting from that checkpoint should result in the same machine state. The same should be true at anytime during the simulation and care must be taken to checkpoint any transient state in a module, such as pending events.
For more information refer to the sections about events and attributes in "Programming with DML", the section about general usability in "Building Well-Behaved Models" and the section about configuration attributes in "Overview" in the Model Builder User's Guide. Also refer to the section "Configuration and Checkpointing" in the Simics User's Guide
GE-02 — Reverse Execution
Models that are deterministic and support checkpointing also work with reverse execution. But the performance of the attribute get/set methods, as well as their memory consumption, are more important. Use image
objects for storing data-type attributes, such as internal memories, of more than a few kilo bytes. This can have dramatic effects on performance, especially when reverse execution is enabled. See also GE-13.
For more information refer to the sections about events and attributes in "Programming with DML", the section about general usability in "Building Well-Behaved Models" and the section about configuration attributes in "Overview" in the Model Builder User's Guide. Also refer to the section "Configuration and Checkpointing" in the Simics User's Guide
GE-03 — Use the Most Recent API
The most recent version of the Simics API should be used. Functions and interfaces marked as deprecated should be avoided.
The latest API is documented in the Reference Manuals included in each Simics package.
GE-04 — Use Standard Simics Interfaces
The Simics interface mechanism should be used when communicating between objects. The standard interface types should be used when possible, allowing newly developed objects to connect to existing ones. References between objects should be implemented using attribute, with the type "os" for port interfaces, "o" for interfaces implemented by the object without any port and "n" to allow no connection. It is recommended that all three variants are supported, i.e. "os|o|n".
For more information see the section about Simics interfaces in "Overview" in the Model Builder User's Guide. The standard interfaces are documented in the Reference Manuals included in each Simics package.
GE-05 — Host Independence
Code should be written to work on both little- and big-endian host systems. Operating system specifics should be avoided if possible, allowing code to run on Windows and Linux. Any access to the host, for example a real network, real display, real USB, etc, should be in a separate "host access" module and not in the device itself
GE-06 — Use Compiler to Catch Possible Errors
All code should compile without warnings. It is recommended that the default flags for the compiler in the Simics build environment are used. For GCC, this is something like -O2 -Wall -Werror
.
GE-07 — Implement info
and status
Commands
All Simics classes should have an info
and a status
command. The info
shows static information about an object. Required attributes used for configuration are typically presented here. The status
command shows dynamic information about an object. For really detailed information, a class specific command is better suited. Objects that do not have any dynamic information should print this fact in the status
command output.
For more information refer to the section about general usability in "Building Well-Behaved Models" in the Model Builder User's Guide.
GE-08 — Check for Memory Leaks
A module should not leak memory while running the simulation, including when taking checkpoints and using reverse execution. The internal Simics command mm-list-*
can be used to see where memory has been allocated. To enable the command, set the environment variable SIMICS_MEMORY_TRACKING
before starting Simics and enable internal commands, using the enable-unsupported-feature "malloc-debug"
command.
For more information see the application note on Debugging User-Developed Simics Modules.
GE-09 — No Side Effects on Attribute Reads
There should never be any side effects when attributes are read. It should always be possible to read out attribute values without affecting the model.
For more information refer to the sections about attributes in "Programming with DML" and the section about configuration attributes in "Overview" in the Model Builder User's Guide.
GE-10 — Class, Attribute and Command Documentation
Classes, non-internal attributes and CLI commands should all be properly documented. For attributes that users may change, all allowed values have to be described.
For more information refer to the sections about structuring DML code in "Building Well-Behaved Models" and "Adding New Commands" in the Model Builder User's Guide.
GE-11 — Follow Naming Guidelines
Try to use coherent naming when creating files, classes, components, objects, attributes and commands in Simics. As a general rule, use lower case names. Abbreviations may be written in all capital letters, but avoid mixing upper and lower case letters, e.g., do not use capitalization. Avoid special characters and stick to plain ASCII.
-comp
suffix. list-objects
.Look at the existing naming for things not covered by the guidelines here.
GE-12 — Avoid Using Indexed Attributes
Index support for attributes should only be added if it is really needed for performance reasons. When lists attributes have index support, the index should run from 0 up to size
- 1. If this is not the case, a dictionary attribute should be used instead of a list.
GE-13 — Write Deterministic Models
A simulation model should behave exactly the same way when it is run with identical external stimuli (e.g., using a recorder, or only scripted input). Never use host functions that do not behave identically between runs in your model, such as gettimeofday()
or rand()
.
This is essential for reverse execution to work correctly, and greatly helps in pinpointing bugs, as those are guaranteed to be repeatable in a deterministic simulation.
For more information refer to the section about general usability in "Building Well-Behaved Models" in the Model Builder User's Guide.
GE-14 — Check Spelling
All user visible strings should be checked for correct spelling and grammar.
GE-15— Do not Assert on User Errors
Errors that can be triggered by a user, for example by running target software that does not follow the specification should not cause Simics to assert. For errors signalling use log messages of the "info", "spec-violation" or "error" type depending on severity. Assert should only be used to protect against bugs in the simulator code.
GE-16 — Do Not Use Deprecated Features
Avoid using features listed as deprecated in the Simics Migration Guide. Check the prefs
object for settings (attributes) whose names start with legacy_
. Make sure your system works with all such settings turned off. Also run Simics with the -wdeprecated command line argument and make sure that there are no run-time warnings generated during simulation.
GE-17 — Avoid Saving Attributes as Binary Data
Structured attribute data should not be saved in binary form, since it prevents user inspection, for example by the info and status commands, and makes it difficult to keep compatibility with old checkpoints. Binary data should only be used when saving memory images and similar.
This section describes important items that, in addition to the generic checklist, should be taken into consideration when writing device models. For more in depth understanding of the importance of these items, please refer to the Model Builder User's Guide.
DE-01 — Source Code in DML
Device models should in general be written in DML. Example of an exception to this rule is code for algorithms already available, or better expressed, in some other language.
DE-02 — Reset Support
Models of devices with one or more reset inputs should properly implement reset. The Simics signal
interface should be used as input with one port interface for each reset input.
DE-03 — Logging
The standard Simics log mechanism should be used to trace things happening in the device. It is important that target software access to unimplemented registers and features of the device are properly logged with the correct type.
A message is most of the time a fragment or, more rarely, one or more complete sentences. If it is a fragment, the message shall start with a lowercase letter (with the obvious exception for words and abbreviations that shall start with an uppercase letter) and have no period at the end. Sentences shall start with an uppercase letter and end with a period.
In DML, a typical log statement may read: log info, 2, 0: "increased counter: %d", value;
.
Do not use exclamation marks and avoid question marks. Multiple question marks in a row shall never be used.
Do not start an "info" message with the words "error", "unimplemented" or "spec_violation", use the appropriate log-type instead.
Do not start an "error" message with the word "error", it is just a repetition. The word "error" might be appropriate inside the message but should in most circumstances be avoided. Same goes for the "critical", "spec_violation", and "unimplemented" log-types.
Do not use newlines, in particular not at the end of the message. Also do not use multiple log statements to output longer messages, include everything in one statement. It is up to the presentation layer to output a long message in a readable format.
Do not mention the name of the object or class which the message refers to, as it is implicitly given by the log statement and output in the log message prefix.
For abbreviations and other special words, write them as specified in the "Dictionary" chapter of the "Writing Documentation" manual or in the src/docs/common/simics-documentation-word-list
or src/docs/internal/documentation-manual/usage.docu
files. Here are some examples: IRQ, DMA, CPU, CPUs.
A message followed by a more specific message, such as: "can't open file "abc": no such file or directory"
should be (as above) separated by a colon. If even more specific messages follow, these are also appended using a colon as separator.
A message which contains some extra information at the end should be written as: "read from register XYZ (value = 0x5000)"
Do not use cryptic abbreviations such as @, addr, idx, reg, len. Instead use: at, address, index, register, length
Do not use variable names (if they aren't complete words) in log messages with log levels 1-3. If values are output, it should be possible to understand what the value represents without reading the source code. I.e. it should be possible to understand the log message without reading the source code.
Do not use assert statements on conditions that can be triggered by users, see GE-15.
Use pre-defined DML templates for different implementations. Log level is automatically handled in some of these templates. For example, reserved
, unimplemented
and read_only
. Full list and descriptions about these templates can be found in the Model Builder DML 1.2 reference manual.
Spec-violation and unimplemented messages are typically logged on level 1. Sometimes they are first logged at log level 1 then log level 3 for spam reduction when unimplemented registers or features are always accessed. log level 3 should be avoided for spec-violation.
For more information refer to "Logging" in the Model Builder User's Guide.
DE-04 — Avoid SIM_
Functions when Modeling Behavior
Code that models the behavior of a device should avoid SIM_
and internal VT_
functions as far as possible. Such functions are mainly intended for simulator specifics such as configuration and logging, but not to model the actual device. Simics interfaces should be used instead to communicate with other objects that a device is connected to. The most common exceptions are SIM_
functions used to access fields in the generic_transaction_t
, timing API functions and event API functions for devices not written in DML.
DE-05 — Avoid Attribute Access when Modeling Behavior
Simics attributes are intended for configuration and diagnostic access to a device. Communication between devices should use Simics interfaces and not rely on reading or writing attributes.
For more information see the section about Simics interfaces in "Overview" in the Model Builder User's Guide. The standard interfaces are documented in the Reference Manuals included in each Simics package.
DE-06 — Handle Persistent Storage
Some kinds of storage are persistent and survive power cycling, for example NVRAMs, certain device registers, and disk images. Models of such entities should be handled as persistent in Simics, allowing the save-persistent-state
and load-persistent-state
commands to work properly for simulating power off followed by power on. To check which images are marked as persistent, use the list-persistent-images
command.
The image
interface on objects of the Simics image
class provides a way to mark an image object as holding persistent data. Custom disk and storage models must call this interface on their associated image objects, if they are persistent.
Device register and device state saved in attributes are marked as persistent by using the Sim_Attr_Persistent
flag on the attribute when it is registered with Simics.
For NVRAMs the persistent-ram
class can be used.
For more information see the section about saving and restoring persistent data in "Configuration and Checkpointing" in the Simics User's Guide
DE-07 — Use DML Device Class Library Code
Device models should share common code if possible, such as the generic PCI,
I2C or MII device code, see the Model Builder User's Guide.
DE-08 — Document Limitations
Parts and features of a device that is not modeled should be described in documentation. For devices written in DML, use the limitations
parameter. For devices not written in DML add the information to the class documentation. Use free form complete sentences or bullet lists:
<ul>
<li>The X device does not implement Y hashing.</li>
<li>The Z feature does not work with the Windows 7 driver.</li>
<li>...</li>
</ul>
See the DML 1.4 Reference Manual for more information.
Unimplemented registers, or registers with limited functionality, should use the standard Simics log mechanism with the Sim_Log_Unimplemented
type to log any accesses.
DE-09 — Performance
Devices should be written with performance in mind. In general this simply
means avoiding expensive operations and using events instead of polling. The
Model Builder User's Guide includes a discussion on performance for device
models.
DE-10 — Internal Device to Device Register Access
Device objects should use the int_register
interface if it has to access registers in another object directly. The typical case is for objects that represent tightly coupled devices. In other situations the devices can use the architecturally specified way of communicating, for example by doing memory mapped accesses or sending bus transactions if a bus interface exists.
The int_register
interface is documented in the Simics Reference Manual
DE-11 — Handle inquiry accesses
Device objects should handle inquiry accesses without performing any side effects beyond changing the state of the register itself. This is done automatically for registers which does not override the read_access
and write_access
methods, but if you override these methods or implement the access at the bank level you have to implement it yourself.
DE-12 — Reboot Support
A machine model should support system reboot. This means software reboot and commands to trigger any reset buttons. Reset signals are typically distributed between simulated devices using the signal
interface unless reset is already part of some technology specific interface such as the pci_device
interface.
DE-13 — Optional attributes should be optional
Any optional attribute should be truly optional. It should make sense and be possible to instantiate the object without setting any optional attributes. Accesses to the device should not cause simulation errors if any optional attributes are not set, for example dereferencing a NIL pointer for an optional object attribute.
DE-14 — Support Multiple Instantiation
It should always be possible to create multiple instances of a device model, for example to have several similar systems networked together.
DE-15 — Use Standard Memory Classes When Possible
When modeling address spaces, reusing the Simics memory-space
or port-space
classes is almost always possible. Similarly, the ram
, rom
and persistent-ram
classes should be used to model RAM and ROM. This is true also for on-chip memory, unless the memory is very small, perhaps a few kilobytes or less. The storage for larger memory areas should be implemented using the standard image
class, that provides delta checkpointing and efficient run-time memory handling.
DE-16 — Only Use the Device API
When writing device models only the Device API should be used. API function, and interfaces, from the Simulator API should not be used. The Device API is documented in the Model Builder User's Guide. See also DE-04 about avoiding SIM_
functions.
DE-17 — Support Deletion
It should be possible to delete object of the device class. All allocated memory should be freed, events should be cancelled, etc.
ET-01 — Separate Transceiver (PHY) Model
Ethernet devices where the transceiver is visible to the software, for example exposed by the MII or similar interface, should have the transceiver modeled as a separate object in Simics. This allows for reuse of transceivers and a number of such models already exist, including a generic MII transceiver.
For more information see the section on Ethernet transceiver in "Modeling Ethernet Devices" in the Model Builder User's Guide.
ET-02 — Bandwidth Limitation
Ethernet devices should use the standard bandwidth limitation support provided by the ieee_802_3_phy_v3
interface. This interface is used when communicating with PHY devices.
ET-03 — Configurable MAC Address
Ethernet devices should provide a way to set the Ethernet MAC address when setting up the system. Typically by providing a mac_address
attribute.
signal
Interface Ports for Inputsignal
type. print-pci-config-regs
Command<pci-device>.print-pci-config-regs
command should be supported by all PCI devices. bios
attribute that is the image file for the expansion ROM. SE-01 — Intentionally left out.
SE-02 — Support Baud Rate but Allow Override
Serial devices should obey the baud rate setting since software may not work with an unrealistic timing behavior. Still, for simulator performance reasons, it is often of interest to optionally run faster in virtual time than the actual device would.
This section describes important items that, in addition to the generic checklist, should be taken into consideration when writing processor models. For more information about processor models, see the Processor Model Integration Guide.
This section describes important items that, in addition to the generic checklist, should be taken into consideration when writing components. For more in depth understanding of the importance of these items, please refer to the Model Builder User's Guide.
CO-01 — Checkpointing of Connection Information
Information that a component receives from another component in a connect method call may have to be checkpointed in case that information has to be used again. This is sometimes the case with hot-plug connections.
CO-02 — Naming of Components and Objects
Until there are proper guidelines for component, connector, and object names, check existing objects in Simics for examples. Some common names are:
eth_adapter
— basename for Ethernet PCI cards. ethernet
— ethernet-link connector name for components with a single ethernet-link connector. CO-03 — Use Standard Connector Types When Possible
The standard component connector types are listed in the Model Builder User's Guide. By using the standard types, the component can more easily be reused in other systems.
CO-04 — Correct Component Abstraction
Components should represent real separate hardware entities with standard hardware interfaces, such as PCI or Ethernet. It should only be possible to build valid systems using components and their connectors. More low-level kinds of connections should be done between configuration objects within the components.
CO-05 — Implement Standard Attributes and Names
Components should implement standard attributes, and in some cases have well
defined sub-strings in their names, that are used by the GUI to extract
system information. This applies to top-level components, components with
memory, Ethernet connectors or disks on them. A complete list is included in
the section about component references in "Components" in the Model Builder
User's Guide. Some commonly used component attribute names are:
cpu_frequency
num_cpus
num_cores
memory_megs
— for components with RAM. rtc_time
— format: "YYYY-MM-DD HH:MM:SS Z". mac_address
— single Ethernet device. mac_address0, mac_address1, ...
— multiple Ethernet devices. size
— for disk components. CO-06 — Slot Names
The slot names in the component should be chosen with care since there can
be name conflicts with attributes and commands for the component. The
priority order for conflicting names are defined in the Model Builder
User's Guide.
CO-07 — Intentionally left out.
CO-08 — Component Error Handling
It should always be possible to create a non-instantiated component as long as the provided arguments are valid. If the component requires any external file, for example, then it should check for its existence and possibly signal any error in the pre_instantiate
method. The connect_<connection>()
, add_objects()
and post_instantiate()
methods should never trigger any errors.
CO-09 — Optional Attributes
Component attributes should in general be made optional with well chosen default values instead of being required.
CO-10 — On-board Software
Boot software such as BIOS, OBP and other firmware that is resident on the hardware should be setup as part of the component. If changing the firmware makes sense, then there should be a configuration attribute to set the image file to use.
This section describes important items that, in addition to the generic checklist, should be taken into consideration when assembling a larger system. See also the "Target Script Checklist".
SY-01 — Reuse of Existing Models
Since developing a new device model may involve a lot of work, it is a good idea to make sure that no previous model of the device exists. Also similar device models can be useful if code can be shared between them.
SY-02 — Build SimicsFS for Linux Target
If Linux is supported for the target system, then a SimicsFS kernel module should be built and installed on the Linux image.
SY-03 — Moved to ST-01.
SY-04 — Moved to ST-02.
SY-05 — Moved to ST-06.
SY-06 — Moved to ST-08.
SY-07 — Moved to ST-17.
SY-08 — Moved to ST-18.
SY-09 — Moved to ST-20.
SY-10 — Only Create Device Objects from Components
All objects implementing the functionality of a target system should be created by components. There should not be any model objects created automatically when loading modules. Also target scripts should only create component objects and no other model objects.
This section describes important items that, in addition to previous checklists, should be taken into consideration when writing the target scripts for a virtual platforms.
ST-01 — Follow Machine Script Guidelines
The .simics
and .include
scripts for a machine should follow the
guidelines in the section about ready-to-run configurations in
"Configuration and Checkpointing" in the Simics User's Guide. For example
the setup of the simulated hardware should be separate from the software
configuration. See also "System Configurations" in the Model Builder User's
Guide.
ST-02 — Possible to Start from All .simics
Scripts
It should be possible to start any .simics
file from scratch. Scripts that require other files to have run first, or require CLI variables to be set, should have the .include
suffix.
ST-03 — Location Independence
It should be possible to launch a target script in Simics no matter what the current directory of Simics is. The %simics%
path marker can be used to reference other scripts in a Simics project, the same, or other packages.
ST-04 — Do not Advance the Simulation
A target script should not run the simulation, but start all processors at step and cycle 0. Script branches can be used to automate setup needed while the system is booting although adding support for it in a system component is recommended, to make sure checkpoints can be taken early.
ST-05 — Supply System Information for GUI Views
The target viewer should report correct information about the system in the built-in Winsome GUI.
ST-06 — Proper Command Error Handling
Errors that are detected in a script should be reported using the interrupt-script
command. Using the quit
command is not advisable in scripts since it will close the interactive session for a user. It is not needed either since Simics will exit on errors anyway when run in batch mode.
ST-07 — Check for External Files
If the script uses files which are not included in the same package, it should verify their presence before referencing them and, if needed, interrupt the script. The lookup-file
command searches for a file and, if not found, it emits an error message and interrupts the script. Otherwise, use the two commands file-exists
and interrupt-script
.
ST-08 — Naming of the Top Component
A machine script (<architecture>-system.include
) should create the top level component with the name configured by the $machine_name
variable. If this variable is not set, it should default to the system name. The name of the created component should then be saved in $system
. It will typically be the same as $machine_name
unless there is a name collision. See also "System Configurations" in the Model Builder User's Guide.
For example:
(in decl) param machine_name : string = "board"
$system = (create-chassis-qsp-x86 name = $machine_name)
As a result, multiple machines can be instantiated in the following way:
$machine_name = machine1
run-command-file "%simics%/targets/qsp-x86/firststeps.simics"
$machine_name = machine2
run-command-file "%simics%/targets/qsp-x86/firststeps.simics"
The old component prefix support should not be used anymore as it will be removed in the future.
ST-09 — Use Common Script to Create Ethernet Network
If applicable to the system being modeled, use the targets/common/add-eth-link.include
script to create a simulated Ethernet network and to configure the service-node.
ST-10 — Include an Ethernet Network
Target scripts should create an Ethernet network by default and connect the primary Ethernet adapter of the system to it.
ST-11 — No Connection to the Real Network
Target scripts should not connect the virtual Ethernet network to the real network by default.
ST-12 — Allow Parameterization
Target scripts should allow users to modify its behavior by setting parameters using CLI variables. All parameters should be optional and have good default values. For boolean variables, TRUE/FALSE should be used. See also ST-13.
ST-13 — Use Standard Parameter Variables
The following standard variables should be implemented if applicable for the target system:
$cpu_cores
. $num_cpus
would be misleading. $disk_image
, if it cannot be automatically determined from the file. "YYYY-MM-DD HH:MM:SS UTC"
format. The following variables are automatically supported if the targets/common/add-eth-link.include
script is used to create a virtual Ethernet network. Scripts creating their own Ethernet network without using add-eth-link.include
should support some subset of these variables.
$service_node
object on the $eth_link
link. $service_node
. Set to 0 to disable DHCP. $eth_link
link. $eth_link
link, used in distributed simulation. ST-14 — Do not Leak CLI Variables
CLI variables are global by default. Scripts should try to make variables local if possible, or unset them after use, to avoid conflicts with other scripts. See also ST-15.
ST-15 — Support Multi-Machine Setup
It should be possible to create multiple target machines by setting the $host_name
variable and then running the target start script (with the -local
flag) without getting any conflicts.
ST-16 — Configure OS Awareness
All top-level components should have software
slot with an os_awareness
component in it. This is typically created in the <architecture>-system.include
script:
new-os-awareness $system.software
If the OS awareness framework in Simics supports the operating system that is configured on the machine, then a parameter file should be created that matches the operating system and that is loaded in the software setup script (i.e. the <architecture>-<software>-setup.include
file), typically using:
$system.software.load-parameters <architecture>-<software>.params
For more details refer to the section "OS Awareness Details" in the Analyzer User's Guide.
ST-17 — Do Not Reference Objects by Name
Simics scripts should not expect that objects created as part of components will get certain names. When creating a component, the returned component name can be saved in a variable for later use.
$console = (new-text-console-comp)
$console.con->title = "new title"
When referencing component and objects created by another machine script, the $system
variable (ST-08) will provide a reference to the top-level component created by that script.
ST-18 — Set Up a Valid Cell Partitioning
Check that the cell partitioning set up by the script is correct by using
check-cell-partitioning
, both after the script has run and for checkpoints
taken of the system. For more information see the section on simulation
cells in the "Multithreading" section of the API Reference Manual.
ST-19 — Keep default global simulation settings
Scripts should not modify default simulation settings. Examples of settings that should not be done in scripts: changing log-level (log-level 2
), explicitly enabling reverse execution (enable-reverse-execution
).
ST-20 — Keep Target Scripts Simple
While following the guidelines in this section, also try to keep the target scripts as simple as possible. Avoid switching between Python and CLI for example. If Python code is needed in a target script, then some component is probably not powerful enough or some new CLI command is needed.