CDC: Repress duplicate paths through same signal

This commit is contained in:
Wilson Snyder 2010-01-15 14:04:15 -05:00
parent 97adede70b
commit a2af4e1284
2 changed files with 24 additions and 18 deletions

View File

@ -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();

View File

@ -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.*',
); );