Esempio n. 1
0
    bool countLoops(AstAssign *initp, AstNode *condp, AstNode *incp, int max, int &outLoopsr) {
	outLoopsr = 0;
	V3Number loopValue = V3Number(initp->fileline());
	if (!simulateTree(initp->rhsp(), NULL, initp, loopValue)) {
	    return false;
	}
	while (1) {
	    V3Number res = V3Number(initp->fileline());
	    if (!simulateTree(condp, &loopValue, NULL, res)) {
		return false;
	    }
	    if (!res.isEqOne()) {
		break;
	    }

	    outLoopsr++;

	    // Run inc
	    AstAssign* incpass = incp->castAssign();
	    V3Number newLoopValue = V3Number(initp->fileline());
	    if (!simulateTree(incpass->rhsp(), &loopValue, incpass, newLoopValue)) {
		return false;
	    }
	    loopValue.opAssign(newLoopValue);
	    if (outLoopsr > max) {
		return false;
	    }
	}
	return true;
    }
Esempio n. 2
0
    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;
    }