Commit Graph

9541 Commits

Author SHA1 Message Date
Stephen Williams 3438078c90
Merge pull request #795 from larsclausen/gh793-add-driver
Insert drivers for undriven nets
2022-12-02 18:03:32 -08:00
Stephen Williams a5a078ae08
Merge pull request #789 from daglem/struct-array-swapped-range
Support for range indexing of arrays with swapped ranges within structs
2022-12-02 18:02:17 -08:00
Jonathan Kimmitt fc2d9372ef Explicitly refer to std::isnan to avoid clash with system standard library 2022-12-02 16:10:36 +00:00
Lars-Peter Clausen 9e37f4382e Add regression test for issue #793
Check that $signed/$unsigned works when being combinatorially assigned with a
delay and the target of the function is a net without any drivers.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-11-29 20:28:03 -08:00
Lars-Peter Clausen d97c1bc6db Insert drivers for undriven nets
Trying to add a drive strength or delay to a undriven net will result in an
assertion. Make sure that a driver is added to undriven nets.

A driver is already added for all NetESignals, which covers most expression that
can produce a raw net rvalue. But there are other ways we can end up with just a
net as the rvalue, e.g.  when applying a sign cast to a net. The following
example triggers the issue

```
wire [7:0] a;
wire [7:0] b = $signed(a);
```

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-11-29 20:28:03 -08:00
Dag Lem 1e3994e1fa Support for range indexing of arrays with swapped ranges within structs
This patch corrects range indexing of members in structs such as:

struct packed {
   bit [0:7] [7:0] a;
   bit [0:15] b;
} bar;
2022-11-15 18:11:18 +01:00
Stephen Williams 74c52d6fa1
Merge pull request #786 from Forty-Bot/ivlpp_segfault_fix
ivlpp: Fix segfault in macro_start_args
2022-10-30 16:00:49 -07:00
Sean Anderson b18d90a2d9 ivlpp: Fix segfault in macro_start_args
macro_start_args truncates def_buf, but does not check to ensure that
someone has allocated def_buf first. This will cause a null pointer
dereference if the first access to def_buf while parsing a file is a
macro invocation. Fix this by avoiding truncating def_buf if it is NULL,
as it is effectively already truncated.

Fixes: 680196953 ("Add support for text macros with arguments.")
Signed-off-by: Sean Anderson <seanga2@gmail.com>
2022-10-30 18:02:40 -04:00
Stephen Williams c2dbf4e483
Merge pull request #785 from larsclausen/type-ref
Improve handling of type identifier references
2022-10-16 20:52:52 -07:00
Stephen Williams 0c8c642022
Merge pull request #784 from larsclausen/class-call-void
Handle calling void function from class method
2022-10-16 20:52:13 -07:00
Stephen Williams 5a98e50db7
Merge pull request #783 from lparkes/master
Add #include <cstdarg> to all source files that use va_list
2022-10-16 20:51:38 -07:00
Martin Whitaker 01a11cce56 Handle C-style comments following a `include directive (issue #782) 2022-10-16 22:03:37 +01:00
Lars-Peter Clausen b9bc06951a Add regression tests for scoped type identifier references
Check that it is possible to have scoped reference to a type identifier in
a package.

 * As part of variable declarations
 * As an argument to a system function
 * As the type in a type cast

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-15 12:32:32 +02:00
Lars-Peter Clausen 998d0c655d Add regression test for chained type definitions
Check that chained type definitions declared in different scopes are
handled correctly.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-15 12:32:32 +02:00
Lars-Peter Clausen 54afdc1e6b Add regression test for module port with vector typedef
Check that for a module port with a vector type identifier the type is
elaborated in the scope where it is declared rather than the scope of the
module port.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-15 12:32:32 +02:00
Lars-Peter Clausen b7fce4a66e Improve handling of type identifier references
Currently when referencing a typedef this gets replaced with the
`data_type_t` that the typedef points to. This works for most cases, but
there are some corner cases where it breaks down.

E.g. it is possible to have a scoped type identifier which references a
type defined in a package. For such type identifiers, only the data_type_t
itself is remembered, but not the package scope. This will cause the type
identifier to be elaborated in the wrong scope.

Furthermore type identifiers of vector types used for module or task port
might not be elaborated in the correct scope.

Introduce a new `typeref_t` which has `data_type_t` as a base type and can
be used as the data type for a signal. A new instance of a `typeref_t` is
created when referencing a type identifier. The `typeref_t` remembers both
the data type and the scope of the type identifier.

When elaborating the `typeref_t` the elaboration is passed through to the
referenced `data_type_t`. But special care is taken to lookup the right
scope first.

With the new approach also typedefs of typedefs are supported. This
previously did not work because chained typedefs all reference the same
`data_type_t`, but each typedef sets the `name` field of the `data_type_t`.
So the second typedef overwrites the first typedef and a lookup of the
scope of the first typedef by name will fail as it will return the scope of
the second typedef.

This refactoring also allows to define clear ownership of a data_type_t
instance. This e.g. means that an array type owns its base type and the
base type can be freed when the array type itself is freed. The same is
true for signals and class properties, they now own their data type and the
data type can be freed when the signal or property is freed.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-15 12:32:22 +02:00
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
Lars-Peter Clausen 9107e298a3 Add regression test for calling void functions from class method
Check that it is possible to call a void function from a class method.
Check this for both functions defined in the global scope as well as
functions that are methods of the class or a base class.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-15 00:15:36 +02:00
Lars-Peter Clausen 85edd8bb18 Handle calling void function from class method
Calling a void function (or a regular function and ignoring the result)
from within a class method will currently result in an error unless the
void function itself is a method of the same class.

This is because we add the implicit `this` as an object on which to search
for the function and if we do not find it print an error. Change this to
only print an error if the implicit this was not added and it was a method
call on an object identifier.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-10-15 00:15:20 +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
Lloyd Parkes 31eab5b528 Put back the #include of <iostream> that I accidently removed when
I fixed up a misclick earlier.

It doesn't seem to be needed, but I should the the file as I found it.
2022-10-14 11:38:13 +13:00
Lloyd Parkes 6c975eb89c Add #include <cstdarg> to all source files that use va_list. 2022-10-12 15:31:35 +13: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