Previous - Up - Next

4.7   Tracing

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.


Note: In the trace you can see one four-byte memory read that is split into four single-byte reads. This reflects how Simics models the accesses to the flash memory it reads from.

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> 


Note: You can use underscores anywhere in numbers to make them more readable. The underscores have no other meaning and are ignored when the number is read.

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> 


Note: There are variants of trace-io, trace-cr and trace-exception that will stop the simulation when respective event occur. These commands begin with break-.

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.

Previous - Up - Next