ハードウェアの気になるあれこれ

技術的に興味のあることを調べて書いてくブログ。主にハードウェアがネタ。

ゲームボーイを作る(14) - キャッシュ機能付きCI環境構築

スポンサーリンク

ゲームボーイを作るその14。テストを作って実装を進めているが、この作業を進めるうちに、少し前に実装してPASSしたテストがFAILするという事がチラホラ起き始めた。そろそろCIを導入してデグレを早期発見できるようにしてみようと思う。

GitHub Actionsを使った自動テスト環境の構築

以前にお試しでGitHub Actionsを使ったChiselのCI環境は構築してみた事があるので、この記事を元に今回のゲームボーイ開発向けのCI環境を構築していく。

上記の記事を書いたときは、とりあえずchisel-templateの環境のテストを動かす所までをやったのだが、verilator等のビルドを毎回やっており、とても効率が悪くなっていた。

今回のCI環境を構築に当たってドキュメント類を確認し直した所、キャッシュ機能も提供されるようになっているようなので、一緒に検討していく。

基本フローの構築

「Chiselのテストを行う」がざっくりした目標となるが、これを満たすに当たって、次のステップを踏む必要がある。

  1. verilatorの依存パッケージのインストール
  2. verilatorのビルドとインストール
  3. sbtのインストール
  4. wla-dxのビルドとインストール
  5. テスト用の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がついていないのが原因になる。

f:id:diningyo-kpuku-jougeki:20210809230643j:plain
キャッシュデータの展開に失敗したところ

ステップの統合とインストール先の変更

これらのライブラリは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'の様に条件を入れる事で、スキップが可能となる。

f:id:diningyo-kpuku-jougeki:20210809230720j:plain
Verilatorのビルドをスキップしたところ

同じような形で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による自動テスト環境を構築することができた。

最終的なワークフローの設定ファイルは、次の場所にあるので興味があればご覧ください。