Compare commits

...
581 Commits
Author SHA1 Message Date
Lars-Peter Clausen 64f13540a6 Add regression tests for forward declared base classes
Check that a class can derive from a forward declared base class that is
defined later, both directly and through a typedef alias. Cover a multi-level
hierarchy, base constructor chaining, and inherited property layout.

Check that a local forward declaration hides an outer class with the same name.
Check forward declared base classes in package scopes and in separate instances
of the same module. Check that inheritance cycles, undefined forward
declarations, and non-class base types are rejected.

Run the tests through the native and vlog95 backends.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-23 14:30:25 -07:00
Lars-Peter Clausen 4d06b81f10 Support forward declared base classes
SystemVerilog allows a forward declared class to be used as the base of a
class that is declared before the base class definition.

    typedef class B;
    class C extends B;
    endclass
    class B;
    endclass

The base type is currently elaborated while creating the derived class. At
that point the base class has not been added to the scope yet and the base
type does not resolve to a class.

Create all classes first and bind their base classes in a second pass. Reject
inheritance cycles before attaching the base class.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-23 14:30:25 -07:00
Lars-Peter Clausen e14ae1ca5f Add regression tests for hierarchy identifiers shadowing type identifiers
Check that `SCOPE.value` resolves to a forward-referenced generate block when
`SCOPE` also names an imported type. The lexer can only see the type at the
point of the reference, so this exercises parsing a `TYPE_IDENTIFIER` as the
first hierarchy component.

Check that a compilation-unit type does not prevent a same-named inherited
class property from being used as a procedural l-value or expression.

Check that empty and queue-bound indices on such hierarchy components are
rejected during parsing instead of reaching elaboration.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-23 11:40:06 -07:00
Lars-Peter Clausen 5a5146e4bd Support hierarchy identifiers shadowing type identifiers
The lexer returns `TYPE_IDENTIFIER` when an identifier matches a visible
typedef. It does not know about hierarchy scopes declared later, so an
imported type can prevent a forward-referenced generate block with the same
name from being used as the first hierarchy component:

    package p;
      typedef int SCOPE;
    endpackage
    import p::*;
    module test;
      initial SCOPE.value = 1;
      if (1) begin : SCOPE
        int value;
      end
    endmodule

The same applies to inherited class properties, which are not visible to the
parser:

    typedef int value;
    class Base;
      int value;
    endclass
    class Derived extends Base;
      function int get;
        return value;
      endfunction
    endclass

Accept `TYPE_IDENTIFIER` as the first hierarchy component and build it through
the same path as `IDENTIFIER`. This applies the existing hierarchy-index
validation before lookup and keeps malformed components out of elaboration.

Named types in expression-like contexts are already resolved through
identifier elaboration, so remove their separate `type_value` alternatives and
use the common hierarchy expression path. Keep atomic types in `type_value`.
This removes the grammar overlap without adding dedicated parameter and system
argument rules.

These identifiers can now reach continuous assignment l-value elaboration.
Use the common type diagnostic there. The implicit-net lookup checks typedefs,
so invalid type uses in continuous assignments, gate terminals, and module
port connections remain rejected rather than silently becoming nets.

This only permits hierarchy names to shadow visible type names. A hierarchical
path that resolves to a type remains rejected during elaboration.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-23 11:40:06 -07:00
Lars-Peter Clausen 4fab4ca04d Add regression test for named type lookup
Check that local, imported, and package-scoped typedefs resolve as declaration
types and as `$bits()` arguments, including attached dimensions and function
return and argument types.

Check lexical visibility before and after a local typedef declaration and an
explicit import. Earlier references resolve to outer typedefs and later
references resolve to the newly visible types.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-23 11:40:06 -07:00
Lars-Peter Clausen b8c54059e1 Factor for-loop variable declaration type grammar
For-loop variable declarations currently match an optional `var` rule
before the data type. If `TYPE_IDENTIFIER` is also allowed to start a
hierarchy identifier, the parser can either shift it as an lvalue or
reduce the empty `K_var_opt` before a declaration.

Fold the optional keyword into `for_decl_data_type` with separate
alternatives for a data type with and without `var`. This keeps
declaration behavior unchanged and prepares for hierarchy identifiers
shadowing typedef names without introducing that shift/reduce conflict.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-23 11:40:06 -07:00
Lars-Peter Clausen f91cca3494 Add regression tests for type identifiers as implicit nets
Check that a type identifier is rejected rather than declared as an implicit
net when used in a continuous assignment, primitive terminal, or ordered
module port connection. Cover local typedefs, explicit imports, and activated
wildcard imports.

These contexts are currently rejected by the grammar. Keep the tests in place
when type and hierarchy identifiers start using the same parser path.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-23 11:40:06 -07:00
Lars-Peter Clausen 65b943b009 Do not create implicit nets for type identifiers
`PEIdent::declare_implicit_nets()` checks visible nets, parameters, genvars,
events, and enum constants before creating an implicit net, but does not check
typedefs. Type identifiers are currently filtered by the grammar before they
can reach this code, but this is not true when type and hierarchy identifier
parsing use the same path.

Check local and imported typedefs while searching the lexical scopes. Stop the
type search when another local declaration hides an outer typedef.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-23 11:40:06 -07:00
Lars-Peter Clausen 5726589cac Add package-scoped subroutine call tests
Check that package tasks can be called as statements both with and
without an argument list. Use a caller variable that shares its name
with a package typedef to verify that call arguments are parsed in the
caller context.

Also check package-scoped void functions and void casts of non-void
functions. Cover class and queue methods whose receiver is a package
member as well.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-22 11:03:59 -07:00
Lars-Peter Clausen 502ba94a07 Support package-scoped subroutine calls
SystemVerilog allows package tasks and functions to be called as
statements through package-qualified names, for example:

    p::run();

`subroutine_call` currently accepts ordinary hierarchical and
class-qualified names, but not `package_scope`, so the parser rejects
these calls.

Accept a package scope before the hierarchical subroutine name. Leave
package lexer mode before parsing arguments so argument names are
classified in the caller context, then retain the package on `PCallTask`
for elaboration.

Also retain the package when a package member is used as a method
receiver. This allows calls such as `p::object.run()` to resolve the
object in the package rather than the caller scope.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-22 11:03:59 -07:00
Lars-Peter Clausen b5fdf06475 Add regression tests for elaborated cast targets
Check a type cast with an inline packed dimension and reject dimensions
following a type identifier in a cast target. Use a dimensioned typedef in
the reject test to distinguish dimensions in the type from dimensions after
the identifier.

Check that an error reported while elaborating a cast-target type is emitted
only once when width checking and expression elaboration reuse the cached
target information. Also check that each module instance resolves a
type-parameter cast target using its own parameter value.

Check that typed dynamic-array elaboration constructs the explicit cast
target rather than the enclosing expression type.

Run the tests through the native and vlog95 backends.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-16 19:31:38 -07:00
Lars-Peter Clausen bea0fdeb3c Resolve type and size cast targets during elaboration
A SystemVerilog cast target can be either a type or a constant size
expression. Currently the parser commits to `PECastType` or `PECastSize`
based on how the target identifier is classified while parsing. This is too
early for identifiers whose meaning is only known after symbol lookup. As a
result, corner cases are handled incorrectly when parser-time classification
does not match the result of elaboration. For example, the parser can not
decide whether an identifier inherited from a base class is a type or a
constant size expression. Supporting the inherited lookup is separate, but
the cast target must remain unresolved until elaboration for that lookup to
be used.

Parse both forms through `expr_primary_or_typename` and represent them with
one `PECast`. Keep atomic types wrapped in `PETypename` and preserve named
targets as `PEIdent`.

Resolve the target during elaboration. First use `test_type()` to distinguish
a type target from a constant size expression. For a type target, use a
contextual `elaborate_type()` call to resolve the type. Diagnose dimensions
after a type identifier directly from `PEIdent::elaborate_type()` when it is
used as a cast target. A failed type elaboration returns `nullptr` and does
not fall back to interpreting the target as a size expression. Dimensions
contained in the named type remain valid.

Cache the resolved target information during width checking because ordinary
expression elaboration needs the same information. Tag the cache with the
`NetScope` and recompute it when the scope changes since type parameters can
give the same cast expression a different target type in each instance.
Typed elaboration can bypass width checking, so resolve into a local value
when no matching cache is available. This avoids modifying the parsed
expression from a const elaboration method while still avoiding repeated
diagnostics between the normal width checking and expression elaboration
phases.

Share the type and size conversion paths between width-based and typed
elaboration. Use the explicit cast target when constructing a dynamic array
instead of the enclosing expression type. Own the cast target and operand
with `std::unique_ptr`.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-16 19:31:38 -07:00
Lars-Peter Clausen 506eaa5415 Add tests for dimensions on named types
Check that packed dimensions are preserved when local and
package-qualified identifiers resolve to types in type parameter values and
system function arguments. Verify that symbolic dimensions are evaluated in
the scope of each module instance.

Check the diagnostics for unsized and queue suffixes, indexed part selects,
and packed dimensions applied to an unpacked named type.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-16 17:19:54 -07:00
Lars-Peter Clausen 21bfe06b33 Add tests for named type expression lookup
Check that lookup chooses the nearest visible type or value when an
identifier can denote either. Cover lexical ordering, inherited properties,
and a bracket suffix that must remain a value select after lookup.

Check typed expression and l-value contexts where a type must be rejected
instead of binding an outer value. Check that a hierarchical type reference
is rejected with the type-specific diagnostic.

Check that probing an invalid hierarchical type parameter does not elaborate
its signal prefix and report a false circular dependency.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-16 17:19:54 -07:00
Lars-Peter Clausen db90f0ef06 Resolve named types during expression elaboration
Named types in expression-like contexts are currently converted to
`PETypename` by the parser. This commits to the type interpretation before
symbol lookup, although the same syntax can represent an ordinary identifier.

Keep atomic types as `PETypename`, but parse local and package-qualified type
identifier candidates as `PEIdent`. Preserve any bracket suffixes so they can
be interpreted as packed dimensions for a type or as selects for a value.

Add `PExpr::test_type()` for non-elaborating type detection and
`PExpr::elaborate_type()` to return the elaborated type. Use these interfaces
for `$bits()`, `$sizeof()` and type parameters. Callers test the
interpretation before elaborating it, so a null type reports an elaboration
failure without incorrectly falling back to value elaboration.

Type testing is normally followed by elaboration, and both operations need
the same symbol lookup. Let `PEIdent::test_type()` cache the result and its
declaration scope, keyed by the lookup scope. Keep `elaborate_type()` const and
perform a local lookup when type testing was skipped or the cached result is
from another scope. This avoids repeated lookup without reusing a
scope-dependent result.

Search the complete identifier path before deciding whether it names a type.
Stop lookup at signal placeholders so they still hide matching types in outer
scopes without being elaborated by the type probe.

The LRM section 6.18 does not allow hierarchical references to type
identifiers, so reject a dotted type reference after lookup and report where
the type was declared. This distinguishes an invalid `test.T` type reference
from a path that does not name a type.

Use the unified symbol lookup result to choose the type or value
interpretation. Report an error when a type reaches an expression or l-value
context. This preserves normal lexical shadowing while deferring only the
syntactic decision.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-16 17:19:54 -07:00
Lars-Peter Clausen a7e258fad1 symbol_search(): Add lookup flags
`symbol_search()` currently uses a boolean argument to allow forward
references to the terminal name. Additional lookup options would require more
boolean arguments and make call sites difficult to read.

Replace the boolean with a bitmask and use a named flag at the existing
forward-reference call sites. Add a second flag that stops lookup at an
unelaborated signal instead of elaborating it. Stopping the lookup makes the
signal continue to hide matching symbols in outer scopes.

Forward-reference permission applies only to the terminal name, while signal
elaboration suppression applies to the complete path. This allows callers
that only need to classify a name to avoid triggering signal elaboration
during lookup.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-16 17:19:54 -07:00
Lars-Peter Clausen 9a2106a439 Add regression tests for types during symbol lookup
Check that a visible type prevents lookup from continuing to an outer value
for function and task calls and implicit `.name` and wildcard `.*` port
connections. Check that types are rejected as disable targets, named events,
procedural l-values, and expressions elaborated with a required type.

Also check the opposite lexical-order case where a typedef declared after a
reference does not hide an outer named event or variable. Use diagnostic gold
files for each negative case that emits the type-specific error.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-16 13:56:31 -07:00
Lars-Peter Clausen c5ab989dc7 Consider types during symbol lookup
SystemVerilog places user-defined types and data identifiers in the same
namespace. Symbol lookup cannot currently return a type, so a value lookup can
skip a nearer typedef and incorrectly bind a value in an outer scope when an
ambiguous identifier is resolved during elaboration.

Add typedef results to `symbol_search()` and check visible typedefs before
continuing to enclosing scopes. Use the lexical visibility limit selected by
the caller. This is normally the reference position, while function and task
call lookup uses the end of the current scope as required by the LRM section
26.3.

Let callers that require a value or another non-type symbol diagnose the type
result and report its declaration location. This includes function and task
calls, expressions with and without a required type, procedural l-values,
named-event triggers, and disable targets. Callers that only probe for a
particular kind of symbol, including port-connection matching, ignore a type
result. Also ensure scope-only callers do not confuse the typedef's owning scope
with the resolved object.

This prepares expression elaboration to defer the type-versus-value decision
while preserving lexical shadowing.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-16 13:56:31 -07:00
Lars-Peter Clausen 3ed306bab8 Add regression tests for disable target lookup
Check separately that a local variable, named event, and parameter hide a
compilation-unit task used as a disable target.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-16 08:43:32 -07:00
Lars-Peter Clausen 6e8c05eda8 Use symbol_search() for disable targets
Disable targets currently use `Design::find_scope()`, which searches only
scope names. A task or named block from an outer scope is therefore selected
even when a variable, named event, or parameter in a closer scope has the
same name.

The LRM section 3.13 places tasks, named blocks, parameters, named events, and
variables in the same local name space. Use normal symbol lookup and require
the result to be a scope. This lets a closer non-scope object hide the outer
disable target and reports an error for the non-scope result.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-16 08:43:32 -07:00
Lars-Peter Clausen b3d0677d08 Add regression tests for task and function call lookup
Check that a closer variable, named event, or parameter hides a task or
function used as a statement. Also check object method lookup and recursive
function calls used as statements.

Check that a later compilation-unit task or function takes precedence over a
matching subroutine in an enclosing instance. Check that different instances
of the same module resolve task calls through their respective enclosing
instances. Check ordinary lexical ordering for a task-call receiver declared
before or after the reference.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-16 08:43:32 -07:00
Lars-Peter Clausen 7c5c1acf02 Use symbol_search() for task and function calls
Task and function calls used as statements currently use
`Design::find_task()` and `Design::find_function()`, which only search for
scopes of the requested type. A closer variable, named event, or parameter is
skipped. This can call a hidden task or function, and can make the non-void
discarded-return path resolve a different symbol and abort.

Use one `symbol_search()` for both task lookup and the function fallback so
all declarations in the shared name space participate in lookup. Accept a
function scope or the return variable of a recursive function call, while
preserving the existing method fallback.

Allow the terminal task or function name to be declared later while resolving
a receiver prefix at the call position. Use the call position when the method
fallback searches for the receiver as well.

Remove the now unused `Design::find_task()` and `Design::find_function()`
helpers.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-16 08:43:32 -07:00
Lars-Peter Clausen e5f2975a97 Add regression tests for compilation-unit lookup order
Check that same-named scopes in the enclosing instance hierarchy do not
interfere with lookup of compilation-unit variables, parameters, named events,
and imported variables. Cover expressions, procedural l-values, implicit and
wildcard port connections, and lookup from module and nested function scopes.

Check task and function calls, including method receivers and chained calls.
Verify that receiver prefixes follow ordinary lexical ordering while direct,
imported, and chained compilation-unit function names can be declared after
their references. Check the enclosing-instance fallback when the compilation
unit has no match.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-16 08:15:31 -07:00
Lars-Peter Clausen 9d7e8e67ab symbol_search(): Search compilation-unit scope before instance hierarchy
`symbol_search()` currently searches the enclosing instance hierarchy before
the compilation-unit scope for ordinary names. An enclosing instance scope can
therefore hide an earlier compilation-unit variable or object, including when
the object is the prefix of a dotted reference.

The LRM section 3.12.1 requires a common lookup order. First search the local
lexical scopes through the design unit. Next search the compilation-unit scope
up to the reference position. If there is no match, resume at the saved
instantiation parent and continue through the instance hierarchy. Disable data
object lookup when resuming so only enclosing scope names can match.

Task and function names follow the same traversal, but the LRM section 23.8.1
lets the terminal subroutine name search the complete compilation unit. Use a
separate terminal lexical limit for this. Resolve a prefix such as `object` in
`object.func()` at the reference position while allowing a forward declaration
of `func`.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-16 08:15:31 -07:00
Lars-Peter Clausen f35515ac65 symbol_search(): Track compilation-unit search explicitly
The scope traversal clears `start_scope` after switching to the compilation
unit and uses the null value to prevent a second compilation-unit search.
This gives the scope used for path evaluation two separate purposes.

Track whether the compilation-unit scope has been searched with a separate
flag. Keep the existing instance-before-compilation-unit traversal order.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-16 08:15:31 -07:00
Lars-Peter Clausen 4e425289bb symbol_search(): Track object visibility directly
The scope traversal tracks whether it has crossed a module boundary and
uses the inverse of that state to decide whether objects are visible.

Track object visibility directly instead. This keeps the existing behavior
while making the module-boundary rule and later traversal changes easier to
follow.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-16 08:15:31 -07:00
Lars-Peter Clausen 6155d56482 symbol_search(): Factor child scope lookup into a helper
Child scopes and interface aliases are matched directly in the scope
traversal. This obscures the code that decides which scope to search next.

Move the child scope and interface alias lookup into a helper. Keep the
existing lookup order and error handling unchanged so the traversal can be
restructured separately.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-16 08:15:31 -07:00
Lars-Peter Clausen cf6f70e03b symbol_search(): Factor object lookup into a helper
The object lookup for each scope is embedded in the scope traversal. This
makes the traversal order and the module boundary handling difficult to
follow.

Move net, event, parameter, class property, and placeholder lookup into a
helper. Use separate found, not found, and failure results so the existing
lookup behavior is preserved. This prepares the scope traversal to be
changed independently.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-16 08:15:31 -07:00
Lars-Peter Clausen 1d2aa1b6fa Add regression tests for duplicate class property names
Check that a class property cannot share a name with another property, a
function, a task, a parameter, a type, or an enum named constant. Check
duplicate properties in both separate and comma-separated declarations. The
latter guards the shared declaration type ownership that previously caused a
crash.

Exercise properties in both declaration orders so both member registration
paths are covered.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-10 20:30:46 -07:00
Lars-Peter Clausen 7752cb8ec1 Reject duplicate class member names involving properties
The LRM requires an identifier to name only one item within a scope. Class
properties are currently stored only in `class_type_t::properties`, outside
the common local symbol table. As a result, declarations such as:

    class C;
      int value;
      function int value;
        return 0;
      endfunction
    endclass

are accepted. A second property in a separate declaration silently replaces
the first property map entry. A repeated name in a comma-separated declaration
such as `int value, value` can crash because both declarators share the same raw
type.

Make `prop_info_t` a named item and register each property in the class local
symbol table. Check the declaration before taking ownership of its type or
initializer, since comma-separated properties share the raw declaration type.
Use `emplace()` for the property map so an accepted property cannot replace an
existing entry.

Properties now take part in the common symbol lookup. Give them a distinct
symbol type so duplicate declaration diagnostics identify them as class
properties, and remove the separate property check from type-identifier
classification.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-10 20:30:46 -07:00
Lars-Peter Clausen 2efe188b52 Add regression tests for invalid index component contexts
Consolidating variable dimensions and hierarchy indices into a shared
grammar makes all index component forms parse in either context.

Check that `+:` and `-:` indexed part selects are rejected as dimensions,
and that `[]` and `[$:N]` are rejected as hierarchy indices. These forms
were previously excluded by the context-specific grammar rules.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-10 20:17:46 -07:00
Lars-Peter Clausen cb3bf494f2 Consolidate variable dimension and hierarchy index grammar
Variable declaration dimensions and hierarchical identifier indices both
use bracketed components, but are parsed by separate grammar rules.
Consolidate them into a shared `index_component` rule and convert the
components once the surrounding context is known.

This prepares for accepting a `TYPE_IDENTIFIER` token as an ordinary name
in a hierarchical path. A path component can have the same spelling as a
typedef visible in the current scope. In the path it is an ordinary
identifier. The hierarchical reference does not override or replace the
typedef.

The shared rule parses component forms that are not valid in both contexts.
Preserve the previous restrictions by explicitly rejecting indexed part
selects in variable dimensions and empty or bounded-queue components in
hierarchical identifiers. Track the location of each component so these
errors point to the invalid suffix.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-10 20:17:46 -07:00
Lars-Peter Clausen 008b76eae6 Add regression tests for null array dimensions
Check that source `null` expressions in `[null]` and `[null:N]` are
rejected rather than treated as the `$` marker for unbounded and bounded
queue dimensions.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-09 15:08:01 -07:00
Lars-Peter Clausen 04c21e1982 Distinguish queue dimensions from null expressions
Queue dimensions use a `PENull` expression as an internal marker for `$`.
This also represents a source `null` expression, so declarations such as:

    integer value[null:2];

are accepted and elaborated as bounded queues.

Use a dedicated `PEQueueDimension` marker for queue dimensions. This lets
source `null` expressions follow normal range expression validation while
preserving the existing representation of dynamic and fixed dimensions.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-09 15:08:01 -07:00
Lars-Peter Clausen 72998c5415 Add regression test for inherited non-void function calls
Check that a bare inherited non-void function call used as a statement emits
the required discarded-return warning and executes the function.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-08 18:44:26 -07:00
Lars-Peter Clausen d1e0fa7da0 Handle inherited non-void function calls as statements
The LRM section 13.4.1 permits a non-void function call to be used as a
statement and requires a warning when the return value is implicitly
discarded. A bare call to an inherited class function currently emits that
warning and then aborts.

Method lookup finds the inherited function through the implicit `this`
receiver. The discarded-result path then rebuilds a `PECallFunction` from the
original bare name, losing the receiver and leaving the expression without a
type.

Pass the resolved method path to the discarded-result path so the rebuilt call
remains qualified by `this`.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-08 18:44:26 -07:00
Lars-Peter Clausen aa8f928ffa Add regression tests for initialized const static properties
Check that a `const static` class property with a declaration
initializer is accepted and has the initialized value. Also check that
subsequent assignments through unqualified and object-member lookup are
rejected.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-08 18:06:24 -07:00
Lars-Peter Clausen 4ffeb748f4 Accept initialized const static properties
Static property declaration initializers are elaborated as standalone
initialization processes instead of through a class constructor. The
const-property bookkeeping therefore does not see the initializer and
reports an initialized `const static` property as missing initialization.

Record whether each parsed property has a declaration initializer and
mark an initialized static const property when its signal is created.
Also mark the signal as const and its declaration assignment as an
initializer. This permits that initial assignment while rejecting later
writes. Uninitialized static const properties remain errors.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-08 18:06:24 -07:00
Lars-Peter Clausen b883f7713c Add regression test for nested const property initialization
Check that a const property can be assigned from a named block inside its
class constructor.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-08 18:06:24 -07:00
Lars-Peter Clausen 14066871e5 Allow const property initialization in nested constructor blocks
A named block inside a class constructor has its own scope. The const property
assignment check currently tests the name of this immediate scope and rejects
the assignment because it is not named `new` or `new@`.

Find the containing class method before deciding whether the assignment is in
the constructor. Assignments from nested blocks in other methods remain
invalid.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-08 18:06:24 -07:00
Lars-Peter Clausen bfc0121fb9 Add regression test for const properties in derived classes
Check that an inherited property does not offset initialization bookkeeping
for a const property assigned in the derived class constructor.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-08 18:06:24 -07:00
Lars-Peter Clausen 6e2c7f352e Fix const property initialization in derived classes
Property indices include the properties inherited from base classes.
`netclass_t::get_prop_initialized()` currently uses this combined index
without removing the inherited property count when accessing the local
property table. This can read past the table and treat a derived const
property as already initialized.

Subtract the inherited property count, matching the other property accessors.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-08 18:06:24 -07:00
Lars-Peter Clausen f493076882 Add regression test for nested class method calls
Check that an unqualified method call from a named block uses the implicit
`this` signal from the containing class method. The compiler currently looks
for the signal in the named-block scope and crashes.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-05 20:45:56 -07:00
Lars-Peter Clausen b4d92f7bb9 Find implicit this in the containing class method
An unqualified method call inside a named block is elaborated from the block
scope. When the call resolves to another method in the same class, receiver
construction looks for the implicit `this` signal directly in that scope:

    function int call_method();
      begin : nested
        return get_value();
      end
    endfunction

The signal belongs to the containing method scope, so the lookup returns null
and the compiler dereferences it.

Find the containing method first and obtain the implicit `this` signal from
that scope.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-05 20:45:56 -07:00
Lars-Peter Clausen c71709d75d Add regression tests for $unit:: reference order
Check separately that `$unit::` references to a variable, named event, and
parameter declared later in the compilation unit are rejected.

Also check that preceding compilation-unit items remain visible and that a
later function name remains visible as permitted by the LRM section 3.12.1
exception.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-05 20:45:43 -07:00
Lars-Peter Clausen 9a06cf5483 Check declaration order for $unit:: variables, events, and parameters
The LRM section 3.12.1 says that `$unit::` only disambiguates a name in
the compilation-unit scope and does not allow a reference to an item declared
later. Currently every bound scope is exempt from declaration-order checks, so
this incorrectly resolves `value`:

    module test;
      initial $display("%0d", $unit::value);
    endmodule

    integer value;

Apply the existing variable, named event, and parameter declaration-order
checks when lookup is bound to a compilation-unit scope. Other hierarchical,
package, and imported lookups remain bound without comparing unrelated lexical
positions. Task and function lookup remains unchanged, as required by the
exception in the same LRM section.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-05 20:45:43 -07:00
Lars-Peter Clausen 8e420f56ff Add regression tests for enum named constant reference order
Check that a reference before an inner enum declaration resolves to a
matching enum named constant in the outer scope, while a reference after the
declaration resolves to the inner constant.

Also check that `-gno-strict-parameter-declaration` continues to allow a
reference to a later enum named constant and identifies it correctly in the
declaration-after-use warning.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-04 21:22:08 -07:00
Lars-Peter Clausen f6f7f9d6d7 Consider lexical ordering for enum named constants
Enum named constants use the parameter lookup path, including its lexical
declaration-order check. Their declaration position is currently reported as
zero, however, so a later enum named constant can incorrectly hide a matching
constant from an outer scope.

Attach the parsed enum item's source location to the elaborated enum constant
and use its lexical position during lookup. Have the position lookup also
identify enum named constants so relaxed-mode warnings do not call them
parameters. Update the position after a warning to retain the existing warning
suppression behavior.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-04 21:22:08 -07:00
Cary R 591d2c2473 Fix for GH 1140 2026-08-03 21:31:18 -07:00
Lars-Peter Clausen 8cd52ac5be Add regression test for wildcard imports in bare delays
Check that a bare delay identifier before a wildcard package import resolves
an outer constant. Check that a following bare delay activates the import and
resolves the package constant.

Run the test through the native and vlog95 backends.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-03 21:20:46 -07:00
Lars-Peter Clausen 101bf5f841 Activate wildcard imports for bare delay identifiers
Bare identifiers used as unparenthesized delays construct `PEIdent` directly.
This bypasses wildcard package import activation, so a delay reference after
an import can resolve to an outer declaration instead of the imported name.

Create the identifier through `pform_new_ident()` so the import becomes
visible at the reference's lexical position.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-03 21:20:46 -07:00
Lars-Peter Clausen e4d29bb1c1 Add regression test for cross-unit package imports
Check that value parameters, `localparam` constants, scalar variables,
unpacked arrays, named events, and enum literals imported from a package in
another compilation unit are visible in the importing module. Exercise both
explicit and wildcard imports.

Give the package declarations larger unit-local lexical positions than the
references in the importing unit so that comparing these unrelated positions
exposes the bug.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-03 20:56:29 -07:00
Lars-Peter Clausen da0adf6614 Avoid comparing lexical positions across units for package imports
Package imports already resolve names declared in packages from other
compilation units. After `NetScope::find_import()` finds such an import,
however, `symbol_search()` continues with an unbound lookup. It then compares
the declaration position in the package with the reference position in the
importing unit. Lexical positions are local to a compilation unit, so these
unrelated values can make a legal imported variable, named event, or parameter
appear to be used before its declaration.

Set `scope_is_bound` after `NetScope::find_import()` has checked that the
import is visible at the reference. The import already identifies the package
that declares the name, so binding the search avoids the invalid cross-unit
comparison and prevents lookup from continuing outside that package.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-03 20:56:29 -07:00
Lars-Peter Clausen 431b3ba1a2 Rename prefix_scope to scope_is_bound
The `prefix_scope` flag indicates that symbol lookup has been bound to a
specific scope. It controls whether lookup can continue outside that scope
and whether declaration ordering must be checked.

Rename it to `scope_is_bound` to describe the lookup state instead of how the
scope was selected. This allows other scope bindings to reuse it.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-03 20:56:29 -07:00
Lars-Peter Clausen e393487126 Add regression test for wildcard imports in implicit named ports
Check that an implicit `.name` port connection before a wildcard import
resolves an outer declaration, while a connection after the import
resolves the declaration from the package.

Run the test through the native and vlog95 backends.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-03 20:37:59 -07:00
Lars-Peter Clausen 19772cfe07 Activate wildcard imports for implicit named port connections
The LRM section 23.3.2.4 says that an implicit `.name` port
connection is a reference that can make a name from a preceding wildcard
package import visible. Currently `.name` creates its `PEIdent` directly
and skips the package import reference bookkeeping, so the imported name
can not be resolved.

Allow `pform_new_ident()` to suppress implicit net creation and use it for
`.name`. This keeps import activation, `PEIdent` construction, and source
location handling in one place while preserving the existing behavior
that prevents `.name` from creating an implicit net.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-03 20:37:59 -07:00
Lars-Peter Clausen c5dbdddf7b Add regression tests for specparam reference order
Check separately that a module-body specparam declaration following a
reference is rejected and that a specparam declared in a specify block
remains visible before its declaration.

Run both tests through the native and vlog95 backends.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-03 20:37:46 -07:00
Lars-Peter Clausen dd403e7ea0 Honor declaration order for module-body specparams
The LRM section 6.20.5 permits `specparam` declarations both in a
module body and in a `specify` block. It states:

    A specify parameter declared outside a specify block shall be declared
    before it is referenced.

Currently all specparams retain a declaration position of zero, making a
later module-body declaration visible to an earlier expression:

    module test;
      wire value;
      assign value = delay;
      specparam delay = 1;
    endmodule

Record the source position for module-body specparams. Track when the
parser is inside a `specify` block so the outside-block restriction is
not applied there.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-03 20:37:46 -07:00
Lars-Peter Clausen 2556b5f073 Add regression test for wildcard import in class copy construction
Check that class copy construction in a nested scope activates a wildcard
package import and resolves the imported source. Check that construction in
the enclosing scope still resolves the same-named local source.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-03 20:37:27 -07:00
Lars-Peter Clausen d05b13b604 Activate wildcard imports for class copy construction
The source expression of a class copy constructor currently bypasses
`pform_new_ident()`. An identifier made visible by a wildcard package import
is therefore not activated and can not be resolved during elaboration.

Create the source expression through `pform_new_ident()`, matching ordinary
identifier expressions and preserving the source location.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-03 20:37:27 -07:00
Cary R b1635c21cc Cleanup cppcheck 2026-08-03 00:39:39 -07:00
Lars-Peter Clausen b8b6e225fc Add regression tests for package import reference order
Check separately that explicit and wildcard package imports only affect
following references. Use outer-scope declarations and package declarations
with the same names so references before and after each import resolve
differently.

Also cover implicit named port connections and repeated explicit imports.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-01 19:04:31 -07:00
Lars-Peter Clausen 3679d25e4b Honor package import lexical order during identifier lookup
Package imports become visible from the import declaration, or for wildcard
imports, from the reference that makes an identifier locally visible. For
example:

    package p;
      parameter X = 2;
    endpackage

    parameter X = 1;

    module m;
      localparam A = X;
      import p::X;
      localparam B = X;
    endmodule

Currently both `A` and `B` resolve to `p::X`. `A` should resolve to the
compilation-unit `X`, while only `B` should resolve to `p::X`.

Record the lexical position where each imported name becomes locally visible.
Pass reference positions through ordinary symbol lookup and implicit named
port connections so imports introduced later are ignored.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-08-01 19:04:31 -07:00
Lars-Peter Clausen eda9fdcd13 Add regression test for imported typedef reference order
Check that a typedef reference in a nested scope keeps the package typedef
selected during parsing when another typedef with the same name is imported
later. Check that a reference following the import selects the new typedef.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-26 20:14:31 -07:00
Lars-Peter Clausen 41f4ff0fbc Use the bound typedef to find its declaration scope
Type names are resolved to `typedef_t` objects during parsing. During
elaboration `find_typedef_scope()` currently resolves the name again through
the completed import table. An import appearing after the original reference
can therefore redirect it to a different typedef with the same name.

Search the enclosing and package scopes for the exact `typedef_t` object
instead. This preserves the parsing-time binding and returns the scope that
owns the selected typedef.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-26 20:14:31 -07:00
Lars-Peter Clausen 8df804c273 Add regression tests for wildcard port declaration order
Check separately that a wildcard port connection ignores a declaration after
the module instance in strict mode and uses the port default.

Check the exact position of `.*`: an implicit net created by an explicit
connection before `.*` is connected, while one created after `.*` is not.
Check that `-gno-strict-net-var-declaration` preserves relaxed behavior and
binds a declaration introduced after `.*`.

Run all three tests through the native and vlog95 backends.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-26 20:14:20 -07:00
Lars-Peter Clausen 8997c01d6f Honor declaration order for wildcard port connections
IEEE 1800-2023 section 23.3.2.4 defines a `.*` connection as equivalent
to an implicit `.name` connection for every port not connected explicitly.
The existing `.name` path resolves the matching identifier at the
connection's lexical position. Wildcard port matching instead searches at
the end of the scope, making it find declarations after the connection:

    child i_child(.*);
    wire value;

Use the lexical position carried by the wildcard binding when looking up
and creating wildcard connections. The position of `.*` itself matters
because an earlier explicit port connection can create an implicit net
that the wildcard connection should see:

    child i_child(.source(value), .*);

This also preserves the relaxed lookup provided by
`-gno-strict-net-var-declaration`.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-26 20:14:20 -07:00
Lars-Peter Clausen 5f479cbad4 Store lexical positions in LineInfo
Several source and netlist objects inherit `LineInfo` while separately
storing the lexical position associated with the same source location. This
requires callers to copy the file, line, and lexical position independently.

Add the lexical position to `LineInfo`. Have `set_line()` initialize it when
it is unset, so new objects inherit the complete source location while later
diagnostic location updates preserve their established declaration order.
Initialize the field to `UINT_MAX` so zero remains available as a valid
scanner position and missing initialization is distinguishable. Have
`FILE_NAME()` preserve a more precise identifier position.

Remove constructor parameters that duplicate the position supplied through
`FILE_NAME()`. Use the shared field for identifiers, wires, events, event
triggers, nets, and elaborated events. Assign static class property nets
their declaration location since they previously relied on the standalone
`NetNet` position defaulting to zero.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-26 20:14:20 -07:00
Lars-Peter Clausen beaf44895a Use LineInfo::set_line() to copy source locations
Some elaboration paths copy the file and line from a LineInfo object
individually. Use set_line() instead. This keeps the copies together when
LineInfo is extended with additional source location information.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-26 20:14:20 -07:00
Cary R. a4989d023d Merge pull request #1422 from muhammadjawadkhan/split/06-sv-array-ordering
SV: reverse(), sort(), rsort(), shuffle() for queues/darrays
2026-07-21 00:00:54 -07:00
mjoekhan 9378bbf337 SV: address review feedback for array ordering methods
Drop redundant eeq checks in descending vec4 sorts, brace reverse loops,
and merge duplicate queue/darray class-property method elab.
2026-07-21 11:48:54 +05:00
mjoekhan f796a59367 SV: merge darray/queue method checks in elab_expr
Combine the nearly identical dynamic-array and queue method blocks in
test_width_method_ and elaborate_expr_method_ (including class property
paths), keeping queue-only pop_front/pop_back gated on queue type.
2026-07-21 11:05:57 +05:00
mjoekhan afe849249c SV: reverse(), sort(), rsort(), shuffle() for queues/darrays
Add ordering methods for queues and dynamic arrays.  Update ivtest gold
files for always_*_warn, br1005, and br_gh710b LXT per review.

Split from steveicarus/iverilog#1330 (part 06/6).
2026-07-21 11:01:29 +05:00
Cary R. f0b6d3addc Merge pull request #1421 from muhammadjawadkhan/split/05-sv-sum-product
SV: sum() and product() reductions on queues/darrays
2026-07-20 22:51:40 -07:00
mjoekhan e628e6c8c5 SV: sum() and product() reductions on queues/darrays
Add integral sum() and product() reductions, including expression
forms, for queues, dynamic arrays, and class properties.

Split from steveicarus/iverilog#1330 (part 05/6).
2026-07-21 10:32:45 +05:00
Cary R. 31d1850bc8 Merge pull request #1445 from larsclausen/procedural-block-prefix-label
Support prefix labels on procedural blocks
2026-07-20 21:32:25 -07:00
Cary R. 402c96583f Merge pull request #1444 from larsclausen/assertion-item-label-type-id-shadow
Support assertion item labels shadowing type identifiers
2026-07-20 21:29:37 -07:00
Cary R f5e496b032 cppcheck cleanup 2026-07-20 21:24:03 -07:00
Lars-Peter Clausen 9c56f0172d Add regression tests for prefix labels on procedural blocks
Check the reproducer from GitHub issue #1321, which uses a prefix label on a
begin-end block inside an `always_comb` process.

Check prefix labels on sequential and parallel blocks. Place attributes between
the labels and block keywords, verify that the sequential label creates a named
scope, cover all fork join types, and use matching closing labels.

Check separately that visible type identifiers can be shadowed by prefix labels
on sequential and parallel blocks.

Check that matching and different block names after `begin` or `fork` are
rejected when a prefix label is already present.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-20 20:55:48 -07:00
Lars-Peter Clausen fd902d1501 Support prefix labels on procedural blocks
SystemVerilog sequential and parallel blocks allow a block identifier before
the `begin` or `fork` keyword:

    LABEL: begin
      statement;
    end

    LABEL: fork
      statement;
    join

The parser currently only accepts the block identifier after `begin` and
`fork`. Add a prefix-label rule using `identifier_name`. This accepts labels
returned as either `IDENTIFIER` or `TYPE_IDENTIFIER` without duplicating the
label grammar. The mixed procedural item list lets the parser use the following
`:` to distinguish a visible type identifier used as a label from the start of
a variable declaration.

Use a shared optional prefix rule for sequential and parallel block forms.
Resolve the prefix and post-keyword names before starting the common block path,
and bind attributes placed between the label and block keyword. Require
SystemVerilog mode when a prefix label is present.

IEEE 1800-2023 section 9.3.5 does not allow a prefix label and a block name
after `begin` or `fork` at the same time. Report an error for this form while
keeping it in the grammar for error recovery. Keep the existing closing label
handling, which allows a matching name after `end` or a join keyword.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-20 20:31:23 -07:00
Lars-Peter Clausen dcc8e93d7e Factor procedural block parsing
The sequential and parallel block grammar duplicates scope setup and teardown,
statement transfer, and closing label handling.

Move the common logic into `pform_start_block()` and
`pform_finish_block()`. This keeps the grammar actions focused on their
syntax-specific checks and makes both block forms use the same scope and
statement ownership paths without changing the accepted syntax.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-20 20:29:48 -07:00
Cary R. 1cf8133420 Merge pull request #1420 from muhammadjawadkhan/split/04-sv-class-prop-locators
SV: locator methods on class queue/darray properties
2026-07-20 18:02:30 -07:00
mjoekhan 78aa852bf1 SV: apply caryr if-style formatting to locator runtime
Use single-line early returns and same-line simple if bodies, matching
the formatting conventions from #1416/#1418 reviews.
2026-07-20 21:08:21 +05:00
mjoekhan 243dccc368 SV: locator methods on class queue/darray properties
Extend locator methods to class queue and dynamic-array properties,
including min/max, unique/min/max with-predicates, and VVP array-pattern
object handling. Built on the #1419 locator helpers.

Split from steveicarus/iverilog#1330 (part 04/6).
2026-07-20 20:41:19 +05:00
Lars-Peter Clausen 713ad762af Add regression test for assertion item labels shadowing type identifiers
Check that a visible type identifier can be shadowed by labels on module
level assertion items. Cover both a concurrent assertion item and a
deferred immediate assertion item.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-19 20:19:07 -07:00
Lars-Peter Clausen a0e5240109 Support assertion item labels shadowing type identifiers
SystemVerilog assertion item labels use ordinary identifiers. A visible
type identifier should therefore be accepted as the label on a module
level assertion item:

    typedef int CHECK;
    module test;
      CHECK: assert property (1);
    endmodule

Procedural assertion statements already accept either identifier token in
their optional label rule. Reusing that rule for module level concurrent
and deferred assertion items exposes a declaration ambiguity: module items
can also start with a typedef name followed by a variable declaration.

Keep the grammar conflict-free by parsing typedef-start variable
declarations in a single production that includes the first declarator.
This lets the parser see `:` before reducing the typedef-start declaration
path, so module and procedural assertions can share the same label rule
while preserving the existing declaration handling for typedef data types.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-19 20:19:07 -07:00
Lars-Peter Clausen 11af9fb3b3 Add regression tests for procedural labels shadowing type identifiers
Check that a visible type identifier can be reused as a procedural assertion
label after a declaration in both task and block bodies. These are the contexts
where label and declaration parsing meet.

Also check that a null statement ends the declaration portion of a procedural
body and a following declaration is rejected.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-19 20:12:11 -07:00
Lars-Peter Clausen 173f6af729 Support shadowing type identifiers in procedural labels
SystemVerilog procedural labels use ordinary identifiers. A visible type
identifier can therefore also be used as a label:

    typedef int T;
    module test;
      initial begin
        T value;
        T: assert (1);
      end
    endmodule

The parser currently handles procedural declarations and statements as
separate lists. After `T value;`, it must decide whether the next
`TYPE_IDENTIFIER` starts another declaration before it can see that the
following `:` makes it an assertion label. Extending the label rule alone
therefore introduces parser conflicts.

Replace the separate lists with a mixed procedural item accumulator so the
parser can keep the declaration-or-statement decision open. Track whether
declarations have been seen, use allocation of the statement vector to record
whether a statement has been seen, collect concrete statements and old-style
task/function ports, and reject a declaration after a statement. A null
statement allocates an empty statement vector and therefore also starts the
statement section, preserving the existing declaration ordering rule. Own the
accumulated statement and port vectors with `unique_ptr` and release old-style
port vectors only when transferring them to a task or function.

Parse assertion labels as `identifier_name ':'` and use the accumulator for
constructors, functions, tasks, and sequential and parallel blocks. Keep the
temporary scope for an unnamed block until its body has been classified. If it
has no declarations, move nested named scopes into the enclosing scope and
reparent them before discarding the temporary scope.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-19 20:12:11 -07:00
Lars-Peter Clausen 36f013f97f Factor statement-or-null grammar
`statement_or_null` currently reaches statements and null statements through
an optional attribute list. Reducing that empty prefix before the parser knows
which form follows makes the rule difficult to use in a mixed procedural item
list without conflicts.

Expand the rule into explicit attributed and unattributed statement and null
forms. This preserves attribute binding and null-statement behavior while
allowing the parser to distinguish the forms from their leading token.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-19 20:12:11 -07:00
Lars-Peter Clausen 97928cfb15 Factor block variable declaration grammar
Block variable declarations currently combine optional `const` and lifetime
qualifiers with the data type. This requires reducing empty qualifier rules
before the parser can determine which declaration form follows, making the
rule difficult to use in a mixed procedural item list without conflicts.

Split the declaration productions according to their leading syntax. Share
required and optional variable lifetime handling and add a rule for data types
following the historical leading `reg` extension. This keeps the declaration
behavior unchanged while allowing the parser to distinguish each form from
its leading token.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-19 20:12:11 -07:00
Lars-Peter Clausen 7792b5ab8a Fix locations of unattributed statements
The `statement` and null-statement rules start with an optional attribute
list. When it is empty, the reduced location starts at the previous token
instead of the statement. Diagnostics using that location can consequently
point to the beginning of the source file.

Use the statement or semicolon location when no attributes are present.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-19 20:12:11 -07:00
Lars-Peter Clausen 3c3f46099d Add regression tests for interface identifier names
Check separately that a visible interface name can be reused as a member,
modport, interface port, ordinary port, interface instance and procedural block
name.

Also check an attributed forward interface port type after another ANSI port
declaration.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-18 11:22:09 -07:00
Lars-Peter Clausen 60f366790b Remove special interface identifier token
The lexer currently returns `INTERFACE_IDENTIFIER` for names of interfaces
that have already been parsed. There are two issues with this approach:

1. Once an interface has been parsed, its name can no longer be used in
   grammar positions that accept an ordinary identifier.
2. The LRM allows an interface to be used before its declaration. Before the
   declaration has been parsed, however, the name remains an ordinary
   identifier and can not be accepted by productions requiring
   `INTERFACE_IDENTIFIER`. Lexer lookahead tries to recognize forward
   interface port types, but this depends on parser-managed port-list state
   and does not cover all cases.

Parse interface port declarations from ordinary `IDENTIFIER` tokens instead.
An interface port can not simply be added to `port_declaration` using an
`IDENTIFIER` token. This creates a shift/reduce conflict on the identifier at
the start of the port list. Shifting starts an old-style `port_reference`,
while reducing the empty `attribute_list_opt` starts an interface
`port_declaration`. The parser has not yet seen the following identifier or
`.` that distinguishes the two forms.

Add leading interface port declarations as base cases of
`list_of_port_declarations`. Both the old-style and ANSI port-list rules can
then shift the common identifier and use the following identifier or `.` to
distinguish the interface port. Keep a separate base case for a non-empty
attribute list so no empty reduction is needed before the identifier. Handle
later interface ports in the recursive list rule and use
`interface_port_modport_opt` to share the forms with and without a modport.
Interface instances can use the existing module instantiation rules.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-18 11:22:09 -07:00
Cary R. 35a809d55b Merge pull request #1419 from muhammadjawadkhan/split/03-sv-locator-methods
SV: queue/darray locator methods (find*, unique*, min/max)
2026-07-16 14:10:18 -07:00
mjoekhan 9740f7bc76 SV: refactor locator elaboration and tgt-vvp lowering
Collapse duplicated unique*/find* paths into parameterized helpers
and table-driven opcode emission so adding types does not require
copying whole method blocks. Align multi-line call arguments.
2026-07-16 23:45:41 +05:00
mjoekhan e3222e77ad SV: queue/darray locator methods (find*, unique*, min/max)
Add find*, unique*, min/max, and with-predicate locator methods for
queues and dynamic arrays, with VVP runtime support and ivtest.

Split from steveicarus/iverilog#1330 (part 03/6).
2026-07-15 22:49:12 +05:00
Cary R 614607c135 Cppcheck fixes in vvp 2026-07-14 01:31:09 -07:00
Cary R dec4e939f4 Fix compile issues in previous patch 2026-07-14 00:09:31 -07:00
Cary R e367080276 Fix incorrect definition 2026-07-14 00:09:24 -07:00
Cary R e4bede3c76 Fix some compile warnings under mingw/cygwin 2026-07-13 23:51:10 -07:00
Cary R. 812c1cedcb Merge pull request #1418 from muhammadjawadkhan/split/02-sv-chained-calls
SV: chained method calls a().b()
2026-07-13 23:05:04 -07:00
Cary R. 67d39803e6 Fix formatting and add braces for clarity 2026-07-13 22:54:26 -07:00
Cary R. 55250457ed Fix formatting in parse.y for call_chain_expr 2026-07-13 22:50:55 -07:00
Cary R. 29a8a4d052 Simplify conditional checks in elab_expr.cc 2026-07-13 22:48:28 -07:00
mjoekhan 4a505546a1 SV: chained method calls a().b()
Add parsing and elaboration for chained calls on expression results,
with sv_call_chain_method1 regression.

Split from steveicarus/iverilog#1330 (part 02/6).
2026-07-13 18:48:30 +05:00
Cary R 15689210c1 Fix the building of libvvp.pc 2026-07-12 17:33:29 -07:00
Cary R e5482b89b1 Fix compile warning 2026-07-12 10:05:55 -07:00
Cary R d376375020 Fix br1005 tests for fsv and vlog95 2026-07-12 10:05:49 -07:00
Cary R. d15f24ff49 Merge pull request #1416 from muhammadjawadkhan/split/01-sv-class-queue-darray-props
SV: class queue/darray property foundation
2026-07-12 08:18:25 -07:00
Cary R. 2ff0be6bfd Fix conditional check for net class type 2026-07-12 08:00:14 -07:00
Cary R. e7233856c8 Simplify conditional return statements 2026-07-12 07:57:09 -07:00
Cary R. 9a7178fef0 Refactor format_darray_pretty for readability 2026-07-12 07:52:48 -07:00
Cary R. 82350c4866 Fix conditional block for boolean type handling 2026-07-12 07:44:20 -07:00
Cary R. 4d07a8466c Merge pull request #1439 from larsclausen/ams-type-id-shadow
Support discipline and nature names shadowing type identifiers
2026-07-12 07:20:11 -07:00
Lars-Peter Clausen 0e3ac8685c Add regression tests for discipline and nature type identifier names
Check that nature and discipline declaration names can match visible type
identifiers. Also check `potential` and `flow` references to nature names that
are visible as type identifiers.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-11 17:47:52 -07:00
Lars-Peter Clausen 1d623a67d1 Support discipline and nature names shadowing type identifiers
Verilog-AMS nature and discipline declarations can use names that are also
visible as type identifiers. The `potential` and `flow` discipline items can
likewise reference a nature whose name is returned as `TYPE_IDENTIFIER` by the
lexer. These grammar positions currently only accept `IDENTIFIER`.

Use `identifier_name` for nature and discipline declaration names and for the
`potential` and `flow` nature references.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-11 17:44:54 -07:00
Lars-Peter Clausen a540a7a163 Add regression tests for for and foreach type identifier names
Check that a for loop variable declaration can use the same name as a
visible typedef, including references from the loop condition and step
expressions.

Also check that procedural foreach can parse an array expression name that
is initially seen as a type identifier. Declare the array after the loop so
the parser sees the outer typedef while parsing the foreach header, then
elaboration resolves the array declaration as a module item.

Use unsigned variables and omit the foreach iterator because these tests do
not depend on signed values or iteration behavior. This lets both tests run
through the vlog95 backend as normal regressions.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-11 15:58:18 -07:00
Lars-Peter Clausen 9ec8f8e2dd Support for and foreach identifiers shadowing type identifiers
SystemVerilog allows a declaration in an inner scope to use the same name as
a type identifier from an outer scope. The lexer reports such names as
`TYPE_IDENTIFIER` until the new declaration has been installed.

The parser previously created the synthetic loop scope and declared the loop
variable only after parsing the complete `for` header. When the variable name
matches a visible typedef, this is too late: the lexer can continue returning
`TYPE_IDENTIFIER` for references to the variable in the initializer,
condition, and step expressions. Accept `identifier_name` for the declaration
name and create the loop scope and variable in a mid-rule action immediately
after it, so the declaration is visible while the rest of the header is
parsed.

The executable foreach grammar also used to require the array expression name
before the index list to be an `IDENTIFIER`. Use `identifier_name` there as
well, since this position is an expression name followed by `[` and not a type
name.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-11 15:58:18 -07:00
Lars-Peter Clausen 36a79568b7 Add regression tests for attribute names matching type identifiers
Check that a standard attribute name can match a visible typedef. Also check
that the global `$attribute` extension can target a primitive whose name is
visible as a type identifier.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-11 15:58:02 -07:00
Lars-Peter Clausen ee14022127 Support type identifier names in attributes
Standard attribute names and target names in both forms of the Icarus
`$attribute` extension are unambiguous identifier positions. When such a name
matches a visible typedef the lexer returns `TYPE_IDENTIFIER`, while the
grammar only accepts `IDENTIFIER`.

Use `identifier_name` for all of these positions.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-11 15:58:02 -07:00
Cary R. 0723d9a477 Merge pull request #1435 from larsclausen/br-gh1385-vlog95
ivtest: Run nested enum tests through vlog95
2026-07-10 10:43:04 -07:00
Cary R. f8069416f2 Merge pull request #1434 from larsclausen/parameter-omit-implicit-type
parser: Reject implicit parameter types without parameter
2026-07-10 10:42:15 -07:00
Lars-Peter Clausen c0cf842eb2 ivtest: Move parameter omit tests to JSON
The parameter_omit tests have different expectations depending on whether the
regression is run in the default Verilog mode or with force SystemVerilog.
The old list files modelled this by registering the same tests in both
regress-vlg.list and regress-fsv.list.

Move the tests to JSON descriptors. Use the existing force-sv override for the
forms that are valid SystemVerilog, and keep the implicit type cases as CE in
both modes. This also runs the tests through the additional configurations
supported by vvp_reg.py, providing better coverage in CI.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-09 20:49:01 -07:00
Lars-Peter Clausen 20a34d33c6 parser: Reject implicit parameter types without parameter
The LRM allows omitting the `parameter` keyword in a module parameter port
list, but the optional type in that form is a data_type, not an implicit
data type. A parameter port list like this is therefore invalid:

    module M #([3:0] P = 1);

The parameter declaration grammar was reusing the general
value_parameter_assign_with_type rule for the omitted-keyword form. That rule
also accepts implicit types so that ordinary `parameter signed P = 1`
declarations work, which made the omitted-keyword form accept implicit types
as well.

Add a separate rule for value parameter assignments without the `parameter`
keyword. The rule still accepts bare identifiers and explicit data types so a
parameter name can shadow a visible typedef name, but it rejects implicit
types.

Fixes: e56c93a2be ("Support shadowing type identifiers in parameter declarations")
Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-09 20:49:01 -07:00
Lars-Peter Clausen f870c755fa ivtest: Run nested enum tests through vlog95
The br_gh1385a, br_gh1385b, and br_gh1385c JSON descriptors mark the vlog95
variants as compile errors. The enum typedefs are translated correctly, so the
compile error expectation causes the tests to fail when compilation succeeds.

Remove the stale overrides and run the translated tests through vlog95.

Fixes: 10349287a0 ("Add regression tests for enum typedefs in nested scopes")
Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-09 20:45:55 -07:00
Lars-Peter Clausen 3e0c298b25 Add regression tests for named selectors matching typedef names
Check that a named binding selector can have the same text as a visible typedef
name. Cover named module port connections, named parameter overrides, and named
task, function and constructor arguments.

Also check that a modport simple port selector can shadow a visible typedef
name. Modport simple port aliases share the same parser rule but declare the
modport-visible name rather than binding to an existing formal.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-09 20:08:25 -07:00
Lars-Peter Clausen 6844ed4194 Accept type-identifier tokens in named binding selectors
A named binding selector such as `.T(expr)` names an existing formal port,
parameter, task or function argument, or constructor argument. It is not a
declaration of a new identifier. If a visible typedef named `T` exists at the
use site the lexer returns `TYPE_IDENTIFIER`, which made the parser reject the
binding selector.

Modport simple port aliases use the same grammar, but are slightly different:
the selector is the modport-visible port name and can shadow a visible typedef
name in the interface scope.

Use `identifier_name` for the selector name in `named_expression` and
`named_expression_opt`. This covers named parameter overrides, named task and
function arguments, named constructor arguments, and modport simple port
aliases. Also use `identifier_name` in the named module port connection rules,
including implicit named port connections and error recovery.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-09 20:08:25 -07:00
mjoekhan 9880fb8d5e SV: class queue/darray property foundation
Fold in Windows VPI routing for vpip_format_pretty, fix queue method
argument elaboration via elaborate_rval_expr, reject class tasks used as
expressions cleanly, and update br1005 now that class queues compile.

Review follow-up: move vpip_format_pretty to vpip_format.cc with
diagnostic return strings, restore NetNet-based queue method elaboration
with a separate property path, drop spurious /devel/ from .gitignore,
and bump copyright years on touched files.

Formatting pass per inline review: brace style for multi-line if bodies,
||/&& at end-of-line continuations, switch/case indentation, single-line
if returns, NetNet-based sys_task_method_ again, and aligned extern decls.
2026-07-07 00:46:45 +05:00
Cary R. e02a0bc2ec Merge pull request #1431 from larsclausen/event-variable-type-id-shadow
Support event names shadowing type identifiers
2026-07-06 09:32:00 -07:00
Lars-Peter Clausen abfb4e83bc Add regression test for event names shadowing type identifiers
Check that event declarations can use visible type identifiers as event names.
Also check that the resulting named event can be triggered and waited on.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-05 21:44:44 -07:00
Lars-Peter Clausen 17ca0948f4 Support event names shadowing type identifiers
SystemVerilog allows a declaration in an inner scope to use the same name as a
type identifier from an outer scope. This also applies to named event
declarations. The lexer reports such names as `TYPE_IDENTIFIER` before the
event has been installed, which made constructs such as:

    typedef int T;
    module test;
      event T;
    endmodule

fail in the event declaration grammar.

Event declarations do not have the local type/name ambiguity that exists for
variable, net, or parameter declarations. The name in `event_variable` is
always the event name. Use `identifier_name` so a `TYPE_IDENTIFIER` token can
be accepted as the event name.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-05 21:44:44 -07:00
Lars-Peter Clausen f6848300b7 Add regression tests for block labels shadowing type identifiers
Check that visible type identifiers can be reused as named block labels. Cover
procedural `begin` blocks, fork blocks, and conditional generate blocks. Also
check matching end labels where the grammar consumes the shared `label_opt`
rule.

The generate test keeps the existing vlog95 compile-error expectation because
named generate scopes are not translated by the vlog95 target.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-05 21:36:32 -07:00
Lars-Peter Clausen 06740d0dda Support block labels shadowing type identifiers
SystemVerilog allows a named block label in an inner scope to use the same
name as a visible type identifier from an outer scope. The lexer reports such
names as `TYPE_IDENTIFIER` before the label has been installed, which made
constructs such as:

    typedef int T;
    module test;
      initial begin
        begin : T
        end : T
      end
    endmodule

fail in the block label grammar.

The affected grammar positions are label names, not declarations with an
adjacent type/name ambiguity. Use `identifier_name` for `label_opt` and for the
anachronistic named generate begin form so a token returned as `TYPE_IDENTIFIER`
can still be accepted as the label name. With `label_opt` able to handle
`TYPE_IDENTIFIER`, the separate class end-label rule is no longer needed.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-05 21:36:32 -07:00
Lars-Peter Clausen 15277c9fa4 Add regression test for package names shadowing type identifiers
Check that a package declaration can use a visible type identifier as its
package name. Also check that the resulting package scope can be selected with
a scope-qualified reference.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-05 21:36:18 -07:00
Lars-Peter Clausen ca5c6fc59f Support package names shadowing type identifiers
SystemVerilog allows a package declaration to use a name that is also visible
as a type identifier. The lexer reports such names as `TYPE_IDENTIFIER` before
the package has been installed, which made constructs such as:

    package p;
      typedef int T;
    endpackage
    import p::*;
    package T;
    endpackage

fail in the package declaration grammar.

Package declarations do not have the local type/name ambiguity that exists for
variable, net, or parameter declarations. After the optional lifetime the next
token is always the package name. Use `identifier_name` so a
`TYPE_IDENTIFIER` token can be accepted as the package name.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-05 21:36:18 -07:00
Lars-Peter Clausen 2cef311be2 Make Bison parser conflicts errors
Bison reports shift/reduce and reduce/reduce parser conflicts as warnings by
default. This allows parser changes to introduce new conflicts while the normal
build still succeeds.

Pass the conflict warning classes as errors to Bison when generating the
parsers. This makes the regular build fail if either parser has unresolved
conflicts.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-05 21:36:03 -07:00
Lars-Peter Clausen ff0b4a3154 parser: Fix parameter assignment grammar conflict
The parameter declaration grammar allows a visible type identifier to be used
as a parameter name. The assignment continuation rule still used
`identifier_name`, which made Bison reduce a `TYPE_IDENTIFIER` before it had
seen whether following dimensions belonged to the parameter name or to an
explicit type identifier.

Match ordinary and type identifiers directly in `parameter_assign` so the
parser can shift dimensions before deciding between a parameter name and an
explicit parameter type.

Fixes: e56c93a2be ("Support shadowing type identifiers in parameter declarations")
Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-05 21:36:03 -07:00
Lars-Peter Clausen 2b67d9f754 Add regression tests for UDP names shadowing type identifiers
Check that UDP primitive and port names can shadow visible type identifiers.
Cover old-style UDP declarations, including input and output declarations and
the initial target, as well as ANSI-style UDP port declarations.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-05 13:58:11 -07:00
Lars-Peter Clausen 56c42dcf37 Support UDP names shadowing type identifiers
SystemVerilog allows a UDP primitive or UDP port declaration to use the same
name as a visible type identifier from another namespace or outer scope. The
lexer reports such names as `TYPE_IDENTIFIER` before the UDP name has been
installed, which made constructs such as:

    typedef int T;
    primitive T (Q, A);
      output Q;
      input A;
      table
        0 : 0;
      endtable
    endprimitive

fail in the UDP grammar.

UDP primitive and port names do not have the local type/name ambiguity that
exists for variable, net, or parameter declarations. Use `identifier_name` for
the primitive name, the UDP port list, UDP port declarations, and the UDP
initial target so a `TYPE_IDENTIFIER` token can be accepted as the UDP name.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-05 13:58:11 -07:00
Lars-Peter Clausen c8568998af Add regression tests for UDP declaration diagnostics
Check that UDP initial values on non-registered outputs generate compile
errors for both old-style and ANSI-style UDP declarations. Also check that
conflicting UDP port declarations generate an error and that a valid
ANSI-style `output reg` initializer is accepted.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-05 13:57:30 -07:00
Lars-Peter Clausen 8d4faf2744 Report UDP declaration errors instead of asserting
Malformed UDP declarations can reach `pform_make_udp()` with conflicting
duplicate port declarations or with an initial value on an output that was not
declared as a register. These cases currently trigger internal assertions
instead of reporting normal compile errors.

The ANSI-style UDP output initializer path also treats the initializer
expression as if it was the old-style `initial out = value` assignment
statement. This makes a valid `output reg out = 1'b0` initializer assert as
well.

Report errors for the invalid declarations and read the ANSI-style initializer
value directly from the initializer expression.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-05 13:57:30 -07:00
Cary R. 025cbcc81f Merge pull request #1426 from larsclausen/enum-item-type-id-shadow
Support enum items shadowing type identifiers
2026-07-04 07:29:07 -07:00
Cary R. b6829ab504 Merge pull request #1425 from larsclausen/taskfunc-type-id-shadow
Support task and function names shadowing type identifiers
2026-07-04 07:26:52 -07:00
Lars-Peter Clausen 43817251f4 Add regression test for enum items shadowing type identifiers
Check that enum item names can shadow visible type identifiers. Cover plain enum
items as well as the counted and ranged enum item sequence forms.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-03 18:13:51 -07:00
Lars-Peter Clausen 0c7341be37 Support enum items shadowing type identifiers
SystemVerilog allows a declaration in an inner scope to use the same name as a
type identifier from an outer scope. This also applies to enum item names. The
lexer reports such names as `TYPE_IDENTIFIER` before the enum item has been
installed, which made constructs such as:

    typedef int T;
    module test;
      enum { T = 1 } e;
    endmodule

fail in the enum item grammar.

Enum item declarations do not have the local type/name ambiguity that exists for
variable, net, or parameter declarations. The name in each `enum_name`
production is always the enum item name, including the sequence forms like
`T[2]` and `T[1:2]`. Use `identifier_name` for these names so they can shadow a
visible type identifier.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-03 18:10:54 -07:00
Lars-Peter Clausen 21b0107bae Add regression tests for type identifier task and function names
Check that function and task declarations can use a visible type identifier as
the declaration name. Cover both ANSI declarations and the non-ANSI forms where
the name is parsed without a separate return type or port list.

Also check class method declarations where the method name is the same as the
enclosing class name. Add GitHub issue #670 coverage for the `function void`
case using the issue-based regression naming scheme.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-03 17:33:07 -07:00
Lars-Peter Clausen 24743af7d5 Support task and function names shadowing type identifiers
SystemVerilog allows a declaration in an inner scope to use the same name as a
type identifier from an outer scope. This also applies to task and function
names. The lexer reports such names as `TYPE_IDENTIFIER` before the new task or
function has been installed, which made constructs such as:

    typedef int T;
    module test;
      function int T(input int value);
        return value;
      endfunction
      task T;
      endtask
    endmodule

fail in the task and function declaration grammar. A class method with the same
name as the class itself hits the same problem because the class name is visible
as a type identifier in the class scope.

The task grammar can accept `identifier_name` directly, because a task has no
return type and the token after `task` and the optional lifetime is always the
task name.

Function declarations have a local return-type/name ambiguity. After
`function T` the parser does not know yet whether `T` is the function name with
no explicit return type, or whether a following identifier will make `T` the
explicit return type as in `function T f`. Parse the optional function return
type and function name together. This allows a `TYPE_IDENTIFIER` token to be
interpreted as the function name when no separate function name follows, while
still parsing typed forms and `void` return types correctly.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-03 17:29:40 -07:00
Cary R. 60a81493cd Merge pull request #1424 from larsclausen/type-id-parameter-declarations
Support shadowing type identifiers in parameter declarations
2026-07-03 07:14:53 -07:00
Lars-Peter Clausen bc6d421ff2 Add regression tests for parameter declarations shadowing type identifiers
Check that visible type identifiers can be shadowed by value parameter names
and by type parameter names. Cover ordinary parameter declarations, typed
parameter declarations, and parameter port list declarations separately.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-02 19:32:32 -07:00
Lars-Peter Clausen e56c93a2be Support shadowing type identifiers in parameter declarations
SystemVerilog allows a visible type identifier to be shadowed by a
parameter declaration name. Parameter declarations still required the
parameter name to be an `IDENTIFIER` token and rejected declarations like:

    typedef int P;
    module test;
      parameter int P = 1;
    endmodule

The parameter grammar can not just accept `TYPE_IDENTIFIER` in every name
position. After `parameter P` the parser does not know yet whether `P` is
the parameter name, or whether a following identifier will make `P` the
parameter type.

Parse the optional value parameter type and the first parameter assignment
together. This allows a `TYPE_IDENTIFIER` token to be interpreted as the
parameter name when no explicit type is present, while still parsing a
following identifier as the parameter name for typed parameters.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-02 19:32:32 -07:00
Cary R. 98d10727f2 Merge pull request #1423 from larsclausen/type-id-class-property
Support class properties shadowing type names
2026-07-02 19:01:57 -07:00
Cary R. 50b477bc1f Merge pull request #1404 from sifferman/param-string-compare
Fix assert on constant == with unequal-length string operands
2026-07-02 18:57:44 -07:00
Lars-Peter Clausen 5364f11d16 Add regression tests for class properties shadowing type names
Check that a class property can have the same name as a type declared in
an outer scope, or a type imported through a wildcard import. Also check
that a class property can have the same name as the class itself.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-02 16:58:42 -07:00
Lars-Peter Clausen dc66f2fe7e Support class properties shadowing type names
SystemVerilog allows a class property to have the same name as a visible
type. The lexer reports the visible type name as `TYPE_IDENTIFIER` before
the property has been installed, which made constructs such as
`typedef int T; class C; int T; endclass` fail in the class item grammar.
A class property with the same name as the class itself hits the same
problem. Member references such as `obj.T` or `obj.C` can also hit the
same tokenization problem in hierarchical names.

Parse class properties through the same declaration helper used for
variables so the first type/name pair can be disambiguated. Also let
hierarchical member names use `identifier_name`.

Stop type lookup when a class scope already has a property with the same
name. This makes method body references resolve as properties instead of
visible types, including type names found through wildcard imports.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-07-02 16:58:42 -07:00
Ethan Sifferman e2ab464656 Fix unequal-length string comparison 2026-07-02 16:21:17 -07:00
Cary R. d01efc910b Merge pull request #1415 from larsclausen/aa-pattern-terms
Detect automatic terms in assignment patterns
2026-07-02 10:00:36 -07:00
Cary R. 158d7b76f2 Merge pull request #1414 from larsclausen/nb-ec-repeat-auto
Allow repeat expression in event control to contain automatic terms
2026-07-02 09:59:07 -07:00
Cary R. 823aa224db Merge pull request #1413 from larsclausen/type-id-vars-wires
Support declaration names shadowing type identifiers
2026-07-02 09:52:03 -07:00
Cary R 5a99d0e449 Update to the latest config.guess and config.sub files 2026-07-01 09:10:08 -07:00
Lars-Peter Clausen 9bbdb0da0e Add regression test for automatic terms in assignment patterns
Check that automatic variables referenced through an assignment pattern in a
procedural `force` statement are rejected.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-30 18:25:52 -07:00
Lars-Peter Clausen 9bff2399df Detect automatic terms in assignment patterns
Assignment patterns contain child expressions, but currently inherit
`PExpr::has_aa_term()` which always returns false. This means automatic
variables inside a pattern are not caught by checks for procedural `force`
and procedural continuous assignment statements.

Implement `has_aa_term()` for `PEAssignPattern` and recurse into all pattern
elements.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-30 18:25:52 -07:00
Lars-Peter Clausen f358b3fa8f Add regression test for automatic event control repeat counts
Check that the repeat count expression of a non-blocking intra-assignment
event control can reference an automatic task argument. The repeat count is
evaluated when the assignment is scheduled, so the automatic variable is not
referenced after the task scope is freed.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-30 16:58:32 -07:00
Lars-Peter Clausen be298d1cca Allow repeat expression in event control to contain automatic terms
The repeat expression of an event controlled non-blocking assignment is
evaluated once when the assignment is scheduled. This means there is no
risk of it being referenced when its scope has already been freed. And
hence there is no need to require the repeat expression to only contain
static terms.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-30 16:20:06 -07:00
Lars-Peter Clausen 89b2c8bd80 Add regression tests for declaration names shadowing type identifiers
Check that variable and net declaration names can shadow a visible type
identifier. Check this for explicit data type declarations, `var` declarations,
and net declarations.

Check that task and function formal argument names can shadow a visible type
identifier, and that typed arguments still use the visible typedef when an
argument name follows.

Check ambiguous module port declarations where a type identifier can be either
the port name or the port type, with and without dimensions, and that
declaration lists continue to use the type selected by the first ambiguous
declarator. Cover both ANSI and non-ANSI module port declarations.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-30 14:47:54 -07:00
Lars-Peter Clausen 7cffbf440d Support declaration names shadowing type identifiers
SystemVerilog allows a declaration in an inner scope to use the same name as a
type identifier from an outer scope. The lexer reports such names as
`TYPE_IDENTIFIER` before the new declaration has been installed, which made
constructs such as `int T;`, `wire T;`, and `input T` fail when `T` was a
visible typedef.

The affected declaration forms have a local type/name/dimension ambiguity. For
example, after `input T` or `wire T` the parser does not know whether `T` is the
declared name, or whether a following identifier will make `T` the declaration
type in `input T x` or `wire T x`. With dimensions, `input T [1:0]` and
`wire T [1:0]` can be either a declaration named `T` with unpacked dimensions or
a declaration using typedef `T` as a packed type followed by another name.

Parse these declaration forms with productions that decide the first declarator
and carry the selected declaration type across the rest of the list. This covers
variable declarations, net declarations, ANSI and non-ANSI module port
declarations, and task/function port declarations. Other identifier uses still
need separate grammar changes.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-30 14:41:06 -07:00
Lars-Peter Clausen a1c333ea6e Add regression test for delayed real assignments
Check that a blocking intra-assignment delay on a real value preserves the
assigned value after the delay.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-29 10:27:57 -07:00
Lars-Peter Clausen d5306085c5 vvp: Support local flag on real variables
The vvp parser did not accept the local flag on `.var/real`
declarations. This can happen when elaboration creates a compiler-generated
real temporary, for example when a blocking intra-assignment delay is
rewritten from:

    r = #1 1.25;

to assign the right hand side to a temporary before the delay and assign
the temporary to the target after the delay.

Add support for the local flag. Keep a VPI symbol for the variable so
`%load/real` can still resolve the label, but do not attach local real
variables to the current scope.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-29 10:27:57 -07:00
Lars-Peter Clausen 77fdcfd800 Add regression tests for shadowing type identifiers
Check that visible type identifiers can be shadowed by declarations in
other namespaces or nested scopes. Keep each grammar category in a
separate regression so failures identify the affected rule.

Also check that package import and export items can name a type
identifier.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-29 09:52:44 -07:00
Lars-Peter Clausen d2a97663b9 Allow type identifiers to be shadowed in more places
SystemVerilog allows an identifier that is visible as a typedef to be
shadowed by a declaration in a nested scope or reused as a declaration
name in another namespace. The lexer can return `TYPE_IDENTIFIER` before
the new name has been installed, so these grammar positions reject
otherwise valid code.

This is not a complete conversion of all identifier grammar sites. Only
handle the trivial conflict-free cases where `IDENTIFIER` can be replaced
by `identifier_name` without any surrounding grammar changes.

Also stop type lookup when the current scope already has a local symbol
with the same name. This makes later references to a shadowing
declaration use the local symbol instead of an outer typedef.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-29 09:52:44 -07:00
Lars-Peter Clausen d246979d26 Add regression test for string substr() arity error
Check that a string substr() call with too few arguments is rejected with a
normal compile error.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-29 09:51:06 -07:00
Lars-Peter Clausen 55d78cf1a8 Handle missing string substr() arguments
The string substr() method reports an error if it is called with the wrong
number of arguments, but the error was not counted and elaboration continued
with missing function arguments. A call such as `s.substr(0)` could therefore
crash after printing the diagnostic.

Count the arity error and fill missing internal arguments with dummy constants
so elaboration can recover without building an incomplete system function call.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-29 09:51:06 -07:00
Cary R. 78750c51d0 Merge pull request #1402 from larsclausen/real-unary-minus-opcode
vvp: Add opcode for unary real minus
2026-06-22 10:00:17 -07:00
Lars-Peter Clausen 0e7c62d579 Add regression tests for unary real minus special values
Check that unary real minus preserves the sign or bit pattern for zero,
NaN, and infinity. Each test starts with the positive value, negates it,
and then negates the result back to the positive value.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-22 07:43:02 -07:00
Lars-Peter Clausen 5311c0cd38 vvp: Add opcode for unary real minus
Currently the vvp target emits unary real minus as `0.0 - value`.
This is not the same operation for all real values. It loses the
negative zero result for `-(+0.0)` and does not reliably flip the sign
bit for NaN values whose bits are visible through `$realtobits`.

Add `%neg/wr` and use it for unary real minus. This performs a direct
negation of the real stack value, so zero, NaN and infinity all use the
same operation as unary minus instead of a binary subtraction from zero.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-22 07:43:02 -07:00
Cary R 8c7f8f3f7b Fix gold file to fix error message change 2026-06-21 23:04:23 -07:00
Cary R 1babbc0c92 Fix segmentation fault when the input file is missing 2026-06-21 22:53:15 -07:00
Cary R. e9bc3488fb Merge pull request #1401 from larsclausen/fix-bad-member-lval-proc-crash
Handle bogus member l-value paths
2026-06-21 21:12:43 -07:00
Cary R. f472a77e3a Merge pull request #1400 from larsclausen/fix-lval-indexed-part-invalid-base-crash
Handle invalid l-value indexed part select bases
2026-06-21 21:11:37 -07:00
Cary R. 8c27786a27 Merge pull request #1398 from larsclausen/vlog95-unsigned-concat-context
tgt-vlog95: Use concatenation for unsigned expression contexts
2026-06-21 21:09:50 -07:00
Cary R. e31c441dbe Merge pull request #1387 from flaviens/patch-2
Preserve sign of negative zero
2026-06-21 21:07:05 -07:00
Cary R. ff0b269ce9 Merge pull request #1397 from larsclausen/draw-net-input-mux-array-port
tgt-vvp: Avoid interleaving array ports into mux output
2026-06-21 21:05:16 -07:00
Flavien SoltandClaude Opus 4.8 c53e4245b9 Add regression test for negative zero sign preservation
Check that the vvp code generator emits a -0.0 real constant with its
sign bit set, so the compiled value matches the runtime real value. The
sign used to be detected with (value < 0), which is false for IEEE 754
-0.0, and a -0.0 constant was turned into +0.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-22 10:38:26 +08:00
Lars-Peter Clausen 3c7250eb51 Add regression test for bogus member l-values
Check that bogus member access on a procedural l-value is rejected with a
normal compile error instead of aborting during elaboration.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-21 18:39:21 -07:00
Lars-Peter Clausen 9fb607d98e Add regression test for indexed part select l-value bases
Check that an invalid indexed part select base on a procedural l-value is
reported as a normal compile error instead of crashing after the bind error.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-21 18:39:21 -07:00
Lars-Peter Clausen eaa7197602 Handle bogus member l-value paths
Currently the procedural l-value path asserts if symbol lookup leaves a
member tail for a variable that is not a struct or class. For example,
`r.bad = 1'b1;` where `r` is a scalar variable aborts during elaboration
instead of reporting a normal error.

Report an error for the leftover member path before the assertion. This
matches the r-value path behavior for the same kind of invalid member access.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-21 18:39:21 -07:00
Lars-Peter Clausen 9004d10df4 Handle invalid l-value indexed part select bases
The l-value indexed part select path elaborates the base expression with
`elab_and_eval()`. If the base expression can not be bound this returns a
nullptr, but the l-value path dereferenced it while checking the expression
type. For example, `a[does_not_exist -: 2] = 2'b00;` reported the bind error
and then crashed.

Return early when base elaboration fails. This matches the r-value indexed
part select path and leaves the existing bind error as the reported
elaboration error.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-21 18:39:21 -07:00
Lars-Peter Clausen 4e168a4d1f ivtest: Detect execution errors in vvp_reg.py
Currently vvp_reg.py uses `returncode >= 256` to distinguish execution
errors from ordinary compile or simulation failures. That matches the encoded
status returned by wait(), but subprocess.run() does not expose that value. Its
returncode is the decoded process exit status, or `-N` if the process was
terminated by signal N. Shell wrappers can also report signal termination as
`128 + N`.

As a result a compiler crash can be reported as `-11` or `139`. Both values
pass the old check and a CE test can be accepted as a normal compiler error.

Treat negative return codes and return codes greater than or equal to 128 as
execution errors before accepting CE and EF results. Also make sure that CE gold
mismatches are reported as failures.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-21 17:23:52 -07:00
Lars-Peter Clausen e75b0d7968 tgt-vlog95: Use concatenation for unsigned expression contexts
The vlog95 backend currently emits `$unsigned()` when it needs to create a
self-determined unsigned expression context. `$unsigned()` is part of the
optional signed expression support in this backend and is only available when
the signed support flag is enabled.

Concatenation is part of the baseline Verilog-95 output and also creates a
self-determined unsigned expression context. Use `{expr}` for the unsigned case
and keep using `$signed()` when a signed context is needed.

Remove `-pallowsigned=1` from the existing vlog95 regression tests that now
pass without the optional signed support flag.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-21 12:48:00 -07:00
Lars-Peter Clausen 167a6bbcdb Add regression test for case muxes with array word inputs
Check that synthesized case statement muxes can use array words as inputs.
This used to generate invalid VVP because .array/port statements were emitted
in the middle of .functor statements.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-21 11:44:15 -07:00
Lars-Peter Clausen a5bf5e145f tgt-vvp: Avoid interleaving array ports into mux output
Currently draw_lpm_mux_nest() calls draw_net_input() while printing a
.functor statement. For array word inputs draw_net_input() emits an
.array/port statement as a side effect, which interleaves the .array/port
text into the middle of the .functor line and generates invalid VVP.

draw_lpm_substitute() has the same pattern. Collect the input labels before
starting to print the consuming statement so any side-effect output appears
as a separate statement first.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-21 11:44:15 -07:00
Cary R. a615ee03e7 Merge pull request #1395 from larsclausen/sv-generate-class
Support classes in generate blocks
2026-06-21 10:00:54 -07:00
Lars-Peter Clausen bb8b05bb5d Add regression test for classes in generate blocks
Check that a class declared in a conditional generate block can be used.
Also check that classes declared in a generate loop get separate class scopes
for each generated instance.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-21 09:30:28 -07:00
Lars-Peter Clausen 7934ab9eeb Support classes in generate blocks
SystemVerilog allows class declarations as module and generate items.
Currently a class declaration in a generate block triggers an assert because
`pform_push_class_scope()` only records classes in `PScopeExtra` scopes.

Add class storage to `PGenerate` and elaborate those classes like module and
package classes. When registering task, function or class declarations, only
use the current `PGenerate` object as the target if it is also the current
lexical scope. This distinction matters for generated classes because
`pform_cur_generate` remains set while the class body is parsed, but the
current lexical scope has changed to the `PClass`. This records the class
declaration in the generate block while leaving methods and constructors in
the class scope.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-21 09:29:54 -07:00
Cary R. daadc38f18 Merge pull request #1394 from larsclausen/class-task-method-expression-error
Report error for class tasks used as expressions
2026-06-21 07:23:17 -07:00
Cary R. a5b9879ada Merge pull request #1393 from larsclausen/netassignnb-dump-rval-error
NetAssignNB: Fix dump fallback for invalid rval
2026-06-21 07:21:37 -07:00
Cary R. 72833b9570 Merge pull request #1392 from larsclausen/fix-negative-packed-slice-width
Fix width calculation for packed array bounds
2026-06-21 07:20:43 -07:00
Lars-Peter Clausen 449abb6bda Add regression test for class tasks used as expressions
Check that using a class task through an object method call in expression
context reports a compile/elaboration error instead of triggering an assert.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-20 17:06:36 -07:00
Lars-Peter Clausen 0637afd284 Report error for class tasks used as expressions
Class object method calls in expression context call func_def() without first
checking that the resolved class method is a function. If the method is a task,
func_def() triggers an assert instead of reporting a normal elaboration error.

Check the method scope type before accessing the function definition and report
an error for tasks.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-20 17:06:36 -07:00
Lars-Peter Clausen c124abaa3e NetAssignNB: Fix dump fallback for invalid rval
Currently NetAssignNB::dump() prints a malformed fallback marker when
there is no rval expression. The leading '<' is missing, making it
inconsistent with the blocking assignment dump output.

Print the complete error marker.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-20 15:15:52 -07:00
Lars-Peter Clausen 03f1bbdd37 Consolidate net up/down part select
The methods for handling up and down part select are nearly identical
and only differ in a hand full of lines.

Consolidate them into a single method to remove the duplicated code.
This makes it easier to maintain the code and add future changes.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-20 14:25:16 -07:00
Lars-Peter Clausen e9d3fe4ea3 Consolidate parameter up/down part select
The methods for handling up and down part select are nearly identical
and only differ in a hand full of lines.

Consolidate them into a single method to remove the duplicated code.
This makes it easier to maintain the code and add future changes.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-20 14:25:16 -07:00
Lars-Peter Clausen 10349287a0 Add regression tests for enum typedefs in nested scopes
Check that enum literals declared by enum typedefs in generate blocks, named
blocks, tasks and functions can be referenced from the same scope.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-20 14:24:53 -07:00
Lars-Peter Clausen 9bc86af284 elab: Elaborate enum types in nested scopes
Enum types declared inside nested scopes are stored separately from typedefs.
The enum sets need to be elaborated when the `NetScope` is created so enum
literals are available for declarations and statements in the same scope.

Module, package and class scopes already do this. Generate, task, function and
named block scopes can also declare enum typedefs, but did not elaborate their
enum sets. Elaborate them while setting up these scopes.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-20 14:24:53 -07:00
Lars-Peter Clausen 593a97bede vvp: Bound VPI label scanset parsing
The VPI label resolver parses word and string labels into a 32 byte
temporary buffer. The scansets used by sscanf() did not specify a width,
so malformed labels could write past the end of the buffer.

Limit the scansets to the size of the buffer.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-20 13:13:24 -07:00
Lars-Peter Clausen d5a16b31a1 Add regression test for empty old-style UDP table
Check that an empty old-style UDP table reports the parser error and the
invalid primitive error instead of crashing.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-20 13:13:05 -07:00
Lars-Peter Clausen 20a969bf38 Handle invalid old-style UDP tables
An empty old-style UDP table leaves the parsed table pointer unset after
the parser reports the table error. The old-style UDP creation path still
passed the null pointer to process_udp_table(), which crashes.

Report an invalid UDP table instead and do not register the primitive.
Also keep the new-style invalid-table diagnostic formatting consistent.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-20 13:13:05 -07:00
Cary R 4b9675abd7 Update unused function in lz4 2026-06-20 08:53:42 -07:00
Cary R 8caa3af689 Update to the latest GTKWave files. 2026-06-20 07:57:16 -07:00
Lars-Peter Clausen 6326c5b1ba Add regression test for negative packed array bounds
Check that variable selects of a packed array with negative bounds use the
correct index width and can read back assigned elements.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-19 22:08:17 -07:00
Lars-Peter Clausen 128c621e85 Fix width calculation for packed array bounds
Variable select base normalization extends the base expression to cover
the packed array bounds. The current code compared min_wid against
num_bits() of each bound, but then assigned the bound value itself to
min_wid.

For positive bounds this can make the generated index expression much
wider than required. For negative bounds the effect is much worse since
min_wid is unsigned. Assigning a negative bound converts it to a huge
width, causing elaboration to try to pad the expression to that size and
abort or run out of memory for otherwise valid variable selects.

Use the bit width of the bound instead of the bound value.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-19 22:08:12 -07:00
Flavien Solt f963322076 Preserve sign of negative zero 2026-06-19 16:00:16 +08:00
Lars-Peter Clausen de415b2f03 Add regression tests for nested function and final contexts
Check that statements that are not allowed in functions or final procedures
are still rejected when they are placed in a named block scope.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-09 21:34:34 -07:00
Lars-Peter Clausen 5b512e4f1e Preserve function and final context in nested scopes
Currently checks for statements that are not allowed in functions or final
procedures only inspect the immediate scope. If the statement is inside a
named block or a block with declarations, the current scope is the block and
the context is lost.

Make `NetScope::in_func()` and `NetScope::in_final()` preserve the context
through begin-end, fork-join and generate block scopes. Other scope types are
treated as context boundaries so function and final state does not leak across
subroutine or definition scopes.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-09 21:34:34 -07:00
Lars-Peter Clausen c5c0b09ef6 Add regression tests for queue method argument count errors
Check that queue push_back(), push_front() and insert() report errors when
called with too few or too many arguments.

These tests are expected to fail as compile/elaboration errors. They also make
sure the invalid calls do not crash during elaboration while reporting the
argument count error.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-09 21:33:58 -07:00
Lars-Peter Clausen aa3d804b72 Fix out-of-bounds write for missing queue method arguments
When a method argument is missing, the error path stores a nullptr in the
argument vector for that missing slot. The vector was sized from the number of
arguments that were present in the source, so calls such as `q.push_back()` or
`q.insert(0)` wrote those nullptr placeholders past the end of the vector.

Size the vector from the number of arguments required by the queue method
instead. This gives the error path slots for the missing arguments while
leaving valid calls unchanged.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-09 21:33:58 -07:00
Lars-Peter Clausen 2fc9d27190 Add regression test for multi-dimensional packed class properties
Check that multi-dimensional packed vector class properties can be emitted,
assigned, and read back through a class object.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-09 21:33:18 -07:00
Lars-Peter Clausen 1e6e69ee7f Support multi-dimensional packed vectors as class properties
Currently multi-dimensional packed vector class properties will cause an
assert and only single dimensional or scalar vectors will pass.

But just as for regular vectors there is nothing special about class
property multi-dimensional vectors as they will be represented in vector
form in vvp.

Removing the asserts allows multi-dimensional packed vectors to be used for
class properties. Indexed access to these properties is not supported yet;
that requires follow-up work to elaborate packed property selects and to
support partial stores to vector class properties.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-06-09 21:33:18 -07:00
Lars-Peter Clausen c7530dbcc1 Add regression test for assignment patterns as queue method arguments
Check that assignment patterns are evaluated in the queue element type
context when they are passed to the queue `push_front()`, `push_back()` and
`insert()` methods.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-31 18:32:44 -07:00
Lars-Peter Clausen e47160c6a8 Evaluate queue method arguments in assignment-like contexts
The arguments of the queue `push_front()`, `push_back()` and `insert()`
methods are passed to subroutine input ports. This makes them
assignment-like contexts with the declared argument type as target type.

Use `elaborate_rval_expr()` instead of `elab_and_eval()` for these
arguments. This evaluates the item argument with the queue element type and
the `insert()` index argument with `integer`, so target-type-dependent
expressions such as assignment patterns work and enum compatibility checks
use the queue element type.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-31 18:32:44 -07:00
Cary R. 311c22e4de Merge pull request #1373 from MrCookieeeee/Ignore-configure-generated-files
Ignore configure generated files
2026-05-22 10:15:55 -07:00
Cary R. 2d3502f4b7 Cleanup .gitignore organization and files 2026-05-22 10:14:31 -07:00
Cary R e54b404700 Update driver make check to work with all systems 2026-05-22 00:28:27 -07:00
Cookie 297dbe94c2 Ignore configure generated files 2026-05-22 15:05:02 +08:00
Cary R. 7b2c050457 Merge pull request #1371 from rhabacker/fix-issue-1370
iverilog: add command line option -BI and -Bt
2026-05-21 09:38:57 -07:00
Cary R. 6a6ff90197 Update clean target in Makefile to remove test.conf
Remove test.conf from the clean target in Makefile.
2026-05-21 09:27:48 -07:00
Cary R aafda65b99 Cppcheck cleanup 2026-05-21 05:21:35 -07:00
Cary R. 129a5c980f Merge pull request #1369 from larsclausen/unpacked-array-assign-strength-delay
Preserve delay and strength in unpacked array continuous assignments
2026-05-20 18:49:41 -07:00
Cary R. da42011b97 Merge pull request #1372 from larsclausen/netevwait-repeat-control
NetEvWait: Don't delete event in destructor
2026-05-20 18:41:38 -07:00
Lars-Peter Clausen e35c857a24 Extend non-blocking event control with <= 0 repeat test
Extend the non-blocking event control assignment tests to check that a 0 or
negative repeat value is handled correctly. In this case the assignment
should be executed like a regular non-blocking assignment and the event
control should be ignored.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-19 21:00:56 -07:00
Lars-Peter Clausen 7e7d0ae94b NetEvWait: Don't delete event in destructor
`NetEvWait` deletes the event that is assigned to it when itself
is deleted. But the event is not owned by the `NetEvWait`, it is shared among
all consumers of the event. Deleting it when the `NetEvWait` is deleted can
result in undefined behavior.

This is mainly a problem for non-blocking event control assignments with a
zero or negative immediate valued repeat. In this case the `NetEvWait` will
be deleted as it is not needed.

```
reg x;
event e;
x <= repeat(1) @e 1'b0;
x <= repeat(0) @e 1'b1; // Assert triggered since in-use event is freed
```

Remove the delete to fix this. Events that end up being unused will be
freed by the nodangle functor.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-19 21:00:39 -07:00
Ralf Habacker 0d74d5b211 iverilog: add test for the vvp example mentioned in the documentation
This test was added to verify the new options
in the `iverilog` program, which allow it to
be run from a build directory.

Since `iverilog` is not compatible with the MSYS2
runtime environment used in CI, the added test is
excluded on this platform.
2026-05-19 22:22:43 +02:00
Ralf Habacker 2e50fb2f06 iverilog: add -Bt option to find <target>.conf when using -t<target> in custom install or build dir 2026-05-18 14:01:02 +02:00
Ralf Habacker 8b861b4171 iverilog: add -BI option to support custom location for the ivl parser 2026-05-18 07:50:07 +02:00
Ralf Habacker ecb8a70bed iverilog: add missing -B<selector> options to man page and app usage 2026-05-18 07:49:42 +02:00
Lars-Peter Clausen 635bdd8eb8 Add regression tests for unpacked array continuous assignment strength and delay
Check that continuous assignments to unpacked net arrays preserve delay and
drive strength on the generated element drivers.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-17 14:46:31 -07:00
Lars-Peter Clausen ab6a0e0799 Preserve delay and strength in unpacked array continuous assignments
Continuous assignments to unpacked arrays are expanded into per-element
BUFZ drivers. Currently this path drops the delay and drive strength from
the original continuous assignment, so `assign #5 a = b` updates the array
immediately and `assign (weak1, weak0) a = b` drives with the default
strength.

Pass the evaluated delay and strength values through the unpacked array
assignment helper and apply them to each generated element driver.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-17 14:34:25 -07:00
Lars-Peter Clausen 85c58d0a7a Use helper types for drive strengths and delays
Drive strengths and delays are often handled as a pair of drive values
and a rise/fall/decay triple. Add small helper types to carry these
groups and use them in the continuous assignment and gate/UDP elaboration
paths.

Use the same helper types when propagating drive and delay values through
netlist links.

Also add helpers for dumping the values in debug output. This keeps the
behavior consistent and fixes one small bug where some of the debug
dumps printed the pointer value for the delays, rather than the actual
delay values.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-17 14:27:45 -07:00
Cary R. cc86f69a89 Merge pull request #1368 from larsclausen/net-decl-consolidation
Support SystemVerilog net declaration assignments
2026-05-17 12:16:25 -07:00
Lars-Peter Clausen 28e121c040 Add regression tests for net declaration assignments
Check that SystemVerilog net declarations can mix entries with and
without initialization.

Check that in SystemVerilog it is possible to do assignments within net array
declarations.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-17 11:12:26 -07:00
Lars-Peter Clausen 02fa1a9978 pform_set_data_type(): Remove net_type parameter
`pform_set_data_type()` is now only called on wires that already have the
correct wire type set. There is no need to pass the same type to
`pform_set_data_type()` and set it again.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-17 11:11:54 -07:00
Lars-Peter Clausen 3495889112 Support SystemVerilog net declaration assignments
SystemVerilog allows initialized and uninitialized net declaration entries to
be mixed in the same declaration, e.g. `wire x, y = 1'b1`. In Verilog,
either all nets need to have an initializer or non can have one.

In addition SystemVerilog also allows assignments to arrays of wires during
declaration. E.g. `wire a[3:0] = b;`

Currently there are two different rules for net declarations, one for each
of the Verilog variants. Combine these into a single rule to support
SystemVerilog mixed declarations as well as the assignment to array nets.

When running in Verilog mode still reject mixed initialized and
uninitialized with a check after the parsing.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-17 11:06:44 -07:00
Lars-Peter Clausen e7934d5e66 pform_makewire(): Fix indentation
The assignment handling block uses space-based indentation that does not match
the surrounding code.

Fix the indentation before changing the block.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-17 11:05:02 -07:00
Cary R 86546b5960 Set LD_LIBRARY for BSD so make check works 2026-05-16 23:17:11 -07:00
Cary R ca3a00a51a Update some vlog95 interface configurations 2026-05-16 23:17:11 -07:00
Cary R. e6cfb08dd6 Merge pull request #1367 from larsclausen/uarray-lvalue-concat
Handle single element static unpacked array assignments
2026-05-16 22:04:59 -07:00
Lars-Peter Clausen 74491cfe9f Add regression tests for single element unpacked array assignments
Check that continuous assignment of an assignment pattern to a single element
unpacked array is accepted. Check that assigning a scalar expression to the
whole unpacked array is rejected for both procedural and continuous
assignments.

Check that a selected element of a single element static unpacked array can be
used in a continuous l-value concatenation.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-16 21:11:30 -07:00
Lars-Peter Clausen dea82c5a91 Handle single element static unpacked array assignments
Currently single element static unpacked arrays are not always treated as
unpacked arrays when elaborating assignment l-values. The net only has one pin,
so checks using `pin_count() > 1` treat the array as a scalar value and skip
the unpacked array path.

Use `unpacked_dimensions() > 0` instead of `pin_count() > 1` when checking
whether a signal is an unpacked array. This lets single element arrays follow
the same l-value elaboration paths as other unpacked arrays.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-16 21:06:16 -07:00
Cary R. 8229ce1b49 Merge pull request #1366 from larsclausen/sv2023-type-param-restrictions
Add support for restricted type parameters
2026-05-16 17:44:12 -07:00
Lars-Peter Clausen 08479888b1 Add regression tests for restricted type parameters
Check that enum, struct, union and class restricted type parameters are
accepted. Check that mismatched default values and overrides are rejected.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-16 17:29:32 -07:00
Lars-Peter Clausen 46c0526dab Add support for restricted type parameters
SystemVerilog 2023 allows type parameters to be restricted to a
specific kind of type, e.g. `parameter type struct T = T0`.

This is very similar to the type restrictions that can be applied to
forward typedefs.

Factor the support code from the typedefs into a standalone helper and
reuse it for both.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-16 17:20:40 -07:00
Cary R. 0f75156d37 Merge pull request #1365 from larsclausen/soft-unions
Support soft packed unions
2026-05-16 17:11:41 -07:00
Lars-Peter Clausen f8e9384689 Add regression tests for soft packed unions
Check that soft packed unions can have members with different widths.
Check that the `soft` qualifier implies `packed` and that nested soft
packed unions use the same representation recursively.

Also check that member bits are right-justified and that assignments to
narrower members leave the MSBs beyond the member bits unchanged. Check
that soft packed unions reject default member values.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-16 16:46:57 -07:00
Lars-Peter Clausen fb3be420b4 Support soft packed unions
SystemVerilog 2023 adds soft packed unions. They are pretty much the same
as regular packed unions except they remove the restriction that all
elements have to have the same packed width.

The packed with of the union itself is the maximum packed width of any
element.

The bits of each member are right-justified towards the LSBs and this
representation is applied recursively to nested soft packed unions. The
existing packed union member offsets already use that layout. When
accessing a field that is smaller than the union itself upper bits are
ignored for both reading and writing.

The `soft` qualifier implies a packed union so both `union soft U { ... }`
and `union soft packed U { ... }` declare a soft packed union.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-16 16:43:06 -07:00
Cary R eb45fb6eec Fix Makefile generation warning in tgt-fpga 2026-05-16 16:23:41 -07:00
Cary R. 1f5c7c888a Merge pull request #1364 from larsclausen/sv2017-2023-generations
Add 2017 and 2023 language flag support
2026-05-16 15:45:52 -07:00
Cary R. 3f0d02350f Merge pull request #1310 from rhabacker/libvpp-versioned-library
vvp: create libvvp as versioned library
2026-05-16 15:41:59 -07:00
Lars-Peter Clausen 0a6fa449de Add regression tests for begin_keywords versions
Check that each valid `begin_keywords` selector is accepted. Only check
that the selector itself is accepted, in these tests there is no check if
the correct keywords are actually accepted or rejected since that would get
pretty exhaustive.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-16 15:40:37 -07:00
Lars-Peter Clausen eadb1d24ae Add 2017 and 2023 language flag support
Add flags to enable IEEE1800-2017 and IEEE1800-2023 languages generations
and also support them in the `begin_keywords macro. Since neither defines
new keywords they'll use the same keyword mask as 2012.

Update the driver, compiler, documentation and regression test harness so
-g2017 and -g2023 are recognized as language generation flags.

There are no specific features from these versions added yet, this is just
the necessary infrastructure to allow gating new features from those
generations when they are added later.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-16 15:40:37 -07:00
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
Cary R. b605f42a1e Update copyright year in parse_misc.h 2026-05-16 15:19:40 -07:00
Cary R. 9f3f35e451 Update copyright year in netmisc.h 2026-05-16 15:19:02 -07:00
Cary R. 73cee3b3e0 Update copyright year in Module.h 2026-05-16 15:18:15 -07:00
Cary R. 9ff4a42171 Update copyright year in Module.cc 2026-05-16 15:17:52 -07:00
Cary R. 84dc4ec99f Update copyright year in elab_net.cc 2026-05-16 15:16:47 -07:00
Cary R. 1751f4ed0b Merge pull request #1361 from larsclausen/unpacked-lvalue-concat-error
Reject unpacked l-value concatenation operands
2026-05-16 14:37:36 -07:00
Lars-Peter Clausen 96cea271ba ivtest: Fix VVP regression test metadata
A few JSON regression test entries reference the wrong source or gold
files. There are also two regress-vvp list entries that reference each
other's JSON file.

Use the matching source and gold files for those entries.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-16 13:43:10 -07:00
Lars-Peter Clausen b8eac7fc19 ivtest: Fix source for sv_mixed_assign2 test
The sv_mixed_assign2 JSON entry accidentally references
sv_mixed_assign1.v. Point it at sv_mixed_assign2.v instead.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-16 12:51:43 -07:00
Lars-Peter Clausen f9ab26b3d9 Add regression tests for unpacked l-value concat errors
Check that class objects, dynamic arrays, queues, strings and static
unpacked arrays can not be used as l-value concatenation operands. Check
procedural and continuous assignment concatenations, including single
operand concatenations.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-15 20:48:19 -07:00
Lars-Peter Clausen 208078838e Reject unpacked l-value concatenation operands
L-value concatenation operands must be packed values. Using an unpacked
array, string, class object or other non-packed value as an operand can
reach later assignment code with an invalid l-value representation.

Check the operand type after l-value elaboration and report an
elaboration error instead.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-15 20:44:47 -07:00
Cary R. 73ae5bd1db Merge pull request #1360 from larsclausen/vvp-case-cmp-e
tgt-vvp: Use `%cmp/e` instead of `%cmp/u` for `case` comparisons
2026-05-15 07:47:46 -07:00
Cary R. 5b62f32ad6 Update copyright year in vvp_process.c 2026-05-15 07:47:24 -07:00
Cary R. a6ba0eef5e Merge pull request #1359 from larsclausen/remove-unused-parser-union-fields
parse.y: Remove unused fields from union
2026-05-14 22:35:07 -07:00
Lars-Peter Clausen d84f1b9843 tgt-vvp: Use %cmp/e instead of %cmp/u for case comparisons
`%cmp/e` and `%cmp/u` are very similar with `%cmp/e` not setting the lt
flag and being a bit faster due to it. For case comparisons the flag is not
needed so switch to `%cmp/e`. This speeds up simulation time designs which
make use of case comparisons.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-14 20:34:30 -07:00
Lars-Peter Clausen f1c71eff5c parse.y: Remove unused fields from union
The parser union still has a few fields that are not used by any
grammar rule. They do not have matching semantic type tags and no
action references them.

Remove the unused fields.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-14 20:18:28 -07:00
Cary R. 5fac9fae4d Merge pull request #1358 from hwhsu1231-fork/edit-this-page
docs: add edit this page to sidebar
2026-05-13 10:01:53 -07:00
Haowei Hsu a042847b38 docs: add edit this page to sidebar 2026-05-13 22:12:30 +08:00
Cary R. 2f1987bded Merge pull request #1357 from hwhsu1231-fork/add-github-url
docs: add github url to html theme options
2026-05-13 02:46:19 -07:00
Ralf Habacker a1299f7ca8 CI: enable building with libvvp and suffix on MacOSX
Adding these build variants to the platform in question results
in the smallest increase in the number of additional build jobs.
2026-05-13 10:48:24 +02:00
Ralf Habacker 00bb35a0ce CI: Add support to compile on all platforms with libvvp and/or suffix enabled
The specified jobs runs the build, check, install and a post install
test stage.
2026-05-13 10:45:04 +02:00
Ralf Habacker 9d3101fd19 vvp: build and install libvvp as a versioned shared library
It uses a dedicated LIBVVP_SOVERSION specified in onfigure.ac
for the SONAME and full library version.

For linking, a pkg-config file is generated, and when building on
Windows, an import library is created that can be used with both
GCC and MSVC compilers.

On non-Windows platforms, all object files are compiled with -fPIC
to ensure compatibility with shared libraries.

On Windows use 'lib' prefix for library name with MinGW compiler
only. Other compiler like MSVC normally are not using any library
prefix.

With this commit the build rules for the vpp executable has been
cleaned too because the complex structure of the manually created
Makefile.in made it very difficult to extract specific parts of
them.
2026-05-13 10:45:04 +02:00
Ralf Habacker 4014db47e0 vvp: introduce variable names for object files used by the vvp library 2026-05-13 10:45:04 +02:00
Ralf Habacker 3e7135aabb vvp: add DLLIB to LIBS to simplify build rules 2026-05-13 10:45:04 +02:00
Ralf Habacker 38a24e71b5 vpp: install missing include directory when installing from 'vvp' directory
This fixes an issue unrelated to the addition of support for
versioned VVP library.
2026-05-13 10:45:04 +02:00
Haowei Hsu 214324db8c docs: add github url to html theme options
Include the GitHub repository URL in the HTML theme options
for better visibility and access to the project's source code.
2026-05-13 15:34:04 +08:00
Cary R 6b1878c1b5 Update to the latest actions to remove Node.js warnings 2026-05-12 21:53:53 -07:00
Cary R 1476f36ff3 Upgrade actions/checkout to version 5 to support proper nodeJS 2026-05-12 21:35:22 -07:00
Cary R. 89740e6f0e Merge pull request #1346 from hwhsu1231-fork/venv-switch-shibuya-theme
docs: switch docs to shibuya theme and install via venv
2026-05-12 21:09:51 -07:00
Cary R. 2449ee2054 Merge pull request #1355 from larsclausen/super-member-access-error
Reject super access without a parent class
2026-05-12 21:08:27 -07:00
Lars-Peter Clausen e4afd6dc25 Add regression test for super access error
Check that access through `super` is rejected when the current class has no
parent class.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-12 20:43:38 -07:00
Lars-Peter Clausen cdb9bc2c21 Reject super access without a parent class
The `super` keyword refers to the parent class of the current class. If the
class has no parent the lookup still returned the current class handle and left
the `super` path component for l-value elaboration. This triggered the
`tail_path.empty()` assert.

Report an error during symbol lookup instead.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-12 20:43:38 -07:00
Cary R. a8eda65859 Merge pull request #1353 from rhabacker/simplify-doc-rules
vvp,tgt-fpga: cleanup doc related rules
2026-05-12 05:27:44 -07:00
Ralf Habacker 33584ec6f1 tgt-fpga: cleanup doc related rules
With this commit, the file “iverilog-fgpa.pdf” is now
also installed in the directory where all the other
PDF files are located.
2026-05-12 10:35:02 +02:00
Ralf Habacker 46a329f16f vvp: cleanup doc related rules 2026-05-12 10:31:19 +02:00
Cary R. 49ee58c356 Merge pull request #1352 from larsclausen/named-event-edge-errors
Report error for `edge` event controls on named events
2026-05-11 22:30:49 -07:00
Cary R 5b51ed9aa5 Fix building and dependency for verion_base.h 2026-05-11 22:16:00 -07:00
Lars-Peter Clausen ba3f46722c Add regression tests for edge controls on named event errors
Check that the compiler reports an error for `posedge`, `negedge` and `edge`
event controls on named events. Edge controls can not be used with named
events.

There is already an existing test that checks both `posedge` and `negedge`.
Split it into separate tests so that each invalid event control is checked
independently.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-11 21:10:35 -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 <[email protected]>
2026-05-11 21:10:32 -07:00
Jose Tejada 56afcb6e75 fix(interface): allow forward interface port types 2026-05-11 22:25:32 +02:00
Haowei Hsu a52bef20ed docs: switch docs to shibuya theme and install via venv
- change documentation theme from `alabaster` to `shibuya`
- add pinned Documentation requirements for `sphinx` and `shibuya`
- update workflows to create `.venv` and install with `requirements.txt`
- ignore common virtual environment directories (`.conda` and `.venv`)
2026-05-11 20:48:58 +08:00
Cary R. f696064af1 Merge pull request #1351 from rhabacker/fixup-for-1331
Makefile.in: 'version_base.h' must not be deleted when running `make …
2026-05-11 04:51:42 -07:00
Ralf Habacker 1ea5f72496 Makefile.in: 'version_base.h' must not be deleted when running make clean
Since this file, just like 'config.h', is generated by autoconf,
it should only be deleted in the `distclean` target.

Also since the project does not currently use automake, manual
maintenance of the timestamp file for 'version_base.h' is required.

Fixup for commit 10b5f70e7 from #1331
2026-05-11 13:16:08 +02:00
Jose Tejada 377881b723 fix(interface): address port array review feedback 2026-05-11 07:44:43 +02:00
Cary R. bcc3a66657 Merge pull request #1350 from larsclausen/array-index-real-error
Reject `real` array indices
2026-05-10 22:40:23 -07:00
Lars-Peter Clausen ea57b6dd9a Add regression test for real array index error
Check that using a real valued expression as an array index is rejected
during elaboration.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-10 22:26:48 -07:00
Lars-Peter Clausen ba74c7b5ad Reject real array indices
Array indices must be integral expressions. Using a real valued expression
as an unpacked array index currently reaches the vvp real expression code
and triggers an assert.

Packed bit and part select indices already report an elaboration error for
real expressions since commit 2249d224de ("Bit/part selects cannot have
real index expressions"). Do the same for unpacked array indices.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-10 22:26:44 -07:00
Cary R. fb6dfebcec Merge pull request #1349 from larsclausen/new-array-init-cleanup
elab: Use common new array initializer elaboration
2026-05-10 15:24:56 -07:00
Cary R 13d5155e88 Docopt is no longer used in the Python test script 2026-05-10 15:19:09 -07:00
Lars-Peter Clausen fde4ef85c1 elab: Use common new array initializer elaboration
here are two separate paths `PENewArray::elaborate_expr()`, one for
assignment patterns and one for everything else.

But since since commit 5ca058bfb ("Add support for darray initialisation
from another darray"). The two paths have been effectively the same.

Both call `elaborate_expr()` on the init values with the same parameters.
The only difference is the regular path casts the type to `netarray_t`, but
that doesn't really do anything since it gets passed to a function that
takes a `ivl_type_t`, so is immediately cast back to the base type.

The comment on the regular path is also outdated since it still refers to
the tpre 5ca058bfb code.

Remove the branching and route it through the same path.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-10 14:59:44 -07:00
Cary R. 8c7f3452c5 Merge pull request #1347 from larsclausen/enum-const-width-cleanup
elab: Remove redundant enum parameter width handling
2026-05-10 14:49:33 -07:00
Cary R 5240790480 Fix/update latest cppcheck issues 2026-05-10 14:47:40 -07: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
Lars-Peter Clausen 71ce460caa elab: Remove redundant enum parameter width handling
`PEIdent::test_width_parameter_()` has a special case for
`NetEConstEnum` that queries the enum base type directly. This was needed
when enum constants kept their enum type separately from the `NetExpr`
type.

Commit f63a162329 ("Provide data type for more NetExpr subclasses") made
`NetEConstEnum` attach the enum type to the `NetExpr`. The generic
parameter width path now gets the same type, width and signedness as the
special case.

Remove the redundant special case and use the common path for enum
constants as well.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-09 19:05:18 -07:00
Cary R e212ea1a1c package liftime test needs signed for vlog95 testing 2026-05-08 05:54:13 -07:00
Cary R 3d8f906bdd Update Copyright that was missed for a few files 2026-05-08 05:35:16 -07:00
Cary R. 3986804264 Merge pull request #1343 from larsclausen/lifetime_package
Allow lifetime specifier for variables declared in packages
2026-05-08 05:21:19 -07:00
Cary R. e0e4a2af48 Merge pull request #1342 from larsclausen/vvp-reduce-speed-up
vvp: Improve reduction operator performance
2026-05-08 05:17:52 -07:00
Lars-Peter Clausen 81222402c7 Add regression tests for package variable lifetimes
Check that package variables can use explicit static lifetime. Check that
automatic lifetime is rejected for package variables.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-07 22:14:20 -07:00
Lars-Peter Clausen c2b63e69a4 Allow lifetime specifier for variables declared in packages
The LRM allows to add a lifetime specified for variables declared in
package scope. It is not particular useful since only static lifetime is
allowed. But it is legal syntax, so support it.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-07 22:14:20 -07:00
Lars-Peter Clausen 48242818b3 vvp: Improve reduction operator performance
The vvp reduction operators evaluate their input bit by bit. This is
expensive for wide vectors.

Add word wide reduction helpers to `vvp_vector4_t` and use them for both
reduction functors and vthread reduction opcodes.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-07 21:26:17 -07:00
Cary R e4c4247266 Fix the full PDF document name 2026-05-07 19:40:58 -07:00
Cary R d8e7cd4037 iverilog-vpi is not in the main directory 2026-05-07 19:34:36 -07:00
Cary R f559a05672 Net arrays are not supported for Verilog 95 2026-05-06 21:25:25 -07:00
Cary R. 99c7a9f940 Merge pull request #1338 from larsclausen/byte-array-string-literal
Support assignment of string literals to byte arrays
2026-05-06 20:44:13 -07:00
Cary R. 33a6d58258 Merge pull request #1341 from larsclausen/vvp-vector-ops-speed-up
vvp: Use word wide bitwise logical ops
2026-05-06 20:37:49 -07:00
Lars-Peter Clausen 6ffb4b9a3a Add regression tests for string literals assigned to byte arrays
Check that string literals can be assigned to byte arrays. Check that
invalid target array types are reported as errors.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-06 19:20:47 -07:00
Cary R. e9cffe506b Merge pull request #1340 from rhabacker/followup-for-1331
Makefile.in: remove obsolete dependency
2026-05-06 18:48:01 -07:00
Cary R. e02eb2a4d8 Merge pull request #1339 from rhabacker/fix-build-rules
Fix incomplete build rules for generating header files
2026-05-06 18:47:37 -07:00
Cary R. 68244563ca Merge pull request #1335 from rhabacker/cleanup-iverilog-vpi
iverilog-vpi: Consolidate creation in driver-vpi
2026-05-06 18:47:05 -07:00
Lars-Peter Clausen 0f454ff548 vvp: Use word wide vector operations for logic functors
The logic functors combine their input vectors bit by bit.

Use the in-place `vvp_vector4_t` operators for the vector operation and
invert the result once for the inverted functors.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-06 13:19:53 -07:00
Lars-Peter Clausen cf53479ba2 vvp: vthread: Use word wide vector operations
The vthread binary logic opcodes update vectors bit by bit.

Use the in-place `vvp_vector4_t` operators instead. This reuses the word
wide implementation and avoids per-bit `value()` and `set_bit()` calls.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-06 13:19:53 -07:00
Lars-Peter Clausen 41c3423209 vvp: Implement vvp_vector4_t xor operator
`vvp_vector4_t` has word wide in-place operators for and and or, but not
for xor.

Add `operator ^=` using the same internal word representation.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-06 13:19:53 -07:00
Ralf Habacker f8e20f5a09 Makefile.in: remove obsolete dependency
Fixup for commit 49eaafe88 from #1331
2026-05-05 08:16:33 +02:00
Ralf Habacker d59e2c97ba Add missing autoconf macro for generating header stamp files
Fixes #1334

Fixup for commit 804e06cce.
2026-05-05 01:16:12 +02: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 <[email protected]>
2026-05-03 19:48:38 -07:00
Lars-Peter Clausen 8519a30354 Add regression test for unpacked array output port expressions
Check that assignment patterns cannot be connected directly to unpacked
array output ports.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-03 17:31:09 -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 <[email protected]>
2026-05-03 17:31:09 -07:00
Lars-Peter Clausen be3be03fec Add regression test for drive strength net declarations
Check that drive strength can be specified between the net type and the
data type in a net declaration and that vector gate arrays resolve
strengths correctly.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-03 17:30:56 -07:00
Lars-Peter Clausen 11c619e265 Fix drive strength in net declaration parsing
The drive strength of a net must be declared between the net type and the data type. E.g.

    wire (weak0, strong1) [7:0] x;

The current implementation expects the drive strength after the data type. Update the parser to fix this.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2026-05-03 17:30:56 -07:00
Ralf Habacker 181cb7b2ed iverilog-vpi: Consolidate creation in driver-vpi
This change standardizes the creation of iverilog-vpi-related
targets, which now follow the same pattern as the iverilog targets
in the 'driver' subdirectory.
2026-05-02 14:03:00 +02:00
Ralf Habacker 9b42bf0df6 Makefile.in, vvp/Makefile.in: introduce ivl_includedir
This variable was introduced to avoid conflicts with
the existing `includedir` variable, which is used for
the general include directory.
2026-05-02 14:02:59 +02:00
Ralf Habacker 0846198602 Makefile.in, driver/Makefile.in: fix setup of generated doc types for iverilog*
This resolves an issue where the man page is built even if
the 'man' program is not installed.
2026-05-02 14:02:59 +02:00
Cary R 6c52271afa Reorder check-installed targets 2026-04-30 08:31:50 -07:00
Cary R. ed7240b392 Merge pull request #1332 from rhabacker/ivtest-in-build-system
Ivtest in build system
2026-04-30 08:22:24 -07:00
Ralf Habacker c14c73dd9a ivtest: Integration of regression tests into the build system
Replace .github/test.sh with a unified set of targets installed
via `make check-*` in ivtest/, thereby removing CI-specific test
coordination. This avoids duplication in the regression logic and
ensures consistent execution between local and CI environments.
PLI1-dependent tests are now correctly controlled via
`configure --enable-libveriuser`.

Currently, the regression suite still depends on an iverilog package,
which must be installed manually at the location specified with
`configure --prefix=*`. Afterward, the complete regression suite
(VVP, VPI, and Python tests) can be run via `make check-installed`
and individual checks can be run with `check-installed-vpi`,
`check-installed-vvp` and `check-installed-vvp-py`.
2026-04-30 17:04:53 +02:00
Cary R. 03cac78504 Merge pull request #1331 from rhabacker/version-base-fixup
Move the use of version.exe to the build system
2026-04-30 08:02:07 -07:00
Ralf Habacker 49eaafe886 Remove support for creating 'version.exe' from the build system
Since this functionality has now been taken over by the build system
and is no longer needed, it can be removed from the build system.
2026-04-30 09:11:21 +02:00
Ralf Habacker 731891b58f Update documentation to clarify that 'version.exe' is no longer used 2026-04-30 09:11:21 +02:00
Ralf Habacker 92d345ddb2 Use autoconf variables in generated man and pdf output 2026-04-30 09:11:21 +02:00
Ralf Habacker 10b5f70e71 Move version info into configure.ac and generate version_base.h from template 2026-04-30 09:11:18 +02:00
Ralf Habacker 68f461f5a9 configure.ac: Sort and reformat the list of generated config files
If there is only one file per line, it is easier to add additional files.
2026-04-30 07:29:03 +02:00
Cary R 6f3beca5fb FST can dump packages 2026-04-29 20:59:19 -07:00
Cary R. 15989f3d62 Merge pull request #1329 from rhabacker/fix-1313
Fix test error with --enable-libvvp
2026-04-28 08:21:43 -07:00
Cary R. db06b37243 Merge pull request #1328 from rhabacker/split-aclocal
Split aclocal macros into m4 files for aclocal-managed autoconf setup
2026-04-28 08:15:34 -07:00
Ralf Habacker 047974bdb6 Fix test error with --enable-libvvp
When running `make check` on a UNIX-like operating system
with the specified `configure` option, `vvp` was unable to
find the required shared library.

This commit ensures that the runtime linker can locate the library.

This fixes issue #1313.
2026-04-28 13:36:47 +02:00
Ralf Habacker e8a4cc7c9e configure: explicitly require C++11
Newer autoconf/toolchains may default to newer C++ standards
(e.g. C++23). Explicitly enforce C++11 to preserve expected
behavior.
2026-04-28 13:15:17 +02:00
Ralf Habacker 804e06cce9 Split aclocal macros into m4 files for aclocal-managed autoconf setup
Future updates are handled via aclocal --install or autoreconf,
no manual edits to aclocal.m4 required.
2026-04-28 13:15:07 +02:00
Martin Whitaker ca756322a7 Add regression test for issue #1323. 2026-04-15 16:44:35 +01:00
Martin Whitaker eed88fc61f ivlpp: Ensure def_buf is allocated when calling macro_start_args()
macro_start_args() inserts a null string for arg 0 at the start of def_buf.
This allows macro_finish_arg() to calculate the length of the first actual
argument (arg 1). But macro_start_args() relied on def_buf having already
been allocated, which isn't the case when all the macros are pre-defined.

This fixes issue #1323.
2026-04-15 16:24:32 +01:00
Cary R 9b0d46b4bf Update to the latest GTKWave files 2026-03-27 19:16:23 -07:00
Cary R 1248394a5d Fix possible parallel build race with compile and dep directory 2026-03-27 18:38:34 -07:00
Cary R fa518a3409 Remove versioned manual pages during make clean 2026-03-27 18:38:34 -07:00
Cary R. aa417d7575 Merge pull request #1315 from vowstar/fix/dep-mkdir-race
Fix parallel build race with dep/ directory
2026-03-27 18:20:06 -07:00
Huang Rui f20865a5ea Include mach-o/dyld.h for _NSGetExecutablePath on macOS
driver/main.c uses _NSGetExecutablePath in the __APPLE__ code path
but does not include the header that declares it, causing a build
failure on macOS.

Signed-off-by: Huang Rui <[email protected]>
2026-03-27 11:45:32 +08:00
Huang Rui ac3ef217c3 Fix parallel build race with dep/ directory
Pattern rules that move .d files into dep/ do not depend on the dep
directory target, so parallel make can attempt the move before the
directory exists.

Add dep as an order-only prerequisite to all affected pattern rules.

Bug: https://bugs.gentoo.org/880921
Bug: https://bugs.gentoo.org/911647
Bug: https://bugs.gentoo.org/917344
Closes: https://github.com/steveicarus/iverilog/issues/1314
Signed-off-by: Huang Rui <[email protected]>
2026-03-27 11:29:24 +08:00
Martin Whitaker 6767a07956 Merge branch 'SiB64-strict-parameter-declaration'
Pulled from https://codeberg.org/SiB64/iverilog strict-parameter-declaration
with further enhancements.
2026-03-21 20:53:12 +00:00
Martin Whitaker 42d0c3fd4a Update test suite to cover -gno-strict-declaration options. 2026-03-21 20:50:18 +00:00
Martin Whitaker 5da8894590 Fix documentation for -Wno-declaration-after-use. 2026-03-21 20:21:05 +00:00
Martin Whitaker 4c315b32d4 Change strict-net-declaration to strict-net-var-declaration.
Internally the compiler uses 'net' for both nets and variables, but
we should make it clear to the user that this option applies to both.
2026-03-21 20:18:53 +00:00
Martin Whitaker dc0d162fa9 Report declaration position when warning about declaration after use. 2026-03-21 19:35:29 +00:00
Martin Whitaker 29e128ed94 Only warn about declaration after use once for each data object. 2026-03-21 18:25:15 +00:00
Martin Whitaker 475f098cab Minor grammar and white space fixes in documentation. 2026-03-21 17:20:27 +00:00
Stephan I. Böttcher 7d438b66c8 add option -gno-strict-declaration
The new option allows parameter, net and events to be used before
declaration.  With variants

 -gno-strict-net-declaration for nets and events,
 -gno-strict-parameter-declaration for parameters.
2026-03-18 18:01:54 +01:00
Stephan I. Böttcher 54f17a2cb1 Add warning class -Wno-declaration-after-use
With `-ggno-strict-parameter-declaration` a warning is issued for
parameter use before declaration.  This warning suppressed with
the new class `-Wno-declaration-after-use`, instead of `-Wno-anachronisms`.
2026-03-18 12:46:42 +01:00
Stephan I. Böttcher 42f7d3a922 strict_param_decl: dedup use after decl test 2026-03-18 12:08:39 +01:00
Stephan I. Böttcher 1f8991e382 Emit a warning with -gno-strict-parameter-declaration
When a parameter is used before declaration, a warning is printed,
unless `-Wno-anachronisms`.
2026-03-17 20:32:06 +01:00
Stephan I. Böttcher ab74cafa20 Add option -gno-strict-parameter-declaration
The standards requires that parameters must be declared
before they are used.  Using -gno-strict-parameter-declaration
will allow using a parameter before declaration, e.g., in a port
declaration, with the parameter declared in the body of the
module.  Prior to version 13 this was allowed, so there is a large body
of existing code depending on the pre version 13 behaviour.
2026-03-17 19:39:51 +01:00
Cary R. ff2f4c6864 Merge pull request #1303 from aelmahmoudy/rename-manpage
Rename manpage to iverilog.1 to match executable name
2026-03-08 15:17:54 -07:00
Cary R. d3bda52d69 Fix man page entry for Icarus Verilog documentation 2026-03-08 15:07:02 -07:00
Cary R d64bf0b0b3 Update to the latest GTKWAve files 2026-03-08 14:51:32 -07:00
Cary R c836236b28 Add Copyright to a couple LGPL2 files 2026-03-08 14:07:04 -07:00
Cary R. 462a15dcbb Merge pull request #1302 from aelmahmoudy/fix-typos
Fix typo: contributer -> contributor
2026-03-05 19:08:39 -08:00
أحمد المحمودي (Ahmed El-Mahmoudy) 57385f9ac6 Rename manpage to iverilog.1 to match executable name 2026-03-05 23:38:16 +01:00
أحمد المحمودي (Ahmed El-Mahmoudy) f9a0542a49 Fix typo: contributer -> contributor 2026-03-05 22:48:57 +01:00
Martin Whitaker 14a25bfe92 Update the copy of ax_prog_cc_for_build.m4 embedded in aclocal.m4
This correctly generates the EXEEXT variable when cross-compiling and
using autoconf 2.70+ (issue #1301).
2026-03-05 17:52:09 +00:00
Martin Whitaker 4dfac864ce Remove duplicated typeders and functions from t-dll.h and t-dll.c
These duplicate the contents of ivl_dlfcn.h
2026-03-05 12:01:03 +00:00
Martin Whitaker 3f936d2d8b Merge duplicated ivl_dlfcn.h files.
The vvp/ivl_dlfcn.h and cadpli/ivl_dlfcn.h files are essentially the
same, but have diverged a bit over the years. Merge them into a single
shared file at the top level. Use the static prefix for all inline
functins (currently only used in the cadpli version) as that will fix
issue #1301. We now require the compiler to support at least C99, so
can use "inline", not "__inline__".
2026-03-05 11:55:56 +00:00
Cary R b8de0499a9 Update vvp examples to match the correct version 2026-03-02 10:48:10 -08:00
Cary R 98391b56bc Update example to match new version 2026-03-01 15:31:50 -08:00
Cary R aec9fe98ab Development is now V14 2026-03-01 15:16:47 -08:00
Cary R 9d0f6fc995 Add CREATE_BRANCH.sh script 2026-03-01 14:48:46 -08:00
Cary R 68ba79eb7a Update the default suffix to be dev for master 2026-03-01 14:43:58 -08:00
Cary R 42d591d296 Update install docs and remove a doc build warning 2026-03-01 14:41:22 -08:00
Cary R f3506a8c92 Update the test scripts to print the suffix being used 2026-03-01 14:37:51 -08:00
Cary R 9a7d852782 Fix some documentation links 2026-02-28 07:28:27 -08:00
Cary R 5d8fcdd7bc Specify the documentation is in english 2026-02-28 07:18:08 -08:00
Cary R 9d3cd045ef Update vvp_reg.py to use env to find python3 2026-02-28 07:06:10 -08:00
Cary R 5beeeee3fa Update the development documentation to match reality 2026-02-28 07:06:01 -08:00
Cary R d736cffc11 The MAKE_* scripts are obsolete 2026-02-28 05:35:32 -08:00
Cary R 2302fa37d5 Add V13 release notes 2026-02-27 21:17:43 -08:00
Cary R 15d6e83f8d Cleanup cppcheck 2026-02-24 23:53:57 -08:00
Cary R 4af84bfaad Fix sdf_interconnect4 failure and reenable 2026-02-24 22:24:17 -08:00
Cary R 9b44d55e9a Make br_gh1248 SV safe 2026-02-20 01:23:27 -08:00
Cary R 935f92da05 Disable sdf_interconnect4 until vpi_handle_multi() is working properly 2026-02-20 00:54:53 -08:00
Cary R 71c8963922 Cleanup space issues 2026-02-19 23:48:10 -08:00
Cary R 8385b13356 Add test for br_gh1248 2026-02-19 23:46:15 -08:00
Cary R b46fbe0892 Another const declaration that can be added 2026-02-19 23:40:42 -08:00
Cary R 5e1f1055e1 Add more const declarations 2026-02-19 23:40:34 -08:00
Cary R. de3e50e486 Merge pull request #1249 from FlinkbaumFAU/improve_interconnect_handling
Improve INTERCONNECT handling for SDF Annotation
2026-02-19 23:06:28 -08:00
Cary R 7786fb67c3 Fix manual PDF generation 2026-02-08 23:07:56 -08:00
Cary R f071957736 New cppcheck cleanup 2026-02-08 22:41:47 -08:00
Cary R a838d5143d cleanup Makefile and add complete man PDF generation 2026-02-08 22:41:35 -08:00
Cary R 4cc6ae35dd Fix the valgrind cleanup of automatic array vars 2026-02-06 21:35:13 -08:00
Cary R 911a20c134 Update blif check script to work with python3 2026-02-06 15:06:42 -08:00
Cary R 9da5c1868f New cppcheck cleanup 2026-02-06 15:06:28 -08:00
Cary R 827e08f8d3 Switch blif test to support python3 and use common program name 2026-02-06 09:48:52 -08:00
Cary R 826672705e Move all simulation callback decls to the header 2026-02-06 09:48:41 -08:00
Cary R e9f26a2f11 Declare vpiPostsim() in a header file 2026-02-06 01:59:11 -08:00
Cary R 8f7b2a23eb pthread_exit() is no longer needed and fixes vvp return 2026-02-06 01:55:36 -08:00
Cary R 9df3cc3126 Skip allocating monitor structure until the start of simulation 2026-02-06 01:52:01 -08:00
Cary R 26ba3f62e3 Use "--keep-debuginfo=yes" for valgrind testing 2026-02-06 01:51:49 -08:00
Cary R dc1763bbf5 Add missing include of algorithm in PExpr.cc 2026-01-26 19:26:11 -08:00
Cary R 5b0ce2c6ca Waive last cppcheck message in vvp 2026-01-26 02:12:17 -08:00
Cary R 2f05c831c0 Add more windows get64 fixes 2026-01-25 18:17:59 -08:00
Cary R 8014c5cee2 Add missing declaration for vpi_get64 to vvp.def 2026-01-25 18:00:55 -08:00
Cary R ebf2dc1685 Add basic support for vpi_get64() to return the nexus pointer 2026-01-25 17:50:06 -08:00
Cary R 49fc24a798 Make main directory cppcheck clean 2026-01-25 13:17:18 -08:00
Cary R 33e28df834 Add final cppcheck waivers to get vpi clean 2026-01-25 12:47:16 -08:00
Cary R 7916ae3c49 Make blif cppcheck clean 2026-01-25 12:17:11 -08:00
Cary R 67e48188a9 Make driver-vpi cppcheck clean 2026-01-25 11:09:15 -08:00
Cary R 60b13d020c The sizer is -tsizer 2026-01-25 11:08:58 -08:00
Cary R f040d513a5 Add missing dump.lxt2 2026-01-22 23:05:08 -08:00
Cary R. dfa824c03e Merge pull request #1259 from oscargus/viewerdocs
Fix issues with waveform viewer documentation and mention Surfer
2026-01-22 22:44:23 -08:00
Cary R. 6b276fa316 Merge pull request #1212 from gian21391/pthread-to-std-thread
Using C++11 threads instead of pthread
2026-01-22 22:42:10 -08:00
Cary R 128d970d60 Remove memory leak when checking if a package has any dumpable items 2026-01-21 20:50:44 -08:00
Cary R 068f33b35a Remove memory leak when multi-bit module path delays fail 2026-01-21 20:50:32 -08:00
Cary R e51ce2a8e9 Cleanup vhdl and most of vvp cppcheck issues 2026-01-19 22:54:45 -08:00
Cary R c3d550e03e More cppcheck cleanup 2026-01-19 19:50:10 -08:00
Cary R 2345c51478 Dosify needs to use CPPCHECK and LDFLAGS 2026-01-13 03:07:30 -08:00
Cary R. 964878382d Merge pull request #1279 from aelmahmoudy/fix-missing-buildflags
Add CPPFLAGS & LDFLAGS for building version.exe & draw_tt build targets
2026-01-13 02:50:41 -08:00
Cary R 78fa7a5a10 Update program copyright to 2026 2026-01-13 02:04:37 -08:00
Cary R 4d0a277f3b Cleanup the python version of vlog95 2026-01-13 01:25:24 -08:00
Cary R 951ede0922 A bunch more cppcheck cleanup 2026-01-13 01:25:01 -08:00
Cary R 6651df6f2c Update the vlog95 python tests to pass more options 2026-01-08 01:36:30 -08:00
Cary R 385a0fb46a vlog95: remove check for dimensions in array pattern 2026-01-07 23:51:18 -08:00
Cary R 7dbaa67a02 vlgo95: add partial array pattern support and other cleanup 2026-01-07 23:32:16 -08:00
Cary R 918976651a Fixes for vlog95 generation and gold file updates 2026-01-06 23:02:55 -08:00
Cary R c3abb84ce6 Fix compile warning when long and int have the same width 2026-01-05 20:50:35 -08:00
Cary R 5708010a5c Fix warning in sys_fst.c 2026-01-05 19:12:11 -08:00
Cary R c172a0d3a7 More cppcheck cleanup 2026-01-05 18:59:08 -08:00
Cary R e5943047da Add preliminary support for Python vlog95 testing 2025-12-30 19:44:06 -08:00
Cary R aad14df3d7 Switch to std::round() and a common routine for real to uint64_t 2025-12-16 19:52:36 -08:00
Cary R eff75f8209 Update msys2 ARM LDFLAGS to not use msys strtod hack 2025-12-16 19:52:29 -08:00
Cary R 44611f8301 Add missing override in vhdlpp 2025-12-08 20:58:07 -08:00
Cary R 2b45f4c399 Python test cleanup 2025-12-08 20:57:56 -08:00
Cary R 95ffc97f5f Some cppcheck cleanup for vhdlpp 2025-12-08 20:57:44 -08:00
Cary R 4f31fec5c8 Fix any_of() return 2025-11-23 01:58:48 -08:00
Cary R d87dbb08cf cppcheck updates 2025-11-23 01:31:14 -08:00
Cary R 1c6f0e768a Update vvp_reg.py to support strict, force-sv and with-valgrind 2025-11-22 13:31:27 -08:00
Martin Whitaker 1b1def7f79 CI: update test runner to use macos-15-intel.
macos-13 is deprecated and will be unavailable after December 8th.
2025-11-11 22:53:04 +00:00
Martin Whitaker f5708a0322 Add regression test for issue #1286. 2025-11-11 22:00:06 +00: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 3b209301e2 More cppcheck cleanup 2025-11-11 01:22:11 -08:00
Cary R 87d9d0ac74 Cleanup python test script and add support for a suffix 2025-11-11 01:21:46 -08:00
Cary R a7502173d3 Fix MSYS2 builds after cleanup 2025-10-25 11:09:39 -07:00
Cary R d697312cf8 Cleanup ivt casting for cppcheck 2025-10-25 10:54:12 -07:00
Martin Whitaker efb0ea2ec7 Try a different way to disable PLI1 in MSYS2 CLANG CI. 2025-10-25 15:54:50 +01:00
Martin Whitaker 70094ce564 Disable PLI1 support in MSYS2/CLANG CI. 2025-10-25 15:49:11 +01:00
Martin Whitaker e32584f228 Remove spurious space in MSYS2 PKGBUILD. 2025-10-25 15:23:12 +01:00
Martin Whitaker 9bf45a85e2 Fix errors in MSYS2 PKGBUILD. 2025-10-25 15:15:51 +01:00
Martin Whitaker 97da696b5a Add missing gperf dependency in MSYS2 PKGBUILD. 2025-10-25 14:33:22 +01:00
Martin Whitaker d392dcf07f Fix syntax error in github workflow. 2025-10-25 14:22:51 +01:00
Martin Whitaker e4b3f1bc69 Make MSYS2 build instructions more prominent in the documentation. 2025-10-25 14:16:00 +01:00
Martin Whitaker b69cb8efda Update documentation to describe the --enable-libveriuser config option.
Also fix a typo in the --with-valgrind description.
2025-10-25 14:16:00 +01:00
Martin Whitaker d766248bc1 Update CI to also test ucrt64 and clang64 builds in MSYS2. 2025-10-25 14:16:00 +01:00
Martin Whitaker 587d87bb96 Update MSYS2 PKGBUILD to support ucrt64 and clang64 as well as mingw64.
Also allow extra configuration options to be passed via the
IVL_CONFIG_OPTIONS environment variable and add some missing
dependencies. Don't include --enable-libveriuser by default.
Update the README accordingly, with sensible line wrapping.
2025-10-25 14:16:00 +01:00
Martin Whitaker da853622e9 Don't delete vvp/libvvp.h when running 'make clean'. 2025-10-25 14:16:00 +01:00
Cary R cc496c3cf3 More ivl cppcheck cleanup 2025-10-23 10:01:06 -07:00
Martin Whitaker 3d4f1eb94b Improved run_program() in Perl regression test scripts.
This version works with the native Windows (mingw64 and clang64)
versions of Perl in MSYS2.

Note that warnings are disabled in the Environment.pm module because
Perl fails to notice that OLDOUT and OLDERR are used when restoring
the STDOUT and STDERR file handles.
2025-10-21 21:47:45 +01:00
Cary R 702189a948 Add correct C++ cast for the vpi_modules 2025-10-21 00:44:23 -07:00
Cary R b7292e0179 Another fix for msys CI 2025-10-21 00:27:35 -07:00
Cary R 0b7bd36960 Fix msys2 compile issue in CI 2025-10-21 00:16:35 -07:00
Cary R 860761f9c6 More cppcheck fixes - part 2 2025-10-20 23:54:15 -07:00
Cary R 08c8ee081a More cppcheck updates 2025-10-20 23:54:15 -07:00
Cary R. 929fbf3507 Merge pull request #1282 from steveicarus/msys2-clang-support
MSYS2 clang support
2025-10-20 19:42:30 -07:00
Martin Whitaker 5f651d944b Check that pointers returned by tf_getp are valid.
When the argument is a literal string, tf_getp returns a pointer to
the string. But the return type is a PLI_INT32, so on machines where
pointers are larger than 32 bits, the pointer value may get truncated.
Check for this at run time, and if it occurs, print a warning and
return 0.
2025-10-18 22:31:07 +01:00
Martin Whitaker 6210c307fa Update CI scripts to continue testing PLI 1 support. 2025-10-18 20:07:23 +01:00
Martin Whitaker 935910c3c9 Modify VPI test suite to make PLI 1 tests optional. 2025-10-18 20:05:58 +01:00
Martin Whitaker cf66c64e32 Make support for PLI 1 (libveriuser and cadpli) a config option.
PLI 1 was deprecated in 1364-2005, so disable by default and note that
it is deprecated in the help text.

This works round the problem that the clang linker (lld) in MSYS2 does
not support the -r option, so cannot be used to build libveriuser.a.
2025-10-18 20:02:48 +01:00
Martin Whitaker 8e2d543304 Rework makefiles to eliminate the use of dlltool in Windows builds.
The clang dlltool is not compatible with the binutils dlltool. However
both the clang and binutils linkers support reading the .def file and
creating the import library directly, so we no longer need to perform
the link in two stages.
2025-10-18 20:00:19 +01:00
Martin Whitaker 10770c9129 Optimise Perl regression test scripts.
When redirection operators are included in a command string passed to
the system() subroutine, it spawns an intermediate shell to handle the
redirection. This is particularly inefficient when running the tests
in MSYS2. Creating our own version of system() based on fork() and
exec() allows us to handle the redirection directly.
2025-10-17 20:58:05 +01:00
Martin Whitaker 884349caab Two compiler warning fixes. 2025-10-13 19:18:20 +01:00
Cary R 94dcd658c8 Update exe and manual pages to report @(C) 2025 2025-10-12 19:13:30 -07:00
Cary R fcb543d6e5 Some cppcheck cleanup 2025-10-12 17:37:50 -07:00
Cary R d79e49a372 Fix compile warning 2025-10-12 17:37:50 -07:00
Martin Whitaker 9c62154924 Fix some new compiler warnings seen when using GCC 15 and clang 21.
No functional changes.
2025-10-12 22:23:24 +01:00
Martin Whitaker 4372560290 Post-snapshot cleanup 2025-10-12 11:32:34 +01:00
Martin Whitaker 3e7cc4eac2 Creating snapshot s20251012 2025-10-12 11:32:34 +01:00
Cary R cc1ead51c7 Add a define for CC which is used by the iverilog-vpi script 2025-10-11 11:04:54 -07:00
Cary R 12b87da742 Update config.guess and config.sub to latest versions 2025-10-11 11:02:12 -07:00
Martin Whitaker fede5239ba Fix builds using both --enable-suffix and --enable-libvvp options.
We need to build libvvp with a suffix from the outset to ensure that
the vvp binary searches for the correct library file name once it is
installed.

Also Windows DLLs need to be stored in the same directory as the main
program, not in a separate lib directory.
2025-10-11 12:03:29 +01:00
Martin Whitaker 23b6f955d4 Fix suffixed vvp build under Windows.
Commit 95810b2f61 mistakenly added the suffix to the output file name
when linking the final vvp.exe binary. 'make check' and 'make install'
assume the suffix is only added when installing.
2025-10-11 10:39:46 +01:00
Martin Whitaker a4c90fb5f0 Add regression test for issue #1273. 2025-10-07 21:54:11 +01:00
Martin Whitaker 936f92ebe6 vvp: demangle identifiers when parsing the input file (issue #1273).
The tgt-vvp code generatpr outputs identifiers as quoted strings, and
because of this, escapes any " and \ characters (which may appear in
escaped indentifiers). We need to undo this when reading them into
vvp, so that the original name is seen by the VPI routines.
2025-10-07 21:53:11 +01:00
Martin Whitaker 1fdeb7b982 Add regression tests for $fmonitor tasks.
Also add a test for multiple $monitor task calls and $monitoron and
$monitoroff.
2025-10-05 12:37:30 +01:00
Martin Whitaker 753a52b56c Add support for $fmonitor tasks (issue #1280) 2025-10-05 12:34:25 +01:00
أحمد المحمودي (Ahmed El-Mahmoudy) 8de5e68e83 Add CPPFLAGS & LDFLAGS for building version.exe & draw_tt build targets
Those are needed to be able to add security hardening buold flags by
downstream package maintainers
2025-09-28 17:23:40 +02:00
Cary R. d67d3323ad Merge pull request #1270 from wsnyder/pr1008_finish
Update pr1008.v test to $finish
2025-09-02 07:51:04 -07:00
Wilson Snyder d400fa21bd Update pr1008.v to $finish 2025-09-01 13:41:25 -04:00
Martin Whitaker dad78d5258 Move details of non-standard behaviour from README to Documentation.
Some of this was duplicated in the documentation, some of it was only
in the README. Let's have it all in one place, linked to from the
README.
2025-08-03 18:19:45 +01:00
Martin Whitaker 1be953cfa6 Move documentation of additional system tasks from quirks to extensions. 2025-08-03 17:38:24 +01:00
Martin Whitaker fa5fc0eca0 Copy portability notes from old Wiki to new documentation area.
From https://iverilog.fandom.com/wiki/Verilog_Portability_Notes

Also add formatting tags to $readmempath documentation to make style
consistent.
2025-08-03 17:32:55 +01:00
Martin Whitaker c0e44b4849 Update README to reflect current state of Verilog/SystemVerilog support.
Also
 - remove reference to mingw.txt, which no longer exists
 - extended types are now enabled/disabled by -gxtypes/-gno-xtypes
2025-08-03 15:47:53 +01:00
Cary R db82380cec Minor cppcheck updates in vvp and switch vvp to use override for virtual functions 2025-07-21 23:32:34 -07:00
Cary R 8bd9cb14e7 Cleanup cppcheck suppression file 2025-07-21 23:24:56 -07:00
Cary R 5a4cb616d1 Fix and cleanup tgt-vp based on cppcheck results 2025-07-21 23:21:57 -07:00
Cary R b979441de2 Improve error messages when bad code is passed to the parser 2025-07-21 14:46:56 -07:00
Cary R c7d37bcc21 Error when trying to elaborate a field of a simple variable 2025-07-16 23:37:14 -07:00
Cary R eceb48e5d6 Add better error messages for output port elaboration issues 2025-07-16 22:37:49 -07:00
Cary R e55d9454da Calling front() on an empty() list is undefined 2025-07-13 19:38:43 -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 cfb8ec17d2 Remove space issues 2025-07-09 07:41:16 -07:00
Martin Whitaker 60e4023e6f Fix log output ordering for vpi_control test when running in Windows.
MSYS2 buffers stderr, so we need to flush the buffers to ensure the
log file matches the gold file.
2025-07-08 22:24:46 +01:00
Martin Whitaker a883f2afe6 Add regression test for vpi_control() return value (issue #1208). 2025-07-08 21:52:13 +01:00
Martin Whitaker 7161dc0ab1 Fix return type of vpi_control() and vpi_sim_control() (issue #1208).
These were implemented as returning nothing (void), and passing an
invalid operation value would trigger an assertion failure. The IEEE
standards define them as returning 1 on success and 0 on failure.

vpi_sim_control() is the name used in Verilog-AMS. Strictly speaking
it should return a bool, but to avoid polluting the namespace by
including stdbool.h, we return a PLI_INT32. As C is a weakly typed
language, this should make no practical difference.
2025-07-08 21:14:49 +01:00
Oscar Gustafsson afc1b2a51b Fix issues with waveform viewer documentation and mention Surfer 2025-07-06 12:47:35 +02:00
Martin Whitaker fd7029a299 Add regression tests for issue #1258. 2025-07-05 22:52:52 +01:00
Martin Whitaker dd714d78c4 Make -gno-specify suppress unsupported timing check warnings (issue #1258) 2025-07-05 22:44:59 +01:00
Martin Whitaker aec91c7754 Add regression tests for issue #1256. 2025-07-05 18:21:32 +01:00
Martin Whitaker 0ecb71625b Support assignment of parray slices (issue #1256)
The existing elaboration code only allowed assignments from/to individual
elements and either failed an assertion (when assigning the entire array)
or failed to compile (when assigning an array slice).
2025-07-05 18:02:40 +01:00
Cary R f82c6c7b3a Add missing gold and fix VHDL inout test 2025-07-01 00:04:09 -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
Cary R 46a5078a68 When optimizing the size of a case keep the sign of the condition 2025-06-25 00:11:22 -07:00
Cary R 6426afc8d0 Avoid overflow in genvar to make duplicate 2025-06-21 18:27:54 -07:00
Cary R a2ffbc307a Validate the generate "loop" expressions 2025-06-21 16:58:30 -07:00
Cary R adcb9f4e0d Add support for passing a real input to logic, mos and if gates 2025-06-21 10:04:12 -07:00
Cary R 26c01e7f0a Use preincrement instead of post in for loop incr 2025-06-20 12:48:01 -07:00
Michael Kupfer 7c60005d1a Improve INTERCONNECT handling for SDF Annotation
Improve path search between nets, so that paths containing
concats as well as part selects can be found.

Signed-off-by: Michael Kupfer <[email protected]>
2025-06-06 17:34:09 +02:00
Cary R ea26587b5e The FST dump file is now a fstWriterContext 2025-05-11 22:53:29 -07:00
Cary R 1aec31ac27 Update to the latest FST files from GTKWave 2025-05-11 22:30:40 -07:00
Martin Whitaker b11749e04c Remove Ubuntu 20.04 from workflows as the runner has been retired. 2025-05-11 11:59:04 +01:00
Martin Whitaker b7f9be9370 Add regression test for issue #1242. 2025-05-11 11:39:29 +01:00
Martin Whitaker 2b01cf335c Increment line number when parsing "// synthesis" pragmas (issue #1242)
Thanks to Robert Lance for proposing the fix.
2025-05-11 11:38:28 +01:00
Cary R. 7e238e7ca5 Merge pull request #1229 from AndreasLoow/typo
Typo in `regress-vvp.list`
2025-03-31 13:00:05 -07:00
Andreas Lööw 4138fcf6c4 typo in regress-vvp.list 2025-03-31 08:44:22 +01:00
Lars-Peter Clausen f5decd471d Merge pull request #1228 from AndreasLoow/typos
Typos in regress-sv.list
2025-03-30 21:03:06 -07:00
Andreas Lööw 7e95dfff5a remove trailing commas 2025-03-30 13:51:44 +01:00
Andreas Lööw bf45073359 typo: nornal -> normal 2025-03-30 13:51:20 +01:00
Cary R b0c57ab177 Update fstapi files to latest from GTKWave 2025-03-12 17:43:38 -07:00
Gianluca Martino 60f5026ae4 Fixed double join in lxt2 writer. 2025-02-25 16:06:32 +01:00
Gianluca MartinoandLars-Peter Clausen 25104ca2a8 work_queue_fill is an unsigned so we can simplify the condition variable predicate.
Co-authored-by: Lars-Peter Clausen <[email protected]>
2025-02-25 12:54:59 +01:00
Gianluca Martino 9afaf6f136 Removed pthread dependency in vcd_priv2.cc 2025-02-19 11:11:40 +01:00
Gianluca Martino cfa4a289ec Adding missing include. 2025-02-19 10:39:40 +01:00
Cary R 99580cd051 Fix warnings that toupper() takes an int 2025-02-17 09:37:18 -08:00
Cary R 6088a26d78 Update VPI example to not have warnings 2025-02-13 01:04:41 -08:00
Cary R 1b729831b7 Cast ispace()/isdigit() args to int to remove warning 2025-02-13 00:03:18 -08:00
Cary R 0ca26c95d8 Cygwin also does not have docopt by default 2025-02-13 00:03:09 -08:00
Cary R 7f4ff37ad0 For cygwin we need to use -std=gnu++11 to get strdup() 2025-02-13 00:02:54 -08:00
Lars-Peter Clausen 14375567c7 Merge pull request #1203 from larsclausen/cast-to-real
Reject invalid casts to real
2025-01-15 19:37:41 -08:00
Lars-Peter Clausen eb90bcf313 Add regression tests for invalid casts to real
Check that invalid casts to real are reported as an error.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2025-01-12 20:34:31 -08:00
Lars-Peter Clausen 4c03ac5b36 Reject invalid casts to real
Only vector types can be cast to real. Report an error when trying to cast
a different type instead of triggering an assert later on.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2025-01-12 19:51:59 -08:00
Cary R 30123f8945 Update fstapi.c to the latest from GTKWave 2025-01-08 19:37:13 -08:00
Lars-Peter Clausen 27bae7eab1 Merge pull request #1201 from larsclausen/nested-lvalue-types
tgt-vvp: Support nested lvalues for all property types
2025-01-07 19:51:37 -08:00
Lars-Peter Clausen e2008c9c0e Add regression tests for nested lvalue object properties
Check that nested object properties of different types are supported as
lvalues.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2025-01-05 16:55:16 -08:00
Lars-Peter Clausen 60b6435653 tgt-vvp: Support nested lvalues for all property types
Currently nested lvalues are only supported for vector typed properties.
Refactor the code to also support other types.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2025-01-05 16:54:18 -08:00
Lars-Peter Clausen b794b9cc26 Merge pull request #1199 from larsclausen/assignment-op
Add support for assignment ops on class properties and dynamic array or queue elements
2025-01-05 16:53:04 -08:00
Lars-Peter Clausen 9f8a8959a7 Add regression tests for assignment operators on queue and darray elements
Check that assignment operators work as expected on queue and dynamic array
elements.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2025-01-05 15:55:34 -08:00
Lars-Peter Clausen 7c970e91b9 Add regression tests for assignment operators on class properties
Check that assignment operators are supported for class properties.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2025-01-05 15:55:20 -08:00
Lars-Peter Clausen 43c138fdd3 tgt-vvp: Support assignment operators on queues and dynamic array elements
Currently assignment operators on queues and dynamic elements trigger an
assert.

Add support for handling this properly. Since the operation for loading an
element for an queue or dynamic array is identical most of the code can be
shared, only writing back the value has to be handled separately.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2025-01-05 15:55:01 -08:00
Lars-Peter Clausen 867c7d18b4 tgt-vvp: Support assignment operators on object properties
Currently assignment operators on object properties are silently
ignored. Make sure that they are handled.

To enable this refactor the code a bit so that the assignment
operator handling can be shared between object property assignments
and scalar value assignments.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2025-01-05 15:55:01 -08:00
Lars-Peter Clausen d0327c5eda Merge pull request #1200 from larsclausen/class-property-logic-init
vvp: Fix logic class property initialization
2025-01-05 15:52:12 -08:00
Lars-Peter Clausen c22b375c86 Add regression test for logic class property default value
Check that class logic class properties get initialized to 'x.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2025-01-05 09:46:07 -08:00
Lars-Peter Clausen 4854de06ca vvp: Fix logic class property initialization
Logic type class properties use the wrong constructor resulting in a
default value of a vector with 0 width. Switch to the right constructor to
fix this.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2025-01-05 09:34:25 -08:00
Martin Whitaker 4471961ed4 Modify snapshot/release creation scripts to run autoconf.sh
Then temporarily add the resulting configure and lexor_keywords.cc
files to the repository so they will be included in the snapshot and
release tarballs that are automatically generated by GitHub. Remove
these files in the post-snapshot/post-release cleanup.
2025-01-05 13:53:22 +00:00
Lars-Peter Clausen 23a7c80dde Merge pull request #1197 from larsclausen/tgt-vvp-remove-implict-cast
tgt-vvp: Remove implicit casts between vector and real
2025-01-03 10:41:37 -08:00
Cary R e3a5567ceb Document how to override a string parameter 2025-01-03 10:41:11 -08:00
Martin Whitaker 9e60be2946 Post-snapshot cleanup 2025-01-03 17:34:34 +00:00
Lars-Peter Clausen 1e9cfc34c0 tgt-vvp: Remove implicit casts between vector and real
Remove implicit casts between vector and real in tgt-vvp. These are not
required since any implicit cast in the source will be converted to an
explicit cast in the elaboration stage.

Signed-off-by: Lars-Peter Clausen <[email protected]>
2025-01-02 17:40:29 -08:00
1469 changed files with 40758 additions and 16322 deletions
-16
View File
@@ -1,16 +0,0 @@
#!/usr/bin/env sh
echo "Using the bundled ivtest to run regression tests."
echo " pwd = $(pwd)"
cd ivtest
status=0
perl vvp_reg.pl || status=1
perl vpi_reg.pl || status=1
python3 vvp_reg.py || status=1
exit $status
+6 -1
View File
@@ -19,10 +19,15 @@ jobs:
- name: Install dependencies
run: |
sudo apt update -qq
sudo apt install -y make autoconf python3-sphinx
sudo apt install -y make autoconf python3-venv
python3 -m venv .venv
. .venv/bin/activate
pip install --upgrade pip
pip install -r Documentation/requirements.txt
- name: Make Documentation
run: |
. .venv/bin/activate
cd Documentation
make html
+62 -27
View File
@@ -14,61 +14,82 @@ jobs:
mac:
strategy:
fail-fast: false
runs-on: macos-13
name: '🍏 macOS'
matrix:
libvvp: [true]
suffix: [true]
runs-on: macos-15-intel
name: 🍏 macOS${{ matrix.libvvp && ' +libvvp' || '' }}${{ matrix.suffix && ' +suffix' || '' }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Install dependencies
run: |
brew install bison
pip3 install --break-system-packages docopt
- name: Build, check and install
run: |
export PATH="/usr/local/opt/bison/bin:$PATH"
CONFIG_OPTS="--enable-libveriuser"
if [ "${{ matrix.libvvp }}" = "true" ]; then
CONFIG_OPTS="$CONFIG_OPTS --enable-libvvp"
fi
if [ "${{ matrix.suffix }}" = "true" ]; then
CONFIG_OPTS="$CONFIG_OPTS --enable-suffix"
fi
autoconf
./configure
./configure $CONFIG_OPTS
make -j$(nproc) check
sudo make install
- name: Test
run: ./.github/test.sh
run: |
make check-installed
lin:
strategy:
fail-fast: false
matrix:
os: [
'20.04',
'22.04',
'24.04'
]
os: ['22.04', '24.04']
# libvvp: [false, true]
# suffix: [false, true]
runs-on: ubuntu-${{ matrix.os }}
name: '🐧 Ubuntu ${{ matrix.os }}'
name: 🐧 Ubuntu ${{ matrix.os }}${{ matrix.libvvp && ' +libvvp' || '' }}${{ matrix.suffix && ' +suffix' || '' }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Install dependencies
run: |
sudo apt update -qq
sudo apt install -y make g++ git bison flex gperf libreadline-dev libbz2-dev autoconf python3-sphinx python3-docopt
sudo apt install -y make g++ git bison flex gperf libreadline-dev libbz2-dev autoconf python3-venv
python3 -m venv .venv
. .venv/bin/activate
pip install --upgrade pip
pip install -r Documentation/requirements.txt
- name: Build, check and install
run: |
CONFIG_OPTS="--enable-libveriuser"
if [ "${{ matrix.libvvp }}" = "true" ]; then
CONFIG_OPTS="$CONFIG_OPTS --enable-libvvp"
fi
if [ "${{ matrix.suffix }}" = "true" ]; then
CONFIG_OPTS="$CONFIG_OPTS --enable-suffix"
fi
autoconf
./configure
./configure $CONFIG_OPTS
make -j$(nproc) check
sudo make install
- name: Test
run: ./.github/test.sh
run:
make check-installed
- name: Documentation
run: |
. .venv/bin/activate
cd Documentation
make html
@@ -77,10 +98,14 @@ jobs:
strategy:
fail-fast: false
matrix:
include: [
{ msystem: MINGW64, arch: x86_64 }
]
name: 🟪 ${{ matrix.msystem}} · ${{ matrix.arch }}
msystem: [MINGW64, UCRT64, CLANG64]
# libvvp: [false, true]
# suffix: [false, true]
include:
- { msystem: MINGW64, env: x86_64 }
- { msystem: UCRT64, env: ucrt-x86_64 }
- { msystem: CLANG64, env: clang-x86_64 }
name: 🟪 ${{ matrix.msystem }}${{ matrix.libvvp && ' +libvvp' || '' }}${{ matrix.suffix && ' +suffix' || '' }}
defaults:
run:
shell: msys2 {0}
@@ -91,7 +116,7 @@ jobs:
- run: git config --global core.autocrlf input
shell: bash
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- uses: msys2/setup-msys2@v2
with:
@@ -100,17 +125,27 @@ jobs:
install: >
git
base-devel
gperf
python-pip
mingw-w64-${{ matrix.arch }}-toolchain
mingw-w64-${{ matrix.env }}-perl
- uses: actions/setup-python@v5
- uses: actions/setup-python@v6
with:
python-version: '>=3.5'
- name: Build and check
run: |
cd msys2
CONFIG_OPTS=""
if [ ${{ matrix.msystem }} != "CLANG64" ] ; then
CONFIG_OPTS="$CONFIG_OPTS --enable-libveriuser"
fi
if [ "${{ matrix.libvvp }}" = "true" ] ; then
CONFIG_OPTS="$CONFIG_OPTS --enable-libvvp"
fi
if [ "${{ matrix.suffix }}" = "true" ]; then
CONFIG_OPTS="$CONFIG_OPTS --enable-suffix"
fi
export IVL_CONFIG_OPTIONS="$CONFIG_OPTS"
makepkg-mingw --noconfirm --noprogressbar -sCLf
- name: Install
@@ -118,9 +153,9 @@ jobs:
- name: Test
run: |
./.github/test.sh
make check-installed
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7
with:
name: ${{ matrix.msystem }}-${{ matrix.arch }}
name: 🟪 ${{ matrix.msystem }}${{ matrix.libvvp && ' +libvvp' || '' }}
path: msys2/*.zst
+26 -21
View File
@@ -8,6 +8,10 @@
*.swp
*~
# Virtual environments
.conda/
.venv/
# Top level generic files
tags
TAGS
@@ -31,16 +35,19 @@ Makefile
/_pli_types.h
config.h
/tgt-pcb/pcb_config.h
/tgt-pcb/fp.cc
/tgt-pcb/fp.h
/tgt-pcb/fp.output
/tgt-pcb/fp_lex.cc
/tgt-vvp/vvp_config.h
/tgt-vhdl/vhdl_config.h
/vhdlpp/vhdlpp_config.h
/vpi/vpi_config.h
stamp-*-h
/version.h
/version_tag.h
/version_base.h
/driver-vpi/iverilog-vpi.man
/driver-vpi/res.rc
/driver/iverilog.man
/vvp/libvvp.pc
/vvp/vvp.man
# Directories
autom4te.cache
@@ -52,8 +59,6 @@ dep
*.vpi
/cadpli/cadpli.vpl
/tgt-blif/Makefile
# lex, yacc and gperf output
/driver/cflexor.c
/driver/cfparse.c
@@ -62,14 +67,6 @@ dep
/ivlpp/lexor.c
/vhdlpp/lexor.cc
/vhdlpp/lexor_keyword.cc
/vhdlpp/parse.cc
/vhdlpp/parse.h
/vhdlpp/parse.output
/vhdlpp/vhdlpp_config.h
/vhdlpp/vhdlpp
/lexor.cc
/lexor_keyword.cc
/parse.cc
@@ -78,6 +75,17 @@ dep
/syn-rules.cc
/syn-rules.output
/tgt-pcb/fp.cc
/tgt-pcb/fp.h
/tgt-pcb/fp.output
/tgt-pcb/fp_lex.cc
/vhdlpp/lexor.cc
/vhdlpp/lexor_keyword.cc
/vhdlpp/parse.cc
/vhdlpp/parse.h
/vhdlpp/parse.output
/vpi/sdf_lexor.c
/vpi/sdf_parse.c
/vpi/sdf_parse.h
@@ -97,17 +105,13 @@ dep
# Program created files
/vvp/tables.cc
/iverilog-vpi.man
/driver-vpi/res.rc
/driver/iverilog.man
/vvp/vvp.man
# The executables.
*.exe
/driver/iverilog
/iverilog-vpi
/driver-vpi/iverilog-vpi
/ivl
/ivlpp/ivlpp
/vhdlpp/vhdlpp
/vvp/vvp
/ivl.exp
@@ -115,3 +119,4 @@ dep
# Check output
/check.vvp
/driver/top.vvp
+8 -5
View File
@@ -1,7 +1,7 @@
#ifndef IVL_AStatement_H
#define IVL_AStatement_H
/*
* Copyright (c) 2008-2021 Stephen Williams ([email protected])
* Copyright (c) 2008-2026 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -40,10 +40,13 @@ class AContrib : public Statement {
public:
AContrib(PExpr*lval, PExpr*rval);
~AContrib();
~AContrib() override;
virtual void dump(std::ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
AContrib(const AContrib&) = delete;
AContrib& operator=(const AContrib&) = delete;
virtual void dump(std::ostream&out, unsigned ind) const override;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
private:
PExpr*lval_;
@@ -61,7 +64,7 @@ class AProcess : public LineInfo {
AProcess(ivl_process_type_t t, Statement*st)
: type_(t), statement_(st) { }
~AProcess();
~AProcess() override;
bool elaborate(Design*des, NetScope*scope) const;
+20 -6
View File
@@ -20,7 +20,7 @@
# -- Project information -----------------------------------------------------
project = 'Icarus Verilog'
copyright = '2024, Stephen Williams'
copyright = '2024-2026, Stephen Williams'
author = 'Stephen Williams'
# The short X.Y version
@@ -58,7 +58,7 @@ master_doc = 'index'
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
language = 'en'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
@@ -73,21 +73,35 @@ highlight_language = 'none'
# -- Options for HTML output -------------------------------------------------
# A dictionary of values to pass into the template engine's context for all pages.
#
html_context = {
# Edit this page
"source_type": "github",
"source_user": "steveicarus",
"source_repo": "iverilog",
"source_version": "master",
"source_docs_path": "/Documentation/",
}
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'
html_theme = 'shibuya'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
# html_theme_options = {}
html_theme_options = {
"github_url": "https://github.com/steveicarus/iverilog",
}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
#html_static_path = ['_static']
html_static_path = []
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
@@ -141,7 +155,7 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'icarusverilog', 'Icarus Verilog Documentation',
(master_doc, 'iverilog-docs', 'Icarus Verilog Documentation',
[author], 1)
]
+28 -5
View File
@@ -103,6 +103,22 @@ reference the correct run time files and directories. The run time will check
that it is running a file with a compatible version e.g.(you can not run a
V0.9 file with the V0.8 run time).
.. code-block:: none
--enable-libvvp
The vvp program is built as a small stub linked to a shared library,
libvvp.so, that may be linked with other programs so that they can host
a vvp simulation.
.. code-block:: none
--enable-libveriuser
PLI version 1 (the ACC and TF routines) were deprecated in IEEE 1364-2005.
These are supported in Icarus Verilog by the libveriuser library and cadpli
module. Starting with v13, these will only be built if this option is used.
A debug options is:
.. code-block:: none
@@ -111,7 +127,7 @@ A debug options is:
This option adds extra memory cleanup code and pool management code to allow
better memory leak checking when valgrind is available. This option is not
need when checking for basic errors with valgrind.
needed when checking for basic errors with valgrind.
Compiling on Linux
------------------
@@ -163,13 +179,21 @@ example:
.. code-block:: console
% cd ivtest
% ./vvp_reg.pl --strict
% ./vvp_reg.pl
% ./vvp_reg.py
% ./vpi_reg.pl
will run all the regression tests for the simulation engine. (This is what
most people will want to do.) You should rerun this test before submitting
most people will want to do.) You should rerun these tests before submitting
patches to the developers. Also, if you are adding a new feature, you should
add test programs to the regression test suite to validate your new feature
(or bug fix.)
(or bug fix.). The python script is the preferred method to add new tests.
All of these scripts take other options to test various configurations. What
options are supported can be found by using the ``-h/--help`` argument. There
is also a separate ``vlog95_reg.pl`` script for testing the vlog95 translation
of the original tests. This is integrated into the existing Python test script
for the new tests.
Note that pull requests will be required to pass these regression tests before
being merged.
@@ -222,4 +246,3 @@ or the version branch that you are working on. Your pull request will be run
through continuous integration, and reviewed by one of the main
authors. Feedback may be offered to your PR, and once accepted, an approved
individual will merge it for you. Then you are done.
+1 -1
View File
@@ -8,7 +8,7 @@ source code itself, so that you can find the global parts where you
can look for even better detail.
The documentation for getting, building and installing Icarus Verilog
is kept and maintained at :doc:`Getting Started as a Contributer <../getting_started>`
is kept and maintained at :doc:`Getting Started as a Contributor <../getting_started>`
See the Installation Guide for getting the current source from the git
repository (and how to use the git repository) and see the Developer Guide
@@ -812,6 +812,10 @@ result is pushed back on the vec4 stack.
This opcode multiplies two real words together.
* %neg/wr
This opcode negates the real value on top of the real stack.
* %nand
Perform the bitwise NAND of two vec4 vectors, and push the result. Each
+9 -5
View File
@@ -54,11 +54,6 @@ This describes the kind of test to run. The valid values are:
that succeeds execute it using the vvp command. If there is no gold file
specified, then look for an output line with the "PASSED" string.
* **normal-vlog95** - This is similar to the normal case, but uses
the -tvlog95 target in a first pass to generate simplified verilog, then a
regular iverilog command with the -tvvp target to generate the actual
executable. This tests the -tvlog95 target.
* **NI** - Mark the test as not implemented. The test will be skipped without
running or reporting an error.
@@ -68,6 +63,9 @@ This describes the kind of test to run. The valid values are:
* **EF** - Compile and run, but expect the run time to fail. This means the
run time program must return an error exit.
* **TE** - This is specific to testing the vlog95 conversion and indicates the
translated code failed to compile.
gold (optional)
^^^^^^^^^^^^^^^
@@ -123,3 +121,9 @@ vvp-args-extended (optional)
If this is specified, it is a lost of strings that are passed as arguments to
the vvp command. These are extended arguments, and are placed after the vvp
input file that is being run. This is where you place things like plusargs.
strict, force-sv or vlog95 (optional)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Any of these can be used to create overrides for the type, gold or
iverilog-args when the given test type is run.
+3 -8
View File
@@ -17,7 +17,7 @@ the "make version" target, or automatically if the version_tag.h
file doesn't exist at all. This implies that a "make version" is
something worth doing when you do a "git pull" or create commits.
The files below are now edited by the makefile and the version.exe program:
The files below are now edited by the Makefile:
* iverilog-vpi.man -- The .TH tag has a version string
* driver/iverilog.man -- The .TH tag has a version string
@@ -28,10 +28,5 @@ This now includes version_base.h to get the version:
* vpi/vams_simparam.c -- Hard coded result to simulatorVersion query
This is actually a test file list that is specific to a major version.
The regression test scripts query the version of the compiler to infer
that it must include this list of tests. For example, for version 12.x
of the compiler, the needs to be an ivltest/regress-v12.list file that
lists the tests that are specific to that version.
* ivltests/regress-XXX.list -- Version specific regression tests
The test suite no longer has version specific files since it tracks along with
the code/branch.
+1
View File
@@ -12,6 +12,7 @@ Welcome to the documentation for Icarus Verilog.
:maxdepth: 2
:caption: Contents:
releases/index
usage/index
targets/index
developer/index
+10
View File
@@ -0,0 +1,10 @@
Icarus Verilog Release Notes
============================
This section contains the release notes for all releases after and including
V13.0. Older release notes can be found here: `<https://iverilog.fandom.com/wiki/User_Guide>`__
.. toctree::
:maxdepth: 1
v13-0-release-note
@@ -0,0 +1,98 @@
🎉 Release V13.0
================
The Icarus Verilog development team is pleased to announce **Release V13** of Icarus Verilog.
Release V13 builds on the V12 series with a focus on correctness, runtime stability, improved
diagnostics, and incremental standard conformance improvements.
----
🐞 Bug Fix Summary
------------------
Release V13 resolves numerous issues reported against V12, including:
* Incorrect signed constant handling.
* Generate block naming collisions.
* Elaboration-time assertion failures.
* Runtime crashes in malformed corner cases.
* Memory management issues during elaboration and simulation.
----
🔄 Major Changes in V13
=======================
🧠 Language & Elaboration Fixes
-------------------------------
Release V13 includes multiple fixes to elaboration and expression handling:
* Resolved generate block scope resolution issues affecting nested and conditional generate constructs.
* Corrected signed arithmetic corner cases, including shift and width propagation behavior.
* Fixed constant expression evaluation inconsistencies during parameter elaboration.
* Improved handling of packed and unpacked arrays in assignments and port binding corner cases.
* Addressed elaboration-time assertion failures triggered by malformed or ambiguous constructs.
* Corrected several source-location reporting issues for elaboration errors.
These changes improve standards conformance and eliminate behavioral inconsistencies observed in the V12 series.
----
⚙️ Simulator (vvp) Improvements
-------------------------------
The `vvp` runtime engine has received internal stability and correctness updates:
* Improved event scheduling behavior in zero-delay and non-blocking assignment scenarios.
* Fixed race-condition corner cases uncovered by expanded regression testing.
* Eliminated memory leaks affecting long-running or large simulations.
* Resolved crash conditions caused by invalid internal state transitions.
* Improved robustness of `$dumpvars` handling in large hierarchical designs.
* General runtime consistency and determinism improvements.
`vvp` continues to enforce version matching between the runtime and generated bytecode. Designs
must be recompiled after upgrading.
----
🔌 VPI Updates
--------------
Fixes improve VPI reliability and conformance:
* Corrected hierarchical object lookup behavior in specific corner cases.
* Improved stability of callback registration during startup and shutdown.
* Fixed invalid handle dereference scenarios that could result in segmentation faults.
* Addressed inconsistencies in VPI object property reporting.
----
🛠 Diagnostics & Toolchain
--------------------------
* Improved clarity and consistency of error and warning messages.
* Better reporting of width mismatches and implicit net declarations.
* More accurate diagnostic source locations.
* Build system updates for compatibility with modern compiler toolchains.
* Regression suite expansion and CI validation improvements.
----
📦 Upgrade Notes
----------------
* Recompile all designs when upgrading from V12 or any other prior version.
* Review warnings carefully; improved diagnostics may expose previously silent issues.
* The only known breaking change is that wires must now be declared before use; which is required in the standard (see `gh1287 <https://github.com/steveicarus/iverilog/issues/1287>`__).
----
🙏 Acknowledgments
------------------
We thank all contributors who reported issues, submitted patches, expanded regression coverage, and
improved documentation. Release 13 reflects continued community effort toward improving correctness,
stability, and maintainability.
+2
View File
@@ -0,0 +1,2 @@
sphinx==8.1.3
shibuya==2026.1.9
+2 -2
View File
@@ -1,6 +1,6 @@
The sizer Code Analyzer (-tvvp)
===============================
The sizer Code Analyzer (-tsizer)
=================================
The sizer target does not generate any code. Instead it will print statistics about the Verilog code.
@@ -68,6 +68,16 @@ These flags affect the general behavior of the compiler.
This flag enables the IEEE1800-2012 standard, which includes
SystemVerilog.
* 2017
This flag enables the IEEE1800-2017 standard, which includes
SystemVerilog.
* 2023
This flag enables the IEEE1800-2023 standard, which includes
SystemVerilog.
* verilog-ams
This flag enables Verilog-AMS features that are supported by Icarus
@@ -131,6 +141,18 @@ These flags affect the general behavior of the compiler.
containing an unsized constant number, and unsized constant numbers are
not truncated to integer width.
* strict-declaration/no-strict-declaration
* strict-net-var-declaration/no-strict-net-var-declaration
* strict-parameter-declaration/no-strict-parameter-declaration
The standards require that nets, variables, and parameters must be
declared lexically before they are used. Using -gno-strict-declaration
will allow using a data object before declaration, with a warning. The
warning can be suppressed with -Wno-declaration-after-use. The option
can be applied for nets and variables and for parameters separately.
* shared-loop-index/no-shared-loop-index
Enable or disable the exclusion of for-loop control variables from
@@ -260,6 +282,7 @@ These flags affect the general behavior of the compiler.
-Wanachronisms
-Wimplicit
-Wimplicit-dimensions
-Wdeclaration-after-use
-Wmacro-replacement
-Wportbind
-Wselect-range
@@ -288,6 +311,15 @@ These flags affect the general behavior of the compiler.
This flag is supported in release 10.1 or master branch snapshots after
2016-02-06.
* declaration-after-use
This enables warnings for declarations after use, when those are not
flagged as errors (enabled by default). Use no-declaration-after-use
to disable this.
This flag was added in version 14.0 or later (and is in the master branch
as of 2026-03-21).
* macro-redefinition
This enables warnings when a macro is redefined, even if the macro text
@@ -7,8 +7,91 @@ standard. Some of these are picked from extended variants of the
language, such as SystemVerilog, and some are expressions of internal
behavior of Icarus Verilog, made available as a tool debugging aid.
Built-in System Functions
-------------------------
Don't use any of these extensions if you want to keep your code portable
across other Verilog compilers.
System Functions
----------------
``$is_signed(<expr>)``
^^^^^^^^^^^^^^^^^^^^^^
This function returns 1 if the expression contained is signed, or 0 otherwise.
This is mostly of use for compiler regression tests.
``$bits(<expr>)``, ``$sizeof(<expr>)``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The ``$bits`` system function returns the size in bits of the expression that
is its argument. The result of this function is undefined if the argument
doesn't have a self-determined size.
The ``$sizeof`` system function is deprecated in favour of ``$bits``, which is
the same thing, but included in the SystemVerilog definition.
``$simtime()``
^^^^^^^^^^^^^^
This returns as a 64bit value the simulation time, unscaled by the time units
of the local scope. This is different from the ``$time`` and ``$stime``
functions which return the scaled times. This function is added for regression
testing of the compiler and run time, but can be used by applications who
really want the simulation time.
Note that the simulation time can be confusing if there are lots of different
```timescales`` within a design. It is not in general possible to predict
what the simulation precision will turn out to be.
``$mti_random()``, ``$mti_dist_uniform``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
These functions are similar to the IEEE 1364 standard ``$random`` functions,
but they use the Mersenne Twister (MT19937) algorithm. This is considered an
excellent random number generator, but does not generate the same sequence as
the standardized ``$random``.
System Tasks
------------
``$readmempath``
^^^^^^^^^^^^^^^^
The ``$readmemb`` and ``$readmemh`` system tasks read text files that contain
data values to populate memories. Normally, those files are found in a current
working directory. The ``$readmempath()`` system task can be used to create a
search path for those files. For example:
.. code-block:: verilog
reg [7:0] mem [0:7];
initial begin
$readmemh("datafile.txt", mem);
end
This assumes that "datafile.txt" is in the current working directory where
the ``vvp`` command is running. But with the ``$readmempath``, one can specify
a search path:
.. code-block:: verilog
reg [7:0] mem [0:7];
initial begin
$readmempath(".:alternative:/global/defaults");
$readmemh("datafile.txt", mem);
end
In this example, "datafile.txt" is searched for in each of the directories
in the above list (separated by ":" characters). The first located instance
is the one that is used. So for example, if "./datafile.txt" exists, then it
is read instead of "/global/defaults/datafile.txt" even if the latter exists.
``$finish_and_return(code)``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This task operates the same as the ``$finish`` system task, but adds the
feature of specifying an exit code for the interpreter. This can be useful in
automated test environments to indicate whether the simulation finished with
or without errors.
Extended Verilog Data Types
---------------------------
+417 -26
View File
@@ -9,39 +9,430 @@ standard, or from other implementations.
This is NOT AN EXHAUSTIVE LIST. If something is missing from this list, let us
know and we can add documentation.
System Tasks - Unique to Icarus Verilog
---------------------------------------
Unsized Numeric Constants are Not Limited to 32 Bits
----------------------------------------------------
These are system tasks that are unique to Icarus Verilog. Don't use any of
these if you want to keep your code portable across other Verilog compilers.
The Verilog standard allows Verilog implementations to limit the size of
unsized constants to a bit width of at least 32. That means that a constant
17179869183 (``36'h3_ffff_ffff``) may overflow some compilers. In fact, it
is common to limit these values to 32 bits. However, a compiler may just as
easily choose another width limit, for example 64 bits. That value is
equally good.
$readmempath
^^^^^^^^^^^^
The "$readmemb" and "$readmemh" system tasks read text files that contain data
values to populate memories. Normally, those files are found in a current work
directory. The "$readmempath()" system task can be used to create a search
path for those files. For example:
However, it is not required that an implementation truncate at 32 bits, and
in fact Icarus Verilog does not truncate at all. It will make the unsized
constant as big as it needs to be to hold the value accurately. This is
especially useful in situations like this;
.. code-block:: verilog
reg [7:0] mem [0:7];
initial begin
$readmemh("datafile.txt", mem);
end
reg [width-1:0] foo = 17179869183;
This assumes that the "datafile.txt" is in the current working directory where
the vvp command is running. But with the "$readmempath", one can specify a
search path:
The programmer wants the constant to take on the width of the reg, which in
this example is parameterized. Since constant sizes cannot be parameterized,
the programmer ideally gives an unsized constant, which the compiler then
expands/contracts to match the l-value.
Also, by choosing to not ever truncate, Icarus Verilog can handle code written
for a 64 bit compiler as easily as for a 32 bit compiler. In particular, any
constants that the user does not expect to be arbitrarily truncated by their
compiler will also not be truncated by Icarus Verilog, no matter what that
other compiler chooses as a truncation point.
Unsized Expressions
-------------------
Icarus Verilog classes any expression containing an unsized numeric constant
or unsized parameter value that is not part of a self-determined operand as
an unsized expression. When calculating the bit width of an unsized expression,
it extends the width of the expression to avoid arithmetic overflow or
underflow; in other words, the expression width will be made large enough to
represent any possible arithmetic result of the expression. If the expression
contains operations that do not follow the normal rules of arithmetic (e.g. an
explicit or implicit cast between signed and unsigned values), the expression
width will be extended to at least the width of an integer.
An exception to the above is made if the expression contains a shift or power
operator with a right hand operand that is a non-constant unsized expression.
In this case any expansion of the expression width due to that operation is
limited to the width of an integer, to avoid excessive expression widths
(without this, an expression such as ``2**(i-1)``, where ``i`` is an integer,
would be expanded to 2\**33 bits).
The above behaviour is a deviation from the Verilog standard, which states
that when calculating an expression width, the width of an unsized constant
number is the same as the width of an integer. If you need strict standard
compliance (for compatibility with other EDA tools), then the compiler has
a command line option, ``-gstrict-expr-width``, which disables the special
treatment of unsized expressions. With this option, the compiler will output
a warning message if an unsized numeric constant is encountered that cannot
be represented in integer-width bits and will truncate the value.
If you are simulating synthesisable code, it is recommended that the
``-gstrict-expr-width`` option is used, as this eliminates a potential
source of synthesis vs. simulation mismatches.
Unsized Parameters
------------------
Icarus Verilog classes any parameter declaration that has no explicit or
implicit range specification as an unsized parameter declaration. When
calculating the bit width of the final value expression for the parameter,
it follows the same rules as it does for unsized expressions, regardless of
whether or not the expression contains any unsized numeric constants.
If the final value expression for an unsized parameter is an unsized
expression (i.e. does contain unsized numeric constants), any subsequent use
of that parameter will be treated as if it was an unsized numeric constant.
If not, it will be treated as if it was a numeric constant of the appropriate
size. For example, with the declarations:
.. code-block:: verilog
reg [7:0] mem [0:7];
initial begin
$readmempath(".:alternative:/global/defaults");
$readmemh("datafile.txt", mem);
end
localparam Value1 = 'd3 + 'd2;
localparam Value2 = 2'd3 + 2'd2;
In this example, the "datafile.txt" is searched for in each of the directories
in the above list (separated by ":" characters). The first located instance
is the one that is used. So for example, if "./datafile.txt" exists, then it
is read instead of "/global/defaults/datafile.txt" even if the latter exists.
any subsequent use of ``Value1`` will be treated as if the programmer had
written ``'d5`` and any subsequent use of ``Value2`` will be treated as if
the programmer had written ``3'd5``. In particular, note that ``Value2`` can
be used as a concatenation operand, but ``Value1`` cannot.
The above behaviour is a deviation from the Verilog standard. As for
unsized expressions, if you need strict standard compliance. use the
``-gstrict-expr-width`` compiler option.
Unsized Expressions as Arguments to Concatenation
-------------------------------------------------
The Verilog standard clearly states in 4.1.14:
"Unsized constant numbers shall not be allowed in concatenations. This
is because the size of each operand in the concatenation is needed to
calculate the complete size of the concatenation."
So for example the expression ``{1'b0, 16}`` is clearly illegal. It also stands
to reason that ``{1'b0, 15+1}`` is illegal, for exactly the same justification.
What is the size of the expression (15+1)? Furthermore, it is reasonable to
expect that (16) and (15+1) are exactly the same so far as the compiler is
concerned.
Unfortunately, Cadence seems to feel otherwise. In particular, it has been
reported that although ``{1'b0, 16}`` causes an error, ``{1'b0, 15+1}`` is
accepted. Further testing shows that any expression other than a simple
unsized constant is accepted there, even if all the operands of all the
operators that make up the expression are unsized integers.
This is a semantic problem. Icarus Verilog doesn't limit the size of integer
constants. This is valid as stated in 2.5.1 Note 3:
"The number of bits that make up an unsized number (which is a simple
decimal number or a number without the size specification) shall be
**at least** 32." [emphasis added]
Icarus Verilog will hold any integer constant, so the size will be as large as
it needs to be, whether that is 64 bits, 128 bits, or more. With this in mind,
what is the value of these expressions?
.. code-block:: verilog
{'h1_00_00_00_00}
{'h1 << 32}
{'h0_00_00_00_01 << 32}
{'h5_00_00_00_00 + 1}
These examples show that the standard is justified in requiring that the
operands of concatenation have size. The dispute is what it takes to cause
an expression to have a size, and what that size is. Verilog-XL claims that
(16) does not have a size, but (15+1) does. The size of the expression (15+1)
is the size of the adder that is created, but how wide is the adder when
adding unsized constants?
One might note that the quote from section 4.1.14 says "Unsized constant
numbers shall not be allowed." It does not say "Unsized expressions...", so
arguably accepting (15+1) or even (16+0) as an operand to a concatenation is
not a violation of the letter of the law. However, the very next sentence of
the quote expresses the intent, and accepting (15+1) as having a more defined
size then (16) seems to be a violation of that intent.
Whatever a compiler decides the size is, the user has no way to predict it,
and the compiler should not have the right to treat (15+1) any differently
then (16). Therefore, Icarus Verilog takes the position that such expressions
are unsized and are not allowed as operands to concatenations. Icarus Verilog
will in general assume that operations on unsized numbers produce unsized
results. There are exceptions when the operator itself does define a size,
such as the comparison operators or the reduction operators. Icarus Verilog
will generate appropriate error messages.
Scope of Macro Defines Doesn't Extend into Libraries
----------------------------------------------------
Icarus Verilog does preprocess modules that are loaded from libraries via the
``-y`` mechanism to substitute macros and load includes. However, the only
macros defined during compilation of an automatically loaded library module
file are those that it defines itself (or includes) or that are defined on the
command line or in the command file. Specifically, macros defined in the non-
library source files are not remembered when the library module is loaded, and
macros defined in a library module do not escape into the rest of the design.
This is intentional. If it were otherwise, then compilation results might vary
depending on the order that libraries are loaded, and that is unacceptable.
For example, given sample library module ``a.v``:
.. code-block:: verilog
`define MACRO_A 1
module a(input x);
always @(x) $display("x=",x);
endmodule
and sample library module ``b.v``:
.. code-block:: verilog
module b(input y);
`ifdef MACRO_A
always @(y) $display("MACRO_A is defined",,y);
`else
always @(y) $display("MACRO_A is NOT defined",,y);
`endif
endmodule
If a program instantiates both of these modules, there is no way to know
which will be loaded first by the compiler, so if the definition of
``MACRO_A`` in ``a.v`` were to escape, then there is no way to predict or
control whether ``MACRO_A`` is defined when ``b.v`` is processed. So the
preprocessor processes automatic library module files as if they are in
their own compilation unit, and you can know that ``MACRO_A`` will not be
defined in ``b.v`` unless it is defined on the command line (a ``-D`` flag)
or in the command file (a ``+define+`` record.)
Of course if ``a.v`` and ``b.v`` were listed in the command file or on the
command line, then the situation is different; the order is clear. The files
are processed as if they were concatenated in the order that they are listed
on the command line. The non-library modules are all together in a main
compilation unit, and they are all processed before any library modules are
loaded.
It is said that some commercial compilers do allow macro definitions to span
library modules. That's just plain weird. However, there is a special case
that Icarus Verilog does handle. Preprocessor definitions that are made in
files explicitly listed on the command line or in the command file, do pass
into implicitly loaded library files. For example, given the source file
``x.v``:
.. code-block:: verilog
module main;
reg foo;
b dut(foo);
endmodule
`define MACRO_A
and the library module file ``b.v`` described above, the situation is well
defined, assuming the ``x.v`` file is listed on the command line or in the
command file. The library module will receive the ``MACRO_A`` definition
from the last explicitly loaded source file. The position of the define of
``MACRO_A`` in the explicitly loaded source files does not matter, as all
explicitly loaded source files are preprocessed before any library files
are loaded.
Continuous Assign L-Values Can Implicit-Define Wires
----------------------------------------------------
The IEEE 1364-2001 standard, Section 3.5, lists the cases where nets may be
implicitly created. These include:
- identifier is a module port
- identifier is passed as a port to a primitive or module
This does not seem to include continuous assignment l-values (or r-values)
so the standard does not justify allowing implicit declarations of nets by
continuous assignment.
However, it has been reported that many Verilog compilers, including the big
name tools, do allow this. So, Icarus Verilog will allow it as well, as an
extension. If ``-gxtypes`` (the default) is used, this extension is enabled.
To turn off this behavior, use the ``-gno-xtypes`` flag.
Dumping Array Words (``$dumpvars``)
-----------------------------------
Icarus has the ability to dump individual array words. They are only dumped
when explicitly passed to $dumpvars. They are not dumped by default. For
example given the following:
.. code-block:: verilog
module top;
reg [7:0] array [2:0];
initial begin
$dumpvars(0, array[0], array[1]);
...
end
endmodule
``array[0]`` and ``array[1]`` will be dumped whenever they change value. They
will be displayed as an escaped identifier and GTKWave fully supports this.
Note that this is an implicitly created escaped identifier that could conflict
with an explicitly created escaped identifier. You can automate adding the
array word by adding an index definition
.. code-block:: verilog
integer idx;
and replacing the previous $dumpvars statement with
.. code-block:: verilog
for (idx = 0; idx < 2; idx = idx + 1) $dumpvars(0, array[idx]);
This will produce the same results as the previous example, but it is much
easier to specify/change which elements are to be dumped. One important note
regarding this syntax. Most system tasks/functions keep the variable selection
(for this case it is a variable array word selection) context. If ``$dumpvars``
did this then all callback created would point to this element and would use
the same index which for the example above would have the value 2. This is
certainly not what is desired and for this special case when ``$dumpvars``
executes it uses the current index value to create a constant array selection
and that is monitored instead of the original variable selection.
Referencing Declarations Within an Unnamed Generate Block
---------------------------------------------------------
The IEEE 1364-2005 standard permits generate blocks to be unnamed, but states:
"If the generate block selected for instantiation is not named, it still
creates a scope; but the declarations within it cannot be referenced using
hierarchical names other than from within the hierarchy instantiated by the
generate block itself."
The standard later defines a scheme for automatically naming the unnamed
scopes for use with external interfaces.
Icarus Verilog implements the defined automatic naming scheme, but does not
prevent the automatically generated names being used in a hierarchical
reference. This behaviour is harmless - the automatically generated names are
guaranteed to be unique within the enclosing scope, so there is no possibility
of confusion with explicit scope names. However, to maintain code portability,
it is recommended that this behavior is not exploited.
``%g/%G`` Format Specifiers
---------------------------
In the IEEE 1364-2001 standard there is a general statement that the real
number format specifiers will use the full formatting capabilities of C.
This is then followed by an example that describes ``%10.3g``. The example
description would be correct for the ``%e`` format specifier which should
always have three fractional digits, but the ``%g`` format specifier does
not work that way. For it the ``.3`` specifies that there will be three
significant digits. What this means is that ``%g`` will always produce one
less significant digit than ``%e`` and will only match the output from ``%f``
for certain values. For example:
.. code-block:: verilog
module top_level;
real rval;
initial begin
rval = 1234567890;
$display("This is g and e: %10.3g, %10.3e.", rval, rval);
rval = 0.1234567890;
$display("This is g and f: %10.3g, %10.3f.", rval, rval);
rval = 1.234567890;
$display("This is more g and f: %10.3g, %10.3f.", rval, rval);
end
endmodule // top_level
will produce the following output:
.. code-block:: verilog
This is g and e: 1.23e+09, 1.235e+09.
This is g and f: 0.123, 0.123.
This is more g and f: 1.23, 1.235.
``%t`` Time Format Specifier Can Specify Width
----------------------------------------------
Standard Verilog does not allow width fields in the ``%t`` formats of display
strings. For example, this is illegal:
.. code-block:: verilog
$display("Time is %0t", $time);
Standard Verilog instead relies on the ``$timeformat`` to completely specify
the format.
Icarus Verilog allows the programmer to specify the field width. The ``%t``
format in Icarus Verilog works exactly as it does in standard Verilog.
However, if the programmer chooses to specify a minimum width (i.e., ``%5t``),
then for that display Icarus Verilog will override the ``$timeformat`` minimum
width and use the explicit minimum width.
``%v`` Format Specifier Can Display Vectors
-------------------------------------------
The IEEE 1364-2005 standard limits the ``%v`` specifier in display strings to
work only with a single bit. Icarus Verilog extends that to support displaying
the strength of vectors. The output is a strength specifier for each bit of the
vector, with underscore characters separating each bit, e.g. ``St0_St1_Pu1_HiZ``.
Most other tools will just print the strength of the least significant bit of
a vector, so this may give different output results for code that otherwise
works fine.
Assign/Deassign and Force/Release of Bit/Part Selects
-----------------------------------------------------
Icarus Verilog allows as an extension the assign/deassign and force/release
of variable bit and part selects in certain cases. This allows the Verilog
test bench writer to assign/deassign for example single bits of a variable
(register, etc.). Other tools will report this as an error.
``repeat`` Statement is Sign Aware
----------------------------------
The standard does not specify what to do for this case, but it does say what
a repeat event control should do. In Icarus Verilog the ``repeat`` statement
is consistent with the repeat event control definition. If the argument is
signed and is a negative value this will be treated the same as an argument
value of 0.
Built-in System Functions May Be Evaluated at Compile Time
----------------------------------------------------------
Certain of the system functions have well-defined meanings, so can
theoretically be evaluated at compile-time, instead of using runtime VPI
code. Doing so means that VPI cannot override the definitions of functions
handled in this manner. On the other hand, this makes them synthesizable,
and also allows for more aggressive constant propagation. The functions
handled in this manner are:
- ``$bits``
- ``$signed``
- ``$sizeof``
- ``$unsigned``
Implementations of these system functions in VPI modules will be ignored.
``vpiScope`` Iterator on ``vpiScope`` Objects
---------------------------------------------
In the VPI, the normal way to iterate over ``vpiScope`` objects contained
within a ``vpiScope`` object, is the ``vpiInternalScope`` iterator. Icarus
Verilog adds support for the ``vpiScope`` iterator of a ``vpiScope`` object,
that iterates over *everything* that is contained in the current scope. This
is useful in cases where one wants to iterate over all the objects in a scope
without iterating over all the contained types explicitly.
Time 0 Race Resolution
----------------------
Combinational logic is routinely modelled using always blocks. However, this
can lead to race conditions if the inputs to the combinational block are
initialized in initial statements. Icarus Verilog slightly modifies time 0
scheduling by arranging for always statements with ANYEDGE sensitivity lists
to be scheduled before any other threads. This causes combinational always
blocks to be triggered when the values in the sensitivity list are initialized
by initial threads.
+1 -1
View File
@@ -18,7 +18,7 @@ This section contains documents to help support Icarus Verilog users.
vvp_debug
vvp_library
vhdlpp_flags
gtkwave
waveform_viewer
vpi
icarus_verilog_extensions
icarus_verilog_quirks
+248 -54
View File
@@ -2,24 +2,26 @@
Installation Guide
==================
Icarus Verilog may be installed from source code, or from pre-packaged binary
distributions. If you don't have need for the very latest, and prepackaged
binaries are available, that would be the best place to start.
Icarus Verilog may be installed from source code (either from ``git`` or a
released `tar/zip` file), or from pre-packaged binary distributions. If you
don't have a need for the very latest, and prepackaged binaries are available,
that is the easiest place to start.
Installation From Source
------------------------
Icarus is developed for Unix-like environments but can also be compiled on
Windows systems using the Cygwin environment or MinGW compilers. The following
instructions are the common steps for obtaining the Icarus Verilog source,
compiling and installing. Note that there are precompiled and/or prepackaged
versions for a variety of systems, so if you find an appropriate packaged
version, then that is the easiest way to install.
Windows systems using the `Cygwin/MSYS2` environments or `MinGW` compilers. The
following instructions are the common steps for obtaining the Icarus Verilog
source code, compiling, installing, and checking the compiled code is working
properly. Note that there are pre-compiled and/or prepackaged versions for a
variety of systems, so if you find an appropriate packaged version, then that
is the easiest way to install.
The source code for Icarus is stored under the git source code control
system. You can use git to get the latest development head or the latest of a
specific branch. Stable releases are placed on branches, and in particular v11
stable releases are on the branch "v11-branch" To get the development version
The source code for Icarus is stored under the `git` source code control
system. You can use ``git`` to get the latest development head or the latest of
a specific branch. Stable releases are placed on branches, and in particular V12
stable releases are on the branch "v12-branch" To get the development version
of the code follow these steps::
% git config --global user.name "Your Name Goes Here"
@@ -29,7 +31,7 @@ of the code follow these steps::
The first two lines are optional and are used to tell git who you are. This
information is important if/when you submit a patch. We suggest that you add
this information now so you don't forget to do it later. The clone will create
a directory, named iverilog, containing the source tree, and will populate
a directory, named `iverilog`, containing the source tree, and will populate
that directory with the most current source from the HEAD of the repository.
Change into this directory using::
@@ -37,19 +39,26 @@ Change into this directory using::
% cd iverilog
Normally, this is enough as you are now pointing at the most current
development code, and you have implicitly created a branch "master" that
development code, and you have implicitly created a branch `master` that
tracks the development head. However, If you want to actually be working on
the v11-branch (the branch where the latest v11 patches are) then you checkout
that branch with the command::
the `v12-branch` (the branch where the latest V12 patches are) then you
checkout that branch with the command::
% git checkout --track -b v11-branch origin/v11-branch
% git checkout --track -b v12-branch origin/v12-branch
This creates a local branch that tracks the v11-branch in the repository, and
switches you over to your new v11-branch. The tracking is important as it
This creates a local branch that tracks the `v12-branch` in the repository, and
switches you over to your new `v12-branch`. The tracking is important as it
causes pulls from the repository to re-merge your local branch with the remote
v11-branch. You always work on a local branch, then merge only when you
`v12-branch`. You always work on a local branch, then merge only when you
push/pull from the remote repository.
The choice between the development branch and the latest released branch
depends on your stability requirements. The released branch will only get bug
fixes. It will not get any enhancements or changes in the compiler output
format. Unlike many project the development branch is fairly stable with only
occasional periods of instability. We do most of our big changes in side
branches and only merge them into the development branch when they are clean.
Now that you've cloned the repository and optionally selected the branch you
want to work on, your local source tree may later be synced up with the
development source by using the git command::
@@ -59,22 +68,33 @@ development source by using the git command::
The git system remembers the repository that it was cloned from, so you don't
need to re-enter it when you pull.
Finally, configuration files are built by the extra step::
To build the `configure` script and hash files you need to run the
following::
% sh autoconf.sh
% cd ..
The source is then compiled as appropriate for your system. See the specific
build instructions below for your operation system for what to do next.
You will need autoconf and gperf installed in order for the script to work.
If you get errors such as::
This is not need for the released `tar/zip` files since they already contain
these files. You only need to run this once after cloning. If you are missing
``autoconf`` or ``gperf`` then the script will fail::
Autoconf in root...
autoconf.sh: 10: autoconf: not found
Precompiling lexor_keyword.gperf
autoconf.sh: 13: gperf: not found.
You will need to install download and install the autoconf and gperf tools.
You will need to install the ``autoconf`` and ``gperf`` tools before you can
continue.
The other way to get the source code is to download a released `tar/zip` file::
% tar -xvzf v13_0.tar.gz
or
% unzip v13_0.zip
See the build instructions for your operation system below to know what to do
next. Though first determine if there are any extra configuration option you
may need.
Icarus Specific Configuration Options
-------------------------------------
@@ -93,43 +113,215 @@ All programs or directories are tagged with this suffix. e.g.(iverilog-0.8,
vvp-0.8, etc.). The output of iverilog will reference the correct run time
files and directories. The run time will check that it is running a file with
a compatible version e.g.(you can not run a V0.9 file with the V0.8 run
time). ::
time).::
--with-valgrind
This option adds extra memory cleanup code and pool management code to allow
better memory leak checking when valgrind is available. This option is not
need when checking for basic errors with valgrind. ::
needed when checking for basic errors with valgrind and should not be used if
you just intend to use ``iverilog`` as a simulator. ::
--enable-libvvp
The vvp progam is built as a small stub linked to a shared library,
The vvp program is built as a small stub linked to a shared library,
libvvp.so, that may be linked with other programs so that they can host
a vvp simulation.
a vvp simulation. ::
--enable-libveriuser
PLI version 1 (the ACC and TF routines) were deprecated in IEEE 1364-2005.
These are supported in Icarus Verilog by the libveriuser library and cadpli
module. Starting with V13, these will only be built if this option is used.
Compiling on Linux/Unix
-----------------------
(Note: You will need to install bison, flex, g++ and gcc) This is probably the
easiest case. Given that you have the source tree from the above instructions,
the compile and install is generally as simple as::
Note: For a gcc compile you will need to install ``bison``, ``flex``, ``g++``,
``gcc`` and preferably `bz2`, `zlib` and `readline` development packages. The
`bz2` and `zlib` development packages are required for the non-VCD waveform
dumpers and the `readline` development package is needed to enable better
terminal control in the ``vvp`` interactive mode.
% ./configure
% make
(su to root)
# make install
If you are only compiling one variant then you can compile directly in the
source tree. If you need multiple variants (optimized, debugging, multiple
compilers) then it is recommended you compile each in their own directory.
The "make install" typically needs to be done as root so that it can install
in directories such as "/usr/local/bin" etc. You can change where you want to
install by passing a prefix to the "configure" command::
For multiple variants create a directory for each of the variants you intend
to create and in each run the following steps, adjusting the options in the
configure stage to get the functionality you want. For a single build you can
either build it with the source or in a separate build directory.
% ./configure --prefix=/my/special/directory
The following is from a Ubuntu 22.04 machine using gcc (version 11.4)::
This will configure the source for eventual installation in the directory that
you specify. Note that "rpm" packages of binaries for Linux are typically
configured with "--prefix=/usr" per the Linux File System Standard.
% mkdir gcc
% cd gcc
or
% cd iverilog
Make sure you have the latest version of flex otherwise you will get an error
You can also use ``clang/clang++``. I usual build optimized version for
normal use and reserve debugging options for a valgrind or a separate
debugging build. Make sure you have `sudo` permission if you are using a
system prefix area, otherwise you need to use some place you have
permission to install (e.g. ~/).::
% env CFLAGS=-O2 CXXFLAGS=-O2 LDFLAGS=-s CC=gcc CXX=g++ ../iverilog/configure --enable-suffix=-gcc --prefix=/usr/local
This will generate the following (with some inline comments)::
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
checking for gcc... gcc
checking whether the C compiler works... yes
...
checking for gperf... gperf # required for git builds
checking for man... man # you likely want manual pages
checking for ps2pdf... ps2pdf
checking for groff... groff
checking for git... git # required for git builds
checking for flex... flex # required
checking for bison... bison # required
...
checking for tputs in -ltermcap... yes
checking for readline in -lreadline... yes
checking for add_history in -lreadline... yes
checking for readline/readline.h... yes
checking for readline/history.h... yes # you likely want this
...
checking for pthread_create in -lpthread... yes
checking for gzwrite in -lz... yes
checking for gzwrite in -lz... (cached) yes
checking for BZ2_bzdopen in -lbz2... yes
checking for BZ2_bzdopen in -lbz2... (cached) yes # you want these for fst dumping
...
<Create all the parameterized Makefile and header files>
Usually if ``configure`` fails there is some required dependency missing. I
usually review all the output to make sure it makes sense (e.g. I requested
``gcc`` and that's what is being used, other things match my expectation). If
all the waveform dumpers are not enabled there could be a few test failures.
Next we need to compile the code. Note: make sure you are using GNU make.
It may be named gmake (e.g. GhostBSD)::
% make check >& make.log
This is for a tcsh/csh shell. Bash/fish/zsh use ``&>`` instead of ``>&``.
Once this has completed check the make.log for any errors. There should not
be any! I also check for warnings. There are often some related to the
output from bison. For example::
From: ./parse.cc
parse.cc:9462:18: warning: missing initializer for member vlltype::lexical_pos [-Wmissing-field-initializers]
9462 | = { 1, 1, 1, 1 }
| ^
parse.cc:9462:18: warning: missing initializer for member vlltype::text [-Wmissing-field-initializers]
and::
From: ./vvp/parse.cc
parse.cc:3242: warning: suspicious sequence in the output: m4_type [-Wother]
parse.cc:3248: warning: suspicious sequence in the output: m4_type [-Wother]
Are common, but benign warnings. Different compilers or compiler versions may
have other warnings.
The expected last few lines of the make.log file and these indicate everything
should be working as expected are::
...
driver/iverilog -B. -BMvpi -BPivlpp -tcheck -ocheck.vvp ../iverilog/examples/hello.vl
vvp/vvp -M- -M./vpi ./check.vvp | grep 'Hello, World'
Hello, World
If everything is good to this point and you are installing into a system
prefix; install using ``sudo`` as shown below. If you are installing into a
personal location skip the ``sudo``::
% sudo make install
Now you should verify the regression test suite is working as expected::
% cd ../iverilog/ivtest
% ./vvp_reg.pl --suffix=-gcc
This is the original test script and should give no failures::
Running compiler/VVP tests for Icarus Verilog version: 13, suffix: -gcc.
----------------------------------------------------------------------------
macro_with_args: Passed.
mcl1: Passed.
pr622: Passed.
pr639: Passed.
...
ssetclr2: Passed.
ssetclr3: Passed.
synth_if_no_else: Passed.
ufuncsynth1: Passed.
============================================================================
Test results:
Total=3018, Passed=3013, Failed=0, Not Implemented=2, Expected Fail=3
Next run the new test script::
% ./vvp_reg.py --suffix=-gcc
This should also give no failures::
Running compiler/VVP tests for Icarus Verilog version: 13, suffix: -gcc
Using list(s): regress-vvp.list
----------------------------------------------------------------------------
always4A: Passed - CE.
always4B: Passed - CE.
analog1: Not Implemented.
analog2: Not Implemented.
...
vvp_quiet_mode: Passed.
warn_opt_sys_tf: Passed - EF.
wreal: Passed.
writemem-invalid: Passed - EF.
============================================================================
Test results: Ran 284, Failed 0.
Finally you can check that the VPI is working properly using::
% ./vpi_reg.pl --suffix=-gcc
The output for this should have no failures::
Running VPI tests for Icarus Verilog version: 13, suffix: -gcc.
----------------------------------------------------------------------------
br_gh59: Passed.
br_gh73a: Passed.
br_gh73b: Passed.
br_gh117: Passed.
...
value_change_cb2: Passed.
value_change_cb3: Passed.
value_change_cb4: Passed.
vpi_control: Passed.
============================================================================
Test results: Total=77, Passed=77, Failed=0, Not Implemented=0
You can uninstall everything using the following. If needed skip the ``sudo``
as described in the install description above.::
% sudo make uninstall
You can cleanup the compile directory using::
% make clean
or
% make distclean
The first just cleans up just the compiled files, etc. The later cleans up
the compiled file along with all the files generated in the ``configure``
phase.
Note that "rpm" packages of binaries for Linux are typically configured with
"--prefix=/usr" per the Linux File System Standard.
Make sure you have a recent version of flex otherwise you will get an error
when parsing lexor.lex.
Compiling on Macintosh OS X
@@ -151,10 +343,16 @@ be updated to version 3. ::
Icarus Verilog is also available through the Homebrew package manager: "brew
install icarus-verilog".
Compiling for Windows
---------------------
Cross-Compiling for Windows
---------------------------
These are instructions for building Icarus Verilog binaries for
The `Cygwin` and `MSYS2` environments can compile Icarus Verilog as described
above for `Linux/Unix`. There is a `MSYS2` build recipe which can be found in
the `msys2/` directory. The accompanying README file provides further details.
`MSYS2` is typically preferred over `Cygwin` since ``GTKWave`` and Icarus
Verilog are both provided as pre-compiled packages.
What follows are older instructions for building Icarus Verilog binaries for
Windows using mingw cross compiler tools on Linux.
To start with, you need the mingw64-cross-* packages for your linux
@@ -175,9 +373,5 @@ Next, compile with the command::
$ make
The configure generated the cross compiler flags, but there are a few
bits that need to be compiled with the native compiler. (version.exe
for example is used by the build process but is not installed.) The
The configure generated the cross compiler flags. The
configure script should have gotten all that right.
There is also a MSYS2 build recipe which you can find under `msys2/` in the repository.
+4 -4
View File
@@ -2,10 +2,10 @@
Reporting Issues
================
The developers of and contributers to Icarus Verilog use github to track
The developers of and contributors to Icarus Verilog use github to track
issues and to create patches for the product. If you believe you have found a
problem, use the Issues tracker at the
`Icarus Verilog github page <https://github.com/steveicarus/iverilog>`_.
`Icarus Verilog github page <https://github.com/steveicarus/iverilog>`__.
You may browse the bugs database for existing
bugs that may be related to yours. You might find that your bug has
@@ -13,7 +13,7 @@ already been fixed in a later release or snapshot. If that's the case,
then you are set.
On the main page, you will find a row of selections near the top. Click the
`Issues <https://github.com/steveicarus/iverilog/issues>`_ link to get to the
`Issues <https://github.com/steveicarus/iverilog/issues>`__ link to get to the
list of issues, open and closed. You will find a friendly green button where
you can create a new issue. You will be asked to create a title for your
issue, and to write a detailed description of your issue. Please include
@@ -60,7 +60,7 @@ Bug reports with patches/PRs are very welcome. Please also add a new test case i
If you are editing the source, you should be using the latest
version from git. Please see the developer documentation for more
detailed instructions -- :doc:`Getting Started as a Contributer <getting_started>` .
detailed instructions -- :doc:`Getting Started as a Contributor <getting_started>` .
COPYRIGHT ISSUES
+5 -3
View File
@@ -42,7 +42,7 @@ module, is a null terminated table of function pointers. The simulator calls
each of the functions in the table in order. The following simple C definition
defines a sample table::
void (*vlog_startup_routines[])() = {
void (*vlog_startup_routines[])(void) = {
hello_register,
0
};
@@ -89,16 +89,18 @@ file hello.c::
static int hello_compiletf(char*user_data)
{
(void)user_data; // Avoid a warning since user_data is not used.
return 0;
}
static int hello_calltf(char*user_data)
{
(void)user_data; // Avoid a warning since user_data is not used.
vpi_printf("Hello, World!\n");
return 0;
}
void hello_register()
void hello_register(void)
{
s_vpi_systf_data tf_data;
@@ -111,7 +113,7 @@ file hello.c::
vpi_register_systf(&tf_data);
}
void (*vlog_startup_routines[])() = {
void (*vlog_startup_routines[])(void) = {
hello_register,
0
};
+1 -1
View File
@@ -105,7 +105,7 @@ behavior.
* -fst
Generate FST format outputs instead of VCD format waveform dumps. This is
the preferred output format if using GTKWave for viewing waveforms.
the preferred output format if using GTKWave or Surfer for viewing waveforms.
* -lxt/-lxt2
@@ -1,22 +1,32 @@
Viewing Waveforms
=================
Waveforms With GTKWave
======================
To view waveforms, either GTKWave or Surfer can be used.
GTKWave is a VCD waveform viewer based on the GTK library. This viewer support
VCD and LXT formats for signal dumps. GTKWAVE is available on github
`here <https://github.com/gtkwave/gtkwave>`_. Most Linux distributions already
include gtkwave prepackaged.
GTKWave is a waveform viewer based on the GTK library. This viewer supports
VCD, FST, LXT, and LXT2 formats for waveform dumps. GTKWave is available on GitHub
`here <https://github.com/gtkwave/gtkwave>`__. Most Linux distributions already
include gtkwave prepackaged and there are binaries for Windows available.
.. image:: GTKWave_Example2.png
Generating VCD/FST files for GTKWAVE ------------------------------------
Surfer is a waveform viewer based on the Rust egui library. This viewer supports
VCD and FST formats for waveform dumps. Surfer is available on GitLab
`here <https://gitlab.com/surfer-project/surfer>`__. It runs on Windows, Linux,
and MacOS, but can also run in a `web browser <https://app.surfer-project.org/>`__
and there is a VS Code
`extension <https://marketplace.visualstudio.com/items?itemName=surfer-project.surfer>`__.
Generating waveform dump files for viewing
------------------------------------------
Waveform dumps are written by the Icarus Verilog runtime program vvp. The user
uses $dumpfile and $dumpvars system tasks to enable waveform dumping, then the
vvp runtime takes care of the rest. The output is written into the file
specified by the $dumpfile system task. If the $dumpfile call is absent, the
compiler will choose the file name dump.vcd or dump.lxt or dump.fst, depending
on runtime flags. The example below dumps everything in and below the test
module:
compiler will choose the file name dump.vcd, dump.lxt, dump.lxt2, or dump.fst,
depending on runtime flags. The example below dumps everything in and below
the test module:
.. code-block:: verilog
@@ -30,9 +40,9 @@ module:
By default, the vvp runtime will generate VCD dump output. This is the default
because it is the most portable. However, when using gtkwave, the FST output
format is faster and most compact. Use the "-fst" extended argument to
activate LXT output. For example, if your compiled output is written into the
file "foo.vvp", the command:
format is faster and most compact. Use the "-fst", "-lxt", or "-lxt2" extended
argument to activate FST, LXT, or LXT2 output, respectively. For example, if
your compiled output is written into the file "foo.vvp", the command:
.. code-block:: console
@@ -40,7 +50,7 @@ file "foo.vvp", the command:
will cause the dumpfile output to be written in FST format. Absent any
specific $dumpfile command, this file will be called dump.fst, which can be
viewed with the command:
viewed with GTKWave using the command:
.. code-block:: console
@@ -105,7 +115,7 @@ Then the simulation file:
$time, value, value);
endmodule // test
Compile, run, and view waveforms with these commands:
Compile, run, and view waveforms with GTKWave using these commands:
.. code-block:: console
@@ -113,6 +123,6 @@ Compile, run, and view waveforms with these commands:
% vvp dsn
% gtkwave test.vcd &
Click on the 'test', then 'c1' in the top left box on GTKWAVE, then drag the
Click on the 'test', then 'c1' in the top left box of GTKWave, then drag the
signals to the Signals box. You will be able to add signals to display,
scanning by scope.
+64 -124
View File
@@ -36,18 +36,23 @@ prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
datarootdir = @datarootdir@
VERSION_MAJOR = @VERSION_MAJOR@
VERSION_MINOR = @VERSION_MINOR@
SUBDIRS = ivlpp vhdlpp vvp vpi libveriuser cadpli tgt-null tgt-stub tgt-vvp \
tgt-vhdl tgt-vlog95 tgt-pcb tgt-blif tgt-sizer driver
SUBDIRS = ivlpp vhdlpp vvp vpi tgt-null tgt-stub tgt-vvp \
tgt-vhdl tgt-vlog95 tgt-pcb tgt-blif tgt-sizer driver \
ivtest
# Only run distclean for these directories.
NOTUSED = tgt-fpga tgt-pal tgt-verilog
ifeq (@MINGW32@,yes)
SUBDIRS += driver-vpi
ifeq (@LIBVERIUSER@,yes)
SUBDIRS += libveriuser cadpli
else
NOTUSED += driver-vpi
NOTUSED += libveriuser cadpli
endif
SUBDIRS += driver-vpi
# To get the version headers to build correctly we only want to look
# for C++ files in the source directory. All other files will require
# an explicit $(srcdir). The one exception to this is if we need to
@@ -61,9 +66,7 @@ bindir = @bindir@
libdir = @libdir@
# This is actually the directory where we install our own header files.
# It is a little different from the generic includedir.
includedir = @includedir@/iverilog$(suffix)
mandir = @mandir@
pdfdir = @docdir@
ivl_includedir = @includedir@/iverilog$(suffix)
dllib=@DLLIB@
@@ -73,16 +76,19 @@ HOSTCFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
BUILDCC = @CC_FOR_BUILD@
BUILDEXT = @BUILD_EXEEXT@
CC = @CC@
CXX = @CXX@
DLLTOOL = @DLLTOOL@
ENV_VVP=@ENV_VVP@
INSTALL = @INSTALL@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
LEX = @LEX@
YACC = @YACC@
YACC_CONFLICT_FLAGS = -Werror=conflicts-sr -Werror=conflicts-rr
MAN = @MAN@
PS2PDF = @PS2PDF@
GROFF = @GROFF@
GIT = @GIT@
ifeq (@srcdir@,.)
@@ -124,7 +130,7 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
PGate.o PGenerate.o PModport.o PNamedItem.o PPackage.o PScope.o PSpec.o PTimingCheck.o \
PTask.o PUdp.o PWire.o Statement.o AStatement.o $M $(FF) $(TT)
all: dep config.h _pli_types.h version_tag.h ivl@EXEEXT@ version.exe iverilog-vpi.man
all: dep config.h _pli_types.h version_tag.h version_base.h ivl@EXEEXT@
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
# In the windows world, the installer will need a dosify program to
@@ -132,37 +138,29 @@ all: dep config.h _pli_types.h version_tag.h ivl@EXEEXT@ version.exe iverilog-vp
ifeq (@MINGW32@,yes)
all: dosify$(BUILDEXT)
dosify$(BUILDEXT): $(srcdir)/dosify.c
$(BUILDCC) $(CFLAGS) -o dosify$(BUILDEXT) $(srcdir)/dosify.c
$(BUILDCC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o dosify$(BUILDEXT) $(srcdir)/dosify.c
endif
# This rule rules the compiler in the trivial hello.vl program to make
# sure the basics were compiled properly.
# This rule runs the compiler using the trivial hello.vl program to make sure
# the base programs are compiled properly.
check: all
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
rm -f check.vvp
test -r check.conf || cp $(srcdir)/check.conf .
driver/iverilog -B. -BMvpi -BPivlpp -tcheck -ocheck.vvp $(srcdir)/examples/hello.vl
ifeq (@WIN32@,yes)
ifeq (@install_suffix@,)
vvp/vvp -M- -M./vpi ./check.vvp | grep 'Hello, World'
else
# On Windows if we have a suffix we must run the vvp part of
# the test with a suffix since it was built/linked that way.
ln vvp/vvp.exe vvp/vvp$(suffix).exe
vvp/vvp$(suffix) -M- -M./vpi ./check.vvp | grep 'Hello, World'
rm vvp/vvp$(suffix).exe
endif
else
vvp/vvp -M- -M./vpi ./check.vvp | grep 'Hello, World'
endif
driver/iverilog@EXEEXT@ -B. -BMvpi -BPivlpp -tcheck -ocheck.vvp $(srcdir)/examples/hello.vl && \
$(ENV_VVP) vvp/vvp$(suffix)@EXEEXT@ -M- -M./vpi ./check.vvp | grep 'Hello, World'
check-installed check-installed-vpi check-installed-vvp check-installed-vvp-py:
$(MAKE) -C ivtest $@
clean:
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
rm -f *.o parse.cc parse.h lexor.cc
rm -f ivl.exp iverilog-vpi.man iverilog-vpi.pdf iverilog-vpi.ps
rm -f ivl.exp
rm -f iverilog_man.ps iverilog_man.pdf iverilog_man_$(VERSION_MAJOR)_$(VERSION_MINOR).pdf
rm -f parse.output syn-rules.output dosify$(BUILDEXT) ivl@EXEEXT@ check.vvp
rm -f lexor_keyword.cc libivl.a libvpi.a iverilog-vpi syn-rules.cc
rm -f lexor_keyword.cc libivl.a libvpi.a syn-rules.cc
rm -rf dep
rm -f version.exe
distclean: clean
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
@@ -170,14 +168,17 @@ distclean: clean
rm -f Makefile config.status config.log config.cache
rm -f stamp-config-h config.h
rm -f stamp-_pli_types-h _pli_types.h
rm -f stamp-version_base-h version_base.h
ifneq (@srcdir@,.)
rm -f version_tag.h check.conf
rmdir $(SUBDIRS) $(NOTUSED)
endif
rm -rf autom4te.cache
cppcheck: $(O:.o=.cc) $(srcdir)/dosify.c $(srcdir)/version.c
cppcheck: $(O:.o=.cc) $(srcdir)/dosify.c
cppcheck --enable=all --std=c99 --std=c++11 -f \
--check-level=exhaustive \
--suppressions-list=$(srcdir)/cppcheck-global.sup \
--suppressions-list=$(srcdir)/cppcheck.sup \
-UYYPARSE_PARAM -UYYPRINT -Ushort -Usize_t -Uyyoverflow \
-UYYTYPE_INT8 -UYYTYPE_INT16 -UYYTYPE_UINT8 -UYYTYPE_UINT16 \
@@ -205,6 +206,11 @@ stamp-_pli_types-h: $(srcdir)/_pli_types.h.in config.status
./config.status _pli_types.h
_pli_types.h: stamp-_pli_types-h
stamp-version_base-h: $(srcdir)/version_base.h.in config.status
@rm -f $@
./config.status version_base.h
version_base.h: stamp-version_base-h
$(srcdir)/configure: $(srcdir)/configure.ac $(srcdir)/aclocal.m4
cd $(srcdir) && autoconf
@@ -213,40 +219,17 @@ config.status: $(srcdir)/configure
./config.status
ifeq (@WIN32@,yes)
# Under Windows (mingw) I need to make the ivl.exe in two steps.
# The first step makes an ivl.exe that dlltool can use to make an
# export and import library, and the last link makes a, ivl.exe
# that really exports the things that the import library imports.
# Under Windows we need to create an import library to allow the target code
# generators to access the items exported by ivl.exe. The .def file controls
# what is visible in the import library.
ivl@EXEEXT@: $O $(srcdir)/ivl.def
$(CXX) -o ivl@EXEEXT@ $O $(dllib) @EXTRALIBS@
$(DLLTOOL) --dllname ivl@EXEEXT@ --def $(srcdir)/ivl.def \
--output-lib libivl.a --output-exp ivl.exp
$(CXX) $(LDFLAGS) -o ivl@EXEEXT@ ivl.exp $O $(dllib) @EXTRALIBS@
$(CXX) $(LDFLAGS) -o ivl@EXEEXT@ -Wl,--out-implib=libivl.a $(srcdir)/ivl.def $O $(dllib) @EXTRALIBS@
else
ivl@EXEEXT@: $O
$(CXX) $(LDFLAGS) -o ivl@EXEEXT@ $O $(dllib)
endif
ifeq (@MINGW32@,no)
all: iverilog-vpi
iverilog-vpi: $(srcdir)/iverilog-vpi.sh Makefile
sed -e 's;@SHARED@;@shared@;' -e 's;@PIC@;@PICFLAG@;' \
-e 's;@SUFFIX@;$(suffix);' \
-e 's;@IVCC@;$(CC);' \
-e 's;@IVCXX@;$(CXX);' \
-e 's;@IVCFLAGS@;$(CFLAGS);' \
-e 's;@IVCXXFLAGS@;$(CXXFLAGS);' \
-e 's;@IVCTARGETFLAGS@;$(CTARGETFLAGS);' \
-e 's;@INCLUDEDIR@;$(includedir);' \
-e 's;@LIBDIR@;@libdir@;' $< > $@
chmod +x $@
endif
version.exe: $(srcdir)/version.c $(srcdir)/version_base.h version_tag.h
$(BUILDCC) $(CFLAGS) -o version.exe -I. -I$(srcdir) $(srcdir)/version.c
%.o: %.cc config.h
%.o: %.cc config.h | dep
$(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
mv $*.d dep/$*.d
@@ -259,10 +242,10 @@ parse.o: parse.cc
# Use pattern rules to avoid parallel build issues (see pr3462585)
parse%cc parse%h: $(srcdir)/parse%y
$(YACC) --verbose -t -p VL --defines=parse.h -o parse.cc $<
$(YACC) --verbose $(YACC_CONFLICT_FLAGS) -t -p VL --defines=parse.h -o parse.cc $<
syn-rules.cc: $(srcdir)/syn-rules.y
$(YACC) --verbose -t -p syn_ -o $@ $<
$(YACC) --verbose $(YACC_CONFLICT_FLAGS) -t -p syn_ -o $@ $<
lexor.cc: $(srcdir)/lexor.lex
$(LEX) -s -t $< > $@
@@ -270,17 +253,14 @@ lexor.cc: $(srcdir)/lexor.lex
lexor_keyword.o: lexor_keyword.cc parse.h
lexor_keyword.cc: $(srcdir)/lexor_keyword.gperf
gperf -o -i 7 -C -k 1-4,6,9,$$ -H keyword_hash -N check_identifier -t $(srcdir)/lexor_keyword.gperf > lexor_keyword.cc || (rm -f lexor_keyword.cc ; false)
gperf -o -i 7 -C -k 1-4,6,9,$$ -H keyword_hash -N check_identifier -t $< > $@ || (rm -f $@ ; false)
iverilog-vpi.man: $(srcdir)/iverilog-vpi.man.in version.exe
./version.exe `head -1 $(srcdir)/iverilog-vpi.man.in`'\n' > $@
tail -n +2 $(srcdir)/iverilog-vpi.man.in >> $@
iverilog_man.ps: driver/iverilog.man vvp/vvp.man driver-vpi/iverilog-vpi.man
$(GROFF) -man -rC1 -rD1 -T ps $^ > $@
iverilog-vpi.ps: iverilog-vpi.man
$(MAN) -t ./iverilog-vpi.man > iverilog-vpi.ps
iverilog-vpi.pdf: iverilog-vpi.ps
$(PS2PDF) iverilog-vpi.ps iverilog-vpi.pdf
iverilog_man.pdf: iverilog_man.ps
$(PS2PDF) $< $@
cp $@ iverilog_man_$(VERSION_MAJOR)_$(VERSION_MINOR).pdf
# For VERSION_TAG in driver/main.c, first try git-describe, then look for a
# release_tag.h file in the source tree (included in snapshots and releases),
@@ -306,33 +286,6 @@ version_tag.h version:
echo '#define VERSION_TAG ""' > version_tag.h; \
fi
ifeq (@MINGW32@,yes)
ifeq ($(MAN),none)
INSTALL_DOC = installman
INSTALL_PDFDIR = $(prefix)
else
ifeq ($(PS2PDF),none)
INSTALL_DOC = installman
INSTALL_PDFDIR = $(prefix)
else
INSTALL_DOC = installpdf installman
INSTALL_PDFDIR = $(pdfdir)
all: dep iverilog-vpi.pdf
endif
endif
INSTALL_DOCDIR = $(mandir)/man1
else
INSTALL_DOC = installman
INSTALL_DOCDIR = $(mandir)/man1
INSTALL_PDFDIR = $(prefix)
endif
ifeq (@MINGW32@,yes)
WIN32_INSTALL =
else
WIN32_INSTALL = installwin32
endif
install: all installdirs installfiles
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
@@ -344,37 +297,24 @@ F = ./ivl@EXEEXT@ \
$(srcdir)/sv_vpi_user.h \
$(srcdir)/vpi_user.h \
$(srcdir)/acc_user.h \
$(srcdir)/veriuser.h \
$(INSTALL_DOC) \
$(WIN32_INSTALL)
installwin32: ./iverilog-vpi installdirs
$(INSTALL_SCRIPT) ./iverilog-vpi "$(DESTDIR)$(bindir)/iverilog-vpi$(suffix)"
installman: iverilog-vpi.man installdirs
$(INSTALL_DATA) iverilog-vpi.man "$(DESTDIR)$(mandir)/man1/iverilog-vpi$(suffix).1"
installpdf: iverilog-vpi.pdf installdirs
$(INSTALL_DATA) iverilog-vpi.pdf "$(DESTDIR)$(pdfdir)/iverilog-vpi$(suffix).pdf"
$(srcdir)/veriuser.h
installfiles: $(F) | installdirs
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ "$(DESTDIR)$(libdir)/ivl$(suffix)/ivl@EXEEXT@"
$(INSTALL_DATA) $(srcdir)/constants.vams "$(DESTDIR)$(libdir)/ivl$(suffix)/include/constants.vams"
$(INSTALL_DATA) $(srcdir)/disciplines.vams "$(DESTDIR)$(libdir)/ivl$(suffix)/include/disciplines.vams"
$(INSTALL_DATA) $(srcdir)/ivl_target.h "$(DESTDIR)$(includedir)/ivl_target.h"
$(INSTALL_DATA) ./_pli_types.h "$(DESTDIR)$(includedir)/_pli_types.h"
$(INSTALL_DATA) $(srcdir)/sv_vpi_user.h "$(DESTDIR)$(includedir)/sv_vpi_user.h"
$(INSTALL_DATA) $(srcdir)/vpi_user.h "$(DESTDIR)$(includedir)/vpi_user.h"
$(INSTALL_DATA) $(srcdir)/acc_user.h "$(DESTDIR)$(includedir)/acc_user.h"
$(INSTALL_DATA) $(srcdir)/veriuser.h "$(DESTDIR)$(includedir)/veriuser.h"
$(INSTALL_DATA) $(srcdir)/ivl_target.h "$(DESTDIR)$(ivl_includedir)/ivl_target.h"
$(INSTALL_DATA) ./_pli_types.h "$(DESTDIR)$(ivl_includedir)/_pli_types.h"
$(INSTALL_DATA) $(srcdir)/sv_vpi_user.h "$(DESTDIR)$(ivl_includedir)/sv_vpi_user.h"
$(INSTALL_DATA) $(srcdir)/vpi_user.h "$(DESTDIR)$(ivl_includedir)/vpi_user.h"
$(INSTALL_DATA) $(srcdir)/acc_user.h "$(DESTDIR)$(ivl_includedir)/acc_user.h"
$(INSTALL_DATA) $(srcdir)/veriuser.h "$(DESTDIR)$(ivl_includedir)/veriuser.h"
installdirs: $(srcdir)/mkinstalldirs
$(srcdir)/mkinstalldirs "$(DESTDIR)$(bindir)" \
"$(DESTDIR)$(includedir)" \
"$(DESTDIR)$(ivl_includedir)" \
"$(DESTDIR)$(libdir)/ivl$(suffix)" \
"$(DESTDIR)$(libdir)/ivl$(suffix)/include" \
"$(DESTDIR)$(INSTALL_DOCDIR)" \
"$(DESTDIR)$(INSTALL_PDFDIR)"
"$(DESTDIR)$(libdir)/ivl$(suffix)/include"
uninstall:
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
@@ -382,13 +322,13 @@ uninstall:
do rm -f "$(DESTDIR)$(libdir)/ivl$(suffix)/$$f"; done
-rmdir "$(DESTDIR)$(libdir)/ivl$(suffix)/include"
-rmdir "$(DESTDIR)$(libdir)/ivl$(suffix)"
for f in verilog$(suffix) iverilog-vpi$(suffix) gverilog$(suffix)@EXEEXT@; \
for f in verilog$(suffix) gverilog$(suffix)@EXEEXT@; \
do rm -f "$(DESTDIR)$(bindir)/$$f"; done
for f in ivl_target.h vpi_user.h _pli_types.h sv_vpi_user.h acc_user.h veriuser.h; \
do rm -f "$(DESTDIR)$(includedir)/$$f"; done
-test X$(suffix) = X || rmdir "$(DESTDIR)$(includedir)"
rm -f "$(DESTDIR)$(mandir)/man1/iverilog-vpi$(suffix).1" \
"$(DESTDIR)$(pdfdir)/iverilog-vpi$(suffix).pdf"
do rm -f "$(DESTDIR)$(ivl_includedir)/$$f"; done
-test X$(suffix) = X || rmdir "$(DESTDIR)$(ivl_includedir)"
-include $(patsubst %.o, dep/%.d, $O)
.PHONY: check-installed check-installed-vpi check-installed-vvp check-installed-vvp-py
+60 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2022 Stephen Williams ([email protected])
* Copyright (c) 1998-2026 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -21,13 +21,65 @@
# include "Module.h"
# include "PGate.h"
# include "PModport.h"
# include "PWire.h"
# include "parse_api.h"
# include "ivl_assert.h"
# include <iostream>
using namespace std;
list<Module::named_expr_t> Module::user_defparms;
Module::port_t::port_t()
: port_kind(P_SIGNAL), default_value(0), interface_unpacked_dimensions(0), lexical_pos(0)
{
}
bool resolve_interface_formal_port(const LineInfo*li, Design*des,
const Module::port_t*port,
interface_formal_port_t&res,
bool emit_errors)
{
ivl_assert(*li, port);
ivl_assert(*li, port->is_interface_port());
res = interface_formal_port_t();
map<perm_string,Module*>::const_iterator mod =
pform_modules.find(port->interface_type);
if (mod == pform_modules.end() || !mod->second->is_interface) {
if (emit_errors) {
cerr << li->get_fileline() << ": error: Interface port "
<< port->name << " uses unknown interface type `"
<< port->interface_type << "'." << endl;
des->errors += 1;
}
return false;
}
res.module = mod->second;
if (port->modport_name.str()) {
map<perm_string,PModport*>::const_iterator mp =
mod->second->modports.find(port->modport_name);
if (mp == mod->second->modports.end()) {
if (emit_errors) {
cerr << li->get_fileline() << ": error: Interface port "
<< port->name << " uses unknown modport `"
<< port->modport_name << "' of interface `"
<< port->interface_type << "'." << endl;
des->errors += 1;
}
return false;
}
res.modport = mp->second;
}
return true;
}
/* n is a permallocated string. */
Module::Module(LexicalScope*parent, perm_string n)
: PScopeExtra(n, parent)
@@ -63,12 +115,18 @@ const vector<PEIdent*>& Module::get_port(unsigned idx) const
ivl_assert(*this, idx < ports.size());
static const vector<PEIdent*> zero;
if (ports[idx])
if (ports[idx] && !ports[idx]->is_interface_port())
return ports[idx]->expr;
else
return zero;
}
const Module::port_t* Module::get_port_info(unsigned idx) const
{
ivl_assert(*this, idx < ports.size());
return ports[idx];
}
unsigned Module::find_port(const char*name) const
{
ivl_assert(*this, name != 0);
+33 -3
View File
@@ -1,7 +1,7 @@
#ifndef IVL_Module_H
#define IVL_Module_H
/*
* Copyright (c) 1998-2021 Stephen Williams ([email protected])
* Copyright (c) 1998-2026 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -43,6 +43,7 @@ class PFunction;
class PWire;
class PProcess;
class Design;
class LineInfo;
class NetScope;
/*
@@ -65,16 +66,32 @@ class Module : public PScopeExtra, public PNamedItem {
default value. */
public:
struct port_t {
enum port_kind_t { P_SIGNAL, P_INTERFACE };
port_t();
port_kind_t port_kind;
perm_string name;
std::vector<PEIdent*> expr;
PExpr*default_value;
/* Interface formal port metadata. For signal ports these
fields are empty/zero. The modport name is optional in the
representation, although the parser initially only accepts
the explicit interface_type.modport form. */
perm_string interface_type;
perm_string modport_name;
std::list<pform_range_t>*interface_unpacked_dimensions;
unsigned lexical_pos;
bool is_interface_port() const { return port_kind == P_INTERFACE; }
};
public:
/* The name passed here is the module name, not the instance
name. This name must be a permallocated string. */
explicit Module(LexicalScope*parent, perm_string name);
~Module();
~Module() override;
/* Initially false. This is set to true if the module has been
declared as a library module. This makes the module
@@ -148,6 +165,7 @@ class Module : public PScopeExtra, public PNamedItem {
unsigned port_count() const;
const std::vector<PEIdent*>& get_port(unsigned idx) const;
const port_t* get_port_info(unsigned idx) const;
unsigned find_port(const char*name) const;
// Return port name ("" for undeclared port)
@@ -167,7 +185,7 @@ class Module : public PScopeExtra, public PNamedItem {
bool elaborate_sig(Design*, NetScope*scope) const;
SymbolType symbol_type() const;
SymbolType symbol_type() const override;
bool can_be_toplevel() const;
@@ -181,4 +199,16 @@ class Module : public PScopeExtra, public PNamedItem {
Module& operator= (const Module&);
};
struct interface_formal_port_t {
interface_formal_port_t() : module(0), modport(0) { }
const Module*module;
const PModport*modport;
};
extern bool resolve_interface_formal_port(const LineInfo*li, Design*des,
const Module::port_t*port,
interface_formal_port_t&res,
bool emit_errors);
#endif /* IVL_Module_H */
+3 -3
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PClass_H
#define IVL_PClass_H
/*
* Copyright (c) 2012-2019 Stephen Williams ([email protected])
* Copyright (c) 2012-2025 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -36,11 +36,11 @@ class PClass : public PScopeExtra, public PNamedItem {
public:
explicit PClass (perm_string name, LexicalScope*parent);
~PClass();
~PClass() override;
void dump(std::ostream&out, unsigned indent) const;
SymbolType symbol_type() const;
SymbolType symbol_type() const override;
public:
class_type_t*type;
+22 -22
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2021 Stephen Williams ([email protected])
* Copyright (c) 1999-2026 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -130,10 +130,11 @@ static NetExpr* make_delay_nets(Design*des, NetScope*scope, NetExpr*expr)
return expr;
}
static NetExpr* calc_decay_time(NetExpr *rise, NetExpr *fall)
static const NetExpr *calc_decay_time(const NetExpr *rise,
const NetExpr *fall)
{
NetEConst *c_rise = dynamic_cast<NetEConst*>(rise);
NetEConst *c_fall = dynamic_cast<NetEConst*>(fall);
const NetEConst *c_rise = dynamic_cast<const NetEConst*>(rise);
const NetEConst *c_fall = dynamic_cast<const NetEConst*>(fall);
if (c_rise && c_fall) {
if (c_rise->value() < c_fall->value()) return rise;
else return fall;
@@ -142,44 +143,43 @@ static NetExpr* calc_decay_time(NetExpr *rise, NetExpr *fall)
return 0;
}
void PDelays::eval_delays(Design*des, NetScope*scope,
NetExpr*&rise_time,
NetExpr*&fall_time,
NetExpr*&decay_time,
void PDelays::eval_delays(Design*des, NetScope*scope, delay_exprs_t &delays,
bool as_nets_flag) const
{
assert(scope);
if (delay_[0]) {
rise_time = calculate_val(des, scope, delay_[0]);
NetExpr *rise = calculate_val(des, scope, delay_[0]);
if (as_nets_flag)
rise_time = make_delay_nets(des, scope, rise_time);
rise = make_delay_nets(des, scope, rise);
delays.rise = rise;
if (delay_[1]) {
fall_time = calculate_val(des, scope, delay_[1]);
NetExpr *fall = calculate_val(des, scope, delay_[1]);
if (as_nets_flag)
fall_time = make_delay_nets(des, scope, fall_time);
fall = make_delay_nets(des, scope, fall);
delays.fall = fall;
if (delay_[2]) {
decay_time = calculate_val(des, scope, delay_[2]);
NetExpr *decay = calculate_val(des, scope, delay_[2]);
if (as_nets_flag)
decay_time = make_delay_nets(des, scope,
decay_time);
decay = make_delay_nets(des, scope, decay);
delays.decay = decay;
} else {
// If this is zero then we need to do the min()
// at run time.
decay_time = calc_decay_time(rise_time, fall_time);
delays.decay = calc_decay_time(delays.rise,
delays.fall);
}
} else {
assert(delay_[2] == 0);
fall_time = rise_time;
decay_time = rise_time;
delays.fall = delays.rise;
delays.decay = delays.rise;
}
} else {
rise_time = 0;
fall_time = 0;
decay_time = 0;
delays.rise = nullptr;
delays.fall = nullptr;
delays.decay = nullptr;
}
}
+3 -5
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PDelays_H
#define IVL_PDelays_H
/*
* Copyright (c) 1999-2021 Stephen Williams ([email protected])
* Copyright (c) 1999-2026 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -27,6 +27,7 @@ class Design;
class NetScope;
class NetExpr;
class PExpr;
struct delay_exprs_t;
/*
* Various PForm objects can carry delays. These delays include rise,
@@ -46,10 +47,7 @@ class PDelays {
unsigned delay_count() const;
void eval_delays(Design*des, NetScope*scope,
NetExpr*&rise_time,
NetExpr*&fall_time,
NetExpr*&decay_time,
void eval_delays(Design*des, NetScope*scope, delay_exprs_t &delays,
bool as_nets_flag =false) const;
void dump_delays(std::ostream&out) const;
+2 -1
View File
@@ -22,8 +22,9 @@
# include "PEvent.h"
PEvent::PEvent(perm_string n, unsigned lexical_pos)
: name_(n), lexical_pos_(lexical_pos)
: name_(n)
{
LineInfo::lexical_pos(lexical_pos);
}
PEvent::~PEvent()
+3 -6
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PEvent_H
#define IVL_PEvent_H
/*
* Copyright (c) 2000-2024 Stephen Williams ([email protected])
* Copyright (c) 2000-2025 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -37,19 +37,16 @@ class PEvent : public PNamedItem {
// The name is a perm-allocated string. It is the simple name
// of the event, without any scope.
explicit PEvent(perm_string name, unsigned lexical_pos);
~PEvent();
~PEvent() override;
perm_string name() const;
unsigned lexical_pos() const { return lexical_pos_; }
void elaborate_scope(Design*des, NetScope*scope) const;
SymbolType symbol_type() const;
SymbolType symbol_type() const override;
private:
perm_string name_;
unsigned lexical_pos_;
private: // not implemented
PEvent(const PEvent&);
+100 -44
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2024 Stephen Williams <[email protected]>
* Copyright (c) 1998-2026 Stephen Williams <[email protected]>
* Copyright CERN 2013 / Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
@@ -20,10 +20,12 @@
# include "config.h"
# include <algorithm>
# include <iostream>
# include "compiler.h"
# include "PExpr.h"
# include "PPackage.h"
# include "PWire.h"
# include "Module.h"
# include "ivl_assert.h"
@@ -54,7 +56,7 @@ bool PExpr::has_aa_term(Design*, NetScope*) const
return false;
}
NetNet* PExpr::elaborate_lnet(Design*, NetScope*) const
NetNet* PExpr::elaborate_lnet(Design*, NetScope*, bool) const
{
cerr << get_fileline() << ": error: "
<< "expression not valid in assign l-value: "
@@ -62,7 +64,7 @@ NetNet* PExpr::elaborate_lnet(Design*, NetScope*) const
return 0;
}
NetNet* PExpr::elaborate_bi_net(Design*, NetScope*) const
NetNet* PExpr::elaborate_bi_net(Design*, NetScope*, bool) const
{
cerr << get_fileline() << ": error: "
<< "expression not valid as argument to inout port: "
@@ -107,6 +109,16 @@ PEAssignPattern::~PEAssignPattern()
{
}
bool PEAssignPattern::has_aa_term(Design*des, NetScope*scope) const
{
bool flag = false;
for (const auto *parm : parms_) {
if (parm)
flag = parm->has_aa_term(des, scope) || flag;
}
return flag;
}
PEBinary::PEBinary(char op, PExpr*l, PExpr*r)
: op_(op), left_(l), right_(r)
{
@@ -128,30 +140,12 @@ bool PEBinary::has_aa_term(Design*des, NetScope*scope) const
return left_->has_aa_term(des, scope) || right_->has_aa_term(des, scope);
}
PECastSize::PECastSize(PExpr*si, PExpr*b)
: size_(si), base_(b)
PECast::PECast(PExpr *target, PExpr *base)
: target_(target), base_(base)
{
}
PECastSize::~PECastSize()
{
}
bool PECastSize::has_aa_term(Design *des, NetScope *scope) const
{
return base_->has_aa_term(des, scope);
}
PECastType::PECastType(data_type_t*t, PExpr*b)
: target_(t), base_(b)
{
}
PECastType::~PECastType()
{
}
bool PECastType::has_aa_term(Design *des, NetScope *scope) const
bool PECast::has_aa_term(Design *des, NetScope *scope) const
{
return base_->has_aa_term(des, scope);
}
@@ -259,26 +253,60 @@ PECallFunction::PECallFunction(perm_string n, const list<named_pexpr_t> &parms)
{
}
PECallFunction::PECallFunction(PExpr* chain_prefix, const pform_name_t &method,
const vector<named_pexpr_t> &parms)
: path_(method), parms_(parms), chain_prefix_(chain_prefix), is_overridden_(false)
{
}
PECallFunction::PECallFunction(PExpr* chain_prefix, const pform_name_t &method,
const list<named_pexpr_t> &parms)
: path_(method), parms_(parms.begin(), parms.end()),
chain_prefix_(chain_prefix), is_overridden_(false)
{
}
void PECallFunction::set_with_clause(PExpr* with_expr)
{
delete with_expr_;
with_expr_ = with_expr;
}
PECallFunction::~PECallFunction()
{
delete chain_prefix_;
delete with_expr_;
}
void PECallFunction::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
{
if (chain_prefix_) {
chain_prefix_->declare_implicit_nets(scope, type);
}
if (with_expr_) {
with_expr_->declare_implicit_nets(scope, type);
}
for (const auto &parm : parms_) {
if (parm.parm)
if (parm.parm) {
parm.parm->declare_implicit_nets(scope, type);
}
}
}
bool PECallFunction::has_aa_term(Design*des, NetScope*scope) const
{
bool flag = false;
for (const auto &parm : parms_) {
if (parm.parm)
flag |= parm.parm->has_aa_term(des, scope);
if (chain_prefix_ && chain_prefix_->has_aa_term(des, scope)) {
return true;
}
return flag;
if (with_expr_ && with_expr_->has_aa_term(des, scope)) {
return true;
}
for (const auto &parm : parms_) {
if (parm.parm && parm.parm->has_aa_term(des, scope)) {
return true;
}
}
return false;
}
PEConcat::PEConcat(const list<PExpr*>&p, PExpr*r)
@@ -360,19 +388,22 @@ const verireal& PEFNumber::value() const
return *value_;
}
PEIdent::PEIdent(const pform_name_t&that, unsigned lexical_pos)
: path_(that), lexical_pos_(lexical_pos), no_implicit_sig_(false)
PEIdent::PEIdent(const pform_name_t&that, unsigned lexical_pos,
bool no_implicit_sig)
: path_(that), no_implicit_sig_(no_implicit_sig)
{
LineInfo::lexical_pos(lexical_pos);
}
PEIdent::PEIdent(perm_string s, unsigned lexical_pos, bool no_implicit_sig)
: lexical_pos_(lexical_pos), no_implicit_sig_(no_implicit_sig)
: no_implicit_sig_(no_implicit_sig)
{
LineInfo::lexical_pos(lexical_pos);
path_.name.push_back(name_component_t(s));
}
PEIdent::PEIdent(PPackage*pkg, const pform_name_t&that, unsigned lexical_pos)
: path_(pkg, that), lexical_pos_(lexical_pos), no_implicit_sig_(true)
PEIdent::PEIdent(PPackage*pkg, const pform_name_t&that)
: path_(pkg, that), no_implicit_sig_(true)
{
}
@@ -382,13 +413,33 @@ PEIdent::~PEIdent()
static bool find_enum_constant(LexicalScope*scope, perm_string name)
{
for (vector<enum_type_t*>::const_iterator cur = scope->enum_sets.begin() ;
cur != scope->enum_sets.end() ; ++ cur) {
for (list<named_pexpr_t>::const_iterator idx = (*cur)->names->begin() ;
idx != (*cur)->names->end() ; ++ idx) {
if (idx->name == name) return true;
return std::any_of(scope->enum_sets.cbegin(), scope->enum_sets.cend(),
[name](const enum_type_t *cur) {
return std::any_of(cur->names->cbegin(), cur->names->cend(),
[name](const named_pexpr_t&idx){return idx.name == name;});
});
}
static bool is_typedef_identifier(LexicalScope *scope, perm_string name)
{
while (scope) {
auto import = scope->explicit_imports.find(name);
if (import != scope->explicit_imports.end()) {
// An explicit import shadows declarations in outer scopes.
const auto &typedefs = import->second.package->typedefs;
return typedefs.find(name) != typedefs.end();
}
if (scope->typedefs.find(name) != scope->typedefs.end())
return true;
// A local non-type declaration also hides outer typedefs.
if (scope->local_symbols.find(name) != scope->local_symbols.end())
return false;
scope = scope->parent_scope();
}
return false;
}
@@ -405,6 +456,9 @@ void PEIdent::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
return;
if (path_.name.size() == 1 && path_.name.front().index.empty()) {
perm_string name = path_.name.front().name;
if (is_typedef_identifier(scope, name))
return;
LexicalScope*ss = scope;
while (ss) {
if (ss->wires.find(name) != ss->wires.end())
@@ -426,9 +480,8 @@ void PEIdent::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
ss = ss->parent_scope();
}
PWire*net = new PWire(name, lexical_pos_, type, NetNet::NOT_A_PORT);
net->set_file(get_file());
net->set_lineno(get_lineno());
PWire*net = new PWire(name, lexical_pos(), type, NetNet::NOT_A_PORT);
net->set_line(*this);
scope->wires[name] = net;
if (warn_implicit) {
cerr << get_fileline() << ": warning: implicit "
@@ -440,7 +493,10 @@ void PEIdent::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
bool PEIdent::has_aa_term(Design*des, NetScope*scope) const
{
symbol_search_results sr;
if (!symbol_search(this, des, scope, path_, lexical_pos_, &sr))
if (!symbol_search(this, des, scope, path_, lexical_pos(), &sr))
return false;
if (sr.type_def)
return false;
// Class properties are not considered automatic since a non-blocking
+282 -197
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PExpr_H
#define IVL_PExpr_H
/*
* Copyright (c) 1998-2024 Stephen Williams <[email protected]>
* Copyright (c) 1998-2026 Stephen Williams <[email protected]>
* Copyright CERN 2013 / Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
@@ -37,6 +37,7 @@ class NetExpr;
class NetScope;
class PPackage;
struct symbol_search_results;
class netclass_t;
/*
* The PExpr class hierarchy supports the description of
@@ -50,6 +51,11 @@ class PExpr : public LineInfo {
// Mode values used by test_width() (see below for description).
enum width_mode_t { SIZED, UNSIZED, EXPAND, LOSSLESS, UPSIZE };
enum class type_elaboration_context_t {
DEFAULT,
CAST_TARGET
};
// Flag values that can be passed to elaborate_expr().
static const unsigned NO_FLAGS = 0x0;
static const unsigned NEED_CONST = 0x1;
@@ -60,7 +66,7 @@ class PExpr : public LineInfo {
static const char*width_mode_name(width_mode_t mode);
PExpr();
virtual ~PExpr();
virtual ~PExpr() override;
virtual void dump(std::ostream&) const;
@@ -127,6 +133,17 @@ class PExpr : public LineInfo {
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
// Return true if this expression represents a type in this scope. This
// may cache lookup state for a subsequent elaborate_type() call.
virtual bool test_type(Design *des, NetScope *scope);
// Elaborate this expression as a type in a specific context. Return
// null if the expression is not a type or elaboration fails.
virtual ivl_type_t elaborate_type(
Design *des, NetScope *scope,
type_elaboration_context_t context =
type_elaboration_context_t::DEFAULT) const;
// After the test_width method is complete, these methods
// return valid results.
ivl_variable_type_t expr_type() const { return expr_type_; }
@@ -156,13 +173,15 @@ class PExpr : public LineInfo {
// This method elaborates the expression as gates, but
// restricted for use as l-values of continuous assignments.
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
bool var_allowed_in_sv) const;
// This is similar to elaborate_lnet, except that the
// expression is evaluated to be bi-directional. This is
// useful for arguments to inout ports of module instances and
// ports of tran primitives.
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope,
bool var_allowed_in_sv) const;
// Expressions that can be in the l-value of procedural
// assignments can be elaborated with this method. If the
@@ -202,17 +221,19 @@ class PEAssignPattern : public PExpr {
public:
explicit PEAssignPattern();
explicit PEAssignPattern(const std::list<PExpr*>&p);
~PEAssignPattern();
~PEAssignPattern() override;
void dump(std::ostream&) const;
void dump(std::ostream&) const override;
virtual unsigned test_width(Design*des, NetScope*scope, width_mode_t&mode);
virtual bool has_aa_term(Design*des, NetScope*scope) const override;
virtual unsigned test_width(Design*des, NetScope*scope, width_mode_t&mode) override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
ivl_type_t type, unsigned flags) const override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid,
unsigned flags) const;
unsigned flags) const override;
private:
NetExpr* elaborate_expr_packed_(Design *des, NetScope *scope,
ivl_variable_type_t base_type,
@@ -240,36 +261,39 @@ class PEConcat : public PExpr {
public:
explicit PEConcat(const std::list<PExpr*>&p, PExpr*r =0);
~PEConcat();
~PEConcat() override;
virtual void dump(std::ostream&) const;
virtual void dump(std::ostream&) const override;
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type) override;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual bool has_aa_term(Design*des, NetScope*scope) const override;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
width_mode_t&mode) override;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
bool var_allowed_in_sv) const override;
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope,
bool var_allowed_in_sv) const override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
ivl_type_t type, unsigned flags) const override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
unsigned flags) const;
unsigned flags) const override;
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_cassign,
bool is_force,
bool is_init = false) const;
bool is_init = false) const override;
virtual bool is_collapsible_net(Design*des, NetScope*scope,
NetNet::PortType port_type) const;
NetNet::PortType port_type) const override;
private:
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
bool bidirectional_flag) const;
bool bidirectional_flag,
bool var_allowed_in_sv) const;
private:
std::vector<PExpr*>parms_;
std::valarray<width_mode_t>width_modes_;
@@ -294,14 +318,14 @@ class PEEvent : public PExpr {
// Use this constructor to create events based on edges or levels.
PEEvent(edge_t t, PExpr*e);
~PEEvent();
~PEEvent() override;
edge_t type() const;
PExpr* expr() const;
virtual void dump(std::ostream&) const;
virtual void dump(std::ostream&) const override;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual bool has_aa_term(Design*des, NetScope*scope) const override;
private:
edge_t type_;
@@ -315,19 +339,19 @@ class PEFNumber : public PExpr {
public:
explicit PEFNumber(verireal*vp);
~PEFNumber();
~PEFNumber() override;
const verireal& value() const;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
width_mode_t&mode) override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
ivl_type_t type, unsigned flags) const;
ivl_type_t type, unsigned flags) const override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
unsigned flags) const;
unsigned flags) const override;
virtual void dump(std::ostream&) const;
virtual void dump(std::ostream&) const override;
private:
verireal*value_;
@@ -337,40 +361,46 @@ class PEIdent : public PExpr {
public:
explicit PEIdent(perm_string, unsigned lexical_pos, bool no_implicit_sig=false);
explicit PEIdent(PPackage*pkg, const pform_name_t&name, unsigned lexical_pos);
explicit PEIdent(const pform_name_t&, unsigned lexical_pos);
~PEIdent();
explicit PEIdent(PPackage*pkg, const pform_name_t&name);
explicit PEIdent(const pform_name_t&, unsigned lexical_pos,
bool no_implicit_sig = false);
~PEIdent() override;
// Add another name to the string of hierarchy that is the
// current identifier.
void append_name(perm_string);
virtual void dump(std::ostream&) const;
virtual void dump(std::ostream&) const override;
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type) override;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual bool has_aa_term(Design*des, NetScope*scope) const override;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
width_mode_t&mode) override;
// Identifiers are allowed (with restrictions) is assign l-values.
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope, bool var_allowed_in_sv) const override;
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope, bool var_allowed_in_sv) const override;
// Identifiers are also allowed as procedural assignment l-values.
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_cassign,
bool is_force,
bool is_init = false) const;
bool is_init = false) const override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
ivl_type_t type, unsigned flags) const override;
bool test_type(Design *des, NetScope *scope) override;
ivl_type_t elaborate_type(
Design *des, NetScope *scope,
type_elaboration_context_t context =
type_elaboration_context_t::DEFAULT) const override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
unsigned flags) const;
unsigned flags) const override;
// Elaborate the PEIdent as a port to a module. This method
// only applies to Ident expressions.
@@ -382,18 +412,27 @@ class PEIdent : public PExpr {
NetNet* elaborate_unpacked_net(Design*des, NetScope*sc) const;
virtual bool is_collapsible_net(Design*des, NetScope*scope,
NetNet::PortType port_type) const;
NetNet::PortType port_type) const override;
const pform_scoped_name_t& path() const { return path_; }
unsigned lexical_pos() const { return lexical_pos_; }
private:
// Type testing and elaboration normally happen as a pair. Preserve the
// lookup result between them, but only reuse it in the same scope.
struct type_lookup_t {
const NetScope *lookup_scope = nullptr;
NetScope *declaration_scope = nullptr;
typedef_t *type_def = nullptr;
bool valid = false;
};
pform_scoped_name_t path_;
unsigned lexical_pos_;
bool no_implicit_sig_;
type_lookup_t type_lookup_;
bool find_type_(Design *des, NetScope *scope,
struct symbol_search_results &search_results) const;
private:
// Common functions to calculate parts of part/bit
// selects. These methods return true if the expressions
// elaborate/calculate, or false if there is some sort of
@@ -407,7 +446,7 @@ class PEIdent : public PExpr {
// the values written to the msb/lsb arguments. If there are
// invalid bits (xz) in either expression, then the defined
// flag is set to *false*.
bool calculate_parts_(Design*, NetScope*, long&msb, long&lsb, bool&defined) const;
void calculate_parts_(Design*, NetScope*, long&msb, long&lsb, bool&defined) const;
NetExpr* calculate_up_do_base_(Design*, NetScope*, bool need_const) const;
bool calculate_up_do_width_(Design*, NetScope*, unsigned long&wid) const;
@@ -421,7 +460,7 @@ class PEIdent : public PExpr {
// [2:0][x] - BAD
// [y][x] - BAD
// Leave the last index for special handling.
bool calculate_packed_indices_(Design*des, NetScope*scope, NetNet*net,
bool calculate_packed_indices_(Design*des, NetScope*scope, const NetNet*net,
std::list<long>&prefix_indices) const;
private:
@@ -483,18 +522,12 @@ class PEIdent : public PExpr {
const NetScope*found_in,
ivl_type_t par_type,
unsigned expr_wid) const;
NetExpr*elaborate_expr_param_idx_up_(Design*des,
NetScope*scope,
const NetExpr*par,
const NetScope*found_in,
ivl_type_t par_type,
bool need_const) const;
NetExpr*elaborate_expr_param_idx_do_(Design*des,
NetScope*scope,
const NetExpr*par,
const NetScope*found_in,
ivl_type_t par_type,
bool need_const) const;
NetExpr*elaborate_expr_param_idx_up_do_(Design*des,
NetScope*scope,
const NetExpr*par,
const NetScope*found_in,
ivl_type_t par_type,
bool up, bool need_const) const;
NetExpr*elaborate_expr_net(Design*des,
NetScope*scope,
NetNet*net,
@@ -512,16 +545,11 @@ class PEIdent : public PExpr {
NetESignal*net,
NetScope*found,
unsigned expr_wid) const;
NetExpr*elaborate_expr_net_idx_up_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found,
bool need_const) const;
NetExpr*elaborate_expr_net_idx_do_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found,
bool need_const) const;
NetExpr*elaborate_expr_net_idx_up_do_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found,
bool up, bool need_const) const;
NetExpr*elaborate_expr_net_bit_(Design*des,
NetScope*scope,
NetESignal*net,
@@ -545,10 +573,11 @@ class PEIdent : public PExpr {
private:
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
bool bidirectional_flag) const;
bool bidirectional_flag,
bool var_allowed_in_sv) const;
bool eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
bool eval_part_select_(Design*des, NetScope*scope, const NetNet*sig,
long&midx, long&lidx) const;
};
@@ -556,16 +585,16 @@ class PENewArray : public PExpr {
public:
explicit PENewArray (PExpr*s, PExpr*i);
~PENewArray();
~PENewArray() override;
virtual void dump(std::ostream&) const;
virtual void dump(std::ostream&) const override;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
width_mode_t&mode) override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
ivl_type_t type, unsigned flags) const override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
unsigned flags) const;
unsigned flags) const override;
private:
PExpr*size_;
@@ -581,18 +610,18 @@ class PENewClass : public PExpr {
explicit PENewClass (const std::list<named_pexpr_t> &p,
data_type_t *class_type = nullptr);
~PENewClass();
~PENewClass() override;
virtual void dump(std::ostream&) const;
virtual void dump(std::ostream&) const override;
// Class objects don't have a useful width, but the expression
// is IVL_VT_CLASS.
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
width_mode_t&mode) override;
// Note that class (new) expressions only appear in context
// that uses this form of the elaborate_expr method. In fact,
// the type argument is going to be a netclass_t object.
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
ivl_type_t type, unsigned flags) const override;
private:
NetExpr* elaborate_expr_constructor_(Design*des, NetScope*scope,
@@ -607,18 +636,18 @@ class PENewClass : public PExpr {
class PENewCopy : public PExpr {
public:
explicit PENewCopy(PExpr*src);
~PENewCopy();
~PENewCopy() override;
virtual void dump(std::ostream&) const;
virtual void dump(std::ostream&) const override;
// Class objects don't have a useful width, but the expression
// is IVL_VT_CLASS.
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
width_mode_t&mode) override;
// Note that class (new) expressions only appear in context
// that uses this form of the elaborate_expr method. In fact,
// the type argument is going to be a netclass_t object.
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
ivl_type_t type, unsigned flags) const override;
private:
PExpr*src_;
@@ -627,39 +656,45 @@ class PENewCopy : public PExpr {
class PENull : public PExpr {
public:
explicit PENull();
~PENull();
~PENull() override;
virtual void dump(std::ostream&) const;
virtual void dump(std::ostream&) const override;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
width_mode_t&mode) override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
ivl_type_t type, unsigned flags) const override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
unsigned flags) const;
unsigned flags) const override;
};
// Internal marker for the '$' in a queue dimension.
class PEQueueDimension : public PExpr {
public:
void dump(std::ostream&) const override;
};
class PENumber : public PExpr {
public:
explicit PENumber(verinum*vp);
~PENumber();
~PENumber() override;
const verinum& value() const;
virtual void dump(std::ostream&) const;
virtual void dump(std::ostream&) const override;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
width_mode_t&mode) override;
virtual NetExpr *elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
ivl_type_t type, unsigned flags) const override;
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid, unsigned) const;
unsigned expr_wid, unsigned) const override;
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_cassign,
bool is_force,
bool is_init = false) const;
bool is_init = false) const override;
private:
verinum*const value_;
@@ -676,20 +711,24 @@ class PEString : public PExpr {
public:
explicit PEString(char*s);
~PEString();
~PEString() override;
std::string value() const;
virtual void dump(std::ostream&) const;
virtual void dump(std::ostream&) const override;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
width_mode_t&mode) override;
virtual NetEConst*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const override;
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid, unsigned) const;
unsigned expr_wid, unsigned) const override;
NetExpr *elaborate_expr_uarray_(Design *des, NetScope *scope,
const netuarray_t *uarray_type,
const std::vector<netrange_t> &dims,
unsigned int cur_dim) const;
private:
char*text_;
};
@@ -697,15 +736,18 @@ class PEString : public PExpr {
class PETypename : public PExpr {
public:
explicit PETypename(data_type_t*data_type);
~PETypename();
~PETypename() override;
virtual void dump(std::ostream&) const;
virtual void dump(std::ostream&) const override;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
width_mode_t&mode) override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
inline data_type_t* get_type() const { return data_type_; }
ivl_type_t type, unsigned flags) const override;
bool test_type(Design *des, NetScope *scope) override;
ivl_type_t elaborate_type(
Design *des, NetScope *scope,
type_elaboration_context_t context =
type_elaboration_context_t::DEFAULT) const override;
private:
data_type_t*data_type_;
@@ -715,20 +757,20 @@ class PEUnary : public PExpr {
public:
explicit PEUnary(char op, PExpr*ex);
~PEUnary();
~PEUnary() override;
virtual void dump(std::ostream&out) const;
virtual void dump(std::ostream&out) const override;
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type) override;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual bool has_aa_term(Design*des, NetScope*scope) const override;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
width_mode_t&mode) override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
unsigned flags) const;
unsigned flags) const override;
public:
inline char get_op() const { return op_; }
@@ -746,20 +788,20 @@ class PEBinary : public PExpr {
public:
explicit PEBinary(char op, PExpr*l, PExpr*r);
~PEBinary();
~PEBinary() override;
virtual void dump(std::ostream&out) const;
virtual void dump(std::ostream&out) const override;
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type) override;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual bool has_aa_term(Design*des, NetScope*scope) const override;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
width_mode_t&mode) override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
unsigned flags) const;
unsigned flags) const override;
protected:
char op_;
@@ -790,13 +832,13 @@ class PEBComp : public PEBinary {
public:
explicit PEBComp(char op, PExpr*l, PExpr*r);
~PEBComp();
~PEBComp() override;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
width_mode_t&mode) override;
NetExpr* elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, unsigned flags) const;
unsigned expr_wid, unsigned flags) const override;
private:
unsigned l_width_;
@@ -810,13 +852,13 @@ class PEBLogic : public PEBinary {
public:
explicit PEBLogic(char op, PExpr*l, PExpr*r);
~PEBLogic();
~PEBLogic() override;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
width_mode_t&mode) override;
NetExpr* elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, unsigned flags) const;
unsigned expr_wid, unsigned flags) const override;
};
/*
@@ -828,38 +870,38 @@ class PEBLeftWidth : public PEBinary {
public:
explicit PEBLeftWidth(char op, PExpr*l, PExpr*r);
~PEBLeftWidth() =0;
~PEBLeftWidth() override =0;
virtual NetExpr*elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
unsigned expr_wid) const =0;
protected:
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
width_mode_t&mode) override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid,
unsigned flags) const;
unsigned flags) const override;
};
class PEBPower : public PEBLeftWidth {
public:
explicit PEBPower(char op, PExpr*l, PExpr*r);
~PEBPower();
~PEBPower() override;
NetExpr*elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
unsigned expr_wid) const;
unsigned expr_wid) const override;
};
class PEBShift : public PEBLeftWidth {
public:
explicit PEBShift(char op, PExpr*l, PExpr*r);
~PEBShift();
~PEBShift() override;
NetExpr*elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
unsigned expr_wid) const;
unsigned expr_wid) const override;
};
/*
@@ -870,20 +912,20 @@ class PETernary : public PExpr {
public:
explicit PETernary(PExpr*e, PExpr*t, PExpr*f);
~PETernary();
~PETernary() override;
virtual void dump(std::ostream&out) const;
virtual void dump(std::ostream&out) const override;
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type) override;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
virtual bool has_aa_term(Design*des, NetScope*scope) const override;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
width_mode_t&mode) override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
unsigned expr_wid,
unsigned flags) const;
unsigned flags) const override;
private:
NetExpr* elab_and_eval_alternative_(Design*des, NetScope*scope,
@@ -918,26 +960,43 @@ class PECallFunction : public PExpr {
explicit PECallFunction(const pform_name_t &n, const std::list<named_pexpr_t> &parms);
explicit PECallFunction(perm_string n, const std::list<named_pexpr_t> &parms);
~PECallFunction();
// SystemVerilog: prefix().method(args) — prefix elaborates to a class handle.
explicit PECallFunction(PExpr* chain_prefix, const pform_name_t &method,
const std::vector<named_pexpr_t> &parms);
explicit PECallFunction(PExpr* chain_prefix, const pform_name_t &method,
const std::list<named_pexpr_t> &parms);
virtual void dump(std::ostream &) const;
// SystemVerilog: q.find with (expr) — iterator "item"/"index" in expr.
void set_with_clause(PExpr* with_expr);
const PExpr* peek_with_clause(void) const { return with_expr_; }
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type);
~PECallFunction() override;
virtual bool has_aa_term(Design*des, NetScope*scope) const;
// For chained-call resolution (path is only the final method name).
const pform_scoped_name_t& peek_path(void) const { return path_; }
const PExpr* peek_chain_prefix(void) const { return chain_prefix_; }
virtual void dump(std::ostream &) const override;
virtual void declare_implicit_nets(LexicalScope*scope, NetNet::Type type) override;
virtual bool has_aa_term(Design*des, NetScope*scope) const override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
ivl_type_t type, unsigned flags) const override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, unsigned flags) const;
unsigned expr_wid, unsigned flags) const override;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
width_mode_t&mode) override;
private:
pform_scoped_name_t path_;
std::vector<named_pexpr_t> parms_;
// If non-null, this call is prefix().tail_name(...) (SV method chain).
PExpr* chain_prefix_ = nullptr;
PExpr* with_expr_ = nullptr;
// For system functions.
bool is_overridden_;
@@ -953,8 +1012,8 @@ class PECallFunction : public PExpr {
NetExpr* elaborate_expr_method_(Design*des, NetScope*scope,
symbol_search_results&search_results)
const;
NetExpr* elaborate_expr_method_par_(Design*des, NetScope*scope,
symbol_search_results&search_results)
NetExpr* elaborate_expr_method_par_(Design*des, const NetScope*scope,
const symbol_search_results&search_results)
const;
@@ -966,69 +1025,95 @@ class PECallFunction : public PExpr {
unsigned test_width_sfunc_(Design*des, NetScope*scope,
width_mode_t&mode);
unsigned test_width_method_(Design*des, NetScope*scope,
symbol_search_results&search_results,
const symbol_search_results&search_results,
width_mode_t&mode);
NetExpr*elaborate_base_(Design*des, NetScope*scope, NetScope*dscope,
unsigned flags) const;
unsigned elaborate_arguments_(Design*des, NetScope*scope,
NetFuncDef*def, bool need_const,
std::vector<NetExpr*>&parms,
unsigned parm_off) const;
const NetFuncDef*def, bool need_const,
std::vector<NetExpr*>&parms,
unsigned parm_off,
const std::vector<named_pexpr_t>*src_parms = nullptr) const;
NetExpr* elaborate_class_method_net_(Design*des, NetScope*scope,
NetNet*net, const netclass_t*class_type,
perm_string method_name,
const std::vector<named_pexpr_t>*src_parms) const;
NetExpr* elaborate_class_method_net_this_(Design*des, NetScope*scope,
NetExpr* this_expr,
const netclass_t*class_type,
perm_string method_name,
const std::vector<named_pexpr_t>*src_parms) const;
NetExpr* elaborate_expr_method_chained_(Design*des, NetScope*scope,
symbol_search_results&search_results) const;
NetExpr* elaborate_expr_chain_(Design*des, NetScope*scope, unsigned flags) const;
unsigned test_width_chain_(Design*des, NetScope*scope, width_mode_t&mode);
};
/*
* Support the SystemVerilog cast to size.
*/
class PECastSize : public PExpr {
/* Support SystemVerilog size and type casts. */
class PECast : public PExpr {
public:
explicit PECastSize(PExpr*size, PExpr*base);
~PECastSize();
explicit PECast(PExpr *target, PExpr *base);
~PECast() override = default;
void dump(std::ostream &out) const;
void dump(std::ostream &out) const override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid,
unsigned flags) const;
NetExpr *elaborate_expr(Design *des, NetScope *scope,
ivl_type_t type, unsigned int flags) const override;
virtual bool has_aa_term(Design *des, NetScope *scope) const;
NetExpr *elaborate_expr(Design *des, NetScope *scope,
unsigned int expr_wid,
unsigned int flags) const override;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
bool has_aa_term(Design *des, NetScope *scope) const override;
unsigned int test_width(Design *des, NetScope *scope,
width_mode_t &mode) override;
private:
PExpr* size_;
PExpr* base_;
};
NetExpr *elaborate_size_cast_(Design *des, NetScope *scope,
unsigned int expr_wid,
unsigned int target_width,
bool signed_flag,
unsigned int flags) const;
NetExpr *elaborate_type_cast_(Design *des, NetScope *scope,
unsigned int expr_wid,
ivl_type_t target_type,
unsigned int target_width,
bool signed_flag,
unsigned int flags) const;
/*
* Support the SystemVerilog cast to a different type.
*/
class PECastType : public PExpr {
enum class target_kind_t {
ERROR,
SIZE,
TYPE
};
public:
explicit PECastType(data_type_t*target, PExpr*base);
~PECastType();
struct target_info_t {
target_kind_t kind = target_kind_t::ERROR;
ivl_type_t type = nullptr;
unsigned int width = 0;
};
void dump(std::ostream &out) const;
target_info_t resolve_target_(Design *des, NetScope *scope) const;
target_info_t target_for_scope_(Design *des, NetScope *scope) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
std::unique_ptr<PExpr> target_;
std::unique_ptr<PExpr> base_;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, unsigned flags) const;
virtual bool has_aa_term(Design *des, NetScope *scope) const;
virtual unsigned test_width(Design*des, NetScope*scope,
width_mode_t&mode);
private:
data_type_t* target_;
ivl_type_t target_type_;
PExpr* base_;
// Cast targets can depend on parameters in the instance scope. Width
// testing and expression elaboration run sequentially for one scope, so
// retain only the most recent result.
const NetScope *target_scope_ = nullptr;
target_info_t target_info_;
bool target_resolved_ = false;
};
/*
@@ -1038,16 +1123,16 @@ class PECastSign : public PExpr {
public:
explicit PECastSign(bool signed_flag, PExpr *base);
~PECastSign() = default;
~PECastSign() override = default;
void dump(std::ostream &out) const;
void dump(std::ostream &out) const override;
NetExpr* elaborate_expr(Design *des, NetScope *scope,
unsigned expr_wid, unsigned flags) const;
unsigned expr_wid, unsigned flags) const override;
virtual bool has_aa_term(Design *des, NetScope *scope) const;
virtual bool has_aa_term(Design *des, NetScope *scope) const override;
unsigned test_width(Design *des, NetScope *scope, width_mode_t &mode);
unsigned test_width(Design *des, NetScope *scope, width_mode_t &mode) override;
private:
std::unique_ptr<PExpr> base_;
@@ -1061,11 +1146,11 @@ class PEVoid : public PExpr {
public:
explicit PEVoid();
~PEVoid();
~PEVoid() override;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid,
unsigned flags) const;
unsigned flags) const override;
};
#endif /* IVL_PExpr_H */
+11 -32
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2021 Stephen Williams ([email protected])
* Copyright (c) 1999-2026 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -41,29 +41,23 @@ void PGate::set_pins_(list<PExpr*>*pins)
}
PGate::PGate(perm_string name, list<PExpr*>*pins, const list<PExpr*>*del)
: name_(name), pins_(pins? pins->size() : 0), ranges_(0)
: name_(name), pins_(pins? pins->size() : 0), ranges_(nullptr)
{
if (pins) set_pins_(pins);
if (del) delay_.set_delays(del);
str0_ = IVL_DR_STRONG;
str1_ = IVL_DR_STRONG;
}
PGate::PGate(perm_string name, list<PExpr*>*pins, PExpr*del)
: name_(name), pins_(pins? pins->size() : 0), ranges_(0)
: name_(name), pins_(pins? pins->size() : 0), ranges_(nullptr)
{
if (pins) set_pins_(pins);
if (del) delay_.set_delay(del);
str0_ = IVL_DR_STRONG;
str1_ = IVL_DR_STRONG;
}
PGate::PGate(perm_string name, list<PExpr*>*pins)
: name_(name), pins_(pins? pins->size() : 0), ranges_(0)
: name_(name), pins_(pins? pins->size() : 0), ranges_(nullptr)
{
if (pins) set_pins_(pins);
str0_ = IVL_DR_STRONG;
str1_ = IVL_DR_STRONG;
}
PGate::~PGate()
@@ -76,24 +70,14 @@ void PGate::set_ranges(list<pform_range_t>*ranges)
ranges_ = ranges;
}
ivl_drive_t PGate::strength0() const
drive_strength_t PGate::strength() const
{
return str0_;
return strength_;
}
void PGate::strength0(ivl_drive_t s)
void PGate::strength(const drive_strength_t &str)
{
str0_ = s;
}
ivl_drive_t PGate::strength1() const
{
return str1_;
}
void PGate::strength1(ivl_drive_t s)
{
str1_ = s;
strength_ = str;
}
void PGate::elaborate_scope(Design*, NetScope*) const
@@ -109,15 +93,10 @@ void PGate::elaborate_scope(Design*, NetScope*) const
* numbers of expressions.
*/
void PGate::eval_delays(Design*des, NetScope*scope,
NetExpr*&rise_expr,
NetExpr*&fall_expr,
NetExpr*&decay_expr,
void PGate::eval_delays(Design*des, NetScope*scope, delay_exprs_t &delays,
bool as_net_flag) const
{
delay_.eval_delays(des, scope,
rise_expr, fall_expr, decay_expr,
as_net_flag);
delay_.eval_delays(des, scope, delays, as_net_flag);
}
unsigned PGate::delay_count() const
@@ -148,7 +127,7 @@ PGAssign::~PGAssign()
PGBuiltin::PGBuiltin(Type t, perm_string name,
list<PExpr*>*pins,
list<PExpr*>*del)
const list<PExpr*>*del)
: PGate(name, pins, del), type_(t)
{
}
+35 -31
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PGate_H
#define IVL_PGate_H
/*
* Copyright (c) 1998-2021 Stephen Williams ([email protected])
* Copyright (c) 1998-2026 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -31,6 +31,8 @@
class PExpr;
class PUdp;
class Module;
struct delay_exprs_t;
struct drive_strength_t;
/*
* A PGate represents a Verilog gate. The gate has a name and other
@@ -57,7 +59,7 @@ class PGate : public PNamedItem {
explicit PGate(perm_string name, std::list<PExpr*>*pins);
virtual ~PGate();
virtual ~PGate() override;
void set_ranges(std::list<pform_range_t>*ranges);
bool is_array() const { return ranges_ != 0; }
@@ -66,10 +68,7 @@ class PGate : public PNamedItem {
// This evaluates the delays as far as possible, but returns
// an expression, and do not signal errors.
void eval_delays(Design*des, NetScope*scope,
NetExpr*&rise_time,
NetExpr*&fall_time,
NetExpr*&decay_time,
void eval_delays(Design*des, NetScope*scope, delay_exprs_t &delays,
bool as_net_flag =false) const;
unsigned delay_count() const;
@@ -77,11 +76,9 @@ class PGate : public PNamedItem {
unsigned pin_count() const { return pins_.size(); }
PExpr*pin(unsigned idx) const { return pins_[idx]; }
ivl_drive_t strength0() const;
ivl_drive_t strength1() const;
drive_strength_t strength() const;
void strength0(ivl_drive_t);
void strength1(ivl_drive_t);
void strength(const drive_strength_t &str);
std::map<perm_string,PExpr*> attributes;
@@ -90,7 +87,7 @@ class PGate : public PNamedItem {
virtual void elaborate_scope(Design*des, NetScope*sc) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
SymbolType symbol_type() const;
SymbolType symbol_type() const override;
protected:
const std::vector<PExpr*>& get_pins() const { return pins_; }
@@ -109,7 +106,7 @@ class PGate : public PNamedItem {
std::list<pform_range_t>*ranges_;
ivl_drive_t str0_, str1_;
drive_strength_t strength_;
void set_pins_(std::list<PExpr*>*pins);
@@ -127,14 +124,15 @@ class PGAssign : public PGate {
public:
explicit PGAssign(std::list<PExpr*>*pins);
explicit PGAssign(std::list<PExpr*>*pins, std::list<PExpr*>*dels);
~PGAssign();
~PGAssign() override;
void dump(std::ostream&out, unsigned ind =4) const;
virtual void elaborate(Design*des, NetScope*scope) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
void dump(std::ostream&out, unsigned ind =4) const override;
virtual void elaborate(Design*des, NetScope*scope) const override;
private:
void elaborate_unpacked_array_(Design*des, NetScope*scope, NetNet*lval) const;
void elaborate_unpacked_array_(Design*des, NetScope*scope, NetNet*lval,
const drive_strength_t &drive,
const delay_exprs_t &delays) const;
};
@@ -159,18 +157,17 @@ class PGBuiltin : public PGate {
public:
explicit PGBuiltin(Type t, perm_string name,
std::list<PExpr*>*pins,
std::list<PExpr*>*del);
const std::list<PExpr*>*del);
explicit PGBuiltin(Type t, perm_string name,
std::list<PExpr*>*pins,
PExpr*del);
~PGBuiltin();
~PGBuiltin() override;
Type type() const { return type_; }
const char * gate_name() const;
virtual void dump(std::ostream&out, unsigned ind =4) const;
virtual void elaborate(Design*, NetScope*scope) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind =4) const override;
virtual void elaborate(Design*, NetScope*scope) const override;
private:
void calculate_gate_and_lval_count_(unsigned&gate_count,
@@ -210,19 +207,17 @@ class PGModule : public PGate {
// constructor.
explicit PGModule(Module*type, perm_string name);
~PGModule();
~PGModule() override;
// Parameter overrides can come as an ordered list, or a set
// of named expressions.
void set_parameters(std::list<PExpr*>*o);
void set_parameters(named_pexpr_t *pa, unsigned npa);
std::map<perm_string,PExpr*> attributes;
virtual void dump(std::ostream&out, unsigned ind =4) const;
virtual void elaborate(Design*, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*sc) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind =4) const override;
virtual void elaborate(Design*, NetScope*scope) const override;
virtual void elaborate_scope(Design*des, NetScope*sc) const override;
virtual bool elaborate_sig(Design*des, NetScope*scope) const override;
// This returns the module name of this module. It is a
// permallocated string.
@@ -240,11 +235,20 @@ class PGModule : public PGate {
unsigned nparms_;
friend class delayed_elaborate_scope_mod_instances;
void elaborate_mod_(Design*, Module*mod, NetScope*scope) const;
void elaborate_mod_(Design*, const Module*mod, NetScope*scope) const;
void elaborate_udp_(Design*, PUdp *udp, NetScope*scope) const;
void elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const;
void elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*sc) const;
bool elaborate_sig_mod_(Design*des, NetScope*scope, Module*mod) const;
bool elaborate_sig_mod_(Design*des, NetScope*scope, const Module*mod) const;
bool bind_interface_ports_(Design*des, const Module*mod,
NetScope*parent_scope, NetScope*instance_scope,
const std::vector<PExpr*>&pins,
const std::vector<bool>&pins_fromwc) const;
bool match_module_ports_(Design*des, const Module*mod,
NetScope*scope,
std::vector<PExpr*>&pins,
std::vector<bool>&pins_fromwc,
std::vector<bool>&pins_is_explicitly_not_connected) const;
// Not currently used.
#if 0
bool elaborate_sig_udp_(Design*des, NetScope*scope, PUdp*udp) const;
+8 -4
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PGenerate_H
#define IVL_PGenerate_H
/*
* Copyright (c) 2006-2021 Stephen Williams ([email protected])
* Copyright (c) 2006-2025 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -26,10 +26,12 @@
# include <list>
# include <map>
# include <valarray>
# include <vector>
# include "pform_types.h"
class Design;
class NetScope;
class PClass;
class PExpr;
class PFunction;
class PProcess;
@@ -54,7 +56,7 @@ class PGenerate : public PNamedItem, public LexicalScope {
public:
explicit PGenerate(LexicalScope*parent, unsigned id_number);
~PGenerate();
~PGenerate() override;
// Generate schemes have an ID number, for when the scope is
// implicit.
@@ -92,9 +94,11 @@ class PGenerate : public PNamedItem, public LexicalScope {
std::list<PGate*> gates;
void add_gate(PGate*);
// Tasks instantiated within this scheme.
// Definitions instantiated within this scheme.
std::map<perm_string,PTask*> tasks;
std::map<perm_string,PFunction*>funcs;
std::map<perm_string,PClass*> classes;
std::vector<PClass*> classes_lexical;
// Generate schemes can contain further generate schemes.
std::list<PGenerate*> generate_schemes;
@@ -112,7 +116,7 @@ class PGenerate : public PNamedItem, public LexicalScope {
void dump(std::ostream&out, unsigned indent) const;
SymbolType symbol_type() const;
SymbolType symbol_type() const override;
private:
void check_for_valid_genvar_value_(long value);
+3 -3
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PModport_H
#define IVL_PModport_H
/*
* Copyright (c) 2015-2021 Stephen Williams ([email protected])
* Copyright (c) 2015-2025 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -34,14 +34,14 @@ class PModport : public PNamedItem {
// The name is a perm-allocated string. It is the simple name
// of the modport, without any scope.
explicit PModport(perm_string name);
~PModport();
~PModport() override;
perm_string name() const { return name_; }
typedef std::pair <NetNet::PortType,PExpr*> simple_port_t;
std::map<perm_string,simple_port_t> simple_ports;
SymbolType symbol_type() const;
SymbolType symbol_type() const override;
private:
perm_string name_;
+3
View File
@@ -48,6 +48,9 @@ std::ostream& operator << (std::ostream&o, PNamedItem::SymbolType st)
case PNamedItem::VAR:
o << "a variable";
break;
case PNamedItem::CLASS_PROPERTY:
o << "a class property";
break;
case PNamedItem::GENVAR:
o << "a genvar";
break;
+5 -5
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PNamedItem_H
#define IVL_PNamedItem_H
/*
* Copyright (c) 2019 Martin Whitaker ([email protected])
* Copyright (c) 2019-2025 Martin Whitaker ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -31,10 +31,10 @@ class PNamedItem : virtual public LineInfo {
enum SymbolType { ANY, PARAM, NET, VAR, GENVAR, EVENT, TYPE, ENUM,
CLASS, FUNCTION, TASK, BLOCK, GENBLOCK, MODPORT,
PACKAGE, MODULE, PROGRAM, INTERFACE, PRIMITIVE,
INSTANCE };
INSTANCE, CLASS_PROPERTY };
explicit PNamedItem();
virtual ~PNamedItem();
virtual ~PNamedItem() override;
virtual SymbolType symbol_type() const;
};
@@ -49,9 +49,9 @@ class PGenvar : public PNamedItem {
public:
explicit PGenvar();
virtual ~PGenvar();
virtual ~PGenvar() override;
SymbolType symbol_type() const;
SymbolType symbol_type() const override;
};
#endif /* IVL_PNamedItem_H */
+2 -2
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PPackage_H
#define IVL_PPackage_H
/*
* Copyright (c) 2012-2014 Stephen Williams ([email protected])
* Copyright (c) 2012-2025 Stephen Williams ([email protected])
* Copyright CERN 2013 / Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
@@ -36,7 +36,7 @@ class PPackage : public PScopeExtra, public LineInfo {
public:
explicit PPackage (perm_string name, LexicalScope*parent);
~PPackage();
~PPackage() override;
bool elaborate_scope(Design*des, NetScope*scope);
bool elaborate_sig(Design*des, NetScope*scope) const;
+18 -5
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PScope_H
#define IVL_PScope_H
/*
* Copyright (c) 2008-2024 Stephen Williams ([email protected])
* Copyright (c) 2008-2026 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -43,6 +43,16 @@ class PCallTask;
class Design;
class NetScope;
struct package_import_t : public LineInfo {
package_import_t() = default;
explicit package_import_t(PPackage *pkg) : package(pkg) { }
PPackage *package = nullptr;
// LineInfo records where the imported name became locally visible.
};
using package_import_map_t = std::map<perm_string, package_import_t>;
/*
* The PScope class is a base representation of an object that
* represents lexical scope. For example, a module, a function/task, a
@@ -71,7 +81,7 @@ class LexicalScope {
// Symbols that are explicitly imported. This contains the package where
// the symbol has been decelared. When using exports, this might not be
// the same as the package where it has been imported from.
std::map<perm_string,PPackage*>explicit_imports;
package_import_map_t explicit_imports;
// Symbols that are explicitly imported. This contains the set of
// packages from which the symbol has been imported. When using exports
// the same identifier can be imported via multiple packages.
@@ -86,7 +96,7 @@ class LexicalScope {
// later in the scope. So here we stash the potential imports for
// task and function calls. They will be added to the explicit
// imports if we don't find a local definition.
std::map<perm_string,PPackage*>possible_imports;
package_import_map_t possible_imports;
struct range_t {
// True if this is an exclude
@@ -121,6 +131,8 @@ class LexicalScope {
bool overridable;
// Whether the parameter is a type parameter
bool type_flag = false;
// Type restriction for a type parameter
type_restrict_t type_restrict;
// The lexical position of the declaration
unsigned lexical_pos = 0;
@@ -164,6 +176,7 @@ class LexicalScope {
unsigned generate_counter;
LexicalScope* parent_scope() const { return parent_; }
void set_parent_scope(LexicalScope *parent) { parent_ = parent; }
virtual bool var_init_needs_explicit_lifetime() const;
@@ -198,7 +211,7 @@ class PScope : public LexicalScope {
// modules. Scopes for tasks and functions point to their
// containing module.
explicit PScope(perm_string name, LexicalScope*parent =0);
virtual ~PScope();
virtual ~PScope() override;
perm_string pscope_name() const { return name_; }
@@ -233,7 +246,7 @@ class PScopeExtra : public PScope {
public:
explicit PScopeExtra(perm_string, LexicalScope*parent =0);
~PScopeExtra();
~PScopeExtra() override;
/* Task definitions within this module */
std::map<perm_string,PTask*> tasks;
+2 -2
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PSpec_H
#define IVL_PSpec_H
/*
* Copyright (c) 2006-2014 Stephen Williams <[email protected]>
* Copyright (c) 2006-2025 Stephen Williams <[email protected]>
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -60,7 +60,7 @@ class PSpecPath : public LineInfo {
PSpecPath(const std::list<perm_string> &src_list,
const std::list<perm_string> &dst_list,
char polarity, bool full_flag);
~PSpecPath();
~PSpecPath() override;
void elaborate(class Design*des, class NetScope*scope) const;
+17 -17
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PTask_H
#define IVL_PTask_H
/*
* Copyright (c) 1999-2021 Stephen Williams ([email protected])
* Copyright (c) 1999-2025 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -39,9 +39,9 @@ class PTaskFunc : public PScope, public PNamedItem {
public:
PTaskFunc(perm_string name, LexicalScope*parent);
~PTaskFunc();
~PTaskFunc() override;
bool var_init_needs_explicit_lifetime() const;
bool var_init_needs_explicit_lifetime() const override;
void set_ports(std::vector<pform_tf_port_t>*p);
@@ -80,7 +80,7 @@ class PTask : public PTaskFunc {
public:
explicit PTask(perm_string name, LexicalScope*parent, bool is_auto);
~PTask();
~PTask() override;
void set_statement(Statement *s);
@@ -91,16 +91,16 @@ class PTask : public PTaskFunc {
void elaborate_scope(Design*des, NetScope*scope) const;
// Bind the ports to the regs that are the ports.
void elaborate_sig(Design*des, NetScope*scope) const;
void elaborate_sig(Design*des, NetScope*scope) const override;
// Elaborate the statement to finish off the task definition.
void elaborate(Design*des, NetScope*scope) const;
void elaborate(Design*des, NetScope*scope) const override;
bool is_auto() const { return is_auto_; };
void dump(std::ostream&, unsigned) const;
void dump(std::ostream&, unsigned) const override;
SymbolType symbol_type() const;
SymbolType symbol_type() const override;
private:
Statement*statement_;
@@ -122,7 +122,7 @@ class PFunction : public PTaskFunc {
public:
explicit PFunction(perm_string name, LexicalScope*parent, bool is_auto);
~PFunction();
~PFunction() override;
void set_statement(Statement *s);
void set_return(data_type_t*t);
@@ -142,16 +142,16 @@ class PFunction : public PTaskFunc {
void elaborate_scope(Design*des, NetScope*scope) const;
/* elaborate the ports and return value. */
void elaborate_sig(Design *des, NetScope*) const;
void elaborate_sig(Design *des, NetScope*) const override;
/* Elaborate the behavioral statement. */
void elaborate(Design *des, NetScope*) const;
void elaborate(Design *des, NetScope*) const override;
bool is_auto() const { return is_auto_; };
void dump(std::ostream&, unsigned) const;
void dump(std::ostream&, unsigned) const override;
SymbolType symbol_type() const;
SymbolType symbol_type() const override;
private:
data_type_t* return_type_;
@@ -174,12 +174,12 @@ class PLet : public PTaskFunc {
// FIXME: Should the port list be a vector. Check once implemented completely
explicit PLet(perm_string name, LexicalScope*parent,
std::list<let_port_t*>*ports, PExpr*expr);
~PLet();
~PLet() override;
void elaborate_sig(Design*des, NetScope*scope) const { (void)des; (void)scope; }
void elaborate(Design*des, NetScope*scope) const { (void)des; (void)scope; }
void elaborate_sig(Design*des, NetScope*scope) const override { (void)des; (void)scope; }
void elaborate(Design*des, NetScope*scope) const override { (void)des; (void)scope; }
void dump(std::ostream&, unsigned) const;
void dump(std::ostream&, unsigned) const override;
private:
std::list<let_port_t*>*ports_;
+4 -4
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PTimingCheck_H
#define IVL_PTimingCheck_H
/*
* Copyright (c) 2006-2023 Stephen Williams <[email protected]>
* Copyright (c) 2006-2025 Stephen Williams <[email protected]>
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -52,7 +52,7 @@ class PTimingCheck : public LineInfo {
};
PTimingCheck() { }
virtual ~PTimingCheck() { }
virtual ~PTimingCheck() override { }
virtual void elaborate(class Design*des, class NetScope*scope) const = 0;
@@ -76,7 +76,7 @@ class PRecRem : public PTimingCheck {
pform_name_t* delayed_reference,
pform_name_t* delayed_data);
~PRecRem();
~PRecRem() override;
void elaborate(class Design*des, class NetScope*scope) const override;
@@ -114,7 +114,7 @@ class PSetupHold : public PTimingCheck {
pform_name_t* delayed_reference,
pform_name_t* delayed_data);
~PSetupHold();
~PSetupHold() override;
void elaborate(class Design*des, class NetScope*scope) const override;
+3 -1
View File
@@ -29,10 +29,12 @@ PWire::PWire(perm_string n,
NetNet::Type t,
NetNet::PortType pt,
PWSRType rt)
: name_(n), lexical_pos_(lp), type_(t), port_type_(pt), signed_(false),
: name_(n), type_(t), port_type_(pt), signed_(false),
port_set_(false), net_set_(false), is_scalar_(false),
error_cnt_(0), discipline_(0)
{
lexical_pos(lp);
switch (rt) {
case SR_PORT:
port_set_ = true;
+2 -5
View File
@@ -1,7 +1,7 @@
#ifndef IVL_PWire_H
#define IVL_PWire_H
/*
* Copyright (c) 1998-2024 Stephen Williams ([email protected])
* Copyright (c) 1998-2025 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -63,8 +63,6 @@ class PWire : public PNamedItem {
// Return a hierarchical name.
perm_string basename() const;
unsigned lexical_pos() const { return lexical_pos_; }
NetNet::Type get_wire_type() const;
bool set_wire_type(NetNet::Type);
@@ -93,7 +91,7 @@ class PWire : public PNamedItem {
NetNet* elaborate_sig(Design*, NetScope*scope);
SymbolType symbol_type() const;
SymbolType symbol_type() const override;
bool is_net() const { return net_set_; };
bool is_port() const { return port_set_; };
@@ -102,7 +100,6 @@ class PWire : public PNamedItem {
private:
perm_string name_;
unsigned lexical_pos_;
NetNet::Type type_;
NetNet::PortType port_type_;
bool signed_;
+18 -154
View File
@@ -1,6 +1,6 @@
# The ICARUS Verilog Compilation System
Copyright 2000-2019 Stephen Williams
Copyright 2000-2026 Stephen Williams
<details>
<summary><h2>Table of Contents</h2></summary>
@@ -35,10 +35,11 @@ Copyright 2000-2019 Stephen Williams
## What is ICARUS Verilog?
Icarus Verilog is intended to compile ALL of the Verilog HDL, as
described in the IEEE-1364 standard. Of course, it's not quite there
yet. It does currently handle a mix of structural and behavioural
constructs. For a view of the current state of Icarus Verilog, see its
home page at https://steveicarus.github.io/iverilog/.
described in the IEEE 1364 standard. Of course, it's not quite there
yet. It also compiles a (slowly growing) subset of the SystemVerilog
language, as described in the IEEE 1800 standard. For a view of the
current state of Icarus Verilog, see its home page at
https://steveicarus.github.io/iverilog/.
Icarus Verilog is not aimed at being a simulator in the traditional
sense, but a compiler that generates code employed by back-end
@@ -55,8 +56,6 @@ system and C/C++ compilation should be able to build the source
distribution with little effort. Some actual programming skills are
not required, but helpful in case of problems.
> If you are building on Windows, see the mingw.txt file.
### Compile Time Prerequisites
You can use:
@@ -83,7 +82,7 @@ on a UNIX-like system:
OSX note: bison 2.3 shipped with MacOS including Catalina generates
broken code, but bison 3+ works. We recommend using the Fink
project version of bison and flex (finkproject.org), brew version
works fine either.
works fine too.
- gperf 3.0 or later
The lexical analyzer doesn't recognize keywords directly,
@@ -392,161 +391,26 @@ Verilog web page for the current state of support for Verilog, and in
particular, browse the bug report database for reported unsupported
constructs.
- System functions are supported, but the return value is a little
tricky. See SYSTEM FUNCTION TABLE FILES in the iverilog man page.
- Specify blocks are parsed but ignored in general.
- Specify blocks are parsed but ignored by default. When enabled
by the `-gspecify` compiler option, a subset of specify block
constructs are supported.
- `trireg` is not supported. `tri0` and `tri1` are supported.
- tran primitives, i.e. `tran`, `tranif1`, `tranif0`, `rtran`, `rtranif1`,
and `rtranif0` are not supported.
- Net delays, of the form `wire #N foo;` do not work. Delays in
every other context do work properly, including the V2001 form
`wire #5 foo = bar;`
- Event controls inside non-blocking assignments are not supported.
i.e.: `a <= @(posedge clk) b;`
The list of unsupported SystemVerilog constructs is too large to
enumerate here.
- Macro arguments are not supported. `` `define `` macros are supported,
but they cannot take arguments.
## Nonstandard Constructs or Behaviors
Icarus Verilog includes some features that are not part of the
IEEE1364 standard, but have well-defined meaning, and also sometimes
gives nonstandard (but extended) meanings to some features of the
language that are defined. See the "extensions.txt" documentation for
more details.
* `$is_signed(<expr>)`
This system function returns 1 if the expression contained is
signed, or 0 otherwise. This is mostly of use for compiler
regression tests.
* `$sizeof(<expr>)`, `$bits(<expr>)`
The `$bits` system function returns the size in bits of the
expression that is its argument. The result of this
function is undefined if the argument doesn't have a
self-determined size.
The `$sizeof` function is deprecated in favour of `$bits`, which is
the same thing, but included in the SystemVerilog definition.
* `$simtime`
The `$simtime` system function returns as a 64bit value the
simulation time, unscaled by the time units of local
scope. This is different from the $time and $stime functions
which return the scaled times. This function is added for
regression testing of the compiler and run time, but can be
used by applications who really want the simulation time.
Note that the simulation time can be confusing if there are
lots of different `` `timescales`` within a design. It is not in
general possible to predict what the simulation precision will
turn out to be.
* `$mti_random()`, `$mti_dist_uniform`
These functions are similar to the IEEE1364 standard $random
functions, but they use the Mersenne Twister (MT19937)
algorithm. This is considered an excellent random number
generator, but does not generate the same sequence as the
standardized $random.
### Builtin system functions
Certain of the system functions have well-defined meanings, so
can theoretically be evaluated at compile-time, instead of
using runtime VPI code. Doing so means that VPI cannot
override the definitions of functions handled in this
manner. On the other hand, this makes them synthesizable, and
also allows for more aggressive constant propagation. The
functions handled in this manner are:
* `$bits`
* `$signed`
* `$sizeof`
* `$unsigned`
Implementations of these system functions in VPI modules will be ignored.
### Preprocessing Library Modules
Icarus Verilog does preprocess modules that are loaded from
libraries via the -y mechanism. However, the only macros
defined during the compilation of that file are those that it
defines itself (or includes) or that are defined in the
command line or command file.
Specifically, macros defined in the non-library source files
are not remembered when the library module is loaded. This is
intentional. If it were otherwise, then compilation results
might vary depending on the order that libraries are loaded,
and that is too unpredictable.
It is said that some commercial compilers do allow macro
definitions to span library modules. That's just plain weird.
### Width in `%t` Time Formats
Standard Verilog does not allow width fields in the %t formats
of display strings. For example, this is illegal:
```
$display("Time is %0t", $time);
```
Standard Verilog instead relies on the $timeformat to
completely specify the format.
Icarus Verilog allows the programmer to specify the field
width. The `%t` format in Icarus Verilog works exactly as it
does in standard Verilog. However, if the programmer chooses
to specify a minimum width (i.e., `%5t`), then for that display
Icarus Verilog will override the `$timeformat` minimum width and
use the explicit minimum width.
### vpiScope Iterator on vpiScope Objects
In the VPI, the normal way to iterate over vpiScope objects
contained within a vpiScope object, is the vpiInternalScope
iterator. Icarus Verilog adds support for the vpiScope
iterator of a vpiScope object, that iterates over *everything*
the is contained in the current scope. This is useful in cases
where one wants to iterate over all the objects in a scope
without iterating over all the contained types explicitly.
### Time 0 Race Resolution
Combinational logic is routinely modelled using always
blocks. However, this can lead to race conditions if the
inputs to the combinational block are initialized in initial
statements. Icarus Verilog slightly modifies time 0 scheduling
by arranging for always statements with ANYEDGE sensitivity
lists to be scheduled before any other threads. This causes
combinational always blocks to be triggered when the values in
the sensitivity list are initialized by initial threads.
### Nets with Types
Icarus Verilog supports an extended syntax that allows nets
and regs to be explicitly typed. The currently supported types
are logic, bool and real. This implies that `logic` and `bool`
are new keywords. Typical syntax is:
```verilog
wire real foo = 1.0;
reg logic bar, bat;
```
... and so forth. The syntax can be turned off by using the
`-g2` flag to iverilog, and turned on explicitly with the `-g2x`
flag to iverilog.
## Nonstandard Constructs and Behaviors
Icarus Verilog includes some features that are not part of the IEEE 1364
standard, but have well-defined meaning, and also sometimes gives nonstandard
(but extended) meanings to some features of the language that are defined.
See the "Icarus Verilog Extensions" and "Icarus Verilog Quirks" sections at
https://steveicarus.github.io/iverilog/ for more details.
## Credits
+4 -4
View File
@@ -396,8 +396,8 @@ PReturn::~PReturn()
delete expr_;
}
PTrigger::PTrigger(PPackage*pkg, const pform_name_t&ev, unsigned lexical_pos)
: event_(pkg, ev), lexical_pos_(lexical_pos)
PTrigger::PTrigger(PPackage*pkg, const pform_name_t&ev)
: event_(pkg, ev)
{
}
@@ -405,8 +405,8 @@ PTrigger::~PTrigger()
{
}
PNBTrigger::PNBTrigger(const pform_name_t&ev, unsigned lexical_pos, PExpr*dly)
: event_(ev), lexical_pos_(lexical_pos), dly_(dly)
PNBTrigger::PNBTrigger(const pform_name_t&ev, PExpr*dly)
: event_(ev), dly_(dly)
{
}
+174 -110
View File
@@ -1,7 +1,7 @@
#ifndef IVL_Statement_H
#define IVL_Statement_H
/*
* Copyright (c) 1998-2024 Stephen Williams ([email protected])
* Copyright (c) 1998-2026 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -40,6 +40,8 @@ class NetCAssign;
class NetDeassign;
class NetForce;
class NetScope;
class NetNet;
class netdarray_t;
/*
* The PProcess is the root of a behavioral process. Each process gets
@@ -53,7 +55,10 @@ class PProcess : public LineInfo {
PProcess(ivl_process_type_t t, Statement*st)
: type_(t), statement_(st) { }
virtual ~PProcess();
virtual ~PProcess() override;
PProcess(const PProcess&) = delete;
PProcess& operator=(const PProcess&) = delete;
bool elaborate(Design*des, NetScope*scope) const;
@@ -78,7 +83,7 @@ class Statement : virtual public LineInfo {
public:
Statement() { }
virtual ~Statement() =0;
virtual ~Statement() override =0;
virtual void dump(std::ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
@@ -99,7 +104,10 @@ class PAssign_ : public Statement {
bool is_init = false);
explicit PAssign_(PExpr*lval, PExpr*de, PExpr*ex);
explicit PAssign_(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
virtual ~PAssign_() =0;
virtual ~PAssign_() override =0;
PAssign_(const PAssign_&) = delete;
PAssign_& operator=(const PAssign_&) = delete;
const PExpr* lval() const { return lval_; }
PExpr* rval() const { return rval_; }
@@ -139,10 +147,10 @@ class PAssign : public PAssign_ {
explicit PAssign(PExpr*lval, PExpr*de, PExpr*ex);
explicit PAssign(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
explicit PAssign(PExpr*lval, PExpr*ex, bool is_constant, bool is_init);
~PAssign();
~PAssign() override;
virtual void dump(std::ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const override;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
private:
NetProc* elaborate_compressed_(Design*des, NetScope*scope) const;
@@ -155,10 +163,10 @@ class PAssignNB : public PAssign_ {
explicit PAssignNB(PExpr*lval, PExpr*ex);
explicit PAssignNB(PExpr*lval, PExpr*de, PExpr*ex);
explicit PAssignNB(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex);
~PAssignNB();
~PAssignNB() override;
virtual void dump(std::ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const override;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
private:
NetProc*assign_to_memory_(class NetMemory*, PExpr*,
@@ -181,11 +189,11 @@ class PBlock : public PScope, public Statement, public PNamedItem {
explicit PBlock(perm_string n, LexicalScope*parent, BL_TYPE t);
// If it doesn't have a name, it's not a scope
explicit PBlock(BL_TYPE t);
~PBlock();
~PBlock() override;
BL_TYPE bl_type() const { return bl_type_; }
bool var_init_needs_explicit_lifetime() const;
bool var_init_needs_explicit_lifetime() const override;
// This is only used if this block is the statement list for a
// constructor. We look for a PChainConstructor as the first
@@ -202,12 +210,12 @@ class PBlock : public PScope, public Statement, public PNamedItem {
// block.
void push_statement_front(Statement*that);
virtual void dump(std::ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const override;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
SymbolType symbol_type() const;
SymbolType symbol_type() const override;
private:
BL_TYPE bl_type_;
@@ -216,8 +224,8 @@ class PBlock : public PScope, public Statement, public PNamedItem {
class PBreak : public Statement {
public:
void dump(std::ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
void dump(std::ostream&out, unsigned ind) const override;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
};
class PCallTask : public Statement {
@@ -226,12 +234,12 @@ class PCallTask : public Statement {
explicit PCallTask(PPackage *pkg, const pform_name_t &n, const std::list<named_pexpr_t> &parms);
explicit PCallTask(const pform_name_t &n, const std::list<named_pexpr_t> &parms);
explicit PCallTask(perm_string n, const std::list<named_pexpr_t> &parms);
~PCallTask();
~PCallTask() override;
const pform_name_t& path() const;
virtual void dump(std::ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const override;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
bool elaborate_elab(Design*des, NetScope*scope) const;
@@ -243,10 +251,12 @@ class PCallTask : public Statement {
NetProc*elaborate_method_(Design*des, NetScope*scope,
bool add_this_flag = false) const;
NetProc*elaborate_function_(Design*des, NetScope*scope) const;
NetProc *elaborate_function_(
Design *des, NetScope *scope, NetScope *func_scope) const;
NetProc*elaborate_void_function_(Design*des, NetScope*scope,
NetFuncDef*def) const;
NetProc *elaborate_non_void_function_(Design *des, NetScope *scope) const;
NetProc *elaborate_non_void_function_(Design *des, NetScope *scope,
const pform_name_t &path) const;
NetProc*elaborate_build_call_(Design*des, NetScope*scope,
NetScope*task, NetExpr*use_this) const;
@@ -255,17 +265,43 @@ class PCallTask : public Statement {
perm_string method_name,
const char *sys_task_name,
const std::vector<perm_string> &parm_names = {}) const;
NetProc*elaborate_sys_task_property_method_(Design*des, NetScope*scope,
NetNet*net, int property_idx,
perm_string method_name,
const char *sys_task_name,
const std::vector<perm_string> &parm_names = {}) const;
NetProc*elaborate_queue_method_(Design*des, NetScope*scope,
NetNet*net,
perm_string method_name,
const char *sys_task_name,
const std::vector<perm_string> &parm_names) const;
NetProc*elaborate_queue_property_method_(Design*des, NetScope*scope,
NetNet*net, int property_idx,
perm_string method_name,
const char *sys_task_name,
const std::vector<perm_string> &parm_names) const;
NetProc*elaborate_method_func_(NetScope*scope,
NetNet*net,
ivl_type_t type,
perm_string method_name,
const char*sys_task_name) const;
bool test_task_calls_ok_(Design*des, NetScope*scope) const;
NetProc*elaborate_method_property_func_(NetScope*scope,
NetNet*net, int property_idx,
ivl_type_t type,
perm_string method_name,
const char*sys_task_name) const;
NetProc*elaborate_queue_method_expr_(Design*des, NetScope*scope,
NetExpr*queue_base,
const netdarray_t*use_darray,
perm_string method_name,
const char *sys_task_name,
const std::vector<perm_string> &parm_names) const;
NetProc*elaborate_method_func_expr_(NetScope*scope,
NetExpr*queue_base,
ivl_type_t type,
perm_string method_name,
const char*sys_task_name) const;
bool test_task_calls_ok_(Design*des, const NetScope*scope) const;
PPackage*package_;
pform_name_t path_;
@@ -282,12 +318,12 @@ class PCase : public Statement {
};
PCase(ivl_case_quality_t, NetCase::TYPE, PExpr*ex, std::vector<Item*>*);
~PCase();
~PCase() override;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
virtual void dump(std::ostream&out, unsigned ind) const override;
private:
ivl_case_quality_t quality_;
@@ -305,10 +341,13 @@ class PCAssign : public Statement {
public:
explicit PCAssign(PExpr*l, PExpr*r);
~PCAssign();
~PCAssign() override;
virtual NetCAssign* elaborate(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const;
PCAssign(const PCAssign&) = delete;
PCAssign& operator=(const PCAssign&) = delete;
virtual NetCAssign* elaborate(Design*des, NetScope*scope) const override;
virtual void dump(std::ostream&out, unsigned ind) const override;
private:
PExpr*lval_;
@@ -324,10 +363,10 @@ class PChainConstructor : public Statement {
public:
explicit PChainConstructor(const std::list<named_pexpr_t> &parms);
explicit PChainConstructor(const std::vector<named_pexpr_t> &parms);
~PChainConstructor();
~PChainConstructor() override;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
virtual void dump(std::ostream&out, unsigned ind) const override;
inline const std::vector<named_pexpr_t>& chain_args(void) const
{ return parms_; }
@@ -340,12 +379,12 @@ class PCondit : public Statement {
public:
PCondit(PExpr*ex, Statement*i, Statement*e);
~PCondit();
~PCondit() override;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
virtual void dump(std::ostream&out, unsigned ind) const override;
private:
PExpr*expr_;
@@ -360,18 +399,21 @@ class PCondit : public Statement {
class PContinue : public Statement {
public:
virtual void dump(std::ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const override;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
};
class PDeassign : public Statement {
public:
explicit PDeassign(PExpr*l);
~PDeassign();
~PDeassign() override;
virtual NetDeassign* elaborate(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const;
PDeassign(const PDeassign&) = delete;
PDeassign& operator=(const PDeassign&) = delete;
virtual NetDeassign* elaborate(Design*des, NetScope*scope) const override;
virtual void dump(std::ostream&out, unsigned ind) const override;
private:
PExpr*lval_;
@@ -381,12 +423,12 @@ class PDelayStatement : public Statement {
public:
PDelayStatement(PExpr*d, Statement*st);
~PDelayStatement();
~PDelayStatement() override;
virtual void dump(std::ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const override;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
private:
PExpr*delay_;
@@ -401,10 +443,10 @@ class PDisable : public Statement {
public:
explicit PDisable(const pform_name_t&sc);
~PDisable();
~PDisable() override;
virtual void dump(std::ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const override;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
private:
pform_name_t scope_;
@@ -414,12 +456,15 @@ class PDoWhile : public Statement {
public:
PDoWhile(PExpr*ex, Statement*st);
~PDoWhile();
~PDoWhile() override;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const;
PDoWhile(const PDoWhile&) = delete;
PDoWhile& operator=(const PDoWhile&) = delete;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
virtual void dump(std::ostream&out, unsigned ind) const override;
private:
PExpr*cond_;
@@ -444,17 +489,17 @@ class PEventStatement : public Statement {
// from functions added and outputs removed for always_comb/latch.
explicit PEventStatement(bool always_sens = false);
~PEventStatement();
~PEventStatement() override;
void set_statement(Statement*st);
virtual void dump(std::ostream&out, unsigned ind) const;
virtual void dump(std::ostream&out, unsigned ind) const override;
// Call this with a NULL statement only. It is used to print
// the event expression for inter-assignment event controls.
virtual void dump_inline(std::ostream&out) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
bool has_aa_term(Design*des, NetScope*scope);
@@ -463,7 +508,7 @@ class PEventStatement : public Statement {
NetProc* elaborate_st(Design*des, NetScope*scope, NetProc*st) const;
NetProc* elaborate_wait(Design*des, NetScope*scope, NetProc*st) const;
NetProc* elaborate_wait_fork(Design*des, NetScope*scope) const;
NetProc* elaborate_wait_fork(Design*des, const NetScope*scope) const;
private:
std::vector<PEEvent*>expr_;
@@ -477,10 +522,13 @@ class PForce : public Statement {
public:
explicit PForce(PExpr*l, PExpr*r);
~PForce();
~PForce() override;
virtual NetForce* elaborate(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const;
PForce(const PForce&) = delete;
PForce& operator=(const PForce&) = delete;
virtual NetForce* elaborate(Design*des, NetScope*scope) const override;
virtual void dump(std::ostream&out, unsigned ind) const override;
private:
PExpr*lval_;
@@ -490,12 +538,15 @@ class PForce : public Statement {
class PForeach : public Statement {
public:
explicit PForeach(perm_string var, const std::list<perm_string>&ix, Statement*stmt);
~PForeach();
~PForeach() override;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const;
PForeach(const PForeach&) = delete;
PForeach& operator=(const PForeach&) = delete;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
virtual void dump(std::ostream&out, unsigned ind) const override;
private:
NetProc* elaborate_static_array_(Design*des, NetScope*scope,
@@ -510,12 +561,15 @@ class PForeach : public Statement {
class PForever : public Statement {
public:
explicit PForever(Statement*s);
~PForever();
~PForever() override;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const;
PForever(const PForever&) = delete;
PForever& operator=(const PForever&) = delete;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
virtual void dump(std::ostream&out, unsigned ind) const override;
private:
Statement*statement_;
@@ -526,12 +580,12 @@ class PForStatement : public Statement {
public:
PForStatement(PExpr*n1, PExpr*e1, PExpr*cond,
Statement*step, Statement*body);
~PForStatement();
~PForStatement() override;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
virtual void dump(std::ostream&out, unsigned ind) const override;
private:
PExpr* name1_;
@@ -548,18 +602,21 @@ class PNoop : public Statement {
public:
PNoop() { }
~PNoop() { }
~PNoop() override { }
};
class PRepeat : public Statement {
public:
explicit PRepeat(PExpr*expr, Statement*s);
~PRepeat();
~PRepeat() override;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const;
PRepeat(const PRepeat&) = delete;
PRepeat& operator=(const PRepeat&) = delete;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
virtual void dump(std::ostream&out, unsigned ind) const override;
private:
PExpr*expr_;
@@ -570,10 +627,13 @@ class PRelease : public Statement {
public:
explicit PRelease(PExpr*l);
~PRelease();
~PRelease() override;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const;
PRelease(const PRelease&) = delete;
PRelease& operator=(const PRelease&) = delete;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
virtual void dump(std::ostream&out, unsigned ind) const override;
private:
PExpr*lval_;
@@ -583,10 +643,13 @@ class PReturn : public Statement {
public:
explicit PReturn(PExpr*e);
~PReturn();
~PReturn() override;
NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const;
PReturn(const PReturn&) = delete;
PReturn& operator=(const PReturn&) = delete;
NetProc* elaborate(Design*des, NetScope*scope) const override;
virtual void dump(std::ostream&out, unsigned ind) const override;
private:
PExpr*expr_;
@@ -599,28 +662,26 @@ class PReturn : public Statement {
class PTrigger : public Statement {
public:
explicit PTrigger(PPackage*pkg, const pform_name_t&ev, unsigned lexical_pos);
~PTrigger();
explicit PTrigger(PPackage*pkg, const pform_name_t&ev);
~PTrigger() override;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
virtual void dump(std::ostream&out, unsigned ind) const override;
private:
pform_scoped_name_t event_;
unsigned lexical_pos_;
};
class PNBTrigger : public Statement {
public:
explicit PNBTrigger(const pform_name_t&ev, unsigned lexical_pos, PExpr*dly);
~PNBTrigger();
explicit PNBTrigger(const pform_name_t&ev, PExpr*dly);
~PNBTrigger() override;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
virtual void dump(std::ostream&out, unsigned ind) const override;
private:
pform_name_t event_;
unsigned lexical_pos_;
PExpr*dly_;
};
@@ -628,12 +689,15 @@ class PWhile : public Statement {
public:
PWhile(PExpr*ex, Statement*st);
~PWhile();
~PWhile() override;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
virtual void elaborate_sig(Design*des, NetScope*scope) const;
virtual void dump(std::ostream&out, unsigned ind) const;
PWhile(const PWhile&) = delete;
PWhile& operator=(const PWhile&) = delete;
virtual NetProc* elaborate(Design*des, NetScope*scope) const override;
virtual void elaborate_scope(Design*des, NetScope*scope) const override;
virtual void elaborate_sig(Design*des, NetScope*scope) const override;
virtual void dump(std::ostream&out, unsigned ind) const override;
private:
PExpr*cond_;
Vendored
+23 -386
View File
@@ -1,390 +1,27 @@
# generated automatically by aclocal 1.18.1 -*- Autoconf -*-
# AX_ENABLE_SUFFIX
# ----------------
# Create the configure option --enable-suffix[=suffix] to generate suffix
# strings for the installed commands. This allows for shared installs of
# different builds. Remember to change the default suffix string to some
# value appropriate for the current version.
AC_DEFUN([AX_ENABLE_SUFFIX],
[AC_ARG_ENABLE([suffix],[AS_HELP_STRING([--enable-suffix],
[Use/set the installation command suffix])],
[true],[enable_suffix=no])
if test X$enable_suffix = Xyes; then
install_suffix='-0.10'
elif test X$enable_suffix = Xno; then
install_suffix=''
else
install_suffix="$enable_suffix"
fi
AC_SUBST(install_suffix)
])# AX_ENABLE_SUFFIX
# Copyright (C) 1996-2025 Free Software Foundation, Inc.
# _AX_C_UNDERSCORES_MATCH_IFELSE(PATTERN, ACTION-IF-MATCH, ACTION-IF-NOMATCH)
# ------------------------------
# Sub-macro for AX_C_UNDERSCORES_LEADING and AX_C_UNDERSCORES_TRAILING.
# Unwarranted assumptions:
# - the object file produced by AC_COMPILE_IFELSE is called
# "conftest.$ac_objext"
# - the nm(1) utility or an equivalent is available, and its name
# is defined by the $NM variable.
AC_DEFUN([_AX_C_UNDERSCORES_MATCH_IF],
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([void underscore(void){}])],
[AS_IF([$NM conftest.$ac_objext|grep $1 >/dev/null 2>/dev/null],[$2],[$3])],
[AC_MSG_ERROR([underscore test crashed])]
)])
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
# AX_C_UNDERSCORES_LEADING
# ---------------------------------
# Check if symbol names in object files produced by C compiler have
# leading underscores. Define NEED_LU if so.
AC_DEFUN([AX_C_UNDERSCORES_LEADING],
[AC_CACHE_CHECK([for leading underscores], ax_cv_c_underscores_leading,
[_AX_C_UNDERSCORES_MATCH_IF([_underscore],
[AS_VAR_SET(ax_cv_c_underscores_leading, yes)],
[AS_VAR_SET(ax_cv_c_underscores_leading, no)])])
if test $ax_cv_c_underscores_leading = yes -a "$CYGWIN" != "yes" -a "$MINGW32" != "yes"; then
AC_DEFINE([NEED_LU], [1], [Symbol names in object files produced by C compiler have leading underscores.])
fi
])# AX_C_UNDERSCORES_LEADING
# AX_C_UNDERSCORES_TRAILING
# ---------------------------------
# Check if symbol names in object files produced by C compiler have
# trailing underscores. Define NEED_TU if so.
AC_DEFUN([AX_C_UNDERSCORES_TRAILING],
[AC_CACHE_CHECK([for trailing underscores], ax_cv_c_underscores_trailing,
[_AX_C_UNDERSCORES_MATCH_IF([underscore_],
[AS_VAR_SET(ax_cv_c_underscores_trailing, yes)],
[AS_VAR_SET(ax_cv_c_underscores_trailing, no)])])
if test $ax_cv_c_underscores_trailing = yes; then
AC_DEFINE([NEED_TU], [1], [Symbol names in object files produced by C compiler have trailing underscores.])
fi
])# AX_C_UNDERSCORES_TRAILING
# AX_WIN32
# --------
# Combined check for several flavors of Microsoft Windows so
# their "issues" can be dealt with
AC_DEFUN([AX_WIN32],
[AC_MSG_CHECKING([for Microsoft Windows])
AC_REQUIRE([AC_CANONICAL_HOST]) []dnl
case $host_os in
*cygwin*) MINGW32=no; WIN32=yes;;
*mingw*) MINGW32=yes; WIN32=yes;;
*) MINGW32=no; WIN32=no;;
esac
AC_SUBST(MINGW32)
AC_SUBST(WIN32)
AC_MSG_RESULT($WIN32)
if test $WIN32 = yes; then
AC_MSG_CHECKING([for MinGW])
AC_MSG_RESULT($MINGW32)
fi
])# AX_WIN32
# AX_LD_EXTRALIBS
# ---------------
# mingw needs to link with libiberty.a, but cygwin alone can't tolerate it
AC_DEFUN([AX_LD_EXTRALIBS],
[AC_MSG_CHECKING([for extra libs needed])
EXTRALIBS=
case "${host}" in
*-*-cygwin* )
if test "$MINGW32" = "yes"; then
EXTRALIBS="-liberty"
fi
;;
esac
AC_SUBST(EXTRALIBS)
AC_MSG_RESULT($EXTRALIBS)
])# AX_LD_EXTRALIBS
# AX_LD_SHAREDLIB_OPTS
# --------------------
# linker options when building a shared library
AC_DEFUN([AX_LD_SHAREDLIB_OPTS],
[AC_MSG_CHECKING([for shared library link flag])
shared=-shared
case "${host}" in
*-*-cygwin*)
shared="-shared -Wl,--enable-auto-image-base"
;;
*-*-mingw*)
shared="-shared -Wl,--enable-auto-image-base"
;;
*-*-hpux*)
shared="-b"
;;
*-*-darwin1.[0123])
shared="-bundle -undefined dynamic_lookup"
;;
*-*-darwin*)
shared="-bundle -undefined dynamic_lookup -flat_namespace"
;;
*-*-solaris*)
if test ${using_sunpro_c} = 1
then
shared="-G"
fi
;;
esac
AC_SUBST(shared)
AC_MSG_RESULT($shared)
])# AX_LD_SHAREDLIB_OPTS
# AX_C_PICFLAG
# ------------
# The -fPIC flag is used to tell the compiler to make position
# independent code. It is needed when making shared objects.
AC_DEFUN([AX_C_PICFLAG],
[AC_MSG_CHECKING([for flag to make position independent code])
PICFLAG=-fPIC
case "${host}" in
*-*-cygwin*)
PICFLAG=
;;
*-*-mingw*)
PICFLAG=
;;
*-*-hpux*)
PICFLAG=+z
;;
*-*-solaris*)
if test ${using_sunpro_c} = 1
then
PICFLAG=-G
fi
;;
esac
AC_SUBST(PICFLAG)
AC_MSG_RESULT($PICFLAG)
])# AX_C_PICFLAG
# AX_LD_RDYNAMIC
# --------------
# The -rdynamic flag is used by iverilog when compiling the target,
# to know how to export symbols of the main program to loadable modules
# that are brought in by -ldl
AC_DEFUN([AX_LD_RDYNAMIC],
[AC_MSG_CHECKING([for -rdynamic compiler flag])
rdynamic=-rdynamic
case "${host}" in
*-*-netbsd*)
rdynamic="-Wl,--export-dynamic"
;;
*-*-openbsd*)
rdynamic="-Wl,--export-dynamic"
;;
*-*-solaris*)
rdynamic=""
;;
*-*-cygwin*)
rdynamic=""
;;
*-*-mingw*)
rdynamic=""
;;
*-*-hpux*)
rdynamic="-E"
;;
*-*-darwin*)
rdynamic="-Wl,-all_load"
strip_dynamic="-SX"
;;
esac
AC_SUBST(rdynamic)
AC_MSG_RESULT($rdynamic)
AC_SUBST(strip_dynamic)
# since we didn't tell them we're "checking", no good place to tell the answer
# AC_MSG_RESULT($strip_dynamic)
])# AX_LD_RDYNAMIC
# AX_C99_STRTOD
# -------------
AC_DEFUN([AX_C99_STRTOD],
[# On MinGW we need to jump through hoops to get a C99 compliant strtod().
# mingw-w64 doesn't need this, and the 64-bit version doesn't support it.
case "${host}" in
x86_64-w64-mingw32)
;;
*-*-mingw32)
LDFLAGS+=" -Wl,--undefined=___strtod,--wrap,strtod,--defsym,___wrap_strtod=___strtod"
;;
esac
])# AX_C99_STRTOD
# When config.status generates a header, we must update the stamp-h file.
# This file resides in the same directory as the config header
# that is generated. The stamp file name are based on the header name.
# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
# loop where config.status creates the headers, so we can generate
# our stamp files there.
AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
[
_config_header=$1
_stamp_name=stamp-`expr //$_config_header : '.*/\([[^./]]*\)\.[[^./]]*$'`-h
echo "timestamp for $_config_header" > `AS_DIRNAME(["$_config_header"])`/[]$_stamp_name
]) #_AC_AM_CONFIG_HEADER_HOOK
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_PROG_CC_FOR_BUILD
#
# DESCRIPTION
#
# This macro searches for a C compiler that generates native executables,
# that is a C compiler that surely is not a cross-compiler. This can be
# useful if you have to generate source code at compile-time like for
# example GCC does.
#
# The macro sets the CC_FOR_BUILD and CPP_FOR_BUILD macros to anything
# needed to compile or link (CC_FOR_BUILD) and preprocess (CPP_FOR_BUILD).
# The value of these variables can be overridden by the user by specifying
# a compiler with an environment variable (like you do for standard CC).
#
# It also sets BUILD_EXEEXT and BUILD_OBJEXT to the executable and object
# file extensions for the build platform, and GCC_FOR_BUILD to `yes' if
# the compiler we found is GCC. All these variables but GCC_FOR_BUILD are
# substituted in the Makefile.
#
# LICENSE
#
# Copyright (c) 2008 Paolo Bonzini <[email protected]>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 18
AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD])
AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl
AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([AC_PROG_CPP])dnl
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
dnl Use the standard macros, but make them use other variable names
dnl
pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl
pushdef([ac_cv_prog_cc_c89], ac_cv_build_prog_cc_c89)dnl
pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl
pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl
pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl
pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl
pushdef([ac_cv_c_compiler_gnu], ac_cv_build_c_compiler_gnu)dnl
pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl
pushdef([ac_cv_objext], ac_cv_build_objext)dnl
pushdef([ac_exeext], ac_build_exeext)dnl
pushdef([ac_objext], ac_build_objext)dnl
pushdef([CC], CC_FOR_BUILD)dnl
pushdef([CPP], CPP_FOR_BUILD)dnl
pushdef([GCC], GCC_FOR_BUILD)dnl
pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl
pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl
pushdef([EXEEXT], BUILD_EXEEXT)dnl
pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl
pushdef([OBJEXT], BUILD_OBJEXT)dnl
pushdef([host], build)dnl
pushdef([host_alias], build_alias)dnl
pushdef([host_cpu], build_cpu)dnl
pushdef([host_vendor], build_vendor)dnl
pushdef([host_os], build_os)dnl
pushdef([ac_cv_host], ac_cv_build)dnl
pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl
pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl
pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl
pushdef([ac_cv_host_os], ac_cv_build_os)dnl
pushdef([ac_tool_prefix], ac_build_tool_prefix)dnl
pushdef([am_cv_CC_dependencies_compiler_type], am_cv_build_CC_dependencies_compiler_type)dnl
pushdef([am_cv_prog_cc_c_o], am_cv_build_prog_cc_c_o)dnl
pushdef([cross_compiling], cross_compiling_build)dnl
cross_compiling_build=no
ac_build_tool_prefix=
AS_IF([test -n "$build"], [ac_build_tool_prefix="$build-"],
[test -n "$build_alias"],[ac_build_tool_prefix="$build_alias-"])
AC_LANG_PUSH([C])
AC_PROG_CC
_AC_COMPILER_EXEEXT
_AC_COMPILER_OBJEXT
AC_PROG_CPP
dnl Restore the old definitions
dnl
popdef([cross_compiling])dnl
popdef([am_cv_prog_cc_c_o])dnl
popdef([am_cv_CC_dependencies_compiler_type])dnl
popdef([ac_tool_prefix])dnl
popdef([ac_cv_host_os])dnl
popdef([ac_cv_host_vendor])dnl
popdef([ac_cv_host_cpu])dnl
popdef([ac_cv_host_alias])dnl
popdef([ac_cv_host])dnl
popdef([host_os])dnl
popdef([host_vendor])dnl
popdef([host_cpu])dnl
popdef([host_alias])dnl
popdef([host])dnl
popdef([OBJEXT])dnl
popdef([LDFLAGS])dnl
popdef([EXEEXT])dnl
popdef([CPPFLAGS])dnl
popdef([CFLAGS])dnl
popdef([GCC])dnl
popdef([CPP])dnl
popdef([CC])dnl
popdef([ac_objext])dnl
popdef([ac_exeext])dnl
popdef([ac_cv_objext])dnl
popdef([ac_cv_exeext])dnl
popdef([ac_cv_c_compiler_gnu])dnl
popdef([ac_cv_prog_cc_g])dnl
popdef([ac_cv_prog_cc_cross])dnl
popdef([ac_cv_prog_cc_works])dnl
popdef([ac_cv_prog_cc_c89])dnl
popdef([ac_cv_prog_gcc])dnl
popdef([ac_cv_prog_CPP])dnl
dnl restore global variables ac_ext, ac_cpp, ac_compile,
dnl ac_link, ac_compiler_gnu (dependant on the current
dnl language after popping):
AC_LANG_POP([C])
dnl Finally, set Makefile variables
dnl
AC_SUBST(BUILD_EXEEXT)dnl
AC_SUBST(BUILD_OBJEXT)dnl
AC_SUBST([CFLAGS_FOR_BUILD])dnl
AC_SUBST([CPPFLAGS_FOR_BUILD])dnl
AC_SUBST([LDFLAGS_FOR_BUILD])dnl
])
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
m4_include([m4/_ac_am_config_header_hook.m4])
m4_include([m4/_ax_c_underscores_match_if.m4])
m4_include([m4/ax_c99_strtod.m4])
m4_include([m4/ax_c_picflag.m4])
m4_include([m4/ax_c_underscores_leading.m4])
m4_include([m4/ax_c_underscores_trailing.m4])
m4_include([m4/ax_cxx_compile_stdcxx.m4])
m4_include([m4/ax_enable_suffix.m4])
m4_include([m4/ax_ld_extralibs.m4])
m4_include([m4/ax_ld_rdynamic.m4])
m4_include([m4/ax_ld_sharedlib_opts.m4])
m4_include([m4/ax_prog_cc_for_build.m4])
m4_include([m4/ax_win32.m4])
-5
View File
@@ -28,11 +28,6 @@ bool NetAssign::is_asynchronous()
return true;
}
bool NetCondit::is_asynchronous()
{
return false;
}
/*
* NetEvWait statements come from statements of the form @(...) in the
* Verilog source. These event waits are considered asynchronous if
+6 -2
View File
@@ -59,7 +59,11 @@ distclean: clean
rm -f Makefile config.log
cppcheck: $(O:.o=.c)
cppcheck --enable=all --std=c99 --std=c++11 -f $(INCLUDE_PATH) $^
cppcheck --enable=all --std=c99 --std=c++11 -f \
--check-level=exhaustive \
--suppressions-list=$(srcdir)/../cppcheck-global.sup \
--suppressions-list=$(srcdir)/cppcheck.sup \
$(INCLUDE_PATH) $^
Makefile: $(srcdir)/Makefile.in ../config.status
cd ..; ./config.status --file=cadpli/$@
@@ -67,7 +71,7 @@ Makefile: $(srcdir)/Makefile.in ../config.status
dep:
mkdir dep
%.o: %.c
%.o: %.c | dep
$(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c $<
mv $*.d dep
+2 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003-2026 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -53,7 +53,7 @@ static void thunker_register(void)
strncpy(module, cp, bp-cp);
module[bp-cp] = 0;
mod = ivl_dlopen(module);
mod = ivl_dlopen(module, false);
if (mod == 0) {
vpi_printf("%s link: %s\n", vlog_info.argv[idx], dlerror());
free(module);
+7
View File
@@ -0,0 +1,7 @@
// We use guarded memory allocation routines, but cppcheck is not
// noticing this so it is complaining we could return a NULL value.
nullPointerOutOfMemory:cadpli.c:53
nullPointerOutOfMemory:cadpli.c:54
// Unused function
unusedFunction:ivl_dlfcn.h:87
-94
View File
@@ -1,94 +0,0 @@
#ifndef IVL_ivl_dlfcn_H
#define IVL_ivl_dlfcn_H
/*
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#if defined(__MINGW32__)
# include <windows.h>
# include <stdio.h>
typedef void * ivl_dll_t;
#elif defined(HAVE_DLFCN_H)
# include <dlfcn.h>
typedef void* ivl_dll_t;
#elif defined(HAVE_DL_H)
# include <dl.h>
typedef shl_t ivl_dll_t;
#endif
#if defined(__MINGW32__)
static __inline__ ivl_dll_t ivl_dlopen(const char *name)
{ return (void *)LoadLibrary(name); }
static __inline__ void *ivl_dlsym(ivl_dll_t dll, const char *nm)
{ return (void *)GetProcAddress((HINSTANCE)dll,nm);}
static __inline__ void ivl_dlclose(ivl_dll_t dll)
{ (void)FreeLibrary((HINSTANCE)dll);}
static __inline__ const char *dlerror(void)
{
static char msg[256];
unsigned long err = GetLastError();
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &msg,
sizeof(msg) - 1,
NULL
);
return msg;
}
#elif defined(HAVE_DLFCN_H)
static __inline__ ivl_dll_t ivl_dlopen(const char*name)
{ return dlopen(name,RTLD_LAZY); }
static __inline__ void* ivl_dlsym(ivl_dll_t dll, const char*nm)
{
void*sym = dlsym(dll, nm);
/* Not found? try without the leading _ */
if (sym == 0 && nm[0] == '_')
sym = dlsym(dll, nm+1);
return sym;
}
static __inline__ void ivl_dlclose(ivl_dll_t dll)
{ dlclose(dll); }
#elif defined(HAVE_DL_H)
static __inline__ ivl_dll_t ivl_dlopen(const char*name)
{ return shl_load(name, BIND_IMMEDIATE, 0); }
static __inline__ void* ivl_dlsym(ivl_dll_t dll, const char*nm)
{
void*sym;
int rc = shl_findsym(&dll, nm, TYPE_PROCEDURE, &sym);
return (rc == 0) ? sym : 0;
}
static __inline__ void ivl_dlclose(ivl_dll_t dll)
{ shl_unload(dll); }
static __inline__ const char*dlerror(void)
{ return strerror( errno ); }
#endif
#endif /* IVL_ivl_dlfcn_H */
+20 -1
View File
@@ -1,7 +1,7 @@
#ifndef IVL_compiler_H
#define IVL_compiler_H
/*
* Copyright (c) 1999-2021 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2026 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -104,6 +104,9 @@ extern bool warn_sens_entire_arr;
/* Warn about level-appropriate anachronisms. */
extern bool warn_anachronisms;
/* Warn about declaration after use (unless flaged as errors). */
extern bool warn_decl_after_use;
/* Warn about nets that are references but not driven. */
extern bool warn_floating_nets;
@@ -162,6 +165,8 @@ enum generation_t {
GN_VER2005_SV = 5,
GN_VER2009 = 6,
GN_VER2012 = 7,
GN_VER2017 = 8,
GN_VER2023 = 9,
GN_DEFAULT = 4
};
@@ -210,6 +215,20 @@ extern bool gn_strict_expr_width_flag;
loop. */
extern bool gn_shared_loop_index_flag;
/* If this flag is true (default), then parameters must be declared before
use. `-gno-strict[-parameter]-declaration` allows to use parameters before
declaration, as prior to version 13.
A warning is emited with -Wdeclaration-after-use (default).
*/
extern bool gn_strict_parameter_declaration;
/* If this flag is true (default), then nets and variablesmust be declared
before use. `-gno-strict[-net-var]-declaration` allows to use nets and
variables before declaration, as prior to version 13.
A warning is emited with -Wdeclaration-after-use (default).
*/
extern bool gn_strict_net_var_declaration;
static inline bool gn_system_verilog(void)
{
if (generation_flag >= GN_VER2005_SV)
Vendored Executable → Regular
+16 -8
View File
@@ -1,10 +1,10 @@
#! /bin/sh
# Attempt to guess a canonical system name.
# Copyright 1992-2024 Free Software Foundation, Inc.
# Copyright 1992-2026 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268 # see below for rationale
timestamp='2024-07-27'
timestamp='2026-05-17'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -60,7 +60,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
Copyright 1992-2024 Free Software Foundation, Inc.
Copyright 1992-2026 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -150,7 +150,7 @@ UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
case $UNAME_SYSTEM in
Linux|GNU|GNU/*)
Ironclad|Linux|GNU|GNU/*)
LIBC=unknown
set_cc_for_build
@@ -167,6 +167,8 @@ Linux|GNU|GNU/*)
LIBC=gnu
#elif defined(__LLVM_LIBC__)
LIBC=llvm
#elif defined(__mlibc__)
LIBC=mlibc
#else
#include <stdarg.h>
/* First heuristic to detect musl libc. */
@@ -1186,6 +1188,9 @@ EOF
sparc:Linux:*:* | sparc64:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
sw_64:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
tile*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
@@ -1597,8 +1602,11 @@ EOF
*:Unleashed:*:*)
GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
;;
*:Ironclad:*:*)
GUESS=$UNAME_MACHINE-unknown-ironclad
x86_64:[Ii]ronclad:*:*|i?86:[Ii]ronclad:*:*)
GUESS=$UNAME_MACHINE-pc-ironclad-$LIBC
;;
*:[Ii]ronclad:*:*)
GUESS=$UNAME_MACHINE-unknown-ironclad-$LIBC
;;
esac
@@ -1808,8 +1816,8 @@ fi
exit 1
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# eval: (add-hook 'before-save-hook 'time-stamp nil t)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-format: "%Y-%02m-%02d"
# time-stamp-end: "'"
# End:
Vendored Executable → Regular
+20 -9
View File
@@ -1,10 +1,10 @@
#! /bin/sh
# Configuration validation subroutine script.
# Copyright 1992-2024 Free Software Foundation, Inc.
# Copyright 1992-2026 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268,SC2162 # see below for rationale
timestamp='2024-05-27'
timestamp='2026-05-17'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -76,7 +76,7 @@ Report bugs and patches to <[email protected]>."
version="\
GNU config.sub ($timestamp)
Copyright 1992-2024 Free Software Foundation, Inc.
Copyright 1992-2026 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -145,6 +145,7 @@ case $1 in
| kfreebsd*-gnu* \
| knetbsd*-gnu* \
| kopensolaris*-gnu* \
| ironclad-* \
| linux-* \
| managarm-* \
| netbsd*-eabi* \
@@ -242,7 +243,6 @@ case $1 in
| rombug \
| semi \
| sequent* \
| siemens \
| sgi* \
| siemens \
| sim \
@@ -261,7 +261,7 @@ case $1 in
basic_machine=$field1-$field2
basic_os=
;;
zephyr*)
tock* | zephyr*)
basic_machine=$field1-unknown
basic_os=$field2
;;
@@ -1194,7 +1194,7 @@ case $cpu-$vendor in
xscale-* | xscalee[bl]-*)
cpu=`echo "$cpu" | sed 's/^xscale/arm/'`
;;
arm64-* | aarch64le-*)
arm64-* | aarch64le-* | arm64_32-*)
cpu=aarch64
;;
@@ -1321,6 +1321,7 @@ case $cpu-$vendor in
| i960 \
| ia16 \
| ia64 \
| intelgt \
| ip2k \
| iq2000 \
| javascript \
@@ -1431,6 +1432,7 @@ case $cpu-$vendor in
| sparcv9v \
| spu \
| sv1 \
| sw_64 \
| sx* \
| tahoe \
| thumbv7* \
@@ -1522,6 +1524,10 @@ EOF
kernel=nto
os=`echo "$basic_os" | sed -e 's|nto|qnx|'`
;;
ironclad*)
kernel=ironclad
os=`echo "$basic_os" | sed -e 's|ironclad|gnu|'`
;;
linux*)
kernel=linux
os=`echo "$basic_os" | sed -e 's|linux|gnu|'`
@@ -1976,6 +1982,7 @@ case $os in
| atheos* \
| auroraux* \
| aux* \
| banan_os* \
| beos* \
| bitrig* \
| bme* \
@@ -2022,7 +2029,6 @@ case $os in
| ios* \
| iris* \
| irix* \
| ironclad* \
| isc* \
| its* \
| l4re* \
@@ -2118,6 +2124,7 @@ case $os in
| sysv* \
| tenex* \
| tirtos* \
| tock* \
| toppers* \
| tops10* \
| tops20* \
@@ -2214,6 +2221,8 @@ case $kernel-$os-$obj in
;;
uclinux-uclibc*- | uclinux-gnu*- )
;;
ironclad-gnu*- | ironclad-mlibc*- )
;;
managarm-mlibc*- | managarm-kernel*- )
;;
windows*-msvc*-)
@@ -2249,6 +2258,8 @@ case $kernel-$os-$obj in
;;
*-eabi*- | *-gnueabi*-)
;;
ios*-simulator- | tvos*-simulator- | watchos*-simulator- )
;;
none--*)
# None (no kernel, i.e. freestanding / bare metal),
# can be paired with an machine code file format
@@ -2347,8 +2358,8 @@ echo "$cpu-$vendor${kernel:+-$kernel}${os:+-$os}${obj:+-$obj}"
exit
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# eval: (add-hook 'before-save-hook 'time-stamp nil t)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-format: "%Y-%02m-%02d"
# time-stamp-end: "'"
# End:
+124 -6
View File
@@ -1,6 +1,35 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT
AC_CONFIG_MACRO_DIRS([m4])
dnl Define project version
m4_define([VER_MAJOR], [14])
m4_define([VER_MINOR], [0])
m4_define([VER_EXTRA], [devel])
dnl define libvvp ABI version
m4_define([LIBVVP_SOVERSION], [1])
AC_INIT([iverilog], [VER_MAJOR.VER_MINOR (VER_EXTRA)])
AC_SUBST([VERSION_MAJOR], [VER_MAJOR])
AC_SUBST([VERSION_MINOR], [VER_MINOR])
AC_SUBST([VERSION_EXTRA], [" (VER_EXTRA)"])
AC_SUBST([VERSION], ["VER_MAJOR.VER_MINOR (VER_EXTRA)"])
# used in res.rc
AC_SUBST([PRODUCTVERSION], ["VER_MAJOR,VER_MINOR,0,0"])
# setup libvvp soversion, which depends on abi not package version
AC_SUBST([LIBVVP_SOVERSION], [LIBVVP_SOVERSION])
# setup libvvp version
AC_SUBST([LIBVVP_VERSION], [LIBVVP_SOVERSION.VER_MAJOR.VER_MINOR])
AC_CONFIG_SRCDIR([netlist.h])
# Need a stamp file like the other header files
AC_CONFIG_FILES([version_base.h],[
_config_header=version_base.h
_stamp_name=stamp-`expr //$_config_header : '.*/\([[^./]]*\)\.[[^./]]*$'`-h
echo "timestamp for $_config_header" > `AS_DIRNAME(["$_config_header"])`/[]$_stamp_name
])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_HEADERS([_pli_types.h])
AC_CONFIG_HEADERS([vhdlpp/vhdlpp_config.h])
@@ -18,15 +47,19 @@ AX_PROG_CC_FOR_BUILD
AC_PREREQ([2.62])
m4_version_prereq([2.70], [], [AC_PROG_CC_C99])
AC_PROG_CXX
# Require C++11 (avoid newer defaults like C++23 from newer toolchains)
AX_CXX_COMPILE_STDCXX(11, noext, mandatory)
AC_PROG_RANLIB
AC_CHECK_TOOL(LD, ld, false)
AC_CHECK_TOOL(AR, ar, false)
AC_CHECK_TOOL(DLLTOOL, dlltool, false)
AC_CHECK_TOOL(STRIP, strip, true)
AC_CHECK_TOOL(WINDRES,windres,false)
AC_CHECK_PROGS(XGPERF,gperf,none)
AC_CHECK_PROGS(MAN,man,none)
AC_CHECK_PROGS(PS2PDF,ps2pdf,none)
AC_CHECK_PROGS(GROFF,groff,none)
AC_CHECK_PROGS(GIT,git,none)
if test "$XGPERF" = "none"
then
@@ -65,6 +98,20 @@ AC_SUBST(EXEEXT)
# Combined check for Microsoft-related bogosities; sets WIN32 if found
AX_WIN32
# Detect which directory/file separator to use
AC_MSG_CHECKING([for directory/file separator])
AS_CASE([$host_os:$MSYSTEM],
[*mingw*:UCRT64|*mingw*:MINGW64|*mingw*:MINGW32|*mingw*:CLANG64|*mingw*:CLANGARM64], [
PATH_SEP=\\\\
],
[
PATH_SEP=/
]
)
AC_MSG_RESULT([$PATH_SEP])
AC_SUBST([PATH_SEP])
# Check to see if we are using the Sun compiler. If so then configure
# some of the flags to match the Sun compiler syntax. This is also used
# in the aclocal.m4 file to configure the flags used to build and link
@@ -104,7 +151,15 @@ AS_IF( [test "x$with_m32" = xyes],
[])
CFLAGS="$CTARGETFLAGS $CFLAGS"
CXXFLAGS="$CTARGETFLAGS $CXXFLAGS -std=c++11"
# Cygwin does not declare strdup() for C++ 11 by default so use gnu++11
# to expose the declaration.
decl_cxx_std="-std=c++11"
case "${host}" in
*-*-cygwin*)
decl_cxx_std="-std=gnu++11"
;;
esac
CXXFLAGS="$CTARGETFLAGS $CXXFLAGS $decl_cxx_std"
LDFLAGS="$CTARGETFLAGS $LDFLAGS"
# Check that we are using either the GNU compilers or the Sun compilers
@@ -170,13 +225,28 @@ AC_SUBST(HAVE_LIBBZ2)
AC_FUNC_ALLOCA
AC_FUNC_FSEEKO
# Package Options
# Feature Options
# ---------------
# Build VVP as a library and stub
AC_ARG_ENABLE([libvvp],
[AS_HELP_STRING([--enable-libvvp], [build VVP as a shared library])],
[AC_SUBST(LIBVVP, yes)],[])
[enable_libvvp=yes],
[enable_libvvp=no])
AC_SUBST([LIBVVP], [$enable_libvvp])
AS_IF([test "x$enable_libvvp" = "xyes"],
[AC_MSG_NOTICE([Building with libvvp support enabled])],
[AC_MSG_NOTICE([Building with libvvp support disabled])])
AC_ARG_ENABLE([libveriuser],
[AS_HELP_STRING([--enable-libveriuser], [include support for PLI 1 (deprecated)])],
[AC_SUBST(LIBVERIUSER, yes)],
[AC_SUBST(LIBVERIUSER, no)])
# Package Options
# ---------------
# valgrind checks
AC_ARG_WITH([valgrind], [AS_HELP_STRING([--with-valgrind],[Add valgrind hooks])],
@@ -253,6 +323,27 @@ case "${host}" in
;;
esac
# Setup test environment for running vvp from build directory
VVP_BUILDDIR="$(pwd)/vvp"
case "$host_os" in
linux*)
ENV_VVP="LD_LIBRARY_PATH=$VVP_BUILDDIR"
;;
*bsd*)
ENV_VVP="LD_LIBRARY_PATH=$VVP_BUILDDIR"
;;
darwin*)
ENV_VVP="DYLD_LIBRARY_PATH=$VVP_BUILDDIR"
;;
*)
# Since the libvvp DLL is located in the same directory as the
# vvp executable, no action is required here
ENV_VVP=""
;;
esac
AC_SUBST([ENV_VVP])
# Do some more operating system specific setup. We put the file64_support
# define in a substitution instead of simply a define because there
# are source files (namely lxt support files) that don't include any
@@ -350,5 +441,32 @@ then
AC_MSG_ERROR(cannot configure white space in libdir: $libdir)
fi
AC_MSG_RESULT(ok)
AC_CONFIG_FILES([Makefile ivlpp/Makefile vhdlpp/Makefile vvp/Makefile vpi/Makefile driver/Makefile driver-vpi/Makefile cadpli/Makefile libveriuser/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-vvp/Makefile tgt-vhdl/Makefile tgt-fpga/Makefile tgt-verilog/Makefile tgt-pal/Makefile tgt-vlog95/Makefile tgt-pcb/Makefile tgt-blif/Makefile tgt-sizer/Makefile])
AC_CONFIG_FILES([
Makefile
cadpli/Makefile
driver-vpi/Makefile
driver-vpi/iverilog-vpi.man
driver-vpi/res.rc
driver/Makefile
driver/iverilog.man
ivlpp/Makefile
ivtest/Makefile
libveriuser/Makefile
tgt-blif/Makefile
tgt-fpga/Makefile
tgt-null/Makefile
tgt-pal/Makefile
tgt-pcb/Makefile
tgt-sizer/Makefile
tgt-stub/Makefile
tgt-verilog/Makefile
tgt-vhdl/Makefile
tgt-vlog95/Makefile
tgt-vvp/Makefile
vhdlpp/Makefile
vpi/Makefile
vvp/Makefile
vvp/libvvp.pc
vvp/vvp.man
])
AC_OUTPUT
+4
View File
@@ -0,0 +1,4 @@
// Skip all messages about missing system include files
missingIncludeSystem
// Skip the active checker report message
checkersReport
+148 -3
View File
@@ -1,10 +1,87 @@
// Skip the use STL messages
useStlAlgorithm
// Skip all memory issues since they should be handled by ivl_alloc.h
ctunullpointerOutOfMemory
nullPointerArithmeticOutOfMemory
nullPointerOutOfMemory
// valgrind does not find any issues so cppcheck is wrong
ctuuninitvar:parse_misc.cc:61
// Skip strdup() not constant.
constVariablePointer:main.cc:421
constVariablePointer:main.cc:425
constVariablePointer:main.cc:675
// const auto should be const
constVariablePointer:elab_expr.cc:628
constVariablePointer:elab_expr.cc:631
constVariablePointer:elab_expr.cc:700
// The reference cannot be const since it is updated in the calling function.
constParameterReference:net_udp.cc:37
// These cannot be static since they access object data
functionStatic:net_link.cc:178
functionStatic:net_link.cc:184
functionStatic:net_link.cc:189
functionStatic:net_link.cc:194
// This cannot be static when checking with valgrind
functionStatic:libmisc/StringHeap.cc
// Skip not initialized in the constructor for target scope
uninitMemberVar:t-dll.cc:41
uninitMemberVar:t-dll.cc:109
// By convention we put statics at the top scope.
variableScope:pform.cc:3630
// These are correct and are used to find the base (zero) pin.
thisSubtraction:netlist.h:5244
thisSubtraction:netlist.h:5253
thisSubtraction:netlist.h:5370
thisSubtraction:netlist.h:5379
// This is used when running a debugger
// debugger_release
knownConditionTrueFalse:main.cc:921
knownConditionTrueFalse:main.cc:955
// These should be checked, but are not real issues
knownConditionTrueFalse:elaborate.cc:8165
knownConditionTrueFalse:elab_sig.cc:272
knownConditionTrueFalse:elab_sig.cc:345
// Yes, it's a duplicate
duplicateCondition:elaborate.cc:8216
// To complicated to use std::find_if()
useStlAlgorithm:map_named_args.cc:38
// The condition is always true at least once based on the previous assertion
derefInvalidIterator:netmisc.cc:420
// By convention we put statics at the top scope.
variableScope:t-dll.cc:2309
// We check memory allocation with valgrind
unsafeClassCanLeak:libmisc/StringHeap.h:79
// We only use a StringHeap or a StringHepLex
duplInheritedMember:libmisc/StringHeap.h:99
duplInheritedMember:libmisc/StringHeap.h:100
duplInheritedMember:libmisc/StringHeap.cc:160
duplInheritedMember:libmisc/StringHeap.cc:182
// cppcheck is wrong this is correct usage
redundantAssignment:syn-rules.y:230
redundantAssignment:syn-rules.y:234
redundantAssignment:syn-rules.y:243
redundantAssignment:syn-rules.y:271
redundantAssignment:syn-rules.y:274
redundantAssignment:syn-rules.y:294
// Cannot define a constructor sine this is in the parser union
noConstructor:property_qual.h:22
// This are just stubs
// vpi_control()
@@ -636,3 +713,71 @@ unusedFunction:t-dll-api.cc:1007
unusedFunction:t-dll-api.cc:1016
// ivl_udp_sequ()
unusedFunction:t-dll-api.cc:980
// Unused routines
// has_compat_attributes()
unusedFunction:Attrib.cc:72
// bl_type()
unusedFunction:Statement.h:194
// chain_args()
unusedFunction:Statement.h:369
// gn_modules_nest()
unusedFunction:compiler.h:247
// driven_mask()
unusedFunction:link_const.cc:275
// find_root_scope()
unusedFunction:net_design.cc:121
// assign_lval()
unusedFunction:net_link.cc:283
// intersect()
unusedFunction:net_link.cc:687
// get_def_fileline()
unusedFunction:net_scope.cc:200
// get_module_port_info()
unusedFunction:net_scope.cc:631
// find_link_signal()
unusedFunction:netlist.cc:113
// find_link()
unusedFunction:netlist.cc:304
// set_module_port_index()
unusedFunction:netlist.cc:658
// width_a()
unusedFunction:netlist.cc:1685
// width_b()
unusedFunction:netlist.cc:1690
// result_sig()
unusedFunction:netlist.cc:2191
// soft_union()
unusedFunction:netstruct.h:93
// test_protected()
unusedFunction:property_qual.h:50
// test_rand()
unusedFunction:property_qual.h:52
// test_randc()
unusedFunction:property_qual.h:53
// sub_off_from_expr_()
unusedFunction:t-dll-expr.cc:55
// mul_expr_by_const_()
unusedFunction:t-dll-expr.cc:91
// net_assign()
unusedFunction:t-dll.cc:2300
// is_before()
unusedFunction:verinum.cc:588
// Errors/limitations in the generated yacc and lex files
constVariablePointer:<stdout>
cstyleCast:<stdout>
duplicateBreak:<stdout>
nullPointer:<stdout>
redundantInitialization:<stdout>
syntaxError:<stdout>
unusedFunction:<stdout>
duplicateBreak:lexor.lex
allocaCalled:parse.cc
constParameterPointer:parse.cc
constVariablePointer:parse.cc
knownConditionTrueFalse:parse.cc
allocaCalled:syn-rules.cc
constParameterPointer:syn-rules.cc
knownConditionTrueFalse:syn-rules.cc
constVariablePointer:syn-rules.cc
+16 -18
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2024 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2026 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -41,16 +41,16 @@ struct cprop_functor : public functor_t {
unsigned count;
virtual void signal(Design*des, NetNet*obj);
virtual void lpm_add_sub(Design*des, NetAddSub*obj);
virtual void lpm_compare(Design*des, const NetCompare*obj);
virtual void lpm_concat(Design*des, NetConcat*obj);
virtual void lpm_ff(Design*des, NetFF*obj);
virtual void lpm_logic(Design*des, NetLogic*obj);
virtual void lpm_mux(Design*des, NetMux*obj);
virtual void lpm_part_select(Design*des, NetPartSelect*obj);
virtual void signal(Design*des, NetNet*obj) override;
virtual void lpm_add_sub(Design*des, NetAddSub*obj) override;
virtual void lpm_compare(Design*des, const NetCompare*obj) override;
virtual void lpm_concat(Design*des, NetConcat*obj) override;
virtual void lpm_ff(Design*des, NetFF*obj) override;
virtual void lpm_logic(Design*des, NetLogic*obj) override;
virtual void lpm_mux(Design*des, NetMux*obj) override;
virtual void lpm_part_select(Design*des, NetPartSelect*obj) override;
void lpm_compare_eq_(Design*des, const NetCompare*obj);
static void lpm_compare_eq_(Design*des, const NetCompare*obj);
};
void cprop_functor::signal(Design*, NetNet*)
@@ -90,7 +90,7 @@ void cprop_functor::lpm_concat(Design*des, NetConcat*obj)
unsigned off = 0;
for (unsigned idx = 1 ; idx < obj->pin_count() ; idx += 1) {
Nexus*nex = obj->pin(idx).nexus();
const Nexus*nex = obj->pin(idx).nexus();
// If there are non-constant drivers, then give up.
if (! nex->drivers_constant())
return;
@@ -156,7 +156,7 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
if (obj->sel_width() != 1)
return;
Nexus*sel_nex = obj->pin_Sel().nexus();
const Nexus*sel_nex = obj->pin_Sel().nexus();
/* If the select input is constant, then replace with a BUFZ */
@@ -180,9 +180,7 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
<< "Replace binary MUX with constant select=" << sel_val
<< " with a BUFZ to the selected input." << endl;
tmp->rise_time(obj->rise_time());
tmp->fall_time(obj->fall_time());
tmp->decay_time(obj->decay_time());
tmp->delay_times(obj->delay_times());
connect(tmp->pin(0), obj->pin_Result());
if (sel_val == verinum::V1)
@@ -194,7 +192,7 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
count += 1;
}
static bool compare_base(NetPartSelect*a, NetPartSelect*b)
static bool compare_base(const NetPartSelect*a, const NetPartSelect*b)
{
return a->base() < b->base();
}
@@ -226,7 +224,7 @@ void cprop_functor::lpm_part_select(Design*des, NetPartSelect*obj)
NetPins*tmp_obj = cur->get_obj();
// Record if we are driving a 2-state net.
NetNet*net_obj = dynamic_cast<NetNet*> (tmp_obj);
const NetNet*net_obj = dynamic_cast<NetNet*> (tmp_obj);
if (net_obj && (net_obj->data_type() == IVL_VT_BOOL))
output_2_state = true;
@@ -355,7 +353,7 @@ void cprop_functor::lpm_part_select(Design*des, NetPartSelect*obj)
*/
struct cprop_dc_functor : public functor_t {
virtual void lpm_const(Design*des, NetConst*obj);
virtual void lpm_const(Design*des, NetConst*obj) override;
};
struct nexus_info_s {
+48 -61
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2021 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2026 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -90,6 +90,30 @@ ostream& operator << (ostream&o, ivl_drive_t str)
return o;
}
ostream &operator << (ostream &o, const drive_strength_t &strength)
{
o << strength.drive0 << "0 " << strength.drive1 << "1";
return o;
}
static void dump_delay_expr(ostream &o, const NetExpr *expr)
{
if (expr)
o << *expr;
else
o << "0";
}
ostream &operator << (ostream &o, const delay_exprs_t &delays)
{
dump_delay_expr(o, delays.rise);
o << ",";
dump_delay_expr(o, delays.fall);
o << ",";
dump_delay_expr(o, delays.decay);
return o;
}
ostream& operator << (ostream&o, ivl_variable_type_t val)
{
switch (val) {
@@ -454,8 +478,7 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
if (scope())
o << " scope=" << scope_path(scope());
o << " #(" << rise_time() << "," << fall_time() << ","
<< decay_time() << ") vector_width=" << vector_width()
o << " #(" << delay_times() << ") vector_width=" << vector_width()
<< " pin_count=" << pin_count();
if (pins_are_virtual()) {
o << " pins_are_virtual" << endl;
@@ -486,8 +509,7 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
void NetNode::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "node: ";
o << typeid(*this).name() << " #(" << rise_time()
<< "," << fall_time() << "," << decay_time() << ") " << name()
o << typeid(*this).name() << " #(" << delay_times() << ") " << name()
<< endl;
dump_node_pins(o, ind+4);
@@ -518,8 +540,7 @@ void NetPins::dump_node_pins(ostream&o, unsigned ind, const char**pin_names) con
break;
}
o << " (" << pin(idx).drive0() << "0 "
<< pin(idx).drive1() << "1): ";
o << " (" << pin(idx).drive() << "): ";
if (pin(idx).is_linked()) {
const Nexus*nex = pin(idx).nexus();
@@ -622,11 +643,7 @@ void NetConcat::dump_node(ostream&o, unsigned ind) const
o << setw(ind) << "" << "NetConcat: ";
o << name();
if (rise_time())
o << " #(" << *rise_time()
<< "," << *fall_time() << "," << *decay_time() << ")";
else
o << " #(0,0,0)";
o << " #(" << delay_times() << ")";
o << " scope=" << scope_path(scope())
<< " width=" << width_ << endl;
dump_node_pins(o, ind+4);
@@ -651,14 +668,7 @@ void NetPow::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_POW (NetPow): " << name()
<< " scope=" << scope_path(scope())
<< " delay=(";
if (rise_time())
o << *rise_time() << "," << *fall_time() << ","
<< *decay_time();
else
o << "0,0,0";
o << ")" << endl;
<< " delay=(" << delay_times() << ")" << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
@@ -676,8 +686,7 @@ void NetBUFZ::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "NetBUFZ: " << name()
<< " scope=" << scope_path(scope())
<< " delay=(" << rise_time() << "," << fall_time() << "," <<
decay_time() << ") width=" << width()
<< " delay=(" << delay_times() << ") width=" << width()
<< (transparent()? " " : " non-") << "transparent" << endl;
dump_node_pins(o, ind+4);
}
@@ -693,10 +702,8 @@ void NetConst::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "constant " << value_;
o << ": " << name();
if (rise_time())
o << " #(" << *rise_time()
<< "," << *fall_time()
<< "," << *decay_time() << ")";
if (delay_times().has_delay())
o << " #(" << delay_times() << ")";
else
o << " #(.,.,.)";
o << endl;
@@ -729,10 +736,8 @@ void NetLiteral::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "constant real " << real_
<< ": " << name();
if (rise_time())
o << " #(" << *rise_time()
<< "," << *fall_time()
<< "," << *decay_time() << ")";
if (delay_times().has_delay())
o << " #(" << delay_times() << ")";
else
o << " #(.,.,.)";
o << endl;
@@ -810,8 +815,7 @@ void NetLogic::dump_node(ostream&o, unsigned ind) const
o << "xor";
break;
}
o << " #(" << rise_time()
<< "," << fall_time() << "," << decay_time() << ") " << name()
o << " #(" << delay_times() << ") " << name()
<< " scope=" << scope_path(scope())
<< endl;
@@ -839,10 +843,8 @@ void NetPartSelect::dump_node(ostream&o, unsigned ind) const
}
o << setw(ind) << "" << "NetPartSelect(" << pt << "): "
<< name();
if (rise_time())
o << " #(" << *rise_time()
<< "," << *fall_time()
<< "," << *decay_time() << ")";
if (delay_times().has_delay())
o << " #(" << delay_times() << ")";
else
o << " #(.,.,.)";
o << " off=" << off_ << " wid=" << wid_ <<endl;
@@ -854,10 +856,8 @@ void NetSubstitute::dump_node(ostream&fd, unsigned ind) const
{
fd << setw(ind) << "" << "NetSubstitute: "
<< name();
if (rise_time())
fd << " #(" << *rise_time()
<< "," << *fall_time()
<< "," << *decay_time() << ")";
if (delay_times().has_delay())
fd << " #(" << delay_times() << ")";
else
fd << " #(.,.,.)";
fd << " width=" << wid_ << " base=" << off_ <<endl;
@@ -877,10 +877,8 @@ void NetReplicate::dump_node(ostream&o, unsigned ind) const
void NetSignExtend::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "NetSignExtend: " << name();
if (rise_time())
o << " #(" << *rise_time()
<< "," << *fall_time()
<< "," << *decay_time() << ")";
if (delay_times().has_delay())
o << " #(" << delay_times() << ")";
else
o << " #(.,.,.)";
o << " output width=" << width_ << endl;
@@ -914,8 +912,7 @@ void NetUReduce::dump_node(ostream&o, unsigned ind) const
o << "xnor";
break;
}
o << " #(" << rise_time()
<< "," << fall_time() << "," << decay_time() << ") " << name()
o << " #(" << delay_times() << ") " << name()
<< " scope=" << scope_path(scope())
<< endl;
@@ -935,10 +932,8 @@ void NetUserFunc::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "USER FUNC: "
<< scope_path(def_);
if (rise_time())
o << " #(" <<*rise_time()
<<","<<*fall_time()
<< "," <<*decay_time() << ")";
if (delay_times().has_delay())
o << " #(" << delay_times() << ")";
o << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
@@ -986,14 +981,7 @@ void NetTran::dump_node(ostream&o, unsigned ind) const
<< " part=" << part_width()
<< " offset=" << part_offset();
}
o << " delay=(";
if (rise_time())
o << *rise_time() << "," << *fall_time() << ","
<< *decay_time();
else
o << "0,0,0";
o << ")" << endl;
o << " delay=(" << delay_times() << ")" << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
@@ -1001,8 +989,7 @@ void NetTran::dump_node(ostream&o, unsigned ind) const
void NetUDP::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "UDP (" << udp_name() << "): ";
o << " #(" << rise_time() << "," << fall_time() << "," << decay_time() <<
") " << name() << endl;
o << " #(" << delay_times() << ") " << name() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
@@ -1151,7 +1138,7 @@ void NetAssignNB::dump(ostream&o, unsigned ind) const
if (rval())
o << *rval() << ";" << endl;
else
o << "rval elaboration error>;" << endl;
o << "<rval elaboration error>;" << endl;
}
+7 -7
View File
@@ -1,7 +1,7 @@
#ifndef IVL_discipline_H
#define IVL_discipline_H
/*
* Copyright (c) 2008-2021 Stephen Williams (steve@icarus.com)
* Copyright (c) 2008-2025 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -36,7 +36,7 @@ extern std::ostream& operator << (std::ostream&, ivl_dis_domain_t);
class ivl_nature_s : public LineInfo {
public:
explicit ivl_nature_s(perm_string name, perm_string access);
~ivl_nature_s();
~ivl_nature_s() override;
perm_string name() const { return name_; }
// Identifier for the access function for this nature
@@ -51,12 +51,12 @@ class ivl_discipline_s : public LineInfo {
public:
explicit ivl_discipline_s (perm_string name, ivl_dis_domain_t dom,
ivl_nature_t pot, ivl_nature_t flow);
~ivl_discipline_s();
~ivl_discipline_s() override;
perm_string name() const { return name_; }
ivl_dis_domain_t domain() const { return domain_; }
ivl_nature_t potential() const { return potential_; }
ivl_nature_t flow() const { return flow_; }
perm_string name() const { return name_; }
ivl_dis_domain_t domain() const { return domain_; }
ivl_nature_t potential() const { return potential_; }
ivl_nature_t flow() const { return flow_; }
private:
perm_string name_;
+2 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2025 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -28,7 +28,7 @@
# include <stdio.h>
int main(int argc, char*argv[])
int main(int argc, const char*argv[])
{
FILE*ifile;
FILE*ofile;
+95 -11
View File
@@ -31,7 +31,11 @@ suffix = @install_suffix@
bindir = $(exec_prefix)/bin
libdir = $(exec_prefix)/lib
includedir = $(prefix)/include
mandir = @mandir@
# This is actually the directory where we install our own header files.
# It is a little different from the generic includedir.
ivl_includedir = @includedir@/iverilog$(suffix)
man1dir = @mandir@/man1
docdir = @docdir@
dllib=@DLLIB@
@@ -39,8 +43,11 @@ CC = @CC@
HOSTCC := @CC@
WINDRES = @WINDRES@
INSTALL = @INSTALL@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
MAN = @MAN@
PS2PDF = @PS2PDF@
ifeq (@srcdir@,.)
INCLUDE_PATH = -I. -I..
@@ -48,31 +55,68 @@ else
INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
endif
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@
CPPFLAGS = @DEFS@ $(INCLUDE_PATH) @CPPFLAGS@
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@
LDFLAGS = @LDFLAGS@
PICFLAGS = @PICFLAG@
LDFLAGS = @rdynamic@ @LDFLAGS@
O = main.o res.o
ifeq (@MINGW32@,yes)
all: iverilog-vpi@EXEEXT@
else
all: iverilog-vpi
endif
INSTALL_DOC =
ifneq ($(MAN),none)
INSTALL_DOC += installman
ifneq ($(PS2PDF),none)
ifeq (@MINGW32@,yes)
INSTALL_DOC += installpdf
all: iverilog-vpi.pdf
endif
endif
endif
check: all
clean:
rm -f *.o config.h iverilog-vpi@EXEEXT@ res.rc
rm -f *.o config.h iverilog-vpi@EXEEXT@ iverilog-vpi \
iverilog-vpi.man iverilog-vpi.ps iverilog-vpi.pdf res.rc
distclean: clean
rm -f Makefile config.log
cppcheck: main.c
cppcheck --enable=all --std=c99 --std=c++11 -f $(INCLUDE_PATH) $^
cppcheck: main.c config.h
cppcheck --enable=all --std=c99 --std=c++11 -f \
--check-level=exhaustive \
--suppressions-list=$(srcdir)/../cppcheck-global.sup \
--suppressions-list=$(srcdir)/cppcheck.sup \
$(INCLUDE_PATH) $^
Makefile: $(srcdir)/Makefile.in ../config.status
cd ..; ./config.status --file=driver-vpi/$@
ifeq (@MINGW32@,yes)
iverilog-vpi@EXEEXT@: $O
$(CC) $(LDFLAGS) $O -o iverilog-vpi@EXEEXT@ @EXTRALIBS@
endif
ifeq (@MINGW32@,no)
iverilog-vpi: $(srcdir)/iverilog-vpi.sh ../config.status
sed -e 's;@SHARED@;@shared@;' -e 's;@PIC@;@PICFLAG@;' \
-e 's;@ENABLE_PLI1@;@LIBVERIUSER@;' \
-e 's;@SUFFIX@;$(suffix);' \
-e 's;@IVCC@;$(CC);' \
-e 's;@IVCXX@;@CXX@;' \
-e 's;@IVCFLAGS@;$(CFLAGS);' \
-e 's;@IVCXXFLAGS@;$(CXXFLAGS);' \
-e 's;@IVCTARGETFLAGS@;@CTARGETFLAGS@;' \
-e 's;@INCLUDEDIR@;$(ivl_includedir);' \
-e 's;@LIBDIR@;@libdir@;' $< > $@
chmod +x $@
endif
main.o: $(srcdir)/main.c config.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c $(srcdir)/main.c
@@ -84,22 +128,46 @@ config.h: $(srcdir)/config.h.in Makefile
-e 's;@IVLCFLAGS@;$(CFLAGS);' \
-e 's;@IVLCXXFLAGS@;$(CXXFLAGS);' \
-e 's;@SHARED@;@shared@;' $< > $@
ifeq (@LIBVERIUSER@,yes)
sed -i 's;@VPILIBS@;-lveriuser$(suffix) -lvpi$(suffix);' $@
else
sed -i 's;@VPILIBS@;-lvpi$(suffix);' $@
endif
# Windows specific...
res.rc: $(srcdir)/res.rc.in ../version.exe
sed -e 's;@PRODUCTVERSION@;'`../version.exe '%M,%n,0,0'`';' \
$(srcdir)/res.rc.in > $@
res.rc: $(srcdir)/res.rc.in ../config.status
cd ..; ./config.status --file=driver-vpi/$@
res.o: res.rc
$(WINDRES) -i res.rc -o res.o
#
iverilog-vpi.man: $(srcdir)/iverilog-vpi.man.in ../config.status
cd ..; ./config.status --file=driver-vpi/$@
iverilog-vpi.ps: iverilog-vpi.man
$(MAN) -t ./$< > $@
iverilog-vpi.pdf: iverilog-vpi.ps
$(PS2PDF) $< $@
install: all installdirs installfiles
F = ./iverilog-vpi@EXEEXT@
F = $(INSTALL_DOC)
ifeq (@MINGW32@,yes)
F += ./iverilog-vpi@EXEEXT@
endif
ifeq (@MINGW32@,no)
F += ./iverilog-vpi
endif
installfiles: $(F) | installdirs
ifeq (@MINGW32@,yes)
$(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ "$(DESTDIR)$(bindir)/iverilog-vpi$(suffix)@EXEEXT@"
endif
ifeq (@MINGW32@,no)
$(INSTALL_SCRIPT) ./iverilog-vpi "$(DESTDIR)$(bindir)/iverilog-vpi$(suffix)"
endif
ifeq (@WIN32@,yes)
ifneq ($(HOSTCC),$(CC))
$(INSTALL_PROGRAM) $(shell $(HOSTCC) --print-file-name=libwinpthread-1.dll) "$(DESTDIR)$(bindir)"
@@ -108,8 +176,24 @@ ifneq ($(HOSTCC),$(CC))
endif
endif
installman: iverilog-vpi.man installdirs
$(INSTALL_DATA) iverilog-vpi.man "$(DESTDIR)$(man1dir)/iverilog-vpi$(suffix).1"
installpdf: iverilog-vpi.pdf installdirs
$(INSTALL_DATA) iverilog-vpi.pdf "$(DESTDIR)$(docdir)/iverilog-vpi$(suffix).pdf"
installdirs: $(srcdir)/../mkinstalldirs
$(srcdir)/../mkinstalldirs "$(DESTDIR)$(bindir)"
$(srcdir)/../mkinstalldirs \
"$(DESTDIR)$(bindir)" \
"$(DESTDIR)$(docdir)" \
"$(DESTDIR)$(man1dir)"
uninstall:
ifeq (@MINGW32@,yes)
rm -f $(DESTDIR)$(bindir)/iverilog-vpi$(suffix)@EXEEXT@
endif
ifeq (@MINGW32@,no)
rm -f $(DESTDIR)$(bindir)/iverilog-vpi$(suffix)
endif
rm -f "$(DESTDIR)$(man1dir)/iverilog-vpi$(suffix).1" \
"$(DESTDIR)$(docdir)/iverilog-vpi$(suffix).pdf"
+1 -1
View File
@@ -6,5 +6,5 @@
#define IVERILOG_VPI_CFLAGS " @IVLCFLAGS@"
#define IVERILOG_VPI_CXXFLAGS " @IVLCXXFLAGS@"
#define IVERILOG_VPI_LDFLAGS "@SHARED@"
#define IVERILOG_VPI_LDLIBS "-lveriuser@SUFFIX@ -lvpi@SUFFIX@"
#define IVERILOG_VPI_LDLIBS "@VPILIBS@"
#define IVERILOG_SUFFIX "@SUFFIX@"
+3
View File
@@ -0,0 +1,3 @@
// ptr is from strrchr() so the result does change
redundantAssignment:main.c:525
knownConditionTrueFalse:main.c:526
@@ -1,4 +1,4 @@
.TH iverilog-vpi 1 "Jan 20th, 2024" "" "Version %M.%n%E"
.TH iverilog-vpi 1 "Jan 13th, 2026" "" "Version @VERSION@"
.SH NAME
iverilog-vpi - Compile front end for VPI modules
@@ -120,7 +120,7 @@ iverilog(1), vvp(1),
.SH COPYRIGHT
.nf
Copyright \(co 2002\-2024 Stephen Williams
Copyright \(co 2002\-2026 Stephen Williams
This document can be freely redistributed according to the terms of the
GNU General Public License version 2.0
@@ -1,5 +1,7 @@
#!/bin/sh
#
# Copyright (c) 1998-2026 Stephen Williams ([email protected])
#
# This source code is free software; you can redistribute it
# and/or modify it in source code form under the terms of the GNU
# Library General Public License as published by the Free Software
@@ -29,7 +31,11 @@ SUFFIX=@SUFFIX@
# These are used for linking...
LD=$CC
LDFLAGS="@IVCTARGETFLAGS@ @SHARED@ -L@LIBDIR@"
LDLIBS="-lveriuser$SUFFIX -lvpi$SUFFIX"
if [ x@ENABLE_PLI1@ = xyes ] ; then
LDLIBS="-lveriuser$SUFFIX -lvpi$SUFFIX"
else
LDLIBS="-lvpi$SUFFIX"
fi
CCSRC=
CXSRC=
+10 -9
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2022 Martin Whitaker
* Copyright (c) 2015-2026 Martin Whitaker
* Copyright (c) 2002 Gus Baldauf (gus@picturel.com)
*
* This source code is free software; you can redistribute it
@@ -34,7 +34,7 @@
#include <windows.h>
static void setup_ivl_environment(void);
static void assign(char **ptr, char *str);
static void assign(char **ptr, const char *str);
/* The compile options: compiler, flags, etc. are in here */
#include "config.h"
@@ -164,7 +164,7 @@ static int startsWith (char *prefix, char *str)
/* append "app" to "ptr", allocating memory as needed */
/* if count is zero, then copy all characters of "app" */
static void appendn (char **ptr, char *app, size_t count)
static void appendn (char **ptr, const char *app, size_t count)
{
char *nptr = (char *) realloc(*ptr, strlen(*ptr) +
(count ? count : strlen(app)) + 1);
@@ -184,7 +184,7 @@ static void appendn (char **ptr, char *app, size_t count)
/* append "app" to "ptr", allocating memory as needed */
static void append (char **ptr, char *app)
static void append (char **ptr, const char *app)
{
appendn(ptr, app, 0);
}
@@ -200,7 +200,7 @@ static void appendBackSlash(char **str)
/* copy count characters of "str" to "ptr", allocating memory as needed */
/* if count is zero, then copy all characters of "str" */
static void assignn (char **ptr, char *str, size_t count)
static void assignn (char **ptr, const char *str, size_t count)
{
char *nptr = (char *) realloc(*ptr, (count ? count : strlen(str)) + 1);
@@ -221,7 +221,7 @@ static void assignn (char **ptr, char *str, size_t count)
/* copy count characters of "str" to "ptr", allocating memory as needed */
static void assign (char **ptr, char *str)
static void assign (char **ptr, const char *str)
{
assignn(ptr, str, 0);
}
@@ -428,7 +428,7 @@ static int parse(int argc, char *argv[])
/* do minimal check that the MinGW root directory looks valid */
static void checkMingwDir(char *root)
static void checkMingwDir(const char *root)
{
int irv;
struct _stat stat_buf;
@@ -551,9 +551,10 @@ static void setup_ivl_environment(void)
/* compile source modules */
static void compile(char *pSource, char *pFlags, char **pObject, int *compile_errors, char *compiler)
static void compile(const char *pSource, const char *pFlags, char **pObject,
int *compile_errors, const char *compiler)
{
char *ptr1 = pSource;
const char *ptr1 = pSource;
char *ptr2 = strchr(ptr1, ' ');
char *buf=0, *src=0, *obj=0;
+44 -35
View File
@@ -17,20 +17,26 @@
#
SHELL = /bin/sh
EXEEXT = @EXEEXT@
ENV_VVP=@ENV_VVP@
PATH_SEP=@PATH_SEP@
suffix = @install_suffix@
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
datarootdir = @datarootdir@
builddir=@builddir@
top_builddir=@top_builddir@
VPATH = $(srcdir)
bindir = $(exec_prefix)/bin
libdir = $(exec_prefix)/lib
includedir = $(prefix)/include
mandir = @mandir@
pdfdir = @docdir@
man1dir = @mandir@/man1
docdir = @docdir@
dllib=@DLLIB@
@@ -58,22 +64,34 @@ O = main.o substit.o cflexor.o cfparse.o
all: dep iverilog@EXEEXT@ iverilog.man
check: all
@echo "driver/iverilog: create a vvp file and then run it."
@rm -f top.vvp
@$(builddir)/iverilog@EXEEXT@ \
-B$(top_builddir)$(PATH_SEP)tgt-vvp \
-BI$(top_builddir) \
-BM$(top_builddir)$(PATH_SEP)vpi \
-BP$(top_builddir)$(PATH_SEP)ivlpp \
-Bt$(top_builddir)$(PATH_SEP)tgt-vvp \
$(verbose) -o top.vvp -s top $(srcdir)/hello_world.v && \
$(ENV_VVP) $(top_builddir)/vvp/vvp$(suffix)@EXEEXT@ top.vvp
clean:
rm -f *.o cflexor.c cfparse.c cfparse.h cfparse.output
rm -f iverilog@EXEEXT@ iverilog.man iverilog.pdf iverilog.ps
rm -rf dep
rm -f top.vvp
distclean: clean
rm -f Makefile config.log
cppcheck: $(O:.o=.c)
cppcheck --enable=all --std=c99 --std=c++11 -f \
-UYY_USER_INIT \
-UYYPARSE_PARAM -UYYPRINT -Ushort -Uyyoverflow \
-UYYTYPE_INT8 -UYYTYPE_INT16 -UYYTYPE_UINT8 -UYYTYPE_UINT16 \
-UYYSTYPE -U__SIZE_TYPE__ -Umalloc -Usize_t -Ufree \
$(INCLUDE_PATH) $^
--check-level=exhaustive \
--suppressions-list=$(srcdir)/../cppcheck-global.sup \
--suppressions-list=$(srcdir)/cppcheck.sup \
-Ushort -Usize_t -Uyyoverflow \
-U__SIZE_TYPE__ -Umalloc -Ufree \
--relative-paths=$(srcdir) $(INCLUDE_PATH) $^
Makefile: $(srcdir)/Makefile.in ../config.status
cd ..; ./config.status --file=driver/$@
@@ -91,45 +109,34 @@ cflexor.c: $(srcdir)/cflexor.lex
cfparse%c cfparse%h: $(srcdir)/cfparse%y
$(YACC) --verbose -t -p cf -d -o cfparse.c $<
%.o: %.c
%.o: %.c | dep
$(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
mv $*.d dep
main.o: main.c globals.h $(srcdir)/../version_base.h ../version_tag.h Makefile
main.o: main.c globals.h ../version_base.h ../version_tag.h Makefile | dep
$(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c -DIVL_ROOT='"@libdir@/ivl$(suffix)"' -DIVL_SUFFIX='"$(suffix)"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DDLLIB='"@DLLIB@"' -DIVL_INCLUDE_INSTALL_DIR="\"$(realpath $(DESTDIR)/$(includedir))\"" $(srcdir)/main.c
mv $*.d dep
cflexor.o: cflexor.c cfparse.h
iverilog.man: $(srcdir)/iverilog.man.in ../version.exe
../version.exe `head -1 $(srcdir)/iverilog.man.in`'\n' > $@
tail -n +2 $(srcdir)/iverilog.man.in >> $@
iverilog.man: $(srcdir)/iverilog.man.in ../config.status
cd ..; ./config.status --file=driver/$@
iverilog.ps: iverilog.man
$(MAN) -t ./iverilog.man > iverilog.ps
$(MAN) -t ./$< > $@
iverilog.pdf: iverilog.ps
$(PS2PDF) iverilog.ps iverilog.pdf
$(PS2PDF) $< $@
INSTALL_DOC =
ifneq ($(MAN),none)
INSTALL_DOC += installman
ifneq ($(PS2PDF),none)
ifeq (@MINGW32@,yes)
ifeq ($(MAN),none)
INSTALL_DOC = installman
INSTALL_PDFDIR = $(prefix)
else
ifeq ($(PS2PDF),none)
INSTALL_DOC = installman
INSTALL_PDFDIR = $(prefix)
else
INSTALL_DOC = installpdf installman
INSTALL_PDFDIR = $(pdfdir)
INSTALL_DOC += installpdf
all: iverilog.pdf
endif
endif
INSTALL_DOCDIR = $(mandir)/man1
else
INSTALL_DOC = installman
INSTALL_DOCDIR = $(mandir)/man1
INSTALL_PDFDIR = $(prefix)
endif
install: all installdirs installfiles
@@ -138,21 +145,23 @@ F = ./iverilog@EXEEXT@ \
$(INSTALL_DOC)
installman: iverilog.man installdirs
$(INSTALL_DATA) iverilog.man "$(DESTDIR)$(mandir)/man1/iverilog$(suffix).1"
$(INSTALL_DATA) iverilog.man "$(DESTDIR)$(man1dir)/iverilog$(suffix).1"
installpdf: iverilog.pdf installdirs
$(INSTALL_DATA) iverilog.pdf "$(DESTDIR)$(pdfdir)/iverilog$(suffix).pdf"
$(INSTALL_DATA) iverilog.pdf "$(DESTDIR)$(docdir)/iverilog$(suffix).pdf"
installfiles: $(F) | installdirs
$(INSTALL_PROGRAM) ./iverilog@EXEEXT@ "$(DESTDIR)$(bindir)/iverilog$(suffix)@EXEEXT@"
installdirs: $(srcdir)/../mkinstalldirs
$(srcdir)/../mkinstalldirs "$(DESTDIR)$(bindir)" \
"$(DESTDIR)$(INSTALL_DOCDIR)" \
"$(DESTDIR)$(INSTALL_PDFDIR)"
$(srcdir)/../mkinstalldirs \
"$(DESTDIR)$(bindir)" \
"$(DESTDIR)$(docdir)" \
"$(DESTDIR)$(man1dir)"
uninstall:
rm -f "$(DESTDIR)$(bindir)/iverilog$(suffix)@EXEEXT@"
rm -f "$(DESTDIR)$(mandir)/man1/iverilog$(suffix).1" "$(DESTDIR)$(pdfdir)/iverilog$(suffix).pdf"
rm -f "$(DESTDIR)$(man1dir)/iverilog$(suffix).1" \
"$(DESTDIR)$(docdir)/iverilog$(suffix).pdf"
-include $(patsubst %.o, dep/%.d, $O)
+31
View File
@@ -0,0 +1,31 @@
// cppcheck is wrong this is correct usage
syntaxError:main.c:415
syntaxError:main.c:412
// cppcheck is missing the code adds a \0 at the previous location.
knownConditionTrueFalse:main.c:1123
redundantAssignment:main.c:1122
// Skip all memory issues since they should be handled by ivl_alloc.h
memleakOnRealloc
nullPointerArithmeticOutOfMemory
nullPointerOutOfMemory
// Errors/limitations in the generated yacc and lex files
duplicateBreak:cflexor.lex
constVariablePointer:cfparse.y
memleakOnRealloc:cfparse.y
allocaCalled:cfparse.c
constParameterPointer:cfparse.c
constVariablePointer:cfparse.c
invalidPrintfArgType_sint:cfparse.c
knownConditionTrueFalse:cfparse.c
sizeofwithnumericparameter:cfparse.c
unsignedPositive:cfparse.c
constVariablePointer:<stdout>
duplicateBreak:<stdout>
nullPointer:<stdout>
redundantInitialization:<stdout>
staticFunction:<stdout>
syntaxError:<stdout>
unusedFunction:<stdout>
+3
View File
@@ -0,0 +1,3 @@
module top;
initial $display("Hello World!");
endmodule
+56 -15
View File
@@ -1,12 +1,12 @@
.TH iverilog 1 "Jan 20th, 2024" "" "Version %M.%n%E"
.TH iverilog 1 "Jan 13th, 2026" "" "Version @VERSION@"
.SH NAME
iverilog - Icarus Verilog compiler
.SH SYNOPSIS
.B iverilog
[\-EiRSuVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]]
[\-EiRSuVv] [\-B[IMPVt]path] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]]
[\-Pparameter=value] [\-pflag=value] [\-dname]
[\-g1995\:|\-g2001\:|\-g2005\:|\-g2005-sv\:|\-g2009\:|\-g2012\:|\-g<feature>]
[\-g1995\:|\-g2001\:|\-g2005\:|\-g2005-sv\:|\-g2009\:|\-g2012\:|\-g2017\:|\-g2023\:|\-g<feature>]
[\-Iincludedir] [\-Lmoduledir] [\-mmodule] [\-M[mode=]file] [\-Nfile]
[\-ooutputfilename] [\-stopmodule] [\-ttype] [\-Tmin/typ/max] [\-Wclass]
[\-ypath] [\-lfile]
@@ -21,13 +21,36 @@ further processing. The main target is \fIvvp\fP for simulation.
.SH OPTIONS
\fIiverilog\fP accepts the following options:
.TP 8
.B -B\fIbase\fP
.BI \-B path
The \fIiverilog\fP program uses external programs and configuration
files to preprocess and compile the Verilog source. Normally, the path
used to locate these tools is built into the \fIiverilog\fP
program. However, the \fB\-B\fP switch allows the user to select a
different set of programs. The path given is used to locate
\fIivlpp\fP, \fIivl\fP, code generators and the VPI modules.
files to preprocess and compile Verilog source files. Normally, the
paths used to locate these tools are built into the
\fIiverilog\fP executable. The \fB\-B\fP option allows the user to
override these paths.
The specified path is used as the default base directory for locating
\fIivlpp\fP, \fIivl\fP, code generators, configuration files, and
VPI modules.
Specialized forms of this option may be used to override individual
tool paths:
.RS
.TP
.BI \-BI path
Directory for the \fIivl\fP parser.
.TP
.BI \-BM path
Directory for VPI modules.
.TP
.BI \-BP path
Directory for the \fIivlpp\fP preprocessor.
.TP
.BI \-BV path
Directory for the \fIvhdlpp\fP VHDL preprocessor.
.TP
.BI \-Bt path
Directory used to locate target configuration files for the
\fB\-t\fP\fItarget\fP option. The configuration file name is
\fItarget\fP.conf.
.RE
.TP 8
.B -c\fIfile\fP -f\fIfile\fP
These flags specify an input file that contains a list of Verilog
@@ -47,7 +70,9 @@ Defines macro \fImacro\fP as \fIdefn\fP.
Override (i.e. defparam) a parameter in a root module. This allows the
user to override at compile time (defparam) a parameter in a root
module instance. For example, \fB\-Pmain.foo=2\fP overrides the
parameter foo in the root instance main with the value 2.
parameter foo in the root instance main with the value 2 and
\fB\-Pmain.foos='"New string value"'\fP will override the parameter
foos in the root instance main with the value "New string value".
.TP 8
.B -d\fIname\fP
Activate a class of compiler debugging messages. The \fB\-d\fP switch may
@@ -61,11 +86,11 @@ is the Verilog input, but with file inclusions and macro references
expanded and removed. This is useful, for example, to preprocess
Verilog source for use by other compilers.
.TP 8
.B -g1995\fI|\fP-g2001\fI|\fP-g2001-noconfig\fI|\fP-g2005\fI|\fP-g2005-sv\fI|\fP-g2009\fI|\fP-g2012
.B -g1995\fI|\fP-g2001\fI|\fP-g2001-noconfig\fI|\fP-g2005\fI|\fP-g2005-sv\fI|\fP-g2009\fI|\fP-g2012\fI|\fP-g2017\fI|\fP-g2023
Select the Verilog language \fIgeneration\fP to support in the compiler.
This selects between \fIIEEE1364\-1995\fP, \fIIEEE1364\-2001\fP,
\fIIEEE1364\-2005\fP, \fIIEEE1800\-2005\fP, \fIIEEE1800\-2009\fP, or
\fIIEEE1800\-2012\fP.
\fIIEEE1364\-2005\fP, \fIIEEE1800\-2005\fP, \fIIEEE1800\-2009\fP,
\fIIEEE1800\-2012\fP, \fIIEEE1800\-2017\fP, or \fIIEEE1800\-2023\fP.
Icarus Verilog currently defaults to the \fIIEEE1364\-2005\fP generation
of the language. This flag is used to restrict the language to a set of
keywords/features, this allows simulation of older Verilog code that may
@@ -122,7 +147,7 @@ to disable extended types if compiling code that clashes with the few
new keywords used to implement the type system.
.TP 8
.B -gio-range-error\fI|\fP-gno-io-range-error
The standards requires that a vectored port have matching ranges for its
The standards require that a vectored port have matching ranges for its
port declaration as well as any net/register declaration. It was common
practice in the past to only specify the range for the net/register
declaration and some tools still allow this. By default any mismatch is
@@ -148,6 +173,17 @@ parameter assignment is evaluated as a lossless expression, as is any
expression containing an unsized constant number, and unsized constant
numbers are not truncated to integer width.
.TP 8
.B -gstrict-declaration\fI|\fP-gno-strict-declaration
.TP 8
.B -gstrict-net-var-declaration\fI|\fP-gno-strict-net-var-declaration
.TP 8
.B -gstrict-parameter-declaration\fI|\fP-gno-strict-parameter-declaration
The standards require that nets, variables, and parameters are declared
lexically before they are used. Using \fB\-gno\-strict\-declaration\fP
will allow using a data object before declaration, with a warning. The
warning can be suppressed with -Wno-declaration-after-use. The option
can be applied for nets and variables and for parameters separately.
.TP 8
.B -gshared-loop-index\fI|\fP-gno-shared-loop-index
Enable (default) or disable the exclusion of for-loop control variables
from implicit event_expression lists. When enabled, if a for-loop control
@@ -365,6 +401,11 @@ This enables warnings for creation of implicit declarations. For
example, if a scalar wire X is used but not declared in the Verilog
source, this will print a warning at its first use.
.TP 8
.B declaration-after-use
This enables warnings for declarations after use, when
those are not flagged as errors (default).
.TP 8
.B macro-redefinition\fI | \fPmacro-replacement
This enables preprocessor warnings when a macro is being redefined.
@@ -643,7 +684,7 @@ Tips on using, debugging, and developing the compiler can be found at
.SH COPYRIGHT
.nf
Copyright \(co 2002\-2024 Stephen Williams
Copyright \(co 2002\-2026 Stephen Williams
This document can be freely redistributed according to the terms of the
GNU General Public License version 2.0
+75 -11
View File
@@ -1,5 +1,5 @@
const char COPYRIGHT[] =
"Copyright (c) 2000-2024 Stephen Williams ([email protected])";
"Copyright (c) 2000-2026 Stephen Williams ([email protected])";
/*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -38,8 +38,8 @@ const char NOTICE[] =
;
const char HELP[] =
"Usage: iverilog [-EiRSuvV] [-B base] [-c cmdfile|-f cmdfile]\n"
" [-g1995|-g2001|-g2005|-g2005-sv|-g2009|-g2012] [-g<feature>]\n"
"Usage: iverilog [-EiRSuvV] [-B[IMPVt] base] [-c cmdfile|-f cmdfile]\n"
" [-g1995|-g2001|-g2005|-g2005-sv|-g2009|-g2012|-g2017|-g2023] [-g<feature>]\n"
" [-D macro[=defn]] [-I includedir] [-L moduledir]\n"
" [-M [mode=]depfile] [-m module]\n"
" [-N file] [-o filename] [-p flag=value]\n"
@@ -69,6 +69,9 @@ const char HELP[] =
# include <libiberty.h>
#endif
#endif
#ifdef __APPLE__
# include <mach-o/dyld.h>
#endif
#include <fcntl.h>
#ifdef HAVE_GETOPT_H
@@ -109,6 +112,8 @@ extern void cfreset(FILE*fd, const char*path);
const char*base = 0;
const char*vpi_dir = 0;
const char*tconfig_dir = 0;
const char*ivl_dir = 0;
const char*ivlpp_dir = 0;
const char*vhdlpp_dir= 0;
const char*vhdlpp_work = 0;
@@ -134,6 +139,8 @@ const char*gen_strict_ca_eval = "no-strict-ca-eval";
const char*gen_strict_expr_width = "no-strict-expr-width";
const char*gen_shared_loop_index = "shared-loop-index";
const char*gen_verilog_ams = "no-verilog-ams";
const char*gen_strict_net_var_declaration = "strict-net-var-declaration";
const char*gen_strict_parameter_declaration = "strict-parameter-declaration";
/* Boolean: true means use a default include dir, false means don't */
int gen_std_include = 1;
@@ -142,7 +149,7 @@ int gen_std_include = 1;
of the include list. */
int gen_relative_include = 0;
char warning_flags[17] = "n";
char warning_flags[18] = "nu";
int separate_compilation_flag = 0;
@@ -335,7 +342,7 @@ static int t_version_only(void)
}
fflush(0);
snprintf(tmp, sizeof tmp, "%s%civl -V -C\"%s\" -C\"%s\"", base, sep,
snprintf(tmp, sizeof tmp, "%s%civl -V -C\"%s\" -C\"%s\"", ivl_dir, sep,
iconfig_path, iconfig_common_path);
rc = system(tmp);
if (rc != 0) {
@@ -442,7 +449,7 @@ static int t_compile(void)
#endif
/* Build the ivl command. */
snprintf(tmp, sizeof tmp, "%s%civl", base, sep);
snprintf(tmp, sizeof tmp, "%s%civl", ivl_dir, sep);
rc = strlen(tmp);
cmd = realloc(cmd, ncmd+rc+1);
strcpy(cmd+ncmd, tmp);
@@ -527,6 +534,7 @@ static void process_warning_switch(const char*name)
{
if (strcmp(name,"all") == 0) {
process_warning_switch("anachronisms");
process_warning_switch("declaration-after-use");
process_warning_switch("implicit");
process_warning_switch("implicit-dimensions");
process_warning_switch("macro-replacement");
@@ -537,6 +545,9 @@ static void process_warning_switch(const char*name)
} else if (strcmp(name,"anachronisms") == 0) {
if (! strchr(warning_flags, 'n'))
strcat(warning_flags, "n");
} else if (strcmp(name,"declaration-after-use") == 0) {
if (! strchr(warning_flags, 'u'))
strcat(warning_flags, "u");
} else if (strcmp(name,"floating-nets") == 0) {
if (! strchr(warning_flags, 'f'))
strcat(warning_flags, "f");
@@ -578,6 +589,12 @@ static void process_warning_switch(const char*name)
cp[0] = cp[1];
cp += 1;
}
} else if (strcmp(name,"no-declaration-after-use") == 0) {
char*cp = strchr(warning_flags, 'u');
if (cp) while (*cp) {
cp[0] = cp[1];
cp += 1;
}
} else if (strcmp(name,"no-floating-nets") == 0) {
char*cp = strchr(warning_flags, 'f');
if (cp) while (*cp) {
@@ -725,6 +742,12 @@ static int process_generation(const char*name)
else if (strcmp(name,"2012") == 0)
generation = "2012";
else if (strcmp(name,"2017") == 0)
generation = "2017";
else if (strcmp(name,"2023") == 0)
generation = "2023";
else if (strcmp(name,"1") == 0) { /* Deprecated: use 1995 */
generation = "1995";
gen_xtypes = "no-xtypes";
@@ -815,6 +838,26 @@ static int process_generation(const char*name)
else if (strcmp(name,"no-verilog-ams") == 0)
gen_verilog_ams = "no-verilog-ams";
else if (strcmp(name,"strict-declaration") == 0) {
gen_strict_net_var_declaration = "strict-net-var-declaration";
gen_strict_parameter_declaration = "strict-parameter-declaration";
}
else if (strcmp(name,"no-strict-declaration") == 0) {
gen_strict_net_var_declaration = "no-strict-net-var-declaration";
gen_strict_parameter_declaration = "no-strict-parameter-declaration";
}
else if (strcmp(name,"strict-net-var-declaration") == 0)
gen_strict_net_var_declaration = "strict-net-var-declaration";
else if (strcmp(name,"no-strict-net-var-declaration") == 0)
gen_strict_net_var_declaration = "no-strict-net-var-declaration";
else if (strcmp(name,"strict-parameter-declaration") == 0)
gen_strict_parameter_declaration = "strict-parameter-declaration";
else if (strcmp(name,"no-strict-parameter-declaration") == 0)
gen_strict_parameter_declaration = "no-strict-parameter-declaration";
else {
fprintf(stderr, "Unknown/Unsupported Language generation "
"%s\n\n", name);
@@ -825,6 +868,8 @@ static int process_generation(const char*name)
" 2005-sv -- IEEE1800-2005\n"
" 2009 -- IEEE1800-2009\n"
" 2012 -- IEEE1800-2012\n"
" 2017 -- IEEE1800-2017\n"
" 2023 -- IEEE1800-2023\n"
"Other generation flags:\n"
" assertions | supported-assertions | no-assertions\n"
" specify | no-specify\n"
@@ -837,7 +882,9 @@ static int process_generation(const char*name)
" io-range-error | no-io-range-error\n"
" strict-ca-eval | no-strict-ca-eval\n"
" strict-expr-width | no-strict-expr-width\n"
" shared-loop-index | no-shared-loop-index\n");
" shared-loop-index | no-shared-loop-index\n"
" strict-declaration | no-strict-declaration\n"
" [no-]strict-[net-var|parameter]-declaration\n");
return 1;
}
@@ -887,7 +934,8 @@ static void add_env_vpi_module_path(const char*path)
static void get_env_vpi_module_paths(void)
{
char *var = getenv("IVERILOG_VPI_MODULE_PATH");
char *ptr, *end;
char *ptr;
const char *end;
if (!var)
return;
@@ -1178,6 +1226,9 @@ int main(int argc, char **argv)
character of the path indicates which path the
user is specifying. */
switch (optarg[0]) {
case 'I': /* Path for the ivl parser */
ivl_dir = optarg+1;
break;
case 'M': /* Path for the VPI modules */
vpi_dir = optarg+1;
break;
@@ -1187,6 +1238,9 @@ int main(int argc, char **argv)
case 'V': /* Path for the vhdlpp VHDL processor */
vhdlpp_dir = optarg+1;
break;
case 't': /* Path to target.conf for the -ttarget option */
tconfig_dir = optarg+1;
break;
default: /* Otherwise, this is a default base. */
base=optarg;
break;
@@ -1329,8 +1383,12 @@ int main(int argc, char **argv)
vpi_dir = base;
if (ivlpp_dir == 0)
ivlpp_dir = base;
if (ivl_dir == 0)
ivl_dir = base;
if (vhdlpp_dir == 0)
vhdlpp_dir = base;
if (tconfig_dir == 0)
tconfig_dir = base;
if (version_flag || verbose_flag) {
printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n");
@@ -1340,7 +1398,7 @@ int main(int argc, char **argv)
/* Make a common conf file path to reflect the target. */
snprintf(iconfig_common_path, sizeof iconfig_common_path, "%s%c%s%s.conf",
base, sep, targ, synth_flag? "-s" : "");
tconfig_dir, sep, targ, synth_flag? "-s" : "");
/* Write values to the iconfig file. */
fprintf(iconfig_file, "basedir:%s\n", base);
@@ -1350,11 +1408,13 @@ int main(int argc, char **argv)
fprintf(iconfig_file, "module:%s%cvhdl_sys.vpi\n", vpi_dir, sep);
fprintf(iconfig_file, "module:%s%cvhdl_textio.vpi\n", vpi_dir, sep);
/* If verilog-2005/09/12 is enabled or icarus-misc or verilog-ams,
/* If verilog-2005/09/12/17/23 is enabled or icarus-misc or verilog-ams,
* then include the v2005_math library. */
if (strcmp(generation, "2005") == 0 ||
strcmp(generation, "2009") == 0 ||
strcmp(generation, "2012") == 0 ||
strcmp(generation, "2017") == 0 ||
strcmp(generation, "2023") == 0 ||
strcmp(gen_icarus, "icarus-misc") == 0 ||
strcmp(gen_verilog_ams, "verilog-ams") == 0) {
fprintf(iconfig_file, "module:%s%cv2005_math.vpi\n", vpi_dir, sep);
@@ -1369,7 +1429,9 @@ int main(int argc, char **argv)
v2009 module. */
if (strcmp(generation, "2005-sv") == 0 ||
strcmp(generation, "2009") == 0 ||
strcmp(generation, "2012") == 0) {
strcmp(generation, "2012") == 0 ||
strcmp(generation, "2017") == 0 ||
strcmp(generation, "2023") == 0) {
fprintf(iconfig_file, "module:%s%cv2009.vpi\n", vpi_dir, sep);
}
@@ -1384,6 +1446,8 @@ int main(int argc, char **argv)
fprintf(iconfig_file, "generation:%s\n", gen_strict_expr_width);
fprintf(iconfig_file, "generation:%s\n", gen_shared_loop_index);
fprintf(iconfig_file, "generation:%s\n", gen_verilog_ams);
fprintf(iconfig_file, "generation:%s\n", gen_strict_net_var_declaration);
fprintf(iconfig_file, "generation:%s\n", gen_strict_parameter_declaration);
fprintf(iconfig_file, "generation:%s\n", gen_icarus);
fprintf(iconfig_file, "warnings:%s\n", warning_flags);
fprintf(iconfig_file, "ignore_missing_modules:%s\n", ignore_missing_modules ? "true" : "false");
+2 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2010 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2026 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -37,7 +37,7 @@ char* substitutions(const char*str)
it in the destination with the contents of the
environment variable x. */
char*name;
char*value;
const char*value;
const char*ep = strchr(str, (str[1]=='(') ? ')' : '}');
str += 2;
+3 -1
View File
@@ -235,7 +235,9 @@ NetESelect* NetESelect::dup_expr() const
NetESFunc* NetESFunc::dup_expr() const
{
NetESFunc*tmp = new NetESFunc(name_, type_, expr_width(), nparms(), is_overridden_);
NetESFunc*tmp = net_type()
? new NetESFunc(name_, net_type(), nparms())
: new NetESFunc(name_, type_, expr_width(), nparms(), is_overridden_);
ivl_assert(*this, tmp);
tmp->cast_signed(has_sign());
+1698 -738
View File
File diff suppressed because it is too large Load Diff
+46 -20
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2024 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2026 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@@ -133,11 +133,13 @@ NetAssign_* PEConcat::elaborate_lval(Design*des,
the compiler catch more errors. */
if (tmp == 0) continue;
if (tmp->expr_type() == IVL_VT_REAL) {
ivl_type_t tmp_type = tmp->net_type();
if (tmp_type && !tmp_type->packed()) {
cerr << parms_[idx]->get_fileline() << ": error: "
<< "concatenation operand can not be real: "
<< "concatenation operand must be packed: "
<< *parms_[idx] << endl;
des->errors += 1;
delete tmp;
continue;
}
@@ -174,10 +176,13 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
}
symbol_search_results sr;
symbol_search(this, des, scope, path_, lexical_pos_, &sr);
symbol_search(this, des, scope, path_, lexical_pos(), &sr);
if (!sr.require_non_type(this, des, "as a procedural l-value"))
return nullptr;
NetNet *reg = sr.net;
pform_name_t &member_path = sr.path_tail;
const pform_name_t &member_path = sr.path_tail;
/* The l-value must be a variable. If not, then give up and
print a useful error message. */
@@ -254,7 +259,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
NetAssign_*PEIdent::elaborate_lval_var_(Design *des, NetScope *scope,
bool is_force, bool is_cassign,
NetNet *reg, ivl_type_t data_type,
pform_name_t tail_path) const
const pform_name_t tail_path) const
{
// We are processing the tail of a string of names. For
// example, the Verilog may be "a.b.c", so we are processing
@@ -296,6 +301,15 @@ NetAssign_*PEIdent::elaborate_lval_var_(Design *des, NetScope *scope,
// Past this point, we should have taken care of the cases
// where the name is a member/method of a struct/class.
// XXXX ivl_assert(*this, method_name.nil());
if (!tail_path.empty()) {
cerr << get_fileline() << ": error: Variable "
<< reg->name()
<< " does not have a field named: "
<< tail_path << "." << endl;
des->errors += 1;
return nullptr;
}
ivl_assert(*this, tail_path.empty());
bool need_const_idx = is_cassign || is_force;
@@ -475,7 +489,7 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
if ((reg->type()==NetNet::UNRESOLVED_WIRE) && !is_force) {
ivl_assert(*this, reg->coerced_to_uwire());
NetEConst*canon_const = dynamic_cast<NetEConst*>(canon_index);
const NetEConst*canon_const = dynamic_cast<NetEConst*>(canon_index);
if (!canon_const || reg->test_part_driven(reg->vector_width() - 1, 0,
canon_const->value().as_long())) {
report_mixed_assignment_conflict_("array word");
@@ -556,7 +570,7 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
return false;
}
if (NetEConst*index_con = dynamic_cast<NetEConst*> (mux)) {
if (const NetEConst*index_con = dynamic_cast<NetEConst*> (mux)) {
// The index has a constant defined value.
if (index_con->value().is_defined()) {
lsb = index_con->value().as_long();
@@ -761,8 +775,7 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
// values into msb and lsb.
long msb, lsb;
bool parts_defined_flag;
bool flag = calculate_parts_(des, scope, msb, lsb, parts_defined_flag);
if (!flag) return false;
calculate_parts_(des, scope, msb, lsb, parts_defined_flag);
NetNet*reg = lv->sig();
ivl_assert(*this, reg);
@@ -882,8 +895,10 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
calculate_up_do_width_(des, scope, wid);
NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1);
if (!base)
return false;
if (base && base->expr_type() == IVL_VT_REAL) {
if (base->expr_type() == IVL_VT_REAL) {
cerr << get_fileline() << ": error: Indexed part select base "
"expression for ";
cerr << lv->sig()->name() << "[" << *base;
@@ -901,7 +916,7 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
// Handle the special case that the base is constant. For this
// case we can reduce the expression.
if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
if (const NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
// For the undefined case just let the constant pass and
// we will handle it in the code generator.
if (base_c->value().is_defined()) {
@@ -1120,18 +1135,27 @@ NetAssign_* PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*scope
// part of the sig, as the l-value.
NetNet*psig = class_type->find_static_property(method_name);
ivl_assert(*this, psig);
if (psig->get_const()) {
cerr << get_fileline() << ": error: Assignment to const signal `"
<< psig->name() << "` is not allowed." << endl;
des->errors++;
return nullptr;
}
lv = new NetAssign_(psig);
return lv;
} else if (qual.test_const()) {
auto method_scope = find_method_containing_scope(*this, scope);
if (class_type->get_prop_initialized(pidx)) {
cerr << get_fileline() << ": error: "
<< "Property " << class_type->get_prop_name(pidx)
<< " is constant in this method."
<< " (scope=" << scope_path(scope) << ")" << endl;
des->errors++;
} else if (scope->basename() != "new" && scope->basename() != "new@") {
} else if (!method_scope ||
(method_scope->basename() != "new" &&
method_scope->basename() != "new@")) {
cerr << get_fileline() << ": error: "
<< "Property " << class_type->get_prop_name(pidx)
<< " is constant in this method."
@@ -1445,14 +1469,18 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
// possibly iterate through more of the member_path.
ivl_assert(*this, array->packed());
ivl_assert(*this, !member_comp.index.empty());
if (member_comp.index.empty()) {
struct_type = 0;
continue;
}
// These are the dimensions defined by the type
const netranges_t&mem_packed_dims = array->static_dimensions();
if (member_comp.index.size() != mem_packed_dims.size()) {
if (member_comp.index.size() > mem_packed_dims.size()) {
cerr << get_fileline() << ": error: "
<< "Incorrect number of index expressions for member "
<< "Too many index expressions for member "
<< member_name << "." << endl;
des->errors += 1;
return false;
@@ -1502,11 +1530,9 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
// The width and offset calculated from the
// indices is actually in elements, and not
// bits. In fact, in this context, the lwid should
// come down to 1 (one element).
// bits.
off += loff * element_width;
ivl_assert(*this, lwid==1);
use_width = element_width;
use_width = lwid * element_width;
// To move on to the next component in the member
// path, get the element type. For example, for
+89 -46
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2024 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2026 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@@ -43,7 +43,8 @@ using namespace std;
* make the l-value connections.
*/
NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
bool bidirectional_flag) const
bool bidirectional_flag,
bool var_allowed_in_sv) const
{
ivl_assert(*this, scope);
@@ -76,22 +77,28 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
}
if (bidirectional_flag) {
nets[idx] = parms_[idx]->elaborate_bi_net(des, scope);
nets[idx] = parms_[idx]->elaborate_bi_net(des, scope, var_allowed_in_sv);
} else {
nets[idx] = parms_[idx]->elaborate_lnet(des, scope);
nets[idx] = parms_[idx]->elaborate_lnet(des, scope, var_allowed_in_sv);
}
if (nets[idx] == 0) {
errors += 1;
} else if (nets[idx]->data_type() == IVL_VT_REAL) {
cerr << parms_[idx]->get_fileline() << ": error: "
<< "concatenation operand can no be real: "
<< *parms_[idx] << endl;
errors += 1;
continue;
} else {
width += nets[idx]->vector_width();
}
ivl_type_t tmp_type = nets[idx]->array_type();
if (!tmp_type)
tmp_type = nets[idx]->net_type();
if (tmp_type && !tmp_type->packed()) {
cerr << parms_[idx]->get_fileline() << ": error: "
<< "concatenation operand must be packed: "
<< *parms_[idx] << endl;
errors += 1;
continue;
}
width += nets[idx]->vector_width();
}
}
if (errors) {
@@ -104,7 +111,7 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
concat operator from most significant to least significant,
which is the order they are given in the concat list. */
netvector_t*tmp2_vec = new netvector_t(nets[0]->data_type(),width-1,0);
const netvector_t*tmp2_vec = new netvector_t(nets[0]->data_type(),width-1,0);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, tmp2_vec);
@@ -163,14 +170,16 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
return osig;
}
NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope) const
NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
bool var_allowed_in_sv) const
{
return elaborate_lnet_common_(des, scope, false);
return elaborate_lnet_common_(des, scope, false, var_allowed_in_sv);
}
NetNet* PEConcat::elaborate_bi_net(Design*des, NetScope*scope) const
NetNet* PEConcat::elaborate_bi_net(Design*des, NetScope*scope,
bool var_allowed_in_sv) const
{
return elaborate_lnet_common_(des, scope, true);
return elaborate_lnet_common_(des, scope, true, var_allowed_in_sv);
}
bool PEConcat::is_collapsible_net(Design*des, NetScope*scope,
@@ -203,7 +212,7 @@ bool PEConcat::is_collapsible_net(Design*des, NetScope*scope,
* results, which may be the whole vector, or a single bit, or
* anything in between. The values are in canonical indices.
*/
bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
bool PEIdent::eval_part_select_(Design*des, NetScope*scope, const NetNet*sig,
long&midx, long&lidx) const
{
list<long> prefix_indices;
@@ -234,7 +243,7 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
case index_component_t::SEL_IDX_DO:
case index_component_t::SEL_IDX_UP: {
NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1, true);
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
const NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
if (!tmp) {
cerr << get_fileline() << ": error: Indexed part select "
"base expression must be a constant integral value "
@@ -518,12 +527,17 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
* so most of the work for both is done here.
*/
NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
bool bidirectional_flag) const
bool bidirectional_flag,
bool var_allowed_in_sv) const
{
ivl_assert(*this, scope);
symbol_search_results sr;
symbol_search(this, des, scope, path_.name, lexical_pos_, &sr);
symbol_search(this, des, scope, path_.name, lexical_pos(), &sr);
if (!sr.require_non_type(this, des,
"as a continuous assignment l-value"))
return nullptr;
if (sr.eve != 0) {
cerr << get_fileline() << ": error: named events (" << path_
@@ -540,6 +554,10 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
if (sig == 0) {
cerr << get_fileline() << ": error: Net " << path_
<< " is not defined in this context." << endl;
if (sr.is_found()) {
cerr << sr.scope->get_fileline() << ": : Found a "
<< sr.result_type() << " with this name here." << endl;
}
if (sr.decl_after_use) {
cerr << sr.decl_after_use->get_fileline() << ": : "
"A symbol with that name was declared here. "
@@ -549,6 +567,9 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
return 0;
}
if (!check_interface_modport_access(this, des, sr, true))
return 0;
if (debug_elaborate) {
cerr << get_fileline() << ": " << __func__ << ": "
<< "Found l-value path_=" << path_
@@ -569,7 +590,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
// If this is SystemVerilog and the variable is not yet
// assigned by anything, then convert it to an unresolved
// wire.
if (gn_var_can_be_uwire()
if (gn_var_can_be_uwire() && var_allowed_in_sv
&& (sig->type() == NetNet::REG)
&& (sig->peek_lref() == 0) ) {
sig->type(NetNet::UNRESOLVED_WIRE);
@@ -577,11 +598,22 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
// Don't allow registers as assign l-values.
if (sig->type() == NetNet::REG) {
cerr << get_fileline() << ": error: reg " << sig->name()
<< "; cannot be driven by primitives"
<< " or continuous assignment." << endl;
cerr << get_fileline() << ": error: Variable '" << sig->name()
<< "' cannot be driven by a ";
if (var_allowed_in_sv) cerr << "continuous assignment/module";
else cerr << "primitive";
if (gn_var_can_be_uwire()) {
cerr << " or continuous assignment with non-default strength." << endl;
} else {
cerr << "." << endl;
if (var_allowed_in_sv) {
cerr << get_fileline() << ": : "
<< "This is allowed when SystemVerilog is enabled."
<< endl;
}
}
des->errors += 1;
return 0;
return nullptr;
}
// Some parts below need the tail component. This is a convenient
@@ -597,7 +629,8 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
// array word assignment.
bool widx_flag = false;
list<long> unpacked_indices_const;
// Whether the signal is an array
const bool sig_is_array = sig->unpacked_dimensions() > 0;
// Detect the net is a structure and there was a method path
// detected. We have already broken the path_ into the path to
@@ -666,6 +699,8 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
return 0;
}
use_path.pop_front();
member_off += tmp_off;
member_width = member->net_type->packed_width();
@@ -673,9 +708,8 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
struct_type = tmp_struct;
} else {
struct_type = 0;
assert (use_path.empty());
}
use_path.pop_front();
}
// Look for part selects on the final member. For example if
@@ -724,7 +758,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
member_select.sel = index_component_t::SEL_BIT;
member_select.msb = new PENumber(new verinum(member_off));
tmp_index.push_back(member_select);
NetExpr*packed_base = collapse_array_indices(des, scope, sig, tmp_index);
const NetExpr*packed_base = collapse_array_indices(des, scope, sig, tmp_index);
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
@@ -733,7 +767,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
}
}
} else if (gn_system_verilog() && sig->unpacked_dimensions() > 0 && path_tail.index.empty()) {
} else if (gn_system_verilog() && sig_is_array && path_tail.index.empty()) {
// In this case, we are doing a continuous assignment to
// an unpacked array. The NetNet representation is a
@@ -743,21 +777,24 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
// This can come up from code like this:
// logic [...] data [0:3];
// assign data = ...;
// In this case, "sig" is "data", and sig->pin_count()
// is 4 to account for the unpacked size.
// In this case, "sig" is "data".
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
<< "Net assign to unpacked array \"" << sig->name()
<< "\" with " << sig->pin_count() << " elements." << endl;
}
} else if (sig->unpacked_dimensions() > 0) {
} else if (sig_is_array) {
list<long> unpacked_indices_const;
// Make sure there are enough indices to address an array element.
if (path_tail.index.size() < sig->unpacked_dimensions()) {
cerr << get_fileline() << ": error: Array " << path()
<< " needs " << sig->unpacked_dimensions() << " indices,"
<< " but got only " << path_tail.index.size() << ". (net)" << endl;
cerr << get_fileline() << ": : Assignment to a whole array requires SystemVerilog."
<< endl;
des->errors += 1;
return 0;
}
@@ -804,7 +841,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
widx_flag = true;
} else {
NetEConst*canon_const = dynamic_cast<NetEConst*>(canon_index);
const NetEConst*canon_const = dynamic_cast<NetEConst*>(canon_index);
ivl_assert(*this, canon_const);
widx = canon_const->value().as_long();
@@ -909,7 +946,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
}
}
if (sig->pin_count() > 1 && widx_flag) {
if (sig_is_array && widx_flag) {
if (widx < 0 || widx >= (long) sig->pin_count())
return 0;
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
@@ -919,7 +956,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
connect(sig->pin(widx), tmp->pin(0));
sig = tmp;
} else if (sig->pin_count() > 1) {
} else if (sig_is_array) {
// If this turns out to be an l-value unpacked array,
// then let the caller handle it. It will probably be
@@ -946,8 +983,8 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
<< " wid=" << subnet_wid <<"]"
<< endl;
netvector_t*tmp2_vec = new netvector_t(sig->data_type(),
subnet_wid-1,0);
const netvector_t*tmp2_vec = new netvector_t(sig->data_type(),
subnet_wid-1,0);
NetNet*subsig = new NetNet(sig->scope(),
sig->scope()->local_symbol(),
NetNet::WIRE, tmp2_vec);
@@ -982,14 +1019,16 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
* Identifiers in continuous assignment l-values are limited to wires
* and that ilk. Detect registers and memories here and report errors.
*/
NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope) const
NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope,
bool var_allowed_in_sv) const
{
return elaborate_lnet_common_(des, scope, false);
return elaborate_lnet_common_(des, scope, false, var_allowed_in_sv);
}
NetNet* PEIdent::elaborate_bi_net(Design*des, NetScope*scope) const
NetNet* PEIdent::elaborate_bi_net(Design*des, NetScope*scope,
bool var_allowed_in_sv) const
{
return elaborate_lnet_common_(des, scope, true);
return elaborate_lnet_common_(des, scope, true, var_allowed_in_sv);
}
/*
@@ -1091,7 +1130,7 @@ NetNet* PEIdent::elaborate_subport(Design*des, NetScope*scope) const
unsigned swid = abs(midx - lidx) + 1;
ivl_assert(*this, swid > 0 && swid < sig->vector_width());
netvector_t*tmp2_vec = new netvector_t(sig->data_type(),swid-1,0);
const netvector_t*tmp2_vec = new netvector_t(sig->data_type(),swid-1,0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, tmp2_vec);
tmp->port_type(sig->port_type());
@@ -1138,10 +1177,14 @@ NetNet* PEIdent::elaborate_subport(Design*des, NetScope*scope) const
NetNet*PEIdent::elaborate_unpacked_net(Design*des, NetScope*scope) const
{
symbol_search_results sr;
symbol_search(this, des, scope, path_, lexical_pos_, &sr);
symbol_search(this, des, scope, path_, lexical_pos(), &sr);
if (!sr.net) {
cerr << get_fileline() << ": error: Net " << path_
<< " is not defined in this context." << endl;
if (sr.is_found()) {
cerr << sr.scope->get_fileline() << ": : Found a "
<< sr.result_type() << " with this name here." << endl;
}
if (sr.decl_after_use) {
cerr << sr.decl_after_use->get_fileline() << ": : "
"A symbol with that name was declared here. "
@@ -1168,7 +1211,7 @@ bool PEIdent::is_collapsible_net(Design*des, NetScope*scope,
ivl_assert(*this, scope);
symbol_search_results sr;
symbol_search(this, des, scope, path_.name, lexical_pos_, &sr);
symbol_search(this, des, scope, path_.name, lexical_pos(), &sr);
if (sr.eve != 0)
return false;
+132 -36
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2024 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2025 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@@ -58,7 +58,7 @@
using namespace std;
void set_scope_timescale(Design*des, NetScope*scope, PScope*pscope)
void set_scope_timescale(Design*des, NetScope*scope, const PScope*pscope)
{
scope->time_unit(pscope->time_unit);
scope->time_precision(pscope->time_precision);
@@ -218,7 +218,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
// There is an explicit value. elaborate/evaluate
// the value and assign it to the enumeration name.
NetExpr*val = elab_and_eval(des, scope, cur->parm, -1);
NetEConst*val_const = dynamic_cast<NetEConst*> (val);
const NetEConst*val_const = dynamic_cast<NetEConst*> (val);
if (val_const == 0) {
cerr << use_enum->get_fileline()
<< ": error: Enumeration expression for "
@@ -241,7 +241,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
}
// If this is a literal constant and it has a defined
// width then the width must match the enumeration width.
if (PENumber *tmp = dynamic_cast<PENumber*>(cur->parm)) {
if (const PENumber *tmp = dynamic_cast<PENumber*>(cur->parm)) {
if (tmp->value().has_len() &&
(tmp->value().len() != enum_width)) {
cerr << use_enum->get_fileline()
@@ -355,7 +355,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
}
rc_flag = use_enum->insert_name(name_idx, cur->name, cur_value);
rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
rc_flag &= scope->add_enumeration_name(use_enum, cur->name, *cur);
if (! rc_flag) {
cerr << use_enum->get_fileline()
@@ -487,19 +487,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
}
const netclass_t*use_base_class = 0;
if (use_type->base_type) {
ivl_type_t base_type = use_type->base_type->elaborate_type(des, scope);
use_base_class = dynamic_cast<const netclass_t *>(base_type);
if (!use_base_class) {
cerr << pclass->get_fileline() << ": error: "
<< "Base type of " << use_type->name
<< " is not a class." << endl;
des->errors += 1;
}
}
netclass_t*use_class = new netclass_t(use_type->name, use_base_class);
netclass_t*use_class = new netclass_t(use_type->name);
NetScope*class_scope = new NetScope(scope, hname_t(pclass->pscope_name()),
NetScope::CLASS, scope->unit());
@@ -583,6 +571,43 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
scope->add_class(use_class);
}
static void elaborate_scope_class_bind_super(Design *des, NetScope *scope,
PClass *pclass)
{
auto *class_type = pclass->type;
if (!class_type->base_type)
return;
ivl_type_t elaborated_base_type =
class_type->base_type->elaborate_type(des, scope);
const auto *base_class =
dynamic_cast<const netclass_t *>(elaborated_base_type);
if (!base_class) {
cerr << pclass->get_fileline() << ": error: "
<< "Base type of " << class_type->name
<< " is not a class." << endl;
des->errors += 1;
return;
}
auto *derived_class = scope->find_class(des, class_type->name);
ivl_assert(*pclass, derived_class);
for (auto ancestor = base_class; ancestor;
ancestor = ancestor->get_super()) {
if (ancestor == derived_class) {
cerr << pclass->get_fileline() << ": error: "
<< "Inheritance cycle detected for class `"
<< class_type->name << "`." << endl;
des->errors += 1;
return;
}
}
derived_class->set_super(base_class);
}
static void elaborate_scope_classes(Design*des, NetScope*scope,
const vector<PClass*>&classes)
{
@@ -597,6 +622,9 @@ static void elaborate_scope_classes(Design*des, NetScope*scope,
blend_class_constructors(classes[idx]);
elaborate_scope_class(des, scope, classes[idx]);
}
for (auto pclass : classes)
elaborate_scope_class_bind_super(des, scope, pclass);
}
static void replace_scope_parameters(Design *des, NetScope*scope, const LineInfo&loc,
@@ -706,7 +734,7 @@ class generate_schemes_work_item_t : public elaborator_work_item_t {
: elaborator_work_item_t(des__), scope_(scope), mod_(mod)
{ }
void elaborate_runrun()
void elaborate_runrun() override
{
if (debug_scopes)
cerr << mod_->get_fileline() << ": debug: "
@@ -942,7 +970,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
while (cscope && !cscope->find_genvar(loop_index)) {
if (cscope->symbol_exists(loop_index)) {
cerr << get_fileline() << ": error: "
<< "generate loop variable '" << loop_index
<< "generate \"loop\" variable '" << loop_index
<< "' is not a genvar in this scope." << endl;
des->errors += 1;
return false;
@@ -965,10 +993,18 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
// use) the genvar itself, so we can evaluate this expression
// the same way any other parameter value is evaluated.
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1, true);
NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
const NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
if (init == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar"
<< " init expression: " << *loop_init << endl;
cerr << get_fileline() << ": error: "
"Cannot evaluate generate \"loop\" initialization "
"expression: " << *loop_init << endl;
des->errors += 1;
return false;
}
if (! init->value().is_defined()) {
cerr << get_fileline() << ": error: "
<< "Generate \"loop\" initialization expression cannot have "
"undefined bits. given (" << *loop_init << ")." << endl;
des->errors += 1;
return false;
}
@@ -979,16 +1015,25 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
if (debug_scopes)
cerr << get_fileline() << ": debug: genvar init = " << genvar << endl;
container->genvar_tmp = loop_index;
container->genvar_tmp_val = genvar;
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1, true);
NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
const NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
if (test == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar"
<< " conditional expression: " << *loop_test << endl;
cerr << get_fileline() << ": error: Cannot evaluate generate \"loop\" "
"conditional expression: " << *loop_test << endl;
des->errors += 1;
return false;
}
if (! test->value().is_defined()) {
cerr << get_fileline() << ": error: "
"Generate \"loop\" conditional expression cannot have "
"undefined bits. given (" << *loop_test << ")." << endl;
des->errors += 1;
return false;
}
unsigned long loop_count = 1;
while (test->value().as_long()) {
// The actual name of the scope includes the genvar so
@@ -996,10 +1041,17 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
// container. The format of using [] is part of the
// Verilog standard.
hname_t use_name (scope_name, genvar);
if (container->child(use_name)) {
cerr << get_fileline() << ": error: "
"Trying to create a duplicate generate scope named \""
<< use_name << "\"." << endl;
des->errors += 1;
return false;
}
if (debug_scopes)
cerr << get_fileline() << ": debug: "
<< "Create generated scope " << use_name << endl;
"Create generated scope " << use_name << endl;
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
@@ -1025,7 +1077,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
scope->set_parameter(loop_index, gp, *this);
if (debug_scopes)
cerr << get_fileline() << ": debug: "
<< "Create implicit localparam "
"Create implicit localparam "
<< loop_index << " = " << genvar_verinum << endl;
}
@@ -1035,8 +1087,8 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1, true);
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
if (step == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar"
<< " step expression: " << *loop_step << endl;
cerr << get_fileline() << ": error: Cannot evaluate generate "
"\"loop\" increment expression: " << *loop_step << endl;
des->errors += 1;
return false;
}
@@ -1044,7 +1096,24 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
cerr << get_fileline() << ": debug: genvar step from "
<< genvar << " to " << step->value().as_long() << endl;
genvar = step->value().as_long();
if (! step->value().is_defined()) {
cerr << get_fileline() << ": error: "
"Generate \"loop\" increment expression cannot have "
"undefined bits, given (" << *loop_step << ")." << endl;
des->errors += 1;
return false;
}
long next_genvar;
next_genvar = step->value().as_long();
if (next_genvar == genvar) {
cerr << get_fileline() << ": error: "
<< "The generate \"loop\" is not incrementing. The "
"previous and next genvar values are ("
<< genvar << ")." << endl;
des->errors += 1;
return false;
}
genvar = next_genvar;
check_for_valid_genvar_value_(genvar);
container->genvar_tmp_val = genvar;
delete step;
@@ -1052,6 +1121,24 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
test_ex = elab_and_eval(des, container, loop_test, -1, true);
test = dynamic_cast<NetEConst*>(test_ex);
ivl_assert(*this, test);
if (! test->value().is_defined()) {
cerr << get_fileline() << ": error: "
"The generate \"loop\" conditional expression cannot have "
"undefined bits. given (" << *loop_test << ")." << endl;
des->errors += 1;
return false;
}
// If there are half a million iterations this is likely an infinite loop!
if (loop_count > 500000) {
cerr << get_fileline() << ": error: "
<< "Probable infinite loop detected in generate \"loop\". "
"It has run for " << loop_count
<< " iterations." << endl;
des->errors += 1;
return false;
}
++loop_count;
}
// Clear the genvar_tmp field in the scope to reflect that the
@@ -1064,7 +1151,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else_flag)
{
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1, true);
NetEConst*test = dynamic_cast<NetEConst*> (test_ex);
const NetEConst*test = dynamic_cast<NetEConst*> (test_ex);
if (test == 0) {
cerr << get_fileline() << ": error: Cannot evaluate genvar"
<< " conditional expression: " << *loop_test << endl;
@@ -1263,6 +1350,10 @@ void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
collect_scope_signals(scope, wires);
elaborate_scope_enumerations(des, scope, enum_sets);
elaborate_scope_classes(des, scope, classes_lexical);
// Run through the defparams for this scope and save the result
// in a table for later final override.
@@ -1321,9 +1412,9 @@ class delayed_elaborate_scope_mod_instances : public elaborator_work_item_t {
NetScope*sc)
: elaborator_work_item_t(des__), obj_(obj), mod_(mod), sc_(sc)
{ }
~delayed_elaborate_scope_mod_instances() { }
~delayed_elaborate_scope_mod_instances() override { }
virtual void elaborate_runrun();
virtual void elaborate_runrun() override;
private:
const PGModule*obj_;
@@ -1577,7 +1668,6 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
void PEvent::elaborate_scope(Design*, NetScope*scope) const
{
NetEvent*ev = new NetEvent(name_);
ev->lexical_pos(lexical_pos_);
ev->set_line(*this);
scope->add_event(ev);
}
@@ -1603,6 +1693,8 @@ void PFunction::elaborate_scope(Design*des, NetScope*scope) const
collect_scope_signals(scope, wires);
elaborate_scope_enumerations(des, scope, enum_sets);
// Scan through all the named events in this scope.
elaborate_scope_events_(des, scope, events);
@@ -1623,6 +1715,8 @@ void PTask::elaborate_scope(Design*des, NetScope*scope) const
collect_scope_signals(scope, wires);
elaborate_scope_enumerations(des, scope, enum_sets);
// Scan through all the named events in this scope.
elaborate_scope_events_(des, scope, events);
@@ -1673,6 +1767,8 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
collect_scope_signals(my_scope, wires);
elaborate_scope_enumerations(des, my_scope, enum_sets);
// Scan through all the named events in this scope.
elaborate_scope_events_(des, my_scope, events);
}
@@ -1692,7 +1788,7 @@ void PCase::elaborate_scope(Design*des, NetScope*scope) const
for (unsigned idx = 0 ; idx < (*items_).size() ; idx += 1) {
ivl_assert(*this, (*items_)[idx]);
if (Statement*sp = (*items_)[idx]->stat)
if (const Statement*sp = (*items_)[idx]->stat)
sp -> elaborate_scope(des, scope);
}
}
+50 -38
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2024 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2026 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@@ -44,6 +44,7 @@
# include "netqueue.h"
# include "netscalar.h"
# include "util.h"
# include "parse_api.h"
# include "ivl_assert.h"
using namespace std;
@@ -90,8 +91,8 @@ void Statement::elaborate_sig(Design*, NetScope*) const
{
}
static void sig_check_data_type(Design*des, NetScope*scope,
PWire *wire, NetNet *sig)
static void sig_check_data_type(Design*des, const NetScope*scope,
const PWire *wire, NetNet *sig)
{
ivl_type_t type = sig->net_type();
@@ -141,8 +142,8 @@ static void sig_check_data_type(Design*des, NetScope*scope,
}
}
static void sig_check_port_type(Design*des, NetScope*scope,
PWire *wire, NetNet *sig)
static void sig_check_port_type(Design*des, const NetScope*scope,
const PWire *wire, const NetNet *sig)
{
if (sig->port_type() == NetNet::PREF) {
cerr << wire->get_fileline() << ": sorry: "
@@ -298,6 +299,12 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
if (pp == 0)
continue;
if (pp->is_interface_port()) {
interface_formal_port_t formal;
resolve_interface_formal_port(this, des, pp, formal, true);
continue;
}
// The port has a name and an array of expressions. The
// expression are all identifiers that should reference
// wires within the scope.
@@ -397,11 +404,6 @@ void netclass_t::elaborate_sig(Design*des, PClass*pclass)
<< " type=" << *use_type << endl;
}
if (dynamic_cast<const netqueue_t *> (use_type)) {
cerr << cur->second.get_fileline() << ": sorry: "
<< "Queues inside classes are not yet supported." << endl;
des->errors++;
}
set_property(cur->first, cur->second.qual, use_type);
if (! cur->second.qual.test_static())
@@ -414,8 +416,17 @@ void netclass_t::elaborate_sig(Design*des, PClass*pclass)
<< "." << endl;
}
/* NetNet*sig = */ new NetNet(class_scope_, cur->first, NetNet::REG,
use_type);
auto sig = new NetNet(class_scope_, cur->first, NetNet::REG,
use_type);
sig->set_line(cur->second);
sig->set_const(cur->second.qual.test_const());
if (cur->second.qual.test_const() &&
cur->second.has_initializer) {
int pidx = property_idx_from_name(cur->first);
ivl_assert(cur->second, pidx >= 0);
set_prop_initialized(pidx);
}
}
for (map<perm_string,PFunction*>::iterator cur = pclass->funcs.begin()
@@ -449,23 +460,19 @@ bool PGate::elaborate_sig(Design*, NetScope*) const
return true;
}
bool PGBuiltin::elaborate_sig(Design*, NetScope*) const
{
return true;
}
bool PGAssign::elaborate_sig(Design*, NetScope*) const
{
return true;
}
bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
Module*rmod) const
const Module*rmod) const
{
bool flag = true;
NetScope::scope_vec_t instance = scope->instance_arrays[get_name()];
vector<PExpr*>pins (rmod->port_count());
vector<bool>pins_fromwc (rmod->port_count(), false);
vector<bool>pins_is_explicitly_not_connected (rmod->port_count(), false);
flag &= match_module_ports_(des, rmod, scope, pins, pins_fromwc,
pins_is_explicitly_not_connected);
for (unsigned idx = 0 ; idx < instance.size() ; idx += 1) {
// I know a priori that the elaborate_scope created the scope
// already, so just look it up as a child of the current scope.
@@ -481,6 +488,9 @@ bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
}
ivl_assert(*this, my_scope->parent() == scope);
if (!bind_interface_ports_(des, rmod, scope, my_scope, pins, pins_fromwc))
flag = false;
if (! rmod->elaborate_sig(des, my_scope))
flag = false;
@@ -517,7 +527,7 @@ bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; ++ cur ) {
PGenerate*item = *cur;
const PGenerate*item = *cur;
if (item->directly_nested || !item->scope_list_.empty()) {
flag &= item->elaborate_sig(des, container);
}
@@ -538,7 +548,7 @@ bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
cerr << get_fileline() << ": debug: Elaborate nets in "
<< "scope " << scope_path(*cur)
<< " in generate " << id_number << endl;
flag = elaborate_sig_(des, *cur) & flag;
flag &= elaborate_sig_(des, *cur) && flag;
}
return flag;
@@ -565,7 +575,7 @@ bool PGenerate::elaborate_sig_direct_(Design*des, NetScope*container) const
if (item->scheme_type == PGenerate::GS_CASE) {
for (generate_it_t icur = item->generate_schemes.begin()
; icur != item->generate_schemes.end() ; ++ icur ) {
PGenerate*case_item = *icur;
const PGenerate*case_item = *icur;
if (case_item->directly_nested || !case_item->scope_list_.empty()) {
flag &= case_item->elaborate_sig(des, container);
}
@@ -584,6 +594,7 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
{
// Scan the declared PWires to elaborate the obvious signals
// in the current scope.
bool flag = true;
typedef map<perm_string,PWire*>::const_iterator wires_it_t;
for (wires_it_t wt = wires.begin()
; wt != wires.end() ; ++ wt ) {
@@ -594,32 +605,34 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
cerr << get_fileline() << ": debug: Elaborate PWire "
<< cur->basename() << " in scope " << scope_path(scope) << endl;
cur->elaborate_sig(des, scope);
const NetNet* res = cur->elaborate_sig(des, scope);
flag &= (res != nullptr);
}
elaborate_sig_funcs(des, scope, funcs);
elaborate_sig_tasks(des, scope, tasks);
elaborate_sig_classes(des, scope, classes);
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; ++ cur ) {
(*cur) -> elaborate_sig(des, scope);
flag &= (*cur)->elaborate_sig(des, scope);
}
typedef list<PGate*>::const_iterator pgate_list_it_t;
for (pgate_list_it_t cur = gates.begin()
; cur != gates.end() ; ++ cur ) {
(*cur) ->elaborate_sig(des, scope);
flag &= (*cur)->elaborate_sig(des, scope);
}
typedef list<PProcess*>::const_iterator proc_it_t;
for (proc_it_t cur = behaviors.begin()
; cur != behaviors.end() ; ++ cur ) {
(*cur) -> statement() -> elaborate_sig(des, scope);
(*cur)->statement()->elaborate_sig(des, scope);
}
return true;
return flag;
}
@@ -671,7 +684,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
ivl_assert(*this, ret_type);
}
} else {
netvector_t*tmp = new netvector_t(IVL_VT_LOGIC);
const netvector_t*tmp = new netvector_t(IVL_VT_LOGIC);
ret_type = tmp;
}
@@ -970,7 +983,7 @@ bool test_ranges_eeq(const netranges_t&lef, const netranges_t&rig)
ivl_type_t PWire::elaborate_type(Design*des, NetScope*scope,
const netranges_t &packed_dimensions) const
{
vector_type_t *vec_type = dynamic_cast<vector_type_t*>(set_data_type_.get());
const vector_type_t *vec_type = dynamic_cast<vector_type_t*>(set_data_type_.get());
if (set_data_type_ && !vec_type) {
ivl_assert(*this, packed_dimensions.empty());
return set_data_type_->elaborate_type(des, scope);
@@ -1156,8 +1169,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope)
}
unsigned nattrib = 0;
attrib_list_t*attrib_list = evaluate_attributes(attributes, nattrib,
des, scope);
const attrib_list_t*attrib_list = evaluate_attributes(attributes, nattrib,
des, scope);
/* If the net type is supply0 or supply1, replace it
with a simple wire with a pulldown/pullup with supply
@@ -1189,8 +1202,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope)
pull = new NetLogic(scope, scope->local_symbol(),
1, pull_type, wid);
pull->set_line(*this);
pull->pin(0).drive0(IVL_DR_SUPPLY);
pull->pin(0).drive1(IVL_DR_SUPPLY);
pull->pin(0).drive(drive_strength_t(IVL_DR_SUPPLY,
IVL_DR_SUPPLY));
des->add_node(pull);
wtype = NetNet::WIRE;
}
@@ -1223,7 +1236,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope)
if (wtype == NetNet::WIRE) sig->devirtualize_pins();
sig->set_line(*this);
sig->port_type(port_type_);
sig->lexical_pos(lexical_pos_);
if (ivl_discipline_t dis = get_discipline()) {
sig->set_discipline(dis);
+10 -29
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2024 Stephen Williams (steve@icarus.com)
* Copyright (c) 2012-2026 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -220,11 +220,13 @@ ivl_type_t struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
res->set_line(*this);
res->packed(packed_flag);
bool is_packed = packed_flag || (union_flag && soft_flag);
res->packed(is_packed);
res->set_signed(signed_flag);
if (union_flag)
res->union_flag(true);
if (union_flag) {
res->union_flag(true, soft_flag);
}
for (list<struct_member_t*>::iterator cur = members->begin()
; cur != members->end() ; ++ cur) {
@@ -242,7 +244,7 @@ ivl_type_t struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
; cur_name != curp->names->end() ; ++ cur_name) {
decl_assignment_t*namep = *cur_name;
if (packed_flag && namep->expr) {
if (is_packed && namep->expr) {
cerr << namep->expr->get_fileline() << " error: "
<< "Packed structs must not have default member values."
<< endl;
@@ -372,9 +374,8 @@ ivl_type_t elaborate_array_type(Design *des, NetScope *scope,
type = elaborate_darray_check_type(des, li, type, "Dynamic array");
type = new netdarray_t(type);
continue;
} else if (dynamic_cast<PENull*>(lidx)) {
// Special case: Detect the mark for a QUEUE declaration,
// which is the dimensions [null:max_idx].
} else if (dynamic_cast<PEQueueDimension*>(lidx)) {
// Special case: Detect the mark for a QUEUE declaration.
type = elaborate_static_array_type(des, li, type, dimensions);
type = elaborate_queue_type(des, scope, li, type, ridx);
continue;
@@ -450,27 +451,7 @@ ivl_type_t typedef_t::elaborate_type(Design *des, NetScope *scope)
if (!elab_type)
return netvector_t::integer_type();
bool type_ok = true;
switch (basic_type) {
case ENUM:
type_ok = dynamic_cast<const netenum_t *>(elab_type);
break;
case STRUCT: {
const netstruct_t *struct_type = dynamic_cast<const netstruct_t *>(elab_type);
type_ok = struct_type && !struct_type->union_flag();
break;
}
case UNION: {
const netstruct_t *struct_type = dynamic_cast<const netstruct_t *>(elab_type);
type_ok = struct_type && struct_type->union_flag();
break;
}
case CLASS:
type_ok = dynamic_cast<const netclass_t *>(elab_type);
break;
default:
break;
}
bool type_ok = basic_type.matches(elab_type);
if (!type_ok) {
cerr << data_type->get_fileline() << " error: "
+919 -285
View File
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2021 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2025 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -391,7 +391,7 @@ void NetBlock::emit_recurse(struct target_t*tgt) const
if (last_ == 0)
return;
NetProc*cur = last_;
const NetProc*cur = last_;
do {
cur = cur->next_;
cur->emit_proc(tgt);
@@ -467,7 +467,7 @@ void NetScope::emit_scope(struct target_t*tgt) const
tgt->scope(this);
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_)
for (const NetEvent*cur = events_ ; cur ; cur = cur->snext_)
tgt->event(cur);
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
@@ -566,7 +566,7 @@ int Design::emit(struct target_t*tgt) const
// emit nodes
bool nodes_rc = true;
if (nodes_) {
NetNode*cur = nodes_->node_next_;
const NetNode*cur = nodes_->node_next_;
do {
nodes_rc = nodes_rc && cur->emit_node(tgt);
cur = cur->node_next_;
@@ -575,7 +575,7 @@ int Design::emit(struct target_t*tgt) const
bool branches_rc = true;
for (NetBranch*cur = branches_ ; cur ; cur = cur->next_) {
for (const NetBranch*cur = branches_ ; cur ; cur = cur->next_) {
branches_rc = tgt->branch(cur) && branches_rc;
}
+3 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2021 Stephen Williams (steve@icarus.com)
* Copyright (c) 2002-2025 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -58,9 +58,9 @@ attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att,
if (!tmp)
continue;
if (NetEConst *ce = dynamic_cast<NetEConst*>(tmp)) {
if (const NetEConst *ce = dynamic_cast<NetEConst*>(tmp)) {
table[idx].val = ce->value();
} else if (NetECReal *cer = dynamic_cast<NetECReal*>(tmp)) {
} else if (const NetECReal *cer = dynamic_cast<NetECReal*>(tmp)) {
table[idx].val = verinum(cer->value().as_long());
} else {
cerr << exp->get_fileline() << ": error: ``"
+32 -13
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2022 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2026 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -26,6 +26,7 @@
# include <cmath>
# include "netlist.h"
# include "netclass.h"
# include "ivl_assert.h"
# include "netmisc.h"
@@ -153,8 +154,8 @@ NetExpr* NetEBAdd::eval_tree()
// example, the expression (a + 2) - 1 can be rewritten as a + 1.
NetEBAdd*se = dynamic_cast<NetEBAdd*>(left_);
NetEConst*lc = se? dynamic_cast<NetEConst*>(se->right_) : NULL;
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
const NetEConst*lc = se? dynamic_cast<NetEConst*>(se->right_) : NULL;
const NetEConst*rc = dynamic_cast<NetEConst*>(right_);
if (lc != 0 && rc != 0) {
ivl_assert(*this, se != 0);
@@ -1194,12 +1195,12 @@ NetEConst* NetEConcat::eval_arguments_(const vector<NetExpr*>&vals,
NetEConst* NetESelect::eval_tree()
{
eval_expr(expr_);
NetEConst*expr = dynamic_cast<NetEConst*>(expr_);
const NetEConst*expr = dynamic_cast<NetEConst*>(expr_);
long bval = 0;
if (base_) {
eval_expr(base_);
NetEConst*base = dynamic_cast<NetEConst*>(base_);
const NetEConst*base = dynamic_cast<NetEConst*>(base_);
if (base == 0) return 0;
@@ -1242,11 +1243,11 @@ NetEConst* NetESelect::eval_tree()
static void print_ternary_cond(NetExpr*expr)
{
if (NetEConst*c = dynamic_cast<NetEConst*>(expr)) {
if (const NetEConst*c = dynamic_cast<NetEConst*>(expr)) {
cerr << c->value() << endl;
return;
}
if (NetECReal*c = dynamic_cast<NetECReal*>(expr)) {
if (const NetECReal*c = dynamic_cast<NetECReal*>(expr)) {
cerr << c->value() << endl;
return;
}
@@ -1687,7 +1688,7 @@ NetEConst* NetESFunc::evaluate_clog2_(const NetExpr*arg_) const
return rtn;
}
NetEConst* NetESFunc::evaluate_rtoi_(const NetExpr*arg_) const
NetEConst* NetESFunc::evaluate_rtoi_(const NetExpr*arg_)
{
const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg_);
const NetECReal*tmpr = dynamic_cast<const NetECReal*>(arg_);
@@ -1710,7 +1711,7 @@ NetEConst* NetESFunc::evaluate_rtoi_(const NetExpr*arg_) const
return new NetEConst(verinum(verinum(arg, false), integer_width));
}
NetECReal* NetESFunc::evaluate_itor_(const NetExpr*arg_) const
NetECReal* NetESFunc::evaluate_itor_(const NetExpr*arg_)
{
const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg_);
const NetECReal*tmpr = dynamic_cast<const NetECReal*>(arg_);
@@ -1727,8 +1728,7 @@ NetECReal* NetESFunc::evaluate_itor_(const NetExpr*arg_) const
return new NetECReal(verireal(0.0));
}
if (arg >= 0.0) arg = floor(arg + 0.5);
else arg = ceil(arg - 0.5);
arg = std::round(arg);
return new NetECReal(verireal(arg));
}
@@ -2140,7 +2140,7 @@ NetEConst* NetESFunc::evaluate_onehot0_(const NetExpr* arg) const
}
/* Get the number of unpacked dimensions for the given expression. */
NetEConst* NetESFunc::evaluate_unpacked_dimensions_(const NetExpr*arg) const
NetEConst* NetESFunc::evaluate_unpacked_dimensions_(const NetExpr*arg)
{
const NetESignal*esig = dynamic_cast<const NetESignal*>(arg);
long res = 0;
@@ -2183,6 +2183,25 @@ static bool get_array_info(const NetExpr*arg, long dim,
left = range.get_msb();
right = range.get_lsb();
return false;
}
/* Class property (e.g. queue field): size is dynamic; defer to runtime
* instead of folding to all-X in evaluate_array_funcs_. */
if (const NetEProperty*prop = dynamic_cast<const NetEProperty*>(arg)) {
const NetNet*obj = prop->get_sig();
const netclass_t*cls = dynamic_cast<const netclass_t*>(obj->net_type());
if (cls == 0) return true;
ivl_type_t ptype = cls->get_prop_type(prop->property_idx());
if (ptype == 0) return true;
switch (ptype->base_type()) {
case IVL_VT_DARRAY:
case IVL_VT_QUEUE:
case IVL_VT_STRING:
defer = true;
return true;
default:
break;
}
return true;
}
/* The argument must be a signal that has enough dimensions. */
const NetESignal*esig = dynamic_cast<const NetESignal*>(arg);
@@ -2499,7 +2518,7 @@ NetExpr* NetEUFunc::eval_tree()
return 0;
}
NetFuncDef*def = func_->func_def();
const NetFuncDef*def = func_->func_def();
ivl_assert(*this, def);
vector<NetExpr*>args(parms_.size());
+4 -4
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2021 Martin Whitaker (icarus@martin-whitaker.me.uk)
* Copyright (c) 2016-2025 Martin Whitaker (icarus@martin-whitaker.me.uk)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -47,9 +47,9 @@ struct exposenodes_functor : public functor_t {
unsigned count;
virtual void lpm_mux(Design*des, NetMux*obj);
virtual void lpm_part_select(Design*des, NetPartSelect*obj);
virtual void lpm_substitute(Design*des, NetSubstitute*obj);
virtual void lpm_mux(Design*des, NetMux*obj) override;
virtual void lpm_part_select(Design*des, NetPartSelect*obj) override;
virtual void lpm_substitute(Design*des, NetSubstitute*obj) override;
};
static bool expose_nexus(Nexus*nex)
+33 -33
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2024 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2025 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -31,7 +31,7 @@
using namespace std;
static NetNet* convert_to_real_const(Design*des, NetScope*scope, NetEConst*expr)
static NetNet* convert_to_real_const(Design*des, NetScope*scope, const NetEConst*expr)
{
verireal vrl(expr->value().as_double());
NetECReal rlval(vrl);
@@ -53,7 +53,7 @@ static bool process_binary_args(Design*des, NetScope*scope, NetExpr*root,
cases of constants, which can be converted more directly. */
if (left->expr_type() == IVL_VT_REAL) {
lsig = left->synthesize(des, scope, root);
} else if (NetEConst*tmpc = dynamic_cast<NetEConst*> (left)) {
} else if (const NetEConst*tmpc = dynamic_cast<NetEConst*> (left)) {
lsig = convert_to_real_const(des, scope, tmpc);
} else {
NetNet*tmp = left->synthesize(des, scope, root);
@@ -62,7 +62,7 @@ static bool process_binary_args(Design*des, NetScope*scope, NetExpr*root,
if (right->expr_type() == IVL_VT_REAL) {
rsig = right->synthesize(des, scope, root);
} else if (NetEConst*tmpc = dynamic_cast<NetEConst*> (right)) {
} else if (const NetEConst*tmpc = dynamic_cast<NetEConst*> (right)) {
rsig = convert_to_real_const(des, scope, tmpc);
} else {
NetNet*tmp = right->synthesize(des, scope, root);
@@ -177,7 +177,7 @@ NetNet* NetEBBits::synthesize(Design*des, NetScope*scope, NetExpr*root)
rsig = pad_to_width(des, rsig, width, *this);
ivl_assert(*this, lsig->vector_width() == rsig->vector_width());
netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0);
const netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
@@ -247,7 +247,7 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root)
rsig = pad_to_width(des, rsig, width, *this);
}
netvector_t*osig_vec = new netvector_t(IVL_VT_LOGIC);
const netvector_t*osig_vec = new netvector_t(IVL_VT_LOGIC);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
@@ -576,7 +576,7 @@ NetNet* NetEBLogic::synthesize(Design*des, NetScope*scope, NetExpr*root)
olog->set_line(*this);
des->add_node(olog);
netvector_t*osig_tmp = new netvector_t(expr_type());
const netvector_t*osig_tmp = new netvector_t(expr_type());
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, osig_tmp);
osig->set_line(*this);
@@ -618,7 +618,7 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root)
/* Detect the special case where the shift amount is
constant. Evaluate the shift amount, and simply reconnect
the left operand to the output, but shifted. */
if (NetEConst*rcon = dynamic_cast<NetEConst*>(right_)) {
if (const NetEConst*rcon = dynamic_cast<NetEConst*>(right_)) {
verinum shift_v = rcon->value();
long shift = shift_v.as_long();
@@ -628,7 +628,7 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root)
if (shift == 0)
return lsig;
netvector_t*osig_vec = new netvector_t(expr_type(), expr_width()-1,0);
const netvector_t*osig_vec = new netvector_t(expr_type(), expr_width()-1,0);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
@@ -650,7 +650,7 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root)
psel->set_line(*this);
des->add_node(psel);
netvector_t*psig_vec = new netvector_t(expr_type(), part_width-1, 0);
const netvector_t*psig_vec = new netvector_t(expr_type(), part_width-1, 0);
NetNet*psig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, psig_vec);
psig->set_line(*this);
@@ -678,8 +678,8 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root)
znum);
des->add_node(zcon);
netvector_t*zsig_vec = new netvector_t(osig->data_type(),
znum.len()-1, 0);
const netvector_t*zsig_vec = new netvector_t(osig->data_type(),
znum.len()-1, 0);
NetNet*zsig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, zsig_vec);
zsig->set_line(*this);
@@ -709,7 +709,7 @@ NetNet* NetEBShift::synthesize(Design*des, NetScope*scope, NetExpr*root)
if (rsig == 0) return 0;
netvector_t*osig_vec = new netvector_t(expr_type(), expr_width()-1, 0);
const netvector_t*osig_vec = new netvector_t(expr_type(), expr_width()-1, 0);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
@@ -966,7 +966,7 @@ NetNet* NetEUBits::synthesize(Design*des, NetScope*scope, NetExpr*root)
}
unsigned width = isig->vector_width();
netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0);
const netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
@@ -1009,8 +1009,8 @@ NetNet* NetEUnary::synthesize(Design*des, NetScope*scope, NetExpr*root)
if (expr_->has_sign() == false)
return sub;
netvector_t*sig_vec = new netvector_t(sub->data_type(),
sub->vector_width()-1, 0);
const netvector_t*sig_vec = new netvector_t(sub->data_type(),
sub->vector_width()-1, 0);
NetNet*sig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, sig_vec);
sig->set_line(*this);
@@ -1084,7 +1084,7 @@ NetNet* NetEUReduce::synthesize(Design*des, NetScope*scope, NetExpr*root)
gate->set_line(*this);
des->add_node(gate);
netvector_t*osig_vec = new netvector_t(expr_type());
const netvector_t*osig_vec = new netvector_t(expr_type());
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
@@ -1139,7 +1139,7 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
// Detect the special case that there is a base expression and
// it is constant. In this case we can generate fixed part selects.
if (NetEConst*base_const = dynamic_cast<NetEConst*>(base_)) {
if (const NetEConst*base_const = dynamic_cast<NetEConst*>(base_)) {
verinum base_tmp = base_const->value();
unsigned select_width = expr_width();
@@ -1194,8 +1194,8 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
des->add_node(sel);
ivl_assert(*this, select_width > 0);
netvector_t*tmp_vec = new netvector_t(sub->data_type(),
select_width-1, 0);
const netvector_t*tmp_vec = new netvector_t(sub->data_type(),
select_width-1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, tmp_vec);
tmp->set_line(*this);
@@ -1243,8 +1243,8 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
sel->set_line(*this);
des->add_node(sel);
netvector_t*tmp_vec = new netvector_t(sub->data_type(),
expr_width()-1, 0);
const netvector_t*tmp_vec = new netvector_t(sub->data_type(),
expr_width()-1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, tmp_vec);
tmp->local_flag(true);
@@ -1321,7 +1321,7 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
con->set_line(*this);
des->add_node(con);
netvector_t*tmp_vec = new netvector_t(expr_type(), pad_width-1, 0);
const netvector_t*tmp_vec = new netvector_t(expr_type(), pad_width-1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, tmp_vec);
tmp->set_line(*this);
@@ -1376,7 +1376,7 @@ NetNet* NetETernary::synthesize(Design *des, NetScope*scope, NetExpr*root)
ivl_assert(*this, csig->vector_width() == 1);
unsigned width=expr_width();
netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0);
const netvector_t*osig_vec = new netvector_t(expr_type(), width-1, 0);
NetNet*osig = new NetNet(csig->scope(), path, NetNet::IMPLICIT, osig_vec);
osig->set_line(*this);
osig->local_flag(true);
@@ -1421,8 +1421,8 @@ NetNet* NetESignal::synthesize(Design*des, NetScope*scope, NetExpr*root)
// If this is a synthesis with a specific value for the
// signal, then replace it (here) with a constant value.
if (net_->scope()==scope && net_->name()==scope->genvar_tmp) {
netvector_t*tmp_vec = new netvector_t(net_->data_type(),
net_->vector_width()-1, 0);
const netvector_t*tmp_vec = new netvector_t(net_->data_type(),
net_->vector_width()-1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, tmp_vec);
tmp->set_line(*this);
@@ -1452,8 +1452,8 @@ NetNet* NetESignal::synthesize(Design*des, NetScope*scope, NetExpr*root)
return tmp;
}
netvector_t*tmp_vec = new netvector_t(net_->data_type(),
net_->vector_width()-1, 0);
const netvector_t*tmp_vec = new netvector_t(net_->data_type(),
net_->vector_width()-1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, tmp_vec);
tmp->set_line(*this);
@@ -1462,7 +1462,7 @@ NetNet* NetESignal::synthesize(Design*des, NetScope*scope, NetExpr*root)
// For NetExpr objects, the word index is already converted to
// a canonical (lsb==0) address. Just use the index directly.
if (NetEConst*index_co = dynamic_cast<NetEConst*> (word_)) {
if (const NetEConst*index_co = dynamic_cast<NetEConst*> (word_)) {
long index = index_co->value().as_long();
connect(tmp->pin(0), net_->pin(index));
@@ -1483,7 +1483,7 @@ NetNet* NetESignal::synthesize(Design*des, NetScope*scope, NetExpr*root)
return tmp;
}
static NetEvWait* make_func_trigger(Design*des, NetScope*scope, NetExpr*root)
static NetEvWait* make_func_trigger(Design*des, NetScope*scope, const NetExpr*root)
{
NetEvWait*trigger = 0;
@@ -1611,8 +1611,8 @@ NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope, NetExpr*root)
des->add_node(net);
/* Create an output signal and connect it to the function. */
netvector_t*osig_vec = new netvector_t(result_sig_->expr_type(),
result_sig_->vector_width()-1, 0);
const netvector_t*osig_vec = new netvector_t(result_sig_->expr_type(),
result_sig_->vector_width()-1, 0);
NetNet*osig = new NetNet(scope_, scope_->local_symbol(), NetNet::WIRE,
osig_vec);
osig->set_line(*this);
@@ -1626,7 +1626,7 @@ NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope, NetExpr*root)
}
/* Connect the pins to the arguments. */
NetFuncDef*def = func_->func_def();
const NetFuncDef*def = func_->func_def();
for (unsigned idx = 0; idx < eparms.size(); idx += 1) {
unsigned width = def->port(idx)->vector_width();
NetNet*tmp;
+1
View File
@@ -337,6 +337,7 @@ ivl_type_packed_width
ivl_type_prop_name
ivl_type_prop_type
ivl_type_properties
ivl_type_queue_max
ivl_type_signed
ivl_udp_init
+22 -3
View File
@@ -1,7 +1,7 @@
#ifndef IVL_ivl_alloc_H
#define IVL_ivl_alloc_H
/*
* Copyright (C) 2010-2014 Cary R. (cygcary@yahoo.com)
* Copyright (C) 2010-2025 Cary R. (cygcary@yahoo.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,12 +21,30 @@
#ifdef __cplusplus
# include <cstdlib>
# include <cstdio>
# include <cstring>
#else
# include <stdlib.h>
# include <stdio.h>
# include <string.h>
#endif
#if defined(__GNUC__)
#if !defined(_MSC_VER)
/*
* Define a safer version of strdup().
*/
#define strdup(__ivl_str) \
({ \
char *__ivl_rtn = strdup(__ivl_str); \
/* If we run out of memory then exit with a message. */ \
if (__ivl_rtn == NULL) { \
fprintf(stderr, "%s:%d: Error: strdup() ran out of memory.\n", \
__FILE__, __LINE__); \
exit(1); \
} \
__ivl_rtn; \
})
/*
* Define a safer version of malloc().
*/
@@ -83,6 +101,7 @@
} \
__ivl_rtn; \
})
#endif
#endif // !defined(_MSC_VER)
#endif /* IVL_ivl_alloc_H */
+23 -13
View File
@@ -1,7 +1,7 @@
#ifndef IVL_ivl_dlfcn_H
#define IVL_ivl_dlfcn_H
/*
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2026 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -21,7 +21,11 @@
#if defined(__MINGW32__)
# include <windows.h>
#if defined(__cplusplus)
# include <cstdio>
#else
# include <stdio.h>
#endif
typedef void * ivl_dll_t;
#elif defined(HAVE_DLFCN_H)
# include <dlfcn.h>
@@ -32,7 +36,7 @@ typedef shl_t ivl_dll_t;
#endif
#if defined(__MINGW32__)
inline ivl_dll_t ivl_dlopen(const char *name, bool)
static inline ivl_dll_t ivl_dlopen(const char *name, bool global_flag)
{
static char full_name[4096];
unsigned long length = GetFullPathName(name, sizeof(full_name),
@@ -40,16 +44,18 @@ inline ivl_dll_t ivl_dlopen(const char *name, bool)
if ((length == 0) || (length > sizeof(full_name)))
return 0;
(void)global_flag;
return (void *)LoadLibrary(full_name);
}
inline void *ivl_dlsym(ivl_dll_t dll, const char *nm)
static inline void *ivl_dlsym(ivl_dll_t dll, const char *nm)
{ return (void *)GetProcAddress((HINSTANCE)dll,nm);}
inline void ivl_dlclose(ivl_dll_t dll)
static inline void ivl_dlclose(ivl_dll_t dll)
{ (void)FreeLibrary((HINSTANCE)dll);}
inline const char *dlerror(void)
static inline const char *dlerror(void)
{
static char msg[256];
unsigned long err = GetLastError();
@@ -66,10 +72,10 @@ inline const char *dlerror(void)
}
#elif defined(HAVE_DLFCN_H)
inline ivl_dll_t ivl_dlopen(const char*name, bool global_flag)
static inline ivl_dll_t ivl_dlopen(const char*name, bool global_flag)
{ return dlopen(name,RTLD_LAZY|(global_flag?RTLD_GLOBAL:0)); }
inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
static inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
{
void*sym = dlsym(dll, nm);
/* Not found? try without the leading _ */
@@ -78,24 +84,28 @@ inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
return sym;
}
inline void ivl_dlclose(ivl_dll_t dll)
static inline void ivl_dlclose(ivl_dll_t dll)
{ dlclose(dll); }
#elif defined(HAVE_DL_H)
inline ivl_dll_t ivl_dlopen(const char*name)
{ return shl_load(name, BIND_IMMEDIATE, 0); }
static inline ivl_dll_t ivl_dlopen(const char*name, bool global_flag)
{
(void)global_flag;
inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
return shl_load(name, BIND_IMMEDIATE, 0);
}
static inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
{
void*sym;
int rc = shl_findsym(&dll, nm, TYPE_PROCEDURE, &sym);
return (rc == 0) ? sym : 0;
}
inline void ivl_dlclose(ivl_dll_t dll)
static inline void ivl_dlclose(ivl_dll_t dll)
{ shl_unload(dll); }
inline const char*dlerror(void)
static inline const char*dlerror(void)
{ return strerror( errno ); }
#endif
+4
View File
@@ -2400,6 +2400,10 @@ extern int ivl_type_properties(ivl_type_t net);
extern const char* ivl_type_prop_name(ivl_type_t net, int idx);
extern ivl_type_t ivl_type_prop_type(ivl_type_t net, int idx);
/* Maximum element count for a queue type (0 = unbounded). Only valid
* when ivl_type_base(net) == IVL_VT_QUEUE. */
extern unsigned ivl_type_queue_max(ivl_type_t net);
#if defined(__MINGW32__) || defined (__CYGWIN__)
# define DLLEXPORT __declspec(dllexport)
+6 -2
View File
@@ -60,7 +60,11 @@ distclean: clean
rm -f Makefile config.log
cppcheck: $(O:.o=.c)
cppcheck --enable=all --std=c99 --std=c++11 -f $(INCLUDE_PATH) $^
cppcheck --enable=all --std=c99 --std=c++11 -f \
--check-level=exhaustive \
--suppressions-list=$(srcdir)/../cppcheck-global.sup \
--suppressions-list=$(srcdir)/cppcheck.sup \
--relative-paths=$(srcdir) $(INCLUDE_PATH) $^
Makefile: $(srcdir)/Makefile.in ../config.status
cd ..; ./config.status --file=ivlpp/$@
@@ -85,4 +89,4 @@ uninstall:
rm -f "$(DESTDIR)$(libdir)/ivl$(suffix)/ivlpp@EXEEXT@"
lexor.o: lexor.c globals.h
main.o: main.c globals.h $(srcdir)/../version_base.h ../version_tag.h
main.o: main.c globals.h ../version_base.h ../version_tag.h
+16
View File
@@ -0,0 +1,16 @@
// Skip the sscanf() field width limit warning
invalidscanf:lexor.lex:1495
// Skip all memory issues since they should be handled by ivl_alloc.h
memleakOnRealloc
nullPointerArithmeticOutOfMemory
nullPointerOutOfMemory
// Errors/limitations in the generated yacc and lex files
ctunullpointerOutOfMemory:lexor.lex
memleakOnRealloc:lexor.lex
nullPointerOutOfMemory:lexor.lex
constVariablePointer:<stdout>
nullPointer:<stdout>
staticFunction:<stdout>
unusedFunction:<stdout>
+552 -555
View File
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -1,5 +1,5 @@
const char COPYRIGHT[] =
"Copyright (c) 1999-2024 Stephen Williams ([email protected])";
"Copyright (c) 1999-2026 Stephen Williams ([email protected])";
/*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -73,7 +73,7 @@ unsigned vhdlpp_libdir_cnt = 0;
static char**source_list = 0;
static unsigned source_cnt = 0;
void add_source_file(const char*name)
static void add_source_file(const char*name)
{
if (source_list == 0) {
source_list = calloc(2, sizeof(char*));
@@ -245,9 +245,9 @@ int main(int argc, char*argv[])
unsigned lp;
const char*flist_path = 0;
unsigned flag_errors = 0;
char*out_path = 0;
const char*out_path = 0;
FILE*out;
char*precomp_out_path = 0;
const char*precomp_out_path = 0;
FILE*precomp_out = NULL;
/* Define preprocessor keywords that I plan to just pass. */

Some files were not shown because too many files have changed in this diff Show More