Static Method

UVM Cookbook is a great tech reference; I appreciate your time and expertise creating it.
I am reading spi_env_config.svh (TestbenchBuild/uvm_tb_build_ss_tb/tb_build/sub_system_tbs/pss_tb/env/pss_env_config.svh), but I could not understand how this line works:

extern static function pss_env_config get_config( uvm_component c);

  1. A static method cannot access automatic properties; pss_env_config is not static. How can this work?
  2. In this method, macro `uvm_fatal is used. This is not “enabled” yet; how can this work?

Thanks.

The only thing special about a static method is that is has no this handle. You cannot reference members of the class the method is defined. t is an automatic variable inside the scope of the get_config() method, and a static method may access anything within its scope.

`uvm_fatal will call the global uvm_report_fatal() function defined in the uvm_pkg. It will not call this.uvm_report_fatal().

In reply to dave_59:

Many thanks for your speedy response; you’re great always.

  1. The pss_env_config is the returned type; when memory is allocated for the static method pss_env_config::get_config, this type is not created yet. Would it not result in “undefined type” during compilation?

  2. As written in line 186 of the uvm_globals.svh, the uvm_globals::uvm_report_fatal is not a static method; an access to this automatic method in a static method will result a syntax error. In the old days, we used macro uvm_fatal_context which uses static uvm_root::get to get around this issue. Has there been a new revision of the UVM, and this issue has been taken care of and there is no need for uvm_*_context?

In reply to TV:

  1. This is called a self-referential type. Remember that when you declare a class variable, you are only declaring the space to hold a handle to a class object, not the class object itself. (Take my short class on classes). The compiler only needs to know that pss_env_config is going to be a type, it does not need a complete definition. As another example, the class uvm_component has many self-referential types as well:
class uvm_component extends uvm_report_object;
...
extern function new (string name, uvm_component parent);
uvm_component m_parent;
protected     uvm_component m_children[string];
protected     uvm_component m_children_by_handle[uvm_component];
...
endclass
  1. The terminology of OOP is heavily overloaded. There is a difference between the static qualifier of a class method, and the static storage lifetime qualifier of a function. The storage lifetime (static or automatic) of a function is legacy from Verilog and does not apply to class methods which only have automatic lifetimes. See this link for more info. A static method of a class can refer to anything that does not require a ‘this’ handle.

In reply to dave_59:

Great responses! I know that I’m gonna learn much from you any time I’d ask; really appreciate this; I agree with most of them.

  1. Indeed the compile needs to know if a type exists; I must agree with your response on this principle. This is precisely why we sometimes do typedef class uvm_component; etc.
    The point is a compile may not know what pss_env_config is until it is defined; therefore, the code as written may not work. More likely or not, it will result in a syntax error due to “undefined” type. For your example, the reason that uvm_component works is that it is typedef’ed in its parent class uvm_report_object line 26.

  2. Who knows and remembers all the terminologies of OOP all the time? Thanks a bunch to point it out :-) I completely agree with you about their loaded words!
    The key word “static” is not a legacy term; it is defined in all IEEE 1800’s including the IEEE 1800-2012 section 8.10 page 141. It is stated that “A static method has no access to non-static members (class properties or methods)”. Accessing a non-static method as shown in pss_env_config::get_config will be a syntax error.
    The reason that uvm_fatal_context works and uvm_fatal does not is that uvm_fatal_context uses a static method but uvm_fatal does not.

The point of my inquiry is that the code as written will have at least a syntax error unless there is some clever trick hidden somewhere which I don’t know and would like to learn.
In my humble opinion, the code would be fine if it would has been written as:
1.
typedef class pss_env_config;
include “pss_env_config.svh” These can be written in the package in which the pss_env_config.svh is include’d.

  1. uvm_fatal_context should be used instead of uvm_fatal.

Thanks again; it is always a pleasure reading your posts; I am a big fan of yours.
Best regards

In reply to TV:

  1. A typedef is not required in this case because pss_env_config is known to be a type when it appears in the variable declaration t. The class pss_env_config in the line above takes care of that. The only time a typedef is absolutely required is when the compiler encounters a never before seen identifier. That happens when you have a pair of cyclic definitions: class A needs a handle to class B, and class B needs a handle to class A. You can only define one class first, the other will need a typedef. The other place you will see typedefs used is then the scripts used to compile code are lax in their compilation order. You will see a lot of that in the UVM.
    If you are getting a syntax error from the compilation of the pss_env_config.svh file, then show the error and let your vendor know they have a bug.
  2. The key word in section 8.10 is members. “A static method has no access to non-static members (class properties or methods)” It does have access to everything else visible within its scope. The functions uvm_report_enable() and uvm_report_fatal() are both defined in the package uvm_pkg, they are not member class methods. So they are visible and accessible to the static method pss_env_config::get_config. Had the class pss_env_config been extended from uvm_component (which is extended from uvm_report_object), then there would be a legitimate syntax error. That is because uvm_report_object does have class member methods named uvm_report_enable and uvm_report_fatal. Those non-static class methods names would be found first, hiding the functions defined at the top-level of the package.

In reply to dave_59:

Hi Rich,

I got a follow-up question to this, I have a static function inside class extended from uvm_sequence(so parent is uvm_object not uvm_component).

Inside the static function if i call 'uvm_error i am getting a compile error

[b]*[b]Illegal to access non-static method ‘uvm_report_enabled’ from a static method.
[/b][/b]***

I am not able to understand why, please enlighten me.

In reply to CRVAddict:

This is because uvm_sequence_item has its own reporting interface. It delegates to the sequencer the sequence is running on, or the uvm_top if the sequencer is null (virtual sequence)

You need to use `uvm_info_context to provide some context for reporting. Without knowing why you need a static method, I can only suggest using uvm_root::get() as the context

In reply to dave_59:

I am trying to access some methods inside the seq without instantiating it