半導体設計民主化のための自作RISC-V SoC実践編

PicoRV32 と Wishbone で作る、フィジカルAI時代の実用オリジナルチップ

← 講義ポータルに戻る 実験並走記録 検証・集大成

第12章 徹底検証 ― シミュレーションとAI活用

ここは、本講座の集大成のひとつです。これまで各章で「最小確認」を積み上げてきましたが、その背骨にあったのが検証でした。次章のテープアウト(実チップ製造)は一発勝負――焼き上がったシリコンは、バグがあっても書き換えられません。だからこそ、製造の前にシミュレーションで徹底的に確かめ、異常系まで網羅し、AIを検証に活かす。本章は、私たちが専用ビルド工程(M1〜M5)で実際にやってきた検証のやり方を言語化し、サインオフ(製造GOの判断)前のチェックリストまで一気に通します。

本章の留保(毎章の約束)。 本章で示すのは、M1〜M5で現に動かしてきた検証の型の一般化です。ただし「シミュレーションで通った=実機でも正しい」ではありません(後述12.6)。掲載するテストベンチは骨格で、ツールの版・作法は更新が速いため断定しません。最終的な正しさの審判は実機(物理)であり、本章はその審判に臨むための備えです([改訂マーカー:実機での最終確認])。

12.1 なぜ検証に最大の時間を割くのか

ソフトウェアなら、バグは見つけ次第パッチを当てられます。けれどチップは違います。製造には時間(数ヶ月)と費用がかかり、届いたチップに欠陥があれば、原則作り直し。この非対称が、ハード開発の鉄則を生みます――「設計より検証に時間を割く」。本講座でも、各章のRTLは「骨格・未検証」と正直に表示し、専用ビルド工程で一つずつシミュレーションにかけて初めて"検証済み"としてきました。テープアウトを前に、その姿勢を最大化します。

12.2 検証の思想 ― 思想は人間、実装はAI、最終審判は物理

本講座を貫く一行を、ここで改めて掲げます。「思想(アーキテクチャ・設計判断)は人間が担い、実装と検証の高速な反復はAIが回し、最終的な正しさの審判は物理(実機)が下す」。この三者の役割分担が、検証の地図になります。

 検証における役割分担
 ───────────────────────────────────────────────────────────────
   人間(アーキテクト)  何を作るか・どう設計するか・何を"正しい"とするか を決める
        ↓ 指示・判断
   AI(実装・検証の手)   ラッパ/テストベンチの生成、IP探索、デバッグ補助 を高速に回す
        ↓ 生成物
   シミュレーション        論理の正しさを「机上で」確かめる(速い・安いが、現実の近似)
        ↓ 通ったもの
   物理(実機・最後は製造) 最終審判。クロック・タイミング・現物の部品で「本当に動くか」
 ───────────────────────────────────────────────────────────────
   ※ AIは速いが間違える。だから「人間の判断」と「物理の審判」を、AIの上下に必ず置く。

12.3 道具 ― Icarus Verilog と Verilator

シミュレータには性格の違う二つがよく使われる、とされます。本講座のM1〜M5はIcarus Verilogで回してきました。

Icarus Verilog(軽量・教材向き)

導入が容易で、iverilogvvp の素直な流れ。小〜中規模の機能検証や学習に向く。M1〜M5の結合検証はこれで実証した。

Verilator(高速・大規模向き)

RTLをC++に変換して回す方式で非常に速い、とされる。大規模な回帰テストや、長いプログラムを流す検証に向く。使い分けの選択肢。

※どちらを使うかは規模と目的で選ぶ(断定回避)。 まずIcarusで「型」を作り、検証が重くなったらVerilatorを検討する、という順序が現実的、と著者は考えます。各ツールの導入手順・対応範囲・版は変動するので、最新は公式で確認してください。

12.4 テストベンチの型 ― 「仕事をするC」と「合否を出す番人TB」を分ける

本講座の検証の一番の発明が、この役割分担です。チップ上で動くCプログラムは「仕事をするだけ」に徹し、合否の判定はテストベンチ(TB)という"番人"が独立に持つ。M5を例にとると、Cは「SPIでmicroSDダミーと1バイト、UART2で無線ダミーと1バイトやり取りし、結果を gpio_outLED に出す」だけ。正しいかどうかは一切判断しません。判断はTBの仕事です。

骨格・概念
// テストベンチ=検査の番人(tb_soc.v の型・骨格)
// Cは「仕事」だけ。合否はこのTBが独立に判定する。
initial begin
    $dumpfile("soc.vcd"); $dumpvars(0, tb_soc);     // 波形(VCD)を残す
    repeat (16) @(posedge clk); rst = 0;            // リセットを十分かけてから解除

    // 完了の印(signature)が立つまで待つ。ただし上限つき=ハングしても必ず止まる
    while ((led !== 8'h5A) && (cyc < 2000000)) begin
        @(posedge clk); cyc = cyc + 1;
    end

    // 独立した2つの検査。どちらも満たして初めて PASS
    chk1 = (gpio_out === 16'h5A4F);   // 検査1:結合往復(上位=SD/下位=無線)
    chk2 = (led === 8'h5A);           // 検査2:signature(完了の印)
    $display(chk1 && chk2 ? "==== RESULT: PASS ====" : "==== RESULT: FAIL ====");
    $finish;
end

// 安全網:いつまでも終わらないときの大域タイムアウト(ハング対策)
initial begin #300000000; $display("==== RESULT: FAIL (timeout) ===="); $finish; end

※この分離が効く理由(著者の整理)。 判定をCに混ぜると、Cのバグとハードのバグが見分けにくくなる。Cを「一直線・最小(第6章の4イディオム)」に保ち、検査をTBに集約すれば、失敗したとき"どこが悪いか"が切り分けやすい。さらに、上限つきの待機大域タイムアウトという二重の安全網で、「テストが固まって終わらない」事故を防ぎます。これはM1〜M5で実際に効いた型です。

12.5 異常系を網羅する ― 正常系だけでは足りない

「期待どおりに動く」ことの確認(正常系)は、検証の半分でしかありません。実チップが現場で壊れるのは、たいてい想定外の入力・境界・タイミングです。だからテープアウト前には、異常系を意図的に突きます。

※「通らないテスト」を歓迎する。 異常系でFAILが出るのは良いことです。製造後ではなく、いま、机上で見つかったのですから。正常系のPASSばかり並べて安心するのは、検証としては危険――と心得ます。

12.6 ダミーと本物の差 ― シミュPASSは実機OKではない

ここは、本講座が最も正直でありたいところです。M5の検証で相手をしたのは、教材用ダミーでした。microSDダミーは「受けたビットを反転して返す」だけ、無線ダミーは「合図に 'O' を返す」だけ。これらは「結合経路が通る」ことを最小に実証しますが、本物のSDカードの初期化(CMD0…)やファイルシステム、本物の無線モジュールのATコマンドや技適ではありません。

 シミュレーションで言えること / 言えないこと
 ───────────────────────────────────────────────────────────────
   ◎ 言える   ・論理(バス・レジスタ・状態遷移)が設計どおり動く
              ・経路が通る(信号が正しく届き、往復する)
   × 言えない ・本物の外部部品の作法(SD初期化手順・AT応答・実タイミング)
              ・実クロックでのタイミング成立、現物の電気的振る舞い、温度・電源
 ───────────────────────────────────────────────────────────────
   → だから本講座は、未確定を [改訂マーカー] で明示し、実機で回収する。

この差を曖昧にしないために、本講座は[改訂マーカー]という印を一貫して使ってきました。「シミュで検証済み/実機で最終確認」を区別し、誇張せずに前進する――この規律こそ、一発勝負のテープアウトに耐える検証の土台です。

12.7 波形とログ ― VCD・検査ログ・無害な警告の見分け

検証の現場で頼るのは、二つの目です。

波形(VCD)

$dumpfile/$dumpvars で残した波形を波形ビューアで見る。「いつ・どの信号が・どう変わったか」を目で追い、想定とのズレを見つける。

検査ログ($display)

TBが出す 検査1 … OK/NGRESULT: PASS、到達サイクル数。まずここで合否と"どこまで進んだか"を掴む。

※"無害な警告"と"本物のエラー"を見分ける。 M1〜M5でも、$readmemh: Not enough words(Flashモデルの空き)や @* sensitive to all 1024 words(非同期メモリの通知)といった無害なメッセージが出ました。これらに動じず、本当に問題のあるエラー(未結線・幅不一致・X伝播)と切り分けるのも検証の技術です。すべての警告を消すのが目的ではなく、意味を理解して仕分けること。

12.8 AIを検証に活かす ― 何を任せ、何を任せないか

本講座は「人がアーキテクト、AIが実装と検証を高速に回す」現代的な開発を実演してきました。検証でも、AIは強力な手になります。ただし節度が要ります。

AIに任せて効くこと

IP候補の探索、Wishboneラッパ等のグルーコード生成テストベンチの叩き台作り、波形・エラーログからの原因推定。反復が速くなる。

AIに任せてはいけないこと

最終判断。AIはもっともらしく間違える(実在しないIP名・ポート・レジスタを"自信満々"に出す)。設計の正否と"何を正しいとするか"は人間が握る。

※だから本講座は断定を避けてきた。 第5章でIPを一次情報(公式リポジトリ)で裏取りしてから本文に載せたのは、まさにAI由来の取り違えを防ぐためでした。AIの出力は必ず現物(データシート・ソース)と物理(シミュ・実機)で検算する速さはAI、確かさは人間と物理――この順序を崩さなければ、AIは検証の最良の相棒になります。
発展:AIに「良いテストベンチ」を書かせるコツ

丸投げではなく、「何を正しいとするか(合否基準)」を人間が先に定義して渡すと、AIのTB生成は精度が上がります。M5なら「gpio_out0x5A4FLED0x5A なら PASS、上限サイクルで FAIL、大域タイムアウトも置く」と基準を明示する。判定の言語化は人間の仕事、その実装の高速化はAIの仕事――役割分担がそのままプロンプトの設計になります。

12.9 サインオフ前チェックリスト

テープアウト(第13章)にGOを出す前に通す、機能検証側のチェックリストです(配置配線・DRC/LVS/STA はテープアウト工程の領域。ここは「論理として正しいか」を固めます)。

 サインオフ前チェックリスト(機能検証)
 ───────────────────────────────────────────────────────────────
   □ 全周辺が個別にシミュ検証済み(M1〜M5 の各検査が PASS)
   □ 結合状態でも検査が PASS(周辺を載せた状態で破綻しない)
   □ 異常系を網羅(境界・タイミング・不正番地・タイムアウト)
   □ 警告をすべて仕分け済み(無害 / 本物のエラー を区別し、後者はゼロ)
   □ メモリマップが「本文・実装・ソフト」で一致(番地整合)
   □ リセット/クロックの扱いを確認(初期化・乱れに耐える)
   □ [改訂マーカー] を棚卸し(実機で確認すべき項目が一覧化されている)
   □ 実機(FPGA)で主要機能を確認(シミュPASS≠実機。物理で最終確認)
 ───────────────────────────────────────────────────────────────
   ※ ここまで通って初めて、第13章(LibreLane/OpenROAD)へ進む。

12.10 この章のまとめ

機能の正しさを固め、チェックリストを通しました。いよいよ、固めたRTLをシリコンへ渡す番です。次章は、LibreLane(内部でOpenROADが配置配線を担う)にRTLを渡し、GDSIIへ変換、DRC/LVS/STAでサインオフしてシャトルへ提出する――ASIC化の本筋への入口、第13章:テープアウト ― LibreLane/OpenROADです。