FPGA開発日記

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

Verilatorのコンパイルフローを観察する (5. 007_JumpLinkについて)

Verilatorの内部構造勉強続き。次は007_JumpLinkについて見てみた。READMEを見てみると以下のように書いてある。

  • src/V3LinkJump.cpp
 // V3LinkJump's Transformations:
 //
 // Each module:
 //   Look for BEGINs
 //      BEGIN(VAR...) -> VAR ... {renamed}
 //   FOR -> WHILEs
 //
 //   Add JumpLabel which branches to after statements within JumpLabel
 //      RETURN -> JUMPBLOCK(statements with RETURN changed to JUMPGO, ..., JUMPLABEL)
 //      WHILE(... BREAK) -> JUMPBLOCK(WHILE(... statements with BREAK changed to JUMPGO),
 //                                    ... JUMPLABEL)
 //      WHILE(... CONTINUE) -> WHILE(JUMPBLOCK(... statements with CONTINUE changed to JUMPGO,
 //                                    ... JUMPPABEL))

どうもこれはロジック的な構文ではなく、while文に関する構文のようだ。ラベルを定義してそっちにジャンプするための構文を作り上げる。While文を削除しすべてJump文に変換するという訳だ。試しに以下のようなコードを作ってみた。以下は全くデジタル的なコードではなく、initial beginに埋め込まれているコードとなる。

 module while_jump;

 int i;
 initial begin
   while(i < 100) begin
     if (i == 10) break;
   end
 end
 endmodule

002_cells007_linkの構文ツリーを見比べてみる。

  • Vwhile_jump_002_cells.tree
 Verilator Tree Dump (format 0x3900) from <e0> to <e41>
      NETLIST 0x7fffd46f3f40 <e1#> {a0aa}  $root [1ps/1ps]
     1: MODULE 0x7fffd4708420 <e41#> {c1ai}  while_jump  L0 [1ps]
     1:2: VAR 0x7fffd4708950 <e6#> {c3af} @dt=0@  i VAR
     1:2:1: BASICDTYPE 0x7fffd4708870 <e7#> {c3ab} @dt=this@(sw32)  int kwd=int range=[31:0]
     1:2: INITIAL 0x7fffd470a4f0 <e38#> {c4ab}
     1:2:2: BEGIN 0x7fffd4708bc0 <e8#> {c4aj}
     1:2:2:1: WHILE 0x7fffd470a3e0 <e35#> {c5ad}
     1:2:2:1:2: LT 0x7fffd4709360 <e36#> {c5al} @dt=0x7fffd4709420@(G/nw1)
     1:2:2:1:2:1: PARSEREF 0x7fffd4708e90 <e15#> {c5aj}  i [TEXT]
     1:2:2:1:2:2: CONST 0x7fffd4709070 <e16#> {c5an} @dt=0x7fffd47091e0@(G/swu32/7)  ?32?sh64
     1:2:2:1:3: BEGIN 0x7fffd4709800 <e21#> {c5as}
     1:2:2:1:3:1: IF 0x7fffd470a2c0 <e33#> {c6af}
     1:2:2:1:3:1:1: EQ 0x7fffd470a050 <e34#> {c6al} @dt=0x7fffd4709420@(G/nw1)
     1:2:2:1:3:1:1:1: PARSEREF 0x7fffd4709b20 <e29#> {c6aj}  i [TEXT]
     1:2:2:1:3:1:1:2: CONST 0x7fffd4709d20 <e30#> {c6ao} @dt=0x7fffd4709ed0@(G/swu32/4)  ?32?sha
     1:2:2:1:3:1:2: BREAK 0x7fffd470a1b0 <e32#> {c6as}
     3: TYPETABLE 0x7fffd46f45e0 <e2#> {a0aa}
            logic  -> BASICDTYPE 0x7fffd4709420 <e19#> {c5al} @dt=this@(G/nw1)  logic [GENERIC] kwd=logic
         detailed  ->  BASICDTYPE 0x7fffd4709420 <e19#> {c5al} @dt=this@(G/nw1)  logic [GENERIC] kwd=logic
         detailed  ->  BASICDTYPE 0x7fffd4709ed0 <e26#> {c6ao} @dt=this@(G/swu32/4)  logic [GENERIC] kwd=logic range=[31:0]
         detailed  ->  BASICDTYPE 0x7fffd47091e0 <e12#> {c5an} @dt=this@(G/swu32/7)  logic [GENERIC] kwd=logic range=[31:0]
     3:1: BASICDTYPE 0x7fffd47091e0 <e12#> {c5an} @dt=this@(G/swu32/7)  logic [GENERIC] kwd=logic range=[31:0]
     3:1: BASICDTYPE 0x7fffd4709420 <e19#> {c5al} @dt=this@(G/nw1)  logic [GENERIC] kwd=logic
     3:1: BASICDTYPE 0x7fffd4709ed0 <e26#> {c6ao} @dt=this@(G/swu32/4)  logic [GENERIC] kwd=logic range=[31:0]
  • Vwhile_jump_007_link.tree
 Verilator Tree Dump (format 0x3900) from <e41> to <e60>
      NETLIST 0x7fffd46f3f40 <e1> {a0aa}  $root [1ps/1ps]
     1: MODULE 0x7fffd4708420 <e41#> {c1ai}  while_jump  L0 [1ps]
     1:2: VAR 0x7fffd4708950 <e6> {c3af} @dt=0@  i [VSTATIC]  VAR
     1:2:1: BASICDTYPE 0x7fffd4708870 <e7> {c3ab} @dt=this@(sw32)  int kwd=int range=[31:0]
     1:2: INITIAL 0x7fffd470a4f0 <e38> {c4ab}
     1:2:2: BEGIN 0x7fffd4708bc0 <e8> {c4aj}
     1:2:2:1: JUMPBLOCK 0x7fffd4705470 <e55#> {c5ad}
     1:2:2:1:1: WHILE 0x7fffd470a3e0 <e54#> {c5ad}
     1:2:2:1:1:2: LT 0x7fffd4709360 <e36> {c5al} @dt=0x7fffd4709420@(G/nw1)
     1:2:2:1:1:2:1: VARREF 0x7fffd47048f0 <e44#> {c5aj} @dt=0@  i [RV] <- VAR 0x7fffd4708950 <e6> {c3af} @dt=0@  i [VSTATIC]  VAR
     1:2:2:1:1:2:2: CONST 0x7fffd4709070 <e16> {c5an} @dt=0x7fffd47091e0@(G/swu32/7)  ?32?sh64
     1:2:2:1:1:3: BEGIN 0x7fffd4709800 <e21> {c5as}
     1:2:2:1:1:3:1: IF 0x7fffd470a2c0 <e33> {c6af}
     1:2:2:1:1:3:1:1: EQ 0x7fffd470a050 <e34> {c6al} @dt=0x7fffd4709420@(G/nw1)
     1:2:2:1:1:3:1:1:1: VARREF 0x7fffd4704a30 <e47#> {c6aj} @dt=0@  i [RV] <- VAR 0x7fffd4708950 <e6> {c3af} @dt=0@  i [VSTATIC]  VAR
     1:2:2:1:1:3:1:1:2: CONST 0x7fffd4709d20 <e30> {c6ao} @dt=0x7fffd4709ed0@(G/swu32/4)  ?32?sha
     1:2:2:1:1:3:1:2: JUMPGO 0x7fffd4705610 <e57#> {c6as} -> JUMPLABEL 0x7fffd4705540 <e53#> {c5ad} -> JUMPBLOCK 0x7fffd4705470 <e55#> {c5ad}
     1:2:2:1:2: JUMPLABEL 0x7fffd4705540 <e53#> {c5ad} -> JUMPBLOCK 0x7fffd4705470 <e55#> {c5ad}
     3: TYPETABLE 0x7fffd46f45e0 <e2> {a0aa}
            logic  -> BASICDTYPE 0x7fffd4709420 <e19> {c5al} @dt=this@(G/nw1)  logic [GENERIC] kwd=logic
         detailed  ->  BASICDTYPE 0x7fffd4709420 <e19> {c5al} @dt=this@(G/nw1)  logic [GENERIC] kwd=logic
         detailed  ->  BASICDTYPE 0x7fffd4709ed0 <e26> {c6ao} @dt=this@(G/swu32/4)  logic [GENERIC] kwd=logic range=[31:0]
         detailed  ->  BASICDTYPE 0x7fffd47091e0 <e12> {c5an} @dt=this@(G/swu32/7)  logic [GENERIC] kwd=logic range=[31:0]
     3:1: BASICDTYPE 0x7fffd47091e0 <e12> {c5an} @dt=this@(G/swu32/7)  logic [GENERIC] kwd=logic range=[31:0]
     3:1: BASICDTYPE 0x7fffd4709420 <e19> {c5al} @dt=this@(G/nw1)  logic [GENERIC] kwd=logic
     3:1: BASICDTYPE 0x7fffd4709ed0 <e26> {c6ao} @dt=this@(G/swu32/4)  logic [GENERIC] kwd=logic range=[31:0]

明確に見て取れるのは、WHILEブロック内のbreak文が無くなって、JUMPGOという演算子が追加されている。これはおそらく前節のEQが成立するとJUMPLABELに飛び、そうでないときはJUMPBLOCKに飛ぶということだろう。

f:id:msyksphinz:20210405235159p:plain