はじめに
SystemVerilogの仕様調査のため言語仕様書(IEEE Std 1800-2017)を読んでいたところ、面白い記述がありました。
If there is a declaration that is incomplete at the end of a file, then the compilation unit including that file
will extend through each successive file until there are no incomplete declarations at the end of the group of
files.
コンパイル単位(compilation unit)についての記述なのですが、簡単に訳すと「ファイルの末尾で宣言が不完全な場合、コンパイル単位は(不完全な宣言がなくなるまで)後続のファイルに延長される」となります。これはつまり「Verilogのソースコードは任意の位置でファイル分割できる」ということになりそうです。他のプログラミング言語でもあまりそういう仕様は聞いたことがないので、実際にできるかどうか試してみました。
以下ではコンパイラとしてVivado Simulator 2019.1を使った場合の結果を示します。
試してみる
以下のようなソースコードを考えます。
module A ();
endmodule
これを適当な位置で分割します。
module A ();
endmodule
この2つのファイルをコンパイルしてみます。
$ xvlog a.v b.v
INFO: [VRFC 10-2263] Analyzing Verilog file ".../a.v" into library work
INFO: [VRFC 10-2263] Analyzing Verilog file ".../b.v" into library work
INFO: [VRFC 10-311] analyzing module A
確かにmodule A
がコンパイルできています。
同様に(
や;
のあたりで分割してもOKでした。
予約語の途中で分割するとどうでしょうか?
module A ();
endm
odule
これはさすがに無理でした。
$ xvlog a.v b.v
INFO: [VRFC 10-2263] Analyzing Verilog file ".../a.v" into library work
INFO: [VRFC 10-311] analyzing module A
INFO: [VRFC 10-2263] Analyzing Verilog file ".../b.v" into library work
ERROR: [VRFC 10-1491] unexpected EOF [.../b.v:1]
他にも識別子の途中やリテラルの途中なども試しましたがダメでした。
ファイル末尾の改行の影響かと思い、split
コマンドでバイナリとして分割しても同様です。
なので基本的に分割できる箇所はスペースを入れられる場所と思えば良さそうです。
split
コマンドで分割する場合は-l
オプションなどで行単位で分割すればいいですね。
なぜこんな仕様があるのか?
調べてもよく分からなかったのでご存知の方教えてください。
想像としては、昔のファイルシステムでファイルサイズ上限に引っかかるのを回避するためではないかという気がします。
Verilogは人が書くだけでなくコンパイラ(的なもの)の中間結果のフォーマットとしても利用されていて、そういった出力は数十GB~数百GBになることがあります。
今どきのファイルシステムではあまり問題になりませんが、ファイルサイズに制限があった時代には適当なサイズに分割する必要があったのかもしれません。