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

Comments

36 thoughts on “SystemVerilog Coding Guidelines: Package import versus `include
  • 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!

  • Vishnu

    Excelent Article Dave

  • Pranav Joshi

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

  • MBS

    good article, thanks or sharing, Dave.

  • 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.

  • 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.

  • 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

  • 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

  • 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.

    • 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

  • Linh Nguyen

    Very clear, thank you!

  • 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 ?

  • Soha Sayed

    Thank you DAVE .. you are a life saver 🙂 .. CHAPEAU!

  • mukesh

    Hi Dave,
    Thanx for ur wonderful explanation .

  • Christopher

    Thanks for finally talking about > SystemVerilog Coding
    Guidelines: Package import versus `include

  • Yogaraj

    Hi Dave,
    Can you explain me the relationship between comparison scope and comparison unit with respect to import package and include

  • Dave Rich

    Hi Yogaraj,

    I assume you meant “compilation” not “comparison”. If so, please read http://go.mentor.com/unit-vs-root and let me know if you have more questions. And remember, `include is just a text processor that knows nothing about the text it is including.

  • sean little

    Adding Questasim / Modelsim error vsim-7065 that will hopefully flag this discussion should anyone be googling one of the errors that can be caused by incorrect usage of `includes.

  • vinod kumar

    I am working on a verification of wishbone memory controller ip core using SV . I have created the whole environment but unable to control the registers of controller and due to which my dut is not giving any response.
    can someone help me , how to control the status registers and control registers.

  • Nigel

    Hi Dave, I’ve seen many excellent responses from you in various forums, thanks for your efforts. One thing I have long been wondering about is the speed of compile. Say for example I have a block level testbench and re-use will ultimately require almost all the code related to that, am I better off (with respect to compile speed) putting all of the files into fewer packages? Normally i tend to put similar types of classes into one package and other types into other packages, but I wonder if that causes a compile speed hit. Obviously my package split would need to take into consideration what I want to re-use elsewhere and what I don’t want to re-use, but other than that maybe I would be better using larger packages?

  • Dave Rich

    I can’t really say as compilation time has never been a major concern. The use of packages is more of a identifier visibility issue and should not affect code generation time. A SystemVerilog package does not have the same dynamic loading issues that you may thinking of in interpretive languages like PERL or python.

  • Amnon

    Does the same rules are valid for interfaces?
    Can two interfaces have the same name?

  • Dave Rich

    Amnon, No. Module and Interface names exist in a separate namespace. There are ways of having two interfaces with the same name, bit it involves some extra effort using a configuration.

  • Rinky Jayaram

    Hi Dave,
    Thanks for this excellent article.

    I have a question, import helps with compatibility of two different variables declared, keeping their scope in mind, ‘include includes the files needed.
    What is the major reason for preferring import over include?

    what does it mean when i say that Items within package cannot have hierarchical references?

    Thanks again for the post.

    -Rinky

    • Dave Rich

      Rinky, The main point of the article was to show that import and include are not exclusive choices, they are orthogonal features in SystemVerilog. To rephrase your question, you should be asking

      What is the benefit of putting type declarations in packages and then importing them, versus not using packages at all and declaring the types wherever I need them?

      If you ask your question that way, then whether you use `include or not to make those declarations in no longer relevant to that question.
      So to answer why you should be using packages. I’ll give you several reasons:

      You want to take advantage of separate compilation steps to make your compilation flow more efficient, you must use packages to keep your types compatible across the different compilation units.
      You want to be able to hand over a pre-compiled set of code to another organization. This forces you into a separate compilation flow and you’ll need to put types in packages
      You want to prevent global namespace collisions. Even if you wind up compiling everything together, you run the risk of global naming collisions. Packages create independent namespaces.
      Using packages forces you into a modeling style that has a clear set of dependencies. This addresses your last question about hierarchical references. The code you write in a package cannot refer to anything outside that package except for what you import from another package. A hierarchical reference usually means accessing a scope inside your DUT or another module instance.

  • Rinky Jayaram

    Thanks Dave, You cleared all my doubts about Packages.

    -Rinky

  • Ranjeet

    Hi Dave,
    Is it possible to include UVM packages in *.vams file

  • Tanish

    Hi Dave,

    Can you please with the error that I am getting?

    File A.sv
    class A;
    int i;
    endclass : A

    File P.sv
    package P;
    `include “A.sv”
    endpackage : P

    File B.sv
    `include “P.sv” //for some reason, I have to include the package as `include and not import.
    typedef class A;

    A a1;

    Class B;
    a1 = A::type_id::create(“a1”, this);
    endclass: B

    I get the following error:
    The forward typedef of the class does not have a definition in the same scope.
    Please provide a definition to the forward class declaration.

    • Dave Rich

      Your code does not work for me fore either import P::*; or `include “P.sv”. You should not have the statement typedef class A; as it will be imported from the package.

  • Tanish

    I tried the following and it worked for me.

    `include “P.sv”
    import P::A;

  • Madhu Eyunni

    Hi Dave,
    Thanks for the explanation. I understood the difference between`include and using a package. Is import, the answer to the question in the article import Vs include, to avoid name scope collisions?
    Thanks,
    Madhu

  • Suyog Chutke

    Great Article. Thanks Dave

  • Chatrapathi

    What is meant by compatibility? In your explanation I didn’t understand the fact you mentioned “The variables R::a1 and S::a1 are type compatible because they are both of type P::A” . Could you please elaborate this point .

Leave a Reply