Typdef class question

hi,
i got at my test:

typedef class this_test;

class unsupported_transaction_seq extends hda_sequence_base;
this_test tst_ptr;
task body();

    assert ($cast(tst_ptr, hda_env_ptr.get_parent()))
    else ovm_report_error("Test", "Bad casting of tst_ptr");

i got that error message :

Error-[SV-UFCD] Undefined forward class declaration
$unit, “this_test”
The forward typedef of the class does not have a definition in the same
scope.
Please provide a definition to the forward class declaration.

can you please advice how to solve it?
i do not understand the meaning of such error, since the test is similar to examples of typdef class i saw at accelera etc.
thanks
ze’ev

The reason you need to use a typedef is because the compiler needs to know that the identifier tst_ptr refers to a data type (in your case, a class) in order to parse the statement in a single pass through the source code. Its called “forward” because the typedef is ahead of the actual definition. So where is your definition?

Dave Rich
Mentor Grpahics

In reply to dave_59:

In C++, I believe this would work. Are you basically saying that SV doesn’t have a notion of a linker stage in its compilation process?

In reply to mpettigr:

Verilog/SystemVerilog has a global elaboration stage, not a linking stage because of the hierarchical references and parameter overrides in its language.

The linking stage in C++ still requires a fully specified prototype of a type before you can generate code that can be linked.

In reply to dave_59:

Thanks, Dave. I did some more digging on the C++ forward declarations of classes.

I was wrong about an equivalent bit of C++ code (described above) being compilable. It’s illegal to use a forward class declaration in C++ (defined as an “incomplete type”) to declare a class member ( see http://jatinganhotra.com/blog/2012/11/25/forward-class-declaration-in-c-plus-plus/ and especially c++ - When can I use a forward declaration? - Stack Overflow ).


typedef class this_test;

class unsupported_transaction_seq extends hda_sequence_base;
this_test tst_ptr;  // This is illegal in C++ if "this_test" is an incomplete type

From the SV 2012 LRM pg 77 section 6.18 and pg 167 section 8.27, it does not appear that SV behaves like C++ with respect to forward class declarations.

SV 2012 LRM states “The actual data type definition of a forward typedef declaration shall be resolved within the same local scope or generate block.” (pg 77 and 167).

So, for example, it does not appear that you can use an “incomplete type” to declare functions which accept or return incomplete types. The type definition must occur in the same local scope. I think that C++ does allow this construction and so you can defer the type definition until the linker stage of compilation. The advantage in C++ is that you can reduce the number of include dependencies with this capability.

To be more concrete, something like


typedef class bar;

class foo;

extern function bar widget();
endclass : foo

would be illegal in SV unless the class definition were present in the same local scope (you either (1) add an `include of the file containing the class ‘bar’ definition, (2) compile multiple files in the same command-line where 1 of the files contains the class ‘bar’ definition or (3) stick the class definition of ‘bar’ at the end of the file).

I’m trying to understand how to best split class declarations and definitions into separate files (.svh and .sv respectively) to minimize the amount of incremental compilation needed when updates occur. There are some pretty good guidelines on how to do this in C++ but the SV community appears silent on the matter. In the UVM BCL, a class is declared and defined in the same .svh file. Then, they’re all `include’d into a single package (in uvm_pkg.sv).

Is this Mentor’s recommended practice when putting together SV class-based code? That is, declare the class, use extern on class methods (out-of-block declarations) and then later on in the same file include the implementation.

In reply to mpettigr:

In SystemVerilog, there are only two benefits when declaring classes using method prototypes and then out-of-block implementations:

  • Documentation - it’s easier to read a class declaration in a more compact form when the implementations are set aside.
  • Encryption - it would be easier to expose the method prototypes this way.

Because of the way compilation works in SystemVerilog, there is no benefit in splitting the class into two files because you cannot incrementally compile a a portion of a single scope. In fact, you will get worse overall performance because of the extra system calls to open more files.

In reply to dave_59:

Thanks, Dave! Your post is kind of huge. Coming from a C++ perspective and the fact that SystemVerilog supports the `include preprocessor directive, it’s totally counterintuitive to hear that the preferred approach to compose a class is to put the interface and implementation in the same file (for advice on doing the opposite in C++ see the references section of the wikipedia entry on Class Implementation file).

Is there any chance a guideline could be added to the SV/Guidelines section of the UVM Cookbook?

In reply to mpettigr:

Partially answering my own question :-), Mentor does provide (very useful) guidelines on how to arrange classes within packages at Package/Organization | Verification Academy .

Can you explain why splitting the class declaration and definition into separate files isn’t recommended? Thanks.