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/