Fix huge shifts to zero with -Wno-WIDTH, bug768.

This commit is contained in:
Wilson Snyder 2014-05-16 07:09:43 -04:00
parent d3049d9c89
commit 06744b664a
5 changed files with 29 additions and 13 deletions

View File

@ -9,7 +9,7 @@ indicates the contributor was also the author of the fix; Thanks!
*** Support SV 2012 package import before port list.
**** Fix huge shifts to zero with -Wno-WIDTH, bug765, bug766. [Clifford Wolf]
**** Fix huge shifts to zero with -Wno-WIDTH, bug765, bug766, bug768. [Clifford Wolf]
**** Fix gate primitives with arrays and non-arrayed pins.

View File

@ -3194,9 +3194,11 @@ struct AstExtendS : public AstNodeUniop {
// Expand a value into a wider entity by sign extension. Width is implied from nodep->width()
AstExtendS(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {}
AstExtendS(FileLine* fl, AstNode* lhsp, int width) : AstNodeUniop(fl, lhsp) {
// Important that widthMin be correct, as opExtend requires it after V3Expand
dtypeSetLogicSized(width,width,AstNumeric::UNSIGNED); }
ASTNODE_NODE_FUNCS(ExtendS, EXTENDS)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opExtendS(lhs); }
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
out.opExtendS(lhs, lhsp()->widthMin()); }
virtual string emitVerilog() { return "%l"; }
virtual string emitC() { return "VL_EXTENDS_%nq%lq(%nw,%lw, %P, %li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;}
@ -3876,10 +3878,12 @@ struct AstShiftRS : public AstNodeBiop {
// Output data type's width determines which bit is used for sign extension
AstShiftRS(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth=0)
: AstNodeBiop(fl, lhsp, rhsp) {
// Important that widthMin be correct, as opExtend requires it after V3Expand
if (setwidth) { dtypeSetLogicSized(setwidth,setwidth,AstNumeric::SIGNED); }
}
ASTNODE_NODE_FUNCS(ShiftRS, SHIFTRS)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opShiftRS(lhs,rhs); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
out.opShiftRS(lhs,rhs,lhsp()->widthMin()); }
virtual string emitVerilog() { return "%k(%l %f>>> %r)"; }
virtual string emitC() { return "VL_SHIFTRS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
virtual string emitSimpleOperator() { return ""; }

View File

@ -1133,7 +1133,7 @@ V3Number& V3Number::opShiftR (const V3Number& lhs, const V3Number& rhs) {
return *this;
}
V3Number& V3Number::opShiftRS (const V3Number& lhs, const V3Number& rhs) {
V3Number& V3Number::opShiftRS (const V3Number& lhs, const V3Number& rhs, uint32_t lbits) {
// L(lhs) bit return
// The spec says a unsigned >>> still acts as a normal >>.
// We presume it is signed; as that's V3Width's job to convert to opShiftR
@ -1142,11 +1142,11 @@ V3Number& V3Number::opShiftRS (const V3Number& lhs, const V3Number& rhs) {
uint32_t rhsval = rhs.toUInt();
if (rhsval < (uint32_t)lhs.width()) {
for (int bit=0; bit<this->width(); bit++) {
setBit(bit,lhs.bitIsExtend(bit + rhsval));
setBit(bit,lhs.bitIsExtend(bit + rhsval, lbits));
}
} else {
for (int bit=0; bit<this->width(); bit++) {
setBit(bit,lhs.bitIsExtend(lhs.width()-1));
setBit(bit,lhs.bitIs(lbits-1));
}
}
return *this;
@ -1481,11 +1481,11 @@ V3Number& V3Number::opAssign (const V3Number& lhs) {
return *this;
}
V3Number& V3Number::opExtendS (const V3Number& lhs) {
V3Number& V3Number::opExtendS (const V3Number& lhs, uint32_t lbits) {
// Note may be a width change during the sign extension
setZero();
for(int bit=0; bit<this->width(); bit++) {
setBit(bit,lhs.bitIsExtend(bit));
setBit(bit,lhs.bitIsExtend(bit, lbits));
}
return *this;
}

View File

@ -66,10 +66,12 @@ private:
}
return ( "01zx"[(((m_value[bit/32] & (1UL<<(bit&31)))?1:0)
| ((m_valueX[bit/32] & (1UL<<(bit&31)))?2:0))] ); }
char bitIsExtend (int bit) const {
char bitIsExtend (int bit, int lbits) const {
// lbits usually = width, but for C optimizations width=32_bits, lbits = 32_or_less
if (bit<0) return '0';
if (bit>=m_width) {
bit = m_width-1;
UASSERT(lbits<=m_width, "Extend of wrong size");
if (bit>=lbits) {
bit = lbits ? lbits-1 : 0;
// We do sign extend
return ( "01zx"[(((m_value[bit/32] & (1UL<<(bit&31)))?1:0)
| ((m_valueX[bit/32] & (1UL<<(bit&31)))?2:0))] );
@ -205,7 +207,7 @@ public:
V3Number& opBitsNonZ(const V3Number& lhs); // Z->0, 0/1/X->1
//
V3Number& opAssign (const V3Number& lhs);
V3Number& opExtendS (const V3Number& lhs); // Sign extension
V3Number& opExtendS (const V3Number& lhs, uint32_t lbits); // Sign extension
V3Number& opRedOr (const V3Number& lhs);
V3Number& opRedAnd (const V3Number& lhs);
V3Number& opRedXor (const V3Number& lhs);
@ -257,7 +259,7 @@ public:
V3Number& opRotR (const V3Number& lhs, const V3Number& rhs);
V3Number& opRotL (const V3Number& lhs, const V3Number& rhs);
V3Number& opShiftR (const V3Number& lhs, const V3Number& rhs);
V3Number& opShiftRS (const V3Number& lhs, const V3Number& rhs); // Arithmetic w/carry
V3Number& opShiftRS (const V3Number& lhs, const V3Number& rhs, uint32_t lbits); // Arithmetic w/carry
V3Number& opShiftL (const V3Number& lhs, const V3Number& rhs);
// Comparisons
V3Number& opEq (const V3Number& lhs, const V3Number& rhs);

View File

@ -123,6 +123,16 @@
w16_u = (w16a_u >> 16) >>> 32'h7ffffff1;
`checkh(w16_u, 16'h0000);
// bug768
w4_s = 4'sd4;
w4_u = $signed(5'd1 > w4_s-w4_s);
`checkh(w4_u, 4'b1111);
`ifdef VERILATOR
w4_s = $c4("4"); // Eval at runtime
`endif
w4_u = $signed(5'd1 > w4_s-w4_s);
`checkh(w4_u, 4'b1111);
if (fail) $stop;
$write("*-* All Finished *-*\n");
$finish;