[CU]field_automation机制2-uvm field automation机制与copy,compare等操作的联系(注意create函数,copy函数,clone函数)

资料来源:

(1) The UVM Primer;

(2) uvm source code;

(3) UVM1.1应用指南及源代码分析;

注1:field automation机制的本质是覆盖了uvm_object类中的m_uvm_field_automation函数,而不是定义了copy等函数,也不是定义了do_copy等函数;

注2:field automation机制使得我们可以不用定义do_copy,do_compare函数,而直接使用copy, compare等操作;但是如果需要特殊的处理或者field automation机制不能满足user需求,可以定义do_copy, do_compare等函数(《practical UVM step by step with IEEE》);

注3:如果没有采用field automation机制,并且需要用到copy, compare等函数,那么需要在派生类中定义do_copy,do_compare等函数;

1.uvm_object中create/copy/clone/compare等操作

1.1create函数

 1   // Function: create
 2   //
 3   // The ~create~ method allocates a new object of the same type as this object
 4   // and returns it via a base uvm_object handle. Every class deriving from
 5   // uvm_object, directly or indirectly, must implement the create method.
 6   //
 7   // A typical implementation is as follows:
 8   //
 9   //|  class mytype extends uvm_object;
10   //|    ...
11   //|    virtual function uvm_object create(string name="");
12   //|      mytype t = new(name);
13   //|      return t;
14   //|    endfunction 
15 
16 `ifdef UVM_CREATE_OPT 
17     virtual function void call_new(); endfunction 
18     virtual function uvm_object create (string name=""); 
19        uvm_object res = $__vcs_new($__vcs_class_handle_obj(this)); 
20        res.call_new(); 
21        if (name!="") res.set_name(name); 
22        return res; 
23     endfunction
24 `else
25   virtual function uvm_object create (string name=""); return null; endfunction
26 `endif

1.2 copy函数

 1 function void uvm_object::copy (uvm_object rhs);
 2   //For cycle checking
 3   static int depth;
 4   if((rhs !=null)  && uvm_global_copy_map.exists(rhs)) begin
 5     return;
 6   end
 7 
 8   if(rhs==null) begin
 9     uvm_report_warning("NULLCP", "A null object was supplied to copy; copy is ignored", UVM_NONE);
10     return;
11   end
12 
13   uvm_global_copy_map[rhs]= this; 
14   ++depth;
15 
16   __m_uvm_field_automation(rhs, UVM_COPY, "");
17   do_copy(rhs);
18 
19   --depth;
20   if(depth==0) begin
21     uvm_global_copy_map.delete();
22   end
23 endfunction
1 function void uvm_object::__m_uvm_field_automation (uvm_object tmp_data__,
2                                               int        what__,
3                                               string     str__ );
4   return;
5 endfunction
1 function void uvm_object::do_copy (uvm_object rhs);
2   return;
3 endfunction
 1 module top;
 2  `include "uvm_macros.svh"
 3  import uvm_pkg::*;
 4  ...
 5 
 6  class_P  class_P_inst1;
 7  class_P  class_P_inst2;
 8  initial begin
 9 
10     class_P_inst1 = new("first_inst");
11     class_P_inst1.randomize();
12     class_P_inst1.print();
13     
14     class_P_inst2 = new("second_inst");
15     class_P_inst2.randomize();
16     class_P_inst2.print();
17 
18     class_P_inst2.copy(class_P_inst1);
19     class_P_inst2.print();
20 
21  end 
22 endmodule

1.3 clone(clone=create+copy)

注1:如果使用clone函数,uvm_object的派生类需要实现create函数;

注2:如果uvm_object派生类在定义时,使用factory机制,那么create函数会自动被定义;

注3:create函数的本质是new,所以说clone=new+copy没有问题;

注4:clone返回的类型是uvm_object,后续使用时可能需要调用$cast进行类型转换;

1 function uvm_object uvm_object::clone();
2   uvm_object tmp;
3   tmp = this.create(get_name());
4   if(tmp == null)
5     uvm_report_warning("CRFLD", $sformatf("The create method failed for %s,  object cannot be cloned", get_name()), UVM_NONE);
6   else
7     tmp.copy(this);
8   return(tmp);
9 endfunction
 1 // Class definition
 2 class class_A extends uvm_object;
 3 
 4     int cl_int;
 5     string cl_string;
 6     int cl_int_arr[];
 7     longint unsigned logic_data[int];
 8 
 9     `uvm_object_utils_begin(class_A)
10             `uvm_field_int(cl_int,UVM_ALL_ON)
11             `uvm_field_string(cl_string,UVM_ALL_ON)
12             `uvm_field_array_int(cl_int_arr,UVM_ALL_ON)
13             `uvm_field_aa_int_longint_unsigned(logic_data,UVM_ALL_ON)
14     `uvm_object_utils_end
15     
16     function void set_value(int value);    
17         cl_int=value;
18     endfunction
19 
20     function new(string name="");
21         super.new(name);    
22         cl_string = name;
23         set_value(10);
24         cl_int_arr = new[cl_int];
25         for(int i = 0; i < cl_int; i++) begin
26             cl_int_arr[i] = i + 1;
27         end
28     endfunction
29 
30 endclass
31 
32 
33 //clone使用示例
34 module top;
35     import uvm_pkg::*;
36     `include "uvm_macros.svh"
37     ...
38     class_A claass_A_inst1;
39     class_A claass_A_inst2;
40 
41     initial begin
42         class_A_inst1=new("child_inst1");
43         class_A_inst1.randomize();
44         class_A_inst1.print();
45         $cast(class_A_inst2, class_A_inst1.clone());
46         class_A_inst2.print();    
47 
48     end
49 endmodule

1.4 compare函数以及其与uvm_default_comparer的结合使用

注1:注意uvm_comparer的使用;

注2:uvm_field_*宏会调用uvm_comparer的compare_*函数,而uvm_comparer的compare_*函数在比较失败时,会调用comparer.print_msg函数,print_msg函数内会对comparer.result进行累加(comparer.result的初始值为0); comparer.result会反映到uvm_object/uvm_component的compare函数返回值上,如果comparer.result!=0,那么uvm_object/uvm_component的compare函数的返回值一定为0,表示compare mismatch;

 1 module top;
 2    `include "uvm_macros.svh"
 3    import uvm_pkg::*;
 4    ...
 5 
 6    class_P class_P_inst1;
 7    class_P class_P_inst2;
 8    bit result;
 9    initial begin
10       uvm_comparer c_comp=new(); //该处也可以使用uvm_comparer c_comp=uvm_comparer::init();
11       c_comp.show_max=1;
12       c_comp.severity=UVM_WARNING;
13 
14       class_P_inst1 = new("class_P_inst1");
15       class_P_inst2 = new("class_P_inst2");
16 
17       class_P_inst1.randomize();
18       class_P_inst2.randomize();
19       
20       class_P_inst2.copy(class_P_inst1);
21 
22       `uvm_info("Compare 1","comparison of identical classes",UVM_LOW)
23       result=class_P_inst1.compare(class_P_inst2, c_comp); //如果不指定comparer,则默认采用uvm_default_comparer;
24       //result=1, compare match!!!
25       class_P_inst1.logic_data[16] = 2;
26       class_P_inst1.logic_data[32] = 2;
27       class_P_inst1.logic_data[64] = 2;
28       class_P_inst1.logic_data[128]= 1;
29 
30       `uvm_info("Compare 2","comparison of nonidentical classes",UVM_LOW)
31       result=class_P_inst1.compare(class_P_inst2, c_comp);
32       //result=0, compare mismatch!!!
33    end 
34 endmodule

1.5 print & sprint & do_print

(1) print与sprint的区别在于sprint返回的要打印的字符串,print将sprint返回的要打印的字符串打印出来;

(2) do_print提供了callback机制,处理object中需要特殊处理的fields或者没有采用field automation机制的fields;

(3) 注意uvm_printer(uvm_default_printer,uvm_default_line_printer,uvm_default_tree_printer,uvm_default_table_printer)的使用;

 1 function void uvm_object::print(uvm_printer printer=null);
 2   if (printer==null)
 3     printer = uvm_default_printer;
 4   if (printer == null)
 5     `uvm_error("NULLPRINTER","uvm_default_printer is null")
 6   $fwrite(printer.knobs.mcd,sprint(printer)); 
 7 endfunction
 8 
 9 
10 // sprint
11 // ------
12 
13 function string uvm_object::sprint(uvm_printer printer=null);
14   bit p;
15 
16   if(printer==null)
17     printer = uvm_default_printer;
18 
19   // not at top-level, must be recursing into sub-object
20   if(!printer.istop()) begin
21     __m_uvm_status_container.printer = printer;
22     __m_uvm_field_automation(null, UVM_PRINT, "");
23     do_print(printer);
24     return "";
25   end
26   
27   printer.print_object(get_name(), this);
28   // backward compat with sprint knob: if used, 
29   //    print that, do not call emit()
30   if (printer.m_string != "")
31     return printer.m_string;
32 
33   return printer.emit();
34 
35 endfunction
 1 module top;
 2     import uvm_pkg::*;
 3     `inclue "uvm_macros.svh"
 4     ...
 5     class_A cl1=new("child class");
 6     initial begin
 7         cl1.print(uvm_default_table_printer);
 8         cl1.print(uvm_default_line_printer);
 9     end
10 endmodule

1.6 pack & do_pack与unpack & do_unpack

(1) 注意uvm_packer的使用;

 1 module top;
 2     import uvm_pkg::*;
 3     `inclue "uvm_macros.svh"
 4     ...
 5 
 6     bit pack_bytes[];
 7     class_P class_P_inst1;
 8     class_P class_P_inst2;
 9     initial begin
10         class_P_inst1=new("first_inst");
11         class_P_inst1.randomize();
12         class_P_inst1.print();
13         //pack object
14         class_P_inst1.pack(pack_bytes);
15 
16         class_P_inst2=new("second_inst");
17         class_P_inst2.print();
18         //unpack object
19         class_P_inst2.unpack(pack_bytes);    
20         class_P_inst2.print();
21     end
22 endmodule

2.uvm factory机制中的相关宏会重载uvm_object内的create操作

1 `define uvm_object_utils_begin(T) \
2    `m_uvm_object_registry_internal(T,T)  \
3    `m_uvm_object_create_func(T) \
4    `m_uvm_get_type_name_func(T) \
5    `uvm_field_utils_begin(T) 
1 `define uvm_object_utils_end \
2      end \
3    endfunction \
 1 `define m_uvm_object_create_func(T) \
 2    `ifdef UVM_CREATE_OPT \
 3         virtual function void call_new(); \
 4         endfunction \
 5    `else \
 6     function uvm_object create (string name=""); \
 7         T tmp; \
 8        `ifdef UVM_OBJECT_MUST_HAVE_CONSTRUCTOR \
 9           if (name=="") tmp = new(); \
10           else tmp = new(name); \
11        `else \
12           tmp = new(); \
13           if (name!="") \
14             tmp.set_name(name); \
15        `endif \
16        return tmp; \
17     endfunction \
18    `endif 
19 
20 // m_uvm_get_type_name_func
21 // ----------------------
22 
23 `define m_uvm_get_type_name_func(T) \
24    const static string type_name = `"T`"; \
25    virtual function string get_type_name (); \
26      return type_name; \
27    endfunction 

3.uvm field automation机制会重载uvm_object的__m_uvm_field_automation函数

 1 `define uvm_field_utils_begin(T) \
 2    function void __m_uvm_field_automation (uvm_object tmp_data__, \
 3                                      int what__, \
 4                                      string str__); \
 5    begin \
 6      T local_data__; /* Used for copy and compare */ \
 7      typedef T ___local_type____; \
 8      string string_aa_key; /* Used for associative array lookups */ \
 9      uvm_object __current_scopes[$]; \
10      if(what__ inside {UVM_SETINT,UVM_SETSTR,UVM_SETOBJ}) begin \
11         if(__m_uvm_status_container.m_do_cycle_check(this)) begin \
12             return; \
13         end \
14         else \
15             __current_scopes=__m_uvm_status_container.m_uvm_cycle_scopes; \
16      end \
17      super.__m_uvm_field_automation(tmp_data__, what__, str__); \
18      /* Type is verified by uvm_object::compare() */ \
19      if(tmp_data__ != null) \
20        /* Allow objects in same hierarchy to be copied/compared */ \
21        if(!$cast(local_data__, tmp_data__)) return; \
22     `ifdef UVM_EMPTY_MFLD_AUTO \
23         $$empty_function_if_last(); \
24     `endif

4.uvm_field_*宏定义了一些case语句块

 1 `define uvm_field_int(ARG,FLAG) \
 2   begin \
 3     case (what__) \
 4       UVM_CHECK_FIELDS: \
 5         begin \
 6           __m_uvm_status_container.do_field_check(`"ARG`", this); \
 7         end \
 8       UVM_COPY: \
 9         begin \
10           if(local_data__ == null) return; \
11           if(!((FLAG)&UVM_NOCOPY)) ARG = local_data__.ARG; \
12         end \
13       UVM_COMPARE: \
14         begin \
15           if(local_data__ == null) return; \
16           if(!((FLAG)&UVM_NOCOMPARE)) begin \
17             if(ARG !== local_data__.ARG) begin \
18                void'(__m_uvm_status_container.comparer.compare_field(`"ARG`", ARG, local_data__.ARG, $bits(ARG))); \
19                if(__m_uvm_status_container.comparer.result && (__m_uvm_status_container.comparer.show_max <= __m_uvm_status_container.comparer.result)) return; \
20             end \
21           end \
22         end \
23       UVM_PACK: \
24         if(!((FLAG)&UVM_NOPACK)) begin \
25           if($bits(ARG) <= 64) __m_uvm_status_container.packer.pack_field_int(ARG, $bits(ARG)); \
26           else __m_uvm_status_container.packer.pack_field(ARG, $bits(ARG)); \
27         end \
28       UVM_UNPACK: \
29         if(!((FLAG)&UVM_NOPACK)) begin \
30           if($bits(ARG) <= 64) ARG =  __m_uvm_status_container.packer.unpack_field_int($bits(ARG)); \
31           else ARG = __m_uvm_status_container.packer.unpack_field($bits(ARG)); \
32         end \
33       UVM_RECORD: \
34         `m_uvm_record_int(ARG, FLAG) \
35       UVM_PRINT: \
36         `m_uvm_print_int(ARG, FLAG) \
37       UVM_SETINT: \
38         begin \
39           bit matched; \
40           __m_uvm_status_container.scope.set_arg(`"ARG`"); \
41           matched = uvm_is_match(str__, __m_uvm_status_container.scope.get()); \
42           if(matched) begin \
43             if((FLAG)&UVM_READONLY) begin \
44               uvm_report_warning("RDONLY", $sformatf("Readonly argument match %s is ignored",  \
45                  __m_uvm_status_container.get_full_scope_arg()), UVM_NONE); \
46             end \
47             else begin \
48               if (__m_uvm_status_container.print_matches) \
49                   uvm_report_info("STRMTC", {"set_int()", ": Matched string ", str__, " to field ", __m_uvm_status_container.get_full_scope_arg()}, UVM_LOW); \
50               ARG = uvm_object::__m_uvm_status_container.bitstream; \
51               uvm_object::__m_uvm_status_container.status = 1; \
52             end \
53           end \
54           __m_uvm_status_container.scope.unset_arg(`"ARG`"); \
55         end \
56     endcase \
57   end

5.`uvm_field_utils_begin宏与`uvm_field_int等宏共同构成function __m_uvm_field_automation的定义

 

posted on 2022-01-14 14:12  知北游。。  阅读(1300)  评论(0编辑  收藏  举报

导航