Uvm_config_db set in generate loop

Hi,

I would like to ask a couple of question related to generate construct and its utilization with uvm_config_db set in the module hierarchy. In my test bench top-level module there are the following contents


module top;
  typedef enum {
    AMBA_BUS1,
    AMBA_BUS2,
    AMBA_BUS_QUANTITY} amba_bus_t;

  amba_bus_t amba_buses = amba_buses.first();  

  // Actual interface (amba_interface) array instance named “i_amba_interface” 
  amba_interface i_amba_interface[AMBA_BUS_QUANTITY}]();

  for (genvar i = 0; i < AMBA_BUS_QUANTITY; i++) begin   // <-- Do we need to name this block if used for uvm_config_db?
    initial begin
      uvm_config_db#(virtual amba_interface)::set(uvm_root::get(), "uvm_test_top", amba_buses.name(), top.i_amba_interface[i]);
      amba_buses = amba_buses.next();  // <-- Is this illegal to assign variable/field in generate loop in that way?
    end
  end
endmodule : top

The questions are (pointed also with “// <–” comments in code):

  1. If we are doing uvm_config_db set within generate loop, whether it is recommended or not to name the generate loop block? If yes, what is the reason to name the block including just uvm_config_db? I think some of simulators raise warnings if you have unnamed generate blocks

  2. Is it legal to assign variable/field within generate loop as shown in the code? In the code, there is used enum built-in methods name() and next() to set proper field string per interface instance for uvm_config_db entries. In simulator, I can see with uvm_config_db_trace that uvm_config_db is configured with those enum names as expected, but I am still wondering if that kind variable assignment is done correctly. If it is legal to assign variables in that way within generate block, are those variables (amba_buses in this example) implicitly defined as a localparam in each instance of the generate block like genvars are?

Thanks

Vaino

  1. You only need to name a generate block if you plan to reference things (ie. variables or instances) declared inside the generate block from outside the generate block.
  2. It’s not illegal to assign
    amba_buses
    in the generate loop. However, it is not a good programming practice to have multiple processes simultaneously writing and reading to the same global variable. A better approach would be using the argument to next() to specify the position of the enum label.
const amba_bus_t amba_bus_first;  
 
  // Actual interface (amba_interface) array instance named “i_amba_interface” 
  amba_interface i_amba_interface[AMBA_BUS_QUANTITY}]();
 
  for (genvar i = 0; i < AMBA_BUS_QUANTITY; i++) begin 
    initial begin
      automatic amba_bus_t local_label = amba_bus_first.next(i);
      uvm_config_db#(virtual amba_interface)::set(uvm_root::get(), "uvm_test_top", local_label.name(), top.i_amba_interface[i]);
    end
  end

In reply to dave_59:

  1. You only need to name a generate block if you plan to reference things (ie. variables or instances) declared inside the generate block from outside the generate block.
  2. It’s not illegal to assign
    amba_buses
    in the generate loop. However, it is not a good programming practice to have multiple processes simultaneously writing and reading to the same global variable. A better approach would be using the argument to next() to specify the position of the enum label.
const amba_bus_t amba_bus_first;  
// Actual interface (amba_interface) array instance named “i_amba_interface” 
amba_interface i_amba_interface[AMBA_BUS_QUANTITY}]();
for (genvar i = 0; i < AMBA_BUS_QUANTITY; i++) begin 
initial begin
automatic amba_bus_t local_label = amba_bus_first.next(i);
uvm_config_db#(virtual amba_interface)::set(uvm_root::get(), "uvm_test_top", local_label.name(), top.i_amba_interface[i]);
end
end

Thanks for clarifying. Could you still explain with a couple of more words the following things:

  1. By declaring amba_bus_first as a const constant, can it be assigned once somewhere within the module?
  2. Why automatic word is used, to get local copy of amba_bus_first for each generate block? What is the fundamental difference to declare local_label variable with/without automatic in this context? I think with automatic keyword local_label is initialized when execution enters the initial process?

-Vaino

*In reply to Vaino:*Sorry for introducing a few extra concepts without explaining. I am making sure that amba_bus_first gets initialized with its default initial value before any reference to that variable occurs. As a general programming rule, you should never rely on the initial state of a static variable. Although static variables get initialized before any always or initial blocks, there is no guaranteed order of initialization between static variables.

A const variable that is not a class member can only be initialized as part of its declaration. A const variable that is a class member can be initialized as part of its declaration or once as an assignment inside the class constructor.

Yes, the key reason I made local_label, an automatic variable was so that the initialization occurs when executing the initial process. I could also made local_label a static variable (which is the default outside of a class declaration), by added a separate assignment statement that write to local_label when executing the initial process.

In reply to dave_59:

I think I am now ok with your original code proposal, thanks! I definitely see your proposal as a good programming practice.

As you stated, the const variable that is not a class member can only be initialized as part of its declaration, but I am a little annoyed because the same explanation cannot be found from IEEE Std 1800-2012. I can only find the const class member initialization explanation, but nothing about outside class const variable initialization. Could you point me a section within IEEE Std 1800-2012 which explains that? Or does it exist at all? Maybe it is kind of implicit rule.

-Vaino

In reply to Vaino:
Section 6.20.6 Const constants explains it, but it uses the word “set” instead of “assigned” or initialized. Those words have the same meaning in this context.

In reply to dave_59:

Ok, thanks. It seems I missed that previously when checking the standard.

In reply to dave_59:

Hii dave,

what if here i have path is uvm_top_test.env.agent[i].* ??(for diff. agent instance)

then how this will be written??

In reply to d_g:

In reply to dave_59:
Hii dave,
what if here i have path is uvm_top_test.env.agent[i].* ??(for diff. agent instance)
then how this will be written??

In the above scenario we can use $sformatf function which will return the string as the third argument to give the path


  $sformatf("uvm_test_top.env.agent[%0d]",i)