FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

ハードウェア開発用の依存関係解決ツールBenderについて

PULPの開発する、ハードウェア開発用の依存関係解決ツールBenderについて調査している。

github.com

まず概要部分を日本語に翻訳してみよう。


Benderはハードウェア設計プロジェクトのための依存関係管理ツールです。IP間の依存関係を定義し、単体テストを実行し、ソースファイルが各種シミュレーションツールや合成ツールで正しく動作することを検証する方法を提供します。


これは基本的にはバージョン管理ツールだが、Gitにもsubmodulesという類似機能があるのに、なぜBenderが必要なのだろうか。

Gitのsubmodulesは、依存する他のリポジトリを含めたり、特定のバージョンに固定したりすることができる。

一方、Benderは複数のGitリポジトリを管理できるだけでなく、依存関係のチェックも行える。


この依存関係のチェックとは具体的に何だろうか。サブモジュールとして管理しているモジュールの仕様が変更されると、メインのリポジトリ側でそれが使用できなくなる可能性がある。単純にサブモジュールをアップデートすると、すぐに互換性が失われる恐れがある。

あるリポジトリrepo_Aに、モジュールAが存在するとする:

module A;
  B inst_B (
  .inA (in_a),
  .inB (in_b),
  .outC (out_c)
  );
endmodule 

別のリポジトリrepo_BにモジュールBが存在し、ABは依存関係にあるとする。

現在、repo_Bのcommit IDは0x100とする。

module B
(
    input inA,
    input inB,
    output outC
);

assign outC = inA + inB;

endmodule

repo_Bに機能が追加されたとする。

機能の追加には以下の種類がある:

  1. 後方互換性のない変更があった場合
  2. 後方互換性のある新規機能の追加があった場合
  3. 後方互換性のあるバグ修正が行われた場合

まず2.と3.の場合を考えよう。バグ修正ではないが、以下のような機能修正が行われたとする。これは下位互換性がある。この変更が行われたrepo_Bのコミットを0x101とする。

module B
(
    input inA,
    input inB,
    output outC
);

always_comb begin
  outC = inA + inB;
end

endmodule

では、1.のような後方互換性のない変更が加わった場合はどうか。上記のモジュールBにおいて、入力inBが不要だったとする。すると、変更後のモジュールBは以下のようになる。この変更が行われたrepo_Bのコミットを0x102とする。

module B
(
    input inA,
    output outC
);

always_comb begin
  outC = !inA;
end

endmodule

この場合、repo_Aにとってrepo_Bの0x100、0x101は使用可能だが、0x102にsubmoduleのリビジョンをアップデートすると動作しなくなる。git submoduleはこのようなサブモジュールの互換性チェックを行わず、単純にリビジョンを更新するため、コンパイル時になって初めて互換性の問題が発覚する。

これをBenderはどのように解決するのか。

Benderは、リポジトリのリビジョン番号に加えて、セマンティック・バージョンをタグとして適用することで互換性を表現する。

MAJOR.MINOR.PATCH
  • MAJOR(メジャー):後方互換性のない変更が加えられた場合に増加
  • MINOR(マイナー):後方互換性のある新機能が追加された場合に増加
  • PATCH(パッチ):後方互換性のあるバグ修正が行われた場合に増加

これにより、上記のrepo_Bでは:

  • 0x100→0x101のときはMINORまたはPATCHの番号を更新する(タグを付ける)
  • 0x101→0x102のときはMAJORの番号を更新する

repo_Arepo_Bの互換性のあるバージョンをYAMLファイルで記述し、repo_Bのタグに含まれるセマンティック・バージョンをチェックすることで、どこまで更新可能かを管理できる。