mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user