分享

UVM糖果爱好者教程 - 15. “Do”钩子函数

 晓理晓章 2022-01-26

这篇文章将解释用户可定义的do_ *钩子函数。 在Field Macros中,我们看到标准数据方法(如copy()和compare())提供了用户可定义的钩子函数,如do_copy()和do_compare()。 我将在这篇文章中定义这些钩子函数。

具有“do”功能的Jelly Bean事务类。

让我们将“do”函数添加到jelly_bean_transaction类。

do_copy

do_copy()方法由copy()方法调用。 do_copy()方法用于复制jelly_bean_transaction对象的所有属性(第10至14行)。 请注意,我们必须将uvm_object(rhs)转换为jelly_bean_transaction(that)以访问jelly_bean_transaction对象(第4行)的属性。 我们必须调用super.do_copy()来复制在超类中定义的属性。

 virtual function void do_copy( uvm_object rhs );
      jelly_bean_transaction that;
 
      if ( ! $cast( that, rhs ) ) begin
         `uvm_error( get_name(), "rhs is not a jelly_bean_transaction" )
         return;
      end
      super.do_copy( rhs );
      this.flavor     = that.flavor;
      this.color      = that.color;
      this.sugar_free = that.sugar_free;
      this.sour       = that.sour;
      this.taste      = that.taste;
   endfunction: do_copy

do_compare

do_compare()方法由compare()方法调用。 do_compare()用于比较jelly_bean_transaction对象的每个属性。如果比较成功,则do_compare()将返回1,如果比较失败,则返回0(第6至11行)。请注意,为了访问jelly_bean_transaction对象的属性(第4行),我们必须再次将uvm_object(rhs)转换为jelly_bean_transaction(that)。我们必须调用super.do_compare()来比较超类​​的属性(第6行)。 uvm_comparer参数提供了用于比较的策略对象,但我们不使用它。
   virtual function bit do_compare( uvm_object rhs, uvm_comparer comparer );
      jelly_bean_transaction that;
 
      if ( ! $cast( that, rhs ) ) return 0;
 
      return ( super.do_compare( rhs, comparer )  &&
               this.flavor     == that.flavor     &&
               this.color      == that.color      &&
               this.sugar_free == that.sugar_free &&
               this.sour       == that.sour       &&
               this.taste      == that.taste );
   endfunction: do_compare

do_pack

do_pack()方法由pack(),pack_bytes()和pack_ints()方法调用。 do_pack()用于使用uvm_packer策略对象打包jelly_bean_transaction对象的每个属性。请参阅寄存器抽象了解每个属性是如何打包的。打包器决定如何包装。我们必须调用super.do_pack()来打包超类的属性(第5行)。

   virtual function void do_pack( uvm_packer packer );
      bit       R1; // reserved bit
      bit [5:0] R6; // reserved bits
 
      super.do_pack( packer );
      packer.pack_field_int( .value( flavor     ), .size( 3 ) );
      packer.pack_field_int( .value( color      ), .size( 2 ) );
      packer.pack_field_int( .value( sugar_free ), .size( 1 ) );
      packer.pack_field_int( .value( sour       ), .size( 1 ) );
      packer.pack_field_int( .value( R1         ), .size( 1 ) );
      packer.pack_field_int( .value( taste      ), .size( 2 ) );
      packer.pack_field_int( .value( R6         ), .size( 6 ) );
   endfunction: do_pack

do_unpack

do_unpack()方法由unpack(),unpack_bytes()和unpack_ints()方法调用。 do_unpack()用于使用uvm_packer策略对象解压jelly_bean_transaction对象的每个属性。分包器决定了拆包应该如何完成。我们必须调用super.do_unpack()来解压超级类的属性(第5行)。

   virtual function void do_unpack( uvm_packer packer );
      bit       R1; // reserved bit
      bit [5:0] R6; // reserved bits
 
      super.do_unpack( packer );
      flavor     = flavor_e'( packer.unpack_field_int( .size( 3 ) ) );
      color      = color_e '( packer.unpack_field_int( .size( 2 ) ) );
      sugar_free =            packer.unpack_field_int( .size( 1 ) );
      sour       =            packer.unpack_field_int( .size( 1 ) );
      R1         =            packer.unpack_field_int( .size( 1 ) );
      taste      = taste_e '( packer.unpack_field_int( .size( 2 ) ) );
      R6         =            packer.unpack_field_int( .size( 6 ) );
   endfunction: do_unpack

convert2string

convert2string()方法由用户调用以提供字符串形式的对象信息。 convert2string()用于将jelly_bean_transaction对象的每个属性转换为一个字符串。我们应该调用super.convert2string()将超类的属性转换为字符串(第2行)。

   virtual function string convert2string();
      string s = super.convert2string();
      s = { s, $psprintf( "\nname      : %s", get_name()    ) };
      s = { s, $psprintf( "\nflavor    : %s", flavor.name() ) };
      s = { s, $psprintf( "\ncolor     : %s", color.name()  ) };
      s = { s, $psprintf( "\nsugar_free: %b", sugar_free    ) };
      s = { s, $psprintf( "\nsour      : %b", sour          ) };
      s = { s, $psprintf( "\ntaste     : %s", taste.name()  ) };
      return s;
   endfunction: convert2string

Test the“do”Hooks

我们来测试一下“do”钩子。我们将如下定义jelly_bean_test类的run_phase()任务。
  1. 创建三个jelly_bean_transactions;对象jb_tx1,jb_tx2和jb_tx3(第11至13行)。
  2. 随机化jb_tx1(第14行)。
  3. 将jb_tx1的属性复制到jb_tx2(第18行)。
  4. 将jb_tx1的属性复制到jb_tx3,但使用pack()和unpack()方法而不是调用copy()方法(第24和25行)。
  5. 现在jb_tx1,jb_tx2和jb_tx3应该具有相同的属性值。使用compare()方法验证它(第29到39行)。
  6. 使用convert2string()方法打印jb_tx1,jb_tx2和jb_tx3的属性以直观地验证属性值(第43至45行)。
   task run_phase( uvm_phase phase );
      jelly_bean_transaction jb_tx1;
      jelly_bean_transaction jb_tx2;
      jelly_bean_transaction jb_tx3;
      uvm_packer jb_packer;
      bit bitstream[];
      int num_bits;
 
      phase.raise_objection( .obj( this ) );
 
      jb_tx1 = jelly_bean_transaction::type_id::create( "jb_tx1" );
      jb_tx2 = jelly_bean_transaction::type_id::create( "jb_tx2" );
      jb_tx3 = jelly_bean_transaction::type_id::create( "jb_tx3" );
      assert( jb_tx1.randomize() );
 
      // copy jb_tx1 to jb_tx2
 
      jb_tx2.copy( jb_tx1 );
 
      // create jb_tx3 by packing and unpacking jb_tx1
 
      jb_packer = new;
      jb_packer.big_endian = 0;
      num_bits = jb_tx1.pack  ( bitstream, jb_packer );
      num_bits = jb_tx3.unpack( bitstream, jb_packer );
 
      // check if jb_tx1, jb_tx2 and jb_tx3 have the same properties
 
      if ( jb_tx1.compare( jb_tx2 ) ) begin
         `uvm_info( get_name(), "jb_tx1 and jb_tx2 matched", UVM_NONE )
      end else begin
         `uvm_error( get_name(), "jb_tx1 and jb_tx2 mismatched" )
      end
 
      if ( jb_tx2.compare( jb_tx3 ) ) begin
         `uvm_info( get_name(), "jb_tx2 and jb_tx3 matched", UVM_NONE )
      end else begin
         `uvm_error( get_name(), "jb_tx2 and jb_tx3 mismatched" )
      end
 
      // print each object
 
      `uvm_info( get_name(), jb_tx1.convert2string(), UVM_NONE )
      `uvm_info( get_name(), jb_tx2.convert2string(), UVM_NONE )
      `uvm_info( get_name(), jb_tx3.convert2string(), UVM_NONE )
 
      phase.drop_objection( .obj( this ) );
   endtask: run_phase

您可能已经注意到我们在第22行创建了一个uvm_packer对象(jb_packer),并将它的big_endian属性设置为0(第23行)。我们在打包和解压jelly_bean_transaction(第24行和第25行)时使用了此打包器。这是为了确保我们将每个属性值打包成小端数,正如我们在寄存器抽象中所做的那样。如果您只想打包并解压缩并且不关心比特流表示,则不必创建uvm_packer对象。如果未指定uvm_packer,则将使用全局uvm_default_packer策略,其中big_endian的值为1.下图显示big_endian的值如何影响比特流表示形式。 m_bits是uvm_packer的一个属性,它以位数组( bit array)的形式表示打包比特流。


Simulation

这是一个仿真结果。如您所见,所有三个jelly_bean_transactions都具有相同的属性值。

UVM_INFO jb15.sv(589) @ 0: uvm_test_top [uvm_test_top] jb_tx1 and jb_tx2 matched
UVM_INFO jb15.sv(595) @ 0: uvm_test_top [uvm_test_top] jb_tx2 and jb_tx3 matched
UVM_INFO jb15.sv(602) @ 0: uvm_test_top [uvm_test_top]
name      : jb_tx1
flavor    : CHOCOLATE
color     : RED
sugar_free: 1
sour      : 0
taste     : UNKNOWN
UVM_INFO jb15.sv(603) @ 0: uvm_test_top [uvm_test_top]
name      : jb_tx2
flavor    : CHOCOLATE
color     : RED
sugar_free: 1
sour      : 0
taste     : UNKNOWN
UVM_INFO jb15.sv(604) @ 0: uvm_test_top [uvm_test_top]
name      : jb_tx3
flavor    : CHOCOLATE
color     : RED
sugar_free: 1
sour      : 0
taste     : UNKNOWN

我希望这篇教程能帮助你理解“do”钩子函数。


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多