Fix false ASSIGNIN on interface input ports driven from outside (#7322)

This commit is contained in:
Yilou Wang
2026-03-26 12:30:16 -04:00
committed by GitHub
parent fbc3b3618d
commit e0963bd587
9 changed files with 186 additions and 12 deletions
+16 -1
View File
@@ -241,6 +241,7 @@ class WidthVisitor final : public VNVisitor {
std::map<const AstNode*, const AstClass*>
m_containingClassp; // Containing class cache for containingClass() function
std::unordered_set<AstVar*> m_aliasedVars; // Variables referenced in alias
std::unordered_set<const AstVar*> m_curModVars; // Variables declared in current module
static constexpr int ENUM_LOOKUP_BITS = 16; // Maximum # bits to make enum lookup table
@@ -2835,7 +2836,18 @@ class WidthVisitor final : public VNVisitor {
&& (!m_ftaskp || !m_ftaskp->isConstructor())
&& !VN_IS(m_procedurep, InitialAutomatic) && !VN_IS(m_procedurep, InitialStatic)
&& !VN_IS(nodep->abovep(), AssignForce) && !VN_IS(nodep->abovep(), Release)) {
nodep->v3warn(ASSIGNIN, "Assigning to input/const variable: " << nodep->prettyNameQ());
// Skip ASSIGNIN for continuous assignments to net-type input ports
// via hierarchical reference. Net ports allow multiple continuous
// drivers (IEEE 1800-2023 23.3.3.3). Input ports default to net
// when port kind is omitted (23.2.2.3, PORT type).
const bool hierRef = !m_curModVars.count(nodep->varp());
const bool netPort
= nodep->varp()->isNet() || nodep->varp()->varType() == VVarType::PORT;
const bool contAssign = VN_IS(nodep->abovep(), AssignW);
if (!(hierRef && netPort && contAssign)) {
nodep->v3warn(ASSIGNIN,
"Assigning to input/const variable: " << nodep->prettyNameQ());
}
} else if (nodep->access().isWriteOrRW() && nodep->varp()->isConst() && !m_paramsOnly
&& (!m_ftaskp || !m_ftaskp->isConstructor())
&& !VN_IS(m_procedurep, InitialAutomatic)
@@ -7374,6 +7386,9 @@ class WidthVisitor final : public VNVisitor {
} else {
VL_RESTORER(m_modep);
m_modep = nodep;
// Collect local variables for ASSIGNIN hierarchical reference check
m_curModVars.clear();
nodep->foreach([this](const AstVar* varp) { m_curModVars.insert(varp); });
userIterateChildren(nodep, nullptr);
}
}
+6 -6
View File
@@ -1437,16 +1437,16 @@ port<nodep>: // ==IEEE: port
{ $$ = $3; VARDTYPE($2); VARIOANSI();
if (AstVar* vp = VARDONEP($$, $4, $5)) { addNextNull($$, vp); vp->valuep($7); } }
| portDirNetE yVAR data_type portSig variable_dimensionListE sigAttrListE
{ $$ = $4; VARDTYPE($3); VARIOANSI();
{ $$ = $4; VARDECL(VAR); VARDTYPE($3); VARIOANSI();
addNextNull($$, VARDONEP($$, $5, $6)); }
| portDirNetE yVAR data_type portSig variable_dimensionListE sigAttrListE '=' constExpr
{ $$ = $4; VARDTYPE($3); VARIOANSI();
{ $$ = $4; VARDECL(VAR); VARDTYPE($3); VARIOANSI();
if (AstVar* vp = VARDONEP($$, $5, $6)) { addNextNull($$, vp); vp->valuep($8); } }
| portDirNetE yVAR implicit_typeE portSig variable_dimensionListE sigAttrListE
{ $$ = $4; VARDTYPE($3); VARIOANSI();
{ $$ = $4; VARDECL(VAR); VARDTYPE($3); VARIOANSI();
addNextNull($$, VARDONEP($$, $5, $6)); }
| portDirNetE yVAR implicit_typeE portSig variable_dimensionListE sigAttrListE '=' constExpr
{ $$ = $4; VARDTYPE($3); VARIOANSI();
{ $$ = $4; VARDECL(VAR); VARDTYPE($3); VARIOANSI();
if (AstVar* vp = VARDONEP($$, $5, $6)) { addNextNull($$, vp); vp->valuep($8); } }
| portDirNetE signing portSig variable_dimensionListE sigAttrListE
{ $$ = $3;
@@ -1955,10 +1955,10 @@ port_declaration<nodep>: // ==IEEE: port_declaration
/*mid*/ { VARDTYPE($3); }
/*cont*/ list_of_variable_decl_assignments { $$ = $5; }
| port_directionReset port_declNetE yVAR data_type
/*mid*/ { VARDTYPE($4); }
/*mid*/ { VARDECL(VAR); VARDTYPE($4); }
/*cont*/ list_of_variable_decl_assignments { $$ = $6; }
| port_directionReset port_declNetE yVAR implicit_typeE
/*mid*/ { VARDTYPE($4); }
/*mid*/ { VARDECL(VAR); VARDTYPE($4); }
/*cont*/ list_of_variable_decl_assignments { $$ = $6; }
| port_directionReset port_declNetE signingE rangeList
/*mid*/ { AstNodeDType* const dtp = GRAMMARP->addRange(