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);
|
||||
}
|
||||
|
||||
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
|
||||
void V3ErrorGuarded::v3errorEnd(std::ostringstream& sstr, const string& extra)
|
||||
VL_REQUIRES(m_mutex) {
|
||||
|
@ -303,7 +310,6 @@ std::ostringstream& V3Error::v3errorPrepFileLine(V3ErrorCode code, const char* f
|
|||
v3errorPrep(code) << file << ":" << std::dec << line << ": ";
|
||||
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) {
|
||||
s().v3errorEnd(sstr, extra);
|
||||
V3Error::s().m_mutex.unlock();
|
||||
|
|
|
@ -325,7 +325,7 @@ private:
|
|||
= V3ErrorCode::EC_FATAL; // Error string being formed will abort
|
||||
bool m_errorSuppressed VL_GUARDED_BY(m_mutex)
|
||||
= 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)
|
||||
= nullptr; // Callback when error occurs for dumping
|
||||
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
|
||||
std::ostringstream m_errorStr VL_GUARDED_BY(m_mutex); // Error string being formed
|
||||
|
||||
void v3errorPrep(V3ErrorCode code) VL_REQUIRES(m_mutex) {
|
||||
m_errorStr.str("");
|
||||
m_errorCode = code;
|
||||
m_errorContexted = false;
|
||||
m_errorSuppressed = false;
|
||||
}
|
||||
void v3errorPrep(V3ErrorCode code) VL_REQUIRES(m_mutex);
|
||||
std::ostringstream& v3errorStr() VL_REQUIRES(m_mutex) { return m_errorStr; }
|
||||
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);
|
||||
void vlAbortOrExit() VL_REQUIRES(m_mutex);
|
||||
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) {
|
||||
m_errCount++;
|
||||
++m_errCount;
|
||||
if (errorCount() == errorLimit()) { // Not >= as would otherwise recurse
|
||||
v3errorEnd(
|
||||
(v3errorPrep(V3ErrorCode::EC_FATALMANY),
|
||||
|
@ -509,14 +504,6 @@ public:
|
|||
|
||||
// When printing an error/warning, print prefix for multiline message
|
||||
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
|
||||
// should be printed after information on the error code.
|
||||
// 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& v3errorPrepFileLine(V3ErrorCode code, const char* file, int line)
|
||||
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 void v3errorEnd(std::ostringstream& sstr, const string& extra = "")
|
||||
VL_RELEASE(s().m_mutex);
|
||||
|
|
|
@ -464,10 +464,6 @@ string FileLine::warnOther() const VL_REQUIRES(V3Error::s().m_mutex) {
|
|||
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 {
|
||||
if (VL_UNCOVERABLE(!m_contentp)) { // LCOV_EXCL_START
|
||||
|
|
|
@ -301,7 +301,6 @@ public:
|
|||
void warnUnusedOff(bool flag);
|
||||
void warnStateFrom(const FileLine& from) { m_msgEnIdx = from.m_msgEnIdx; }
|
||||
void warnResetDefault() { warnStateFrom(defaultFileLine()); }
|
||||
bool lastWarnWaived() const { return m_waive; }
|
||||
|
||||
// Specific flag ACCESSORS/METHODS
|
||||
bool celldefineOn() const { return msgEn().test(V3ErrorCode::I_CELLDEFINE); }
|
||||
|
@ -356,7 +355,6 @@ public:
|
|||
/// When building an error, prefix for printing secondary information
|
||||
/// from a different FileLine than the original error
|
||||
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
|
||||
/// If not used in a given error, automatically pasted at end of error
|
||||
string warnContextPrimary() const VL_REQUIRES(V3Error::s().m_mutex) {
|
||||
|
|
|
@ -233,13 +233,16 @@ void V3Graph::clearColors() {
|
|||
//======================================================================
|
||||
// Dumping
|
||||
|
||||
void V3Graph::loopsMessageCb(V3GraphVertex* vertexp) {
|
||||
vertexp->v3fatalSrc("Loops detected in graph: " << vertexp);
|
||||
void V3Graph::loopsMessageCb(V3GraphVertex* vertexp, V3EdgeFuncP edgeFuncp) {
|
||||
vertexp->v3fatalSrc("Loops detected in graph: " << vertexp << "\n"
|
||||
<< reportLoops(edgeFuncp, vertexp));
|
||||
}
|
||||
|
||||
void V3Graph::loopsVertexCb(V3GraphVertex* vertexp) {
|
||||
string V3Graph::loopsVertexCb(V3GraphVertex* vertexp) {
|
||||
// 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 {
|
||||
|
|
|
@ -430,7 +430,7 @@ public:
|
|||
|
||||
/// Call loopsVertexCb on any one loop starting where specified
|
||||
/// 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
|
||||
/// Side-effect: changes user()
|
||||
|
@ -484,8 +484,8 @@ public:
|
|||
parallelismReport(std::function<uint64_t(const V3GraphVertex*)> vertexCost) VL_MT_DISABLED;
|
||||
|
||||
// CALLBACKS
|
||||
virtual void loopsMessageCb(V3GraphVertex* vertexp) VL_MT_DISABLED;
|
||||
virtual void loopsVertexCb(V3GraphVertex* vertexp) VL_MT_DISABLED;
|
||||
virtual void loopsMessageCb(V3GraphVertex* vertexp, V3EdgeFuncP edgeFuncp) VL_MT_DISABLED;
|
||||
virtual string loopsVertexCb(V3GraphVertex* vertexp) VL_MT_DISABLED;
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
|
|
@ -343,10 +343,9 @@ void GraphAcyc::simplifyOut(GraphAcycVertex* avertexp) {
|
|||
V3GraphVertex* inVertexp = inEdgep->fromp();
|
||||
if (inVertexp == avertexp) {
|
||||
if (debug()) v3error("Non-cutable vertex=" << avertexp); // LCOV_EXCL_LINE
|
||||
v3error("Circular logic when ordering code (non-cutable edge loop)");
|
||||
m_origGraphp->reportLoops(
|
||||
&V3GraphEdge::followNotCutable,
|
||||
avertexp->origVertexp()); // calls OrderGraph::loopsVertexCb
|
||||
v3error("Circular logic when ordering code (non-cutable edge loop)\n"
|
||||
<< m_origGraphp->reportLoops( // calls OrderGraph::loopsVertexCb
|
||||
&V3GraphEdge::followNotCutable, avertexp->origVertexp()));
|
||||
// Things are unlikely to end well at this point,
|
||||
// but we'll try something to get to further errors...
|
||||
inEdgep->cutable(true);
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
@ -281,8 +282,7 @@ class GraphAlgRank final : GraphAlg<> {
|
|||
// If larger rank is found, assign it and loop back through
|
||||
// If we hit a back node make a list of all loops
|
||||
if (vertexp->user() == 1) {
|
||||
m_graphp->reportLoops(m_edgeFuncp, vertexp);
|
||||
m_graphp->loopsMessageCb(vertexp);
|
||||
m_graphp->loopsMessageCb(vertexp, m_edgeFuncp);
|
||||
return; // LCOV_EXCL_LINE // gcc gprof bug misses this return
|
||||
}
|
||||
if (vertexp->rank() >= currentRank) return; // Already processed it
|
||||
|
@ -313,6 +313,7 @@ void V3Graph::rank(V3EdgeFuncP edgeFuncp) { GraphAlgRank{this, edgeFuncp}; }
|
|||
|
||||
class GraphAlgRLoops final : GraphAlg<> {
|
||||
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
|
||||
|
||||
void main(V3GraphVertex* vertexp) {
|
||||
|
@ -333,9 +334,8 @@ class GraphAlgRLoops final : GraphAlg<> {
|
|||
m_callTrace[currentRank++] = vertexp;
|
||||
|
||||
if (vertexp->user() == 1) {
|
||||
for (unsigned i = 0; i < currentRank; i++) { //
|
||||
m_graphp->loopsVertexCb(m_callTrace[i]);
|
||||
}
|
||||
for (unsigned i = 0; i < currentRank; i++)
|
||||
m_msgs.emplace_back(m_graphp->loopsVertexCb(m_callTrace[i]));
|
||||
m_done = true;
|
||||
return;
|
||||
}
|
||||
|
@ -353,10 +353,13 @@ public:
|
|||
main(vertexp);
|
||||
}
|
||||
~GraphAlgRLoops() = default;
|
||||
string message() const {
|
||||
return std::accumulate(m_msgs.begin(), m_msgs.end(), std::string{""});
|
||||
}
|
||||
};
|
||||
|
||||
void V3Graph::reportLoops(V3EdgeFuncP edgeFuncp, V3GraphVertex* vertexp) {
|
||||
GraphAlgRLoops{this, edgeFuncp, vertexp};
|
||||
string V3Graph::reportLoops(V3EdgeFuncP edgeFuncp, V3GraphVertex* vertexp) {
|
||||
return GraphAlgRLoops{this, edgeFuncp, vertexp}.message();
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
|
|
@ -43,7 +43,7 @@ class LinkCellsGraph final : public V3Graph {
|
|||
public:
|
||||
LinkCellsGraph() = default;
|
||||
~LinkCellsGraph() override = default;
|
||||
void loopsMessageCb(V3GraphVertex* vertexp) override;
|
||||
void loopsMessageCb(V3GraphVertex* vertexp, V3EdgeFuncP edgeFuncp) override;
|
||||
};
|
||||
|
||||
class LinkCellsVertex final : public V3GraphVertex {
|
||||
|
@ -73,7 +73,7 @@ public:
|
|||
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>()) {
|
||||
vvertexp->modp()->v3warn(E_UNSUPPORTED,
|
||||
"Unsupported: Recursive multiple modules (module instantiates "
|
||||
|
|
|
@ -3422,11 +3422,11 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
<< (!baddot.empty() ? AstNode::prettyNameQ(baddot)
|
||||
: nodep->prettyNameQ())
|
||||
<< " in dotted " << expectWhat << ": '"
|
||||
<< m_ds.m_dotText + "." + nodep->prettyName() << "'");
|
||||
if (okSymp) {
|
||||
okSymp->cellErrorScopes(nodep,
|
||||
AstNode::prettyName(m_ds.m_dotText));
|
||||
}
|
||||
<< m_ds.m_dotText + "." + nodep->prettyName() << "'\n"
|
||||
<< nodep->warnContextPrimary()
|
||||
<< (okSymp ? okSymp->cellErrorScopes(
|
||||
nodep, AstNode::prettyName(m_ds.m_dotText))
|
||||
: ""));
|
||||
}
|
||||
m_ds.m_dotErr = true;
|
||||
}
|
||||
|
@ -3611,8 +3611,9 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
if (!nodep->varp()) {
|
||||
nodep->v3error("Can't find definition of "
|
||||
<< AstNode::prettyNameQ(baddot) << " in dotted signal: '"
|
||||
<< nodep->dotted() + "." + nodep->prettyName() << "'");
|
||||
okSymp->cellErrorScopes(nodep);
|
||||
<< nodep->dotted() + "." + nodep->prettyName() << "'\n"
|
||||
<< nodep->warnContextPrimary()
|
||||
<< okSymp->cellErrorScopes(nodep));
|
||||
return;
|
||||
}
|
||||
// V3Inst may have expanded arrays of interfaces to
|
||||
|
@ -3636,8 +3637,9 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
if (!vscp) {
|
||||
nodep->v3error("Can't find varpin scope of "
|
||||
<< AstNode::prettyNameQ(baddot) << " in dotted signal: '"
|
||||
<< nodep->dotted() + "." + nodep->prettyName() << "'");
|
||||
okSymp->cellErrorScopes(nodep);
|
||||
<< nodep->dotted() + "." + nodep->prettyName() << "'\n"
|
||||
<< nodep->warnContextPrimary()
|
||||
<< okSymp->cellErrorScopes(nodep));
|
||||
} else {
|
||||
while (vscp->user2p()) { // If V3Inline aliased it, pick up the new signal
|
||||
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,
|
||||
true);
|
||||
if (!dotSymp) {
|
||||
okSymp->cellErrorScopes(nodep);
|
||||
nodep->v3fatalSrc("Couldn't resolve inlined scope "
|
||||
<< 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,
|
||||
|
@ -3974,8 +3977,9 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
nodep->v3error("Can't find definition of "
|
||||
<< AstNode::prettyNameQ(baddot) << " in dotted task/function: '"
|
||||
<< nodep->dotted() + "." + nodep->prettyName() << "'\n"
|
||||
<< (suggest.empty() ? "" : nodep->warnMore() + suggest));
|
||||
okSymp->cellErrorScopes(nodep);
|
||||
<< (suggest.empty() ? "" : nodep->warnMore() + suggest) << '\n'
|
||||
<< 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
|
||||
if (errmsg != "") {
|
||||
fl->v3error(errmsg + "'"s + filename + "'"s);
|
||||
filePathLookedMsg(fl, filename);
|
||||
fl->v3error(errmsg << "'"s << filename << "'\n"s << fl->warnContextPrimary()
|
||||
<< V3Error::warnAdditionalInfo() << filePathLookedMsg(fl, filename));
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void V3Options::filePathLookedMsg(FileLine* fl, const string& modname) {
|
||||
string V3Options::filePathLookedMsg(FileLine* fl, const string& modname) {
|
||||
static bool shown_notfound_msg = false;
|
||||
std::ostringstream ss;
|
||||
if (modname.find("__Vhsh") != string::npos) {
|
||||
std::cerr << V3Error::warnMoreStandalone()
|
||||
<< "... Note: Name is longer than 127 characters; automatic"
|
||||
<< " file lookup may have failed due to OS filename length limits.\n";
|
||||
std::cerr << V3Error::warnMoreStandalone()
|
||||
<< "... Suggest putting filename with this module/package"
|
||||
<< " onto command line instead.\n";
|
||||
ss << V3Error::warnMore() << "... Note: Name is longer than 127 characters; automatic"
|
||||
<< " file lookup may have failed due to OS filename length limits.\n";
|
||||
ss << V3Error::warnMore() << "... Suggest putting filename with this module/package"
|
||||
<< " onto command line instead.\n";
|
||||
} else if (!shown_notfound_msg) {
|
||||
shown_notfound_msg = true;
|
||||
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& ext : m_impp->m_libExtVs) {
|
||||
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& ext : m_impp->m_libExtVs) {
|
||||
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
|
||||
|
|
|
@ -779,7 +779,7 @@ public:
|
|||
string fileExists(const string& filename);
|
||||
string filePath(FileLine* fl, const string& modname, const string& lastpath,
|
||||
const string& errmsg);
|
||||
void filePathLookedMsg(FileLine* fl, const string& modname);
|
||||
string filePathLookedMsg(FileLine* fl, const string& modname);
|
||||
V3LangCode fileLanguage(const string& filename);
|
||||
static bool fileStatNormal(const string& filename);
|
||||
|
||||
|
|
|
@ -100,17 +100,16 @@ public:
|
|||
};
|
||||
|
||||
class Graph final : public V3Graph {
|
||||
void loopsVertexCb(V3GraphVertex* vtxp) override {
|
||||
// TODO: 'typeName' is an internal thing. This should be more human readable.
|
||||
string loopsVertexCb(V3GraphVertex* vtxp) override {
|
||||
if (SchedAcyclicLogicVertex* const lvtxp = vtxp->cast<SchedAcyclicLogicVertex>()) {
|
||||
AstNode* const logicp = lvtxp->logicp();
|
||||
std::cerr << logicp->fileline()->warnOtherStandalone()
|
||||
<< " Example path: " << logicp->typeName() << endl;
|
||||
return logicp->fileline()->warnOther()
|
||||
+ " Example path: " + logicp->prettyTypeName() + "\n";
|
||||
} else {
|
||||
SchedAcyclicVarVertex* const vvtxp = vtxp->as<SchedAcyclicVarVertex>();
|
||||
AstVarScope* const vscp = vvtxp->vscp();
|
||||
std::cerr << vscp->fileline()->warnOtherStandalone()
|
||||
<< " Example path: " << vscp->prettyName() << endl;
|
||||
return vscp->fileline()->warnOther() + " Example path: " + vscp->prettyName()
|
||||
+ "\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.
|
||||
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.
|
||||
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.
|
||||
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
|
||||
// important" signals.
|
||||
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::ostringstream ss2;
|
||||
for (size_t i = 0; i < 10; i++) {
|
||||
if (i == candidates.size()) break;
|
||||
const Candidate& candidate = candidates[i];
|
||||
AstVar* const varp = candidate.first->varp();
|
||||
std::cerr << V3Error::warnMoreStandalone() << " " << varp->fileline() << " "
|
||||
<< varp->prettyName() << ", width " << std::dec << varp->width()
|
||||
<< ", circular fanout " << candidate.second;
|
||||
|
||||
ss2 << V3Error::warnMore() << " " << varp->fileline() << ' ' << varp->prettyName()
|
||||
<< ", width " << std::dec << varp->width() << ", circular fanout "
|
||||
<< candidate.second;
|
||||
if (V3SplitVar::canSplitVar(varp)) {
|
||||
std::cerr << ", can split_var";
|
||||
ss2 << ", can split_var";
|
||||
++splittable;
|
||||
}
|
||||
std::cerr << '\n';
|
||||
ss2 << '\n';
|
||||
}
|
||||
return ss2.str();
|
||||
};
|
||||
|
||||
// Widest variables
|
||||
std::cerr << V3Error::warnMoreStandalone() << "... Widest variables candidate to splitting:\n";
|
||||
reportFirst10([](const Candidate& a, const Candidate& b) {
|
||||
return a.first->varp()->width() > b.first->varp()->width();
|
||||
});
|
||||
ss << V3Error::warnMore() << "... Widest variables candidate to splitting:\n"
|
||||
<< reportFirst10([](const Candidate& a, const Candidate& b) {
|
||||
return a.first->varp()->width() > b.first->varp()->width();
|
||||
});
|
||||
|
||||
// Highest fanout
|
||||
std::cerr << V3Error::warnMoreStandalone() << "... Candidates with the highest fanout:\n";
|
||||
reportFirst10([](const Candidate& a, const Candidate& b) { //
|
||||
return a.second > b.second;
|
||||
});
|
||||
ss << V3Error::warnMore() << "... Candidates with the highest fanout:\n"
|
||||
<< reportFirst10([](const Candidate& a, const Candidate& b) { //
|
||||
return a.second > b.second;
|
||||
});
|
||||
|
||||
if (splittable) {
|
||||
std::cerr << V3Error::warnMoreStandalone()
|
||||
<< "... Suggest add /*verilator split_var*/ or /*verilator "
|
||||
"isolate_assignments*/ to appropriate variables above."
|
||||
<< std::endl;
|
||||
ss << V3Error::warnMore()
|
||||
<< "... Suggest add /*verilator split_var*/ or /*verilator "
|
||||
"isolate_assignments*/ to appropriate variables above.\n";
|
||||
}
|
||||
V3Stats::addStat("Scheduling, split_var, candidates", splittable);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
// First v3warn not inside warnIsOff so we can see the suppressions with --debug
|
||||
vscp->v3warn(UNOPTFLAT, "Signal unoptimizable: Circular combinational logic: "
|
||||
<< vscp->prettyNameQ());
|
||||
if (!flp->warnIsOff(V3ErrorCode::UNOPTFLAT) && !flp->lastWarnWaived()) {
|
||||
if (flp->warnIsOff(V3ErrorCode::UNOPTFLAT)) {
|
||||
// First v3warn not inside warnIsOff so we can see the suppressions with --debug
|
||||
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
|
||||
flp->modifyWarnOff(V3ErrorCode::UNOPTFLAT, true);
|
||||
// Calls Graph::loopsVertexCb
|
||||
graphp->reportLoops(&V3GraphEdge::followAlwaysTrue, vvtxp);
|
||||
// Create a subgraph for the UNOPTFLAT loop
|
||||
if (v3Global.opt.reportUnoptflat()) {
|
||||
// Report candidate variables for splitting
|
||||
reportLoopVars(graphp, vvtxp);
|
||||
// Create a subgraph for the UNOPTFLAT loop
|
||||
V3Graph loopGraph;
|
||||
graphp->subtreeLoops(&V3GraphEdge::followAlwaysTrue, vvtxp, &loopGraph);
|
||||
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();
|
||||
string scopes;
|
||||
for (IdNameMap::iterator it = m_idNameMap.begin(); it != m_idNameMap.end(); ++it) {
|
||||
|
@ -267,9 +267,9 @@ public:
|
|||
}
|
||||
}
|
||||
if (scopes == "") scopes = "<no instances found>";
|
||||
std::cerr << V3Error::warnMoreStandalone() << "... Known scopes under '" << prettyName
|
||||
<< "': " << scopes << endl;
|
||||
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
|
||||
// finally time to report it.
|
||||
// Note only here in V3Width as this is first visitor after V3Dead.
|
||||
nodep->modNameFileline()->v3error("Cannot find file containing module: '"
|
||||
<< nodep->modName() << "'");
|
||||
v3Global.opt.filePathLookedMsg(nodep->modNameFileline(), nodep->modName());
|
||||
nodep->modNameFileline()->v3error(
|
||||
"Cannot find file containing module: '"
|
||||
<< 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());
|
||||
userIterateAndNext(nodep->pinsp(), nullptr);
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
8 | nfound nfound();
|
||||
| ^~~~~~
|
||||
... 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>.
|
||||
8 | nfound nfound();
|
||||
| ^~~~~~
|
||||
... This may be because there's no search path specified with -I<dir>.
|
||||
... Looked in:
|
||||
nfound
|
||||
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'
|
||||
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>
|
||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||
%Error: Exiting due to
|
||||
|
|
Loading…
Reference in New Issue