UVMのデフォルト結果サマリー表示
UVMを使うとシミュレーションの最後にどんなメッセージが何回表示されたかとか、UVM_INFO/WARNING/ERROR/FATALがそれぞれいくつであったかなどの統計サマリー情報が表示される。
こんな感じに。
...
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()の中身を見ると以下の様になっている。
// 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()での設定でもよい。
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
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
この様に表示されるようになる。
...
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
これを使うと表示サマリーは以下のようになる。
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に入れた。
`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
`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
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
是非ご自身の環境で実行してみていろいろいじってみてお好みのフォーマットで表示するようにしてみてください。