Verilator 5系 SystemVerilog対応状況 詳細ガイド (2025年6月版)

---

### Verilator 5系 SystemVerilog対応状況 詳細ガイド (2025年6月版)

#### 1. はじめに

##### 1.1. 本記事の位置づけ
本記事は、オープンソースの高速RTLシミュレータである**Verilator**のバージョン5系における、SystemVerilog言語機能の対応状況をまとめた詳細ガイドです。Verilatorの設計思想（合成可能なロジックの高速な機能検証）を背景に、各機能のサポートレベルだけでなく、実務上の制約や代替策についても解説します。

##### 1.2. 対象読者と前提知識
*   **対象読者**: Verilatorを実務で利用する、または導入を検討しているハードウェア/検証エンジニア。
*   **前提知識**: SystemVerilogの基本的な文法と、C++によるテストベンチ作成の基礎的な経験があることを想定しています。

##### 1.3. 検証環境とバージョン情報
*   **主要検証バージョン**: 安定版リリースである **`tag v5.036`** (2025-04-27リリース) を基準とします。（開発版の**v5.037-devel**も存在します）
*   **必須C++コンパイラ**: **GCC 13以上**または**Clang 18以上**の使用が必須です。
*   **OSサポートに関する注意**: Ubuntu 20.04 LTSの公式サポートはv5.034で終了しました。同様に、CentOS 7 / Rocky Linux 8向けの公式パッケージもv5.034が最後となります。古いLTS環境を利用する場合は、Verilatorのバージョンを`v5.034`に固定することを推奨します。

---

#### 2. SystemVerilog機能対応表

**凡例**
*   **◯**: ほぼ完全対応。主要なユースケースで問題なく動作する。
*   **△**: 部分対応。特定のオプションやコーディングスタイルが必要、または一部機能に制約がある。
*   **✕**: 未対応または非推奨。機能しないか、意図しない動作をする可能性が高い。

| 区分 | 主な言語機能 | 状態 | 詳細・備考 | 代替策・ワークアラウンド |
| :--- | :--- | :--- | :--- | :--- |
| **基本構文** | `always_comb`, `always_ff`, `always_latch` | ◯ | 組み合わせロジックは感度リストなしで自動的に依存関係を解決する。 | 特になし。標準的な使い方を推奨。 |
| **型システム** | `enum`, `typedef`, `string` | ◯ | C++の型に変換され、ホストC++側でも型安全が保証される。 | 特になし。積極的に活用を推奨。 |
| | `struct`/`union` (packed/unpacked) | △ | **packed**: ◯。<br>**unpacked**: メンバへの代入は同一クロックドメインの`always_ff`内が前提。ブロッキング/ノンブロッキング混在不可。 | 複雑なデータ構造は、C++側の構造体とDPI-C経由でマッピングする。 |
| **配列** | 固定長配列 (packed/unpacked) | ◯ | 配列の次元や範囲外アクセスは、コンパイル時に静的に検出されることが多い。 | 特になし。 |
| | 動的配列, キュー (`queue`) | △ | 基本的なメソッドはサポート。v5.034以降、内部実装が見直され性能が向上したが、複雑な操作には依然として制限あり。 | C++の`std::vector`等を使い、DPI-C経由で連携する。 |
| | 連想配列 (`associative array`) | △ | `exists()`, `first()`, `last()`, `num()` など主要メソッドは動作する。`delete()`のみ未実装。 | C++の`std::map`や`std::unordered_map`をDPI-C経由で利用する。 |
| **接続性** | `interface`, `modport` | △ | 基本的なインタフェースと`modport`はサポート。階層をまたいだ接続に利用可能。 | トップモジュールでインスタンス化し、`bind`文やポート接続でDUTと接続する。 |
| | `virtual interface` | ✕ | **未実装**。UVM等クラスベース検証環境を直接動かせない主要因の一つ。 | DPI-CやVPIを使い、C++テストベンチ側で信号パスを管理・接続する。 |
| **OOP機能** | クラス基本定義, `nested`/`generated class` | △ | `nested`/`generated class`は正式サポート済み。**`virtual`メソッドと`$cast`は未対応**。 | C++で完全なオブジェクト指向テストベンチを記述し、DPI-Cで連携するのが最も強力。 |
| **ランダム化** | `rand`/`randc`, `std::randomize()` | △ | `solve...before`は実用レベルに安定化。`randc`の周期保証は未実装（例: >32bit、特に64bit以上では実質的に非周回となる問題 [#5259](https://github.com/verilator/verilator/issues/5259)）。`dist`など複雑な制約は未対応。 | C++の`<random>`等、高機能な乱数生成器をDPI-C経由で利用する。 |
| **アサーション (SVA)** | 即時アサーション (`assert final`) | △ | 単一サイクルの最終評価値に基づくアサーションはサポート。`--assert-enable`によるグローバル制御が可能。 | 単純な条件チェックには有効。 |
| | 並列プロパティ/シーケンス (`##`, "\|->") | ✕ | **未実装**。時間的な順序関係を持つプロパティは解釈されず、無視される。 | C++テストベンチ側でFSMを実装し、シーケンスを監視・検証する。 |
| **カバレッジ** | `covergroup`, `coverpoint` | ✕ | **未実装**。Roadmapにも記載がなく、当面サポートされる見込みは低い。 | `SVA cover property`で代替するか、C++側で独自に機能カバレッジを実装する。 |
| | SVAベース機能カバレッジ (`cover property`) | △ | `--coverage`で有効化。**単一サイクルの即時プロパティのみ対象**で、シーケンスを含むものは無視される。後処理ツール`verilator_coverage --annotate`実行時に階層HTMLレポートが生成可能。 | 合成可能なサブセットのSVAでカバレッジ項目を記述する。 |
| | 式カバレッジ (Expression Coverage) | △ | `--coverage --coverage-expr`で有効化 (v5.034+)。**組合せ回路の式のみ対象**で、`always_ff`内などは対象外。Fuzzing等で論理式の各項が結果に与えた影響を計測できる（β版機能）。 | Fuzzingや形式的検証との組み合わせで威力を発揮。 |
| **スケジューラ** | イベント制御 (`@`, `wait`) | △ | `--timing`有効時にサポート。サイクルベースシミュレーションが基本のため多用は非推奨。 | テストベンチの同期には`posedge clk`など、クロック同期を基本とする。 |
| | `fork`/`join`, `join_any`, `join_none` | △ | v5.034で安定性が向上。警告コードが`FORKJOINLIFE`に整理された（主に`automatic`変数のライフタイム問題）。既存の`lint_off`指定は修正が必要。 | 複雑な並列処理は、C++の`std::thread`などを使い、テストベンチ側で管理する。 |
| **4値・Z対応**| `===`/`!==`, X/Z | △ | 2値主体。`--x-assign`でXをランダム化可能。**注意：`===`/`!==`は、左右のオペランドどちらにも定数が含まれない場合、2値比較に降格される。** | リセット時に全FFを初期化するなど、Xの発生源を断つ設計を心掛ける。 |
| **外部連携** | **DPI-C** (`import`/`export`) | ◯ | C++との連携における推奨手段。Verilator独自の拡張も提供され、最も堅牢で高速。 | 複雑なテストベンチ、モデル連携、UVM的な環境構築に必須。 |
| | **VPI** (`--vpi`) | △ | **読み出し(◯)**: 多次元配列を含めほぼフルサポート。ただし`packed struct`のメンバ走査など一部制限あり。<br>**書き込み(△)**: `packed logic/scalar`（構造体・unpackedは不可）が対象。多次元配列は実験的サポート。**プラグマに加え`--vpi-write`オプションが必須。**本番利用時は`--vpi-no-write`で無効化を推奨。<br>**【実務メモ】**<br>1. **信号公開**: `/*verilator public_flat_rd*/` や `/*verilator public_flat_rw*/` 等のプラグマが必須。 | 互換性維持目的以外では、新規開発にはDPI-Cを強く推奨。 |

---

#### 3. 実用上のヒント

##### 3.1. v5.036での主な新機能と変更点
*   **Expression Coverage (`--coverage-expr` — `--coverage`との併用必須)**: 組み合わせロジックの各項が式の最終結果に影響を与えたかを計測する、高度なカバレッジ機能です（β版）。
*   **カバレッジ対象信号の拡張 (`--coverage-underscores`)**: 通常は無視される、名前がアンダースコア(`_`)で始まる信号もカバレッジ対象に含めます。
*   **トレースファイルのローテーション (`--trace-fst-rotate <N>`)**: 長時間シミュレーションで肥大化するFSTファイルを、指定したファイル数(`N`)でローテーションし、ディスク容量の溢れを防ぎます。
*   **大規模デザイン向け並列Lint (`--lint-only --lint-split`)**: Lint処理を並列化し、大規模SoCのCIにおける実行時間を短縮します。

##### 3.2. パフォーマンスに関する考慮事項
*   **カバレッジコンパイルの高速化**: v5.034以降、`--split-instances`使用時の内部処理が高速化され、大規模デザインのカバレッジ取得時のコンパイル時間が10-15%改善しました。
*   `--timing`, `--coverage`, `--trace`などのオプションは依然として性能に影響を与えます。デバッグや最終回帰テストなど、目的に応じて限定的に使用してください。

##### 3.3. 主要機能の簡単な使用例
*   **DPI-CによるC++関数連携:** C++側のチェック関数をSystemVerilogから呼び出します。
    ```systemverilog
    // SystemVerilog側
    module dut ( ... );
        import "DPI-C" function void check_result(input int value);
        // ...
    endmodule
    ```
*   **VPIのための信号公開:** `/*verilator public_flat_rd*/`プラグマで信号を公開します。
    ```systemverilog
    // C++から読み出したい信号にプラグマを付与
    logic [7:0] internal_counter /*verilator public_flat_rd*/;
    ```

---

#### 4. 参考資料

本ガイドでカバーしきれない詳細な仕様や最新情報については、必ず公式ドキュメントおよびリリースノートをご参照ください。

*   **Verilator 公式サイト & ドキュメント**: [https://verilator.org](https://verilator.org)
*   **Verilator GitHubリポジトリ `Changes` ファイル**: [https://github.com/verilator/verilator/blob/master/Changes](https://github.com/verilator/verilator/blob/master/Changes)
*   **Verilator Wiki: Advanced Coverage**: [https://github.com/verilator/verilator/wiki/Advanced-Coverage](https://github.com/verilator/verilator/wiki/Advanced-Coverage)

---

#### 5. 更新履歴
*   **2025-06-22 (改訂)**: v5.036安定版の情報を基に、Expression Coverage、VPI書き込みサポート、OSサポート状況、各種制限事項を更新。
*   **2024-06-22 (初版)**: v5.032の情報を基に作成。

---
**免責事項**: 本資料は、その内容の正確性について保証はありません。最終的な判断は公式ドキュメントを基に行ってください。