UVM糖果爱好者教程 - 8.配置

这篇文章将解释UVM配置对象,因为之前的文章并没有太多的介绍。  jelly-bean验证平台使用jelly_bean_agent_config和jelly_bean_env_config两种配置对象。 前者配置jelly_bean_agent,后者配置jelly_bean_env。 下图显示了验证平台和配置相关类的类图。

                                    Verification Platform


                                 Class Diagram of the Configuration Classes

Agent Configuration

jelly_bean_agent_config类配置jelly_bean_agent。这个类有两个开关; active和has_jb_fc_sub(第4和5行)。active控制代理是处于主动模式还是处于被动模式。在主动模式下,将创建一个sequencer(jelly_bean_sequencer)和一个driver(jelly_bean_driver)。在被动模式下,不会创建任何sequencer或driver。类似地,has_jb_fc_sub开关控制代理是否实例化功能覆盖采集器(jelly_bean_fc_subscriber)。根据开关的值,代理将被组织为下图所示的四种可能配置之一。 jelly_bean_agent_config类也具有jelly_bean_if(第7行)的句柄。

class jelly_bean_agent_config extends uvm_object;
   `uvm_object_utils( jelly_bean_agent_config )
 
   uvm_active_passive_enum active = UVM_ACTIVE;
   bit has_jb_fc_sub = 1; // switch to instantiate a functional coverage subscriber
 
   virtual jelly_bean_if jb_if;
 
   function new( string name = "" );
      super.new( name );
   endfunction: new
endclass: jelly_bean_agent_config

                    Four Possible Agent Configurations

Environment Configuration

类似于jelly_bean_agent_config,jelly_bean_env_config配置jelly_bean_env。该类有四个开关来定义环境的结构(第4至7行)。它还有两个处理jelly_bean_agent_config;每个代理人一个句柄(第9和10行)。

class jelly_bean_env_config extends uvm_object;
   `uvm_object_utils( jelly_bean_env_config )
 
   bit has_jb_agent1 = 1; // switch to instantiate an agent #1
   bit has_jb_agent2 = 1; // switch to instantiate an agent #2
   bit has_jb_sb1    = 1; // switch to instantiate a scoreboard #1
   bit has_jb_sb2    = 1; // switch to instantiate a scoreboard #2
 
   jelly_bean_agent_config jb_agent_cfg1;
   jelly_bean_agent_config jb_agent_cfg2;
 
   function new( string name = "" );
      super.new( name );
   endfunction: new
endclass: jelly_bean_env_config

Top Module

顶级Verilog模块实例化两个jelly_bean_ifs(第6行和第7行)并将它们存储在配置数据库中(第17行至第20行)。 cntxt和inst_name提供正在存储的虚拟接口的范围信息。由于顶层模块不是uvm_component,所以null被用作cntxt。 uvm_test_top是由uvm_root类的run_test()任务实例化的顶层uvm_component的名称。

module top;
   import uvm_pkg::*;
 
   reg clk;
 
   jelly_bean_if        jb_if1( clk );
   jelly_bean_if        jb_if2( clk );
   jelly_bean_subsystem dut( jb_if1, jb_if2 );
 
   initial begin
      clk = 0;
      #5ns ;
      forever #5ns clk = ! clk;
   end
 
   initial begin
      uvm_config_db#( virtual jelly_bean_if )::set
         ( .cntxt( null ), .inst_name( "uvm_test_top" ), .field_name( "jb_if1" ), .value( jb_if1 ) );
      uvm_config_db#( virtual jelly_bean_if )::set
         ( .cntxt( null ), .inst_name( "uvm_test_top" ), .field_name( "jb_if2" ), .value( jb_if2 ) );
      run_test();
   end
endmodule: top

Base Test

基本测试按如下方式构建配置对象:

  1. 基础测试为验证环境创建一个配置对象(jb_env_cfg),并为jelly-bean代理(第16至18行)创建两个配置对象(jb_agent_cfg1和jb_agent_cfg2)。

  2. 我们在顶层模块中创建的jelly_bean_ifs从配置数据库中检索。然后将每个检索到的接口分配给相应的代理配置(第20至27行)。

  3. 代理配置分配给jb_env_cfg(第29和30行)。

  4. jb_env_cfg存储在配置数据库中,以便验证环境稍后可以从数据库中获取其配置(第32行和第33行)。

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_cfg1;
   jelly_bean_agent_config jb_agent_cfg2;
 
   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_env_cfg    = jelly_bean_env_config  ::type_id::create( "jb_env_cfg"    );
      jb_agent_cfg1 = jelly_bean_agent_config::type_id::create( "jb_agent_cfg1" );
      jb_agent_cfg2 = jelly_bean_agent_config::type_id::create( "jb_agent_cfg2" );
 
      if ( ! uvm_config_db#( virtual jelly_bean_if )::get
         ( .cntxt( this ), .inst_name( "" ), .field_name( "jb_if1" ), .value( jb_agent_cfg1.jb_if ) ) ) begin
            `uvm_error( "jelly_bean_test", "jb_if1 not found" )
      end
      if ( ! uvm_config_db#( virtual jelly_bean_if )::get
         ( .cntxt( this ), .inst_name( "" ), .field_name( "jb_if2" ), .value( jb_agent_cfg2.jb_if ) ) ) begin
            `uvm_error( "jelly_bean_test", "jb_if2 not found" )
      end
 
      jb_env_cfg.jb_agent_cfg1 = jb_agent_cfg1;
      jb_env_cfg.jb_agent_cfg2 = jb_agent_cfg2;
 
      uvm_config_db#( jelly_bean_env_config )::set
         ( .cntxt( this ), .inst_name( "*" ), .field_name( "jb_env_cfg" ), .value( jb_env_cfg ) );
 
      jb_env = jelly_bean_env::type_id::create( .name( "jb_env" ), .parent( this ) );
   endfunction: build_phase
endclass: jelly_bean_base_test

Environment

验证环境使用其配置对象构建自身,如下所示:

  1. 环境类从配置数据库(第17到20行)获取其配置对象(jb_env_cfg)。

  2. 如果配置对象指示要创建的代理#1,则环境会创建它并将其配置(jb_agent_cfg1)存储到配置数据库(第23至25行)。

  3. 如果配置对象指示创建计分板,则会创建一个计分板(第27至29行)。

  4. 如果两个对象都被实例化(代码行47和48),代理的分析端口和计分板的export都是连接的。

class jelly_bean_env extends uvm_env;
   `uvm_component_utils( jelly_bean_env )
 
   jelly_bean_env_config jb_env_cfg;
   jelly_bean_agent      jb_agent1;
   jelly_bean_agent      jb_agent2;
   jelly_bean_scoreboard jb_sb1;
   jelly_bean_scoreboard jb_sb2;
 
   function new( string name, uvm_component parent );
      super.new( name, parent );
   endfunction: new
 
   function void build_phase( uvm_phase phase );
      super.build_phase( phase );
 
      if ( ! uvm_config_db#( jelly_bean_env_config )::get
            ( .cntxt( this ), .inst_name( "" ), .field_name( "jb_env_cfg" ), .value( jb_env_cfg ) ) ) begin
         `uvm_error( "jelly_bean_env", "jb_env_cfg not found" )
      end
 
      if ( jb_env_cfg.has_jb_agent1 ) begin
         uvm_config_db#( jelly_bean_agent_config )::set
            ( .cntxt( this ), .inst_name( "jb_agent1*" ), .field_name( "jb_agent_cfg" ), .value( jb_env_cfg.jb_agent_cfg1 ) );
         jb_agent1 = jelly_bean_agent::type_id::create( .name( "jb_agent1" ), .parent( this ) );
 
         if ( jb_env_cfg.has_jb_sb1 ) begin
            jb_sb1 = jelly_bean_scoreboard::type_id::create( .name( "jb_sb1" ), .parent( this ) );
         end
      end
 
      if ( jb_env_cfg.has_jb_agent2 ) begin
         uvm_config_db#( jelly_bean_agent_config )::set
            ( .cntxt( this ), .inst_name( "jb_agent2*" ), .field_name( "jb_agent_cfg" ), .value( jb_env_cfg.jb_agent_cfg2 ) );
         jb_agent2 = jelly_bean_agent::type_id::create( .name( "jb_agent2" ), .parent( this ) );
 
         if ( jb_env_cfg.has_jb_sb2 ) begin
            jb_sb2 = jelly_bean_scoreboard::type_id::create( .name( "jb_sb2" ), .parent( this ) );
         end
      end
 
    endfunction: build_phase
 
   function void connect_phase( uvm_phase phase );
      super.connect_phase( phase );
 
      if ( jb_env_cfg.has_jb_agent1 && jb_env_cfg.has_jb_sb1 ) jb_agent1.jb_ap.connect( jb_sb1.jb_analysis_export );
      if ( jb_env_cfg.has_jb_agent2 && jb_env_cfg.has_jb_sb2 ) jb_agent2.jb_ap.connect( jb_sb2.jb_analysis_export );
   endfunction: connect_phase
 
endclass: jelly_bean_env

Agent

代理使用其配置对象构建自己,如下所示:

  1. 代理类从配置数据库(第19行到第22行)获取其配置对象(jb_agent_cfg)。

  2. 如果配置对象指示代理处于活动状态,则代理会创建一个sequencer和一个driver(第24至27行)。

  3. 如果配置对象指示这样做,则创建功能覆盖用户(第29到31行)。

  4. 如果代理处于活动状态,则连接driver的端口和sequencer的export。driver的虚拟接口也已连接(第42至45行)。

  5. 如果功能覆盖用户存在(第47至49行),则代理的分析端口和功能覆盖用户的分析export被连接。

class jelly_bean_agent extends uvm_agent;
   `uvm_component_utils( jelly_bean_agent )
 
   jelly_bean_agent_config  jb_agent_cfg;
   jelly_bean_sequencer     jb_seqr;
   jelly_bean_driver        jb_drvr;
   jelly_bean_monitor       jb_mon;
   jelly_bean_fc_subscriber jb_fc_sub;
 
   uvm_analysis_port#( jelly_bean_transaction ) jb_ap;
 
   function new( string name, uvm_component parent );
      super.new( name, parent );
   endfunction: new
 
   function void build_phase( uvm_phase phase );
      super.build_phase( phase );
 
      if ( ! uvm_config_db#( jelly_bean_agent_config )::get
            ( .cntxt( this ), .inst_name( "" ), .field_name( "jb_agent_cfg" ), .value( jb_agent_cfg ) ) ) begin
         `uvm_error( "jelly_bean_agent", "jb_agent_cfg not found" )
      end
 
      if ( jb_agent_cfg.active == UVM_ACTIVE ) begin
         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 ) );
      end
 
      if ( jb_agent_cfg.has_jb_fc_sub ) begin
        jb_fc_sub = jelly_bean_fc_subscriber::type_id::create( .name( "jb_fc_sub" ), .parent( this ) );
      end
 
      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_mon.jb_if = jb_agent_cfg.jb_if;
      jb_ap = jb_mon.jb_ap;
 
      if ( jb_agent_cfg.active == UVM_ACTIVE ) begin
         jb_drvr.seq_item_port.connect( jb_seqr.seq_item_export );
         jb_drvr.jb_if = jb_agent_cfg.jb_if;
      end
 
      if ( jb_agent_cfg.has_jb_fc_sub ) begin
         jb_ap.connect( jb_fc_sub.analysis_export );
      end
   endfunction: connect_phase
endclass: jelly_bean_agent

Sequence Diagram

以下序列图总结了上述配置过程。


                                                                Sequence Diagram of the Build Phases

我希望本教程能帮助你理解UVM的配置过程。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值