How to make VIP robust so that they can be used inside multiple sub-env's with different settings?

Hello !

Wanted to make the VIP re-usable, so that can be instanced within multiple env’s inside a top level env and configure them unique-ly within each sub-env.

a. Have a VIP-package where all the files are included. And have a parameter defined which defines the no. of agents to be created.

   package vip_pkg;
      `ifndef MY_PAR
      `define MY_PAR 2
      `endif

       parameter  no_of_agt = `MY_PAR;
   endpackage: vip_pkg

b. I wanted to pass / somehow use the same parameter inside the interface file used for this VIP.

c. Expectation is like, within a sub_env_package the user can import the above vip and configure as required apart from the default MY_PAR of 2.

  package sub_env_pkg;
    `define MY_PAR 5 // Configuring the VIP as per the requirement. Overriding the default value of 2. So when they import the package below, no_of_agt is taken as 5 instead of 2. 
     import vip_pkg::*;
   endpackage: sub_env_pkg

c. If different users import the package within their sub-env’s, will the `define become global ? or will it be local ? So that each user can import the vip at their sub-env ?

Or is there a better way where the VIP can be configured ? So that multiple user can import the package into their sub-envs and re-configure the parameter [which configures/defines the No_of_agents to be created] according to their requirement, so that it doesn’t affect the other env’s and all of them can act unique [say for eg: subenv1 has 4 agents within VIP, subenv2 has 2 agents within VIP etc]. Any suggestions would be really helpful to incorporate a generic methodology and best practice to be followed ?

In reply to desperadorocks:

Update:

a. What i tried is, I created a separate package called defines package as shown below and imported the package inside the vip_env_pkg and also the corresponding interface file. So that the same package is used to the tb and interface. And user can override the value from the compile time.

package defines_pkg;

`ifndef NUM_AGT
`define NUM_AGT  1
`endif

 parameter NO_AGT = `NO_AGT;

endpackage: defines_pkg

b. But how to modify it in such a way so that the same vip pkg, imported within multiple envs inside a top level env can have unique / different configuration as per the user requirement ?

Can I use some macros ? so that user can define the macro from command i.e. include multiple macros for each env and that expands to unique parameter assignment values ? Please share your inputs.

In reply to desperadorocks:

You don’t want to make the number of agents to create a parameter. You want to make it a member of the environment’s config class.

When the test creates the environment’s config class, it will specify the required number of agents. The environment will get it’s config class and create the specified number of agents.

In reply to cgales:

Hello Cgales,

Thanks for your inputs.

a. So you wanted me to do like, define the agent instance like dynamic array

   class hello_env extends uvm_env;
      // Previous Instantiation : array
      // hello_agents  hello_agts[NO_AGT];

      // Suggested Way From cgales 
      hello_agents  hello_agts[]; 

      function build_phase();
         if (!uvm_config_db#(hello_env_config)::get(this, "*", "hello_env_config", hello_env_cfg))

        hello_agts = new[hello_env_cfg.no_of_agts];
      endfunction: build_phase
   endclass: hello_env

b. But wanted to make my interface as well like arrays, so that the required owners can use the hello_agent_id based approach to drive signals from their driver or monitor them using the same instead of passing N-interface instance as shown below.


     // Sample Interface Code: Which is the better way to pass the NO_AGT info 
     // to the interface file so that is also configurable based on NO_AGT like how you 
     // configure the env settings via configs ?
     interface hello_if ;
      logic [NO_AGT-1:0] tb_sig;
     endinterface: hello_if
// Sample code for driver : Wanted to use agent_id based approach to drive. 
     hello_vif.tb_sig[hello_agent_id] = 1'b1;
     #10;
     hello_vif.tb_sig[hello_agent_id] = 1'b0;
     #10;

So summarize, controlling the number of agents creating withint the env via config file is fine, so that each user when they import the package, they can configure the required config file to form their required number of agents, but how to pass that info the interface as well ?

Please clarify the same and provide some best practice methods to be used !

In reply to desperadorocks:

You don’t want to do that. You want each agent to deal with one interface which correlates to one instance of the agent. In other words, you don’t want one agent to try and handle multiple signal interfaces.

You will need to create individual interface instances for each agent.

In reply to cgales:

Hello Cgales,

Thanks a lot for the clarification. THink this way we don’t have to worry about passing parameters or `defines to configure the n-agents or interfaces or etc. or worry about the compilation scope. Should take care of everything at the top level [i.e. required no of interface connected to the dut and pass them via config db as virtual] and at the top/base test level, get those individual interface via config and then assign them to the corresponding interface to the leaf level configs via the top level env configs and get it going.

So this would be a better and robust approach rather than passing `defines, parameters etc? right Cgales ?