FPGA開発日記

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

Verilatorのコンパイルフローを観察する (11. V3Const.cppについて)

Verilatorの解析続き。

V3Const.cppには、いくつかの定数最適化が加わっているようだ。astgenというPythonスクリプトによってソースコードが拡張されている。展開用のスクリプトは長くてすぐには理解できないのだが、生成されたソースコードを読んでみる。

  • verilator/src/obj_dbg/V3Const__gen.cpp
     // Generated by astgen
     virtual void visit(AstAdd* nodep) override {
         iterateChildren(nodep);
         if (match_NodeBiop_0(nodep)) return;
         if (match_NodeBiCom_0(nodep)) return;
         if (match_NodeBiComAsv_0(nodep)) return;
         if (match_NodeBiComAsv_1(nodep)) return;
         if (match_NodeBiComAsv_2(nodep)) return;
         if (match_NodeBiComAsv_3(nodep)) return;
         if (match_Add_0(nodep)) return;
         if (match_Add_1(nodep)) return;
     }

AstAddノードに遭遇すると、これらの最適化を行うようだ。

  • match_Add_0 / match_Add_1 どちらかのオペランドが0の場合は加算ノードを省略する。
     bool match_Add_0(AstAdd* nodep) {
     // TREEOP ("AstAdd   {$lhsp.isZero, $rhsp}",   "replaceWRhs(nodep)")
     if (m_doNConst && nodep->lhsp()->isZero()) {
         UINFO(7,cvtToHex(nodep)<<" TREEOP ( AstAdd $lhsp.isZero, $rhsp , replaceWRhs(nodep) )\n");
         replaceWRhs(nodep);
         return true;
     }
     return false;
     }

この条件はこのマクロから来ているようだ。

     // Zero on one side or the other
     TREEOP ("AstAdd   {$lhsp.isZero, $rhsp}",   "replaceWRhs(nodep)");
     TREEOP ("AstAdd   {$lhsp, $rhsp.isZero}",   "replaceWLhs(nodep)");

AstNodeBiOpは2項演算のノードにはすべて適用されるようだ。つまり、両方のオペランドが定数の場合はこれを置き換える。

     // Generic constants on both side.  Do this first to avoid other replacements
     TREEOPA("AstNodeBiop {$lhsp.castConst, $rhsp.castConst, nodep->isPredictOptimizable()}",  "replaceConst(nodep)");
     // Generated by astgen
     bool match_NodeBiop_0(AstNodeBiop* nodep) {
     // TREEOPA("AstNodeBiop {$lhsp.castConst, $rhsp.castConst, nodep->isPredictOptimizable()}",  "replaceConst(nodep)")
     if (VN_IS(nodep->lhsp(),Const) && VN_IS(nodep->rhsp(),Const) && nodep->isPredictOptimizable()) {
         UINFO(7,cvtToHex(nodep)<<" TREEOPA( AstNodeBiop $lhsp.castConst, $rhsp.castConst, nodep->isPredictOptimizable() , replaceConst(nodep) )\n");
         replaceConst(nodep);
         return true;
     }

BiComというのは2項演算の可換な演算のようだ。これに対する最適化も定義されている。

         if (match_NodeBiComAsv_0(nodep)) return;
         if (match_NodeBiComAsv_1(nodep)) return;
         if (match_NodeBiComAsv_2(nodep)) return;
         if (match_NodeBiComAsv_3(nodep)) return;