Types for array signals are currently handled as a special case. The type
that is associated with the signal is not the array type itself but rather
the element type.
There is a fair amount of existing code that depends on this behavior so it
is not trivial to change this.
But there are certain constructs such as assignment patterns or array
concatenation where the array type itself is required.
Add a new `NetNet::array_type()` method that will return the array type if
the signal is an array. This will allow to query the array type when
needed.
`NetAssign_::net_type()` is updated to use this new method to return the
array type if the assigned signal is an array.
Long term the special handling of arrays for signals should be removed.
This will for example allow to unify the handling of arrays for signals,
class properties and struct members.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
`ivl_assert()` is similar to `assert()` except that it will also include
source file and line information about the expression for which the assert
was triggered.
Use `ivl_assert()` instead of `assert()` where the line information is
available. This will generate better bug reports and make it easier to
diagnose why an assert is triggered.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
In SystemVerilog it is not allowed to assign a value to a enum variable
that is not of the same time as the enum variable.
This is currently enforced for assignment and continuous assignment. But
ignored in other places such as function parameter passing.
Move the enum type check into `elab_rval_expr()` to cover more cases.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
In most cases the type of an lvalue part select is the base type of the
lvalue with the width of the part select. But there are some exceptions.
1) An index into a `string` type is of type `byte`.
2) Packed structs are implemented as packed arrays under the hood. A lvalue
struct member is elaborated as a normal part select on a packed array. The
type of that select should be the type of the member.
For the case 1 there is some special handling for strings that accounts for
this. But for case 2 the type information of the member is lost.
This works fine for most things but there are a few constructs where the
type information is required.
* Enum type compatibility check
* Assignment pattern behavior depends on the type of the lvalue
Allow to attach a specific type to a lvalue part select to allow correct
behavior for constructs where the type is required.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
The NetAssign_:net_type() function return the type of lvalue expression.
But it only does so for a limited amount of cases.
Refactor the function so that it works for the general case and always
returns the data type, if the data type of the lvalue expression is known.
This will allow to implement better type checking and other constructs such
as pattern assignments that require to know the type of the lvalue.
It also allows to remove some duplicated code in other methods of
NetAssign_ that want to lookup the type.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
SystemVerilog allows to use the `super` keyword to access properties and
methods of a base class. This is useful if there is for example an
identifier with the same name in the current class as in the base class and
the code wants to access the base class identifier.
To support this a bit of refactoring is required. Currently properties are
internally referenced by name, this does not work if there are multiple
properties of the same. Instead reference properties always by index.
In addition when looking up an identifier that resolves to an object return
both the type and the object itself. This is necessary since both `this`
and `super` resolve to the same object, but each with a different type.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
A compressed assignment statement should give exactly the same
result as the equivalent uncompressed statement. This means
that the type (signed/unsigned) of the LHS affects the type of
the RHS expression (unlike in normal assignments). We need to
take care that bit/part selects and concatenations are correctly
identified as unsigned values, even in the cases where they
reduce to a single whole signal.
This allows for syntax like a.b.c where a is a class with member
b, which is a class with member c, and so on. The handling is mostly
for the support of compound objects like classes.
This gets nested l-values to (but just short of) the ivl_target API.
Now the elaborator can process nested l-values, but I haven't figured
out how to present that at the ivl_target.h API.
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.
Implement through the ivl core to the ivl_target.h API.
Also draft implementation of creating and storing arrays
in the vvp runtime and code generator.
Remove an unused variable (desired_vector_width) in elaborate.cc.
Reduce the scope of spin to make it obvious it is only used locally
in elaborate.cc. Initialize sel_type_ in the NetAssign_ constructor
(net_assign.cc). The code doesn't currently require this since
sel_type_ is only used when the base is not zero and it is always
defined when base is not zero, but giving this a default value in
the constructor hedges against accidentally using an undefined
value if someone checks the select type when the base is zero.
This patch modifies the compiler and the ivl interface to pass the
type of indexed part select that is being represented (up/down) in
a procedural L-value or R-value. This is needed by any back end that
wants to correctly denormalize the (zero based) base expression.
This patch cleans up some style issues: no need to check that a value
is defined before freeing or deleting it, use C++ style casts, make
sure to NULL terminate strncpy(), empty() is faster than size() for
size == 0 or size >= 0 checks, re-scope some variables, etc.
Widths of real values are always 1. When paired with vectorable types
in expressions, the vectorable type is processed as losslessly self-
determined. ("unsized" in the test_width methods.)
This patch pushes the non-blocking event control information to
the code generator. It adds the %evctl statements that are used
to put the event control information into the special thread
event control registers. The signed version (%evctl/s) required
the implementation of %ix/getv/s to load a signed value into
an index register. It then adds %assign/wr/e event control based
non-blocking assignment for real values. It also fixes the other
non-blocking real assignments to use Transport instead of inertial
delays.
more general concept of arrays. The NetMemory and NetEMemory
classes are removed from the ivl core program, and the IVL_LPM_RAM
lpm type is removed from the ivl_target API.
instead of link into the netlist. This is faster
and uses less space. Make the NetAssignNB carry
the delays instead of the NetAssign_ lval objects.
Change the vvp code generator to support multiple
l-values, i.e. concatenations of part selects.