目录
uvm_object
- uvm世界中的类都是从一个uvm_void根类root class继承,这个类没有成员变量和方法,是个virtual类,继承于此的有两个类
- uvm_void
- uvm_object:主要提供与数据操作相关的服务
- 其他所有的类
- uvm_port_base
- transaction interface
- uvm_object:主要提供与数据操作相关的服务
域的自动化filed automation
- 从UVM通过域的自动化,用户在注册uvm类的同时,也可以声明今后会参与到的对象拷贝、克隆、打印等操作的成员变量
- 域的自动化filed automation:直接使用uvm_object的一些预定义方法
class box extends uvm_object;
int volume=120;
color_t color = white;
string name= "box";
`uvm_object_utils_begin(box)//注册box的同时
`uvm_filed_int(volume, UVM_ALL_ON)//声明了会参与到object数据操作的成员变量
`uvm_filed_enum(color_t, color, UVM_ALL_ON)
`uvm_filed_string(name, UVM_ALL_ON)
`uvm_object_utils_end
......
endclass
box b1, b2;
initial begin//声明过的成员变量将在数据操作时自动参与进来
b1 = new("box1");
b1.volume = 80;
b1.color = black;
b2 = new();
b2.copy(b1);//否则不会自动参与数据的操作,要自己定义数据操作方法
b2.name = "box2";
end
- 在注册{component,object}时,用
uvm_{component, object}_utils_begin和
uvm_{component, object}_utils_end包住所有需要用到的域自动化,尽量多的变量 - (成员变量,用来标记的数据操作)后者默认采取UVM_ALL_ON和UVM_DEFAULT,所有操作方法都打开
拷贝copy
- 拷贝和克隆clone的区别
- copy默认已经创建好对象,只拷贝了数据过去
- clone会自动创建对象,拷贝数据(source object),返回新对象(target object)的句柄
- 如果数据成员包括句柄呢?
class ball extends uvm_object;
int diameter = 10;
color_t color = red;
`uvm_object_utils_begin(ball)//域的自动化
`uvm_filed_int(diameter, UVM_DEFAULT)
`uvm_filed_enum(color_t, color, UVM_NOCOPY)
`uvm_object_utils_end
......//(省略new函数)
function void do_copy (uvm_object rhs);//预定义好的函数do_copy()是copy()的回调函数
//如果没有定义这个函数,copy执行完后就不会执行do_copy
ball b;
$cast(b,rhs);
$display("ball::do_copy entered");
if(b.diameter <= 20) begin
diameter = 20;
end
endfunction
endclass
class box extends uvm_object;
int volume= 120;
color_t color = white;
string name = "box";
ball b;//在box中例化了ball
`uvm_object_utils_begin(box)
`uvm_filed_int(volume, UVM_ALL_ON)
`uvm_filed_enum(color_t, color, UVM_ALL_ON)
`uvm_filed_string(name, UVM_ALL_ON)
`uvm_filed_object(b, UVM_ALL_ON)
`uvm_object_utils_end
....
endclass
box b1, b2;
initial begin
b1 = new("box1");
b1.volume = 80;
b1.color=black;
b1.b.color=white;
b2 = new();
b2.copy(b1);
b2.name="box2";
$display("%s", b1.sprint());//sprint()也是预定义函数,打印所有成员变量
$display("%s", b2.sprint());
end
//代码解析:
- b1和b2是box类型的句柄
- 例化b1,命名对象b1为box1,volume从120变成80,color从white变成black
- box1修改其ball的color从red变成white
- 例化box类型的b2对象,将b1的成员变量数据复制到b2,ball是深拷贝,b1中的ball对象中的成员变量也得到拷贝
- 但是color由于在域的自动化声明中是UVM_NOCOPY,所以没有得到拷贝
- diameter=10拷贝后,由于执行了do_copy(),10≤20,所以diameter变成了20,‘h14
比较compare
function bit compare (uvm_object, uvm_comparer comparer=null);
- 如果不对比较的情况做额外配置,调用compare()方法时可以省略第二项参数,采用默认的比较配置
- 比较方法经常在两个数据类之间进行(例如ch_trans和monitor_data)
- 如果是同一种类型的数据类。可以直接使用uvm_object::compare()函数实现数据比较+消息打印
class box extends uvm_object;//1继承
int volume= 120;
color_t color = white;
string name = "box";
ball b;//在box中例化了ball
`uvm_object_utils_begin(box)//2注册
`uvm_filed_int(volume, UVM_ALL_ON)
`uvm_filed_enum(color_t, color, UVM_ALL_ON)
`uvm_filed_string(name, UVM_ALL_ON)
`uvm_object_utils_end
....//3例化
endclass
box b1, b2;
initial begin
b1 = new("box1");
b1.volume = 80;
b1.color=black;
b2 = new("box2");
b2.volume=90;
if(!**b2.compare(b1)**) begin//返回1则比较成功
`uvm_info("COMPARE", "b2 compared with b1 failure", UVM_LOW) end
else begin
`uvm_info("COMPARE","success", UVM_LOW) end
end
自动输出:volume不相同,1次比较不同。由于比较失败,比较函数返回0,打印failure
- 原因:默认的比较器uvm_package::uvm_default_comparer最大输出的错误比较信息是1,所以发生1次错误就不会再进行后续比较
- 在uvm_object使用到的方法compare()、print()、pack(),如果没有指定数据操作配置对象作为参数时,会使用uvm_pkg中例化的全局数据操作配置成员
打印print
-
目的:便于开发和调试(断点也可以调试)
-
通过域的自动化,声明后各个成员域会在调用
uvm_object::print()函数时自动打印出来
class box extends uvm_object;//1继承
int volume= 120;
color_t color = white;
string name = "box";
`uvm_object_utils_begin(box)//2注册
`uvm_filed_int(volume, UVM_ALL_ON)
`uvm_filed_enum(color_t, color, UVM_ALL_ON)
`uvm_filed_string(name, UVM_ALL_ON)
`uvm_object_utils_end
....//3例化
endclass
box b1;
uvm_table_printer local_printer;//声明printer的句柄
initial begin
b1=new ("box1");
local_printer=new ();//例化这个printer,默认使用uvm_default_printer,这个默认用的是uvm_table_printer
$display("default table printer format");
b1.print();//uvm_table_printer
$display("default line printer format");
uvm_default_printer=uvm_default_line_printer;
b1.print();//用的是uvm_default_line_printer,不需要做例化,uvm已经例化好了
$display("default tree printer format");
uvm_default_printer=uvm_default_tree_printer;
b1.print();/用的是uvm_default_tree_printer
$display("cusromized printer format");
local_printer.knobs.full_name =1;
b1.print(local_printer);//用的是local_printer
end
打包pack和解包unpack
- 目的:完成大型标量数据的整形串发,面向的是SV与硬件和其他语言接口直接的精确通信
- 同print,在pack()和unpack()的参数中,uvm_packer可以缺省,如果不做特别指定,那么uvm_packer会使用uvm_pkg中例化的全局对象uvm_default_packer
- 需要自行打包,就要自定义do_pack()回调函数
function int pack (ref bit bitstream[], int uvm_pakcer packer=null);
function int unpack (ref bit bitstream[], int uvm_pakcer packer=null);
- pack是为了将自动化声明后的域(标量)打包成比特流bit stream,是个动态数组。类似struct packed,可以充分利用数据空间,更容易与硬件之间进行数据传递和比对
- unpack反之,适用于从硬件一侧接收串行数据,校验后还原为软件侧对象中各自对应的成员变量
- 与外界环境发生大规模数据传递时该方法是首选,通过简单的数据流实现精确的数据传输