Commit Graph

476 Commits

Author SHA1 Message Date
Stephen Williams 7b1fad78c3
Merge pull request #824 from larsclausen/class-lifetime
Fix variable initialization in class methods
2022-12-24 17:33:29 -08:00
Martin Whitaker 6b04d9795a Use consistent capitalisation for compiler parser warning messages. 2022-12-22 10:47:45 +00:00
Martin Whitaker 82aedbc36c Don't automatically add the "warning: " prefix in VLwarn().
One variant did, the other variant didn't. As well as being a trap for
the unwary, this gets in the way of using yywarn/VLwarn for non-fatal
"sorry" messages.
2022-12-22 10:34:56 +00:00
Martin Whitaker a56ccabf7f Use consistent format for compiler parser error messages.
Always prefix with "error: " or "sorry: ". Capitalise the first word
of the main message unless it's a Verilog keyword.
2022-12-22 10:13:26 +00:00
Lars-Peter Clausen 54a4e7ff0b Fix variable initialization in class methods
Up to 1800-2017 the grammar in the LRM allowed an optional lifetime
qualifier for class declarations. Icarus supports this and uses this as the
default lifetime for methods of the class. But the LRM never specified what
this qualifier should do actually actually. Starting with 1800-2023 the
qualifier will be removed from the grammar[1].

Furthermore the LRM states that methods of a class are supposed to have
automatic storage and static storage is forbidden.

This currently works in Icarus for the most part since the liftime attached
to class methods is ignored during elaboration in most places. Where it
does not work is for variable initializers where it results in broken code
being generated and vvp crashes at runtime. E.g.

```
class C;
  task t;
    int x = 10;
  endtask
endclass
```

Keep the optional lifetime qualifier for classes in the grammar for now, to
ensure backwards compatibility in case somebody is actually using it. But
ignore it and print a warning if it is specified.

In addition set the default lifetime for all classes to automatic. This
makes sure that variable initialization in classes works as expected.

[1] https://accellera.mantishub.io/view.php?id=3561

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-12-21 19:28:35 -08:00
Stephen Williams 03f912dc55 Clean up warnings
Clean up warnings that show up on newer compilers. Many of these warnings
are related to obsolete c library features or language features. This does
not clear up warnings in code generated by bison or flex.
2022-12-18 10:18:10 -05:00
Lars-Peter Clausen 79771b17b2 Consolidate functions for task port declaration
With the recent refactorings pform_make_task_ports_vec() and
do_make_task_ports() are now very similar.

Consolidate them into a single function.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-12-11 17:39:34 -08:00
Lars-Peter Clausen 4e69fe1355 Remove ivl_variable_type_t from PWire
The ivl_variable_type_t in PWire is now only used for passing the base type
for vector types to the elaboration stage. But we can query the base the
from the vector_type_t itself. If the there is no data_type_t set for the
PWire the base type will default to IVL_VT_LOGIC.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-12-11 17:08:24 -08:00
Stephen Williams 4ead552203
Merge pull request #805 from larsclausen/sv-type-params
Support type parameters
2022-12-11 16:45:39 -08:00
Lars-Peter Clausen e141aef828 Allow to omit dimensions in foreach loop
SystemVerilog allows to skip dimensions in a foreach loop by not specifying
an identifier name for the dimensions. E.g. the following will iterate over
the first and last dimensions, but skip the middle dimension.

```
int x[1][2][3];
foreach(x[a,,b]) ...
```

Add support for this to the parser as well as elaboration.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-12-11 13:56:48 -08:00
Lars-Peter Clausen 5ef847ea87 Support type parameters
SystemVerilog supports type parameters. These are similar to value
parameters, but they allow to pass a type to a module or similar when
instantiating it.

E.g.

```
module A #(parameter type T = int);
endmodule

module B;
  A #(.T(real)) i_a;
endmodule
```

Add support for handling type parameters.

For the vlog95 and vhdl backends type parameters, similar to typedefs, get
replaced with their actual value. For modules with non-local type
parameters for each module instance a unique module or architecture is
generated with the actual type.

Querying type parameters through VPI is not yet supported.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-12-11 13:50:14 -08:00
Lars-Peter Clausen cdc9629ce7 Add support for forward type declarations
SystemVerilog supports forward type declarations. This allows to declare a
type identifier and use it, e.g. in a signal declaration, before declaring
what the actual type is. The type still needs to be fully defined
eventually in the same scope as its forward type declaration. E.g.

```
typedef T;
T x;
typedef int T;
```

The forward type definition can also contain the kind of the type it is
going to be. E.g struct, union, class, etc. The LRM calls this the basic
type. If the actual type is not of the basic type specified in the forward
type declaration this is an error. E.g.

```
typedef struct T;
typedef int T; // Error, int is not a struct
```

It is legal to have more than one forward type declaration for the same
type name, as long as the basic type is the compatible. It is even legal to
have a forward type declaration after the actual type has already been
declared. E.g.

```
typedef T;
typedef int T;
typedef T;
```

Implement support for forward type definitions as part of the new
typedef_t. The basic type will be attached to the typedef_t.

The compatibility of the basic type for multiple forward type declarations
will be checked in the parser. The compatibility of the basic type to the
actual type will be checked during elaboration, once the actual type is
known.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-12-11 10:19:59 -08:00
Lars-Peter Clausen 2e0d6d5af1 Allow to attach additional information to typedefs
Currently typedefs are just a pointer to a data_type_t.

Currently typedefs are implemented by setting the name field of a
data_type_t when a typedef of the type is declared. This works mostly, but
there are some corner cases that can't be supported.

E.g. a typedef of a typedef does not work as it overwrites the name field
of the same data_type_t multiple times.

Forward typedefs can also not be supported since forward typedefs allow to
reference a type before it has been declared.

There are also some problems with type identifier references from a
higher-level scope if there is a type identifier in the current scope with
the same name, but it is declared after the type identifier has been
referenced. E.g. in the following x should be a vector fo width 8, but it
will be a vector of width 4, because while the right type is used it is
elaborated in the wrong scope.

```
localparam A = 8;
typedef logic [A-1:0] T;
module M;
  localparam A = 4;
  T x;
  typedef int T;
endmodule
```

Furthermore typedefs used for the type of ports are elaborated in the wrong
scope.

To handle these corner case issues introduce a data_type_t for typedefs.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-12-11 10:18:22 -08:00
Lars-Peter Clausen 410c8207ef Support compressed assignment statements for genvar loops
SystemVerilog supports using compressed assignment operators for the genvar
for loop variable update.

Add support for this in a similar way as increment/decrement operators by
transforming the statement to its uncompressed equivalent. E.g. `x += y`
gets transformed to `x = x + y`.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-12-04 14:37:21 -08: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 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 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
Lars-Peter Clausen 6204b78610 Prevent invalid port redeclaration
(System)Verilog allows to declare the port direction separate from the
signal declaration. E.g.

```
output x;
integer x;
```

But this is only allowed if the port declaration
 * does not have an explicit net type
 * does not have an explicit data type
 * is a non-ANSI style declaration

For all other cases of port declarations the signal is considered fully
defined and it is not allowed to have a separate signal declaration.

In addition the declared packed dimensions need to match between the port
and signal declaration.

In the current implementation there are a few cases where this is not
handled correctly.

1) It is possible to declare non-ANSI task ports with the same name over
and over again, if it was declared as a signal before the port.

```
task t;
  string x;
  input logic x;
  output real x;
endtask
```

2) It is possible to re-declare non-ANSI input ports of a module that have
a data type, but no explicit net type.

```
module M;
  input integer x;
  wire integer x;
endmodule
```

3) It is possible to re-declare a ANSI port if it has an implicit data type.

```
module M(output [1:0] x);
  reg [1:0] x;
endmodule
```

4) It is possible to declare a vector signal for a scalar non-ANSI task
port.

```
task t;
input x;
reg [7:0] x;
```

To handle all of these correctly refactor signal declaration and lookup a
bit.

The PWire class that represents a signal already has two flags `port_set_`
and `net_set_`. These flags indicate whether a signal has already been used
in a port or signal declaration. A port declaration that includes an
explicit data type is considered both a port and signal declaration.

Use these flags to decide whether it is possible to extend an existing
declaration. E.g. when creating a port without an explicit data type and a
PWire by that name already exists and the `port_set_` flag is not set
extend the existing PWire. On the other hand if the `port_set_` flag is
already set report an error.

Similar for signals but with the `net_set_` flag.

For port declarations with an explicit data type or ANSI style port
declarations it is always an error if a PWire by that name already exists.

This is for both module and task/function ports.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-09-14 18:55:19 +02:00
Lars-Peter Clausen e15b125da8 Replace svector with std::vector
The custom `svector` class is essentially a subset of `std::vector`. There
is no inherent advantage to using `svector`. Both have the same memory
footprint.

`svector` was designed to be of static size, but there are a few places in
the parser where it has to grow at runtime. Handling this becomes a bit
easier by switching to `std::vector` since it is possible to use its
methods which take care of resizing the vector.

This also allows to remove the unused parameter of the `lgate` struct
constructor, which was only needed for compatibility with `svector`.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-05-15 21:56:48 +02:00
Lars-Peter Clausen dddc41891e lgate: Inherit from LineInfo
The lgate struct has its own fields for tracking file and line number,
while everything else that has this information attached inherits from the
LineInfo class.

Make lgate also inherit from LineInfo for consistency.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-04-24 17:00:46 +02:00
Lars-Peter Clausen 854422a3eb Allow `shortreal` module ports
Currently there is a restriction in the parser that rejects `shortreal`
typed module ports. And while at the moment `shortreal` signals are
implemented as `real` typed signals, which is not standard compliant, there
is nothing special about module ports in this regard.

Note that support for `shortreal` (and `real`) nets is an Icarus extension,
but ports can also be variables, in which case a shortreal port is allowed
by the LRM.

`shortreal` variables and nets are allowed everywhere else. There is no
good reason to not allow them for module ports, so remove the restriction.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-04-21 10:17:50 +02:00
Lars-Peter Clausen 254e9dc094 pform_set_data_type(): Avoid signal look-up by name
The `pform_set_data_type()` function is used to set the data type as well
as attributes on a list of signals. Currently the signals are passed as a
list of signal names and then the function looks up the actual signals from
the names.

Refactor the code to directly pass a list of signals. This will allow to
skip the look-up by name.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-04-18 12:07:16 +02:00
Lars-Peter Clausen 135c664adf pform_set_net_range(): Avoid signal look-up by name
The `pform_set_net_range()` function currently looks up a signal by name.
But in all places where it is called the reference to the signal is already
available.

Refactor the code to pass the signal itself, rather than the signal name, to
`pform_set_net_range()`. This allows to skip the look-up by name.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-04-18 11:19:52 +02:00
Lars-Peter Clausen e815d37c25 pform_make_var_init(): Remove unnecessary signal look-up by name
`pform_make_var_init()` calls `pform_get_wire_in_scope()` but never uses
the result other than checking that the signal exists. But we already know
that the signal exists since we only call `pform_make_var_init()` for a freshly
created signal.

Remove the unnecessary signal look-up by name.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-04-18 11:19:11 +02:00
Stephen Williams 66a5cfe660
Merge pull request #691 from larsclausen/cleanup-pform-makewire
Small cleanups for `pform_makewire()`
2022-04-17 18:38:15 -07:00
Lars-Peter Clausen 52da910313 Move pform_set_reg_idx() into pform_makewire()
`pform_set_reg_idx()` is always called right after `pform_makewire()`. Move
it into the function. This avoids the extra lookup that
`pform_set_reg_idx()` does to get the PWire from the name.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-04-17 09:22:47 +02:00
Lars-Peter Clausen 7aee124cfe pform_makewire(): Remove unused parameters
There are a few parameters for `pform_makewire()` and related functions
that always get passed the same value.

 * port_type is always NetNet::NOT_A_PORT
 * attr is always 0

Remove these parameters.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-04-17 09:22:31 +02:00
Lars-Peter Clausen b2516ead66 Remove unused function `pform_set_param_from_type()`
The `pform_set_param_from_type()` function is not used. The last user was
removed in commit 16646c547c ("Rework parsing of parameter types").

Remove the function itself.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-04-16 15:28:35 +02:00
Lars-Peter Clausen 1bf568d808 Use `real_type_t` as the data type for `real` type signals
Currently a `vector_type_t` with the base type set to `IVL_VT_REAL` is used as
the data type for real type signals. But there is also the `real_type_t` data
type, which is used as the data type for function return types and class
properties.

Move signals also over to using `real_type_t`. This ensures consistent
behavior between all sorts of constructs with a data type, makes sure that
`vector_type_t` is only used for vector types.

It also allows to eventually differentiate between `real` and `shortreal`
at the elaboration stage. Currently this information is discarded by the
parser.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-04-12 19:35:54 +02:00
Lars-Peter Clausen f6042033d0 Correctly handle separate port type declaration for `integer` and `time`
When using non-ANSI style port declarations it is possible to declare the
port direction and the data type for the port in separate statements. E.g.

```
input x;
reg x;
```

When using packed array dimensions they must match for both declarations.
E.g.

```
input [3:0] x;
reg [3:0] x;
```

But this only applies for vector types, i.e. the packed dimension is
explicitly declared. It does not apply to the `integer` and `time` types,
which have an implicit packed dimension.

The current implementation requires that even for `integer` and `time`
types the implicit dimension needs to be explicitly declared in the port
direction. E.g. the following will result in a elaboration error
complaining about a packed dimension mismatch.

```
module test;
  output x;
  integer x;
endmodule
```

Currently the parser creates a vector_type_t for `time` and `integer`. This
means that e.g. `time` and `reg [63:0]` are indistinguishable during
elaboration, even though they require different behavior.

To fix let the atom2_type_t handle `integer` and `time`. Since it no longer
exclusively handles 2-state types, rename it to atom_type_t.

This also fixes a problem with the vlog95 target unit tests. The vlog95
target translates

```
module test(output integer x);
endmodule
```

to

```
module test(x);
  output x;
  integer x;
endmodule
```

which then fails when being elaborated again. There were some regression
tests that were failing because of this that will now pass.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-03-28 10:40:06 +02:00
Lars-Peter Clausen de9e3b791b Correctly handle separate port type declaration for atom2 types
When using non-ANSI style port declarations it is possible to declare the
port direction and the data type for the port in separate statements. E.g.

```
input x;
reg x;
```

When using packed array dimensions they must match for both declarations.
E.g.

```
input [3:0] x;
reg [3:0] x;
```

But this only applies to vector types, i.e. the packed dimension is
explicitly declared. It does not apply to the atom2 types which have an
implicit packed dimension.

The current implementation requires that even for atom2 types the implicit
dimension needs to be explicitly declared in the port direction. E.g. the
following will result in a elaboration error complaining about a packed
dimension mismatch.

```
module test;
  output x;
  byte x;
endmodule
```

Currently atom2_type_t's are deconstructed into base type, range and
signdness in the parser. That data is then passed to the signal
elaboration, which will then construct a netvector_t from it. This makes it
impossible to e.g. differentiate between `bit signed [31:0]` and `int`
during elaboration.

Instead of breaking the data type apart pass it as the data_type_t of the
signal and use the elaborate_type() method in the signal elaboration to
generate the netvector_t.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-03-28 10:23:00 +02:00
Stephen Williams 1de38dde12
Merge pull request #651 from larsclausen/consolidate-pform-set-datatype
Consolidate most pform_set_<type>_data_type() functions
2022-03-20 19:11:49 -07:00
Lars-Peter Clausen a4eb971655 Remove unused parameter from pform_set_net_range()
The `net_type` and `dt` parameter of `pform_set_net_range()` always get
passed the same value, NetNet::NONE and IVL_VT_NO_TYPE respectively. Both
these values are ignore by the function. So these parameters don't do
anything useful, remove them.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-03-16 11:42:53 +01:00
Lars-Peter Clausen aa7e253026 Consolidate most pform_set_<type>_data_type() functions
There are a couple of different functions for the different data types that
are called when the type of a signal is set. But they all effectively do
the same.

Consolidate this code by moving the common code into the main
pform_set_data_type() function.

This allows to remove most of the type specific functions and eliminates
some duplicated code. It ensures consistent and data type independent
behavior at the parser level. Something that will be required to eventually
support type parameters.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-03-16 11:41:27 +01:00
Lars-Peter Clausen 962c0af1b6 Don't set information not needed on enum signals
When creating a PWire for a enum type the signedness as well as whether
the base type is an integer is assigned to the wire.

But this information is never queried again. When creating the netenum_t
this information is directly taken from the enum_type_t.

The signedness and integer information of the PWire is only used when
elaborating a netvector_t.

Removing this makes the pfrom_set_enum() function similar to those for
other types and will allow us to consolidate them in follow up patches.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-03-16 11:09:01 +01:00
Lars-Peter Clausen 53284b95af Allow to declare direction after data type for non-ANSI ports
When using non-ANSI ports (System)Verilog allows to have separate
declarations for the port direction and data type. E.g.

```
input x;
reg x;
```

It is also allowed to first declare the data type and then the port type.
E.g.

```
reg x;
input x;
```

Currently this fails with an error message. Add support for handling this
by allowing to change the port type of a signal from `NOT_A_PORT` to port
direction.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-03-15 11:18:56 +01:00
Lars-Peter Clausen 56f36a96d3 parser: Consistently pass line information as `vlltype`
Currently there is a mix of passing line information either as `struct
vlltype` or as a separate `const char *file` and `unsigned lineno`.

For consistency always use the struct vlltype variant.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-03-12 16:18:31 +01:00
Lars-Peter Clausen f67cdddecf Don't make input `integer` ports variables
In Verilog module input ports can only have a packed dimensions and a
signed flag, but no explicit data type.

In SystemVerilog an explicit data type can be specified for module input
ports. Such a port is a net, regardless of the data type, unless
explicitly made a variable using the `var` keyword.

This works for the most part in the current implementation, but for some
data types such as `reg` and `integer` the input port is turned into a
variable. And since input port's can't be variables in the current
implementation this results in an error.

Fix this by completely removing the `reg_flag` that is used to indicate
that a certain data type is always a variable. There is no such restriction
on data types for SystemVerilog and for Verilog there are already checks in
place that a input port can only have an implicit (or real) data type.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-03-03 10:30:28 +01:00
Lars-Peter Clausen 472598dd74 Report errors for nets with invalid data type
While a variable can have any data type the data type for nets is quite
restricted.

The SystemVerilog LRM section 6.7.1 ("Net declarations with built-in net
types") requires that the data type of a wire is either a 4-state packed or
a unpacked struct or unpacked array of 4-state packed types.

As an extension to this iverilog allows real data type for wires as well as
2-state packed types.

Add a check that reports an error if a net with any other type is declared.

In addition in Verilog a net can not have an explicit data type at all. It
can only have a packed dimension and a signed flag. As an extension to this
Icarus also allows wires to be of `real` data type.

Note that in Verilog mode the data type is checked in the parser since only
the parser knows whether the data type is an implicit type (`input reg
[7:0]` and `input [7:0] x` elaborate the same). But for SystemVerilog the
type is checked during elaboration since due to forward typedefs and type
parameters the type is not necessarily known in the parser.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-03-03 10:30:12 +01:00
Lars-Peter Clausen bbe44deec2 Support all packed types for module ports
Currently module ports only support vectors, atom2, enum and struct packed
types, but not packed arrays.

Generalize the code so that any packed type is supported.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-27 13:28:07 +01:00
Stephen Williams 978717f914
Merge pull request #623 from larsclausen/task-ports-sv
Support SystemVerilog non-ansi task/function port declarations
2022-02-26 09:16:33 -08:00
Lars-Peter Clausen 5f71307ab4 Use data_type_t to pass `string` type information to signal elaboration
For signals that are declared in a block string_type_t is already used to
pass the type information to the signal elaboration.

But for task ports it is passed as IVL_VT_STRING. Switch this over to also
passing the type information as a data_type_t.

This allows to remove the special handling for IVL_VT_STRING in the signal
elaboration.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-25 10:43:28 +01:00
Lars-Peter Clausen b0c386182a Support unpacked array dimensions on non-ansi style task ports
SystemVerilog allows unpacked array dimensions on non-ANSI style task and
function ports.

To support this refactor pform_make_task_ports() to accept a of
pform_port_t, which in addition to the identifier name also allows to
specify per port unpacked dimensions.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-25 10:43:28 +01:00
Lars-Peter Clausen c631ff2483 Support SystemVerilog types for non-ansi task port declarations
Tasks and functions support two types of port declarations. Either ANSI
style, in parenthesis after the task name, or non-ANSI style, as
declaration statements in the task body.

In the current implementation SystemVerilog types are only accept for ANSI
style port declarations, while non-ANSI style only accept Verilog types
(reg, integer, time, real).

Add support for SystemVerilog data types for non-ansi style ports.

This also makes the parsing rules simpler since we can use `data_type` to
match all data types and don't need a explicit rule for each supported data
type.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-25 10:42:56 +01:00
Lars-Peter Clausen d104e28dbf Support non-overridable parameters in classes
SystemVerilog allows `parameter` and `localparam` to declare constants
within a class scope.  E.g.

```SystemVerilog
class C;
localparam A = 10;
endclass
```

In this context both declare a local parameter that can not be overwritten.

Supporting this can be achieved for the most part by adding a parser
sub-rule in class declaration rule. In addition some extra support code is
needed to mark the parameter as non-overridable.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-02-19 13:45:22 +01:00
Stephen Williams cc0a8c8dd2
Merge pull request #618 from larsclausen/signal-decl-consolidation
Consolidate signal declaration
2022-02-18 08:27:52 -08:00
Stephen Williams afaaaed0a4
Merge pull request #617 from larsclausen/generate-invalid
Generate error for invalid declarations within generate block
2022-02-18 08:26:08 -08:00