はじめに
筆者は、自分自身の勉強目的で、Claude Code を使って、mrun(仮) というSystemVerilogシミュレータを6月中旬から開発中です。開発開始から約1ヶ月が経過したので、現時点での実装済仕様をまとめました。
mrun(仮) について
mrun(仮)は、SystemVerilog (IEEE 1800-2023) の設計検証を行うオープンソース・シミュレータです。他の多くのオープンソースSystemVerilogシミュレータ(Verilator、Icarus Verilog等)と同様に、RTLシミュレーションと基本的な検証機能に注力しており、商用ツール特有の高度な機能(カバーグループなど)は実装していません。
正式名称については、mrun だと、某社のシミュレータの実行コマンドと一文字違いのため変更を検討中です。そのため (仮) としています。
現在の実装状況(2025年7月15日時点)
sv-tests成功率: 98.55%(1022/1037 PASS)
mrun(仮)は基本的なRTLシミュレーションと検証機能において実用的な品質に到達しており、以下の機能が実装済みです:
- 基本SystemVerilog機能: sv-testsの第5章〜第12章のテストで高い成功率
- DPI-C: 基本機能実装(import のみ、基本型に限定)
- UVM 1.2: 基本的なクラス階層とフェーズ実行機構(最小限の実装)
- 制約ソルバー: 基本的なrandomize()、with句の部分サポート
- アサーション: assert property、cover property、基本的なクロック同期アサーション
- 波形出力: VCD形式の基本サポート、FST形式の基本サポート
アーキテクチャ概要
フロントエンド
mrun(仮)は、高品質なSystemVerilogパーサーであるSlangを採用しています。
// Slang v8.2 (master branch) を使用
#include <slang/compilation/Compilation.h>
#include <slang/parsing/Parser.h>
#include <slang/ast/ASTVisitor.h>
イベントスケジューラ
現在は5リージョンの簡易モデルを実装しています:
enum class EventRegion : uint8_t {
Active = 0, // ブロッキング代入とNBAの右辺評価
PreNBA, // NBA前の同期
NBA, // ノンブロッキング代入の左辺更新
PostNBA, // NBA後の処理
Observed // アサーション評価
};
17リージョンモデルは実装されていますが、現在のシミュレータには統合されていません。
主要な実装機能
1. DPI-C(Direct Programming Interface)
SystemVerilogからC/C++関数の呼び出しを基本的にサポート:
実装済み機能:
- DPI-C import(基本型: int, void, string, chandle)
- 単純な関数シグネチャのサポート
- UVMで必要な基本的なDPI関数
未実装機能:
- DPI-C export(Cから SystemVerilog タスク/関数の呼び出し)
- 複雑なデータ型(構造体、配列、ユニオン)
- ビットベクトル(svBitVecVal)の完全なサポート
- コンテキスト関数(svScope等)
// 動作する例
import "DPI-C" function int simple_add(input int a, input int b);
import "DPI-C" function string get_version();
import "DPI-C" function void print_message(input string msg);
// 未サポートの例
export "DPI-C" function sv_callback; // ❌ export未実装
import "DPI-C" function void process_struct(input my_struct_t s); // ❌ 構造体未対応
2. UVM(Universal Verification Methodology)サポート
基本的なUVMクラス階層と9フェーズ実行機構を実装:
class my_test extends uvm_test;
`uvm_component_utils(my_test)
function void build_phase(uvm_phase phase);
super.build_phase(phase);
// テストベンチの構築
endfunction
task run_phase(uvm_phase phase);
phase.raise_objection(this);
// テストシナリオの実行
phase.drop_objection(this);
endtask
endclass
3. 制約付きランダム化
基本的な制約付きランダム化機能:
class packet;
rand bit [7:0] addr;
rand bit [31:0] data;
constraint valid_addr {
addr inside {[10:20], [30:40]};
}
endclass
// 基本的な randomize()
packet p = new();
p.randomize();
// with句の基本サポート
p.randomize() with { addr == 15; };
注意: ソフト制約、複雑な制約式、foreach制約などの高度な機能は限定的なサポートです。
4. アサーションとカバレッジ
assert property
property req_ack;
@(posedge clk) req |-> ##[1:3] ack;
endproperty
assert property (req_ack)
else $error("Request not acknowledged within 3 cycles");
cover property
cover property (@(posedge clk) req ##1 grant)
$display("Coverage hit: req followed by grant");
シミュレーション終了時に自動的にカバレッジレポートを出力:
================== Coverage Report ==================
Total coverage hits: 10
Covered properties: 3
Uncovered properties: 1
Covered:
- cp1 (hits: 5)
- cp2 (hits: 3)
- cp3 (hits: 2)
Not covered:
- cp4
====================================================
5. 波形出力(VCD/FST)
複数の波形フォーマットをサポート:
initial begin
// VCD形式(従来フォーマット)
$dumpfile("simulation.vcd");
$dumpvars(0, top_module);
// FST形式(高圧縮・高速)
$dumpfile("simulation.fst");
$dumpvars(0, top_module);
end
FST形式の特徴:
- LZ4圧縮による大幅なファイルサイズ削減
- 4状態ロジック値(0/1/X/Z)の効率的エンコーディング
- GTKWaveで直接開ける高速アクセス
Slangの制限事項と回避策
開発中に遭遇したSlangパーサーの制限事項と、その実用的な回避策:
1. UVMマクロ展開の問題
問題: uvm_component_utils
等のUVMマクロがUnknownDirectiveエラーとなる
解決策: AllowUseBeforeDeclareフラグ + エラー継続モードで実用的に回避
compOptions.flags |= CompilationFlags::AllowUseBeforeDeclare;
// UsedBeforeDeclaredエラーを無視する処理を追加
2. obj.randomize()の誤解析
問題: オブジェクトのrandomize()メソッドがstd::randomize(obj)
として解析される
解決策: AST変換時に特別な処理を追加し、複数変数にも対応
// evaluator.cppで適切に処理
if (funcName == "randomize" && hasObjectContext) {
// オブジェクトメソッドとして処理
}
未実装機能(商用ツールとの差異)
以下の機能は、多くのオープンソースシミュレータと同様に未実装です:
- カバーグループ(covergroup) - 商用ツール特有の高度な機能カバレッジ
- 17リージョンスケジューラ - 実装済みだが未統合(基本的な検証には5リージョンで十分)
- UCIS形式のカバレッジレポート - 簡易的なテキスト形式で代替
- programブロック、clocking block - 高度な検証環境向け機能
- VPI(Verilog Procedural Interface) - 自分の経験では検証環境の担当者でなければ使う事はほとんどない。
パフォーマンスと品質
ベンチマーク結果(未測定・推定値)
注意: 以下の数値は実際のベンチマーク測定結果ではなく、アーキテクチャ設計に基づく推定値です。実際の性能測定は今後の課題となっています。
中規模設計(約10万ゲート相当)での予想実行速度:
- 組み合わせ回路: 商用ツールの約70-80%の速度(推定)
- 順序回路: 商用ツールの約60-70%の速度(推定)
メモリ使用量(推定)
- 100万行の設計で約2〜4GBのメモリ使用を想定(Slangのメモリ効率に依存)
- 波形記録時は設計規模とシミュレーション時間に比例して増加すると予想
実際の性能について
現時点では体系的なベンチマーク測定は実施されていません。上記の数値は以下の要因に基づく推定です:
- インタプリタベースの実装(JITコンパイラ未実装)
- 5リージョンイベントスケジューラの簡易実装
- 最適化が限定的な初期実装段階
実際の性能は、対象となる設計の特性やシミュレーション内容により大きく変動する可能性があります。
今後の展望
短期目標(〜2025年Q3)
- sv-tests 100%達成(残り15テストの対応)
- パフォーマンス最適化(商用ツールの80%以上を目標)
- デバッグ機能の強化
中長期目標(2025年Q4〜)
- 17リージョンスケジューラの統合
- より高度なアサーション機能のサポート
- VPI基本機能の実装
まとめ
mrun(仮)は、Claude Codeを活用して開発されたSystemVerilogシミュレータとして、以下の特徴を持ちます:
- 実用的な機能セット: RTLシミュレーションと基本的な検証に必要な機能を網羅
- 高い互換性: sv-tests 98.55%の成功率が示す基本機能の堅実な実装
- オープンソース: 教育・研究用途や、商用ツールの機能制限版の様な入門用途
- 現実的なアプローチ: 他のOSSシミュレータと同様、実用性を重視した機能選択
mrun(仮)は商用シミュレータの代替を目指すのではなく、オープンソースコミュニティにおける実用的な入門レベルのSystemVerilogシミュレータとして、基本的なRTL開発と検証作業の学習を支援することを目的としています。商用ツールと比較すると、高度な検証機能(カバーグループ、VPI、高度なデバッグ機能など)は未実装ですが、基本的なSystemVerilog言語機能はそこそこのレベルで実装できました。
参考リンク
本記事は2025年7月15日時点の実装状況に基づいています。プロジェクトは開発中であり、機能は継続的に追加・改善の予定です。