Re: [sv-bc] Search order for functions/tasks in modules, $unit and packages

From: Clifford E. Cummings <cliffc_at_.....>
Date: Fri Aug 26 2005 - 14:40:29 PDT
Hi, All -

Responding to sv-bc@eda.org is good enough. I don't need multiple copies in 
my email inboxes.

I will take a stab at this. I believe the governing rules are found in the 
three rules elaborated in section 19.3 and Table 19-1 (granted, this can be 
confusing).

See below.

Regards - Cliff

At 05:08 PM 8/25/2005, Gord wrote:
 >I'm not sure that I want to suggest answers at this point, but
 >here are some additional similar scenarios:
 >
 >1)
 >    module m;
 >      parameter p = 1;
 >      function int fn();
 >         return 0;
 >      endfunction
 >
 >      if (p) begin:b   // generate
 >          reg x = fn();
 >          function int fn();
 >              return 1;
 >          endfunction
 >      end
 >    endmodule

See the rules mentioned below, but I again think local scope wins (the 
function is called from the generated b-block).

 >2)
 >    // file mode compilation unit
 >    module m;
 >      int x = fn();
 >    endmodule
 >
 >    function int fn();
 >      return 1;
 >    endfunction

If they are in the same file, they are in the same compilation unit and per 
rule #2 below, $unit.fn is called.

The only ambiguity that I can think of is that declarations must be made 
before used (true in Verilog modules today) but functions and tasks can be 
called before being declared (per Verilog today). I don't know of any P1800 
verbiage that might have changed the function/task can be called before 
being declared rule(??)

 >3)
 >    // file mode compilation unit
 >    module m;
 >      int x = a;   // error?
 >    endmodule
 >
 >    localparam a = 1;
 >
 >The basic question relates to whether that Mark raises and that
 >is in (1) and (2) above is whether the function name goes
 >through a "resolve" step in the complete context or whether
 >lexical scoping dominates.  In the case of (3), the issue
 >is whether the compilation unit is really an implicit package
 >that bundles all the declarations up as though they exist before
 >any of the scoped items in the compilation unit or whether they
 >follow lexical visibility rules.

I have been under the impression that declarations of variables, wires, 
parameters, etc., must be declared before being used, while tasks and 
functions did not have to be declared before being used, but had to be 
declared in the same module and now the same $unit. I would say that the 
above localparam has not been declared before being used.

In the absence of an alternate description in the P1800 standard, I believe 
Verilog rules apply. Just my opinion.

 >I'll follow up again tomorrow.
 >
 >Gord.
 >
 >
 >
 >
 >Mark Hartoog wrote:
 >>
 >>I tried to send this yesterday, but I never saw it appear on the list.
 >>I am not completely clear on the search order rules for finding
 >>functions and tasks. Consider this case:
 >>
 >>    function int fn();
 >>      return 0;
 >>    endfunction
 >>
 >>    module m();
 >>      int x;
 >>
 >>      initial x = fn(); // which fn() does this bind to?
 >>
 >>      function int fn()
 >>        return 1;
 >>      endfunction
 >>    endmodule
 >>
 >>I think in this case the fn() call in the initial block binds to the
 >>local definition in the module 'm', not to the function in $unit, but I
 >>do not think this is clearly spelled out in the LRM. Do other people
 >>agree with this?

I believe this is "adequately" covered in:

19.3 Compilation unit support

...

When an identifier is referenced within a scope, SystemVerilog follows the 
Verilog name search rules:
  First, the nested scope is searched (P1364 12.6) (including nested module 
declarations), including any identifiers made available through package 
import declarations
  Next, the compilation-unit scope is searched (including any identifiers 
made available through package import declarations
  Finally, the instance hierarchy is searched (P1364 12.5)


The P1364 references also talk about tasks and functions, so "identifier" 
in P1800 should probably also reference tasks and functions (not just 
identifiers) but I assumed this to be true.


 >>What about this case:
 >>
 >>    package p;
 >>      function int fn();
 >>        return 0;
 >>      endfunction
 >>    endpackage
 >>
 >>    module m();
 >>      import p::*;
 >>      int x;
 >>      initial x = fn(); // which fn() does this bind to?
 >>
 >>      function int fn()
 >>        return 1;
 >>      endfunction
 >>    endmodule
 >>
 >>A literal reading of section 19.2.2 would lead me to believe that this
 >>is an error, since the fn() call in the initial block cause the fn() to
 >>be imported from the package, making the subsequent local definition
 >>illegal. Is this what was intended?

I disagree. import::* does not import anything until referenced and if 
there is a local declaration with the same name, the import::* declaration 
is ignored. The local function is called and the import::* function is ignored.

I believe this is loosely covered in Table 19-1 (a very abbreviated and 
therefore confusing table until you expand out the examples, which I did to 
understand this better) - See row 3, which I believe again "adequately" 
covers this case (I would not oppose future modifications to the spec to 
clarify this).

 >>    package p;
 >>      function int fn();
 >>        return 0;
 >>      endfunction
 >>    endpackage
 >>
 >>    import p::*;
 >>
 >>    module m();
 >>      int x;
 >>      initial x = fn(); // which fn() does this bind to?
 >>
 >>      function int fn()
 >>        return 1;
 >>      endfunction
 >>    endmodule
 >>
 >>What about this case? Is this legal? Does the call to fn() in the
 >>initial block cause fn() to be imported into the $unit scope?
 >>
 >>Does that make the subsequent definition of fn() in module 'm' illegal?
 >>
 >>In this case it seems to me that the fn() call in the initial block
 >>should go to the local fn() in the module 'm' and should not cause 'fn'
 >>to be imported into $unit.

I absolutely agree. The local function is called. The import::* function is 
at the $unit level but it is not even actually imported in this scenario. 
Again using the Table 19-1 rules and previous compilation scope search rules.

 >>What is the search order for looking for functions/tasks? I was thinking
 >>module -> module imports -> $unit -> $unit imports

I agree, per the three rules from 19.3 and Table 19-1. Of course, the 
imports assume import::* as opposed to direct import::function, which could 
cause name conflicts and errors (per Table 19-1).

module -> module import::* Is first (local module - rule #1 - then follow 
Table 19-1)
$unit -> $unit import::* is second ($unit scope - rule #2 - then follow 
Table 19-1)

 >>But for backwards compatibility you can not do this while parsing, but
 >>only after the module is complete, and I guess after $unit is complete.
 >>
 >>    package p;
 >>      function int fn();
 >>        return 0;
 >>      endfunction
 >>    endpackage
 >>
 >>    import p::*;
 >>
 >>    module m();
 >>      int x;
 >>      initial x = fn(); // which fn() does this bind to?
 >>    endmodule
 >>
 >>    function int fn()
 >>      return 1;
 >>    endfunction
 >>
 >>Is this an error? or does the fn() call bind to the fn() in $unit?

$unit.fn exists, so it should be used (per rule #2) and if it did not exist 
then $unit(package).fn would exist per rule #2 and Table 19-1.

This has been my interpretation all along, which could be completely wrong.

 >>Mark Hartoog
 >>700 E. Middlefield Road
 >>Mountain View, CA 94043
 >>650 584-5404
 >>markh@synopsys.com
 >>
 >
 >--
 >--------------------------------------------------------------------
 >Gordon Vreugdenhil                                503-685-0808
 >Model Technology (Mentor Graphics)                gordonv@model.com
 >
----------------------------------------------------
Cliff Cummings - Sunburst Design, Inc.
14314 SW Allen Blvd., PMB 501, Beaverton, OR 97005
Phone: 503-641-8446 / FAX: 503-641-8486
cliffc@sunburst-design.com / www.sunburst-design.com
Expert Verilog, SystemVerilog, Synthesis and Verification Training 
Received on Fri Aug 26 14:40:45 2005

This archive was generated by hypermail 2.1.8 : Fri Aug 26 2005 - 14:42:14 PDT