Re: [sv-bc] FW: wildcard import name resolution

From: Greg Jaxon <Greg.Jaxon_at_.....>
Date: Wed Dec 12 2007 - 23:21:15 PST
Some minor comments and a disagreement over the task/function
rule are interspersed below...

> *From:* Francoise Martinolle
> *Sent:* Friday, December 07, 2007 10:05 PM
> *To:* sv-bc@eda.org
> *Subject:* wildcard import name resolution
> 
>  
> This is a proposal to formally describe name resolution in presence of
> wildcard imports.
> I also included some examples that Gordon sent me to illustrate this formal
> description. This proposal is to replace the last couple of paragraphs
> in section 25.3.
>  
> 
> A wildcard import is of the following form:* *
> 
> import ComplexPkg::*;
> 
> For the purpose of describing how names resolve to wildcard imported
> declarations we define what is a
> 
> locally visible and potentially visible name.
> 
> Locally visible names are the names of locally visible declarations.
> 
> 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/
> 
> 3.     the name is visible from an import select
>        occurring within /S/ before point /P/
> 
> A name is /potentially locally visible/ at some point, P,
> in a scope, /S/, if : there exist a wildcard import of a
> package within scope /S/ which contains a declaration of that name.

I understand this to mean that the name is also potentially visible
within scopes nested inside S, unless otherwise shadowed.

> Additionally a potentially locally visible symbol from a wild card
> import may become locally visible if
> no locally visible symbol is found and the resolution of an
> identifier causes the potentially locally visible name
> to become locally visible.
> 
> The following paragraph describes how identifiers can be resolved to
> wildcard imported declarations.
> 
> A wildcard import makes all identifiers declared within a
> package potential locally visible symbols in the importing scope, /S /
> 
> A potentially locally visible symbol may become locally visible during
> name resolution in accordance to the following rules:
> 
> If  the identifier is not a function or task call,
> 
> The following algorithm is repeated for each scope /S /until a
> declaration is found which matches the identifier name or there is no
> more lexical scopes. The compilation unit scope being the final scope
> searched.
> 
> 1 - the locally visible declarations in scope /S/ are first searched for
> a match, if a match is found the identifier is bound to that declaration
> 
> 2- else if no locally visible symbol match, then the potentially locally
> visible symbols in the scope /S//, *lexically preceding* /the identifier
> name are searched for a match. If a match is found, the symbol from the
> package is imported in scope /S/ and becomes a locally visible
> declaration in scope /S,/ that declaration  is bound to the identifier.

"Potentially locally visible" symbols are introduced by the first lexical
occurrence of a wildcard import from a package that declares them.

... if a _unique_ match is found ...  (Recall that multiply sourced
candidates cannot be bound following these rules; they become an
immediate error in this case.)

> 3- else /S/ is set to its upper scope
> 
> If there is no more lexical scopes, and the identifier cannot be bound,
> an undeclared symbol error shall be issued.
> 
> If the identifier is a function or task call, the rules are slightly
> different and follow upwards hierarchical name resolution (section 22.7).
> 
>   1- First the *entire *scope /S/ (all the declarations of locally
> visible names up to the end of the scope) is searched for a matching
> declaration, if a match, the identifier is resolved to that declaration,

This differs from the rules currently given in the LRM.  A function
name that is available as potentially locally visible in any of the enclosing
scopes is considered /before/ later declarations as a function in any
of those scopes.  A later declaration may thus be a multiple declaration error.
The example at the bottom of page 331 in 1800-2005 is typical, although it
does not involve a function declaration.  A testcase for this would be
useful so we can see who's on board and who isn't.

package automatic confound;
  function void foo();
  endfunction
endpackage

module global_pollution;
  import confound::*;
  always begin
      foo();
  end
  function void foo();
  endfunction
endmodule

I'm seeing:
Error:  francoise.sv:11: Function declaration redeclares symbol 'foo'. (VER-106)

If this search for the function is supposedly behaving "hierarchically",
the error seems to be perfectly appropriate.  There is a simple workaround:
move the function declaration before its use.  Given the collision of
these two definitions, an error is not an unfriendly outcome, although
I can appreciate how it makes wildcard import into legacy verilog
more risky.

>   2- else if no match is found, the wildcard import potentially locally
> visible symbols in scope /, *lexically preceding */the identifier name
> are searched for a match,

Suppose the scope doesn't declare the function, but instead explicitly
imports it from elsewhere.   If "import elsewhere::foo" appeared in place
of the declaration, would you choose that binding?

> if a match is found, the potential visible symbol becomes locally
> visible, imported in scope /S/ and bound to that identifier,
> 
>  3- else of no match is found, the above algorithm steps 1, 2, 3  are
> repeated for the upper scope of /S,/ including when S is the compilation
> unit scope.
> 
> 4. else if no match, steps b and c of the upwards name resolution are
> executed (the function and task name are searched up the instance
> hierarchy).
> 
>  If the same name is potentially locally visible from more than one
> wildcard imported package in scope /S/, and those wildcard imports are
> *lexically preceding* an identifier of that name,  the identifier shall
> be undefined within that scope. 

If the wildcard imports of two or more definitions of an identifier
*lexically precede* a use of that identifier, the usage is in error.


> Example 1:
> 
>  package p;
> 
>       int x;
> 
> endpackage
> 
> module top;
> 
>       import p::*; // line 1
> 
>       if (1) begin : b
> 
>               initial x = 1; // line 2
> 
>               int x; // line 3
> 
>               initial x = 1; // line 4
> 
>        end
> 
>       int x; // line 5
> 
> endmodule
> 
>  
> 
> The reference in line 2 causes "p::x" to become visible in top and line
> 2 initializes p::x.
> 
> Line 4 initializes top.b.x. Line 5 is illegal since it conflicts with
> the name x imported from p.
> 
>  
> 
>  
> 
>  Example  2:
> 
> package p;
> 
>       int x;
> 
> endpackage
> 
> package p2;
> 
>       int x;
> 
> endpackage
> 
> module top;
> 
>       import p::*; // line 1
> 
>       if (1) begin : b
> 
>           initial x = 1; // line 2
> 
>           import p2::*; // line 3
> 
>       end
> 
> endmodule
> 
> line 2 causes the import of p::x because the wildcard import p::* is in
> the outer scope
> 
> and precedes the occurrence of x.
> 
>  
> 
>  *Example*  3:
> 
> package p;
> 
> function int f(); return 1; endfunction
> 
> endpackage
> 
> module top;
> 
> int x;
> 
> if (1) begin : b
> 
> initial x = f(); // line 2
> 
> import p::*; // line 3
> 
> end
> 
> function int f(); return 1; endfunction
> 
> endmodule
> 
> "f" binds to top.f and not to p::f since the import is after the
> function reference. Do you agree?  

I get the error I reported above, and feel this follows 2005 LRM.
Functions and tasks were given no special consideration there, so
perhaps you feel they warrant a special case now as a change to correct
some usability problem.

> Example 4:
> 
> package p;
> 
>       function int f(); return 1; endfunction
> 
> endpackage
> 
> package p2;
> 
>       function int f(); return 1; endfunction
> 
> endpackage
> 
> module top;
> 
>       import p::*;
> 
>       int x;
> 
>       if (1) begin : b
> 
>               initial x = f(); // line 1
> 
>       end
> 
>       import p2::*;
> 
> endmodule
> 
>  
> 
> Since "f" is not found in scope b, the rules require inspection   of
>  all wildcard imports in the parent.  There are two wildcard imports,
> but p::* occurs before the occurrence of f(). In this case "f" binds  to
> p::f since the enclosing scope's reference occurs before the p2::* import.
> 
> With the above  formal description approved,  mantis 1809  can be
> revised. Basically the wildcard import only would occur
> 
> if it would be actually bound to an identifier. Currently 1809 imports
> symbols from wildcard imports
> 
> which are not used. My revision of 1809 follows (striked  sentences are
> in (green) ) 
> 
> 22.7.1 Task and Function name resolution
> 
>  
> 
> Task and function names are resolved following slightly different rules
> than other references.  (When a task or function name matches a
> potential name from a wildcard import, that name is imported as would
> normally occur.  However, even when such an import occurs, a task or
> function name resolution does not necessarily bind to the imported
> name. ) Task and function name resolution follows the rules for upwards
> hierarchical name resolution as described in 22.7, step (a).  Then,
> before proceeding with step (b), an implementation shall look in the
> complete compilation unit of the reference.  If a task or function with
> a matching name is found there, the name resolves to that task or
> function.  Only then does the resolution proceed with step (b) and
> iterate as normal.  The special matching within the compilation unit
> shall only take place the first time through the iteration through steps
> (a)-(c);  a task or function name shall never match a task or function
> in a compilation unit other than the compilation unit enclosing the
> reference.
> 
>  
> 
> Example:
> 
>  
> 
> *task** *t;
> 
> *     int *x;
> 
> x = f(1);             // valid reference to function f in $unit scope
> 
> *endtask*
> 
> *function** int *f(*int* y);
> 
> *     return* y+1;
> 
> *endfunction*
> 
>  
> 
>  
> 
> Example:
> 
>  
> 
> *package* p;
> 
>   *function* *void* f();
> 
>     $display("p::f");
> 
>   *endfunction***
> 
> *endpackage***
> 
>  
> 
> *module* top;
> 
>   *import* p::*;
> 
>  
> 
>   *if* (1) *begin* : b         // generate block
> 
>      *initial* f();          // reference to “f”
> 
>      *function* *void* f();
> 
>        $display("top.b.f");
> 
>      *endfunction***
> 
>   *end***
> 
> *endmodule***
> 
>  
> 
> (The reference to f in the initial block causes the identifier f to be
> imported into the scope of module top since there is no previously
> declared name f in the scopes enclosing the reference.  However,) the
> resolution of the name f follows the hierarchical rules and therefore is
> resolved to the function top.b.f.  The output of the example would be
> the output of the string “top.b.f”.
> 
>  
> 
> 
> -- 
> This message has been scanned for viruses and
> dangerous content by *MailScanner* <http://www.mailscanner.info/>, and is
> believed to be clean.


-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
Received on Wed Dec 12 23:54:44 2007

This archive was generated by hypermail 2.1.8 : Wed Dec 12 2007 - 23:55:30 PST