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

UVM——RAL模型运用之三(uvm_reg的访问方法介绍) - 灰信网(软件开发博客聚合)

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

  寄存器模型相关类的访问方法:

  在此注意区分,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值属性是公共的。 其他属性是本地的,因此我们无法直接从类外访问它们。 对于本地属性只能使用寄存器访问方法进行访问


源代码如下:m_reset值不是必需的

<span style="background-color:#fafafa"><span style="color:#000000"><code class="language-c">`ifndef  UVM_REG_ADDR_WIDTH
    `define  UVM_REG_ADDR_WIDTH   <span style="color:#986801">64</span>       <span style="color:#708090">//定义宏</span>
`endif
`ifndef  UVM_REG_ADDR_WIDTH
    `define  UVM_REG_DATA_WIDTH   <span style="color:#986801">64</span>      <span style="color:#708090">//定义宏</span>
`endif
<span style="color:#0077aa">typedef</span> bit <span style="color:#0077aa">unsigned</span> <span style="color:#999999">[</span>`UVM_REG_DATA_WIDTH<span style="color:#a67f59">-</span><span style="color:#986801">1</span> :<span style="color:#986801">0</span><span style="color:#999999">]</span>    uvm_reg_data_t<span style="color:#999999">;</span>
<span style="color:#0077aa">typedef</span> bit <span style="color:#0077aa">unsigned</span> <span style="color:#999999">[</span>`UVM_REG_ADDR_WIDTH<span style="color:#a67f59">-</span><span style="color:#986801">1</span> :<span style="color:#986801">0</span><span style="color:#999999">]</span>    uvm_reg_addr_t<span style="color:#999999">;</span>

class uvm_reg_field extends uvm_object<span style="color:#999999">;</span>
   `<span style="color:#dd4a68">uvm_object_utils</span><span style="color:#999999">(</span>uvm_reg_field<span style="color:#999999">)</span>
   rand   uvm_reg_data_t   value<span style="color:#999999">;</span>        <span style="color:#708090">//1. 公共属性,针对覆盖率和随机化</span>
   local  uvm_reg_data_t   m_mirrored<span style="color:#999999">;</span>   <span style="color:#708090">//2. 本地属性,DUT的镜像值</span>
   local  uvm_reg_data_t   m_desired<span style="color:#999999">;</span>    <span style="color:#708090">//3. 本地属性,期望值,用户域值</span>
endclass
</code></span></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

2.2. CONFIGURE()配置UVM_REG_FIELD

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

<span style="background-color:#fafafa"><span style="color:#000000"><code class="language-c">rxtx0 <span style="color:#a67f59">=</span> uvm_reg_field<span style="color:#999999">:</span><span style="color:#999999">:</span>type_id<span style="color:#999999">:</span><span style="color:#999999">:</span><span style="color:#dd4a68">create</span><span style="color:#999999">(</span> <span style="color:#50a14f">"rxtx0"</span> <span style="color:#999999">)</span><span style="color:#999999">;</span>         <span style="color:#708090">//</span>
rxtx0<span style="color:#999999">.</span><span style="color:#dd4a68">configure</span><span style="color:#999999">(</span> <span style="color:#999999">.</span>parent                 <span style="color:#999999">(</span> this <span style="color:#999999">)</span><span style="color:#999999">,</span>         <span style="color:#708090">//此域的父辈,也就是此域位于哪个寄存器中,即是this;</span>
                  <span style="color:#999999">.</span>size                   <span style="color:#999999">(</span> <span style="color:#986801">3</span>    <span style="color:#999999">)</span><span style="color:#999999">,</span>        <span style="color:#708090">//此域的宽度</span>
                  <span style="color:#999999">.</span>lsb_pos                <span style="color:#999999">(</span> <span style="color:#986801">0</span>    <span style="color:#999999">)</span><span style="color:#999999">,</span>        <span style="color:#708090">//此域的最低位在整个寄存器的位置</span>
                  <span style="color:#999999">.</span>access                 <span style="color:#999999">(</span> <span style="color:#50a14f">"RW"</span> <span style="color:#999999">)</span><span style="color:#999999">,</span>        <span style="color:#708090">//此域段的存取方式(属性);</span>
                  <span style="color:#999999">.</span><span style="color:#0077aa">volatile</span>               <span style="color:#999999">(</span> <span style="color:#986801">0</span>    <span style="color:#999999">)</span><span style="color:#999999">,</span>        <span style="color:#708090">//是否是易失的(volatile),这个参数一般不会使用;</span>
                  <span style="color:#999999">.</span>reset                  <span style="color:#999999">(</span> <span style="color:#986801">0</span>    <span style="color:#999999">)</span><span style="color:#999999">,</span>        <span style="color:#708090">//此域上电复位后的默认值;</span>
                  <span style="color:#999999">.</span>has_reset              <span style="color:#999999">(</span> <span style="color:#986801">1</span>    <span style="color:#999999">)</span><span style="color:#999999">,</span>        <span style="color:#708090">//此域可复位</span>
                  <span style="color:#999999">.</span>is_rand                <span style="color:#999999">(</span> <span style="color:#986801">1</span>    <span style="color:#999999">)</span><span style="color:#999999">,</span>        <span style="color:#708090">//是否可随机化</span>
                  <span style="color:#999999">.</span><span style="color:#dd4a68">individually_accessible</span><span style="color:#999999">(</span> <span style="color:#986801">0</span>    <span style="color:#999999">)</span> <span style="color:#999999">)</span><span style="color:#999999">;</span>      <span style="color:#708090">//是否可以单独存取</span>
</code></span></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

  如果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()方法。
<span style="background-color:#fafafa"><span style="color:#000000"><code class="language-c">       regmodel<span style="color:#999999">.</span><span style="color:#0077aa">register</span><span style="color:#999999">.</span><span style="color:#dd4a68">set</span><span style="color:#999999">(</span>value<span style="color:#999999">)</span><span style="color:#999999">;</span>            <span style="color:#708090">//设置本地寄存器的期望值</span>
</code></span></span>
  • 1
  • get()方法——读取模型寄存器域段的期望值。 get()方法不会从DUT中的寄存器获取值。它只获取m_desired属性的值。要实际从DUT获取值,请使用read()或mirror()方法。
<span style="background-color:#fafafa"><span style="color:#000000"><code class="language-c">还有两个get方法访问本地属性。 
         get_reset()            ————检索m_reset <span style="color:#999999">[</span>kind<span style="color:#999999">]</span>属性的值,
         get_mirrored_value()   ————方法检索m_mirrored属性的值。
使用方法:
        desired_value <span style="color:#a67f59">=</span> regmodel<span style="color:#999999">.</span><span style="color:#0077aa">register</span><span style="color:#999999">.</span><span style="color:#dd4a68">get</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span>                  <span style="color:#708090">//读取期望值</span>
        mirrored_value <span style="color:#a67f59">=</span> regmodel<span style="color:#999999">.</span><span style="color:#0077aa">register</span><span style="color:#999999">.</span><span style="color:#dd4a68">get_mirrored_value</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span>  <span style="color:#708090">//读取镜像值</span>
</code></span></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • randomize()方法——随机化一个模型寄存器域段对象期望值。
    (随机化后,post_randomize()方法将value属性的值复制到m_desired属性。请注意,如果value属性的rand_mode为OFF,则pre_randomize()方法会将m_desired的值复制到value属性。)
<span style="background-color:#fafafa"><span style="color:#000000"><code class="language-c">        <span style="color:#0077aa">register</span><span style="color:#999999">.</span><span style="color:#dd4a68">randomize</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span>              <span style="color:#708090">//随机化创建期望值</span>
</code></span></span>
  • 1

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

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

write()方法实现涉及多个步骤:见下图

1)、在reg_seq中创建与写入操作对应的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用于更新值,value、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用于更新值,value、m_mirrored和m_desired属性。

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

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

<span style="background-color:#fafafa"><span style="color:#000000"><code class="language-c">     regmodel<span style="color:#999999">.</span><span style="color:#0077aa">register</span><span style="color:#999999">.</span><span style="color:#dd4a68">update</span><span style="color:#999999">(</span>status<span style="color:#999999">,</span> <span style="color:#999999">[</span>path<span style="color:#999999">]</span><span style="color:#999999">,</span> <span style="color:#999999">.</span><span style="color:#dd4a68">parent</span><span style="color:#999999">(</span>this<span style="color:#999999">)</span><span style="color:#999999">)</span><span style="color:#999999">;</span>        <span style="color:#708090">//可以使用前门访问,也可以使用后门访问</span>
     <span style="color:#dd4a68">update_reg</span><span style="color:#999999">(</span>model<span style="color:#999999">,</span> status<span style="color:#999999">,</span> <span style="color:#999999">[</span>path<span style="color:#999999">]</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
</code></span></span>
  • 1
  • 2

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

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

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

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

<span style="background-color:#fafafa"><span style="color:#000000"><code class="language-c">     regmodel<span style="color:#999999">.</span><span style="color:#0077aa">register</span><span style="color:#999999">.</span><span style="color:#dd4a68">mirror</span><span style="color:#999999">(</span>status<span style="color:#999999">,</span> <span style="color:#999999">[</span>check<span style="color:#999999">]</span><span style="color:#999999">,</span> <span style="color:#999999">[</span>path<span style="color:#999999">]</span><span style="color:#999999">,</span> <span style="color:#999999">.</span><span style="color:#dd4a68">parent</span><span style="color:#999999">(</span>this<span style="color:#999999">)</span><span style="color:#999999">)</span><span style="color:#999999">;</span>       <span style="color:#708090">//可以前门访问也可以后门访问</span>
     <span style="color:#dd4a68">mirror_reg</span><span style="color:#999999">(</span>regmodel<span style="color:#999999">.</span><span style="color:#0077aa">register</span><span style="color:#999999">,</span> status<span style="color:#999999">,</span> <span style="color:#999999">[</span>check<span style="color:#999999">]</span><span style="color:#999999">,</span> <span style="color:#999999">[</span>path<span style="color:#999999">]</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
</code></span></span>
  • 1
  • 2

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

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

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

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

<span style="background-color:#fafafa"><span style="color:#000000"><code class="language-c">        regmodel<span style="color:#999999">.</span><span style="color:#0077aa">register</span><span style="color:#999999">.</span><span style="color:#dd4a68">predict</span><span style="color:#999999">(</span>value<span style="color:#999999">)</span><span style="color:#999999">;</span>                         <span style="color:#708090">//设置镜像值</span>
        mirrored_value <span style="color:#a67f59">=</span> regmodel<span style="color:#999999">.</span><span style="color:#0077aa">register</span><span style="color:#999999">.</span><span style="color:#dd4a68">get_mirrored_value</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span>  <span style="color:#708090">//读取镜像值</span>
</code></span></span>
  • 1
  • 2


参考:http://cluelogic.com/2013/02/uvm-tutorial-for-candy-lovers-register-access-methods/

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值