mirror,set,write,update

1.1 randomize的影响

(1) randomize操作会改变register field的期望值(uvm_reg_field的post_randomize函数内,会将期望值设置为随机的结果),镜像值不会改变;

1 function void uvm_reg_field::post_randomize();
2    m_desired = value;
3 endfunction: post_randomize

(2) 如果在randomize后,跟着调用update,会将期望值写入DUT;

1.2 randomize的使用

(1) 在向uvm_reg中加入uvm_reg_field时,将加入的uvm_reg_field定义为rand类型;

(2) 在将uvm_reg加入到uvm_reg_block中时,将uvm_reg定义为rand类型;

(3) 如果要使某个uvm_reg_field能够随机化,只是将其定义为rand类型并不够; 在将uvm_reg_field加入uvm_reg时,要调用其configure函数并设置合适的参数;此外,uvm_reg_field还需是合适的类型,如RW, WRC, WRS等;

(4) 可以在uvm_reg_field, uvm_reg等中为randomize定义约束;

2. update

2.1 update操作的影响

(1) update操作会检查寄存器的期望值和镜像值是否一致(调用needs_update进行检查);

(2) 如果期望值(可以调用set()或者randomize()函数进行改变)和镜像值不同,调用update函数,期望值会通过write函数被配置到DUT中(可以指定使用FRONTDOOR还是BACKDOOR),同时镜像值也会更新;

1 my_reg1.myfield2.set(0x11);
2 my_reg1.myfield3.set(1);
3 my_reg1.update();

3. get & set

(1) 获取(get)或修改(set)期望值(不是硬件实际值);set操作会更新期望值,但是镜像值不会改变;

(2) 如果在set后,跟着调用update,会将期望值写入DUT;

 4. mirror

4.1 mirror操作的影响

(1) mirror方法会调用read()函数,读取DUT(读取的方式可以选择BACKDOOR或者FRONTDOOR),然后根据read的返回值,更新镜像值和期望值;

(2) mirror方法的两种应用场景:

一是在仿真中不断的调用它,使得到整个寄存器模型的镜像值与DUT中寄存器的值保持一致,此时check选项是关闭的(即如果mirror操作发现DUT中寄存器的值和寄存器模型中的镜像值不一致,那么在更新寄存器模型之前不给出错误提示);

二是在仿真即将结束时,检查DUT中寄存器的值与寄存器模型中DUT的镜像值是否一致,这种情况下,check选项是打开的;

4.2 mirror源码

(1) mirror操作中会根据check参数的情况,来决定是否把mirror前的寄存器值保存下来; 如果设置了UVM_CHECK,后面会对mirror前后的寄存器值进行比较;

5. predict

5.1 predict操作的影响

(1) 可以实现人为地更新镜像值和期望值为要设置的值,但是同时又不对DUT进行任何操作;这种情况下,需要采用kind的默认值,即UVM_PREDICT_DIRECT;

5.2 predict操作的使用

(1) read/peek和write/poke操作对DUT完成读写后,也会调用此函数,只是它们给出的参数是UVM_PREDICT_READ和UVM_PREDICT_WRITE(使用这两个参数的区别? 详见uvm_reg_field的do_predict函数);

(2) 在显式预测中,predictor内会调用uvm_predict函数进行镜像值的更新;

6. reset

(1) reset方法将寄存器的期望值和镜像值设置为预定义的register reset值;

(2) 当硬件发生reset时,会将内部寄存器值复位,寄存器模型在捕捉到复位事件时,需要调用register model.reset保证硬件和register model的一致性;

(3) 硬件复位后,用户可以通过读取寄存器模型的复位值(与寄存器描述文件一致),与前门访问获取的寄存器复位值进行比较,以此判断硬件各个寄存器的复位值是否按照寄存器描述去实现。

7. get_reset

(1) get_reset方法返回register或者register field预定义的reset值;

(2) get_reset通常和read/mirror共同使用,用于检查register是否被正确的reset;

8.get_parent

9.get_mirrored_value

10. peek/poke (path=BACKDOOR)

(1) peek/poke同属于后门访问register/register field方式, 与backdoor read/write类似,但是peek/poke不会模拟寄存器的行为;

(2)如果对一个只读寄存器进行write操作,无论是BACKDOOR还是FRONTDOOR,都不能写进去,而对其进行poke操作(即写操作),能写进去; 

(3) 如果对一个读清零的寄存器来说,进行read操作,无论是BACKDOOR还是FRONTDOOR, DUT中此寄存器的值在read操作之后都会变为0,而peek则会得到寄存器的值,但是DUT中寄存器的值依然保持不变;

1 regmodel.register.poke(status,value,.parent(this));
2 regmodel.register.peek(status,value,.parent(this));

(4) peek/poke操作完成后,寄存器模型会根据操作的结果更新期望值和镜像值(二者相等);

2. peek源码

(1) peek task内部会判断寄存器是否能进行BACKDOOR操作,比如是否设置该寄存器的hdl path;

(2) 主要是调用backdoor_rd task与do_predict(UVM_PREDICT_READ); do_predict用于更新register model中寄存器的相关值;

task uvm_reg::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);

   uvm_reg_backdoor bkdr = get_backdoor();
   uvm_reg_item rw;

   m_fname = fname;
   m_lineno = lineno;

   if (bkdr == null && !has_hdl_path(kind)) begin
      `uvm_error("RegModel",
        $sformatf("No backdoor access available to peek register \"%s\"",
                  get_full_name()));
      status = UVM_NOT_OK;
      return;
   end

   if(!m_is_locked_by_field)
      XatomicX(1);

   // create an abstract transaction for this operation
   rw = uvm_reg_item::type_id::create("mem_peek_item",,get_full_name());
   rw.element      = this;
   rw.path         = UVM_BACKDOOR;
   rw.element_kind = UVM_REG;
   rw.kind         = UVM_READ;
   rw.bd_kind      = kind;
   rw.parent       = parent;
   rw.extension    = extension;
   rw.fname        = fname;
   rw.lineno       = lineno;

   if (bkdr != null)
     bkdr.read(rw);
   else
     backdoor_read(rw);

   status = rw.status;
   value = rw.value[0];
   `uvm_info("RegModel", $sformatf("Peeked register \"%s\": 'h%h",
                          get_full_name(), value),UVM_HIGH);

   do_predict(rw, UVM_PREDICT_READ);

   if (!m_is_locked_by_field)
      XatomicX(0);
endtask: peek
3. poke源码

(1) 主要是调用backdoor_wr task与do_predict(UVM_PREDICT_WRITE);

(2) 本质上采用的是deposit函数;

(3) poke与backdoor write的区别在于后者在调用backdoor_write操作前,先使用backdoor的read读出原来寄存器的值,把读出来的值以及要写入的数值通过调用uvm_reg_field的XpredictX,得到一个新的值,这个值其实就完全模拟了FRONTDOOR行为的一个值,之后再把这个值写入,而前者则是直接写入;

task uvm_reg::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);

   uvm_reg_backdoor bkdr = get_backdoor();
   uvm_reg_item rw;

   m_fname = fname;
   m_lineno = lineno;


   if (bkdr == null && !has_hdl_path(kind)) begin
      `uvm_error("RegModel",
        {"No backdoor access available to poke register '",get_full_name(),"'"})
      status = UVM_NOT_OK;
      return;
   end

   if (!m_is_locked_by_field)
     XatomicX(1);

   // create an abstract transaction for this operation
   rw = uvm_reg_item::type_id::create("reg_poke_item",,get_full_name());
   rw.element      = this;
   rw.path         = UVM_BACKDOOR;
   rw.element_kind = UVM_REG;
   rw.kind         = UVM_WRITE;
   rw.bd_kind      = kind;
   rw.value[0]     = value & ((1 << m_n_bits)-1);
   rw.parent       = parent;
   rw.extension    = extension;
   rw.fname        = fname;
   rw.lineno       = lineno;

   if (bkdr != null)
     bkdr.write(rw);
   else
     backdoor_write(rw);

   status = rw.status;
   `uvm_info("RegModel", $sformatf("Poked register \"%s\": 'h%h",
                              get_full_name(), value),UVM_HIGH);

   do_predict(rw, UVM_PREDICT_WRITE);

   if (!m_is_locked_by_field)
     XatomicX(0);
endtask: poke

11. read/write (frontdoor)

1 regmodel.register.read(status,value,UVM_FRONTDOOR,.parent(this));
2 regmodel.register.write(status,value,UVM_FRONTDOOR,.parent(this));

11.1 read/write (frontdoor)操作的影响

(1) 当使用front-door(path=BFM), 一个或多个实际的transaction会发往DUT进行register的读写;

(2) 无论通过前门访问还是后门访问的方式从DUT中读取或写入寄存器的值,在操作完成后,寄存器模型都会根据读写的结果更新期望值和镜像值(其实是有前提条件的,对于后门访问,会自动更新镜像值和期望值; 对于前门访问,更新镜像值和期望值有两种方法: (a) auto_predict功能需要打开,即在env中调用uvm_reg_map.set_auto_predict(1),然后调用do-predict函数更新寄存器模型的mirror值; (b)关闭auto_predict功能,使用uvm_reg_predictor进行更新);

(3) 如果寄存器map到多个uvm_address_map,在调用uvm_reg的write/read task进行前门访问时,需要指定uvm_reg_map参数; 

(1) uvm_reg::write

(1.1) FRONTDOOR write操作最终会转换为uvm_reg_map的do_write任务;

(1.2) uvm_reg_map的do_write任务会查看系统是否设置了adapter,如果没有设置,就直接启动sequence, 让sequencer发送uvm_reg_item类型的transaction;如果设置了,那就调用do_bus_write任务.

(1.3) uvm_reg_map的do_write完成后,如果auto predict功能打开了, uvm_reg的do_write会根据写入的值更新register model中寄存器的值;

(2) uvm_reg::do_write

(3) uvm_reg_map.do_write

(3.1) 24到26行把要写的item通过sequencer发送出去,27行调用rw.end_event的wait_on;

(3.2) sequence.finish_item task中会调用sequencer.end_tr,而sequencer.end_tr会在driver调用item_done后结束;

(3.3) sequencer.end_tr内会触发end_event事件;

12. read/write (backdoor)

(1) 当使用back-door(path=BACKDOOR)时, 会通过uvm_hdl_read/uvm_hdl_deposit函数获取或修改DUT register值,而不会通过物理上的interface;

(2) 但是back-door的访问方式会尽量模拟前门访问的行为,比如如果对一个只读寄存器进行后门写操作,由于要模拟DUT的只读行为,所以是写不进去的;

(3) 无论通过前门访问还是后门访问的方式,从DUT中读取或写入寄存器的值,在操作完成后,寄存器模型都会根据读写的结果更新期望值和镜像值(对于前门访问而言,前提条件是system_map.get_auto_predict为1);

寄存器模型有期望值和镜像值,镜像值是用于和DUT保持同步;镜像值是改变DUT中寄存器值的一个变量。可以直接调用write()写入dut;也可以通过set()更新期望值,然后通过update()将期望值写到DUT,最后更新镜像值。

update是将寄存器的期望值与镜像值作对比,不同就将期望值写进dut并更新镜像值;

mirror是将dut的值读出与寄存器模型的值比较并更新寄存器模型的mirror值;

set()会更新期望值,不会更新镜像值;

get()会返回寄存器模型中当前寄存器的期望值;

  read&write操作:这两个操作在前面已经使用过了。无论通过后门访问还是前门访问的方式从 DUT中读取或写入寄存器的 值,在操作完成后,寄存器模型都会根据读写的结果更新期望值和镜像值(二者相等)。
peek&poke操作:前文中也讲述过这两个操作的示例。在操作完成后,寄存器模型会根据操作的结果更新期望值和镜像值 (二者相等)。
randomize操作:寄存器模型提供 randomize接口。
randomize之后,期望值将会变为随机出的数值,镜像值不会改变。但是并不是寄存器模型中所有寄存器都支持此函数。如果不支持,则randomize调用后其期望值不变。 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值