UVM——寄存器模型相关的一些函数

0. 引言

  在UVM支持的寄存器操作中,有get、update、mirror、write等等一些方法,在这里整理一下他们的用法。

  寄存器模型中的寄存器值应该与DUT保持同步,但是由于DUT的值是实时更新的,所以寄存器模型并不能实时知道这种更新,在寄存器模型中专门有个值来尽可能与DUT中寄存器的值保持一致,叫镜像值(mirrorred value)。寄存器模型中还有一个值叫期望值(respected value),这个值保存我们希望写入寄存器的值。比如希望向DUT某个寄存器写入'h1,用set函数设置期望值,然后用update任务(update会比较镜像值和期望值,如果不一样,将期望值写入DUT,并更新镜像值)。

 

1.  函数

1.1 set 

1

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

  设置模型中寄存器的期望值,不会改变DUT中这个寄存器的值。

1.2 get

1

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

  返回模型中寄存器的期望值,而不是DUT中的寄存器值

1.3 get_mirrored_value

1

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

  返回模型中寄存器的镜像值。

1.4 get_reset

1

virtual function uvm_reg_data_t get_reset(  string  kind     =  "HARD"  )

  返回寄存器的复位值。

1.5 predict

1

2

3

4

5

6

7

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   )

  更新模型中的镜像值。新的镜像值通过value参数传入。

  当在DUT中实现一个计数器的时候,模型中的计数器是静止的。如果想在模型中得到DUT的技术值,这就需要手动更新镜像值,又不能对DUT进行操作,这可以通过predict函数。

第三个参数是uvm_predict_e枚举类型,他有如下三个元素:

UVM_PREDICT_DIRECTPredicted value is as-is
UVM_PREDICT_READPredict based on the specified value having been read
UVM_PREDICT_WRITEPredict based on the specified value having been written

如果想要更新镜像值又不对DUT进行操作,要用UVM_PREDICT_DIRECT。

  write、read、peek和poke在完成对DUT的读写之后也会调用这个函数,更新镜像值。

1.6 randomize

  无论是uvm_reg,还是uvm_field、uvm_block,都是支持randomize()。

1

2

3

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

assert(rm.invert.randomize());

assert(rm.randomize()):

  

  当寄存器随机化后,期望值会被随机,但是镜像值不变,之后调用update任务,可以更新DUT中的寄存器值。

  但是一个field能够被随机化,需要:

    1. 在filed的configure第八个参数设为1.

    2. filed为rand类型。

    3. filed的读写类型为可写的。

 

2. 任务

2.1  update

1

2

3

4

5

6

7

8

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   )

  将模型中的期望值更新到DUT中。改变DUT中的寄存器。update会检查模型中的期望值和镜像值,如果两者不相等,那么将期望值更新到DUT中,并且更新镜像值。update与mirror操作相反。

  如果镜像值和期望值相同,那么不会写DUT寄存器,也就不会产生总线transaction。

2.2 mirror

1

2

3

4

5

6

7

8

9

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   )

  读DUT中寄存器的值,与update操作相反。如果第二个参数check为UVM_CHECK,那么会检查读取的值与镜像值是否一样,如果不一样报错。通过mirror读取DUT的寄存器值之后,可以再用predict函数,更新镜像值。

  mirror有两种应用场景:一是在仿真中不断调用,但此时是UVM_NO_CHECK,保证镜像值与DUT中的值相等;二是在仿真结束的时候调用,这时是UVM_CHECK检查模型中的镜像值与DUT中的寄存器值是否一致。

2.3 write

1

2

3

4

5

6

7

8

9

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   )

  模仿DUT的行为,通过前门或者后门方式向DUT中写入寄存器值,会产生总线transaction。并且调用predict更新镜像值。

  uvm_path_e定义寄存器操作类型,如下:

UVM_FRONTDOORUse the front door
UVM_BACKDOORUse the back door
UVM_PREDICTOperation derived from observations by a bus monitor via the uvm_reg_predictor class.
UVM_DEFAULT_PATHOperation specified by the context

2.4 read

1

2

3

4

5

6

7

8

9

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   )

  模仿DUT的行为,通过前门或者后门方式读取DUT中寄存器的值,并更新镜像值,会产生总线transaction

2.5 peek

1

2

3

4

5

6

7

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   )

  通过后门访问方式读取寄存器的值,不关心DUT的行为,即使寄存器的读写类型是不能读,也可以将值读出来

 

2.6 poke

1

2

3

4

5

6

7

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   )

  通过后门访问方式写入寄存器的值,不关心DUT的行为,即使寄存器的读写类型是不能写,也可以将值写进去

  • 0
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UVM提供了uvm_reg_backdoor类,用于在测试中访问寄存器的内部实现。这个类可以让我们在测试中使用不同的方式来访问寄存器,以验证寄存器的功能和性能。 uvm_reg_backdoor类主要有两个方法: - `void read(uvm_reg_item rw)`:读取寄存器的值,将结果存储在rw.value中。 - `void write(uvm_reg_item rw)`:写入寄存器的值,将值存储在rw.value中。 其中,`uvm_reg_item`是一个包含寄存器地址、写入/读取值等信息的uvm序列化对象。 要使用uvm_reg_backdoor类,我们需要创建一个新类,继承自uvm_reg_backdoor。在新类的构造函数中,我们需要调用基类的构造函数,并通过该函数将要访问的寄存器作为参数传递。 下面是一个使用uvm_reg_backdoor类的示例: ```systemverilog class my_reg_backdoor extends uvm_reg_backdoor; `uvm_object_utils(my_reg_backdoor) function new(string name = "my_reg_backdoor"); super.new(name); endfunction virtual function void read(uvm_reg_item rw); // 从寄存器中读取值 endfunction virtual function void write(uvm_reg_item rw); // 将值写入寄存器 endfunction endclass ``` 在测试中,我们可以使用uvm_reg_backdoor类的实例来访问寄存器。例如: ```systemverilog my_reg_backdoor my_bd = new; uvm_reg_item rw = new; rw.element = my_reg; rw.kind = UVM_REG; rw.path = UVM_FRONTDOOR; rw.offset = 0; rw.value[0] = 0x1234; my_bd.write(rw); // 从寄存器中读取值 my_bd.read(rw); $display("value = %h", rw.value[0]); ``` 使用uvm_reg_backdoor类可以方便地访问寄存器的内部实现,从而进行更全面和深入的验证。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值