Example #1
0
    FromData fromDataForArray(AstNode* nodep, AstNode* basefromp, bool rangedSelect) {
	// What is the data type and information for this SEL-ish's from()?
	UINFO(9,"  fromData start ddtypep = "<<basefromp<<endl);
	VNumRange fromRange;  // constructs to isRanged(false)
	while (basefromp) {
	    if (basefromp->castAttrOf()) {
		basefromp = basefromp->castAttrOf()->fromp();
		continue;
	    }
	    break;
	}
	if (!basefromp || !basefromp->dtypep()) nodep->v3fatalSrc("Select with no from dtype");
	AstNodeDType* ddtypep = basefromp->dtypep()->skipRefp();
	AstNode* errp = ddtypep;
	UINFO(9,"  fromData.ddtypep = "<<ddtypep<<endl);
	if (AstNodeArrayDType* adtypep = ddtypep->castNodeArrayDType()) {
	    fromRange = adtypep->declRange();
	}
	else if (AstNodeClassDType* adtypep = ddtypep->castNodeClassDType()) {
	    fromRange = adtypep->declRange();
	}
	else if (AstBasicDType* adtypep = ddtypep->castBasicDType()) {
	    if (adtypep->isRanged()) {
		if (adtypep->rangep()
		    && (!adtypep->rangep()->msbp()->castConst()
			|| !adtypep->rangep()->lsbp()->castConst()))
		    nodep->v3fatalSrc("Non-constant variable range; errored earlier");  // in constifyParam(bfdtypep)
		fromRange = adtypep->declRange();
	    } else {
		nodep->v3error("Illegal bit or array select; type does not have a bit range, or bad dimension: type is "
			       <<errp->prettyName());
	    }
	}
	else {
	    nodep->v3error("Illegal bit or array select; type already selected, or bad dimension: type is "
			   <<errp->prettyName());
	}
	return FromData(errp,ddtypep,fromRange);
    }
Example #2
0
    void replaceSelPlusMinus(AstNodePreSel* nodep) {
	// Select of a range specified with +: or -:, i.e. "array[2+:3], [2-:3]"
	// This select style has a lsb and width
	UINFO(6,"SELPLUS/MINUS "<<nodep<<endl);
	// Below 2 lines may change nodep->widthp()
	if (debug()>=9) nodep->dumpTree(cout,"--SELPM0: ");
	V3Const::constifyParamsEdit(nodep->thsp()); // May relink pointed to node
	checkConstantOrReplace(nodep->thsp(), "Width of :+ or :- bit extract isn't a constant");
	if (debug()>=9) nodep->dumpTree(cout,"--SELPM3: ");
	// Now replace it with an AstSel
	AstNode* fromp = nodep->lhsp()->unlinkFrBack();
	AstNode* rhsp  = nodep->rhsp()->unlinkFrBack();
	AstNode* widthp = nodep->thsp()->unlinkFrBack();
	int width = widthp->castConst()->toSInt();
	if (width > (1<<28)) nodep->v3error("Width of :+ or :- is huge; vector of over 1billion bits: "<<widthp->prettyName());
	if (width<0) nodep->v3error("Width of :+ or :- is < 0: "<<widthp->prettyName());
	FromData fromdata = fromDataForArray(nodep, fromp, width!=1);
	AstNodeDType* ddtypep = fromdata.m_dtypep;
	VNumRange fromRange = fromdata.m_fromRange;
	if (ddtypep->castBasicDType()
	    || ddtypep->castPackArrayDType()
	    || (ddtypep->castNodeClassDType()
		&& ddtypep->castNodeClassDType()->packedUnsup())) {
	    int elwidth = 1;
	    AstNode* newwidthp = widthp;
	    if (AstPackArrayDType* adtypep = ddtypep->castPackArrayDType()) {
		elwidth = adtypep->width() / fromRange.elements();
		newwidthp = new AstConst (nodep->fileline(),AstConst::Unsized32(), width * elwidth);
	    }
	    AstNode* newlsbp = NULL;
	    if (nodep->castSelPlus()) {
		if (fromRange.littleEndian()) {
		    // SELPLUS(from,lsb,width) -> SEL(from, (vector_msb-width+1)-sel, width)
		    newlsbp = newSubNeg((fromRange.hi()-width+1), rhsp);
		} else {
		    // SELPLUS(from,lsb,width) -> SEL(from, lsb-vector_lsb, width)
		    newlsbp = newSubNeg(rhsp, fromRange.lo());
		}
	    } else if (nodep->castSelMinus()) {
		if (fromRange.littleEndian()) {
		    // SELMINUS(from,msb,width) -> SEL(from, msb-[bit])
		    newlsbp = newSubNeg(fromRange.hi(), rhsp);
		} else {
		    // SELMINUS(from,msb,width) -> SEL(from, msb-(width-1)-lsb#)
		    newlsbp = newSubNeg(rhsp, fromRange.lo()+(width-1));
		}
	    } else {
		nodep->v3fatalSrc("Bad Case");
	    }
	    if (elwidth != 1) newlsbp = new AstMul (nodep->fileline(), newlsbp,
						    new AstConst (nodep->fileline(), elwidth));
	    AstSel* newp = new AstSel (nodep->fileline(),
				       fromp, newlsbp, newwidthp);
	    newp->declRange(fromRange);
	    newp->declElWidth(elwidth);
	    UINFO(6,"   new "<<newp<<endl);
	    if (debug()>=9) newp->dumpTree(cout,"--SELNEW: ");
	    nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
	}
	else {  // NULL=bad extract, or unknown node type
	    nodep->v3error("Illegal +: or -: select; type already selected, or bad dimension: type is "
			   <<fromdata.m_errp->prettyTypeName());
	    // How to recover?  We'll strip a dimension.
	    nodep->replaceWith(fromp); pushDeletep(nodep); VL_DANGLING(nodep);
	}
	// delete whataver we didn't use in reconstruction
	if (!fromp->backp()) { pushDeletep(fromp); VL_DANGLING(fromp); }
	if (!rhsp->backp()) { pushDeletep(rhsp); VL_DANGLING(rhsp); }
	if (!widthp->backp()) { pushDeletep(widthp); VL_DANGLING(widthp); }
    }