本文整理汇总了C++中AstConst类的典型用法代码示例。如果您正苦于以下问题:C++ AstConst类的具体用法?C++ AstConst怎么用?C++ AstConst使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了AstConst类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: visit
virtual void visit(AstVar* nodep, AstNUser*) {
if (nodep->user2p()) {
// Make an assignment, so we'll trace it properly
// user2p is either a const or a var.
AstConst* exprconstp = nodep->user2p()->castNode()->castConst();
AstVarRef* exprvarrefp = nodep->user2p()->castNode()->castVarRef();
UINFO(8,"connectto: "<<nodep->user2p()->castNode()<<endl);
if (!exprconstp && !exprvarrefp) {
nodep->v3fatalSrc("Unknown interconnect type; pinReconnectSimple should have cleared up\n");
}
if (exprconstp) {
m_modp->addStmtp(new AstAssignW(nodep->fileline(),
new AstVarRef(nodep->fileline(), nodep, true),
exprconstp->cloneTree(true)));
} else if (nodep->user3()) {
// Public variable at the lower module end - we need to make sure we propagate
// the logic changes up and down; if we aliased, we might remove the change detection
// on the output variable.
UINFO(9,"public pin assign: "<<exprvarrefp<<endl);
if (nodep->isInput()) nodep->v3fatalSrc("Outputs only - inputs use AssignAlias");
m_modp->addStmtp(new AstAssignW(nodep->fileline(),
new AstVarRef(nodep->fileline(), exprvarrefp->varp(), true),
new AstVarRef(nodep->fileline(), nodep, false)));
} else if (nodep->isIfaceRef()) {
m_modp->addStmtp(new AstAssignVarScope(nodep->fileline(),
new AstVarRef(nodep->fileline(), nodep, true),
new AstVarRef(nodep->fileline(), exprvarrefp->varp(), false)));
AstNode* nodebp=exprvarrefp->varp();
nodep ->fileline()->modifyStateInherit(nodebp->fileline());
nodebp->fileline()->modifyStateInherit(nodep ->fileline());
} else {
// Do to inlining child's variable now within the same module, so a AstVarRef not AstVarXRef below
m_modp->addStmtp(new AstAssignAlias(nodep->fileline(),
new AstVarRef(nodep->fileline(), nodep, true),
new AstVarRef(nodep->fileline(), exprvarrefp->varp(), false)));
AstNode* nodebp=exprvarrefp->varp();
nodep ->fileline()->modifyStateInherit(nodebp->fileline());
nodebp->fileline()->modifyStateInherit(nodep ->fileline());
}
}
// Variable under the inline cell, need to rename to avoid conflicts
// Also clear I/O bits, as it is now local.
string name = m_cellp->name() + "__DOT__" + nodep->name();
if (!nodep->isFuncLocal()) nodep->inlineAttrReset(name);
if (debug()>=9) { nodep->dumpTree(cout,"varchanged:"); }
if (debug()>=9) { nodep->valuep()->dumpTree(cout,"varchangei:"); }
// Iterate won't hit AstIfaceRefDType directly as it is no longer underneath the module
if (AstIfaceRefDType* ifacerefp = nodep->dtypep()->castIfaceRefDType()) {
// Relink to point to newly cloned cell
if (ifacerefp->cellp()) {
if (AstCell* newcellp = ifacerefp->cellp()->user4p()->castNode()->castCell()) {
ifacerefp->cellp(newcellp);
ifacerefp->cellName(newcellp->name());
}
}
}
nodep->iterateChildren(*this);
}
示例2: visit
virtual void visit(AstSel* nodep, AstNUser*) {
AstVarRef* varrefp = nodep->fromp()->castVarRef();
AstConst* constp = nodep->lsbp()->castConst();
if (varrefp && constp && !constp->num().isFourState()) {
UndrivenVarEntry* entryp = getEntryp (varrefp->varp());
int lsb = constp->toUInt();
if (m_markBoth || varrefp->lvalue()) entryp->drivenBit(lsb, nodep->width());
if (m_markBoth || !varrefp->lvalue()) entryp->usedBit(lsb, nodep->width());
} else {
// else other varrefs handled as unknown mess in AstVarRef
nodep->iterateChildren(*this);
}
}
示例3: visit
virtual void visit(AstGenCase* nodep, AstNUser*) {
UINFO(9," GENCASE "<<nodep<<endl);
AstNode* keepp = NULL;
nodep->exprp()->iterateAndNext(*this);
V3Case::caseLint(nodep);
V3Width::widthParamsEdit(nodep); // Param typed widthing will NOT recurse the body,
// don't trigger errors yet.
V3Const::constifyParamsEdit(nodep->exprp()); // exprp may change
AstConst* exprp = nodep->exprp()->castConst();
// Constify
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
for (AstNode* ep = itemp->condsp(); ep; ) {
AstNode* nextp = ep->nextp(); //May edit list
ep->iterateAndNext(*this);
V3Const::constifyParamsEdit(ep); ep=NULL; // ep may change
// cppcheck-suppress redundantAssignment
ep = nextp;
}
}
// Item match
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
if (!itemp->isDefault()) {
for (AstNode* ep = itemp->condsp(); ep; ep=ep->nextp()) {
if (AstConst* ccondp = ep->castConst()) {
V3Number match (nodep->fileline(), 1);
match.opEq(ccondp->num(), exprp->num());
if (!keepp && match.isNeqZero()) {
keepp = itemp->bodysp();
}
} else {
itemp->v3error("Generate Case item does not evaluate to constant");
}
}
}
}
// Else default match
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
if (itemp->isDefault()) {
if (!keepp) keepp=itemp->bodysp();
}
}
// Replace
if (keepp) {
keepp->unlinkFrBackWithNext();
nodep->replaceWith(keepp);
}
else nodep->unlinkFrBack();
nodep->deleteTree(); nodep=NULL;
}
示例4: visitShift
void visitShift (AstNodeBiop* nodep) {
// Shifts of > 32/64 bits in C++ will wrap-around and generate non-0s
if (!nodep->user2SetOnce()) {
UINFO(4," ShiftFix "<<nodep<<endl);
AstConst* shiftp = nodep->rhsp()->castConst();
if (shiftp && shiftp->num().mostSetBitP1() > 32) {
shiftp->v3error("Unsupported: Shifting of by over 32-bit number isn't supported."
<<" (This isn't a shift of 32 bits, but a shift of 2^32, or 4 billion!)\n");
}
if (nodep->widthMin()<=64 // Else we'll use large operators which work right
// C operator's width must be < maximum shift which is based on Verilog width
&& nodep->width() < (1LL<<nodep->rhsp()->widthMin())) {
AstNRelinker replaceHandle;
nodep->unlinkFrBack(&replaceHandle);
AstNode* constzerop;
int m1value = nodep->widthMin()-1; // Constant of width-1; not changing dtype width
if (nodep->signedFlavor()) {
// Then over shifting gives the sign bit, not all zeros
// Note *NOT* clean output -- just like normal shift!
// Create equivalent of VL_SIGNONES_(node_width)
constzerop = new AstNegate (nodep->fileline(),
new AstShiftR(nodep->fileline(),
nodep->lhsp()->cloneTree(false),
new AstConst(nodep->fileline(),
m1value),
nodep->width()));
} else {
V3Number zeronum (nodep->fileline(), nodep->width(), 0);
constzerop = new AstConst(nodep->fileline(), zeronum);
}
constzerop->dtypeFrom (nodep); // unsigned
V3Number widthnum (nodep->fileline(), nodep->rhsp()->widthMin(), m1value);
AstNode* constwidthp = new AstConst(nodep->fileline(), widthnum);
constwidthp->dtypeFrom (nodep->rhsp()); // unsigned
AstCond* newp =
new AstCond (nodep->fileline(),
new AstGte (nodep->fileline(),
constwidthp,
nodep->rhsp()->cloneTree(false)),
nodep,
constzerop);
replaceHandle.relink(newp);
}
}
nodep->iterateChildren(*this); checkNode(nodep);
}
示例5: RenderConst
static bool
RenderConst(WasmRenderContext& c, AstConst& cst)
{
if (!c.buffer.append('('))
return false;
if (!RenderValType(c, cst.val().type()))
return false;
if (!c.buffer.append(".const "))
return false;
switch (ToExprType(cst.val().type())) {
case ExprType::I32:
if (!RenderInt32(c, (uint32_t)cst.val().i32()))
return false;
break;
case ExprType::I64:
if (!RenderInt64(c, (uint32_t)cst.val().i64()))
return false;
break;
case ExprType::F32:
if (!RenderDouble(c, (double)cst.val().f32()))
return false;
break;
case ExprType::F64:
if (!RenderDouble(c, cst.val().f64()))
return false;
break;
default:
return false;
}
if (!c.buffer.append(")"))
return false;
return true;
}
示例6: RenderConst
static bool
RenderConst(WasmRenderContext& c, AstConst& cst)
{
if (!RenderIndent(c))
return false;
MAP_AST_EXPR(c, cst);
if (!RenderValType(c, cst.val().type()))
return false;
if (!c.buffer.append(".const "))
return false;
switch (ToExprType(cst.val().type())) {
case ExprType::I32:
return RenderInt32(c, (int32_t)cst.val().i32());
case ExprType::I64:
return RenderInt64(c, (int64_t)cst.val().i64());
case ExprType::F32:
return RenderFloat32(c, cst.val().f32());
case ExprType::F64:
return RenderDouble(c, cst.val().f64());
default:
break;
}
return false;
}
示例7: visit
virtual void visit(AstSel* nodep, AstNUser*) {
AstVarRef* varrefp = nodep->fromp()->castVarRef();
AstConst* constp = nodep->lsbp()->castConst();
if (varrefp && constp && !constp->num().isFourState()) {
for (int usr=1; usr<(m_alwaysp?3:2); ++usr) {
UndrivenVarEntry* entryp = getEntryp (varrefp->varp(), usr);
int lsb = constp->toUInt();
if (m_markBoth || varrefp->lvalue()) {
// Don't warn if already driven earlier as "a=0; if(a) a=1;" is fine.
if (usr==2 && m_alwaysp && entryp->isUsedNotDrivenBit(lsb, nodep->width())) {
UINFO(9," Select. Entryp="<<(void*)entryp<<endl);
warnAlwCombOrder(varrefp);
}
entryp->drivenBit(lsb, nodep->width());
}
if (m_markBoth || !varrefp->lvalue()) entryp->usedBit(lsb, nodep->width());
}
} else {
// else other varrefs handled as unknown mess in AstVarRef
nodep->iterateChildren(*this);
}
}
示例8: UINFO
void ParamVisitor::visitCell(AstCell* nodep) {
// Cell: Check for parameters in the instantiation.
nodep->iterateChildren(*this);
if (!nodep->modp()) nodep->v3fatalSrc("Not linked?");
if (nodep->paramsp()
|| 1 // Need to look for interfaces; could track when one exists, but should be harmless to always do this
) {
UINFO(4,"De-parameterize: "<<nodep<<endl);
// Create new module name with _'s between the constants
if (debug()>=10) nodep->dumpTree(cout,"-cell:\t");
// Evaluate all module constants
V3Const::constifyParamsEdit(nodep);
// Make sure constification worked
// Must be a separate loop, as constant conversion may have changed some pointers.
//if (debug()) nodep->dumpTree(cout,"-cel2:\t");
string longname = nodep->modp()->name();
bool any_overrides = false;
longname += "_";
if (debug()>8) nodep->paramsp()->dumpTreeAndNext(cout,"-cellparams:\t");
for (AstPin* pinp = nodep->paramsp(); pinp; pinp=pinp->nextp()->castPin()) {
if (!pinp->exprp()) continue; // No-connect
AstVar* modvarp = pinp->modVarp();
if (!modvarp) {
pinp->v3error("Parameter not found in sub-module: Param "<<pinp->name()<<" of "<<nodep->prettyName());
} else if (!modvarp->isGParam()) {
pinp->v3error("Attempted parameter setting of non-parameter: Param "<<pinp->name()<<" of "<<nodep->prettyName());
} else {
AstConst* constp = pinp->exprp()->castConst();
AstConst* origconstp = modvarp->valuep()->castConst();
if (!constp) {
//if (debug()) pinp->dumpTree(cout,"error:");
pinp->v3error("Can't convert defparam value to constant: Param "<<pinp->name()<<" of "<<nodep->prettyName());
pinp->exprp()->replaceWith(new AstConst(pinp->fileline(), V3Number(pinp->fileline(), modvarp->width(), 0)));
} else if (origconstp && constp->sameTree(origconstp)) {
// Setting parameter to its default value. Just ignore it.
// This prevents making additional modules, and makes coverage more
// obvious as it won't show up under a unique module page name.
} else {
longname += "_" + paramSmallName(nodep->modp(),pinp->modVarp())+constp->num().ascii(false);
any_overrides = true;
}
}
}
IfaceRefRefs ifaceRefRefs;
for (AstPin* pinp = nodep->pinsp(); pinp; pinp=pinp->nextp()->castPin()) {
AstVar* modvarp = pinp->modVarp();
if (modvarp->isIfaceRef()) {
AstIfaceRefDType* portIrefp = modvarp->subDTypep()->castIfaceRefDType();
//UINFO(9," portIfaceRef "<<portIrefp<<endl);
if (!pinp->exprp()
|| !pinp->exprp()->castVarRef()
|| !pinp->exprp()->castVarRef()->varp()
|| !pinp->exprp()->castVarRef()->varp()->subDTypep()
|| !pinp->exprp()->castVarRef()->varp()->subDTypep()->castIfaceRefDType()) {
pinp->v3error("Interface port '"<<modvarp->prettyName()<<"' is not connected to interface/modport pin expression");
} else {
AstIfaceRefDType* pinIrefp = pinp->exprp()->castVarRef()->varp()->subDTypep()->castIfaceRefDType();
//UINFO(9," pinIfaceRef "<<pinIrefp<<endl);
if (portIrefp->ifaceViaCellp() != pinIrefp->ifaceViaCellp()) {
UINFO(9," IfaceRefDType needs reconnect "<<pinIrefp<<endl);
longname += "_" + paramSmallName(nodep->modp(),pinp->modVarp())+paramValueNumber(pinIrefp);
any_overrides = true;
ifaceRefRefs.push_back(make_pair(portIrefp,pinIrefp));
}
}
}
}
if (!any_overrides) {
UINFO(8,"Cell parameters all match original values, skipping expansion.\n");
} else {
// If the name is very long, we don't want to overwhelm the filename limit
// We don't do this always, as it aids debugability to have intuitive naming.
// TODO can use new V3Name hash replacement instead of this
string newname = longname;
if (longname.length()>30) {
LongMap::iterator iter = m_longMap.find(longname);
if (iter != m_longMap.end()) {
newname = iter->second;
} else {
newname = nodep->modp()->name();
newname += "__pi"+cvtToStr(++m_longId); // We use all upper case above, so lower here can't conflict
m_longMap.insert(make_pair(longname, newname));
}
}
UINFO(4,"Name: "<<nodep->modp()->name()<<"->"<<longname<<"->"<<newname<<endl);
//
// Already made this flavor?
AstNodeModule* modp = NULL;
ModNameMap::iterator iter = m_modNameMap.find(newname);
if (iter != m_modNameMap.end()) modp = iter->second.m_modp;
if (!modp) {
// Deep clone of new module
// Note all module internal variables will be re-linked to the new modules by clone
// However links outside the module (like on the upper cells) will not.
modp = nodep->modp()->cloneTree(false);
modp->name(newname);
modp->user5(false); // We need to re-recurse this module once changed
//.........这里部分代码省略.........
示例9: 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;
}
示例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: isCaseTreeFast
bool isCaseTreeFast(AstCase* nodep) {
int width = 0;
bool opaque = false;
m_caseItems = 0;
m_caseNoOverlapsAllCovered = true;
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
if (icondp->width() > width) width = icondp->width();
if (icondp->isDouble()) opaque = true;
if (!icondp->castConst()) width = CASE_BARF; // Can't parse; not a constant
m_caseItems++;
}
}
m_caseWidth = width;
if (width==0 || width > CASE_OVERLAP_WIDTH || opaque) {
m_caseNoOverlapsAllCovered = false;
return false; // Too wide for analysis
}
UINFO(8,"Simple case statement: "<<nodep<<endl);
// Zero list of items for each value
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) m_valueItem[i] = NULL;
// Now pick up the values for each assignment
// We can cheat and use uint32_t's because we only support narrow case's
bool bitched = false;
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
//if (debug()>=9) icondp->dumpTree(cout," caseitem: ");
AstConst* iconstp = icondp->castConst();
if (!iconstp) nodep->v3fatalSrc("above 'can't parse' should have caught this\n");
if (neverItem(nodep, iconstp)) {
// X in casez can't ever be executed
} else {
V3Number nummask (itemp->fileline(), iconstp->width());
nummask.opBitsNonX(iconstp->num());
uint32_t mask = nummask.toUInt();
V3Number numval (itemp->fileline(), iconstp->width());
numval.opBitsOne(iconstp->num());
uint32_t val = numval.toUInt();
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
if ((i & mask) == val) {
if (!m_valueItem[i]) {
m_valueItem[i] = itemp;
} else if (!itemp->ignoreOverlap() && !bitched) {
itemp->v3warn(CASEOVERLAP,"Case values overlap (example pattern 0x"<<hex<<i<<")");
bitched = true;
m_caseNoOverlapsAllCovered = false;
}
}
}
}
}
// Defaults were moved to last in the caseitem list by V3LinkDot
if (itemp->isDefault()) { // Case statement's default... Fill the table
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
if (!m_valueItem[i]) m_valueItem[i] = itemp;
}
}
}
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
if (!m_valueItem[i]) {
nodep->v3warn(CASEINCOMPLETE,"Case values incompletely covered (example pattern 0x"<<hex<<i<<")");
m_caseNoOverlapsAllCovered = false;
return false;
}
}
if (m_caseItems <= 3) return false; // Not worth simplifing
// Convert valueItem from AstCaseItem* to the expression
// Not done earlier, as we may now have a NULL because it's just a ";" NOP branch
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
m_valueItem[i] = m_valueItem[i]->castCaseItem()->bodysp();
}
return true; // All is fine
}
示例12: forUnrollCheck
bool forUnrollCheck(AstNode* nodep,
AstNode* initp, // Maybe under nodep (no nextp), or standalone (ignore nextp)
AstNode* precondsp, AstNode* condp,
AstNode* incp, // Maybe under nodep or in bodysp
AstNode* bodysp) {
// To keep the IF levels low, we return as each test fails.
UINFO(4, " FOR Check "<<nodep<<endl);
if (initp) UINFO(6, " Init "<<initp<<endl);
if (precondsp) UINFO(6, " Pcon "<<precondsp<<endl);
if (condp) UINFO(6, " Cond "<<condp<<endl);
if (incp) UINFO(6, " Inc "<<incp<<endl);
// Initial value check
AstAssign* initAssp = initp->castAssign();
if (!initAssp) return cantUnroll(nodep, "no initial assignment");
if (initp->nextp() && initp->nextp()!=nodep) nodep->v3fatalSrc("initial assignment shouldn't be a list");
if (!initAssp->lhsp()->castVarRef()) return cantUnroll(nodep, "no initial assignment to simple variable");
m_forVarp = initAssp->lhsp()->castVarRef()->varp();
m_forVscp = initAssp->lhsp()->castVarRef()->varScopep();
if (nodep->castGenFor() && !m_forVarp->isGenVar()) {
nodep->v3error("Non-genvar used in generate for: "<<m_forVarp->name()<<endl);
}
if (m_generate) V3Const::constifyParamsEdit(initAssp->rhsp()); // rhsp may change
AstConst* constInitp = initAssp->rhsp()->castConst();
if (!constInitp) return cantUnroll(nodep, "non-constant initializer");
//
// Condition check
if (condp->nextp()) nodep->v3fatalSrc("conditional shouldn't be a list");
//
// Assignment of next value check
AstAssign* incAssp = incp->castAssign();
if (!incAssp) return cantUnroll(nodep, "no increment assignment");
if (incAssp->nextp()) nodep->v3fatalSrc("increment shouldn't be a list");
AstNodeBiop* incInstrp = incAssp->rhsp()->castNodeBiop();
//
if (m_forVscp) { UINFO(8, " Loop Variable: "<<m_forVscp<<endl); }
else { UINFO(8, " Loop Variable: "<<m_forVarp<<endl); }
if (debug()>=9) nodep->dumpTree(cout,"- for: ");
//
// Extract the constant loop bounds
bool subtract = incInstrp->castSub();
{
if (!subtract && !incInstrp->castAdd()) return cantUnroll(nodep, "missing add/sub for incrementer");
AstVarRef* incVarrp = (subtract ? incInstrp->lhsp()->castVarRef()
: incInstrp->rhsp()->castVarRef());
if (!incVarrp) return cantUnroll(nodep, "missing variable in incrementer");
if (incVarrp->varp() != m_forVarp
|| incVarrp->varScopep() != m_forVscp) {
return cantUnroll(nodep, "different variables in incrementer");
}
}
//
// Adds have the # on the lhsp because V3Const pushes rhs consts over to the lhs
// Subtracts have it on the rhs, because you write i=i-1; i=1-i is non-sensible.
AstConst* preconstIncp = (subtract ? incInstrp->rhsp()->castConst()
: incInstrp->lhsp()->castConst());
if (m_generate) preconstIncp = V3Const::constifyParamsEdit(preconstIncp)->castConst();
AstConst* constIncp = (subtract ? incInstrp->rhsp()->castConst()
: incInstrp->lhsp()->castConst());
UINFO(8, " Inc expr ok: "<<constIncp<<endl);
if (!constIncp) return cantUnroll(nodep, "non-constant increment");
if (constIncp->isZero()) return cantUnroll(nodep, "zero increment"); // Or we could loop forever below...
bool lt = condp->castLt() || condp->castLtS();
bool lte = condp->castLte() || condp->castLteS();
bool gt = condp->castGt() || condp->castGtS();
bool gte = condp->castGte() || condp->castGteS();
if (!lt && !lte && !gt && !gte)
return cantUnroll(nodep, "condition not <= or <");
AstNodeBiop* condBip = condp->castNodeBiop();
if (!condBip->lhsp()->castVarRef())
return cantUnroll(nodep, "no variable on lhs of condition");
if (condBip->lhsp()->castVarRef()->varp() != m_forVarp
|| condBip->lhsp()->castVarRef()->varScopep() != m_forVscp)
return cantUnroll(nodep, "different variable in condition");
if (m_generate) V3Const::constifyParamsEdit(condBip->rhsp()); // rhsp may change
AstConst* constStopp = condBip->rhsp()->castConst();
if (!constStopp) return cantUnroll(nodep, "non-constant final value");
UINFO(8, " Stop expr ok: "<<constStopp<<endl);
//
if (constInitp->width()>32 || constInitp->num().isFourState()
|| constStopp->width()>32 || constStopp->num().isFourState()
|| constIncp->width()>32 || constIncp->num().isFourState())
return cantUnroll(nodep, "init/final/increment too large or four state");
vlsint32_t valInit = constInitp->num().toSInt();
vlsint32_t valStop = constStopp->num().toSInt();
if (lte) valStop++; if (gte) valStop--;
vlsint32_t valInc = constIncp->num().toSInt();
if (subtract) valInc = -valInc;
UINFO(8," In Numbers: for (v="<<valInit<<"; v<"<<valStop<<"; v=v+"<<valInc<<")\n");
//
if (!m_generate) {
int loops = ((valStop - valInit)/valInc);
if (loops < 0) { loops += (1ULL<<constStopp->width()); } // Will roll around
UINFO(8, " ~Iters: "<<loops<<" c="<<unrollCount()<<endl);
if (loops > unrollCount())
return cantUnroll(nodep, "too many iterations");
// Less than 10 statements in the body?
int bodySize = 0;
int bodyLimit = v3Global.opt.unrollStmts();
//.........这里部分代码省略.........
示例13: 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: ");
}
示例14: visit
virtual void visit(AstNodeAssign* nodep) {
if (!m_cfuncp) return;
// Left select WordSel or ArraySel
AstNodeSel* lselp = VN_CAST(nodep->lhsp(), NodeSel);
if (!lselp) { mergeEnd(); return; } // Not ever merged
// Of a constant index
AstConst* lbitp = VN_CAST(lselp->bitp(), Const);
if (!lbitp) { mergeEnd(); return; }
uint32_t index = lbitp->toUInt();
// Of variable
AstNodeVarRef* lvarrefp = VN_CAST(lselp->fromp(), NodeVarRef);
if (!lvarrefp) { mergeEnd(); return; }
// RHS is a constant or a select
AstConst* rconstp = VN_CAST(nodep->rhsp(), Const);
AstNodeSel* rselp = VN_CAST(nodep->rhsp(), NodeSel);
AstNodeVarRef* rvarrefp = NULL;
if (rconstp) { // Ok
} else {
if (!rselp) { mergeEnd(); return; }
AstConst* rbitp = VN_CAST(rselp->bitp(), Const);
rvarrefp = VN_CAST(rselp->fromp(), NodeVarRef);
if (!rbitp || rbitp->toUInt() != index
|| !rvarrefp
|| lvarrefp->varp() == rvarrefp->varp()) {
mergeEnd(); return;
}
}
if (m_mgSelLp) { // Old merge
if (m_mgCfuncp == m_cfuncp
&& m_mgNextp == nodep
&& m_mgSelLp->same(lselp)
&& m_mgVarrefLp->same(lvarrefp)
&& (m_mgConstRp
? (rconstp && m_mgConstRp->same(rconstp))
: (rselp
&& m_mgSelRp->same(rselp)
&& m_mgVarrefRp->same(rvarrefp)))
&& (index == m_mgIndexLo-1
|| index == m_mgIndexHi+1)) {
// Sequentially next to last assign; continue merge
if (index == m_mgIndexLo-1) m_mgIndexLo = index;
else if (index == m_mgIndexHi+1) m_mgIndexHi = index;
UINFO(9, "Continue merge i="<<index
<<" "<<m_mgIndexHi<<":"<<m_mgIndexLo<<" "<<nodep<<endl);
m_mgAssignps.push_back(nodep);
m_mgNextp = nodep->nextp();
return;
}
else {
// This assign doesn't merge with previous assign,
// but should start a new merge
mergeEnd();
}
}
// Merge start
m_mgAssignps.push_back(nodep);
m_mgCfuncp = m_cfuncp;
m_mgNextp = nodep->nextp();
m_mgSelLp = lselp;
m_mgSelRp = rselp;
m_mgVarrefLp = lvarrefp;
m_mgVarrefRp = rvarrefp;
m_mgConstRp = rconstp;
m_mgIndexLo = index;
m_mgIndexHi = index;
UINFO(9, "Start merge i="<<index<<" "<<nodep<<endl);
}
示例15: visit
virtual void visit(AstVarRef* nodep, AstNUser*) {
if (m_varModeCheck
&& nodep->varp() == m_forVarp
&& nodep->varScopep() == m_forVscp
&& nodep->lvalue()) {
UINFO(8," Itervar assigned to: "<<nodep<<endl);
m_varAssignHit = true;
}
if (m_varModeReplace
&& nodep->varp() == m_forVarp
&& nodep->varScopep() == m_forVscp
&& !nodep->lvalue()) {
AstNode* newconstp = m_varValuep->cloneTree(false);
nodep->replaceWith(newconstp);
pushDeletep(nodep);
}
}