Parameters can have string type and do the usual string stuff,
and also implement some of the string methods on string parameters
so that they evaluate down to constants.
Use the common data_type_or_implicit rules to support type
definitions for parameters. This eliminates a bunch of special
rules in parse.y, and opens the door for parameters having
more complex types.
This.new is not allowed.
super.new beyond the first statement is not allowed.
And while I'm at it, clean up the use of "@" and "#" in
the code as tokens for this and super.
A NetESelect is used for accessing packed struct members and also for
accessing dynamic array elements. In these cases the expr_type() and
enumeration() methods should reflect the member/element type.
When -pfileline=1 is used the queue procedural warnings have file
and line information added to the messages. Also switch the trace
debugging to be off by default.
Also, Add some preliminary missing darray functionality.
When strings are arguments to functions/tasks, that doesn't suddenly
make them implicitly scalar. Strings are vectors and should be treated
that was, even if they are IMPLICIT_REG.
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.
Casting from signed to unsigned types and vice versa is legal in SV,
as is casting from a larger to a smaller size. Obey Verilog rules
for expression bit width and signedness.
A compressed assignment statement should give exactly the same
result as the equivalent uncompressed statement. This means
that the type (signed/unsigned) of the LHS affects the type of
the RHS expression (unlike in normal assignments). We need to
take care that bit/part selects and concatenations are correctly
identified as unsigned values, even in the cases where they
reduce to a single whole signal.
This goes all the way down to the vvp level, where we create support
for arrays of objects, generate the new code in the -tvvp code
generator, and elaborate the arrays in the first place.
If an expression contains a division, remainder, or right shift operation,
set the expression min_width to UINT_MAX to flag that the expression width
cannot be pruned. Using UINT_MAX ensures that the min_width won't change
as we continue to elaborate the expression.
Internally, treat the "$" as a special expression type that takes
as an argument the signal that is being indexed. In the vvp target,
use the $last system function to implement this.
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 netparray_t::slice_dimensions bug was the most insidious and
caused all manner of confusion. Also fix some other packed array
and unpacked array (and mixed) indexing calculations.
When an expression is elaborated, the compiler converts multiplies with
one constamt zero operand into a constant zero value. This is only valid
if the other operand is not a 4-state variable.
Unsized expressions can expand to extremely large widths. Usually this
is actually a mistake in the source code, but it can lead to the compiler
temporarily using extremely large amounts of memory, or in the worst
case, crashing. This adds a cap on the width of unsized expressions (by
default 65536 bits, but overridable by the user), and causes a warning
message to be output when the cap is reached.
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.
This changes the verinum pow() function to use the more efficient algorithm
used in the vvp runtime. It will still be slow if the left operand is unsized
and the right operand is large, as it will expand the result vector to avoid
overflow.