UVM——RAL模型运用之三(uvm_reg的访问方法介绍)


文章目录

  • 一、寄存器的访问方法汇总
  • 二、以前门访问方式对方法进行说明
    • 2.1. uvm_reg_field的属性成员介绍
    • 2.2. configure()配置uvm_reg_field
    • 2.3. 方法——reset()/get()/set()/randomize()—操作期望值
    • 2.4. 方法——write()—写入DUT
    • 2.5. 方法——read()—读出DUT
    • 2.6. 方法——update()—写入DUT和更新镜像值
    • 2.7. 方法——mirror()—读取DUT和更新镜像值
    • 2.8. 方法——predict()—操作镜像值

一、寄存器的访问方法汇总

??寄存器模型相关类的访问方法:
在这里插入图片描述
??在此注意区分,uvm_reg所提供的四种方法read()、write()、peek()、poke(),其中read()、write()用于前门访问时,只针对寄存器对象;用于后门访问时,不仅针对寄存器对象,还针对寄存器域。而peek()、poke()只能用于后门访问即针对寄存器对象(Register)、还针对寄存器域(Field)和寄存器块(Block)。详细用法在键RAL用法二。

??寄存器序列提供的寄存器访问方法:
在这里插入图片描述

??上述方法由uvm_reg_sequence序列所提供,针对寄存器对象(Register)操作。

二、以前门访问方式对方法进行说明

2.1. uvm_reg_field的属性成员介绍

??在对寄存器访问方式进行介绍之前,先了解uvm_reg_field是如何存储寄存器的值。 uvm_reg_field使用四个属性来存储各种寄存器字段值

  • m_reset [“HARD”]——存储硬件复位值。 m_reset是一种带有重置键的关联数组。
  • m_mirrored镜像值)——存储DUT当前的已知状态值,镜像值往往有模型预测给出。
  • m_desired期望值)——存储我们想要设置给DUT的值,用以更新硬件(DUT)值。
  • value真实值)——存储硬件(DUT)真实值,该值会被采样并存储在功能覆盖率中,或者当该字段被随机化时该value值会被约束。

??在这些属性中,只有value值属性是公共的。 其他属性是本地的,因此我们无法直接从类外访问它们。 对于 本地属性只能使用寄存器访问方法进行访问

在这里插入图片描述

2.2. configure()配置uvm_reg_field

??在 创建uvm_reg_field后执行的第一件事是配置它。在寄存器抽象中,我们如下配置“rxtx0”域段。请注意,在Register Abstraction中,我们将“rxtx0”域段定义为“RW”(读/写),以使该字段更通用。知道各个参数的含义。

1
2
3
4
5
6
7
8
9
10
rxtx0 = uvm_reg_field::type_id::create( "rxtx0" );         //
rxtx0.configure( .parent                 ( this ),         //此域的父辈,也就是此域位于哪个寄存器中,即是this;
                  .size                   ( 3    ),        //此域的宽度
                  .lsb_pos                ( 0    ),        //此域的最低位在整个寄存器的位置
                  .access                 ( "RW" ),        //此域段的存取方式(属性);
                  .volatile               ( 0    ),        //是否是易失的(volatile),这个参数一般不会使用;
                  .reset                  ( 0    ),        //此域上电复位后的默认值;
                  .has_reset              ( 1    ),        //此域可复位
                  .is_rand                ( 1    ),        //是否可随机化
                  .individually_accessible( 0    ) );      //是否可以单独存取

??如果has_reset参数为1,则复位参数的值将被视为“HARD”复位值。如果has_reset值为0,则复位值将被忽略。复位值应与DUT的复位状态相匹配。如果您想在配置后修改复位值,可以使用set_reset()方法。

2.3. 方法——reset()/get()/set()/randomize()—操作期望值

  • reset()方法——只复位模型寄存器域段对象的复位值属性。不会复位DUT中的寄存器。注意,如果m_reset [kind]存在,reset()方法将重置寄存器域段的属性。默认类型是“HARD”。如果m_reset [kind]不存在,则reset()方法不执行任何操作。
  • set()方法——设置(修改)模型寄存器域段的期望值。 set()方法不会修改DUT中的寄存器的值。要真正将值设置为DUT中的寄存器,请使用write()或update()方法。
1
       regmodel.register.set(value);            //设置本地寄存器的期望值
  • get()方法——读取模型寄存器域段的期望值。 get()方法不会从DUT中的寄存器获取值。它只获取m_desired属性的值。要实际从DUT获取值,请使用read()或mirror()方法。
1
2
3
4
5
6
还有两个get方法访问本地属性。
         get_reset()            ————检索m_reset [kind]属性的值,
         get_mirrored_value()   ————方法检索m_mirrored属性的值。
使用方法:
        desired_value = regmodel.register.get();                  //读取期望值
        mirrored_value = regmodel.register.get_mirrored_value();  //读取镜像值
  • randomize()方法——随机化一个模型寄存器域段对象期望值。
    (随机化后,post_randomize()方法将value属性的值复制到m_desired属性。请注意,如果value属性的rand_mode为OFF,则pre_randomize()方法会将m_desired的值复制到value属性。)
1
        register.randomize();              //随机化创建期望值

2.4. 方法——write()—写入DUT

?? write()方法实际上向DUT写入一个值。语法见上一节。注意,如果在配置寄存器域段时,individually_accessible访问参数为0,则包含该域段的整个寄存器会被写入,因为该字段不可单独访问。在这种情况下,m_mirrored值将用作其他域段的写入值。

write()方法实现涉及多个步骤:见下图
在这里插入图片描述
1)、创建与写入操作对应的uvm_reg_item对象。
2)、uvm_reg_adapter将写入操作转换为相应的总线事务。
3)、uvm_driver执行到DUT的总线事务。
4)、uvm_monitor捕获总线事务。
5)、uvm_reg_predictor要求uvm_reg_adapter将总线事务转换为相应的寄存器操作。
6)、寄存器操作转换为uvm_reg_item。
7)、uvm_reg_item用于更新值,m_mirrored和m_desired属性。

2.5. 方法——read()—读出DUT

?? write()方法实际上从DUT读取一个寄存器值.语法见上一节。注意,如果在配置寄存器域段时,individually_accessible访问参数为0,则会读取包含域段的整个寄存器。在这种情况下,也会为其他字段更新m_mirrored值。

read()方法实现涉及多个步骤:见下图
在这里插入图片描述

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

2.6. 方法——update()—写入DUT和更新镜像值

?? update()方法——实际上是向DUT写入一个寄存器值,同时更新镜像值。只有期望值与镜像值不一致,才向DUT写入期望值。 update()方法属于uvm_reg类。

1
2
     regmodel.register.update(status, [path], .parent(this));        //可以使用前门访问,也可以使用后门访问
     update_reg(model, status, [path]);

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

  • write()方法将一个值作为其参数写入,而update()方法使用m_desired属性的值作为要写入的值。
  • 只有当m_mirrored和m_desired不相等时,update()方法才向DUT写入该值。
    在这里插入图片描述

2.7. 方法——mirror()—读取DUT和更新镜像值

?? mirror()方法——实际上是从DUT读取一个寄存器值,并将它们更新到寄存器模型中。

1
2
     regmodel.register.mirror(status, [check], [path], .parent(this));       //可以前门访问也可以后门访问
     mirror_reg(regmodel.register, status, [check], [path]);

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

  • read()方法返回寄存器值给调用者,而mirror()方法不返回寄存器值。 mirror()方法只更新m_mirrored属性的值。
  • 如果check参数的值默认为UVM_NO_CHECK,但若为为UVM_CHECK,则mirror()方法将读取值与镜像值进行比较。
    在这里插入图片描述

2.8. 方法——predict()—操作镜像值

?? predict()方法——只用于设置模型寄存器镜像值 。人为的根据DUT来更新寄存器模型中的镜像值。但同时又不对DUT进行任何操作。

1
2
        regmodel.register.predict(value);                         //设置镜像值
        mirrored_value = regmodel.register.get_mirrored_value();  //读取镜像值

在这里插入图片描述
参考:http://cluelogic.com/2013/02/uvm-tutorial-for-candy-lovers-register-access-methods/