Expression bit-length and Associativity

Hi Forum,

( A) I was trying the following code to calculate the bit length of an expression

The 1st initial block i1 has 6 $display statements where the intended output is observed in the last 4 $display statements.

(1) When we write 32’( i << j ) is the 32’ size cast applied to both operands or is it only i or j ?

(B) Return value of $bits based on expression-bit-length-determination-with-cast

As per LRM ::

$bits returns the number of bits required to hold an expression as a bit stream

Using the 2nd initial block i2 I am trying to understand the meaning of above quote

(2) When we write $bits(i << j), how is the return value calculated ?

(3) Why does $bits(32'(i << j)) give same output as $bits(32'(i) << j) or $bits(i << 32'(j)) ?

(4) When written in a conditional operation I observe different results with last 2 $display statements of i2, why is it so ?

(C) As per LRM binary operators + - have the same precedence.

Associativity for these operators is left to right.

What does the left to right mean here ?

For the following constraint expression A + B - C + D - E + F == Z

Does the quote imply that the calculation starts from leftmost variable i.e A ?

How would Z be calculated be in this case ?

Thanks

The answers to your questions are found in Table 11-2—Operator precedence and associativity and Table 11-21—Bit lengths resulting from self-determined expressions of the IEEE 1800-2023 SystemVerilog LRM. These tables are described in the sections they are enclosed in.

When writing the expression i << j, the width of the result is solely determined by the width of operandi. The operand ”j” is used in a self-determined or isolated context. The cast 32’( i << j ) is used to cast the result of the expression. The value that i or j holds is irrelevant to determining the width of that expression.

Associativity rules apply to operators that have the same precedence level. == has lower precedence than +/- so the result of A + B - C + D - E + F would be constrained to equal Z. Expressions with operators of the same precedence are ordered from left to right when left associativity is used as in
(((((A + B) - C) + D) - E) + F).

Hi Dave,

I get this part.Due to this reason we observe output as ‘d0 for the first two $displays in i1

Unfortunately I am still confused regarding this quote.

Does the 32’ cast take effect ( i.e variable i is size extended to 32-bits ) before the left shift operation ?

I am trying to correlate the above 32’ cast to size casting within with clause of array reduction

rand bit [3:0] a1[10];

constraint summ { a1.sum() with (32'(item)) == 25; }

Here each element is size casted to 32-bits in the equivalent expression i. e each element is padded with 0’s prior to addition operation.This ensures that sum doesn’t overflow

constraint summ2 { 32'( a1.sum() ) == 25; }

Here the 32’ size cast has no effect in the addition operation as the elements would use their default width of 4-bits

(B) Could you please share your thoughts on (2) , (3) and (4) above

How do I calculate the value returned by $bits in these three scenarios

Thanks

It would be helpful to clearly label all the questions and points when asking multiple questions around multiple points.

Variables don’t get extended; the operands of an expression can be extended before the expression is evaluated. In your example, the operand of the left shift operator is an expression consisting of a single variable. If you had written 32'( {1'b0, i} << j), the operand {1'b0, i} is what get extended because of the cast (assuming i is less than 31 bits). A cast creates an assignment-like context, similar to assigning a temporary variable of the same size as the casting width. That context gets applied to the LHS operand of the shift operator.

The array reduction methods are functions, and the context of the expression used with a function does not flow into the function itself. The with () clause of the array reduction methods is actually part of the definition of the inside of that function.

The operands of an expression can be extended before the expression is evaluated.

Thanks Dave. Hence the 32’ cast takes effect before the shift operation

A cast creates an assignment-like context, similar to assigning a temporary variable of the same size as the casting width.

That context gets applied to the LHS operand of the shift operator.

As lhs operand is 1-bit wide, the 32’ cast is equivalent to the following

bit [31:0] temp_i = 1'b1; // appends { 31{ 1'b0} }

( temp_i << a );  // No overflow during shift operation

It would be helpful to clearly label all the questions and points when asking multiple questions around multiple points.

My Apologies Dave. Let me re-phrase my questions on $bits

As per LRM

$bits returns the number of bits required to hold an expression as a bit stream

Using the 2nd initial block i2 in edalink, I am trying to decode the above line

Generally I have used $bits to define dimensions of packed / unpacked array or part of constraint expression.

I was curious to know how the return value of $bits is calculated for the expressions in i2

(Q1) When we write $bits( i << j ), how is the return value calculated ?

Will it return the bit width of lhs operand i ?

Is the return value essentially independent of the bit width of rhs operand j ?

(Q2) Why do I observe different output in below 2 $display statements in i2 ?

$display("Conditional $bits(1'b1 << a) is 'd%0d",(1'b1 ? $bits(1'b1 << a) : 0 ) ); 
$display("Conditional $bits(1'b1 << a) is 'd%0d", $bits( 1'b1 ? (1'b1 << a) : 0 ) );

Thanks in Advance

Q1) The returned value of the expression $bits( i << j ) represents the width of the expression i<<j, which, as per table 11-21, is the width of i.

Q2) The function $bits() returns a 32-bit signed integer that represents the width of the expression enclosed in parentheses. In the first statement, the width of the expression 1'b1 << a is 1. In the second statement, the width of the expression 1'b1 ? (1'b1 << a) : 0 is 32 because 0 is a 32-bit signed integer, and according to table 11-21, the width of the conditional operator is the larger of the true/false operands.