From e7d63c76443dcf84cf67cd5884064228b70180b7 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Mon, 8 Oct 2012 07:05:54 -0400 Subject: [PATCH] Fix large shift error on large shift constants. --- Changes | 2 ++ src/V3Width.cpp | 16 +++++++++++++--- test_regress/t/t_math_shift.v | 2 ++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Changes b/Changes index deb9a126d..86cfdcfa9 100644 --- a/Changes +++ b/Changes @@ -7,6 +7,8 @@ indicates the contributor was also the author of the fix; Thanks! **** Fix parameter pins interspersed with cells broke in 3.840. [Bernard Deadman] +**** Fix large shift error on large shift constants. [David Welch] + * Verilator 3.841 2012/09/03 diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 8e76277ef..ca39ebbb5 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1821,9 +1821,19 @@ private: int width=nodep->width(); int ewidth=nodep->widthMin(); nodep->lhsp()->iterateAndNext(*this,WidthVP(width,ewidth,FINAL).p()); widthCheck(nodep,"LHS",nodep->lhsp(),width,ewidth); - if (nodep->rhsp()->width()>32) - nodep->rhsp()->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->rhsp()->width()>32) { + AstConst* shiftp = nodep->rhsp()->castConst(); + if (shiftp && shiftp->num().mostSetBitP1() <= 32) { + // If (number)<<96'h1, then make it into (number)<<32'h1 + V3Number num (shiftp->fileline(), 32, 0); num.opAssign(shiftp->num()); + AstNode* shiftp = nodep->rhsp(); + nodep->rhsp()->replaceWith(new AstConst(shiftp->fileline(), num)); + shiftp->deleteTree(); shiftp=NULL; + } else { + nodep->rhsp()->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"); + } + } } return nodep; // May edit } diff --git a/test_regress/t/t_math_shift.v b/test_regress/t/t_math_shift.v index 3069a3d40..796c7403b 100644 --- a/test_regress/t/t_math_shift.v +++ b/test_regress/t/t_math_shift.v @@ -40,6 +40,8 @@ module t (/*AUTOARG*/ if (5'sb10110>>>2 != 5'sb11101) $stop; if (5'sb10110<<2 != 5'sb11000) $stop; if (5'sb10110<<<2 != 5'sb11000) $stop; + // Allow >64 bit shifts if the shift amount is a constant + if ((64'sh458c2de282e30f8b >> 68'sh4) !== 64'sh0458c2de282e30f8) $stop; end if (cyc==2) begin amt <= 32'd28;