Thursday, March 19, 2015

Important notes on inheritance and factory registration of parametrized classes in UVM-1.1


For last 2 days I was busy making an understanding about inheriting/handling and overriding parametrized classes. I have noted some important things which we may overlook. I hope this will prove useful to us J

Following are the points to note while using parametrized classes in uvm (Can also be useful in pure systemverilog).
1)      While defining a parametrized class make sure to use either one of following macros
a.       `uvm_component_param_utils
b.      `uvm_object_param_utils

2)      While extending a parametrized class, make sure that the extended class is also parametrized. For example there are three classes, class fruit, class apple and class orange. Apple extends from fruit and orange extends from apple. Then they should be extended as following.
class fruit#(int PRICE = 32) extends uvm_component
class apple#(int PRICE = 32) extends fruit#(PRICE)
class orange#(int PRICE = 32, int QNTTY=1) extends apple#(PRICE)

3)      Macros `uvm_component_param_utils are little different from the `uvm_component_utils.
a.       `uvm_component_utils assigns ‘type_name’ to a class and also define a function get_type_name() for that class. (get_type_name() function is the same function which we mostly used while using `uvm_info macro)
b.      `uvm_component_param_utils does not define ‘type_name’ or get_type_name() function. It should be defined manually else whenever we use get_type_name() it will not give expected string.
c.       ‘type_name’ and get_type_name() are also important while looking up factory using get_name()

Following example can be referred for better understanding:
~/proj/uvm-1.2/examples/simple/registers/integration/10direct/tmp.sv.html
 1 //file name :  parametrized_class_uvm_example.sv
 2 package my_pkg;
 3   import uvm_pkg::*;
 4   `include "uvm_macros.svh"
 5 
 6   class fruit#(int PRICE = 32) extends uvm_component;
 7     `uvm_component_param_utils(fruit#(PRICE)id)
 8     const static string type_name = {"fruit #(",$psprintf("%0d",PRICE),")"};
 9     virtual function string get_type_name ();
10       return type_name;
11     endfunction
12 
13     function new(string name, uvm_component parent);
14       super.new(name,parent);
15     endfunction : new
16     task run_phase (uvm_phase phase);
17       `uvm_info(get_type_name(),"run_phase: Executing.   fruit run_phase<<<<",UVM_LOW)
18       `uvm_info(get_type_name(),$psprintf("run_phase: Executing.   fruit run_phase<<<<, PRICE=%0d",PRICE),UVM_LOW)
19     endtask : run_phase
20     function print_val();
21       `uvm_info(get_type_name(),$psprintf("print_val: Executing.   print_val run_phase<<<<, PRICE=%0d",PRICE),UVM_LOW)
22     endfunction
23   endclass : fruit
24 
25   class apple#(int PRICE = 32) extends fruit#(PRICE);
26     `uvm_component_param_utils(apple#(PRICE))
27     const static string type_name = {"apple #(",$psprintf("%0d",PRICE),")"};
28       virtual function string get_type_name ();
29       return type_name;
30     endfunction
31       function new(string name, uvm_component parent);
32       super.new(name,parent);
33     endfunction : new
34     task run_phase (uvm_phase phase);
35       `uvm_info("UVC","run_phase: Executing.   Apple run_phase<<<",UVM_LOW)
36       `uvm_info("UVC",$psprintf("run_phase: Executing.   Apple run_phase<<<<, PRICE=%0d",PRICE),UVM_LOW)
37     endtask : run_phase
38   endclass : apple
39 
40   class orange#(int PRICE = 32, int QNTTY=1) extends apple#(PRICE);
41 
42     `uvm_component_param_utils(orange#(PRICE,QNTTY))
43     const static string type_name = {"orange #(",$psprintf("%0d",PRICE),")"};
44       virtual function string get_type_name ();
45       return type_name;
46     endfunction
47     function new(string name, uvm_component parent);
48       super.new(name,parent);
49     endfunction : new
50     task run_phase (uvm_phase phase);
51       `uvm_info(get_type_name(),$psprintf("run_phase: Executing.   Orange run_phase<<<<, PRICE=%0d, QNTTY=%0d",PRICE,QNTTY),UVM_LOW)
52       print_val();
53     endtask : run_phase
54   endclass : orange
55 
56   class my_testbench extends uvm_component;
57     `define FRUIT_PRICE 22
58     fruit#(`FRUIT_PRICE) my_uvc;
59     `uvm_component_utils(my_testbench)
60 
61     function new(string name, uvm_component parent);
62       super.new(name, parent);
63     endfunction : new
64     function void build_phase(uvm_phase phase);
65       super.build_phase(phase);
66       fruit#(`FRUIT_PRICE)::type_id::set_type_override(orange#(`FRUIT_PRICE,2)::get_type()); //Replace fruit with pine
67       my_uvc=fruit#(`FRUIT_PRICE)::type_id::create("my_uvc",this);
68     endfunction : build_phase
69 
70     task run_phase (uvm_phase phase);
71     `uvm_info("TESTBENCH","run_phase: Executing.  Testbench run_phase<<<<",UVM_LOW)
72     endtask : run_phase
73   endclass : my_testbench
74 endpackage : my_pkg
75 
76 module top;
77   import uvm_pkg::*;
78   `include "uvm_macros.svh"
79   import my_pkg::*;
80 
81   my_testbench testbench;
82 
83   initial begin
84     $display("******Start of Sim w/ the kids*******************");
85     testbench = my_testbench::type_id::create("testbench",null);
86     run_test();
87   end
88 endmodule : top


If you are using synopsys tool, your VCS_HOME, UVM_HOME and license file are pointing to correct locations then you can also simulate this using following command :

vcs -sverilog +incdir+$UVM_HOME $UVM_HOME/uvm_pkg.sv -ntb_opts uvm-1.1 -R +vcs+lic+wait parametrized_class_uvm_example.sv