UVM糖果爱好者教程 - 29.后门访问时HDL路径

我们的  jelly-bean品尝业务非常成功,因此我们决定将我们的业务扩展为与另一名  jelly-bean类品牌合作。 然而,在合并过程中,我们发现合作伙伴的寄存器结构与我们的略有不同。 我们希望通过后门访问合作伙伴的寄存器,而无需修改我们已有的寄存器模型。 但是,我们如何指定HDL路径呢?

伙伴关系(DUT)

这就是新的DUT(jelly_bean_partnership)的外观。


                                                   合作模块(DUT)

合作伙伴模块包括我们的旧jelly_bean_taster以及新的jelly_bean_partner。 我们还添加了一个名为taster_id的新信号,用于选择品尝者或伙伴,以供jelly_bean_if使用。

module jelly_bean_partnership( jelly_bean_if.slave_mp jb_if );
   import jelly_bean_pkg::*;
 
   jelly_bean_if jb_if0( jb_if.clk );
   jelly_bean_if jb_if1( jb_if.clk );
 
   jelly_bean_taster  taster ( jb_if0 );
   jelly_bean_partner partner( jb_if1 );
 
   always @* begin
      jb_if0.flavor     = jb_if.flavor;
      jb_if1.flavor     = jb_if.flavor;
      jb_if0.color      = jb_if.color;
      jb_if1.color      = jb_if.color;
      jb_if0.sugar_free = jb_if.sugar_free;
      jb_if1.sugar_free = jb_if.sugar_free;
      jb_if0.sour       = jb_if.sour;
      jb_if1.sour       = jb_if.sour;
 
      if ( jb_if.taster_id == 0 ) begin
	 jb_if0.command = jb_if.command;
	 jb_if1.command = NO_OP;
	 jb_if.taste    = jb_if0.taste;
      end else begin
	 jb_if0.command = NO_OP;
	 jb_if1.command = jb_if.command;
	 jb_if.taste    = jb_if1.taste;
      end
   end // always @ *
 
endmodule: jelly_bean_partnership

伙伴

合作伙伴模块以与jelly_bean_taster类似的方式进行 jelly-bean品尝。它具有与jelly_bean_taster相同的寄存器,但其结构不同。尤其是:

  • 合作伙伴有一个5位整合的color_and_flavor寄存器(第5行)。
  • sour和free_free寄存器位于另一个称为extra的模块实例中(第37和38行)​​。
module jelly_bean_partner( jelly_bean_if.slave_mp jb_if );
   import jelly_bean_pkg::*;
 
   reg [1:0] taste;
   reg [4:0] color_and_flavor;
   reg [1:0] command;
 
   jelly_bean_extra extra();
 
   initial begin
      color_and_flavor = 0;
      extra.sugar_free = 0;
      extra.sour       = 0;
      command          = 0;
      taste            = 0;
   end
 
   always @ ( posedge jb_if.clk ) begin
      command < = jb_if.command;
      if ( jb_if.command == JB_WRITE ) begin
	 color_and_flavor <= { jb_if.color, jb_if.flavor };
	 extra.sugar_free <= jb_if.sugar_free;
	 extra.sour       <= jb_if.sour;
      end else if ( jb_if.command == JB_READ ) begin
	 jb_if.taste <= #2ns taste;
      end
   end
 
   always @ ( posedge jb_if.clk ) begin
      if ( jb_if.flavor == CHOCOLATE && jb_if.sour ) taste <= YUCKY;
      else if ( jb_if.flavor != NO_FLAVOR )          taste <= YUMMY;
   end
 
endmodule: jelly_bean_partner
 
module jelly_bean_extra;
   reg sugar_free;
   reg sour;
endmodule: jelly_bean_extra

寄存器模型

顶层寄存器块(jelly_bean_partnership_reg_block)实例化我们之前创建的两个jelly_bean_reg_blocks;一个(jb_reg_blocks [0])用于品尝者,另一个(jb_reg_block [1])用于伙伴。


                               顶层寄存器模型

然后,我们将jb_reg_blocks [0]的HDL路径设置为“taster”(第16行),它与jelly_bean_partnership模块中的jelly_bean_taster的实例名称相匹配(请参阅上面的jelly_bean_partnership的第7行)。同样,我们将jb_reg_blocks [1]的HDL路径设置为“partner”(第21行),它与jelly_bean_partnership模块中的jelly_bean_partner的实例名称相匹配(请参阅上面的jelly_bean_partnership的第8行)。

class jelly_bean_partnership_reg_block extends uvm_reg_block;
   `uvm_object_utils( jelly_bean_partnership_reg_block )
 
   rand jelly_bean_reg_block jb_reg_blocks[2];
   uvm_reg_map               reg_map;
 
   function new( string name = "jelly_bean_partnership_reg_block" );
      super.new( .name( name ), .has_coverage( UVM_NO_COVERAGE ) );
   endfunction: new
 
   virtual function void build();
      reg_map = create_map( .name( "reg_map" ), .base_addr( 8'h00 ), 
                            .n_bytes( 1 ), .endian( UVM_LITTLE_ENDIAN ) );
 
      jb_reg_blocks[0] = jelly_bean_reg_block::type_id::create( "jb_reg_blocks[0]" );
      jb_reg_blocks[0].configure( .parent( this ), .hdl_path( "taster" ) );
      jb_reg_blocks[0].build();
      reg_map.add_submap( .child_map( jb_reg_blocks[0].reg_map ), .offset( 0 ) );
 
      jb_reg_blocks[1] = jelly_bean_reg_block::type_id::create( "jb_reg_blocks[1]" );
      jb_reg_blocks[1].configure( .parent( this ), .hdl_path( "partner" ) );
      jb_reg_blocks[1].build();
      reg_map.add_submap( .child_map( jb_reg_blocks[1].reg_map ), .offset( 2 ) );
   endfunction: build
endclass: jelly_bean_partnership_reg_block

设置HDL路径

现在我们准备实例化顶层寄存器模型。首先,假设我们有以下顶层验证平台,我们将顶层寄存器块的HDL路径设置为“top.dut”(下面的jelly_bean_base_test的第18行)。

module top;
  import uvm_pkg::*;
 
  reg clk;
  jelly_bean_if          jb_if( clk );
  jelly_bean_partnership dut( jb_if ); // DUT
 
  // ... omit ...
 
endmodule: top

然后,我们将HDL路径片段设置为伙伴的recipe 寄存器(第22至24行)。请注意,我们在设置切片之前清除了第21行上的jb_recipe_reg的HDL路径。这是因为重用的jelly_bean_recipe_reg已经有HDL路径片段,它们与搭档的HDL路径不匹配(如果您有兴趣,请通过后门在Register Register中查看jelly_bean_recipe_reg的第66至69行)。

class jelly_bean_base_test extends uvm_test;
   `uvm_component_utils( jelly_bean_base_test )
 
   jelly_bean_env                   jb_env;
   jelly_bean_env_config            jb_env_cfg;
   jelly_bean_agent_config          jb_agent_cfg;
   jelly_bean_partnership_reg_block jb_partnership_reg_block;
 
   function new( string name, uvm_component parent );
      super.new( name, parent );
   endfunction: new
 
   function void build_phase( uvm_phase phase );
      jelly_bean_recipe_reg jb_recipe_reg;
 
      super.build_phase( phase );
      jb_partnership_reg_block = jelly_bean_partnership_reg_block::type_id::create( "jb_partnership_reg_block" );
      jb_partnership_reg_block.configure( .hdl_path( "top.dut" ) );
      jb_partnership_reg_block.build();
      jb_recipe_reg = jb_partnership_reg_block.jb_reg_blocks[1].jb_recipe_reg; // shorthand
      jb_recipe_reg.clear_hdl_path();
      jb_recipe_reg.add_hdl_path_slice( .name( "color_and_flavor" ), .offset( 0 ), .size( 5 ) );
      jb_recipe_reg.add_hdl_path_slice( .name( "extra.sugar_free" ), .offset( 5 ), .size( 1 ) );
      jb_recipe_reg.add_hdl_path_slice( .name( "extra.sour"       ), .offset( 6 ), .size( 1 ) );
      jb_partnership_reg_block.lock_model(); // finalize the address mapping
 
   // ... omit ...
 
endclass: jelly_bean_base_test

下表总结了我们为伙伴的配方寄存器定义的总体HDL路径。

Modeljb_partnership_reg_blockjb_reg_block[1]jb_recipe_reg
Pathtop.dutpartnercolor_and_flavor
Pathtop.dutpartnerextra.sugar_free
Pathtop.dutpartnerextra.sour

合作伙伴的品味寄存器使用我们已经在jelly_bean_taste_reg中定义的HDL路径(味道)。

Modeljb_partnership_reg_blockjb_reg_block[1]jb_taste_reg
Pathtop.dutpartnertaste

仅供参考,下表总结了我们为品尝者提供的总体HDL路径。

Modeljb_partnership_reg_blockjb_reg_block[0]jb_recipe_reg
Pathtop.duttasterflavor
Pathtop.duttastercolor
Pathtop.duttastersugar_free
Pathtop.duttastersour
Modeljb_partnership_reg_blockjb_reg_block[0]jb_taste_reg
Pathtop.duttastertaste

寄存器访问sequence

我们使用以下序列验证HDL路径。我们在序列中有三个后门写入(突出显示)。

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_partnership_reg_block jb_partnership_reg_block;
      jelly_bean_reg_block             partner_reg_block;
      flavor_e                         flavor;
      color_e                          color;
      bit                              sugar_free;
      bit                              sour;
      uvm_status_e                     status;
      uvm_reg_data_t                   value;
 
      $cast( jb_partnership_reg_block, model );
      partner_reg_block = jb_partnership_reg_block.jb_reg_blocks[1]; // shorthand
 
      sugar_free = 0;
      sour       = 1;
 
      // back-door writes
      flavor = BLUEBERRY;
      color  = BLUE;
      poke_reg( partner_reg_block.jb_recipe_reg, status, 
                { sour, sugar_free, color, flavor } ); // 'h5A
      #10ns ;
 
      flavor = BUBBLE_GUM;
      color  = GREEN;
      write_reg( partner_reg_block.jb_recipe_reg, status, 
                 { sour, sugar_free, color, flavor }, UVM_BACKDOOR ); // 'h53
      #10ns ;
 
      flavor = CHOCOLATE;
      color  = RED;
      partner_reg_block.jb_recipe_reg.write( status, 
        { sour, sugar_free, color, flavor }, UVM_BACKDOOR, .parent( this ) ); // 'h4C
      #10ns ;
   endtask: body
 
endclass: jelly_bean_reg_sequence

仿真

当你运行一个仿真时,你应该看到像这样的结果:

# KERNEL: UVM_INFO /home/build/vlib1/vlib/uvm-1.2/src/reg/uvm_reg.svh(2820) @ 0:
 reporter [RegModel] Poked register "jb_partnership_reg_block.jb_reg_blocks[1].jb_recipe_reg": 'h000000000000005a
# KERNEL: UVM_INFO @ 10: reporter [RegModel] Wrote register via DPI backdoor: 
 jb_partnership_reg_block.jb_reg_blocks[1].jb_recipe_reg=0x53
# KERNEL: UVM_INFO @ 20: reporter [RegModel] Wrote register via DPI backdoor: 
 jb_partnership_reg_block.jb_reg_blocks[1].jb_recipe_reg=0x4c

我希望这篇文章能帮助你澄清HDL路径。

您可以在EDA Playground上查看并运行代码。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值