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

From: Brad Pierce <Brad.Pierce_at_.....>
Date: Fri Jul 28 2006 - 13:21:38 PDT
-----Non-member submission-----
From: Will Adams [mailto:wadams@freescale.com] 
Sent: Friday, July 28, 2006 1:15 PM
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 Fri Jul 28 13:21:46 2006

This archive was generated by hypermail 2.1.8 : Fri Jul 28 2006 - 13:21:52 PDT