mirror of
https://github.com/verilator/verilator.git
synced 2025-04-30 20:46:54 +00:00
CDC: Repress duplicate paths through same signal
This commit is contained in:
parent
97adede70b
commit
a2af4e1284
@ -109,18 +109,19 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class CdcLogicVertex : public CdcEitherVertex {
|
class CdcLogicVertex : public CdcEitherVertex {
|
||||||
bool m_safe;
|
bool m_hazard;
|
||||||
bool m_isFlop;
|
bool m_isFlop;
|
||||||
public:
|
public:
|
||||||
CdcLogicVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep, AstSenTree* sensenodep)
|
CdcLogicVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep, AstSenTree* sensenodep)
|
||||||
: CdcEitherVertex(graphp,scopep,nodep), m_safe(true), m_isFlop(false)
|
: CdcEitherVertex(graphp,scopep,nodep), m_hazard(false), m_isFlop(false)
|
||||||
{ srcDomainp(sensenodep); dstDomainp(sensenodep); }
|
{ srcDomainp(sensenodep); dstDomainp(sensenodep); }
|
||||||
virtual ~CdcLogicVertex() {}
|
virtual ~CdcLogicVertex() {}
|
||||||
// Accessors
|
// Accessors
|
||||||
virtual string name() const { return (cvtToStr((void*)nodep())+"@"+scopep()->prettyName()); }
|
virtual string name() const { return (cvtToStr((void*)nodep())+"@"+scopep()->prettyName()); }
|
||||||
virtual string dotColor() const { return safe() ? "black" : "yellow"; }
|
virtual string dotColor() const { return hazard() ? "black" : "yellow"; }
|
||||||
bool safe() const { return m_safe; }
|
bool hazard() const { return m_hazard; }
|
||||||
void clearSafe(AstNode* nodep) { m_safe = false; nodep->user3(true); }
|
void setHazard(AstNode* nodep) { m_hazard = true; nodep->user3(true); }
|
||||||
|
void clearHazard() { m_hazard = false; }
|
||||||
bool isFlop() const { return m_isFlop; }
|
bool isFlop() const { return m_isFlop; }
|
||||||
void isFlop(bool flag) { m_isFlop = flag; }
|
void isFlop(bool flag) { m_isFlop = flag; }
|
||||||
};
|
};
|
||||||
@ -131,7 +132,7 @@ class CdcDumpVisitor : public CdcBaseVisitor {
|
|||||||
private:
|
private:
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
//Entire netlist:
|
//Entire netlist:
|
||||||
// {statement}Node::user3p -> bool, indicating not safe
|
// {statement}Node::user3p -> bool, indicating not hazard
|
||||||
ofstream* m_ofp; // Output file
|
ofstream* m_ofp; // Output file
|
||||||
string m_prefix;
|
string m_prefix;
|
||||||
|
|
||||||
@ -279,13 +280,13 @@ private:
|
|||||||
*m_ofp<<"%Warning-"<<code.ascii()<<": "<<nodep->fileline()<<" "<<msg<<endl;
|
*m_ofp<<"%Warning-"<<code.ascii()<<": "<<nodep->fileline()<<" "<<msg<<endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearNodeSafe(AstNode* nodep) {
|
void setNodeHazard(AstNode* nodep) {
|
||||||
// Need to not clear if warnings are off (rather than when report it)
|
// Need to not clear if warnings are off (rather than when report it)
|
||||||
// as bypassing this warning may turn up another path that isn't warning off'ed.
|
// as bypassing this warning may turn up another path that isn't warning off'ed.
|
||||||
if (!m_domainp || m_domainp->hasCombo()) { // Source flop logic in a posedge block is OK for reset (not async though)
|
if (!m_domainp || m_domainp->hasCombo()) { // Source flop logic in a posedge block is OK for reset (not async though)
|
||||||
if (m_logicVertexp && !nodep->fileline()->warnIsOff(V3ErrorCode::CDCRSTLOGIC)) {
|
if (m_logicVertexp && !nodep->fileline()->warnIsOff(V3ErrorCode::CDCRSTLOGIC)) {
|
||||||
UINFO(9,"Clear safe "<<nodep<<endl);
|
UINFO(9,"Set hazard "<<nodep<<endl);
|
||||||
m_logicVertexp->clearSafe(nodep);
|
m_logicVertexp->setHazard(nodep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -343,7 +344,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
CdcEitherVertex* traceAsyncRecurse(CdcEitherVertex* vertexp, bool mark) {
|
CdcEitherVertex* traceAsyncRecurse(CdcEitherVertex* vertexp, bool mark) {
|
||||||
// Return vertex of any dangerous stuff attached, or NULL if OK
|
// Return vertex of any hazardous stuff attached, or NULL if OK
|
||||||
if (vertexp->user()>=m_userGeneration) return false; // Processed - prevent loop
|
if (vertexp->user()>=m_userGeneration) return false; // Processed - prevent loop
|
||||||
vertexp->user(m_userGeneration);
|
vertexp->user(m_userGeneration);
|
||||||
|
|
||||||
@ -355,7 +356,7 @@ private:
|
|||||||
|
|
||||||
if (CdcLogicVertex* vvertexp = dynamic_cast<CdcLogicVertex*>(vertexp)) {
|
if (CdcLogicVertex* vvertexp = dynamic_cast<CdcLogicVertex*>(vertexp)) {
|
||||||
// Any logic considered bad, at the moment, anyhow
|
// Any logic considered bad, at the moment, anyhow
|
||||||
if (!vvertexp->safe() && !mark_outp) mark_outp = vvertexp;
|
if (vvertexp->hazard() && !mark_outp) mark_outp = vvertexp;
|
||||||
// And keep tracing back so the user can understand what's up
|
// And keep tracing back so the user can understand what's up
|
||||||
}
|
}
|
||||||
else if (CdcVarVertex* vvertexp = dynamic_cast<CdcVarVertex*>(vertexp)) {
|
else if (CdcVarVertex* vvertexp = dynamic_cast<CdcVarVertex*>(vertexp)) {
|
||||||
@ -410,7 +411,7 @@ private:
|
|||||||
bool dumpAsyncRecurse(CdcEitherVertex* vertexp, const string& prefix, const string& sep, int level) {
|
bool dumpAsyncRecurse(CdcEitherVertex* vertexp, const string& prefix, const string& sep, int level) {
|
||||||
// level=0 is special, indicates to dump destination flop
|
// level=0 is special, indicates to dump destination flop
|
||||||
// Return true if printed anything
|
// Return true if printed anything
|
||||||
// If mark, also mark the output even if nothing dangerous below
|
// If mark, also mark the output even if nothing hazardous below
|
||||||
if (vertexp->user()>=m_userGeneration) return false; // Processed - prevent loop
|
if (vertexp->user()>=m_userGeneration) return false; // Processed - prevent loop
|
||||||
vertexp->user(m_userGeneration);
|
vertexp->user(m_userGeneration);
|
||||||
if (!vertexp->asyncPath() && level!=0) return false; // Not part of path
|
if (!vertexp->asyncPath() && level!=0) return false; // Not part of path
|
||||||
@ -442,6 +443,12 @@ private:
|
|||||||
|
|
||||||
nextsep = " | ";
|
nextsep = " | ";
|
||||||
if (level) *m_ofp<<V3OutFile::indentSpaces(filelineWidth())<<" "<<prefix<<nextsep<<"\n";
|
if (level) *m_ofp<<V3OutFile::indentSpaces(filelineWidth())<<" "<<prefix<<nextsep<<"\n";
|
||||||
|
|
||||||
|
if (CdcLogicVertex* vvertexp = dynamic_cast<CdcLogicVertex*>(vertexp)) {
|
||||||
|
// Now that we've printed a path with this hazard, don't bother to print any more
|
||||||
|
// Otherwise, we'd get a path for almost every destination flop
|
||||||
|
vvertexp->clearHazard();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -640,7 +647,7 @@ private:
|
|||||||
iterateNewStmt(nodep);
|
iterateNewStmt(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Math that shouldn't cause us to clear safe
|
// Math that shouldn't cause us to clear hazard
|
||||||
virtual void visit(AstConst* nodep, AstNUser*) { }
|
virtual void visit(AstConst* nodep, AstNUser*) { }
|
||||||
virtual void visit(AstReplicate* nodep, AstNUser*) {
|
virtual void visit(AstReplicate* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
@ -652,11 +659,11 @@ private:
|
|||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstSel* nodep, AstNUser*) {
|
virtual void visit(AstSel* nodep, AstNUser*) {
|
||||||
if (!nodep->lsbp()->castConst()) clearNodeSafe(nodep);
|
if (!nodep->lsbp()->castConst()) setNodeHazard(nodep);
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeSel* nodep, AstNUser*) {
|
virtual void visit(AstNodeSel* nodep, AstNUser*) {
|
||||||
if (!nodep->bitp()->castConst()) clearNodeSafe(nodep);
|
if (!nodep->bitp()->castConst()) setNodeHazard(nodep);
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -668,7 +675,7 @@ private:
|
|||||||
//--------------------
|
//--------------------
|
||||||
// Default
|
// Default
|
||||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {
|
virtual void visit(AstNodeMath* nodep, AstNUser*) {
|
||||||
clearNodeSafe(nodep);
|
setNodeHazard(nodep);
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
@ -696,7 +703,7 @@ public:
|
|||||||
*m_ofp<<"Each dump below traces logic from inputs/source flops to destination flop(s).\n";
|
*m_ofp<<"Each dump below traces logic from inputs/source flops to destination flop(s).\n";
|
||||||
*m_ofp<<"First source logic is listed, then a variable that logic generates,\n";
|
*m_ofp<<"First source logic is listed, then a variable that logic generates,\n";
|
||||||
*m_ofp<<"repeating recursively forwards to the destination flop(s).\n";
|
*m_ofp<<"repeating recursively forwards to the destination flop(s).\n";
|
||||||
*m_ofp<<"%% Indicates the operator considered potentially unsafe.\n";
|
*m_ofp<<"%% Indicates the operator considered potentially hazardous.\n";
|
||||||
|
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
analyze();
|
analyze();
|
||||||
|
@ -16,7 +16,6 @@ compile (
|
|||||||
%Warning-CDCRSTLOGIC: Use "/\* verilator lint_off CDCRSTLOGIC \*/" and lint_on around source to disable this message.
|
%Warning-CDCRSTLOGIC: Use "/\* verilator lint_off CDCRSTLOGIC \*/" and lint_on around source to disable this message.
|
||||||
%Warning-CDCRSTLOGIC: See details in obj_dir/t_cdc_async_bad/Vt_cdc_async_bad__cdc.txt
|
%Warning-CDCRSTLOGIC: See details in obj_dir/t_cdc_async_bad/Vt_cdc_async_bad__cdc.txt
|
||||||
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: TOP->v.rst6a_bad_n
|
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: TOP->v.rst6a_bad_n
|
||||||
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: TOP->v.rst6b_bad_n
|
|
||||||
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: TOP->v.rst3_bad_n
|
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: TOP->v.rst3_bad_n
|
||||||
%Error: Exiting due to.*',
|
%Error: Exiting due to.*',
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user