[sv-bc] RE: [sv-ec] Name resolution issues

From: Mark Hartoog <Mark.Hartoog_at_.....>
Date: Tue Aug 07 2007 - 15:29:30 PDT
 

> -----Original Message-----
> From: Gordon Vreugdenhil [mailto:gordonv@model.com] 
> () Lack of Rules
> 
> Mark's write-up has some interesting examples and
> suggestions about deferred handling of name resolution
> but there are no clear rules about how to apply
> the suggested approaches.  The lack of definite rules
> makes it difficult to extrapolate the examples to non-trivial
> circumstances.

I have written a set of rules, but I thought it would be clear to 
explain things with a few simple cases than the general rules. 
I will try to send out the rules this week.
 
> 
> () Bind semantics
> 
> I completely disagree with Mark's assumption that "bind"
> may cause more names to be imported.  Adding names to a
> scope during elaboration is a recipe for error prone design.
> Mark's example is a trivial case that appears to be desirable,
> but he has not provided addressed non-trivial cases involving,
> for example, binding into a nested module.  In such cases,
> the outer lexical scope is in play as well as the inner
> nested module scope.  Allowing the bind to impact the effective
> import name set in the outer scope coule invalidate code in
> that scope.  A instance introduced by a "bind" is supposed
> to use the names that exist in the scope of the target -- I don't
> agree with Mark that bind should be allowed to introduce names
> (even potential names) from a lexically visible import.

There are questions about how bind should work in nested scopes. I gave
examples of a module in $unit scope.  Exactly the same problem exists
in nested modules. I suggest a 3 different ways of resolving this
issue. 

In verilog, it appears that you can forward reference task and function
names, because they are resolved at elaboration time. Since identifiers 
in bind are also being resolved at elaboration time, I would be ok with
letting them bind to any identifier in enclosing scopes. In this case
there would be no issue with wildcard imports in enclosing scopes
causing errors.
  
> () Class properties
> 
> Although I don't necessarily object to allowing forward
> references to class property names, the rules for this
> have to be specified very carefully.  C++, for example,
> does not allow a name use to change kind from
> a type to non-type or vice versa if the name is visible
> via a "use" prior to its existence as a class property.
> This would be very important to handle in any proposed set
> of rules.  In addition, there may well be interactions
> with the move macro-like handling of assertions constructs
> within classes.

The macro-like assertion constructs like sequences and properties
can only be fully understood and error checked after they are fully
expanded and this can only be done after elaboration. As far as
I know, there are no issues with wild card imports in these 
constructs though. Identifiers that are not formals are treated
and resolved like any other identifier at parse time. 
 
> () Inline constraints
> 
> I have substantial problems with the direction that Mark
> is suggesting for inline constraints.  In particular,
> the deferred error handling is going to be highly susceptible
> to changes in user code and won't be detectable until
> elaboration time.  In complex design scenarios such very
> late detection of basic name conflicts are going to cause
> serious usability problems.
> 
> In addition, there is still no way, given Mark's suggestion,
> to reliable write a function such as:
>     function void do_rand(class_type c, int x);
>         c.randomize with {prop < x};
>     endfunction
> 
> Since "x" can bind into "c" due to remote and incidental
> changes to "class_type" AND since you can't name the
> function formal in an authoritative manner, such cases
> will make writing robust code very difficult.

I agree that the deferred error handling is less than optimal,
but System Verilog is an approved IEEE standard at this time. 
Other ways of fixing this problem require language changes that
are not backwards compatible. I believe at this time the bar for
justifying a language change that is not backwards compatible is
higher than I don't like it that I cannot detect this error until
elaboration. There are lots circumstances in System Verilog where 
errors that could be detected at parse time in 1364 now have to be 
deferred until after elaboration. This is largely because of 
type parameters, but other features like generic interfaces require
delayed error checking.

The do_rand function example you show illustrates the big problem I
have with your proposal for 1858. The 1858 proposal does nothing to
solve the problem in this case. You want to add an optional "item."
prefix to say this must resolve in the variable, but resolution 
in the variable is default behavior. If you say
   c.randomize with { item.prop < x }
you still have the same problem, because the default is to resolve
'x' first in the variable. It would be better to add some new
optional syntax to force an identifier to not be resolved in the
variable. This is a capability that is not in the language currently.

module m;
int b;

class C;
  int a, b;
endclass

C c;

initial c.randomize with { a < b };
endmodule

If I really wanted 'b' in the randomize with block to bind to the 'b'
at module scope, there is no way to express that in the language.  If
'b' were in $unit, I could say $unit::b, but for the general case of
enclosing scopes there is no way to force an idenfier to not resolve
in the scope. If I could say "notitem." this would add some new
capability
to the language that is not currently there, though obviously "notitem."
is not the right keyword here. 


> () Hierarchical name rules
> 
> Mark has not discussed how dotted names (hierarchical or
> selects) are to be handled.  This is a critical aspect
> of any proposal.  How and when one commits to a "select"
> versus a hierarchical name for a dotted name is a
> fundamental question.
> 

I did not include hierarchical names in this proposal to 
keep the first email simple. Essentially, you can commit
to the beginning of a dotted name being a hierarchical name
or a select at the same time that you can finalize simple
identifier resolution. Of course you can have hierarchical names
to selects, which cannot be completely finalized until after
elaboration. In fact, you cannot tell where the hierarchical 
name ends and where the select begins until after elaboration.
  
> 
> Summary
> 
> I am pretty seriously opposed to Mark's direction of
> making name resolution substantially more dynamic.  Such
> approaches lead to less reliable systems and poor composition
> of design components.  Although technically feasible,
> I seriously question the long term impact this is
> going to have on design composition for the users.
> 
> A design component should have a clearly defined set of
> interaction rules (I want to say "interface" but don't
> want to confuse that with the SV interface!).
> 
> I think that it would be much better to work on mechanisms
> for having specifications in the more dynamic circumstances
> that state the invariants that must hold for the design
> to be valid.  A design component can then be separately
> compiled with knowledge that its internal behavior cannot
> be compromised if the specification holds.
> 
> Most of the issues involve class interactions with type
> parameters.  Why not just provide a specification for
> the type parameter such that one has definite knowledge
> early?  Something along the lines of a Java interface is
> what I have in mind.  This could easily be expressed in
> the current language by changing the semantics of a
> type parameter default to mean "any override must satisfy
> the name resolution of the default".  So a class default
> provides essentially a specification of the names that
> any override must provide.
> 
> Such a change would be simple to make and would address
> the more dynamic cases without weakening system composition
> in the manner that Mark is suggesting.
> 
> Gord

Verilog as a language has always had dynamic name resolution.
Task, function and hierarchical names have always been resolved 
at elaboration. There is no question that System Verilog has
made the language even more dynamic. Features such as type parameters,
interface ports, generic interfaces, bind, and the macro like constructs
in the assertion language mean a lot more error checking is only
possible after elaboration.

We can argue whether this makes the language good or bad, but the 
time to argue that the language was too dynamic was before it was 
approved as a IEEE standard. I am strongly opposed to making changes
to the language at this point that are not backwards compatible 
for the purpose of making the language less dynamic and easier to
error check at parse time. If we can find ways to enhance parse
time error checking without sacrificing backwards compatibility 
we can consider those kinds of changes. 

 
 

-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
Received on Tue Aug 7 15:29:56 2007

This archive was generated by hypermail 2.1.8 : Tue Aug 07 2007 - 15:31:33 PDT