SystemVerilog Coding Guidelines: Package import versus `include

Another frequently asked question: Should I import my classes from a package or `include them? To answer this properly, you need to know more about SystemVerilog’s type system, especially the difference between its strong and weak typing systems.

In programming languages, weak typing is characterized by implicit  or ad-hoc conversions without explicit casting between values of different data types. Verilog’s bit vectors, or integral types, represent these weak typing aspects by implicitly padding and truncating values to be the proper bit lengths – at least proper by Verilog standards. If you perform a bitwise AND of a 7-bit and 8-bit vector, Verilog implicitly zero pads an 8th bit to the 7-bit operand and returns an 8-bit result. In contrast using VHDL, you would have to explicitly state whether you wanted the 7-bit operand to be padded, or the 8-bit operand to be truncated so that you have an expression with operands of equal size.

With a few exceptions, all other types in SystemVerilog follow strong typing rules. Strong typing rules require explicit conversions or casts when assigning or expressing operands of unequal types. And understanding what SystemVerilog considers equivalent types is key to understanding the effect of importing a class from a package versus including it from a file.

Inheritance aside, SystemVerilog uses the name of a type alone to determine type equivalence of a class. For example, suppose I have these two class definitions A and B below:

class A;
int i;
endclass : A
class B;
int i;
endclass : B

SystemVerilog considers these two class definitions unequal types because they have different names, even though their contents, or class bodies, are identical. The name of a class includes more than just the simple names A and B; the names also include the scope where the definition is declared. When you declare a class in a package, the package name becomes a prefix to the class name:

package P;
class A;
int i;
endclass : A
A a1;
endpackage : P
package Q;
class A;
int i;
endclass : A
A a1;
endpackage : Q

Now there are two definitions of class A, one called P::A and the other called Q::A. And the variables P::a1 and Q::a1 are type incompatible referencing two different class A’s. Re-writing the above example using an include file creates the same situation – two incompatible class definitions.

File A.sv File P.sv File Q.sv
class A;
int i;
endclass : A
package P;
`include “A.sv"
A a1;
endpackage : P
package Q;
`include “A.sv"
A a1;
endpackage : Q

After `including class A into each package, you wind up with two definitions of class A. Using `include is just a shortcut for cut and pasting text in a file. Importing a name from a package does not duplicate text; it makes that name visible from another package without copying the definition.

File A.sv File P.sv File R.sv File S.sv
class A;
int i;
endclass : A
package P;
`include “A.sv"
endpackage : P
package R;
import P::A;
A a1;
endpackage : R
package S;
import P::A;
A a1;
endpackage : S

Class A is declared in package P, and only in package P. The variables R::a1 and S::a1 are type compatible because they are both of type P::A. The fact that class A was `included from another file once it is expanded is no longer relevant once you consider the placement of the text from the file.

When you get compiler errors claiming that two types are incompatible even though they appear to have the same name, make sure you consider the scope where the types are declared as part of the full name. Class names declared in a module are prefixed by the module instance name, so the same module instantiated multiple times will create unique class names, all incompatible types.

For further information about packages, check out the June Verification Horizons article entitled “Using SystemVerilog Packages in Real Verification Projects”.

Dave Rich

Post Author

Posted July 13th, 2010, by

Post Tags

, , ,

Post Comments

14 Comments

About Verification Horizons BLOG

This blog will provide an online forum to provide weekly updates on concepts, values, standards, methodologies and examples to assist with the understanding of what advanced functional verification technologies can do and how to most effectively apply them. We're looking forward to your comments and suggestions on the posts to make this a useful tool. Verification Horizons BLOG

@dennisbrophy Tweets

  • Loading tweets...

@dave_59 Tweets

  • Loading tweets...

@HarryAtMentor Tweets

  • Loading tweets...

Comments

14 comments on this post | ↓ Add Your Own

Commented on July 13, 2010 at 11:11 pm
By Greg Jaxon

Excellent illustration, Dave!

What you say about classes also applies to most structs, unions, and enums, too.

One situation to watch is `includes into the $unit scope (outside any module or other part description). Whether the same include file brought into the $unit scope of distinct files can create matching types is a delicate matter; users probably should not expect SV implementations to agree on every case of this.

Good thing packages are so easy to use to get this right!

Commented on July 17, 2010 at 11:34 am
By Vishnu

Excelent Article Dave

Commented on February 8, 2011 at 6:57 am
By Pranav Joshi

This is an excellent piece of explanation. I must use this to train engineers of my team.

Commented on June 28, 2011 at 5:07 pm
By geonerstiem

thanks

Commented on July 7, 2011 at 1:40 am
By MBS

good article, thanks or sharing, Dave.

Commented on September 9, 2011 at 12:00 pm
By Mark Curry

In the final solution – why bother using the include at all? The file’s not included anywhere else – just put the definition in the ‘P’ package and be done with it.

Commented on September 9, 2011 at 1:02 pm
By Dave Rich

Hi Mark,
When you package starts having class A, B, C, etc. you need separate files for better revision control. Then `include shows the required file dependencies and compilation order.

Commented on April 16, 2012 at 3:42 pm
By omer

Hello Dave,

Thank you very much for progressive explanation. I have been trying to understand the difference between the two a while now as I am new to OOP.

Take care

Commented on September 12, 2012 at 10:01 am
By Dave Rich

You can certainly use ‘extern’ to separate class declarations from method declarations, but the methods must be defined before closing the scope. So everything has to be inside the package.
For example
package p;
`include “myclass_declarations.svh”
`include “myclass_methods.svh”
endpackage

Commented on July 3, 2013 at 9:57 pm
By MBC

Hi Dave,

can you give an example of how P::A is type incompatible with Q::A (when you are showing the effects of `include).

It would be nice if you can show a snippet of code that demonstrates the type incompatibility issue between the two variables.

Commented on July 8, 2013 at 7:15 am
By Dave Rich

Shaun,

The code shown in the example showing the effects of `include behaves exactly as the previous example where package P and Q are defined without `include. So if you had

P::A handle_a1;
Q::A handle_a2;
handle_a1 = new();
handle_a2=handle_a1; // this is illegal

Commented on September 16, 2013 at 2:40 pm
By Linh Nguyen

Very clear, thank you!

Commented on January 21, 2014 at 6:24 am
By Surya

HI Dave,

That’s a great explanation. Here is some issue I am facing with my compiler (vcs):

package test_lib_pkg;

import uvm_pkg::*;
`include “uvm_macros.svh”

import bus_agent_pkg::*;
import bus_seq_lib_pkg::*;

`include “bus_test_base.sv”

endpackage

My compiler give me an error saying, “file could not be found” when this included file is not in the same dir as my Makefile is, or else if both are in the same dir it comiples without error. Now how do I tell my compiler to look into the same dir where my pakage files are ?

Commented on January 21, 2014 at 8:17 am
By Dave Rich

This is a tool issue, not a language issue. Please contact your vendor for support.

Add Your Comment

Archives