はじめに
前回 (2025/12/20 版) からの続報です。
拙作の SystemVerilog シミュレータ sukimasim は Claude Code を主軸に、Codex も併用しながら開発を続けており、前回の報告から半年弱で IEEE 1800-2023 のほぼすべての機能と UVM 1.2 が一通り通る様になっています。
本記事は 「2025/12/20 〜 2026/5/4 で何が変わったか」 をまとめると同時に、最近の開発の中心テーマである
-
../IEEE_1800_2023_function_coverage(LRM 機能カバレッジ網羅) -
../uvm_compliance(UVM 1800.2-2020 章別 + 統合 + 実 VIP 検証) -
../verif(29 個の独立な検証環境、内訳は §1.1.1)
の 3 つの外部リポジトリでバグを抽出 → minrepro 化 → CTest に登録 → ./scripts/update_dashboard.sh で全体回帰 という品質向上ループの実態を紹介します。
AI 開発を継続するうえでリグレッションテストが大事だと感じた
ここ半年継続的に開発を続けて感じたのは、AI を使った長期開発では、リグレッションテストの厚みがコードベースの崩壊や手戻りを防いでくれる、ということでした。
AI (Claude Code / Codex) は人間より速くコードを書きますが、人間と同じように "良かれと思って" 既存挙動を壊すことがあります。
sukimasim のようにコード行数が数十万行規模になってくると、ある fix が遠くの別機能を壊す副次回帰がしばしば発生し、それを人の手で全部追い切るのは現実的ではなく、テストの網に任せざるを得ない感覚になってきました。
そこで運用ルールとして、
- commit 候補毎に 17,412 テストを 3 分で全部回す
- Failしたら commit を作らない
- 新しい fix は minrepro (minimal reproduction、最小再現コード) を先に CTest として追加してから本体を直す (副次回帰のキャッチ網を先に張る)
の 3 つを置いています。
12/20 版で 7,714 だったテスト数が 5/4 で 17,412 まで増えた理由の多くは、機能追加よりも
「AI が大きめの変更をかけても安心できるように、テスト側を先に厚くしておく」 という方針で増やしてきたものです。
逆に言うと、リグレッションの網が薄いまま AI に長期開発を任せていると、
だんだん 「何が壊れているのか把握しきれない」状態に近づいていく 感覚があります。
本記事の中盤で扱う 3 つの外部リポジトリ運用も、この網の上に乗せている枠組みです。
この記事の要約
- 17,412 / 17,412 PASS (Failed 0 / Timeouts 0、wall 197s、24 並列、5/4 snapshot)
- CTest (RealWorld / IbexDV 除く) 2,229 / 2,229 PASS
- GoogleTest Unit 1,190 / 1,190 PASS
- IEEE 1800-2023 LRM Functional Coverage UNION 959 / 959 (100.0 %) を 5/1 に達成 (意図的未実装節は除く、§4 参照)
- AXI-Lite UVM DV 15 / 15 PASS / Mirafra APB AVIP (商用 VIP) 6 / 6 PASS
- 外部 29 検証環境 (
../verif) で env 側 workaround 0 件 - 既知の未解消 real bug 0 件 / Known minrepro 0 件
- 累計バグ解消 676 + 件、
tests/bugs/の minrepro 503 ファイル / 37,156 行、BugFix.*テスト 436 ケース、Bugs.B*採番は B265 まで - 直近 5 月だけで 57 commit、5/4 単独で 6 commit (RAL HDL-backdoor / DPI export callback / HPDcache solver / UVM enum reflection 等)
1. 品質向上の三層ループ
12/20 時点では「sukimasim が解釈できる SystemVerilog の幅」を IEEE LRM 章単位の自作テストで担保していましたが、4 月以降は 既存の OSS / 商用検証環境を片端から sukimasim に通し、躓いた箇所を即 minrepro 化する フローに切り替えました。
これが今期最大の品質ジャンプの源泉です。
1.1 三つの外部リポジトリの役割分担
| リポジトリ | 役割 | 規模 / 実績 |
|---|---|---|
../IEEE_1800_2023_function_coverage |
IEEE 1800-2023 LRM の各節の "実行されたか" を機能カバレッジで網羅 | LRM 59 章 + AXI-Lite cov 15 + UNION 959 / 959 cp (100.0 %) ※意図的未実装節 (§4) は coverpoint 対象外 |
../uvm_compliance |
UVM 1800.2-2020 を章別 (ch5..ch12 + ext) + 統合 + 実 VIP 3 層で検証 | 87 クラス、Phase A-E 完走、HPDcache UVM 環境を smoke-PASS |
../verif |
バスプロトコル / ペリフェラル / OpenTitan / CPU / UVM 機能フォーカス系の dummy DV 一式 (§1.1.1) | 29 環境、全 smoke-PASS、env 側 workaround 0 件 |
準拠率の測り方について (dogfooding)
../IEEE_1800_2023_function_coverageの 959 / 959 (100.0 %) という数字は、
sukimasim 自身のファンクションカバレッジ機能 (covergroup/coverpoint/crossの実装) を使って収集しています。
なお Protection Envelope や multi-thread parallel sim など、§4 で「意図的未実装」と明記している節は coverpoint 対象から外しているため、この 959 cp には含まれていません。
つまり 「sukimasim が IEEE 1800-2023 の各節をどれだけ実行できたか」を sukimasim の機能カバレッジ機能自身で観測している 構造です。
自己採点という弱点はありますが、副次的な利点として
「カバレッジ機能そのものが壊れていれば、この LRM coverage の数字も同時に崩れる」 ため、
coverage サブシステムの自己チェックを兼ねている面があります。
1.1.1 ../verif の内訳 (29 環境)
各 env は独立した git submodule で、rtl/ (DUT) + dv/ (UVM TB) + Makefile + checkpoints/ の最小構成。
親 Makefile から make regress 一発で全 env が回る、各 IP は基本 1 〜 4 テストの smoke 規模です
(網羅性ではなく 「sukimasim が踏みうる code path を広く当てる」 のが目的)。
バスプロトコル系 (8)
| env | 対象 |
|---|---|
AHB |
AMBA AHB-Lite dummy slave |
APB |
AMBA APB3 dummy slave |
AXI-lite |
AXI-Lite dummy slave (phase 2-5、15 tests) |
AXI-Full |
AXI4 full: tvip-axi VIP + pulp-platform/axi + verilog-axi + AXI-Lite の 4 パターン + regression |
AXI-Stream |
Core JPEG AXI-Stream UVM DV (smoke / single_image / backpressure / reset_stress / truncated_stream / multi_image) |
Wishbone |
Wishbone B3 classic dummy slave |
PCIe |
PCIe TLP-only endpoint (Config Space + BAR0 + Completion) |
AsyncFIFO |
非同期 FIFO (CDC) |
ペリフェラル / 通信系 (5)
| env | 対象 |
|---|---|
I2C |
I2C 7-bit dummy slave (tri1 双方向) |
SPI |
SPI mode 0 dummy slave |
Ethernet |
Ethernet MAC (smoke / loopback / backpressure 系 3 tests) |
CAN_FD |
CAN FD コントローラ |
DMA |
DMA controller |
OpenTitan 系 (3)
| env | 対象 |
|---|---|
OpenTitan_IP_DV |
OpenTitan dummy IP (最小 UVM DV テンプレ、smoke + csr-rw + reset-stress) |
OpenTitan_UART_DV |
OpenTitan-style UART (all_tests) |
OpenTitan_AES_DV |
OpenTitan-style AES (regress) |
CPU / 演算 / 暗号系 (3)
| env | 対象 |
|---|---|
PicoRV32 |
minirv コア (RISC-V 系の最小実装) |
FPU |
浮動小数演算ユニット |
HMAC |
HMAC 暗号ハッシュ |
UVM / SV 機能フォーカス系 (10)
IP が主役ではなく 「sukimasim の特定機能だけを集中的に踏み抜く」 役の env 群です。
ここの fail は外部 IP の挙動ではなく シミュレータ側の機能バグ に直結するため、優先度が高くなります。
| env | 対象機能 |
|---|---|
RAL_Backdoor |
UVM RAL の add_hdl_path + UVM_BACKDOOR peek/poke (5/4 で BugFix.UvmRegHdlPathBackdoor 解消) |
DPI_Export |
export "DPI-C" の C → SV → C ラウンドトリップ (5/4 で BugFix.DpiExportCallbackSymbol 解消) |
DPI_Scoreboard |
DPI 経由 ALU scoreboard、SV ↔ C 間の構造体マーシャリング |
TLM2 |
TLM2 socket chain (b_transport / nb_transport / put_get_socket) |
SVA_Protocol |
SVA プロトコル (handshake シーケンス、multi-clock、reset disable) |
CovGroup |
covergroup の sample / cross / 連結カバレッジ集計 |
SoftConstraints |
UVM soft 制約の優先度逆転 / 衝突解消 |
ProcessControl |
process クラス / disable fork / wait fork のセマンティクス |
FileIO |
$fopen / $fwrite / $fread / $fscanf の各種フォーマット |
Mailbox |
mailbox メッセージング (bounded / unbounded、peek / try_peek) |
合計 8 + 5 + 3 + 3 + 10 = 29 環境。
4 月開始時点では README に列挙されていた 12 環境がスタートでしたが、そこから外部 env で踏まれない code path をピンポイントで攻める「機能フォーカス系」を継ぎ足していった結果、現在の 29 環境構成になっています。
../verif 配下は sukimasim_feedback_2026-05-04_*.md のように 日付付きフィードバック書式 で、
Claude Code が外部 env を sukimasim に通して "落ちた症状" を観測 → 蒸留した最小再現を .sv で共有 する構造になっています
(以下のファイル名 prefix sukimasim_repro_* は Claude Code 由来。Codex は後段の C++ 修正フェーズに入る)。
一例だけ抜粋すると 5/4 だけでも次のような repro が生成されました。
../verif/sukimasim_repro_2026-05-04_g_ral_backdoor.sv ← UVM RAL HDL-path backdoor の 0 戻り
../verif/sukimasim_repro_2026-05-04_h_dpi_export.sv / .c ← export "DPI-C" の C 側 undefined symbol
../verif/sukimasim_repro_2026-05-04_i_readmemh_sigsegv.sv ← $readmemh パース異常時 SIGSEGV
../verif/sukimasim_repro_2026-05-04_j_dist_constraint.sv ← dist 制約のレンジ末尾要素計算
1.2 バグ抽出 → minrepro → CTest → ダッシュボードのループ
4 月以降ずっと回している基本フローです。
外部 env で一発でも fail / mismatch を引いたら、すぐに CTest 化する を運用ルールにしました。
[../verif や ../uvm_compliance の env が fail / mismatch]
│
│ Claude Code がバイセクションして最小化
▼
[tests/bugs/test_<symptom>.sv に minrepro を新規作成] ← Claude Code 担当
│
▼
[tests/CMakeLists.txt に BugFix.<Symptom> / Bugs.B<num> として add_test]
│ - WILL_FAIL の状態で先に commit
▼
[./scripts/update_dashboard.sh で全体回帰 (24 並列, ~3 分)] ← Claude Code 担当
│ - dashboard 上で WILL_FAIL のまま (本体未修正)
▼
[docs/codex_handoff_*.md でハンドオフ]
│
▼
[Codex が C++ 本体をバイセクション → root cause 特定 → patch] ← Codex 担当
│
▼
[Claude Code が再度 update_dashboard.sh を回し、副次回帰の有無を確認]
│ - WILL_FAIL → PASS に遷移、かつ他 17,411 件が引き続き PASS
▼
[fix commit → docs/codex_handoff_*.md に短報 → verif 側に "解消" 通達]
5/4 時点での内訳:
| カウンタ | 値 | 備考 |
|---|---|---|
tests/bugs/*.sv |
503 ファイル / 37,156 行 | minrepro 集約ディレクトリ (再帰、ヘルパ含まず) |
BugFix.<Name> CTest |
436 ケース | 機能名ベース (例: BugFix.UvmRegHdlPathBackdoor) |
Bugs.B<num> CTest |
B237 〜 B265 が直近採番 | 連番ベース、5 月だけで +28 件 |
add_test(...) 総数 |
1,567 件 |
tests/CMakeLists.txt 全 18,824 行 |
| 5 月の commit 数 | 57 件 | うち 過半数が外部 env 由来の bug fix |
1.3 ./scripts/update_dashboard.sh の役割
このスクリプトは "minrepro が PASS したかどうかだけ" を見るのではなく、追加した修正で Dashboard 17,412 のうち何かが Fail になっていないか を 24 並列で確認します。
# 標準実行 (~3 分、IbexDV 除く)
./scripts/update_dashboard.sh --no-extended
# IbexDV まで含む完全回帰 (~1.5 時間、158 テスト)
./scripts/update_dashboard.sh --extended
# IbexDV だけ
./scripts/update_dashboard.sh --extended --extended-list ibex_dv
生成物は comprehensive_dashboard_v2.html と test_dashboard.md。
個別の repro 投入で局所的に PASS にしても全体が崩れていれば commit 不可、というガードレールになっています。
2. 直近の代表的な fix (5 月)
「外部 env 由来の bug を minrepro で固定する」流れを具体化した、ここ 1 週間分の fix を抜粋します。
2.1 UVM RAL HDL-path backdoor (5/4, 36ba13d57)
add_hdl_path + UVM_BACKDOOR reads が常に 0 を返す不具合。
uvm_support.cpp で uvm_reg::configure(..., hdl_path) / uvm_reg::add_hdl_path(...) /
uvm_reg::add_hdl_path_slice(name, offset, size) / uvm_reg_block::configure(..., hdl_path) /
uvm_reg_block::add_hdl_path(root) が __uvm_hdl_path* メタを格納し、
m_backdoor 未設定時のデフォルト UVM_BACKDOOR read/write を hdl path 経由で peek/poke するよう拡張。
testbench_runtime.cpp::setHierarchicalSignalValue で top-module prefix を strip し、
test_uvm_reg_hdl_path_backdoor.u_dut.reg_a_q → u_dut.reg_a_q を解決します。
- minrepro:
tests/bugs/test_uvm_reg_hdl_path_backdoor.sv - CTest:
BugFix.UvmRegHdlPathBackdoor - 解消した env:
../verif/RAL_Backdoor
2.2 export "DPI-C" callback symbol (5/4, 36ba13d57)
export "DPI-C" で SV 関数を C 側から呼ぶときに、コールバック未登録のため undefined symbol になっていた件。
dpi_export_stub_bridge.cpp に C-visible な sv_callback(unsigned int, unsigned int) と登録経路を追加し、
testbench_runtime.cpp::executeDPIExport がモジュール関数を検出して executeFunction(...) へ委譲し、戻り値を C に伝搬するようにしました。
- minrepro:
tests/bugs/test_dpi_export_functions.cpp+ 対応.sv - CTest:
BugFix.DpiExportCallbackSymbol(C → SV → C ラウンドトリップ = 10 を pin) - 解消した env:
../verif/DPI_Export
2.3 HPDcache solver regression 群 (5/3, 69e2948c9)
uvm_compliance の HPDcache (CV-HPDcache verif) で AMO LR/SC の response-delay /
hwpf-stride randomize が post_reset で fatal していた件。
constraint_solver.cpp を +286 行で拡張し、object-member implications / duplicate fixed-delay equality /
large dist ranges / enum implication / product-derived dist endpoints の 5 パターンに対応。
- CTest:
BugFix.HPDcacheAmoLrScRandomizeRegression - 同一 commit に派生 fix 3 件:
Bugs.B265_HPDcacheInterfaceAssertionWarningFree-
BugFix.BitsClassImplementsInterface($bitson a class implementing an interface class) -
BugFix.WaitAfterClassMemberEvent(class method 内のwait(cond)が class member event trigger 後に resume しない件)
2.4 IEEE 1800-2023 §16.13.1 multi-clock SVA (5/1, d986f2c37)
@(posedge clk) req ##1 @(posedge clk2) gnt 形式で外側 clock gate に阻まれて
内側 clk2 edge で sequence token が advance しなかった件。
これが残っていたため cg_extras6.cp_multi_clk だけが hit せず IEEE coverage が 958/959 で停滞していたのを、
959/959 (100.0 %) 達成 につなげました。
- CTest:
Bugs.B264_SvaMulticlockSequenceCover - 解消ソース:
../IEEE_1800_2023_function_coverage
2.5 UVM sequence virtual interface (5/2, 1987cb56d 系 5 commit)
5/2 は ../verif フィードバックループの "VIF 系限界" を 5 件まとめて潰した日でした。
- UVM sequence の VIF task call が timing-control 認識に参加するよう修正
-
payload[i]recovered IdentifierExpr → ArrayAccessExpr 再構築 - flattened dotted-chain resolution が queue / dyn array / assoc array root を accept
- interface array element
bus[0]を VIF actual でVirtualInterfaceRefValue解決 - static timing-control scan の receiver 早期評価 guard
CTest 化: BugFix.UvmSequenceVifTaskLoopBlocking + BugFix.UvmSequenceNestedVifQueueNba。
これで Dashboard 17,238 → 17,344 (+106)、CTest 2,163 → 2,171 (+8)。
2.6 PITFALL-MISSING-APOSTROPHE 警告の追加 (5/1, e043159fd)
LRM §10.9 / §11.4.12 — packed struct や多要素 packed array に {...} (Verilog bit concat) で代入し、
operand 数が field / element 数と一致するケースを [WARNING] PITFALL-MISSING-APOSTROPHE として検出。
'{...} (assignment pattern) を意図したであろう典型 typo を catch します。
typedef struct packed { logic [3:0] a; logic [3:0] b; } pair_t;
pair_t p;
assign p = {4'h1, 4'h2}; // ← Xcelium は救済するが、'{4'h1, 4'h2} の typo を疑う
--lint / --pitfall-checks で ON、デフォルトは OFF (回帰 BugFix.PitfallMissingApostrophe + BugFix.PitfallMissingApostropheDefaultOff)。
3. テストダッシュボード概況 (2026-05-04)
| カテゴリ | 結果 | 備考 |
|---|---|---|
| 全カテゴリ合計 | 17,412 / 17,412 PASS | wall 197s、24 並列 |
| CTest (RealWorld / IbexDV 除く) | 2,229 / 2,229 PASS | 5/4 で +58 |
| GoogleTest Unit | 1,190 / 1,190 PASS | |
| sv-tests | 1,666 / 1,666 PASS | external suite |
| UVM Base / Advanced / Phase | 82 / 82, 19 / 19, 46 / 46 | 87 クラス |
| IEEE 1800-2023 LRM Func Cov | UNION 959 / 959 (100.0 %) | 5/1 達成、5/4 維持 (意図的未実装節は coverpoint 対象外) |
| AXI-Lite UVM DV | 15 / 15 PASS | Bug 1-31 全解消 |
| Mirafra APB AVIP (商用 VIP) | 6 / 6 PASS | Issue #12 / #13 / #14 全解消 |
../verif 29 envs |
全 smoke-PASS | env 側 workaround 0 件 (内訳 §1.1.1) |
| IbexDV (RISC-V DV) | 158 / 158 PASS | 0 workarounds、~1.5 時間 |
| Real-world RTL | 9 CPUs + OpenTitan 10 IP + AMBA SoC + CVA6 cv32a60x elaboration PASS | |
| 既知未解消 real bug | 0 件 | Known minrepro 0 件 |
| 累計解消バグ | ~676 + 件 |
Bugs.B265 まで採番 |
CV32E40P (Issue #1 〜 #29 全クローズ) や Mirafra APB AVIP (Round 1 〜 Round 8 で完走) のように、
「外部の OSS / 商用 IP の DV 環境を 1 つ完走させると、その横に並んでいる別の env もまとめて解消する」 連鎖がここ 1 ヶ月の典型パターンになっています。
4. IEEE 1800-2023 と既知制限の現状
12/20 版で残していた未実装系は、4 月後半の集中 sprint でほぼ全て吸収されました。
現在 docs/KNOWN_LIMITATIONS_2026-05-04.md に残っているのは 意図的に避けている / 性能特性 のものだけです。
| カテゴリ | 状態 |
|---|---|
| §1.1 Protection Envelope (SS34) | 意図的に非対応 (vendor 固有暗号化)。検出時は LRM §34.3 準拠の警告を stderr 出力 |
| §2.1 Multi-thread parallel sim | アーキ上の制約 (single-threaded) |
| §2.2 GUI 統合デバッガ |
--interactive REPL と --dap 実装済。Verdi 級波形 GUI はスコープ外 |
§3.1 PLI $memory_open / $memory_close
|
$fopen / $fclose 互換エイリアスとして実装済 |
| §3.2 stdin 系関数 | safety 上 --allow-stdin で opt-in |
§3.3 $future_gclk
|
4/26 解消 (deferred evaluation sentinel) |
| §3.4 VPI Assertion Control API (SS39) | 4/26 完成 → §10.13 へ昇格 (control 25 op + callback 32 件) |
| §3.5 Config block (SS33) |
4/26 完成 → §10.12 へ昇格 (-v <LIB>=<FILE> + --config <name> + --enable-uvm 共存) |
| §4.1 性能 (interpreted) | Verilator 比 100〜1000× 遅い (intentional) |
LRM 仕様としては「拒否することが正しい」ものは LRM-conformant rejection としてそのまま rejection を返す方針で、これらは limitation ではなく仕様準拠として記述しています
(checker の inout / ref ports、固定長 / dyn array に push_back 等)。
5. Verilator との比較と本プロジェクトの位置付け
sukimasim は AST インタプリタ型なので、実業務にも使われている Verilator (SystemVerilog → C++ コンパイル型) と比べると、実行速度では大きく負けています。
ただ、本プロジェクトは 私自身の SystemVerilog / UVM / EDA まわりの勉強が一番の目的 であり、速度よりも IEEE 1800-2023 / UVM 1.2 の機能網羅と「素直に動く実装」のほうを優先しています。
そのため Verilator との速度差を埋める方向には当面動いていません。
| 項目 | Verilator (v5.x 系) | sukimasim (0.9.9.2) |
|---|---|---|
| 実行モデル | コンパイル型 (SV → C++ → 最適化バイナリ) | AST インタプリタ |
| 実行速度 | 業界標準クラスに高速 | Verilator 比 100〜1000× 遅い (interpreted) |
| 言語サポート | 合成可能サブセット中心 | IEEE 1800-2023 をほぼ完備 |
| クラス / OOP | 限定的 | フル対応 |
| UVM | 公式サポートなし (動かないクラス多数) | UVM 1.2 + Advanced 完走 (87 クラス) |
| Constrained random | 限定的 | フル対応 (inline / soft / hard / dist 等) |
| SVA | 限定的 | フル対応 (multi-clock / disable iff / abort 等) |
| SDF backannotation | 非対応 | フル対応 (Phase 1-4) |
| DPI-C | 対応 | 対応 (export "DPI-C" 含む) |
| 波形 | VCD / FST | VCD / FST / EVCD / SWDB 1.0 |
| デバッガ | 別ツール (GTKWave 等) と組み合わせ | DAP server 内蔵 (--dap) + REPL (--interactive) |
| ライセンス | LGPL / Artistic | 私的開発 |
| 主な用途 | 産業用 RTL の高速シミュレーション | 個人の自己学習 / IEEE LRM 実装の探求 |
ざっくり言うと Verilator は「synthesizable RTL を最速で回す」ためのツール、
sukimasim は 「IEEE 1800-2023 の振る舞いを AST レベルで素直に追える」ことに特化した単なる個人プロジェクト です。
速度ベンチで Verilator に勝つことは目標にしていない、という前提で本記事を読んでいただけるとありがたいです。
速度を上げる選択肢 (LLVM JIT / SIMD / 並列実行) は技術的には検討余地がありますが、
- 特許リスク回避方針 (12/20 版で明文化、本記事 §8 末尾で再掲)
- AST インタプリタの素直さがデバッグの容易さに直結している
- そもそも自分の勉強用なので速度がボトルネックになる場面が無い
という理由で、当面は速度よりも機能網羅と LRM 準拠を引き続き優先する方針を続けます。
6. 開発体制 (Claude Code + Codex の役割分担)
6.1 現在の役割分担
現状はざっくり 「Claude Code がテスト工程、Codex がバグ調査・修正工程」 という分担で落ち着いています。
完全に固定しているわけではありませんが、ここ 1 ヶ月ほどはこの形がいちばん安定して回っています。
| フェーズ | 担当エージェント | 具体的な作業 |
|---|---|---|
| ① テスト作成 | Claude Code (Opus 4.7) | LRM §節 / UVM 章 / 外部 env から新規テストを起こす |
| ② テスト実行 | Claude Code |
./scripts/update_dashboard.sh を回し、Dashboard 17,412 を完走確認 |
| ③ バグ発生時の minrepro 作成 | Claude Code | 数千行の外部 env を tests/bugs/test_*.sv の数十行に蒸留 |
| ④ バグ調査 (root cause 特定) | Codex (GPT-5.5) | sukimasim の約 42 万行 C++ をバイセクション、コールスタックを追跡 |
| ⑤ バグ修正 (C++ patch) | Codex | 該当 *.cpp / *.h を実際に書き換え、IEEE LRM §節を引用しながら fix |
| ⑥ 回帰確認 | Claude Code | fix 後に再度 Dashboard を回し、副次回帰の有無を判定 |
| ⑦ ハンドオフ文書化 | 両者 |
docs/codex_handoff_*.md に 1 セッション 1 ファイルで記録 |
6.2 なぜこの分担に落ち着いたか — バグ修正で Claude Code が詰まりがちだった
最初は Claude Code 単独で「テスト作成 → 実行 → minrepro → 調査 → 修正」まで全工程を回していました。
ただ運用を続けるうちに、バグ修正フェーズで以下のような傾向が目につくようになりました
(あくまで自分の使い方での印象で、プロンプト次第で変わる部分はあると思います):
-
症状をその場しのぎで隠す patch が出てくることがある — 例: NPE が出たので
if (ptr) { ... }を被せて return、根本原因の追跡まで踏み込まない - 修正範囲が広がりがち — 該当の 1 関数だけ直せば済むはずが、周辺ファイルも一緒にリファクタしようとする
- 副次回帰が出やすい — 1 つ直すと別の数件が Fail し、追いかけて直すとさらに別が Fail する、という連鎖
- 同じバグに何度か挑戦して同じ方針で詰まることがある — セッションをまたぐと前回の試行錯誤が落ちるためと思われる
一方で、テスト作成と minrepro の蒸留に関しては Claude Code がよく機能してくれました。
LRM 仕様を引用しつつ、1 ファイルで PASS/FAIL を観測できる最小再現を比較的短時間で作ってきます。
503 個の minrepro (37k 行) の多くはこの工程で作られたものです。
そこで 4 月はじめ頃から、ざっくり Claude Code = テスト・回帰側、Codex = C++ 修正側 に分けてみました。
すると、
- Codex は C++ のスタックトレースから素直に原因を辿り、修正範囲も比較的狭く収めてくれる
- Claude Code は minrepro 作成と Dashboard 回帰運用に集中できるので、副次回帰の検出が機能しやすい
という形で、ひとまず安定して回るようになりました。
5 月の commit 57 件もおおむねこの分業に沿った内訳になっています。
6.3 ハンドオフ文書
両エージェントは 直接対話しません。間に必ず docs/codex_handoff_*.md を挟み、
セッション境界をまたいでも文脈が落ちないようにしています。5 月だけでも:
docs/codex_handoff_session_state_2026-04-28.md
docs/codex_handoff_session_state_2026-05-01.md
docs/codex_handoff_session_state_2026-05-02.md
docs/codex_handoff_session_state_2026-05-04.md
docs/codex_handoff_ieee1800_multiclock_sva_b264_2026-05-01.md
docs/codex_handoff_ibexdv_disable_fork_livelock_2026-05-02.md
docs/codex_handoff_mirafra_issue14_uvm_req_cross_instance_2026-04-27.md
人間 (私) の役割は 「次にどの env / どの LRM §節を片付けるか」を選ぶこと、
patent risk / IEEE 仕様解釈の最終判断、および 両 AI のハンドオフが噛み合っているかの監督 の 3 点です。
12/20 時点では人間がコードレビューで律速していましたが、5 月時点では Codex が一次レビューも兼ねるため、人間の介入はほぼ "向き先の指示" のみになりました。
7. minrepro を CTest 化するときの作法 (Claude Code パート)
外部検証環境から「これがFailする」と言われたとき、いきなり Codex に渡して C++ を直させるのではなく、
まず Claude Code が 「同じ症状を tests/bugs/test_*.sv 1 ファイルだけで再現する」 ところから始めます。
「Codex に渡すインプットの質が C++ patch の質を決める」 という経験則のもとで定着した運用です。
7.1 minrepro 化のチェックリスト
-
1 ファイルで再現する (UVM が必要なら
--enable-uvmだけで完結) -
期待値が
$displayで観測できる (PASS / FAIL の判定が grep 可能) -
tests/bugs/test_<feature>_<symptom>.sv命名 (検索性のため動詞は使わない) - 元の env の URL / commit を冒頭コメントに残す
-
LRM §節を本文コメントで引用 (例:
// IEEE 1800-2023 §16.13.1)
7.2 CTest への登録例
# tests/CMakeLists.txt 抜粋
add_test(
NAME BugFix.UvmRegHdlPathBackdoor
COMMAND ${SUKIMASIM_BIN}
--enable-uvm
${CMAKE_CURRENT_SOURCE_DIR}/bugs/test_uvm_reg_hdl_path_backdoor.sv
)
set_tests_properties(BugFix.UvmRegHdlPathBackdoor PROPERTIES
PASS_REGULAR_EXPRESSION "TEST PASSED"
FAIL_REGULAR_EXPRESSION "TEST FAILED|UVM_FATAL|UVM_ERROR"
TIMEOUT 60
)
7.3 Dashboard 反映
./scripts/update_dashboard.sh --no-extended
# → comprehensive_dashboard_v2.html / test_dashboard.md が更新される
# → 17,412 / 17,412 が崩れていないことを確認してから commit
この Dashboard が完全グリーンであること を commit gate にしているため、
「ある env では PASS したが他でFAILになった」というケースは即時に検出されます。
8. 12/20 → 5/4 で何が変わったか
| 項目 | 12/20 時点 | 5/4 時点 | 差分 |
|---|---|---|---|
| 総テスト数 | 7,714 | 17,412 | + 9,698 |
| CTest | 約 1,940 | 2,229 | + 289 |
tests/bugs/ minrepro |
(集計なし) | 503 ファイル / 37,156 行 | -- |
Bugs.B* 採番 |
-- | B265 まで | -- |
| 累計解消バグ | (集計なし) | 676 + 件 | -- |
| IEEE 1800-2023 準拠率 | 約 99 % | 99 % + (LRM cov 100.0 %) | LRM cov を初達成 |
| UVM 1.2 | 100 % (Phase A-E) | 100 % (+ Advanced 19 / 19) | Advanced 拡張完走 |
| 外部 env 検証 | sv-tests + 一部 OSS RTL | ../verif 29 envs / Mirafra / HPDcache / OpenTitan / CV32E40P / Ibex |
商用 VIP まで拡張 |
| 既知未解消 real bug | (記述なし) | 0 件 | -- |
| 開発体制 | Claude Code 単独 | Claude Code + Codex の 2 エージェント協調 | 並行検証フロー確立 |
特許リスク回避方針 (12/20 で明文化した「安全な実装 > 高速だが危険な実装」) は引き続き堅持しており、
ThreadPoolExecutor / SIMD (AVX-512) / Loop fusion / Adaptive runtime 系は 無効のまま です。
代わりに delta-cycle scheduler の 5 phase 最適化、always_comb dirty-set 最適化、
delta-cycle dependency cache などの 特許リスクが小さい古典的最適化 だけで Dashboard 197s に収めています。
9. プロジェクト規模 (5/4 snapshot)
「半年で 1 万行のテスト追加」が体感のオーダー感だったので、改めて行数ベースで実測しました。
find ... -exec cat {} + の正確な集計値です。
9.1 シミュレータ本体 (C++)
| 場所 | ファイル数 | 行数 |
|---|---|---|
src/ (実装) |
-- | 367,398 行 |
include/ (公開ヘッダ) |
-- | 49,792 行 |
| 合計 (C++ 本体) | 484 ファイル | 417,190 行 |
build/sukimasim バイナリ |
-- | 31 MB (Release ビルド) |
12/20 版から比べると行数はそれなりに増えました。
内訳としては src/eval/ (式・文の評価) と src/uvm/ (UVM ランタイム) が特に膨らんでいます。
9.2 テストコード (SystemVerilog + GoogleTest)
| 場所 | ファイル数 | 行数 | 用途 |
|---|---|---|---|
tests/eval_coverage/ |
4,854 | 327,996 行 | 評価器のカバレッジ網羅 |
tests/real_world/ |
537 | 176,912 行 | 実 RTL (CPU / SoC / IP) |
tests/coverage_targeted/ |
456 | 120,119 行 | 弱点ピンポイント網羅 |
tests/edge_cases/ |
317 | 55,977 行 | LRM 境界条件 |
tests/bugs/ (★ minrepro) |
503 | 37,156 行 | 外部 env 由来バグの最小再現 |
tests/lrm/ |
200 | 30,079 行 | LRM 章別テスト |
tests/combination/ |
218 | 28,811 行 | 機能組み合わせ |
tests/assertions/ |
474 | 25,432 行 | SVA |
tests/fcov/ |
639 | 24,056 行 | Functional Coverage |
tests/uvm/ |
90 | 11,171 行 | UVM 1.2 ランタイム |
| その他 | -- | -- | -- |
tests/ 合計 (.sv / .svh) |
11,834 ファイル | 1,171,671 行 | -- |
tests/unit/ (GoogleTest C++) |
-- | 30,461 行 | 内部 API ユニット |
tests/CMakeLists.txt |
1 | 18,824 行 |
add_test(...) 1,567 件 |
SystemVerilog テストは本体 C++ の 2.8 倍 (1,171k 行 vs 417k 行) になっています。
これは設計が綺麗だからというより、AI 開発で副次回帰を検出するために
「本体を 1 行触るならテストも厚めに足しておく」 を継続してきた結果という側面が強いです。
9.3 補助資産
| 場所 | 規模 | 内容 |
|---|---|---|
uvm-core/ (vendored) |
87,181 行 | Accellera UVM 1800.2-2020 ライブラリ |
scripts/ |
73,375 行 | dashboard / regression / 補助 Python + Bash |
docs/ |
96,579 行 / 300 ファイル | LRM 準拠カタログ / handoff / bug report |
9.4 「リグレッション網」のサイズ感
- 本体 1 行に対し テスト約 2.8 行 + ドキュメント約 0.23 行 がついて回る
- minrepro 1 ファイル平均は 約 74 行 (37,156 / 503) — 外部の数千行規模の env から数十行に圧縮したもの
-
add_test(...)1,567 件がupdate_dashboard.shの 24 並列で 約 3 分 で回る - 完走時間が伸びるとフィードバックループが鈍くなり開発も遅くなるので、dashboard 完走時間 5 分以内 を一応の目安にしています
10. これから (短期 / 中期 / 長期)
短期 (5 月中)
- HPDcache full smoke completion の throughput 改善
(UVM API は完走、残るは large-hierarchy interpreted-mode の性能特性) -
../verif30 番目の環境 (RISC-V Vector / 検討中) の bring-up -
BugFix.*テストの命名整理 (機能名ベースと連番ベースの混在を整理)
中期 (今夏)
- DAP デバッガの step into / watch expression 拡充
-
--profileの hotspot レポートを HTML 化 - VPI Assertion Control API のユーザサンプル整備 (cbAssertionStep* の NFA-shaped trace)
長期
- FMI 3.0 による SPICE シミュレータとのデジアナ混載 (gRPC + protobuf)
- 並列実行は依然 patent risk が大きいため未着手 (LRM §1.2 単一スレッド前提を維持)
まとめ
2025/12/20 → 2026/5/4 の半年弱で sukimasim は
- テスト数 7,714 → 17,412 (+ 約 1 万)
- IEEE 1800-2023 LRM Functional Coverage 100 % 達成 (意図的未実装は除く、§4 参照)
- 既知の未解消 real bug 0 件
まで来ました。
振り返ると効いた要素は大きく 2 つで、
-
外部の OSS / 商用検証環境で実バグを引き、minrepro を CTest 化して
./scripts/update_dashboard.shで全体回帰を回す という運用を続けたこと - Claude Code (テスト・回帰側) と Codex (C++ 修正側) でゆるく分業した こと
の組み合わせが、自分の使い方では一番安定しました。
当初は Claude Code 1 体で全工程を回していましたが、バグ修正フェーズで詰まりがちだったので、4 月はじめ頃に Codex に修正側を委ねる形に切り替えたところ、副次回帰の頻度が下がって扱いやすくなった、という経緯です。
これが普遍的なベストプラクティスかというとまだ自信はなく、プロンプトの書き方やプロジェクトの性質次第で結論は変わると思います。
ただ、1 体の AI で全部やらせるより、役割を分けて複数の AI を直列に並べたほうが扱いやすい場面はありそうだ、というのが半年運用してみての所感です。
EDA / 検証分野での AI 活用に関心のある方の参考になれば幸いです。
※ 本記事中の数値・実装状況は 2026-05-04 snapshot です (
CLAUDE.md/tests/test_suite_manifest.json由来)。
※ AI 生成コードの法的責任は使用者にあります。AIで作ったものの商用利用時は別途特許 / ライセンス調査をした方がよいと思います。
※ dogfooding (ドッグフーディング): 自社製品を自社の開発・検証に使うことを指す IT 業界のスラング。語源は英語の "Eat your own dog food" (自分のドッグフードを自分で食べる)。本記事では §1.1 の注釈で「sukimasim 自身の機能カバレッジ機能を使って sukimasim 自身の IEEE 1800-2023 準拠率を測っている」自己参照構造を指してこの語を使っています。