Number | 96
|
Category | errata
|
Synopsis | 4.1.12: ambiguity in the signedness of the >>> operator
|
State | closed
|
Class | superceded
|
Arrival-Date | Aug 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