0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

UVMの結果サマリー表示のカスタマイズ

0
Last updated at Posted at 2026-03-21

UVMのデフォルト結果サマリー表示

UVMを使うとシミュレーションの最後にどんなメッセージが何回表示されたかとか、UVM_INFO/WARNING/ERROR/FATALがそれぞれいくつであったかなどの統計サマリー情報が表示される。
こんな感じに。

log
...
UVM_INFO uvm_report_server.svh(847) @ 0: reporter [UVM/REPORT/SERVER] 
--- UVM Report Summary ---

** Report counts by severity
UVM_INFO :    6
UVM_WARNING :    2
UVM_ERROR :    1
UVM_FATAL :    0
** Report counts by id
[RNTST]     1
[UVM/RELNOTES]     1
[build]     2
[end_of_elaboration]     1
[run]     3
[start_of_simulation]     1

しかし、デフォルト表示が気に入らなくて変えたくなる事がある。その場合には自分好みにカスタマイズする事が可能。

以下の記事では、`uvm_info/warning/error/fatalで表示されるメッセージプリンティングをカスタマイズする方法が紹介されている。メッセージ表示はuvm_default_report_serverと言うUVMクラスのcompose_report_message()と言うfunctionが行う。なのでそれをoverrideしてカスタマイズしている。

サマリー表示はuvm_default_report_serverのreport_summarize()と言うfunctionが行っている。なので、同様にそれをoverrideすればサマリ表示のカスタマイズもできる。
report_summarize()の中身を見ると以下の様になっている。

uvm_default_report_server::report_sumarize()
  // Function: report_summarize
  //
  // Outputs statistical information on the reports issued by this central report
  // server. This information will be sent to the command line if ~file~ is 0, or
  // to the file descriptor ~file~ if it is not 0.
  //
  // The <run_test> method in uvm_top calls this method.

  virtual function void report_summarize(UVM_FILE file = 0);
    string id;
    string name;
    string output_str;
    string q[$];

    uvm_report_catcher::summarize();
    q.push_back("\n--- UVM Report Summary ---\n\n");

    if(m_max_quit_count != 0) begin
      if ( m_quit_count >= m_max_quit_count )
        q.push_back("Quit count reached!\n");
      q.push_back($sformatf("Quit count : %5d of %5d\n",m_quit_count, m_max_quit_count));
    end

    q.push_back("** Report counts by severity\n");
    foreach(m_severity_count[s]) begin
      q.push_back($sformatf("%s :%5d\n", s.name(), m_severity_count[s]));
    end

    if (enable_report_id_count_summary) begin
      q.push_back("** Report counts by id\n");
      foreach(m_id_count[id])
        q.push_back($sformatf("[%s] %5d\n", id, m_id_count[id]));
    end

    `uvm_info("UVM/REPORT/SERVER",`UVM_STRING_QUEUE_STREAMING_PACK(q),UVM_LOW)
  endfunction

ID毎のカウント表示を止める

テストベンチの規模が大きくなってきたり、或いはシーケンスやトランザクション毎に違うIDのメッセージログを表示をさせたりして、IDの種類が多くなってくると、サマリー表示の中でも特にID毎のカウントレポートが長くなってうざくなって来る。
uvm_default_report_server::report_summarize()を見るとenable_report_id_count_summaryと言うフラグがあり、それを表示させない為の仕組みが既に用意されている事が分かる。

なのでID事のカウント集計を止めるだけであればUVMデフォルトのレポートサーバにdenable_report_id_count_summary = 0を設定して使うだけで良い。
設定す場所はtb module内のrun_test()の前でも、test classのnew()やbuild_phase()等でも良い。最後に表示する内容の制御なのでreport_phase()やfinal_phase()での設定でもよい。

tb内で設定の例
module tb;
  ...
  initial begin
    uvm_pkg::uvm_default_report_server rs;
    rs = new("my_report_server");
    rs.enable_report_id_count_summary = 0;
    uvm_pkg::uvm_report_server::set_server(rs);
    uvm_pkg::run_test();
  end

endmodule
test class内で設定の例
class my_test extends uvm_test;

  `uvm_component_utils(my_test)

  virtual function void set_report_server();
    uvm_default_report_server rs;
    rs = new("my_report_server");
    rs.enable_report_id_count_summary = 0;
    uvm_report_server::set_server(rs);
  endfunction

  function new(string name, uvm_component parent);
    super.new(name, parent);
    this.set_report_server();
  endfunction

  virtual function void build_phase(uvm_phase phase);
  //this.set_report_server();
    super.build_phase(phase);
    ... 
  endfunction

  virtual function void final_phase(uvm_phase phase);
  //this.set_report_server();
    super.final_phase(phase);
    ... 
  endfunction

endclass

この様に表示されるようになる。

log
...
UVM_INFO uvm_report_server.svh(847) @ 0: reporter [UVM/REPORT/SERVER] 
--- UVM Report Summary ---

** Report counts by severity
UVM_INFO :    6
UVM_WARNING :    2
UVM_ERROR :    1
UVM_FATAL :    0

サマリー表示を自由にカスタマイズ

IDカウント集計だけでなくサマリー表示フォーマット自体を変えたい場合はuvm_default_report_serverを継承してreport_summarize()をoverrideして独自のカスタムレポートサーバを作る必要がある。
以下、その例。

virtual function void report_summarize(UVM_FILE file = 0);
  //string output_str;
    string q[$];

  //uvm_report_catcher::summarize();

    q.push_back("\n------------- UVM Report Summary -------------\n");

    if(this.get_max_quit_count() != 0) begin
        if (this.is_quit_count_reached()) //if ( get_quit_count() >= get_max_quit_count() )
            q.push_back("Quit count reached!\n");
        q.push_back($sformatf("Quit count : %5d of %5d\n", this.get_quit_count(),  this.get_max_quit_count()));
    end

  //string name;
  //q.push_back("** Report counts by severity\n");
  //foreach(m_severity_count[s])
  //    q.push_back($sformatf("%s :%5d\n", s.name(), m_severity_count[s]));
    //################# CUSTOM SUMMARY CONTENT START #################
    q.push_back($sformatf("   TEST NAME   : [%s]\n", uvm_pkg::uvm_top.find("uvm_test_top").get_type_name()));
    q.push_back($sformatf("  %s :%5d\n", "UVM_INFO   ", get_severity_count(UVM_INFO)));
    q.push_back($sformatf("  %s :%5d\n", "UVM_WARNING", get_severity_count(UVM_WARNING)));
    q.push_back($sformatf("  %s :%5d\n", "UVM_ERROR  ", get_severity_count(UVM_ERROR)));
    q.push_back($sformatf("  %s :%5d\n", "UVM_FATAL  ", get_severity_count(UVM_FATAL)));
    //#################################################################

  //if (enable_report_id_count_summary) begin
  //    q.push_back("** Report counts by id\n");
  //    foreach(m_id_count[id])
  //        q.push_back($sformatf("[%s] %5d\n", id, m_id_count[id]));
  //end

    q.push_back("----------------------------------------------");

    `uvm_info("UVM/REPORT/SERVER",`UVM_STRING_QUEUE_STREAMING_PACK(q),UVM_LOW)

endfunction

これを使うと表示サマリーは以下のようになる。

log
UVM_INFO tb.sv(  80) @ 0: reporter [UVM/REPORT/SERVER] 
------------- UVM Report Summary -------------
  TEST NAME   : [my_test]
  UVM_INFO    :    6
  UVM_WARNING :    2
  UVM_ERROR   :    1
  UVM_FATAL   :    0
----------------------------------------------

大分すっきりしたし、何のテストが実行されたのかを分かり易くするためにuvm_pkg::uvm_top.find("uvm_test_top").get_type_name()を使ってテスト名も表示するようにしてみた。

元のuvm_default_report_serverではm_max_quit_countおよびm_quit_countはlocalで宣言されている。

class uvm_default_report_server extends uvm_report_server;

  local int m_quit_count;
  local int m_max_quit_count;
  bit max_quit_overridable = 1;
  local int m_severity_count[uvm_severity];

なのでその派生クラスからはこれらは参照できない。したがってこの例では代わりに以下の公開されている関数を使った。

  // Function: set_max_quit_count
  //
  // Get or set the maximum number of COUNT actions that can be tolerated
  // before a UVM_EXIT action is taken. The default is 0, which specifies
  // no maximum.

  function void set_max_quit_count(int count, bit overridable = 1);
    if (max_quit_overridable == 0) begin
      uvm_report_info("NOMAXQUITOVR", 
        $sformatf("The max quit count setting of %0d is not overridable to %0d due to a previous setting.", 
        m_max_quit_count, count), UVM_NONE);
      return;
    end
    max_quit_overridable = overridable;
    m_max_quit_count = count < 0 ? 0 : count;
  endfunction
  // Function: is_quit_count_reached
  //
  // If is_quit_count_reached returns 1, then the quit counter has reached
  // the maximum.

  function bit is_quit_count_reached();
    return (m_quit_count >= m_max_quit_count);
  endfunction

m_severity_countもlocalでアクセスできないのでUVM_INFO/WARNING/ERROR/FATALを個別に書き出したのとget_severity_count()でそれぞれのカウント数を取得するようにした。

  // Function: get_severity_count

  function int get_severity_count(uvm_severity severity);
    return m_severity_count[severity];
  endfunction

サンプルコード

以下に動作可能な全体のサンプルコードを示す。
この例ではdefault report serverでid毎の集計を止める設定をしたset_default_report_server()と言う関数とカスタムのreport serverを設定するset_custom_report_server()と言う関数を作り、my_pkgと言うpackageに入れた。

my_pkg.sv
`include "uvm_macros.svh"

package my_pkg;
    import uvm_pkg::*;

    class custom_report_server extends uvm_default_report_server;

        virtual function void report_summarize(UVM_FILE file = 0);
            string q[$];

          //uvm_report_catcher::summarize();

            q.push_back("\n------------- UVM Report Summary -------------\n");

            if(this.get_max_quit_count() != 0) begin
                if (this.is_quit_count_reached()) //if ( get_quit_count() >= get_max_quit_count() )
                    q.push_back("Quit count reached!\n");
                q.push_back($sformatf("Quit count : %5d of %5d\n", this.get_quit_count(),  this.get_max_quit_count()));
            end

          //string name;
          //q.push_back("** Report counts by severity\n");
          //foreach(m_severity_count[s])
          //    q.push_back($sformatf("%s :%5d\n", s.name(), m_severity_count[s]));
            q.push_back($sformatf("   TEST NAME   : [%s]\n", uvm_pkg::uvm_top.find("uvm_test_top").get_type_name()));
            q.push_back($sformatf("** %s :%5d\n", "UVM_INFO   ", get_severity_count(UVM_INFO)));
            q.push_back($sformatf("** %s :%5d\n", "UVM_WARNING", get_severity_count(UVM_WARNING)));
            q.push_back($sformatf("** %s :%5d\n", "UVM_ERROR  ", get_severity_count(UVM_ERROR)));
            q.push_back($sformatf("** %s :%5d\n", "UVM_FATAL  ", get_severity_count(UVM_FATAL)));

          //if (enable_report_id_count_summary) begin
          //    q.push_back("** Report counts by id\n");
          //    foreach(m_id_count[id])
          //        q.push_back($sformatf("[%s] %5d\n", id, m_id_count[id]));
          //end

            q.push_back("----------------------------------------------");

            `uvm_info("UVM/REPORT/SERVER", `UVM_STRING_QUEUE_STREAMING_PACK(q), UVM_LOW)

        endfunction

    endclass

    //##### Default Report Server #####
    function void set_default_report_server(bit id_count_summary = 0);
        uvm_default_report_server def_rs;
        def_rs = new();
        def_rs.enable_report_id_count_summary = id_count_summary;
        uvm_report_server::set_server(def_rs);
    endfunction

    //##### Custom Report Server #####
    function void set_custom_report_server();
        custom_report_server my_rs;
        my_rs = new();
        uvm_report_server::set_server(my_rs);
    endfunction

endpackage : my_pkg
test_pkg.sv
`include "uvm_macros.svh"

package test_pkg;
    import uvm_pkg::*;

    class my_test extends uvm_test;

        function new(string name, uvm_component parent);
            super.new(name, parent);
          //my_pkg::set_default_report_server(0);
          //my_pkg::set_my_report_server();
        endfunction

        `uvm_component_utils(my_test)

        virtual function void build_phase(uvm_phase phase);
            `uvm_info   (phase.get_name(), "Test build phase executed", UVM_MEDIUM)
            `uvm_warning(phase.get_name(), "Test build phase executed")
        endfunction

        virtual function void end_of_elaboration_phase(uvm_phase phase);
            `uvm_info(phase.get_name(), "Test end_of_elaboration phase executed", UVM_MEDIUM)
        endfunction
            
        virtual function void start_of_simulation_phase(uvm_phase phase);
            `uvm_info(phase.get_name(), "Test start_of_simulation phase executed", UVM_MEDIUM)
        endfunction

        virtual task run_phase(uvm_phase phase);
            `uvm_info   (phase.get_name(), "Test run phase executed", UVM_MEDIUM)
            `uvm_warning(phase.get_name(), "Test run phase executed")
            `uvm_error  (phase.get_name(), "Test run phase executed")
        endtask

    endclass

endpackage : test_pkg
tb.sv
module tb;
    import uvm_pkg::*;
    import test_pkg::*;

    initial begin
      //my_pkg::set_default_report_server(0);
        my_pkg::set_custom_report_server();
        uvm_pkg::run_test("my_test");
    end

endmodule

是非ご自身の環境で実行してみていろいろいじってみてお好みのフォーマットで表示するようにしてみてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?