`std::vector<netrange_t>` is used for signal array dimensions. As such it is
used in quite a few places.
Add a typedef that can be used as a shorthand to refer to it. This helps to
keep lines where this is used from growing to overly long.
The new type is called `netranges_t`.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
The are many binary operations where if the two operands are 2-state the
result is guaranteed to be 2-state.
This is true for all arithmetic operation with the exception of division
where division by 0 will always result in 'x even if the inputs are both
2-state.
The same is true for all binary bitwise operators as well as the binary
logical operators.
Having the expression type be 2-state avoids some unnecessary %cast2
instructions that would otherwise get inserted when assigning the result to
a 2-state variable.
E.g without this change the following will result in
```
int a, b, c;
b = a + b;
```
will result in
```
%load/vec4 ...;
%load/vec4 ...;
%add;
%cast2;
%store/vec4 ...;
```
For binary comparison operators this is already handled.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Consistently use ivl_assert() instead of assert() in the eval_tree()
implementations. ivl_assert() includes information about which expression
triggered the assert and it makes debugging easier.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
If the left-hand side of a logical operator is a constant that causes the
right-hand side to be short-circuited the right-hand side can be discarded
even if it is not constant.
In this case replace the expression by a constant.
E.g.
* `0 && expr` will be replaced by a constant 0.
* `1 || expr` will be replaced by a constant 1.
* `0 -> expr` will be replaced by a constant 1.
Note that it is not possible to replace the expression by a constant if
only the right-hand side is a constant, even when the value of the
expression is constant. The left side still has to be evaluated for side
effects.
E.g. it is known at elaboration that `a++ && 0` will yield 0, but the
increment on `a` has to be executed regardless.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
We don't support evaluating user-defined system functions at compile
time. If possible, defer evaluation until run time. If used in a
constant expression, output a "sorry" message.
This works by translating it to a $size() system function call.
The $size function is already implemented for dynamic queues and
it is easy enough to expand it for queues.
The root cause was that NetESignal::dup_exr() was not copying the calculated
type (signed/unsigned) of the expression.
In passing, found and fixed a similar issue when calculating a blended value
for a constant ternary expression.
For shift operations evaluated at compile time, the compiler was converting
the right operand to a native unsigned long value. If the operand exceeded
the size of an unsigned long, excess bits were discarded, which could lead
to an incorrect result.
The fix I've chosen is to add an as_unsigned() function to the verinum class
which returns the maximum unsigned value if the internal verinum value is
wider than the native unsigned type. This then naturally gives the correct
result for shifts, as the verinum bit width is also an unsigned value.
I've changed the as_ulong() and as_ulong64() functions to do likewise, as
this is more likely to either give the correct behaviour or to give some
indication that an overflow has occurred where these functions are used.
The verinum arithmetic operators now observe the standard Verilog
rules for calculating the result width if all operands are sized.
If any operand is unsized, the result is lossless, as before.
They also now all observe the standard rules for handling partially
undefined operands (if any operand bit is 'x', the entire result is
'x').
I've also added the unary '-' operator, and renamed v_not() to be
the unary '~' operator. This has allowed some simplification in
other parts of the compiler.
During expression evaluation, the compiler attempts to optimise away
relational operations when one side is constant and all possible values
of the other side would result in the relation being true. This is not
a valid optimisation if the other side is a 4-state variable, as an
'x' or 'z' will result in the relation being unknown.
This patchs adds support for the $dimensions() and $unpacked_dimensions()
array functions. Since the argument is only used to get the type information
these functions can always be evaluated at compile time.
For the following functions if the dimension argument is constant or omitted
and the first argument is not dynamic (a string or dynamic array) they will
return the specified information.
$left(), $right(), $high(), $low(), $increment() and $size()
Dynamic information and a variable second argument will be implement in a
future patch.
This patch implements the evaluate_function method for the NetDisable
and NetSTask classes. It also makes the checks for a function being
constant work when the function contains nested scopes (named blocks).
Pure functions with constant operands can be evaluated at compile
time rather than at run time. This patch provides a global control
to enable this optimisation. Until constant function support is
complete, by default it is disabled.
IVL_VT_NO_TYPE is now used to signal an untyped LHS in a parameter
declaration. The parser function that handles specparam declarations
needs to do this too. Also, although it should never happen, make
sure we don't set the expression width in a NetECast object to a
negative number. Make constant evaluation of NetECast objects
observe the expression width.
This patch fixes a few issues/bugs that showed up when testing the
fixes for implicit casts:
1. Make the compile-time implementation of $abs, $min, and $max match
the run-time behaviour (system functions can't be polymorphic).
2. Correctly set the type (signed/unsigned) of the result of an
assignment inside a constant user function (the LHS should not
inherit the type of the RHS).
3. Fix a bug in the verinum(double) constructor (insufficient bits
were allocated in the case where the double value rounded up to
the next power of two).
This patch adds support for implicit casts to the elaborate_rval_expr()
function. This will handle the majority of cases where an implicit cast
can occur.
This patch implements the evaluate_function method for the NetEBBits,
NetEBDiv, NetEBLogic, NetEBMinMax, and NetEBPow classes. It also
factors out some common code into the NetEBinary class.
This involves working out the code to get the base type of a select
expression of a darray. Also added the runtime support for darrays
with real value elements.