When to use set_config/get_config

I’m just starting to put together an OVM based test bench and have come upon this question of when it’s appropriate to use set_config/get_config to pass object handles into components. What I’m hearing is that the OVM community is leaning toward always using it rather than have hierarchical references to child components.

I think I’m in a minority in thinking that hierarchical references to child objects is okay. If driver, for instance, is implemented in env, I think it’s fair for env to understand something about what’s inside of driver. In which case it might be fair to pass a reg handle to driver in this manner
driver.reg = reg;

Now, in case the author of driver wants to change the name or location of its internal reg, then I should pass the handle to reg something more like this so that driver can store the handle whereever makes sense for the current implementation without effecting my env code.
driver_obj.connect_reg(reg);

Using set_config/get_config, the env coder still needs to know some details about the internals of driver - the string value that driver will use to find the reg handle.

An analogy is that I have a bag of money for you, so I’ll put it out in the woods in a place you said you will look for it - rather than just hand the bag to you as long as you’re right here. There’s a chance I’ll misunderstand the string you said you’d look under - whereas handing it to you I’ll know right away that you got it.

I see three places where set_config/get_config is appropriate

  1. The test case sets the configuration object so that any component out there can get it to see what the test wants done
  2. The test bench top module can’t hand the interface handles to the env directly because env hasn’t been instantiated yet
  3. The value is meant for an object that will be declared some layers down from the parent - the parent shouldn’t know that full hierarchy

I’m sure there are others, but I don’t think it’s always appropriate to use set_config/get_config.

George

Hi George,

I think that a couple of reasons why you would use the config facility, even for direct children, is that

  • It is a good habit to design with the future in mind, and always keep your options open. In other words, the driver might not always be a direct child of the environment. You, or someone else who reuses your environment, might want or need to reorganize things. When that happens, you have to find all the direct references and change them for each and every change to the topology.

  • The configuration settings can be overriden by components “higher” in the hierarchy. So, if your environment uses set_config for a direct child, another component higher up can override it without making any code changes to the environment.

Bottom line, is it MANDATORY to use set/get config? No, absolutely not. Your environment will work just fine by setting child data members directly. The question is, will you end up making it harder to maintain and extend your environment in the future? That’s where using the configuration facility pays off.

Regards,
-Kurt

True enough to all Kurt says but I feel he missed
an important point beyond all his good reasons.

I often use config when I want to share an instance
in more than one place. A good example of this is
DUT configuration. Several types of components may
need access to this, from generation to checking to
coverage. One set, multiple gets. None of the components
need to know hierarchy, not even the top level.

This allows a distributed team approach to TB development
and easier integration of the parts. Hidden in the arguments
you may notice my bias to maintain an object’s autonomy.
That is, each component seemingly aware of only its own data.

Finally, this is not just an academic discussion, it has to be written
and get_config comes to you almost for free when you use ovm_component_utils and the ovm_field_XX macros.
They build the entire get infrastructure and all you have to do is
set it - or not - at a higher level.

JPK

I agree with Kurt. Nothing is mandatory – it’s all just a pile of code. The point, however, is to design your components and infrastructure with reuse in mind.

When the parent knows the structure of its children and operates them through means other than well defined interfaces, then there is a depdendency between the parent and child. Maybe now that’s not a problem but sometime in the future you may wish to have a different child which was not built by the same person who built the first set of children. If he doesn’t know about the particular conventions you used the new child may not work correctly.

Instead of a bag of money in the woods, consider sending a letter. Let’s say the mailman comes by everyday at noon. I can take advantage of this fact when I want to mail a letter. On my way out for lunch I just hand him the letter. This works fine for quite a long time. Then the Postmaster rearranges the routes and I get a new mailman the comes at a different time. Next time I want to mail a letter I go out a noon as usual, but no mailman appears. The letter doesn’t get mailed. Further, it turns out that the mailman now sometimes comes at 10:00am and sometimes at 2:30pm and I have no way to predict which on any particular day. So to mail a letter I have to go out at 10:00 and, if he’s not there go out again at 2:30. I have to change how I mail a letter just because the mailman changed.

The alternative is the mailbox. This forms a well-defined interface between me, the letter sender, and the mailman. I can put the letter in the mailbox and I know that the next time the mailman comes by, whenever that is, he will take it. Should the mailman change again, no worries, the interface is the same and I don’t need to change anything.

Get/set_config_* form a well defined interface to setting and retrieving configuration data. Information will still be properly exchanged even if the setter or getter change since the interface remains constant. While it can be slightly more verbose than just assigning values directly, the arms-length relationship through a well-defined interface maintains the reusability of the components.

By the way, the string issue you mentioned is a real concern. A spelling mistake can cause the data to not be transferred properly. It’s possible for a testbench to silently do the wrong thing. One way around this is to use string constants instead of typing the string. E.g.

package config_pkg;
 
  const string config_size = "size";
  const string config_length = "length";
  ...
 
endpackage

Then, you can use the const variables in the package instead of directly typing the names.

import config_pkg::*;
 
set_config_int(config_size, ...);
...
get_config_int(config_size, ...);

This is a flaw in the interface and doesn’t justify NOT using any interface. We are looking into ways to remove this flaw with some auditing functionality in the config facility.

– Mark

I think that most of the important things have been said on this topic, but I would like to hightlight a few points that I think are important:

  1. get_config has a performance impact and thus should not be used for high frequency operations. It is intended to get “configuration” type information, not continually updated information.
  2. get_config has a structured precedence ordering based on hierarchy and order within hierarchy. This allows a config from an env to be overridden from above in a structured way (at the time get_config is called). Using an assignment pattern the last assigner wins without regard to order.
  3. get_config is controlled by the target. Thus, the target can choose appropriate times in which to access configuration information. An assignment pattern would happen immediately. Of course, a user could create a method for this, but then they have to invent there own setting mechanism. This is what Mark is talking about.
  4. get_config doesn’t require an actual variable (local storage in the class). There is often a variable assoicated with some configuration property, but it isn’t required. This gives the implementor a lot of flexibility in how they design their IP.
  5. set_config allows for wildcarding. This makes it really useful for generic types of fields (like the type of info to print, etc) where you want to broadcast a setting and you don’t necessary want to set every individual thing.
  6. set_config can be done before the hierarchy has been created. In fact, it isn’t necessary for the hierarchy to exist. This is convenient if the hierarchy is configurable and it is not possible for the object that needs to set a configuration property to know, a priori, what the final hierarchy configuration will be.

Where get_config is not appropriate is inside of some tight loop that will get called often at run time. In such a case you will incur a significant performance penalty even when configuration information isn’t changing. It is okay to use get_config for runtime stuff, you just want to avoid doing it in tight loops. Of course, there are things that can be done in ovm to minimize the performance impacts here (e.g. providing caching information), but for now I would avoid having get_configs in tight loops.

I agree that direct assignment from above is, in general, okay. However, you need to be careful about how you do it, and the lower level ip writer needs to decide if it is okay, or not, for higher level entities to make changes at any specific time. Direct assignment is efficient, and if it is sufficient for a specific situation, then by all means it should be done. But, as others have noted above, there are a variety of good reasons to use a well defined interface for setting configuration properties, and that is what the get/set_config interface gives you.

john

Thanks for all the feedback – it’s a little overwhelming for me. I’ve been resistant about the config space because it seems like a hidden interface sort of like setenv variables or global `defines. Your descriptions here lead me to think it could be more formal than I had thought, though its formal definition is not clear to me. I’m not quite understanding yet the search hierarchy and the significance of each of the two strings passed to set_config_* where only one is passed to get_config_*. It looks like apply_config_settings could be useful, but it’s not clear in the reference what it does exactly.

Is there a user guide that covers this? The OVM Class Reference describes each function, but I’m missing the big picture. I’ll keep researching - but, as JPK says, this is not academic - I need to stop researching and start coding soon.

George

Hi George,

Both the reference manual and user guide have information on this and there are some examples in the installation, but it probably needs to be revamped to provide the information in a clearer way.Here are the basics, hopefully this will help:

  • set_config takes two arguments, a component instance and a field.

  • The component instance is a hierarchical reference rooted from the instance that is doing the set. For instance, if you are in top.u1 and you provide “u2.u3.u4” as the instance, then the full path that the setting is applied to is top.u1.u2.u3.u4.

  • The component instance can have wildcard. For instance, you could have “*.u3.u4” which will match any instances that have u3.u4 as a leaf.

  • The field is completely arbitrary. This is the item that Mark is talking about using const strings for identifiers. It is up to the IP writer to decide a set of fields which will use the get_config mechanism to be set.

  • The field does not need to be a real object. There just needs to be a match between the field name that is retrieved using get_config() and the one that is set using set_config().

  • get_config() only specifies the field. The instance path is the component that calls get_config().

  • set_config is a constant time (O(1)) operation that is just putting information into a table. Nothing actually happens when set_config is called other than the table being filled in. Your analogy to setenv is similar. The difference is that set_config is not global, it is local to a specific component instance. This may change if we add set_config checking, but no matter what, set_config will be a fast operation.

  • get_config is where stuff happens. It is an O(n,m) operation where n is the depth of the component instance from the root and m is the total number of sets that were done in that path. For instance, if you do a get_config() from u1.u2.u3.u4, n=4 and m is the sum of the settings from root, u1, u2 and u3.

  • When get_config is called, a list of the settings that apply to the target component is created. A setting applies to the target component if the instance path in the set call matches the full name of the target component, and the field from the set matches the target field name. The list is built top down (root first) and back to front. Thus, the last set at the root is first in the list and the first set in the immediate parent is the last in the list.

  • apply_config_settings() automates the calling of get_config() during the build phase for all registered (using the automation macros) fields. This is really hidden magic, and I am not a big fan, but it does make things “easy”.

  • If an automation field is set as OVM_READONLY then it does not participate in the automated configuration.

I hope this helps clarify how things work. When to use this utility depends a lot on what you want to do. One of the reasons of having this type of utility is so that configuration information doesn’t need to be passed through a constructor. The problem with passing information through a constructor is that, as you build up the hierarchy, you containing ctors become unwieldy; you end up needing configuration structures to pass around and that creates its own set of reusability issues.

As you noted, the main flaw in the configuration mechanism is the use of strings. Because they are arbitrary, it can be really hard to tell if you have made a mistake. As Mark said, we are looking at ways we can provide feedback to help alleviate this, and there are strategies to minimize the issue.The nice thing about strings it that they are really flexible. For instance, you can write a text file that gets processed by your environment to do configuration in an interpreted manner. Since configuration is not a high frequency operation, having the flexibility of an interpreter for setting up configuration is really nice.

Take care.

john