Fix shifts by more than 32-bit numbers, bug1174.

This commit is contained in:
Wilson Snyder 2017-06-05 07:56:59 -04:00
parent a01c96140b
commit 9b06178f35
3 changed files with 83 additions and 1 deletions

View File

@ -5,6 +5,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 3.905 devel
*** Fix shifts by more than 32-bit numbers, bug1174. [Clifford Wolf]
* Verilator 3.904 2017-05-30

View File

@ -1585,6 +1585,22 @@ static inline WDataOutP VL_SHIFTL_WWI(int obits,int,int,WDataOutP owp,WDataInP l
}
return(owp);
}
static inline WDataOutP VL_SHIFTL_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) {
for (int i=1; i < VL_WORDS_I(rbits); i++) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
return VL_ZERO_RESET_W(obits, owp);
}
}
return VL_SHIFTL_WWI(obits,lbits,32,owp,lwp,rwp[0]);
}
static inline IData VL_SHIFTL_IIW(int obits,int,int rbits,IData lhs, WDataInP rwp) {
for (int i=1; i < VL_WORDS_I(rbits); i++) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
return 0;
}
}
return VL_CLEAN_II(obits,obits,lhs<<rwp[0]);
}
// EMIT_RULE: VL_SHIFTR: oclean=lclean; rclean==clean;
// Important: Unlike most other funcs, the shift might well be a computed
@ -1614,6 +1630,22 @@ static inline WDataOutP VL_SHIFTR_WWI(int obits,int,int,WDataOutP owp,WDataInP l
}
return(owp);
}
static inline WDataOutP VL_SHIFTR_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) {
for (int i=1; i < VL_WORDS_I(rbits); i++) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
return VL_ZERO_RESET_W(obits, owp);
}
}
return VL_SHIFTR_WWI(obits,lbits,32,owp,lwp,rwp[0]);
}
static inline IData VL_SHIFTR_IIW(int obits,int,int rbits,IData lhs, WDataInP rwp) {
for (int i=1; i < VL_WORDS_I(rbits); i++) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
return 0;
}
}
return VL_CLEAN_II(obits,obits,lhs>>rwp[0]);
}
// EMIT_RULE: VL_SHIFTRS: oclean=false; lclean=clean, rclean==clean;
static inline IData VL_SHIFTRS_III(int obits, int lbits, int, IData lhs, IData rhs) {
@ -1665,6 +1697,44 @@ static inline WDataOutP VL_SHIFTRS_WWI(int obits,int lbits,int,WDataOutP owp,WDa
}
return(owp);
}
static inline WDataOutP VL_SHIFTRS_WWW(int obits,int lbits,int rbits,WDataOutP owp,WDataInP lwp, WDataInP rwp) {
for (int i=1; i < VL_WORDS_I(rbits); i++) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
int lmsw = VL_WORDS_I(obits)-1;
IData sign = VL_SIGNONES_I(lbits,lwp[lmsw]);
for (int i=0; i <= lmsw; i++) owp[i] = sign;
owp[lmsw] &= VL_MASK_I(lbits);
return owp;
}
}
return VL_SHIFTRS_WWI(obits,lbits,32,owp,lwp,rwp[0]);
}
static inline IData VL_SHIFTRS_IIW(int obits,int lbits,int rbits,IData lhs, WDataInP rwp) {
for (int i=1; i < VL_WORDS_I(rbits); i++) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
IData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative
return VL_CLEAN_II(obits,obits,sign);
}
}
return VL_SHIFTRS_III(obits,lbits,32,lhs,rwp[0]);
}
static inline QData VL_SHIFTRS_QQW(int obits,int lbits,int rbits,QData lhs, WDataInP rwp) {
for (int i=1; i < VL_WORDS_I(rbits); i++) {
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
QData sign = -(lhs >> (lbits-1)); // ffff_ffff if negative
return VL_CLEAN_QQ(obits,obits,sign);
}
}
return VL_SHIFTRS_QQI(obits,lbits,32,lhs,rwp[0]);
}
static inline IData VL_SHIFTRS_IIQ(int obits,int lbits,int rbits,IData lhs, QData rhs) {
WData rwp[2]; VL_SET_WQ(rwp,rhs);
return VL_SHIFTRS_IIW(obits,lbits,rbits,lhs,rwp);
}
static inline QData VL_SHIFTRS_QQQ(int obits,int lbits,int rbits,QData lhs, QData rhs) {
WData rwp[2]; VL_SET_WQ(rwp,rhs);
return VL_SHIFTRS_QQW(obits,lbits,rbits,lhs,rwp);
}
//===================================================================
// Bit selection

View File

@ -5,13 +5,15 @@
module t (/*AUTOARG*/
// Outputs
ign,
ign, ign2, ign3,
// Inputs
clk
);
input clk;
output [31:0] ign;
output [3:0] ign2;
output [11:0] ign3;
parameter [95:0] P6 = 6;
localparam P64 = (1 << P6);
@ -23,6 +25,14 @@ module t (/*AUTOARG*/
reg [31:0] amt;
assign ign = {31'h0, clk} >>> 4'bx; // bug760
assign ign2 = {amt[1:0] >> {22{amt[5:2]}}, amt[1:0] << (0 <<< amt[5:2])}; // bug1174
assign ign3 = {amt[1:0] >> {22{amt[5:2]}},
amt[1:0] >> {11{amt[5:2]}},
$signed(amt[1:0]) >>> {22{amt[5:2]}},
$signed(amt[1:0]) >>> {11{amt[5:2]}},
amt[1:0] << {22{amt[5:2]}},
amt[1:0] << {11{amt[5:2]}}};
always @* begin
right = 32'h819b018a >> amt;