[UVM]图解UVM寄存器訪問方法(Register Access Methods)

            图说UVM寄存器訪問方法(Register Access Methods)

 

       前言:UVM的寄存器抽象层(RAL)提供了几种访问寄存器的方法。这篇文章将解释注册表访问方法是如何工作的。在寄存器抽象中,我们介绍了RAL的概述并解释了如何定义寄存器。在这篇文章中,我们将介绍如何访问寄存器。

 

一、Summary

       下表总结了每个方法如何更新register-field对象的属性。

Methodm_reset
["HARD"]
valuem_desiredm_mirroredDUT
configure
(.reset(val),
.has_reset(1))
set the value of val    
set_reset(val)set the value of val    
reset() copy the value of m_reset
["HARD"]
copy the value of m_reset
["HARD"]
copy the value of m_reset
["HARD"]
 
set(val) set the value of valset the value of val  
get_reset()return the value of m_reset
["HARD"]
    
get()  return the value of m_desired  
get_mirrored_value()   return the value of m_mirrored 
randomize() randomizecopy the value of value  
write(.value(val)) set the value of valset the value of valset the value of valwrite the value of val
read(.value(val)) set the read valueset the read valueset the read valueread the register
update() set the value of m_desiredset the value of m_desiredset the value of m_desiredwrite the value of m_desired
mirror() set the read valueset the read valueset the read valueread the register
predict
(.value(val))
 set the value of valset the value of valset the value of val

 

二、uvm_reg_field的屬性

       在深入研究寄存器访问方法之前,让我们看看寄存器值是如何存储的。从寄存器抽象中可以看出,uvm_reg_field是最低的寄存器抽象层,它表示寄存器的位。uvm_reg_field使用几个属性来存储各种寄存器字段值:

  1. m_reset["HARD"]存储一个硬重置值。注意m_reset是一个关联数组,它的键是reset。
  2. m_mirrored存储了我们在设计测试(DUT)中所认为的值。
  3. m_desired存储我们想要设置到DUT的值。
  4. value存储要在功能覆盖中采样的值,或在随机化字段时要约束的值。

       注意,在这些属性中,只有value属性是公共的。其他属性是本地的,因此我们不能从类的外部直接访问它们。稍后,我们将向您展示如何使用寄存器访问方法访问这些本地属性。

        

 

 2.1、configure()

       在创建uvm_reg_field之后,我们要做的第一件事就是配置它。在Register抽象中,我们对flavor字段的配置如下。注意,在寄存器抽象中,我们将flavor字段定义为“WO”(只写),但这里我们将它定义为“RW”(读/写),以使该字段更加通用。

flavor = uvm_reg_field::type_id::create( "flavor" );
flavor.configure( .parent                 ( this ),.size                   ( 3    ),.lsb_pos                ( 0    ),.access                 ( "RW" ),.volatile               ( 0    ),.reset                  ( 0    ),.has_reset              ( 1    ),.is_rand                ( 1    ),.individually_accessible( 0    ) );
  • 如果has_reset参数为1,则reset参数的值将作为“硬”重置值。如果has_reset值为0,则会忽略reset的值。reset的值应与DUT的reset状态相匹配。如果希望在配置之后修改重置值,可以使用set_reset()方法。
flavor.set_reset( .value( 0 ), .kind( "HARD" ) ); // kind == "HARD" by default

        

 

 2.2、reset()

       如果存在m_reset[kind], reset()方法将重置寄存器字段的属性。默认的类型是“硬”。如果m_reset[kind]不存在,reset()方法什么也不做。请注意,reset()方法不会重置DUT中的寄存器。它只重置register-field对象的属性。

flavor.reset( .kind( "HARD" ) ); // kind == "HARD" by default

 

 2.3、set()

       方法的作用是:设置寄存器字段的期望值。set()方法不将值设置为DUT中的寄存器。它只将值设置为m_desired和register-field对象的值属性。要实际设置DUT中的寄存器的值,请使用write()或update()方法。这些方法将在后面解释。

flavor.set( .value( 1 ) );

 

 2.4、get()

       get()方法获取寄存器字段的期望值。get()方法不从DUT中的寄存器获取值。它只获取m_desired属性的值。要实际从DUT获取值,请使用read()或mirror()方法。这些方法将在后面解释。与get()方法类似,还有两个getter方法来访问本地属性。get_reset()方法检索m_reset[kind]属性的值,而get_red_value()方法检索m_属性的值。

uvm_reg_data_t desired_value  = flavor.get();
uvm_reg_data_t reset_value    = flavor.get_reset( .kind( "HARD" ) ); // kind == "HARD" by default
uvm_reg_data_t mirrored_value = flavor.get_mirrored_value();

 

 2.5、randomize()

       randomize()方法是SystemVerilog方法。它随机化寄存器字段对象的值属性。在随机化之后,post_randomize()方法将value属性的值复制到m_desired属性。注意,如果值属性的rand_mode关闭,那么pre_randomize()方法会将m_desired的值复制到值属性。  

 

 2.6、write()

       write()方法实际上将一个值写入DUT。write()方法涉及多个步骤。

uvm_status_e status;
flavor.write( .status( status ), .value( 1 ) );
  1. 创建与写操作对应的uvm_reg_item对象。
  2. uvm_reg_adapter将写操作转换为相应的总线事务。
  3. uvm_driver执行对DUT的总线事务。
  4. uvm_monitor捕获总线事务。
  5. uvm_reg_predictor要求
  6. uvm_reg_adapter将总线事务转换为相应的寄存器操作。
  7. register操作被转换为uvm_reg_item。
  8. uvm_reg_item用于更新值、m_mirrored和m_desired属性。

       注意,如果在配置寄存器字段时,individual _accessible参数为0,那么将写入包含该字段的整个寄存器,因为该字段不是单独可访问的。在这种情况下,m_mirrored值用作其他字段的写值。

 

 2.7、read()

       read()方法实际上从DUT中读取寄存器值。与write()方法类似,read()方法涉及多个步骤。

uvm_status_e   status;
uvm_reg_data_t value;flavor.read( .status( status ), .value( value ) );
  1. 创建一个与读取操作对应的uvm_reg_item对象。
  2. uvm_reg_adapter将读取操作转换为相应的总线事务。
  3. uvm_driver执行对DUT的总线事务。
  4. uvm_reg_apapter将带有读数据的总线事务转换为寄存器操作。
  5. read()方法将读值返回给调用者。同时,uvm_monitor捕获总线事务。
  6. uvm_reg_predictor要求uvm_reg_adapter将总线事务转换为相应的寄存器操作。register操作被转换为uvm_reg_item。
  7. uvm_reg_item用于更新值、m_mirrored和m_desired属性。

        注意,如果在配置寄存器字段时,individual _accessible参数为0,那么将读取包含该字段的整个寄存器。在这种情况下,m_mirrored值也会为其他字段更新。 

 

 2.8、update()

       update()方法实际上将寄存器值写入DUT。update()方法属于uvm_reg类。uvm_reg_field类没有update()方法。

uvm_status_e status;jb_recipe_reg.update( .status( status ) );

      write()方法和update()方法的区别是:

  1. write()方法接受一个值作为参数,而update()方法使用m_desired属性的值作为要写入的值。
  2. update()方法只在m_mirrored和m_desired不相等时才写值。

  1. update()方法在内部调用write(.value(m_desired))。因此,m_mirrored的值在更新之后也会被更新。

 

 2.9、mirror()

       mirror()方法实际上从DUT读取寄存器。

uvm_status_e status;
flavor.mirror( .status( status ), .check( UVM_CHECK ) );

       read()方法和mirror()方法的区别是:

  1. read()方法将寄存器值返回给调用者,而mirror()方法不返回寄存器值。方法只更新m_mirrored属性的值。
  2. 如果检查参数的值是UVM_CHECK, mirror()方法会将读值与m_desired值进行比较。
  3. 关于检查的另一个警告是,如果在配置register字段时将volatile参数设置为1,那么即使将check参数设置为UVM_CHECK,也不会检查register字段。这是因为我们不能确定地预测寄存器字段的值,因为它可能已经在DUT中被更改(volatile)了。
  4. mirror()方法在内部调用do_read()方法。这与read()方法在内部调用的方法相同。因此,除了 m_mirrored属性之外,mirror()方法还将更新值和m_desired属性。

 

 2.10、predict()

       The predict() method updates the mirrored value.

flavor.predict( .value( 1 ) );

       The predict() method also updates the value and the m_desired properties.

        

 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部