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 — Snapshots Models that support
checkpointing also work with in-memory snapshots. 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.
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. Memory transactions shall
however not explicitly use the connected interface but instead use
SIM_new_map_target() together with SIM_issue_transaction() on the
connected memory object. References between objects should be implemented
using attribute, with the type “o” for objects and “n” to allow no connection.
It is recommended that both variants are supported, i.e. “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 — Do not use explicit memory interface calls
Memory accesses shall not use direct interface calls for memory accesses
but shall instead use function SIM_issue_transaction()
on a map_target_t.
In Simics there are several memory interfaces. Each serving a different
purpose. For your device to be generic and easily integrated into
a platform it is best to be agnostic about which memory interface
the device is connected to.
GE-06 — 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-07 — 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-08 — 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-09 — Check for Memory Leaks A module should not
leak memory while running the simulation, including when taking checkpoints
and snapshots. 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.
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.
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-12 — 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.
size - 1. If this is not the case, a dictionary
attribute should be used instead of a list.gettimeofday() or rand().This 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.
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.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.
signal
interface should be used as input with one port interface for each reset
input.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.
For more information see the section on Ethernet transceiver in “Modeling Ethernet Devices” in the Model Builder User’s Guide.
ieee_802_3_phy_v3 interface. This interface is used when communicating with
PHY devices.mac_address attribute.signal Interface Ports for Input
Each interrupt input should be implemented using a port interface of the
signal type.bios
attribute that is the image file for the expansion ROM.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_frequencynum_cpusnum_coresmemory_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-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-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-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-script "%simics%/targets/qsp-x86/firststeps.simics"
$machine_name = machine2
run-script "%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.
- <span class="term">$create\_network</span> Boolean variable specifying if
a simulated Ethernet network link should be created together with the
system.
- <span class="term">$eth\_link</span>
The name of an existing Ethernet link object.
- <span class="term">$service\_node</span>
The name of an existing service node object.
- <span class="term">$service\_node\_ip\_address</span>
The IP address of the `$service_node` object on the `$eth_link` link.
- <span class="term">$dhcp\_pool\_ip</span> The first address in the pool of
IP addresses used for DHCP in the $service\_node.
- <span class="term">$dhcp\_pool\_size</span> The size of the IP address
pool used for DHCP in the `$service_node`. Set to 0 to disable DHCP.
- <span class="term">$network\_goal\_latency</span>
The requested network latency of the `$eth_link` link.
- <span class="term">$eth\_link\_gid</span> The global identifier for the
`$eth_link` link, used in distributed simulation.
</div>
$host_name
variable and then running the target start script (with the -local flag)
without getting any conflicts.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.
$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.
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.log-level 2),
changing output radix (<output-radix 16).