UVM学习笔记

1.寄存器模型

transaction的一般样式:

class my_transaction extends uvm_sequence_item;//derived from uvm_sequence_item

     rand bit[47:0] smac;

     rand bit[47:0] dmac;

     rand bit[31:0] vlan[];

     rand bit[15:0] eth_type;

     rand byte pload[];

     rand bit[31:0] crc;

     `uvm_object_utils_begin(my_transaction)//register factory scheme

             `uvm_field_int(smac,UVM_ALL_ON)//field automation scheme

             `uvm_field_int(dmac,UVM_ALL_ON)

             `uvm_field_array_int(vlan,UVM_ALL_ON)

             `uvm_field_int(eth_type,UVM_ALL_ON)

             `uvm_field_array_int(pload,UVM_ALL_ON)

    `uvm_object_utils_end

endclass

例化并随机化: 

my_transaction tr;
tr = new();
assert(tr.randomize() with {vlan.size() == 1;});

UVM config方法:在 build_phase中使用

set_config_object("path","field",value);

set_config_string("path","field",value);

set_config_int("path","field",value);

或:

uvm_config_int::set(this,path,field,value)  [uvm_config_db#(int)::set(this,path,field,value)]

uvm_config_int::get(this,"",field,value) [uvm_config_db#(int)::get(this,"",field,value)]

uvm_config_string::set(this,path,field,value) [uvm_config_db#(string)::set(this,path,field,value)]

uvm_config_string::get(this,"",field,value) [uvm_config_db#(string)::get(this,"",field,value)]

uvm_config_object::set(this,path,field,value) [uvm_config_db#(object)::set(this,path,field,value)]

uvm_config_object::get(this,"",field,value) [uvm_config_db#(object)::get(this,"",field,value)]

p_sequencer的声明:在一个sequenc里面,通过`uvm_declare_p_sequencer(v_sequencer)宏定义一个p_sequencer变量,通过p_sequencer可以把v_sequencer中的值传递到sequence里面去,从而对sequence进行控制。 

`uvm_declare_p_sequencer(axi4UVMUserVirtualSequencer)
相当于声明了一个axi4UVMUserVirtualSequencer类型的p_sequencer变量:
axi4UVMUserVirtualSequencer p_sequencer;

transaction里面通过get_sequencer()方法可以得到该transaction的sequencer的引用:

class MyAxiTransaction extends denaliCdn_axiTransaction;
    `uvm_object_utils(MyAxiTransaction)
    axi4UvmUserConfig cfg;
    function void pre_randomize();
        cdnAxiUvmSequencer seqr;

        super.pre_randomize();

        if(!$cast(seqr,get_sequencer()))begin
            `uvm_fatal(get_type_name(),"failed $cast(seqr,get_sequencer())");
        end
        ...
     endfunction
...
endclass

Sequence启动的各种方式:

1.直接启动:reg_seq.start(p_sqr);另一种方式是在test的build_phase()中设置default_sequence;

下面几种方法可以在一个sequence的body()任务中使用,用于启动嵌套的sequence?

2.`uvm_create(tr)和`uvm_send(tr)或`uvm_create_on(masterBurst,p_sequencer.masterSeqr)和`uvm_rand_send_with(masterBurst,{masterBurst.Cacheable == DENALI_CDN_AXI_CACHEMODE_CACHEABLE;

                                                        masterBurst.StartAddress == 'h0010;})

3.先手动设置好tr中的各项内容,然后`uvm_create(tr)   ----参考UVM实战230页。

4.使用各种相关的宏:`uvm_do(tr),`uvm_do_on,`uvm_do_with,`uvm_do_on_with等

在base_test类的connect_phase中,使用uvm_top.print_topology()打印UVM树形结构:

function void base_test::connect_phase(uvm_phase phase);
     super.connect_phase(phase);
     uvm_top.print_topology();
endfunction

UVM中的factory机制:重载

1.1 SystemVerilog对重载的支持

    1.1.1 任务与函数的重载-虚方法

     1.1.2 约束的重载

2.2 使用factory机制进行重载:

      factory机制最伟大的地方在于其具有重载的功能。

function void my_case0::build_phase(uvm_phase phase);
                ...
     set_type_override_by_type(bird::get_type(),parrot::get_type());
  
     bird_inst = bird::type_id::create("bird_inst");
     parrot_inst = parrot::type_id::create("parrot_inst");
     print_hungry(bird_inst);
     print_hungry(parrot_inst);
endfunction

要想使用重载的功能,必须满足一下要求:

1.无论是重载的类还是被重载的类,都要在定义时注册到factory机制中(使用宏`uvm_object_utils*和`uvm_component_utils*)

2.被重载的类在实例化时,要使用factory机制式的实例化方式(即使用xxx::type_id::create("xxx_inst"),而不能使用传统的new()方式。

3.重载的类与被重载的类之间要有派生关系。重载的类必须派生自被重载的类,被重载的类必须是重载类的父类。

4.component和object之间互相不能重载。

1.2.2 重载的方式及种类

extern static function void set_type_override_by_type(uvm_object_wrapper original_type,
                                                      uvm_object_wrapper override_type,
                                                      bit replace = 1);
extern functioin void set_inst_override_by_type(string relative_inst_path,
                                                 uvm_object_wrapper original_type,
                                                 uvm_object_wrapper override_type);

以上两个函数都位于uvm_component中。

set_type_override_by_type将验证平台中的A类型全部替换成B类型。

set_inst_override_by_type将验证平台中的A类型的某个 实例替换成B类型。

无论是set_type_override_by_type还是set_inst_override_by_type,它们的参数都是一个uvm_object_wrapper类型,这种参数可通过xxx::get_type()的形式获得。

UVM还提供了字符串的写法来替换上述的写法:

extern static function void set_type_override(string original_type_name,
                                              string override_type_name,
                                              bit replace = 1);
ex:
set_type_override("bird","parrot")

extern function void set_inst_override(string relative_inst_path,
                                       string original_type_name,
                                       string override_type_name);
ex:
set_inst_overroide("env.o_agt.mon","my_monitor","new_monitor");

上述的所有函数都是uvm_component的函数,但是如果在一个无法使用component的地方,如在top_tb的initial语句里,就无法使用。UVM提供了另外四个函数来替换上述四个函数,它们的原型为:

extern function void set_type_override_by_type(uvm_object_wrapper original_type
                                               uvm_object_wrapper override_type,
                                               bit replace = 1);
extern function void set_inst_override_by_type(uvm_object_wrapper original_type,
                                               uvm_object_wrapper override_type,
                                               string full_inst_path);
extern function void set_type_override_by_name(string original_type_name,
                                               string override_type_name,
                                               bit replace = 1);
extern function void set_inst_override_by_name(string original_type_name,
                                               string override_type_name,
                                               string full_inst_path);

这四个函数都位于uvm_factory类中。其中第一个函数与uvm_component中的同名函数类似,传递的参数相同。第二个对应uvm_component中的同名函数,只是其输入参数变了,这里需要输入一个字符串类型的full_inst_path。这个full_inst_path就是要替换的实例中使用get_full_name()得到的路径值。第三个与uvm_component中的set_type_override类似,传递的参数相同。第四个函数对应uvm_component中的set_inst_override,也需要一个full_inst_path。

如何使用这四个函数呢?系统中存在一个uvm_factory类型的全局变量factory。可以在initial语句里使用如下的方式调用这四个函数。

initial begin
    factory.set_type_override_by_type(bird::get_type(),parrot::get_type());
end

在一个component内也完全可以直接调用factory机制的重载函数:

factory.set_type_override_by_type(bird::get_type(),parrot::get_type());

事实上,uvm_component的四个重载函数直接调用了factory的相应函数。

除了可以在代码中进行重在外,还可以在命令行中进行重载。对于实例重载和类型重载,分别有各自的命令行参数:

<sim_command>  +uvm_set_inst_override=<req_type>,<override_type>,<full_inst_path>

ex:
<sim_command>  +uvm_set_inst_override="my_monitor,new_monitor,uvm_test_top.env.o_agt.mon"


<sim_command>  +uvm_set_type_override=<req_type>,<override_type>[,<replace>]
ex:
<sim_command>  +uvm_set_type_override="my_monitor,new_monitor"

这两个命令行分别对应于set_inst_override_by_name和set_type_override_by_name。

类型重载的命令行参数中有三个选项,其中最后一个replace表述是否可以被后面的重载覆盖。

1.2.3 复杂的重载

1.2.3.1UVM支持连续的重载(即祖孙三代式,A->B;B->C,最终结果是A->C,其中B派生自A,C派生自B)

set_type_override_by_type(bird::get_type(),parrot::get_type());
set_type_override_by_type(parrot::get_type(),big_parrot::get_type());

1.2.3.2覆盖的重载(即父子三人式,A->B,A->C,最终结果是A->C,其中A是父类,B和C是派生自A的子类)

set_type_override_by_type(bird::get_type(),parrot::get_type());
set_type_override_by_type(bird::get_type(),sparrow::get_type());

这种替换式的重载的前提是调用 set_type_override_by_type时,其第三个replace参数被设置为1(默认情况下即为1)。

下面的重载也是可以的,

set_type_override_by_type(bird::get_type(),parrot::get_type());
set_type_override_by_type(parrot::get_type(),sparrow::get_type());

其中parrot和sparrow之间不存在派生关系,这违背了重载四个前提中的第三个前提,但是这样仍然可以工作。原因是最初被重载的类型bird和最终重载的类型sparrow存在派生关系,只是不能在代码中例化parrot的实例,如果例化了parrot的实例,UVM则会报错。

重载四前提的第三条应该改为:

在有多个重载时,最终重载的类与最初被重载的类有派生关系。

1.2.4 factory 机制的调试

1.2.5 用factory机制创建实例的接口

factory机制提供了一系列接口来创建实例。

create_object_by_name,用于根据类名字创建一个object,其原型为:
function uvm_object uvm_factory::create_object_by_name(string requested_type_name,
                                                       string parent_inst_path = "",
                                                       string name = "");
一般只使用第一个参数:
my_transaction tr;
void'($cast(tr,factory.create_object_by_name("my_transaction")));

create_object_by_type,用于根据类型创建一个object,其原型为:
function uvm_object uvm_factory::create_object_by_type(uvm_object_wrapper 
                                                                         requested_type,
                                                       string parent_inst_path = "",
                                                       string name = "");
一般也只使用第一个参数:
my_transaction tr;
void'($cast(tr,factory.create_object_by_type(my_transaction::get_type())));

create_component_by_name,根据类名创建一个component,其原型为:

function uvm_component uvm_factory::create_component_by_name(string requested_type_name,
                                                             string parent_inst_path=""
                                                             string name,
                                                             uvm_component parent);
my_scoreboard scb;
void'($cast(scb,factory.create_component_by_name("my_scoreboard",get_full_name(),"scb",this);

create_component_by_type,根据类型创建一个component,其原型为:

function uvm_component uvm_factory::create_component_by_type(uvm_object_wrapper 
                                                                         
                                                                      requested_type,
                                                              string 
                                                              parent_inst_path="",
                                                              string name;
                                                              uvm_component parent);

my_scoreboard scb;
void'($cast(scb,factory.create_component_by_type(my_transaction::get_type(),get_full_name(),"scb",this);


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值