Beispiel #1
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;
	}
    }
Beispiel #2
0
    void visitShift (AstNodeBiop* nodep) {
	// Shifts of > 32/64 bits in C++ will wrap-around and generate non-0s
	if (!nodep->user2SetOnce()) {
	    UINFO(4,"  ShiftFix  "<<nodep<<endl);
	    AstConst* shiftp = nodep->rhsp()->castConst();
	    if (shiftp && shiftp->num().mostSetBitP1() > 32) {
		shiftp->v3error("Unsupported: Shifting of by over 32-bit number isn't supported."
				<<" (This isn't a shift of 32 bits, but a shift of 2^32, or 4 billion!)\n");
	    }
	    if (nodep->widthMin()<=64  // Else we'll use large operators which work right
		// C operator's width must be < maximum shift which is based on Verilog width
		&& nodep->width() < (1LL<<nodep->rhsp()->widthMin())) {
		AstNRelinker replaceHandle;
		nodep->unlinkFrBack(&replaceHandle);
		AstNode* constzerop;
		int m1value = nodep->widthMin()-1; // Constant of width-1; not changing dtype width
		if (nodep->signedFlavor()) {
		    // Then over shifting gives the sign bit, not all zeros
		    // Note *NOT* clean output -- just like normal shift!
		    // Create equivalent of VL_SIGNONES_(node_width)
		    constzerop = new AstNegate (nodep->fileline(),
						new AstShiftR(nodep->fileline(),
							      nodep->lhsp()->cloneTree(false),
							      new AstConst(nodep->fileline(),
									   m1value),
							      nodep->width()));
		} else {
		    V3Number zeronum  (nodep->fileline(), nodep->width(), 0);
		    constzerop = new AstConst(nodep->fileline(), zeronum);
		}
		constzerop->dtypeFrom (nodep);  // unsigned

		V3Number widthnum (nodep->fileline(), nodep->rhsp()->widthMin(), m1value);
		AstNode* constwidthp = new AstConst(nodep->fileline(), widthnum);
		constwidthp->dtypeFrom (nodep->rhsp());  // unsigned
		AstCond* newp =
		    new AstCond (nodep->fileline(),
				 new AstGte (nodep->fileline(),
					     constwidthp,
					     nodep->rhsp()->cloneTree(false)),
				 nodep,
				 constzerop);
		replaceHandle.relink(newp);
	    }
	}
	nodep->iterateChildren(*this); checkNode(nodep);
    }
Beispiel #3
0
    AstNode* newSubNeg(vlsint32_t lhs, AstNode* rhsp) {
	// Return lhs-rhs
	// We must make sure sub gets sign of original value
	AstNode* newp = new AstSub(rhsp->fileline(),
				   new AstConst(rhsp->fileline(), AstConst::Unsized32(), lhs),
				   rhsp);
	newp->dtypeFrom(rhsp);  // Important as AstSub default is lhs's sign
	return newp;
    }