URL
https://opencores.org/ocsvn/uart2bus_testbench/uart2bus_testbench/trunk
Subversion Repositories uart2bus_testbench
[/] [uart2bus_testbench/] [trunk/] [tb/] [uvm_src/] [base/] [uvm_printer.svh] - Rev 16
Compare with Previous | Blame | View Log
////------------------------------------------------------------------------------// Copyright 2007-2011 Mentor Graphics Corporation// Copyright 2007-2011 Cadence Design Systems, Inc.// Copyright 2010 Synopsys, Inc.// All Rights Reserved Worldwide//// Licensed under the Apache License, Version 2.0 (the// "License"); you may not use this file except in// compliance with the License. You may obtain a copy of// the License at//// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in// writing, software distributed under the License is// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR// CONDITIONS OF ANY KIND, either express or implied. See// the License or the specific language governing// permissions and limitations under the License.//------------------------------------------------------------------------------typedef class uvm_printer_knobs;parameter UVM_STDOUT = 1; // Writes to standard out and logfiletypedef struct {int level;string name;string type_name;string size;string val;} uvm_printer_row_info;//------------------------------------------------------------------------------//// Class: uvm_printer//// The uvm_printer class provides an interface for printing <uvm_objects> in// various formats. Subtypes of uvm_printer implement different print formats,// or policies.//// A user-defined printer format can be created, or one of the following four// built-in printers can be used://// - <uvm_printer> - provides base printer functionality; must be overridden.//// - <uvm_table_printer> - prints the object in a tabular form.//// - <uvm_tree_printer> - prints the object in a tree form.//// - <uvm_line_printer> - prints the information on a single line, but uses the// same object separators as the tree printer.//// Printers have knobs that you use to control what and how information is printed.// These knobs are contained in a separate knob class://// - <uvm_printer_knobs> - common printer settings//// For convenience, global instances of each printer type are available for// direct reference in your testbenches.//// - <uvm_default_tree_printer>// - <uvm_default_line_printer>// - <uvm_default_table_printer>// - <uvm_default_printer> (set to default_table_printer by default)//// When <uvm_object::print> and <uvm_object::sprint> are called without// specifying a printer, the <uvm_default_printer> is used.////------------------------------------------------------------------------------virtual class uvm_printer;// Variable: knobs//// The knob object provides access to the variety of knobs associated with a// specific printer instance.//uvm_printer_knobs knobs = new;// Group: Methods for printer usage// These functions are called from <uvm_object::print>, or they are called// directly on any data to get formatted printing.// Function: print_field//// Prints an integral field (up to 4096 bits).//// name - The name of the field.// value - The value of the field.// size - The number of bits of the field (maximum is 4096).// radix - The radix to use for printing. The printer knob for radix is used// if no radix is specified.// scope_separator - is used to find the leaf name since many printers only// print the leaf name of a field. Typical values for the separator// are . (dot) or [ (open bracket).extern virtual function void print_field (string name,uvm_bitstream_t value,int size,uvm_radix_enum radix=UVM_NORADIX,byte scope_separator=".",string type_name="");// backward compatibilityvirtual function void print_int (string name,uvm_bitstream_t value,int size,uvm_radix_enum radix=UVM_NORADIX,byte scope_separator=".",string type_name="");print_field (name, value, size, radix, scope_separator, type_name);endfunction// Function: print_field_int//// Prints an integral field (up to 64 bits).//// name - The name of the field.// value - The value of the field.// size - The number of bits of the field (maximum is 64).// radix - The radix to use for printing. The printer knob for radix is used// if no radix is specified.// scope_separator - is used to find the leaf name since many printers only// print the leaf name of a field. Typical values for the separator// are . (dot) or [ (open bracket).extern virtual function void print_field_int (string name,uvm_integral_t value,int size,uvm_radix_enum radix=UVM_NORADIX,byte scope_separator=".",string type_name="");// Function: print_object//// Prints an object. Whether the object is recursed depends on a variety of// knobs, such as the depth knob; if the current depth is at or below the// depth setting, then the object is not recursed.//// By default, the children of <uvm_components> are printed. To turn this// behavior off, you must set the <uvm_component::print_enabled> bit to 0 for// the specific children you do not want automatically printed.extern virtual function void print_object (string name,uvm_object value,byte scope_separator=".");extern virtual function void print_object_header (string name,uvm_object value,byte scope_separator=".");// Function: print_string//// Prints a string field.extern virtual function void print_string (string name,string value,byte scope_separator=".");// Function: print_time//// Prints a time value. name is the name of the field, and value is the// value to print.//// The print is subject to the ~$timeformat~ system task for formatting time// values.extern virtual function void print_time (string name,time value,byte scope_separator=".");// Function: print_real//// Prints a real field.extern virtual function void print_real (string name,real value,byte scope_separator=".");// Function: print_generic//// Prints a field having the given ~name~, ~type_name~, ~size~, and ~value~.extern virtual function void print_generic (string name,string type_name,int size,string value,byte scope_separator=".");// Group: Methods for printer subtyping// Function: emit//// Emits a string representing the contents of an object// in a format defined by an extension of this object.//extern virtual function string emit ();// Function: format_row//// Hook for producing custom output of a single field (row).//extern virtual function string format_row (uvm_printer_row_info row);// Function: format_header//// Hook to override base header with a custom header.virtual function string format_header();return "";endfunction// Function: format_footer//// Hook to override base footer with a custom footer.virtual function string format_footer();return "";endfunction// Function: adjust_name//// Prints a field's name, or ~id~, which is the full instance name.//// The intent of the separator is to mark where the leaf name starts if the// printer if configured to print only the leaf name of the identifier.extern virtual protected function string adjust_name (string id,byte scope_separator=".");// Function: print_array_header//// Prints the header of an array. This function is called before each// individual element is printed. <print_array_footer> is called to mark the// completion of array printing.extern virtual function void print_array_header(string name,int size,string arraytype="array",byte scope_separator=".");// Function: print_array_range//// Prints a range using ellipses for values. This method is used when honoring// the array knobs for partial printing of large arrays,// <uvm_printer_knobs::begin_elements> and <uvm_printer_knobs::end_elements>.//// This function should be called after begin_elements have been printed// and before end_elements have been printed.extern virtual function void print_array_range (int min, int max);// Function: print_array_footer//// Prints the header of a footer. This function marks the end of an array// print. Generally, there is no output associated with the array footer, but// this method let's the printer know that the array printing is complete.extern virtual function void print_array_footer (int size = 0);// Utility methodsextern function bit istop ();extern function string index_string (int index, string name="");protected bit m_array_stack[$];uvm_scope_stack m_scope = new;string m_string;// holds each cell entryprotected uvm_printer_row_info m_rows[$];endclass//------------------------------------------------------------------------------//// Class: uvm_table_printer//// The table printer prints output in a tabular format.//// The following shows sample output from the table printer.////| ---------------------------------------------------//| Name Type Size Value//| ---------------------------------------------------//| c1 container - @1013//| d1 mydata - @1022//| v1 integral 32 'hcb8f1c97//| e1 enum 32 THREE//| str string 2 hi//| value integral 12 'h2d//| ---------------------------------------------------////------------------------------------------------------------------------------class uvm_table_printer extends uvm_printer;// Variable: new//// Creates a new instance of ~uvm_table_printer~.//extern function new();// Function: emit//// Formats the collected information from prior calls to ~print_*~// into table format.//extern virtual function string emit();// Variables- m_max_*//// holds max size of each column, so table columns can be resized dynamicallyprotected int m_max_name;protected int m_max_type;protected int m_max_size;protected int m_max_value;extern function void calculate_max_widths();endclass//------------------------------------------------------------------------------//// Class: uvm_tree_printer//// By overriding various methods of the <uvm_printer> super class,// the tree printer prints output in a tree format.//// The following shows sample output from the tree printer.////| c1: (container@1013) {//| d1: (mydata@1022) {//| v1: 'hcb8f1c97//| e1: THREE//| str: hi//| }//| value: 'h2d//| }////------------------------------------------------------------------------------class uvm_tree_printer extends uvm_printer;string newline = "\n";// Variable: new//// Creates a new instance of ~uvm_tree_printer~.extern function new();// Function: emit//// Formats the collected information from prior calls to ~print_*~// into hierarchical tree format.//extern virtual function string emit();endclass//------------------------------------------------------------------------------//// Class: uvm_line_printer//// The line printer prints output in a line format.//// The following shows sample output from the line printer.////| c1: (container@1013) { d1: (mydata@1022) { v1: 'hcb8f1c97 e1: THREE str: hi } value: 'h2d }//------------------------------------------------------------------------------class uvm_line_printer extends uvm_tree_printer;// Variable: new//// Creates a new instance of ~uvm_line_printer~. It differs from the// <uvm_tree_printer> only in that the output contains no line-feeds// and indentation.function new();newline = " ";knobs.indent = 0;endfunctionendclass//------------------------------------------------------------------------------//// Class: uvm_printer_knobs//// The ~uvm_printer_knobs~ class defines the printer settings available to all// printer subtypes.////------------------------------------------------------------------------------class uvm_printer_knobs;// Variable: header//// Indicates whether the <uvm_printer::format_header> function should be called when// printing an object.bit header = 1;// Variable: footer//// Indicates whether the <uvm_printer::format_footer> function should be called when// printing an object.bit footer = 1;// Variable: full_name//// Indicates whether <uvm_printer::adjust_name> should print the full name of an identifier// or just the leaf name.bit full_name = 0;// Variable: identifier//// Indicates whether <uvm_printer::adjust_name> should print the identifier. This is useful// in cases where you just want the values of an object, but no identifiers.bit identifier = 1;// Variable: type_name//// Controls whether to print a field's type name.bit type_name = 1;// Variable: size//// Controls whether to print a field's size.bit size = 1;// Variable: depth//// Indicates how deep to recurse when printing objects.// A depth of -1 means to print everything.int depth = -1;// Variable: reference//// Controls whether to print a unique reference ID for object handles.// The behavior of this knob is simulator-dependent.bit reference = 1;// Variable: begin_elements//// Defines the number of elements at the head of a list to print.// Use -1 for no max.int begin_elements = 5;// Variable: end_elements//// This defines the number of elements at the end of a list that// should be printed.int end_elements = 5;// Variable: prefix//// Specifies the string prepended to each output linestring prefix = "";// Variable: indent//// This knob specifies the number of spaces to use for level indentation.// The default level indentation is two spaces.int indent = 2;// Variable: show_root//// This setting indicates whether or not the initial object that is printed// (when current depth is 0) prints the full path name. By default, the first// object is treated like all other objects and only the leaf name is printed.bit show_root = 0;// Variable: mcd//// This is a file descriptor, or multi-channel descriptor, that specifies// where the print output should be directed.//// By default, the output goes to the standard output of the simulator.int mcd = UVM_STDOUT;// Variable: separator//// For tree printers only, determines the opening and closing// separators used for nested objects.string separator = "{}";// Variable: show_radix//// Indicates whether the radix string ('h, and so on) should be prepended to// an integral value when one is printed.bit show_radix = 1;// Variable: default_radix//// This knob sets the default radix to use for integral values when no radix// enum is explicitly supplied to the <uvm_printer::print_field> or// <uvm_printer::print_field_int> methods.uvm_radix_enum default_radix = UVM_HEX;// Variable: dec_radix//// This string should be prepended to the value of an integral type when a// radix of <UVM_DEC> is used for the radix of the integral object.//// When a negative number is printed, the radix is not printed since only// signed decimal values can print as negative.string dec_radix = "'d";// Variable: bin_radix//// This string should be prepended to the value of an integral type when a// radix of <UVM_BIN> is used for the radix of the integral object.string bin_radix = "'b";// Variable: oct_radix//// This string should be prepended to the value of an integral type when a// radix of <UVM_OCT> is used for the radix of the integral object.string oct_radix = "'o";// Variable: unsigned_radix//// This is the string which should be prepended to the value of an integral// type when a radix of <UVM_UNSIGNED> is used for the radix of the integral// object.string unsigned_radix = "'d";// Variable: hex_radix//// This string should be prepended to the value of an integral type when a// radix of <UVM_HEX> is used for the radix of the integral object.string hex_radix = "'h";// Function: get_radix_str//// Converts the radix from an enumerated to a printable radix according to// the radix printing knobs (bin_radix, and so on).function string get_radix_str(uvm_radix_enum radix);if(show_radix == 0)return "";if(radix == UVM_NORADIX)radix = default_radix;case(radix)UVM_BIN: return bin_radix;UVM_OCT: return oct_radix;UVM_DEC: return dec_radix;UVM_HEX: return hex_radix;UVM_UNSIGNED: return unsigned_radix;default: return "";endcaseendfunction// Deprecated knobs, hereafter ignoredint max_width = 999;string truncation = "+";int name_width = -1;int type_width = -1;int size_width = -1;int value_width = -1;bit sprint = 1;endclasstypedef uvm_printer_knobs uvm_table_printer_knobs;typedef uvm_printer_knobs uvm_tree_printer_knobs;//------------------------------------------------------------------------------// IMPLEMENTATION//------------------------------------------------------------------------------// emit// ----function string uvm_printer::emit ();`uvm_error("NO_OVERRIDE","emit() method not overridden in printer subtype")return "";endfunction// format_row// ----------function string uvm_printer::format_row (uvm_printer_row_info row);return "";endfunction// print_array_header// ------------------function void uvm_printer::print_array_header (string name,int size,string arraytype="array",byte scope_separator=".");uvm_printer_row_info row_info;if(name != "")m_scope.set_arg(name);row_info.level = m_scope.depth();row_info.name = adjust_name(m_scope.get(),scope_separator);row_info.type_name = arraytype;row_info.size = $sformatf("%0d",size);row_info.val = "-";m_rows.push_back(row_info);m_scope.down(name);m_array_stack.push_back(1);endfunction// print_array_footer// ------------------function void uvm_printer::print_array_footer (int size=0);if(m_array_stack.size()) beginm_scope.up();void'(m_array_stack.pop_front());endendfunction// print_array_range// -----------------function void uvm_printer::print_array_range(int min, int max);string tmpstr;if(min == -1 && max == -1)return;if(min == -1)min = max;if(max == -1)max = min;if(max < min)return;print_generic("...", "...", -2, "...");endfunction// print_object_header// -------------------function void uvm_printer::print_object_header (string name,uvm_object value,byte scope_separator=".");uvm_printer_row_info row_info;uvm_component comp;if(name == "") beginif(value!=null) beginif((m_scope.depth()==0) && $cast(comp, value)) beginname = comp.get_full_name();endelse beginname=value.get_name();endendendif(name == "")name = "<unnamed>";m_scope.set_arg(name);row_info.level = m_scope.depth();if(row_info.level == 0 && knobs.show_root==1)row_info.name = value.get_full_name();elserow_info.name = adjust_name(m_scope.get(),scope_separator);row_info.type_name = (value != null) ? value.get_type_name() : "object";row_info.size = "-";row_info.val = knobs.reference ? uvm_object_value_str(value) : "-";m_rows.push_back(row_info);endfunction// print_object// ------------function void uvm_printer::print_object (string name, uvm_object value,byte scope_separator=".");uvm_component comp, child_comp;print_object_header(name,value,scope_separator);if(value != null) beginif((knobs.depth == -1 || (knobs.depth > m_scope.depth())) &&!value.__m_uvm_status_container.cycle_check.exists(value)) beginvalue.__m_uvm_status_container.cycle_check[value] = 1;if(name=="" && value!=null)m_scope.down(value.get_name());elsem_scope.down(name);//Handle children of the compif($cast(comp, value)) beginstring name;if (comp.get_first_child(name))do beginchild_comp = comp.get_child(name);if(child_comp.print_enabled)this.print_object("",child_comp);end while (comp.get_next_child(name));end// print members of objectvoid'(value.sprint(this));if(name != "" && name[0] == "[")m_scope.up("[");elsem_scope.up(".");value.__m_uvm_status_container.cycle_check.delete(value);endendendfunction// istop// -----function bit uvm_printer::istop ();return (m_scope.depth() == 0);endfunction// adjust_name// -----------function string uvm_printer::adjust_name(string id, byte scope_separator=".");if (knobs.show_root && m_scope.depth()==0 || knobs.full_name || id == "...")return id;return uvm_leaf_scope(id, scope_separator);endfunction// print_generic// -------------function void uvm_printer::print_generic (string name,string type_name,int size,string value,byte scope_separator=".");uvm_printer_row_info row_info;if (name != "" && name != "...") beginm_scope.set_arg(name);name = m_scope.get();endrow_info.level = m_scope.depth();row_info.name = adjust_name(name,scope_separator);row_info.type_name = type_name;row_info.size = (size == -2 ? "..." : $sformatf("%0d",size));row_info.val = (value == "" ? "\"\"" : value);m_rows.push_back(row_info);endfunction// print_field// ---------function void uvm_printer::print_field (string name,uvm_bitstream_t value,int size,uvm_radix_enum radix=UVM_NORADIX,byte scope_separator=".",string type_name="");uvm_printer_row_info row_info;string sz_str, val_str;if(name != "") beginm_scope.set_arg(name);name = m_scope.get();endif(type_name == "") beginif(radix == UVM_TIME)type_name ="time";else if(radix == UVM_STRING)type_name ="string";elsetype_name ="integral";endsz_str.itoa(size);if(radix == UVM_NORADIX)radix = knobs.default_radix;val_str = uvm_bitstream_to_string (value, size, radix,knobs.get_radix_str(radix));row_info.level = m_scope.depth();row_info.name = adjust_name(name,scope_separator);row_info.type_name = type_name;row_info.size = sz_str;row_info.val = val_str;m_rows.push_back(row_info);endfunction// print_field_int// ---------function void uvm_printer::print_field_int (string name,uvm_integral_t value,int size,uvm_radix_enum radix=UVM_NORADIX,byte scope_separator=".",string type_name="");uvm_printer_row_info row_info;string sz_str, val_str;if(name != "") beginm_scope.set_arg(name);name = m_scope.get();endif(type_name == "") beginif(radix == UVM_TIME)type_name ="time";else if(radix == UVM_STRING)type_name ="string";elsetype_name ="integral";endsz_str.itoa(size);if(radix == UVM_NORADIX)radix = knobs.default_radix;val_str = uvm_integral_to_string (value, size, radix,knobs.get_radix_str(radix));row_info.level = m_scope.depth();row_info.name = adjust_name(name,scope_separator);row_info.type_name = type_name;row_info.size = sz_str;row_info.val = val_str;m_rows.push_back(row_info);endfunction// print_time// ----------function void uvm_printer::print_time (string name,time value,byte scope_separator=".");print_field_int(name, value, 64, UVM_TIME, scope_separator);endfunction// print_string// ------------function void uvm_printer::print_string (string name,string value,byte scope_separator=".");uvm_printer_row_info row_info;if(name != "")m_scope.set_arg(name);row_info.level = m_scope.depth();row_info.name = adjust_name(m_scope.get(),scope_separator);row_info.type_name = "string";row_info.size = $sformatf("%0d",value.len());row_info.val = (value == "" ? "\"\"" : value);m_rows.push_back(row_info);endfunction// print_real// ----------function void uvm_printer::print_real (string name,real value,byte scope_separator=".");uvm_printer_row_info row_info;if (name != "" && name != "...") beginm_scope.set_arg(name);name = m_scope.get();endrow_info.level = m_scope.depth();row_info.name = adjust_name(m_scope.get(),scope_separator);row_info.type_name = "real";row_info.size = "64";row_info.val = $sformatf("%f",value);m_rows.push_back(row_info);endfunction// index_string// ------------function string uvm_printer::index_string(int index, string name="");index_string.itoa(index);index_string = { name, "[", index_string, "]" };endfunction//------------------------------------------------------------------------------// Class- uvm_table_printer//------------------------------------------------------------------------------// new// ---function uvm_table_printer::new();super.new();endfunction// calculate_max_widths// --------------------function void uvm_table_printer::calculate_max_widths();m_max_name=4;m_max_type=4;m_max_size = 4;m_max_value= 5;foreach(m_rows[j]) beginint name_len;uvm_printer_row_info row = m_rows[j];name_len = knobs.indent*row.level + row.name.len();if (name_len > m_max_name)m_max_name = name_len;if (row.type_name.len() > m_max_type)m_max_type = row.type_name.len();if (row.size.len() > m_max_size)m_max_size = row.size.len();if (row.val.len() > m_max_value)m_max_value = row.val.len();endendfunction// emit// ----function string uvm_table_printer::emit();string s;string user_format;static string dash; // = "---------------------------------------------------------------------------------------------------";static string space; //= " ";string dashes;string linefeed = {"\n", knobs.prefix};calculate_max_widths();beginint q[5];int m;int qq[$];q = '{m_max_name,m_max_type,m_max_size,m_max_value,100};qq = q.max;m = qq[0];if(dash.len()<m) begindash = {m{"-"}};space = {m{" "}};endendif (knobs.header) beginstring header;user_format = format_header();if (user_format == "") beginstring dash_id, dash_typ, dash_sz;string head_id, head_typ, head_sz;if (knobs.identifier) begindashes = {dash.substr(1,m_max_name+2)};header = {"Name",space.substr(1,m_max_name-2)};endif (knobs.type_name) begindashes = {dashes, dash.substr(1,m_max_type+2)};header = {header, "Type",space.substr(1,m_max_type-2)};endif (knobs.size) begindashes = {dashes, dash.substr(1,m_max_size+2)};header = {header, "Size",space.substr(1,m_max_size-2)};enddashes = {dashes, dash.substr(1,m_max_value), linefeed};header = {header, "Value", space.substr(1,m_max_value-5), linefeed};s = {s, dashes, header, dashes};endelse begins = {s, user_format, linefeed};endendforeach (m_rows[i]) beginuvm_printer_row_info row = m_rows[i];user_format = format_row(row);if (user_format == "") beginstring row_str;if (knobs.identifier)row_str = {space.substr(1,row.level * knobs.indent), row.name,space.substr(1,m_max_name-row.name.len()-(row.level*knobs.indent)+2)};if (knobs.type_name)row_str = {row_str, row.type_name, space.substr(1,m_max_type-row.type_name.len()+2)};if (knobs.size)row_str = {row_str, row.size, space.substr(1,m_max_size-row.size.len()+2)};s = {s, row_str, row.val, space.substr(1,m_max_value-row.val.len()), linefeed};endelses = {s, user_format, linefeed};endif (knobs.footer) beginuser_format = format_footer();if (user_format == "")s = {s, dashes};elses = {s, user_format, linefeed};endemit = {knobs.prefix, s};m_rows.delete();endfunction//------------------------------------------------------------------------------// Class- uvm_tree_printer//------------------------------------------------------------------------------// new// ---function uvm_tree_printer::new();super.new();knobs.size = 0;knobs.type_name = 0;knobs.header = 0;knobs.footer = 0;endfunction// emit// ----function string uvm_tree_printer::emit();string s = knobs.prefix;string space= " ";string user_format;string linefeed = newline == "" || newline == " " ? newline : {newline, knobs.prefix};// Headerif (knobs.header) beginuser_format = format_header();if (user_format != "")s = {s, user_format, linefeed};endforeach (m_rows[i]) beginuvm_printer_row_info row = m_rows[i];user_format = format_row(row);if (user_format == "") beginstring indent_str;indent_str = space.substr(1,row.level * knobs.indent);// Name (id)if (knobs.identifier) begins = {s,indent_str, row.name};if (row.name != "" && row.name != "...")s = {s, ": "};end// Type Nameif (row.val[0] == "@") // is an object w/ knobs.reference ons = {s,"(",row.type_name,row.val,") "};elseif (knobs.type_name &&(row.type_name != "" ||row.type_name != "-" ||row.type_name != "..."))s = {s,"(",row.type_name,") "};// Sizeif (knobs.size) beginif (row.size != "" || row.size != "-")s = {s,"(",row.size,") "};endif (i < m_rows.size()-1) beginif (m_rows[i+1].level > row.level) begins = {s, string'(knobs.separator[0]), linefeed};continue;endend// Value (unconditional)s = {s, row.val, " ", linefeed};// Scope handling...if (i <= m_rows.size()-1) beginint end_level;if (i == m_rows.size()-1)end_level = 0;elseend_level = m_rows[i+1].level;if (end_level < row.level) beginstring indent_str;for (int l=row.level-1; l >= end_level; l--) beginindent_str = space.substr(1,l * knobs.indent);s = {s, indent_str, string'(knobs.separator[1]), linefeed};endendendendelses = {s, user_format};end// Footerif (knobs.footer) beginuser_format = format_footer();if (user_format != "")s = {s, user_format, linefeed};endif (newline == "" || newline == " ")s = {s, "\n"};emit = s;m_rows.delete();endfunction
