Commit Graph

829 Commits

Author SHA1 Message Date
Cary R. 00325f3efb
Merge pull request #1348 from jotego/interface-ports
Support SystemVerilog interface-typed module ports
2026-05-16 15:33:56 -07:00
Lars-Peter Clausen 265272a962 Report error for `edge` event controls on named events
Using an edge control with a named event is invalid. The existing elaboration
code already reports an error for `posedge` and `negedge`, but the `edge` case
falls through to the default path and triggers an assert.

Handle `PEEvent::EDGE` like the other edge-control cases and report the same
kind of error instead.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2026-05-11 21:10:32 -07:00
Jose Tejada 377881b723 fix(interface): address port array review feedback 2026-05-11 07:44:43 +02:00
Jose Tejada 417ab54445 feat(interface): support interface port arrays 2026-05-10 17:30:54 +02:00
Jose Tejada 2228e31a6a refactor(interface): share port resolution paths 2026-05-10 17:08:35 +02:00
Jose Tejada 39072cd452 feat(interface): broaden interface port binding 2026-05-10 16:34:21 +02:00
Jose Tejada c963809709 feat(sv): support interface-typed module ports 2026-05-10 14:45:33 +02:00
Cary R 3d8f906bdd Update Copyright that was missed for a few files 2026-05-08 05:35:16 -07:00
Lars-Peter Clausen 272cf91eae Support assignment of string literals to byte arrays
SystemVerilog defines a special case that allows to assign string literals
to byte arrays. Each character of the string is copied to 1 element of the
byte array.

The size of string literal and the byte array does not have to match. If
the string literal is longer it is truncated. If it is shorter it will be
padded with null-bytes.

The assignment is done left aligned, the first character ends up in the
left most entry of the array. This means the order will differ whether the
array is declared with ascending or descending element order.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2026-05-03 19:48:38 -07:00
Lars-Peter Clausen d39e81e1d1 Reject non-assignable unpacked array output port expressions
Output port expressions must support continuous assignment. Assignment
patterns for unpacked array output ports are currently elaborated as
temporary arrays and the connection is silently discarded.

Report an error instead.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2026-05-03 17:31:09 -07:00
Cary R d87dbb08cf cppcheck updates 2025-11-23 01:31:14 -08:00
Martin Whitaker 28717b4de7 Don't include duplicate nodes in NetEvent objects (issue #1286).
Currently, when a constant bit/part select is found in the implicit
sensitivity list for an always_* construct, it is replaced by the
entire signal. If there is more than one bit/part select from the
same signal, that signal gets added to the list multiple times. This
breaks the algorithm used to detect duplicate events in the nodangle
functor, causing it to erroneously merge non-identical events in some
cases.

The proper fix is to support sensitivity at the bit/part level, as
required by IEEE 1800. But for now, just make sure we only include
the entire signal once, regardless of how many different bit/part
selects we find. Enhance the "sorry" message to report which signals
are contributing excessively to the process sensitivity.
2025-11-11 21:59:31 +00:00
Cary R cc496c3cf3 More ivl cppcheck cleanup 2025-10-23 10:01:06 -07:00
Cary R 860761f9c6 More cppcheck fixes - part 2 2025-10-20 23:54:15 -07:00
Cary R eceb48e5d6 Add better error messages for output port elaboration issues 2025-07-16 22:37:49 -07:00
Cary R 30f1de9062 Elaborate input port default value expressions in the correct scope 2025-07-09 09:19:42 -07:00
Cary R 66d57628bf Check what can drive a variable in SystemVerilog 2025-06-30 23:48:26 -07:00
Cary R a05da1ca08 Only synth when the R-value is valid 2025-06-30 16:25:16 -07: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
Martin Whitaker f08ff895af Add informational messages that point to declaration after use. 2024-02-25 16:12:31 +00:00
Martin Whitaker 1c28948484 Pass lexical position information to PTrigger and PNBTrigger objects. 2024-02-19 18:20:14 +00:00
Martin Whitaker 649fbb9a59 Modify symbol_search() to only return declared nets and named events.
This only applies to simple identifiers. Only return a match if the
lexical position of the identifier being searched is later in the
source text than the lexical position of a matching symbol.
2024-02-19 18:19:55 +00:00
Martin Whitaker 079108f32b Add lexical position information to PEIdent objects. 2024-02-19 18:13:29 +00:00
Martin Whitaker ccf925a4f7 Remove the legacy version of symbol_search(). 2024-02-18 09:36:23 +00:00
Martin Whitaker c9d87abc10 Convert unpacked array variable to net when connected to a module output port.
SystemVerilog allows variables to be driven by continuous assignments,
including port connections. Internally we handle this by converting
the NetNet from a REG to an UNRESOLVED_WIRE. Here we handle the case
of an unpacked array variable connected to a module output port.

This fixes issue #1001.
2024-01-30 23:18:03 +00:00
Cary R 1471e7d53d MModule elab should check elab tasks first 2023-12-28 15:26:59 -08:00
Cary R cc829031ff Elaborate system elab tasks in gen blocks 2023-12-28 15:07:37 -08:00
Lars-Peter Clausen 763907b0e5 Add a typedef for `std::vector<netrange_t>`
`std::vector<netrange_t>` is used for signal array dimensions. As such it is
used in quite a few places.

Add a typedef that can be used as a shorthand to refer to it. This helps to
keep lines where this is used from growing to overly long.

The new type is called `netranges_t`.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2023-09-09 05:50:40 -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
Lars-Peter Clausen f6a51bc9db Add support for binding function/task arguments by name
In addition to providing positional arguments for task and functions
SystemVerilog allows to bind arguments by name. This is similar to how
module ports can be bound by name.

```
task t(int a, int b); ... endtask
...
t(.b(1), .a(2));
```

Extend the parser and elaboration stage to be able to handle this. During
elaboration the named argument list is transformed into a purely positional
list so that later stages like synthesis do not have to care about the
names.

For system functions and tasks all arguments must be unnamed, otherwise an
error will be reported.

In addition to functions and tasks arguments can also be bound by name for
the various different ways of invoking a class constructor.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2023-08-20 08:20:54 -07:00
Lars-Peter Clausen 6ea01cbf7f Fix class constructor chaining corner cases
There are some corner cases around class constructor chaining that can
result in chained constructors not being called, or being called multiple
times.

This is primarily related to that a class can have either an explicit
constructor called `new` and an implicit constructor called `new@` and how
the lookup of them is done.

Lookup is currently done independently for the implicit and explicit
constructor using the `method_from_name()` method. `method_from_name()`
will search the whole class hierarchy for a class method. If a class
doesn't have a method by that name it will look in the parent class and so
on.

As a result the lookup for the explicit constructor can return the explicit
constructor of a parent class if the class itself only has an implicit
constructor and vice versa.

E.g. in the following example the constructor of D will not be called
because the implicit constructor for C is found when looking for a implicit
constructor in D.

```
class C;
  int x = 10;
endclass

class D extends C;
  function new;
    $display("D");
  endfunction
endclass

class E extends D;
  int y;
  function new;
    y = 20;
  endfunction
endclass

E e = new;
```

There is a similar case where the constructor of a base class can be called
multiple times if the base class has an explicit constructor and the
derived class has an implicit constructor. In that case the derived class
constructor will call the base class constructor, but the code that is
emitted for the `new` statement will call both of them.

To mitigate this introduce a new method to lookup the constructor that will
search for either the explicit or implicit constructor in the current class
and only continue to search in the base class if neither is found.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2023-08-06 02:10:28 -07:00
Lars-Peter Clausen 3daa2982ac Add support for `const` variables
SystemVerilog allows to declare const variables. These variables are
read-only and can not be assigned a value after their declaration. It is
only possible to assign an initial value as an initializer.

E.g.
```
const int x = 10;
x = 20; // Error
```

The LRM requires that for variable declarations with static storage the
initializer is a constant expression with the extension that other const
variables are also allowed. const variables with automatic storage can
be initialized by any expression.

Checking if an expression contains only const variables requires a bit more
work to implement. So for now be more lenient that what the standard
requires and allow arbitrary expressions to initialize const variables even
for those with static storage.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2023-07-23 15:08:39 -07:00
Cary R ceb07dc9db
Merge pull request #966 from mole99/delayed-signals
Handle delayed signals in timing checks as assignments
2023-07-14 06:33:37 -07:00
mole99 6b2990cfec Use more C++11 features 2023-07-12 15:10:23 +02:00
Cary R 095e6daa0a Cannot use posedge, negedge or edge with a real expression 2023-07-09 05:02:01 -07:00
mole99 e54ff22fce Fix wrong output 2023-07-05 16:50:10 +02:00
mole99 87885dbd9b Handle delayed signals in timing checks as assignments 2023-07-05 16:22:08 +02: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 3fc6ab5afc Replace assert() with ivl_assert() where line information is available
`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>
2023-06-16 05:06:15 -07:00
Lars-Peter Clausen b8eb21b3ac Allow to omit trailing module ports in ordered list connection
The current implementation expects that for a module instantiation with a
ordered list connection all ports are supplied.

But there doesn't seem to be such a requirement in the LRMs. The Verilog
LRM doesn't mention anything in this regard and the SystemVerilog LRM
mentions in section 23.3.2.1 that a blank or omitted port connection is
either left unconnected or uses the default value of the port.

Update the implementation so that it allows to omit trailing ports and only
generates an error message if too many ports are specified in the ordered
port list.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2023-06-11 08:45:34 -07:00
Cary R 9cb3d53633
Merge pull request #918 from larsclausen/fix-single-element-array-ports
Fix connecting single element array ports
2023-06-04 21:09:04 -07:00
Cary R f22c1a519b
Merge pull request #900 from larsclausen/task-return
Support return in tasks
2023-06-04 21:07:30 -07:00
Cary R ef931e2e0d Spelling and space cleanup 2023-05-31 22:44:13 -07:00
Lars-Peter Clausen 829af9f438 Fix connecting single element array ports
The current check to decide whether a port is an array or a scalar signal
uses the number of pins on the NetNet. If it is larger than one the code
assumes that it is an array.

But for arrays with on a single element the number of pins will be 1 and
the port is incorrectly treated as a scalar signal which results in an
error.

Instead of using the number of pins check for the number of unpacked
dimensions to decide whether the port is an array.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2023-05-06 09:28:40 -07:00
Lars-Peter Clausen 730c9c28b2 Support return in tasks
SystemVerilog allows to use the `return` statement in a task to exit the
task before it reaches the end of its execution. This is defined in section
13.3 ("Tasks") of the LRM (1800-2017).

This is similar to using `disable` to stop a task from within itself with
the difference that `disable` will affect all concurrently running
executions of a task, while `return` will only affect the task from which
it has been called.

The `%disable/flow` vvp instruction allows to implement the required
behavior for task return.

There is one complication in that it is not allowed to call return from
inside a parallel block (fork-join). If a parallel block is unnamed and has
no variable declarations there won't be a NetScope for it. So it is not
possible to detect whether the return is inside a parallel block by
walking up the scope chain.

To solve this add a design global counter that gets incremented when
entering a fork block and decremented when exiting a parallel block. The
return implementation then checks if the counter is non 0 to determine
whether it is in a parallel block.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2023-04-16 19:22:29 -07:00
Lars-Peter Clausen e19d077d44 Iterate static arrays $left to $right in foreach loops
foreach loops are supposed to iterate arrays $left to $right. E.g. `reg
x[3:0]` should be iterated from 3 to 0 and `y[1:4]` from 1 to 4.

The current implementation iterates them from $low to $high. Modify this to
either count up or down depending on whether $left or $right is the larger
of the two values.

Note that the same applies for dynamic arrays. But since for dynamic arrays
$left is always 0 and $right is always $high they always count up and we do
not need to differentiate between two different cases.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
2023-03-12 18:04:31 -07:00
Stephen Williams 18192fdba9
Merge pull request #862 from larsclausen/enum-compat-check
Improve enum compatbility checks
2023-01-16 19:34:05 -08:00
Stephen Williams b6644186a6
Merge pull request #861 from larsclausen/scoped-symbol-search
Add common implementation for scoped symbol search
2023-01-16 19:30:25 -08:00
Stephen Williams e740e4b3f3
Merge pull request #859 from larsclausen/func-empty-arg
Improvements for calling functions with empty arguments
2023-01-16 19:26:23 -08:00