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つのパラメータを持っている。param
とplus_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つポートとして宣言されている。
その次の010_paramLink
ではこれらのポートが静的な値として変更されている。インスタンスの名前がtest_2_P8_PB9
と変更されている。
ログには以下のように表示されていた。
- 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)
おそらくパラメータの定数への変換を行っていると思われる。この辺について深堀していきたい。