概要
世は大マルチコア時代、身近なコンピュータシステムの多くがマルチコアのCPUを搭載しています。
本記事では、WSL2上でLinuxの動くマルチコアRISC-V SoCをシミュレートし、その動作を観察します。
作業
今回はLinux on LiteX-VexRiscvを使います。 まずはこれを使うにあたって必要な準備をします。 基本的に、READMEの内容に従います。
LiteXなどのインストール
Linux on LiteX-VexRiscvはLiteXのインフラを用います。 そのため、LiteXおよびその周辺環境をインストールする必要があります。 LiteXのREADMEや過去の記事を参考に、LiteX、meson、ninja、riscv-gnu-toolchainをインストールします。
Verilatorのインストール
Linux on LiteX-VexRiscvはシミュレータとしてVerilator (v4.2xx以降) を用います。
一方で、Ubuntuのapt
でインストールされるものは記事執筆時点でv4.038のため、自前でビルドする必要があります。
Verilatorのドキュメントや過去の記事を参考に、Verilatorの最新安定版をインストールします。
筆者の環境ではVerilator v5.026がインストールされました。
$ verilator --version Verilator 5.026 2024-06-15 rev UNKNOWN.REV
SBTのインストール
Linux on LiteX-VexRiscvのREADMEには「標準的なVexRiscv-smpは生成済みだぜ。カスタムしたものを生成したい時だけSBTを使うぜ」と書いていますが、実際に作業を進めていると、どうやらシミュレーション用のCPUをSBTで生成するステップがあるようでした。 そのため、SBTをインストールします。
SBTのドキュメントや過去の記事を参考に、SBTをインストールします。
筆者の環境ではSBT 1.10.1がインストールされました。
LinuX on Litex-VexRiscvのクローンとシミュレーション実行
初めに依存パッケージのインストールを行います。
sudo apt install -y build-essential device-tree-compiler wget git python3-setuptools
続いて、Linux on LiteX-VexRiscvをGitHubからクローンし、ディレクトリに移動します。
git clone https://github.com/litex-hub/linux-on-litex-vexriscv cd linux-on-litex-vexriscv
次に、Issue #164からビルド済みのLinuxイメージおよびOpenSBIイメージをダウンロードし、適切な場所へ配置します。
cd images wget https://github.com/litex-hub/linux-on-litex-vexriscv/files/8331338/linux_2022_03_23.zip unzip -o linux_2022_03_23.zip cd ..
そして、SoCを生成しシミュレーションを実行します。
./sim.py
おやおや、ライブラリが足りないと怒られました。 筆者の環境ではlibevent-devとlibjson-c-devを追加したところ動きました。
sudo apt install -y libevent-dev libjson-c-dev
再度sim.py
を実行したところ、LiteXのBIOSが起動し、OpenSBIが起動し、そしてLinux (buildroot) が起動しました。
シミュレーションのため、Linuxが起動してログインプロンプトが表示されるまでは数分程度かかりました。
ログインプロンプトにはユーザ名root
を入力することでログインできます。
マルチコアでLinuxを起動してみる
続いて、コア数を増やしてシミュレーションを行ってみます。
sim.py
を読むと、このファイルは引数をCPUであるVexRiscv-SMPのargs_fill
メソッドに渡しそれを処理させていると分かります。
parser = argparse.ArgumentParser(description="Linux on LiteX-VexRiscv Simulation.") parser.add_argument("--with-sdram", action="store_true", help="Enable SDRAM support.") parser.add_argument("--sdram-module", default="MT48LC16M16", help="Select SDRAM chip.") parser.add_argument("--sdram-data-width", default=32, help="Set SDRAM chip data width.") parser.add_argument("--sdram-verbosity", default=0, help="Set SDRAM checker verbosity.") VexRiscvSMP.args_fill(parser) verilator_build_args(parser) args = parser.parse_args() VexRiscvSMP.args_read(args)
では、このVexRiscv-SMPのクラスはどこで定義されるかというと、それはLiteXのディレクトリにあるlitex/soc/cores/cpu/vexriscv_smp/core.py
の中です。
args_fill
メソッドの定義を見るに引数--cpu-count
でCPUコア数を指定できるようです。
それでは、--cpu-count=4
としてシミュレーションを行ってみます。
初めにSBTが起動し、4コア版VexRiscv-SMPのVerilogファイルを生成します。
その後、1コア同様LiteX SoCやソフトウェアのビルドが走り、シミュレーションが開始します。
シミュレーションでは、やはりOpenSBIが起動し、Linuxカーネルが起動します。
注目すべき点は、セカンダリCPUたちの起動 (smp: Bringinc up secondary CPUs ...
) の後に4つのCPUが認識されていることでしょう。
[ 0.033890] smp: Bringing up secondary CPUs ... [ 0.061381] smp: Brought up 1 node, 4 CPUs
その後、しばらく (ほんとうにほんとうにしばらく) 待つとログインプロンプトが表示されます。 筆者の環境では、体感で20分以上かかりました。 筆者は筋トレ (大胸筋、肩、前腕) して時間をつぶしました。
さて、ログインプロンプトが表示されたら、先述のようにroot
でログインします。
すると、Linux on LiteX-VexRiscvのAAが表示され、コマンドを入力できるようになります。
ただ、キーボードから文字を入力して反映されるまでも非常に時間がかかります。
「マルチコアなんだから速くなるのでは?」と思うかもしれませんが、今動いているものはあくまでシミュレーション、つまりソフトウェアです。
コアが増えた分シミュレーションモデルが大きくなり、ソフトウェアとして処理すべき事柄が増えたこと、そしておそらくシミュレーション自体はシングルスレッドで動いていること (htop
とかでCPU使用率を見ると1スレッドが100%に張り付いているだけ。) から、現実の実行時間が大きくなっていると考えられます。
さて、念のためnproc
を実行してみましょう。
root@buildroot:~# nproc 4
無事に4と表示されました。
まとめ
本記事ではLinux on LiteX-VexRiscvを用いて、WSL2上でLinuxの動くマルチコアRISC-V SoCをシミュレートしました。 その中で、Linux on LiteX-VexRiscvの処理の流れやLinux (buildroot) がRISC-V SoC上で起動する流れを確認しました。