Commit Graph

9421 Commits

Author SHA1 Message Date
Lars-Peter Clausen 20d82bbdcb Simplify class end label parser rule
The current class end label parser rule gets the data type from the
TYPE_IDENTIFIER, casts that to a class_type_t and gets the name from that.
This code was written when the TYPE_IDENTIFIER only provided the data type.

But these days it provides both the data type and the name. Simplify the
code to get the name directly from the TYPE_IDENTIIFER.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-15 12:32:02 +02:00
Lars-Peter Clausen 0a2cbcb4b7 Remove pre C++11 compatibility code for unique_ptr
There is compatibility code that defines unique_ptr  as auto_ptr if the C++
version is before C++11.

But there are already other parts of the codebase that do require C++11 and
the minimum required version to build the project is C++11. So remove the
compat code as it is no longer needed.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-15 12:32:02 +02:00
Lars-Peter Clausen 4522709c06 Use C++11 for building the project
There are C++11 constructs in Icarus at the moment and the plan is to
retain C++11 compatibility until more modern versions are widely available
in the default installation of systems.

Pass `-std=c++11` to the compile to enforce building with C++11, this will
make sure that neither an older nor a newer version is used. E.g. compilers
on some platforms still default to an earlier version of C++11.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-15 12:32:02 +02:00
Stephen Williams 10a39e59a1
Merge pull request #781 from larsclausen/darray-type-compat
Improve type compatibility checking for dynamic arrays and queues
2022-10-14 08:15:50 -07:00
Stephen Williams b0c262de80
Merge pull request #780 from larsclausen/nb-auto-struct-fail
Prevent non-blocking writes to fields of automatic structs
2022-10-14 08:13:53 -07:00
Stephen Williams 8bbddfb69f
Merge pull request #779 from larsclausen/method-call-default
Handle default argument values for class function method calls
2022-10-14 08:11:45 -07:00
Stephen Williams 90538e4193
Merge pull request #778 from larsclausen/ps-identifier
Improve parsing of package scoped identifiers
2022-10-14 08:10:24 -07:00
Lars-Peter Clausen 7896349380 Add regression tests for dynamic array/queue type compatibility
Check for various dynamic array and queue types that their type
compatibility is handled correctly.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-08 14:01:41 +02:00
Lars-Peter Clausen e897e3ab5f Avoid confusing type compatibility error messages
Icarus allows to pass a value of the element type as an argument to the
dynamic new operator. To allow this the type compatibility check for
dynamic arrays allows both the dynamic array type itself and also the
element type.

This currently leads to a confusing error message if neither type matches.
The error message will say that the passed value is not compatible with the
element type. E.g.

```
  real d1[];
  int d2[];
  d1 = d2;
```

results in

```
error: the type of the variable 'd2' doesn't match the context type.
     : variable type=dynamic array of netvector_t:bool signed[31:0]
     : context type=real
```

This is slightly confusing. Change the way the error message is reported so
that the context type is the type of the dynamic array and not the element.
With the change the above results in

```
error: the type of the variable 'd2' doesn't match the context type.
     : variable type=dynamic array of netvector_t:bool signed[31:0]
     : context type=dynamic array of real
```

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-08 14:01:41 +02:00
Lars-Peter Clausen 5fa1aecd4f Improve type compatibility checking for dynamic arrays and queues
SystemVerilog defines different levels of type compatibility.
 * Matching
 * Equivalent
 * Assignment compatible
 * Cast compatible

At the moment the `nettype_t` has only one type compatibility test. It is
used to check assignment compatibility when assigning to a dynamic array,
queue or class.

The current implementation rejects a few cases that should allowed and
allows a few cases that should be rejected.

Dynamic arrays and queues are assignment compatible if their element types
are compatible. And two packed types are equivalent if they are both
2-state or 4-state, both signed or unsigned and have the same packed with.

In the current implementation the sign is not considered and instead of
checking if the packed width is the same it checks that the dimensions are
identical.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-08 14:01:41 +02:00
Lars-Peter Clausen d4765e3354 Don't implement `packed_width()` for dynamic array types
The `netdarray_t` type implements the `packed_width()` method by returning
the packed width of the element type. It is the only non-packed type that
implements the method.

This triggers an assert in the vlog95 backend for tasks with dynamic array
typed parameters. And while the vlog95 backend does not support dynamic
array types it should not result in a crash, just an error message.

The only place that relies on the behavior that the packed width of the
element type is returned is in the vvp backend where variable declarations
are generated. Update that code to query the packed width of the element
type instead and then remove the `packed_width()` implementation for the
`netdarray_t` type.

This fixes the assert in the vlog95 backend. But it is also nicer from an
architectural perspective as this brings the type in line with the other
types in terms of behavior.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-08 13:42:45 +02:00
Lars-Peter Clausen f831d7d76f Add `ivl_type_packed_width()` API
The C++ API for `ivl_type_t` has a method to query the total width of a
packed type. This is currently not exported to the C API and the tgt-vvp
backend implements similar functionality by querying the individual
dimensions of a type.

Export the `packed_width()` method to the C API. This allows to remove the
custom implementation from the tgt-vvp backend.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-08 13:42:40 +02:00
Lars-Peter Clausen 070fc2aedc Add regression tests for invalid non-blocking writes to SV constructs
Current regression tests only cover checking for invalid non-blocking
writes to constructs that are valid in Verilog. Add two tests to
additionally cover some SystemVerilog constructs.

 * Non-blocking writes to members of a struct typed variable with automatic
   lifetime
 * Non-blocking writes to class typed variables with automatic lifetime

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-06 10:51:49 +02:00
Lars-Peter Clausen e7d3e7440d Prevent non-blocking writes to fields of automatic structs
The `PEIdent::has_aa_term()` method still uses the old `symbol_search()`
and will fail to find the variable if part of the identifier path is a
member select of a variable.

As a result such writes to fields of automatic structs can be classified as
static and it is possible to do non-blocking assignments to them. E.g.

```
task automatic t;
  struct packed {
    logic x;
  } s;
  s <= ...; // This fails
  s.x <= ...; // This works, but should fail
endtask
```

Switch to the new symbol search to make sure this case is handled
correctly. The new symbol search will correctly handle identifier paths
that have a trailing item after the variable, while the old symbol search
will always return an error in that case.

Note that while it is not allowed to do a non-blocking write to a class
object automatic variable, it is allowed to do a non-blocking write to a
property of a class object that is stored in an automatic variable, as the
non-blocking write is supposed to capture a reference to the object and not
reference the variable. E.g.

```
class C;
  int x;
endclass

task automatic t;
  C c;
  c <= ...; // Not allowed
  c.x <= ...; // Allowed
endtask
```

Non-blocking access to class properties is not yet support in
Icarus in general, but the error handling for that needs to be done
somewhere else.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-06 10:25:48 +02:00
Lars-Peter Clausen 0aef9326ca Add regression test for class method argument defaults
Check that default values for class methods are handled correctly and it is
possible to omit any argument. Check it for both functions and tasks.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-05 08:49:25 +02:00
Lars-Peter Clausen 46951c778e Handle default argument values for class function method calls
For class function method calls currently only as many arguments as have
been supplied are elaborated. Any trailing arguments that might have default
values are skipped. This will trigger an assertion later on in the vvp code
generator backend.

Fix this by making sure that all arguments of the function are evaluated.

Note that this already works correctly for class task method calls.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-05 08:49:25 +02:00
Lars-Peter Clausen 159345ca96 Add regression tests for package scope identifiers
Check that it is possible to reference a package scoped identifier that has
the same name as a local identifier, but is a different kind of identifier.

 * A variable or function identifier from a package scope if it is a
   type identifier in the current scope
 * A type identifier from a package scope if it is a non-type identifier
   in the current scope

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-04 11:13:37 +02:00
Lars-Peter Clausen 8d7e7b6283 Improve parsing of package scoped identifiers
In order to avoid conflicts in the grammar the lexer distinguishes between
identifiers and type identifiers. To correctly classify an identifier the
lexer needs to know in which scope a token is parsed. E.g. when the parser
encounters a package scope operator it calls `lex_in_package_scope()` to tell
the lexer which scope the following identifier should be classified in.

Currently the `lex_in_package_scope()` is only used when a type identifiers
is parsed, but on for normal identifiers. As a result it is not possible to
reference variables or function from a package scope that have the same
name as a type identifier in the current scope. E.g.

```
package P;
  int T;
endpackage

module test;
  typedef int T;
  initial $display(P::T);
endmodule
```

Another problem is that in expressions both type identifiers and signal
identifiers can be referenced. As a result there are two rules in an
expression that can be reduced

  * <PACKAGE_TYPE> :: <TYPE_IDENTIFIER>
  * <PACKAGE_TYPE> :: <IDENTIFIER>

The way the rules are formulated at the moment the parser has to use token
lookahead to decide which rule to follow before it can reduce the package
scope operator. As a result the lexer detects the token before
lex_in_package_scope() is called and the identifier does not get evaluated
in the package scope, but in the current scope. Which can cause the
identifier to be misclassified. E.g.

```
package P;
  typedef int T;
  shortint X;
endpackage

module test;
   typedef byte X;
   initial $display($bits(P::T));
   initial $display($bits(P::X));
endmodule
```

Here `P::T` gets classified as a signal identifier and `P::X` gets
classified as a type identifier.

To solve this introduce a common rule for the package scope operator. Using
the same rule everywhere allows the parser to reduce it unconditionally
without using lookahead.

Note that there are additional problems with resolving the type of a scoped
type identifiers in expressions, but this is a prerequisite to solve that.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-04 10:42:56 +02:00
Stephen Williams 3b711ed785
Merge pull request #777 from larsclausen/remove-elab-anet
Remove unused elab_anet.cc
2022-10-03 19:44:03 -07:00
Stephen Williams 4f1dbee4ee
Merge pull request #775 from larsclausen/ps-function-call
Allow package scoped functions to be called without arguments
2022-10-03 19:43:26 -07:00
Stephen Williams b83fc0ac59
Merge pull request #774 from larsclausen/darray-copy-empty
vvp: Handle copying of empty dynamic array and queue
2022-10-03 19:42:13 -07:00
Stephen Williams 463f18a03f
Merge pull request #773 from larsclausen/function-return-class
Support class objects as function return values
2022-10-03 19:40:42 -07:00
Stephen Williams 7c52d239db
Merge pull request #772 from larsclausen/uarray-port-typedef
Correctly handle unpacked array typedefs for ports
2022-10-03 19:39:01 -07:00
Lars-Peter Clausen 4c0b06329f Add regression test for nested unpacked arrays
Check that it is possible to declare an unpacked array type with an
unpacked array type as the base type.

Also check that it is possible to declare an signal with an unpacked array
dimension with an unpacked array base type.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-01 13:51:55 +02:00
Lars-Peter Clausen b19a6a7518 Support nested unpacked array types
It is currently possible to declare an unpacked array with multiple
dimensions. But trying to declare an unpacked array that has another
unpacked array as a base type will result in undefined behavior. E.g.

```
typedef int T1[1:0];
typedef T1 T2[3:0];
T2 x[7:0];
```

To support this recursively unwrap the data type and add the unpacked
dimensions to the signal until the base type no longer is a unpacked array
type.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-01 13:51:55 +02:00
Lars-Peter Clausen bcc0730b6b Add regression test for module port with array typedef
Check that for a module port with an array type identifier the type is
elaborated in the right scope.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-01 13:51:51 +02:00
Lars-Peter Clausen 69b108f661 Remove unused elab_anet.cc
elab_anet.cc was removed from the build in commit 4a8be3db9c ("Implement
bi-directional part selects."). But the file itself was never removed,
remove it now.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-01 12:06:57 +02:00
Lars-Peter Clausen 6fe3e52085 Add regression tests for package scoped function calls
Check that package scope function calls work with and without arguments as
well as empty positional arguments.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-09-20 20:44:27 +02:00
Lars-Peter Clausen fb8681a376 Allow package scoped functions to be called without arguments
The parser currently only allows package scoped functions to be called if
there is at least one argument. But package scoped functions are the same
as normal functions and it is allowed to call them with no arguments. It is
even possible to pass no value for a positional argument, if the positional
argument has a default value.

Update the parser to handle this.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-09-20 20:41:23 +02:00
Lars-Peter Clausen f9aadc13b5 Fix memory leaks when parsing function calls
For function calls when calling the PECallFunction() constructor a copy is
made of the argument expression list. This means the original list should
be deleted within the rule.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-09-20 20:08:24 +02:00
Lars-Peter Clausen 2385b32cb3 Correctly handle unpacked array typedefs for ports
If the type of a port is an array type it currently always gets evaluated
in the scope where the port is declared.

But if the type is a typedef it might be declared in a different scope and
must be evaluated in that scope. E.g. the following will declare an array
port with 10 entries and an element type of a 5 bit vector, while it should
declare one with 4 entries and an element type of a 2 bit vector.

```
localparam A = 2;
localparam B = 4;
typedef [A-1:0] T[B];

module test (
  T x
);

localparam A = 5;
localparam B = 10;

endmodule
```

This is in part due to array types being given special handling. This was
necessary before because each base type required slightly different
handling and so the base type had to be extracted from the array type.

This has now been consolidated and all data types are treated the same.
The only exception is the vector type which still needs special handling to
support separate definition of port direction and type.

As a result it is possible to remove the special handling of the array
type. This solves the problem of evaluating the type in the wrong scope.

Some special handling needs to be retained though to be able to
differentiate between array dimensions that are part of a type and array
dimensions that are part of port declaration. This is again necessary to
correctly support separate definition of port direction and type. E.g. in
the example below port `x` and `y` get treated slightly differently, even
though the resulting signals will be identical.

```
typedef logic [7:0] T[1:0];
...
input T x;
input [7:0] y[1:0];
```

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-09-20 12:25:14 +02:00
Lars-Peter Clausen 72e59fc626 Add regression tests for copying empty dynamic array and queue
Check that it is possible to copy empty dynamic arrays and queues.

If the target is a dynamic arrays there are two ways of copying. Through
direct assignment as well as the array new operator.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-09-19 18:47:22 +02:00
Lars-Peter Clausen 567df9c29a vvp: Handle copying of empty dynamic array and queue
An empty dynamic array or queue is represented by a null object in vvp.

Currently when trying to copy such an object results in undefined behavior
in various places. Either hitting an assert or causing a nullptr
dereference.

Make sure that the empty object is handled correctly by treating it as a
special case.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-09-19 18:47:18 +02:00
Lars-Peter Clausen d4c662c6a1 Add regression tests for returning class objects from functions
Check that returning class objects from functions is supported.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-09-19 18:20:16 +02:00
Lars-Peter Clausen 1fd968773e Support class objects as function return values
There is nothing special to do for return class objects from a function.
They can be handled the same as other objects such as dynamic arrays and
queues.

But there currently is an assert in the code that handles function calls
assigned to objects that will trigger if the target type is not an queue or
dynamic array.

This is because Icarus allows dynamic arrays to be initialized with a
single value and for that the element with of the dynamic array needs to be
known, so the single value expression can be evaluated correctly.

Since classes can not be initialized from vector expressions the width does
not matter in that case.

Update the code to only query the element width if the target type is an
dynamic array or queue and pass a placeholder value of 1 for the width
otherwise.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-09-19 18:20:16 +02:00
Stephen Williams fd69d4e09c
Merge pull request #770 from larsclausen/vlog95-localparam
tgt-vlog95: Consider scopes with only localparams as unique
2022-09-18 09:04:39 -07:00
Lars-Peter Clausen 6ea7763c31 tgt-vlog95: Consider scopes with only localparams as unique
For modules with parameters the vlog95 backend generates one module
declaration for each module instance. This is done so that different values
for the module parameters can be supported.

Local parameters are guaranteed to have the same value for all module
instances though. Add support for detecting the case that all module
parameters are local parameters and in that case only create one shared
module declaration. This is similar to what the vhdl backend does.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-09-18 17:33:20 +02:00
Lars-Peter Clausen a2aa659717 Consider non-overridable parameters as local for the backend
We differentiate between local and non-overridable parameters
in the frontend to be able to generate better error messages.

For the backend they should both be considered local parameters.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-09-18 17:33:20 +02:00
Stephen Williams b0b0b84815
Merge pull request #771 from larsclausen/macos-runner-update
ci: Upgrade macOS runner
2022-09-18 08:29:20 -07:00
Stephen Williams 0d180ae465
Merge pull request #769 from larsclausen/struct-member-unpacked-array
Handle unpacked dimensions for struct and union members
2022-09-18 08:27:41 -07:00
Stephen Williams 8abb59022b
Merge pull request #768 from larsclausen/parser-type-agnostic
Make the parser mostly data type agnostic
2022-09-18 08:25:39 -07:00
Lars-Peter Clausen d6912fb504 ci: Upgrade macOS runner
Github had deprecated MacOS 10.15 runner[1] and it has now been removed and
the corresponding test always fails. Similar to the Windows runner use the
`latest` version to auto-upgrade the environment to a supported version.

[1] https://github.blog/changelog/2022-07-20-github-actions-the-macos-10-15-actions-runner-image-is-being-deprecated-and-will-be-removed-by-8-30-22/

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-09-16 17:37:01 +02:00
Lars-Peter Clausen cff24f77b4 Add regression tests for packed struct/union with unpacked array members
Check that a packed struct or union with an unpacked array, dynamic array
or queue as a member is detected as an error.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-09-15 12:53:29 +02:00
Lars-Peter Clausen 832917008c Handle unpacked dimensions for struct and union members
Unpacked dimensions for struct or union members are currently silently
discarded. E.g.

```
struct packed { int x[2]; } s;
```

will elaborate successfully as a struct with a non-array int typed field.

This should instead elaborate to an unpacked array of ints typed field. And
subsequently, since unpacked arrays are not allowed in a packed struct or
union, result in an error instead.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-09-15 12:53:29 +02:00
Lars-Peter Clausen e799a09605 data_type_t: Remove figure_packed_base_type() method
The figure_packed_base_type() method can be used to check whether a type is
2-state or 4-state at parse time. The parser no longer cares about the
specific type of a data type. The figure_packed_base_type() function is
no longer used, so remove it.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-09-15 10:07:10 +02:00
Lars-Peter Clausen d6337a5bc5 parray_type_t: Check if base type is packed after elaboration
Packed arrays are only allowed of packed base types. Currently whether the
base type is packed is checked before elaborating the base type.

This works as long as the actual type is known before elaboration. But for
example with type parameters the actual type is only known after
elaboration. In order to be able to support type parameters move the check
for whether the type is packed after elaboration.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-09-15 10:06:43 +02:00
Lars-Peter Clausen 8f78590bd2 Remove most references to ivl_variable_type_t from the parser
The parser used to have behavior that was dependent on the
`ivl_variable_type_t` of a signal. It also used the `ivl_variable_type_t`
of a signal to decide whether a signal can be re-declared as part of a
non-ANSI port declaration.

Neither of these is done anymore and most of the reference to
`ivl_variable_type_t` can be removed from the parser. The only thing it is
still needed for is to decide whether a vector type is 4-state or 2-state.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-09-15 09:36:19 +02:00
Lars-Peter Clausen b307da0831 pform_make_task_ports(): Reuse `pform_set_net_range()`
`pform_make_task_ports()` has code very similar to `pform_set_net_range()`.
Use that helper function instead of duplicating the code.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-09-15 09:36:19 +02:00
Lars-Peter Clausen c5ebe35953 pform_module_define_port(): Reuse `pform_set_net_range()`
pform_module_define_port() has code very similar to `pform_set_net_range()`.
Use that helper function instead of duplicating the code.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-09-15 09:36:19 +02:00
Lars-Peter Clausen d3be19081f pform_set_range(): Pass full vector_type_t as argument
Now that pform_set_range() is only used for vector types pass the
vector_type_t as an argument rather than deconstructing the type into range
and signedness.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-09-15 09:36:19 +02:00