image/svg+xml
  • Contents
      • Back
      • Digital Basics
      • Verilog
      • Verification
      • SystemVerilog
      • UVM
Most Popular
Verification
  Testbench Evolution
  Constraint Random Verification
  Verification Techniques
  Verification Plan
  Code Coverage

Verilog
  Data Types
  Basic Constructs
  Behavioral Modeling
  Gate Modeling
  Simulation Basics
  Design Examples

SystemVerilog
  Data Types
  Class
  Interface
  Constraints and more!
  Testbench Examples

UVM
  Sequences
  Testbench Components
  TLM Tutorial
  Register Model Tutorial
  Testbench Examples

Digital Fundamentals
  Binary Arithmetic
  Boolean Logic
  Karnaugh Maps
  Combinational Logic
  Sequential Logic




Verilog Tutorial

  1. What is Verilog ?
  2. What was used before Verilog ?
  3. Why is Verilog better than its predecessor languages ?
  4. How is Verilog useful ?
    1. Verilog Code Example
  5. How is Verilog different from software languages like C and Java ?
  6. What may replace Verilog in the future ?

What is Verilog ?

Verilog is a hardware description language (HDL) that is used to describe digital systems and circuits in the form of code. It was developed by Gateway Design Automation in the mid-1980s and later acquired by Cadence Design Systems.

Verilog is widely used for design and verification of digital and mixed-signal systems, including both application-specific integrated circuits (ASICs) and field-programmable gate arrays (FPGAs). It supports a range of levels of abstraction, from structural to behavioral, and is used for both simulation-based design and synthesis-based design.

The language is used to describe digital circuits hierarchically, starting with the most basic elements such as logic gates and flip-flops and building up to more complex functional blocks and systems. It also supports a range of modeling techniques, including gate-level, RTL-level, and behavioral-level modeling.

What was used before Verilog ?

Before the development of Verilog, the primary hardware description language (HDL) used for digital circuit design and verification was VHDL (VHSIC Hardware Description Language). VHDL was developed in the 1980s by the U.S. Department of Defense as part of the Very High-Speed Integrated Circuit (VHSIC) program to design and test high-speed digital circuits.

VHDL is a complex language that enables designers to describe digital systems using a range of abstraction levels, from the low-level transistor and gate levels up to complex hierarchical systems. It was designed to be more descriptive and flexible than earlier HDLs, such as ABEL (Advanced Boolean Expression Language), ISP (Integrated System Synthesis Procedure), and CUPL (Compiler for Universal Programmable Logic).

Despite the development of Verilog and its increasing popularity since the 1980s, VHDL remains a widely used HDL, particularly in Europe and in the military and aerospace industries. Today, both Verilog and VHDL are widely used in digital circuit design and verification, with many companies and organizations using a combination of the two languages.

Why is Verilog better than its predecessor languages ?

Verilog introduced several important improvements over its predecessor languages, which helped make it a more popular and effective HDL for digital circuit design and verification. Here are a few reasons why Verilog is considered better than its predecessor HDLs:

  • Simpler syntax: Verilog has a simpler syntax compared to VHDL, which allows designers to write code more quickly and with fewer errors.
  • Better support for behavioral modeling: Verilog provides better support for describing the behavior and functionality of digital designs. It supports a range of modeling techniques, from gate-level to behavioral-level modeling, which makes it easier to describe the behavior of complex digital circuits.
  • Higher level of abstraction: Verilog provides a higher level of abstraction than its predecessor languages. It enables designers to describe digital circuits using concepts such as modules and ports, which makes the design process more efficient.
  • Better tool support: Due to its increasing popularity, Verilog has better tool support than its predecessor languages. Verilog has a range of integrated development environments (IDEs) and simulation tools available, which makes it easier to design and verify digital circuits.

How is Verilog useful ?

Verilog creates a level of abstraction that helps hide away the details of its implementation and technology.

For example, the design of a D flip-flop would require the knowledge of how the transistors need to be arranged to achieve a positive-edge triggered FF and what the rise, fall and clk-Q times required to latch the value onto a flop among many other technology oriented details. Power dissipation, timing and the ability to drive nets and other flops would also require a more thorough understanding of the physical characteristics of a transistor.

Verilog helps us to focus on the behavior and leave the rest to be sorted out later.

Verilog Code Example

The following Verilog code describes the behavior of a counter. The counter counts up if the up_down signal is 1, and down if its value is 0. It also resets the counter if the signal rstn becomes 0, making it an active-low reset.


	module ctr (input  				up_down,
									clk,
									rstn,
	            output reg [2:0] 	out);
		
		always @ (posedge clk)
			if (!rstn)
				out <= 0;
			else begin
				if (up_down)
					out <= out + 1;
				else
					out <= out - 1;
			end
	endmodule

The simple example shown above illustrates how all the physical implementation details (interconnection of underlying logic gates like NAND and NOR) have been hidden while still providing a clear idea of how the counter functions.

ctr is a module that represents an up/down counter, and it is possible to choose the actual physical implementation of the design from a wide variety of different styles of flops optimized for area, power and performance. They are usually compiled into libraries and will be available for us to select within EDA tools at a later stage in the design process.

How is Verilog different from software languages like C and Java ?

Verilog is a hardware description language (HDL) used to describe digital circuits and systems, while C and Java are software programming languages used to write code that runs on general-purpose computers. Here are some of the main differences between Verilog and programming languages like C and Java:

  • Purpose: Verilog is used to describe digital circuits and systems, while C and Java are used to write software programs that run on computers.
  • Syntax: Verilog has a different syntax than C and Java, as it is designed to describe the behavior of digital circuits rather than the execution of software instructions. For example, Verilog describes the properties of wires, registers, and logic gates, while C and Java define variables, functions, and control loops.
  • Execution: Verilog is used to describe how digital circuits should behave, but it doesn't directly execute code. Instead, the Verilog code is compiled into a hardware configuration that can be implemented in a physical circuit or FPGA. C and Java code, on the other hand, is compiled into machine code that can be executed directly by a computer processor.
  • Testing and Verification: Verilog is typically used to simulate the behavior of digital systems before they are physically implemented, while C and Java programs are usually tested and verified through software-based simulations or code reviews.
  • Nesting of Design: In Verilog, the designs can be created as modules and can be reused which is not in the case of programming languages like C and Java where the code is written for a specific purpose.

Overall, Verilog is a specialized language designed specifically for digital circuit design and isn't used for general-purpose programming like C and Java. While there are some similarities in syntax and programming concepts between these languages, the primary focus and application of Verilog is on the design, simulation, and implementation of digital circuits and systems.

What may replace Verilog in the future ?

It's difficult to predict exactly what may replace Verilog in the future, but there are several emerging technologies and languages that may have an impact on the future of digital system design and verification.

One technology that may affect the future of digital system design is High-Level Synthesis (HLS), which is a technique for automatically generating hardware designs from high-level descriptions in languages like C, C++, and SystemC. HLS allows designers to express their design intents and functionality at a higher level of abstraction, rather than specifying the details of logic gates and register transfers in Verilog or VHDL. This could enable more efficient and rapid design of digital systems, and allow designers to explore more design space in a shorter period of time.

Another technology that may impact the future of digital system design is machine learning and artificial intelligence (AI), which have the potential to significantly streamline the design and verification process of digital systems. For example, machine learning algorithms can be used to automatically optimize and generate hardware designs, reducing the need for manual design efforts.

There are also emerging HDLs that are trying to address some of the limitations of Verilog and VHDL, such as Chisel and MyHDL, which are based on more modern programming concepts and provide higher-level abstractions.

Setting policy using uvm_comparer

      1. Example
  1. Using _decl macro in TLM
-->

uvm_comparer is the standalone class used to set a policy for doing comparisons and determines how miscompares are counted. Every uvm_object instance has a compare() method for performing comparisons with another object. A policy object can be passed along to set parameters like depth of comparison, verbosity, maximum number of miscompares etc - an extra layer of flexibility. uvm_comparer also has a set of comparison methods for integers, strings, real numbers and objects.

Note that the number of miscompares is stored in an internal variable called "result", which gets incremented upon every such occurrence. Hence, if you are using the same object to compare two different items, the number of miscompares shown in the end might not be correct. It is advised to clear the "result" variable for every new comparison. This is only valid if you are directly using an object like in the example shown below.

When the uvm_comparer object is passed onto uvm_object::compare() method, the comparison policy will be set, and result will be cleared. If no uvm_comparer object is passed along, then it will take the default global level uvm_comparer policy object.



Example

This example will build upon the How to use uvm_printer set of data objects.


class base_test extends uvm_test;
   `uvm_component_utils (base_test)

   my_data obj0, obj1;
   derivative dv0, dv1;

   uvm_comparer uc0;

   function new (string name = "base_test", uvm_component parent);
      super.new (name, parent);
   endfunction

   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      obj0 = my_data::type_id::create ("obj0");
      obj1 = my_data::type_id::create ("obj1");
      uc0 = new();
   endfunction

   virtual task run_phase (uvm_phase phase);

      cfg_comparer();
      // Do not use the same uvm_compare object to do multiple comparisons, like shown below 
      // The example is a demonstration of the different methods of uvm_compare
      // NOTE: There's an internal variable "result" that stores the number of miscompares.
      // This variable will continue to be incremented for every mismatch, until cleared manually 

      `uvm_info ("COMPARE", "Trying out compare_field", UVM_MEDIUM)
      uc0.compare_field ("compare_field1", 7, 7, 2);            // pass
      uc0.compare_field ("compare_field2", 8'd45, 8'd8, 2);     // fail

      `uvm_info ("COMPARE", "Trying out field_int", UVM_MEDIUM)
      uc0.compare_field_int ("field_int1", 64'hface_deaf_feed_cafe, 64'hfabe_deaf_feed_cafe, 64);  // fail 
      uc0.compare_field_int ("field_int2", 64'habcd_ef12_3456_7890, 64'habcd_ef12_3456_7890, 64);  // pass
      
      uc0.compare_field_int ("field_int3", 64'hface_deaf_feed_cafe, 64'h7ace_deaf_feed_cafe, 63);  // pass 
      uc0.compare_field_int ("field_int4", 64'hface_deaf_feed_cafe, 64'h8abe_deaf_feed_cafe, 64);  // fail 

      uc0.compare_field_int ("field_int5", 68'hbbbb_face_deaf_feed_cafe, 68'haaaa_8abe_deaf_feed_cafe, 68); //  won't work; nothing happens
      uc0.compare_field ("field", 68'hb_face_deaf_feed_cafe, 68'haa_8abe_deaf_feed_cafe, 68); // fail: will work with field, because size > 64

      `uvm_info ("COMPARE", "Trying out compare_object", UVM_MEDIUM)
      void'(obj0.randomize());
      void'(obj1.randomize());
      uc0.compare_object ("object1", obj0, obj1);  // fail
      obj1.copy (obj0);
      uc0.compare_object ("object2", obj0, obj1);  // pass

      `uvm_info ("COMPARE", "Trying out compare_string", UVM_MEDIUM)
      uc0.compare_string ("string1", "Hello", "World");   // fail
      uc0.compare_string ("string2", "Hello", "Hello");   // pass

      
      // Proper Usage: Set the configuration for uvm_comparer and pass it to compare()
      // The "result" variable is cleared before comparison starts within uvm_object::compare()
      obj0.name = "Apple";
      obj0.m_format0.m_color.fav = "magenta";
      obj0.m_format0.m_color.unfav = "yellow";

      obj1.name = "Orange";
      obj1.m_format0.m_color.fav = "magenta";
      obj1.m_format0.m_color.unfav = "green";

      cfg_comparer();
      void'(obj0.randomize());
      obj1.compare (obj0, uc0);

      // randomize and compare again
      void'(obj0.randomize());
      obj1.compare (obj0, uc0);
      

   endtask

   virtual function cfg_comparer();
      uc0.show_max = 20;     // total number of miscompares to be printed
      uc0.verbosity = UVM_MEDIUM;
   endfunction

endclass
 Simulation Log
UVM_INFO @ 0: reporter [RNTST] Running test base_test...
UVM_INFO ./tb/test_pkg.sv(43) @ 0: uvm_test_top [COMPARE] Trying out compare_field
UVM_INFO @ 0: reporter [MISCMP] Miscompare for compare_field2: lhs = 'h1 : rhs = 'h0
UVM_INFO ./tb/test_pkg.sv(47) @ 0: uvm_test_top [COMPARE] Trying out field_int
UVM_INFO @ 0: reporter [MISCMP] Miscompare for field_int1: lhs = 'hfacedeaffeedcafe : rhs = 'hfabedeaffeedcafe
UVM_INFO @ 0: reporter [MISCMP] Miscompare for field_int4: lhs = 'hfacedeaffeedcafe : rhs = 'h8abedeaffeedcafe
UVM_INFO @ 0: reporter [MISCMP] Miscompare for field: lhs = 'hbfacedeaffeedcafe : rhs = 'ha8abedeaffeedcafe
UVM_INFO ./tb/test_pkg.sv(57) @ 0: uvm_test_top [COMPARE] Trying out compare_object
UVM_INFO @ 0: reporter [MISCMP] Miscompare for object1.data: lhs = 'h5a : rhs = 'h47
UVM_INFO @ 0: reporter [MISCMP] Miscompare for object1.addr: lhs = 'h1 : rhs = 'h2
UVM_INFO @ 0: reporter [MISCMP] Miscompare for object1.m_format0.header: lhs = 'hb : rhs = 'h2
UVM_INFO @ 0: reporter [MISCMP] Miscompare for object1.m_format0.footer: lhs = 'h0 : rhs = 'h7
UVM_INFO @ 0: reporter [MISCMP] Miscompare for object1.m_format0.body: lhs = 'h1 : rhs = 'h2
UVM_INFO @ 0: reporter [MISCMP] Miscompare for object1.m_format0.m_color.color: lhs = 'h8 : rhs = 'h2
UVM_INFO @ 0: reporter [MISCMP] 10 Miscompare(s) for object obj1@2722 vs. obj0@2687
UVM_INFO @ 0: reporter [MISCMP] 10 Miscompare(s) for object obj1@2722 vs. obj0@2687
UVM_INFO ./tb/test_pkg.sv(64) @ 0: uvm_test_top [COMPARE] Trying out compare_string
UVM_INFO @ 0: reporter [MISCMP] Miscompare for string1: lhs = "Hello" : rhs = "World"
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.data: lhs = 'h5a : rhs = 'hee
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.addr: lhs = 'h1 : rhs = 'h2
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.m_format0.header: lhs = 'hb : rhs = 'hf
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.m_format0.body: lhs = 'h1 : rhs = 'h2
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.m_format0.m_color.color: lhs = 'h8 : rhs = 'h7
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.m_format0.m_color.enable: lhs = 'h0 : rhs = 'h1
UVM_INFO @ 0: reporter [MISCMP] 6 Miscompare(s) for object obj0@2687 vs. obj1@2722
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.data: lhs = 'h5a : rhs = 'h2d
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.addr: lhs = 'h1 : rhs = 'h3
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.m_format0.header: lhs = 'hb : rhs = 'h9
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.m_format0.footer: lhs = 'h0 : rhs = 'h6
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.m_format0.enable: lhs = 'h1 : rhs = 'h0
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.m_format0.m_color.color: lhs = 'h8 : rhs = 'h0
UVM_INFO @ 0: reporter [MISCMP] Miscompare for obj1.m_format0.m_color.enable: lhs = 'h0 : rhs = 'h1
UVM_INFO @ 0: reporter [MISCMP] 7 Miscompare(s) for object obj0@2687 vs. obj1@2722

--- UVM Report catcher Summary ---

Using _decl macro in TLM

  1. How to use uvm_printer
-->

We have seen the scenario in TLM - Put, where data sent to componentB is executed using the put() method defined in B. Let us consider the case where there are two components A and C connected to B's export. Then, any data object sent by either componentA or componentC will be received by componentB and operated upon by the same put() method. If there's a need to be able to process them separately, you would need to have two separate put() methods.

componentA and componentC connected to same export

Read more: Using _decl macro in TLM

How to use uvm_printer

  1. Old-school style
  2. How its done in UVM
      1. Styles
      2. Usage
      3. Conditions
      4. Knobs
      5. Example
  3. UVM Factory Override
-->

In a random verification environment where data objects are being continuously generated and operated upon by different components, debug would become easier if contents of an object can be displayed.

Old-school style

Traditionally this is done by printing out values to either a logfile or screen via $display statements and custom print functions.


class Packet;
	bit [31:0]  addr;
	int         count_id;
	bit [3:0]   length;
	...
	function display ();
		$display ("addr=0x%0h count_id=0x%0h length=0x%0h", p1.addr, p1.count_id, p1.length);
	endfunction
endclass

module tb;
	initial begin
		Packet p1 = new();
		p1.display();
	end
endmodule

There was no built-in print mechanisms for a class which made testbench developers to write customized versions of print functions for every class like the display() method in the snippet above.

How its done in UVM

UVM avoids the need for customized print functions by incorporating its own uvm_printer class that takes care of all the required configurations to print class properties. It makes sense to include print features in uvm_object so that all child classes will automatically gain access to those features.

Every class item derived from uvm_object will have a printer instance within it. So, a data class derived from uvm_sequence_item or uvm_component will have access to the print() function as well. The major advantage UVM provides are the `uvm_field_* macros that automates the process of writing special print methods.


virtual class uvm_object extends uvm_void;
	...
	function void print (uvm_printer printer=null);
		if (printer==null)
    		printer = uvm_default_printer;
    	...
	endfunction
	...
endclass


Styles

There are three main printers in UVM and have the following display formats.

  • 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
      ---------------------------------------------------
    
  • Tree printer

      c1: (container@1013) {
        d1: (mydata@1022) {
             v1: 'hcb8f1c97
             e1: THREE
             str: hi
        }  
        value: 'h2d
      }
    
  • Line printer

      c1: (container@1013) { d1: (mydata@1022) { v1: 'hcb8f1c97 e1: THREE str: hi } value: 'h2d }
    


Usage

By default, UVM assigns table printer to handle every print() function, and hence is the uvm_default_printer. For convenience, global instances of each printer type are available for direct reference in your testbenches.

uvm_printer hierarchy

uvm_table_printer   uvm_default_table_printer = new();
uvm_tree_printer    uvm_default_tree_printer = new();
uvm_line_printer    uvm_default_line_printer = new();

uvm_printer uvm_default_printer = uvm_default_table_printer;

You can pass any of the three printer instance to the print() function to make it print in that particular style. Remember that the print() function receives a printer object.


class my_data extends uvm_sequence_item;
	bit [2:0] mode;
endclass

my_data obj0;
obj0.print ();                               // Calls table printer by default
obj0.print (uvm_default_line_printer);       // Calls line printer


Conditions

Calling print() is only possible if you do either of the two things.

  • Add any member that needs to be printed, within `uvm_object_utils_begin and `uvm_object_utils_end

  • 
    class my_data extends uvm_sequence_item;
       rand bit [7:0]   data;
       rand bit [7:0]   addr;
    
       constraint c_addr { addr > 0; addr < 8;}
    
       `uvm_object_utils_begin (my_data)
          `uvm_field_int (data, UVM_ALL_ON)
          `uvm_field_int (addr, UVM_ALL_ON)
       `uvm_object_utils_end
    
       function new (string name = "my_data");
          super.new (name);
       endfunction
    endclass  
    

    By applying variables to the macros, UVM automates these members to be included in the common utilties defined in uvm_object class namely, print(), copy(), compare(), etc

  • Define a do_print() function for the class

  • 
    class derivative extends my_data;
       `uvm_object_utils (derivative)
    
       rand bit [2:0] mode;
    
       function new (string name="derivative");
          super.new (name);
       endfunction
    
       virtual function void do_print (uvm_printer printer);
          printer.print_int ("mode", mode, $bits(mode));
          `uvm_info ("DVR", "do_print called", UVM_MEDIUM)
       endfunction
    endclass 
    

    If you did not use the utils_begin/end macros, you should define the do_print() method. Remember to use functions within the uvm_printer class to print.

Note that you can also do both the approaches together. The do_print() method will simply append whatever it is provided with to the macro.


class derivative extends my_data;

   rand bit [2:0] mode;
   rand bit [1:0] format;
   
   `uvm_object_utils_begin (derivative)
   		`uvm_field_int (format, UVM_ALL_ON)
   `uvm_object_utils_end

   function new (string name="derivative");
      super.new (name);
   endfunction

   virtual function void do_print (uvm_printer printer);
      printer.print_int ("mode", mode, $bits(mode));
      `uvm_info ("DVR", "do_print called", UVM_MEDIUM)
   endfunction
endclass 


Knobs

There is an instance of a class called uvm_printer_knobs within every printer. This can be used to change some of the settings and parameters used by the print() function.


uvm_default_printer.knobs.size = 0;                   // Will not display the size column
uvm_default_printer.knobs.indent = 4;                 // Indents to the right by 4 spaces instead of the default 2
uvm_default_printer.hex_radix = "0x";                 // Replaces the hex radix of 'h with 0x
Refer Class Definitions for full usage.



Example

example nested classes

First, we'll define a few data item objects. colors is nested inside format, which is inturn nested in the class my_data to create a nested hierarchy.


//---------------------- colors --------------------------
class colors extends uvm_sequence_item;
   rand bit [3:0] color;
   rand bit       enable;

   `uvm_object_utils_begin (colors)
      `uvm_field_int (color, UVM_ALL_ON)
      `uvm_field_int (enable, UVM_ALL_ON)
   `uvm_object_utils_end

endclass

//---------------------- format --------------------------
class format extends uvm_sequence_item;

   rand bit [3:0]    header;
   rand bit [2:0]    footer;
   rand bit          enable;
   rand bit [1:0]    body;
   rand colors       m_color;

   `uvm_object_utils_begin (format)
      `uvm_field_int (header, UVM_ALL_ON)
      `uvm_field_int (footer, UVM_ALL_ON)
      `uvm_field_int (enable, UVM_ALL_ON)
      `uvm_field_int (body, UVM_ALL_ON)
   `uvm_object_utils_end

   function new (string name = "format");
      super.new (name);
      m_color = colors::type_id::create ("m_color");
   endfunction

   virtual function void do_print (uvm_printer printer);
      printer.print_object ("m_color", m_color);
   endfunction
endclass


//---------------------- my_data --------------------------
class my_data extends uvm_sequence_item;
   rand format      m_format0;
   rand bit [7:0]   data;
   rand bit [7:0]   addr;

   constraint c_addr { addr > 0; addr < 8;}

   `uvm_object_utils_begin (my_data)
      `uvm_field_int (data, UVM_ALL_ON)
      `uvm_field_int (addr, UVM_ALL_ON)
      `uvm_field_object (m_format0, UVM_ALL_ON)
   `uvm_object_utils_end

   function new (string name = "my_data");
      super.new (name);
      m_format0 = format::type_id::create ("m_format0");
   endfunction
endclass 

//---------------------- derivative --------------------------
class derivative extends my_data;
   `uvm_object_utils (derivative)

   rand bit [2:0] mode;

   function new (string name="derivative");
      super.new (name);
   endfunction

   virtual function void do_print (uvm_printer printer);
      printer.knobs.depth=0;
      printer.print_int ("mode", mode, $bits(mode));
      `uvm_info ("DVR", "do_print called", UVM_MEDIUM)
   endfunction
endclass 

Note the following for the code shown above:

  • All the members of the class colors are added to the `uvm_object_utils_begin/end macro
  • All the class objects have to be instantiated either using new() or type_id::create()
  • In class format, all members except m_color is used in the macro, while m_color is used inside do_print() method
  • Class derivative adds the mode via do_print() method.

class base_test extends uvm_test;
   `uvm_component_utils (base_test)

   my_data obj0;
   derivative dv0;
   uvm_table_printer tprinter;

   function new (string name = "base_test", uvm_component parent);
      super.new (name, parent);
   endfunction

   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      obj0 = my_data::type_id::create ("obj0");
      dv0 = derivative::type_id::create ("dv0");
      tprinter = new();
      cfg_printer();
   endfunction

   virtual task run_phase (uvm_phase phase);
      void'(obj0.randomize());
      `uvm_info ("TST", "print() called with no arguments", UVM_MEDIUM)
      obj0.print ();     // uses uvm_default_printer

      `uvm_info ("TST", "Calling print (uvm_default_line_printer)", UVM_MEDIUM)
      obj0.print (uvm_default_line_printer);

      `uvm_info ("TST", "Calling print (uvm_default_tree_printer)", UVM_MEDIUM)
      obj0.print (uvm_default_tree_printer);

      `uvm_info ("TST", "Calling print (uvm_default_table_printer)", UVM_MEDIUM)
      obj0.print (uvm_default_table_printer);
      
      `uvm_info ("TST", "Calling print (tprinter)", UVM_MEDIUM)
      obj0.print (tprinter);
      
      `uvm_info ("TST", "Print derivative (tprinter)", UVM_MEDIUM)
      dv0.print (uvm_default_table_printer);
   endtask

   // Configuration to change display settings for the printer
   virtual function void cfg_printer ();
      tprinter.knobs.full_name = 1;               // Show full name of the variable relative to class instance
      tprinter.knobs.size = 0;                    // Do not show size column
      tprinter.knobs.depth = 1;                   // Only show upto 1 level of the nested hierarchy
      tprinter.knobs.reference = 2;               // Do not print object ID handles
      tprinter.knobs.type_name = 0;               // Do not show Type column
      tprinter.knobs.indent = 4;                  // Indent from the left by 4
      tprinter.knobs.hex_radix = "0x";            // Replace 'h radix by 0x - observe Value field to see this
   endfunction
endclass
 Simulation Log
----------------------------------------------------------------
CDNS-UVM-1.1d (14.22-s009)
(C) 2007-2013 Mentor Graphics Corporation
(C) 2007-2013 Cadence Design Systems, Inc.
(C) 2006-2013 Synopsys, Inc.
(C) 2011-2013 Cypress Semiconductor Corp.
----------------------------------------------------------------
UVM_INFO @ 0: reporter [RNTST] Running test base_test...
UVM_INFO ./tb/test_pkg.sv(34) @ 0: uvm_test_top [TST] print() called with no arguments
-----------------------------------
Name          Type      Size  Value
-----------------------------------
obj0          my_data   -     @2687
  data        integral  8     'h5a
  addr        integral  8     'h1
  m_format0   format    -     @2700
    header    integral  4     'hb
    footer    integral  3     'h0
    enable    integral  1     'h1
    body      integral  2     'h1
    m_color   colors    -     @2711
      color   integral  4     'h8
      enable  integral  1     'h0
-----------------------------------
UVM_INFO ./tb/test_pkg.sv(37) @ 0: uvm_test_top [TST] Calling print (uvm_default_line_printer)
obj0: (my_data@2687) { data: 'h5a  addr: 'h1  m_format0: (format@2700) { header: 'hb  footer: 'h0  enable: 'h1  body: 'h1  m_color: (colors@2711) { color: 'h8  enable: 'h0  } } }
UVM_INFO ./tb/test_pkg.sv(40) @ 0: uvm_test_top [TST] Calling print (uvm_default_tree_printer)
obj0: (my_data@2687) {
  data: 'h5a
  addr: 'h1
  m_format0: (format@2700) {
    header: 'hb
    footer: 'h0
    enable: 'h1
    body: 'h1
    m_color: (colors@2711) {
      color: 'h8
      enable: 'h0
    }
  }
}
UVM_INFO ./tb/test_pkg.sv(43) @ 0: uvm_test_top [TST] Calling print (uvm_default_table_printer)
-----------------------------------
Name          Type      Size  Value
-----------------------------------
obj0          my_data   -     @2687
  data        integral  8     'h5a
  addr        integral  8     'h1
  m_format0   format    -     @2700
    header    integral  4     'hb
    footer    integral  3     'h0
    enable    integral  1     'h1
    body      integral  2     'h1
    m_color   colors    -     @2711
      color   integral  4     'h8
      enable  integral  1     'h0
-----------------------------------
UVM_INFO ./tb/test_pkg.sv(46) @ 0: uvm_test_top [TST] Calling print (tprinter)
-------------------------
Name                Value
-------------------------
obj0                -
    obj0.data       0x5a
    obj0.addr       0x1
    obj0.m_format0  -
-------------------------
UVM_INFO ./tb/test_pkg.sv(49) @ 0: uvm_test_top [TST] Print derivative (tprinter)
UVM_INFO ./tb/my_pkg.sv(94) @ 0: reporter@@dv0 [DVR] do_print called
-------------------------------------
Name          Type        Size  Value
-------------------------------------
dv0           derivative  -     @2722
  data        integral    8     'h0
  addr        integral    8     'h0
  m_format0   format      -     @2732
    header    integral    4     'h0
    footer    integral    3     'h0
    enable    integral    1     'h0
    body      integral    2     'h0
    m_color   colors      -     @2741
      color   integral    4     'h0
      enable  integral    1     'h0
  mode        integral    3     'h0
-------------------------------------

--- UVM Report catcher Summary ---

UVM Factory Override

  1. Factory Override Methods
  2. Method Examples
    1. 1. Type override by Type/Name
    2. 2. Instance override by Type/Name
  3. Why is UVM factory required ?
  4. Practical Example
-->

UVM factory is a mechanism to improve flexibility and scalability of the testbench by allowing the user to substitute an existing class object by any of its inherited child class objects.

For this purpose, the factory needs to know all the types of classes created within the testbench by a process called as registration. There are UVM macros that allow classes to be registered with the factory, and methods that allow certain types and instances of class objects to be overridden by its derived types.

factory

Factory Override Methods


// Override all the objects of a particular type
set_type_override_by_type ( uvm_object_wrapper original_type, 
                            uvm_object_wrapper override_type, 
                            bit replace=1);
 
set_type_override_by_name ( string original_type_name,
                            string override_type_name,
                            bit replace=1);
 
// Override a type within a particular instance
set_inst_override_by_type (uvm_object_wrapper original_type,
                           uvm_object_wrapper override_type,
                           string full_inst_path);
 
set_inst_override_by_name (string original_type_name,
                           string override_type_name,
                           string full_inst_path);

Method Examples

Shown below is an example testbench structure comprising of a base agent inside a base environment that is instantiated within the test class. We will try to use factory override methods to override the base class with child class.


// Define a base class agent
class base_agent extends uvm_agent;
  `uvm_component_utils(base_agent)
  function new(string name, uvm_component parent);
    super.new(name, parent);
  endfunction
endclass

// Define child class that extends base agent
class child_agent extends base_agent;
  `uvm_component_utils(child_agent)
  function new(string name, uvm_component parent);
    super.new(name, parent);
  endfunction
endclass

// Environment contains the agent
class base_env extends uvm_env;
  `uvm_component_utils(base_env)
  function new(string name, uvm_component parent);
    super.new(name, parent);
  endfunction
  
  // 'm_agent' is a class handle to hold base_agent
  // type class objects
  base_agent m_agent;
  
  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    
    // Use create method to request factory to return a base_agent
    // type of class object
    m_agent = base_agent::type_id::create("m_agent", this);
    
    // Now print the type of the object pointing to by the 'm_agent' class handle
    `uvm_info("AGENT", $sformatf("Factory returned agent of type=%s, path=%s", m_agent.get_type_name(), m_agent.get_full_name()), UVM_LOW)
  endfunction
endclass

1. Type override by Type/Name


class base_test extends uvm_test;
  `uvm_component_utils(base_test)
  function new(string name, uvm_component parent);
    super.new(name, parent);
  endfunction
  
  base_env m_env;
  
  virtual function void build_phase(uvm_phase phase);
  	// Get handle to the singleton factory instance
    uvm_factory factory = uvm_factory::get();
    
    super.build_phase(phase);

    // Set factory to override 'base_agent' by 'child_agent' by type
    set_type_override_by_type(base_agent::get_type(), child_agent::get_type());
    
    // Or set factory to override 'base_agent' by 'child_agent' by name
    // factory.set_type_override_by_name("base_agent", "child_agent");
    
    // Print factory configuration
    factory.print();
    
    // Now create environment 
    m_env = base_env::type_id::create("m_env", this);
  endfunction
endclass

The following log shows that a type override is configured and replaces base_agent with child_agent . This is also evident from the info statement that prints type of the returned object.

 Simulation Log
UVM_INFO @ 0: reporter [RNTST] Running test base_test...
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_factory.svh(1645) @ 0: reporter [UVM/FACTORY/PRINT] 
#### Factory Configuration (*)

No instance overrides are registered with this factory

Type Overrides:

  Requested Type  Override Type
  --------------  -------------
  base_agent      child_agent

All types registered with the factory: 54 total
  Type Name
  ---------
  base_agent
  base_env
  base_test
  child_agent
(*) Types with no associated type name will be printed as 

####


UVM_INFO testbench.sv(32) @ 0: uvm_test_top.m_env [AGENT] Factory returned agent of type=child_agent, path=uvm_test_top.m_env.m_agent
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_report_server.svh(847) @ 0: reporter [UVM/REPORT/SERVER] 
--- UVM Report Summary ---

2. Instance override by Type/Name

This is most useful when only a few instances of the given type has to be overriden. A type override by type will replace all instances of the given type by the new type.


class base_test extends uvm_test;
  `uvm_component_utils(base_test)
  function new(string name, uvm_component parent);
    super.new(name, parent);
  endfunction
  
  base_env m_env;
  
  virtual function void build_phase(uvm_phase phase);
  	// Get handle to the singleton factory instance
    uvm_factory factory = uvm_factory::get();
    
    super.build_phase(phase);

    // Set factory to override all instances under m_env of type 'base_agent' by 'child_agent'
    set_inst_override_by_type("m_env.*", base_agent::get_type(), child_agent::get_type());
    
    // Or set factory to override all instances under 'm_env' called 'base_agent' by 'child_agent' by name
    // factory.set_inst_override_by_name("base_agent", "child_agent", {get_full_name(), ".m_env.*"});
    
    // Print factory configuration
    factory.print();
    
    // Now create environment 
    m_env = base_env::type_id::create("m_env", this);
  endfunction
endclass
 Simulation Log
UVM_INFO @ 0: reporter [RNTST] Running test base_test...
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_factory.svh(1645) @ 0: reporter [UVM/FACTORY/PRINT] 
#### Factory Configuration (*)

Instance Overrides:

  Requested Type  Override Path         Override Type
  --------------  --------------------  -------------
  base_agent      uvm_test_top.m_env.*  child_agent

No type overrides are registered with this factory

All types registered with the factory: 54 total
  Type Name
  ---------
  base_agent
  base_env
  base_test
  child_agent
(*) Types with no associated type name will be printed as 

####


UVM_INFO testbench.sv(32) @ 0: uvm_test_top.m_env [AGENT] Factory returned agent of type=child_agent, path=uvm_test_top.m_env.m_agent
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_report_server.svh(847) @ 0: reporter [UVM/REPORT/SERVER] 
--- UVM Report Summary ---

Why is UVM factory required ?

The new function is used in SystemVerilog to create a class object and is perfectly valid to be used in UVM as well. Assume that an existing testbench uses Wishbone v1.0 protocol data packet class and is used throughout the testbench in components like driver, monitor, scoreboard, and many other sequences. If Wishbone v2.0 is released and the testbench is required to update and start using packet definition for the new protocol, there would be many places in the testbench that would require an update in code which can prove to be cumbersome.


class wb_seq extends uvm_sequence_item;
	...
	
	virtual task body();
		// new() function allocates space for the new class object
		// and assigns the handle 'm_wb_pkt' to new object
		wb_pkt m_wb_pkt = new();
		
		// This new object may be used everywhere in the sequence
		start_item(m_wb_pkt);
		m_wb_pkt.randomize();
		...
	endtask
	
endclass

UVM has a feature called factory which allows users to modify or substitute type of the item created by the factory without having to modify existing class instantiations. Instead of text substitution of class name of existing data packet, a child class object can be created that makes necessary modifications for 2.0 and the factory can be used to return the newly defined class object in all places within the testbench instead of the first one. So, the preferred method of object creation in UVM testbench is by using create method.


class wb_seq extends uvm_sequence_item;
	...
	
	virtual task body();
		// By calling create() method, the factory will create an instance of the requested 
		// type and assign the handle 'm_wb_pkt' to the new object. This override of type 
		// can be done at a higher level like the test class
		wb_pkt m_wb_pkt = wb_pkt::type_id::create("wb_pkt", this);
		
		// This new object may be used everywhere in the sequence
		start_item(m_wb_pkt);
		m_wb_pkt.randomize();
		...
	endtask
	
endclass

Practical Example

To illustrate the example of a factory override, we'll create an environment as shown above with a couple of different drivers, sequences, and data object types. The image shown above is the default configuration.

factory override default configuration
Components:
- Agents 
	- my_agent         (Base)
		1. my_agent_v2   (child)
- Drivers
	base_driver       (Base)
	 	1. eth_driver   (child)
		2. spi_driver   (child)
- Sequencer - my_seqeuncer
- Sequences
	- base_sequence   (Base)
		1. seq1         (child)
		2. seq2         (child)
		3. seq3         (child)
- Data
	- eth_packet        (Basse)
		- eth_v2_packet   (child)

Sequencer within m_agnt2 operate on seq3, while the other two operate on seq1 by default.
example inheritance diagram

Let us first define a base data packet and derive a child class for it.


//------------------ eth_packet-----------------------------------
class eth_packet extends uvm_sequence_item;
   `uvm_object_utils (eth_packet)

	...

   function new (string name = "eth_packet");
      super.new (name);
      `uvm_info (get_type_name(), "Packet created", UVM_MEDIUM)
   endfunction
endclass   

//------------------ eth_v2_packet-----------------------------------
class eth_v2_packet extends eth_packet; 
   `uvm_object_utils (eth_v2_packet)

 	...
   
   function new (string name = "eth_v2_packet");
      super.new (name);
   endfunction
endclass  

Now let us create a base driver class and extend two more driver classes eth_driver and spi_driver. To show the effect of a factory override, we'll keep these classes to have minimum data and methods.


//------------------ base_driver-----------------------------------

class base_driver #(type T=eth_packet) extends uvm_driver;
   `uvm_component_utils (base_driver #(T))

   T pkt;

   function new (string name, uvm_component parent);
      super.new (name, parent);
   endfunction

   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      pkt = T::type_id::create ("pkt0");
   endfunction

   virtual task run_phase (uvm_phase phase);
      super.run_phase (phase);
      `uvm_info (get_type_name(), $sformatf("Driver running ...with packet of type : %s", pkt.get_type_name()), UVM_MEDIUM)
   endtask

endclass

//----------------- eth_driver-----------------------------------

class eth_driver #(type T=eth_packet) extends base_driver #(T);
   `uvm_component_utils (eth_driver #(T))

   function new (string name, uvm_component parent);
      super.new (name, parent);
   endfunction
endclass

//----------------- spi_driver-----------------------------------

class spi_driver #(type T=eth_packet) extends base_driver #(T); 
   `uvm_component_utils (spi_driver #(T))

   function new (string name, uvm_component parent);
      super.new (name, parent);
   endfunction
endclass 

Coming to the sequences which will be executed by our sequencer


//----------------- base_sequence-----------------------------------
class base_sequence extends uvm_sequence;
	`uvm_object_utils (base_sequence)
endclass

//----------------- seq1 -------------------------------------------
class seq1 extends base_eth_sequence;
   `uvm_object_utils (seq1)
	...
endclass

//----------------- seq2 -------------------------------------------
class seq2 extends base_eth_sequence;
   `uvm_object_utils (seq2)
   ...
endclass

//----------------- seq3 -------------------------------------------
class seq3 extends base_eth_sequence;
   `uvm_object_utils (seq3)
	...
endclass

We'll create two agents as described below.


//----------------- my_agent -------------------------------------------
class my_agent extends uvm_agent;
   `uvm_component_utils (my_agent)

   base_driver    m_drv0;
   my_sequencer   m_seqr0;

   function new (string name, uvm_component parent);
      super.new (name, parent);
   endfunction

   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      m_drv0 = base_driver::type_id::create ("m_drv0", this);
      m_seqr0 = my_sequencer::type_id::create ("m_seqr0", this);
   endfunction

   virtual function void connect_phase (uvm_phase phase);
      super.connect_phase (phase);
      m_drv0.seq_item_port.connect (m_seqr0.seq_item_export);
   endfunction
endclass

//----------------- my_agent_v2 -------------------------------------------
class my_agent_v2 extends uvm_agent;
   `uvm_component_utils (my_agent_v2)

   eth_driver     m_drv0;
   my_sequencer   m_seqr0;

   function new (string name, uvm_component parent);
      super.new (name, parent);
   endfunction

   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      m_drv0 = eth_driver::type_id::create ("m_drv0", this);
      m_seqr0 = my_sequencer::type_id::create ("m_seqr0", this);
   endfunction

   virtual function void connect_phase (uvm_phase phase);
      super.connect_phase (phase);
      m_drv0.seq_item_port.connect (m_seqr0.seq_item_export);
   endfunction
endclass

Note that my_agent has base_driver, while my_agent_v2 contains eth_driver. All drivers and sequencers are instantiated within the build_phase() and connected in connect_phase().

The top container "my_env" is still left.


class my_env extends uvm_env ;
   `uvm_component_utils (my_env)

   my_agent       m_agnt0; 
   my_agent       m_agnt1; 
   my_agent_v2    m_agnt2;

   function new (string name, uvm_component parent);
      super.new (name, parent);
   endfunction : new

   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      m_agnt0 = my_agent::type_id::create ("m_agnt0", this);
      m_agnt1 = my_agent::type_id::create ("m_agnt1", this);
      m_agnt2 = my_agent_v2::type_id::create ("m_agnt2", this);
   endfunction : build_phase
endclass : my_env

We have put our components into boxes, and arranged everything. It's time to write the test, and this is where factory override helps. We'll be able to substitute drivers, data packets and sequences by calling a few factory methods.

factory override configuration

   class feature_test extends base_test;
      `uvm_component_utils (feature_test)

      function new (string name, uvm_component parent = null);
         super.new (name, parent);
      endfunction 

      virtual function void build_phase (uvm_phase phase);
         super.build_phase (phase); 

`ifdef PKT_OVERRIDE
         // Substitute all eth_packets with eth_v2_packet
         set_type_override_by_type (eth_packet::get_type(), eth_v2_packet::get_type());
`endif



// These are the three different styles to override something

`ifdef DRV_STYLE1
         // Substitute all instances of base_driver with driver2 
         set_type_override_by_type (base_driver::get_type(), spi_driver::get_type());
`elsif DRV_STYLE2
         // Substitute only eth_driver in agnt2 with spi_driver - by calling the component to be replaced method
         eth_driver::type_id::set_inst_override (spi_driver::get_type(), "m_top_env.m_agnt2.m_drv0", this);
`elsif DRV_STYLE3
         // Substitute base_driver only in agnt0 - by calling the factory method
         factory.set_inst_override_by_type (base_driver::get_type(), eth_driver::get_type(), {get_full_name(), ".m_top_env.m_agnt0.*"});
`endif



// Trying to override a sequence

`ifdef SEQ_TYPE
         // Substitute seq1 with seq2
         set_type_override_by_type (seq1::get_type(), seq3::get_type());
`elsif SEQ_INST
         // Substitute seq1 with seq2 only for agnt1
         set_inst_override_by_type ("m_top_env.m_agnt1.m_seqr0.*", seq1::get_type(), seq2::get_type());
`else
`endif
         factory.print();
      endfunction
      // Enter test code for feature here
   endclass

These results are for running the test with defines PKT_OVERRIDE, DRV_STYLE3 and SEQ_INST. Also, note that the factory configuration is shown in the log.

 Simulation Log
----------------------------------------------------------------
CDNS-UVM-1.1d (14.10-s013)
(C) 2007-2013 Mentor Graphics Corporation
(C) 2007-2013 Cadence Design Systems, Inc.
(C) 2006-2013 Synopsys, Inc.
(C) 2011-2013 Cypress Semiconductor Corp.
----------------------------------------------------------------
UVM_INFO @ 0: reporter [RNTST] Running test feature_test...

#### Factory Configuration (*)

Instance Overrides:

  Requested Type    Override Path                             Override Type
  ----------------  ----------------------------------------  ---------------
  base_driver #(T)  uvm_test_top.m_top_env.m_agnt0.*          eth_driver #(T)
  seq1              uvm_test_top.m_top_env.m_agnt1.m_seqr0.*  seq2

Type Overrides:

  Requested Type    Override Type
  ----------------  ----------------------------------------
  eth_packet        eth_v2_packet

All types registered with the factory: 51 total
(types without type names will not be printed)

  Type Name
  ---------
  base_driver #(T)
  base_eth_sequence
  base_test
  eth_driver #(T)
  eth_packet
  eth_v2_packet
  feature_test
  my_agent
  my_agent_v2
  my_env
  my_sequencer
  reg_test
  seq1
  seq2
  seq3
(*) Types with no associated type name will be printed as 

####

UVM_INFO ./tb/my_pkg.sv(45) @ 0: reporter@@eth_v2_packet [eth_v2_packet] Packet created
UVM_INFO ./tb/my_pkg.sv(45) @ 0: reporter@@eth_v2_packet [eth_v2_packet] Packet created
UVM_INFO ./tb/my_pkg.sv(45) @ 0: reporter@@eth_v2_packet [eth_v2_packet] Packet created
UVM_INFO @ 0: reporter [UVMTOP] UVM testbench topology:
--------------------------------------------------------------
Name                       Type                    Size  Value
--------------------------------------------------------------
uvm_test_top               feature_test            -     @2657
  m_top_env                my_env                  -     @218
    m_agnt0                my_agent                -     @2772
      m_drv0               eth_driver #(T)         -     @2770
        rsp_port           uvm_analysis_port       -     @2963
        seq_item_port      uvm_seq_item_pull_port  -     @2912
      m_seqr0              my_sequencer            -     @2996
        rsp_export         uvm_analysis_export     -     @3054
        seq_item_export    uvm_seq_item_pull_imp   -     @3602
        arbitration_queue  array                   0     -
        lock_queue         array                   0     -
        num_last_reqs      integral                32    'd1
        num_last_rsps      integral                32    'd1
    m_agnt1                my_agent                -     @2751
      m_drv0               base_driver #(T)        -     @3676
        rsp_port           uvm_analysis_port       -     @3773
        seq_item_port      uvm_seq_item_pull_port  -     @3725
      m_seqr0              my_sequencer            -     @3754
        rsp_export         uvm_analysis_export     -     @3859
        seq_item_export    uvm_seq_item_pull_imp   -     @4399
        arbitration_queue  array                   0     -
        lock_queue         array                   0     -
        num_last_reqs      integral                32    'd1
        num_last_rsps      integral                32    'd1
    m_agnt2                my_agent_v2             -     @2802
      m_drv0               eth_driver #(T)         -     @4455
        rsp_port           uvm_analysis_port       -     @4553
        seq_item_port      uvm_seq_item_pull_port  -     @4505
      m_seqr0              my_sequencer            -     @3803
        rsp_export         uvm_analysis_export     -     @4639
        seq_item_export    uvm_seq_item_pull_imp   -     @5179
        arbitration_queue  array                   0     -
        lock_queue         array                   0     -
        num_last_reqs      integral                32    'd1
        num_last_rsps      integral                32    'd1
--------------------------------------------------------------

UVM_INFO ./tb/my_pkg.sv(94) @ 0: uvm_test_top.m_top_env.m_agnt2.m_drv0 [eth_driver #(T)] Driver running ...with packet of type : eth_v2_packet
UVM_INFO ./tb/my_pkg.sv(94) @ 0: uvm_test_top.m_top_env.m_agnt1.m_drv0 [base_driver #(T)] Driver running ...with packet of type : eth_v2_packet
UVM_INFO ./tb/my_pkg.sv(94) @ 0: uvm_test_top.m_top_env.m_agnt0.m_drv0 [eth_driver #(T)] Driver running ...with packet of type : eth_v2_packet
UVM_INFO ./tb/my_pkg.sv(278) @ 0: uvm_test_top.m_top_env.m_agnt2.m_seqr0@@seq3 [seq3] Executing pre_body
UVM_INFO ./tb/my_pkg.sv(250) @ 0: uvm_test_top.m_top_env.m_agnt1.m_seqr0@@seq1 [seq2] Executing pre_body
UVM_INFO ./tb/my_pkg.sv(282) @ 0: uvm_test_top.m_top_env.m_agnt2.m_seqr0@@seq3 [SEQ3] Starting seq3
UVM_INFO ./tb/my_pkg.sv(255) @ 0: uvm_test_top.m_top_env.m_agnt1.m_seqr0@@seq1 [SEQ2] Starting seq2
UVM_INFO ./tb/my_pkg.sv(232) @ 0: uvm_test_top.m_top_env.m_agnt0.m_seqr0@@seq1 [SEQ1] Starting seq1
UVM_INFO ./tb/my_pkg.sv(284) @ 10000: uvm_test_top.m_top_env.m_agnt2.m_seqr0@@seq3 [SEQ3] Ending seq3
UVM_INFO ./tb/my_pkg.sv(257) @ 10000: uvm_test_top.m_top_env.m_agnt1.m_seqr0@@seq1 [SEQ2] Ending seq2
UVM_INFO ./tb/my_pkg.sv(234) @ 10000: uvm_test_top.m_top_env.m_agnt0.m_seqr0@@seq1 [SEQ1] Ending seq1
UVM_INFO ./tb/my_pkg.sv(288) @ 10000: uvm_test_top.m_top_env.m_agnt2.m_seqr0@@seq3 [seq3] Executing post_body
UVM_INFO ./tb/my_pkg.sv(262) @ 10000: uvm_test_top.m_top_env.m_agnt1.m_seqr0@@seq1 [seq2] Executing post_body
UVM_INFO ./tb/my_pkg.sv(292) @ 10000: uvm_test_top.m_top_env.m_agnt2.m_seqr0@@seq3 [seq3] Executing post_start

--- UVM Report catcher Summary ---
  1. Using the sequence library
  2. Executing sequence macros
  3. How to execute sequences via start( )
  4. How to use `uvm_do sequence macros ?
  5. How to create and use a sequence

Page 45 of 63

  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
Interview Questions
  Verilog Interview Set 1
  Verilog Interview Set 2
  Verilog Interview Set 3
  Verilog Interview Set 4
  Verilog Interview Set 5

  SystemVerilog Interview Set 1
  SystemVerilog Interview Set 2
  SystemVerilog Interview Set 3
  SystemVerilog Interview Set 4
  SystemVerilog Interview Set 5

  UVM Interview Set 1
  UVM Interview Set 2
  UVM Interview Set 3
  UVM Interview Set 4
Related Topics
  Digital Fundamentals
  Verilog Tutorial

  Verification
  SystemVerilog Tutorial
  UVM Tutorial
  • Verilog Testbench
  • Verilog Coding Style Effect
  • Verilog Conditional Statements
  • Verilog Interview Set 10
  • Synchronous FIFO
  • SystemVerilog Interview Set 10
  • SystemVerilog Interview Set 9
  • SystemVerilog Interview Set 8
  • SystemVerilog Interview Set 7
  • SystemVerilog Interview Set 6
  • UVM Singleton Object
  • UVM Component [uvm_component]
  • UVM Object [uvm_object]
  • UVM Root [uvm_root]
  • UVM Interview Set 4
© 2015 - 2023 ChipVerify
Terms and Conditions | DMCA.com Protection Status