Internals: Redo post-error additional information to be part of error calls.
This commit is contained in:
parent
0f528d136d
commit
680236b03e
|
|
@ -122,6 +122,13 @@ void V3ErrorGuarded::suppressThisWarning() VL_REQUIRES(m_mutex) {
|
||||||
errorSuppressed(true);
|
errorSuppressed(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V3ErrorGuarded::v3errorPrep(V3ErrorCode code) VL_REQUIRES(m_mutex) {
|
||||||
|
m_errorStr.str("");
|
||||||
|
m_errorCode = code;
|
||||||
|
m_errorContexted = false;
|
||||||
|
m_errorSuppressed = false;
|
||||||
|
}
|
||||||
|
|
||||||
// cppcheck-has-bug-suppress constParameter
|
// cppcheck-has-bug-suppress constParameter
|
||||||
void V3ErrorGuarded::v3errorEnd(std::ostringstream& sstr, const string& extra)
|
void V3ErrorGuarded::v3errorEnd(std::ostringstream& sstr, const string& extra)
|
||||||
VL_REQUIRES(m_mutex) {
|
VL_REQUIRES(m_mutex) {
|
||||||
|
|
@ -303,7 +310,6 @@ std::ostringstream& V3Error::v3errorPrepFileLine(V3ErrorCode code, const char* f
|
||||||
v3errorPrep(code) << file << ":" << std::dec << line << ": ";
|
v3errorPrep(code) << file << ":" << std::dec << line << ": ";
|
||||||
return v3errorStr();
|
return v3errorStr();
|
||||||
}
|
}
|
||||||
std::ostringstream& V3Error::v3errorStr() VL_REQUIRES(s().m_mutex) { return s().v3errorStr(); }
|
|
||||||
void V3Error::v3errorEnd(std::ostringstream& sstr, const string& extra) VL_RELEASE(s().m_mutex) {
|
void V3Error::v3errorEnd(std::ostringstream& sstr, const string& extra) VL_RELEASE(s().m_mutex) {
|
||||||
s().v3errorEnd(sstr, extra);
|
s().v3errorEnd(sstr, extra);
|
||||||
V3Error::s().m_mutex.unlock();
|
V3Error::s().m_mutex.unlock();
|
||||||
|
|
|
||||||
|
|
@ -325,7 +325,7 @@ private:
|
||||||
= V3ErrorCode::EC_FATAL; // Error string being formed will abort
|
= V3ErrorCode::EC_FATAL; // Error string being formed will abort
|
||||||
bool m_errorSuppressed VL_GUARDED_BY(m_mutex)
|
bool m_errorSuppressed VL_GUARDED_BY(m_mutex)
|
||||||
= false; // Error being formed should be suppressed
|
= false; // Error being formed should be suppressed
|
||||||
MessagesSet m_messages VL_GUARDED_BY(m_mutex); // What errors we've outputted
|
MessagesSet m_messages VL_GUARDED_BY(m_mutex); // Errors outputted, to remove dups
|
||||||
ErrorExitCb m_errorExitCb VL_GUARDED_BY(m_mutex)
|
ErrorExitCb m_errorExitCb VL_GUARDED_BY(m_mutex)
|
||||||
= nullptr; // Callback when error occurs for dumping
|
= nullptr; // Callback when error occurs for dumping
|
||||||
bool m_errorContexted VL_GUARDED_BY(m_mutex) = false; // Error being formed got context
|
bool m_errorContexted VL_GUARDED_BY(m_mutex) = false; // Error being formed got context
|
||||||
|
|
@ -341,12 +341,7 @@ private:
|
||||||
bool m_warnFatal VL_GUARDED_BY(m_mutex) = true; // Option: --warnFatal Warnings are fatal
|
bool m_warnFatal VL_GUARDED_BY(m_mutex) = true; // Option: --warnFatal Warnings are fatal
|
||||||
std::ostringstream m_errorStr VL_GUARDED_BY(m_mutex); // Error string being formed
|
std::ostringstream m_errorStr VL_GUARDED_BY(m_mutex); // Error string being formed
|
||||||
|
|
||||||
void v3errorPrep(V3ErrorCode code) VL_REQUIRES(m_mutex) {
|
void v3errorPrep(V3ErrorCode code) VL_REQUIRES(m_mutex);
|
||||||
m_errorStr.str("");
|
|
||||||
m_errorCode = code;
|
|
||||||
m_errorContexted = false;
|
|
||||||
m_errorSuppressed = false;
|
|
||||||
}
|
|
||||||
std::ostringstream& v3errorStr() VL_REQUIRES(m_mutex) { return m_errorStr; }
|
std::ostringstream& v3errorStr() VL_REQUIRES(m_mutex) { return m_errorStr; }
|
||||||
void v3errorEnd(std::ostringstream& sstr, const string& extra = "") VL_REQUIRES(m_mutex);
|
void v3errorEnd(std::ostringstream& sstr, const string& extra = "") VL_REQUIRES(m_mutex);
|
||||||
|
|
||||||
|
|
@ -363,9 +358,9 @@ public:
|
||||||
bool isError(V3ErrorCode code, bool supp) VL_REQUIRES(m_mutex);
|
bool isError(V3ErrorCode code, bool supp) VL_REQUIRES(m_mutex);
|
||||||
void vlAbortOrExit() VL_REQUIRES(m_mutex);
|
void vlAbortOrExit() VL_REQUIRES(m_mutex);
|
||||||
void errorContexted(bool flag) VL_REQUIRES(m_mutex) { m_errorContexted = flag; }
|
void errorContexted(bool flag) VL_REQUIRES(m_mutex) { m_errorContexted = flag; }
|
||||||
void incWarnings() VL_REQUIRES(m_mutex) { m_warnCount++; }
|
void incWarnings() VL_REQUIRES(m_mutex) { ++m_warnCount; }
|
||||||
void incErrors() VL_REQUIRES(m_mutex) {
|
void incErrors() VL_REQUIRES(m_mutex) {
|
||||||
m_errCount++;
|
++m_errCount;
|
||||||
if (errorCount() == errorLimit()) { // Not >= as would otherwise recurse
|
if (errorCount() == errorLimit()) { // Not >= as would otherwise recurse
|
||||||
v3errorEnd(
|
v3errorEnd(
|
||||||
(v3errorPrep(V3ErrorCode::EC_FATALMANY),
|
(v3errorPrep(V3ErrorCode::EC_FATALMANY),
|
||||||
|
|
@ -509,14 +504,6 @@ public:
|
||||||
|
|
||||||
// When printing an error/warning, print prefix for multiline message
|
// When printing an error/warning, print prefix for multiline message
|
||||||
static string warnMore() VL_REQUIRES(s().m_mutex) { return s().warnMore(); }
|
static string warnMore() VL_REQUIRES(s().m_mutex) { return s().warnMore(); }
|
||||||
// This function should only be used when it is impossible to
|
|
||||||
// generate whole error message inside v3warn macros and it needs to be
|
|
||||||
// streamed directly to cerr.
|
|
||||||
// Use with caution as this function isn't MT_SAFE.
|
|
||||||
static string warnMoreStandalone() VL_EXCLUDES(s().m_mutex) VL_MT_UNSAFE {
|
|
||||||
const V3RecursiveLockGuard guard{s().m_mutex};
|
|
||||||
return s().warnMore();
|
|
||||||
}
|
|
||||||
// This function marks place in error message from which point message
|
// This function marks place in error message from which point message
|
||||||
// should be printed after information on the error code.
|
// should be printed after information on the error code.
|
||||||
// The post-processing is done in v3errorEnd function.
|
// The post-processing is done in v3errorEnd function.
|
||||||
|
|
@ -532,7 +519,7 @@ public:
|
||||||
static std::ostringstream& v3errorPrep(V3ErrorCode code) VL_ACQUIRE(s().m_mutex);
|
static std::ostringstream& v3errorPrep(V3ErrorCode code) VL_ACQUIRE(s().m_mutex);
|
||||||
static std::ostringstream& v3errorPrepFileLine(V3ErrorCode code, const char* file, int line)
|
static std::ostringstream& v3errorPrepFileLine(V3ErrorCode code, const char* file, int line)
|
||||||
VL_ACQUIRE(s().m_mutex);
|
VL_ACQUIRE(s().m_mutex);
|
||||||
static std::ostringstream& v3errorStr() VL_REQUIRES(s().m_mutex);
|
static std::ostringstream& v3errorStr() VL_REQUIRES(s().m_mutex) { return s().v3errorStr(); }
|
||||||
// static, but often overridden in classes.
|
// static, but often overridden in classes.
|
||||||
static void v3errorEnd(std::ostringstream& sstr, const string& extra = "")
|
static void v3errorEnd(std::ostringstream& sstr, const string& extra = "")
|
||||||
VL_RELEASE(s().m_mutex);
|
VL_RELEASE(s().m_mutex);
|
||||||
|
|
|
||||||
|
|
@ -464,10 +464,6 @@ string FileLine::warnOther() const VL_REQUIRES(V3Error::s().m_mutex) {
|
||||||
return V3Error::s().warnMore();
|
return V3Error::s().warnMore();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
string FileLine::warnOtherStandalone() const VL_EXCLUDES(V3Error::s().m_mutex) VL_MT_UNSAFE {
|
|
||||||
const V3RecursiveLockGuard guard{V3Error::s().m_mutex};
|
|
||||||
return warnOther();
|
|
||||||
}
|
|
||||||
|
|
||||||
string FileLine::source() const VL_MT_SAFE {
|
string FileLine::source() const VL_MT_SAFE {
|
||||||
if (VL_UNCOVERABLE(!m_contentp)) { // LCOV_EXCL_START
|
if (VL_UNCOVERABLE(!m_contentp)) { // LCOV_EXCL_START
|
||||||
|
|
|
||||||
|
|
@ -301,7 +301,6 @@ public:
|
||||||
void warnUnusedOff(bool flag);
|
void warnUnusedOff(bool flag);
|
||||||
void warnStateFrom(const FileLine& from) { m_msgEnIdx = from.m_msgEnIdx; }
|
void warnStateFrom(const FileLine& from) { m_msgEnIdx = from.m_msgEnIdx; }
|
||||||
void warnResetDefault() { warnStateFrom(defaultFileLine()); }
|
void warnResetDefault() { warnStateFrom(defaultFileLine()); }
|
||||||
bool lastWarnWaived() const { return m_waive; }
|
|
||||||
|
|
||||||
// Specific flag ACCESSORS/METHODS
|
// Specific flag ACCESSORS/METHODS
|
||||||
bool celldefineOn() const { return msgEn().test(V3ErrorCode::I_CELLDEFINE); }
|
bool celldefineOn() const { return msgEn().test(V3ErrorCode::I_CELLDEFINE); }
|
||||||
|
|
@ -356,7 +355,6 @@ public:
|
||||||
/// When building an error, prefix for printing secondary information
|
/// When building an error, prefix for printing secondary information
|
||||||
/// from a different FileLine than the original error
|
/// from a different FileLine than the original error
|
||||||
string warnOther() const VL_REQUIRES(V3Error::s().m_mutex);
|
string warnOther() const VL_REQUIRES(V3Error::s().m_mutex);
|
||||||
string warnOtherStandalone() const VL_EXCLUDES(V3Error::s().m_mutex) VL_MT_UNSAFE;
|
|
||||||
/// When building an error, current location in include etc
|
/// When building an error, current location in include etc
|
||||||
/// If not used in a given error, automatically pasted at end of error
|
/// If not used in a given error, automatically pasted at end of error
|
||||||
string warnContextPrimary() const VL_REQUIRES(V3Error::s().m_mutex) {
|
string warnContextPrimary() const VL_REQUIRES(V3Error::s().m_mutex) {
|
||||||
|
|
|
||||||
|
|
@ -233,13 +233,16 @@ void V3Graph::clearColors() {
|
||||||
//======================================================================
|
//======================================================================
|
||||||
// Dumping
|
// Dumping
|
||||||
|
|
||||||
void V3Graph::loopsMessageCb(V3GraphVertex* vertexp) {
|
void V3Graph::loopsMessageCb(V3GraphVertex* vertexp, V3EdgeFuncP edgeFuncp) {
|
||||||
vertexp->v3fatalSrc("Loops detected in graph: " << vertexp);
|
vertexp->v3fatalSrc("Loops detected in graph: " << vertexp << "\n"
|
||||||
|
<< reportLoops(edgeFuncp, vertexp));
|
||||||
}
|
}
|
||||||
|
string V3Graph::loopsVertexCb(V3GraphVertex* vertexp) {
|
||||||
void V3Graph::loopsVertexCb(V3GraphVertex* vertexp) {
|
|
||||||
// Needed here as V3GraphVertex<< isn't defined until later in header
|
// Needed here as V3GraphVertex<< isn't defined until later in header
|
||||||
if (debug()) std::cerr << "-Info-Loop: " << cvtToHex(vertexp) << " " << vertexp << endl;
|
if (debug())
|
||||||
|
return "-Info-Loop: "s + cvtToHex(vertexp) + ' ' + cvtToStr(vertexp) + '\n';
|
||||||
|
else
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void V3Graph::dump(std::ostream& os) const {
|
void V3Graph::dump(std::ostream& os) const {
|
||||||
|
|
|
||||||
|
|
@ -430,7 +430,7 @@ public:
|
||||||
|
|
||||||
/// Call loopsVertexCb on any one loop starting where specified
|
/// Call loopsVertexCb on any one loop starting where specified
|
||||||
/// Side-effect: changes user()
|
/// Side-effect: changes user()
|
||||||
void reportLoops(V3EdgeFuncP edgeFuncp, V3GraphVertex* vertexp) VL_MT_DISABLED;
|
string reportLoops(V3EdgeFuncP edgeFuncp, V3GraphVertex* vertexp) VL_MT_DISABLED;
|
||||||
|
|
||||||
/// Build a subgraph of all loops starting where specified
|
/// Build a subgraph of all loops starting where specified
|
||||||
/// Side-effect: changes user()
|
/// Side-effect: changes user()
|
||||||
|
|
@ -484,8 +484,8 @@ public:
|
||||||
parallelismReport(std::function<uint64_t(const V3GraphVertex*)> vertexCost) VL_MT_DISABLED;
|
parallelismReport(std::function<uint64_t(const V3GraphVertex*)> vertexCost) VL_MT_DISABLED;
|
||||||
|
|
||||||
// CALLBACKS
|
// CALLBACKS
|
||||||
virtual void loopsMessageCb(V3GraphVertex* vertexp) VL_MT_DISABLED;
|
virtual void loopsMessageCb(V3GraphVertex* vertexp, V3EdgeFuncP edgeFuncp) VL_MT_DISABLED;
|
||||||
virtual void loopsVertexCb(V3GraphVertex* vertexp) VL_MT_DISABLED;
|
virtual string loopsVertexCb(V3GraphVertex* vertexp) VL_MT_DISABLED;
|
||||||
};
|
};
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
|
||||||
|
|
@ -343,10 +343,9 @@ void GraphAcyc::simplifyOut(GraphAcycVertex* avertexp) {
|
||||||
V3GraphVertex* inVertexp = inEdgep->fromp();
|
V3GraphVertex* inVertexp = inEdgep->fromp();
|
||||||
if (inVertexp == avertexp) {
|
if (inVertexp == avertexp) {
|
||||||
if (debug()) v3error("Non-cutable vertex=" << avertexp); // LCOV_EXCL_LINE
|
if (debug()) v3error("Non-cutable vertex=" << avertexp); // LCOV_EXCL_LINE
|
||||||
v3error("Circular logic when ordering code (non-cutable edge loop)");
|
v3error("Circular logic when ordering code (non-cutable edge loop)\n"
|
||||||
m_origGraphp->reportLoops(
|
<< m_origGraphp->reportLoops( // calls OrderGraph::loopsVertexCb
|
||||||
&V3GraphEdge::followNotCutable,
|
&V3GraphEdge::followNotCutable, avertexp->origVertexp()));
|
||||||
avertexp->origVertexp()); // calls OrderGraph::loopsVertexCb
|
|
||||||
// Things are unlikely to end well at this point,
|
// Things are unlikely to end well at this point,
|
||||||
// but we'll try something to get to further errors...
|
// but we'll try something to get to further errors...
|
||||||
inEdgep->cutable(true);
|
inEdgep->cutable(true);
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <numeric>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||||
|
|
@ -281,8 +282,7 @@ class GraphAlgRank final : GraphAlg<> {
|
||||||
// If larger rank is found, assign it and loop back through
|
// If larger rank is found, assign it and loop back through
|
||||||
// If we hit a back node make a list of all loops
|
// If we hit a back node make a list of all loops
|
||||||
if (vertexp->user() == 1) {
|
if (vertexp->user() == 1) {
|
||||||
m_graphp->reportLoops(m_edgeFuncp, vertexp);
|
m_graphp->loopsMessageCb(vertexp, m_edgeFuncp);
|
||||||
m_graphp->loopsMessageCb(vertexp);
|
|
||||||
return; // LCOV_EXCL_LINE // gcc gprof bug misses this return
|
return; // LCOV_EXCL_LINE // gcc gprof bug misses this return
|
||||||
}
|
}
|
||||||
if (vertexp->rank() >= currentRank) return; // Already processed it
|
if (vertexp->rank() >= currentRank) return; // Already processed it
|
||||||
|
|
@ -313,6 +313,7 @@ void V3Graph::rank(V3EdgeFuncP edgeFuncp) { GraphAlgRank{this, edgeFuncp}; }
|
||||||
|
|
||||||
class GraphAlgRLoops final : GraphAlg<> {
|
class GraphAlgRLoops final : GraphAlg<> {
|
||||||
std::vector<V3GraphVertex*> m_callTrace; // List of everything we hit processing so far
|
std::vector<V3GraphVertex*> m_callTrace; // List of everything we hit processing so far
|
||||||
|
std::vector<string> m_msgs; // Output messages
|
||||||
bool m_done = false; // Exit algorithm
|
bool m_done = false; // Exit algorithm
|
||||||
|
|
||||||
void main(V3GraphVertex* vertexp) {
|
void main(V3GraphVertex* vertexp) {
|
||||||
|
|
@ -333,9 +334,8 @@ class GraphAlgRLoops final : GraphAlg<> {
|
||||||
m_callTrace[currentRank++] = vertexp;
|
m_callTrace[currentRank++] = vertexp;
|
||||||
|
|
||||||
if (vertexp->user() == 1) {
|
if (vertexp->user() == 1) {
|
||||||
for (unsigned i = 0; i < currentRank; i++) { //
|
for (unsigned i = 0; i < currentRank; i++)
|
||||||
m_graphp->loopsVertexCb(m_callTrace[i]);
|
m_msgs.emplace_back(m_graphp->loopsVertexCb(m_callTrace[i]));
|
||||||
}
|
|
||||||
m_done = true;
|
m_done = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -353,10 +353,13 @@ public:
|
||||||
main(vertexp);
|
main(vertexp);
|
||||||
}
|
}
|
||||||
~GraphAlgRLoops() = default;
|
~GraphAlgRLoops() = default;
|
||||||
|
string message() const {
|
||||||
|
return std::accumulate(m_msgs.begin(), m_msgs.end(), std::string{""});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void V3Graph::reportLoops(V3EdgeFuncP edgeFuncp, V3GraphVertex* vertexp) {
|
string V3Graph::reportLoops(V3EdgeFuncP edgeFuncp, V3GraphVertex* vertexp) {
|
||||||
GraphAlgRLoops{this, edgeFuncp, vertexp};
|
return GraphAlgRLoops{this, edgeFuncp, vertexp}.message();
|
||||||
}
|
}
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ class LinkCellsGraph final : public V3Graph {
|
||||||
public:
|
public:
|
||||||
LinkCellsGraph() = default;
|
LinkCellsGraph() = default;
|
||||||
~LinkCellsGraph() override = default;
|
~LinkCellsGraph() override = default;
|
||||||
void loopsMessageCb(V3GraphVertex* vertexp) override;
|
void loopsMessageCb(V3GraphVertex* vertexp, V3EdgeFuncP edgeFuncp) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LinkCellsVertex final : public V3GraphVertex {
|
class LinkCellsVertex final : public V3GraphVertex {
|
||||||
|
|
@ -73,7 +73,7 @@ public:
|
||||||
string name() const override VL_MT_STABLE { return "*LIBRARY*"; }
|
string name() const override VL_MT_STABLE { return "*LIBRARY*"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
void LinkCellsGraph::loopsMessageCb(V3GraphVertex* vertexp) {
|
void LinkCellsGraph::loopsMessageCb(V3GraphVertex* vertexp, V3EdgeFuncP edgeFuncp) {
|
||||||
if (const LinkCellsVertex* const vvertexp = vertexp->cast<LinkCellsVertex>()) {
|
if (const LinkCellsVertex* const vvertexp = vertexp->cast<LinkCellsVertex>()) {
|
||||||
vvertexp->modp()->v3warn(E_UNSUPPORTED,
|
vvertexp->modp()->v3warn(E_UNSUPPORTED,
|
||||||
"Unsupported: Recursive multiple modules (module instantiates "
|
"Unsupported: Recursive multiple modules (module instantiates "
|
||||||
|
|
|
||||||
|
|
@ -3422,11 +3422,11 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
<< (!baddot.empty() ? AstNode::prettyNameQ(baddot)
|
<< (!baddot.empty() ? AstNode::prettyNameQ(baddot)
|
||||||
: nodep->prettyNameQ())
|
: nodep->prettyNameQ())
|
||||||
<< " in dotted " << expectWhat << ": '"
|
<< " in dotted " << expectWhat << ": '"
|
||||||
<< m_ds.m_dotText + "." + nodep->prettyName() << "'");
|
<< m_ds.m_dotText + "." + nodep->prettyName() << "'\n"
|
||||||
if (okSymp) {
|
<< nodep->warnContextPrimary()
|
||||||
okSymp->cellErrorScopes(nodep,
|
<< (okSymp ? okSymp->cellErrorScopes(
|
||||||
AstNode::prettyName(m_ds.m_dotText));
|
nodep, AstNode::prettyName(m_ds.m_dotText))
|
||||||
}
|
: ""));
|
||||||
}
|
}
|
||||||
m_ds.m_dotErr = true;
|
m_ds.m_dotErr = true;
|
||||||
}
|
}
|
||||||
|
|
@ -3611,8 +3611,9 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
if (!nodep->varp()) {
|
if (!nodep->varp()) {
|
||||||
nodep->v3error("Can't find definition of "
|
nodep->v3error("Can't find definition of "
|
||||||
<< AstNode::prettyNameQ(baddot) << " in dotted signal: '"
|
<< AstNode::prettyNameQ(baddot) << " in dotted signal: '"
|
||||||
<< nodep->dotted() + "." + nodep->prettyName() << "'");
|
<< nodep->dotted() + "." + nodep->prettyName() << "'\n"
|
||||||
okSymp->cellErrorScopes(nodep);
|
<< nodep->warnContextPrimary()
|
||||||
|
<< okSymp->cellErrorScopes(nodep));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// V3Inst may have expanded arrays of interfaces to
|
// V3Inst may have expanded arrays of interfaces to
|
||||||
|
|
@ -3636,8 +3637,9 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
if (!vscp) {
|
if (!vscp) {
|
||||||
nodep->v3error("Can't find varpin scope of "
|
nodep->v3error("Can't find varpin scope of "
|
||||||
<< AstNode::prettyNameQ(baddot) << " in dotted signal: '"
|
<< AstNode::prettyNameQ(baddot) << " in dotted signal: '"
|
||||||
<< nodep->dotted() + "." + nodep->prettyName() << "'");
|
<< nodep->dotted() + "." + nodep->prettyName() << "'\n"
|
||||||
okSymp->cellErrorScopes(nodep);
|
<< nodep->warnContextPrimary()
|
||||||
|
<< okSymp->cellErrorScopes(nodep));
|
||||||
} else {
|
} else {
|
||||||
while (vscp->user2p()) { // If V3Inline aliased it, pick up the new signal
|
while (vscp->user2p()) { // If V3Inline aliased it, pick up the new signal
|
||||||
UINFO(7, indent() << "Resolved pre-alias " << vscp
|
UINFO(7, indent() << "Resolved pre-alias " << vscp
|
||||||
|
|
@ -3844,10 +3846,11 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
dotSymp = m_statep->findDotted(nodep->fileline(), dotSymp, inl, baddot, okSymp,
|
dotSymp = m_statep->findDotted(nodep->fileline(), dotSymp, inl, baddot, okSymp,
|
||||||
true);
|
true);
|
||||||
if (!dotSymp) {
|
if (!dotSymp) {
|
||||||
okSymp->cellErrorScopes(nodep);
|
|
||||||
nodep->v3fatalSrc("Couldn't resolve inlined scope "
|
nodep->v3fatalSrc("Couldn't resolve inlined scope "
|
||||||
<< AstNode::prettyNameQ(baddot)
|
<< AstNode::prettyNameQ(baddot)
|
||||||
<< " in: " << nodep->inlinedDots());
|
<< " in: " << nodep->inlinedDots() << '\n'
|
||||||
|
<< nodep->warnContextPrimary()
|
||||||
|
<< okSymp->cellErrorScopes(nodep));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dotSymp = m_statep->findDotted(nodep->fileline(), dotSymp, nodep->dotted(), baddot,
|
dotSymp = m_statep->findDotted(nodep->fileline(), dotSymp, nodep->dotted(), baddot,
|
||||||
|
|
@ -3974,8 +3977,9 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
nodep->v3error("Can't find definition of "
|
nodep->v3error("Can't find definition of "
|
||||||
<< AstNode::prettyNameQ(baddot) << " in dotted task/function: '"
|
<< AstNode::prettyNameQ(baddot) << " in dotted task/function: '"
|
||||||
<< nodep->dotted() + "." + nodep->prettyName() << "'\n"
|
<< nodep->dotted() + "." + nodep->prettyName() << "'\n"
|
||||||
<< (suggest.empty() ? "" : nodep->warnMore() + suggest));
|
<< (suggest.empty() ? "" : nodep->warnMore() + suggest) << '\n'
|
||||||
okSymp->cellErrorScopes(nodep);
|
<< nodep->warnContextPrimary()
|
||||||
|
<< okSymp->cellErrorScopes(nodep));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -595,40 +595,41 @@ string V3Options::filePath(FileLine* fl, const string& modname, const string& la
|
||||||
|
|
||||||
// Warn and return not found
|
// Warn and return not found
|
||||||
if (errmsg != "") {
|
if (errmsg != "") {
|
||||||
fl->v3error(errmsg + "'"s + filename + "'"s);
|
fl->v3error(errmsg << "'"s << filename << "'\n"s << fl->warnContextPrimary()
|
||||||
filePathLookedMsg(fl, filename);
|
<< V3Error::warnAdditionalInfo() << filePathLookedMsg(fl, filename));
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void V3Options::filePathLookedMsg(FileLine* fl, const string& modname) {
|
string V3Options::filePathLookedMsg(FileLine* fl, const string& modname) {
|
||||||
static bool shown_notfound_msg = false;
|
static bool shown_notfound_msg = false;
|
||||||
|
std::ostringstream ss;
|
||||||
if (modname.find("__Vhsh") != string::npos) {
|
if (modname.find("__Vhsh") != string::npos) {
|
||||||
std::cerr << V3Error::warnMoreStandalone()
|
ss << V3Error::warnMore() << "... Note: Name is longer than 127 characters; automatic"
|
||||||
<< "... Note: Name is longer than 127 characters; automatic"
|
<< " file lookup may have failed due to OS filename length limits.\n";
|
||||||
<< " file lookup may have failed due to OS filename length limits.\n";
|
ss << V3Error::warnMore() << "... Suggest putting filename with this module/package"
|
||||||
std::cerr << V3Error::warnMoreStandalone()
|
<< " onto command line instead.\n";
|
||||||
<< "... Suggest putting filename with this module/package"
|
|
||||||
<< " onto command line instead.\n";
|
|
||||||
} else if (!shown_notfound_msg) {
|
} else if (!shown_notfound_msg) {
|
||||||
shown_notfound_msg = true;
|
shown_notfound_msg = true;
|
||||||
if (m_impp->m_incDirUsers.empty()) {
|
if (m_impp->m_incDirUsers.empty()) {
|
||||||
fl->v3error("This may be because there's no search path specified with -I<dir>.");
|
ss << V3Error::warnMore()
|
||||||
|
<< "... This may be because there's no search path specified with -I<dir>.\n";
|
||||||
}
|
}
|
||||||
std::cerr << V3Error::warnMoreStandalone() << "... Looked in:" << endl;
|
ss << V3Error::warnMore() << "... Looked in:\n";
|
||||||
for (const string& dir : m_impp->m_incDirUsers) {
|
for (const string& dir : m_impp->m_incDirUsers) {
|
||||||
for (const string& ext : m_impp->m_libExtVs) {
|
for (const string& ext : m_impp->m_libExtVs) {
|
||||||
const string fn = V3Os::filenameJoin(dir, modname + ext);
|
const string fn = V3Os::filenameJoin(dir, modname + ext);
|
||||||
std::cerr << V3Error::warnMoreStandalone() << " " << fn << endl;
|
ss << V3Error::warnMore() << " " << fn << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const string& dir : m_impp->m_incDirFallbacks) {
|
for (const string& dir : m_impp->m_incDirFallbacks) {
|
||||||
for (const string& ext : m_impp->m_libExtVs) {
|
for (const string& ext : m_impp->m_libExtVs) {
|
||||||
const string fn = V3Os::filenameJoin(dir, modname + ext);
|
const string fn = V3Os::filenameJoin(dir, modname + ext);
|
||||||
std::cerr << V3Error::warnMoreStandalone() << " " << fn << endl;
|
ss << V3Error::warnMore() << " " << fn << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Determine what language is associated with a filename
|
//! Determine what language is associated with a filename
|
||||||
|
|
|
||||||
|
|
@ -779,7 +779,7 @@ public:
|
||||||
string fileExists(const string& filename);
|
string fileExists(const string& filename);
|
||||||
string filePath(FileLine* fl, const string& modname, const string& lastpath,
|
string filePath(FileLine* fl, const string& modname, const string& lastpath,
|
||||||
const string& errmsg);
|
const string& errmsg);
|
||||||
void filePathLookedMsg(FileLine* fl, const string& modname);
|
string filePathLookedMsg(FileLine* fl, const string& modname);
|
||||||
V3LangCode fileLanguage(const string& filename);
|
V3LangCode fileLanguage(const string& filename);
|
||||||
static bool fileStatNormal(const string& filename);
|
static bool fileStatNormal(const string& filename);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -100,17 +100,16 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class Graph final : public V3Graph {
|
class Graph final : public V3Graph {
|
||||||
void loopsVertexCb(V3GraphVertex* vtxp) override {
|
string loopsVertexCb(V3GraphVertex* vtxp) override {
|
||||||
// TODO: 'typeName' is an internal thing. This should be more human readable.
|
|
||||||
if (SchedAcyclicLogicVertex* const lvtxp = vtxp->cast<SchedAcyclicLogicVertex>()) {
|
if (SchedAcyclicLogicVertex* const lvtxp = vtxp->cast<SchedAcyclicLogicVertex>()) {
|
||||||
AstNode* const logicp = lvtxp->logicp();
|
AstNode* const logicp = lvtxp->logicp();
|
||||||
std::cerr << logicp->fileline()->warnOtherStandalone()
|
return logicp->fileline()->warnOther()
|
||||||
<< " Example path: " << logicp->typeName() << endl;
|
+ " Example path: " + logicp->prettyTypeName() + "\n";
|
||||||
} else {
|
} else {
|
||||||
SchedAcyclicVarVertex* const vvtxp = vtxp->as<SchedAcyclicVarVertex>();
|
SchedAcyclicVarVertex* const vvtxp = vtxp->as<SchedAcyclicVarVertex>();
|
||||||
AstVarScope* const vscp = vvtxp->vscp();
|
AstVarScope* const vscp = vvtxp->vscp();
|
||||||
std::cerr << vscp->fileline()->warnOtherStandalone()
|
return vscp->fileline()->warnOther() + " Example path: " + vscp->prettyName()
|
||||||
<< " Example path: " << vscp->prettyName() << endl;
|
+ "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -268,7 +267,8 @@ void gatherSCCCandidates(V3GraphVertex* vtxp, std::vector<Candidate>& candidates
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find all variables in a loop (SCC) that are candidates for splitting to break loops.
|
// Find all variables in a loop (SCC) that are candidates for splitting to break loops.
|
||||||
void reportLoopVars(Graph* graphp, SchedAcyclicVarVertex* vvtxp) {
|
std::string reportLoopVars(FileLine* warnFl, Graph* graphp, SchedAcyclicVarVertex* vvtxp) {
|
||||||
|
std::ostringstream ss;
|
||||||
// Vector of variables in UNOPTFLAT loop that are candidates for splitting.
|
// Vector of variables in UNOPTFLAT loop that are candidates for splitting.
|
||||||
std::vector<Candidate> candidates;
|
std::vector<Candidate> candidates;
|
||||||
{
|
{
|
||||||
|
|
@ -281,47 +281,51 @@ void reportLoopVars(Graph* graphp, SchedAcyclicVarVertex* vvtxp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Possible we only have candidates the user cannot do anything about, so don't bother them.
|
// Possible we only have candidates the user cannot do anything about, so don't bother them.
|
||||||
if (candidates.empty()) return;
|
if (candidates.empty()) return "";
|
||||||
|
|
||||||
// There may be a very large number of candidates, so only report up to 10 of the "most
|
// There may be a very large number of candidates, so only report up to 10 of the "most
|
||||||
// important" signals.
|
// important" signals.
|
||||||
unsigned splittable = 0;
|
unsigned splittable = 0;
|
||||||
const auto reportFirst10 = [&](std::function<bool(const Candidate&, const Candidate&)> less) {
|
const auto reportFirst10
|
||||||
|
= [&](std::function<bool(const Candidate&, const Candidate&)> less) -> string {
|
||||||
std::stable_sort(candidates.begin(), candidates.end(), less);
|
std::stable_sort(candidates.begin(), candidates.end(), less);
|
||||||
|
std::ostringstream ss2;
|
||||||
for (size_t i = 0; i < 10; i++) {
|
for (size_t i = 0; i < 10; i++) {
|
||||||
if (i == candidates.size()) break;
|
if (i == candidates.size()) break;
|
||||||
const Candidate& candidate = candidates[i];
|
const Candidate& candidate = candidates[i];
|
||||||
AstVar* const varp = candidate.first->varp();
|
AstVar* const varp = candidate.first->varp();
|
||||||
std::cerr << V3Error::warnMoreStandalone() << " " << varp->fileline() << " "
|
|
||||||
<< varp->prettyName() << ", width " << std::dec << varp->width()
|
ss2 << V3Error::warnMore() << " " << varp->fileline() << ' ' << varp->prettyName()
|
||||||
<< ", circular fanout " << candidate.second;
|
<< ", width " << std::dec << varp->width() << ", circular fanout "
|
||||||
|
<< candidate.second;
|
||||||
if (V3SplitVar::canSplitVar(varp)) {
|
if (V3SplitVar::canSplitVar(varp)) {
|
||||||
std::cerr << ", can split_var";
|
ss2 << ", can split_var";
|
||||||
++splittable;
|
++splittable;
|
||||||
}
|
}
|
||||||
std::cerr << '\n';
|
ss2 << '\n';
|
||||||
}
|
}
|
||||||
|
return ss2.str();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Widest variables
|
// Widest variables
|
||||||
std::cerr << V3Error::warnMoreStandalone() << "... Widest variables candidate to splitting:\n";
|
ss << V3Error::warnMore() << "... Widest variables candidate to splitting:\n"
|
||||||
reportFirst10([](const Candidate& a, const Candidate& b) {
|
<< reportFirst10([](const Candidate& a, const Candidate& b) {
|
||||||
return a.first->varp()->width() > b.first->varp()->width();
|
return a.first->varp()->width() > b.first->varp()->width();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Highest fanout
|
// Highest fanout
|
||||||
std::cerr << V3Error::warnMoreStandalone() << "... Candidates with the highest fanout:\n";
|
ss << V3Error::warnMore() << "... Candidates with the highest fanout:\n"
|
||||||
reportFirst10([](const Candidate& a, const Candidate& b) { //
|
<< reportFirst10([](const Candidate& a, const Candidate& b) { //
|
||||||
return a.second > b.second;
|
return a.second > b.second;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (splittable) {
|
if (splittable) {
|
||||||
std::cerr << V3Error::warnMoreStandalone()
|
ss << V3Error::warnMore()
|
||||||
<< "... Suggest add /*verilator split_var*/ or /*verilator "
|
<< "... Suggest add /*verilator split_var*/ or /*verilator "
|
||||||
"isolate_assignments*/ to appropriate variables above."
|
"isolate_assignments*/ to appropriate variables above.\n";
|
||||||
<< std::endl;
|
|
||||||
}
|
}
|
||||||
V3Stats::addStat("Scheduling, split_var, candidates", splittable);
|
V3Stats::addStat("Scheduling, split_var, candidates", splittable);
|
||||||
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void reportCycles(Graph* graphp, const std::vector<SchedAcyclicVarVertex*>& cutVertices) {
|
void reportCycles(Graph* graphp, const std::vector<SchedAcyclicVarVertex*>& cutVertices) {
|
||||||
|
|
@ -330,17 +334,26 @@ void reportCycles(Graph* graphp, const std::vector<SchedAcyclicVarVertex*>& cutV
|
||||||
FileLine* const flp = vscp->fileline();
|
FileLine* const flp = vscp->fileline();
|
||||||
|
|
||||||
// First v3warn not inside warnIsOff so we can see the suppressions with --debug
|
// First v3warn not inside warnIsOff so we can see the suppressions with --debug
|
||||||
vscp->v3warn(UNOPTFLAT, "Signal unoptimizable: Circular combinational logic: "
|
if (flp->warnIsOff(V3ErrorCode::UNOPTFLAT)) {
|
||||||
<< vscp->prettyNameQ());
|
// First v3warn not inside warnIsOff so we can see the suppressions with --debug
|
||||||
if (!flp->warnIsOff(V3ErrorCode::UNOPTFLAT) && !flp->lastWarnWaived()) {
|
vscp->v3warn(UNOPTFLAT, "Signal unoptimizable: Circular combinational logic: "
|
||||||
|
<< vscp->prettyNameQ());
|
||||||
|
} else {
|
||||||
|
vscp->v3warn(UNOPTFLAT,
|
||||||
|
"Signal unoptimizable: Circular combinational logic: "
|
||||||
|
<< vscp->prettyNameQ() << '\n'
|
||||||
|
<< vscp->warnContextPrimary()
|
||||||
|
<< V3Error::warnAdditionalInfo()
|
||||||
|
// Calls Graph::loopsVertexCb
|
||||||
|
<< graphp->reportLoops(&V3GraphEdge::followAlwaysTrue, vvtxp)
|
||||||
|
// Report candidate variables for splitting
|
||||||
|
<< (v3Global.opt.reportUnoptflat()
|
||||||
|
? reportLoopVars(vscp->fileline(), graphp, vvtxp)
|
||||||
|
: ""));
|
||||||
// Complain just once
|
// Complain just once
|
||||||
flp->modifyWarnOff(V3ErrorCode::UNOPTFLAT, true);
|
flp->modifyWarnOff(V3ErrorCode::UNOPTFLAT, true);
|
||||||
// Calls Graph::loopsVertexCb
|
// Create a subgraph for the UNOPTFLAT loop
|
||||||
graphp->reportLoops(&V3GraphEdge::followAlwaysTrue, vvtxp);
|
|
||||||
if (v3Global.opt.reportUnoptflat()) {
|
if (v3Global.opt.reportUnoptflat()) {
|
||||||
// Report candidate variables for splitting
|
|
||||||
reportLoopVars(graphp, vvtxp);
|
|
||||||
// Create a subgraph for the UNOPTFLAT loop
|
|
||||||
V3Graph loopGraph;
|
V3Graph loopGraph;
|
||||||
graphp->subtreeLoops(&V3GraphEdge::followAlwaysTrue, vvtxp, &loopGraph);
|
graphp->subtreeLoops(&V3GraphEdge::followAlwaysTrue, vvtxp, &loopGraph);
|
||||||
loopGraph.dumpDotFilePrefixedAlways("unoptflat");
|
loopGraph.dumpDotFilePrefixedAlways("unoptflat");
|
||||||
|
|
|
||||||
|
|
@ -256,7 +256,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void cellErrorScopes(AstNode* lookp, string prettyName = "") {
|
string cellErrorScopes(AstNode* lookp, string prettyName = "") {
|
||||||
if (prettyName == "") prettyName = lookp->prettyName();
|
if (prettyName == "") prettyName = lookp->prettyName();
|
||||||
string scopes;
|
string scopes;
|
||||||
for (IdNameMap::iterator it = m_idNameMap.begin(); it != m_idNameMap.end(); ++it) {
|
for (IdNameMap::iterator it = m_idNameMap.begin(); it != m_idNameMap.end(); ++it) {
|
||||||
|
|
@ -267,9 +267,9 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (scopes == "") scopes = "<no instances found>";
|
if (scopes == "") scopes = "<no instances found>";
|
||||||
std::cerr << V3Error::warnMoreStandalone() << "... Known scopes under '" << prettyName
|
|
||||||
<< "': " << scopes << endl;
|
|
||||||
if (debug()) dumpSelf(std::cerr, " KnownScope: ", 1);
|
if (debug()) dumpSelf(std::cerr, " KnownScope: ", 1);
|
||||||
|
return V3Error::warnMore() + "... Known scopes under '" + prettyName + "': " + scopes
|
||||||
|
+ '\n';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5876,9 +5876,12 @@ class WidthVisitor final : public VNVisitor {
|
||||||
// We've resolved parameters and hit a module that we couldn't resolve. It's
|
// We've resolved parameters and hit a module that we couldn't resolve. It's
|
||||||
// finally time to report it.
|
// finally time to report it.
|
||||||
// Note only here in V3Width as this is first visitor after V3Dead.
|
// Note only here in V3Width as this is first visitor after V3Dead.
|
||||||
nodep->modNameFileline()->v3error("Cannot find file containing module: '"
|
nodep->modNameFileline()->v3error(
|
||||||
<< nodep->modName() << "'");
|
"Cannot find file containing module: '"
|
||||||
v3Global.opt.filePathLookedMsg(nodep->modNameFileline(), nodep->modName());
|
<< nodep->modName() << "'\n"
|
||||||
|
<< nodep->modNameFileline()->warnContextPrimary()
|
||||||
|
<< V3Error::warnAdditionalInfo()
|
||||||
|
<< v3Global.opt.filePathLookedMsg(nodep->modNameFileline(), nodep->modName()));
|
||||||
}
|
}
|
||||||
if (nodep->rangep()) userIterateAndNext(nodep->rangep(), WidthVP{SELF, BOTH}.p());
|
if (nodep->rangep()) userIterateAndNext(nodep->rangep(), WidthVP{SELF, BOTH}.p());
|
||||||
userIterateAndNext(nodep->pinsp(), nullptr);
|
userIterateAndNext(nodep->pinsp(), nullptr);
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,7 @@
|
||||||
8 | nfound nfound();
|
8 | nfound nfound();
|
||||||
| ^~~~~~
|
| ^~~~~~
|
||||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||||
%Error: t/t_gen_nonconst_bad.v:8:4: This may be because there's no search path specified with -I<dir>.
|
... This may be because there's no search path specified with -I<dir>.
|
||||||
8 | nfound nfound();
|
|
||||||
| ^~~~~~
|
|
||||||
... Looked in:
|
... Looked in:
|
||||||
nfound
|
nfound
|
||||||
nfound.v
|
nfound.v
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
%Error: t/t_interface_mismodport_bad.v:32:12: Can't find definition of 'bad' in dotted signal: 'isub.bad'
|
%Error: t/t_interface_mismodport_bad.v:32:12: Can't find definition of 'bad' in dotted signal: 'isub.bad'
|
||||||
32 | isub.bad = i_value;
|
32 | isub.bad = i_value;
|
||||||
| ^~~
|
| ^~~
|
||||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
|
||||||
... Known scopes under 'bad': <no instances found>
|
... Known scopes under 'bad': <no instances found>
|
||||||
|
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||||
%Error: Exiting due to
|
%Error: Exiting due to
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue