ISSUE 96

Number 96
Category errata
Synopsis 4.1.12: ambiguity in the signedness of the >>> operator
State closed
Class superceded
Arrival-DateAug 13 2002
Originator Karen Pieper <Karen.Pieper@synopsys.com>
Release 2001b: 4.1.12
Environment
Description
There seems to be some ambiguity in the standard dealing with the
signedness of the >>> operator.

> >some abstract from 1364-2001.pdf
> >
> >page 63
> >4.1.12 Shift operators
> >...
> >The arithmetic right shift shall fill the vacated bit positions with
zeroes
> >if the result type is unsigned.
> >It shall fill the vacated bit positions with the value of the
most-significant
> >(i.e., sign) bit of the left operand if the result type is signed.
> >The right operand is always treated as an unsigned number and has no
effect
> >on the signedness of the result.
> >The result signedness is determined by the left-hand operand and the
remainder
> >of the expression, as outlined in 4.5.1.
> >
> >
> >page 75
> >4.5.1 Rules for expression types
> >...
> >For non-self-determined operands the following rules apply:
> >if any operand is unsigned, the result is unsigned, regardless of the
> >operator;
> >
> >

It is not clear what is meant in the first quote by "the remainder of the
expression."

In the following example, is the right shift signed or unsigned?

> > > >> ----------------------------------------
> > > >> input [7:0] a,b;
> > > >> output [7:0] o1;
> > > >>
> > > >> assign o1 = a + ($signed(b)>>>3);
> > > >>
> > > >> --------------------------------------

Since the addition is unsigned (and can be interpreted as "the remainder of
the expression")
is the right shift unsigned, or since $signed(b) is signed, is the right
shift signed?

I propose that the right shift is signed, and that the the language in the
first excerpt be modified to
read, "The result signedness is determined solely by the left-hand operand."

Fix
superceded by 282
Audit-Trail

From: Steven Sharp <sharp@cadence.com>
To: etf-bugs@boyd.com, Karen.Pieper@synopsys.com
Cc:
Subject: Re: errata/96: Errata ambiguity in 4.1.12 on the >>> operator
Date: Wed, 14 Aug 2002 20:58:20 -0400 (EDT)

>There seems to be some ambiguity in the standard dealing with the
>signedness of the >>> operator.

I think there is some confusing wording on the signedness of expressions
in general. However, once that is determined, the behavior of >>> is
clearly defined.

> > >some abstract from 1364-2001.pdf
> > >
> > >page 63
> > >4.1.12 Shift operators
> > >...
> > >The arithmetic right shift shall fill the vacated bit positions with
>zeroes
> > >if the result type is unsigned.
> > >It shall fill the vacated bit positions with the value of the
>most-significant
> > >(i.e., sign) bit of the left operand if the result type is signed.
> > >The right operand is always treated as an unsigned number and has no
>effect
> > >on the signedness of the result.
> > >The result signedness is determined by the left-hand operand and the
>remainder
> > >of the expression, as outlined in 4.5.1.
> > >
> > >
> > >page 75
> > >4.5.1 Rules for expression types
> > >...
> > >For non-self-determined operands the following rules apply:
> > >if any operand is unsigned, the result is unsigned, regardless of the
> > >operator;
> > >
> > >
>
>It is not clear what is meant in the first quote by "the remainder of the
>expression."

You have to also include the rules from 4.5.2. By 4.5.1, if any operand
of an expression is unsigned, the result type is unsigned. But by 4.5.2,
if the result is unsigned, then all operands will be coerced to unsigned
too. And it isn't clear from the description, but that means that the
result type of the operands actually becomes unsigned. So not only does
unsignedness propagate upward to the result type, but the result type
propagates back downward to the operands. And since it changes their
result type, that propagates further downward to their operands as well.

Ultimately, this means that an unsigned operand anywhere in the expression
will cause everything to become unsigned (aside from self-determined
sub-expressions). This is just like all operands being converted to the
widest width before any operations are performed. Unsigned wins, just like
the widest width wins. This is what is meant by referring to the rest of
the expression.

It is patterned after the rules for width-extension, but does not work
as naturally. It is also different from most other languages (like C), so
it works differently from what most people expect. I'm not fond of it
myself. However, that's how it was defined. The easiest way to stay
out of trouble is to avoid mixing signed and unsigned values in expressions.

>In the following example, is the right shift signed or unsigned?
>
> > > > >> ----------------------------------------
> > > > >> input [7:0] a,b;
> > > > >> output [7:0] o1;
> > > > >>
> > > > >> assign o1 = a + ($signed(b)>>>3);
> > > > >>
> > > > >> --------------------------------------
>
>Since the addition is unsigned (and can be interpreted as "the remainder of
>the expression")
>is the right shift unsigned, or since $signed(b) is signed, is the right
>shift signed?

It is unsigned. Since a is unsigned, the result type of the expression is
unsigned. That means that the operands of the + are unsigned. That means
that the result type of the >>> is unsigned. And that means that the shift
will be unsigned by the rules in 4.1.12.

Unfortunately, the text could also be interpreted as doing the shift as
signed, and then coercing the result to unsigned just before the add. But
if you look at the sentence about size extension of operands to the size of
the expression, you will see that this is done before any operation, and
using the signedness after coercion. In other words, coercion to unsigned
is done before size extension, which is done before the operator. So the
operand has already been converted before the shift occurs.

Since the text from the proposal was an attempt to describe an existing
implementation in Verilog-XL, I can say that this was the intent. It is
unfortunate that it was not clearer, especially since the "reference
implementation" is not available to everyone, but I am willing to answer
any questions about it. The rules for width-extension are similarly
confusing and difficult to understand without access to an implementation.

>I propose that the right shift is signed, and that the the language in the
>first excerpt be modified to
>read, "The result signedness is determined solely by the left-hand operand."

That change wouldn't actually get the result you want. As noted above, the
result type of the shift is unsigned. Since the left-hand operand of the
shift is not self-determined, the left-hand operand would be coerced to
unsigned before the shift. So the shift would still be unsigned, even if
it were based only on the signedness of the left-hand operand. Note that
converting b to signed is useless, since it is immediately coerced back to
unsigned.

There are a couple of different ways of getting the result you want:

assign o1 = $signed(a) + ($signed(b)>>>3);

By making both operands of the + signed, the entire expression is signed,
and both its operands are signed, so the shift is done signed.

A second approach relies on the poorly documented fact that $signed and
$unsigned effectively shield their argument from the signedness of the
rest of the expression. They are probably more useful for that than for
the explicit conversion they perform. So another way of getting a signed
shift is:

assign o1 = a + $unsigned($signed(b)>>>3);

Since I know I have explained how this works before, there may be some
further descriptions and examples in the archives.

Steven Sharp
sharp@cadence.com


From: Karen Pieper <Karen.Pieper@synopsys.com>
To: etf-bugs@boyd.com
Cc:
Subject: Fwd: Re: errata/96: Errata ambiguity in 4.1.12 on the >>>
Date: Thu, 15 Aug 2002 09:55:15 -0700

>Category: errata
>Confidential: no
>Originator: Karen Pieper <Karen.Pieper@synopsys.com>
>Class: TBD
>Description:
Comments from one of my engineers:


> > A second approach relies on the poorly documented fact that $signed and
> > $unsigned effectively shield their argument from the signedness of the
> > rest of the expression. They are probably more useful for that than for
> > the explicit conversion they perform. So another way of getting a signed
> > shift is:
> >
> > assign o1 = a + $unsigned($signed(b)>>>3);
>
>I think this is the most interesting part of the reply -- the rest
>more or less makes sense given the rules. I've often wondered how the
>explicit conversion nodes are supposed to work when they are in a
>place where an ordinary expression would be coerced to a different
>signedness.
>
>Here is another example:
>
> assign o1 = a + $signed($signed(b) >>>3);
>
>I'm curious if this also works (which of course we can check, but I
>haven't run it through yet.) The thing is, I can't tell from the
>standard or from this reply whether this will do the same thing, or if
>only an $unsigned protect its argument from being coerced to unsigned.
>This would leave you in the weird situation where the result of the
>outer $signed is coerced to unsigned, but the inner $signed is allowed
>to take effect because it's "protected" by the outer one.
>
>If it does work, then it also means that the specific type conversion
>you use there is completely irrelevant -- whether you mark it signed
>or unsigned, you get the exact same interpretation! BUT, despite the
>fact that it doesn't matter whether you mark it $signed or $unsigned,
>it DOES matter that you have SOME type conversion there -- you can't
>leave it out, or you get a different result! Weird. But I don't
>think I'd be any happer if it DIDN'T work.
>
>It'd also mean that there's a semantic effect when you take an
>expression, all of whose inputs are signed, and which in isolation
>would be interpreted as signed, and then mark it as signed. Whew.
>
>Maybe the behavior of $signed and $unsigned would be a good topic for
>an erratum.


Unformatted


Hosted by Boyd Technology