Example #1
0
    AstNode* nafgCreateRecurse(V3GraphVertex* vertexp, uint32_t generation) {
	// Forewards follow user() marked previously and build tree
	AstNode* nodep = NULL;
	// OR across all edges found at this level
	//UINFO(9," nafgEnter: v "<<(void*)(vertexp)<<" "<<vertexp->name()<<endl);
	for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
	    if (edgep->user() == generation) {
		GaterEdge* cedgep = static_cast<GaterEdge*>(edgep);
		AstNode* eqnp = NULL;
		//UINFO(9," nafgFollow: "<<(void*)(edgep)<<" "<<edgep->name()<<endl);
		if (dynamic_cast<GaterHeadVertex*>(edgep->fromp())) {
		    // Just OR in all lower terms
		    eqnp = nafgCreateRecurse(edgep->top(), generation);
		} else if (GaterIfVertex* cVxp = dynamic_cast<GaterIfVertex*>(edgep->fromp())) {
		    // Edges from IFs represent a real IF branch in the equation tree
		    //UINFO(9,"  ifver "<<(void*)(edgep)<<" cc"<<edgep->dotColor()<<endl);
		    eqnp = cVxp->nodep()->condp()->cloneTree(true);
		    if (eqnp && cedgep->ifelseFalse()) {
			eqnp = new AstNot(eqnp->fileline(),eqnp);
		    }
		    // We need to AND this term onto whatever was found below it
		    AstNode* belowp = nafgCreateRecurse(edgep->top(), generation);
		    if (belowp) eqnp = new AstAnd(eqnp->fileline(),eqnp,belowp);
		}
		// Top level we could choose to make multiple gaters, or ORs under the gater
		// Right now we'll put OR lower down and let other optimizations deal
		if (nodep) nodep = new AstOr(eqnp->fileline(),nodep,eqnp);
		else nodep = eqnp;
		//if (debug()>=9) nodep->dumpTree(cout,"      followExpr: ");
	    }
	}
	//UINFO(9," nafgExit:  "<<(void*)(vertexp)<<" "<<vertexp->name()<<endl);
	return nodep;
    }
void TypeInferenceVisitor::visitBinaryOpNode(BinaryOpNode* node) {
	AstNode* left = node->left();
	AstNode* right = node->right();
	left->visit(this);
	right->visit(this);
	_types[node] = maxType(_types[left], _types[right]);
}
Example #3
0
MultiTopicImpl::MultiTopicImpl(const char* name,
  const char* type_name, const char* subscription_expression,
  const DDS::StringSeq& expression_parameters,
  DomainParticipantImpl* participant)
  : TopicDescriptionImpl(name, type_name,
      findTypeSupport(participant, type_name),
      participant)
  , subscription_expression_(subscription_expression)
  , expression_parameters_(expression_parameters)
  , filter_eval_(NULL)
{
  const char* out = subscription_expression
    + std::strlen(subscription_expression);
  yard::SimpleTextParser parser(subscription_expression, out);
  if (!parser.Parse<TopicExpressionGrammar::TopicCompleteInput>()) {
    reportErrors(parser, subscription_expression);
  }

  for (AstNode* iter = parser.GetAstRoot()->GetFirstChild(); iter;
      iter = iter->GetSibling()) {
    if (iter->TypeMatches<TopicExpressionGrammar::SubjectFieldSpec>()) {
      AstNode* fieldName = iter->GetFirstChild();
      aggregation_.push_back(SubjectFieldSpec(toString(fieldName),
        toString(fieldName->GetSibling())));
    } else if (iter->TypeMatches<TopicExpressionGrammar::TopicName>()) {
      selection_.push_back(toString(iter));
    } else {
      filter_eval_ = new FilterEvaluator(iter);
    }
  }
}
Example #4
0
    AstVar* createEnableVar(AstNode* outp, AstVarRef* outrefp, AstNode* enrhsp, int width, string suffix="") {
	// this function creates an  __en Var that corresponds to
	// the outp and outrefp and creates an assignw to enrhsp
        AstVar* enp = new AstVar (outrefp->varp()->fileline(),
				  AstVarType::MODULETEMP,
				  outrefp->name() + "__en" + suffix + cvtToStr(m_unique++),
				  AstLogicPacked(), width);
	enp->varType2Out();

	if (enp->width() != enrhsp->width()) {
	    if (enrhsp->width1()) { // it seems from my futzing that the linter guarantees this condition
		enrhsp = new AstReplicate(enrhsp->fileline(), enrhsp,
					  new AstConst(enrhsp->fileline(), V3Number(enrhsp->fileline(), 32, enp->width())));
		enrhsp->width(enp->width(), enp->width());  //minwidth==width
	    } else {
		enrhsp->v3error("Don't know how to deal with selection logic wider than 1 bit");
	    }
	}

	AstNode* newassp = new AstAssignW (enp->fileline(),
					   new AstVarRef (enp->fileline(), enp, true),
					   enrhsp);
	if (debug()>=9) enp->dumpTreeAndNext(cout,"-   cev-out: ");
	if (debug()>=9) newassp->dumpTreeAndNext(cout,"-   cev-out: ");
        m_modp->addStmtp(enp);
        m_modp->addStmtp(newassp);

	outrefp->user1p(enp); // put __en signal into varref for later usage
	outrefp->varp()->user1p(enp); // put __en signal into var as well in the event this is a single lhs driver and this needs passed up one level

	return enp;
    }
Example #5
0
void V3Hashed::erase(iterator it) {
    AstNode* nodep = iteratorNodep(it);
    UINFO(8,"   erase "<<nodep<<endl);
    if (!nodep->user4p()) nodep->v3fatalSrc("Called removeNode on non-hashed node");
    m_hashMmap.erase(it);
    nodep->user4p(NULL);   // So we don't allow removeNode again
}
Example #6
0
    AstNode* newSubNeg(AstNode* lhsp, vlsint32_t rhs) {
	// Return lhs-rhs, but if rhs is negative use an add, so we won't
	// have to deal with signed math and related 32bit sign extension problems
	if (rhs == 0) {
	    return lhsp;
	} else if (lhsp->castConst()) {
	    // Optional vs just making add/sub below, but saves constification some work
	    V3Number num (lhsp->fileline(), lhsp->width());
	    num.opSub(lhsp->castConst()->num(), V3Number(lhsp->fileline(), 32, rhs));
	    num.isSigned(lhsp->isSigned());
	    AstNode* newp = new AstConst(lhsp->fileline(), num);
	    return newp;
	} else if (rhs > 0) {
	    AstNode* newp = new AstSub(lhsp->fileline(), lhsp,
				       new AstConst(lhsp->fileline(), AstConst::Unsized32(), rhs));
	    // We must make sure sub gets sign of original value, not from the constant
	    newp->dtypeFrom(lhsp);
	    return newp;
	} else {  // rhs < 0;
	    AstNode* newp = new AstAdd(lhsp->fileline(), lhsp,
				       new AstConst(lhsp->fileline(), AstConst::Unsized32(), -rhs));
	    // We must make sure sub gets sign of original value, not from the constant
	    newp->dtypeFrom(lhsp);
	    return newp;
	}
    }
Example #7
0
    virtual void visit(AstNodeClassDType* nodep, AstNUser*) {
	if (m_traVscp) {
	    if (nodep->packed() && !v3Global.opt.traceStructs()) {
		// Everything downstream is packed, so deal with as one trace unit
		// This may not be the nicest for user presentation, but is a much faster way to trace
		addTraceDecl(VNumRange());
	    } else {
		if (!nodep->packed()) {
		    addIgnore("Unsupported: Unpacked struct/union");
		} else {
		    for (AstMemberDType* itemp = nodep->membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) {
			AstNodeDType* subtypep = itemp->subDTypep()->skipRefp();
			string oldShowname = m_traShowname;
			AstNode* oldValuep = m_traValuep;
			{
			    m_traShowname += string(" ")+itemp->prettyName();
			    if (nodep->castStructDType()) {
				m_traValuep = new AstSel(nodep->fileline(), m_traValuep->cloneTree(true),
							 itemp->lsb(), subtypep->width());
				subtypep->accept(*this);
				m_traValuep->deleteTree(); m_traValuep = NULL;
			    } else { // Else union, replicate fields
				subtypep->accept(*this);
			    }
			}
			m_traShowname = oldShowname;
			m_traValuep = oldValuep;
		    }
		}
	    }
	}
    }
Example #8
0
    AstVarScope* getCreateLastClk(AstVarScope* vscp) {
	if (vscp->user1p()) return ((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);
        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);
        // Add init
        AstNode* fromp = new AstVarRef(newvarp->fileline(), vscp, false);
        if (v3Global.opt.xInitialEdge()) fromp = new AstNot(fromp->fileline(), fromp);
        AstNode* newinitp = new AstAssign(vscp->fileline(),
                                          new AstVarRef(newvarp->fileline(), newvscp, true),
                                          fromp);
        addToInitial(newinitp);
	// 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;
    }
Example #9
0
    virtual void visit(AstPackArrayDType* nodep, AstNUser*) {
	if (m_traVscp) {
	    if (!v3Global.opt.traceStructs()) {
		// Everything downstream is packed, so deal with as one trace unit
		// This may not be the nicest for user presentation, but is a much faster way to trace
		addTraceDecl(VNumRange());
	    } else {
		AstNodeDType* subtypep = nodep->subDTypep()->skipRefp();
		for (int i=nodep->lsb(); i<=nodep->msb(); ++i) {
		    string oldShowname = m_traShowname;
		    AstNode* oldValuep = m_traValuep;
		    {
			m_traShowname += string("(")+cvtToStr(i)+string(")");
			m_traValuep = new AstSel(nodep->fileline(), m_traValuep->cloneTree(true),
						 (i - nodep->lsb())*subtypep->width(),
						 subtypep->width());
			subtypep->accept(*this);
			m_traValuep->deleteTree(); m_traValuep = NULL;
		    }
		    m_traShowname = oldShowname;
		    m_traValuep = oldValuep;
		}
	    }
	}
    }
Example #10
0
void Printer::printBlockContents(BlockNode* node) {
    // functions delcarations
    Scope::FunctionIterator funIt(node->scope());
    while (funIt.hasNext()) {
        funIt.next()->node()->visit(this);
        out << '\n';
    }

	// variables declarations
    Scope::VarIterator varIt(node->scope());
    while (varIt.hasNext()) {
        AstVar* var = varIt.next();
        out << typeToName(var->type()) 
        	<< " " << var->name() << ";\n";
    }

    // nodes
    for (size_t i = 0; i < node->nodes(); ++i) {
        AstNode* subNode = node->nodeAt(i);
        subNode->visit(this);
        if (!subNode->isIfNode() && 
        	!subNode->isWhileNode() && 
        	!subNode->isForNode()) {
            out << ';';
        }
        out << '\n';
    }
}
Example #11
0
    AstArraySel* insertImplicit(AstNode* nodep, unsigned start, unsigned count) {
	// Insert any implicit slices as explicit slices (ArraySel nodes).
	// Return a new pointer to replace nodep() in the ArraySel.
	UINFO(9,"  insertImplicit (start="<<start<<",c="<<count<<") "<<nodep<<endl);
	AstVarRef* refp = nodep->user1p()->castNode()->castVarRef();
	if (!refp) nodep->v3fatalSrc("No VarRef in user1 of node "<<nodep);
	AstVar* varp = refp->varp();
	AstNode* topp = nodep;
	for (unsigned i = start; i < start + count; ++i) {
	    AstNodeDType* dtypep = varp->dtypep()->dtypeDimensionp(i-1);
	    AstUnpackArrayDType* adtypep = dtypep->castUnpackArrayDType();
	    if (!adtypep) nodep->v3fatalSrc("insertImplicit tried to expand an array without an ArrayDType");
	    vlsint32_t msb = adtypep->msb();
	    vlsint32_t lsb = adtypep->lsb();
	    if (lsb > msb) {
		// Below code assumes big bit endian; just works out if we swap
		int x = msb; msb = lsb; lsb = x;
	    }
	    UINFO(9,"    ArraySel-child: "<<topp<<endl);
	    AstArraySel* newp = new AstArraySel(nodep->fileline(), topp,
						// "lsb-lsb": Arrays are zero-based so index 0 is always lsb
						new AstConst(nodep->fileline(), lsb-lsb));
	    if (!newp->dtypep()) {
		newp->v3fatalSrc("ArraySel dtyping failed when resolving slice");  // see ArraySel constructor
	    }
	    newp->user1p(refp);
	    newp->start(lsb);
	    newp->length(msb - lsb + 1);
	    topp = newp;
	}
	return topp->castArraySel();
    }
    virtual void visit(AstUdpTable* nodep, AstNUser*) {
	UINFO(5,"UDPTABLE  "<<nodep<<endl);
	if (!v3Global.opt.bboxUnsup()) {
	    // We don't warn until V3Inst, so that UDPs that are in libraries and
	    // never used won't result in any warnings.
	} else {
	    // Massive hack, just tie off all outputs so our analysis can proceed
	    AstVar* varoutp = NULL;
	    for (AstNode* stmtp = m_modp->stmtsp(); stmtp; stmtp=stmtp->nextp()) {
		if (AstVar* varp = stmtp->castVar()) {
		    if (varp->isInput()) {
		    } else if (varp->isOutput()) {
			if (varoutp) { varp->v3error("Multiple outputs not allowed in udp modules"); }
			varoutp = varp;
			// Tie off
			m_modp->addStmtp(new AstAssignW(varp->fileline(),
							new AstVarRef(varp->fileline(), varp, true),
							new AstConst(varp->fileline(), AstConst::LogicFalse())));
		    } else {
			varp->v3error("Only inputs and outputs are allowed in udp modules");
		    }
		}
	    }
	    nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
	}
    }
Example #13
0
    // ACCESSORS
    // Do not make accessor for nodep(),  It may change due to
    // reordering a lower block, but we don't repair it
    virtual string name() const {
	if (m_nodep->name() == "") {
	    return cvtToStr((void*)m_nodep);
	} else {
	    return m_nodep->name();
	}
    }
Example #14
0
    void processBlock(AstNode* nodep) {
	if (!nodep) return;	// Empty lists are ignorable
	// Pass the first node in a list of block items, we'll process them
	// Check there's >= 2 sub statements, else nothing to analyze
	// Save recursion state
	AstNode* firstp = nodep;   // We may reorder, and nodep is no longer first.
	void* oldBlockUser3 = nodep->user3p();   // May be overloaded in below loop, save it
	nodep->user3p(NULL);
	if (!nodep->firstAbovep()) nodep->v3fatalSrc("Node passed is in next list; should have processed all list at once");
	// Process it
	if (!nodep->nextp()) {
	    // Just one, so can't reorder.  Just look for more blocks/statements.
            iterate(nodep);
	} else {
	    UINFO(9,"  processBlock "<<nodep<<endl);
	    // Process block and followers
	    scanBlock(nodep);
	    if (m_noReorderWhy != "") {  // Jump or something nasty
		UINFO(9,"  NoReorderBlock because "<<m_noReorderWhy<<endl);
	    } else {
		// Reorder statements in this block
		cleanupBlockGraph(nodep);
		reorderBlock(nodep);
		// Delete old vertexes and edges only applying to this block
		while (firstp->backp()->nextp()==firstp) firstp = firstp->backp();  // Walk back to first in list
		for (AstNode* nextp=firstp; nextp; nextp=nextp->nextp()) {
		    SplitLogicVertex* vvertexp = (SplitLogicVertex*)nextp->user3p();
		    vvertexp->unlinkDelete(&m_graph);
		}
	    }
	}
	// Again, nodep may no longer be first.
	firstp->user3p(oldBlockUser3);
    }
Example #15
0
    virtual void visit(AstWhile* nodep, AstNUser*) {
	nodep->iterateChildren(*this);
	if (m_varModeCheck || m_varModeReplace) {
	} else {
	    // Constify before unroll call, as it may change what is underneath.
	    if (nodep->precondsp()) V3Const::constifyEdit(nodep->precondsp());  // precondsp may change
	    if (nodep->condp()) V3Const::constifyEdit(nodep->condp()); // condp may change
	    // Grab initial value
	    AstNode* initp = NULL;  // Should be statement before the while.
	    if (nodep->backp()->nextp() == nodep) initp=nodep->backp();
	    if (initp) { V3Const::constifyEdit(initp); VL_DANGLING(initp); }
	    if (nodep->backp()->nextp() == nodep) initp=nodep->backp();
	    // Grab assignment
	    AstNode* incp = NULL;  // Should be last statement
	    if (nodep->incsp()) V3Const::constifyEdit(nodep->incsp());
	    if (nodep->incsp()) incp = nodep->incsp();
	    else {
		for (incp = nodep->bodysp(); incp && incp->nextp(); incp = incp->nextp()) {}
		if (incp) { V3Const::constifyEdit(incp); VL_DANGLING(incp); }
		for (incp = nodep->bodysp(); incp && incp->nextp(); incp = incp->nextp()) {}  // Again, as may have changed
	    }
	    // And check it
	    if (forUnrollCheck(nodep, initp,
			       nodep->precondsp(), nodep->condp(),
			       incp, nodep->bodysp())) {
		pushDeletep(nodep); VL_DANGLING(nodep); // Did replacement
	    }
	}
    }
Example #16
0
void TypeCheckerVisitor::visitBinaryOpNode(BinaryOpNode* node) {
	AstNode* left = node->left();
	AstNode* right = node->right();
	left->visit(this);
	right->visit(this);
	setNodeType(node, getOperationResultType(node->kind(), left, right));
}
Example #17
0
    virtual void visit(AstConst* nodep, AstNUser*) {
	m_extend = true;
	if (m_assignp && m_assignp->user2() > 1 && !m_assignError) {
	    m_assignp->v3error("Unsupported: Assignment between a constant and an array slice");
	    m_assignError = true;
	}
    }
Example #18
0
void ByteCodeVisitor::visitCallNode(mathvm::CallNode *node) {
    unsigned long stackSize = currStack->size();
    AstFunction *astFunction = currScope->lookupFunction(node->name(), true);

    AstFunctionInfo *functionInfo = (AstFunctionInfo *) astFunction->info();
    Scope *parameterScope = astFunction->scope();

    if (node->parametersNumber() != parameterScope->variablesCount()) {
        error("parameters number mistmach in calling %s", node->name().c_str());
    }
    vector<VarType> declaredParameters;
    declaredParameters.reserve(parameterScope->variablesCount());
    Scope::VarIterator varIterator(parameterScope);
    while (varIterator.hasNext()) {
        declaredParameters.push_back(varIterator.next()->type());
    }

    vector<VarType>::reverse_iterator it = declaredParameters.rbegin();

    for (uint32_t i = node->parametersNumber(); i > 0; --i, ++it) {
        AstNode *n = node->parameterAt(i - 1);
        n->visit(this);
        cast(topStack(), (*it));
    }

    insn(BC_CALL);
    typed(functionInfo->function->id());
    if (astFunction->returnType() != VT_VOID) {
        pushStack(astFunction->returnType());
    }
}
Example #19
0
    virtual void visit(AstUnpackArrayDType* nodep, AstNUser*) {
	// Note more specific dtypes above
	if (m_traVscp) {
	    if ((int)nodep->arrayUnpackedElements() > v3Global.opt.traceMaxArray()) {
		addIgnore("Wide memory > --trace-max-array ents");
	    } else if (nodep->subDTypep()->skipRefp()->castBasicDType()  // Nothing lower than this array
		       && m_traVscp->dtypep()->skipRefp() == nodep) {  // Nothing above this array
		// Simple 1-D array, use exising V3EmitC runtime loop rather than unrolling
		// This will put "(index)" at end of signal name for us
		addTraceDecl(nodep->declRange());
	    } else {
		// Unroll now, as have no other method to get right signal names
		AstNodeDType* subtypep = nodep->subDTypep()->skipRefp();
		for (int i=nodep->lsb(); i<=nodep->msb(); ++i) {
		    string oldShowname = m_traShowname;
		    AstNode* oldValuep = m_traValuep;
		    {
			m_traShowname += string("(")+cvtToStr(i)+string(")");
			m_traValuep = new AstArraySel(nodep->fileline(), m_traValuep->cloneTree(true),
						      i - nodep->lsb());

			subtypep->accept(*this);
			m_traValuep->deleteTree(); m_traValuep = NULL;
		    }
		    m_traShowname = oldShowname;
		    m_traValuep = oldValuep;
		}
	    }
	}
    }
    virtual void visit(AstGenIf* nodep, AstNUser*) {
	UINFO(9,"  GENIF "<<nodep<<endl);
	nodep->condp()->iterateAndNext(*this);
	// We suppress errors when widthing params since short-circuiting in
	// the conditional evaluation may mean these error can never occur. We
	// then make sure that short-circuiting is used by constifyParamsEdit.
	V3Width::widthGenerateParamsEdit(nodep);  // Param typed widthing will
						  // NOT recurse the body.
	V3Const::constifyGenerateParamsEdit(nodep->condp()); // condp may change
	if (AstConst* constp = nodep->condp()->castConst()) {
	    AstNode* keepp = (constp->isZero()
			      ? nodep->elsesp()
			      : nodep->ifsp());
	    if (keepp) {
		keepp->unlinkFrBackWithNext();
		nodep->replaceWith(keepp);
	    } else {
		nodep->unlinkFrBack();
	    }
	    nodep->deleteTree(); nodep=NULL;
	    // Normal edit rules will now recurse the replacement
	} else {
	    nodep->condp()->v3error("Generate If condition must evaluate to constant");
	}
    }
    virtual void visit(AstPin* nodep, AstNUser*) {
	// Any non-direct pins need reconnection with a part-select
	if (!nodep->exprp()) return; // No-connect
	if (m_cellRangep) {
	    UINFO(4,"   PIN  "<<nodep<<endl);
	    int pinwidth = nodep->modVarp()->width();
	    int expwidth = nodep->exprp()->width();
	    if (expwidth == pinwidth) {
		// NOP: Arrayed instants: widths match so connect to each instance
	    } else if (expwidth == pinwidth*m_cellRangep->elementsConst()) {
		// Arrayed instants: one bit for each of the instants (each assign is 1 pinwidth wide)
		AstNode* exprp = nodep->exprp()->unlinkFrBack();
		bool inputPin = nodep->modVarp()->isInput();
		if (!inputPin && !exprp->castVarRef()
		    && !exprp->castConcat()  // V3Const will collapse the SEL with the one we're about to make
		    && !exprp->castSel()) {  // V3Const will collapse the SEL with the one we're about to make
		    nodep->v3error("Unsupported: Per-bit array instantiations with output connections to non-wires.");
		    // Note spec allows more complicated matches such as slices and such
		}
		exprp = new AstSel (exprp->fileline(), exprp,
				    pinwidth*(m_instNum-m_instLsb),
				    pinwidth);
		nodep->exprp(exprp);
	    } else {
		nodep->v3fatalSrc("Width mismatch; V3Width should have errored out.");
	    }
	}
    }
Example #22
0
    virtual void visit(AstRepeat* nodep, AstNUser*) {
	// So later optimizations don't need to deal with them,
	//    REPEAT(count,body) -> loop=count,WHILE(loop>0) { body, loop-- }
	// Note var can be signed or unsigned based on original number.
	AstNode* countp = nodep->countp()->unlinkFrBackWithNext();
   	string name = string("__Vrepeat")+cvtToStr(m_repeatNum++);
	// Spec says value is integral, if negative is ignored
	AstVar* varp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, name,
				  nodep->findSigned32DType());
	varp->usedLoopIdx(true);
	m_modp->addStmtp(varp);
	AstNode* initsp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
					countp);
	AstNode* decp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
				      new AstSub(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
						 new AstConst(nodep->fileline(), 1)));
	V3Number zero (nodep->fileline(), 32, 0);  zero.isSigned(true);
	AstNode* zerosp = new AstConst(nodep->fileline(), zero);
	AstNode* condp = new AstGtS(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
				    zerosp);
	AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext();
	AstNode* newp = new AstWhile(nodep->fileline(),
				     condp,
				     bodysp,
				     decp);
	initsp = initsp->addNext(newp);
	newp = initsp;
	nodep->replaceWith(newp);
	nodep->deleteTree(); VL_DANGLING(nodep);
    }
Example #23
0
    void visitEqNeqCase(AstNodeBiop* nodep) {
	UINFO(4," N/EQCASE->EQ "<<nodep<<endl);
	V3Const::constifyEdit(nodep->lhsp());  // lhsp may change
	V3Const::constifyEdit(nodep->rhsp());  // rhsp may change
	if (nodep->lhsp()->castConst() && nodep->rhsp()->castConst()) {
	    // Both sides are constant, node can be constant
	    V3Const::constifyEdit(nodep); VL_DANGLING(nodep);
	    return;
	} else {
	    AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
	    AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
	    AstNode* newp;
	    // If we got ==1'bx it can never be true (but 1'bx==1'bx can be!)
	    if (((lhsp->castConst() && lhsp->castConst()->num().isFourState())
		 || (rhsp->castConst() && rhsp->castConst()->num().isFourState()))) {
		V3Number num (nodep->fileline(), 1, (nodep->castEqCase()?0:1));
		newp = new AstConst (nodep->fileline(), num);
		lhsp->deleteTree(); VL_DANGLING(lhsp);
		rhsp->deleteTree(); VL_DANGLING(rhsp);
	    } else {
		if (nodep->castEqCase())
		newp = new AstEq (nodep->fileline(), lhsp, rhsp);
		else newp = new AstNeq (nodep->fileline(), lhsp, rhsp);
	    }
	    nodep->replaceWith(newp);
	    nodep->deleteTree(); VL_DANGLING(nodep);
	    // Iterate tree now that we may have gotten rid of Xs
	    newp->iterateChildren(*this);
	}
    }
Example #24
0
    AstNode* newFireAssert(AstNode* nodep, const string& message) {
	AstDisplay* dispp = new AstDisplay (nodep->fileline(), AstDisplayType::DT_ERROR, message, NULL, NULL);
	AstNode* bodysp = dispp;
	replaceDisplay(dispp, "%%Error");   // Convert to standard DISPLAY format
	bodysp->addNext(new AstStop (nodep->fileline()));
	bodysp = newIfAssertOn(bodysp);
	return bodysp;
    }
Example #25
0
    virtual void visit(AstCoverToggle* nodep, AstNUser*) {
	// Add to list of blocks under this scope
	UINFO(4,"    Move "<<nodep<<endl);
	AstNode* clonep = nodep->cloneTree(false);
	nodep->user2p(clonep);
	m_scopep->addActivep(clonep);
	clonep->iterateChildren(*this);	// We iterate under the *clone*
    }
Example #26
0
    virtual void visit(AstSel* nodep, AstNUser*) {
	m_extend = true;
	if (m_assignp && m_assignp->user2() > 1 && !m_assignError) {
	    m_assignp->v3error("Unsupported: Assignment between unpacked arrays of different dimensions");
	    m_assignError = true;
	}
	nodep->iterateChildren(*this);
    }
Example #27
0
    virtual void visit(AstAssignVarScope* nodep, AstNUser*) {
	// Copy under the scope but don't recurse
	UINFO(4,"    Move "<<nodep<<endl);
	AstNode* clonep = nodep->cloneTree(false);
	nodep->user2p(clonep);
	m_scopep->addActivep(clonep);
	clonep->iterateChildren(*this);	// We iterate under the *clone*
    }
Example #28
0
 explicit RemovePlaceholdersVisitor(AstNode* nodep) {
     iterate(nodep);
     for (NodeSet::const_iterator it = m_removeSet.begin();
          it != m_removeSet.end(); ++it) {
         AstNode* np = *it;
         np->unlinkFrBack();  // Without next
         np->deleteTree(); VL_DANGLING(np);
     }
 }
Example #29
0
    // VISITORS
    virtual void visit(AstVarScope* nodep, AstNUser*) {
	if (AstNodeAssign* assp = nodep->valuep()->castNodeAssign()) {
	    UINFO(5," Removeassign "<<assp<<endl);
	    AstNode* valuep = assp->rhsp();
	    valuep->unlinkFrBack();
	    assp->replaceWith(valuep);
	    assp->deleteTree(); VL_DANGLING(assp);
	}
    }
void AstTypeTable::repairCache() {
    // After we mass-change widthMin in V3WidthCommit, we need to correct the table.
    clearCache();
    for (AstNode* nodep = typesp(); nodep; nodep=nodep->nextp()) {
	if (AstBasicDType* bdtypep = nodep->castBasicDType()) {
	    (void)findInsertSameDType(bdtypep);
	}
    }
}