UVM Tutorial for Candy Lovers – 8. Configurations

This post will give an explanation on UVM configuration objects, since the earlier posts did not cover much on them. The jelly-bean verification platform uses two kinds of configuration objects, jelly_bean_agent_config and jelly_bean_env_config. The former configures the jelly_bean_agent and the latter configures the jelly_bean_env. The figures below show the verification platform and the class diagram of the configuration-related classes.

                                                                                           Verification Platform

                                                                            Class Diagram of the Configuration Classes

Agent Configuration

The jelly_bean_agent_config class configures the jelly_bean_agent. The class has two switches; active and has_jb_fc_sub (lines 4 and 5). The active switch controls whether the agent is in active mode or in passive mode. In the active mode, a sequencer (jelly_bean_sequencer) and a driver (jelly_bean_driver) will be created. In the passive mode, no sequencer or driver will be created. Similarly, the has_jb_fc_sub switch controls whether the agent instantiates a functional coverage subscriber (jelly_bean_fc_subscriber) or not. Based on the values of the switches, the agent will be structured as one of the four possible configurations shown in the figure below. The jelly_bean_agent_config class also has a handle to the jelly_bean_if (line 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

Similar to the jelly_bean_agent_config, the jelly_bean_env_config configures the jelly_bean_env. The class has four switches to define the structure of the environment (lines 4 to 7). It also has two handles to the jelly_bean_agent_config; one handle per agent (lines 9 and 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

The top Verilog module instantiates two jelly_bean_ifs (line 6 and 7) and stores them in configuration database (lines 17 to 20). The cntxt and inst_name provide the scope information of the virtual interface being stored. Since the top module is not a uvm_componentnull is used as the cntxt. The uvm_test_top is the name of the top-level uvm_component instantiated by the run_test() task of the uvm_root class.

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

The base test builds configuration objects as follows:

  1. The base test creates one configuration object (jb_env_cfg) for the verification environment, and two configuration objects (jb_agent_cfg1 and jb_agent_cfg2) for the jelly-bean agents (lines 16 to 18).
  2. The jelly_bean_ifs, which we’ve created in the top module, are retrieved from the configuration database. Then each retrieved interface is assigned to the corresponding agent configuration (lines 20 to 27).
  3. The agent configurations are assigned to the jb_env_cfg (lines 29 and 30).
  4. The jb_env_cfg is stored in the configuration database so that the verification environment can get its configuration from the database later (line 32 and 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

The verification environment builds itself using its configuration object as follows:

  1. The environment class gets its configuration object (jb_env_cfg) from the configuration database (lines 17 to 20).
  2. If the configuration object indicates the agent #1 to be created, then the environment creates it and stores its configuration (jb_agent_cfg1) to the configuration database (lines 23 to 25).
  3. A scoreboard is created if the configuration object indicates to do so (lines 27 to 29).
  4. The analysis port of the agent and the export of the scoreboard are connected if the both objects are instantiated (lines 47 and 48).
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

The agent builds itself using its configuration object as follows:

  1. The agent class gets its configuration object (jb_agent_cfg) from the configuration database (lines 19 to 22).
  2. If the configuration object indicates the agent is active, then the agent creates a sequencer and a driver (lines 24 to 27).
  3. A functional coverage subscriber is created if the configuration object indicates to do so (lines 29 to 31).
  4. The port of the driver and the export of the sequencer are connected if the agent is active. The virtual interface of the driver is also connected (lines 42 to 45).
  5. The analysis port of the agent and the analysis export of the functional-coverage subscriber are connected if the functional-coverage subscriber exists (lines 47 to 49).
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

The following sequence diagram summarizes the configuration process described above.

                                                                        Sequence Diagram of the Build Phases

I hope this tutorial helped you to understand the UVM configuration process.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值