Support default value on module input (#5358) (#5373)

This commit is contained in:
Drew Ranck
2024-08-15 10:04:07 -04:00
committed by GitHub
parent 563faeb33f
commit 48c71ef76c
22 changed files with 524 additions and 27 deletions
+1
View File
@@ -787,6 +787,7 @@ public:
bool isAny() const { return m_e != NONE; }
// Looks like inout - "ish" because not identical to being an INOUT
bool isInoutish() const { return m_e == INOUT; }
bool isInput() const { return m_e == INPUT; }
bool isNonOutput() const {
return m_e == INPUT || m_e == INOUT || m_e == REF || m_e == CONSTREF;
}
+1
View File
@@ -2014,6 +2014,7 @@ public:
bool isContinuously() const { return m_isContinuously; }
bool isDeclTyped() const { return m_declTyped; }
bool isInoutish() const { return m_direction.isInoutish(); }
bool isInput() const { return m_direction.isInput(); }
bool isNonOutput() const { return m_direction.isNonOutput(); }
bool isReadOnly() const VL_MT_SAFE { return m_direction.isReadOnly(); }
bool isConstRef() const VL_MT_SAFE { return m_direction.isConstRef(); }
+44 -9
View File
@@ -398,6 +398,7 @@ class LinkCellsVisitor final : public VNVisitor {
for (AstNode* portnodep = nodep->modp()->stmtsp(); portnodep;
portnodep = portnodep->nextp()) {
if (const AstPort* const portp = VN_CAST(portnodep, Port)) {
if (ports.find(portp->name()) == ports.end()
&& ports.find("__pinNumber" + cvtToStr(portp->pinNum())) == ports.end()) {
if (pinStar) {
@@ -411,15 +412,49 @@ class LinkCellsVisitor final : public VNVisitor {
newp->svImplicit(true);
nodep->addPinsp(newp);
} else { // warn on the CELL that needs it, not the port
nodep->v3warn(PINMISSING, "Cell has missing pin: "
<< portp->prettyNameQ() << '\n'
<< nodep->warnContextPrimary() << '\n'
<< portp->warnOther()
<< "... Location of port declaration\n"
<< portp->warnContextSecondary());
AstPin* const newp
= new AstPin{nodep->fileline(), 0, portp->name(), nullptr};
nodep->addPinsp(newp);
// We *might* not want to warn on this port, if it happened to be
// an input with a default value in the module declaration. Our
// AstPort* (portp) doesn't have that information, but the Module
// (nodep->modp()) statements do that have information in an AstVar*
// with the same name() as the port. We'll look for that in-line here,
// if a port is missing on this instance.
// Get the AstVar for this AstPort, if it exists, using this
// inefficient O(n) lookup to match the port name.
const AstVar* portp_varp = nullptr;
for (AstNode* module_stmtsp = nodep->modp()->stmtsp(); module_stmtsp;
module_stmtsp = module_stmtsp->nextp()) {
if (const AstVar* const varp = VN_CAST(module_stmtsp, Var)) {
if (!varp->isParam() && varp->name() == portp->name()) {
// not a parameter, same name, break, this is our varp
// (AstVar*)
portp_varp = varp;
break;
}
}
}
// Is the matching Module port: an INPUT, with default value (in
// valuep):
if (portp_varp && portp_varp->isInput() && portp_varp->valuep()) {
// Do not warn
// Create b/c not already connected, and it does exist.
AstPin* const newp
= new AstPin{nodep->fileline(), 0, portp->name(), nullptr};
nodep->addPinsp(newp);
} else {
nodep->v3warn(PINMISSING,
"Cell has missing pin: "
<< portp->prettyNameQ() << '\n'
<< nodep->warnContextPrimary() << '\n'
<< portp->warnOther()
<< "... Location of port declaration\n"
<< portp->warnContextSecondary());
AstPin* const newp
= new AstPin{nodep->fileline(), 0, portp->name(), nullptr};
nodep->addPinsp(newp);
}
}
}
}
+5 -2
View File
@@ -62,8 +62,11 @@ class LinkLValueVisitor final : public VNVisitor {
if (m_setForcedByCode) {
nodep->varp()->setForcedByCode();
} else if (!nodep->varp()->isFuncLocal() && nodep->varp()->isReadOnly()) {
nodep->v3warn(ASSIGNIN,
"Assigning to input/const variable: " << nodep->prettyNameQ());
// This is allowed with IEEE 1800-2009 module input with default value.
// the checking now happens in V3Width::visit(AstNodeVarRef*)
// If you were to check here, it would fail on module inputs with default value,
// because Inputs are isReadOnly()=true, and we don't yet have visibility into
// it being an Initial style procedure.
}
}
iterateChildren(nodep);
+6 -3
View File
@@ -371,9 +371,12 @@ class LinkParseVisitor final : public VNVisitor {
FileLine* const fl = nodep->valuep()->fileline();
if (nodep->isParam() || (m_ftaskp && nodep->isNonOutput())) {
// 1. Parameters and function inputs: It's a default to use if not overridden
} else if (!m_ftaskp && !VN_IS(m_modp, Class) && nodep->isNonOutput()) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: Default value on module input: "
<< nodep->prettyNameQ());
} else if (!m_ftaskp && !VN_IS(m_modp, Class) && nodep->isNonOutput()
&& !nodep->isInput()) {
// Module inout/ref/constref: const default to use
nodep->v3warn(E_UNSUPPORTED,
"Unsupported: Default value on module inout/ref/constref: "
<< nodep->prettyNameQ());
nodep->valuep()->unlinkFrBack()->deleteTree();
} // 2. Under modules/class, it's an initial value to be loaded at time 0 via an
// AstInitial
+6
View File
@@ -2343,6 +2343,12 @@ class WidthVisitor final : public VNVisitor {
// if (debug() >= 9) nodep->dumpTree("- VRout: ");
if (nodep->access().isWriteOrRW() && nodep->varp()->direction() == VDirection::CONSTREF) {
nodep->v3error("Assigning to const ref variable: " << nodep->prettyNameQ());
} else if (!nodep->varp()->isForced() && nodep->access().isWriteOrRW()
&& nodep->varp()->isInput() && !nodep->varp()->isFuncLocal()
&& nodep->varp()->isReadOnly() && (!m_ftaskp || !m_ftaskp->isConstructor())
&& !VN_IS(m_procedurep, InitialAutomatic)
&& !VN_IS(m_procedurep, InitialStatic)) {
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)