A
ABW
Guest
Hi.
Recently I was digging into details of case constructs. After reading LRM
description and BTF issues on case (especially
http://www.boyd.com/1364_btf/report/full_pr/344.html) I came to some
conclusions.
Let's consider following:
case (case_expression)
case_item_expr1 : case_item_stmt1;
case_item_expr2 : case_item_stmt2;
default : default_stmt;
endcase
First. If case_expression or any of the case item expressions is real, then
the whole case construct is an equivallent of the following if-else-if
sequence:
real temp;
temp = case_expression;
if (temp == case_item_expr1)
case_item_stmt1;
else if (temp == case_item_expr2)
case_item_stmt2;
else
default_stmt;
Steven Sharp's summary of case construct ("(...) It is all consistent with
the way operands of any operator work; it is just
an "operator" with a lot of operands in this case.") suggested me that not
only width of expressions but also signedness is coerced according to
standard rules.
If my understanding was valid it would mean that there is no general way to
express case construct with all vector expressions with if-else-if sequence
because there is no way of forcing signedness of expression outside of this
expression (one can easily force size by assigning expression to vector of
appropriate size, but all the ways of affecting signedness involve other
operators which at best convert all high impendance bits to unknowns and
that would make difference for case).
What if some vendors actually did implement case as if-else-if sequence
similar to the above for reals? It is easy to miss the difference and
neither LRM nor any of the comments of BTF issues say explicitely that
signedness is to be coerced between expressions used in case.
There are couple of approaches to the implementation, each seems to be valid
according to LRM and each can give different results.
First is what matches above mentioned suggestion and this is what I actually
expect:
- if any expression used in case construct is unsigned then all of them
get coerced to unsigned (of course before they are computed), expressions
are computed and compared as signed only if all of them are signed
There is no equivallent in if-else-if sequence.
Second is an equivallent of the following algorithm:
assign case_expression to the temporary vector of the size of the widest
expression used in case construct; signedness of the temporary vector is
determined by the standard rules, that is, if all expressions used in the
case constructs are signed then temporary is signed, otherwise it is
unsigned; use the temporary and case equality operator (===) to match
consecutive case item expressions in the if-else-if sequence
This approach differs from the first because signedness of the case item
expressions does not influence the way case_expression is evaluated. Case
item expressions, however, do influence each other in terms of signedness
and they are influenced by the signedness of case_expression.
Third is just like the second but signedness of temporary vector used to
keep value of case_expression is determined by signedness of case_expression
only. It means that unlike in second approach case item expressions don't
influence each other in terms of signedness. All case item expressions are
still affected by the signedness of case_expression.
Fourth approach is like third but each case item expression is assigned to
its own temporary vector of the same size as the one for case_expression and
then these temporary vectors are compared. Since they are of the same size
their signedness does not really matter. All expressions used in this
approach are self-determined in terms of signedness.
There may be more approaches but these four is enough.
In order to clarify my doubts on how case construct is supposed to behave
I've used three simulators and a simple test that shows differences between
the above approaches. It seems that VXL follows first approach, NCSim
follows fourth and VCS follows second. My test is really simple and it does
not prove that these tools actually implement it the way I described but it
is enough to show that they differ in the way they handle signedness in case
construct.
I know that in real world the differences are not important because
expressions are of the same sizes but it bothers me anyway.
Regards
ABW
Recently I was digging into details of case constructs. After reading LRM
description and BTF issues on case (especially
http://www.boyd.com/1364_btf/report/full_pr/344.html) I came to some
conclusions.
Let's consider following:
case (case_expression)
case_item_expr1 : case_item_stmt1;
case_item_expr2 : case_item_stmt2;
default : default_stmt;
endcase
First. If case_expression or any of the case item expressions is real, then
the whole case construct is an equivallent of the following if-else-if
sequence:
real temp;
temp = case_expression;
if (temp == case_item_expr1)
case_item_stmt1;
else if (temp == case_item_expr2)
case_item_stmt2;
else
default_stmt;
Steven Sharp's summary of case construct ("(...) It is all consistent with
the way operands of any operator work; it is just
an "operator" with a lot of operands in this case.") suggested me that not
only width of expressions but also signedness is coerced according to
standard rules.
If my understanding was valid it would mean that there is no general way to
express case construct with all vector expressions with if-else-if sequence
because there is no way of forcing signedness of expression outside of this
expression (one can easily force size by assigning expression to vector of
appropriate size, but all the ways of affecting signedness involve other
operators which at best convert all high impendance bits to unknowns and
that would make difference for case).
What if some vendors actually did implement case as if-else-if sequence
similar to the above for reals? It is easy to miss the difference and
neither LRM nor any of the comments of BTF issues say explicitely that
signedness is to be coerced between expressions used in case.
There are couple of approaches to the implementation, each seems to be valid
according to LRM and each can give different results.
First is what matches above mentioned suggestion and this is what I actually
expect:
- if any expression used in case construct is unsigned then all of them
get coerced to unsigned (of course before they are computed), expressions
are computed and compared as signed only if all of them are signed
There is no equivallent in if-else-if sequence.
Second is an equivallent of the following algorithm:
assign case_expression to the temporary vector of the size of the widest
expression used in case construct; signedness of the temporary vector is
determined by the standard rules, that is, if all expressions used in the
case constructs are signed then temporary is signed, otherwise it is
unsigned; use the temporary and case equality operator (===) to match
consecutive case item expressions in the if-else-if sequence
This approach differs from the first because signedness of the case item
expressions does not influence the way case_expression is evaluated. Case
item expressions, however, do influence each other in terms of signedness
and they are influenced by the signedness of case_expression.
Third is just like the second but signedness of temporary vector used to
keep value of case_expression is determined by signedness of case_expression
only. It means that unlike in second approach case item expressions don't
influence each other in terms of signedness. All case item expressions are
still affected by the signedness of case_expression.
Fourth approach is like third but each case item expression is assigned to
its own temporary vector of the same size as the one for case_expression and
then these temporary vectors are compared. Since they are of the same size
their signedness does not really matter. All expressions used in this
approach are self-determined in terms of signedness.
There may be more approaches but these four is enough.
In order to clarify my doubts on how case construct is supposed to behave
I've used three simulators and a simple test that shows differences between
the above approaches. It seems that VXL follows first approach, NCSim
follows fourth and VCS follows second. My test is really simple and it does
not prove that these tools actually implement it the way I described but it
is enough to show that they differ in the way they handle signedness in case
construct.
I know that in real world the differences are not important because
expressions are of the same sizes but it bothers me anyway.
Regards
ABW