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);
     }
 }
Example #2
0
    virtual void visit(AstArraySel* nodep, AstNUser*) {
	if (!m_assignp) return;
	if (nodep->user3()) return;  // Prevent recursion on just created nodes
	unsigned dim = explicitDimensions(nodep);
	AstVarRef* refp = nodep->user1p()->castNode()->castVarRef();
	pair<uint32_t,uint32_t> arrDim = refp->varp()->dtypep()->dimensions(false);
	uint32_t implicit = (arrDim.second) - dim;
	if (implicit > 0) {
	    AstArraySel* newp = insertImplicit(nodep->cloneTree(false), dim+1, implicit);
	    nodep->replaceWith(newp); nodep = newp;
	    nodep->user3(true);
	}
	int clones = countClones(nodep);
	if (m_assignp->user2() > 0 && m_assignp->user2() != clones) {
	    m_assignp->v3error("Slices of arrays in assignments must have the same unpacked dimensions");
	} else if (!m_assignp->user2()) {
	    if (m_extend && clones > 1 && !m_assignError) {
		m_assignp->v3error("Unsupported: Assignment between unpacked arrays of different dimensions");
		m_assignError = true;
	    }
	    if (clones > 1 && !refp->lvalue() && refp->varp() == m_lhsVarRefp->varp()
		&& !m_assignp->castAssignDly() && !m_assignError) {
		// LHS Var != RHS Var for a non-delayed assignment
		m_assignp->v3error("Unsupported: Slices in a non-delayed assignment with the same Var on both sides");
		m_assignError = true;
	    }
	    m_assignp->user2(clones);
	}
    }
Example #3
0
    virtual void visit(AstPin* nodep, AstNUser*) {
	// Check to see if any output pins have __en pins and create the __en pins to match
	AstVarRef* refp = findVarRef(nodep);

	if (refp && refp->lvalue() && nodep->modVarp()->user1p()) {
	    AstVar* enchildp = (AstVar*)nodep->modVarp()->user1p();
	    UINFO(9, "       Pulling __en var" << enchildp << endl);
	    AstVar* enp = new AstVar(enchildp->fileline(),
				     AstVarType::OUTPUT,
				     enchildp->name()+cvtToStr(m_unique++),
				     enchildp);
	    enp->user2(enchildp->user2());
	    m_modp->addStmtp(enp);
	    AstPin* pinp = new AstPin(nodep->fileline(),
				      nodep->pinNum(),
				      enp->name(),
				      new AstVarRef(nodep->fileline(), enp, true));
	    AstVarRef *rp = findVarRef(pinp);
	    rp->replaceWith(new AstVarRef(nodep->fileline(), enp, true));
	    rp->deleteTree(); rp=NULL;
	    pinp->width(enp->width(),enp->width());  // minwidth==width
	    pinp->modVarp(enchildp);
	    m_cellp->addPinsp(pinp);
	    refp->user1p(enp);
	    refp->varp()->user1p(enp);
	}
	// Simplify interconnect in preperation for V3Inst
	// (This could be a separate visitor, but we're in the neighborhood)
	V3Inst::pinReconnectSimple(nodep, m_cellp, m_modp);
    }
Example #4
0
    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);
	}
    }
Example #5
0
    //*******************************************************************
    // The following visitor functions deal with detecting Z's in the
    // logic, stripping the Z's out and creating an __en signal and its
    // logic.
    //*******************************************************************
    virtual void visit(AstPull* nodep, AstNUser*) {
        // replace any pullup/pulldowns with assignw logic and an __en
        // signal just like it is any other tristate signal.  The only
        // difference is that the user2() variable on the __en signal
        // will be given a pull direction--i.e. pulldown=1, pullup=2.
        // This will signal the driver exansion logic to put a default
        // pullup or pulldown state on the tristate bus under the high-Z
        // condition when no one is driving the bus.  Given the complexity
        // of merging tristate drivers at any level, the current limitation
        // of this implementation is that a pullup/down gets applied
        // to all bits of a bus and a bus cannot have drivers in opposite
        // directions on indvidual pins.
        AstNode* outp = nodep->lhsp()->unlinkFrBack();;
        AstVarRef* outrefp = NULL;
	int width=-1;
	if (outp->castVarRef()) {
	    outrefp = outp->castVarRef();
	} else if (outp->castSel()) {
	    outrefp = outp->castSel()->fromp()->castVarRef();
	    width = outp->castSel()->widthConst();
	} else {
	    nodep->v3error("Can't find LHS varref");
	}
	outrefp->lvalue(true);
	AstVar* varp = outrefp->varp();
	if (width==-1) width=varp->width();

        V3Number num0 (nodep->fileline(), width);
	num0.setAllBits0();
	V3Number num1 (nodep->fileline(), width);
	num1.setAllBits1();

	AstConst* enrhsp = new AstConst(nodep->fileline(), num0);
	AstVar* enp = createEnableVar(outp, outrefp, enrhsp, width, "pull");
	enp->user2(nodep->direction()+1); // record the pull direction

	AstAssignW* newassp = new AstAssignW(nodep->fileline(), outp,
					     new AstConst(nodep->fileline(), nodep->direction() ? num1 : num0));
	nodep->replaceWith(newassp);
	nodep->deleteTree(); nodep=NULL;
	newassp->iterateChildren(*this);
    }