Commit Graph

1105 Commits

Author SHA1 Message Date
Cary R 527b0daed6 Fix some clang warnings 2024-11-26 23:33:52 -08:00
martinwhitaker 34ed6f6f97
Merge pull request #1168 from steveicarus/fix-vvp-cg-array-word-aliasing
Fix vvp cg array word aliasing
2024-09-07 17:04:57 +01:00
martinwhitaker 74ba42e2df
Merge pull request #1166 from larsclausen/fix-ix-load-sign
tgt-vvp: Use signedness of expression instead of signal for index load
2024-09-07 17:04:40 +01:00
Martin Whitaker d6abe59983 Improve annotation in vvp code generation. 2024-09-03 21:34:46 +01:00
Martin Whitaker f8947a6aab Fix indentation and white space. 2024-09-03 21:34:12 +01:00
Martin Whitaker d99add9dbe Fix vvp code generator for array word alias corner case (issue #1155)
When multiple words in one array were connected to the same nexus as a
single word array, the code generator was sometimes failing to generate
all the necessary aliases. This was highly dependent on the elaboration
order.

This fix should be more robust, but there are currently no tests in the
test suite that cause the compiler to generate whole-array aliases, and
I can't think of a way to make it do so as we don't yet support unpacked
arrays in module ports, so that branch of the code is currently untested.
2024-09-03 21:24:25 +01:00
Lars-Peter Clausen 50d9a32d56 tgt-vvp: Use signedness of expression instead of signal for index load
When loading a signal into into an index register currently the signedness
of the signal is used when deciding whether sign-extension should be
performed or not. But this can lead to incorrect results, instead the
signedness of the expression must be used as that might be different from
the signal. E.g.

```
reg signed [1:0] = 2'b10;
$display(1 << x[1:0]);
```

gives the wrong result without this.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2024-09-02 19:09:06 +02:00
Lars-Peter Clausen 80fd301fc1 tgt-vvp: Fix vector assignment with undefined delay
Assignments with an undefined intra-assignment delay should be treated like
assignments with zero delay. For the most part this is implemented
correctly, except for assignments to a part of a vector where the offset
inside the vector is an immediate value. E.g.
```
reg [1:0] x;
integer d = 'x;
...
x[0] <= #d 1'b1
```

Here when loading the delay into the index register flag 4 is updated, but
never cleared afterwards. As a result, if the delay is undefined, the vector
assignment will be skipped. Fix this by making sure flag 4 is always
cleared before the vector assignment instruction.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2024-09-02 14:10:25 +02:00
Lars-Peter Clausen de9d5e98b1 tgt-vvp: Replace `%pushi ...; %op` with `%opi`
For sequences where the tgt-vvp backend generates `%pushi` followed by one
of the operations that have an immediate version replace it with the
immediate version. This is slightly more efficient.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2024-08-31 13:46:30 +02:00
Martin Whitaker a204af04a5 Support for loops with no loop condition.
SystemVerilog makes all of the initialisation, condition, and step
components of a for loop optional. We already support this for the
initialisation and step components.
2024-07-09 21:58:15 +01:00
Paul Rigge 28187823ed
Update handling of single-element arrays.
Also, add a test. This fixes #1113.
2024-04-15 13:14:53 -07:00
Cary R 2948e9a89f Update cppcheck to use c++11 2024-02-05 02:21:24 -08:00
Cary R dc047799d6 Update displayed Copyright 2024-01-20 17:52:04 -08:00
Cary R 5c9ec105d9 Fix some compile issues 2024-01-20 12:42:55 -08:00
Cary R d42f97ecbe Cleanup space issues 2024-01-20 11:26:06 -08:00
Martin Whitaker 94b443a7fe tgt-vvp: inform vvp about undriven constant values.
This causes tgt-vvp to use a lower case 'c' instead of an upper case
'C' as the prefix for constant values used to initialise undriven nets.

For use by the following commit.
2024-01-07 09:34:36 +00:00
Lars-Peter Clausen 85bf2d11fa tgt-vvp: Cast reads from 2-state dynamic arrays/queues
vvp does not track whether the values stored in a dynamic array or queue
are 2-state or 4-state. Internally the data is always stored as 4-state.

To make sure that the read value is actually 2-state do a cast for 2-state
reads.

E.g. performing an out-of-bounds access on a 2-state dynamic array or queue
will yield a undefined value.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2023-10-01 09:09:31 -07:00
Cary R f229dfcb2b Fix the trigger for user functions with no args 2023-09-03 18:41:38 -07:00
Cary R 64cfd681af
Merge pull request #980 from sifferman/argumentless-functions-fix
Argumentless functions fix
2023-09-03 17:31:10 -07:00
mole99 11c944f5e9 Cleanup 2023-08-29 09:54:39 +02:00
mole99 6d3e2bf344 Improve SDF interconnect support, add -ginterconnect flag 2023-08-23 12:56:11 +02:00
Ethan Sifferman eb104a727e initial commit 2023-07-28 22:22:15 -07:00
Lars-Peter Clausen 9549156226 Add initial support for array assignment patterns
SystemVerilog allows to use assignment patterns to assign values to an
array. E.g. `int a[4] = '{1, 2, 3, 4}`.

Each value is evaluated in the context of the element type of the array.

Nested assignment patterns are supported. E.g. `int a[2][2] = '{'{1, 2},
'{1, 2}};`

Add initial support for array assignment patterns for both continuous as
well as procedural assignments.

For continuous assignments the assignment pattern is synthesized into an
array of nets. Each pin is connected to one of the assignment pattern
values and then the whole net array is connected to target array.

For procedural assignments it is unrolled in the vvp backend. E.g
effectively turning `a = '{1, 2};` into `a[0] = 1; a[1] = 2;`.

Not yet supported are indexed initializers or `default`.
E.g. `int a[10] = '{1:10, default: 20};`

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2023-06-17 11:50:23 -07:00
Lars-Peter Clausen 872ccd32c4 tgt-vvp: Add resize for string element assignment where necessary
There are some cases where during an assignment the elaboration step can
generate constructs with the right-hand-side expression being wider than
the left-hand-side expression.

To handle this the tgt-vvp backend inserts a %pad operation when necessary.
One place where this is missing is when writing to an string element. Here
instead an assert is triggered requiring the right-hand-side expression to
be 8 bits wide.

E.g.
```
bit [7:0] x;
bit [8:0] y;
string s;

x = y; // tgt-vvp inserts %pad
s[0] = y; // tgt-vvp triggers assert
```

Long term this should be fixed at the elaboration stage and insert the
proper width cast. But for now solve this the same way as other places in
tgt-vvp and insert the %pad operation for string element assignments if the
width does not match.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2023-06-16 07:29:16 -07:00
Lars-Peter Clausen fb403c6266 tgt-vvp: Handle continue/break in do-while loops
Currently continue and break are supported in most loops. But not in
do-while loops. Add support for them in do-while loops as well.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2023-06-11 07:20:15 -07:00
Cary R ee14cb0eb0 Update displayed Copyright dates 2023-06-10 20:33:08 -07:00
mole99 b0c1eab51e Move textfiles to documentation 2023-06-09 13:30:44 +02:00
Cary R ef931e2e0d Spelling and space cleanup 2023-05-31 22:44:13 -07:00
Cary R 7ac6182d4c Update to compile with older GCC versions 2023-05-31 20:02:36 -07:00
Stephen Williams 6c9c876c83 Add compiler support for break and continue
This includes support at the parser (pform) through enaboration
and the netlist format for the break and continue statements.

Elaboration actually already worked for for-loops, but since the code
generators need more information, this is a rewire of that support to
be explicit about for-loops. This means they are not rewritten as fancy
while loops. The code generators will have to handle that.

Given the elaboration of for-loops now work, write the vvp code generator
support needed to implement it.

Now that for-loops are presented as for-loops to the code generator, the
vlog95 code generator doesn't need to infer them anymore. Generate the code
more directly.

Also update the tests list so that the vlog95_reg tests all pass.
2023-01-15 21:46:20 -08:00
Cary R dc8b7d0184 Cleanup some cppcheck warnings 2022-12-28 00:00:31 -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 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 c3c7f6d9ee tgt-vvp: Fix syntax when using multiple events for non-blocking event control
When multiple events are used in a non-blocking event control they need to
be combined into a single event using `event/or`.

The generated `event/or` statement is missing the trailing semicolon and
newline, which results in parser error when vvp tries to run.

E.g.

```
event e, f;
integer x;
x <= @(e or f) 10;
```

Add the missing semicolon and newline to fix this.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-06-06 17:00:13 +02:00
Lars-Peter Clausen ec75c1aa74 Handle non-blocking event control to lvalue concatenation
A non-blocking event controlled assignment consists of 3 steps.

 * Setup event
 * Perform assignment
 * Clear event

This works fine if the lvalue is a singular value. If the lvalue is a
concatenation multiple assignments are generated and the event is cleared
after each assignment. As a result only the first assignment is event
controlled. All other assignments will be regular non-blocking assignments.

E.g.

```
reg x, y;
event e;
{x,y} <= @e 2'b11;
$display(x, y); // x will be 1'b1, y will be 1'bx
```

To resolve this the event needs to be cleared after all assignments have
been done. This requires changes to both tgt-vvp and the vvp runtime.

tgt-vvp is updated to only insert a single `%evctl/c` instruction for each
event controlled non-blocking assignment.

The vvp runtime is not updated to implicitly clear the event in the
`%assign/vec4/e` instruction and instead rely on the explicit `%evctl/c`.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-06-04 22:27:00 +02:00
Lars-Peter Clausen ab95d1d903 tgt-vvp: Handle dynamic part select on array element non-blocking event control
VVP array assignment operations expect the array element index to be in
index register 3.

For array element assignments with a dynamic part select the array index
gets moved into a temporary index register and has to be moved into
register 3 after evaluating the dynamic part select.  This is currently not
done non-blocking event control assignments. This causes the write to go to
the wrong array element. It will go to whatever value is in the register 3
from previous operations.

```
reg [3:0] a[1:0];
integer i = 0;
event e;
a[1][i+:2] <= @e 2'b10; // Will write to the wrong array element
->e;
```

Make sure to move the temporary register to register 3.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-06-04 22:26:53 +02:00
Stephen Williams bf4bee319d
Merge pull request #722 from larsclausen/real-array-assignment-op
tgt-vvp: Handle assignment operator on real array entries
2022-06-01 23:13:05 -07:00
Lars-Peter Clausen a4eeea75ce tgt-vvp: Handle assignment operator on real array entries
The basic structure for supporting assignment operators on real arrays
exists in the tgt-vvp backend. But there are a few problems, most
importantly it generates the wrong instruction for loading data from the
real array.

The instruction it uses is `%load/reala`, but that instruction does not
exist, the correct name is `%load/ar`.

In addition to this there are a few minor problems.
  * Out-of-bounds access on the array triggers an assert
  * Missing `%pop/real` instruction when skipping a write due to
    out-of-bounds access

Address these so assignment operators are supported on real array entries.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-05-26 21:30:04 +02:00
Lars-Peter Clausen d3573334d6 tgt-vvp: Handle signedness when passing struct member to system function
Access to members in packed struct fields is internally implemented using a
part select.

vvp has a special syntax for passing a part select of a vector to a system
function. This special syntax assumes that the part select is unsigned like
it is for normal Verilog part selects.

As a result passing a signed struct member to a system function will
interpret it as unsigned.

Add a check to make sure that the expression is actually unsigned. If it is
not fall back to evaluating the expression on the vector stack and pass the
value on the stack to the system function.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-05-24 11:32:19 +02:00
Lars-Peter Clausen d651aefd92 tgt-vvp: Allow out-of-bounds assignment operator on arrays wider than 32 bits
For an out-of-bounds assignment operator on an array element an assert is
hit if the element width is great than 32.

Remove the assert and make sure that this case is handled correctly by
using the `%pad/s` instruction to extended the X value to the correct
width.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-05-21 21:30:33 +02:00
Lars-Peter Clausen d746c592b2 tgt-vvp: Fix out-of-bounds compressed assignment to arrays
If the index of an array access is known to be out-of-bounds during
elaboration it is replaced with 'x. In the tgt-vvp backend that is handling
compressed array assignments there is an assert() that triggers if the
index is an undefined immediate.

There is already an existing code path that is capable of handling
out-of-bounds access. Remove the assert and set the index to ULONG_MAX to
trigger taking the out-of-bound access path.

On this out-of-bounds path the write to the array is skipped. But this
leaves the result on the vector stack. Insert the `%pop/vec4` instruction
to make sure it is removed.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-05-21 21:15:20 +02:00
Lars-Peter Clausen e263d5b268 tgt-vvp: Fix store skip for assignment operator on dynamic part select
The operator assignment on dynamic part selects uses the `%store/vec4`
instruction to store the value. This instruction will skip the assignment
if flag 4 is set. This is for handling the case where the index is
undefined.

Since the left hand side of the assignment is an arbitrary expression it
can change the flag. The implementation handles this by making a copy of
the flag and restoring it before executing the `%store/vec4` instruction.

The flag is set by the `%ix/vec4` instruction when loading the index
register. But the copy of the flag is made before that and just picks
up the flag that was stored by previous expressions. This can cause
the store to be skipped when it shouldn't.

E.g. in the following code the increment will be skipped. Flag 4 is used
from the `a == 0` comparison, rather than from computing the part select
index.

```
int a = 0;
if (a == 0) begin
  a[a+:2] += 1;
end
$display(a); // Will print 0, should print 1
```

Fix this by moving the copy of the flag after the `%ix/vec4` instruction.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-05-16 10:18:27 +02:00
Lars-Peter Clausen 2abfef68ff tgt-vvp: Fix load skip for assignment operator to array entry
The vvp `%load/vec4a` instruction will skip the load if vvp flag 4 is set
and return 'x. This is meant for handling the case where the index is
undefined.

For assignment operators on array entries, when the index is an immediate
value, vvp flag 4 is not cleared before the load instruction. If a previous
instruction set flag 4 it load yield 'x.

E.g. for the following sequence `x[0]` should be `11`, but will be `'x`.

```
integer x[10];
logic a = 1'b0;
x[0] = 10;
if (a == 0) begin
  x[0] += 1;
end
```

Properly clear the flag before the load instruction to handle this
correctly.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-05-16 10:18:27 +02:00
Lars-Peter Clausen b83ebf3c8e tgt-vvp: Fix store skip on real typed array entries
When assigning a value to a real typed array entry the vvp `%store/reala`
instruction. This instruction will skip the store if the vvp flag 4 is set.
This is to handle the case where the index is undefined.

When the index into the array is an immediate value the flag 4 is not
cleared. If a previous instruction set flag 4 the store will be skipped.

E.g. for the following r[0] will remain 0.0 since the assignment to it is
skipped.

```
integer a = 0;
real r[1:0];
if (a == 0) begin
  r[0] = 1.23;
end
```

Fix this by using the `draw_eval_expr_into_integer()` helper function to
evaluate the index into a word register. The function correctly handles all
the special cases.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-05-16 10:18:27 +02:00
Stephen Williams e67a796a77
Merge pull request #709 from larsclausen/remove-draw-bool
tgt-vvp: Remove unused draw_eval_bool64()
2022-05-12 14:49:42 -07:00
Lars-Peter Clausen 5a616bcaf4 tgt-vvp: Remove unused draw_eval_bool64()
Ever since the conversion to use a stack for vectors `draw_eval_bool64()`
has been unused. The last caller of `draw_eval_bool64()` was removed in
commit e4b862f3d1 ("Clean up vector handling dead code.").

Remove `draw_eval_bool64()` and related functions as well.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-05-04 11:45:46 +02:00
Lars-Peter Clausen 1eb22b7e14 tgt-vvp: Allow multi-dimensional real arrays
There is currently a restriction in the vvp code generator backend that
throws an assertion when generating wire access for a multi-dimensional
real array.

But there is nothing special about multi-dimensional arrays. In vvp arrays
are in canonical form. Meaning they only have a single dimension and the
conversion form multi to single dimension is done in the higher layers.

Remove the assert to allow multi-dimensional real arrays.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-05-02 14:29:15 +02:00
Lars-Peter Clausen b11da7e16f tgt-vvp: Don't accidentally skip assignment pattern initialization
The `%store/dar/...` and `%store/qdar/...` instructions are used to load a
value into an entry in dynamic array or queue. These instructions will skip
the load if VVP flag 4 is 1.

For assignment pattern initialization these instructions are used to load
the value of the individual assignment pattern expressions into the dynamic
array.

For queues flag 4 is never cleared when generating the code for the
assignment pattern. This means the initialization might be skipped
depending on what value the flag had before.

```
int a = 1;
int q[$];
a = a == 1;
q = {1, 2, 3, 4};
```

For dynamic arrays it is cleared once in the beginning. But each item in
the assignment pattern can be an arbitrary expression.  Evaluating the
expression can cause the flag to get overwritten. E.g. the following code
will skip the assignments.

```
int a = 1;
int d[];
d = {a ? 1 : 1, 2, 3, 4};
```

To fix these issues make sure that the flag is cleared after evaluating
each initialization expression and before executing the `%store/...`
instruction.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-04-17 09:09:38 +02:00
Lars-Peter Clausen 84c3c72563 Support recursive functions using `return` statement
A `return` statement in a function gets translated into a vvp `%disable`
instruction. This works fine as long as no recursion is involved. The
`%disable` instruction will stop execution of all active threads of a
particular scope. For recursive functions this means as soon as the inner
most function returns all containing outer function calls get disabled as
well. This results in incorrect behavior.

To make recursive functions using the `return` statement work use the new
vvp `%disable/parent` instruction. This instruction will only disable the
closest thread in the thread hierarchy that matches the target scope.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2022-04-11 22:03:02 +02:00