Fix huge shifts to zero with -Wno-WIDTH, bug768.
This commit is contained in:
parent
d3049d9c89
commit
06744b664a
2
Changes
2
Changes
|
|
@ -9,7 +9,7 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||||
|
|
||||||
*** Support SV 2012 package import before port list.
|
*** 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.
|
**** Fix gate primitives with arrays and non-arrayed pins.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3194,9 +3194,11 @@ struct AstExtendS : public AstNodeUniop {
|
||||||
// Expand a value into a wider entity by sign extension. Width is implied from nodep->width()
|
// 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) : AstNodeUniop(fl, lhsp) {}
|
||||||
AstExtendS(FileLine* fl, AstNode* lhsp, int width) : 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); }
|
dtypeSetLogicSized(width,width,AstNumeric::UNSIGNED); }
|
||||||
ASTNODE_NODE_FUNCS(ExtendS, EXTENDS)
|
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 emitVerilog() { return "%l"; }
|
||||||
virtual string emitC() { return "VL_EXTENDS_%nq%lq(%nw,%lw, %P, %li)"; }
|
virtual string emitC() { return "VL_EXTENDS_%nq%lq(%nw,%lw, %P, %li)"; }
|
||||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;}
|
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
|
// Output data type's width determines which bit is used for sign extension
|
||||||
AstShiftRS(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth=0)
|
AstShiftRS(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth=0)
|
||||||
: AstNodeBiop(fl, lhsp, rhsp) {
|
: AstNodeBiop(fl, lhsp, rhsp) {
|
||||||
|
// Important that widthMin be correct, as opExtend requires it after V3Expand
|
||||||
if (setwidth) { dtypeSetLogicSized(setwidth,setwidth,AstNumeric::SIGNED); }
|
if (setwidth) { dtypeSetLogicSized(setwidth,setwidth,AstNumeric::SIGNED); }
|
||||||
}
|
}
|
||||||
ASTNODE_NODE_FUNCS(ShiftRS, SHIFTRS)
|
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 emitVerilog() { return "%k(%l %f>>> %r)"; }
|
||||||
virtual string emitC() { return "VL_SHIFTRS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
virtual string emitC() { return "VL_SHIFTRS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||||
virtual string emitSimpleOperator() { return ""; }
|
virtual string emitSimpleOperator() { return ""; }
|
||||||
|
|
|
||||||
|
|
@ -1133,7 +1133,7 @@ V3Number& V3Number::opShiftR (const V3Number& lhs, const V3Number& rhs) {
|
||||||
return *this;
|
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
|
// L(lhs) bit return
|
||||||
// The spec says a unsigned >>> still acts as a normal >>.
|
// 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
|
// 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();
|
uint32_t rhsval = rhs.toUInt();
|
||||||
if (rhsval < (uint32_t)lhs.width()) {
|
if (rhsval < (uint32_t)lhs.width()) {
|
||||||
for (int bit=0; bit<this->width(); bit++) {
|
for (int bit=0; bit<this->width(); bit++) {
|
||||||
setBit(bit,lhs.bitIsExtend(bit + rhsval));
|
setBit(bit,lhs.bitIsExtend(bit + rhsval, lbits));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int bit=0; bit<this->width(); bit++) {
|
for (int bit=0; bit<this->width(); bit++) {
|
||||||
setBit(bit,lhs.bitIsExtend(lhs.width()-1));
|
setBit(bit,lhs.bitIs(lbits-1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
|
|
@ -1481,11 +1481,11 @@ V3Number& V3Number::opAssign (const V3Number& lhs) {
|
||||||
return *this;
|
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
|
// Note may be a width change during the sign extension
|
||||||
setZero();
|
setZero();
|
||||||
for(int bit=0; bit<this->width(); bit++) {
|
for(int bit=0; bit<this->width(); bit++) {
|
||||||
setBit(bit,lhs.bitIsExtend(bit));
|
setBit(bit,lhs.bitIsExtend(bit, lbits));
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,10 +66,12 @@ private:
|
||||||
}
|
}
|
||||||
return ( "01zx"[(((m_value[bit/32] & (1UL<<(bit&31)))?1:0)
|
return ( "01zx"[(((m_value[bit/32] & (1UL<<(bit&31)))?1:0)
|
||||||
| ((m_valueX[bit/32] & (1UL<<(bit&31)))?2: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<0) return '0';
|
||||||
if (bit>=m_width) {
|
UASSERT(lbits<=m_width, "Extend of wrong size");
|
||||||
bit = m_width-1;
|
if (bit>=lbits) {
|
||||||
|
bit = lbits ? lbits-1 : 0;
|
||||||
// We do sign extend
|
// We do sign extend
|
||||||
return ( "01zx"[(((m_value[bit/32] & (1UL<<(bit&31)))?1:0)
|
return ( "01zx"[(((m_value[bit/32] & (1UL<<(bit&31)))?1:0)
|
||||||
| ((m_valueX[bit/32] & (1UL<<(bit&31)))?2: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& opBitsNonZ(const V3Number& lhs); // Z->0, 0/1/X->1
|
||||||
//
|
//
|
||||||
V3Number& opAssign (const V3Number& lhs);
|
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& opRedOr (const V3Number& lhs);
|
||||||
V3Number& opRedAnd (const V3Number& lhs);
|
V3Number& opRedAnd (const V3Number& lhs);
|
||||||
V3Number& opRedXor (const V3Number& lhs);
|
V3Number& opRedXor (const V3Number& lhs);
|
||||||
|
|
@ -257,7 +259,7 @@ public:
|
||||||
V3Number& opRotR (const V3Number& lhs, const V3Number& rhs);
|
V3Number& opRotR (const V3Number& lhs, const V3Number& rhs);
|
||||||
V3Number& opRotL (const V3Number& lhs, const V3Number& rhs);
|
V3Number& opRotL (const V3Number& lhs, const V3Number& rhs);
|
||||||
V3Number& opShiftR (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);
|
V3Number& opShiftL (const V3Number& lhs, const V3Number& rhs);
|
||||||
// Comparisons
|
// Comparisons
|
||||||
V3Number& opEq (const V3Number& lhs, const V3Number& rhs);
|
V3Number& opEq (const V3Number& lhs, const V3Number& rhs);
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,16 @@
|
||||||
w16_u = (w16a_u >> 16) >>> 32'h7ffffff1;
|
w16_u = (w16a_u >> 16) >>> 32'h7ffffff1;
|
||||||
`checkh(w16_u, 16'h0000);
|
`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;
|
if (fail) $stop;
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue