Check that assigning array that have opposite left-to-righto order for
their dimensions have their elements assigned in reversed order.
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>
In the current implementation a `%fork` instruction in a final block will
get scheduled, but never executed.
And while SystemVerilog requires a `final` procedure to execute in 0 time
and so no SystemVerilog `fork` is allowed inside of it, there are some
other scenarios where iverilog generates `%fork` statements.
For example when declaring variables in a sub-block a sub-scope with its
own thread is is used to allocate the storage for those variables and
`%fork` is used to execute the child thread.
E.g. the following, while being valid SystemVerilog, will never execute the
loop because the generated code will implement the loop as a child thread
being executed by a `%fork` statement.
```
final for (int i = 0; i < 10; i++) $display(i);
```
To mitigate this treat final statements the same as functions and rather
than scheduling a child thread, execute it immediately when using the
`%fork` statement.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
The port_index_ member of the NetNet is not initialized which can lead to
undefined behavior. Make sure to initialize to -1 to indicate that the net
is not associated with any port.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Check that foreach counts counts from $left to $right. This means it should
count up if $left is less than $right and count down otherwise.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
foreach loops are supposed to iterate arrays $left to $right. E.g. `reg
x[3:0]` should be iterated from 3 to 0 and `y[1:4]` from 1 to 4.
The current implementation iterates them from $low to $high. Modify this to
either count up or down depending on whether $left or $right is the larger
of the two values.
Note that the same applies for dynamic arrays. But since for dynamic arrays
$left is always 0 and $right is always $high they always count up and we do
not need to differentiate between two different cases.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
vvp_reg.py requires 4 gold files. One for each of stdout and stderr of both
iverilog and vvp. Most of these log files will be empty for most test
cases. This will result in a lot of empty files being added to the
repository.
If a gold file for a specific output stream can not be found assume that
the output stream is supposed to empty. This allows to omit the empty gold
files.
Also remove all the existing empty gold files.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This adds the "normal-vlog95" test type, because we need to run a different
set of commands for this to work so a new test type makes sense. This also
moves a few of the existing tests to the new format in order to test the
new test rig.
Check that packed array assignment patterns and struct assignment patterns
are supported for continuous assignments.
Check for both assignment to variables as well as array elements.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Currently when creating the NetNet for a continuous assignment to an array
element the type of the element is flattened into a canonical 1 dimensional
form. This works for most cases because packed types are compatible if
their total packed with is the same.
But there are some contexts such as if the right-hand-side is an assignment
pattern where the actual type matters and flattening the type will result
in incorrect behavior.
Retain the original type of the array element when creating the NetNet for
the array element assignment.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Add a regression test to show that the proper dumpfile is selected, by
noting in the output from the vvp command what file name it is creating.
To make this work, I also needed to add some capabilities to the vvp_reg.py
regression test rig.
The -dumpfile=<path> vvp extended argument sets the default nanme to use
for the various dumpers. If this flag is not given, the default is "dump".
The $dumpfile system task overrides the default or this command line flag.
This commit also factors out all the dumpfile selection code for the various
dumper implementations.
This generates a fresh copy of config.sub.
The existing config.sub calls 64-bit ARM targets `aarch64`, which is
the official name for the target. However, Apple targets go by the
name `arm64-apple`. As a result, this platform was not recognized.
This gets iverilog building on Apple targets with 64-bit ARM processors.
Signed-off-by: Sean Cross <sean@xobs.io>
This creates a new test suite driver and infrastructure for going
forward. This cleans up the descriptions for tests, and is more
extensible.
Include documentation for the new engine, so that new tests can go
here instead of the old test suite.
Check that struct assignment patterns with only positional arguments are
supported. Also check that invalid assignment patterns for structs report
an error.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Check that positional and nested positional assignment patterns are
supported for packed arrays. Also check that invalid assignment patterns
for packed arrays result in an error.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Structs can be initialized by an assignment pattern. E.g.
```
struct packed {
int x;
shortint y;
} S = '{ 1, 2};
```
is the same as
```
struct packed {
int x;
shortint y;
} S;
s.x = 1;
s.y = 2;
```
Add initial support for unnamed struct assignment patterns. Named struct
assignment patterns like
```
struct packed {
int x;
shortint y;
} S = '{x: 1, y: 2};
```
are still unsupported.
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>
Check that package exports are supported. Also check for various scenarios
where package exports should fail.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
By default an identifier that has been imported into a package is not
available for imports by other packages. Only imports that have been
exported can be imported again. E.g.
```
package P1;
int x;
endpackage
package P2;
import P1::x;
export P1::x;
endpackage
module test;
import P2::x; // This will only work if x has been exported.
endmodule
```
Exports follow the same syntax as imports and allow both export of specific
identifiers or wildcard export. Export supports the special `*::*` target,
which will export all imported items.
Add support for handling package exports.
There is one special cases that needs to be considered. Usually when using
wildcard imports from multiple packages it is an error if there multiple
import candidates for an identifier. With exports it is possible that there
are multiple candidates through different packets, but they all refer to
the same identifier. In this case it does not create a conflict. E.g.
```
package P1;
int x;
endpackage
package P2;
import P1::x;
export P1::x;
endpackage
package P3;
import P1::*;
import P2::*;
int y = x; // No import conflict
endpackage
```
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This is a test for github issue#800. This should work on all platforms,
but Windows seems weird. The issue seems to be with Windows comparing
gold files with CR-LF weirdly, so make all the tests internal.
Add additional enum compatibility tests that check for compatibility in
different contexts.
* Array element
* Function return value
* Function and task argument
* struct member
* class property
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
In SystemVerilog it is not allowed to assign a value to a enum variable
that is not of the same time as the enum variable.
This is currently enforced for assignment and continuous assignment. But
ignored in other places such as function parameter passing.
Move the enum type check into `elab_rval_expr()` to cover more cases.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
In most cases the type of an lvalue part select is the base type of the
lvalue with the width of the part select. But there are some exceptions.
1) An index into a `string` type is of type `byte`.
2) Packed structs are implemented as packed arrays under the hood. A lvalue
struct member is elaborated as a normal part select on a packed array. The
type of that select should be the type of the member.
For the case 1 there is some special handling for strings that accounts for
this. But for case 2 the type information of the member is lost.
This works fine for most things but there are a few constructs where the
type information is required.
* Enum type compatibility check
* Assignment pattern behavior depends on the type of the lvalue
Allow to attach a specific type to a lvalue part select to allow correct
behavior for constructs where the type is required.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
The NetAssign_:net_type() function return the type of lvalue expression.
But it only does so for a limited amount of cases.
Refactor the function so that it works for the general case and always
returns the data type, if the data type of the lvalue expression is known.
This will allow to implement better type checking and other constructs such
as pattern assignments that require to know the type of the lvalue.
It also allows to remove some duplicated code in other methods of
NetAssign_ that want to lookup the type.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Check that an error is reported when accessing a hierarchical identifier
through a package scoped identifier.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Package scoped identifiers should only be able to access identifiers that
are declared in the package, but not identifiers that are visible in the
package, but declared outside of it.
```
int x;
package P;
int y;
endpackage
module test;
initial begin
$display(P::x); // Should fail
$display(P::y); // OK
end
endmodule
```
Make sure that the symbol search will not attempt to cross the package
boundary during identifier lookup.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
In SystemVerilog identifiers can usually have an additional package scope
in which they should be resolved. At the moment there are many places in
the code base that handle the resolution of the package scope.
Add a common data type for package scoped paths as well as a
symbol_search() variant that works on package scoped identifiers. This
allows to handle package scope resolution in a central place.
Having the code in a central place makes it easier to ensure consistent and
correct behavior. E.g. there are currently some corner case bugs that are
common to all implementations. With the common implementation it only has
to be fixed in one place.
It will also make it easier to eventually implement class scoped
identifiers.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
There are a few NetExpr subclasses where the data type of the expression
is known, but it not attached to the NetExpr and only kept as a private
member in the subclass.
Attaching the type directly to the NetExpr allows to query it externally
and implement better type checking.
It also allows to remove a bit of duplicated code in the subclasses and
rely on the default implementation in the NetExpr base class.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
The current NetExpr::enumeration() always returns a nullptr.
The NetExpr class has a ivl_type_t member that represents
the type of the expression.
Provide a default implementation of NetExpr::enumeration() that
casts this type to the netenum_t type. This will allow
to share this implementation between subclasses and remove
a bit of duplicated code.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>