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 <lars@metafoo.de>
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 <lars@metafoo.de>
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 <lars@metafoo.de>
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 <lars@metafoo.de>
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 <lars@metafoo.de>
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 <lars@metafoo.de>
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.
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).
Add integral sum() and product() reductions, including expression
forms, for queues, dynamic arrays, and class properties.
Split from steveicarus/iverilog#1330 (part 05/6).
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 <lars@metafoo.de>
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 <lars@metafoo.de>
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 <lars@metafoo.de>
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).
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 <lars@metafoo.de>
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 <lars@metafoo.de>
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 <lars@metafoo.de>
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 <lars@metafoo.de>
`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 <lars@metafoo.de>
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 <lars@metafoo.de>
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 <lars@metafoo.de>
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 <lars@metafoo.de>
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 <lars@metafoo.de>
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.
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).
Add parsing and elaboration for chained calls on expression results,
with sv_call_chain_method1 regression.
Split from steveicarus/iverilog#1330 (part 02/6).