gem5を構成するSimObjectを追加するためのチュートリアルをやってみる。
前章で作成したSimObjectの標準出力をデバッグ機能に変更してみる。
gem5はprintfスタイルのトレース・デバッグ機能をサポートしており、これを使うためにはdebug flagを使用する。このフラグによってすべてのコンポーネントがdebug-print文を使用することができる。gem5を実行したとき、debug flagを使用してどのデバッグオプションを使用するか指定できる。
デバッグフラグの使用
例えば、simple.pyスクリプトにおいてDRAM
デバッグフラグを使用することによって、以下のような出力を得ることができる。これによって非常に多くのデバッグ情報が出力されることに注意すること。
$ ./build/X86/gem5.opt --debug-flags=DRAM configs/learning_gem5/part1/simple.py | head -n 50
gem5 Simulator System. http://gem5.org DRAM device capacity (gem5 is copyrighted software; use the --copyright option for details. gem5 compiled Jan 3 2017 16:03:38 gem5 started Jan 3 2017 16:09:53 gem5 executing on chinook, pid 19223 command line: build/X86/gem5.opt --debug-flags=DRAM configs/learning_gem5/part1/simple.py Global frequency set at 1000000000000 ticks per second 0: system.mem_ctrl: Memory capacity 536870912 (536870912) bytes 0: system.mem_ctrl: Row buffer size 8192 bytes with 128 columns per row buffer 0: system.remote_gdb.listener: listening for remote gdb #0 on port 7000 Beginning simulation! info: Entering event queue @ 0. Starting simulation... 0: system.mem_ctrl: recvTimingReq: request ReadReq addr 400 size 8 0: system.mem_ctrl: Read queue limit 32, current size 0, entries needed 1 0: system.mem_ctrl: Address: 400 Rank 0 Bank 0 Row 0 0: system.mem_ctrl: Read queue limit 32, current size 0, entries needed 1 0: system.mem_ctrl: Adding to read queue 0: system.mem_ctrl: Request scheduled immediately 0: system.mem_ctrl: Single request, going to a free rank 0: system.mem_ctrl: Timing access to addr 400, rank/bank/row 0 0 0 0: system.mem_ctrl: Activate at tick 0 0: system.mem_ctrl: Activate bank 0, rank 0 at tick 0, now got 1 active 0: system.mem_ctrl: Access to 400, ready at 46250 bus busy until 46250. 46250: system.mem_ctrl: processRespondEvent(): Some req has reached its readyTime 46250: system.mem_ctrl: number of read entries for rank 0 is 0 46250: system.mem_ctrl: Responding to Address 400.. 46250: system.mem_ctrl: Done 77000: system.mem_ctrl: recvTimingReq: request ReadReq addr 400 size 8 77000: system.mem_ctrl: Read queue limit 32, current size 0, entries needed 1 77000: system.mem_ctrl: Address: 400 Rank 0 Bank 0 Row 0 77000: system.mem_ctrl: Read queue limit 32, current size 0, entries needed 1 77000: system.mem_ctrl: Adding to read queue 77000: system.mem_ctrl: Request scheduled immediately 77000: system.mem_ctrl: Single request, going to a free rank 77000: system.mem_ctrl: Timing access to addr 400, rank/bank/row 0 0 0 77000: system.mem_ctrl: Access to 400, ready at 101750 bus busy until 101750. 101750: system.mem_ctrl: processRespondEvent(): Some req has reached its readyTime 101750: system.mem_ctrl: number of read entries for rank 0 is 0 101750: system.mem_ctrl: Responding to Address 400.. 101750: system.mem_ctrl: Done 132000: system.mem_ctrl: recvTimingReq: request ReadReq addr 400 size 8 132000: system.mem_ctrl: Read queue limit 32, current size 0, entries needed 1 132000: system.mem_ctrl: Address: 400 Rank 0 Bank 0 Row 0 132000: system.mem_ctrl: Read queue limit 32, current size 0, entries needed 1 132000: system.mem_ctrl: Adding to read queue 132000: system.mem_ctrl: Request scheduled immediately 132000: system.mem_ctrl: Single request, going to a free rank 132000: system.mem_ctrl: Timing access to addr 400, rank/bank/row 0 0 0 132000: system.mem_ctrl: Access to 400, ready at 156750 bus busy until 156750. 156750: system.mem_ctrl: processRespondEvent(): Some req has reached its readyTime 156750: system.mem_ctrl: number of read entries for rank 0 is 0
もしくは、CPUの実行した命令のトレースを出力するために、Exec
デバッグフラグを使用することができる。このデバッグフラグによって、CPUがどのような命令を実行したかのトレースを得ることができる。
$ ./build/X86/gem5.opt --debug-flags=Exec configs/learning_gem5/part1/simple.py | head -n 50
gem5 Simulator System. http://gem5.org gem5 is copyrighted software; use the --copyright option for details. gem5 compiled Jan 3 2017 16:03:38 gem5 started Jan 3 2017 16:11:47 gem5 executing on chinook, pid 19234 command line: build/X86/gem5.opt --debug-flags=Exec configs/learning_gem5/part1/simple.py Global frequency set at 1000000000000 ticks per second 0: system.remote_gdb.listener: listening for remote gdb #0 on port 7000 warn: ClockedObject: More than one power state change request encountered within the same simulation tick Beginning simulation! info: Entering event queue @ 0. Starting simulation... 77000: system.cpu T0 : @_start : xor rbp, rbp 77000: system.cpu T0 : @_start.0 : XOR_R_R : xor rbp, rbp, rbp : IntAlu : D=0x0000000000000000 132000: system.cpu T0 : @_start+3 : mov r9, rdx 132000: system.cpu T0 : @_start+3.0 : MOV_R_R : mov r9, r9, rdx : IntAlu : D=0x0000000000000000 187000: system.cpu T0 : @_start+6 : pop rsi 187000: system.cpu T0 : @_start+6.0 : POP_R : ld t1, SS:[rsp] : MemRead : D=0x0000000000000001 A=0x7fffffffee30 250000: system.cpu T0 : @_start+6.1 : POP_R : addi rsp, rsp, 0x8 : IntAlu : D=0x00007fffffffee38 250000: system.cpu T0 : @_start+6.2 : POP_R : mov rsi, rsi, t1 : IntAlu : D=0x0000000000000001 360000: system.cpu T0 : @_start+7 : mov rdx, rsp 360000: system.cpu T0 : @_start+7.0 : MOV_R_R : mov rdx, rdx, rsp : IntAlu : D=0x00007fffffffee38 415000: system.cpu T0 : @_start+10 : and rax, 0xfffffffffffffff0 415000: system.cpu T0 : @_start+10.0 : AND_R_I : limm t1, 0xfffffffffffffff0 : IntAlu : D=0xfffffffffffffff0 415000: system.cpu T0 : @_start+10.1 : AND_R_I : and rsp, rsp, t1 : IntAlu : D=0x0000000000000000 470000: system.cpu T0 : @_start+14 : push rax 470000: system.cpu T0 : @_start+14.0 : PUSH_R : st rax, SS:[rsp + 0xfffffffffffffff8] : MemWrite : D=0x0000000000000000 A=0x7fffffffee28 491000: system.cpu T0 : @_start+14.1 : PUSH_R : subi rsp, rsp, 0x8 : IntAlu : D=0x00007fffffffee28 546000: system.cpu T0 : @_start+15 : push rsp 546000: system.cpu T0 : @_start+15.0 : PUSH_R : st rsp, SS:[rsp + 0xfffffffffffffff8] : MemWrite : D=0x00007fffffffee28 A=0x7fffffffee20 567000: system.cpu T0 : @_start+15.1 : PUSH_R : subi rsp, rsp, 0x8 : IntAlu : D=0x00007fffffffee20 622000: system.cpu T0 : @_start+16 : mov r15, 0x40a060 622000: system.cpu T0 : @_start+16.0 : MOV_R_I : limm r8, 0x40a060 : IntAlu : D=0x000000000040a060 732000: system.cpu T0 : @_start+23 : mov rdi, 0x409ff0 732000: system.cpu T0 : @_start+23.0 : MOV_R_I : limm rcx, 0x409ff0 : IntAlu : D=0x0000000000409ff0 842000: system.cpu T0 : @_start+30 : mov rdi, 0x400274 842000: system.cpu T0 : @_start+30.0 : MOV_R_I : limm rdi, 0x400274 : IntAlu : D=0x0000000000400274 952000: system.cpu T0 : @_start+37 : call 0x9846 952000: system.cpu T0 : @_start+37.0 : CALL_NEAR_I : limm t1, 0x9846 : IntAlu : D=0x0000000000009846 952000: system.cpu T0 : @_start+37.1 : CALL_NEAR_I : rdip t7, %ctrl153, : IntAlu : D=0x00000000004001ba 952000: system.cpu T0 : @_start+37.2 : CALL_NEAR_I : st t7, SS:[rsp + 0xfffffffffffffff8] : MemWrite : D=0x00000000004001ba A=0x7fffffffee18 973000: system.cpu T0 : @_start+37.3 : CALL_NEAR_I : subi rsp, rsp, 0x8 : IntAlu : D=0x00007fffffffee18 973000: system.cpu T0 : @_start+37.4 : CALL_NEAR_I : wrip , t7, t1 : IntAlu : 1042000: system.cpu T0 : @__libc_start_main : push r15 1042000: system.cpu T0 : @__libc_start_main.0 : PUSH_R : st r15, SS:[rsp + 0xfffffffffffffff8] : MemWrite : D=0x0000000000000000 A=0x7fffffffee10 1063000: system.cpu T0 : @__libc_start_main.1 : PUSH_R : subi rsp, rsp, 0x8 : IntAlu : D=0x00007fffffffee10 1118000: system.cpu T0 : @__libc_start_main+2 : movsxd rax, rsi 1118000: system.cpu T0 : @__libc_start_main+2.0 : MOVSXD_R_R : sexti rax, rsi, 0x1f : IntAlu : D=0x0000000000000001 1173000: system.cpu T0 : @__libc_start_main+5 : mov r15, r9 1173000: system.cpu T0 : @__libc_start_main+5.0 : MOV_R_R : mov r15, r15, r9 : IntAlu : D=0x0000000000000000 1228000: system.cpu T0 : @__libc_start_main+8 : push r14
実際、Execフラグは複数のデバッグフラグの集合体である。—debug-help
パラメータによって、フラグの種類を確認できる。
Base Flags: Activity: None AddrRanges: None Annotate: State machine annotation debugging AnnotateQ: State machine annotation queue debugging AnnotateVerbose: Dump all state machine annotation details BaseXBar: None Branch: None Bridge: None CCRegs: None CMOS: Accesses to CMOS devices Cache: None CacheComp: None CachePort: None CacheRepl: None CacheTags: None CacheVerbose: None Checker: None Checkpoint: None ClockDomain: None ... Compound Flags: All: Controls all debug flags. It should not be used within C++ code. All Base Flags AnnotateAll: All Annotation flags Annotate, AnnotateQ, AnnotateVerbose CacheAll: None Cache, CacheComp, CachePort, CacheRepl, CacheVerbose, HWPrefetch DiskImageAll: None DiskImageRead, DiskImageWrite ... XBar: None BaseXBar, CoherentXBar, NoncoherentXBar, SnoopFilter
新しいデバッグフラグの追加
前節では、SimObject内の出力をstd::coutによって記述したが、これは推奨されていない。その代わりに、gem5のデバッグ機能を使用するべきである。
新しいデバッグフラグを使用するためにはSConscriptファイルを使用する。hello objectコード(src/learning_gem5/SConscrpt
)に以下を追加する。
DebugFlag('HelloExample')
これは "HelloExample "というデバッグフラグを宣言している。これで、SimObjectのデバッグ文にこれを使うことができる。
SConscriptファイルでフラグを宣言することにより、デバッグフラグを使用するためのデバッグヘッダが自動的に生成される。このヘッダーファイルはデバッグディレクトリにあり、SConscriptファイルで宣言したものと同じ名前(および大文字)を持つ。したがって、デバッグフラグを使う予定のファイルには、自動生成されたヘッダーファイルをインクルードする必要がある。
hello_object.cc
ファイルでは、ヘッダーファイルをインクルードする必要がある。
#include "base/trace.hh" #include "debug/HelloExample.hh"
必要なヘッダー・ファイルをインクルードしたので、std::cout
コールをデバッグ・ステートメントに置き換えてみよう。
DPRINTF(HelloExample, "Created the hello object\n");
DPRINTFはC++マクロである。最初のパラメータはSConscriptファイルで宣言されたデバッグフラグである。src/learning_gem5/SConscriptファイルで宣言したので、HelloExampleフラグを使うことができる。残りの引数は変数で、printf文に渡すようなものなら何でもいい。 さて、gem5を再コンパイルし、"HelloExample "デバッグ・フラグを付けて実行すると、次のような結果が得られる。
$ ./scons build/X86/gem5.opt $ ./build/X86/gem5.opt --debug-flags=HelloExample configs/learning_gem5/part2/run_hello.py
gem5 Simulator System. http://gem5.org gem5 is copyrighted software; use the --copyright option for details. gem5 compiled Jan 4 2017 09:40:10 gem5 started Jan 4 2017 09:41:01 gem5 executing on chinook, pid 29078 command line: build/X86/gem5.opt --debug-flags=HelloExample configs/learning_gem5/part2/run_hello.py Global frequency set at 1000000000000 ticks per second 0: hello: Created the hello object Beginning simulation! info: Entering event queue @ 0. Starting simulation... Exiting @ tick 18446744073709551615 because simulate() limit reached