[UVM]图解UVM寄存器訪問方法(Register Access Methods)
图说UVM寄存器訪問方法(Register Access Methods)
前言:UVM的寄存器抽象层(RAL)提供了几种访问寄存器的方法。这篇文章将解释注册表访问方法是如何工作的。在寄存器抽象中,我们介绍了RAL的概述并解释了如何定义寄存器。在这篇文章中,我们将介绍如何访问寄存器。
一、Summary
下表总结了每个方法如何更新register-field对象的属性。
| Method | m_reset | value | m_desired | m_mirrored | DUT |
|---|---|---|---|---|---|
configure | set the value of val | ||||
set_reset(val) | set the value of val | ||||
reset() | copy the value of m_reset | copy the value of m_reset | copy the value of m_reset | ||
set(val) | set the value of val | set the value of val | |||
get_reset() | return the value of m_reset | ||||
get() | return the value of m_desired | ||||
get_mirrored_value() | return the value of m_mirrored | ||||
randomize() | randomize | copy the value of value | |||
write(.value(val)) | set the value of val | set the value of val | set the value of val | write the value of val | |
read(.value(val)) | set the read value | set the read value | set the read value | read the register | |
update() | set the value of m_desired | set the value of m_desired | set the value of m_desired | write the value of m_desired | |
mirror() | set the read value | set the read value | set the read value | read the register | |
predict | set the value of val | set the value of val | set the value of val |
二、uvm_reg_field的屬性
在深入研究寄存器访问方法之前,让我们看看寄存器值是如何存储的。从寄存器抽象中可以看出,uvm_reg_field是最低的寄存器抽象层,它表示寄存器的位。uvm_reg_field使用几个属性来存储各种寄存器字段值:
- m_reset["HARD"]存储一个硬重置值。注意m_reset是一个关联数组,它的键是reset。
- m_mirrored存储了我们在设计测试(DUT)中所认为的值。
- m_desired存储我们想要设置到DUT的值。
- 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 ) );
- 创建与写操作对应的uvm_reg_item对象。
- uvm_reg_adapter将写操作转换为相应的总线事务。
- uvm_driver执行对DUT的总线事务。
- uvm_monitor捕获总线事务。
- uvm_reg_predictor要求
- uvm_reg_adapter将总线事务转换为相应的寄存器操作。
- register操作被转换为uvm_reg_item。
- 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 ) );
- 创建一个与读取操作对应的uvm_reg_item对象。
- uvm_reg_adapter将读取操作转换为相应的总线事务。
- uvm_driver执行对DUT的总线事务。
- uvm_reg_apapter将带有读数据的总线事务转换为寄存器操作。
- read()方法将读值返回给调用者。同时,uvm_monitor捕获总线事务。
- uvm_reg_predictor要求uvm_reg_adapter将总线事务转换为相应的寄存器操作。register操作被转换为uvm_reg_item。
- 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()方法的区别是:
- write()方法接受一个值作为参数,而update()方法使用m_desired属性的值作为要写入的值。
- update()方法只在m_mirrored和m_desired不相等时才写值。

- 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()方法的区别是:
- read()方法将寄存器值返回给调用者,而mirror()方法不返回寄存器值。方法只更新m_mirrored属性的值。
- 如果检查参数的值是UVM_CHECK, mirror()方法会将读值与m_desired值进行比较。
- 关于检查的另一个警告是,如果在配置register字段时将volatile参数设置为1,那么即使将check参数设置为UVM_CHECK,也不会检查register字段。这是因为我们不能确定地预测寄存器字段的值,因为它可能已经在DUT中被更改(volatile)了。
- 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.

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