本文整理汇总了C++中AstNode::dumpTree方法的典型用法代码示例。如果您正苦于以下问题:C++ AstNode::dumpTree方法的具体用法?C++ AstNode::dumpTree怎么用?C++ AstNode::dumpTree使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类AstNode
的用法示例。
在下文中一共展示了AstNode::dumpTree方法的12个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: visitStmt
void visitStmt(AstNodeStmt* nodep) {
m_depth++;
if (m_depth > v3Global.opt.compLimitBlocks()
&& !nodep->castCCall()) { // Already done
UINFO(4, "DeepBlocks "<<m_depth<<" "<<nodep<<endl);
AstNode* backp = nodep->backp(); // Only for debug
if (debug()>=9) backp->dumpTree(cout,"- pre : ");
AstCFunc* funcp = createDeepFunc(nodep);
funcp->accept(*this);
if (debug()>=9) backp->dumpTree(cout,"- post: ");
if (debug()>=9) funcp->dumpTree(cout,"- func: ");
} else {
nodep->iterateChildren(*this);
}
m_depth--;
}
示例2: replaceCaseFast
void replaceCaseFast(AstCase* nodep) {
// CASEx(cexpr,....
// -> tree of IF(msb, IF(msb-1, 11, 10)
// IF(msb-1, 01, 00))
AstNode* cexprp = nodep->exprp()->unlinkFrBack();
if (debug()>=9) {
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
if (AstNode* itemp = m_valueItem[i]) {
UINFO(9,"Value "<<hex<<i<<" "<<itemp<<endl);
}
}
}
// Handle any assertions
replaceCaseParallel(nodep, m_caseNoOverlapsAllCovered);
AstNode::user3ClearTree();
AstNode* ifrootp = replaceCaseFastRecurse(cexprp, m_caseWidth-1, 0UL);
// Case expressions can't be linked twice, so clone them
if (ifrootp && !ifrootp->user3()) ifrootp = ifrootp->cloneTree(true);
if (ifrootp) nodep->replaceWith(ifrootp);
else nodep->unlinkFrBack();
nodep->deleteTree(); nodep=NULL;
cexprp->deleteTree(); cexprp=NULL;
if (debug()>=9) ifrootp->dumpTree(cout," _simp: ");
}
示例3: mergeEnd
void mergeEnd() {
if (!m_mgAssignps.empty()) {
uint32_t items = m_mgIndexHi - m_mgIndexLo + 1;
UINFO(9, "End merge iter="<<items<<" "<<m_mgIndexHi<<":"<<m_mgIndexLo
<<" "<<m_mgAssignps[0]<<endl);
if (items >= RELOOP_MIN_ITERS) {
UINFO(6, "Reloop merging items="<<items<<" "<<m_mgIndexHi<<":"<<m_mgIndexLo
<<" "<<m_mgAssignps[0]<<endl);
++m_statReloops;
m_statReItems += items;
// Transform first assign into for loop body
AstNodeAssign* bodyp = m_mgAssignps.front();
if (bodyp->lhsp() != m_mgSelLp) bodyp->v3fatalSrc("Corrupt queue/state");
FileLine* fl = bodyp->fileline();
AstVar* itp = findCreateVarTemp(fl, m_mgCfuncp);
AstNode* initp = new AstAssign(fl, new AstVarRef(fl, itp, true),
new AstConst(fl, m_mgIndexLo));
AstNode* condp = new AstLte(fl, new AstVarRef(fl, itp, false),
new AstConst(fl, m_mgIndexHi));
AstNode* incp = new AstAssign(fl, new AstVarRef(fl, itp, true),
new AstAdd(fl, new AstConst(fl, 1),
new AstVarRef(fl, itp, false)));
AstWhile* whilep = new AstWhile(fl, condp, NULL, incp);
initp->addNext(whilep);
bodyp->replaceWith(initp);
whilep->addBodysp(bodyp);
// Replace constant index with new loop index
AstNode* lbitp = m_mgSelLp->bitp();
lbitp->replaceWith(new AstVarRef(fl, itp, false));
lbitp->deleteTree(); VL_DANGLING(lbitp);
if (m_mgSelRp) { // else constant and no replace
AstNode* rbitp = m_mgSelRp->bitp();
rbitp->replaceWith(new AstVarRef(fl, itp, false));
rbitp->deleteTree(); VL_DANGLING(lbitp);
}
if (debug()>=9) initp->dumpTree(cout, "-new: ");
if (debug()>=9) whilep->dumpTree(cout, "-new: ");
// Remove remaining assigns
for (AssVec::iterator it=m_mgAssignps.begin(); it!=m_mgAssignps.end(); ++it) {
AstNodeAssign* assp = *it;
if (assp != bodyp) {
assp->unlinkFrBack()->deleteTree(); VL_DANGLING(assp);
}
}
}
// Setup for next merge
m_mgAssignps.clear();
m_mgSelLp = NULL;
m_mgSelRp = NULL;
m_mgVarrefLp = NULL;
m_mgVarrefRp = NULL;
m_mgConstRp = NULL;
}
}
示例4: newExprFromGraph
AstNode* newExprFromGraph(GaterVarVertex* vertexp) {
// Recurse backwards, then form equation on return path
// We could use user()!=0, but zeroing it is slow, so instead we'll mark with a generation
// We get equations like "a | (!a & b)" which obviously could be reduced here,
// instead out of generality, there's a V3Const::matchOrAndNot that'll clean it up
static uint32_t s_generation = 0;
++s_generation;
nafgMarkRecurse(vertexp, s_generation);
AstNode* nodep = nafgCreateRecurse(m_headVertexp, s_generation);
if (debug()>=9) nodep->dumpTree(cout," GateExpr: ");
return nodep;
}
示例5: visit
void visit(AstSel* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (!nodep->user1Inc()) {
// Guard against reading/writing past end of bit vector array
int maxmsb = 0;
bool lvalue = false;
AstNode* basefromp = AstArraySel::baseFromp(nodep);
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) {
lvalue = varrefp->lvalue();
maxmsb = (varrefp->varp()->width()-1);
} else {
// If it's a PARAMETER[bit], then basefromp may be a constant instead of a varrefp
maxmsb = basefromp->width()-1;
}
int maxlsb = maxmsb - nodep->width() + 1;
if (debug()>=9) nodep->dumpTree(cout,"sel_old: ");
V3Number maxlsbnum (nodep->fileline(), nodep->lsbp()->width(), maxlsb);
// See if the condition is constant true
AstNode* condp = new AstLte (nodep->fileline(),
nodep->lsbp()->cloneTree(false),
new AstConst(nodep->fileline(), maxlsbnum));
// Note below has null backp(); the Edit function knows how to deal with that.
condp = V3Const::constifyEdit(condp);
if (condp->isOne()) {
// We don't need to add a conditional; we know the existing expression is ok
condp->deleteTree();
}
else if (!lvalue) {
// SEL(...) -> COND(LTE(bit<=maxlsb), ARRAYSEL(...), {width{1'bx}})
AstNRelinker replaceHandle;
nodep->unlinkFrBack(&replaceHandle);
V3Number xnum (nodep->fileline(), nodep->width());
xnum.setAllBitsX();
AstNode* newp = new AstCondBound (nodep->fileline(),
condp,
nodep,
new AstConst(nodep->fileline(), xnum));
if (debug()>=9) newp->dumpTree(cout," _new: ");
// Link in conditional
replaceHandle.relink(newp);
// Added X's, tristate them too
newp->accept(*this);
}
else { // lvalue
replaceBoundLvalue(nodep, condp);
}
}
}
示例6: visit
virtual void visit(AstSel* nodep) {
nodep->iterateChildren(*this);
if (!nodep->user1SetOnce()) {
// Guard against reading/writing past end of bit vector array
AstNode* basefromp = AstArraySel::baseFromp(nodep);
bool lvalue = false;
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) {
lvalue = varrefp->lvalue();
}
// Find range of dtype we are selecting from
// Similar code in V3Const::warnSelect
int maxmsb = nodep->fromp()->dtypep()->width()-1;
if (debug()>=9) nodep->dumpTree(cout,"sel_old: ");
V3Number maxmsbnum (nodep->fileline(), nodep->lsbp()->width(), maxmsb);
// If (maxmsb >= selected), we're in bound
AstNode* condp = new AstGte (nodep->fileline(),
new AstConst(nodep->fileline(), maxmsbnum),
nodep->lsbp()->cloneTree(false));
// See if the condition is constant true (e.g. always in bound due to constant select)
// Note below has null backp(); the Edit function knows how to deal with that.
condp = V3Const::constifyEdit(condp);
if (condp->isOne()) {
// We don't need to add a conditional; we know the existing expression is ok
condp->deleteTree();
}
else if (!lvalue) {
// SEL(...) -> COND(LTE(bit<=maxmsb), ARRAYSEL(...), {width{1'bx}})
AstNRelinker replaceHandle;
nodep->unlinkFrBack(&replaceHandle);
V3Number xnum (nodep->fileline(), nodep->width());
xnum.setAllBitsX();
AstNode* newp = new AstCondBound (nodep->fileline(),
condp,
nodep,
new AstConst(nodep->fileline(), xnum));
if (debug()>=9) newp->dumpTree(cout," _new: ");
// Link in conditional
replaceHandle.relink(newp);
// Added X's, tristate them too
newp->accept(*this);
}
else { // lvalue
replaceBoundLvalue(nodep, condp);
}
}
}
示例7: visit
virtual void visit(AstPin* nodep, AstNUser*) {
// PIN(p,expr) -> ASSIGNW(VARXREF(p),expr) (if sub's input)
// or ASSIGNW(expr,VARXREF(p)) (if sub's output)
UINFO(4," PIN "<<nodep<<endl);
if (!nodep->exprp()) return; // No-connect
if (debug()>=9) nodep->dumpTree(cout," Pin_oldb: ");
if (nodep->modVarp()->isOutOnly() && nodep->exprp()->castConst())
nodep->v3error("Output port is connected to a constant pin, electrical short");
// Use user1p on the PIN to indicate we created an assign for this pin
if (!nodep->user1SetOnce()) {
// Simplify it
V3Inst::pinReconnectSimple(nodep, m_cellp, m_modp, false);
// Make a ASSIGNW (expr, pin)
AstNode* exprp = nodep->exprp()->cloneTree(false);
if (exprp->width() != nodep->modVarp()->width())
nodep->v3fatalSrc("Width mismatch, should have been handled in pinReconnectSimple\n");
if (nodep->modVarp()->isInout()) {
nodep->v3fatalSrc("Unsupported: Verilator is a 2-state simulator");
} else if (nodep->modVarp()->isOutput()) {
AstNode* rhsp = new AstVarXRef (exprp->fileline(), nodep->modVarp(), m_cellp->name(), false);
AstAssignW* assp = new AstAssignW (exprp->fileline(), exprp, rhsp);
m_modp->addStmtp(assp);
} else if (nodep->modVarp()->isInput()) {
// Don't bother moving constants now,
// we'll be pushing the const down to the cell soon enough.
AstNode* assp = new AstAssignW
(exprp->fileline(),
new AstVarXRef(exprp->fileline(), nodep->modVarp(), m_cellp->name(), true),
exprp);
m_modp->addStmtp(assp);
if (debug()>=9) assp->dumpTree(cout," _new: ");
} else if (nodep->modVarp()->isIfaceRef()) {
// Create an AstAssignVarScope for Vars to Cells so we can link with their scope later
AstNode* lhsp = new AstVarXRef (exprp->fileline(), nodep->modVarp(), m_cellp->name(), false);
AstVarRef* refp = exprp->castVarRef();
if (!refp) exprp->v3fatalSrc("Interfaces: Pin is not connected to a VarRef");
AstAssignVarScope* assp = new AstAssignVarScope(exprp->fileline(), lhsp, refp);
m_modp->addStmtp(assp);
} else {
nodep->v3error("Assigned pin is neither input nor output");
}
}
// We're done with the pin
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
}
示例8: forUnroller
bool forUnroller(AstNode* nodep,
AstAssign* initp,
AstNode* condp,
AstNode* precondsp,
AstNode* incp, AstNode* bodysp) {
V3Number loopValue = V3Number(nodep->fileline());
if (!simulateTree(initp->rhsp(), NULL, initp, loopValue)) {
return false;
}
AstNode* stmtsp = NULL;
if (initp) {
initp->unlinkFrBack(); // Always a single statement; nextp() may be nodep
// Don't add to list, we do it once, and setting loop index isn't needed as we're constant propagating it
}
if (precondsp) {
precondsp->unlinkFrBackWithNext();
// cppcheck-suppress nullPointer // addNextNull deals with it
stmtsp = stmtsp->addNextNull(precondsp);
}
if (bodysp) {
bodysp->unlinkFrBackWithNext();
// cppcheck-suppress nullPointer // addNextNull deals with it
stmtsp = stmtsp->addNextNull(bodysp); // Maybe null if no body
}
if (incp && !nodep->castGenFor()) { // Generates don't need to increment loop index
incp->unlinkFrBackWithNext();
// cppcheck-suppress nullPointer // addNextNull deals with it
stmtsp = stmtsp->addNextNull(incp); // Maybe null if no body
}
// Mark variable to disable some later warnings
m_forVarp->usedLoopIdx(true);
AstNode* newbodysp = NULL;
++m_statLoops;
if (stmtsp) {
int times = 0;
while (1) {
UINFO(8," Looping "<<loopValue<<endl);
V3Number res = V3Number(nodep->fileline());
if (!simulateTree(condp, &loopValue, NULL, res)) {
nodep->v3error("Loop unrolling failed.");
return false;
}
if (!res.isEqOne()) {
break; // Done with the loop
}
else {
// Replace iterator values with constant.
AstNode* oneloopp = stmtsp->cloneTree(true);
m_varValuep = new AstConst(nodep->fileline(), loopValue);
// Iteration requires a back, so put under temporary node
if (oneloopp) {
AstBegin* tempp = new AstBegin(oneloopp->fileline(),"[EditWrapper]",oneloopp);
m_varModeReplace = true;
tempp->stmtsp()->iterateAndNext(*this);
m_varModeReplace = false;
oneloopp = tempp->stmtsp()->unlinkFrBackWithNext(); tempp->deleteTree(); VL_DANGLING(tempp);
}
if (m_generate) {
string index = AstNode::encodeNumber(m_varValuep->toSInt());
string nname = m_beginName + "__BRA__" + index + "__KET__";
oneloopp = new AstBegin(oneloopp->fileline(),nname,oneloopp,true);
}
pushDeletep(m_varValuep); m_varValuep=NULL;
if (newbodysp) newbodysp->addNext(oneloopp);
else newbodysp = oneloopp;
++m_statIters;
if (++times > unrollCount()*3) {
nodep->v3error("Loop unrolling took too long; probably this is an infinite loop, or set --unroll-count above "<<unrollCount());
break;
}
// loopValue += valInc
AstAssign *incpass = incp->castAssign();
V3Number newLoopValue = V3Number(nodep->fileline());
if (!simulateTree(incpass->rhsp(), &loopValue, incpass, newLoopValue)) {
nodep->v3error("Loop unrolling failed");
return false;
}
loopValue.opAssign(newLoopValue);
}
}
}
// Replace the FOR()
if (newbodysp) nodep->replaceWith(newbodysp);
else nodep->unlinkFrBack();
if (bodysp) { pushDeletep(bodysp); VL_DANGLING(bodysp); }
if (precondsp) { pushDeletep(precondsp); VL_DANGLING(precondsp); }
if (initp) { pushDeletep(initp); VL_DANGLING(initp); }
if (incp && !incp->backp()) { pushDeletep(incp); VL_DANGLING(incp); }
if (debug()>=9) newbodysp->dumpTree(cout,"- _new: ");
return true;
}
示例9: optimizeSignals
void GateVisitor::optimizeSignals(bool allowMultiIn) {
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
if (GateVarVertex* vvertexp = dynamic_cast<GateVarVertex*>(itp)) {
if (vvertexp->inEmpty()) {
vvertexp->clearReducibleAndDedupable("inEmpty"); // Can't deal with no sources
if (!vvertexp->isTop() // Ok if top inputs are driverless
&& !vvertexp->varScp()->varp()->valuep()
&& !vvertexp->varScp()->varp()->isSigPublic()) {
UINFO(4, "No drivers "<<vvertexp->varScp()<<endl);
if (0) {
// If we warned here after constant propagation, what the user considered
// reasonable logic may have disappeared. Issuing a warning would
// thus be confusing. V3Undriven now handles this.
vvertexp->varScp()->varp()->v3warn(UNDRIVEN,"Signal has no drivers "
<<vvertexp->scopep()->prettyName()<<"."
<<vvertexp->varScp()->varp()->prettyName());
}
}
}
else if (!vvertexp->inSize1()) {
vvertexp->clearReducibleAndDedupable("size!1"); // Can't deal with more than one src
}
// Reduce it?
if (!vvertexp->reducible()) {
UINFO(8, "SigNotRed "<<vvertexp->name()<<endl);
} else {
UINFO(8, "Sig "<<vvertexp->name()<<endl);
GateLogicVertex* logicVertexp = dynamic_cast<GateLogicVertex*>
(vvertexp->inBeginp()->fromp());
UINFO(8, " From "<<logicVertexp->name()<<endl);
AstNode* logicp = logicVertexp->nodep();
if (logicVertexp->reducible()) {
// Can we eliminate?
GateOkVisitor okVisitor(logicp, vvertexp->isClock(), false);
bool multiInputs = okVisitor.rhsVarRefs().size() > 1;
// Was it ok?
bool doit = okVisitor.isSimple();
if (doit && multiInputs) {
if (!allowMultiIn) doit = false;
// Doit if one input, or not used, or used only once, ignoring traces
int n=0;
for (V3GraphEdge* edgep = vvertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
GateLogicVertex* consumeVertexp = dynamic_cast<GateLogicVertex*>(edgep->top());
if (!consumeVertexp->slow()) { // Not tracing or other slow path junk
if (edgep->top()->outBeginp()) { // Destination is itself used
n += edgep->weight();
}
}
if (n>1) {
doit = false;
break;
}
}
}
// Process it
if (!doit) {
if (allowMultiIn && (debug()>=9)) {
UINFO(9, "Not ok simp"<<okVisitor.isSimple()<<" mi"<<multiInputs
<<" ob"<<vvertexp->outBeginp()<<" on"<<(vvertexp->outBeginp()?vvertexp->outBeginp()->outNextp():0)
<<" "<<vvertexp->name()
<<endl);
for (V3GraphEdge* edgep = vvertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
GateLogicVertex* consumeVertexp = dynamic_cast<GateLogicVertex*>(edgep->top());
UINFO(9, " edge "<<edgep<<" to: "<<consumeVertexp->nodep()<<endl);
}
for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
GateLogicVertex* consumeVertexp = dynamic_cast<GateLogicVertex*>(edgep->fromp());
UINFO(9, " edge "<<edgep<<" from: "<<consumeVertexp->nodep()<<endl);
}
}
}
else {
AstNode* substp = okVisitor.substTree();
if (debug()>=5) logicp->dumpTree(cout,"\telimVar: ");
if (debug()>=5) substp->dumpTree(cout,"\t subst: ");
++m_statSigs;
bool removedAllUsages = true;
for (V3GraphEdge* edgep = vvertexp->outBeginp();
edgep; ) {
GateLogicVertex* consumeVertexp = dynamic_cast<GateLogicVertex*>(edgep->top());
AstNode* consumerp = consumeVertexp->nodep();
if (!elimLogicOkOutputs(consumeVertexp, okVisitor/*ref*/)) {
// Cannot optimize this replacement
removedAllUsages = false;
edgep = edgep->outNextp();
} else {
optimizeElimVar(vvertexp->varScp(), substp, consumerp);
// If the new replacement referred to a signal,
// Correct the graph to point to this new generating variable
const GateVarRefList& rhsVarRefs = okVisitor.rhsVarRefs();
for (GateVarRefList::const_iterator it = rhsVarRefs.begin();
it != rhsVarRefs.end(); ++it) {
AstVarScope* newvarscp = (*it)->varScopep();
UINFO(9," Point-to-new vertex "<<newvarscp<<endl);
GateVarVertex* varvertexp = makeVarVertex(newvarscp);
new V3GraphEdge(&m_graph, varvertexp, consumeVertexp, 1);
// Propagate clock attribute onto generating node
varvertexp->propagateAttrClocksFrom(vvertexp);
}
// Remove the edge
//.........这里部分代码省略.........
示例10: replaceCaseComplicated
void replaceCaseComplicated(AstCase* nodep) {
// CASEx(cexpr,ITEM(icond1,istmts1),ITEM(icond2,istmts2),ITEM(default,istmts3))
// -> IF((cexpr==icond1),istmts1,
// IF((EQ (AND MASK cexpr) (AND MASK icond1)
// ,istmts2, istmts3
AstNode* cexprp = nodep->exprp()->unlinkFrBack();
// We'll do this in two stages. First stage, convert the conditions to
// the appropriate IF AND terms.
if (debug()>=9) nodep->dumpTree(cout," _comp_IN: ");
bool hadDefault = false;
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
if (!itemp->condsp()) {
// Default clause. Just make true, we'll optimize it away later
itemp->condsp(new AstConst(itemp->fileline(), AstConst::LogicTrue()));
hadDefault = true;
} else {
// Expressioned clause
AstNode* icondNextp = NULL;
AstNode* ifexprp = NULL; // If expression to test
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondNextp) {
icondNextp = icondp->nextp();
icondp->unlinkFrBack();
AstNode* condp = NULL; // Default is to use and1p/and2p
AstConst* iconstp = icondp->castConst();
if (iconstp && neverItem(nodep, iconstp)) {
// X in casez can't ever be executed
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
// For simplicity, make expression that is not equal, and let later
// optimizations remove it
condp = new AstConst(itemp->fileline(), AstConst::LogicFalse());
} else if (AstInsideRange* irangep = icondp->castInsideRange()) {
// Similar logic in V3Width::visit(AstInside)
AstNode* ap = AstGte::newTyped(itemp->fileline(),
cexprp->cloneTree(false),
irangep->lhsp()->unlinkFrBack());
AstNode* bp = AstLte::newTyped(itemp->fileline(),
cexprp->cloneTree(false),
irangep->rhsp()->unlinkFrBack());
condp = new AstAnd(itemp->fileline(), ap, bp);
} else if (iconstp && iconstp->num().isFourState()
&& (nodep->casex() || nodep->casez() || nodep->caseInside())) {
V3Number nummask (itemp->fileline(), iconstp->width());
nummask.opBitsNonX(iconstp->num());
V3Number numval (itemp->fileline(), iconstp->width());
numval.opBitsOne(iconstp->num());
AstNode* and1p = new AstAnd(itemp->fileline(), cexprp->cloneTree(false),
new AstConst(itemp->fileline(), nummask));
AstNode* and2p = new AstAnd(itemp->fileline(),
new AstConst(itemp->fileline(), numval),
new AstConst(itemp->fileline(), nummask));
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
condp = AstEq::newTyped(itemp->fileline(), and1p, and2p);
} else {
// Not a caseX mask, we can simply build CASEEQ(cexpr icond)
AstNode* and1p = cexprp->cloneTree(false);
AstNode* and2p = icondp;
condp = AstEq::newTyped(itemp->fileline(), and1p, and2p);
}
if (!ifexprp) {
ifexprp = condp;
} else {
ifexprp = new AstLogOr(itemp->fileline(), ifexprp, condp);
}
}
// Replace expression in tree
itemp->condsp(ifexprp);
}
}
cexprp->deleteTree(); cexprp=NULL;
if (!hadDefault) {
// If there was no default, add a empty one, this greatly simplifies below code
// and constant propagation will just eliminate it for us later.
nodep->addItemsp(new AstCaseItem(nodep->fileline(),
new AstConst(nodep->fileline(), AstConst::LogicTrue()),
NULL));
}
if (debug()>=9) nodep->dumpTree(cout," _comp_COND: ");
// Now build the IF statement tree
// The tree can be quite huge. Pull ever group of 8 out, and make a OR tree.
// This reduces the depth for the bottom elements, at the cost of some of the top elements.
// If we ever have profiling data, we should pull out the most common item from here and
// instead make it the first IF branch.
int depth = 0;
AstNode* grouprootp = NULL;
AstIf* groupnextp = NULL;
AstIf* itemnextp = NULL;
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
AstNode* istmtsp = itemp->bodysp(); // Maybe null -- no action.
if (istmtsp) istmtsp->unlinkFrBackWithNext();
// Expressioned clause
AstNode* ifexprp = itemp->condsp()->unlinkFrBack();
{ // Prepare for next group
if (++depth > CASE_ENCODER_GROUP_DEPTH) depth = 1;
if (depth == 1) { // First group or starting new group
itemnextp = NULL;
AstIf* newp = new AstIf(itemp->fileline(), ifexprp->cloneTree(true), NULL, NULL);
if (groupnextp) groupnextp->addElsesp(newp);
else grouprootp = newp;
groupnextp = newp;
//.........这里部分代码省略.........
示例11: forUnroller
void forUnroller(AstNode* nodep,
AstNode* initp,
AstNode* precondsp, AstNode* condp,
AstNode* incp, AstNode* bodysp,
const V3Number& numInit,
AstNodeBiop* cmpInstrp, const V3Number& numStop,
AstNodeBiop* incInstrp, const V3Number& numInc) {
UINFO(4, " Unroll for var="<<numInit<<"; var<"<<numStop<<"; var+="<<numInc<<endl);
UINFO(6, " cmpI "<<cmpInstrp<<endl);
UINFO(6, " IncI "<<incInstrp<<endl);
AstNode* stmtsp = NULL;
if (initp) {
initp->unlinkFrBack(); // Always a single statement; nextp() may be nodep
// Don't add to list, we do it once, and setting loop index isn't needed as we're constant propagating it
}
if (precondsp) {
precondsp->unlinkFrBackWithNext();
// cppcheck-suppress nullPointer // addNextNull deals with it
stmtsp = stmtsp->addNextNull(precondsp);
}
if (bodysp) {
bodysp->unlinkFrBackWithNext();
// cppcheck-suppress nullPointer // addNextNull deals with it
stmtsp = stmtsp->addNextNull(bodysp); // Maybe null if no body
}
if (incp && !nodep->castGenFor()) { // Generates don't need to increment loop index
incp->unlinkFrBackWithNext();
// cppcheck-suppress nullPointer // addNextNull deals with it
stmtsp = stmtsp->addNextNull(incp); // Maybe null if no body
}
// Mark variable to disable some later warnings
m_forVarp->usedLoopIdx(true);
// If it's a While, then incp is already part of bodysp.
V3Number loopValue(nodep->fileline(), m_forVarp->width()); // May differ in size from numInitp
loopValue.opAssign(numInit);
AstNode* newbodysp = NULL;
++m_statLoops;
if (stmtsp) {
int times = 0;
while (1) {
UINFO(8," Looping "<<loopValue<<endl);
// if loopValue<valStop
V3Number contin (nodep->fileline(), 1);
cmpInstrp->numberOperate(contin, loopValue, numStop);
if (contin.isEqZero()) {
break; // Done with the loop
} else {
// Replace iterator values with constant.
AstNode* oneloopp = stmtsp->cloneTree(true);
m_varValuep = new AstConst(nodep->fileline(), loopValue);
// Iteration requires a back, so put under temporary node
if (oneloopp) {
AstBegin* tempp = new AstBegin(oneloopp->fileline(),"[EditWrapper]",oneloopp);
m_varModeReplace = true;
tempp->stmtsp()->iterateAndNext(*this);
m_varModeReplace = false;
oneloopp = tempp->stmtsp()->unlinkFrBackWithNext(); tempp->deleteTree(); tempp=NULL;
}
if (m_generate) {
string index = AstNode::encodeNumber(m_varValuep->toSInt());
string nname = m_beginName + "__BRA__" + index + "__KET__";
oneloopp = new AstBegin(oneloopp->fileline(),nname,oneloopp,true);
}
if (newbodysp) newbodysp->addNext(oneloopp);
else newbodysp = oneloopp;
++m_statIters;
if (++times > unrollCount()*3) {
nodep->v3error("Loop unrolling took too long; probably this is an infinite loop, or set --unroll-count above "<<unrollCount());
break;
}
//loopValue += valInc
V3Number newnum(nodep->fileline(), m_forVarp->width()); // Can't increment in-place
incInstrp->numberOperate(newnum, loopValue, numInc);
loopValue.opAssign(newnum);
pushDeletep(m_varValuep); m_varValuep=NULL;
}
}
}
// Replace the FOR()
if (newbodysp) nodep->replaceWith(newbodysp);
else nodep->unlinkFrBack();
if (bodysp) { pushDeletep(bodysp); bodysp=NULL; }
if (precondsp) { pushDeletep(precondsp); precondsp=NULL; }
if (initp) { pushDeletep(initp); initp=NULL; }
if (incp && !incp->backp()) { pushDeletep(incp); incp=NULL; }
if (debug()>=9) newbodysp->dumpTree(cout,"- _new: ");
}
示例12: replaceBoundLvalue
void replaceBoundLvalue(AstNode* nodep, AstNode* condp) {
// Spec says a out-of-range LHS SEL results in a NOP.
// This is a PITA. We could:
// 1. IF(...) around an ASSIGN,
// but that would break a "foo[TOO_BIG]=$fopen(...)".
// 2. Hack to extend the size of the output structure
// by one bit, and write to that temporary, but never read it.
// That makes there be two widths() and is likely a bug farm.
// 3. Make a special SEL to choose between the real lvalue
// and a temporary NOP register.
// 4. Assign to a temp, then IF that assignment.
// This is suspected to be nicest to later optimizations.
// 4 seems best but breaks later optimizations. 3 was tried,
// but makes a mess in the emitter as lvalue switching is needed. So 4.
// SEL(...) -> temp
// if (COND(LTE(bit<=maxlsb))) ASSIGN(SEL(...)),temp)
if (m_assignwp) {
// Wire assigns must become always statements to deal with insertion
// of multiple statements. Perhaps someday make all wassigns into always's?
UINFO(5," IM_WireRep "<<m_assignwp<<endl);
m_assignwp->convertToAlways(); pushDeletep(m_assignwp); m_assignwp=NULL;
}
bool needDly = (m_assigndlyp != NULL);
if (m_assigndlyp) {
// Delayed assignments become normal assignments,
// then the temp created becomes the delayed assignment
AstNode* newp = new AstAssign(m_assigndlyp->fileline(),
m_assigndlyp->lhsp()->unlinkFrBackWithNext(),
m_assigndlyp->rhsp()->unlinkFrBackWithNext());
m_assigndlyp->replaceWith(newp); pushDeletep(m_assigndlyp); m_assigndlyp=NULL;
}
AstNode* prep = nodep;
// Scan back to put the condlvalue above all selects (IE top of the lvalue)
while (prep->backp()->castNodeSel()
|| prep->backp()->castSel()) {
prep=prep->backp();
}
FileLine* fl = nodep->fileline();
VL_DANGLING(nodep); // Zap it so we don't use it by mistake - use prep
// Already exists; rather than IF(a,... IF(b... optimize to IF(a&&b,
// Saves us teaching V3Const how to optimize, and it won't be needed again.
if (AstIf* ifp = prep->user2p()->castIf()) {
if (needDly) prep->v3fatalSrc("Should have already converted to non-delay");
AstNRelinker replaceHandle;
AstNode* earliercondp = ifp->condp()->unlinkFrBack(&replaceHandle);
AstNode* newp = new AstLogAnd (condp->fileline(),
condp,
earliercondp);
UINFO(4, "Edit BOUNDLVALUE "<<newp<<endl);
replaceHandle.relink(newp);
}
else {
string name = ((string)"__Vlvbound"+cvtToStr(m_modp->varNumGetInc()));
AstVar* varp = new AstVar(fl, AstVarType::MODULETEMP, name,
prep->dtypep());
m_modp->addStmtp(varp);
AstNode* abovep = prep->backp(); // Grab above point before lose it w/ next replace
prep->replaceWith(new AstVarRef(fl, varp, true));
AstNode* newp = new AstIf(fl, condp,
(needDly
? static_cast<AstNode*>
(new AstAssignDly(fl, prep,
new AstVarRef(fl, varp, false)))
: static_cast<AstNode*>
(new AstAssign (fl, prep,
new AstVarRef(fl, varp, false)))),
NULL);
if (debug()>=9) newp->dumpTree(cout," _new: ");
abovep->addNextStmt(newp,abovep);
prep->user2p(newp); // Save so we may LogAnd it next time
}
}