Re: [sv-bc] [Fwd: Issues with IEEE 1364-2005]

From: Brad Pierce <Brad.Pierce_at_.....>
Date: Wed Jul 26 2006 - 10:15:12 PDT
-----Non-member submission-----

From: Will Adams <wadams@freescale.com>

On the evaluation of the conditional operator, IEEE 1364-2005, section
5.1.13 `Conditional operator', states the following.

   conditional_expression ::= (From A.8.3)
     expression1 ? { attribute_instance } expression2 : expression3
   expression1 ::= expression
   expression2 ::= expression
   expression3 ::= expression

   The evaluation of a conditional operator shall begin with a logical
   equality comparison (see 5.1.8) of expression1 with zero, termed the
   condition. If the condition evaluates to false (0), then expression3
   shall be evaluated and used as the result of the conditional
   expression. If the condition evaluates to true (1), then expression2
   is evaluated and used as the result. If the condition evaluates to an
   ambiguous value (x or z), then both expression2 and expression3 shall
   be evaluated; and their results shall be combined, bit by bit, using
   Table 5-21 to calculate the final result unless expression2 or
   expression3 is real, in which case the result shall be 0.

I am not sure why this defines `condition' as `a logical equality
comparison of expression1 with zero', since this means that `condition'
is the negation of `expression1' (`expression1 == 0' is 1 when 
`expression1' is 0, 0 when it is 1, and X when it is X or Z), and, 
applying the rest of the definition, when `expression1' is 1,
`condition' is 0, and so `expression3' is evaluated as the result of the
conditional expression. Similarly, if `expression1' is 0, then
`expression2' is evaluated as the result of the conditional expression.
This seems to give the semantics of an `if else then' operator, rather
than an `if then else', which I doubt is what is intended.

Regardless, it does state that `expression1' must be evaluated first,
and only one of `expression2' and `expression3' is evaluated when
`condition' is 1 or 0, and both are evaluated when `condition' is X or
Z. It also clearly states that evaluation of the conditional operator
`shall begin with' the evaluation of the condition, and only after this
is evaluated does it start evaluating `expression2' or `expression3'.

Given this, my question about the order of evaluation of the two
conditional operators in `a ? b : c ? d : e' remains. In cases where the
right-hand conditional operator is evaluated, the evaluation of the 
left-hand conditional operator begins before, and ends after, the
evaluation of the right-hand operator, so in what sense is this
right-to-left evaluation of the operators?

There is, in my mind, a problem with the statement in section 5.1.4,
`However, if the final result of an expression can be determined early,
the entire expression need not be evaluated.' This refers only to the
_result_ of an expression, and not to any side-effects, which leaves us
in a position where side-effects of potentially unevaluated arguments
may or may not occur. This in turn requires excessively careful coding
to avoid code that may give different results on different
Standard-conforming implementations.

If this section is read strictly, then we must write code as though all
operands may be evaluated, and may not be if other operands are
sufficient to determine the result of the expression. Thus my example
`p != null && p.data > 0' is illegal, since `p.data' is illegal when `p'
is null, and a Standard-conforming implementation may evaluate the
second operand when `p' is null. (We can, of course, rewrite this as
`p != null ? p.data > 0 : 0', to give an expression that is guaranteed
not to evaluate `p.data' when `p' is null.)

Also, we should never write `f( ) + a' if function call `f( )' has a
side-effect, because a Standard-conforming implementation may choose not
to evaluate the first operand if `a' evaluates to X (and thus the result
of the expression is X, regardless of the value of `f( )').

My preference is for a rule that mandates which operands are evaluated, 
and in which order (where this is important), together with a rule
similar to the `as if' rule of the C standard, which allows
implementations to break the rules as long as the observable effect is
as if they had been followed. So, for example, if the rule is that all
operands in an arithmetic expression must be evaluated, using the `as
if' rule, an implementation is allowed not to evaluate `a' in `a + X'
provided that it can determine that the evaluation of `a' has no
observable side-effects.

will adams


Bresticker, Shalom wrote:

> 1. As Brad points out, 1364 does relate to short-circuiting by saying
>  that an implementation may optionally implement short-circuiting, 
> but is not required to do so.
> 
> 2. In the given example,
>> a ? b : c ? d : e
> which is parsed as
>> a ? b : ( c ? d : e )
> 
> Will says, " If `a' is 1, then the RH `?:' operator is not evaluated"
>  .
> 
> That is not at all clear. Will himself says, " The operand evaluation
>  order only really needs to be defined
>> when the result of evaluating one operand affects how the remaining
>>  operands are evaluated."
> 
> I don't know what implementations actually do. But at least in most 
> cases, there is no problem in principle in defining that the second 
> ?: is evaluated first. If an implementation optimizes by identifying 
> that it is unnecessary, that is not a problem as long as it does not 
> change the result.
> 
> Shalom
> 
> 
> 
>> -----Original Message----- From: owner-sv-bc@server.eda-stds.org 
>> [mailto:owner-sv-bc@server.eda- stds.org] On Behalf Of Brad Pierce
>>  Sent: Tuesday, July 25, 2006 9:26 PM To: sv-bc@server.eda-stds.org
>>  Cc: michael.burns@freescale.com; WADAMS@freescale.com Subject: Re:
>>  [sv-bc] [Fwd: Issues with IEEE 1364-2005]
>> 
>> See http://www.eda-stds.org/sv-ac/hm/2501.html .
>> 
>> -- Brad
>> 
>> -----Original Message----- From: owner-sv-bc@eda-stds.org 
>> [mailto:owner-sv-bc@eda-stds.org] On Behalf Of Brad Pierce Sent: 
>> Tuesday, July 25, 2006 11:20 AM To: sv-bc@eda-stds.org Cc: 
>> michael.burns@freescale.com; WADAMS@freescale.com Subject: [sv-bc] 
>> [Fwd: Issues with IEEE 1364-2005]
>> 
>> -----Non-member submission-----
>> 
>> Date: Tue, 25 Jul 2006 09:19:24 -0700 From: Michael Burns 
>> <michael.burns@freescale.com> CC: William Adams 
>> <WADAMS@freescale.com>
>> 
>> Hi folks,
>> 
>> A comment on precedence definitions in Verilog from one of our 
>> engineers.
>> 
>> --Mike
>> 
>> -------- Original Message -------- Subject: Issues with IEEE 
>> 1364-2005 Date: Mon, 24 Jul 2006 09:34:24 -0500 From: Will Adams 
>> <wadams@freescale.com> To: Michael Burns 
>> <michael.burns@freescale.com>
>> 
>> There is a misstatement in the IEEE 1364-2005 standard, which has 
>> been there for a while (it was in 1364-2001, and perhaps in earlier
>>  versions of the Standard). Do you know how to get it fixed?
>> 
>> The error is in section 5.1.2 `Operator precedence'. There it 
>> states
>> 
>> All operators shall associate left to right with the exception of
> the
>> conditional operator, which shall associate right to left. 
>> Associativity refers to the order in which the operators having the
>>  same precedence are evaluated.
>> 
>> This is wrong. It does not make a lot of sense to talk about `the
> order
>> in which operators ... are evaluated', since I do not think this is
>>  well-defined in all circumstances (see below). What can be defined
>>  is the order of _operand_ evaluation.
>> 
>> This clause confuses associativity, which concerns the parsing of 
>> expressions that are not fully parenthesized, with evaluation 
>> order. I think what this may be getting at is that if `a + b + c' 
>> is parsed as `(a + b) + c', then the LH `+' operator is evaluated 
>> before the RH `+' operator, since subexpression must be evaluated 
>> before a containing expression. This definition fails to adequately
>>  describe the intended evaluation of the conditional operator,
>> which associates
> right-to-left,
>> but whose operands are evaluated left-to-right.
>> 
>> The right-to-left associativity of the conditional operator means 
>> that the expression
>> 
>> a ? b : c ? d : e
>> 
>> is parsed as
>> 
>> a ? b : ( c ? d : e )
>> 
>> and not as
>> 
>> ( a ? b : c ) ? d : e
>> 
>> This is the same as in C, and allows the writing of `if ... else if
>> 
>> 
> ...
>> else ...' constructs using the conditional operator without 
>> excessive parentheses.
>> 
>> However, the conditional operator is evaluated left-to-right. First
>> 
>> 
> the
>> condition is evaluated, and then one or both branches is evaluated.
>> 
>> 
>> 
>> To see that the order of _operator_ evaluation is not always well 
>> defined, consider the evaluation of this expression. Operand `a'
> (which
>> is an operand of the LH `?:' operator) is evaluated first. If `a' 
>> is
> 1,
>> then the RH `?:' operator is not evaluated; if `a' is 0, then the
> `else'
>> expression (ie, `c ? d : e') is evaluated, and its value is the 
>> value
> of
>> the whole expression (ie, of the LH `?:' operator); and if `a' is X
>>  or Z, then the RH `?:' is evaluated, and its result is combined 
>> bitwise with the result of evaluating `b' to yield the overall 
>> result of the whole expression. So, in cases where the RH `?:' 
>> operator is
> evaluated,
>> the evaluation of the LH `?:' operator begins before, and ends 
>> after, the evaluation of the RH `?:' operator. So what is the 
>> operator evaluation order?
>> 
>> I have seen similar mistakes in several C++ textbooks. As far as I 
>> can tell, it is necessary to have three concepts to clearly define 
>> how expressions are parsed and evaluated: precedence, 
>> associativity, and operand evaluation order. The first two together
>>  allow the
> construction
>> of a unique parse tree for any expression, and the third then 
>> mandates how this parse tree is to be evaluated.
>> 
>> For most operators, there should be no operand evaluation order. 
>> For
> the
>> expression `a + b', an implementor should be free to evaluate `a'
> first,
>> `b' first, or both simultaneously, and they should be free to 
>> choose a different order each time the expression is evaluated, if 
>> it suits
> them
>> to do so. The operand evaluation order only really needs to be 
>> defined when the result of evaluating one operand affects how the 
>> remaining operands are evaluated (the only exception to this I can 
>> think of is
> the
>> `,' sequencing operator in C).
>> 
>> On a related issue, Section 5.1.9 `Logical operators' does not 
>> state
> if
>> `&&' and `||' are evaluated in a short-circuit fashion, as they are
>>  in C. That is, for the C expression `a && b', `a' is evaluated 
>> first,
> and,
>> if it is 0, `b' is not evaluated, since the value of the expression
>>  is
> 0
>> regardless of the value of `b'. If this is not the case, then
> different
>> coding idioms are required. In C, to test if integer pointer `p' is
>>  non-null, and points to a positive value, we write `p != 0 && *p >
>>  0'. This never leads to segfault, since `p' is not dereferenced if
>>  it is null. An equivalent expression in SystemVerilog, `p != null 
>> && p->data > 0' will cause a null object access error if
> both
>> operands are evaluated when `p' is null.
>> 
>> Keeping the concepts of associativity and evaluation order separate
>>  allows for a clearer statement of the requirements. We can 
>> distinguish `&&', which associates left-to-right, and whose 
>> operands (I am
> assuming)
>> are evaluated left-to-right, from `+', which associates 
>> left-to-right, but has no required evaluation order. Operator `?:' 
>> associates right-to-left, and evaluates left-to-right.
>> 
>> I appreciate that these are minor issues, but I think the Standard
>>  should be fixed to precisely define the requirements on 
>> implementors.
>> 
>> will
> 
Received on Wed Jul 26 10:42:10 2006

This archive was generated by hypermail 2.1.8 : Wed Jul 26 2006 - 10:42:18 PDT