PULPの開発する、ハードウェア開発用の依存関係解決ツールBenderについて調査している。
まず概要部分を日本語に翻訳してみよう。
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
が存在し、A
とB
は依存関係にあるとする。
現在、repo_B
のcommit IDは0x100とする。
module B ( input inA, input inB, output outC ); assign outC = inA + inB; endmodule
repo_B
に機能が追加されたとする。
機能の追加には以下の種類がある:
- 後方互換性のない変更があった場合
- 後方互換性のある新規機能の追加があった場合
- 後方互換性のあるバグ修正が行われた場合
まず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_A
はrepo_B
の互換性のあるバージョンをYAMLファイルで記述し、repo_B
のタグに含まれるセマンティック・バージョンをチェックすることで、どこまで更新可能かを管理できる。