> -----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