UVM糖果爱好者教程 - 4.代理

上一篇文章集中讨论了 jelly-bean系统的transaction和sequence。本文将深入解释验证环境中的验证组件。

interface

在这一部分,将提供接口(jelly_bean_if)的一般解释及其绑定验证组件和jelly-bean(DUT)的作用。

下图显示了jelly_bean_if的内容。实质上,jelly_bean_if已包含从jelly_bean_transaction中的属性转换而来的信号。

interface jelly_bean_if(input bit clk);
   logic [2:0] flavor;
   logic [1:0] color;
   logic       sugar_free;
   logic       sour;
   logic [1:0] taste;
 
   clocking master_cb @ (posedge clk);
      default input #1step output #1ns;
      output flavor, color, sugar_free, sour;
      input  taste;
   endclocking: master_cb
 
   clocking slave_cb @ (posedge clk);
      default input #1step output #1ns;
      input  flavor, color, sugar_free, sour;
      output taste;
   endclocking: slave_cb
 
   modport master_mp(input clk, taste, output flavor, color, sugar_free, sour);
   modport slave_mp(input clk, flavor, color, sugar_free, sour, output taste);
   modport master_sync_mp(clocking master_cb);
   modport slave_sync_mp(clocking slave_cb);
endinterface: jelly_bean_if

各个信号的时序由时钟块定义。 master_cb从总线master的角度定义时序,而slave_cb从总线slave的角度定义时序。

该接口还有modport列表,它定义了接口内信号的方向。我们定义了四个modport列表:


DUT使用异步modport列表(master_mp和slave_mp),而testbench使用同步modport列表(master_sync_mp和slave_sync_mp)。

更新(2014年4月2日):我们注意到有些仿真器不支持#1步骤(第9和15行)。如果是这种情况,您可以将其更改为#1ns。

DUT

下面的代码显示了jelly_bean_taster的一个简单结构。第1行指定了我们刚刚定义的jelly_bean_if,以及slave_mp为接口信号选择适当的方向信息。品尝师只会对酸味巧克力口味产生负面影响(即有酸味的巧克力)!

module jelly_bean_taster( jelly_bean_if.slave_mp jb_slave_if );
   import jelly_bean_pkg::*;
   always @ ( posedge jb_slave_if.clk ) begin
      if ( jb_slave_if.flavor == jelly_bean_transaction::CHOCOLATE &&
           jb_slave_if.sour ) begin
         jb_slave_if.taste <= jelly_bean_transaction::YUCKY;
      end else begin
         jb_slave_if.taste <= jelly_bean_transaction::YUMMY;
      end
   end
endmodule: jelly_bean_taster

或者,您可以在模块实例的端口连接中指定modport列表。

module jelly_bean_taster( jelly_bean_if jb_slave_if ); // no modport specified
  // ...
endmodule
 
module top;
  reg               clk;
  jelly_bean_if     jb_slave_if( clk );
  jelly_bean_taster jb_taster( jb_slave_if.slave_mp ); // modport specified
  // ...
endmodule

您可以在模块声明和模块实例中指定modport列表,但如果您这样做,它们必须相同。如果完全没有指定modport列表,则接口中的信号被假定为无法访问。

Sequencer

 jelly-bean sequence由sequencer处理。 uvm_sequencer按原样使用,因为 jelly-bean sequencer不涉及任何类型的扩展功能。

typedef uvm_sequencer#(jelly_bean_transaction) jelly_bean_sequencer;

Driver

driver通过22行中的seq_item_port接收jelly_bean_transaction,然后驱动interface上的信号。driver使用driver和DUT之间的interface来驱动信号。该interface存储在uvm_resource_db(第12行)中。

更新(2014年4月2日):在本教程中,我们使用uvm_resource_db来检索jelly_bean_if(第12和13行)。 UVM建议使用uvm_config_db而不是uvm_resource_db,因为前者更健壮。您可以用下列内容替换第12行和第13行:

assert( uvm_config_db#( virtual jelly_bean_if )::
        get( .cntxt( this ), .inst_name( "" ), .field_name( "jelly_bean_if" ), .value( jb_vi ) ) );
class jelly_bean_driver extends uvm_driver#(jelly_bean_transaction);
   `uvm_component_utils(jelly_bean_driver)
 
   virtual jelly_bean_if jb_vi;
 
   function new(string name, uvm_component parent);
      super.new(name, parent);
   endfunction: new
 
   function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      void'(uvm_resource_db#(virtual jelly_bean_if)::read_by_name
           (.scope("ifs"), .name("jelly_bean_if"), .val(jb_vi)));
   endfunction: build_phase
 
   task run_phase(uvm_phase phase);
      jelly_bean_transaction jb_tx;
 
      forever begin
         @jb_vi.master_cb;
         jb_vi.master_cb.flavor <= jelly_bean_transaction::NO_FLAVOR;
         seq_item_port.get_next_item(jb_tx);
         @jb_vi.master_cb;
         jb_vi.master_cb.flavor     <= jb_tx.flavor;
         jb_vi.master_cb.color      <= jb_tx.color;
         jb_vi.master_cb.sugar_free <= jb_tx.sugar_free;
         jb_vi.master_cb.sour       <= jb_tx.sour;
         seq_item_port.item_done();
      end
   endtask: run_phase
endclass: jelly_bean_driver

第20和23是所谓的时钟块事件。它们相当于@(posedge jb_vi.clk)

Monitor

monitor中的数据流向与driver中相反,但与驱动程序类似。 DUT的interface(jelly_bean_if)位于uvm_resource_db(第14行)。monitor密切监视jelly_bean_if,并获取信号的值。我们的monitor监视一个非NO_FLAVOR果冻豆(第23行)并创建一个jelly_bean_transaction(第24行)。创建的transaction通过analysis port发送给31行的用户。

更新(2014年4月2日):我们使用uvm_resource_db来检索jelly_bean_if(第14行和第15行)。有关如何使用uvm_config_db而不是uvm_resource_db,请参阅上一节。

class jelly_bean_monitor extends uvm_monitor;
   `uvm_component_utils(jelly_bean_monitor)
 
   uvm_analysis_port#(jelly_bean_transaction) jb_ap;
 
   virtual jelly_bean_if jb_vi;
 
   function new(string name, uvm_component parent);
      super.new(name, parent);
   endfunction: new
 
   function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      void'(uvm_resource_db#(virtual jelly_bean_if)::read_by_name
           (.scope("ifs"), .name("jelly_bean_if"), .val(jb_vi)));
      jb_ap = new(.name("jb_ap"), .parent(this));
   endfunction: build_phase
 
   task run_phase(uvm_phase phase);
      forever begin
         jelly_bean_transaction jb_tx;
         @jb_vi.slave_cb;
         if (jb_vi.slave_cb.flavor != jelly_bean_transaction::NO_FLAVOR) begin
            jb_tx = jelly_bean_transaction::type_id::create(.name("jb_tx"), .contxt(get_full_name()));
            jb_tx.flavor     = jelly_bean_transaction::flavor_e'(jb_vi.slave_cb.flavor);
            jb_tx.color      = jelly_bean_transaction::color_e'(jb_vi.slave_cb.color);
            jb_tx.sugar_free = jb_vi.slave_cb.sugar_free;
            jb_tx.sour       = jb_vi.slave_cb.sour;
            @jb_vi.master_cb;
            jb_tx.taste = jelly_bean_transaction::taste_e'(jb_vi.master_cb.taste);
            jb_ap.write(jb_tx);
         end
      end
   endtask: run_phase
endclass: jelly_bean_monitor

Agent

sequencer,driver,monitor - 全部例化在在agent中。这些组件在build_phase中创建,创建的组件在connect_phase中连接。由于subscriber没有例化在agent,但是monitor要向subscriber发送trans,所以创建analysis port以与subscriber进行通信。agent和monitor中的analysis port在26行相互连接。然后,agent中的analysis port又和subscriber中的analysis imp在env中连接。

class jelly_bean_agent extends uvm_agent;
   `uvm_component_utils(jelly_bean_agent)
 
   uvm_analysis_port#(jelly_bean_transaction) jb_ap;
 
   jelly_bean_sequencer jb_seqr;
   jelly_bean_driver    jb_drvr;
   jelly_bean_monitor   jb_mon;
 
   function new(string name, uvm_component parent);
      super.new(name, parent);
   endfunction: new
 
   function void build_phase(uvm_phase phase);
      super.build_phase(phase);
 
      jb_ap = new(.name("jb_ap"), .parent(this));
      jb_seqr = jelly_bean_sequencer::type_id::create(.name("jb_seqr"), .parent(this));
      jb_drvr = jelly_bean_driver::type_id::create(.name("jb_drvr"), .parent(this));
      jb_mon  = jelly_bean_monitor::type_id::create(.name("jb_mon"), .parent(this));
   endfunction: build_phase
 
   function void connect_phase(uvm_phase phase);
      super.connect_phase(phase);
      jb_drvr.seq_item_port.connect(jb_seqr.seq_item_export);
      jb_mon.jb_ap.connect(jb_ap);
   endfunction: connect_phase
endclass: jelly_bean_agent

虽然这篇文章到这里就结束,但下一篇将继续介绍其他验证组件。






  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值