Commit Graph

9421 Commits

Author SHA1 Message Date
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
Stephen Williams 9898bffd41
Merge pull request #590 from larsclausen/packed-type-cast
Add support for explicit cast to packed array, packed struct and enum
2022-01-17 12:27:11 -08:00
Lars-Peter Clausen 5fc1976496 Add regression test for explicit cast to packed array and packed struct
These test verify that explicit cast to packed array and packed struct
types are supported and executed correctly.

The tests are based on the test for integer casts. Just the type of the
variables was changed to packed array and packed struct respectively.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-17 20:21:29 +01:00
Lars-Peter Clausen 1858c6a313 Set regression test for explicit enum cast to supported
Update the enum cast test to reflect that enum casts are now supported.

Also add a small check to verify that the right value got assigned to the
enum after the cast.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-17 20:21:28 +01:00
Lars-Peter Clausen 053453c645 Add support for explicit cast to enum
Assigning a value to an enum signal that is not of the same type as the
enum requires an explicit cast.

To support this attach the type of a type cast to the resulting expression.
This allows the assignment elaboration to confirm that value has been
explicitly cast to the right type.

Also handle the case where the value is a constant. In this case create a
NetEConstEnum instead of a NetEConst as the resulting expression.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-17 20:21:28 +01:00
Lars-Peter Clausen 9b7c99b8a8 NetEConstEnum: Remove unused scope_ field
The scope_ field of the NetEConstEnum class is initialized in the
constructor, but never used anywhere again. Remove it.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-17 20:21:28 +01:00
Lars-Peter Clausen 25dae60bb6 Add support for explicit cast to packed struct and packed array
Currently explicit cast is supported to atom2 and vector types. packed
struct, packed array and enum are not supported.

An explicit cast to packed type works the same for all packed types though.

Add support for handling also packed structs, packed arrays and enums by
make the code more generic and querying the packed base type from the
ivl_type_t.

To correctly handle enums a bit more work is necessary, which will be done
in a follow up patch.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-17 20:21:28 +01:00
Stephen Williams be06e293f6
Merge pull request #587 from steveicarus/ivtests-fail-exit
Rework the regression tests to not use regression_report references
2022-01-16 13:36:09 -08:00
Stephen Williams 7c73ef8fb6 ivtest: Mark as NI tests that are known to fail.
Mark them as NI so that in the fugure they might be turned back
on if they can be made to work. Keep the tests around as reference.

Also, remove reports that are no longer tested in CI. This is because
they are no longer tested by a previous patch that relies on the
change vvp_reg.pl behavior around failed tests.

Remove now obsolete update_msys2_report.pl, and simplify the test.sh
script, since diff commands and Windows specific trickery are no
longer needed.
2022-01-16 13:17:46 -08:00
Stephen Williams d0b9c11d35 ivtest: vvp_reg.pl sets exit status
If there are any failures, return a non-zero exit status so that
invoking scripts can detect that failures happen. This eliminates
the need to use regression report reference outputs, and should
make it easier to merge PRs that add or impact tests.
2022-01-16 11:03:21 -08:00
Stephen Williams f5f07d52b0
Merge pull request #586 from larsclausen/struct-signed
Add  support for signed packed structs/unions
2022-01-16 10:37:44 -08:00
Lars-Peter Clausen e176ce0776 Add regression test for signed struct
Add a test that checks that signing annotations on structs are supported
and that signed structs are properly evaluated as a signed value.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-16 16:16:33 +01:00
Lars-Peter Clausen 09ac7c207e Add support for signed packed structs/unions
packed structs and packed unions as a whole can either be signed or
unsigned. This information is used when it is used as a primary in an
expression, i.e. without accessing any of the members.

Add support for parsing and elaborating signed structs.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-16 16:16:24 +01:00
Stephen Williams f1c543194c
Merge pull request #585 from larsclausen/packed-array-direct-struct-enum
Support direct packed arrays of struct and enums and packed arrays of scoped types
2022-01-15 18:51:11 -08:00
Lars-Peter Clausen 38c4c20cbc Add test for packed arrays of types from other scopes
Extend the array_packed test to check declaring a packed array of a type
from another scope that is addressed via a scoped identifier.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-15 22:26:29 +01:00
Lars-Peter Clausen c670170ac0 Add test for direct packed arrays of struct and enums
It is possible to directly declare a packed array of a struct or enum
without having to create a typedef first.

Add a check to the array_packed test that this is supported and works as
expected.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-15 22:26:29 +01:00
Lars-Peter Clausen 3ca1c129ce Allow packed arrays of scoped types identifiers
Allow scoped identifiers to be used as the base type for packed array
types. Scoped type identifiers can be used the same way as unscoped type
identifiers.

E.g.
```
package p;
  typedef logic [1:0] vector;
endpackage

module test;
  p::vector [1:0] pa;
endmodule
```

is a valid construct.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-15 22:26:29 +01:00
Lars-Peter Clausen ae954e5df7 Support direct packed arrays of structs and enums
It is possible to directly declare a packed array of a struct or enum,
without having to typedef the struct or enum first. E.g.

```
struct packed {
  int x;
} [1:0] pa;
```

Add support to the parser for handling this.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-15 22:26:29 +01:00
Stephen Williams 6222a84d67
Merge pull request #584 from larsclausen/enum-put-in-scope
Put enum type into scope when declaring it
2022-01-15 13:21:50 -08:00
Lars-Peter Clausen d856a35e4d Add regression test for enums declared in structs and classes
These tests check that a enum that is declared in a struct or class are
correctly elaborated and also name collisions with the enum names are
detected.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-15 21:43:01 +01:00
Lars-Peter Clausen 9e6f651e09 Put enum type into scope when declaring it
When creating an enum type it must be added to the scope where it is
declared so it can later be elaborated and the enum and its names can be
referenced in expressions.

In addition the names of the enum must be added to the lexor scope so that
name collisions are detected and can be reported as errors.

This is done with pform_put_enum_type_in_scope() function.

At the moment the function is called from two different places
 * When adding a typedef of a enum type
 * When creating a signal of a enum type

In addition the enum_type_t is added to a class scope `enum_sets` when
declaring a enum property in a class. But this only makes sure that the
enum gets elaborated, its names are not added to the lexor scope.

This works fine for the most part, but breaks for a few corner cases.

E.g. it is possible to declare a enum type as part of the subtype of
another packed type such as structs or packed arrays. E.g.

```
struct packed {
  enum {
    A
  } e;
} s;
```

This is not covered by either of the cases above and neither do the names
of the enum get added to the lexor scope, nor is the enum type elaborated.

Another corner case that is currently not working is declaring a class
property where the type is a typedef of a enum that is declared outside of
the class. In this case the enum is elaborated again inside the class
scope. E.g. the below is supposed to work, but fails with an already
declared symbol error.

```
typedef enum {
  A
} e_t;

class C;
  typedef enum {
    A
  } e1;
  e_t e2;
endclass
```

In addition since for enums declared in classes they are only added to
`enum_sets`, but names are not added to the lexor scope, it is possible to
declare a different symbol in the class scope with the same name.

E.g. the following elaborates fine

```
class C;
  enum {
    A
  } e;
  typedef int A;
endclass
```

To fix this call pform_put_enum_type_in_scope() when the enum_type_t is
created in the parser. This makes sure that it is handled the same
regardless where the type is declared or used.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-01-15 21:24:23 +01:00