The `elaborate_rval_expr()` function takes a `data_type_t`, a
`ivl_variable_type_t` and a `width` parameter. In most places the
ivl_variable_type_t and width are directly derived from the data_type_t.
This slightly simplifies the code.
The only place where this is currently not possible is when assigning to a
compound expression like a concatenation, e.g. `{a,b} = c;`.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
The result for the built-in methods for the SystemVerilog types is
currently always unsigned. This can lead to incorrect behavior if the value
is sign extended or passed as an argument to a system function (e.g.
$display).
For most built-in methods this does not matter, since even though they have
a signed return type, they will not return a negative value. E.g. the
string `len()` or queue `size()` functions.
It does make a difference though for the queue `pop_front()` and
`pop_back()` methods. Their return type is the element type of the queue.
If the element type is signed and the value in queue is negative is will be
handled incorrectly.
E.g. the following will print `4294967295` rather than `-1`.
```
int q[$];
q.push_back(-1);
$display(q.pop_front());
```
To correctly support this consistently assign the actual data type of the
built-in method's return value to the `NetESFunc`, rather than just the width
and base type. The width, base type and also the signedness can be derived
from the data type.
Note that this only fixes the default signedness, but not the case where
the signedness of the expression is changed by its context (e.g. in
arithmetic expression). Handling this will require some additional work.
Also note that assigning the actual data type is also required to support type
checking on the return value, e.g. as needed for enum types.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
A `return` statement in a function gets translated into a vvp `%disable`
instruction. This works fine as long as no recursion is involved. The
`%disable` instruction will stop execution of all active threads of a
particular scope. For recursive functions this means as soon as the inner
most function returns all containing outer function calls get disabled as
well. This results in incorrect behavior.
To make recursive functions using the `return` statement work use the new
vvp `%disable/parent` instruction. This instruction will only disable the
closest thread in the thread hierarchy that matches the target scope.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
During parsing parameters and localparams are kept in a separate list only
to be collected into the same list during elaboration.
Store them in the same list during parsing as well, this allows to remove
some duplicated code.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
A module port list may contain unnamed entries, e.g.
module dut(a,);
When performing a wildcard connection, these entries should be skipped,
as there is no name to match.
There are too many ad hoc handlers of symbol_search partial results.
Rewrite symbol_search to clean up things like partial results and
member/method detections. Use this reworked symbol_search function
to rewrite expression elaborate for the PECallFunction expressions.
When elaborating a subclass, the base class scope needs to be elaborated
before the subclass scope. If the base class and subclass are defined in
different packages, this requires the package scopes to be elaborated in
the correct order. SystemVerilog reqires packages to be defined before
they are used, so that is the order we should elaborate them in.
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.
Depending on the order of elaboration, a function may not have been
elaborated before a call to it is elaborated, so don't assert that it
has been. As an optimisation, try to elaborate it on the fly, so we can
elide the call if the function body is empty.
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.
When module ports are collapsed, we can't tell which of the nexus drivers
are associated with a given module port and should be routed through an
associated modpath delay. Work round this by inserting a transparent
buffer or tran_vp if an output or inout port has a modpath delay. The
target code generator can elide this once it has handled the modpath
delays.
The unique, unique0, and priority keywords can decorate case statements
to tell the run time (or synthesis) to do extra tests (or make extra
assumptions). These tests are not implemented in the vvp run time, but
now the decorations make it to the code generators.