Gem5の勉強のために、チュートリアルを1からやってみることにした。
ビルドの方法
ビルドの方法は大体わかっている。RISC-V向けのシミュレーションのためには以下のコマンドでビルドする。
scons build/RISCV/gem5.opt
このopt
のオプションにはいくつか種類があるらしい。
gem5.debug
デバッグオプション付き。デバッグシンボル付きで、最適化なしでコンパイルする。gem5.opt
デバッグオプション付き。-O3
オプションでコンパイルする。gem5.fast
デバッグオプションもつかない。最適化オプション付きでコンパイルする。アサーションも削除される。
コンフィグレーションスクリプトについて
次にコンフィグレーションスクリプトの作成。このコンフィグレーションスクリプトにより、Gem5でシミュレーションしたいシステムの構成を決定する。
これらの多くの例は、configs/examples
に格納されている。
SimObject
について
Gem5におけるシミュレーション対象となるオブジェクト(CPU・キャッシュ・メモリコントローラ・バスなど)は、SimObject
を基底として作られている。
このオブジェクトは最終的にPythonに変換されるらしい。したがって、Python上からこれらのオブジェクトを作成したり呼び出すことができるようになる。
コンフィグレーションスクリプトの作成
まずは簡単なコンフィグレーションスクリプトを作ってみる。
mkdir configs/tutorial/part1/ touch configs/tutorial/part1/simple.py
次のコードはまあおまじないのように考えればよい。
import m5 from m5.objects import *
次にSystem
オブジェクトを作成する。これには、タイミング情報を含まないシステムシミュレーション(物理メモリアドレス配置・クロックドメインなど)の環境が含まれている。
system = System()
システムクロックを作成し、システムに接続する。
system.clk_domain = SrcClockDomain()
system.clk_domain.clock = '1GHz'
system.clk_domain.voltage_domain = VoltageDomain()
次にメモリを作成する。ここでは512MBの小さなメモリを接続し、タイミングモードで動作するようにする。
system.mem_mode = 'timing' system.mem_ranges = [AddrRange('512MB')]
CPUを接続する。X86の場合は下記だが、RiscvTimingSimpleCPU
などでもよい。
system.cpu = X86TimingSimpleCPU()
メモリのためのクロスバーと、キャッシュを接続する。
# システム内でのメモリバスを作成する system.membus = SystemXBar() # キャッシュを持っていないので、命令キャッシュとデータキャッシュのポートを直接メモリに接続する system.cpu.icache_port = system.membus.cpu_side_ports system.cpu.dcache_port = system.membus.cpu_side_ports
余談:Gem5のポート
メモリオブジェクトは、「リクエスト」と「レスポンス」のポートを持っている。
Pythonの=
を用いて、簡単に接続できる。CPUの命令キャッシュのRequestポートを、cpu_side Responseポートに接続する。
system.cpu.icache_port = system.l1_cache.cpu_side
また、これらのポートは一方が1つの信号で、もう片方に複数のポートを接続しても良い。
下記の例では、icache_portをメモリ側のcpu_side_portsに接続しており、cpu_side_portsは配列に相当する。この例では、cpu_side_ports側に新しいポートが自動的に追加されることになる。
system.cpu.icache_port = system.membus.cpu_side_ports
とりあえずここまで。