はじめに
以前、RISCVのコンパイラ環境を構築するのに、Linux初学者だった身が32ビット環境のみの構築に対して時間をかけてしまったのでこちらですぐにできる方法を共有できればと思います。
32ビットのみのコンパイラを構築する方がストレージ消費量が少なく、コンパイラのビルド時間も大幅に短縮されます。
開発において、何度も32ビットコンパイラ構築を行う方には、riscv-gnu-toolchainの multilib ではなくて32ビットのみだとありがたいですね。(そんな人あんまいない気するけど)
※ multilib は64ビットと32ビットのクロスコンパイラの両方です。構築するのにかなり時間がかかります。
構築するDockerイメージの環境について
RISCVのレジスタ長は128bit、64bit、32bitがあります。32ビットのRISCVはレジスタ長が32ビットのRISCVということです。
RV32GCというのは、32ビットRISCV用の命令セットです。
こちらはG; General Purpose ISA(I, M, A, F, D の集合)とC; Compressedの命令セットを含みます。
今回は、DockerでUbuntu18.04環境上でRV32開発用のコンパイラを含むイメージを作成して、コンテナを起動するという形です。
作成するのは以下をすでにインストールされている環境です。
- RV32GC用クロスコンパイラ (参考: riscv-gnu-toolchain)
- Spike
- riscv-pk
その為Dockerイメージが大きくなってしまうので、ストレージが圧迫されてしまうことにお気をつけください。(約15GB)
※もちろんこの記事の方法ではなく、Dockerfileを用いずにubuntu18.04環境をdocker pullして構築する方法でも構いません
方法
まずDockerをインストールしてください。
私はMacだった為、Homebrewを用いてインストールを行いました。
→ 参考: DockerをHomebrewでMac OSに導入する方法
Dockerのインストールができましたら、以下の記述のDockerfileを適当なフォルダ内においてください。
FROM ubuntu:18.04
LABEL version="1.0"
LABEL description="RV32GC Compiler Environment"
WORKDIR /tmp/
SHELL ["/bin/bash", "-c"]
RUN apt -y update
RUN apt -y install git autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev
RUN git clone --recursive https://github.com/riscv-collab/riscv-gnu-toolchain.git
ENV RV32 /opt/rv32gc
RUN cd riscv-gnu-toolchain && \
mkdir build && cd build && \
../configure --prefix=$RV32/cross --with-arch=rv32gc --with-abi=ilp32d && \
make -j$(nproc)
RUN echo 'export PATH=$PATH:$RV32/cross/bin' >> ~/.bashrc
RUN apt install device-tree-compiler
RUN git clone https://github.com/riscv-software-src/riscv-isa-sim.git
RUN cd riscv-isa-sim && \
mkdir build && cd build && \
../configure --prefix=$RV32/spike --with-isa=rv32gc && \
make && \
make install
RUN echo 'export PATH=$PATH:$RV32/spike/bin' >> ~/.bashrc
RUN git clone https://github.com/riscv-software-src/riscv-pk.git
RUN cd riscv-pk && \
git reset --hard 423801e35d048187d88fcbff55e20c4c34d27bee && \
mkdir build && cd build && \
export PATH=$PATH:$RV32/cross/bin && \
../configure --prefix=$RV32/pk --host=riscv32-unknown-elf && \
make && \
make install
RUN echo 'export PATH=$PATH:$RV32/pk/riscv32-unknown-elf/bin' >> ~/.bashrc
WORKDIR /workdir
今回は「rv32」フォルダ内にそのDockerfileを置いていることを想定しているので、cdコマンドで移動します。
cd rv32
そして、適当な名前とタグをつけて、Dockerイメージを作成します。
docker build -t ubuntu/rv32:1.0 .
かなりの時間がかかるので、一旦休んで別のことをして1時間後に戻りましょう。
余談。。。
最後の「.」と指定することでイメージの build 時、デフォルトではフォルダー内にある Dockerfile を実行させます。
(一般的にはDockerfileという名前を使用するのだと思ってますが、何かしらの理由で別ファイルでイメージをビルドしたいときは -f オプションを使用するらしいです。
そこの辺りは、 コマンド docker build --help
とかで確認してください。)
余談ここまで
戻ってきたら以下のコマンドを打って、コンテナを作成します。
docker run -it ubuntu/rv32:1.0
ubuntu/rv32:1.0
のかわりに [IMAGE ID]
というものでも大丈夫です。
イメージIDは docker images
コマンドで確認ができます。
コンテナに入れたかと思いますので、次に適当なCプログラムをクロスコンパイル&シミュレーションしていきます。
user@computer_name % docker run -it ubuntu/rv32:1.0
root@15ea6a0ef57c:/workdir#
クロスコンパイル&シミュレーション
適当なCプログラムをとってきます。
#include <stdio.h>
int main()
{
printf("Hello World\n");
}
以下のコマンドでRISCV用の実行ファイル a.out を生成します。
riscv32-unknown-elf-gcc hello.c
Spikeとriscv-pkを用いてシミュレーションを行ってみましょう。
この際、pkは、フルパスでpkを指定する(方法1)か、pk実行ファイルをディレクトリ内にコピーする必要があります(方法2)。
pk のパスが通っていても 方法1 では pk をフルパスで指定する必要があります。
ちなみに--isa
オプションでどの命令セットでシミュレーションするか指定してます。
方法1
root@15ea6a0ef57c:/workdir# spike --isa=RV32GC /opt/rv32gc/pk/riscv32-unknown-elf/bin/pk a.out
bbl loader
Hello World
一応コンパイラのパスの確認は、例えばwhich pk
コマンドでできるようにしてあります。
(コンテナ起動時、必要なパスをすでに通すようにしているため)
root@15ea6a0ef57c:/workdir# which pk
/opt/rv32gc/pk/riscv32-unknown-elf/bin/pk
方法2
root@15ea6a0ef57c:/workdir# cp /opt/rv32gc/pk/riscv32-unknown-elf/bin/pk .
root@15ea6a0ef57c:/workdir# spike --isa=RV32GC pk a.out
bbl loader
Hello World
シミュレーションできましたね。
*ちなみに bbl loader
というのはBerkeley Boot Loaderのことです。
気になる方はお調べください。(参考)
コンテナの出方と入り方
コンテナを出る際にはexit
コマンドを打ってください。
root@15ea6a0ef57c:/workdir# exit
コンテナをまた起動するには1つとして以下の方法があります。
user@computer_name % docker ps -a //コンテナIDの確認
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a6fed20a4325 ubuntu/rv32:1.0 "bash" 12 minutes ago Exited (0) 3 seconds ago blissful_dhawan
user@computer_name % docker start a6fed20a4325 // [CONTAINER ID]の代わりに[NAMES]値でもOK
user@computer_name % docker attach a6fed20a4325 // [CONTAINER ID]の代わりに[NAMES]でもOK
root@15ea6a0ef57c:/workdir#
あとは、VSCodeをお使いになられている場合、コンテナ用の拡張機能を使用する方法がおすすめです。
参考: VSCode Remote Containerが良い
経緯
ご指摘やご質問などございましたらお気軽にお尋ねください。
参考
こちらの記事(RISC-Vを使用したアセンブリ言語入門 〜1. 環境構築編〜) に、各コンパイラについて(riscv-gnu-toolchain, Spike, riscv-pkなど)とても分かりやすく説明がのっておりました。
私も今回この記事を書くときに参考にさせていただきました。