预定义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;
virtual class uvm_object extends uvm_void;
endclass
// 静态变量,决定是否使能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 ""; 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 "";
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() == "") 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 参数控制的格式和方式深度打印该对象的属性。如果参数没有指定,那么使用全局的
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