UVM糖果爱好者教程 - 32.定义do_print

当我们之前实现“do”钩子时,我们定义了convert2string函数,但是我们没有定义我们自己的do_print函数。这是因为convert2string非常灵活且重量轻,因为它不需要提供打印格式的所谓打印策略。但是如果您定义了自己的do_print,则可以立即享受预定义的打印格式。您也可以创建自己的格式。本文展示了如何使用do_print。

定义do_print

定义do_print本身并不是很困难。但在这之前,我们先看看我们之前定义的convert2string函数。如您所见,convert2string函数定义了要打印的变量以及如何操作。

class jelly_bean_transaction extends uvm_sequence_item;
   virtual function string convert2string();
      string s = super.convert2string();
      s = { s, $psprintf( "\nname      : %s", get_name()    ) };
      s = { s, $psprintf( "\nflavor    : %s", flavor.name() ) };
      s = { s, $psprintf( "\ncolor     : %s", color.name()  ) };
      s = { s, $psprintf( "\nsugar_free: %b", sugar_free    ) };
      s = { s, $psprintf( "\nsour      : %b", sour          ) };
      s = { s, $psprintf( "\ntaste     : %s", taste.name()  ) };
      return s;
   endfunction: convert2string
   // ...
endclass: jelly_bean_transaction
与convert2string不同,通常do_print本身并不定义打印格式。相反,它会将格式委托给打印策略对象(printer)。以下是我们对do_print的定义。 uvm_printer类提供了以各种格式打印uvm_objects的接口(第1行)。在do_print函数中,我们仅使用uvm_printer类的函数(第3到第8行)列出要打印的变量。

严格地说,您可以在不使用uvm_printer的情况下定义do_print,但如果这样做,则无法使用uvm_printer的子类中定义的打印机格式。

   virtual function void do_print( uvm_printer printer );
      super.do_print( printer );
      printer.print_string( "name",   get_name() );
      printer.print_string( "flavor", flavor.name() );
      printer.print_string( "color",  color.name() );
      printer.print_field_int( "sugar_free", sugar_free, .size( 1 ) );
      printer.print_field_int( "sour",       sour,       .size( 1 ) );
      printer.print_string( "taste",  taste.name() );
   endfunction: do_print

使用do_print

uvm_object的print和sprint函数调用do_print。让我们在我们的果冻豆记分板中调用sprint。为方便起见,UVM预先定义了三个打印策略(uvm_default_table_printer,uvm_default_tree_printer和uvm_default_line_printer;第5至7行)。如果您未指定打印策略,则会使用默认设置为uvm_default_table_printer的uvm_default_printer(第4行)。为了比较,我们也在第3行调用convert2string。

class jelly_bean_sb_subscriber extends uvm_subscriber#( jelly_bean_transaction );
  function void write( jelly_bean_transaction t );
    `uvm_info( get_name(), { "using convert2string",              t.convert2string() }, UVM_LOW )
    `uvm_info( get_name(), { "using uvm_default_printer\n",       t.sprint() }, UVM_LOW ) // use uvm_default_printer
    `uvm_info( get_name(), { "using uvm_default_table_printer\n", t.sprint( uvm_default_table_printer ) }, UVM_LOW )
    `uvm_info( get_name(), { "using uvm_default_tree_printer\n",  t.sprint( uvm_default_tree_printer  ) }, UVM_LOW )
    `uvm_info( get_name(), { "using uvm_default_line_printer\n",  t.sprint( uvm_default_line_printer  ) }, UVM_LOW )
  endfunction: write
  // ...
endclass: jelly_bean_sb_subscriber
让我们看看每个输出。运行仿真之后,您应该看到如下所示的内容:

convert2string的输出

这是我们的老朋友。我们看到在该函数中指定的输出。

UVM_INFO env.svh(134) @ 185: uvm_test_top.jb_env.jb_sb [jb_sb] using convert2string
name      : jb_tx
flavor    : BUBBLE_GUM
color     : RED
sugar_free: 1
sour      : 1
taste     : YUMMY

使用uvm_default_printer输出

如果我们不指定打印策略,这是输出。正如我们前面提到的那样,使用了uvm_default_printer,默认情况下它被设置为uvm_default_table_printer。

UVM_INFO env.svh(136) @ 185: uvm_test_top.jb_env.jb_sb [jb_sb] using uvm_default_printer
-----------------------------------------------------------------
Name          Type                               Size  Value     
-----------------------------------------------------------------
jb_tx         sugar_free_jelly_bean_transaction  -     @861      
  name        string                             5     jb_tx     
  flavor      string                             10    BUBBLE_GUM
  color       string                             3     RED       
  sugar_free  integral                           1     'h1       
  sour        integral                           1     'h1       
  taste       string                             5     YUMMY     
-----------------------------------------------------------------

使用uvm_default_table_printer输出

该输出与上述完全相同。

UVM_INFO env.svh(138) @ 185: uvm_test_top.jb_env.jb_sb [jb_sb] using uvm_default_table_printer
-----------------------------------------------------------------
Name          Type                               Size  Value     
-----------------------------------------------------------------
jb_tx         sugar_free_jelly_bean_transaction  -     @861      
  name        string                             5     jb_tx     
  flavor      string                             10    BUBBLE_GUM
  color       string                             3     RED       
  sugar_free  integral                           1     'h1       
  sour        integral                           1     'h1       
  taste       string                             5     YUMMY     
-----------------------------------------------------------------

使用uvm_default_tree_printer输出

uvm_default_tree_printer以树形式输出对象。

UVM_INFO env.svh(140) @ 185: uvm_test_top.jb_env.jb_sb [jb_sb] using uvm_default_tree_printer
jb_tx: (sugar_free_jelly_bean_transaction@861) {
  name: jb_tx 
  flavor: BUBBLE_GUM 
  color: RED 
  sugar_free: 'h1 
  sour: 'h1 
  taste: YUMMY 
}

使用uvm_default_line_printer输出

uvm_default_line_printer输出与uvm_default_tree_printer相同的信息,但在一行中。

UVM_INFO env.svh(142) @ 185: uvm_test_top.jb_env.jb_sb [jb_sb] using uvm_default_line_printer
jb_tx: (sugar_free_jelly_bean_transaction@861) { name: jb_tx  flavor: BUBBLE_GUM  color: RED  sugar_free: 'h1  sour: 'h1  taste: YUMMY  }

定义我们自己的打印策略

如果预定义的格式不能满足您的需求,您可以创建自己的打印策略。作为一个例子,我们将创建一个打印JSON格式的uvm_object的策略。我们的目标是打印一个像这样的jelly_bean_transaction:

{
  "jb_tx": {
    "name": "jb_tx",
    "flavor": "BUBBLE_GUM",
    "color": "RED",
    "sugar_free": "'h1",
    "sour": "'h1",
    "taste": "YUMMY"
  }
}

对于那些不熟悉JSON的人,请看这个链接

要创建您自己的打印策略,您需要扩展uvm_printer类并定义emit函数。要打印的信息存储在保存变量名称,大小,值等的uvm_printer_row_info结构(第16行)的数组(m_​​rows)中。第31行打印名称 - 值对,如“flavor”:“BUBBLE_GUM”。我不会逐行解释实现,因为大多数其他行处理细节格式。我必须提到的一点是,printer设置是在knobs中定义的(uvm_printer_knobs类的一个对象)。我们使用第18行的其中一个设置(缩进;用定义缩进的空格数量)。

class json_printer extends uvm_printer;
   function new();
      super.new();
   endfunction: new
 
   virtual function string emit();
      string s;
      string comma = "";
      string space = { 100 { " " } };
      string indent;
      int    next_level;
 
      s = "{\n"; // begin JSON
 
      foreach ( m_rows[i] ) begin
         uvm_printer_row_info row = m_rows[i];
 
         indent = space.substr( 1, ( row.level + 1 ) * knobs.indent );
         s = { s, comma, indent };
 
         if ( i == m_rows.size() - 1 ) begin // last row
            next_level = 0;
         end else begin // not last row
            next_level = m_rows[ i + 1 ].level;
            if ( row.level < next_level ) begin // next level is deepr
               s = { s, "\"", row.name, "\": {\n" }; // begin nested JSON object
               comma = "";
               continue;
            end
         end
         s = { s, "\"", row.name, "\": \"", row.val, "\"" }; // name-value pair
         comma = ",\n";
 
         if ( next_level < row.level ) begin // next level is shallower
            for ( int l = row.level; l > next_level; l-- ) begin
               indent = space.substr( 1, l * knobs.indent );
               s = { s, "\n", indent, "}" }; // end nested JSON object
            end
         end
      end // foreach ( m_rows[i] )
 
      emit = { s, "\n}" }; // end JSON
      m_rows.delete();
   endfunction: emit
endclass: json_printer

要使用新的打印策略,我们创建它(第6行),并在我们称为sprint(第10行)时传递它。

class jelly_bean_sb_subscriber extends uvm_subscriber#( jelly_bean_transaction );
  json_printer json_p;
 
  virtual function void build_phase( uvm_phase phase );
    super.build_phase( phase );
    json_p = new;
  endfunction: build_phase
 
  function void write( jelly_bean_transaction t );
    `uvm_info( get_name(), { "using json_printer\n", t.sprint( json_p ) }, UVM_LOW )
  endfunction: write
  // ...
endclass: jelly_bean_sb_subscriber

运行时应该会看到类似这样的内容:

UVM_INFO env.svh(144) @ 185: uvm_test_top.jb_env.jb_sb [jb_sb] using json_printer
{
  "jb_tx": {
    "name": "jb_tx",
    "flavor": "BUBBLE_GUM",
    "color": "RED",
    "sugar_free": "'h1",
    "sour": "'h1",
    "taste": "YUMMY"
  }
}

为了您的参考,这些是我们在本文中使用的类和结构。


                                                               UVM printer类 


您可以在EDA Playground上查看并运行代码。

猜你喜欢

转载自blog.csdn.net/zhajio/article/details/80842553