| // |
| //------------------------------------------------------------------------------ |
| // Copyright 2007-2010 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 for the specific language governing |
| // permissions and limitations under the License. |
| //------------------------------------------------------------------------------ |
| |
| `ifndef UVM_REPORT_SERVER_SVH |
| `define UVM_REPORT_SERVER_SVH |
| |
| typedef class uvm_report_object; |
| |
| //------------------------------------------------------------------------------ |
| // |
| // CLASS: uvm_report_server |
| // |
| // uvm_report_server is a global server that processes all of the reports |
| // generated by an uvm_report_handler. None of its methods are intended to be |
| // called by normal testbench code, although in some circumstances the virtual |
| // methods process_report and/or compose_uvm_info may be overloaded in a |
| // subclass. |
| // |
| //------------------------------------------------------------------------------ |
| |
| typedef class uvm_report_catcher; |
| class uvm_report_server extends uvm_object; |
| |
| local int max_quit_count; |
| local int quit_count; |
| local int severity_count[uvm_severity]; |
| |
| // Needed for callbacks |
| function string get_type_name(); |
| return "uvm_report_server"; |
| endfunction |
| |
| // Variable: id_count |
| // |
| // An associative array holding the number of occurences |
| // for each unique report ID. |
| |
| protected int id_count[string]; |
| |
| bit enable_report_id_count_summary=1; |
| |
| |
| // Function: new |
| // |
| // Creates an instance of the class. |
| |
| function new(); |
| set_name("uvm_report_server"); |
| set_max_quit_count(0); |
| reset_quit_count(); |
| reset_severity_counts(); |
| endfunction |
| |
| |
| static protected uvm_report_server m_global_report_server = get_server(); |
| |
| // Function: set_server |
| // |
| // Sets the global report server to use for reporting. The report |
| // server is responsible for formatting messages. |
| |
| static function void set_server(uvm_report_server server); |
| if(m_global_report_server != null) begin |
| server.set_max_quit_count(m_global_report_server.get_max_quit_count()); |
| server.set_quit_count(m_global_report_server.get_quit_count()); |
| m_global_report_server.copy_severity_counts(server); |
| m_global_report_server.copy_id_counts(server); |
| end |
| |
| m_global_report_server = server; |
| endfunction |
| |
| |
| // Function: get_server |
| // |
| // Gets the global report server. The method will always return |
| // a valid handle to a report server. |
| |
| static function uvm_report_server get_server(); |
| if (m_global_report_server == null) |
| m_global_report_server = new; |
| return m_global_report_server; |
| endfunction |
| |
| local bit m_max_quit_overridable = 1; |
| |
| // Function: set_max_quit_count |
| |
| function void set_max_quit_count(int count, bit overridable = 1); |
| if (m_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.", max_quit_count, count), UVM_NONE); |
| return; |
| end |
| m_max_quit_overridable = overridable; |
| max_quit_count = count < 0 ? 0 : count; |
| endfunction |
| |
| // Function: get_max_quit_count |
| // |
| // Get or set the maximum number of COUNT actions that can be tolerated |
| // before an UVM_EXIT action is taken. The default is 0, which specifies |
| // no maximum. |
| |
| function int get_max_quit_count(); |
| return max_quit_count; |
| endfunction |
| |
| |
| // Function: set_quit_count |
| |
| function void set_quit_count(int quit_count); |
| quit_count = quit_count < 0 ? 0 : quit_count; |
| endfunction |
| |
| // Function: get_quit_count |
| |
| function int get_quit_count(); |
| return quit_count; |
| endfunction |
| |
| // Function: incr_quit_count |
| |
| function void incr_quit_count(); |
| quit_count++; |
| endfunction |
| |
| // Function: reset_quit_count |
| // |
| // Set, get, increment, or reset to 0 the quit count, i.e., the number of |
| // COUNT actions issued. |
| |
| function void reset_quit_count(); |
| quit_count = 0; |
| 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 (quit_count >= max_quit_count); |
| endfunction |
| |
| |
| // Function: set_severity_count |
| |
| function void set_severity_count(uvm_severity severity, int count); |
| severity_count[severity] = count < 0 ? 0 : count; |
| endfunction |
| |
| // Function: get_severity_count |
| |
| function int get_severity_count(uvm_severity severity); |
| return severity_count[severity]; |
| endfunction |
| |
| // Function: incr_severity_count |
| |
| function void incr_severity_count(uvm_severity severity); |
| severity_count[severity]++; |
| endfunction |
| |
| // Function: reset_severity_counts |
| // |
| // Set, get, or increment the counter for the given severity, or reset |
| // all severity counters to 0. |
| |
| function void reset_severity_counts(); |
| uvm_severity_type s; |
| s = s.first(); |
| forever begin |
| severity_count[s] = 0; |
| if(s == s.last()) break; |
| s = s.next(); |
| end |
| endfunction |
| |
| |
| // Function: set_id_count |
| |
| function void set_id_count(string id, int count); |
| id_count[id] = count < 0 ? 0 : count; |
| endfunction |
| |
| // Function: get_id_count |
| |
| function int get_id_count(string id); |
| if(id_count.exists(id)) |
| return id_count[id]; |
| return 0; |
| endfunction |
| |
| // Function: incr_id_count |
| // |
| // Set, get, or increment the counter for reports with the given id. |
| |
| function void incr_id_count(string id); |
| if(id_count.exists(id)) |
| id_count[id]++; |
| else |
| id_count[id] = 1; |
| endfunction |
| |
| |
| // f_display |
| // |
| // This method sends string severity to the command line if file is 0 and to |
| // the file(s) specified by file if it is not 0. |
| |
| function void f_display(UVM_FILE file, string str); |
| if (file == 0) |
| $display("%s", str); |
| else |
| $fdisplay(file, "%s", str); |
| endfunction |
| |
| |
| // Function- report |
| // |
| // |
| |
| virtual function void report( |
| uvm_severity severity, |
| string name, |
| string id, |
| string message, |
| int verbosity_level, |
| string filename, |
| int line, |
| uvm_report_object client |
| ); |
| string m; |
| uvm_action a; |
| UVM_FILE f; |
| bit report_ok; |
| uvm_report_handler rh; |
| |
| rh = client.get_report_handler(); |
| |
| // filter based on verbosity level |
| |
| if(!client.uvm_report_enabled(verbosity_level, severity, id)) begin |
| return; |
| end |
| |
| // determine file to send report and actions to execute |
| |
| a = rh.get_action(severity, id); |
| if( uvm_action_type'(a) == UVM_NO_ACTION ) |
| return; |
| |
| f = rh.get_file_handle(severity, id); |
| |
| // The hooks can do additional filtering. If the hook function |
| // return 1 then continue processing the report. If the hook |
| // returns 0 then skip processing the report. |
| |
| if(a & UVM_CALL_HOOK) |
| report_ok = rh.run_hooks(client, severity, id, |
| message, verbosity_level, filename, line); |
| else |
| report_ok = 1; |
| |
| if(report_ok) |
| report_ok = uvm_report_catcher::process_all_report_catchers( |
| this, client, severity, name, id, message, |
| verbosity_level, a, filename, line); |
| |
| if(report_ok) begin |
| m = compose_message(severity, name, id, message, filename, line); |
| process_report(severity, name, id, message, a, f, filename, |
| line, m, verbosity_level, client); |
| end |
| |
| endfunction |
| |
| |
| |
| // Function: process_report |
| // |
| // Calls <compose_message> to construct the actual message to be |
| // output. It then takes the appropriate action according to the value of |
| // action and file. |
| // |
| // This method can be overloaded by expert users to customize the way the |
| // reporting system processes reports and the actions enabled for them. |
| |
| virtual function void process_report( |
| uvm_severity severity, |
| string name, |
| string id, |
| string message, |
| uvm_action action, |
| UVM_FILE file, |
| string filename, |
| int line, |
| string composed_message, |
| int verbosity_level, |
| uvm_report_object client |
| ); |
| // update counts |
| incr_severity_count(severity); |
| incr_id_count(id); |
| |
| if(action & UVM_DISPLAY) |
| $display("%s",composed_message); |
| |
| // if log is set we need to send to the file but not resend to the |
| // display. So, we need to mask off stdout for an mcd or we need |
| // to ignore the stdout file handle for a file handle. |
| if(action & UVM_LOG) |
| if( (file == 0) || (file != 32'h8000_0001) ) //ignore stdout handle |
| begin |
| UVM_FILE tmp_file = file; |
| if( (file&32'h8000_0000) == 0) //is an mcd so mask off stdout |
| begin |
| tmp_file = file & 32'hffff_fffe; |
| end |
| f_display(tmp_file,composed_message); |
| end |
| |
| if(action & UVM_EXIT) client.die(); |
| |
| if(action & UVM_COUNT) begin |
| if(get_max_quit_count() != 0) begin |
| incr_quit_count(); |
| if(is_quit_count_reached()) begin |
| client.die(); |
| end |
| end |
| end |
| |
| if (action & UVM_STOP) $stop; |
| |
| endfunction |
| |
| |
| |
| // Function: compose_message |
| // |
| // Constructs the actual string sent to the file or command line |
| // from the severity, component name, report id, and the message itself. |
| // |
| // Expert users can overload this method to customize report formatting. |
| |
| virtual function string compose_message( |
| uvm_severity severity, |
| string name, |
| string id, |
| string message, |
| string filename, |
| int line |
| ); |
| uvm_severity_type sv; |
| string time_str; |
| string line_str; |
| |
| sv = uvm_severity_type'(severity); |
| $swrite(time_str, "%0t", $realtime); |
| |
| case(1) |
| (name == "" && filename == ""): |
| return {sv.name(), " @ ", time_str, " [", id, "] ", message}; |
| (name != "" && filename == ""): |
| return {sv.name(), " @ ", time_str, ": ", name, " [", id, "] ", message}; |
| (name == "" && filename != ""): |
| begin |
| $swrite(line_str, "%0d", line); |
| return {sv.name(), " ",filename, "(", line_str, ")", " @ ", time_str, " [", id, "] ", message}; |
| end |
| (name != "" && filename != ""): |
| begin |
| $swrite(line_str, "%0d", line); |
| return {sv.name(), " ", filename, "(", line_str, ")", " @ ", time_str, ": ", name, " [", id, "] ", message}; |
| end |
| endcase |
| endfunction |
| |
| |
| |
| |
| // Function: summarize |
| // |
| // See <uvm_report_object::report_summarize> method. |
| |
| virtual function void summarize(UVM_FILE file=0); |
| string id; |
| string name; |
| string output_str; |
| uvm_report_catcher::summarize_report_catcher(file); |
| f_display(file, ""); |
| f_display(file, "--- UVM Report Summary ---"); |
| f_display(file, ""); |
| |
| if(max_quit_count != 0) begin |
| if ( quit_count >= max_quit_count ) f_display(file, "Quit count reached!"); |
| $sformat(output_str, "Quit count : %5d of %5d", |
| quit_count, max_quit_count); |
| f_display(file, output_str); |
| end |
| |
| f_display(file, "** Report counts by severity"); |
| for(uvm_severity_type s = s.first(); 1; s = s.next()) begin |
| if(severity_count.exists(s)) begin |
| int cnt; |
| cnt = severity_count[s]; |
| name = s.name(); |
| $sformat(output_str, "%s :%5d", name, cnt); |
| f_display(file, output_str); |
| end |
| if(s == s.last()) break; |
| end |
| |
| if (enable_report_id_count_summary) begin |
| |
| f_display(file, "** Report counts by id"); |
| for(int found = id_count.first(id); |
| found; |
| found = id_count.next(id)) begin |
| int cnt; |
| cnt = id_count[id]; |
| $sformat(output_str, "[%s] %5d", id, cnt); |
| f_display(file, output_str); |
| end |
| |
| end |
| |
| endfunction |
| |
| |
| // Function: dump_server_state |
| // |
| // Dumps server state information. |
| |
| function void dump_server_state(); |
| |
| string s; |
| uvm_severity_type sev; |
| string id; |
| |
| f_display(0, "report server state"); |
| f_display(0, ""); |
| f_display(0, "+-------------+"); |
| f_display(0, "| counts |"); |
| f_display(0, "+-------------+"); |
| f_display(0, ""); |
| |
| $sformat(s, "max quit count = %5d", max_quit_count); |
| f_display(0, s); |
| $sformat(s, "quit count = %5d", quit_count); |
| f_display(0, s); |
| |
| sev = sev.first(); |
| forever begin |
| int cnt; |
| cnt = severity_count[sev]; |
| s = sev.name(); |
| $sformat(s, "%s :%5d", s, cnt); |
| f_display(0, s); |
| if(sev == sev.last()) |
| break; |
| sev = sev.next(); |
| end |
| |
| if(id_count.first(id)) |
| do begin |
| int cnt; |
| cnt = id_count[id]; |
| $sformat(s, "%s :%5d", id, cnt); |
| f_display(0, s); |
| end |
| while (id_count.next(id)); |
| |
| endfunction |
| |
| |
| // Function- copy_severity_counts |
| // |
| // Internal method. |
| |
| function void copy_severity_counts(uvm_report_server dst); |
| foreach(severity_count[s]) begin |
| dst.set_severity_count(s,severity_count[s]); |
| end |
| endfunction |
| |
| |
| // Function- copy_severity_counts |
| // |
| // Internal method. |
| |
| function void copy_id_counts(uvm_report_server dst); |
| foreach(id_count[s]) begin |
| dst.set_id_count(s,id_count[s]); |
| end |
| endfunction |
| |
| |
| endclass |
| |
| |
| |
| //---------------------------------------------------------------------- |
| // CLASS- uvm_report_global_server |
| // |
| // Singleton object that maintains a single global report server |
| //---------------------------------------------------------------------- |
| class uvm_report_global_server; |
| |
| function new(); |
| void'(get_server()); |
| endfunction |
| |
| |
| // Function: get_server |
| // |
| // Returns a handle to the central report server. |
| |
| function uvm_report_server get_server(); |
| return uvm_report_server::get_server(); |
| endfunction |
| |
| |
| // Function- set_server (deprecated) |
| // |
| // |
| |
| function void set_server(uvm_report_server server); |
| uvm_report_server::set_server(server); |
| endfunction |
| |
| endclass |
| |
| |
| `endif // UVM_REPORT_SERVER_SVH |