mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 10:03:44 +02:00
Internals: Detab and fix spacing style issues. No functional change.
When diff, recommend using "git diff --ignore-all-space" When merging, recommend using "git merge -Xignore-all-space"
This commit is contained in:
+271
-266
@@ -22,11 +22,11 @@
|
||||
// Top Scope:
|
||||
// Check created ACTIVEs
|
||||
// Compress adjacent ACTIVEs with same sensitivity list
|
||||
// Form master _eval function
|
||||
// Add around the SENTREE a (IF POSEDGE(..))
|
||||
// Add a __Vlast_{clock} for the comparison
|
||||
// Set the __Vlast_{clock} at the end of the block
|
||||
// Replace UNTILSTABLEs with loops until specified signals become const.
|
||||
// Form master _eval function
|
||||
// Add around the SENTREE a (IF POSEDGE(..))
|
||||
// Add a __Vlast_{clock} for the comparison
|
||||
// Set the __Vlast_{clock} at the end of the block
|
||||
// Replace UNTILSTABLEs with loops until specified signals become const.
|
||||
// Create global calling function for any per-scope functions. (For FINALs).
|
||||
//
|
||||
//*************************************************************************
|
||||
@@ -49,22 +49,22 @@ class ClockVisitor : public AstNVisitor {
|
||||
private:
|
||||
// NODE STATE
|
||||
// Cleared each Module:
|
||||
// AstVarScope::user1p() -> AstVarScope*. Temporary signal that was created.
|
||||
AstUser1InUse m_inuser1;
|
||||
// AstVarScope::user1p() -> AstVarScope*. Temporary signal that was created.
|
||||
AstUser1InUse m_inuser1;
|
||||
|
||||
// TYPES
|
||||
enum { DOUBLE_OR_RATE = 10 }; // How many | per ||, Determined experimentally as best
|
||||
enum { DOUBLE_OR_RATE = 10 }; // How many | per ||, Determined experimentally as best
|
||||
|
||||
// STATE
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstTopScope* m_topScopep; // Current top scope
|
||||
AstScope* m_scopep; // Current scope
|
||||
AstCFunc* m_evalFuncp; // Top eval function we are creating
|
||||
AstCFunc* m_initFuncp; // Top initial function we are creating
|
||||
AstCFunc* m_finalFuncp; // Top final function we are creating
|
||||
AstCFunc* m_settleFuncp; // Top settlement function we are creating
|
||||
AstSenTree* m_lastSenp; // Last sensitivity match, so we can detect duplicates.
|
||||
AstIf* m_lastIfp; // Last sensitivity if active to add more under
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstTopScope* m_topScopep; // Current top scope
|
||||
AstScope* m_scopep; // Current scope
|
||||
AstCFunc* m_evalFuncp; // Top eval function we are creating
|
||||
AstCFunc* m_initFuncp; // Top initial function we are creating
|
||||
AstCFunc* m_finalFuncp; // Top final function we are creating
|
||||
AstCFunc* m_settleFuncp; // Top settlement function we are creating
|
||||
AstSenTree* m_lastSenp; // Last sensitivity match, so we can detect duplicates.
|
||||
AstIf* m_lastIfp; // Last sensitivity if active to add more under
|
||||
AstMTaskBody* m_mtaskBodyp; // Current mtask body
|
||||
|
||||
// METHODS
|
||||
@@ -72,15 +72,18 @@ private:
|
||||
|
||||
AstVarScope* getCreateLastClk(AstVarScope* vscp) {
|
||||
if (vscp->user1p()) return static_cast<AstVarScope*>(vscp->user1p());
|
||||
AstVar* varp = vscp->varp();
|
||||
if (!varp->width1()) varp->v3error("Unsupported: Clock edge on non-single bit signal: "<<varp->prettyName());
|
||||
string newvarname = (string("__Vclklast__")+vscp->scopep()->nameDotless()+"__"+varp->name());
|
||||
AstVar* newvarp = new AstVar(vscp->fileline(), AstVarType::MODULETEMP, newvarname, VFlagLogicPacked(), 1);
|
||||
AstVar* varp = vscp->varp();
|
||||
if (!varp->width1()) varp->v3error("Unsupported: Clock edge on non-single bit signal: "
|
||||
<<varp->prettyName());
|
||||
string newvarname = (string("__Vclklast__")
|
||||
+vscp->scopep()->nameDotless()+"__"+varp->name());
|
||||
AstVar* newvarp = new AstVar(vscp->fileline(),
|
||||
AstVarType::MODULETEMP, newvarname, VFlagLogicPacked(), 1);
|
||||
newvarp->noReset(true); // Reset by below assign
|
||||
m_modp->addStmtp(newvarp);
|
||||
AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopep, newvarp);
|
||||
vscp->user1p(newvscp);
|
||||
m_scopep->addVarp(newvscp);
|
||||
m_modp->addStmtp(newvarp);
|
||||
AstVarScope* newvscp = new AstVarScope(vscp->fileline(), m_scopep, newvarp);
|
||||
vscp->user1p(newvscp);
|
||||
m_scopep->addVarp(newvscp);
|
||||
// Add init
|
||||
AstNode* fromp = new AstVarRef(newvarp->fileline(), vscp, false);
|
||||
if (v3Global.opt.xInitialEdge()) fromp = new AstNot(fromp->fileline(), fromp);
|
||||
@@ -88,243 +91,245 @@ private:
|
||||
new AstVarRef(newvarp->fileline(), newvscp, true),
|
||||
fromp);
|
||||
addToInitial(newinitp);
|
||||
// At bottom, assign them
|
||||
AstAssign* finalp
|
||||
// At bottom, assign them
|
||||
AstAssign* finalp
|
||||
= new AstAssign(vscp->fileline(),
|
||||
new AstVarRef(vscp->fileline(), newvscp, true),
|
||||
new AstVarRef(vscp->fileline(), vscp, false));
|
||||
m_evalFuncp->addFinalsp(finalp);
|
||||
//
|
||||
UINFO(4,"New Last: "<<newvscp<<endl);
|
||||
return newvscp;
|
||||
m_evalFuncp->addFinalsp(finalp);
|
||||
//
|
||||
UINFO(4,"New Last: "<<newvscp<<endl);
|
||||
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;
|
||||
if (nodep->edgeType()==AstEdgeType::ET_ILLEGAL) {
|
||||
if (!v3Global.opt.bboxUnsup()) {
|
||||
nodep->v3error("Unsupported: Complicated event expression in sensitive activity list");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
AstVarScope* clkvscp = nodep->varrefp()->varScopep();
|
||||
if (nodep->edgeType()==AstEdgeType::ET_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::ET_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::ET_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::ET_HIGHEDGE) {
|
||||
newp = new AstVarRef(nodep->fileline(),
|
||||
clkvscp, false);
|
||||
} else if (nodep->edgeType()==AstEdgeType::ET_LOWEDGE) {
|
||||
newp = new AstNot(nodep->fileline(),
|
||||
new AstVarRef(nodep->fileline(),
|
||||
clkvscp, false));
|
||||
} else {
|
||||
nodep->v3fatalSrc("Bad edge type");
|
||||
}
|
||||
return newp;
|
||||
// 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;
|
||||
if (nodep->edgeType()==AstEdgeType::ET_ILLEGAL) {
|
||||
if (!v3Global.opt.bboxUnsup()) {
|
||||
nodep->v3error("Unsupported: Complicated event expression in sensitive activity list");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
AstVarScope* clkvscp = nodep->varrefp()->varScopep();
|
||||
if (nodep->edgeType()==AstEdgeType::ET_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::ET_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::ET_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::ET_HIGHEDGE) {
|
||||
newp = new AstVarRef(nodep->fileline(),
|
||||
clkvscp, false);
|
||||
} else if (nodep->edgeType()==AstEdgeType::ET_LOWEDGE) {
|
||||
newp = new AstNot(nodep->fileline(),
|
||||
new AstVarRef(nodep->fileline(),
|
||||
clkvscp, false));
|
||||
} else {
|
||||
nodep->v3fatalSrc("Bad edge type");
|
||||
}
|
||||
return newp;
|
||||
}
|
||||
AstNode* createSenGateEquation(AstSenGate* nodep) {
|
||||
AstNode* newp = new AstAnd(nodep->fileline(),
|
||||
createSenseEquation(nodep->sensesp()),
|
||||
nodep->rhsp()->cloneTree(true));
|
||||
return newp;
|
||||
AstNode* newp = new AstAnd(nodep->fileline(),
|
||||
createSenseEquation(nodep->sensesp()),
|
||||
nodep->rhsp()->cloneTree(true));
|
||||
return newp;
|
||||
}
|
||||
AstNode* createSenseEquation(AstNodeSenItem* nodesp) {
|
||||
// Nodep may be a list of elements; we need to walk it
|
||||
AstNode* senEqnp = NULL;
|
||||
for (AstNodeSenItem* senp = nodesp; senp; senp=VN_CAST(senp->nextp(), NodeSenItem)) {
|
||||
AstNode* senOnep = NULL;
|
||||
// Nodep may be a list of elements; we need to walk it
|
||||
AstNode* senEqnp = NULL;
|
||||
for (AstNodeSenItem* senp = nodesp; senp; senp = VN_CAST(senp->nextp(), NodeSenItem)) {
|
||||
AstNode* senOnep = NULL;
|
||||
if (AstSenItem* itemp = VN_CAST(senp, SenItem)) {
|
||||
senOnep = createSenItemEquation(itemp);
|
||||
senOnep = createSenItemEquation(itemp);
|
||||
} else if (AstSenGate* itemp = VN_CAST(senp, SenGate)) {
|
||||
senOnep = createSenGateEquation(itemp);
|
||||
} else {
|
||||
senp->v3fatalSrc("Strange node under sentree");
|
||||
}
|
||||
if (senEqnp) {
|
||||
// Add new OR to the sensitivity list equation
|
||||
senEqnp = new AstOr(senp->fileline(), senEqnp, senOnep);
|
||||
} else {
|
||||
senEqnp = senOnep;
|
||||
}
|
||||
}
|
||||
return senEqnp;
|
||||
senOnep = createSenGateEquation(itemp);
|
||||
} else {
|
||||
senp->v3fatalSrc("Strange node under sentree");
|
||||
}
|
||||
if (senEqnp) {
|
||||
// Add new OR to the sensitivity list equation
|
||||
senEqnp = new AstOr(senp->fileline(), senEqnp, senOnep);
|
||||
} else {
|
||||
senEqnp = senOnep;
|
||||
}
|
||||
}
|
||||
return senEqnp;
|
||||
}
|
||||
AstIf* makeActiveIf(AstSenTree* sensesp) {
|
||||
AstNode* senEqnp = createSenseEquation(sensesp->sensesp());
|
||||
if (!senEqnp) sensesp->v3fatalSrc("No sense equation, shouldn't be in sequent activation.");
|
||||
AstNode* senEqnp = createSenseEquation(sensesp->sensesp());
|
||||
if (!senEqnp) sensesp->v3fatalSrc("No sense equation, shouldn't be in sequent activation.");
|
||||
AstIf* newifp = new AstIf(sensesp->fileline(), senEqnp, NULL, NULL);
|
||||
return (newifp);
|
||||
return (newifp);
|
||||
}
|
||||
void clearLastSen() {
|
||||
m_lastSenp = NULL;
|
||||
m_lastIfp = NULL;
|
||||
m_lastSenp = NULL;
|
||||
m_lastIfp = NULL;
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstTopScope* nodep) {
|
||||
UINFO(4," TOPSCOPE "<<nodep<<endl);
|
||||
m_topScopep=nodep;
|
||||
m_scopep = nodep->scopep();
|
||||
if (!m_scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?");
|
||||
//VV***** We reset all user1p()
|
||||
AstNode::user1ClearTree();
|
||||
// Make top functions
|
||||
{
|
||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval", m_scopep);
|
||||
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
funcp->dontCombine(true);
|
||||
funcp->symProlog(true);
|
||||
funcp->isStatic(true);
|
||||
funcp->entryPoint(true);
|
||||
m_scopep->addActivep(funcp);
|
||||
m_evalFuncp = funcp;
|
||||
}
|
||||
{
|
||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval_initial", m_scopep);
|
||||
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
funcp->dontCombine(true);
|
||||
funcp->slow(true);
|
||||
funcp->symProlog(true);
|
||||
funcp->isStatic(true);
|
||||
funcp->entryPoint(true);
|
||||
m_scopep->addActivep(funcp);
|
||||
m_initFuncp = funcp;
|
||||
}
|
||||
{
|
||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "final", m_scopep);
|
||||
funcp->skipDecl(true);
|
||||
funcp->dontCombine(true);
|
||||
funcp->slow(true);
|
||||
funcp->isStatic(false);
|
||||
funcp->entryPoint(true);
|
||||
funcp->addInitsp(new AstCStmt(nodep->fileline(),
|
||||
EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp;\n"));
|
||||
funcp->addInitsp(new AstCStmt(nodep->fileline(), EmitCBaseVisitor::symTopAssign()+"\n"));
|
||||
m_scopep->addActivep(funcp);
|
||||
m_finalFuncp = funcp;
|
||||
}
|
||||
{
|
||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval_settle", m_scopep);
|
||||
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
funcp->dontCombine(true);
|
||||
funcp->slow(true);
|
||||
funcp->isStatic(true);
|
||||
funcp->symProlog(true);
|
||||
funcp->entryPoint(true);
|
||||
m_scopep->addActivep(funcp);
|
||||
m_settleFuncp = funcp;
|
||||
}
|
||||
// Process the activates
|
||||
UINFO(4," TOPSCOPE "<<nodep<<endl);
|
||||
m_topScopep = nodep;
|
||||
m_scopep = nodep->scopep();
|
||||
if (!m_scopep) nodep->v3fatalSrc("No scope found on top level, perhaps you have no statements?");
|
||||
//VV***** We reset all user1p()
|
||||
AstNode::user1ClearTree();
|
||||
// Make top functions
|
||||
{
|
||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval", m_scopep);
|
||||
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
funcp->dontCombine(true);
|
||||
funcp->symProlog(true);
|
||||
funcp->isStatic(true);
|
||||
funcp->entryPoint(true);
|
||||
m_scopep->addActivep(funcp);
|
||||
m_evalFuncp = funcp;
|
||||
}
|
||||
{
|
||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval_initial", m_scopep);
|
||||
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
funcp->dontCombine(true);
|
||||
funcp->slow(true);
|
||||
funcp->symProlog(true);
|
||||
funcp->isStatic(true);
|
||||
funcp->entryPoint(true);
|
||||
m_scopep->addActivep(funcp);
|
||||
m_initFuncp = funcp;
|
||||
}
|
||||
{
|
||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "final", m_scopep);
|
||||
funcp->skipDecl(true);
|
||||
funcp->dontCombine(true);
|
||||
funcp->slow(true);
|
||||
funcp->isStatic(false);
|
||||
funcp->entryPoint(true);
|
||||
funcp->addInitsp(new AstCStmt
|
||||
(nodep->fileline(),
|
||||
EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp;\n"));
|
||||
funcp->addInitsp(new AstCStmt(nodep->fileline(),
|
||||
EmitCBaseVisitor::symTopAssign()+"\n"));
|
||||
m_scopep->addActivep(funcp);
|
||||
m_finalFuncp = funcp;
|
||||
}
|
||||
{
|
||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval_settle", m_scopep);
|
||||
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
funcp->dontCombine(true);
|
||||
funcp->slow(true);
|
||||
funcp->isStatic(true);
|
||||
funcp->symProlog(true);
|
||||
funcp->entryPoint(true);
|
||||
m_scopep->addActivep(funcp);
|
||||
m_settleFuncp = funcp;
|
||||
}
|
||||
// Process the activates
|
||||
iterateChildren(nodep);
|
||||
// Done, clear so we can detect errors
|
||||
UINFO(4," TOPSCOPEDONE "<<nodep<<endl);
|
||||
clearLastSen();
|
||||
m_topScopep=NULL;
|
||||
m_scopep = NULL;
|
||||
// Done, clear so we can detect errors
|
||||
UINFO(4," TOPSCOPEDONE "<<nodep<<endl);
|
||||
clearLastSen();
|
||||
m_topScopep = NULL;
|
||||
m_scopep = NULL;
|
||||
}
|
||||
virtual void visit(AstNodeModule* nodep) {
|
||||
//UINFO(4," MOD "<<nodep<<endl);
|
||||
m_modp = nodep;
|
||||
//UINFO(4," MOD "<<nodep<<endl);
|
||||
m_modp = nodep;
|
||||
iterateChildren(nodep);
|
||||
m_modp= NULL;
|
||||
m_modp= NULL;
|
||||
}
|
||||
virtual void visit(AstScope* nodep) {
|
||||
//UINFO(4," SCOPE "<<nodep<<endl);
|
||||
m_scopep = nodep;
|
||||
//UINFO(4," SCOPE "<<nodep<<endl);
|
||||
m_scopep = nodep;
|
||||
iterateChildren(nodep);
|
||||
if (AstNode* movep = nodep->finalClksp()) {
|
||||
if (!m_topScopep) nodep->v3fatalSrc("Final clocks under non-top scope");
|
||||
movep->unlinkFrBackWithNext();
|
||||
m_evalFuncp->addFinalsp(movep);
|
||||
}
|
||||
m_scopep = NULL;
|
||||
if (AstNode* movep = nodep->finalClksp()) {
|
||||
if (!m_topScopep) nodep->v3fatalSrc("Final clocks under non-top scope");
|
||||
movep->unlinkFrBackWithNext();
|
||||
m_evalFuncp->addFinalsp(movep);
|
||||
}
|
||||
m_scopep = NULL;
|
||||
}
|
||||
virtual void visit(AstAlways* nodep) {
|
||||
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName());
|
||||
nodep->replaceWith(cmtp);
|
||||
if (AstNode* stmtsp = nodep->bodysp()) {
|
||||
stmtsp->unlinkFrBackWithNext();
|
||||
cmtp->addNextHere(stmtsp);
|
||||
}
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName());
|
||||
nodep->replaceWith(cmtp);
|
||||
if (AstNode* stmtsp = nodep->bodysp()) {
|
||||
stmtsp->unlinkFrBackWithNext();
|
||||
cmtp->addNextHere(stmtsp);
|
||||
}
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
virtual void visit(AstAlwaysPost* nodep) {
|
||||
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName());
|
||||
nodep->replaceWith(cmtp);
|
||||
if (AstNode* stmtsp = nodep->bodysp()) {
|
||||
stmtsp->unlinkFrBackWithNext();
|
||||
cmtp->addNextHere(stmtsp);
|
||||
}
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName());
|
||||
nodep->replaceWith(cmtp);
|
||||
if (AstNode* stmtsp = nodep->bodysp()) {
|
||||
stmtsp->unlinkFrBackWithNext();
|
||||
cmtp->addNextHere(stmtsp);
|
||||
}
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
virtual void visit(AstCoverToggle* nodep) {
|
||||
//nodep->dumpTree(cout,"ct:");
|
||||
//COVERTOGGLE(INC, ORIG, CHANGE) ->
|
||||
// IF(ORIG ^ CHANGE) { INC; CHANGE = ORIG; }
|
||||
AstNode* incp = nodep->incp()->unlinkFrBack();
|
||||
AstNode* origp = nodep->origp()->unlinkFrBack();
|
||||
AstNode* changep = nodep->changep()->unlinkFrBack();
|
||||
AstIf* newp = new AstIf(nodep->fileline(),
|
||||
new AstXor(nodep->fileline(),
|
||||
origp,
|
||||
changep),
|
||||
incp, NULL);
|
||||
// We could add another IF to detect posedges, and only increment if so.
|
||||
// It's another whole branch though verus a potential memory miss.
|
||||
// We'll go with the miss.
|
||||
newp->addIfsp(new AstAssign(nodep->fileline(),
|
||||
changep->cloneTree(false),
|
||||
origp->cloneTree(false)));
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
//nodep->dumpTree(cout, "ct:");
|
||||
//COVERTOGGLE(INC, ORIG, CHANGE) ->
|
||||
// IF(ORIG ^ CHANGE) { INC; CHANGE = ORIG; }
|
||||
AstNode* incp = nodep->incp()->unlinkFrBack();
|
||||
AstNode* origp = nodep->origp()->unlinkFrBack();
|
||||
AstNode* changep = nodep->changep()->unlinkFrBack();
|
||||
AstIf* newp = new AstIf(nodep->fileline(),
|
||||
new AstXor(nodep->fileline(),
|
||||
origp,
|
||||
changep),
|
||||
incp, NULL);
|
||||
// We could add another IF to detect posedges, and only increment if so.
|
||||
// It's another whole branch though verus a potential memory miss.
|
||||
// We'll go with the miss.
|
||||
newp->addIfsp(new AstAssign(nodep->fileline(),
|
||||
changep->cloneTree(false),
|
||||
origp->cloneTree(false)));
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
virtual void visit(AstInitial* nodep) {
|
||||
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName());
|
||||
nodep->replaceWith(cmtp);
|
||||
if (AstNode* stmtsp = nodep->bodysp()) {
|
||||
stmtsp->unlinkFrBackWithNext();
|
||||
cmtp->addNextHere(stmtsp);
|
||||
}
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName());
|
||||
nodep->replaceWith(cmtp);
|
||||
if (AstNode* stmtsp = nodep->bodysp()) {
|
||||
stmtsp->unlinkFrBackWithNext();
|
||||
cmtp->addNextHere(stmtsp);
|
||||
}
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) {
|
||||
iterateChildren(nodep);
|
||||
// Link to global function
|
||||
if (nodep->formCallTree()) {
|
||||
UINFO(4, " formCallTree "<<nodep<<endl);
|
||||
AstCCall* callp = new AstCCall(nodep->fileline(), nodep);
|
||||
callp->argTypes("vlSymsp");
|
||||
m_finalFuncp->addStmtsp(callp);
|
||||
}
|
||||
// Link to global function
|
||||
if (nodep->formCallTree()) {
|
||||
UINFO(4, " formCallTree "<<nodep<<endl);
|
||||
AstCCall* callp = new AstCCall(nodep->fileline(), nodep);
|
||||
callp->argTypes("vlSymsp");
|
||||
m_finalFuncp->addStmtsp(callp);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstSenTree* nodep) {
|
||||
// Delete it later; Actives still pointing to it
|
||||
nodep->unlinkFrBack();
|
||||
pushDeletep(nodep);
|
||||
// Delete it later; Actives still pointing to it
|
||||
nodep->unlinkFrBack();
|
||||
pushDeletep(nodep);
|
||||
}
|
||||
void addToEvalLoop(AstNode* stmtsp) {
|
||||
m_evalFuncp->addStmtsp(stmtsp); // add to top level function
|
||||
@@ -336,13 +341,13 @@ private:
|
||||
m_initFuncp->addStmtsp(stmtsp); // add to top level function
|
||||
}
|
||||
virtual void visit(AstActive* nodep) {
|
||||
// Careful if adding variables here, ACTIVES can be under other ACTIVES
|
||||
// Need to save and restore any member state in AstUntilStable block
|
||||
if (!m_topScopep || !nodep->stmtsp()) {
|
||||
// Not at the top or empty block...
|
||||
// Only empty blocks should be leftover on the non-top. Killem.
|
||||
if (nodep->stmtsp()) nodep->v3fatalSrc("Non-empty lower active");
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
// Careful if adding variables here, ACTIVES can be under other ACTIVES
|
||||
// Need to save and restore any member state in AstUntilStable block
|
||||
if (!m_topScopep || !nodep->stmtsp()) {
|
||||
// Not at the top or empty block...
|
||||
// Only empty blocks should be leftover on the non-top. Killem.
|
||||
if (nodep->stmtsp()) nodep->v3fatalSrc("Non-empty lower active");
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
} else if (m_mtaskBodyp) {
|
||||
UINFO(4," TR ACTIVE "<<nodep<<endl);
|
||||
AstNode* stmtsp = nodep->stmtsp()->unlinkFrBackWithNext();
|
||||
@@ -367,39 +372,39 @@ private:
|
||||
m_mtaskBodyp->addStmtsp(stmtsp);
|
||||
}
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
} else {
|
||||
UINFO(4," ACTIVE "<<nodep<<endl);
|
||||
AstNode* stmtsp = nodep->stmtsp()->unlinkFrBackWithNext();
|
||||
if (nodep->hasClocked()) {
|
||||
// Remember the latest sensitivity so we can compare it next time
|
||||
if (nodep->hasInitial()) nodep->v3fatalSrc("Initial block should not have clock sensitivity");
|
||||
if (m_lastSenp && nodep->sensesp()->sameTree(m_lastSenp)) {
|
||||
UINFO(4," sameSenseTree\n");
|
||||
} else {
|
||||
clearLastSen();
|
||||
m_lastSenp = nodep->sensesp();
|
||||
// Make a new if statement
|
||||
m_lastIfp = makeActiveIf(m_lastSenp);
|
||||
addToEvalLoop(m_lastIfp);
|
||||
}
|
||||
// Move statements to if
|
||||
m_lastIfp->addIfsp(stmtsp);
|
||||
} else if (nodep->hasInitial()) {
|
||||
// Don't need to: clearLastSen();, as we're adding it to different cfunc
|
||||
// Move statements to function
|
||||
addToInitial(stmtsp);
|
||||
} else if (nodep->hasSettle()) {
|
||||
// Don't need to: clearLastSen();, as we're adding it to different cfunc
|
||||
// Move statements to function
|
||||
addToSettleLoop(stmtsp);
|
||||
} else {
|
||||
// Combo
|
||||
clearLastSen();
|
||||
// Move statements to function
|
||||
addToEvalLoop(stmtsp);
|
||||
}
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
} else {
|
||||
UINFO(4," ACTIVE "<<nodep<<endl);
|
||||
AstNode* stmtsp = nodep->stmtsp()->unlinkFrBackWithNext();
|
||||
if (nodep->hasClocked()) {
|
||||
// Remember the latest sensitivity so we can compare it next time
|
||||
if (nodep->hasInitial()) nodep->v3fatalSrc("Initial block should not have clock sensitivity");
|
||||
if (m_lastSenp && nodep->sensesp()->sameTree(m_lastSenp)) {
|
||||
UINFO(4," sameSenseTree\n");
|
||||
} else {
|
||||
clearLastSen();
|
||||
m_lastSenp = nodep->sensesp();
|
||||
// Make a new if statement
|
||||
m_lastIfp = makeActiveIf(m_lastSenp);
|
||||
addToEvalLoop(m_lastIfp);
|
||||
}
|
||||
// Move statements to if
|
||||
m_lastIfp->addIfsp(stmtsp);
|
||||
} else if (nodep->hasInitial()) {
|
||||
// Don't need to: clearLastSen();, as we're adding it to different cfunc
|
||||
// Move statements to function
|
||||
addToInitial(stmtsp);
|
||||
} else if (nodep->hasSettle()) {
|
||||
// Don't need to: clearLastSen();, as we're adding it to different cfunc
|
||||
// Move statements to function
|
||||
addToSettleLoop(stmtsp);
|
||||
} else {
|
||||
// Combo
|
||||
clearLastSen();
|
||||
// Move statements to function
|
||||
addToEvalLoop(stmtsp);
|
||||
}
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstExecGraph* nodep) {
|
||||
for (m_mtaskBodyp = VN_CAST(nodep->op1p(), MTaskBody);
|
||||
@@ -426,16 +431,16 @@ public:
|
||||
// CONSTUCTORS
|
||||
explicit ClockVisitor(AstNetlist* nodep) {
|
||||
m_modp = NULL;
|
||||
m_evalFuncp = NULL;
|
||||
m_evalFuncp = NULL;
|
||||
m_initFuncp = NULL;
|
||||
m_finalFuncp = NULL;
|
||||
m_settleFuncp = NULL;
|
||||
m_topScopep = NULL;
|
||||
m_lastSenp = NULL;
|
||||
m_lastIfp = NULL;
|
||||
m_scopep = NULL;
|
||||
m_lastIfp = NULL;
|
||||
m_scopep = NULL;
|
||||
m_mtaskBodyp = NULL;
|
||||
//
|
||||
//
|
||||
iterate(nodep);
|
||||
// Allow downstream modules to find _eval()
|
||||
// easily without iterating through the tree.
|
||||
|
||||
Reference in New Issue
Block a user