数字验证--uvm寄存器模型常用函数介绍

 

DUT中寄存器的值可能是实时变更的, 寄存器模型并不能实时地知道这种变更, 因此, 寄存器模型中的寄存器的值有时与DUT中相关寄存器的值并不一致。 对于任意一个寄存器, 寄存器模型中都会有一个专门的变量用于最大可能地与DUT保持同步, 这个变量在寄存器模型中称为DUT的镜像值( mirrored value)寄存器模型中还有一个值叫期望值(respected value),这个值保存我们希望写入寄存器的值比如希望向DUT某个寄存器写入'h1,用set函数设置期望值,然后用update任务(update会比较镜像值和期望值,如果不一样,将期望值写入DUT,并更新镜像值)。

 

寄存器模型的使用的优点:

1.可进行后门方式访问dut中的寄存器;

2.在参考模型中不必引入全局变量可得到寄存器模型中值的变化;

3.提供很多函数使用方便;

4.可以很方便的对寄存器的 coverage 验证点的收集。

 

 寄存器模型中的单位

uvm_reg_field:这是寄存器模型中的最小单位。
uvm_reg:它比 uvm_reg_field 高一个级别,但是依然是比较小的单位。一个寄存器中至少包含一个 uvm_reg_field。
uvm_reg_block:它是一个比较大的单位,在其中可以加入许多的 uvm_reg,也可以加入其他的 uvm_reg_block。一个寄存器模型中至少包含一个 uvm_reg_block。
uvm_reg_map:每个寄存器在加入寄存器模型时都有其地址,uvm_reg_map 就是存储这些地址,并将其转换成可以访问的物理地址(因为加入寄存器模型中的寄存器地址一般都是偏移地址,而不是绝对地址)。当寄存器模型使用前门访问方式来实现读或写操作时,uvm_reg_map 就会将地址转换成绝对地址,启动一个读或写的 sequence,并将读或写的结果返回。在每个 reg_block 内部,至少有一个(通常也只有一个)uvm_reg_map。

 

一个简单的寄存器模型,每个派生自uvm_reg的类都有一个build()函数,它只能手工调用.(可直接通过脚本将excel生成寄存器模型。脚本地址 https://download.csdn.net/download/qq_38620826/18198642)

class reg_invert extends uvm_reg;
    rand uvm_reg_field reg_data; //在reg中定义field
    virtual function void build(); //build
        reg_data = uvm_reg_field::type_id::create("reg_data");
        // parameter: parent, size, lsb_pos, access, volatile, reset value, has_reset, is_rand, individually accessible
        reg_data.configure(this, 1, 0, "RW", 1, 0, 1, 1, 0); //上面一行是参数介绍
    endfunction
    
    function new(input string name="reg_invert");
        //parameter: name, size, has_coverage
        super.new(name, 16, UVM_NO_COVERAGE); //16是这个寄存器的宽度,
    endfunction
endclass

 

寄存器模型中常用的函数  

read 函数的原型(将根据从dut寄存器中读取的结果同时更新寄存器模型的期望值和镜像值),有多个参数, 常用的是其前三个参数。 其中第一个是uvm_status_e型的变量, 这是一个输出, 用于表明读操作是否成功;第二个是读取的数值, 也是一个输出; 第三个是读取的方式, 可选UVM_FRONTDOOR和UVM_BACKDOOR。

   extern virtual task read(output uvm_status_e      status,
                            output uvm_reg_data_t    value,
                            input  uvm_path_e        path = UVM_DEFAULT_PATH,
                            input  uvm_reg_map       map = null,
                            input  uvm_sequence_base parent = null,
                            input  int               prior = -1,
                            input  uvm_object        extension = null,
                            input  string            fname = "",
                            input  int               lineno = 0);

使用示例

p_sequencer.p_rm.invert.read(status, value, UVM_FRONTDOOR);

 

write函数的原型(将值写入到dut的寄存器中同时更新寄存器模型的期望值和镜像值),参数也有很多个, 但是与read类似, 常用的也只有前三个。 其中第一个为uvm_status_e型的变量, 这是一个输出, 用于表明写操作是否成功。 第二个要写的值, 是一个输入, 第三个是写操作的方式, 可选UVM_FRONTDOOR和UVM_BACKDOOR。

   extern virtual task write(output uvm_status_e      status,
                             input  uvm_reg_data_t    value,
                             input  uvm_path_e        path = UVM_DEFAULT_PATH,
                             input  uvm_reg_map       map = null,
                             input  uvm_sequence_base parent = null,
                             input  int               prior = -1,
                             input  uvm_object        extension = null,
                             input  string            fname = "",
                             input  int               lineno = 0);

使用示例

p_sequencer.p_rm.invert.write(status, 1, UVM_FRONTDOOR);

 

peek后门读函数(将根据从dut寄存器中读取的结果同时更新寄存器模型的期望值和镜像值),虽然read函数也能选择后门访问的方式读取寄存器,但是dut中的寄存器如果是只写的则使用呢read不能读取出来,但是使用peek是不管dut中寄存器的类型的,一定可以读取出来。

   extern virtual task peek(output uvm_status_e      status,
                            output uvm_reg_data_t    value,
                            input  string            kind = "",
                            input  uvm_sequence_base parent = null,
                            input  uvm_object        extension = null,
                            input  string            fname = "",
                            input  int               lineno = 0);

使用示例

p_sequencer.p_rm.invert.peek(status, value);

 

poke后门写函数(将值写入到dut的寄存器中同时更新寄存器模型的期望值和镜像值)。虽然write函数也能选择后门访问的方式写寄存器,但是dut中如果是一个只读寄存器,使用write则不能写入成功,但poke是不管dut中寄存器的类型的,可以完成对只读寄存器的写入。

   extern virtual task poke(output uvm_status_e      status,
                            input  uvm_reg_data_t    value,
                            input  string            kind = "",
                            input  uvm_sequence_base parent = null,
                            input  uvm_object        extension = null,
                            input  string            fname = "",
                            input  int               lineno = 0);

使用示例

 

set:将值写入到寄存器模型的期望值中

   extern virtual function void set (uvm_reg_data_t  value,
                                     string          fname = "",
                                     int             lineno = 0);

使用示例

p_sequencer.p_rm.invert.set(16'h1);

 

update:将期望值和镜像值比对,如果不一致则吧期望值写入到dut的寄存器中,同时更新寄存器模型镜像值。uvm_reg级别被调用, 也可以在uvm_reg_block级别被调用。

 

   extern virtual task update(output uvm_status_e      status,
                              input  uvm_path_e        path = UVM_DEFAULT_PATH,
                              input  uvm_reg_map       map = null,
                              input  uvm_sequence_base parent = null,
                              input  int               prior = -1,
                              input  uvm_object        extension = null,
                              input  string            fname = "",
                              input  int               lineno = 0);

使用示例

p_sequencer.p_rm.invert.update(status, UVM_FRONTDOOR);

 

get:得到寄存器模型的期望值

   extern virtual function uvm_reg_data_t  get(string  fname = "",
                                               int     lineno = 0);

使用示例

value = p_sequencer.p_rm.invert.get();

 

get_mirrored_value:得到寄存器模型的镜像值

   extern virtual function uvm_reg_data_t  get_mirrored_value(string  fname = "",
                                               int     lineno = 0);

使用示例

value = p_sequencer.p_rm.invert.get_mirrored_value();

 

mirror:将dut中的寄存器值更新到寄存器模型的镜像值值和期望值,其中第二个参数指的是如果发现DUT中寄存器的值与寄存器模型中的镜像值不一致, 那么在更新寄存器模型之前是否给出错误提示。 其可选的值为UVM_CHECK和UVM_NO_CHECK。它有两种应用场景, 一是在仿真中不断地调用它, 使得到整个寄存器模型的值与DUT中寄存器的值保持一致, 此时check选项是关闭的。 二是在仿真即将结束时, 检查DUT中寄存器的值与寄存器模型中寄存器的镜像值是否一致, 这种情况下, check选项是打开的。mirror操作既可以在uvm_reg级别被调用, 也可以在uvm_reg_block级别被调用。

   extern virtual task mirror(output uvm_status_e      status,
                              input uvm_check_e        check  = UVM_NO_CHECK,
                              input uvm_path_e         path = UVM_DEFAULT_PATH,
                              input uvm_reg_map        map = null,
                              input uvm_sequence_base  parent = null,
                              input int                prior = -1,
                              input  uvm_object        extension = null,
                              input string             fname = "",
                              input int                lineno = 0);

使用示例

 p_sequencer.p_rm.counter.mirror(status, UVM_CHECK, UVM_FRONTDOOR);

 

predict:在DUT中的计数器是不断累加的, 但是寄存器模型中的计数器则保持静止。参考模型会不断统计收到了多少包。如果想将参考模型中的数据传递给寄存器模型又不对dut进行操作,可以通过precict,predict操作会更新镜像值和期望值。

其中第一个参数表示要预测的值, 第二个参数是byte_en, 默认-1的意思是全部有效, 第三个参数是预测的类型, 第四个参数是后门访问或者是前门访问。 要实现在参考模型中更新寄存器模型而又不影响DUT的值, 第三个参数需要使用UVM_PREDICT_DIRECT

,第三个参数预测类型有如下几种可以选择

UVM_PREDICT_DIRECT :Predicted value is as-is
UVM_PREDICT_READ :Predict based on the specified value having been read
UVM_PREDICT_WRITE :Predict based on the specified value having been written

   extern virtual function bit predict (uvm_reg_data_t    value,
                                        uvm_reg_byte_en_t be = -1,
                                        uvm_predict_e     kind = UVM_PREDICT_DIRECT,
                                        uvm_path_e        path = UVM_FRONTDOOR,
                                        uvm_reg_map       map = null,
                                        string            fname = "",
                                        int               lineno = 0);

使用示例

p_rm.counter.predict(counter);

 

randomize寄存器模型期望值随机化,可以在uvm_reg_block级别调用randomize函数, 也可以在uvm_reg级别, 甚至可以在uvm_reg_field级别调用:可通过下面调用示例完成寄存器随机化

assert(rm.randomize());
assert(rm.invert.randomize());
assert(rm.invert.reg_data.randomize());

只使用randomize是不能完成寄存器值随机化的还要保证下面三点:

1.当在uvm_reg中定义此field时, 设置为rand类型。

2.在调用此field的configure函数时, 第八个参数设置为1。

3.寄存器类型是可写的
 

 



 

 

  • 10
    点赞
  • 87
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UVM(Universal Verification Methodology)寄存器模型是一用于验证芯片寄存器功能的标准方法。它提供了一个统一的、可重用的框架,用于建立和管理寄存器模型,以及执行寄存器访问和验证UVM寄存器模型的主要组成部分包括寄存器模型寄存器层次结构、寄存器操作和寄存器验证环境。 1. 寄存器模型UVM寄存器模型是一个抽象的表示,用于描述芯片内部的寄存器寄存器字段。它提供了一种结构化的方式来定义寄存器的属性、寄存器字段的位宽和访问权限等。 2. 寄存器层次结构:UVM寄存器模型支持多层级的寄存器结构,可以通过层级关系来描述芯片内部的寄存器模块和子模块。这样可以更好地组织和管理寄存器模型,并提供寄存器之间的相互作用和访问。 3. 寄存器操作:UVM提供了一系列的API,用于执行寄存器读写操作。通过这些API,可以向寄存器模型发送读写请求,并获取响应。同时,还可以对寄存器的访问进行配置和控制,如重置、写入默认值等。 4. 寄存器验证环境:UVM寄存器模型可以与其他验证环境进行集成,以验证寄存器功能的正确性。通过使用事务级建模(TLM)接口,可以将寄存器操作与其他验证组件进行交互,并进行功能验证、覆盖率分析和错误注入等。 总之,UVM寄存器模型提供了一种规范化的方法来描述和验证芯片寄存器功能。它具有可重用性、灵活性和扩展性,并能与其他验证组件进行集成,从而提高验证效率和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值