Internals: Create AstNodeSelItem in prep for future commits.
No real functional change, outside of minor debug dump differences.
This commit is contained in:
parent
ab668b066f
commit
ddbfc176b6
|
|
@ -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: "
|
||||
<<senp->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: "
|
||||
<<itemp->varrefp()->prettyName());
|
||||
sequent = true;
|
||||
itemp->varrefp()->varp()->usedClock(true);
|
||||
}
|
||||
} else {
|
||||
senp->v3fatalSrc("Strange node under sentree");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
15
src/V3Ast.h
15
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:
|
||||
|
|
|
|||
|
|
@ -186,15 +186,16 @@ void AstSenTree::sortSenses() {
|
|||
// Also, remove duplicate assignments, and fold POS&NEGs into ANYEDGEs
|
||||
//cout<<endl; this->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<AstSenItem*> 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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -370,8 +370,8 @@ private:
|
|||
UINFO(4," Act: "<<m_activep<<endl);
|
||||
UINFO(4," Act: "<<oldactivep<<endl);
|
||||
// Make a new sensitivity list, which is the combination of both blocks
|
||||
AstSenItem* sena = m_activep->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()) {
|
||||
|
|
|
|||
|
|
@ -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"); }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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<<str; }
|
||||
void putbs(const string& str) { m_os<<str; }
|
||||
void putsNoTracking(const string& str) { m_os<<str; }
|
||||
|
||||
public:
|
||||
EmitVStreamVisitor(AstNode* nodep, ostream& os)
|
||||
: m_os(os) {
|
||||
nodep->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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
class V3EmitV {
|
||||
public:
|
||||
static void emitv();
|
||||
static void verilogForTree(AstNode* nodep, ostream& os=cout);
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<<" "<<setw(50)<<name<<" ";
|
||||
AstSenTree* sentreep = vvertexp->domainp();
|
||||
if (sentreep) {
|
||||
bool first = true;
|
||||
for (AstSenItem* itemp=sentreep->sensesp(); itemp; itemp=itemp->nextp()->castSenItem()) {
|
||||
if (first) os<<"@( "; else os<<", ";
|
||||
first = false;
|
||||
os<<itemp->edgeType().verilogKwd();
|
||||
if (itemp->varrefp()) {
|
||||
os<<" "+itemp->varrefp()->prettyName();
|
||||
}
|
||||
}
|
||||
if (!first) os<<" )";
|
||||
}
|
||||
if (sentreep) V3EmitV::verilogForTree(sentreep, os);
|
||||
report.push_back(os.str());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ class AstSenTree;
|
|||
AstParseRef* parserefp;
|
||||
AstPin* pinp;
|
||||
AstRange* rangep;
|
||||
AstSenItem* senitemp;
|
||||
AstNodeSenItem* senitemp;
|
||||
AstSenTree* sentreep;
|
||||
AstVar* varp;
|
||||
AstVarRef* varrefp;
|
||||
|
|
|
|||
Loading…
Reference in New Issue