Commit Graph

9541 Commits

Author SHA1 Message Date
Lars-Peter Clausen ef42df6fef Add a regression test for calling $bits() with a data type
Check that $bits() can be called with packed data types.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-13 15:03:49 +01:00
Lars-Peter Clausen c4feb89957 Handle unpacked array types for $bits()
For unpacked statically sized array types $bits() is supposed to return the
total size of the array. Accumulated the number of unpacked dimensions and
multiply it by the packed with of the base type to get the right result.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-13 15:03:49 +01:00
Lars-Peter Clausen c76db2867c Allow any data type in primary expression
There are a few system functions that take either an expression or a data
type. This is implemented in the parser by allowing a type identifier as a
primary expression.

But those functions allow any data type, not just typedefs. E.g.

```
$bits(int);
$bits(reg [1:0]);
$bits(struct packed { int x; });
```

Support this by changing the parser rule from TYPE_IDENTIFIER to data_type.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-13 14:49:29 +01:00
Lars-Peter Clausen 481f461e59 Add regression test for expressions in attributes
Check that all types of constant expressions are supported in attributes.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-12 17:56:30 +01:00
Lars-Peter Clausen 497c98bf9b Remove eval_const()
There are no more users of the eval_const() system. Lets remove it.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-12 17:41:41 +01:00
Lars-Peter Clausen 30ff2aa5d1 Support full set of constant expressions in attributes
There are currently two different systems to evaluate constant expressions
in iverilog.

The PExpr based system using the eval_const() method and the NetExpr based
system using the eval_tree() method. The latter is more complete while the
former only implements the bare minimum and also has some minor bugs.

The PExpr based system is only used to evaluate expressions within
attributes.

Switch attribute expression evaluation over to elab_and_eval(). This
enables to use the full  set of constant expressions for attributes, maybe
most importantly constant functions and system math functions.

It also allows to remove the PExpr based system since there are no more
users.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-12 17:40:45 +01:00
Lars-Peter Clausen 7f40e120c8 Add regression tests for omitting `parameter` in parameter port list
SystemVerilog allows to completely omit the `parameter` or `localparam`
keyword in the parameter list. Both at the beginning and before redefining
the parameter data type. This is not support in Verilog.

Add regression tests that check that this is supported when in
SystemVerilog mode.

It is not valid to use an implicit data type e.g. just `signed` when
`parameter` was omitted, add regression tests to check for this as well.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-11 11:09:59 +01:00
Lars-Peter Clausen 89e935c210 Allow omitting `parameter` in module parameter port list
SystemVerilog allows to completely omit the `parameter` keyword in a
module parameter port list. This is described in section 6.20.1 ("Parameter
declaration syntax") of the LRM (1800-2017).

E.g.

```
module a #(X = 10) ...
module b #(int Y = 20) ...
```

It also allows to redefine the parameter type without having to have a
parameter or localparam before the type.

E.g.

```
module a #(parameter int A = 1, real B = 2.0) ...
module b #(int X = 3, real Y = 4.0) ...
```

Extend the parser to support this.

Note that it is not possible to declare a parameter with an implicit data
type this way.

E.g. the following is not legal SystemVerilog
```
module a #([3:0] A = 1) ...
module b #(int X = 2, signed Y = 3.0) ...
```

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-11 10:57:46 +01:00
Lars-Peter Clausen 618959d147 Add helper function to emit error when SystemVerilog is requried
When encountering a construct that requires SystemVerilog in most cases an
error message is generated when SystemVerilog is not enabled and parsing
simply continues.

Factor the checking and generating of the error message into a helper
function. This slightly reduces boiler plate code and gives consistent
error messages.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-11 10:46:02 +01:00
Stephen Williams 771d02bee1
Merge pull request #607 from larsclausen/sv-parameter-in-generate
Allow parameter in generate blocks for SystemVerilog
2022-02-10 17:16:22 -08:00
Stephen Williams bb36a16704
Merge pull request #604 from larsclausen/parser-end-label-unnamed
Let the parser recover from end label on unnamed block
2022-02-10 17:14:42 -08:00
Stephen Williams a7a154047a
Merge pull request #605 from larsclausen/class-scoped-base
Support scoped base class type
2022-02-10 17:12:27 -08:00
Lars-Peter Clausen 47e6c71113 Add regression tests for parameters in generate blocks
In Verilog a parameter in a generate block is invalid and should
result in a compile error.

In SystemVerilog on the other hand it is valid, but it is equivalent
to a localparam and can't be overridden.

Add regression tests that check for this.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-10 11:37:38 +01:00
Lars-Peter Clausen 9a94e6b43b Allow `parameter` in generate blocks for SystemVerilog
SystemVerilog allows to use the `parameter` keyword in a generate
block. If used in a generate block it behaves like a `localparam` and
cannot be overridden.

This is described in section 27.2 ("Generate constructs - Overview") of the
LRM (1800-2017).

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-10 11:37:38 +01:00
Lars-Peter Clausen 9f5ad34e35 Track whether a parameter is overridable
Parameters declared in certain scopes behave like local parameters and can
not be overridden. Rather than making those parameters a localparam track
whether a parameter can be overridden.

This allows to generate better error messages when trying to override the
parameter.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-10 11:37:34 +01:00
Lars-Peter Clausen 1207e908b1 PScope: Keep parameter and localparams in the same list
During parsing parameters and localparams are kept in a separate list only
to be collected into the same list during elaboration.

Store them in the same list during parsing as well, this allows to remove
some duplicated code.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-10 11:07:03 +01:00
Lars-Peter Clausen 42dd8a0703 Add regression test for class with scoped base class type
Check that classes with a scoped base class type get elaborated correctly.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-06 21:50:51 +01:00
Lars-Peter Clausen 6a61144937 Support scoped base class type
A base class can be referenced by scope. E.g. if the base class is in a
package.

```
package P;
  class B;
  endclass
endpackage

module test;
  class C extends P::B;
  endlcass
endmodule
```

To support this let the parser accept a scope identifier for the base
class.

A small change is also necessary to how the base class lockup is done
during elaboration. At the moment the code will search for the base class
by name in the current scope. This doesn't work with scoped identifiers.

But we already have a reference to the base class data type, so we don't
have to search for it by name.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-06 21:37:46 +01:00
Lars-Peter Clausen 4bebcad6fd Add common parser rule for (scoped) type identifier
There are multiple places in the grammar where either a type identifier or
scoped type identifier is accepted.

Factor this into a common parser rule. This removes some duplicated code.
But it will also be required to avoid reduce-reduce conflicts for future
grammar extensions, e.g. to support type parameters.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-06 21:37:46 +01:00
Lars-Peter Clausen 305a1a9262 Add regression test for end labels on unnamed blocks
An end label on an unnamed block should generate an error. Add a regression
test to check this.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-06 21:33:36 +01:00
Lars-Peter Clausen e950e2d0d3 Let the parser recover from end label on unnamed block
Currently when encountering an end label on a unnamed block
a 'syntax error' will be generated and the parser will give up.

Slightly refactor the parser so that this case is detected, a more specific
error message is generated and the parser can recover and continue.

This also slightly reduces the parser since it allows to merge the almost
identical rules for handling named and unnamed blocks.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-06 21:33:36 +01:00
Lars-Peter Clausen 7e18eba848 Add helper function to check end label
Most named constructs support a end label in SystemVerilog. The handling of
this end label is always the same.

 * Generate an error if the end label does not match the name of the block
 * Generate an error if not in SystemVerilog mode
 * Delete the end label

Factor this into a common helper function. This reduces code size a bit and
results in consistent error messages.

The latter requires refreshing of some gold files to match the slightly
different error messages.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-06 21:33:36 +01:00
Stephen Williams bc0fc4ab89
Merge pull request #603 from larsclausen/unnamed-fork-variable-decl
Allow unnamed parallel block with only variable declarations
2022-02-06 09:49:11 -08:00
Lars-Peter Clausen 4a9200f5f2 Add regression test for variable declarations in unnamed forks
SystemVerilog supports variable declarations in unnamed forks, while
Verilog does not.

Add a regression test that checks for this.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-06 14:13:17 +01:00
Lars-Peter Clausen f2c1e21ad3 Allow unnamed parallel block with only variable declarations
While it is not a particular useful construct it is legal to have a
parallel block with just variable declarations and no statements. E.g.

```
fork
  int x;
join
```

At the moment there is a special rule for completely empty parallel
blocks. Remove that rule and change the statement_or_null_list in the
fork/join parser section to a statement_or_null_list_opt. This way it
covers both completely empty parallel blocks as well as parallel blocks
with only variable declarations.

Note that this already works as expected for named parallel blocks.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-06 14:13:02 +01:00
Stephen Williams 922a2e0e13
Merge pull request #601 from steveicarus/verireal-dead-code
Remove some dead code
2022-02-03 07:23:52 -08:00
Stephen Williams 8b4abd3228 Remove some dead code
This dead code was discovered by gcov testing.
2022-02-03 07:04:39 -08:00
Stephen Williams 04bff70a17
Merge pull request #600 from steveicarus/fix-localparam_implicit-tests
Fix localparam_implicit.v test
2022-02-03 07:03:57 -08:00
Stephen Williams 687abbd030 Fix localparam_implicit.v test
The localparam_implicit.v test was broken by a recent commit. Fix the
test, since the commit is correct and the test really is broken.
2022-02-01 19:15:01 -08:00
Stephen Williams 6db40d9f14
Merge pull request #599 from larsclausen/parameter-invalid-error
Report error when trying to override non-existing parameter
2022-02-01 17:39:44 -08:00
Stephen Williams dd0a4c9a5e
Merge pull request #598 from larsclausen/fix-implicit-localparam
Handle implicit `localparam`
2022-02-01 15:24:57 -08:00
Lars-Peter Clausen 880f4927bf Add regression test for invalid parameter overrides
Check that invalid parameter overrides generate an error.

There are some cases that are not handled correctly today. The test will be
updated once they are addressed.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-01 23:17:47 +01:00
Lars-Peter Clausen 0ab1ed916f Report error when trying to override non-existing parameter
Overriding a parameter that does not exist will only generate a warning at
the moment. This can hide programming mistakes such as an typo in a
parameter override.

There is nothing in the LRMs to support that this should only be warning,
so elevate this to an error. This is consistent with how an error is
generated when trying to reference a non-existing port or variable.

The generated error message differentiates between whether the parameter
does not exist at all, or whether it is a localparam.

There are two regression tests that rely on that only a warning is
generated, these have been updated to expect an error.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-01 22:50:21 +01:00
Lars-Peter Clausen f25d7a74bc Add regression test for implicit `localparam`
Check that all parameters in a parameter port list after a `localparam` get
elaborated as localparams, until the next `parameter`.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-31 10:09:45 +01:00
Lars-Peter Clausen 1549fd4332 Handle implicit `localparam`
When declaring module parameters in the ANSI style parameter list it is
possible to omit the `parameter` or `localparam` keyword. In this case
whether the parameter is local or non-local is inherited from the previous
parameter.

In the current implementation when the type of the parameter is not
specified it will always use parameter. E.g. the following will create a
localparam A and a parameter B, while it should be localparam A and B.

```
module #(localparam A = 1, B = 2);
```

Fix this by remembering whether the previous entry was a parameter or
localparam. This is similar to how the parameter data type is already
remembered.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-31 09:36:38 +01:00
Lars-Peter Clausen 0b30894f81 Support parameter value ranges on localparams
Verilog-AMS defines parameter value ranges which can restrict the value
that can be assigned to a parameter. It defines this for both `parameter`
and `localparam`. Currently it is only implemented for `parameter`. Support
it for `localparam` as well for consistency.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-27 18:51:13 +01:00
Lars-Peter Clausen ac040dae42 Consolidate parameter and localparam declaration handling
The code for handling parameter and localparameter declarations is very
similar. Consolidate this into a single helper function.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-27 18:51:13 +01:00
Stephen Williams 30c169026e
Merge pull request #596 from larsclausen/struct-field-signing
Handle signedness of struct members
2022-01-27 09:01:48 -08:00
Lars-Peter Clausen 1c0955178d Add regression test for struct member signedness
Check that when using a struct member in an expression its signedness is
handled correctly.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-27 10:54:41 +01:00
Lars-Peter Clausen 662e82c013 Handle signedness of struct members
struct members are currently always treated as unsigned. This leads to
incorrect behavior in contexts where the sign makes a difference. E.g.

```
struct packed {
  int x;
} s;

s.x = -1;
if (s.x > 0) $display("FAILED");
```

Query the signedness of the struct member form the type of the member.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-27 10:53:19 +01:00
Stephen Williams 2477f79f52
Merge pull request #595 from larsclausen/struct-enum-line-info
Set correct line info for enums and structs
2022-01-23 17:03:01 -08:00
Lars-Peter Clausen fa643cbfe1 Add regression tests for enum and struct line info
Check that when an error message for a enum or struct data type is
generated it points to the location of the declaration of the type.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-23 20:09:05 +01:00
Lars-Peter Clausen 057cd700fe netenum_t: Fix line info
enum_type_t inherits from LineInfo, but also has a LineInfo field called
`li`.

When a enum_type_t is created the LineInfo of the object itself is set to
the location where the type is declared.

The `li` field gets set when a signal of the enum_type_t is created to the
location where the signal is created. The `li` field is then used when
elaborating a netenum_t to set the line information on the netenum_t.

This works fine when the enum is directly used to declare a signal, since
the location of the type and signal declaration are the same and there is
only one signal of that type.

But when using a typedef and declaring multiple signals with the same type
the `li` field will be repeatedly set and eventually point to the last
signal declaration of that type.

On the other hand when using or declaring an enum as part of an aggregate
type such as an array, struct or class the line info will never be
set.

This can cause misleading error messages. E.g.

```
typedef enum {
  A, B = A
} e_t;

struct packed {
  e_t e;
} s;
```

will generate

```
:0: error: Enumeration name B and A have the same value: 32'sd0
```

To fix this use the LineInfo that was assigned to the enum_type_t itself
when it was declared and remove the `li` field.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-23 20:07:00 +01:00
Lars-Peter Clausen ac815a6118 netstruct_t: Set line info
netstruct_t inherits from LineInfo. But the file and line information is
never set leading to messages like

  :0: error: Member r of packed struct/union must be packed.

When elaborating a netstruct_t set the line info from the struct_type_t it
is elaborated from. This makes sure that error messages for the struct type
have the proper file and line information when printed.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-23 19:47:46 +01:00
Stephen Williams 32f01f87a6
Merge pull request #594 from larsclausen/block-with-only-var-decl
Allow unnamed begin/end block with only variable declarations
2022-01-23 10:41:48 -08:00
Stephen Williams 8502f3bd85
Merge pull request #593 from larsclausen/enum-elab-order
Elaborate enums in the order they have been declared
2022-01-23 10:41:01 -08:00
Lars-Peter Clausen 67b29ab5d4 Add a regression test to check enum elaboration order
Test that enums are elaborated in declaration order and a enum declaration
can reference a item of an enum that was declared before it.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-23 19:08:22 +01:00
Lars-Peter Clausen 30b70923b5 Add regression test for variable declarations in unnamed blocks
SystemVerilog supports variable declarations in unnamed blocks, while
Verilog does not.

Add a regression test that checks for this.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-23 18:52:35 +01:00
Lars-Peter Clausen ad6131b1c4 Allow unnamed begin/end block with only variable declarations
While it is not a particular useful construct it is legal to have a
begin/end block with just variable declarations and no statements. E.g.

```
begin
  int x;
end
```

At the moment there is a special rule for completely empty begin/end
blocks. Remove that rule and change the statement_or_null_list in the
begin/end block parser section to a statement_or_null_list_opt. This way it
covers both completely empty blocks as well as blocks with only variable
declarations.

Note that this already works as expected for named begin/end blocks.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-22 13:28:27 +01:00
Lars-Peter Clausen e75ad281fc Elaborate enums in the order they have been declared
enums for a scope are stored in a std::set. This means when iterating over
the enums during elaboration it is possible that they are elaborated in a
different order than they have been declared in. This causes problems if
one enum references items of the other enum. E.g.

```
enum {
  A
} a;

enum {
  B = A
} b;
```

In the current implementation whether this works or not depends on the
pointer values of the enum_type_t for `a` and `b`, which can change between
environments.

To make sure that enums are elaborated in the same order use a std::vector
instead of a std::set.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-22 12:24:05 +01:00