This chapter shows you how to use the memory spaces in Simics. Memory spaces is a fundamental abstraction in Simics providing support for generic 64-bit address spaces into which memory and devices can be mapped. More concretely a memory space takes a stream of transactions to an address space and distributes them to devices mapped into the address space in a highly efficient manner while optionally providing address translations, byte swapping, and break point support. Memory space objects can be cascaded to form arbitrarily complex mappings and support dynamic reconfiguration and remapping at run time through attributes to support modeling of buses with dynamic addressing.
Simics memory-spaces are handled by the generic memory-space
class. A memory-space
object implements interface functions for memory accesses, and it has attributes specifying how the mappings are set up.
The most important attribute in a memory-space is the map
attribute. This is a list of mapped objects that may contain devices, RAM and ROM objects, and other memory-spaces. In addition to the map
attribute, there is also a default_target
attribute that is used for accesses that do not match any of the targets in the map list.
Python example of a memory-space
object where already created objects are mapped into a new memory space:
@mem = pre_conf_object('phys_mem', 'memory-space')
@mem.map = [[0x00000000, conf.ram0, 0, 0, 0xa0000],
[0x000a0000, conf.vga0, 1, 0, 0x20000],
[0x000c0000, conf.rom0, 0, 0, 0x10000],
[0x000f0000, conf.rom0, 0, 0, 0x10000],
[0x00100000, conf.ram0, 0, 0x100000, 0xff00000],
[0xfee00000, conf.apic0, 0, 0, 0x4000],
[0xffe81000, conf.hfs0, 0, 0, 16],
[0xffff0000, conf.rom0, 0, 0, 0x10000]]
@mem.default_target = [conf.pci_mem0, 0, 0, conf.pci_mem0]
@SIM_add_configuration([mem], None)
The fields for an entry in the map list are as follows:
map_info_t
struct
, which is passed as a parameter of all io_memory
interface functions. none
, 1 is bus
, 2 is bus-trans
and 3 is trans
. As the name suggests, none
performs no swapping while bus
swaps data based on the align-size setting. If any swapping is used, bus
is most common. It is also possible to swap all bytes of the access based on the access size by using trans
and finally combine the two swappings into bus-trans
. As an example, consider a mapping with a 4-byte align-size and memory at address 0 that contains the following bytes: 0x00 0x01 0x02 0x03
. A 2-byte big-endian read access at address 0 will give the following values as results. No swap: 0x0001
, bus swap: 0x0302
, bus and transaction swap: 0x0203
and transaction swap: 0x0100
.All mappings in a memory-space can be viewed with the <memory-space>.map
command. Example:
simics> board.mb.nb.pci_mem.map
Base Object Fn Offset Length Target Prio Align Swap
0xa0000 board.mb.gpu.dmap_space 0x0 0x20000 0
0xc0000 board.mb.shadow 0x0 0x40000 board.mb.shadow_mem 1
0xfec00000 board.mb.sb.ioapic 0x0 0x20 0 8
0xffe00000 board.mb.rom 0x0 0x200000 0
-default- board.mb.dram_space 0x0
Another useful command is devs
, that lists all mapped devices in the system.
simics> devs
Count Device Space Range Func/Port
0 chmmu0 phys_io0 0x0000040000400000 - 0x0000040000400047 0
0 e2bus24B_1 bus_pcicfg24B 0x0000000000000800 - 0x00000000000008ff 255
0 empty0_0 phys_io0 0x000007fff0800060 - 0x000007fff080006f 0
0 empty1_0 phys_io0 0x000007fff091e000 - 0x000007fff091e11f 0
0 fpost_data0 phys_io0 0x000007fff0104000 - 0x000007fff0105fff 0
0 glm0 bus_pcicfg25B 0x0000000000001000 - 0x00000000000010ff 255
[…]
It is also possible to modify mappings interactively from the command line, or from a script, by using the add-map
and del-map
memory-space commands. Try help <memory-space>.add-map
from the command line for more information or refer to the API Reference Manual.
Additionally memory mappings can be viewed in the GUI see Getting Started or the Simics User's Guide for details.
There are a few different kinds of memory mappings. All use the format described in the previous section.
translator
or the translate
interface. When an access reaches a translator mapping, the translate
function in the interface is called. Please refer to the documentation of the translator
and the translate
interfaces for more information about their usage.bridge
interface. The target field is set to the destination memory-space. If both a translator and a bridge are needed, they must be implemented by the same object. If an access is made where nothing is mapped, the memory-space by default returns the Sim_PE_IO_Not_Taken
pseudo exception. But if the access was made through a bridge mapping, the bridge device will be called to notify it about the unmapped access. It can then update any internal status registers, specify a new return exception, and set the data that should be returned in the case of a read access. Since the bridge is associated with the mapping and not the memory-space itself, several bridges can exist for one space, and devices doing accesses directly to the memory-space in question will not affect the bridge for non-mapped addresses. In the latter case, the device itself has to interpret the Sim_PE_IO_Not_Taken
exception. The Sim_PE_IO_Error
exception, indicating that a device returned an error is also sent to the bridge. Finally, bridges are called for accesses that generate Sim_PE_Inquiry_Outside_Memory
, i.e., an inquiry access where nothing is mapped. In this case the bridge may have to set a default return value, such as -1.Since memory-spaces can be mapped in other memory-spaces, it is possible to create loops where accesses never reach any target device. One typical case is a PCI memory-space with bridges that has both downstream and upstream mappings. In a real system, the bridge typically does not snoop its own transactions and there will be no loop. In Simics there are usually no bridge devices mapped between different memory-spaces, instead the bridge will create space-to-space mappings. The bridge has to be careful to avoid addresses which will cause loops between memory-spaces when accessed.
To catch invalid configurations Simics will make sure that an access does not loop by terminating it after 512 memory-space transitions. If this limit is reached, it is considered a configuration error and Simics will stop.