I am forwarding an email which I sent to the customer outlining my opinion on this issue. We can use this email and its follow up as a starting point for analysis. Chuck Swart -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.
attached mail follows:
THE ISSUE: A customer (Tim McBrayer from Mathworks) reports a problem with our compiler on the following code: LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.numeric_std.all; ENTITY badconcat IS PORT ( in_0 : IN unsigned(1 DOWNTO 0); in_1 : IN unsigned(1 DOWNTO 0); in_2 : IN unsigned(1 DOWNTO 0); out1 : OUT std_logic_vector(5 DOWNTO 0)); END badconcat; ARCHITECTURE arch OF badconcat IS TYPE bad_type IS ARRAY (0 to 99) of unsigned(1 to 1000); BEGIN out1 <= std_logic_vector(in_0 & in_1 & in_2); END arch; Modelsim fails to compile this code, complaining about the type conversion std_logic_vector(...). Modelsim claims that there is an ambiguous type in trying to interpret the operand type of the type conversion. The two possible types and accompanying interpretations are: 1) bad_type (in_0, in_1 and in_2 are interpreted as elements whose result type is bad_type, ie &(element_type of T, element-type of T) return T where T is "bad_type") and 2) unsigned (in_0, in_1 and in_2 are interpreted as the resulting array type, ie &(T,T) return T where T is "unsigned") Modelsim engineers argue that all visible operators are examined. The customer argues that the &(element,element) return T case should not be considered because of two statements in the LRM. Clause 7.3.5, "Type conversions", states: "The type of the operand of a type conversion must be determinable independent of the context (in particular, independent of the target type)." and Clause 7.2.4, "Adding operators", states for the &(element,element) return T case: "If both operands are of the same type and it is the element type of some one-dimensional array type, the type of the result must be known from the context and is this one-dimensional array type." So who's right? ANALYSIS: RELEVANT REFERENCES TO "CONTEXT": There are only a few places in which expressions are evaluated "independent of context." They are: 3.2.1.1 "Index constraints and discrete ranges" which states that if both bounds of the discrete range are not of type universal integer, then both bounds must be of the same type and "this type must be determined independently of the context, but using the fact that the type must be discrete and that both bounds must have the same type." 7.3.5 "Type conversions" the area under discussion, described above. 8.8 "Case statement" which states that the type of the case expression "must be determinable independently of the context in which the expression occurs, but using the fact that the expression must be of a discrete type or a one-dimensional character array type." No other references mention type determination independent of context. Several parts of the LRM mention the use of context to determine meaning: These include: 4.2 "Subtype declarations" 6.4 "Indexed names" 7.2.4 "Adding operators" (under discussion) 7.2.4 "Adding operators" (example of use of context to disambiguate concatenation) 7.3.2.2 "Array aggregates" (types and bounds of aggregates containing "others") 7.3.3 "Function calls" 7.3.4 "Qualified expressions" (use of qualified expression to disambiguate an ambiguous expression) 7.3.5 "Type conversions" (under discussion) 7.3.5 "Type conversions" (implicit conversion of universal operands) Several clauses mention use of context with some restrictions and additional rules: These are: 7.3.1 "Literals" (Type of a string or bit string literal is determined by context without examining the literal itself, but using the fact that the type is a one-dimensional array of a character type) 7.3.2 "Array aggregates" (Type of an aggregate is determined by context without examining the aggregate itself but using the fact that the type is a composite type) 7.3.6 "Allocators" ("The type of the access value returned by an allocator must be determinable solely from the context, but using the fact that the value returned is of an access type having the named designated type.") 8.4 "Signal assignment statement" (Rules when the target is an aggregate similar to 7.3.2) 8.5 "Variable assignment statement" (Rules when the target is an aggregate similar to 7.3.2) Of particular interest is clause 7.1, "Expressions", which states: "The type of an expression depends only upon the types of its operands and of the operators applied; for an overloaded operand or operator, the determination of the operand type, or the identification of the overloaded operator, depends on the context." Finally, Clauses 10.3, "Visibility", and 10.5, "The context of overload resolution", give detailed rules about determining the meaning of expressions and statements. OUR INTERPRETATION: To begin, lets confine our analysis to the simplified expression: ...std_logic_vector(in_0 & in_1)... This deals with the essential problem. We will discuss the more complicated expression later. First, we believe that, in clause 7.2.4, "Adding operators", the mention of context for the &(element,element) return T case is redundant. This rule is already covered by the general rule in clause 7.1 given above. It is not present in the original Ada Reference Manual. We believe that its inclusion was intended to call attention to the existing overload resolution rules, not to change the semantics of overload resolution by adding a restriction. Second, all three references in the LRM to determining types independent of context give additional or specific rules which indicate intent. In the case of type conversions, the statement that the type of the operand must be determinable "independent of the operand type" gives the intent of the restriction. This is intended to imply, among other things, that you can't use the fact that the target type is an array type to disambiguate the operand type (In Ada 95 this particular restriction has been lifted.). Our interpretation is that the rules of Clause 10.5 are applied within the operand expression to determine the type of the expression, but that no information in the context outside of the expression is used in this determination. We believe that this is the only reasonable interpretation, otherwise, there are no criteria to determine which rules of 10.5 to apply. For example, 10.5 states "At such a place, all visible declarations are considered." If this rule doesn't apply, then how do we decide which declarations are to be considered? Consequently, we believe that our interpretation is correct, that the expression is ambiguous, and that a qualified expression must be used to remove the ambiguity. COMMENT ON THE ORIGINAL CASE OF TWO & OPERATORS We believe that the original case presented by the customer is ambiguous, even if you accept the customer's argument that the element,element case does not apply to the expression: ...std_logic_vector(in_0 & in_1)... In the original expression: ...std_logic_vector(in_0 & in_1 & in_2)... the subexpression: in_0 & in_1 must be resolved, and there is ambiguity caused by two possible interpretations. The first interpretation is &(element,element) return T where T is "bad_type". The second interpretation is &(T,T) return T where T is "unsigned". The first interpretation would cause the ...& in_2 operator to be interpreted as the &(T,element) return T operator, where T is "bad_logic", while the second interpretation would use the &(T,T) return T operator, where T is "unsigned". WHERE DO WE GO FROM HERE? The submitter might not accept our interpretation. If so, then we propose that either we or the customer submit an IR to the VHDL ISAC to get this issue officially resolved. I will be happy to submit this on behalf of the customer. Chuck SwartReceived on Wed Dec 19 11:18:45 2007
This archive was generated by hypermail 2.1.8 : Wed Dec 19 2007 - 11:18:48 PST