// //------------------------------------------------------------------------------ // Copyright 2010-2012 AMD // Copyright 2015 Analog Devices, Inc. // Copyright 2007-2018 Cadence Design Systems, Inc. // Copyright 2014-2017 Cisco Systems, Inc. // Copyright 2007-2020 Mentor Graphics Corporation // Copyright 2014-2020 NVIDIA Corporation // Copyright 2014 Semifore // Copyright 2010-2018 Synopsys, Inc. // Copyright 2013 Verilab // 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; //------------------------------------------------------------------------------ // Title -- NODOCS -- UVM Report Server // // This page covers the classes that define the UVM report server facility. //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // // CLASS -- NODOCS -- uvm_report_server // // uvm_report_server is a global server that processes all of the reports // generated by a uvm_report_handler. // // The ~uvm_report_server~ is an abstract class which declares many of its methods // as ~pure virtual~. The UVM uses the class // as its default report server implementation. //------------------------------------------------------------------------------ typedef class uvm_default_report_server; // @uvm-ieee 1800.2-2020 auto 6.5.1.1 virtual class uvm_report_server extends uvm_object; function string get_type_name(); return "uvm_report_server"; endfunction // @uvm-ieee 1800.2-2020 auto 6.5.1.2.1 function new(string name="base"); super.new(name); endfunction // @uvm-ieee 1800.2-2020 auto 6.5.1.2.3 pure virtual function void set_max_quit_count(int count, bit overridable = 1); // @uvm-ieee 1800.2-2020 auto 6.5.1.2.2 pure virtual function int get_max_quit_count(); // @uvm-ieee 1800.2-2020 auto 6.5.1.2.5 pure virtual function void set_quit_count(int quit_count); // @uvm-ieee 1800.2-2020 auto 6.5.1.2.4 pure virtual function int get_quit_count(); // @uvm-ieee 1800.2-2020 auto 6.5.1.2.7 pure virtual function void set_severity_count(uvm_severity severity, int count); // @uvm-ieee 1800.2-2020 auto 6.5.1.2.6 pure virtual function int get_severity_count(uvm_severity severity); // Function -- NODOCS -- set_id_count // sets the count of already passed messages with ~id~ to ~count~ pure virtual function void set_id_count(string id, int count); // @uvm-ieee 1800.2-2020 auto 6.5.1.2.8 pure virtual function int get_id_count(string id); // @uvm-ieee 1800.2-2020 auto 6.5.1.2.9 pure virtual function void get_id_set(output string q[$]); // @uvm-ieee 1800.2-2020 auto 6.5.1.2.10 pure virtual function void get_severity_set(output uvm_severity q[$]); // @uvm-ieee 1800.2-2020 auto 6.5.1.2.12 pure virtual function void set_message_database(uvm_tr_database database); // @uvm-ieee 1800.2-2020 auto 6.5.1.2.11 pure virtual function uvm_tr_database get_message_database(); // @uvm-ieee 1800.2-2020 auto 6.5.1.2.13 function void do_copy (uvm_object rhs); uvm_report_server rhs_; super.do_copy(rhs); if(!$cast(rhs_,rhs)) `uvm_error("UVM/REPORT/SERVER/RPTCOPY","cannot copy to report_server from the given datatype") begin uvm_severity q[$]; rhs_.get_severity_set(q); foreach(q[s]) set_severity_count(q[s],rhs_.get_severity_count(q[s])); end begin string q[$]; rhs_.get_id_set(q); foreach(q[s]) set_id_count(q[s],rhs_.get_id_count(q[s])); end set_message_database(rhs_.get_message_database()); set_max_quit_count(rhs_.get_max_quit_count()); set_quit_count(rhs_.get_quit_count()); endfunction // Function- process_report_message // // Main entry for uvm_report_server, combines execute_report_message and compose_report_message // @uvm-ieee 1800.2-2020 auto 6.5.1.2.14 pure virtual function void process_report_message(uvm_report_message report_message); // Function -- NODOCS -- execute_report_message // // Processes the provided message per the actions contained within. // // Expert users can overload this method to customize action processing. // @uvm-ieee 1800.2-2020 auto 6.5.1.2.16 pure virtual function void execute_report_message(uvm_report_message report_message, string composed_message); // Function -- NODOCS -- compose_report_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. // @uvm-ieee 1800.2-2020 auto 6.5.1.2.15 pure virtual function string compose_report_message(uvm_report_message report_message, string report_object_name = ""); // Function -- NODOCS -- 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 method in uvm_top calls this method. // @uvm-ieee 1800.2-2020 auto 6.5.1.2.17 pure virtual function void report_summarize(UVM_FILE file = UVM_STDOUT); // Function -- NODOCS -- set_server // // Sets the global report server to use for reporting. // // This method is provided as a convenience wrapper around // setting the report server via the // method. // // In addition to setting the server this also copies the severity/id counts // from the current report_server to the new one // // | // Using the uvm_coreservice_t: // | uvm_coreservice_t cs; // | cs = uvm_coreservice_t::get(); // | your_server.copy(cs.get_report_server()); // | cs.set_report_server(your_server); // | // | // Not using the uvm_coreservice_t: // | uvm_report_server::set_server(your_server); // @uvm-ieee 1800.2-2020 auto 6.5.1.2.19 static function void set_server(uvm_report_server server); uvm_coreservice_t cs = uvm_coreservice_t::get(); server.copy(cs.get_report_server()); cs.set_report_server(server); endfunction // Function -- NODOCS -- get_server // // Gets the global report server used for reporting. // // This method is provided as a convenience wrapper // around retrieving the report server via the // method. // // | // Using the uvm_coreservice_t: // | uvm_coreservice_t cs; // | uvm_report_server rs; // | cs = uvm_coreservice_t::get(); // | rs = cs.get_report_server(); // | // | // Not using the uvm_coreservice_t: // | uvm_report_server rs; // | rs = uvm_report_server::get_server(); // // @uvm-ieee 1800.2-2020 auto 6.5.1.2.18 static function uvm_report_server get_server(); uvm_coreservice_t cs = uvm_coreservice_t::get(); return cs.get_report_server(); endfunction endclass //------------------------------------------------------------------------------ // // CLASS: uvm_default_report_server // // Default implementation of the UVM report server, as defined in section // 6.5.2 of 1800.2-2020 // // @uvm-ieee 1800.2-2020 auto 6.5.2 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]; protected int m_id_count[string]; protected uvm_tr_database m_message_db; protected uvm_tr_stream m_streams[string][string]; // ro.name,rh.name // Variable: enable_report_id_count_summary // // A flag to enable report count summary for each ID // // @uvm-accellera This API is specific to the Accellera implementation, and is not being considered for contribution to 1800.2 bit enable_report_id_count_summary=1; // Variable: record_all_messages // // A flag to force recording of all messages (add UVM_RM_RECORD action) // // @uvm-accellera This API is specific to the Accellera implementation, and is not being considered for contribution to 1800.2 bit record_all_messages = 0; // Variable: show_verbosity // // A flag to include verbosity in the messages, e.g. // // "UVM_INFO(UVM_MEDIUM) file.v(3) @ 60: reporter [ID0] Message 0" // // @uvm-accellera This API is specific to the Accellera implementation, and is not being considered for contribution to 1800.2 bit show_verbosity = 0; // Variable: show_terminator // // A flag to add a terminator in the messages, e.g. // // "UVM_INFO file.v(3) @ 60: reporter [ID0] Message 0 -UVM_INFO" // bit show_terminator = 0; // Needed for callbacks function string get_type_name(); return "uvm_default_report_server"; endfunction // Function --NODOCS-- new // // Creates an instance of the class. function new(string name = "uvm_report_server"); super.new(name); set_max_quit_count(0); reset_quit_count(); reset_severity_counts(); endfunction // Function --NODOCS-- print // // The uvm_report_server implements the such that // ~print~ method provides UVM printer formatted output // of the current configuration. A snippet of example output is shown here: // // |uvm_report_server uvm_report_server - @13 // | quit_count int 32 'd0 // | max_quit_count int 32 'd5 // | max_quit_overridable bit 1 'b1 // | severity_count severity counts 4 - // | [UVM_INFO] integral 32 'd4 // | [UVM_WARNING] integral 32 'd2 // | [UVM_ERROR] integral 32 'd50 // | [UVM_FATAL] integral 32 'd10 // | id_count id counts 4 - // | [ID1] integral 32 'd1 // | [ID2] integral 32 'd2 // | [RNTST] integral 32 'd1 // | enable_report_id_count_summary bit 1 'b1 // | record_all_messages bit 1 `b0 // | show_verbosity bit 1 `b0 // | show_terminator bit 1 `b0 // Print to show report server state virtual function void do_print (uvm_printer printer); uvm_severity l_severity_count_index; string l_id_count_index; printer.print_field("quit_count", m_quit_count, $bits(m_quit_count), UVM_DEC, ".", "int"); printer.print_field("max_quit_count", m_max_quit_count, $bits(m_max_quit_count), UVM_DEC, ".", "int"); printer.print_field("max_quit_overridable", max_quit_overridable, $bits(max_quit_overridable), UVM_BIN, ".", "bit"); if (m_severity_count.first(l_severity_count_index)) begin printer.print_array_header("severity_count",m_severity_count.size(),"severity counts"); do printer.print_field($sformatf("[%s]",l_severity_count_index.name()), m_severity_count[l_severity_count_index], 32, UVM_DEC); while (m_severity_count.next(l_severity_count_index)); printer.print_array_footer(); end if (m_id_count.first(l_id_count_index)) begin printer.print_array_header("id_count",m_id_count.size(),"id counts"); do printer.print_field($sformatf("[%s]",l_id_count_index), m_id_count[l_id_count_index], 32, UVM_DEC); while (m_id_count.next(l_id_count_index)); printer.print_array_footer(); end printer.print_field("enable_report_id_count_summary", enable_report_id_count_summary, $bits(enable_report_id_count_summary), UVM_BIN, ".", "bit"); printer.print_field("record_all_messages", record_all_messages, $bits(record_all_messages), UVM_BIN, ".", "bit"); printer.print_field("show_verbosity", show_verbosity, $bits(show_verbosity), UVM_BIN, ".", "bit"); printer.print_field("show_terminator", show_terminator, $bits(show_terminator), UVM_BIN, ".", "bit"); endfunction //---------------------------------------------------------------------------- // Group --NODOCS-- Quit Count //---------------------------------------------------------------------------- // Function --NODOCS-- get_max_quit_count function int get_max_quit_count(); return m_max_quit_count; endfunction // Function --NODOCS-- 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 --NODOCS-- get_quit_count function int get_quit_count(); return m_quit_count; endfunction // Function --NODOCS-- set_quit_count function void set_quit_count(int quit_count); m_quit_count = quit_count < 0 ? 0 : quit_count; endfunction // Function --NODOCS-- incr_quit_count function void incr_quit_count(); m_quit_count++; endfunction // Function --NODOCS-- 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(); m_quit_count = 0; endfunction // Function --NODOCS-- 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 //---------------------------------------------------------------------------- // Group --NODOCS-- Severity Count //---------------------------------------------------------------------------- // Function --NODOCS-- get_severity_count function int get_severity_count(uvm_severity severity); return m_severity_count[severity]; endfunction // Function --NODOCS-- set_severity_count function void set_severity_count(uvm_severity severity, int count); m_severity_count[severity] = count < 0 ? 0 : count; endfunction // Function --NODOCS-- incr_severity_count function void incr_severity_count(uvm_severity severity); m_severity_count[severity]++; endfunction // Function --NODOCS-- 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 s; s = s.first(); forever begin m_severity_count[s] = 0; if(s == s.last()) break; s = s.next(); end endfunction //---------------------------------------------------------------------------- // Group --NODOCS-- id Count //---------------------------------------------------------------------------- // Function --NODOCS-- get_id_count function int get_id_count(string id); if(m_id_count.exists(id)) return m_id_count[id]; return 0; endfunction // Function --NODOCS-- set_id_count function void set_id_count(string id, int count); m_id_count[id] = count < 0 ? 0 : count; endfunction // Function --NODOCS-- incr_id_count // // Set, get, or increment the counter for reports with the given id. function void incr_id_count(string id); if(m_id_count.exists(id)) m_id_count[id]++; else m_id_count[id] = 1; endfunction //---------------------------------------------------------------------------- // Group --NODOCS-- message recording // // The ~uvm_default_report_server~ will record messages into the message // database, using one transaction per message, and one stream per report // object/handler pair. // //---------------------------------------------------------------------------- // Function --NODOCS-- set_message_database // sets the used for recording messages virtual function void set_message_database(uvm_tr_database database); m_message_db = database; endfunction : set_message_database // Function --NODOCS-- get_message_database // returns the used for recording messages // virtual function uvm_tr_database get_message_database(); return m_message_db; endfunction : get_message_database virtual function void get_severity_set(output uvm_severity q[$]); foreach(m_severity_count[idx]) q.push_back(idx); endfunction virtual function void get_id_set(output string q[$]); foreach(m_id_count[idx]) q.push_back(idx); endfunction // Function- 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- process_report_message // // virtual function void process_report_message(uvm_report_message report_message); uvm_report_handler l_report_handler = report_message.get_report_handler(); process p = process::self(); bit report_ok = 1; // Set the report server for this message report_message.set_report_server(this); if(report_ok) report_ok = uvm_report_catcher::process_all_report_catchers(report_message); if(uvm_action_type'(report_message.get_action()) == UVM_NO_ACTION) report_ok = 0; if(report_ok) begin string m; uvm_coreservice_t cs = uvm_coreservice_t::get(); // give the global server a chance to intercept the calls uvm_report_server svr = cs.get_report_server(); // no need to compose when neither UVM_DISPLAY nor UVM_LOG is set if (report_message.get_action() & (UVM_LOG|UVM_DISPLAY)) m = svr.compose_report_message(report_message); svr.execute_report_message(report_message, m); end endfunction //---------------------------------------------------------------------------- // Group --NODOCS-- Message Processing //---------------------------------------------------------------------------- // Function --NODOCS-- execute_report_message // // Processes the provided message per the actions contained within. // // Expert users can overload this method to customize action processing. virtual function void execute_report_message(uvm_report_message report_message, string composed_message); process p = process::self(); // Update counts incr_severity_count(report_message.get_severity()); incr_id_count(report_message.get_id()); if (record_all_messages) report_message.set_action(report_message.get_action() | UVM_RM_RECORD); // UVM_RM_RECORD action if(report_message.get_action() & UVM_RM_RECORD) begin uvm_tr_stream stream; uvm_report_object ro = report_message.get_report_object(); uvm_report_handler rh = report_message.get_report_handler(); // Check for pre-existing stream if (m_streams.exists(ro.get_name()) && (m_streams[ro.get_name()].exists(rh.get_name()))) stream = m_streams[ro.get_name()][rh.get_name()]; // If no pre-existing stream (or for some reason pre-existing stream was ~null~) if (stream == null) begin uvm_tr_database db; // Grab the database db = get_message_database(); // If database is ~null~, use the default database if (db == null) begin uvm_coreservice_t cs = uvm_coreservice_t::get(); db = cs.get_default_tr_database(); end if (db != null) begin // Open the stream. Name=report object name, scope=report handler name, type=MESSAGES stream = db.open_stream(ro.get_name(), rh.get_name(), "MESSAGES"); // Save off the openned stream m_streams[ro.get_name()][rh.get_name()] = stream; end end if (stream != null) begin uvm_recorder recorder = stream.open_recorder(report_message.get_name(),,report_message.get_type_name()); if (recorder != null) begin report_message.record(recorder); recorder.free(); end end end // DISPLAY action if(report_message.get_action() & UVM_DISPLAY) $display("%s", composed_message); // LOG action // 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(report_message.get_action() & UVM_LOG) if( (report_message.get_file() == 0) || (report_message.get_file() != 32'h8000_0001) ) begin //ignore stdout handle UVM_FILE tmp_file = report_message.get_file(); if((report_message.get_file() & 32'h8000_0000) == 0) begin //is an mcd so mask off stdout tmp_file = report_message.get_file() & 32'hffff_fffe; end f_display(tmp_file, composed_message); end // Process the UVM_COUNT action if(report_message.get_action() & UVM_COUNT) begin if(get_max_quit_count() != 0) begin incr_quit_count(); // If quit count is reached, add the UVM_EXIT action. if(is_quit_count_reached()) begin report_message.set_action(report_message.get_action() | UVM_EXIT); end end end // Process the UVM_EXIT action if(report_message.get_action() & UVM_EXIT) begin uvm_root l_root; uvm_coreservice_t cs; cs = uvm_coreservice_t::get(); l_root = cs.get_root(); l_root.die(); end // Process the UVM_STOP action if (report_message.get_action() & UVM_STOP) $stop; endfunction // Function: compose_report_message // // Constructs the actual string sent to the file or command line // from the report message. // // The return value is constructed by concatenating the following strings in order, // with spaces between. // // Severity and verbosity - If is '1', then this value is the concatenation // of {S1,"(",S2,")"}, where ~S1~ is the severity of the message as // returned by , and ~S2~ is the // verbosity of the message, as returned by . // If is '0', then this value is simply the severity // of the message. // // File name and line - If returns an empty string (""), // then this value is the empty string (""). Otherwise // this string is formatted as "%s(%0d)", where ~%s~ is the file // name, and ~%0d~ is the line number. // // Timestamp - This value is the concatenation of {"@",TIME,":"}, where ~TIME~ is determined by formatting // ~$time~ as "%0t". Note that ~$time~ is being resolved inside of the scope. // // Full report context - If , returns an empty string (""), then // this value is the full name of the report object returned by // . Otherwise this // value is the the concatenation of {S1,"@@",S2}, where ~S1~ is the full // name of the report object for the message, and ~S2~ is // the context string. // // ID - The concatenation of {"[", ID, "]"}, where ~ID~ is the return value of . // // Message - The message string, as determined by // // Terminator - If is '1', then the terminator string is {"-", SEV}, where ~SEV~ is // the severity as determined by . If show_terminator is // '0', then this is the empty string (""). // //For example, the following report messages... //| `uvm_info("Example", "Info message", UVM_LOW) //| uvm_report_info("Example", "No file/line"); //| uvm_report_info("Example", "With context", UVM_LOW, //| "demo_pkg.sv", 57, "example_context"); //| //| // show_verbosity = 1 //| `uvm_info("Example", "With verbosity", UVM_LOW) //| // show_terminator = 1 //| `uvm_info("Example", "With terminator", UvM_LOW) //| // show_verbosity = 1, show_terminator = 1 //| `uvm_info("Example", "With both", UVM_NONE) // //...result in the output below //| //| UVM_INFO demo_pkg.sv(55) @ 0: uvm_test_top [Example] Info message //| UVM_INFO @ 0: uvm_test_top [Example] No file/line //| UVM_INFO demo_pkg.sv(57) @ 0: uvm_test_top@@example_context [Example] With context //| //| // show_verbosity = 1 //| UVM_INFO(UVM_LOW) demo_pkg.sv(60) @ 0: uvm_test_top [Example] Info message //| // show_terminator = 1 //| UVM_INFO demo_pkg.sv(62) @ 0: uvm_test_top [Example] Info message -UVM_INFO //| // show_verbosity = 1, show_terminator = 1 //| UVM_INFO(UVM_NONE) demo_pkg.sv(64) @ 0: uvm_test_top [Example] With both -UVM_INFO // // @uvm-accellera The details of this API are specific to the Accellera implementation, and are not being considered for contribution to 1800.2 virtual function string compose_report_message(uvm_report_message report_message, string report_object_name = ""); string sev_string; uvm_severity l_severity; uvm_verbosity l_verbosity; string filename_line_string; string time_str; string line_str; string context_str; string verbosity_str; string terminator_str; string msg_body_str; uvm_report_message_element_container el_container; string prefix; uvm_report_handler l_report_handler; l_severity = report_message.get_severity(); sev_string = l_severity.name(); if (report_message.get_filename() != "") begin line_str.itoa(report_message.get_line()); filename_line_string = {report_message.get_filename(), "(", line_str, ") "}; end // Make definable in terms of units. $swrite(time_str, "%0t", $time); if (report_message.get_context() != "") context_str = {"@@", report_message.get_context()}; if (show_verbosity) begin if ($cast(l_verbosity, report_message.get_verbosity())) verbosity_str = l_verbosity.name(); else verbosity_str.itoa(report_message.get_verbosity()); verbosity_str = {"(", verbosity_str, ")"}; end if (show_terminator) terminator_str = {" -",sev_string}; el_container = report_message.get_element_container(); if (el_container.size() == 0) msg_body_str = report_message.get_message(); else begin uvm_printer uvm_default_printer = uvm_printer::get_default() ; prefix = uvm_default_printer.get_line_prefix(); uvm_default_printer.set_line_prefix(" +"); msg_body_str = {report_message.get_message(), "\n", el_container.sprint()}; uvm_default_printer.set_line_prefix(prefix); end if (report_object_name == "") begin l_report_handler = report_message.get_report_handler(); report_object_name = l_report_handler.get_full_name(); end compose_report_message = {sev_string, verbosity_str, " ", filename_line_string, "@ ", time_str, ": ", report_object_name, context_str, " [", report_message.get_id(), "] ", msg_body_str, terminator_str}; endfunction // Function --NODOCS-- 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 UVM_STDOUT, or // to the file descriptor ~file~ if it is not UVM_STDOUT. // // The method in uvm_top calls this method. virtual function void report_summarize(UVM_FILE file = UVM_STDOUT); string id; string name; uvm_root root; uvm_action action; string output_str; string q[$]; uvm_report_catcher::summarize(file); 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 if(file == UVM_STDOUT) begin `uvm_info("UVM/REPORT/SERVER",`UVM_STRING_QUEUE_STREAMING_PACK(q),UVM_NONE) end else begin // Re-route the output for the message to the file by changing the action, restoring to original setting after message reported root = uvm_root::get(); action = root.get_report_action(UVM_INFO, "UVM/REPORT/SERVER"); root.set_report_id_action("UVM/REPORT/SERVER", UVM_LOG); root.set_report_id_file("UVM/REPORT/SERVER", file); `uvm_info("UVM/REPORT/SERVER",`UVM_STRING_QUEUE_STREAMING_PACK(q),UVM_NONE) root.set_report_id_action("UVM/REPORT/SERVER", action); end endfunction endclass `endif // UVM_REPORT_SERVER_SVH