There are currently two implementations for elaborating unpacked array
types. One that is used when elaborating a signal with an unpacked array
type and one that is used everywhere else using the elaborate_type()
infrastructure.
The elaborate_type() implementation is less complete and for example does
not support bounded queue types.
Consolidate both into a single implementation to reduce duplicated code and
get consistent behavior. This for example makes sure that the maximum queue
size is respected when used as a function return type.
Nested data structures of arrays, dynamic arrays or queues are not yet
supported. In the current implementation when encountering such a type an
assert will be triggered and the application crashes. In the new
implementation an error message will be printed without crashing the
application.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Currently the elaboration function for unpacked array types prints an error
for queues that they are not allowed inside classes. And while this error
gets triggered when declaring a property with a queue type, it also gets
triggered for other places that uses a queue type, e.g. a function return
type. The only exception is signals which uses a different internal code
path when elaborating queue types.
Move the error message, that is class property specific, to the class
property elaboration. This also makes sure that the error messages
references the line where the property is declared and not the line where
the type is declared.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
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>
For classes declared inside a module each module instance creates a new
unique class type. These types are not compatible to each other. This is
necessary since module parameters can change the class implementation.
This is defined in section 6.22 ("Type compatibility") of the LRM (1800-2017).
In the current implementation when a class is elaborated the elaborated
type is stored in the class_type_t so it is possible to look up the
elaborated class type. But this class_type_t is shared among elaborated
class types. As a result when creating multiple instances of a module with
a class definition an internal assert is triggered.
To support multiple module instances with class definitions instead of
storing the elaborated type in the type definition look up the type in the
scope in which the type definition is references.
This is similar to how the same problem is solved for enum types.
For packages we still need to remember the elaborated type otherwise scoped
class type references wont work. Since there is only one instance of a
package this doesn't have the same problem as classes in modules.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
For some data types the value returned by the `elaborate_type()` method is
shared among different signals of that type. E.g. all string or real types
get elaborated to the same ivl_type_s. This means the returned value must
not be modified, otherwise the data type for unrelated signals might get
changed.
To enforce this and protect against accidental breakage make the return
type of the `elaborate_type()` and the related `elaborate_type_raw()`
methods const.
Note that `ivl_type_t` is used for the new return type which is a typedef
for `const ivl_type_s*`.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
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>
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>
When creating a signal of a packed array it is checked that the base-type
of the packed array is a packed type.
But this check is only done if the packed array itself is the type of the
signal. Placing the packed array in a struct or class will elaborate fine,
but then crash during simulation.
E.g.
```
typedef real myreal;
struct packed {
myreal [1:0] p;
} s;
```
Move the check from signal creation to type elaboration, so that it is not
possible to create a packed type with a non-packed base-type.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Trying to elaborate a type with invalid packed dimensions currently results
in a crash. E.g. `typedef logic [] T;`
The issue is in the `elaborate_array_ranges()` function which
does not verify that the range specification is valid.
Replace the `elaborate_array_ranges()` with `evaluate_ranges()`, which does
the same thing, but properly checks the range specification and
reports an error if it is invalid.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
The compiler elaborates types on the fly as they are used. For user-
defined types (typedefs) we must do the elaboration in the scope where
the type was declared, not in the scope where it is used.
As reported on iverilog-devel on 2018-10-12, a dimension size of zero
could case the compiler to go into an infinite loop. Further tests
showed that unsized or queue dimensions entered as packed dimensions
would cause the compiler to crash.
The compilation unit scope is now treated as a specialised form of
package (with an automatically generated name). All items declared
outside a design element are added to the current compilation unit
package. Apart from when searching for a symbol, once we get into
elaboration we can treat these just like any other package.
Changes for "Microsoft Visual Studio Express 2015 RC Web" to first check for a dereferencable iterator so pr1741212.v, and many others, will pass with a DEBUG build.
If elaboration of the msb or lsb expression in the range of a vector
type specification failed (due to an error in the Verilog code being
compiled), an assertion failure was being triggered when the compiler
attempted to evaluate the expressions. Bypassing the evaluation (and
using a default value) should allow us to recover from the error.
Some types, i.e. vector types with parameterized dimensions,
may have different elaboration results in different scopes.
Handle those cases in the elaboration caches.
When a module is instantiated multiple times, the enum
types contained within would cause trouble. This fixes
that by elaborating in proper scope context.
There were also some subtleties related to using enumerations
from typedefs and using them in multiple places. Fix various
bugs related to those issues.
Add properties to the classes, and elaborate expressions that
have class properties. Describe class object property references
all the way down to the stub target.