FPGA開発日記

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

Verilatorのコンパイルフローを観察する (8. 010_paramLinkについて)

010_paramLinkはSystemVerilogにおけるパラメータの決定を行う。例えば以下のようなデザインをサンプルとして作ってみた。

  • test.sv
module test;

localparam p = 4;

logic [p-1: 0] in;

test2
  #(.param(p * 2),
    .plus_p(9))
u_test2
  (
   .in({in, in}),
   .out()
   );

endmodule

module test2
  #(
    parameter param = 2,
    parameter plus_p = 1
    )
(
 input logic [param-1: 0]    in,
 output logic [param*2-1: 0] out
 );


assign out = {in, in} + plus_p;

endmodule // test2

test2モジュールは2つのパラメータを持っている。paramplus_pだ。これらをparamLinkのステージで決定する。

paramLinkの前までのステージ008_linkIncまでは以下のようなツリーでtestモジュールが構成されている。

    1: MODULE 0x7fffb8b146d0 <e226> {c1ai}  test  L2 [1ps]
    1:2: VAR 0x7fffb8b14da0 <e10> {c3am} @dt=0@  p [VSTATIC]  LPARAM
    1:2:1: BASICDTYPE 0x7fffb8b14cc0 <e11> {c3am} @dt=this@(nw0)  LOGIC_IMPLICIT kwd=LOGIC_IMPLICIT
    1:2:3: CONST 0x7fffb8b0dc60 <e12> {c3aq} @dt=0x7fffb8b14b40@(G/swu32/3)  ?32?sh4
    1:2: VAR 0x7fffb8b16080 <e36> {c5aq} @dt=0@  in [VSTATIC]  VAR
    1:2:1: BASICDTYPE 0x7fffb8b15a60 <e35> {c5ab} @dt=this@(nw1)  logic kwd=logic
    1:2:1:1: RANGE 0x7fffb8b15b40 <e33> {c5ah}
    1:2:1:1:2: SUB 0x7fffb8b15c00 <e31> {c5aj} @dt=0@
    1:2:1:1:2:1: VARREF 0x7fffb8b104f0 <e255#> {c5ai} @dt=0@  p [RV] <- VAR 0x7fffb8b14da0 <e10> {c3am} @dt=0@  p [VSTATIC]  LPARAM
    1:2:1:1:2:2: CONST 0x7fffb8b15da0 <e23> {c5ak} @dt=0x7fffb8b15320@(G/swu32/1)  ?32?sh1
    1:2:1:1:3: CONST 0x7fffb8b15f10 <e32> {c5an} @dt=0x7fffb8b15320@(G/swu32/1)  ?32?sh0
    1:2: CELL 0x7fffb8b18970 <e92> {c10ab}  u_test2 -> MODULE 0x7fffb8b19270 <e228#> {c18ai}  test2  L3 [1ps]
    1:2:1: PIN 0x7fffb8b17e60 <e80> {c12af}  in -> VAR 0x7fffb8b1b410 <e143> {c24be} @dt=0@  in INPUT [VSTATIC]  PORT
    1:2:1:1: REPLICATE 0x7fffb8b17990 <e81> {c12ai} @dt=0x7fffb8b17d30@(G/w0)
    1:2:1:1:1: CONCAT 0x7fffb8b17880 <e74> {c12al} @dt=0@
    1:2:1:1:1:1: VARREF 0x7fffb8b10630 <e258#> {c12aj} @dt=0@  in [RV] <- VAR 0x7fffb8b16080 <e36> {c5aq} @dt=0@  in [VSTATIC]  VAR
    1:2:1:1:1:2: VARREF 0x7fffb8b10770 <e261#> {c12an} @dt=0@  in [RV] <- VAR 0x7fffb8b16080 <e36> {c5aq} @dt=0@  in [VSTATIC]  VAR
    1:2:1:1:2: CONST 0x7fffb8b17a50 <e75> {c12ai} @dt=0x7fffb8b17c00@(G/w32)  32'h1
    1:2:1: PIN 0x7fffb8b18120 <e83> {c13af}  out -> VAR 0x7fffb8b1d270 <e185> {c25be} @dt=0@  out OUTPUT [VSTATIC]  PORT
    1:2:2: PIN 0x7fffb8b18270 <e46> {c8ag}  param -> VAR 0x7fffb8b19810 <e103> {c20ap} @dt=0@  param [VSTATIC]  GPARAM
    1:2:2:1: MUL 0x7fffb8b18370 <e47> {c8ao} @dt=0@
    1:2:2:1:1: VARREF 0x7fffb8b10940 <e264#> {c8am} @dt=0@  p [RV] <- VAR 0x7fffb8b14da0 <e10> {c3am} @dt=0@  p [VSTATIC]  LPARAM
    1:2:2:1:2: CONST 0x7fffb8b18510 <e45> {c8aq} @dt=0x7fffb8b16c40@(G/swu32/2)  ?32?sh2
    1:2:2: PIN 0x7fffb8b186c0 <e55> {c9ag}  plus_p -> VAR 0x7fffb8b19d00 <e117> {c21ap} @dt=0@  plus_p [VSTATIC]  GPARAM
    1:2:2:1: CONST 0x7fffb8b187c0 <e54> {c9an} @dt=0x7fffb8b170e0@(G/swu32/4)  ?32?sh9

よく見なければならいのは、CELLのPINが2つポートとして宣言されている。

f:id:msyksphinz:20210409002501p:plain

その次の010_paramLinkではこれらのポートが静的な値として変更されている。インスタンスの名前がtest_2_P8_PB9と変更されている。

f:id:msyksphinz:20210409002534p:plain

ログには以下のように表示されていた。

- V3Param.cpp:346:    Name: test2->test2__P8_PB9->test2__P8_PB9
- V3Param.cpp:546:         De-parameterize to new: MODULE 0x7fffd93c4ae0 <e332#> {c19ai}  test2__P8_PB9  L3 [1ps]
- V3Param.cpp:579:           set param VAR 0x7fffd93c4c20 <e103> {c21ap} u4=0x50 @dt=0@  param [VSTATIC]  GPARAM = CONST 0x7fffd93c7d50 <e327#> {c8ao} @dt=0x7fffd93c8af0@(G/swu32/3)  32'h8
- V3Param.cpp:579:           set param VAR 0x7fffd93c4ff0 <e117> {c22ap} u4=0x150 @dt=0@  plus_p [VSTATIC]  GPARAM = CONST 0x7fffd93cc790 <e54> {c9an} @dt=0x7fffd93cb0b0@(G/swu32/4)  ?32?sh9
- V3Param.cpp:787:         Done with MODULE 0x7fffd93c4ae0 <e332#> {c19ai}  test2__P8_PB9  L3 [1ps]
- V3Param.cpp:794:         Done with CELL 0x7fffd93cc940 <e92> {c11ab}  u_test2 -> MODULE 0x7fffd93c4ae0 <e332#> {c19ai}  test2__P8_PB9  L3 [1ps]
- V3Param.cpp:871:     MOD-done
- V3Param.cpp:849:     MOD   MODULE 0x7fffd93c4ae0 <e332#> {c19ai} u5=0x1  test2__P8_PB9  L3 [1ps]
- V3Param.cpp:871:     MOD-done
- V3Param.cpp:912:     MOD-dead?  MODULE 0x7fffd93cd240 <e228> {c19ai}  test2  L3 [1ps]
- V3Param.cpp:909:     MOD-done   MODULE 0x7fffd93c4ae0 <e332#> {c19ai} u5=0x1  test2__P8_PB9  L3 [1ps]
     // Make sure all parameters are constantified
     virtual void visit(AstVar* nodep) override {
         if (nodep->user5SetOnce()) return;  // Process once
         iterateChildren(nodep);
         if (nodep->isParam()) {
             if (!nodep->valuep()) {
                 nodep->v3error("Parameter without initial value is never given value"
                                << " (IEEE 1800-2017 6.20.1): " << nodep->prettyNameQ());
             } else {
                 V3Const::constifyParamsEdit(nodep);  // The variable, not just the var->init()
                 if (!VN_IS(nodep->valuep(), Const)
                     && !VN_IS(nodep->valuep(), Unbounded)) {  // Complex init, like an array
                     // Make a new INITIAL to set the value.
                     // This allows the normal array/struct handling code to properly
/* ... 中略 ... */

おそらくV3Const::costifyParamEdit(nodep)おそらくパラメータの定数への変換を行っていると思われる。この辺について深堀していきたい。