看了XtremeDV对cluelogic.com的“UVM Tutorial for Candy Lovers”系列的翻译,翻译的很棒。
看原文还有两节没有翻译,自己尝试翻译一下,有不合适地方,敬请谅解并帮忙指出,进行修改。
https://blog.csdn.net/zhajio/category_9272893.html
Jelly_Bean_Taster的寄存器
在UVM的寄存器抽象层(RAL)那一节,我们定义了两个寄存器:RECIPE和TASTE。寄存器RECIPE有4个只写的域(sour,sugar_free,color和flavor)。寄存器TASTE只有一个只读的域(taste)。
![](https://img-blog.csdnimg.cn/ece63cde5ce84e4aa6f2f0b8f18886d7.png)
复位后,DUT和寄存器模型的寄存器值如下。
![](https://img-blog.csdnimg.cn/3b20facf982a4dbba3408afecf14bb74.png)
现在让我们用一个sour-green apple食谱来写寄存器RECIPE(第24行)。
class jelly_bean_reg_sequence extends uvm_reg_sequence;
`uvm_object_utils(jelly_bean_reg_sequence)
function new(string name = "");
super.new(name);
endfunction : new
virtual task body();
jelly_bean_reg_block jb_reg_block;
jelly_bean_types::flavor_e flavor;
jelly_bean_types::color_e color;
bit sugar_free;
bit sour;
jelly_bean_types::taste_e taste;
uvm_status_e status;
uvm_reg_data_t value;
$cast(jb_reg_block, model);
flavor = jelly_bean_types::APPLE;
color = jelly_bean_types::GREEN;
sugar_free = 0;
sour = 1;
jb_reg_block.jb_recipe_reg.write(status, {sour, sugar_free, color, flavor});
taste = jelly_bean_types::taste_e'(jb_reg_block.jb_taste_reg.taste.get_mirrored_value());
`uvm_info("body", $sformatf("taste=%s", taste.name()), UVM_NONE)
endtask : body
endclass : jelly_bean_reg_sequence
寄存器写完后,DUT内部的寄存器值变成如下:
![](https://img-blog.csdnimg.cn/2b2b609b5ad348c083485325cf3c4b7d.png)
值得注意的是,DUT也会更新TASTE寄存器当进行写RECIPE寄存器。然后,寄存器模型(register model)的TASTE寄存器不变仍然是NO_TASTE,你可以从log文件里看到。因为寄存器模型不知道如何更新TASTE寄存器。
![](https://img-blog.csdnimg.cn/775f91456706411783ece18045c27767.png)
UVM_INFO sequences.svh(59) @ 20: uvm_test_top.jb_env.jb_agent.jb_seqr@@jb_reg_seq [body] taste=NO_TASTE
定义一个寄存器回调函数(Register Callback)
为了更新TASTE寄存器,我们准备为RECIPE寄存器定义一个callback(jelly_bean_recipe_reg_callback)。每当写RECIPE寄存器时,这个回调函数就会更新TASTE寄存器。我们继承于uvm_reg_cbs类(line1),该类定义了task: pre_write, post_write, pre_read和post_read。如名字所示,pre_write在寄存器写操作之前被调用,post_write在寄存器写操作后被调用。pre_read在寄存器读之前调用,post_read在寄存器读之后调用。
在本文中,我们只定义task post_write(line10)。当uvm_reg类的write task被调用时,会create一个uvm_reg_item类的object然后调用post_write。寄存器写value存储在uvm_reg_item object的value[0]中。第14行和15行从寄存器中抽出了一些域的值。最后,task基于写进去的值(line18-20)更新TASTE寄存器的taste 域。
class jelly_bean_recipe_reg_callback extends uvm_reg_cbs;
`uvm_object_utils( jelly_bean_recipe_reg_callback )
jelly_bean_taste_reg jb_taste_reg;
function new( string name = "jelly_bean_recipe_reg_callback" );
super.new( name );
endfunction: new
virtual task post_write( uvm_reg_item rw );
jelly_bean_types::flavor_e flavor;
bit sour;
flavor = jelly_bean_types::flavor_e'( rw.value[0][2:0] ); // rw.value[0] holds the written value
sour = rw.value[0][6];
`uvm_info( "post_write", $sformatf( "%s, flavor=%s sour=%b", rw.convert2string(), flavor.name(), sour ), UVM_DEBUG )
if ( flavor == jelly_bean_types::CHOCOLATE && sour )
assert( jb_taste_reg.taste.predict( jelly_bean_types::YUCKY ) );
else
assert( jb_taste_reg.taste.predict( jelly_bean_types::YUMMY ) );
endtask: post_write
endclass: jelly_bean_recipe_reg_callback
使用寄存器回调函数
我们用callback来更新之前的jelly_bean_reg_sequence。第26行和第27行创建/实列了一个callback 类,并让它知道TASTE寄存器(并将TASTE寄存器句柄复制给它)。第28行将callback加到了RECIPE寄存器。
注意:
第28行的uvm_reg_cb是uvm_callbacks的typedef而已,请不要将之前我们用到的uvm_reg_cbs和这里uvm_reg_cb混淆。uvm_callbacks类将给定的callback添加到给定的object。
typedef uvm_callbacks#(uvm_reg, uvm_reg_cbs) uvm_reg_cb;
class jelly_bean_reg_sequence extends uvm_reg_sequence;
`uvm_object_utils( jelly_bean_reg_sequence )
function new( string name = "" );
super.new( name );
endfunction: new
virtual task body();
jelly_bean_reg_block jb_reg_block;
jelly_bean_types::flavor_e flavor;
jelly_bean_types::color_e color;
bit sugar_free;
bit sour;
jelly_bean_types::taste_e taste;
uvm_status_e status;
uvm_reg_data_t value;
jelly_bean_recipe_reg_callback jb_recipe_reg_cb;
$cast( jb_reg_block, model );
flavor = jelly_bean_types::APPLE;
color = jelly_bean_types::GREEN;
sugar_free = 0;
sour = 1;
jb_recipe_reg_cb = jelly_bean_recipe_reg_callback::type_id::create( "jb_recipe_reg_cb" );
jb_recipe_reg_cb.jb_taste_reg = jb_reg_block.jb_taste_reg;
uvm_reg_cb::add( jb_reg_block.jb_recipe_reg, jb_recipe_reg_cb );
jb_reg_block.jb_recipe_reg.write( status, { sour, sugar_free, color, flavor } );
taste = jelly_bean_types::taste_e'( jb_reg_block.jb_taste_reg.taste.get_mirrored_value() );
`uvm_info( "body", $sformatf( "taste=%s", taste.name() ), UVM_NONE )
endtask: body
endclass: jelly_bean_reg_sequence
下面的图显示了本文用到的类。粉色的是UVM类,绿色的是jelly-bean类。
![](https://img-blog.csdnimg.cn/direct/29f9f9947d2646819176eef43ef489fa.png)
仿真
注册完callback后,当写RECIPE寄存器是,寄存器模型也会更新TASTE寄存器的值。
![](https://img-blog.csdnimg.cn/direct/ce6c8dba64c34bcab2d549ad7b664239.png)
UVM_INFO sequences.svh(59) @ 20: uvm_test_top.jb_env.jb_agent.jb_seqr@@jb_reg_seq [body] taste=YUMMY |