As discussed in issue #1143, the for loop initialisation statement,
termination condition, and step statement were only made optional in
IEEE 1800-2012. So check all three are present when compiling for
ealier generations.
SystemVerilog makes all of the initialisation, condition, and step
components of a for loop optional. We already support this for the
initialisation and step components.
Enhance the lists of identifiers and declaration assignments generated
by the parser to associate each identifier with its lexical_pos. Also do
this for single items in complex parser rules where the location passed
to the pform is not the location of the identifier.
This is needed for detecting use before declaration. The lexical scanner
is the only place where we process the source text in strict lexical
order, so do it there.
As Verilog allows modules to span multiple source files, don't reset
the counter when we reset the lexor.
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>
Attach line information to named items. This allows to provide better
location information for messages involving named items. The location of
item itself can't always be used, since the item itself might be empty.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
There are a few different places in the parser that all parse named
expressions in the same way. Consolidate them into a single rule.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
The last user of the named_number_t type was removed in commit 2f474358d9
("2f474358d99929ec625a46690d1be6939ed67064"). Remove the type as well.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Commit 3daa2982ac ("Add support for `const` variables") added support for
constant variables, but had a small mistake and did propagate the constant
flag from the parser if the variable is declared with the `var` keyword.
Still allowing to modify those variables. Fix this.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
SystemVerilog allows to declare const variables. These variables are
read-only and can not be assigned a value after their declaration. It is
only possible to assign an initial value as an initializer.
E.g.
```
const int x = 10;
x = 20; // Error
```
The LRM requires that for variable declarations with static storage the
initializer is a constant expression with the extension that other const
variables are also allowed. const variables with automatic storage can
be initialized by any expression.
Checking if an expression contains only const variables requires a bit more
work to implement. So for now be more lenient that what the standard
requires and allow arbitrary expressions to initialize const variables even
for those with static storage.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
In Verilog it is possible to declare multiple ports as part of the same
port declaration. Ports declared this way all have same direction, signal
kind and data type. E.g.
```
module M (input [3:0] a, b, c) ...
```
SystemVerilog extends this and allows to override on a per port basis
certain port attributes. E.g. redefine just the data type
```
module test (input [3:0] a, [1:0] b, int c) ...
```
Or to just redefine the port kind
```
module test(input [3:0] a, var b, wire c) ...
```
It is even possible to leave out the direction for the very first port. As
long as at least one other property of the port is specified. In that case
the direction will default to `inout`. E.g.
```
module test(integer a, b, c) ...
```
Furthermore it is possible to specify unpacked dimensions for each of the
ports. E.g.
```
module test(input integer a, b[1:0], c[3:0][1:0]) ...
```
If all port properties are omitted for the first port this indicates the
start of a non-ANSI port list.
Extend the parser to handle this.
If all three direction, port kind and data type are omitted they are
inherited from the previous port. Otherwise
* If the direction is omitted it is inherited from the previous port.
* If the data type is omitted it defaults to logic.
* If the port kind is omitted the behavior depends on the direction.
For output ports with an explicit data type it is a variable, for
all others it is a net.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Add a helper function to the parser that handles module port declaration.
This allows to reduce a bit of duplicated code.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
At the moment there are two rules for port declarations. One that allows
the port to be declared as an unpacked array, the other that allows to
specify an initializer expression.
SystemVerilog allows both to be specified in the same port declaration. Add
support for this to the parser.
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>
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>
As a quirk of the (System)Verilog grammar a function or task argument list
with no arguments can not be distinguished from a argument list with a
single empty argument. The iverilog parses it as the latter. There are
currently many places in the code base where this is fixed up in slightly
different ways.
Fix this up in the parser in a central way before passing the arguments to
the elaboration stage.
The existing implementation in some cases removes all empty trailing
arguments. While this works to handle the case for zero arguments it also
hides some errors that should be detected. E.g. in the following 3
arguments are passed to a function which only takes two arguments. But no
error is reported since the explicitly specified empty arguments are
removed.
```
function f(integer a, integer b = 2); ... endfunction
f(1,,);
```
In the new implementation the empty argument will only be removed if there
is exactly one empty argument in the argument list.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This includes support at the parser (pform) through enaboration
and the netlist format for the break and continue statements.
Elaboration actually already worked for for-loops, but since the code
generators need more information, this is a rewire of that support to
be explicit about for-loops. This means they are not rewritten as fancy
while loops. The code generators will have to handle that.
Given the elaboration of for-loops now work, write the vvp code generator
support needed to implement it.
Now that for-loops are presented as for-loops to the code generator, the
vlog95 code generator doesn't need to infer them anymore. Generate the code
more directly.
Also update the tests list so that the vlog95_reg tests all pass.
Currently package scoped function calls are supported. Update the parser
and elaboration to also allow method calls on packaged scoped variables.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
SystemVerilog allows to use either `super` or `this.super` to access the
base class. Both have the same behavior. Currently only `super` is
supported, also add support for `this.super`.
To support it the parser has to be changed slightly and move the trailing
`.` after the `this` or `super` keywords into the `implicit_class_handle`
parser rule. This is necessary to avoid reduce conflicts in the grammar.
As a side effect `super` can no longer be used as a standalone identifier.
E.g. `return super;` But that's not legal SystemVerilog anyway, so that is
OK.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
One variant did, the other variant didn't. As well as being a trap for
the unwary, this gets in the way of using yywarn/VLwarn for non-fatal
"sorry" messages.
By default when creating a new class object the type of the object is
determined by the type of the target.
SystemVerilog also allows to explicitly specify the type of the object to
be created. The specified class still needs to be assignment compatible
with the target. This is e.g. useful to construct an object of a derived
class of the target. E.g.
```
class B; ... endclass
class C extends B; ... endclass
B b;
b = C::new;
```
Add support for this to the parser as well as handling it during
elaboration.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Up to 1800-2017 the grammar in the LRM allowed an optional lifetime
qualifier for class declarations. Icarus supports this and uses this as the
default lifetime for methods of the class. But the LRM never specified what
this qualifier should do actually actually. Starting with 1800-2023 the
qualifier will be removed from the grammar[1].
Furthermore the LRM states that methods of a class are supposed to have
automatic storage and static storage is forbidden.
This currently works in Icarus for the most part since the liftime attached
to class methods is ignored during elaboration in most places. Where it
does not work is for variable initializers where it results in broken code
being generated and vvp crashes at runtime. E.g.
```
class C;
task t;
int x = 10;
endtask
endclass
```
Keep the optional lifetime qualifier for classes in the grammar for now, to
ensure backwards compatibility in case somebody is actually using it. But
ignore it and print a warning if it is specified.
In addition set the default lifetime for all classes to automatic. This
makes sure that variable initialization in classes works as expected.
[1] https://accellera.mantishub.io/view.php?id=3561
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
SystemVerilog has explicit support for calling a function
as a statement. This is allowed when the function call is encapsulated in
`void'(...)`. E.g. `void'(f(1, 2, 3));`
We already support calling function calls as statements without the void
cast and emit a warning when doing so.
Adding support for void casts only requires to update the parser to handle
the void cast and then do not emit the warning if a function is called as
a statement as part of a void cast.
Void casting a task or void function call is not allowed and will generate
an elaboration error.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>