예제 #1
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); }
    }
예제 #2
0
    virtual void visit(AstSelBit* nodep, AstNUser*) {
	// Select of a non-width specified part of an array, i.e. "array[2]"
	// This select style has a lsb and msb (no user specified width)
	UINFO(6,"SELBIT "<<nodep<<endl);
	if (debug()>=9) nodep->backp()->dumpTree(cout,"--SELBT0: ");
	// lhsp/rhsp do not need to be constant
	AstNode* fromp = nodep->lhsp()->unlinkFrBack();
	AstNode* rhsp = nodep->rhsp()->unlinkFrBack();  // bit we're extracting
	if (debug()>=9) nodep->dumpTree(cout,"--SELBT2: ");
	FromData fromdata = fromDataForArray(nodep, fromp, false);
	AstNodeDType* ddtypep = fromdata.m_dtypep;
	VNumRange fromRange = fromdata.m_fromRange;
	UINFO(6,"  ddtypep "<<ddtypep<<endl);
	if (AstUnpackArrayDType* adtypep = ddtypep->castUnpackArrayDType()) {
	    // SELBIT(array, index) -> ARRAYSEL(array, index)
	    AstNode* subp = rhsp;
	    if (fromRange.lo()!=0 || fromRange.hi()<0) {
		subp = newSubNeg (subp, fromRange.lo());
	    }
	    AstArraySel* newp = new AstArraySel (nodep->fileline(),
						 fromp, subp);
	    newp->dtypeFrom(adtypep->subDTypep());  // Need to strip off array reference
	    if (debug()>=9) newp->dumpTree(cout,"--SELBTn: ");
	    nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
	}
	else if (AstPackArrayDType* adtypep = ddtypep->castPackArrayDType()) {
	    // SELBIT(array, index) -> SEL(array, index*width-of-subindex, width-of-subindex)
	    AstNode* subp = rhsp;
	    if (fromRange.lo()!=0 || fromRange.hi()<0) {
		subp = newSubNeg (subp, fromRange.lo());
	    }
	    if (!fromRange.elements() || (adtypep->width() % fromRange.elements())!=0)
		adtypep->v3fatalSrc("Array extraction with width miscomputed "
				    <<adtypep->width()<<"/"<<fromRange.elements());
	    int elwidth = adtypep->width() / fromRange.elements();
	    AstSel* newp = new AstSel (nodep->fileline(),
				       fromp,
				       new AstMul(nodep->fileline(),
						  new AstConst(nodep->fileline(),AstConst::Unsized32(),elwidth),
						  subp),
				       new AstConst (nodep->fileline(),AstConst::Unsized32(),elwidth));
	    newp->declRange(fromRange);
	    newp->declElWidth(elwidth);
	    newp->dtypeFrom(adtypep->subDTypep());  // Need to strip off array reference
	    if (debug()>=9) newp->dumpTree(cout,"--SELBTn: ");
	    nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
	}
	else if (ddtypep->castBasicDType()) {
	    // SELBIT(range, index) -> SEL(array, index, 1)
	    AstSel* newp = new AstSel (nodep->fileline(),
				       fromp,
				       newSubLsbOf(rhsp, fromRange),
				       // Unsized so width from user
				       new AstConst (nodep->fileline(),AstConst::Unsized32(),1));
	    newp->declRange(fromRange);
	    UINFO(6,"   new "<<newp<<endl);
	    if (debug()>=9) newp->dumpTree(cout,"--SELBTn: ");
	    nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
	}
	else if (ddtypep->castNodeClassDType()) {  // It's packed, so a bit from the packed struct
	    // SELBIT(range, index) -> SEL(array, index, 1)
	    AstSel* newp = new AstSel (nodep->fileline(),
				       fromp,
				       newSubLsbOf(rhsp, fromRange),
				       // Unsized so width from user
				       new AstConst (nodep->fileline(),AstConst::Unsized32(),1));
	    newp->declRange(fromRange);
	    UINFO(6,"   new "<<newp<<endl);
	    if (debug()>=9) newp->dumpTree(cout,"--SELBTn: ");
	    nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
	}
	else {  // NULL=bad extract, or unknown node type
	    nodep->v3error("Illegal bit or array select; type already selected, or bad dimension: type is"
			   <<fromdata.m_errp->prettyName());
	    // How to recover?  We'll strip a dimension.
	    nodep->replaceWith(fromp); pushDeletep(nodep); VL_DANGLING(nodep);
	}
	if (!rhsp->backp()) { pushDeletep(rhsp); VL_DANGLING(rhsp); }
    }