For Good FPGA Design

UVMの環境構築!(6) Monitor

UVMの環境構築第6回では、モニターの定義(作成)方法について解説していきます。

なお、ソースコードはGitHubに公開しています。

目次

シリーズ目次

UVMの環境構築!シリーズの目次は、第1回 解説編の一番下をご覧ください。

モニターの概要

モニターはuvm_monitorまたはそのサブクラスを継承して定義します。

モニターはコレクターからDUTのレスポンス情報を受け取り、レスポンスのチェックやカバレッジ計算を行います。また、レスポンスの情報をほかのコンポーネントに送信します。レスポンスの情報はトランザクションでやり取りします。

図1 UVMにおけるモニター

モニターの定義方法

ベースクラスとするuvm_monitorには、トランザクションを受け取るためのAnalysis exportと、トランザクションを送信するためのAnalysis portが定義されていません。したがって、ユーザーがAnalysis exportとAnalysis portを定義する必要があります。

今回は、まず基本的なモニター機能をもつmy_monitorを定義します。そして、my_monitorを継承して、カバレッジ計算機能を追加したmy_monitor_coverageを定義します。classの継承を利用して、このように機能追加することで、検証環境の再利用性が高まります。

my_monitor

それでは、ソースコードを見ながら、モニターの定義方法について解説します。

my_monitor.sv

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class my_monitor extends uvm_monitor;
 
    uvm_analysis_imp #(my_item, my_monitor) analysis_export;
    uvm_analysis_port #(my_item)            item_collected_port;
 
    `uvm_component_utils(my_monitor)
 
    /* Constructor */
    function new(string name, uvm_component parent);
        super.new(name, parent);
        analysis_export = new ("analysis_export", this);
        item_collected_port = new ("item_collected_port", this);
    endfunction
 
    /* Write() of analysis_export */
    virtual function void write(my_item data);
        $display("@%4t: a_in = %d, b_in = %d, mult_out = %d",
            $time, data.a_in, data.b_in, data.mult_out);
 
        item_collected_port.write(data);
    endfunction
 
endclass
  • 1行目:uvm_monitorを継承して、my_monitorを定義します。
  • 3行目:コレクターからトランザクションを受け取るためのAnalysis exportを定義します。
  • 4行目:他のコンポーネントにトランザクションを送信するためのAnalysis portを定義します。UVMのユーザーガイドの例に従い、ポートの名前をitem_collected_portとしています。
  • 8~13行目:コンストラクタを定義します。この中でanalysis_export, item_collected_portのインスタンスを作成します。
  • 15~21行目:write()メソッドを定義します。analysis_exportで接続したコレクターがwrite()を呼ぶと、ここで定義したwrite()が動作します。今回は、トランザクションの内容の表示と、トランザクションの送信を行います。一般的には、レスポンスのチェックを実装する場合もあります。

my_monitor_coverage

my_monitorにカバレッジ計算機能を追加します。

my_monitor_coverage.sv

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class my_monitor_coverage extends my_monitor;
 
    bit coverage_enable = 1'b1;
 
    /* Define cover group */
    covergroup cg with function sample(
        bit[`BW_A - 1:0] a_in,
        bit[`BW_B - 1:0] b_in
    );
        coverpoint a_in { bins a_value[] = { [1 : 200] };}
        coverpoint b_in { bins b_value[] = { [1 : 10] };}
    endgroup
 
    `uvm_component_utils_begin(my_monitor_coverage)
        `uvm_field_int(coverage_enable, UVM_DEFAULT)
    `uvm_component_utils_end
 
    /* Constructor */
    function new(string name, uvm_component parent);
        super.new(name, parent);
        cg = new;       /* Create an instance */
    endfunction
 
    /* Override write() */
    function void write(my_item data);
        super.write(data);
 
        if (coverage_enable) cg.sample(data.a_in, data.b_in);   /* Coverage collection */
    endfunction
 
endclass
  • 1行目:my_monitorを継承して、my_monitor_coverageを定義します。
  • 3行目:カバレッジ計算の有効・無効を制御するためフィールドを定義します。uvm_config_dbにより、トップモジュールなどから有効・無効を切り替えることができます。
  • 5~12行目:カバーグループを定義します。今回は、DUTへの入力a_in, b_inのカバレッジを計算します。入力値が取り得る値に従い、coverpointを定義します。入力値はmy_itemの中で次のように制約しています。
3
4
    constraint CA { (a_in >= 1) && (a_in <= 200); }
    constraint CB { (b_in >= 1) && (b_in <= 10); }
  • 14~16行目:UVMマクロとフィールドマクロを書きます。
  • 18~22行目:コンストラクタを定義します。この中でカバーグループのインスタンスを作成します。
  • 24~29行目:write()メソッドにカバレッジ計算を追加します。cg.sample(data.a_in, data.b_in)でカバレッジ計算が行われます。

カバレッジの確認方法

XilinxのVivado環境でのカバレッジ確認方法を説明します。なお、ここで説明する操作は、UVM環境構築&実行した後に行います。

シミュレーション終了後、Tcl Consoleで、下記を実行します。(MC_MULTは今回のプロジェクト名です。)

1
xcrg -report_format html -dir ./MC_MULT.sim/sim_1/behav/xsim/xsim.covdb

プロジェクトディレクトリ下に、xcrg_reportというディレクトリが生成されます。xcrg_report\groups.htmlをブラウザで表示することで、図2のようなカバレッジレポートが確認できます。

図2 カバレッジレポート

まとめ

今回は、モニターの定義方法について解説しました。シリーズを通してご覧いただけると、UVM検証環境が構築できるようになりますので、ぜひ他のコンポーネントの解説もご覧ください。

シリーズ目次はこちら

アバター画像
Writer
ジーノ。大手電機メーカーで、基板設計の全般と、FPGAの設計に従事した経験を活かし、FPGAについて情報発信中。
RTL設計、シミュレーション、タイミング・クロージャ、FPGAまわりのハードウェア開発まで、幅広く取り扱っております。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA