はじめに
以下の記事で、Claude Code で開発中の SystemVerilogシミュレータ mrun(仮)
の途中経過を報告させていただきました。
記事 | 主な内容 |
---|---|
Claude Codeを使用してSystemVerilogシミュレータを開発してみた (2024/7/5 開発状況) | 開発動機と開発状況 |
mrun(仮) は、なぜバイトコード方式なのか? | VMアーキテクチャと命令セット設計 |
mrun(仮)
の開発は順調に進んでおり、2025年6月30日時点で、sv-tests がある程度Passするまでになっています。(なお、sv-tests は、CHIPS Alliance が運営するオープンソースの SystemVerilog 互換性テストスイート で、目的は 「各種 Verilog/SystemVerilog ツールが仕様のどの機能をサポートし、どこが未対応かを体系的に可視化する」 ことです。GitHub で公開されており、毎日のように主要 OSS ツールをビルドしてテスト結果をダッシュボードで公開しています。)
0. 本記事のスコープ
本記事では、シミュレータの心臓部であるイベントスケジューラに焦点を当てます。SystemVerilog シミュレータの品質は、IEEE 1800規格が定める「イベント処理17領域(リージョン)」をいかに忠実に、かつ効率的に実装するかにかかっています。
本記事では、この17領域(以降はリージョンと記載します)を軸に、
- What: 各リージョンは具体的に何をしているのか? (仕様の理解)
- Why: なぜ規格は“そこまで”細分化したのか? (設計思想の背景)
-
How:
mrun(仮)
はこれをどう実装しているのか? (mrun(仮)での実装方針)
の3点を、VerilogとSystemVerilogの歴史を交えながら解説してみます。
なお、
mrun(仮)
は、まずは、軽量なテストベンチ用のシミュレータ を目標とし、スケジューラを簡略化しています。
- 対象範囲: 純粋な RTL +
initial/always
ベースの簡易テストベンチ。現在、サポートしているのは 7つの主要Simリージョン (Preponed, Active, Inactive, NBA, Observed, Reactive, Postponed) です。VPI/DPI専用リージョンは現時点では実装しておらず、program
/clocking
ブロック、UVM拡張はサポート外です。- ロードマップ: VPIフック用リージョンを含む 17 リージョン完全対応 は次期フェーズで実装予定。ここで UVM / DPI に正式対応予定。
- 既知の制約: 未サポート構文をコンパイル時エラーで拒否します。(誤動作より早期失敗を優先。)
- Δ(デルタ)ループ検出は、オプション
--delta-cycle-limit=<N>
で調整可能にしています。なお、将来の拡張を見据え、コードベースはリージョン追加が容易な層構造で実装しています。
1. Δ(デルタ)ステップの中では何が起きているのか?
シミュレータは、ある単一のシミュレーション時刻(タイムスロット)内で、複数の計算ステップを踏むことがあります。この「同一シミュレーション時刻内で実行される、時間経過を伴わない追加の評価サイクル」をΔ(デルタ)ステップ (delta cycle) と呼びます。IEEE 1800規格は、このΔ(デルタ)ステップ内での処理順序を保証するため、17のイベントリージョンを定義しています。
Note: 本記事で用いる
$…$
記法は、Qiitaの数式表示機能(MathJax)を有効にすることで正しくレンダリングされます。
1.1. リージョンのグルーピングと目的
17リージョンは無秩序に並んでいるわけではなく、明確な目的を持ったグループに分けることができます。
この階層化により、シミュレータは1つのタイムスロット内で常に以下の順序を保証します。
設計 (RTL) の状態の更新 → 検証 (アサーション) の評価 → 検証 (テストベンチ) の反応 → 最終値の表示
これにより、設計と検証の間のレースコンディションを原理的に排除しています。
ただし、図中の Event Rescheduling
が示すように、17リージョンは単純な一方通行ではありません。Concurrent Assertionの失敗やclocking
ブロックの出力駆動など、特定の条件では後方のリージョンから前方のActiveリージョンへイベントが再スケジュールされることも規格で定義されており、これがΔ(デルタ)無限ループの一因となることもあります。
1.2. 全17リージョンリスト
表1.1: IEEE 1800-2023 イベント処理17リージョンとVPIコールバック (クリックで展開)
No. | リージョン名 | 種別[*1] | 主な役割と代表的なトリガ | VPIコールバック (vpiCbReasonT ) |
---|---|---|---|---|
1 | Preponed | Sim | Concurrent Assertion用の値サンプリング。読み取り専用。 | (なし)[*2] |
2 | Pre-Active | VPI | Activeリージョン前に値を観測 (読み取りが主)。時刻が進んだ直後や遅延完了時に呼ばれる。 |
cbAtStartOfSimTime , cbNextSimTime [*3], cbAfterDelay
|
3 | Active | Sim | RTLのブロッキング代入(= )、NBAのRHS評価、連続代入、$display 。 |
- |
4 | Inactive | Sim |
#0 付きブロッキング代入。Activeリージョンとの競合を回避。 |
- |
5 | Pre-NBA | VPI | NBA更新直前の同期ポイント。[*4] | cbNBASynch |
6 | NBA | Sim | ノンブロッキング代入(<= )のLHS更新を一括適用。 |
- |
7 | Post-NBA | VPI | NBA完了後の同期ポイント。値の書き込みも可能。 | cbReadWriteSynch |
8 | Pre-Observed | VPI | Observedリージョン前のフック。 | (なし)[*5] |
9 | Observed | Sim | Concurrent Assertionの評価、clocking ブロックの入力サンプリング。 |
- |
10 | Post-Observed | VPI | アサーション評価後のフック。 | (なし)[*5] |
11 | Reactive | Sim |
program ブロックのコード、アサーションのアクションブロック実行。 |
- |
12 | Re-Inactive | Sim |
program ブロック内の#0 付きブロッキング代入。 |
- |
13 | Pre-Re-NBA | VPI |
program ブロックのNBA更新前フック。 |
(なし)[*5] |
14 | Re-NBA | Sim |
program 内のNBA更新、clocking ブロックの出力駆動。 |
- |
15 | Post-Re-NBA | VPI |
program ブロックのNBA更新後フック。 |
(なし)[*5] |
16 | Pre-Postponed | VPI | Postponedリージョン直前の最終確認用。値更新は可能だが、現タイムスロットへのイベントの巻き戻しは禁止。 | cbAtEndOfSimTime |
17 | Postponed | Sim |
$strobe /$monitor 、最終値の表示。読み取り専用。 |
cbReadOnlySynch |
[*1] Sim: SystemVerilog構文(
always
ブロック、アサーション等)が直接配置されるコアなリージョン。 VPI: VPI/DPIコールバック専用のフック用リージョン。SystemVerilogの構文は直接配置できない。
[*2]Preponed
リージョンに直接フックするVPIコールバックは規格で定義されていません。なお、アサーション内の関数/タスクが評価される際にcbStartOfSubprogram
(vpi_user.h
での正式名称)がトリガされることがありますが、これはリージョン自体へのコールバックとは異なります。
[*3]cbAtStartOfSimTime
とcbNextSimTime
は、多くのシミュレータ実装で**読み取り専用(read-only)**として扱われます。値の変更が許可されるかは実装依存であり、注意が必要です。
[*4]cbNBASynch
は、NBA更新の直前であることと、Post-NBAリージョンで実行されるcbReadWriteSynch
より前に実行されることが保証されます。
[*5] 規格策定の歴史的経緯や、実用上の需要とのバランスから、すべてのリージョン遷移点にVPIフックが設けられているわけではありません。
2. なぜ 17 リージョンまで厳密に決めるのか (Why)
- 決定性の保証: 同じHDLコードは、どのベンダーのシミュレータで実行しても、ビット単位で同一の波形を生成しなければなりません。17リージョンは、そのための厳格な契約書です。
-
レース排除: ${\rm Active};\to;{\rm NBA};\to;{\rm Observed};\to;{\rm Reactive}$ という主要なリージョンの流れ、より広義には
Active Set
(設計の更新) からReactive Set
(検証の反応) への流れにより、「DUTの更新が終わって安定してから、TBが値を観測・反応する」という理想的な動作を時間論理的に保証します。 - 高位検証機能の地盤: Concurrent AssertionはObserved、カバレッジはPostponedと、各機能の実行タイミングを釘付けにすることで、検証IP(VIP)のポータビリティと再利用性を担保します。
- 実装自由度と互換性の両立: 規格はリージョン間の遷移順序のみを規定します。リージョン内のイベントをどう処理するか(並列実行、JITコンパイルなど)はシミュレータベンダーの裁量に任されており、性能最適化の余地を残しています。
3. 歴史的背景 ― ツール互換性問題が促した細分化 (Why)
年 | IEEE規格 | トピック |
---|---|---|
1995 | IEEE 1364-1995 | (Verilog-95) 明示的な領域定義はなかったが、ノンブロッキング代入 (Non-blocking Assignment, NBA) の評価と更新を分離する概念は存在した。 |
2001 | IEEE 1364-2001 | (Verilog-2001) generate 文等の導入で設計が大規模化し、<= の解釈がベンダー間で微妙に異なり、ツール依存のレースが噴出。 |
2005 | IEEE 1364-2005 | (Verilog-2005) これを最後に、Verilog 規格は単独で更新されていない。以後の言語仕様更新は SystemVerilog 規格側でのみ行われており、Verilog 側の年号呼称もそこで終わった。 |
2005 | IEEE 1800-2005 | (SystemVerilog 初版) ベンダー間の非互換問題を解決するため、NBA領域を正式化。さらにテストベンチとDUTを分離するため Observed/Reactive領域を導入。17リージョンの基本構造が確立。 |
2009 | IEEE 1800-2009 | (SystemVerilog 2009) Verilog規格(IEEE 1364)が廃止され、SystemVerilog側に正式統合。単一の言語規格となる。 |
2012 | IEEE 1800-2012 | (SystemVerilog 2012) interface class やsoft 制約など検証機能が大幅に強化。スケジューリングは安定化・成熟期へ。 |
2017 | IEEE 1800-2017 | (SystemVerilog 2017) 17リージョンの定義が現在の形で安定化。IEEE GET Program経由での無償公開により、規格へのアクセス性が向上。 |
2023 | IEEE 1800-2023 | (SystemVerilog 2023) DPI-C拡張など細則の穴埋め・用語統一が中心。より厳密な定義へ。 |
4. 17リージョンを意識した設計・検証ガイドライン (How to Write)
17リージョンの存在を理解すると、「なぜそのように書くべきか」が明確になります。
-
RTLはActive/NBAに収める:
always_ff
やassign
を正しく使えば、設計コードはActive Set内で完結し、予測可能に動作します。 -
テストベンチは
program
ブロックで書く: これにより、DUTの値が完全に確定した後(NBA後)にTBが反応することを保証でき、最も安全です。ただし、program
ブロック内でも#0
を乱用するとRe-Inactiveリージョンでの予期せぬスケジューリングが発生しうるため注意が必要です。 -
ゼロ遅延 (
#0
) は使わない:#0
は設計側ではInactive、テスト側ではRe-Inactiveに入り、意図せぬ動作やレースの原因となります。ノンブロッキング代入やclocking
ブロックで代替すべきです。ただし、古いコードや特定の状況では互換性のために使われることもありますが、意図しない競合の原因となりやすいため、現代の設計では避けるのが鉄則です。 - Concurrent Assertionは「サンプル(Preponed)→評価(Observed)」: 観測と評価のタイミングが分離されているため、信号が安定した状態で評価されることが保証されます。
-
値の表示は
$strobe
を使う: Postponedリージョンで実行される$strobe
は、そのタイムスロットで全ての更新が終わった後の「最終確定値」を表示します。デバッグには$display
(Activeリージョンで実行)より$strobe
が鉄則です。initial begin a=1; b=0; #1; // ActiveリージョンでRHS(b=0, a=1)が評価され、NBAリージョンでの更新がスケジュールされる a <= b; b <= a; // Activeリージョン: NBAのLHS更新はまだ。更新前の値を表示。 $display("@%0t: display: a=%0d, b=%0d", $time, a, b); // Postponedリージョン: 全ての更新が終わった後の最終値を表示 $strobe ("@%0t: strobe: a=%0d, b=%0d", $time, a, b); end // 出力例: // @1: display: a=1, b=0 // @1: strobe: a=0, b=1
-
VPI/DPIは適切なフックリージョンを選ぶ: NBA更新後の値を安全に観測したい場合、
Post-NBA
リージョン (cbReadWriteSynch
フック) よりも、すべての値が確定し読み取り専用となるPostponed
リージョン (cbReadOnlySynch
フック) を使うのが鉄則です。なぜなら、Post-NBA
リージョンは依然として値の書き込みが許可されており、その後のObserved
やReactive
リージョンでのイベントが新たな更新をスケジュールする可能性があるためです。
5. mrun(仮)
の実装方針とΔ(デルタ)無限ループ検出 (How to Implement)
5.1. mrun(仮)
スケジューラの設計方針
この歴史と仕様を踏まえ、mrun(仮)
のスケジューラは以下の3つを設計の柱とします。
-
段階的な規格準拠:
- 現在の実装では、0章で述べた通り、7つの主要Simリージョン(Preponed, Active, Inactive, NBA, Observed, Reactive, Postponed)をサポートしています。
- 各リージョンに対応するイベントをバイナリヒープベースの優先度キューで管理し、時刻順・リージョン順・優先度順で処理します。
- 将来的には17リージョン完全対応を目指しますが、現時点では最低限実用上必要な主要リージョンに焦点を当てています。
// mrun(仮)の実装を簡略化した疑似コード。 // 実際の実装では、より複雑なエラーハンドリングや最適化が含まれます。 enum class EventRegion { Preponed = 0, Active = 1, Inactive = 2, NBA = 3, Observed = 4, Reactive = 5, Postponed = 6 }; class BinaryHeapScheduler { std::priority_queue<ScheduledEvent> events_; void processEvents() { while (!events_.empty() && events_.top().time == currentTime_) { auto event = events_.top(); events_.pop(); // イベントを実行(プロセスの再開など) executeEvent(event); } } };
-
VMとの協調によるRHS/LHS分離:
- VMはノンブロッキング代入(
<=
)に遭遇すると、EVAL_RHS
命令で右辺値を評価し、続くSCHEDULE_NBA
命令でイベントオブジェクトをNBAリージョンのキューに登録します。 - スケジューラがNBAリージョンに到達した際、初めてキュー内のイベントが実行され、変数の値がコミットされます。
- VMはノンブロッキング代入(
-
並列化への布石:
- リージョンの境界が自然な**同期ポイント(フェンス)**となります。将来、リージョン内の依存しないイベント群を並列実行させることで、性能をスケールさせる構想です。
5.2. Δ(デルタ)無限ループ検出
Δ(デルタ)無限ループは、Active/Inactive/NBAリージョン等を循環するゼロ遅延の組み合わせループで発生します。
logic a, b;
// 明示的な初期化(ツール互換性のため)
initial begin
a = 0;
b = 0;
end
always @(a) b = ~a; // aの変化がこのalwaysをトリガ
always @(b) a = ~b; // bの変化がこのalwaysをトリガ
mrun(仮)
では、リージョンを横断する総イベント数でこれを検出し、ユーザーに通知します。
-
検出ロジック: 1タイムスロット内で実行されるイベント総数が、しきい値(デフォルト100万回)を超えた場合、無限ループと判断。
-
診断情報: 無限ループを検出したら、エラーメッセージと共に、デバッグに役立つ情報を出力します。
[MRUN-ERROR] Delta cycle limit exceeded (1,000,000 iterations) at time 0 ns. Simulation stopped due to a possible infinite loop. Loop detected in 'Active' region (3/17). Pending events in 'Active' queue: 2 - Process triggered by 'a' at test.sv:4 - Process triggered by 'b' at test.sv:5 To adjust the limit per time slot, use --delta-cycle-limit=<N>. Hint: For advanced debugging, a future --trace-delta-loop option will provide detailed event history.
-
UVM対応: 将来UVMをサポートする際は、この検出機構をフックして
uvm_fatal
を発行できるようにAPIを整備します。
6. まとめ
17リージョンは、レース排除と高機能化のための契約である。
この階層構造を理解することで、
-
RTL → Assertion → Testbench → Report
という厳密な実行順序がなぜ保証されるのか、 - ノンブロッキング代入(
<=
)やclocking
ブロックがなぜそのように振る舞うのか、 - VPI/DPIコールバックをどこにフックすれば安全か、
を体系的に説明できるようになります。
mrun(仮)
では、現在の実装では7つの主要Simリージョンをサポートしており、将来的に17リージョン完全対応を目指しています。
参考文献
- IEEE Standard for SystemVerilog: IEEE 1800-2023, Clause 4. Stratified event scheduler. (Available through [IEEE GET Program][ref_ieee])1
- Wikipedia “Verilog”2
- SystemVerilog Scheduling Semantics - Verification Guide3
- SV Time Slot Regions - Step By Step ASIC Verification4
Appendix A: SystemCのイベントスケジューラとの比較
SystemVerilogの17リージョンがいかに精緻な構造を持つかを理解するために、もう一つの代表的なハードウェア記述言語であるSystemCのスケジューラと比較してみます。この比較により、SystemVerilogのスケジューラ設計の必然性がより明確になるでしょう。
SystemCのシンプルなΔ(デルタ)サイクル構造
SystemCのイベントスケジューラは、「Δ(デルタ)サイクル」を軸とした3フェーズ構造をしています。SystemVerilogのような17の細分化されたリージョンは存在しません。
図の説明: Notifyフェーズで即時イベントが通知されると、シミュレーション時間を進めることなく、再び同じ時刻でEvaluateフェーズから次のΔ(デルタ)サイクルを開始します。
-
Evaluate Phase (E): 感度リストによって起動されたプロセス(
SC_METHOD
,SC_THREAD
)が実行されます。 -
Update Phase (U): Evaluate Phaseで発行された全ての
sc_signal
への書き込み要求が、このフェーズで一括してコミット(値の確定)されます。これにより「評価と更新の分離」が保証されます。 -
Notify Phase (N): Update Phaseで値が変化した信号に関連するイベントが通知されます。
notify()
で生成されたイベントは、感応するプロセスを次のΔ(デルタ)サイクルのEvaluateフェーズで実行可能にするようにスケジュールします。
SystemVerilog 17リージョン vs SystemC 3フェーズ
両者の設計思想の違いは、スケジューラの構造に明確に表れています。
表 A.1: SystemVerilogとSystemCのスケジューラ比較
観点 | SystemVerilog | SystemC |
---|---|---|
1Δ内のスロット数 | 17 (Sim 9 + PLI 8) | 3 (Evaluate / Update / Notify) |
プロセス種別 |
always_* , program , Concurrent Assertionなど多数 |
SC_METHOD , SC_THREAD , SC_CTHREAD
|
NBA相当の機構 | NBAリージョンでのLHS更新 | Update Phaseでの一括コミット |
ゼロ遅延相当¹ |
#0 (同一Δ(デルタ)ステップ内の後続リージョンで実行) |
wait(SC_ZERO_TIME) (次のΔ(デルタ)サイクルの開始時に実行) |
アサーション | Concurrent Assertion (SVA) を言語機能として内蔵 | 標準では sc_assert(expr) (C標準assert と同等の即時型)のみ。SVA相当はPSL (IEEE 1850)や外部ライブラリで補う。 |
外部フック² | VPI/DPI用のPre/Postリージョンが8つ標準化 | 標準LRMにVPI同等の時相フックはないが、sc_trace や実装依存の拡張機能で対応。 |
¹ゼロ遅延の挙動の違い: SystemVerilogの
#0
は同一Δ(デルタ)ステップ内の後続リージョンで実行されますが、SystemCのwait(SC_ZERO_TIME)
はプロセスを次のΔ(デルタ)サイクルで再スケジュールするため、実行タイミングが1Δ(デルタ)サイクル分遅れます。
²外部フック:sc_kernel_callbacks
のようなAPIはSystemCの標準ではなく、シミュレータベンダーによる実装依存の拡張機能です。
パフォーマンスと具体例
-
パフォーマンス: SystemVerilogの17リージョンは、厳密な順序保証とツール連携のために設計されており、その管理には相応のオーバーヘッドが伴います。一方、SystemCのシンプルな3フェーズ構造は、特に高位レベルのシミュレーションにおいて高速に動作する要因の一つです。これは「正確性・機能性」と「パフォーマンス」のトレードオフと言えます。
-
コード例: クロック同期で信号
a
とb
の値をスワップする動作を考えます。SystemVerilog (NBAを使用)
// ノンブロッキング代入により、RHSは現在のクロックでの値が評価され、 // 値の更新(スワップ)が正しく行われる。 always_ff @(posedge clk) begin a <= b; // 現在のbの値を読み、次のクロックでaに代入するよう予約 b <= a; // 現在のaの値を読み、次のクロックでbに代入するよう予約 end
SystemC (
sc_signal
を使用)// SC_METHODとsensitiveリストでクロック同期プロセスを定義 SC_METHOD(swap_proc); sensitive << clk.pos(); // クロックの立ち上がりエッジに反応 void swap_proc() { // write()はUpdate Phaseでの更新を予約するだけ。 // read()はEvaluate Phaseで現在の値を読むため、正しくスワップされる。 a.write(b.read()); b.write(a.read()); }
両者とも「評価と更新の分離」という共通のメカニズムにより、期待通りに値がスワップされます。
実務上のインパクト
-
テストベンチとDUTの分離:
SystemVerilogのprogram
ブロックはDUTの動作安定を保証しますが、SystemCではwait(SC_ZERO_TIME)
を意図的に挿入してΔ(デルタ)サイクルをずらす設計テクニックが必要です。 -
UVMとの連携:
UVM-SystemCでは、SystemVerilog UVMのフェージング機構(run_phase
内の各サブフェーズなど)を、SystemCのイベント通知とwait
文を駆使して擬似的に実装します。これにより、言語は違えどUVMの検証手法の恩恵を受けられるようになりますが、その実現にはスケジューラへの深い理解が求められます。
まとめ:どちらが優れているか?
- SystemCの3フェーズは、C++ベースの高速なシミュレーションと、TLMなどの高位合成に適したシンプルで効率的な構造です。
- SystemVerilogの17リージョンは、ハードウェアの挙動を正確に記述し、UVMのような再利用性の高い検証資産と堅牢に連携するための、精緻で網羅的な契約です。
どちらの言語を選択するかは、設計・検証の抽象度とプロジェクトの要求に依存するので、一言でどちらが優れているとは言えません。
SystemVerilogの精緻なスケジューラは、RTLレベルでの決定性とツール互換性を最大限に高めるための強力な仕組みと言えるでしょう。
参考文献 (Appendix)
- IEEE Std 1666-2011, Standard for SystemC Language Reference Manual
- IEEE Std 1850-2010, Standard for Property Specification Language (PSL)
- Accellera Systems Initiative - SystemC Verification Standard (SCV)
Appendix B: SystemVerilog のリージョン数を整理する
まとめ
- IEEE 1800‑2023 は §4.4.2 で 9 個の simulation regions を定義している。
- 直後の §4.4.3 では、PLI/DPI 用コールバックとして 8 個の PLI regions を別途定義している。
- “17 リージョン” と呼ばれるのは、
$9_{\text{simulation}} + 8_{\text{PLI}} = 17$
という「9 + 8」構成を示したものである。
どう数えるかで個数は変わる
数え方 | 含めるリージョン | 個数 |
---|---|---|
Simulation のみ | Preponed, Active, Inactive, NBA, Observed, Reactive, Re‑Inactive, Re‑NBA, Postponed | 9 |
Simulation+主要 PLI (本記事の “17 リージョン”) |
上記 9 + Pre‑Active, Pre‑NBA, Post‑NBA, Pre‑Observed, Post‑Observed, Pre‑Re‑NBA, Post‑Re‑NBA, Pre‑Postponed | 17 |
SystemVerilog 拡張の要点
-
NBA と BA の実行順序
Active → Inactive → NBA → … の流れを示すと、タイミング依存不具合を説明しやすい。 -
プログラムブロックとモジュールブロックのタイミング
program
内の blocking 代入は Reactive、non‑blocking 代入は Re‑NBA に配置される。 -
Concurrent Assertion
サンプリングは Observed、pass/fail アクションは Reactive に入る。
これらは 9 simulation リージョン の枠組みだけで十分に語れるため、テストベンチと DUT 間のレース防止という SystemVerilog 拡張の要点を端的に表している。
実務での指針
- 通常は 9 リージョンを覚えれば足りる。 PLI コールバックまで扱う場合にのみ追加リージョンを意識する。
- Reactive と Re‑NBA の区別は テストベンチ側の signal forcing でバグを生まないための最重要ポイント。
- SystemVerilog LRM では “simulation regions” と “PLI regions” を明確に分離 している。
参考資料
- IEEE Std 1800‑2023 © IEEE — SystemVerilog Language Reference Manual, §4.4.
- Mentor Graphics, Questa Advanced SV Course, "Simulation Region Scheduling".
- Accellera, SystemVerilog 3.1a LRM (2004), Figure 4‑1.
-
https://www.accellera.org/news/press-releases/394-accellera-announces-ieee-1800-2023-standard-available-through-ieee-get-program ↩
-
https://verificationguide.com/systemverilog/systemverilog-scheduling-semantics/ ↩
-
https://stepbystepasicblog.wordpress.com/2017/07/09/sv-time-slot-regions/
[link_1]: https://qiita.com/sukimaengineer/items/3b508484e36fc128a6db
[link_2]: https://qiita.com/sukimaengineer/items/a649d74a3f76cc4cc7eb ↩