2.7 Getting data into the simulated system 2.9 Debugging Target Software
Getting Started  /  2 Tutorials  / 

2.8 Hardware inspection

One of the important reasons to use a simulator such as Simics is the ability to inspect hardware in a non-intrusive way. This section will describe various Simics features that facilitates hardware inspection.

  1. Inspection of registers in processors and devices.
  2. Controlling the logging system to obtain information on what is happening in the hardware.
  3. Using tracing to see what the simulation is doing.
  4. Using the instrumentation framework to obtain statistics about instructions, exceptions and caches.

2.8.1 Processor and device inspection

Here are some examples of how to inspect processors and devices, when running the

%simics%/targets/qsp-x86/firststeps.simics

target machine.

$ bin/simics targets/qsp-x86/firststeps.simics
simics> list-objects -local
┌─────────────────┬───────────────────┐
│     Object      │  Component Class  │
├─────────────────┼───────────────────┤
│board            │<chassis_qsp_x86>  │
│ethernet_switch0 │<ethernet_switch>  │
│service_node_cmp0│<service_node_comp>│
└─────────────────┴───────────────────┘
┌───────────────────┬─────────────────┐
│      Object       │      Class      │
├───────────────────┼─────────────────┤
│bp                 │<bp-manager>     │
│breakpoints        │<breakpoints-old>│
│default_sync_domain│<sync_domain>    │
│params             │<script-params>  │
│prefs              │<preferences>    │
│sim                │<sim>            │
└───────────────────┴─────────────────┘
simics> list-objects namespace = board -local
┌─────────────────┬───────────────────────┐
│     Object      │    Component Class    │
├─────────────────┼───────────────────────┤
│board.cdrom      │<sata_cdrom_comp>      │
│board.console    │<gfx_console_comp>     │
│board.disk0      │<sata_disk_comp>       │
│board.disk1      │<sata_disk_comp>       │
│board.mb         │<motherboard_x58_ich10>│
│board.serconsole │<txt_console_comp>     │
│board.serconsole1│<txt_console_comp>     │
│board.tablet     │<usb_tablet_component> │
└─────────────────┴───────────────────────┘
┌──────────────────┬──────────────┐
│      Object      │    Class     │
├──────────────────┼──────────────┤
│board.cell        │<cell>        │
│board.cell_context│<context>     │
│board.cell_rec0   │<recorder>    │
│board.software    │<os_awareness>│
└──────────────────┴──────────────┘
simics> list-objects -show-port-objects namespace = board.mb.cpu0 -tree
┐
├ apic[0] ┐
│         └ [0] ┐
│               ├ bank ┐
│               │      └ apic_regs 
│               └ port ┐
│                      └ freq_listener 
├ core[0] ┐
│         └ [0] ┐
│               └ vtime ┐
│                       ├ cycles 
│                       └ ps 
├ mem[0] ┐
│        └ [0] 
├ socket 
└ tlb[0] ┐
         └ [0] 
simics> list-processors
┌────────────────────────┬─┬─────────┬────────┬────────────────────────────────────────┐
│        CPU Name        │ │CPU Class│  Freq  │              Disassembly               │
├────────────────────────┼─┼─────────┼────────┼────────────────────────────────────────┤
│board.mb.cpu0.core[0][0]│*│x86QSP1  │2.00 GHz│cs:0x000000000000fff0 p:0x0fffffff0  nop│
└────────────────────────┴─┴─────────┴────────┴────────────────────────────────────────┘
* = selected CPU
simics> list-processors -disassemble
┌────────────────────────┬─┬─────────┬────────┬────────────────────────────────────────┐
│        CPU Name        │ │CPU Class│  Freq  │              Disassembly               │
├────────────────────────┼─┼─────────┼────────┼────────────────────────────────────────┤
│board.mb.cpu0.core[0][0]│*│x86QSP1  │2.00 GHz│cs:0x000000000000fff0 p:0x0fffffff0  nop│
└────────────────────────┴─┴─────────┴────────┴────────────────────────────────────────┘
simics> cpu
"board.mb.cpu0.core[0][0]"

simics> cpu # press tab twice to expand everything starting with cpu
cpu->  cpu-pages-dump  cpu-switch-time  cpu.  cpu.vtime.

simics> cpu. # press tab twice to expand child objects and commands
cpu.aprof-views                    cpu.break-vmread                    cpu.print-idt
cpu.bp-break-control-register      cpu.break-vmwrite                   cpu.print-mp-tables
...

simics> cpu-> # press tab twice to expand attributes
cpu->a20_inhibited                             cpu->ia32_unknown_3fe
cpu->a20mask                                   cpu->ia32_unknown_4b
...
simics> pselect "board.mb.cpu0.core[0][0]"
simics> pselect
"board.mb.cpu0.core[0][0]"
simics> board.mb.cpu0.core[0][0].print-processor-registers
16-bit legacy real mode
rax = 0x0000000000000000             r8  = 0x0000000000000000
rcx = 0x0000000000000000             r9  = 0x0000000000000000
rdx = 0x00000000000106a1             r10 = 0x0000000000000000
rbx = 0x0000000000000000             r11 = 0x0000000000000000
rsp = 0x0000000000000000             r12 = 0x0000000000000000
rbp = 0x0000000000000000             r13 = 0x0000000000000000
rsi = 0x0000000000000000             r14 = 0x0000000000000000
rdi = 0x0000000000000000             r15 = 0x0000000000000000

rip = 0x000000000000fff0

eflags = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 = 0x00000002
         I V V A V R - N I I O D I T S Z - A - P - C
         D I I C M F   T O O F F F F F F   F   F   F
           P F           P P                        
                         L L                        

simics> print-processor-registers
simics> output-radix 16
simics> %rdx
0x106a1
simics> list-classes -l substr = dmi -show-port-classes
The following classes have been registered:
┌───────────────────┬──────────────────────────────────────────────────┐
│       Class       │                Short description                 │
├───────────────────┼──────────────────────────────────────────────────┤
│osa_admin_emulator │deprecated OS awareness administrator             │
│x58-dmi            │Intel® X58 DMI unit                               │
│x58-dmi.HRESET     │                                                  │
│x58-dmi.io_regs    │                                                  │
│x58-dmi.msg        │legacy PCI INTx message to pci_interrupt converter│
│x58-dmi.pcie_config│                                                  │
│x58-dmi.phy        │                                                  │
└───────────────────┴──────────────────────────────────────────────────┘
simics> list-objects class = x58-dmi -all
┌──────────────────┬─────────┐
│      Object      │  Class  │
├──────────────────┼─────────┤
│board.mb.nb.bridge│<x58-dmi>│
└──────────────────┴─────────┘
simics> print-device-regs bank = board.mb.nb.bridge
Bank: io_regs
Offset  Name            Size  Value | Offset  Name         Size  Value
------------------------------------+---------------------------------
 0xcf8  config_address     4    0x0 |  0xcfc  config_data     4    0x0

Bank: pcie_config
Offset  Name                 Size    Value
------------------------------------------
   0x0  vendor_id               2   0x8086
   0x2  device_id               2   0x3400
   0x4  command                 2      0x0
   0x6  status                  2     0x10
   0x8  revision_id             1     0x13
   0x9  class_code              3  0x80000
   0xc  cache_line_size         1      0x0
   0xd  latency_timer           1      0x0
   0xe  header_type             1      0x0
   0xf  bist                    1      0x0
  0x2c  subsystem_vendor_id     2   0x8086
  0x2e  subsystem_id            2      0x0
  0x34  capabilities_ptr        1      0x0
  0x3c  interrupt_line          1      0x0
  0x3d  interrupt_pin           1      0x0
simics> print-device-regs bank = board.mb.nb.bridge pattern = vendor_id
Bank: pcie_config
Offset  Name       Size   Value
-------------------------------
   0x0  vendor_id     2  0x8086
simics> print-device-reg-info register = board.mb.nb.bridge.bank.pcie_config.vendor_id
Vendor ID [board.mb.nb.bridge.bank.pcie_config.vendor_id]

                  Bits : 16
                Offset : 0x0
                 Value : 32902 (0x8086)

Bit Fields:
    vendor_id @ [15:0] : 1000000010000110

When retrieving a register value for inspection or use in further code, it is better to use one of the commands designed for that purpose:

The command names have the following meanings:

simics> get-device-reg board.mb.nb.bridge.bank.pcie_config.device_id
0x3400
simics> get-device-offset board.mb.nb.bridge.bank.pcie_config offset = 2 size = 2
0x3400 (LE)

To sum up, we have shown a few simple ways in which the hardware can be inspected. One important point is that the inspection is non-intrusive, any software running on the target machine cannot notice anything of our inspection.

2.8.2 Logging

Simics hardware models generally output log messages for various kinds of events. The Simics log system offers a very powerful system for configuring which log messages to see - from which objects, at which level. The result is often large volumes of output. That output can be configured and sent to files for later inspection, as well as used in scripts to stop Simics or take other actions when a log message appears.

Here we will show some logging examples when running the

%simics%/targets/qsp-x86/firststeps.simics

target machine.

$ bin/simics targets/qsp-x86/firststeps.simics
simics> log-setup
Time stamp      : disabled
Picoseconds     : disabled
Real time       : disabled
Disassemble     : disabled
Log to console  : enabled
Include group   : disabled
Include level   : disabled
Log file        : disabled
simics> log-level board.mb.nb.bridge 2
[board.mb.nb.bridge] Changing log level: 1 -> 2
simics> log-level board.mb.nb.bridge
Current log levels:

Lvl  Object                              | Lvl  Object
-----------------------------------------+------------------------------------
  2  board.mb.nb.bridge                  |   2  board.mb.nb.bridge.port
  2  board.mb.nb.bridge.bank             |   2  board.mb.nb.bridge.port.HRESET
  2  board.mb.nb.bridge.bank.io_regs     |   2  board.mb.nb.bridge.port.msg
  2  board.mb.nb.bridge.bank.pcie_config |   2  board.mb.nb.bridge.port.phy
simics> log-type board.mb.nb.bridge info
board.mb.nb.bridge:
 enabled log types: "info"
 disabled log types: "error" "spec-viol" "unimpl" "critical"
board.mb.nb.bridge.bank:
 enabled log types: "info"
 disabled log types: "error" "spec-viol" "unimpl" "critical"
board.mb.nb.bridge.bank.io_regs:
 enabled log types: "info"
 disabled log types: "error" "spec-viol" "unimpl" "critical"
board.mb.nb.bridge.bank.pcie_config:
 enabled log types: "info"
 disabled log types: "error" "spec-viol" "unimpl" "critical"
board.mb.nb.bridge.port:
 enabled log types: "info"
 disabled log types: "error" "spec-viol" "unimpl" "critical"
board.mb.nb.bridge.port.HRESET:
 enabled log types: "info"
 disabled log types: "error" "spec-viol" "unimpl" "critical"
simics> run 1000
[board.mb.nb.bridge.bank.io_regs info] PCIe write 0xe0000001 to ff:0.1 offset 0x50, 4 bytes
simics> log-setup -time-stamp
simics> bp.log.break object = board.mb.nb.bridge.bank.io_regs type = info
Breakpoint 2: Break on 'info' log messages from board.mb.nb.bridge.bank.io_regs hierarchy
simics> run
[board.mb.nb.bridge.bank.io_regs info] {board.mb.cpu0.core[0][0] 0xfffecbf7 136713}
PCI read 0x0 from bus 0, device 31, function 0, register 68 (0x44, 1 bytes), PCIE address = 0xf8044
[board.mb.nb.bridge.bank.io_regs] Breakpoint 1: board.mb.nb.bridge.bank.io_regs log message of type info

To send all log outputs to a file, use log-setup logfile=<filename>. To overwrite an existing file, the -overwrite flag must be given. To stop output, use the command log-setup -no-log-file.

2.8.3 Tracing

Tracing is a way to observe what is going on during the simulation. Simics has a Breakpoint Manager that includes functionality for tracing various types of events. This means that messages (in fact, Simics log messages) are printed when an event of the specified occurs. Such a sequence of messages is what is here is known as a trace.

Here we will show some tracing examples when running the

%simics%/targets/qsp-x86/firststeps.simics

target machine.

$ bin/simics targets/qsp-x86/firststeps.simics
simics> bp.control_register.trace -all
[board.mb.cpu0.core[0][0] info] VMP not engaged. Reason: hap installed on CR0 read.
2
simics> run 1000
[bp.control_register trace] [trace:2] board.mb.cpu0.core[0][0] cr0 <- 0x40000023
[bp.control_register trace] [trace:2] board.mb.cpu0.core[0][0] cr4 <- 0x640
[bp.control_register trace] [trace:2] board.mb.cpu0.core[0][0] read of cr4
[bp.control_register trace] [trace:2] board.mb.cpu0.core[0][0] cr4 <- 0x640
simics> log-setup -time-stamp
simics> c 17450
[bp.control_register trace] {board.mb.cpu0.core[0][0] 0xfffec638 398442} [trace:2] board.mb.cpu0.core[0][0] read of IA32_APIC_BASE
simics> bp.delete -all
simics> bp.memory.trace address = 0 length = 100000 -r
simics> run 365_016_915 cycles
[bp.memory trace] {board.mb.cpu0.core[0][0] 0x836872 365415364} [trace:3]
board.cell_context 'r' access to v:0x10 len=4

Several other types of events can also be traced, such as target console string output and hits at specific source code lines.

2.8.4 Instrumentation

The Simics instrumentation framework has powerful ways to inspect the simulation. It is built on four core concepts:

At the Simics command line, it is the tools and filters that are manipulated. To see a list of available tools:

simics> list-instrumentation-tools substr = bank
┌──────────────────────┬──────────────────┬──────────────────────────────┐
│ Tool create command  │    Tool class    │         Description          │
├──────────────────────┼──────────────────┼──────────────────────────────┤
│new-bank-coverage-tool│bank_coverage_tool│register bank coverage tool   │
│new-bank-patch-tool   │bank_patch_tool   │device access miss repair tool│
└──────────────────────┴──────────────────┴──────────────────────────────┘

Here is an example of using instrumentation to compare user and supervisor mode instruction occurrences, when running the

%simics%/targets/qsp-x86/firststeps.simics

target machine.

$ bin/simics targets/qsp-x86/firststeps.simics
simics> new-instruction-histogram name = user_instr -connect-all
[board.mb.cpu0.core[0][0] info] VMP not engaged. Reason: instrumentation enabled.
Created user_instr (connected to 1 processor)
simics> new-instruction-histogram name = kernel_instr -connect-all
Created kernel_instr (connected to 1 processor)
simics> new-cpu-mode-filter name = usermode mode = user
Created filter usermode with mode user
simics> new-cpu-mode-filter name = kernelmode mode = supervisor
Created filter kernelmode with mode supervisor
simics> user_instr.add-filter filter = usermode
Added filter to 1 connections
simics> kernel_instr.add-filter filter = kernelmode
Added filter to 1 connections
simics> run 4 s
simics> user_instr.histogram max = 15
┌─────────┬────────┬────────┬───────┬───────────┐
│  Row #  │mnemonic│ Count  │Count% │Accumulated│
│         │        │        │       │  Count%   │
├─────────┼────────┼────────┼───────┼───────────┤
│        1│mov     │12137948│ 28.98%│     28.98%│
│        2│cmp     │ 3030796│  7.24%│     36.22%│
│        3│je      │ 2846035│  6.80%│     43.01%│
│        4│test    │ 2661377│  6.35%│     49.37%│
│        5│push    │ 2068299│  4.94%│     54.30%│
│        6│pop     │ 2022557│  4.83%│     59.13%│
│        7│jne     │ 1810666│  4.32%│     63.46%│
│        8│add     │ 1596786│  3.81%│     67.27%│
│        9│xor     │ 1540722│  3.68%│     70.95%│
│       10│lea     │ 1492439│  3.56%│     74.51%│
│       11│jmp     │ 1056509│  2.52%│     77.03%│
│       12│sub     │  914262│  2.18%│     79.22%│
│       13│ret     │  874834│  2.09%│     81.30%│
│       14│call    │  874753│  2.09%│     83.39%│
│       15│movzx   │  858974│  2.05%│     85.44%│
├─────────┼────────┼────────┼───────┼───────────┤
│# 15/149 │        │        │       │           │
│Sum (all)│        │41883708│100.00%│           │
│Sum shown│        │35786957│ 85.44%│           │
└─────────┴────────┴────────┴───────┴───────────┘
simics> kernel_instr.histogram max = 15
┌─────────┬────────┬────────┬───────┬───────────┐
│  Row #  │mnemonic│ Count  │Count% │Accumulated│
│         │        │        │       │  Count%   │
├─────────┼────────┼────────┼───────┼───────────┤
│        1│mov     │ 8427494│ 37.31%│     37.31%│
│        2│je      │ 1372749│  6.08%│     43.39%│
│        3│push    │ 1362419│  6.03%│     49.42%│
│        4│test    │ 1326411│  5.87%│     55.29%│
│        5│pop     │ 1315206│  5.82%│     61.12%│
│        6│cmp     │ 1227033│  5.43%│     66.55%│
│        7│xor     │  910401│  4.03%│     70.58%│
│        8│jne     │  868442│  3.84%│     74.42%│
│        9│add     │  723691│  3.20%│     77.63%│
│       10│lea     │  695604│  3.08%│     80.71%│
│       11│call    │  616243│  2.73%│     83.44%│
│       12│ret     │  597695│  2.65%│     86.08%│
│       13│and     │  534859│  2.37%│     88.45%│
│       14│sub     │  358369│  1.59%│     90.04%│
│       15│jmp     │  268310│  1.19%│     91.23%│
├─────────┼────────┼────────┼───────┼───────────┤
│# 15/108 │        │        │       │           │
│Sum (all)│        │22586736│100.00%│           │
│Sum shown│        │20604926│ 91.23%│           │
└─────────┴────────┴────────┴───────┴───────────┘

Here is another example of using instrumentation to show exception occurrences, when running the

%simics%/targets/qsp-x86/firststeps.simics

target machine.

$ bin/simics targets/qsp-x86/firststeps.simics
simics> new-exception-histogram name = exc_hist -connect-all
[board.mb.cpu0.core[0][0] info] VMP not engaged. Reason: instrumentation enabled.
Created exc_hist (connected to 1 processor)
simics> run 60 s
simics> exc_hist.histogram
┌─────┬────────────────────────────┬─────┬───────┬───────────┐
│Row #│         Exception          │Count│Count% │Accumulated│
│     │                            │     │       │  Count%   │
├─────┼────────────────────────────┼─────┼───────┼───────────┤
│    1│Page_Fault_Exception        │ 7956│ 44.22%│     44.22%│
│    2│Interrupt_64                │ 5312│ 29.52%│     73.74%│
│    3│Interrupt_34                │ 2720│ 15.12%│     88.86%│
│    4│Interrupt_35                │ 1535│  8.53%│     97.39%│
│    5│Interrupt_236               │  314│  1.75%│     99.14%│
│    6│Interrupt_48                │  112│  0.62%│     99.76%│
│    7│General_Protection_Exception│   21│  0.12%│     99.88%│
│    8│Interrupt_37                │   16│  0.09%│     99.97%│
│    9│NMI                         │    4│  0.02%│     99.99%│
│   10│Interrupt_40                │    1│  0.01%│     99.99%│
│   11│Interrupt_39                │    1│  0.01%│    100.00%│
├─────┼────────────────────────────┼─────┼───────┼───────────┤
│Sum  │                            │17992│100.00%│           │
└─────┴────────────────────────────┴─────┴───────┴───────────┘

Source code for instrumentation tools are in


    src/extensions/instruction-histogram
    src/extensions/exception-histogram
    src/extensions/cpu-mode-filter
  

in the Simics-Base package.

2.8.5 Connecting a cache model

Let us now show a simple example of how to use simple cache model in Simics. By default, Simics does not model any cache system. It uses its own memory system to achieve high speed simulation and modeling a hardware cache model would only slow it down. However, via the instrumentation framework, the flow of memory operations coming from the processor can be captured, and this allows modelling caches.

Here is an example of using instrumentation to connect a simple cache model, when running the

%simics%/targets/qsp-x86/firststeps.simics

target machine.

$ bin/simics targets/qsp-x86/firststeps.simics
simics> new-simple-cache-tool name = cachetool -connect-all
[board.mb.cpu0.core[0][0] info] VMP not engaged. Reason: instrumentation enabled.
Created cachetool (connected to 1 provider)
simics> cachetool.add-l1d-cache name = l1d line-size = 64 sets = 64 ways = 12 -ip-read-prefetcher prefetch-additional = 1
Created cache board.mb.cpu0.cache[0].l1d
simics> cachetool.add-l1i-cache name = l1i line-size = 64 sets = 64 ways = 8
Created cache board.mb.cpu0.cache[0].l1i
simics> cachetool.add-l2-cache name = l2 line-size = 64 sets = 1024 ways = 20 -prefetch-adjacent prefetch-additional = 4
Created cache board.mb.cpu0.cache[0].l2
simics> cachetool.add-l3-cache name = l3 line-size = 64 sets = 8192 ways = 12
Created cache board.mb.cpu0.l3
simics> run 55 s
simics> board.mb.cpu0.cache[0].l1d.print-statistics
┌─────┬───────────────────────────────────┬─────────┬─────┐
│Row #│              Counter              │  Value  │  %  │
├─────┼───────────────────────────────────┼─────────┼─────┤
│    1│read accesses                      │699427620│     │
│    2│read misses                        │  2905903│ 0.42│
│    3│write accesses                     │432645847│     │
│    4│write misses                       │  7196304│ 1.66│
│    5│prefetch accesses                  │  6509721│     │
│    6│prefetch misses                    │  4468886│68.65│
│    7│prefetched lines used              │  2828455│43.45│
│    8│evicted lines (total)              │ 14570325│     │
│    9│evicted modified lines             │  7651899│52.52│
│   10│entire cache flushes (invd, wbinvd)│        8│     │
│   11│uncachable read accesses           │110513271│     │
│   12│uncachable write accesses          │ 70608384│     │
└─────┴───────────────────────────────────┴─────────┴─────┘
simics> board.mb.cpu0.cache[0].l1d.print-statistics
┌─────┬───────────────────────────────────┬─────────┬─────┐
│Row #│              Counter              │  Value  │  %  │
├─────┼───────────────────────────────────┼─────────┼─────┤
│    1│read accesses                      │651920234│     │
│    2│read misses                        │  2659454│ 0.41│
│    3│write accesses                     │432965032│     │
│    4│write misses                       │  8850450│ 2.04│
│    5│prefetch accesses                  │  5561939│     │
│    6│prefetch misses                    │  3800816│68.34│
│    7│prefetched lines used              │  2176319│39.13│
│    8│prefetch instructions              │     1741│     │
│    9│evicted lines (total)              │ 15309952│     │
│   10│evicted modified lines             │  9257461│60.47│
│   11│entire cache flushes (invd, wbinvd)│        8│     │
│   12│uncachable read accesses           │ 56577895│     │
│   13│uncachable write accesses          │ 39917361│     │
└─────┴───────────────────────────────────┴─────────┴─────┘

Source code for cache model is in

    src/extensions/simple-cache-tool

in the Simics-Base package.

2.7 Getting data into the simulated system 2.9 Debugging Target Software