Verilog: allow interface, package and class names as named formals - #2080
Draft
kroening wants to merge 1 commit into
Draft
Verilog: allow interface, package and class names as named formals#2080kroening wants to merge 1 commit into
kroening wants to merge 1 commit into
Conversation
Once a name had been declared as an interface, package or class, it could no longer be used as the formal name in a named port connection `.name(expr)` or in a named parameter assignment `.NAME(value)`. The parser rejected such code with syntax error, unexpected TOK_INTERFACE_IDENTIFIER, expecting TOK_NON_TYPE_IDENTIFIER or TOK_TYPE_IDENTIFIER The formal name in a named port connection or named parameter assignment is resolved in the port respectively parameter name space of the instantiated module (IEEE 1800-2017 3.13 and 23.3.2.2), and not in the scope in which the instantiation appears. Hence any name may be used there, irrespective of what it denotes locally. Note that interface, package and class names go into the global scope and persist across all input files, so a single interface declaration anywhere would poison the formal-name space of every instantiation in the design. The scanner classifies identifiers into distinct token classes (TOK_NON_TYPE_IDENTIFIER, TOK_TYPE_IDENTIFIER, TOK_INTERFACE_IDENTIFIER, TOK_PACKAGE_IDENTIFIER, TOK_CLASS_IDENTIFIER) using the scope table, but `any_identifier` covered only the first two. The same problem had previously been patched for typedefs only. This change extends `any_identifier` to all identifier token classes, which is the general version of that fix, and switches `parameter_identifier` (used by named parameter assignments) to `any_identifier` as well. No action code is needed for the new alternatives: the scanner gives every identifier token the same irep shape, namely ID_verilog_identifier with ID_base_name set, which is what the consumers read. The grammar remains conflict-free. Note that `port_identifier` (a port name in a declaration) is left unchanged deliberately: it is a genuinely different case, since the name being declared does live in the local scope, and widening it is not possible without introducing grammar conflicts. Widening `port_identifier` itself yields 2 shift/reduce conflicts for TOK_INTERFACE_IDENTIFIER (states where `attribute_instance_brace` can be reduced empty ahead of an ANSI port declaration, which itself may start with TOK_INTERFACE_IDENTIFIER) and 6 shift/reduce conflicts each for the other token classes (against the empty reductions of `net_type_opt` and `signing_opt`, i.e. an implicitly typed port name is indistinguishable from a data type). Widening individual uses of `port_identifier` instead produces reduce/reduce conflicts between the port declaration and port reference rules. Adds regression tests regression/verilog/modules/named_port_connection2, regression/verilog/modules/named_parameter_assignment1 and regression/verilog/interface/port4.
kroening
marked this pull request as draft
August 11, 2026 17:03
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Once a name has been declared as an interface, a package or a class, it could no longer be used as the formal name in a named port connection
.name(expr)or in a named parameter assignment.NAME(value).Minimal example
Before this change, the parser rejected the instantiation with
The same happened for named parameter assignments, e.g.
sub #(.data_if(1)) u();.Why this is legal
The formal name in a named port connection resp. a named parameter assignment is resolved in the port resp. parameter name space of the instantiated module (IEEE 1800-2017, 3.13 and 23.3.2.2), not in the scope in which the instantiation appears. Hence any name may be used there, irrespective of what it denotes locally.
This is aggravated by the fact that interface, package and class names go into the global scope and persist across all input files, so a single interface declaration anywhere in the input would poison the formal-name space of every module instantiation in the design.
The fix
The scanner classifies identifiers into distinct token classes (
TOK_NON_TYPE_IDENTIFIER,TOK_TYPE_IDENTIFIER,TOK_INTERFACE_IDENTIFIER,TOK_PACKAGE_IDENTIFIER,TOK_CLASS_IDENTIFIER) from the scope table, but the grammar'sany_identifiercovered only the first two. The same problem had previously been patched for typedefs only; this change is the general version of that fix:any_identifiernow covers all identifier token classes.parameter_identifier, which is used by named parameter assignments, now usesany_identifier.No action code is needed for the new alternatives, since the scanner gives every identifier token the same irep shape, namely
ID_verilog_identifierwithID_base_nameset, which is what the consumers read. The grammar remains conflict-free.port_identifier(the name of a port in a declaration) is deliberately left unchanged. It is a different case, as the name being declared does live in the local scope, and it cannot be widened without introducing grammar conflicts: wideningport_identifiergives 2 shift/reduce conflicts forTOK_INTERFACE_IDENTIFIER(states whereattribute_instance_bracecan be reduced empty ahead of an ANSI port declaration, which itself may start withTOK_INTERFACE_IDENTIFIER), and 6 shift/reduce conflicts each for the other token classes (against the empty reductions ofnet_type_optandsigning_opt, i.e. an implicitly typed port name is indistinguishable from a data type). Widening individual uses ofport_identifierinstead produces reduce/reduce conflicts between the port declaration and port reference rules.Tests
regression/verilog/modules/named_port_connection2-- formals named after a typedef, interface, package and classregression/verilog/modules/named_parameter_assignment1-- the same for named parameter assignmentsregression/verilog/interface/port4-- the interface case above