SystemVerilog allows initialized and uninitialized net declaration entries to
be mixed in the same declaration, e.g. `wire x, y = 1'b1`. In Verilog,
either all nets need to have an initializer or non can have one.
In addition SystemVerilog also allows assignments to arrays of wires during
declaration. E.g. `wire a[3:0] = b;`
Currently there are two different rules for net declarations, one for each
of the Verilog variants. Combine these into a single rule to support
SystemVerilog mixed declarations as well as the assignment to array nets.
When running in Verilog mode still reject mixed initialized and
uninitialized with a check after the parsing.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
SystemVerilog 2023 allows type parameters to be restricted to a
specific kind of type, e.g. `parameter type struct T = T0`.
This is very similar to the type restrictions that can be applied to
forward typedefs.
Factor the support code from the typedefs into a standalone helper and
reuse it for both.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
SystemVerilog 2023 adds soft packed unions. They are pretty much the same
as regular packed unions except they remove the restriction that all
elements have to have the same packed width.
The packed with of the union itself is the maximum packed width of any
element.
The bits of each member are right-justified towards the LSBs and this
representation is applied recursively to nested soft packed unions. The
existing packed union member offsets already use that layout. When
accessing a field that is smaller than the union itself upper bits are
ignored for both reading and writing.
The `soft` qualifier implies a packed union so both `union soft U { ... }`
and `union soft packed U { ... }` declare a soft packed union.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
The parser union still has a few fields that are not used by any
grammar rule. They do not have matching semantic type tags and no
action references them.
Remove the unused fields.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
The LRM allows to add a lifetime specified for variables declared in
package scope. It is not particular useful since only static lifetime is
allowed. But it is legal syntax, so support it.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
The drive strength of a net must be declared between the net type and the data type. E.g.
wire (weak0, strong1) [7:0] x;
The current implementation expects the drive strength after the data type. Update the parser to fix this.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
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>