uvm_object类是所有UVM数据以及层次结构的基类,其主要的角色是定义一系列的方法,比如一些公共的操作:create(), copy(), compare(), print(), record()等。
- 其中的 create() 与 get_type_name() 虚方法被简单实现,不再是纯虚方法。但在扩展类中如果需要使用与这两种方法的相关方法时必须实现这两种方法。
1. 层次结构
2. 类的预定义
-
预定义uvm_object的相关扩展类,以便在uvm_object的相关方法中调用:
typedef class uvm_report_object; typedef class uvm_object_wrapper; typedef class uvm_objection; // uvm_object类中未使用 typedef class uvm_component; // uvm_object类中未使用 typedef class uvm_status_container;
3. 类的声明
virtual class uvm_object extends uvm_void;
endclass
4. 类的方法
变量的声明
// 静态变量,决定是否使能UVM中的播种机制,影响全局的reseed()方法;
static bit use_uvm_seeding = 1;
// 局部变量,通过new函数将类的实例化名传递给该变量,变量对子类及外部不可见;
local string m_leaf_name;
// 局部变量,使用new()函数实例化类时,m_inst_count自动加1并传递给该局部变量,用于返回实例化id,变量对子类及外部不可见;
local int m_inst_id;
// 静态局部变量,用于返回实例化次数,该局部变量对子类可见,对外部不可见;
static protected int m_inst_count;
static uvm_status_container __m_uvm_status_container = new;
// 查找表,用于copy()函数的实现;
local static uvm_object uvm_global_copy_map[uvm_object];
方法的声明
extern function new (string name="");
extern static function int get_inst_count();
extern virtual function int get_inst_id ();
extern virtual function string get_name ();
extern virtual function string get_full_name ();
extern virtual function void set_name (string name);
virtual function string get_type_name (); return "<unknown>"; endfunction
virtual function uvm_object create (string name=""); return null; endfunction
extern function void reseed ();
extern static function uvm_object_wrapper get_type ();
extern virtual function uvm_object_wrapper get_object_type ();
extern virtual function uvm_object clone ();
extern function void print (uvm_printer printer=null);
extern function string sprint (uvm_printer printer=null);
extern virtual function void do_print (uvm_printer printer);
extern virtual function string convert2string();
extern function void record (uvm_recorder recorder=null);
extern virtual function void do_record (uvm_recorder recorder);
extern function void copy (uvm_object rhs);
extern virtual function void do_copy (uvm_object rhs);
extern function bit compare (uvm_object rhs, uvm_comparer comparer=null);
extern virtual function bit do_compare (uvm_object rhs,
uvm_comparer comparer);
extern function int pack (ref bit bitstream[],
input uvm_packer packer=null);
extern function int pack_bytes (ref byte unsigned bytestream[],
input uvm_packer packer=null);
extern function int pack_ints (ref int unsigned intstream[],
input uvm_packer packer=null);
extern virtual function void do_pack (uvm_packer packer);
extern function int unpack (ref bit bitstream[],
input uvm_packer packer=null);
extern function int unpack_bytes (ref byte unsigned bytestream[],
input uvm_packer packer=null);
extern function int unpack_ints (ref int unsigned intstream[],
input uvm_packer packer=null);
extern virtual function void do_unpack (uvm_packer packer);
extern virtual function void set_int_local (string field_name,
uvm_bitstream_t value,
bit recurse=1);
extern virtual function void set_string_local (string field_name,
string value,
bit recurse=1);
extern virtual function void set_object_local (string field_name,
uvm_object value,
bit clone=1,
bit recurse=1);
extern local function void m_pack (inout uvm_packer packer);
extern local function void m_unpack_pre (inout uvm_packer packer);
extern local function void m_unpack_post (uvm_packer packer);
extern virtual function void __m_uvm_field_automation (uvm_object tmp_data__,
int what__,
string str__);
extern protected virtual function uvm_report_object m_get_report_object();
方法的实现
-
new()函数:通过给定的字符串名称创造该类的实例化对象,如果名字没有给定,那么该对象无名。字符串名传递给局部变量m_leaf_name,实例化 m_inst_id 通过静态局部变量m_inst_count计数的方式指定。
function uvm_object::new (string name=""); m_inst_id = m_inst_count++; m_leaf_name = name; endfunction
-
get_inst_count()函数:返回实例化数量。
function int uvm_object::get_inst_count(); return m_inst_count; endfunction
-
get_inst_id()函数:返回实例化 id 。
function int uvm_object::get_inst_id(); return m_inst_id; endfunction
-
get_name()函数:返回实例化名m_leaf_name。
function string uvm_object::get_name (); return m_leaf_name; endfunction
-
get_full_name()函数:调用get_name()函数
function string uvm_object::get_full_name (); return get_name(); endfunction
-
set_name()函数:将字符串名称通过参数传递给内部变量m_leaf_name,用于重命名例化名。
function void uvm_object::set_name (string name); m_leaf_name = name; endfunction
-
create()函数:无返回,保留函数。UVM参考手册中指出直接或者间接扩展自uvm_object的类必须实现create()方法,但在源码中是在需要时才会实现。clone函数会使用到create()方法,因此,直接或者间接扩展最好实现create()方法。
virtual function uvm_object create (string name=""); return null; endfunction
-
get_type_name()函数:无返回,保留函数用于被扩展类重写。在每个扩展类中均需实现该方法。reseed()等方法会调用该函数,因此直接或者间接扩展自uvm_object的类最好实现该方法函数。
virtual function string get_type_name (); return "<unknown>"; endfunction
-
reseed ()函数:uvm_create_random_seed方法根据字符串名称返回随机种子值,而后通过调用SV中的srandom方法手动播种当前类对象或者线程的RNG(Random Number Generator)。
它根据类型名和实例名而不是基于线程中的实例位置来设置种子。
如果静态变量use_uvm_seeding被设置为0,那么该函数为空函数。function void uvm_object::reseed (); if(use_uvm_seeding) this.srandom(uvm_create_random_seed(get_type_name(), get_full_name())); endfunction
-
get_type ()函数:返回当前对象的代理(或者wrapper)。默认的实现方式会产生一个error并返回null。要启用此方法,用户的子类型必须实现返回子类型包装的版本。
function uvm_object_wrapper uvm_object::get_type(); uvm_report_error("NOTYPID", "get_type not implemented in derived class.", UVM_NONE); return null; endfunction
-
get_object_type ()函数:返回当前对象的代理(或者wrapper)。与get_type()方法类似,但使用已分配的对象来确定要访问的类型代理(而不是使用静态对象)。
使用工厂机制并通过get_type_name()的返回值来进行查找,如果通过get_type_name()返回的类型没有注册工厂机制,那么返回空句柄。
function uvm_object_wrapper uvm_object::get_object_type(); uvm_coreservice_t cs = uvm_coreservice_t::get(); uvm_factory factory=cs.get_factory(); if(get_type_name() == "<unknown>") return null; return factory.find_wrapper_by_name(get_type_name()); endfunction
-
clone ()函数:虚方法,创建并返回待clone对象的副本。
function uvm_object uvm_object::clone(); uvm_object tmp; tmp = this.create(get_name()); // 调用create()方法,创建实例 if(tmp == null) uvm_report_warning("CRFLD", $sformatf("The create method failed for %s, object cannot be cloned", get_name()), UVM_NONE); else tmp.copy(this); // 调用uvm_object中的copy函数 return(tmp); endfunction
-
print ()函数:方法以给定的 printer 参数控制的格式和方式深度打印该对象的属性。如果参数没有指定,那么使用全局的<uvm_default_printer>所定义的输出格式。
function void uvm_object::print(uvm_printer printer=null); if (printer==null) // 检查是否给定uvm_printer参数,如果没有指定参数,使用默认的uvm_default_printer; printer = uvm_default_printer; if (printer == null) // 检查uvm_default_printer是否为空; `uvm_error("NULLPRINTER","uvm_default_printer is null") // 其中printer.knobs.mcd=UVM_STDOUT=1 $fwrite(printer.knobs.mcd,sprint(printer)); // 使用$fwrite调用sprint函数将类对象的属性打印至标准输出。 endfunction
-
sprint ()函数: 与 print() 函数类似,但 sprint() 函数返回字符串而不是显示到标准输出。因此该函数被print()函数调用。
非虚函数,不可被重载,继承子类必须重写do_print()函数,并且使用提供的printer策略来格式化输出。
function string uvm_object::sprint(uvm_printer printer=null); bit p; if(printer==null) printer = uvm_default_printer; // 同样的,调用该方法时如果没有指定参数,那么使用默认的uvm_default_printer; // not at top-level, must be recursing into sub-object if(!printer.istop()) begin __m_uvm_status_container.printer = printer; __m_uvm_field_automation(null, UVM_PRINT, ""); do_print(printer); return ""; end printer.print_object(get_name(), this); // 如果printer对象中的m_string字符串非空,那么返回该非空字符串,不再调用emit()方法; if (printer.m_string != "") return printer.m_string; return printer.emit(); endfunction
输出如下表格形式字符串:
--------------------------------------------------- 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 ---------------------------------------------------
-
do_print ()函数:虚函数,用于自定义输出格式。参数用于管理输出格式与内容。
function void uvm_object::do_print(uvm_printer printer); return; endfunction
-
convert2string()函数:用户自定义方法,返回字符串。
function string uvm_object::convert2string(); return ""; endfunction
实例如下:
class base extends uvm_object; string field = "foo"; virtual function string convert2string(); convert2string = {"base_field=",field}; // 使用函数名隐式指明函数返回值。 endfunction endclass
-
record ()函数:根据可选的记录器策略深度记录此对象的属性,可选的记录器参数指定记录策略。
function void uvm_object::record (uvm_recorder recorder=null); if(recorder == null) // 记录策略为空,直接返回; return; __m_uvm_status_container.recorder = recorder; recorder.recording_depth++; __m_uvm_field_automation(null, UVM_RECORD, ""); do_record(recorder); recorder.recording_depth--; endfunction
-
do_record ()函数:用户可定义的方法。派生类应重写此方法以将其字段包含在记录操作中。do_recored()方法的实现应该在其每个域中调用恰当的记录方法。该方法被recored()方法调用。
function void uvm_object::do_record (uvm_recorder recorder); return; endfunction
典型的实现方式如下:
class mytype extends uvm_object; data_obj data; int f1; function void do_record (uvm_recorder recorder); recorder.record_field("f1", f1, $bits(f1), UVM_DEC); recorder.record_object("data", data); endfunction endclass
-
copy ()函数:拷贝一份备份到指定对象,用于实例的复制,使用B.copy(A)的方式将A的实例拷贝到B的实例中,此时B的实例已经分配好了内存空间。该函数没有使用关键字virtual,不可被子类覆盖(override)。
function void uvm_object::copy (uvm_object rhs); // For cycle checking static int depth; // 如果copy对象非空且已经存在于局部变量uvm_global_copy_map中,此时已经保存了该对象的备份,那么直接返回; if((rhs !=null) && uvm_global_copy_map.exists(rhs)) begin return; end // 如果copy对象为空,那么给出警告并返回; if(rhs==null) begin uvm_report_warning("NULLCP", "A null object was supplied to copy; copy is ignored", UVM_NONE); return; end // 如果对象非空且没有被保存,那么将该类对象保存到uvm_global_copy_map且深度+1 uvm_global_copy_map[rhs]= this; ++depth; __m_uvm_field_automation(rhs, UVM_COPY, ""); // 调用虚函数,没有被重写时无返回值; do_copy(rhs); // 调用虚函数,没有被重写时无返回值; --depth; // 调用完毕后深度计数递减并删除copy至uvm_global_copy_map的对象; if(depth==0) begin uvm_global_copy_map.delete(); end endfunction
-
do_copy ()函数:无任何返回值,由于copy()函数不可被override(没有用virtual关键字),因此do_copy()函数被用来copy一个子类域。
function void uvm_object::do_copy (uvm_object rhs); return; endfunction
实现方式如下:子类必须调用父类的do_copy()函数,且必须在copy之前使用$cast进行类型转换。
class mytype extends uvm_object; ... int f1; virtual function void do_copy (uvm_object rhs); mytype rhs_; super.do_copy(rhs); $cast(rhs_,rhs); field_1 = rhs_.field_1; endfunction
-
compare ()函数:深度比较此数据对象的成员与rhs(right hand side)中提供的对象的成员。匹配返回1,否则返回0。
function bit uvm_object::compare (uvm_object rhs, uvm_comparer comparer=null); ... if(!done) begin comparer.compare_map[rhs]= this; __m_uvm_field_automation(rhs, UVM_COMPARE, ""); dc = do_compare(rhs, comparer); // 返回dc显示调用do_compare()方法; end ... return (comparer.result == 0 && dc == 1); endfunction
-
do_compare ()函数:虚函数,用户自定义比较函数。在实现时序调用上层的super.do_compare()来确保基类的属性
1.值得注意的是:在自定义时比较成功那么返回1 ,否则返回0。
2.由于参数中的rhs是基类uvm_object的句柄,因此扩展类需使用$cast进行向下类型转换。``` function bit uvm_object::do_compare (uvm_object rhs, uvm_comparer comparer); return 1; endfunction ```
do_compare()使用示例如下:
class mytype extends uvm_object; ... int f1; virtual function bit do_compare (uvm_object rhs,uvm_comparer comparer); mytype rhs_; do_compare = super.do_compare(rhs,comparer); $cast(rhs_,rhs); do_compare &= comparer.compare_field_int("f1", f1, rhs_.f1); endfunction endclass
-
pack ()函数:将对象的属性按位串接在bit数组中;
function int uvm_object::pack (ref bit bitstream [], input uvm_packer packer =null ); m_pack(packer); packer.get_bits(bitstream); return packer.get_packed_size(); endfunction
-
pack_bytes ()函数:将对象的属性按位串接在byte数组中;
-
pack_ints ()函数:将对象的属性按位串接在int数组中;
-
do_pack ()函数:用户自定义方法的钩子,被pack()方法以及m_pack()方法调用。实现时必须调用super.do_pack()以便基类的属性一并被打包。
function void uvm_object::do_pack (uvm_packer packer ); return; endfunction
-
unpack ()函数:从bit数组中提取对象的属性值。
function int uvm_object::unpack (ref bit bitstream [], input uvm_packer packer=null); m_unpack_pre(packer); packer.put_bits(bitstream); m_unpack_post(packer); packer.set_packed_size(); return packer.get_packed_size(); endfunction
-
unpack_bytes ()函数:从byte数组中提取对象的属性值。
-
unpack_ints ()函数:从int数组中提取对象的属性值。
-
do_unpack ()函数:用户可定义,被unpack()方法调用
function void uvm_object::do_unpack (uvm_packer packer); return; endfunction
-
set_int_local ()函数:未完待续…
-
set_string_local ()函数:未完待续…
-
set_object_local ()函数:未完待续…
-
m_pack ()函数:uvm_object类内部方法,不能直接使用。
function void uvm_object::m_pack (inout uvm_packer packer); // 参数如果是null,那么使用默认uvm_default_packer,这与uvm_printer使用类似; if(packer!=null) __m_uvm_status_container.packer = packer; else __m_uvm_status_container.packer = uvm_default_packer; packer = __m_uvm_status_container.packer; packer.reset(); // 初始化变量 packer.scope.down(get_name()); // 将实例化对象的字符串名称push到packer的局部变量m_stack中; __m_uvm_field_automation(null, UVM_PACK, ""); do_pack(packer); // 调用do_pack()方法; packer.set_packed_size(); // 设置包的大小 packer.scope.up(); // 将m_stack队列出栈并进行其他操作; endfunction
-
m_unpack_pre ()函数:m_pack()的前半部分。
function void uvm_object::m_unpack_pre (inout uvm_packer packer); if(packer!=null) __m_uvm_status_container.packer = packer; else __m_uvm_status_container.packer = uvm_default_packer; packer = __m_uvm_status_container.packer; packer.reset(); endfunction
-
m_unpack_post ()函数:类似于m_pack()的后半部分。
function void uvm_object::m_unpack_post (uvm_packer packer); int provided_size; provided_size = packer.get_packed_size(); //Put this object into the hierarchy packer.scope.down(get_name()); __m_uvm_field_automation(null, UVM_UNPACK, ""); do_unpack(packer); //Scope back up before leaving packer.scope.up(); if(packer.get_packed_size() != provided_size) begin uvm_report_warning("BDUNPK", $sformatf("Unpack operation unsuccessful: unpacked %0d bits from a total of %0d bits", packer.get_packed_size(), provided_size), UVM_NONE); end endfunction
-
__m_uvm_field_automation ()函数:虚函数无返回值,预留方法。用于后续宏定义uvm_object_utils等宏时进行override进而用此宏进行宏注册。
function void uvm_object::__m_uvm_field_automation (uvm_object tmp_data__, int what__, string str__ ); return; endfunction
-
m_get_report_object()函数:虚方法,基类以及子类可见的私有方法,关键字 " protected"。
function uvm_report_object uvm_object::m_get_report_object(); return null; endfunction