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

From: Brad Pierce <Brad.Pierce_at_.....>
Date: Wed Aug 02 2006 - 10:39:43 PDT
 -----Non-member submission from [Will Adams
<wadams@freescale.com>]-----
Date: Wed, 02 Aug 2006 12:17:17 -0500

Whether the short-circuit evaluation of the logical operators in C is a
mistake or not, this definition is well-entrenched and widely
understood, and the same operators are used, with short-circuit
semantics, in Unix shells (Bourne shell, C-shell, etc), Perl, Vera, and
other languages. Optionally allowing these these operators to have
non-short-circuit semantics requires different coding idioms.

Optionally allowing short-circuit evaluation of arithmetic expressions
seems to me to be a mistake, unless the conditions under which this is
allowed are strengthened from the `same result' to the `same effect' 
(ie, the same result _and_ identical side-effects). A more general way
to express this requirement is the `as if' rule, as in the C Standard.

will


Bresticker, Shalom wrote:
> I won't take a position here on what the semantics in Verilog should 
> be, but I will note that generally, compatibility to C is not 
> necessarily always desirable.
> 
> There have been cases where the C semantics have been considered 
> unfortunate (a misfeature), and in such cases, it is not necessarily 
> wise to continue to propagate what is considered to be a mistake.
> 
> Shalom
> 
>> -----Original Message-----
>> From: Will Adams [mailto:wadams@freescale.com]
>> Sent: Friday, July 28, 2006 11:15 PM
>> To: Bresticker, Shalom
>> Cc: Brad Pierce; sv-bc@eda-stds.org; michael.burns@freescale.com
>> Subject: Re: [sv-bc] [Fwd: Issues with IEEE 1364-2005]
>>
>> I agree that functions with side effects are a programming practice 
>> to be avoided. But the Standard itself requires the implementation of

>> functions that have side effects (for example `$fgetc()'). Functions
> can
>> only be called in an expression context. A user would likely be 
>> surprised to discover (I know I was!) that the statement `b = 
>> $fgetc(fd) + a' is not guaranteed to read a character from file `fd'.
>>
>> The `contradictory desirable behaviors' that I describe are the
> behavior
>> shown by the C language for the syntax given. In C the operands of a 
>> logical operator are always evaluated left-to-right, stopping as soon
> as
>> the result is known; all operands of an arithmetic operator are 
>> evaluated, in any order. C has been in use for over 30 years, and its

>> semantics are well known by a large community of programmers.
>>
>> I think it is unfortunate that Verilog uses the same operator symbols
> as
>> C, but allows them to be implemented with different semantics. It is 
>> particularly unfortunate that the change in semantics is optional, so

>> users must be aware of all the different, legal, ways that a 
>> statement may be executed to fully understand if it will behave as 
>> they desire
> on
>> any Standard-conforming implementation.
>>
>> will
>>
>>
>> Bresticker, Shalom wrote:
>>> Side-effects are in general an undesirable programming practice.
>>>
>>> Will's two examples produce two contradictory desirable behaviors:
>>>
>>> In the example "p != null && p.data > 0", one would desire that the 
>>> expression be short-circuited.
>>>
>>> On the other hand, in the expression "f( ) + a", one would normally
>> want
>>> the side-effect to occur regardless of a, especially because most
>> users
>>> don't even know that short-circuiting can occur.
>>>
>>> I do agree that the description of the condition evaluation in
> 5.1.13
>>> appears to be reversed.
>>>
>>> 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: Wednesday, July 26, 2006 8:13 PM
>>>> To: Will Adams
>>>> Cc: sv-bc@server.eda-stds.org; michael.burns@freescale.com
>>>> Subject: RE: [sv-bc] [Fwd: Issues with IEEE 1364-2005]
>>>>
>>>> See also --
>>>>
>>>>     http://www.boyd.com/1364_btf/report/full_pr/449.html
>>>>     http://www.boyd.com/1364_btf/report/full_pr/288.html
>>>>
>>>> -- Brad
>>>>
>>>> -----Original Message-----
>>>> From: Will Adams [mailto:wadams@freescale.com]
>>>> Sent: Wednesday, July 26, 2006 9:31 AM
>>>> To: Bresticker, Shalom
>>>> Cc: Brad Pierce; sv-bc@eda-stds.org; michael.burns@freescale.com
>>>> Subject: Re: [sv-bc] [Fwd: Issues with IEEE 1364-2005]
>>>>
>>>> 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 Aug 2 10:40:06 2006

This archive was generated by hypermail 2.1.8 : Wed Aug 02 2006 - 10:40:12 PDT