ゲームボーイを作るその14。テストを作って実装を進めているが、この作業を進めるうちに、少し前に実装してPASSしたテストがFAILするという事がチラホラ起き始めた。そろそろCIを導入してデグレを早期発見できるようにしてみようと思う。
GitHub Actionsを使った自動テスト環境の構築
以前にお試しでGitHub Actionsを使ったChiselのCI環境は構築してみた事があるので、この記事を元に今回のゲームボーイ開発向けのCI環境を構築していく。
上記の記事を書いたときは、とりあえずchisel-templateの環境のテストを動かす所までをやったのだが、verilator等のビルドを毎回やっており、とても効率が悪くなっていた。
今回のCI環境を構築に当たってドキュメント類を確認し直した所、キャッシュ機能も提供されるようになっているようなので、一緒に検討していく。
基本フローの構築
「Chiselのテストを行う」がざっくりした目標となるが、これを満たすに当たって、次のステップを踏む必要がある。
- verilatorの依存パッケージのインストール
- verilatorのビルドとインストール
- sbtのインストール
- wla-dxのビルドとインストール
- テスト用のHEXデータ生成
これを愚直にActions用のステップとして実装したのが次のコードだ。
name: Chisel-test on: [push] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Build and Install Verilator run: | sudo apt-get install git perl python3 make autoconf g++ flex bison ccache sudo apt-get install libfl2 libfl-dev sudo apt-get install zlibc zlib1g zlib1g-dev wget https://github.com/verilator/verilator/archive/refs/tags/v4.210.tar.gz tar xf v4.210.tar.gz cd verilator-4.210 autoconf ./configure --prefix=/home/runner/tools/verilator make -j 2 make install - name: Build and Install WLA DX run: | sudo apt install cmake git clone https://github.com/vhelin/wla-dx cd wla-dx git checkout -b v10.0 refs/tags/v10.0 mkdir build && cd build # Create building directory cmake .. -DCMAKE_INSTALL_PREFIX=/home/runner/tools/wla-dx cmake --build . --config Release cmake -P cmake_install.cmake - name: Install sbt run: | echo "deb https://repo.scala-sbt.org/scalasbt/debian all main" | sudo tee /etc/apt/sources.list.d/sbt.list echo "deb https://repo.scala-sbt.org/scalasbt/debian /" | sudo tee /etc/apt/sources.list.d/sbt_old.list curl -sL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x2EE0EA64E40A89B84B2DF73499E82A75642AC823" | sudo apt-key add sudo apt-get update sudo apt-get install sbt - name: Run test run: | sudo apt-get install ccache export PATH=/home/runner/tools/verilator/bin:/home/runner/tools/wla-dx/bin:$PATH sbt "convertBin2Hex" sbt "testOnly CpuTest"
ここではVerilatorはGitHubのリリースに付属するソースコード一式をダウンロードして、ビルドするというフローにしてある。 この状態でCIを実行するとVerilatorのビルドだけで12分ほどかかっており、CIを実行することは可能だが色々もったいない。。
キャッシュ機能の導入
という事で、キャッシュ機能を試してみよう。このキャッシュ機能は公式が提供しているもので、基本的な説明はGitHubのREADMEを読めば大体わかるようになっていた。
次のコードはサンプルで記載されていた物。
- name: Cache multiple paths uses: actions/cache@v2 with: path: | ~/cache !~/cache/exclude key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
キャッシュしたいデータをpath
に書いておけば良さそう。Actionsがワークフロー実行時にkey
の内容にヒットしたものがあればpath
に記載したデータを復元、無ければワークフロー完了時にそのデータをキャッシュしてくれる様子。
キャッシュの細かい動きについては次のドキュメントが役にたった。
最初のキャッシュ機能実装(失敗)
ドキュメントを元に、キャッシュを試してみたその1が次のコード(失敗)。なおVerilatorビルドの依存ライブラリへのキャッシュ機能の部分のみを抜粋してます。
- name: Cache verilator dependancy id: cache-verilator-dependancy uses: actions/cache@v2 with: path: | /usr/bin/ccache /usr/include/FlexLexer.h /usr/lib/x86_64-linux-gnu/libfl.* /usr/lib/x86_64-linux-gnu/libl.* /usr/lib/x86_64-linux-gnu/pkgconfig/libfl.pc /etc/zlibc.conf /lib/uncompress.so key: ${{ runner.os }}-verilator-dependancy - name: Install Dependancy if: steps.cache-verilator-dependancy.outputs.cache-hit != 'true' run: | sudo apt-get install git perl python3 make autoconf g++ flex bison ccache sudo apt-get install libfl2 libfl-dev sudo apt-get install zlibc zlib1g zlib1g-dev
これで試すとキャッシュ自体は成功するのだが、次のCI実行時にキャッシュデータを対象ディレクトリに展開しようとすると、書き込み権限が無くて失敗した。これはライブラリのインストールをsudo
で実行しているが、展開時のtar
コマンドにはsudo
がついていないのが原因になる。
ステップの統合とインストール先の変更
これらのライブラリはVerilatorのビルドに必要なのであって、Verilatorのビルド&インストールが終わればOKなのでステップ自体を組み替えることにした。またデフォルトのインストール先だとsudo
なしではインストールできないので、インストール先を変更してある。
- name: Cache verilator id: cache-verilator uses: actions/cache@v2 with: path: | ~/verilator-4.210 ~/tools/verilator key: ${{ runner.os }}-verilator - name: Build and Install Verilator if: steps.cache-verilator.outputs.cache-hit != 'true' run: | sudo apt-get install git perl python3 make autoconf g++ flex bison ccache sudo apt-get install libfl2 libfl-dev sudo apt-get install zlibc zlib1g zlib1g-dev wget https://github.com/verilator/verilator/archive/refs/tags/v4.210.tar.gz tar xf v4.210.tar.gz cd verilator-4.210 autoconf ./configure --prefix=/home/runner/tools/verilator make -j 2 make install
このようにすることで、Verilatorのビルドプロセスをスキップすることができた。なおキャッシュにヒットした場合には、スキップしたいステップにif: steps.<id>.cache-hit != 'true'
の様に条件を入れる事で、スキップが可能となる。
同じような形でwla-dx
のビルド&インストールもキャッシュ機能を有効にした状態でのフロー組み込みできた。
sbtのデータのキャッシュ
sbt
を使ったプロジェクトでは、初回の起動時にbuild.sbt
記載の依存ライブラリがダウンロードされ、所定のディレクトリに格納される。これらのデータもキャッシュすることで、ダウンロード時間が省けることからCI実行時間を削減可能だ。
sbt
についてはドキュメントにサンプルが掲載されていたので、それをそのまま流用させてもらった。
- name: Cache SBT uses: actions/cache@v2 with: path: | ~/.ivy2/cache ~/.sbt key: ${{ runner.os }}-sbt-${{ hashFiles('**/build.sbt') }}
この設定においてはbuild.sbt
というファイルから生成されたハッシュがkey
に含まれているためbuild.sbt
に変更が入った際には、再度キャッシュデータが再生成されるようになっている。なので今後タスクを修正したり、Chiselのバージョンを更新したりした際にも、きちんとCIが実行できるようになっている。
ということ事で、まだ少し改善できる部分はあるがキャッシュ機能を有効にしたGitHub Actionsによる自動テスト環境を構築することができた。
最終的なワークフローの設定ファイルは、次の場所にあるので興味があればご覧ください。