Verilogなどで実装したプロセッサのデバッグをしているとき、プログラムカウンタと各パイプラインステージで処理中の命令の波形をGTKWaveに表示することがしばしばあります。 しかしながら、命令のフォーマットを覚えてないと、今目の前でバグを引き起こしている命令が何の命令なのかわかりません。
このような場合、筆者はプロセッサが実行しているELFファイルをobjdump
し、アセンブリと波形の両方を交互に眺めるという作業をしていました。
しかし、ある日、GTKWaveに命令のアセンブリを表示している人がいることを知りました。
The bubbles hurt me. pic.twitter.com/P37mNdud2w
— logic destroyer (@splinedrive) January 26, 2025
「これは便利そうだ」 と思い、この方のGitHubリポジトリを探してみたところ、公開されているGTKWaveのワークスペースファイル内で 以下の記述を見かけました。
^>1 /home/hd/hacking/asic_harris/projects/kianv/gtkwave-python-filter-process/examples/riscv-filter.py
どうやら、このPythonスクリプトが鍵のようです。 これは以下のリポジトリで配布されているものと思われます。
ビデオデモに沿って、このスクリプトをフィルタとして波形に適用します。
無事にアセンブリを表示できました!
ところで、これはどのようにして実現しているのでしょうか? Pythonスクリプトは以下の処理を繰り返し行っているようでした (一部略)。
tempfile
で一時ファイルobj_temp
とasm_temp
を作る。- 標準入力から読んだ値
l
を用いてasm_temp
に.word 0xl
を書く。例えば、l
が00000213
ならば.word 0x00000213
を書く。 riscv64-unknown-elf-as
でasm_temp
をアセンブルしobj_temp
に保存する。riscv64-unknown-elf-objdump
でobj_temp
を逆アセンブルする。このとき、.word 0x00000213
はli tp,0
などになる。- 逆アセンブルの結果を標準出力に書く。
GTKWave側で波形の情報をスクリプトの標準入力に書き、標準出力から読んだ値を表示しているようです。 なるほど、これはいろいろなことに応用できそうです。
…ちなみに、GNUツールチェーンの (特にas
とobjdump
の) バージョンによっては逆アセンブル時に.word 0x...
しか表示されないという現象が起こるようです。
以下に、筆者が利用したGNUツールチェーンのバージョンを示します。
- うまくデコードできた: 2.35.1
- うまくいかなかった: 2.40.0.20230214, 2.43.1
引用したコードのライセンスを示します。
Copyright (C) 2022 Hirosh Dabui hirosh@dabui.de Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.