diff --git a/src/V3Active.cpp b/src/V3Active.cpp index 3622656f9..12178a06c 100644 --- a/src/V3Active.cpp +++ b/src/V3Active.cpp @@ -255,7 +255,10 @@ private: nodep->unlinkFrBack()->deleteTree(); nodep=NULL; return; } - if (nodep->sensesp() && nodep->sensesp()->sensesp() && nodep->sensesp()->sensesp()->isNever()) { + if (nodep->sensesp() + && nodep->sensesp()->sensesp() + && nodep->sensesp()->sensesp()->castSenItem() + && nodep->sensesp()->sensesp()->castSenItem()->isNever()) { // Never executing. Kill it. if (nodep->sensesp()->sensesp()->nextp()) nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated."); nodep->unlinkFrBack()->deleteTree(); nodep=NULL; @@ -266,18 +269,22 @@ private: bool combo = false; bool sequent = false; if (nodep->sensesp()) { - for (AstSenItem* nextp, *senp = nodep->sensesp()->sensesp(); senp; senp=nextp) { - nextp = senp->nextp()->castSenItem(); - if (senp->edgeType() == AstEdgeType::ANYEDGE) { - combo = true; - // Delete the sensitivity - // We'll add it as a generic COMBO SenItem in a moment. - senp->unlinkFrBack()->deleteTree(); senp=NULL; - } else if (senp->varrefp()) { - if (senp->varrefp()->width()>1) senp->v3error("Unsupported: Non-single bit wide signal pos/negedge sensitivity: " - <varrefp()->prettyName()); - sequent = true; - senp->varrefp()->varp()->usedClock(true); + for (AstNodeSenItem* nextp, *senp = nodep->sensesp()->sensesp(); senp; senp=nextp) { + nextp = senp->nextp()->castNodeSenItem(); + if (AstSenItem* itemp = senp->castSenItem()) { + if (itemp->edgeType() == AstEdgeType::ANYEDGE) { + combo = true; + // Delete the sensitivity + // We'll add it as a generic COMBO SenItem in a moment. + itemp->unlinkFrBack()->deleteTree(); itemp=NULL; senp=NULL; + } else if (itemp->varrefp()) { + if (itemp->varrefp()->width()>1) itemp->v3error("Unsupported: Non-single bit wide signal pos/negedge sensitivity: " + <varrefp()->prettyName()); + sequent = true; + itemp->varrefp()->varp()->usedClock(true); + } + } else { + senp->v3fatalSrc("Strange node under sentree"); } } } diff --git a/src/V3ActiveTop.cpp b/src/V3ActiveTop.cpp index c957dccfe..35996c5c3 100644 --- a/src/V3ActiveTop.cpp +++ b/src/V3ActiveTop.cpp @@ -71,7 +71,9 @@ private: AstSenTree* sensesp = nodep->sensesp(); if (!sensesp) nodep->v3fatalSrc("NULL"); sensesp->sortSenses(); // Remove duplicate clocks and such - if (sensesp->sensesp() && sensesp->sensesp()->isNever()) { + if (sensesp->sensesp() + && sensesp->sensesp()->castSenItem() + && sensesp->sensesp()->castSenItem()->isNever()) { // Never executing. Kill it. if (sensesp->sensesp()->nextp()) nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated."); nodep->unlinkFrBack()->deleteTree(); nodep=NULL; diff --git a/src/V3AssertPre.cpp b/src/V3AssertPre.cpp index afdf63279..566b9f8b5 100644 --- a/src/V3AssertPre.cpp +++ b/src/V3AssertPre.cpp @@ -44,9 +44,9 @@ private: // NODE STATE/TYPES // STATE // Reset each module: - AstSenItem* m_seniDefaultp; // Default sensitivity (from AstDefClock) + AstNodeSenItem* m_seniDefaultp; // Default sensitivity (from AstDefClock) // Reset each assertion: - AstSenItem* m_senip; // Last sensitivity + AstNodeSenItem* m_senip; // Last sensitivity int debug() { return 0; } @@ -55,7 +55,7 @@ private: // Create sentree based on clocked or default clock // Return NULL for always AstSenTree* newp = NULL; - AstSenItem* senip = m_senip ? m_senip : m_seniDefaultp; + AstNodeSenItem* senip = m_senip ? m_senip : m_seniDefaultp; if (!senip) { nodep->v3error("Unsupported: Unclocked assertion"); newp = new AstSenTree(nodep->fileline(), NULL); diff --git a/src/V3Ast.h b/src/V3Ast.h index 5885a187c..17ea84943 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -149,8 +149,8 @@ public: }; const char* verilogKwd() const { static const char* names[] = { - "%E-edge", "", "[both]", "posedge", "negedge", "[high]","[low]", - "/*AS*/","[initial]","[settle]","[never]" + "%E-edge", "[any]", "[both]", "posedge", "negedge", "[high]","[low]", + "*","[initial]","[settle]","[never]" }; return names[m_e]; }; @@ -924,6 +924,17 @@ struct AstNodeCase : public AstNodeStmt { void addNotParallelp(AstNode* nodep) { setOp3p(nodep); } }; +struct AstNodeSenItem : public AstNode { + // A AstSenItem under + AstNodeSenItem(FileLine* fl) : AstNode(fl) {} + ASTNODE_BASE_FUNCS(NodeSenItem) + virtual bool isClocked() const = 0; + virtual bool isCombo() const = 0; + virtual bool isInitial() const = 0; + virtual bool isSettle() const = 0; + virtual bool isNever() const = 0; +}; + class AstNodeVarRef : public AstNodeMath { // A AstVarRef or AstVarXRef private: diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index ee73e5264..4adddc396 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -186,15 +186,16 @@ void AstSenTree::sortSenses() { // Also, remove duplicate assignments, and fold POS&NEGs into ANYEDGEs //cout<dumpTree(cout,"ssin: "); AstSenItem* nextp; + if (sensesp() && !sensesp()->castSenItem()) v3fatalSrc("Unsupported node type under sentree"); // Make things a little faster; check first if we need a sort - for (AstSenItem* senp = sensesp(); senp; senp=senp->nextp()->castSenItem()) { + for (AstSenItem* senp = sensesp()->castSenItem(); senp; senp=senp->nextp()->castSenItem()) { nextp=senp->nextp()->castSenItem(); AstSenItemCmp cmp; if (nextp && !cmp(senp, nextp)) { // Something's out of order, sort it senp = NULL; vector vec; - for (AstSenItem* senp = sensesp(); senp; senp=senp->nextp()->castSenItem()) { + for (AstSenItem* senp = sensesp()->castSenItem(); senp; senp=senp->nextp()->castSenItem()) { vec.push_back(senp); } sort(vec.begin(), vec.end(), AstSenItemCmp()); @@ -209,7 +210,7 @@ void AstSenTree::sortSenses() { } // Pass2, remove dup edges - for (AstSenItem* senp = sensesp(); senp; senp=nextp) { + for (AstSenItem* senp = sensesp()->castSenItem(); senp; senp=nextp) { nextp=senp->nextp()->castSenItem(); AstSenItem* cmpp = nextp; if (cmpp @@ -236,7 +237,7 @@ void AstSenTree::sortSenses() { // Pass3, remove nevers if (sensesp()->nextp()) { // Else only one never, can't remove it - for (AstSenItem* senp = sensesp(); senp; senp=nextp) { + for (AstSenItem* senp = sensesp()->castSenItem(); senp; senp=nextp) { nextp=senp->nextp()->castSenItem(); if (senp->isNever()) { senp->unlinkFrBack()->deleteTree(); senp=NULL; @@ -248,28 +249,28 @@ void AstSenTree::sortSenses() { bool AstSenTree::hasClocked() { if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it"); - for (AstSenItem* senp = sensesp(); senp; senp=senp->nextp()->castSenItem()) { + for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) { if (senp->isClocked()) return true; } return false; } bool AstSenTree::hasSettle() { if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it"); - for (AstSenItem* senp = sensesp(); senp; senp=senp->nextp()->castSenItem()) { + for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) { if (senp->isSettle()) return true; } return false; } bool AstSenTree::hasInitial() { if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it"); - for (AstSenItem* senp = sensesp(); senp; senp=senp->nextp()->castSenItem()) { + for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) { if (senp->isInitial()) return true; } return false; } bool AstSenTree::hasCombo() { if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it"); - for (AstSenItem* senp = sensesp(); senp; senp=senp->nextp()->castSenItem()) { + for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) { if (senp->isCombo()) return true; } return false; diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 21be9dd9a..93ae9e6ca 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -799,7 +799,7 @@ struct AstFuncRef : public AstNodeFTaskRef { //###################################################################### -struct AstSenItem : public AstNode { +struct AstSenItem : public AstNodeSenItem { // Parents: SENTREE // Children: (optional) VARREF private: @@ -810,27 +810,27 @@ public: class Settle {}; // for creator type-overload selection class Never {}; // for creator type-overload selection AstSenItem(FileLine* fl, AstEdgeType edgeType, AstNodeVarRef* varrefp) - : AstNode(fl), m_edgeType(edgeType) { + : AstNodeSenItem(fl), m_edgeType(edgeType) { setOp1p(varrefp); } AstSenItem(FileLine* fl, AstEdgeType edgeType, AstParseRef* varrefp) - : AstNode(fl), m_edgeType(edgeType) { + : AstNodeSenItem(fl), m_edgeType(edgeType) { setOp1p(varrefp); } AstSenItem(FileLine* fl, Combo) - : AstNode(fl) { + : AstNodeSenItem(fl) { m_edgeType = AstEdgeType::COMBO; } AstSenItem(FileLine* fl, Initial) - : AstNode(fl) { + : AstNodeSenItem(fl) { m_edgeType = AstEdgeType::INITIAL; } AstSenItem(FileLine* fl, Settle) - : AstNode(fl) { + : AstNodeSenItem(fl) { m_edgeType = AstEdgeType::SETTLE; } AstSenItem(FileLine* fl, Never) - : AstNode(fl) { + : AstNodeSenItem(fl) { m_edgeType = AstEdgeType::NEVER; } ASTNODE_NODE_FUNCS(SenItem, SENITEM) @@ -843,11 +843,11 @@ public: AstNode* sensp() const { return op1p(); } // op1 = Signal sensitized AstNodeVarRef* varrefp() const { return op1p()->castNodeVarRef(); } // op1 = Signal sensitized // - bool isClocked() const { return edgeType().clockedStmt(); } - bool isCombo() const { return edgeType()==AstEdgeType::COMBO; } - bool isInitial() const { return edgeType()==AstEdgeType::INITIAL; } - bool isSettle() const { return edgeType()==AstEdgeType::SETTLE; } - bool isNever() const { return edgeType()==AstEdgeType::NEVER; } + virtual bool isClocked() const { return edgeType().clockedStmt(); } + virtual bool isCombo() const { return edgeType()==AstEdgeType::COMBO; } + virtual bool isInitial() const { return edgeType()==AstEdgeType::INITIAL; } + virtual bool isSettle() const { return edgeType()==AstEdgeType::SETTLE; } + virtual bool isNever() const { return edgeType()==AstEdgeType::NEVER; } bool hasVar() const { return !(isCombo()||isInitial()||isSettle()||isNever()); } }; @@ -858,7 +858,7 @@ struct AstSenTree : public AstNode { private: bool m_multi; // Created from combo logic by ORing multiple clock domains public: - AstSenTree(FileLine* fl, AstSenItem* sensesp) + AstSenTree(FileLine* fl, AstNodeSenItem* sensesp) : AstNode(fl), m_multi(false) { addNOp1p(sensesp); } @@ -866,8 +866,8 @@ public: virtual void dump(ostream& str); virtual bool maybePointedTo() const { return true; } bool isMulti() const { return m_multi; } - AstSenItem* sensesp() const { return op1p()->castSenItem(); } // op1 = Sensitivity list - void addSensesp(AstSenItem* nodep) { addOp1p(nodep); } + AstNodeSenItem* sensesp() const { return op1p()->castNodeSenItem(); } // op1 = Sensitivity list + void addSensesp(AstNodeSenItem* nodep) { addOp1p(nodep); } void multi(bool flag) { m_multi = true; } // METHODS void sortSenses(); // Sort senitems in standard way @@ -2450,13 +2450,13 @@ struct AstClocking : public AstNode { // Parents: MODULE // Children: Assertions public: - AstClocking(FileLine* fl, AstSenItem* sensesp, AstNode* bodysp) + AstClocking(FileLine* fl, AstNodeSenItem* sensesp, AstNode* bodysp) : AstNode(fl) { addOp1p(sensesp); addNOp2p(bodysp); } ASTNODE_NODE_FUNCS(Clocking, CLOCKING) - AstSenItem* sensesp() const { return op1p()->castSenItem(); } // op1 = Sensitivity list + AstNodeSenItem* sensesp() const { return op1p()->castNodeSenItem(); } // op1 = Sensitivity list AstNode* bodysp() const { return op2p(); } // op2 = Body }; @@ -2468,12 +2468,12 @@ struct AstPslDefClock : public AstNode { // Parents: MODULE // Children: SENITEM public: - AstPslDefClock(FileLine* fl, AstSenItem* sensesp) + AstPslDefClock(FileLine* fl, AstNodeSenItem* sensesp) : AstNode(fl) { addNOp1p(sensesp); } ASTNODE_NODE_FUNCS(PslDefClock, PSLDEFCLOCK) - AstSenItem* sensesp() const { return op1p()->castSenItem(); } // op1 = Sensitivity list + AstNodeSenItem* sensesp() const { return op1p()->castNodeSenItem(); } // op1 = Sensitivity list }; struct AstPslClocked : public AstNode { @@ -2481,14 +2481,14 @@ struct AstPslClocked : public AstNode { // Parents: ASSERT|COVER (property) // Children: SENITEM, Properties public: - AstPslClocked(FileLine* fl, AstSenItem* sensesp, AstNode* disablep, AstNode* propp) + AstPslClocked(FileLine* fl, AstNodeSenItem* sensesp, AstNode* disablep, AstNode* propp) : AstNode(fl) { addNOp1p(sensesp); addNOp2p(disablep); addOp3p(propp); } ASTNODE_NODE_FUNCS(PslClocked, PSLCLOCKED) - AstSenItem* sensesp() const { return op1p()->castSenItem(); } // op1 = Sensitivity list + AstNodeSenItem* sensesp() const { return op1p()->castNodeSenItem(); } // op1 = Sensitivity list AstNode* disablep() const { return op2p(); } // op2 = disable AstNode* propp() const { return op3p(); } // op3 = property }; diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp index da7cc5a67..a568bc535 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -106,48 +106,57 @@ private: m_scopep->addVarp(newvscp); return newvscp; } + AstNode* createSenItemEquation(AstSenItem* nodep) { + // We know the var is clean, and one bit, so we use binary ops + // for speed instead of logical ops. + // POSEDGE: var & ~var_last + // NEGEDGE: ~var & var_last + // BOTHEDGE: var ^ var_last + // HIGHEDGE: var + // LOWEDGE: ~var + AstNode* newp = NULL; + AstVarScope* clkvscp = nodep->varrefp()->varScopep(); + if (nodep->edgeType()==AstEdgeType::POSEDGE) { + AstVarScope* lastVscp = getCreateLastClk(clkvscp); + newp = new AstAnd(nodep->fileline(), + new AstVarRef(nodep->fileline(), + nodep->varrefp()->varScopep(), false), + new AstNot(nodep->fileline(), + new AstVarRef(nodep->fileline(), + lastVscp, false))); + } else if (nodep->edgeType()==AstEdgeType::NEGEDGE) { + AstVarScope* lastVscp = getCreateLastClk(clkvscp); + newp = new AstAnd(nodep->fileline(), + new AstNot(nodep->fileline(), + new AstVarRef(nodep->fileline(), + nodep->varrefp()->varScopep(), false)), + new AstVarRef(nodep->fileline(), lastVscp, false)); + } else if (nodep->edgeType()==AstEdgeType::BOTHEDGE) { + AstVarScope* lastVscp = getCreateLastClk(clkvscp); + newp = new AstXor(nodep->fileline(), + new AstVarRef(nodep->fileline(), + nodep->varrefp()->varScopep(), false), + new AstVarRef(nodep->fileline(), lastVscp, false)); + } else if (nodep->edgeType()==AstEdgeType::HIGHEDGE) { + newp = new AstVarRef(nodep->fileline(), + clkvscp, false); + } else if (nodep->edgeType()==AstEdgeType::LOWEDGE) { + newp = new AstNot(nodep->fileline(), + new AstVarRef(nodep->fileline(), + clkvscp, false)); + } else { + nodep->v3fatalSrc("Bad edge type"); + } + return newp; + } AstNode* createSenseEquation(AstSenTree* nodep) { AstNode* senEqnp = NULL; - for (AstSenItem* senp = nodep->sensesp(); senp; senp=senp->nextp()->castSenItem()) { - // We know the var is clean, and one bit, so we use binary ops - // for speed instead of logical ops. - // POSEDGE: var & ~var_last - // NEGEDGE: ~var & var_last - // BOTHEDGE: var ^ var_last - // HIGHEDGE: var - // LOWEDGE: ~var - AstVarScope* lastVscp = senp->varrefp()->varScopep()->userp()->castNode()->castVarScope(); + for (AstNodeSenItem* senp = nodep->sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) { AstNode* senOnep = NULL; - if (senp->edgeType()==AstEdgeType::POSEDGE) { - if (!lastVscp) senp->v3fatalSrc("No last var ptr?\n"); - senOnep = new AstAnd(senp->fileline(), - new AstVarRef(senp->fileline(), - senp->varrefp()->varScopep(), false), - new AstNot(senp->fileline(), - new AstVarRef(senp->fileline(), - lastVscp, false))); - } else if (senp->edgeType()==AstEdgeType::NEGEDGE) { - if (!lastVscp) senp->v3fatalSrc("No last var ptr?\n"); - senOnep = new AstAnd(senp->fileline(), - new AstNot(senp->fileline(), - new AstVarRef(senp->fileline(), - senp->varrefp()->varScopep(), false)), - new AstVarRef(senp->fileline(), lastVscp, false)); - } else if (senp->edgeType()==AstEdgeType::BOTHEDGE) { - if (!lastVscp) senp->v3fatalSrc("No last var ptr?\n"); - senOnep = new AstXor(senp->fileline(), - new AstVarRef(senp->fileline(), - senp->varrefp()->varScopep(), false), - new AstVarRef(senp->fileline(), lastVscp, false)); - } else if (senp->edgeType()==AstEdgeType::HIGHEDGE) { - senOnep = new AstVarRef(senp->fileline(), - senp->varrefp()->varScopep(), false); - } else if (senp->edgeType()==AstEdgeType::LOWEDGE) { - senOnep = new AstNot(senp->fileline(), - new AstVarRef(senp->fileline(), - senp->varrefp()->varScopep(), false)); + if (AstSenItem* itemp = senp->castSenItem()) { + senOnep = createSenItemEquation(itemp); } else { - senp->v3fatalSrc("Bad edge type"); + senp->v3fatalSrc("Strange node under sentree"); } if (senEqnp) { // Add new OR to the sensitivity list equation @@ -159,13 +168,6 @@ private: return senEqnp; } AstIf* makeActiveIf(AstSenTree* sensesp) { - for (AstSenItem* senp = sensesp->sensesp(); senp; senp=senp->nextp()->castSenItem()) { - if (senp->edgeType() != AstEdgeType::HIGHEDGE - && senp->varrefp()) { - AstVarScope* oldvscp = senp->varrefp()->varScopep(); - getCreateLastClk(oldvscp); - } - } AstNode* senEqnp = createSenseEquation(sensesp); if (!senEqnp) sensesp->v3fatalSrc("No sense equation, shouldn't be in sequent activation."); AstIf* newifp = new AstIf (sensesp->fileline(), diff --git a/src/V3Delayed.cpp b/src/V3Delayed.cpp index 84c9cf8e8..6156b9705 100644 --- a/src/V3Delayed.cpp +++ b/src/V3Delayed.cpp @@ -370,8 +370,8 @@ private: UINFO(4," Act: "<sensesp()->sensesp()->cloneTree(true); - AstSenItem* senb = oldactivep->sensesp()->sensesp()->cloneTree(true); + AstNodeSenItem* sena = m_activep->sensesp()->sensesp()->cloneTree(true); + AstNodeSenItem* senb = oldactivep->sensesp()->sensesp()->cloneTree(true); AstSenTree* treep = new AstSenTree(m_activep->fileline(), sena); if (senb) treep->addSensesp(senb); if (AstSenTree* storep = oldactivep->sensesStorep()) { diff --git a/src/V3EmitCBase.h b/src/V3EmitCBase.h index fea68e139..3fa486989 100644 --- a/src/V3EmitCBase.h +++ b/src/V3EmitCBase.h @@ -78,9 +78,9 @@ public: virtual void putsIntTopInclude() { puts("#include \"systemperl.h\"\n"); } }; -class V3OutVFile : public V3OutCFile { +class V3OutVFile : public V3OutFile { public: - V3OutVFile(const string& filename) : V3OutCFile(filename) {} + V3OutVFile(const string& filename) : V3OutFile(filename) {} virtual ~V3OutVFile() {}; virtual void putsHeader() { puts("// Verilated -*- Verilog -*-\n"); } }; diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index ef57ab2b7..28266cb5b 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -35,25 +35,24 @@ //###################################################################### // Emit statements and math operators -class EmitVImp : public EmitCBaseVisitor { -private: +class EmitVBaseVisitor : public EmitCBaseVisitor { + // MEMBERS bool m_suppressSemi; - AstModule* m_modp; -public: //int debug() { return 9; } // METHODS - + virtual void puts(const string& str) = 0; + virtual void putbs(const string& str) = 0; + virtual void putsNoTracking(const string& str) = 0; + // VISITORS virtual void visit(AstNetlist* nodep, AstNUser*) { nodep->iterateChildren(*this); } virtual void visit(AstModule* nodep, AstNUser*) { - m_modp = nodep; putbs("module "+modClassName(nodep)+";\n"); nodep->iterateChildren(*this); puts("endmodule\n"); - m_modp = NULL; } virtual void visit(AstNodeFTask* nodep, AstNUser*) { putbs(nodep->castTask() ? "task ":"function "); @@ -87,7 +86,7 @@ public: virtual void visit(AstAlways* nodep, AstNUser*) { putbs("always "); nodep->sensesp()->iterateAndNext(*this); - putbs("begin\n"); + putbs(" begin\n"); nodep->bodysp()->iterateAndNext(*this); puts("end\n"); } @@ -118,17 +117,17 @@ public: if (!m_suppressSemi) puts(";\n"); } virtual void visit(AstSenTree* nodep, AstNUser*) { + // AstSenItem is called for dumping in isolation by V3Order putbs("@("); nodep->iterateChildren(*this); - puts(") "); + puts(")"); } virtual void visit(AstSenItem* nodep, AstNUser*) { putbs(""); - if (nodep->backp()->castSenItem()) puts(" or "); + if (!nodep->backp()->castSenTree()) puts(" or "); puts(nodep->edgeType().verilogKwd()); - puts(" "); + if (nodep->sensp()) puts(" "); nodep->iterateChildren(*this); - puts(" "); } virtual void visit(AstNodeCase* nodep, AstNUser*) { putbs(nodep->verilogKwd()); @@ -170,7 +169,7 @@ public: putbs(" ("); if (filep) { filep->iterateAndNext(*this); putbs(","); } puts("\""); - ofp()->putsNoTracking(text); + putsNoTracking(text); puts("\""); for (AstNode* expp=exprsp; expp; expp = expp->nextp()) { puts(","); @@ -261,7 +260,7 @@ public: putbs("$finish;\n"); } virtual void visit(AstText* nodep, AstNUser*) { - ofp()->putsNoTracking(nodep->text()); + putsNoTracking(nodep->text()); } virtual void visit(AstScopeName* nodep, AstNUser*) { } @@ -434,21 +433,50 @@ public: } public: - EmitVImp() { + EmitVBaseVisitor() { m_suppressSemi = false; - m_modp = NULL; } - void main(AstNode* nodep, V3OutCFile* ofp); - virtual ~EmitVImp() {} + virtual ~EmitVBaseVisitor() {} }; //###################################################################### +// Emit to an output file -void EmitVImp::main(AstNode* modp, V3OutCFile* ofp) { - // Output a module, or overall netlist - m_ofp = ofp; - modp->accept(*this); -} +class EmitVFileVisitor : public EmitVBaseVisitor { + // MEMBERS + V3OutFile* m_ofp; + // METHODS + V3OutFile* ofp() const { return m_ofp; }; + void puts(const string& str) { ofp()->puts(str); } + void putbs(const string& str) { ofp()->putbs(str); } + void putsNoTracking(const string& str) { ofp()->putsNoTracking(str); } + +public: + EmitVFileVisitor(AstNode* nodep, V3OutFile* ofp) { + m_ofp = ofp; + nodep->accept(*this); + } + virtual ~EmitVFileVisitor() {} +}; + +//###################################################################### +// Emit to a stream (perhaps stringstream) + +class EmitVStreamVisitor : public EmitVBaseVisitor { + // MEMBERS + ostream& m_os; + // METHODS + void puts(const string& str) { m_os<accept(*this); + } + virtual ~EmitVStreamVisitor() {} +}; //###################################################################### // EmitV class functions @@ -459,15 +487,18 @@ void V3EmitV::emitv() { // All-in-one file V3OutVFile of (v3Global.opt.makeDir()+"/"+v3Global.opt.prefix()+"__Vout.v"); of.putsHeader(); - EmitVImp imp; - imp.main(v3Global.rootp(), &of); + EmitVFileVisitor visitor (v3Global.rootp(), &of); } else { // Process each module in turn for (AstModule* modp = v3Global.rootp()->modulesp(); modp; modp=modp->nextp()->castModule()) { - EmitVImp imp; - V3OutVFile of (v3Global.opt.makeDir()+"/"+imp.modClassName(modp)+"__Vout.v"); + V3OutVFile of (v3Global.opt.makeDir() + +"/"+EmitCBaseVisitor::modClassName(modp)+"__Vout.v"); of.putsHeader(); - imp.main(modp, &of); + EmitVFileVisitor visitor (modp, &of); } } } + +void V3EmitV::verilogForTree(AstNode* nodep, ostream& os) { + EmitVStreamVisitor(nodep, os); +} diff --git a/src/V3EmitV.h b/src/V3EmitV.h index 5e9647d46..d11edb20d 100644 --- a/src/V3EmitV.h +++ b/src/V3EmitV.h @@ -31,6 +31,7 @@ class V3EmitV { public: static void emitv(); + static void verilogForTree(AstNode* nodep, ostream& os=cout); }; #endif // Guard diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index fe5d7eac3..768e7f646 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -356,7 +356,7 @@ private: virtual void visit(AstCFunc* nodep, AstNUser*) { iterateNewStmt(nodep, "User C Function", "User C Function"); } - virtual void visit(AstSenItem* nodep, AstNUser*) { + virtual void visit(AstNodeSenItem* nodep, AstNUser*) { m_inSenItem = true; iterateNewStmt(nodep, NULL, NULL); m_inSenItem = false; diff --git a/src/V3Order.cpp b/src/V3Order.cpp index 38578e4ee..b3423ece4 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -110,6 +110,7 @@ #include "V3Order.h" #include "V3OrderGraph.h" +#include "V3EmitV.h" class OrderMoveDomScope; @@ -239,7 +240,6 @@ private: // Forming graph: // Entire Netlist: // AstVarScope::userp -> OrderUser* for usage var - // AstActive::user3() -> uint clocks hash of sensitivity list // {statement}Node::userp-> AstModule* statement is under // USER5 Cleared on each Logic stmt // AstVarScope::user5() -> VarUsage(gen/con/both). Where already encountered signal @@ -480,17 +480,6 @@ private: m_activep = nodep; m_activeSenVxp = NULL; m_inClocked = nodep->hasClocked(); - // Compute hash of sensitivity list - V3Hash clocks; - if (nodep->sensesp()) { - for (AstSenItem* senp = nodep->sensesp()->sensesp(); senp; senp=senp->nextp()->castSenItem()) { - clocks = V3Hash(clocks, V3Hash(senp->edgeType())); - if (senp->varrefp()) { - clocks = V3Hash(clocks, V3Hash(senp->varrefp()->varScopep())); - } - } - } - nodep->user3(clocks.hshval()); // Grab the sensitivity list if (nodep->sensesStorep()) nodep->v3fatalSrc("Senses should have been activeTop'ed to be global!"); nodep->sensesp()->accept(*this); @@ -1086,7 +1075,7 @@ void OrderVisitor::processDomainsIterate(OrderEitherVertex* vertexp) { fromVertexp->domainp()->dumpTree(cout); } AstSenTree* newtreep = domainp->cloneTree(false); - AstSenItem* newtree2p = fromVertexp->domainp()->sensesp()->cloneTree(true); + AstNodeSenItem* newtree2p = fromVertexp->domainp()->sensesp()->cloneTree(true); if (!newtree2p) fromVertexp->domainp()->v3fatalSrc("No senitem found under clocked domain"); newtreep->addSensesp(newtree2p); newtreep->sortSenses(); // Remove duplicates @@ -1143,18 +1132,7 @@ void OrderVisitor::processEdgeReport() { os.setf(ios::left); os<<" "<domainp(); - if (sentreep) { - bool first = true; - for (AstSenItem* itemp=sentreep->sensesp(); itemp; itemp=itemp->nextp()->castSenItem()) { - if (first) os<<"@( "; else os<<", "; - first = false; - os<edgeType().verilogKwd(); - if (itemp->varrefp()) { - os<<" "+itemp->varrefp()->prettyName(); - } - } - if (!first) os<<" )"; - } + if (sentreep) V3EmitV::verilogForTree(sentreep, os); report.push_back(os.str()); } } diff --git a/src/V3SenTree.h b/src/V3SenTree.h index 4fa7e469b..423aff9d2 100644 --- a/src/V3SenTree.h +++ b/src/V3SenTree.h @@ -66,7 +66,7 @@ private: virtual void visit(AstTopScope* nodep, AstNUser*) { m_topscopep = nodep; nodep->iterateChildren(*this); - // Don't clear scopep, the namer persists beyond this visit + // Don't clear topscopep, the namer persists beyond this visit } virtual void visit(AstScope* nodep, AstNUser*) { // But no SenTrees under TopScope's scope diff --git a/src/verilog.y b/src/verilog.y index 5f033e054..42c2a8677 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -124,7 +124,7 @@ class AstSenTree; AstParseRef* parserefp; AstPin* pinp; AstRange* rangep; - AstSenItem* senitemp; + AstNodeSenItem* senitemp; AstSenTree* sentreep; AstVar* varp; AstVarRef* varrefp;