FPGA開発日記

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

SystemVerilog の Streaming演算について勉強 (Verilatorでの生成結果)

SystemVerilogのStream演算について、念のためVerilatorでどのように生成されているのか確認しておこうと思った。

まず、簡単な構成として以下のようなStream演算をコンパイルしてみた。

 initial begin
 static bit [7:0] value_a = 8'h8C;
 static bit [7:0] value_b = {<<{value_a}};

   $display("value_b = 0x%h", value_b);
 end

C++に変換された結果を見てみると、単純に定数が生成されていた。あ、そうですか...

     // Body
     vlSelf->streaming__DOT__unnamedblk1__DOT__value_a = 0x8cU;
     vlSelf->streaming__DOT__unnamedblk1__DOT__value_b = 0x31U;
     VL_WRITEF("value_b = 0x31\n");

次に、入出力を付けてモジュール宣言してみた。

 module streaming
   (
    input logic [ 7: 0]  in,
    output logic [ 7: 0] out
    );
 assign out = {<<{in}};

生成されたC++を確認してみると、マクロが埋め込まれているようだった。

 VL_INLINE_OPT void Vstreaming___024root___combo__TOP__2(Vstreaming___024root* vlSelf) {
     if (false && vlSelf) {}  // Prevent unused
     Vstreaming__Syms* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;
     VL_DEBUG_IF(VL_DBG_MSGF("+    Vstreaming___024root___combo__TOP__2\n"); );
     // Body
     vlSelf->out = VL_STREAML_FAST_III(8,8,32,(IData)(vlSelf->in), 0);
 }

マクロの定義を確認してみる。意外とよく見るビット反転のプログラムで構成されていた。

github.com

    switch (rd_log2) {
        case 0:
            ret = ((ret >> 1) & VL_UL(0x55555555))
                | ((ret & VL_UL(0x55555555)) << 1);  // FALLTHRU
        case 1:
            ret = ((ret >> 2) & VL_UL(0x33333333))
                | ((ret & VL_UL(0x33333333)) << 2);  // FALLTHRU
        case 2:
            ret = ((ret >> 4) & VL_UL(0x0f0f0f0f))
                | ((ret & VL_UL(0x0f0f0f0f)) << 4);  // FALLTHRU
        case 3:
            ret = ((ret >> 8) & VL_UL(0x00ff00ff))
                | ((ret & VL_UL(0x00ff00ff)) << 8);  // FALLTHRU
        case 4:
            ret = ((ret >> 16) | (ret << 16));
    }