[sv-bc] Discussion overview of SV name resolution

From: Gordon Vreugdenhil <gordonv_at_.....>
Date: Fri Jun 02 2006 - 09:15:31 PDT
At the last SV-BC meeting, I committed to sending out a
preliminary version of a document outlining my thoughts
on a framework for SV name resolution.  Attached is an
html version of that document.  This is not intended to be an LRM
proposal (yet) though at some point the issues and clarifications
raised in the document need to become part of a combined 1364/1800
spec.  Ideally, I would like to see this become the basis for
a more systematic approach for reaching consensus on name
resolution issues.  Feedback is definitely welcome.

This is also attached to Mantis 1043 as it is directly related.
See:
    http://www.eda.org/svdb/bug_view_page.php?bug_id=0001043
for the attachment "name_resolution.htm"

Gord.
-- 
--------------------------------------------------------------------
Gordon Vreugdenhil                                503-685-0808
Model Technology (Mentor Graphics)                gordonv@model.com


Name resolution in SystemVerilog

Name resolution in SystemVerilog

 

 

In this document, all references to “Verilog” refer to IEEE 1364-2005 and all references to “SystemVerilog” refer to IEEE P1800-2005.

 

SystemVerilog has added several levels of complexity to Verilog name resolution.  In Verilog, any sequence of identifiers (or indexed identifiers) with “dot” separators was considered a hierarchical name and followed the resolution rules in 1364-2005 Clause 12.5 – 12.7.  In SystemVerilog such names could be either hierarchical names or selected names since simple variables can now have type structure.  The package import rules and class derivation add additional complexity to the resolution. 

 

The following document clarifies the relationships between various forms of name resolution in SystemVerilog with the goal of preserving compatibility with Verilog name resolution on all legacy Verilog designs.

 

The document incorporates some recent committee consensus that packages may not depend on compilation unit declarations.

 

The definitions and algorithms determine resolution for resolvable names; handling of incorrect references is an implementation issue.  The algorithms are defined in terms of resolution of names within the fully elaborated design.  Name resolution that occurs during elaboration (for defparam statements and similar) is not directly addressed but follows the same algorithm within the partially elaborated design. 

 

Definitions

 

A name component is a simple identifier followed by an optional sequence of index expressions.

 

A dotted name is sequence of name components separated by dots.

 

A hierarchical name is a “topological reference” that is resolved in the context of the structure of the instantiated design.

 

A selected name is a “structure reference” that is resolved in the context of the types of the expressions.

 

The lexical parent of a scope is the enclosing scope in the text of the design.  Compilation units and packages are the only scopes that do not have a lexical parent.

 

The topological parent of a scope is defined only for instantiations and is the scope of the instantiation statement within the parent instance (or top level module) in the elaborated design.   Per the LRM, the parent must be either a top level module, an instantiation, or an elaborated generate scope.

 

Note that in the context of nested generate constructs, the “lexical parent” of an elaboration of the inner construct is the elaborated outer construct.

 

It is legal to have a dotted name composed of a hierarchical prefix followed by a dot followed by a selected name.  It is not legal to have a dotted name composed of a selected name followed by a hierarchical name.

 

In Verilog, a name component in a hierarchical name can resolve in an upwards manner through the design topology following the rules in 1364-2005 Clause 12.6.  A key aspect of the rules proposed here is that upwards name resolution shall only apply during resolution of the hierarchical portion of a dotted name; once the resolution of a dotted name begins treating name components as part of a selected name, upwards resolution no longer occurs.

 

The basic algorithm for resolving a dotted name follows three phases:

  1. “local” resolution of the first name component
  2. resolution of the hierarchical name components (if any)
  3. resolution of the selected name components (if any)

 

Additional definitions

 

A name is locally visible at some point, P, in a scope, S, if one of the following holds:

1.     the name denotes a scope within S

2.     the name is declared within S before point P [1]

3.     the name is visible from an import occurring within S before point P

 

For a class, a name is directly visible by inheritance if the name is a method or property of a class extended by this class unless the base class is either

1.     A type parameter

2.     A typedef  defined by a reference to an interface port type.

3.     A forward type declaration whose full type has not been defined

4.     A typedef of any of the preceding types

 

A design unit is a scope defined by a  primitive, program, interface module, macromodule or package declaration.

 

 


Algorithm

 

Let scope be the scope within the instantiation containing a dotted name reference

Let component be the first name component in the dotted name

Let name be the name portion of component

 

Phase 1

 

while (1)

if name is “this”[2]

                        scope = the class enclosing scope

break

else if name is “super”

                        scope = base class of the class enclosing scope

                        break

            else if name is “$root”

                        name = next name component

                        scope = the top level design unit denoted by name

else if name is locally visible in scope[3]

                        break

            else if scope is a class declaration and name is directly visible by inheritance

                        break

            else if scope is a design unit

                        if topological_start is not set

toplogical_start = scope

scope = the lexical parent of scope

            else if scope is the compilation unit

                        break

            else

                        scope = the lexical parent of scope

 

if name was not found or name is an instantiation or a generate scope name

            if name is not found in scope

                        scope = toplogical_start[4]

goto phase 2

else

            goto phase 3

           

 


Phase 2[5]

            while name is not found in scope or name does not denote a scope[6]

                        if the scope is an instantiation

                                    scope = topological parent of scope

                        else

                                    scope = lexical parent of scope

            if name denotes a scope

                        scope = scope denoted by name[7]

                        name = next name component

                        goto Phase 2

            else

                        goto Phase 3           

 

 

Phase 3

name is a non-scope declaration within scope; resolve remaining name components as selects into the variable denoted by name

 

 

Additional observations

 

  1. it shall be legal for a class to declare a property or method with a name which hides a property or non-virtual method name which is visible by inheritance
  2. if a name is visible by way of a wildcard import directly in the class scope, that name shall be selected before considering names visible by inheritance.
  3. for nested design units, lexical scoping takes precedence over topological searching.
  4. within classes, a local declaration within a method shall be selected before considering names visible by inheritance
  5. the handling of class and package names (of the form “id::name”) are not addressed here.  Such names can occur as the prefix of a dotted name but denote either a scope or variable name and fall into either the phase 2 or phase 3 parts of the algorithm directly.

 

 

 

 



[1] The combination of points 1 and 2 require “declaration before use” for variables but not for scopes, including function or task references.

[2] The names “this” or “super” are reserved in SystemVerilog and can only be used as the first component of a dotted name.  The description here ignores the effects of having a legal use of  “this” or “super” when using the keywords directives to ignore SystemVerilog keywords.

[3] For modport and interface port handling, this implies that a dotted name becomes strictly downward after a modport or interface port.  This preserves the expressed visibility.  Additionally, the algorithm here assumes that for a modport, the “scope” contains only the names legally visible via the modport.

[4] This condition ensures that for nested design units, upwards toplogical references begin their resolution at the instantiation of the nested design unit

[5] Phase 2 is essentially a more algorithmic expression of the 1364-2005 12.6 rules for upwards name referencing rules.

[6] The “name does not denote a scope” part of this condition is for backwards compatibility.  This condition implies that an upwards resolving “next” name must denote a scope and not a variable or net, etc.  Topological upwards search is thus different than lexical upwards search that is done in phase 1.

[7] The algorithm assumes that the referenced name exists; in the context of a arrayed instance or a reference into an elaborated generate loop, if the name matches and the index is invalid, the upwards search does not continue and an error is reported.

Received on Fri Jun 2 09:15:20 2006

This archive was generated by hypermail 2.1.8 : Fri Jun 02 2006 - 09:15:26 PDT