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.
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.
All machines are based on a top-level component. The top-level component is the root of the component hierarchy and is often a motherboard, backplane, or system chassis.
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.
A standalone component is a component that can be instantiated without being connected to a component hierarchy. A typical example is a hotplug device, such as a PC Card (PCMCIA) or an Ethernet link.
simics> import-pci-components simics> import-std-components simics> import-memory-components simics> import-ppc440gp-components
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 'ebony-board' component representing an Ebony Reference Board, called 'board'
simics> (create-ebony-board board cpu_frequency = 100 ....... mac_address0 = "00:04:ac:00:50:00" ....... mac_address1 = "00:04:ac:00:50:01" ....... rtc_time = "2003-09-03 11:17:00 UTC") .......The parentheses are needed to allow multi-line input. The command arguments set the processor frequency, the MAC addresses of the on-board network adapters, and the time and date of the real-time clock.
In multi machine configurations it is often useful to separate objects from the different machines by name. The command set-component-prefix str causes all following create- commands to prefix all created object names—including the names of the components themselves—with the string str.
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. A typical example of a hotplug multi connector is the Ethernet link.
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> board.info Information about board [class ebony-board] =========================================== Implementing objects: Connectors: ddr-slot0 : mem-bus down ddr-slot1 : mem-bus down emac0 : ethernet-link down hotplug emac1 : ethernet-link down hotplug pci-slot0 : pci-bus down pci-slot1 : pci-bus down pci-slot2 : pci-bus down pci-slot3 : pci-bus down uart0 : serial down hotplug uart1 : serial down hotplugSince the component in the example isn't instantiated yet, the list of implementing objects is empty. The ebony-board has two slots for DDR SDRAM modules, four PCI slots, two serial ports and two Ethernet ports. The memory slot is not listed as hotplug since DDR modules have to be inserted when the machine is configured initially, while serial and Ethernet ports support connect and disconnect in run-time. As the ebony-board is a top-level component, there are no up connectors.
To enable input and output for the simulated machine, the following commands create a serial text console and connects it to the uart0 connector of the Ebony board. Since the text console only has a single connector, it does not have to be specified in the connect command.
simics> board.connect uart0 (create-std-text-console) Created non-instantiated 'std-text-console' component 'text_console_cmp0'.Since no name is given the console component, a unique name will be assigned to it by the configuration system. The create- command returns the name of the newly created component, allowing it to be used as in the example above.
If the board only had a single serial connector, the uart0 connector name could have been left out as well.
Since the machine needs some memory to run, we also add a DDR memory module to our example. A CLI variable is used to hold the name of the memory component.
simics> $ddr = (create-ddr-memory-module rank_density = 128 module_data_width = 64) Created non-instantiated 'ddr-memory-module' component 'ddr_memory_module_cmp0'. simics> board.connect ddr-slot0 $ddr
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 Ebony board 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 name-space command provides static information about a component, such as the implementing objects and a list of connectors.
The status name-space command provides dynamic information about a component, such as attribute values and a list of all current connections. The output from status in the Ebony example:
simics> board.status Status of board [class ebony-board] =================================== Attributes: rtc_time : 2003-09-03 11:17:00 UTC cpu_frequency : 100 mac_address0 : 00:04:ac:00:50:00 mac_address1 : 00:04:ac:00:50:01 Connections: uart0 : text_console_cmp0 ddr-slot0 : ddr_memory_module_cmp0
The Eclipse-based User Interface includes a Configuration Browser where the configuration can be browsed visually.
simics> p -x (board.get-component-object cpu)->pcThe get-component-object is mainly useful in scripts, when running interactively it is easy to find object names using the info command, or list-objects.
The get-component-object command does not work for non-instantiated components since they do not have any associated configuration objects. But it is possible to access the pre_conf_objects of the non-instantiated component from Python using the get_component_object() function. This functions works for both instantiated and non-instantiated components, and Python code as in the following example works in both cases:
@print "0x%x" % get_component_object(conf.board, 'cpu').pc