本文主要是介绍UVM Tutorial for Candy Lovers – 33. Defining do_print,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
When we implemented the “do” hooks before, we defined the convert2string
function, but we did not define our own do_print
function. This was because the convert2string
is very flexible and light weight as it does not require a so-called print policy that provides a print format. But if you define your own do_print
, you can enjoy pre-defined print formats immediately. You can also create your own formats. This article shows how.
Defining do_print
Defining do_print
itself is not very difficult. But before doing so, let’s look at the convert2string
function we defined before. As you see, the convert2string
function defines what variables to print and how.
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
Unlike convert2string
, usually do_print
does not define a print format by itself. Instead, it delegates the formatting to a print policy object (printer
). Below is our definition of do_print
. The uvm_printer
class provides an interface for printing uvm_object
s in various formats (line 1). In the do_print
function, we merely list the variables we want to print using the functions of uvm_printer
class (lines 3 to 8).
Strictly speaking, you can define the
do_print
without using theuvm_printer
, but if you do so, you are not able to use the printer formats defined in the subclasses ofuvm_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
Using do_print
The print
and sprint
functions of uvm_object
call the do_print
. Let’s call the sprint
in our jelly bean scoreboard. For convenience, UVM pre-defines three print policies (uvm_default_table_printer
, uvm_default_tree_printer
, and uvm_default_line_printer
; lines 5 to 7). If you do not specify a print policy, uvm_default_printer
, which is set to uvm_default_table_printer
by default, is used (line 4). For comparison, we call convert2string
on line 3, too.
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
Let’s see the each output. After running a simulation, you should see something like these:
Output of convert2string
This is our old friend. We see the output as specified in the function.
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
Output of sprint using uvm_default_printer
This is the output if we do not specify the print policy. As we mentioned before, the uvm_default_printer
is used, which is set to uvm_default_table_printer
by default.
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_GUMcolor string 3 RED sugar_free integral 1 'h1 sour integral 1 'h1 taste string 5 YUMMY
-----------------------------------------------------------------
Output of sprint using uvm_default_table_printer
This output is exactly same as the above.
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_GUMcolor string 3 RED sugar_free integral 1 'h1 sour integral 1 'h1 taste string 5 YUMMY
-----------------------------------------------------------------
Output of sprint using uvm_default_tree_printer
The uvm_default_tree_printer outputs the object in a tree form.
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
}
Output of sprint using uvm_default_line_printer
The uvm_default_line_printer
outputs the same information as the uvm_default_tree_printer
does, but in one line.
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 }
Defining our own print policy
If the pre-defined formats do not satisfy your needs, you can create your own print policy. As an example, we are going to create a policy that prints an uvm_object
in JSON format. Our goal is to print a jelly_bean_transaction
like this:
{"jb_tx": {"name": "jb_tx","flavor": "BUBBLE_GUM","color": "RED","sugar_free": "'h1","sour": "'h1","taste": "YUMMY"}
}
For those of you who are not familiar with JSON, please see this link.
To create your own print policy, you need to extend the uvm_printer
class and define the emit
function. The information to print is stored in an array (m_rows
) of uvm_printer_row_info
structure (line 16) which holds the name of variable, size, value, etc. Line 31 prints a name-value pair such as "flavor":"BUBBLE_GUM"
. I’m not going to explain the implementation line-by-line because most of the other lines deal with detail formatting. One note I have to mention, though, is that the printer settings are defined in knobs
(an object of uvm_printer_knobs
class). We use one of the settings (indent
; the number of spaces to use for level indentation) on line 18.
class json_printer extends uvm_printer;function new();super.new();endfunction: newvirtual function string emit();string s;string comma = "";string space = { 100 { " " } };string indent;int next_level;s = "{\n"; // begin JSONforeach ( m_rows[i] ) beginuvm_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 rownext_level = 0;end else begin // not last rownext_level = m_rows[ i + 1 ].level;if ( row.level < next_level ) begin // next level is deeprs = { s, "\"", row.name, "\": {\n" }; // begin nested JSON objectcomma = "";continue;endends = { s, "\"", row.name, "\": \"", row.val, "\"" }; // name-value paircomma = ",\n";if ( next_level < row.level ) begin // next level is shallowerfor ( int l = row.level; l > next_level; l-- ) beginindent = space.substr( 1, l * knobs.indent );s = { s, "\n", indent, "}" }; // end nested JSON objectendendend // foreach ( m_rows[i] )emit = { s, "\n}" }; // end JSONm_rows.delete();endfunction: emit
endclass: json_printer
To use the new print policy, we create it (line 6) and pass it when we call sprint
(line 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_phasefunction 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
You should see something like this when you run:
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"}
}
For your reference, these are the classes and struct we used in this article.
这篇关于UVM Tutorial for Candy Lovers – 33. Defining do_print的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!