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>
Types for array signals are currently handled as a special case. The type
that is associated with the signal is not the array type itself but rather
the element type.
There is a fair amount of existing code that depends on this behavior so it
is not trivial to change this.
But there are certain constructs such as assignment patterns or array
concatenation where the array type itself is required.
Add a new `NetNet::array_type()` method that will return the array type if
the signal is an array. This will allow to query the array type when
needed.
`NetAssign_::net_type()` is updated to use this new method to return the
array type if the assigned signal is an array.
Long term the special handling of arrays for signals should be removed.
This will for example allow to unify the handling of arrays for signals,
class properties and struct members.
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>
There are some cases where during an assignment the elaboration step can
generate constructs with the right-hand-side expression being wider than
the left-hand-side expression.
To handle this the tgt-vvp backend inserts a %pad operation when necessary.
One place where this is missing is when writing to an string element. Here
instead an assert is triggered requiring the right-hand-side expression to
be 8 bits wide.
E.g.
```
bit [7:0] x;
bit [8:0] y;
string s;
x = y; // tgt-vvp inserts %pad
s[0] = y; // tgt-vvp triggers assert
```
Long term this should be fixed at the elaboration stage and insert the
proper width cast. But for now solve this the same way as other places in
tgt-vvp and insert the %pad operation for string element assignments if the
width does not match.
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>
Check that the file and line location is correct for errors
related to implicit named port connections.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Some tests require a specific compiler error, rather than just failing. Add
support for this by allowing to check for gold files for CE tests.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Implicit named port connections are only supported by SystemVerilog. Add a
check to generate an error when trying to use it in Verilog mode.
Regression test br_gh315 is modified to run in SystemVerilog mode since it
makes use of implicit named port connections.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
The implicitly generated identifier for implicit named port connections
gets its file and line information from the optional attributes. If no
attribute list is specified this will just point to the beginning of the
file resulting in incorrect line information.
Use the file and line information from the identifier token instead to fix
this.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Check that implicit import of functions and tasks is supported if the
wildcard import statement is in the unit scope.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
SystemVerilog requires that functions and tasks are not implicitly imported
if a symbol with the same name appears in the scope, even if it the symbol
is declared after its usage.
To support this a list of potential imports is collected while parsing a
scope and only when the end of the scope is reached it is evaluated whether
the symbol should be imported or not based on whether it already exists in
the scope.
This currently works fine for all scopes except for the unit scope. Since
the unit scope might span multiple files it is never explicitly closed and
the potential imports are never checked.
Make sure that after parsing all files is done the potential imports for
the unit scope are checked.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Add support for `continue` and `break` in constant functions. This is done
in a similar way to how `disable` is implemented for constant functions.
Two new global flags are introduced `loop_break` and `loop_continue` that
get set when evaluating the corresponding statement. If either of these
flags are set all other statements are ignored until the end of a loop is
reached. At the end of the loop both `loop_break` and `loop_continue` get
cleared. If `loop_break` was set before clearing it the loop is exited.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Check that it is possible to omit trailing ports in a module ordered list
connection list.
Also check that an error is generated if too many ports are specified in a
ordered list connection.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
The current implementation expects that for a module instantiation with a
ordered list connection all ports are supplied.
But there doesn't seem to be such a requirement in the LRMs. The Verilog
LRM doesn't mention anything in this regard and the SystemVerilog LRM
mentions in section 23.3.2.1 that a blank or omitted port connection is
either left unconnected or uses the default value of the port.
Update the implementation so that it allows to omit trailing ports and only
generates an error message if too many ports are specified in the ordered
port list.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Currently continue and break are supported in most loops. But not in
do-while loops. Add support for them in do-while loops as well.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Check that partial and fully out-of-bound writes to a function's return
value are handled correctly. Check this for both 4-state and 2-state
vectors.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Partial out-of-bounds write to a function's return value will trigger an
assert, even though the operation is valid.
The assert checks that the truncated value has the expected width, but
instead it should check that the non-truncated value has the expected with.
Move the assert before the truncation to fix this.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>