3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude Code を使用して SystemVerilogシミュレータ を開発してみた(C++ツールチェーン編)

Last updated at Posted at 2025-07-06

はじめに

Claude Code で開発するにしても、SystemVerilogシミュレータのような大規模で複雑なソフトウェア開発では、優れたツールセットが生産性と品質を大きく左右します。特にC++をメイン言語とする場合、そのエコシステムは広大で、どのツールを選ぶべきか迷うことも少なくない状況です。

本記事では、自作のSystemVerilogシミュレータ mrun(仮) 開発プロジェクトで実際に効果が大きかったツールを、ビルドシステム選定からHDL特化検証まで網羅的にご紹介します。単なるリストではなく、「なぜこれが必要か」「導入難易度」「具体的な導入コマンド例」、さらには 「トラブルシューティングの実例」 まで踏み込んだ、実践的なガイドになっていると思います。

なお、当初目標としていた C++23 での開発は、slang v8.1 との互換性確保のためあきらめ、slangと同じ C++20 での開発に変更しました ...


mrun(仮)プロジェクトの現状(2025年1月9日更新)

  • 開発フェーズ: Phase E(高度な言語機能の実装)進行中
  • バージョン: 0.5.5(フェーズE、ビルド5)
  • 完了フェーズ:
    • Phase 0〜D(基本〜高度な機能)完了 ✅
    • Phase E.1: ストリーミング演算子、文字列連結、連想配列完了 ✅
    • Phase E.2: ソフト制約、dist演算子(基本実装)完了 ✅
    • Phase E.3: 含意演算子(->)、if-else制約完了 ✅
    • Phase E.4: dist演算子とuniqueness制約の完全実装完了 ✅
    • Phase E.5: shallow copy、compound assignment、randomize() with {}完了 ✅
  • Phase E進行中:
    • E.6: typed constructor param、tagged union修正(実装中)
    • E.7: constraint_mode/rand_mode、UVMコンポーネント階層(実装予定)
  • 対応バージョン: SystemVerilog IEEE 1800-2023 (目標)
  • 言語標準: C++20(slang v8.1 との互換性確保のため C++23 対応はあきらめました ... )
  • コンパイラ: clang++ 21.0.0(ローカル) / clang++ 21(CI/CD)
  • ビルドシステム: CMake 4.0.3 + Ninja 1.11.1
  • 主要依存: slang v8.1.0(SystemVerilogフロントエンド)、CLI11 v2.4.2、tl::expected v1.1.0、mimalloc v2.1、Google Test v1.14.0、LZ4 v1.10.0
  • テスト実績:
    • 単体テスト: 150個以上全て成功
    • sv-tests: 全体進捗87.8%(911/1037テスト成功)
    • Chapter 16(制約): 53.9%(34/63テスト成功)
    • Chapter 18(ランダム化): 42.5%(57/134テスト成功)

ツールエコシステムの全体像

まずは、開発プロセスにおける各ツールの関係性を俯瞰してみます。


【STEP 1】開発基盤の構築

コードを書き始める前に、プロジェクトの骨格となる環境を固めます。

1.1. ビルドシステムの選定

mrun(仮)プロジェクトではCMakeを採用しています。

観点 CMake(mrun採用) 採用理由
バージョン 4.0.3 C++20サポート、FetchContent改良版、プリセット機能
ジェネレータ Ninja 1.11.1採用 ビルド高速化(make比で50%短縮)
IDE統合 VS Code完全対応 CMakeTools拡張、IntelliSense統合
実際の設定例 cmake -GNinja -DCMAKE_BUILD_TYPE=Debug .. デフォルトではSanitizer無効

mrun(仮)プロジェクトのビルド構成

# 開発用デバッグビルド(Sanitizerはデフォルト無効、パフォーマンス優先)
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON ..

# 品質確認ビルド(バグ調査・PR前確認用、ビルド時間2-3倍増加)
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DENABLE_ASAN=ON -DENABLE_UBSAN=ON ..

# リリースビルド(最適化有効)
cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-march=native" ..

# テスト専用ビルド(Google Test統合)
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON ..
ninja mrun_unit_tests && ./tests/unit/mrun_unit_tests

# ccacheが利用可能な場合は自動検出・有効化されます

1.2. コンパイラのバージョン管理

mrun(仮)プロジェクトはC++20準拠で、以下のコンパイラをサポートしています。

# Ubuntu 24.04 LTSでの推奨セットアップ
sudo apt install g++-14 clang-21

# update-alternativesでの管理(mrun推奨)
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-14 140
sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-21 210

# 実際の切り替え
sudo update-alternatives --config clang++

mrun(仮) での実際のコンパイラ使い分け

  • 開発時: clang++ 21.0.0(最新C++20機能、優れた診断メッセージ)
  • CI/警告チェック: clang++ 21(Ubuntu 24.04標準、安定性重視)
  • リリースビルド: clang++ 21.0.0(最適化性能が良好)

1.3. ビルド効率・依存管理ツール

mrun(仮)プロジェクトで実際に使用しているツール構成です。

目的 mrun(仮)採用ツール 実際の効果と設定
ビルド高速化 Ninja + ccache ninja -j32でフルビルド2分以内。
ccacheインストール時は自動で70%高速化。
設定例: ninja -j32 で32並列ビルド
依存ライブラリ管理 FetchContent 中心 slang、CLI11、tl::expected、mimalloc、Google TestをFetchContentで管理。
例: CMakeLists.txtで自動ダウンロード・ビルド
テストフレームワーク Google Test v1.14.0 48個のユニットテスト全て成功。CTestと統合。
実行例: ctest --output-on-failure または ./tests/unit/mrun_unit_tests
プリコミット pre-commit 3.6.2 + clang-format 21 .pre-commit-config.yamlで自動フォーマット。
設定例: pre-commit install でGitフック自動化

mrun(仮)の実際の依存関係

# CMakeLists.txtでの依存管理例(P0-1実装)
FetchContent_Declare(
    slang
    GIT_REPOSITORY https://github.com/MikePopoloski/slang.git
    GIT_TAG        v8.1
)

FetchContent_Declare(
    googletest
    GIT_REPOSITORY https://github.com/google/googletest.git
    GIT_TAG        v1.14.0
)

# mimalloc統合(pedantic警告を適切に抑制)
FetchContent_MakeAvailable(mimalloc)
if(TARGET mimalloc-static)
    target_compile_options(mimalloc-static PRIVATE 
        $<$<CXX_COMPILER_ID:Clang>:-Wno-pedantic>
    )
endif()

【STEP 2】品質保証の自動化

実行前にバグの芽を摘み、コード品質を維持する仕組みです。

2.1. 静的解析&セキュリティ

mrun(仮)プロジェクトで実際に活用している静的解析ツールです。

カテゴリ mrun(仮)採用ツール 実際の検出例とコマンド
汎用静的解析 clang-tidy 未使用変数、メモリリークを多数検出。
実行例: clang-tidy src/**/*.cpp -- -std=c++20
補完的解析 cppcheck clang-tidyが見逃したnull参照を発見。
実行例: cppcheck --enable=all src/
依存関係過剰検知 手動レビュー 大規模リファクタリング時に実施。include graphを可視化。
セキュリティスキャン GitHub Dependabot slangの脆弱性を自動検出・PR作成。無料で十分実用的。

mrun(仮)での静的解析設定(.clang-tidy)

Checks: >
  -*,
  bugprone-*,
  clang-analyzer-*,
  cppcoreguidelines-*,
  modernize-*,
  performance-*,
  readability-*,
  -modernize-use-trailing-return-type,
  -cppcoreguidelines-avoid-magic-numbers

WarningsAsErrors: 'bugprone-*,clang-analyzer-*'

2.2. 動的解析&パフォーマンス計測

mrun(仮)プロジェクトで実際に効果があった動的解析手法です。

Sanitizers実践活用(mrunでの実績と方針)

Sanitizer運用方針(2025年7月6日決定):

  • デフォルト: 無効(ビルド時間優先、開発効率重視)
  • 有効化条件: バグ調査、プルリクエスト前確認、CI環境での品質保証
  • ビルド時間影響: 2-3倍増加(slang依存関係が大きいため)
# 標準開発ビルド(高速、推奨)
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON ..
ninja -j32  # 約1分40秒

# 品質確認ビルド(必要時のみ)
cmake -GNinja -DCMAKE_BUILD_TYPE=Debug \
      -DENABLE_ASAN=ON -DENABLE_UBSAN=ON ..
ninja -j32  # 約4-5分(2-3倍増加)

# 実際の効果: メモリエラー、未定義動作の早期検出
# Phase E段階で複雑な制約処理が増加した際に特に有効

パフォーマンス計測の実例

ツール mrun(仮)での用途 発見した最適化機会
gdb + backward-cpp デバッグとクラッシュ解析 セグフォルト時に自動でスタックトレース表示、原因特定時間50%短縮
Google Benchmark Value演算子の性能測定 operator+が想定より10倍遅い→インライン化で解決
hyperfine sv-tests実行時間の統計的測定 always #delay修正前後の性能を定量比較、回帰防止
分析ツール 失敗パターンの自動分類 stoulエラー156件(25.3%)を特定→優先修正で大幅改善

Sanitizersの活用Tips

# AddressSanitizerを有効にしてビルド
cmake -DCMAKE_BUILD_TYPE=Debug -DENABLE_SANITIZERS=ON ..
# 実行時にエラーを検出
./mrun test.sv

【STEP 3】テスト&HDL特化検証

mrun(仮)プロジェクトのテスト戦略と実績です。

テストフレームワークとカバレッジ

目的 mrun(仮)採用ツール 実績と設定例
単体テスト Google Test v1.14.0 + CTest 102個のテストケース全て成功。
実行例: ./tests/unit/mrun_unit_tests
カバレッジ計測 gcovr(将来予定) 目標: 85%以上のコードカバレッジ
計測例: cmake -DENABLE_COVERAGE=ON ..
リグレッションテスト 自動テスト実行(CI統合予定) GitHub Actionsでの自動テスト実行を計画

SystemVerilog準拠テスト(sv-tests)

# sv-tests実行状況(2025年1月9日)
# 全体進捗: 87.8% (911/1037テスト成功)
# 実装済みテスト: 1037 (成功率: 87.8%)
# 全22チャプター実行(5-26、17/19除く)

# sv-testsローカル実行コマンド
./scripts/run_sv_tests_local.sh  # 全チャプター並列実行

# 単体テスト実行(150個以上全て成功)
ninja mrun_unit_tests && ./tests/unit/mrun_unit_tests
# または
ctest --output-on-failure

HDL特化検証ツール

検証項目 実装状況 今後の計画
波形出力 VCD/FST出力実装 大規模波形の最適化
VPI/DPI DPI基本実装 VPI完全実装予定
階層ダンプ 完全実装 階層解析・可視化機能完成
AST→IR変換 高度な構文対応 制約、クラス、ランダム化対応済み
回路評価 完全実装 組み合わせ・順序回路評価エンジン
制約ソルバー 基本実装 ソフト制約、dist演算子対応中

Phase Eまでで統合済みのツール(2025年1月8日更新)

Google Test v1.14.0(テストフレームワーク)

# FetchContentで自動統合
FetchContent_Declare(
    googletest
    GIT_REPOSITORY https://github.com/google/googletest.git
    GIT_TAG        v1.14.0
)

# GMockは無効化(BUILD_GMOCK=OFF)
# character-conversion警告を抑制

効果:

  • 150個以上のテスト全て成功(Phase 0〜E実装分)
  • CTest統合により ctest コマンドで簡単実行
  • TDD開発により品質とスピードを両立

ccache(ビルド高速化)

# CMakeに統合済み - インストールするだけで有効化
sudo apt install ccache

# 統計情報の確認
ccache -s

# キャッシュクリア(必要時)
ccache -C

効果:

  • 再ビルド時間を70%短縮
  • sv-tests修正のイテレーション速度が大幅向上
  • CI/CDでも効果的

AddressSanitizer/UndefinedBehaviorSanitizer(メモリエラー検出)

運用方針: デフォルト無効、必要時のみ有効化(2025年7月6日決定)

# 標準開発ビルド(高速)
cmake -DCMAKE_BUILD_TYPE=Debug ..
ninja -j32  # 約1分40秒

# 品質確認ビルド(必要時のみ)
cmake -DCMAKE_BUILD_TYPE=Debug -DENABLE_ASAN=ON -DENABLE_UBSAN=ON ..
ninja -j32  # 約4-5分(2-3倍増加)

# 実行時に自動でメモリエラーを検出
./mrun problematic_test.sv
# ==> ERROR: AddressSanitizer: heap-buffer-overflow...

効果:

  • 複雑なIR操作でのメモリエラーを即座に検出
  • Value/Expression/Generate実装時のバグを早期発見
  • セグフォルトの原因を詳細に表示
  • 使用場面: バグ調査、PR前確認、CI環境での品質保証

hyperfine(統計的ベンチマークツール)

# インストール
./scripts/install_hyperfine.sh

# CMakeターゲットで実行
make benchmark        # 一般的なベンチマーク
make benchmark-delay  # always #delay問題の測定

# 直接実行例
hyperfine --warmup 3 './mrun test1.sv' './mrun test2.sv'

効果:

  • always #delay無限ループ問題の定量的測定
  • 修正前後の性能を統計的に比較
  • CI/CDでの性能回帰検出

sv-tests失敗パターン分析ツール

# 全チャプター分析(約10分)- 全20チャプター対応
./scripts/analyze_sv_failures.py

# ダッシュボード生成
./scripts/run_sv_tests_local.sh

# 進捗状況確認
# 全体進捗: 87.8% (790/899テスト成功)
# 実装済みテスト: 899 (成功率: 87.8%)

効果:

  • 失敗原因を自動分類して修正優先順位を提案
  • 各エラーパターンの影響度を可視化
  • 全20チャプターのテスト実行とダッシュボード生成

【STEP 4】CI/CD・リリース・ドキュメント

mrun(仮)プロジェクトの自動化とドキュメント戦略です。

CI/CD実装(GitHub Actions)

# .github/workflows/build.ymlの概要
name: Build and Test
on: [push, pull_request]

jobs:
  build:
    strategy:
      matrix:
        compiler: [g++-14, clang++-21]
        build_type: [Debug, Release]

    steps:
      - uses: actions/checkout@v3
      - name: Build with ${{ matrix.compiler }}
        run: |
          cmake -B build -DCMAKE_CXX_COMPILER=${{ matrix.compiler }}
          cmake --build build -j$(nproc)
      - name: Run tests
        run: ctest --test-dir build --output-on-failure

リリース戦略

方法 現状 将来計画
バイナリ配布 手動ビルド+GitHub Releases CPack自動パッケージング
コンテナ なし Docker公式イメージ提供
パッケージ管理 なし Ubuntu PPA、AUR対応

ドキュメント管理

  • コード: Doxygenコメント記述中(約60%完了)
  • ユーザーガイド: Markdown形式でdocs/配下に集約
  • 開発記録: セッションごとにMarkdownで詳細記録
  • 図表: Mermaidで統一(GitHub/Qiita直接表示対応)

推奨ツール導入ロードマップ

mrun(仮)プロジェクトの経験に基づく、段階的なツール導入指針です。

mrun(仮)プロジェクトの成長過程

フェーズ 期間 主要ツール 効果
Phase 0: 基本インフラ 完了 CMake 4.0.3, Ninja, clang++ 21, Google Test インフラ確立、48テスト成功
Phase 1: 基本言語機能 完了 +Generate IR、型システム拡張 Generate構文、配列対応
Phase 2: 高度な機能 実行中 +パッケージ、インターフェース パッケージシステム実装
Phase 3: 高度な制御構造 実行中 +fork-join、ファイル操作 並列実行制御実装
Phase 4: 検証機能 実行中 +アサーション、カバレッジ 基本的な検証機能実装
Phase 5: 最適化 実行中 +最適化パス、高速化 実行効率改善
Phase A: VPI/DPI 実行中 +SystemVerilog DPI DPI関数呼び出し実装
Phase B: ライブラリ統合 +標準ライブラリ SystemVerilogライブラリ対応
Phase C: UVM対応 実行中 +UVM基本サポート UVM基本クラス対応
Phase D: 拡張機能 +カスタム拡張 ユーザー拡張機能
Phase E: 高度な言語機能 実行中 +制約ソルバー、ランダム化 87.8%進捗、制約機能実装中

トラブルシューティングの実例

mrun開発で実際に遭遇した問題と解決策です。

Q1. Google Test v1.14.0でcharacter-conversion警告

問題 clang++ 21.0.0でGoogle Testビルド時に警告エラー
原因 char16_t → char32_tの暗黙変換
解決策 CMakeで一時的に警告を抑制
add_compile_options(-Wno-character-conversion)

Q2. slang v8.1 APIの非互換性

問題 Diagnostic::isWarning()が存在しない
原因 slang v8.1でAPIが変更されている
解決策 isError()のみ使用、詳細なエラー表示はP0-2で実装

Q3. tl::expectedのテストビルドエラー

問題 non-void関数でreturn文がない
原因 tl::expected内部のテストコードの問題
解決策 -DBUILD_TESTING=OFFでテストを無効化

Q4. mimallocでpedantic警告

問題 -Wpedanticで大量の警告
原因 mimallocのコードスタイル
解決策 ターゲット固有のオプションで抑制
target_compile_options(mimalloc-static PRIVATE -Wno-pedantic)

Q5. CTestでtl::expected::testsが失敗

問題 実行ファイルが見つからない
原因 tl::expectedがテスト実行ファイルを生成しない
解決策 無視して問題なし(mrunのテストは全て成功)

Q6. CLI11で-Dオプションが認識されない

問題 mrun -D DEFINE=1 test.sv で "files is required" エラー
原因 CLI11は位置引数(ファイル名)をオプションより前に要求する
解決策 ファイル名を先に指定: mrun test.sv -D DEFINE=1
実装例 parse_complete_callbackを使用してオプション順序を柔軟に

Q7. slangのCallExpressionから配列メソッドのwith句を抽出

問題 array.find_first with (item == value) の with句が取得できない
原因 slangではSystemCallInfo内のIteratorCallInfoに格納されている
解決策 std::get<1>(callExpr->subroutine).extraInfo からIteratorCallInfoを取得
実装例 auto& iterInfo = std::get<1>(systemInfo.extraInfo); iterExpr = iterInfo.iterExpr;

Q8. 文字列値の比較で常にX(不定値)が返る

問題 item == "hello" の評価結果が常にX
原因 ValueOps::equal関数がStringValueをLogicVectorに変換しようとしていた
解決策 StringValue専用の比較ロジックを追加
実装例 if (auto strA = std::dynamic_pointer_cast<ir::StringValue>(a)) { ... }

Q9. Sanitizerを有効にするとビルド時間が大幅増加

問題 ASan/UBSan有効時にビルド時間が2-3倍(4-5分)に増加
原因 slangなどの大規模依存関係もSanitizerでビルドされるため
解決策 デフォルトでSanitizer無効、必要時のみ有効化する運用方針を採用
運用例 通常開発: -DENABLE_ASAN=OFF、バグ調査時: -DENABLE_ASAN=ON

Q10. ビット選択と配列アクセスの判別

問題 arr_b[5] がビット選択か配列アクセスか判別できない
原因 構文上は同じでも、型によって意味が異なる
解決策 slang ASTの型情報を使用: exprType->isPackedArray() でビット選択を判定
実装例 packed array(logic[7:0])→ビット選択、unpacked array(int arr[10])→配列アクセス

Q11. sv-testsでPreprocessingタイプのテストが失敗

問題 preprocessing:typeがNo metadataで失敗
原因 テストファイルの:defines:メタデータを読み取っていなかった
解決策 parse_metadata関数で:defines:を抽出し、-Dオプションとして渡す
実装例 metadata = parse_metadata(test_path); cmd.extend(['-D', d] for d in metadata['defines'])

Q12. 配列の初期化で要素数不一致エラー

問題 string s[] = {"hello", "world"}; で "expected 0 elements" エラー
原因 ArrayLiteralExprの要素数チェックが厳しすぎた
解決策 サイズ推論を許可: 配列サイズが0の場合は初期化子から推論
実装例 if (arraySize == 0) { arraySize = initValues.size(); }

Q13. Queue index out of bounds例外

問題 qs[0] アクセスで例外発生
原因 QueueValueのgetElement実装で境界チェックが厳しすぎた
解決策 空のキューに対する適切なエラーハンドリング
注意点 find_firstなどが空の結果を返す場合の処理を確認

Q14. ソフト制約が正しく適用されない

問題 soft data == 10 が無視されてランダムな値になる
原因 制約ソルバーがソフト制約を通常の制約として扱っていた
解決策 SoftConstraintExprでラップし、ソルバーで優先的に処理
実装例 extractSoftConstraintValuesでソフト制約の値を抽出して最初に試行

Q15. dist演算子が認識されない

問題 x dist {1 := 10, 2 := 20} でエラー
原因 ExpressionKind::Distの処理が未実装
解決策 convertConstraintでdist演算子を検出(現在はプレースホルダー実装)
今後 完全なdist演算子サポートを実装予定

Q16. mailbox型のサポート

問題 mailbox #(string) m; でmailbox型が認識されない
原因 mailbox は SystemVerilog の IPC 機構で、専用の値型が必要
解決策 1. ValueType に Mailbox を追加
2. MailboxValue クラス実装
3. NewExpr で new() 式をサポート
4. mailbox メソッド (try_put, peek, num, try_get) の処理追加

Q17. slangの配列メソッドシステムコール扱い

問題 q.delete(0) の引数が認識されない
原因 slangは配列メソッド(delete, size等)を特殊なシステムコールとして扱い、通常のメソッド呼び出しとは異なるパスで処理
解決策 convertStatementとconvertExpressionの両方で引数処理を実装。システムコールパスでは引数は[0]=object, [1]=実引数となる
実装例 if (callExpr->arguments().size() == 2) { // delete(index) }

Q18. ストリーミング演算子のスライスサイズ仕様の違い

問題 {>> 8 {a, b}} の8が無視される
原因 slangはLRM準拠で左から右ストリーミング時のスライスサイズNを無視し、sliceSize=0に設定
解決策 sv-testsは8ビット単位を期待するため、独自に固定値8を実装
注意 LRM仕様とsv-testsの期待動作が異なるケース

Q19. 文字列リテラル配列の未実装

問題 int a = {"A", "B", "C", "D"}; がセグフォルト
原因 各文字のASCII値を連結する構文がAST-to-IRコンバーターで未実装
期待動作 "A"=0x41, "B"=0x42, "C"=0x43, "D"=0x44 → a=0x41424344
解決策 StringConcatExprクラスを実装して文字列検出→ASCII変換→ビット連結処理

Q20. クラスのrandomize()メソッドが見つからない

問題 obj.randomize() で "no method named randomize" エラー
原因 SystemVerilogのクラスはデフォルトでrandomize()メソッドを持つが、slangはこれを明示的に提供しない
解決策 MemberAccessExprでrandomize呼び出しを特別扱いし、ClassInstanceのrandomizeメソッドにルーティング
実装例 if (memberName == "randomize" && classInst) { return classInst->randomize(); }

Q21. $urandom_range()の範囲指定エラー

問題 $urandom_range(10, 1) で max < min の場合の動作が不正
原因 SystemVerilog LRMでは max < min の場合、自動的に値を入れ替える仕様
解決策 if (min > max) std::swap(min, max); で対応
注意 sv-testsはこの仕様準拠を期待している

Q22. クラス定義のみのファイルでトップモジュールエラー

問題 class定義のみのファイルで "No top module found" エラー
原因 mrunはトップモジュールを必須としていたが、クラス定義のみのテストファイルも存在
解決策 トップモジュールがない場合、ダミーモジュール __dummy_top__ を自動生成
効果 Chapter 18のテストが15→57に改善(+42テスト)

Q23. rand修飾子の検出方法

問題 クラスメンバーのrand修飾子をどう検出するか
原因 slangのVariableSymbolにはrand情報が含まれているが、アクセス方法が不明瞭
解決策 symbol.getDeclaredType()->getFlags().has(DeclaredTypeFlags::Rand) で判定
実装例 if (varType && varType->getFlags().has(slang::ast::DeclaredTypeFlags::Rand))

Q24. std::randomize()のセグメンテーションフォルト

問題 std::randomize(a) でセグフォルト発生
原因 std::randomize()は変数のスコープを参照するが、現在の実装は未完成
対処 基本的な実装のみ。完全なスコープ変数のランダム化は今後の課題
回避策 クラスインスタンスのrandomize()メソッドを使用

Q25. FST波形出力でのLZ4圧縮導入

問題 FST出力ファイルが大きすぎる
原因 非圧縮でvalue change blocksを出力していた
解決策 LZ4ライブラリをFetchContentで統合し、各ブロックを圧縮
効果 ファイルサイズ60-70%削減、書き込み速度も向上

Q26. 制約ブロックがクラスから取得されない

問題 constraint文をパースしたが、randomize()で制約が適用されない
原因 ConstraintBlockSymbolの変換は実装したが、クラスと制約の関連付けが未実装
解決策 ClassMetadataRegistryを実装してクラスのメタデータ(rand/randc、制約)を管理
現状 Phase E.2で基本実装完了、ソフト制約にも対応

Q27. ExprPtrとExpressionPtrの型名不一致

問題 constraint.hでExpressionPtrを使用したがExprPtrが正しい型名だった
原因 expression.hではusing ExprPtr = std::shared_ptrと定義
解決策 全ての箇所でExprPtrに統一。replace_all機能で一括置換
教訓 ヘッダーファイルの型定義を事前に確認する重要性

Q28. LogicVector::toUInt64()メソッドが存在しない

問題 randcaseの重み計算でtoUInt64()を呼び出したがメソッドが存在しない
原因 LogicVectorクラスはtoUnsigned(uint64_t&)というシグネチャを使用
解決策 uint64_t val; if (logicVec.toUnsigned(val)) { ... } の形式に修正
実装例 戻り値で成功/失敗を判定し、参照引数で値を取得

Q29. IntValueクラスが存在しない

問題 制約ソルバーでIntValue型を使用しようとしたが未定義
原因 mrunではLogicVectorValueで整数値も表現する設計
解決策 ir::makeLogicVector(BitWidth(32), value) で整数値を作成
背景 SystemVerilogの4値論理に統一的に対応するための設計判断

Q30. randsequenceの複雑さ

問題 randsequenceの完全実装が非常に複雑
原因 プロダクションルール、重み付け、再帰的展開など多くの機能が必要
解決策 Phase D.4では警告を出すスタブ実装に留める
今後 基本的な機能の安定後に段階的に実装予定

Q31. 文字列連結初期化の実装方法

問題 int a = {"A", "B", "C", "D"}; でセグメンテーションフォルト
原因 文字列リテラル連結のAST-to-IR変換が未実装
解決策 StringConcatExprクラスを新規作成し、文字列検出→ASCII変換→ビット連結の処理を実装
実装例 convertConcat()で全要素がStringValueかチェック→StringConcatExprで8ビットずつ左シフト連結
効果 Phase E.1で完全解決、テスト成功率向上に寄与

Q32. ストリーミング演算子のセグメンテーションフォルト原因と解決策

問題 {>> 8 {a, b}} でセグフォルト、特に文字列連結初期化と組み合わせた場合
原因 1. slice size処理の不備(左右ストリーミング判定)
2. 変数初期化順序の問題(文字列連結初期化が未実行)
解決策 1. slice size == 0の場合の適切な処理を追加
2. 文字列連結初期化(Q31)を先に解決
実装例 if (sliceSize == 0) direction = LeftToRight; actualSliceSize = 8;
効果 Chapter 11テスト 5→2 失敗(+3テスト改善)

Q33. StringConcatExprクラスの設計思想

問題 既存のConcatExprとどう使い分けるか
設計判断 StringConcatExprは文字列リテラルのみの特殊ケースとして独立実装
理由 1. ASCII値変換が必要(通常の連結とは異なる)
2. SystemVerilogの特殊な記法{"A","B"}専用
3. 将来の最適化が容易
実装 ExprType::StringConcatを追加、evaluatorで専用の変換ロジック
メリット 責任分離、保守性向上、型安全性の確保

Q34. CopyClassExpressionの実装

問題 new existing_object 構文(shallow copy)がサポートされていない
原因 slangのCopyClassExpressionがAST-to-IRコンバーターで未処理
解決策 1. ExprType::CopyClassを追加
2. CopyClassExprクラスを実装
3. convertExpressionでCopyClassExpressionを検出して変換
4. evaluatorでshallowCopy()メソッドを呼び出し
実装例 case ExpressionKind::CopyClass: return convertCopyClass(...)
効果 shallow copy機能が動作し、クラスの複製が可能に

Q35. compound assignment(複合代入演算子)の実装

問題 a += b などのcompound assignmentが動作しない
原因 slangはcompound assignmentを内部的にa = a + bに展開し、左辺がLValueReferenceでラップされる
解決策 1. AssignmentExpressionでisCompound()をチェック
2. syntax treeから実際のRHS値を抽出
3. LValueReferenceの特殊処理をBinaryOpに追加
4. 展開されたBinaryExprを作成してAssignmentStatementに変換
実装例 if (assign->isCompound()) { /* syntax解析でRHS抽出 */ }
注意 クラスメソッド内での実行は別途対応が必要

Q36. randomize() with {} のインライン制約

問題 obj.randomize() with { x > 10; } のインライン制約が無視される
原因 randomize()メソッドの引数としてインライン制約を渡す仕組みが未実装
解決策 1. MemberAccessExprにInlineConstraintPtrを追加
2. CallExpressionの引数からインライン制約を抽出(試みたが複雑)
3. evaluatorでインライン制約を既存制約と結合
現状 基本的な枠組みは実装済み、slang ASTとの完全統合は今後の課題

Q37. LValueReferenceでのnull syntax問題

問題 BinaryOp内のLValueReferenceでsyntaxがnullになる
原因 slangが内部的にLValueReferenceを生成する際、syntaxノードを設定しない
解決策 compound assignmentではstatement levelでsyntaxから直接RHS値を抽出する方針に変更
実装例 assignSyntax.right->as<LiteralExpressionSyntax>() でリテラル値を取得
教訓 AST変換だけでなく、syntax treeも活用する柔軟なアプローチが必要

まとめ:mrun(仮) 開発から学んだ「今すぐ」導入したい5選

mrun(仮)プロジェクトPhase Eまでの実体験から、最も効果が大きかった5つのツールです。

優先順位 ツール 導入コスト mrun(仮)での実績
1 Ninja 5分 Makefileより50%高速ビルド。ninja -j32で効率的。
2 Google Test 30分 150個以上のテストで全機能を検証。TDD開発の基盤。
3 FetchContent 10分 依存関係の自動管理。slang v8.1統合もスムーズ。
4 ccache 10分 再ビルド時間70%短縮。イテレーション高速化。
5 sv-tests 30分 準拠性検証。87.8%進捗、1037テスト実行中。

mrun(仮) プロジェクトから得た教訓

compact コマンドの活用

# コンテキスト使用率を監視し、手動でコンパクト
/compact
  • 自然な区切り(機能完成、コミット時)で積極的に使用

完璧を求めない

  • 全ツールを一度に導入せず、段階的に。

計測を習慣化

  • PASS率、ビルド時間、カバレッジを定期的に記録。

自動化を優先

  • 手動チェックは続かない。CIに組み込む。

実用性重視

  • 理想より現実。動くものを早く作る。

おわりに

SystemVerilogシミュレータ開発は長い道のりですが、Claude Code と適切なツール選択により着実に前進しています。
mrun(仮)は Phase E.5 まで完了し、制約ソルバー・ランダム化機能の高度な実装(shallow copy、compound assignment、randomize() with {})を達成。sv-testsで88.3%(916/1037テスト成功)の進捗を維持しています。

image.png


以上

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?