Most places in the code use a std::vector for array dimensions.
The only exception is the constructor of NetNet, which uses
a `std::list` to pass the unpacked dimensions. But to store the
unpacked dimensions it also uses a `std::vector`.
There does not seem to be a good reason why the constructor
has to take a `std::list`, so switch it also to `std::vector`.
This allows to simplify the code and remove some special handling
for `std::list<netrange_t>`.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
`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>
In addition to providing positional arguments for task and functions
SystemVerilog allows to bind arguments by name. This is similar to how
module ports can be bound by name.
```
task t(int a, int b); ... endtask
...
t(.b(1), .a(2));
```
Extend the parser and elaboration stage to be able to handle this. During
elaboration the named argument list is transformed into a purely positional
list so that later stages like synthesis do not have to care about the
names.
For system functions and tasks all arguments must be unnamed, otherwise an
error will be reported.
In addition to functions and tasks arguments can also be bound by name for
the various different ways of invoking a class constructor.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
SystemVerilog allows to use assignment patterns to assign values to an
array. E.g. `int a[4] = '{1, 2, 3, 4}`.
Each value is evaluated in the context of the element type of the array.
Nested assignment patterns are supported. E.g. `int a[2][2] = '{'{1, 2},
'{1, 2}};`
Add initial support for array assignment patterns for both continuous as
well as procedural assignments.
For continuous assignments the assignment pattern is synthesized into an
array of nets. Each pin is connected to one of the assignment pattern
values and then the whole net array is connected to target array.
For procedural assignments it is unrolled in the vvp backend. E.g
effectively turning `a = '{1, 2};` into `a[0] = 1; a[1] = 2;`.
Not yet supported are indexed initializers or `default`.
E.g. `int a[10] = '{1:10, default: 20};`
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
`ivl_assert()` is similar to `assert()` except that it will also include
source file and line information about the expression for which the assert
was triggered.
Use `ivl_assert()` instead of `assert()` where the line information is
available. This will generate better bug reports and make it easier to
diagnose why an assert is triggered.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
In SystemVerilog arrays assignments are supposed to be connected left to
right. This means if the left to right direction differs between the two
arrays they will be connected in reverse order.
E.g.
```
logic a[1:0];
logic b[0:1];
assign b = a;
```
should connect a[0] to b[1] and a[1] to b[0]. Things get a bit more tricky
for multi-dimensional arrays where some dimensions have a matching
direction and some do not.
The current implementation always connects them low to high, which results
in incorrect behavior.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
SystemVerilog allows to use assignment patterns to assign a value to a
packed array.
This is similar to using a concatenation, with the difference that for
concatenations the values are evaluated in a self-determined context and
for assignment patterns they are evaluated in a context defined by the
element type of the packed array. This means that the value is for example
automatically width expanded or truncated if it does not have the same size
as the element type. Automatic type conversion is also done when allowed. E.g.
```
bit [3:0][3:0] x = '{1'b1, 32'h2, 3.0, "TEST"};
$display("%x", x); // -> 1234
```
Nested assignment patterns are also supported. E.g.
```
bit [1:0][3:0][3:0] x = '{'{1, 2, 3, 4.0}, '{5, 6, 7, 8}};
$display("%x", x); // -> 12345678
```
Add support for using assignment patterns as the right hand side value.
Since the complete type of the target variable is required to correctly
evaluate the assignment pattern it is handled as a special case in
`elab_rval_expression()`. For other types of expressions for packed values
only the total width of the target value is provided to the rvalue
elaboration function.
SystemVerilog also supports assignment patterns for the left hand side in
assignments. This is not yet supported.
Also not yet supported is specifying array elements by index, including
`default`.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Unpacked array dimensions that are specified with only a single size value
(C-style unpacked arrays) have a $left of 0 and a $right of size - 1. E.g.
`x[10]` is equivalent to `x[0:9]`. This is defined in the LRM (1800-2017)
section 7.4.2 ("Unpacked arrays").
Currently it is implemented the other way around. There are a few contexts
where this distinction matters. For example array to array assignments,
which are supposed to be done left-to-right.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Dynamic arrays and queues can be implicitly cast between each other. At the
moment this only works if the right hand side is a signal or assignment
pattern.
But this should be possible for other r-value expression that returns a
queue or dynamic array type. E.g. function calls or class properties.
Since the expr_type() method is defined for all NetExpr objects we can use
that and do not have to cast to NetESignal.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
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.
As reported on iverilog-devel on 2018-10-12, a dimension size of zero
could case the compiler to go into an infinite loop. Further tests
showed that unsized or queue dimensions entered as packed dimensions
would cause the compiler to crash.
As discussed on iverilog-devel (2018-03-09), the existing implementation
(using Icarus-specific vpi functions) only worked with assignments to
simple variables, and could not be easily modified to work more generally.
So use the new vvp instructions added in the previous two commits.
This does a better job of setting the intermediate expression types
and widths when calculating the canonical index into a packed array.
It still doesn't properly handle out-of-bound indices (br953).
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.
If an error is found whilst elaborating a range expression in a signal
declaration, create a dummy range and continue elaboration. This stops
the compiler reporting an error every time that signal is referenced.
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.