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.
|
||||
|
||||
**** 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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ""; }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue