In Section 18.1 AFTER:
A global declaration space, visible to all modules at all levels of hierarchy
ADD:
A concept of packages to simplify sharing of data, types and functions
ADD a section 18.3 moving all later sub-sections in Section 18 up by one sub-section number. Also move all syntax boxes from Section 18 up by 2.
SystemVerilog packages provide an additional mechanism for sharing parameters, data, type, task, and function declarations amongst multiple SystemVerilog modules, interfaces and programs. Packages are explicitly named scopes appearing at the outer level of the source text (at the same level as modules, primitives, interfaces, etc.). Types, variables, tasks, and functions may be declared within a package. Such declarations may be referenced within modules, macromodules, interfaces, and other packages by either import or hierarchical name.
Syntax 18-1--Package syntax (excerpt from Annex A)
The package declaration creates a top-level region to contain declarations intended to be shared among one or more modules, macromodules, or interfaces. Items within packages are generally type definitions, tasks, and functions. It is also possible to populate packages with parameters, variables and nets. This may occasionally be useful for globals that aren't conveniently passed down through the hierarchy. Any variables that have initial values defined for them will be initialized in the same way the initialization occurs for variables declared in $root.
The following is an example of a package:
package ComplexPkg;
typedef struct {
float i, r;
} Complex;
function Complex add(input Complex a, b)
add.r = a.r + b.r;
add.i = a.i + b.i;
endfunction
function Complex mul(input Complex a, b)
mul.r = (a.r * b.r) + (a.i * b.i);
mul.i = (a.r * b.i) + (a.i * b.r);
endfunction
endpackage : ComplexPkg
Packages must be defined before before they are referenced to allow the types they define to be recognized by the modules that import from them.
One of the ways to utilize declarations made in a packages is to reference them using the namespace operator "::".
ComplexPkg::Complex cout = ComplexPkg::mul(a, b);
An alternate method for utilizing declarations is the import statement.
Syntax 18-2--Import syntax (excerpt from Annex A)
The import statement provides direct visibility of symbols within Packages. It allows those symbols declared within Packages to be visible within the current scope by their declared simple name. Package hierarchical names to the imported symbols can be created as if the symbol were defined in the importing scope. Two forms of the import statement are provided: explicit import, and wildcard import. Explicit import allows control over precisely which symbols are imported:
import ComplexPkg::Complex;
import ComplexPkg::add;
Explicit imports are treated similarly to a declaration. An explicit import shall be illegal if another symbol by the same name has already been declared or imported into the same scope unless the symbol is from the same package. Similarly, after importing a symbol by a given name, it shall be illegal to then declare a symbol by that same name within the same scope.
Wildcard import allows symbols defined within a package to be imported provided the symbol is not otherwise defined in the importing scope:
import ComplexPkg::*;
All the symbols within a package implied by a wildcard import are candidates for import. They, in fact, become imported only if there are no other symbols by the same name declared or imported in the same scope. Similarly, their visibility may be limited by a subsequent declaration of the same name in the same scope. If the same symbol is defined in two wildcard imports in the same scope, the symbol shall be undefined within that scope.
8.13.2 Search order Rules
Table 8.x describes the search order rules for the declarations imported from a package. To understand the table,
consider the following package declarations:
package
p;package q;
const c = 0;
endpackage;
Syntax |
Description |
Scope containing a local declaration of c |
Scope not containing a local declaration of c |
Scope contains a declaration of c imported using import q::c |
Scope contains a declaration of c imported as import q::* |
|
A qualified package identifier is visible in any scope (without the need for an import clause). |
OK .Direct reference to c refers to the locally declared c. p::c refers to the c in package p. |
OK Direct reference to c is illegal since it is undefined. p::c refers to the c in package p. |
OK .Direct reference to c refers to the c imported from q. p::c refers to the c in package p. |
OK .Direct reference to c refers to the c imported from q. p::c refers to the c in package p. |
import p::*;
. . . y = FALSE; |
All declarations inside package p become potentially directly visible in the importing scope: |
OK .Direct reference to c refers to the locally declared c. Direct reference to other identifiers (e.g., FALSE) refer to those implicitly imported from package p. |
OK .Direct reference to c refers to the c imported from package p. |
OK .Direct reference to c refers to the c imported from package q. |
OK / ERRORc is undefined in the importing scope. Thus, a direct reference to c is illegal and results in an error. The import clause is otherwise allowed. |
import p::c;
. . . if( ! c ) ... |
The imported identifiers become directly visible in the importing scope: |
ERROR .It shall be illegal to import an identifier defined in the importing scope. |
OK .Direct reference to c refers to the c imported from package p.
|
ERROR .It shall be illegal to import an identifier defined in the importing scope. |
OK / ERROR It shall be illegal to reference c before the import of p::c. Otherwise, direct reference to c refers to the c imported from package p. |
Table 8.x Scoping Rules for Package Importation
When using the import p::c form of importation, the use of a variable forces the import of that variable into the local scope, thus creating an error if another package with the same variable name is imported later. This is shown in the following example:
module foo;
import q::*;
wire a=c; // This statement forces the import of q::c;
import p::c; // The conflict with q::c and p::c creates an error.
endmodule;
ADD a new section 23 between Section 23 and 24:
Section 23
Separate Compilation Support
SystemVerilog supports separate compilation through the idea of a separately compiled unit. The smallest unit that can be separately compiled in SystemVerilog is anything that can exist within $root: module definitions, module instantiations, type declarations, program blocks, namespaces, and so on. The beginning of each separate unit is defined by a separate_root statement. The keyword is optionally followed by a name, which serves the effect of naming the $root space of the unit. If a name is not provided one shall be created. Only module, macromodule, interface, udp and namespace definitions are directly visible to other compilation units. Cross unit references to other $root objects in a separately compiled unit are only allowed through the use of namespaces. PLI access to $root objects not declared in namespaces are supported through the use of <unit_name>.<object_name>.
Syntax 23-1--Separate_root syntax (excerpt from Annex A)
References within the unit can access objects within the $root space either by the object's name (<object_name>), by $root.<object_name>. In resolving a reference, SystemVerilog follows the Verilog name search rules within the current separate compilation unit, and then searches the $root for the current separate compilation unit, and then searches the scope containing modules, macromodules, interfaces, udps, and namespaces (i.e. separate_units and objects exported directly from separate units).
A tool may implement the ability to create and name a unit through a tool specific mechanism without requiring a separate_root statement.
Verilog supports the idea that compiler directives once seen by a tool will apply to all forthcoming modules or files in the design. This behavior shall be supported within a separately compiled unit; however, compiler directives from one separately compiled unit shall not impact the behavior of another separately compiled unit.
ADD to Appendix A:
In A.1.3 in the description production before | statement_or_null, ADD:
| package_declaration
| separate_root_statement
In A.1.3 at the end of the section ADD:
Separate_root_statement ::= separate_root [identifier] ;
In A.1.5 in the production for module_common_item, APPEND:
| { attribute_instance } package_import_declaration
Before A.2 Declarations ADD:
A.1.10 Packages:
| anonymous_program
package_import_declaration ::=
import package_import_item { , package_import_item } ;
package_import_item ::=
package_identifier :: identifier
| package_identifier :: *
anonymous_program ::=
program ; { anonymous_program_item } endprogramanonymous_program_item ::=
task_declaration
| function_declaration
| class_declaration
A.9.3 Identifiers
REPLACE:
hierarchical_identifier ::=
simple_hierarchical_identifier
| escaped_hierarchical_identifier
WITH:
hierarchical_identifier ::=
simple_hierarchical_identifier
| escaped_hierarchical_identifier
| package_hierarchical_identifier
ADD:
package_hierarchical_identifier ::= package_identifier :: identifier
package_identifier ::= identifier