[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的定义