Tracing is a way to observe what is going on during the simulation. This section describes how to trace memory accesses, I/O accesses, control register writes, and exceptions in Simics.
The tracing facility provided by the trace module will display all memory accesses, both instruction fetches and data accesses.
First, launch the ebony-linux-firststeps.simics configuration, but not boot it. Second, create a tracer:
simics> new-tracer Trace object 'trace0' created. Enable tracing with 'trace0.start'. simics>
Now we are going to trace a few of instructions executed when booting Ebony. We execute 300 instructions without tracing first to reach a sequence of instructions that includes memory accesses:
simics> continue 300 [cpu0] v:0xfffff160 p:0x1fffff160 tlbwe r1,r4,1 simics> trace0.start Tracing enabled. Writing text output to standard output. simics> continue 6 inst: [ 1] CPU 0 <v:0xfffff160> [...] 7c240fa4 tlbwe r1,r4,1 inst: [ 2] CPU 0 <v:0xfffff164> [...] 7c4417a4 tlbwe r2,r4,2 inst: [ 3] CPU 0 <v:0xfffff168> [...] 38840001 addi r4,r4,1 inst: [ 4] CPU 0 <v:0xfffff16c> [...] 4200ffdc bdnz+ 0xfffff148 inst: [ 5] CPU 0 <v:0xfffff148> [...] 84050004 lwzu r0,4(r5) data: [ 1] CPU 0 <v:0xfffff1b8> [...] Read 1 bytes 0xc0 data: [ 2] CPU 0 <v:0xfffff1b9> [...] Read 1 bytes 0x0 data: [ 3] CPU 0 <v:0xfffff1ba> [...] Read 1 bytes 0x12 data: [ 4] CPU 0 <v:0xfffff1bb> [...] Read 1 bytes 0x10 inst: [ 6] CPU 0 <v:0xfffff14c> [...] 2c000000 cmpwi r0,0 [cpu0] v:0xfffff150 p:0x1fffff150 beq- 0xfffff170 simics>
Lines beginning with inst: are executed instructions. Each line contains the address (both virtual and physical) and the instruction itself, in both hexadecimal form and the mnemonic.
Lines beginning with data: indicate that some instructions are performing memory operations. Each line contains the operation address (again, both virtual and physical), the type of operation (read or write), the size and the value.
It is also possible to only trace accesses to a certain device. This is done with the trace-io command. In this example we are looking at in the interaction with the UART device.
simics> trace0.stop Tracing disabled simics> trace-io uart0 simics> continue 30_000 [cpu0 -> uart0] Write: 0x140000203 1 0x80 [cpu0 -> uart0] Write: 0x140000200 1 0x48 [cpu0 -> uart0] Write: 0x140000201 1 0 [cpu0 -> uart0] Write: 0x140000203 1 0x3 [cpu0 -> uart0] Write: 0x140000202 1 0 [cpu0 -> uart0] Write: 0x140000204 1 0 [cpu0 -> uart0] Read: 0x140000205 1 0x60 [cpu0 -> uart0] Read: 0x140000200 1 0 [cpu0 -> uart0] Write: 0x140000207 1 0 [cpu0 -> uart0] Write: 0x140000201 1 0 [cpu0 -> uart0] Read: 0x140000205 1 0x60 [cpu0 -> uart0] Write: 0x140000200 1 0xd [cpu0 -> uart0] Read: 0x140000205 1 0 [cpu0] v:0xfff8a634 p:0x1fff8a634 bl 0xfff8a608 simics>
trace-cr turns on tracing of changes in the processor's control registers.
simics> untrace-io uart0 simics> trace-cr -all simics> continue 6_500_000 [cpu0] tcr <- 0 [cpu0] dec <- 0 [cpu0] decar <- 0 [cpu0] tsr <- 0x8000000 [cpu0] decar <- 0x51615 [cpu0] dec <- 0x51615 [cpu0] tcr <- 0x4400000 [cpu0] ivpr <- 0 [cpu0] msr <- 0x29000 [cpu0] msr <- 0 [...] [cpu0] [cpu0] v:0x07fd8634 p:0x007fd8634 bl 0x7fd8608 simics>
We can single-step with the -r flag, to see what registers each instruction changes.
simics> untrace-cr -all simics> step-instruction -r 10 [cpu0] v:0x07fd8608 p:0x007fd8608 mftbu r3 [cpu0] v:0x07fd860c p:0x007fd860c mftbl r4 r4 <- 6529678 [cpu0] v:0x07fd8610 p:0x007fd8610 mftbu r5 [cpu0] v:0x07fd8614 p:0x007fd8614 cmpw r3,r5 [cpu0] v:0x07fd8618 p:0x007fd8618 bne+ 0x7fd8608 [cpu0] v:0x07fd861c p:0x007fd861c blr [cpu0] v:0x07fd8638 p:0x007fd8638 subfc r4,r4,r7 r4 <- 1384 [cpu0] v:0x07fd863c p:0x007fd863c subfe. r3,r3,r6 [cpu0] v:0x07fd8640 p:0x007fd8640 bge+ 0x7fd8634 [cpu0] v:0x07fd8634 p:0x007fd8634 bl 0x7fd8608 simics>
Simics can also monitor exceptions. Here we will trace all system calls.
simics> trace-exception System_call simics> c [cpu0] (@ cycle 203963506) Exception 8: System_call [cpu0] (@ cycle 205608905) Exception 8: System_call [cpu0] (@ cycle 205617423) Exception 8: System_call [...] [control-C] [cpu0] v:0xc01bc12c p:0x0001bc12c addi r10,r10,1 simics> untrace-exception -all simics>
Why do we need to create an object to trace instructions? This is because the tracing should be easy to customize to your needs. By changing some attributes, it is possible to choose what to trace on, and control the output format. You can also build your own tracer based on the source of this tracer. All attributes are described in the Reference Manual.