So You Want a Different UVM Report Server. Doesn’t Everyone? Where To Start…
So. You want a different report server. Maybe something fancier. Maybe something simpler. Maybe something with special formatting.
How to get started?
Good news – it’s easy. This is an example of customizing a UVM report server using the new IEEE Std 1800.2-2017. This example will not work on UVM 1.1d or UVM 1.2, but with some changes it should. The idea is the same in each UVM version. Replace the default report server with a custom version.
In the discussion below, the default UVM report server will be replaced with a custom report server which produces messages which have column-ized fields. Object Oriented concepts will be used: inheritance and function override. The custom report server changes are simple. The default report server will be extended and then a key function call, compose_report_message(), will be replaced with a custom version. Only a few lines of code will be changed in compose_report_message().
The first thing to do is to create a package that can be used for the new report server – “my_report_server_pkg.sv”. This package will define a couple of helper functions.
- tail_width() returns the LAST few characters of its argument string.
- fixed_width() returns the argument string either truncated to the specified width, or white space padded to that width.
These helper functions will be used in the custom report server.
package my_report_server_pkg; import uvm_pkg::*; `include "uvm_macros.svh" function string tail_width(string s, int width); string tmp; int m, n; if (s.len() > width) begin m = s.len()-width; n = s.len()-1; tmp = s.substr(m, n); end else tmp = s; return fixed_width(tmp, width); endfunction function string fixed_width(string s, int width); string tmp; if (s.len() > width) begin // s is longer, truncate tmp = s.substr(0, width-1); end else begin // s is shorter. whitespace fill int n; n = width - s.len(); tmp = {s, {n{" "}}}; end return tmp; endfunction `include "my_report_server.svh" endpackage
The new report_server itself is in the file “my_report_server.svh
“:
class my_report_server_t extends uvm_default_report_server; virtual function string compose_report_message(uvm_report_message report_message, string report_object_name = ""); ... endfunction endclass
Above, a new class, ‘my_report_server_t’, is created by extending uvm_default_report_server. Copy the entire contents of the function ‘compose_report_message()’ from the uvm_report_server.svh::uvm_default_report_server class. That code is about 60 lines of formatting code. Edit the formatting as desired – just a couple of lines.
The body of the built-in compose_report_message() uses the uvm_report_message structure, and formats each piece. Then at the end of the routine, those formatted pieces are concatenated into a string. That concatenated string is the “composed message”. The new, replacement report server is to have a different “composed string”.
The original string concatenation is below
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};
The new string concatenation is below. The BOLD text above is changed to the BOLD text below. Same for BOLD Italic.
compose_report_message = {sev_string, verbosity_str, " ", filename_line_string, "@ ", time_str, ": ", tail_width({report_object_name, context_str}, 10), " [", fixed_width(report_message.get_id(), 12), "] ", msg_body_str, terminator_str};
In the case of the report_object_name and context_str, just the last 10 characters are returned. For example, a name like “uvm_test_top.VIPA.environment_c.agent_1.driver3” will be displayed as “_1.driver3”. For the get_id() (the Message ID), a fixed size string of 12 characters are returned. The string will either be extended with whitespace to 12 characters, or truncated to 12 characters – in both cases resulting in a 12 character field. Filename_line_string is formatted in a different section of compose_report_message(). Get the example to see.
Helper functions have been created: tail_width() and fixed_width(), along with a new report server class, containing an overridden compose_report_message function. Now to put it all to good use.
In the top level, or in the test – somewhere early in simulation, the new report server class needs to be constructed, and then it needs to replace the default report server. For example:
module top(); initial begin my_report_server_t my_report_server; my_report_server = new("my_report_server"); uvm_coreservice_t::get().set_report_server(my_report_server); run_test(); end endmodule
A class handle is declared and constructed, and then a call to ‘set_report_server()’ in uvm_coreservice_t installs the replacement. Done.
The output is “columnized”. The file-path-name, the UVM hierarchical path and the Message ID, have been made to fit in the various column sizes. (See BOLD below).
# UVM_INFO b/sim/t.sv( 114) @ 1285: t_top.a1.d [driver4 ] Got [transaction ] data=96 # UVM_INFO b/sim/t.sv( 114) @ 1288: t_top.a2.d [driver3 ] Got [transaction ] data=96 # UVM_INFO b/sim/t.sv( 114) @ 1290: t_top.a2.d [driver3 ] Got [my_special_transaction ] data=97 # UVM_INFO b/sim/t.sv( 114) @ 1290: t_top.a1.d [driver4 ] Got [my_special_transaction ] data=97 # UVM_INFO b/sim/t.sv( 114) @ 1295: t_top.a1.d [driver4 ] Got [transaction ] data=98 # UVM_INFO b/sim/t.sv( 114) @ 1296: t_top.a2.d [driver3 ] Got [transaction ] data=98 # UVM_INFO b/sim/t.sv( 114) @ 1301: t_top.a2.d [driver3 ] Got [my_special_transaction ] data=99 # UVM_INFO b/sim/t.sv( 114) @ 1302: t_top.a1.d [driver4 ] Got [my_special_transaction ] data=99 # UVM_INFO b/sim/t.sv( 114) @ 1306: t_top.a1.d [driver4 ] Got [transaction ] data=100 # UVM_INFO b/sim/t.sv( 114) @ 1307: t_top.a2.d [driver3 ] Got [transaction ] data=100 # UVM_INFO b/sim/t.sv( 89) @ 1311: qr@@seq1-3 [my_sequence ] Finished # UVM_INFO b/sim/t.sv( 89) @ 1312: qr@@seq2-3 [my_sequence ] Finished
It took a couple of helper functions, two lines of change in compose_report_message() and 3 lines of initialization and installation. Easy. Source code is available for this example. Please email if you would like it. rich_edelman@mentor.com
Come see and hear more about the UVM and find out about the new UVM IEEE standard at DVCON this year, February 25-28, 2019.
UVM at DVCON includes
- A tutorial Monday February 25 from 9 to 12 by Cliff Cummings – “Gain Valuable Insight into the Changes and Features that are part of the new IEEE 1800.2 Standard for UVM and how to make the most of them”.
- UVM papers in Session 5, Tuesday February 26 from 3 to 4:30 – “The Universal Verification Methodology (UVM)“. You can hear about UVM sequences, the UVM coreservices, and synchronization.
Or stop by the Mentor Booth to chat during the DVCON Expo. I’ll be there and I love to talk UVM and Debug. (Tuesday, 5-7, Wednesday 2:30-6, Thursday 2:30-6).
See you at the show.
Get the UVM. Download UVM 1.1d or UVM 1.2
Download UVM IEEE Std. 1800.2-2017 It’s free. Create a free account. Download.
Mentor DVCON Expo Theater Schedule (Located in the Mentor Booth)
Monday | February 25
5:00pm | Portable Stimulus from IP to SoC – Achieve More Verification with Questa inFact |
5:45pm | Accelerate SoC Power, Veloce Strato – PowerPro |
6:30pm | Exploring Veloce DFT and Fault Apps |
Tuesday | February 26
3:00pm | Mentor Safe IC – ISO 26262 & IEC 61508 Functional Safety |
3:45pm | Adding Determinism to Power in Early RTL Using Metrics |
4:30pm | Scaling Acceleration Productivity Beyond Hardward |
5:15pm | Adding Determinism to Power in Early RTL Using Metrics |
Wednesday | February 27
3:00pm | Verification Signoff of HLS C++/SystemC Designs |
4:00pm | An Emulation Strategy for AI and ML Designs |
5:00pm | Advanced UVM Debugging |
Comments
Leave a Reply
You must be logged in to post a comment.
Thanks for sharing!
Hi Jamal,
Glad to share. If you come up with a nifty Report Server, let us know
Best Regards